diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e36b28b67..0b3006f0d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,6 @@ on: push: branches: [main] pull_request: - branches: [main] # Cancel in-progress runs when a new commit is pushed to the same PR concurrency: @@ -63,6 +62,7 @@ jobs: - 'apps/web/jest.config.ts' - 'apps/web/postcss.config.mjs' - 'apps/web/sentry.*' + - 'packages/agent-harness/**' - 'packages/db/**' - 'packages/encryption/**' - 'packages/trpc/**' @@ -99,6 +99,9 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Verify agent harness CI contracts and boundaries + run: pnpm run test:agent-harness-ci + - name: Plugin shared-schemas sync check run: bash scripts/sync-plugin-shared.sh --check diff --git a/.github/workflows/kilo-app-ci.yml b/.github/workflows/kilo-app-ci.yml index 7bbb23c1c2..30a6847b4d 100644 --- a/.github/workflows/kilo-app-ci.yml +++ b/.github/workflows/kilo-app-ci.yml @@ -7,6 +7,7 @@ on: - 'apps/mobile/**' - 'packages/trpc/**' - 'apps/web/src/routers/**' + - 'packages/agent-harness/**' - 'packages/app-shared/**' - 'packages/kilo-chat/**' - 'packages/kilo-chat-hooks/**' @@ -16,11 +17,11 @@ on: - 'pnpm-lock.yaml' - '.github/workflows/kilo-app-ci.yml' pull_request: - branches: [main] paths: - 'apps/mobile/**' - 'packages/trpc/**' - 'apps/web/src/routers/**' + - 'packages/agent-harness/**' - 'packages/app-shared/**' - 'packages/kilo-chat/**' - 'packages/kilo-chat-hooks/**' diff --git a/apps/web/jest.config.ts b/apps/web/jest.config.ts index d84eeb592e..7c7b0e8e0a 100644 --- a/apps/web/jest.config.ts +++ b/apps/web/jest.config.ts @@ -5,7 +5,20 @@ import type { Config } from 'jest'; const config: Config = { testEnvironment: 'node', transform: { - '^.+\\.(t|j)sx?$': [ + '^.+\\.tsx$': [ + '@swc/jest', + { + jsc: { + parser: { syntax: 'typescript', tsx: true, decorators: true }, + transform: { + legacyDecorator: true, + decoratorMetadata: true, + react: { runtime: 'automatic' }, + }, + }, + }, + ], + '^.+\\.(ts|jsx?)$': [ '@swc/jest', { jsc: { @@ -35,7 +48,11 @@ const config: Config = { '^@/(.*)$': '/src/$1', '^server-only$': '/src/tests/setup/__mocks__/server-only.js', }, - testMatch: ['**/src/**/*.test.ts', '/../../packages/db/src/**/*.test.ts'], + testMatch: [ + '**/src/**/*.test.ts', + '/src/components/quick-chat/**/*.test.tsx', + '/../../packages/db/src/**/*.test.ts', + ], testPathIgnorePatterns: [ '/../../.kilocode/', '/../../services/cloud-agent-next/', diff --git a/apps/web/package.json b/apps/web/package.json index 39e6e51e69..04d4369c03 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -44,6 +44,7 @@ "@chat-adapter/state-redis": "4.36.0", "@emoji-mart/data": "1.2.1", "@emoji-mart/react": "1.1.1", + "@kilocode/agent-harness": "workspace:*", "@kilocode/app-shared": "workspace:*", "@kilocode/auto-routing-contracts": "workspace:*", "@kilocode/cloud-agent-profile": "workspace:*", @@ -140,6 +141,7 @@ "fflate": "0.8.2", "form-data": "4.0.6", "google-auth-library": "10.6.2", + "idb": "8.0.3", "jotai": "2.18.1", "jotai-minidb": "0.0.8", "js-cookie": "3.0.8", @@ -185,6 +187,10 @@ "@swc/jest": "0.2.39", "@tailwindcss/postcss": "4.2.4", "@tailwindcss/typography": "0.5.19", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.9.1", + "@testing-library/react": "16.3.0", + "@testing-library/user-event": "14.6.1", "@types/jest": "30.0.0", "@types/jsonwebtoken": "catalog:", "@types/linkify-it": "5.0.0", @@ -196,9 +202,11 @@ "babel-plugin-react-compiler": "1.0.0", "dependency-cruiser": "17.3.10", "dotenv": "17.3.1", + "fake-indexeddb": "6.2.4", "graphql": "16.14.2", "ink": "6.8.0", "jest": "30.3.0", + "jest-environment-jsdom": "30.3.0", "knip": "5.86.0", "madge": "8.0.0", "postcss": "8.5.23", diff --git a/package.json b/package.json index 59d3721fb3..7dade18142 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "test:web-env": "tsx --tsconfig scripts/web-env/tsconfig.json --test scripts/web-env/*.test.ts", "test:setup-smoke": "pnpm --filter web run test:setup-smoke", "test:mobile-artifacts": "node --test scripts/inspect-mobile-artifacts.test.mjs", + "test:agent-harness-ci": "node --test scripts/agent-harness-ci.test.mjs && pnpm --filter @kilocode/agent-harness exec vitest run src/boundaries.test.ts", "lint": "scripts/lint-all.sh", "format": "oxfmt", "format:check": "oxfmt --list-different .", diff --git a/packages/agent-harness/package.json b/packages/agent-harness/package.json new file mode 100644 index 0000000000..3eba1e7937 --- /dev/null +++ b/packages/agent-harness/package.json @@ -0,0 +1,38 @@ +{ + "name": "@kilocode/agent-harness", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + ".": "./src/version.ts", + "./react": "./src/react.ts", + "./*.test": null, + "./*": "./src/*.ts" + }, + "scripts": { + "test": "vitest run", + "typecheck": "tsgo --noEmit", + "lint": "oxlint --config ../../.oxlintrc.json", + "format": "oxfmt" + }, + "dependencies": { + "@kilocode/mcp-gateway": "workspace:*", + "zod": "catalog:" + }, + "peerDependencies": { + "react": "^19.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + }, + "devDependencies": { + "@types/node": "catalog:", + "@types/react": "19.2.14", + "@typescript/native-preview": "catalog:", + "dependency-cruiser": "17.3.10", + "typescript": "catalog:", + "vitest": "catalog:" + } +} diff --git a/packages/agent-harness/src/boundaries.test.ts b/packages/agent-harness/src/boundaries.test.ts new file mode 100644 index 0000000000..ae268c989b --- /dev/null +++ b/packages/agent-harness/src/boundaries.test.ts @@ -0,0 +1,184 @@ +import { globSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join, relative } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { cruise, type IForbiddenRuleType } from 'dependency-cruiser'; +import extractTSConfig from 'dependency-cruiser/config-utl/extract-ts-config'; +import ts from 'typescript'; +import { afterEach, expect, it } from 'vitest'; + +const root = fileURLToPath(new URL('../../../', import.meta.url)); +const core = '^packages/agent-harness/src/(?!react\\.ts$)'; +const browser = '^apps/web/src/(lib/agent-harness/(browser-|transport\\.)|components/quick-chat/)'; +const native = '^apps/mobile/src/lib/agent-harness/'; +const rules: IForbiddenRuleType[] = [ + { + name: 'portable-core', + severity: 'error', + from: { path: core }, + to: { + reachable: true, + pathNot: `${core}|^packages/mcp-gateway/src/|(^|/)node_modules/zod/`, + }, + }, + { + name: 'no-client-executors-or-credentials', + severity: 'error', + from: { path: `${browser}|${native}|^packages/agent-harness/src/react\\.ts$` }, + to: { + reachable: true, + path: '^services/|^packages/(db|encryption|worker-utils|cloud-agent-profile)/|^apps/web/src/(routers/|app/api/|lib/(tokens|drizzle|agent-harness/(?!browser-|transport\\.)))|(^|/)(server-only|@ai-sdk|@modelcontextprotocol|ai)(/|$)', + }, + }, +]; + +async function violations(baseDir: string, files: string[], project?: string) { + // The resolver follows symlinks before calculating paths relative to this directory. + const directory = realpathSync(baseDir); + const tsConfigFile = project ? join(directory, project, 'tsconfig.json') : undefined; + const tsConfig = tsConfigFile ? extractTSConfig(tsConfigFile) : undefined; + // Otherwise dependency-cruiser resolves aliases from process.cwd(), not the project. + if (tsConfig && project) tsConfig.options.baseUrl ??= join(directory, project); + const { output } = await cruise( + files, + { + baseDir: directory, + validate: true, + ruleSet: { forbidden: rules }, + doNotFollow: { path: 'node_modules' }, + enhancedResolveOptions: { exportsFields: ['exports'], conditionNames: ['import', 'default'] }, + exclude: '\\.test\\.[jt]sx?$', + tsConfig: tsConfigFile ? { fileName: tsConfigFile } : undefined, + }, + undefined, + { tsConfig } + ); + if (typeof output === 'string') throw new Error('Expected a dependency graph'); + return output.summary.violations; +} + +function portabilityErrors(files: string[]) { + const program = ts.createProgram(files, { + target: ts.ScriptTarget.ES2022, + module: ts.ModuleKind.ESNext, + moduleResolution: ts.ModuleResolutionKind.Bundler, + lib: ['lib.es2022.d.ts'], + types: [], + strict: true, + skipLibCheck: true, + noEmit: true, + }); + return ts + .getPreEmitDiagnostics(program) + .map(error => ts.flattenDiagnosticMessageText(error.messageText, '\n')); +} + +const fixtures: string[] = []; +afterEach(() => fixtures.splice(0).forEach(path => rmSync(path, { recursive: true, force: true }))); +function fixture(files: Record) { + const directory = mkdtempSync(join(tmpdir(), 'harness-boundary-')); + fixtures.push(directory); + for (const [path, content] of Object.entries(files)) { + mkdirSync(dirname(join(directory, path)), { recursive: true }); + writeFileSync(join(directory, path), content); + } + return directory; +} + +it('keeps the portable package and present host entrypoints within their boundaries', async () => { + const surfaces = [ + ['packages/agent-harness', ['packages/agent-harness/src/**/*.ts']], + [ + 'apps/web', + [ + 'apps/web/src/lib/agent-harness/browser-*.ts', + 'apps/web/src/lib/agent-harness/transport.ts', + 'apps/web/src/components/quick-chat/**/*.tsx', + ], + ], + ['apps/mobile', ['apps/mobile/src/lib/agent-harness/**/*.ts']], + ] as const; + for (const [project, patterns] of surfaces) { + const files = globSync([...patterns], { cwd: root }).filter( + file => !/\.test\.[jt]sx?$/.test(file) + ); + if (files.length) expect(await violations(root, files, project)).toEqual([]); + if (project === 'packages/agent-harness') { + expect( + portabilityErrors( + files.filter(file => !file.endsWith('/react.ts')).map(file => join(root, file)) + ) + ).toEqual([]); + } + } +}); + +const entry = 'packages/agent-harness/src/entry.ts'; +const relay = 'packages/mcp-gateway/src/relay.ts'; +const relayImport = "export * from '../../mcp-gateway/src/relay';"; +it('allows a transitive portable helper but rejects its Node builtin import', async () => { + const directory = fixture({ + [entry]: relayImport, + [relay]: 'export const value = Math.max(1, 2);', + }); + expect(await violations(directory, [entry])).toEqual([]); + expect(portabilityErrors([join(directory, entry)])).toEqual([]); + writeFileSync(join(directory, relay), "import 'node:fs';"); + expect(await violations(directory, [entry])).toContainEqual( + expect.objectContaining({ + from: entry, + to: 'fs', + rule: { name: 'portable-core', severity: 'error' }, + }) + ); +}); +it.each([ + 'services/agent-harness/src/dispatch.ts', + 'apps/web/src/lib/tokens.ts', + 'node_modules/react-native/index.js', + 'node_modules/react/index.js', + 'node_modules/idb/index.js', +])('rejects a transitive core import of %s', async target => { + const directory = fixture({ + [entry]: relayImport, + [relay]: `export * from '${relative(dirname(relay), target)}';`, + [target]: 'export const value = 1;', + }); + expect(await violations(directory, [entry])).toContainEqual( + expect.objectContaining({ from: entry, to: target }) + ); +}); + +it.each(['window', 'document', 'navigator', 'localStorage', 'indexedDB'])( + 'rejects the browser global %s through a helper', + name => { + const directory = fixture({ + [entry]: relayImport, + [relay]: `export const value = ${name};`, + }); + expect(portabilityErrors([join(directory, entry)]).join('\n')).toContain( + `Cannot find name '${name}'` + ); + } +); + +it.each([ + 'apps/web/src/lib/agent-harness/browser-bridge.ts', + 'apps/mobile/src/lib/agent-harness/native-bridge.ts', +])('rejects transitive credentials from the host %s', async host => { + const target = 'apps/web/src/lib/tokens.ts'; + const project = host.startsWith('apps/web/') ? 'apps/web' : 'apps/mobile'; + const helper = `${project}/src/relay.ts`; + const directory = fixture({ + [`${project}/tsconfig.json`]: JSON.stringify({ + compilerOptions: { paths: { '@/*': ['./src/*'] } }, + }), + [host]: "export * from '@/relay';", + [helper]: `export * from '${relative(dirname(helper), relay)}';`, + [relay]: `export * from '${relative(dirname(relay), target)}';`, + [target]: 'export const credential = "fixture";', + }); + expect(await violations(directory, [host], project)).toContainEqual( + expect.objectContaining({ from: host, to: target }) + ); +}); diff --git a/packages/agent-harness/src/version.ts b/packages/agent-harness/src/version.ts new file mode 100644 index 0000000000..cbb10b8b7a --- /dev/null +++ b/packages/agent-harness/src/version.ts @@ -0,0 +1 @@ +export const AGENT_HARNESS_PROTOCOL_VERSION = 1; diff --git a/packages/agent-harness/tsconfig.json b/packages/agent-harness/tsconfig.json new file mode 100644 index 0000000000..5a3d69bbdd --- /dev/null +++ b/packages/agent-harness/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022"], + "types": [], + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts"] +} diff --git a/packages/agent-harness/vitest.config.ts b/packages/agent-harness/vitest.config.ts new file mode 100644 index 0000000000..147b0c62c6 --- /dev/null +++ b/packages/agent-harness/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ test: { environment: 'node', include: ['src/**/*.test.ts'] } }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 954f0206a2..4d4e64cd93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -227,7 +227,7 @@ importers: version: link:../../packages/trpc '@modelcontextprotocol/sdk': specifier: 1.30.0 - version: 1.30.0(zod@4.4.3) + version: 1.30.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) '@tanstack/react-query': specifier: 'catalog:' version: 5.100.10(react@19.2.6) @@ -786,6 +786,9 @@ importers: '@emoji-mart/react': specifier: 1.1.1 version: 1.1.1(emoji-mart@5.6.0)(react@19.2.6) + '@kilocode/agent-harness': + specifier: workspace:* + version: link:../../packages/agent-harness '@kilocode/app-shared': specifier: workspace:* version: link:../../packages/app-shared @@ -1074,6 +1077,9 @@ importers: google-auth-library: specifier: 10.6.2 version: 10.6.2 + idb: + specifier: 8.0.3 + version: 8.0.3 jotai: specifier: 2.18.1 version: 2.18.1(@babel/core@7.29.7)(@babel/template@7.29.7)(@types/react@19.2.14)(react@19.2.6) @@ -1185,7 +1191,7 @@ importers: devDependencies: '@chromatic-com/playwright': specifier: 0.12.8 - version: 0.12.8(@playwright/test@1.58.2)(@swc/core@1.15.18)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)(utf-8-validate@6.0.6) + version: 0.12.8(@playwright/test@1.58.2)(@swc/core@1.15.18)(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)(utf-8-validate@6.0.6) '@jest/globals': specifier: 30.3.0 version: 30.3.0 @@ -1204,6 +1210,18 @@ importers: '@tailwindcss/typography': specifier: 0.5.19 version: 0.5.19(tailwindcss@4.2.4) + '@testing-library/dom': + specifier: 10.4.1 + version: 10.4.1 + '@testing-library/jest-dom': + specifier: 6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: 16.3.0 + version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@testing-library/user-event': + specifier: 14.6.1 + version: 14.6.1(@testing-library/dom@10.4.1) '@types/jest': specifier: 30.0.0 version: 30.0.0 @@ -1237,6 +1255,9 @@ importers: dotenv: specifier: 17.3.1 version: 17.3.1 + fake-indexeddb: + specifier: 6.2.4 + version: 6.2.4 graphql: specifier: 16.14.2 version: 16.14.2 @@ -1246,6 +1267,9 @@ importers: jest: specifier: 30.3.0 version: 30.3.0(@types/node@24.12.4)(node-notifier@10.0.1) + jest-environment-jsdom: + specifier: 30.3.0 + version: 30.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) knip: specifier: 5.86.0 version: 5.86.0(@types/node@24.12.4)(typescript@5.9.3) @@ -1274,6 +1298,34 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/agent-harness: + dependencies: + '@kilocode/mcp-gateway': + specifier: workspace:* + version: link:../mcp-gateway + zod: + specifier: 'catalog:' + version: 4.4.3 + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 24.12.4 + '@types/react': + specifier: 19.2.14 + version: 19.2.14 + '@typescript/native-preview': + specifier: 'catalog:' + version: 7.0.0-dev.20260514.1 + dependency-cruiser: + specifier: 17.3.10 + version: 17.3.10 + typescript: + specifier: 'catalog:' + version: 5.9.3 + vitest: + specifier: 'catalog:' + version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) + packages/app-shared: dependencies: zod: @@ -1372,7 +1424,7 @@ importers: version: 7.0.0-dev.20260514.1 jest: specifier: 30.3.0 - version: 30.3.0(@types/node@25.5.2)(node-notifier@10.0.1) + version: 30.3.0(@types/node@24.12.4)(node-notifier@10.0.1) typescript: specifier: 'catalog:' version: 5.9.3 @@ -1723,6 +1775,67 @@ importers: specifier: 'catalog:' version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) + services/agent-harness: + dependencies: + '@ai-sdk/openai-compatible': + specifier: 3.0.11 + version: 3.0.11(zod@4.4.3) + '@cfworker/json-schema': + specifier: 4.1.1 + version: 4.1.1 + '@kilocode/agent-harness': + specifier: workspace:* + version: link:../../packages/agent-harness + '@kilocode/mcp-gateway': + specifier: workspace:* + version: link:../../packages/mcp-gateway + '@kilocode/worker-utils': + specifier: workspace:* + version: link:../../packages/worker-utils + '@modelcontextprotocol/sdk': + specifier: 1.30.0 + version: 1.30.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) + ai: + specifier: 7.0.29 + version: 7.0.29(zod@4.4.3) + drizzle-orm: + specifier: 0.45.2 + version: 0.45.2(@cloudflare/workers-types@4.20260605.1)(@opentelemetry/api@1.9.1)(@types/pg@8.18.0)(@upstash/redis@1.38.0)(bun-types@1.3.14)(expo-sqlite@57.0.1(expo@57.0.15)(react-native@0.86.2(@types/react@19.2.14)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6))(kysely@0.29.2)(pg@8.20.0) + hono: + specifier: 4.12.34 + version: 4.12.34 + jose: + specifier: 'catalog:' + version: 6.2.3 + zod: + specifier: 'catalog:' + version: 4.4.3 + devDependencies: + '@cloudflare/vitest-pool-workers': + specifier: 'catalog:' + version: 0.16.13(@cloudflare/workers-types@4.20260605.1)(@types/node@24.12.4)(@vitest/runner@4.1.6)(@vitest/snapshot@4.1.6)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(vitest@4.1.6) + '@cloudflare/workers-types': + specifier: 'catalog:' + version: 4.20260605.1 + '@types/node': + specifier: 'catalog:' + version: 24.12.4 + '@typescript/native-preview': + specifier: 'catalog:' + version: 7.0.0-dev.20260514.1 + drizzle-kit: + specifier: 'catalog:' + version: 0.31.10 + typescript: + specifier: 'catalog:' + version: 5.9.3 + vitest: + specifier: 'catalog:' + version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) + wrangler: + specifier: 'catalog:' + version: 4.112.0(@cloudflare/workers-types@4.20260605.1)(@types/node@24.12.4)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + services/ai-attribution: dependencies: '@kilocode/worker-utils': @@ -2534,7 +2647,7 @@ importers: dependencies: '@modelcontextprotocol/sdk': specifier: 1.30.0 - version: 1.30.0(zod@4.4.3) + version: 1.30.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) aws4fetch: specifier: 'catalog:' version: 1.0.20 @@ -2842,7 +2955,7 @@ importers: version: 0.28.1 openclaw: specifier: 2026.7.1 - version: 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) vitest: specifier: 'catalog:' version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) @@ -2866,7 +2979,7 @@ importers: version: 0.28.1 openclaw: specifier: 2026.7.1 - version: 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) + version: 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) vitest: specifier: 'catalog:' version: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) @@ -3410,6 +3523,9 @@ packages: '@apple/app-store-server-library@3.1.0': resolution: {integrity: sha512-d26SICRz8BwCV2qPR0BSXBMxmw0NEvJLwsdREcBmCrus8NmyHw2XgOOP0fiFjcctPn/JXtmSDuGVnaHe+dqO+A==} + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@asamuzakjp/css-color@5.1.11': resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -4336,6 +4452,9 @@ packages: resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + '@chat-adapter/github@4.36.0': resolution: {integrity: sha512-uAM3qM7W8RPQc859SgSdfK1UYm/eX33QJW7c0ej4tp+XxSDp5hBF6iNiUFLAEqcQ0anBy1U8D8r6+K/ewllmOA==} engines: {node: '>=20'} @@ -4626,10 +4745,21 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + '@csstools/color-helpers@6.1.0': resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} engines: {node: '>=20.19.0'} + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-calc@3.3.0': resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} engines: {node: '>=20.19.0'} @@ -4637,6 +4767,13 @@ packages: '@csstools/css-parser-algorithms': ^4.0.0 '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-color-parser@4.1.10': resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==} engines: {node: '>=20.19.0'} @@ -4644,6 +4781,12 @@ packages: '@csstools/css-parser-algorithms': ^4.0.0 '@csstools/css-tokenizer': ^4.0.0 + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms@4.0.0': resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} engines: {node: '>=20.19.0'} @@ -4658,6 +4801,10 @@ packages: css-tree: optional: true + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@csstools/css-tokenizer@4.0.0': resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} engines: {node: '>=20.19.0'} @@ -5559,6 +5706,16 @@ packages: resolution: {integrity: sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/environment-jsdom-abstract@30.3.0': + resolution: {integrity: sha512-0hNFs5N6We3DMCwobzI0ydhkY10sT1tZSC0AAiy+0g2Dt/qEWgrcV5BrMxPczhe41cxW4qm6X+jqZaUdpZIajA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + jsdom: '*' + peerDependenciesMeta: + canvas: + optional: true + '@jest/environment@29.7.0': resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -7966,7 +8123,6 @@ packages: '@rocicorp/resolver@1.0.2': resolution: {integrity: sha512-TfjMTQp9cNNqNtHFfa+XHEGdA7NnmDRu+ZJH4YF3dso0Xk/b9DMhg/sl+b6CR4ThFZArXXDsG1j8Mwl34wcOZQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - deprecated: Use Promise.withResolvers instead '@rolldown/binding-android-arm64@1.0.3': resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} @@ -9636,6 +9792,21 @@ packages: resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + '@testing-library/react@16.3.0': + resolution: {integrity: sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@testing-library/react@16.3.2': resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} engines: {node: '>=18'} @@ -9834,6 +10005,9 @@ packages: '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -9914,6 +10088,9 @@ packages: '@types/tar-stream@3.1.4': resolution: {integrity: sha512-921gW0+g29mCJX0fRvqeHzBlE/XclDaAG0Ousy1LCghsOhvaKacDeRGEVzQP9IPfKn8Vysy7FEXAIxycpc/CMg==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -11658,6 +11835,10 @@ packages: cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -11720,6 +11901,10 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + data-urls@7.0.0: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -12408,7 +12593,6 @@ packages: eslint@9.39.4: resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -12925,6 +13109,10 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + fake-indexeddb@6.2.4: + resolution: {integrity: sha512-INKeIKEtSViN4yVtEWEUqbsqmaIy7Ls+MfU0yxQVXg67pOJ/sH1ZxcVrP8XrKULUFohcPD9gnmym+qBfEybACw==} + engines: {node: '>=18'} + fast-check@4.8.0: resolution: {integrity: sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==} engines: {node: '>=12.17.0'} @@ -13531,6 +13719,10 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + html-encoding-sniffer@6.0.0: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -13641,6 +13833,9 @@ packages: idb-keyval@6.2.2: resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} + idb@8.0.3: + resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -14117,6 +14312,15 @@ packages: resolution: {integrity: sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-environment-jsdom@30.3.0: + resolution: {integrity: sha512-RLEOJy6ip1lpw0yqJ8tB3i88FC7VBz7i00Zvl2qF71IdxjS98gC9/0SPWYIBVXHm5hgCYK0PAlSlnHGGy9RoMg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -14394,6 +14598,15 @@ packages: jsc-safe-url@0.2.4: resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsdom@29.1.1: resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} @@ -14463,7 +14676,6 @@ packages: jsrsasign@11.1.3: resolution: {integrity: sha512-nPnK5D/4lv0Dwr7TlzrKtAd8JlLZwFTqTUUB3NQCbtdobcRcohGFxjbPySDVh74iWUudcCsapYT6OxoyhJLhhA==} - deprecated: This package is no longer maintained. jsx-ast-utils-x@0.1.0: resolution: {integrity: sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw==} @@ -15478,6 +15690,9 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + nwsapi@2.2.24: + resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} + nyc@15.1.0: resolution: {integrity: sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==} engines: {node: '>=8.9'} @@ -16924,6 +17139,9 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + rtl-detect@1.1.2: resolution: {integrity: sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==} @@ -17736,9 +17954,16 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + tldts-core@7.0.30: resolution: {integrity: sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==} + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + tldts@7.0.30: resolution: {integrity: sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==} hasBin: true @@ -17781,6 +18006,10 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + tough-cookie@6.0.2: resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} @@ -18886,6 +19115,14 @@ snapshots: transitivePeerDependencies: - encoding + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@asamuzakjp/css-color@5.1.11': dependencies: '@asamuzakjp/generational-cache': 1.0.1 @@ -20294,6 +20531,8 @@ snapshots: dependencies: css-tree: 3.2.1 + '@cfworker/json-schema@4.1.1': {} + '@chat-adapter/github@4.36.0(ai@7.0.29(zod@4.4.3))(zod@4.4.3)': dependencies: '@chat-adapter/shared': 4.36.0(ai@7.0.29(zod@4.4.3))(zod@4.4.3) @@ -20362,15 +20601,15 @@ snapshots: - workflow - zod - '@chromatic-com/playwright@0.12.8(@playwright/test@1.58.2)(@swc/core@1.15.18)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)(utf-8-validate@6.0.6)': + '@chromatic-com/playwright@0.12.8(@playwright/test@1.58.2)(@swc/core@1.15.18)(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: '@chromaui/rrweb-snapshot': 2.0.0-alpha.18-noAbsolute '@playwright/test': 1.58.2 '@segment/analytics-node': 2.1.3 - '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@storybook/csf': 0.1.13 - '@storybook/manager-api': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/server-webpack5': 8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) + '@storybook/manager-api': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/server-webpack5': 8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 transitivePeerDependencies: @@ -20395,9 +20634,9 @@ snapshots: '@chromaui/rrweb-snapshot': 2.0.0-alpha.18-noAbsolute '@playwright/test': 1.58.2 '@segment/analytics-node': 2.1.3 - '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-essentials': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@storybook/csf': 0.1.13 - '@storybook/manager-api': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/manager-api': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@storybook/server-webpack5': 8.5.8(esbuild@0.28.1)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 @@ -20870,13 +21109,27 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@csstools/color-helpers@5.1.0': {} + '@csstools/color-helpers@6.1.0': {} + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/color-helpers': 6.1.0 @@ -20884,6 +21137,10 @@ snapshots: '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': dependencies: '@csstools/css-tokenizer': 4.0.0 @@ -20892,6 +21149,8 @@ snapshots: optionalDependencies: css-tree: 3.2.1 + '@csstools/css-tokenizer@3.0.4': {} + '@csstools/css-tokenizer@4.0.0': {} '@cto.af/wtf8@0.0.5': {} @@ -21976,14 +22235,14 @@ snapshots: '@fregante/relaxed-json@2.0.0': {} - '@google/genai@2.10.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6)': + '@google/genai@2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6)': dependencies: google-auth-library: 10.6.2 p-retry: 4.6.2 protobufjs: 7.6.5 ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) transitivePeerDependencies: - bufferutil - supports-color @@ -22269,6 +22528,17 @@ snapshots: '@jest/diff-sequences@30.3.0': {} + '@jest/environment-jsdom-abstract@30.3.0(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + dependencies: + '@jest/environment': 30.3.0 + '@jest/fake-timers': 30.3.0 + '@jest/types': 30.3.0 + '@types/jsdom': 21.1.7 + '@types/node': 24.12.4 + jest-mock: 30.3.0 + jest-util: 30.3.0 + jsdom: 26.1.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 @@ -23011,7 +23281,7 @@ snapshots: - bufferutil - utf-8-validate - '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': + '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3)': dependencies: '@hono/node-server': 1.19.17(hono@4.12.34) ajv: 8.20.0 @@ -23030,10 +23300,12 @@ snapshots: raw-body: 3.0.2 zod: 4.4.3 zod-to-json-schema: 3.25.1(zod@4.4.3) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 transitivePeerDependencies: - supports-color - '@modelcontextprotocol/sdk@1.30.0(zod@4.4.3)': + '@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.4.3)': dependencies: '@hono/node-server': 2.0.10(hono@4.12.34) ajv: 8.20.0 @@ -23052,6 +23324,8 @@ snapshots: raw-body: 3.0.2 zod: 4.4.3 zod-to-json-schema: 3.25.1(zod@4.4.3) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 transitivePeerDependencies: - supports-color @@ -23309,10 +23583,10 @@ snapshots: '@open-draft/deferred-promise@2.2.0': {} - '@openclaw/ai@2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.4.3)': + '@openclaw/ai@2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.4.3)': dependencies: '@anthropic-ai/sdk': 0.109.1(zod@4.4.3) - '@google/genai': 2.10.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@google/genai': 2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@mistralai/mistralai': 2.4.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) openai: 6.45.0(@aws-sdk/credential-provider-node@3.972.21)(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.4.3) partial-json: 0.1.7 @@ -25986,7 +26260,7 @@ snapshots: '@stitches/core@1.2.8': {} - '@storybook/addon-actions@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-actions@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 @@ -25995,14 +26269,14 @@ snapshots: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) uuid: 11.1.1 - '@storybook/addon-backgrounds@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-backgrounds@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 - '@storybook/addon-controls@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-controls@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 dequal: 2.0.3 @@ -26028,12 +26302,12 @@ snapshots: - vite - webpack - '@storybook/addon-docs@8.5.8(@types/react@19.2.14)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-docs@8.5.8(@types/react@19.2.14)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.6) - '@storybook/blocks': 8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/csf-plugin': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/react-dom-shim': 8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/blocks': 8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/csf-plugin': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/react-dom-shim': 8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) react: 19.2.6 react-dom: 19.2.6(react@19.2.6) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) @@ -26041,49 +26315,49 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@storybook/addon-essentials@8.5.8(@types/react@19.2.14)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': - dependencies: - '@storybook/addon-actions': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-backgrounds': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-controls': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-docs': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-highlight': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-measure': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-outline': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-toolbars': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/addon-viewport': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-essentials@8.5.8(@types/react@19.2.14)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + dependencies: + '@storybook/addon-actions': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-backgrounds': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-controls': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-docs': 8.5.8(@types/react@19.2.14)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-highlight': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-measure': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-outline': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-toolbars': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/addon-viewport': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-highlight@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-highlight@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) - '@storybook/addon-measure@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-measure@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) tiny-invariant: 1.3.3 - '@storybook/addon-outline@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-outline@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/global': 5.0.0 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 - '@storybook/addon-toolbars@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-toolbars@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) - '@storybook/addon-viewport@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/addon-viewport@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: memoizerific: 1.11.3 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) - '@storybook/blocks@8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/blocks@8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: '@storybook/csf': 0.1.12 '@storybook/icons': 1.6.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -26120,9 +26394,9 @@ snapshots: - uglify-js - webpack-cli - '@storybook/builder-webpack5@8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': + '@storybook/builder-webpack5@8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': dependencies: - '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@types/semver': 7.7.1 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 @@ -26158,7 +26432,7 @@ snapshots: '@storybook/builder-webpack5@8.5.8(esbuild@0.28.1)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': dependencies: - '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@types/semver': 7.7.1 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 @@ -26193,7 +26467,7 @@ snapshots: - webpack-cli optional: true - '@storybook/components@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/components@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) @@ -26202,7 +26476,7 @@ snapshots: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 - '@storybook/core-webpack@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/core-webpack@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 @@ -26217,7 +26491,7 @@ snapshots: vite: 8.0.16(@types/node@25.5.2)(esbuild@0.28.1)(jiti@2.7.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) webpack: 5.105.4(esbuild@0.28.1) - '@storybook/csf-plugin@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/csf-plugin@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) unplugin: 1.16.1 @@ -26242,7 +26516,7 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - '@storybook/manager-api@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/manager-api@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) @@ -26331,17 +26605,17 @@ snapshots: - uglify-js - webpack-cli - '@storybook/preset-server-webpack@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/preset-server-webpack@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: - '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/core-webpack': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@storybook/global': 5.0.0 - '@storybook/server': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/server': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) safe-identifier: 0.4.2 storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 yaml-loader: 0.8.1 - '@storybook/preview-api@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/preview-api@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) @@ -26368,7 +26642,7 @@ snapshots: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) - '@storybook/react-dom-shim@8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/react-dom-shim@8.5.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) @@ -26390,11 +26664,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/server-webpack5@8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': + '@storybook/server-webpack5@8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': dependencies: - '@storybook/builder-webpack5': 8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) - '@storybook/preset-server-webpack': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/server': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/builder-webpack5': 8.5.8(@swc/core@1.15.18)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) + '@storybook/preset-server-webpack': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/server': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) transitivePeerDependencies: - '@rspack/core' @@ -26407,8 +26681,8 @@ snapshots: '@storybook/server-webpack5@8.5.8(esbuild@0.28.1)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3)': dependencies: '@storybook/builder-webpack5': 8.5.8(esbuild@0.28.1)(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))(typescript@5.9.3) - '@storybook/preset-server-webpack': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/server': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/preset-server-webpack': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/server': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) transitivePeerDependencies: - '@rspack/core' @@ -26419,14 +26693,14 @@ snapshots: - webpack-cli optional: true - '@storybook/server@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/server@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: - '@storybook/components': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/components': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) '@storybook/csf': 0.1.12 '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/preview-api': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) - '@storybook/theming': 8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/manager-api': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/preview-api': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) + '@storybook/theming': 8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6)) storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) ts-dedent: 2.2.0 yaml: 2.8.4 @@ -26465,7 +26739,7 @@ snapshots: - supports-color - ts-node - '@storybook/theming@8.5.8(storybook@10.4.6(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': + '@storybook/theming@8.5.8(storybook@10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6))': dependencies: storybook: 10.4.6(@testing-library/dom@10.4.1)(@types/react@19.2.14)(bufferutil@4.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(utf-8-validate@6.0.6) @@ -26802,6 +27076,16 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 + '@testing-library/react@16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + dependencies: + '@babel/runtime': 7.29.7 + '@testing-library/dom': 10.4.1 + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@babel/runtime': 7.29.7 @@ -27021,6 +27305,12 @@ snapshots: '@types/js-yaml@4.0.9': {} + '@types/jsdom@21.1.7': + dependencies: + '@types/node': 24.12.4 + '@types/tough-cookie': 4.0.5 + parse5: 7.3.0 + '@types/json-schema@7.0.15': {} '@types/jsonwebtoken@9.0.10': @@ -27108,6 +27398,8 @@ snapshots: dependencies: '@types/node': 24.12.4 + '@types/tough-cookie@4.0.5': {} + '@types/trusted-types@2.0.7': optional: true @@ -27354,7 +27646,7 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) + vitest: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) '@vitest/expect@3.2.4': dependencies: @@ -27432,7 +27724,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vitest: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@25.5.2)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) + vitest: 4.1.6(@opentelemetry/api@1.9.1)(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(@vitest/ui@4.1.6)(esbuild@0.28.1)(jiti@2.7.0)(jsdom@29.1.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.4) '@vitest/utils@3.2.4': dependencies: @@ -29050,6 +29342,11 @@ snapshots: cssom@0.5.0: {} + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + csstype@3.2.3: {} csv-parse@6.2.1: {} @@ -29104,6 +29401,11 @@ snapshots: data-uri-to-buffer@4.0.1: {} + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + data-urls@7.0.0: dependencies: whatwg-mimetype: 5.0.0 @@ -30592,6 +30894,8 @@ snapshots: extend@3.0.2: {} + fake-indexeddb@6.2.4: {} + fast-check@4.8.0: dependencies: pure-rand: 8.4.0 @@ -31281,6 +31585,10 @@ snapshots: dependencies: lru-cache: 10.4.3 + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + html-encoding-sniffer@6.0.0: dependencies: '@exodus/bytes': 1.15.1 @@ -31409,6 +31717,8 @@ snapshots: idb-keyval@6.2.2: {} + idb@8.0.3: {} + ieee754@1.2.1: {} ignore@5.3.2: {} @@ -32009,6 +32319,16 @@ snapshots: jest-util: 30.3.0 pretty-format: 30.3.0 + jest-environment-jsdom@30.3.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + '@jest/environment': 30.3.0 + '@jest/environment-jsdom-abstract': 30.3.0(jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + jsdom: 26.1.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jest-environment-node@29.7.0: dependencies: '@jest/environment': 29.7.0 @@ -32551,6 +32871,33 @@ snapshots: jsc-safe-url@0.2.4: {} + jsdom@26.1.0(bufferutil@4.1.0)(utf-8-validate@6.0.6): + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.24 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsdom@29.1.1: dependencies: '@asamuzakjp/css-color': 5.1.11 @@ -34156,6 +34503,8 @@ snapshots: nullthrows@1.1.1: {} + nwsapi@2.2.24: {} + nyc@15.1.0: dependencies: '@istanbuljs/load-nyc-config': 1.1.0 @@ -34303,22 +34652,22 @@ snapshots: ws: 8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) zod: 4.4.3 - openclaw@2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6): + openclaw@2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@cfworker/json-schema@4.1.1)(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6): dependencies: '@agentclientprotocol/sdk': 1.1.0(zod@4.4.3) '@anthropic-ai/sdk': 0.109.1(zod@4.4.3) '@clack/core': 1.4.2 '@clack/prompts': 1.6.0 '@earendil-works/pi-tui': 0.80.3 - '@google/genai': 2.10.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6) + '@google/genai': 2.10.0(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@grammyjs/runner': 2.0.3(grammy@1.44.0) '@grammyjs/transformer-throttler': 1.2.1(grammy@1.44.0) '@homebridge/ciao': 1.3.9 '@lydell/node-pty': 1.2.0-beta.12 '@mistralai/mistralai': 2.4.0(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6) - '@modelcontextprotocol/sdk': 1.29.0(zod@4.4.3) + '@modelcontextprotocol/sdk': 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3) '@mozilla/readability': 0.6.0 - '@openclaw/ai': 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.4.3) + '@openclaw/ai': 2026.7.1(@aws-sdk/credential-provider-node@3.972.21)(@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(@opentelemetry/api@1.9.1)(bufferutil@4.1.0)(utf-8-validate@6.0.6)(ws@8.21.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.4.3) '@openclaw/fs-safe': 0.4.1 '@openclaw/proxyline': 0.3.3(undici@8.9.0) '@silvia-odwyer/photon-node': 0.3.4 @@ -36186,6 +36535,8 @@ snapshots: transitivePeerDependencies: - supports-color + rrweb-cssom@0.8.0: {} + rtl-detect@1.1.2: {} run-applescript@7.1.0: {} @@ -37114,8 +37465,14 @@ snapshots: tinyspy@4.0.4: {} + tldts-core@6.1.86: {} + tldts-core@7.0.30: {} + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + tldts@7.0.30: dependencies: tldts-core: 7.0.30 @@ -37150,6 +37507,10 @@ snapshots: totalist@3.0.1: {} + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + tough-cookie@6.0.2: dependencies: tldts: 7.0.30 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9abae0bd2e..72780e1eb9 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -158,8 +158,13 @@ patchedDependencies: expo-router@57.0.15: patches/expo-router@57.0.15.patch expo-server-sdk: patches/expo-server-sdk.patch react-native-appsflyer@6.18.0: patches/react-native-appsflyer@6.18.0.patch +# Exclude jsdom declarations from both hoists; Vitest otherwise adds DOM globals to Workers. +hoistPattern: + - '*' + - '!@types/jsdom' publicHoistPattern: - '@types/*' + - '!@types/jsdom' - '*import-in-the-middle*' - '*require-in-the-middle*' - metro diff --git a/scripts/agent-harness-ci.test.mjs b/scripts/agent-harness-ci.test.mjs new file mode 100644 index 0000000000..1cdcaee963 --- /dev/null +++ b/scripts/agent-harness-ci.test.mjs @@ -0,0 +1,272 @@ +import assert from 'node:assert/strict'; +import { execFileSync, spawnSync } from 'node:child_process'; +import { + globSync, + mkdirSync, + mkdtempSync, + readFileSync, + realpathSync, + rmSync, + symlinkSync, + writeFileSync, +} from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join, matchesGlob } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import test from 'node:test'; +import { load } from 'js-yaml'; +import jestConfig from '../apps/web/jest.config.ts'; + +const root = fileURLToPath(new URL('../', import.meta.url)); +const web = join(root, 'apps/web'); +const run = (command, args, cwd = root, env = process.env) => + execFileSync(command, args, { cwd, env, encoding: 'utf8' }); +const read = path => readFileSync(join(root, path), 'utf8'); +function fixture(t, modules = root) { + const directory = realpathSync(mkdtempSync(join(tmpdir(), 'harness-ci-'))); + t.after(() => rmSync(directory, { recursive: true, force: true })); + symlinkSync(join(modules, 'node_modules'), join(directory, 'node_modules'), 'dir'); + const write = (path, content) => { + mkdirSync(dirname(join(directory, path)), { recursive: true }); + writeFileSync(join(directory, path), content); + }; + return { directory, write }; +} + +test('stack-base PRs retain root and mobile checks for portable changes', () => { + for (const path of ['.github/workflows/ci.yml', '.github/workflows/kilo-app-ci.yml']) { + const workflow = load(read(path)); + assert.ok(Object.hasOwn(workflow.on, 'pull_request')); + assert.equal(workflow.on.pull_request?.branches, undefined, path); + assert.equal(workflow.on.pull_request?.['branches-ignore'], undefined, path); + assert.deepEqual(workflow.on.push.branches, ['main']); + if (path.endsWith('kilo-app-ci.yml')) { + for (const event of ['push', 'pull_request']) { + assert.ok( + workflow.on[event].paths.some(pattern => + matchesGlob('packages/agent-harness/src/client.ts', pattern) + ) + ); + } + } else { + const steps = Object.values(workflow.jobs).flatMap(job => job.steps ?? []); + assert.ok(steps.some(step => step.run === 'pnpm run test:agent-harness-ci')); + const filters = load(steps.find(step => step.id === 'filter').with.filters); + assert.ok( + filters.kilocode_backend.some(pattern => + matchesGlob('packages/agent-harness/src/client.ts', pattern) + ) + ); + } + } +}); + +test('pnpm discovers both harness workspaces and resolves the portable root', () => { + const workspaces = JSON.parse( + run('pnpm', [ + '--filter', + '@kilocode/agent-harness', + '--filter', + '@kilocode/agent-harness-worker', + 'ls', + '--json', + '--depth', + '-1', + ]) + ); + assert.deepEqual(workspaces.map(workspace => workspace.name).sort(), [ + '@kilocode/agent-harness', + '@kilocode/agent-harness-worker', + ]); + run( + process.execPath, + ['--input-type=module', '-e', "await import('@kilocode/agent-harness')"], + web + ); +}); + +test('workspace selection uses the PR target/head, pushed range, and local fallback', t => { + const { directory, write } = fixture(t); + const git = (...args) => + run('git', args, directory, { + ...process.env, + GIT_AUTHOR_NAME: 'Fixture', + GIT_COMMITTER_NAME: 'Fixture', + GIT_AUTHOR_EMAIL: 'fixture@example.invalid', + GIT_COMMITTER_EMAIL: 'fixture@example.invalid', + }).trim(); + const commit = () => { + git('add', '.'); + git('commit', '-qm', 'fixture'); + return git('rev-parse', 'HEAD'); + }; + git('init', '-q'); + write('.gitignore', 'node_modules\nevent.json\n'); + write('package.json', JSON.stringify({ private: true, packageManager: 'pnpm@11.1.2' })); + write('pnpm-workspace.yaml', 'packages:\n - services/*\n - packages/*\n'); + for (const path of ['scripts/changed-workspaces.sh', 'scripts/changed-dependencies.mjs']) + write(path, read(path)); + const names = ['lower', 'base-only', '@kilocode/agent-harness-worker', '@kilocode/agent-harness']; + const dirs = [ + 'services/lower', + 'services/base-only', + 'services/agent-harness', + 'packages/agent-harness', + ]; + dirs.forEach((dir, index) => { + write( + `${dir}/package.json`, + JSON.stringify({ name: names[index], scripts: { test: 'vitest run' } }) + ); + write(`${dir}/src/probe.test.ts`, 'export {};'); + }); + const lock = { + lockfileVersion: '9.0', + settings: {}, + importers: Object.fromEntries(['.', ...dirs].map(dir => [dir, {}])), + packages: { 'leaf@1.0.0': {}, 'leaf@2.0.0': {} }, + snapshots: { 'leaf@1.0.0': {}, 'leaf@2.0.0': {} }, + }; + lock.importers['services/agent-harness'] = { dependencies: { leaf: { version: '1.0.0' } } }; + write('pnpm-lock.yaml', JSON.stringify(lock)); + const main = commit(); + git('update-ref', 'refs/remotes/origin/main', main); + write('services/lower/src/probe.test.ts', 'export const lower = 1;'); + const stack = commit(); + write('packages/agent-harness/src/probe.test.ts', 'export const feature = 1;'); + lock.importers['services/agent-harness'].dependencies.leaf.version = '2.0.0'; + write('pnpm-lock.yaml', JSON.stringify(lock)); + commit(); + write('services/agent-harness/src/probe.test.ts', 'export const feature = 1;'); + const head = commit(); + git('checkout', '-q', '--detach', stack); + write('services/base-only/src/probe.test.ts', 'export const base = 1;'); + write('pnpm-lock.yaml', JSON.stringify({ ...lock, settings: { changedOnBase: true } })); + const base = commit(); + git('checkout', '-q', '--detach', head); + write('services/base-only/src/probe.test.ts', 'export const base = 1;'); + write('pnpm-lock.yaml', JSON.stringify({ ...lock, settings: { changedOnBase: true } })); + commit(); + const selected = (event, payload) => { + write('event.json', JSON.stringify(payload)); + return JSON.parse( + run('bash', ['scripts/changed-workspaces.sh'], directory, { + ...process.env, + GITHUB_EVENT_NAME: event, + GITHUB_EVENT_PATH: join(directory, 'event.json'), + }) + ) + .map(workspace => workspace.name) + .sort(); + }; + const harnesses = ['@kilocode/agent-harness', '@kilocode/agent-harness-worker']; + assert.deepEqual( + selected('pull_request', { pull_request: { base: { sha: base }, head: { sha: head } } }), + harnesses + ); + git('checkout', '-q', '--detach', head); + assert.deepEqual(selected('push', { before: stack }), harnesses); + for (const before of ['0'.repeat(40), 'f'.repeat(40)]) + assert.deepEqual(selected('push', { before }), ['@kilocode/agent-harness-worker']); + write('services/base-only/src/probe.test.ts', 'export const local = 1;'); + assert.deepEqual(selected('', {}), [...names].sort()); +}); + +test('Vitest declarations preserve Worker byte responses and timingSafeEqual without DOM types', t => { + const { directory, write } = fixture(t, join(root, 'services/agent-harness')); + write( + 'tsconfig.json', + JSON.stringify({ + compilerOptions: { + target: 'ESNext', + module: 'ESNext', + moduleResolution: 'Bundler', + lib: ['ESNext'], + types: ['node', '@cloudflare/workers-types'], + strict: true, + skipLibCheck: true, + declaration: true, + emitDeclarationOnly: true, + noEmitOnError: true, + outDir: 'declarations', + }, + files: ['probe.ts'], + }) + ); + for (const withVitest of [false, true]) { + write( + 'probe.ts', + `${withVitest ? "import 'vitest/config';" : ''} +export function byteResponse(bytes: Uint8Array) { + return new Response(bytes); +} +export function safeEqual(left: ArrayBuffer, right: ArrayBuffer) { + return crypto.subtle.timingSafeEqual(left, right); +}` + ); + const result = spawnSync( + process.execPath, + [ + join(root, 'node_modules/@typescript/native-preview/bin/tsgo.js'), + '-p', + directory, + '--listFiles', + ], + { cwd: directory, encoding: 'utf8' } + ); + assert.equal(result.status, 0, result.stdout + result.stderr); + assert.doesNotMatch(result.stdout, /[/\\]lib\.dom(?:\.iterable)?\.d\.ts/); + if (withVitest) assert.match(result.stdout, /vitest[/\\]optional-types\.d\.ts/); + assert.match( + readFileSync(join(directory, 'declarations/probe.d.ts'), 'utf8'), + /export declare function safeEqual\(left: ArrayBuffer, right: ArrayBuffer\): boolean;/ + ); + } +}); + +test('Jest discovers every harness TSX test without expanding unrelated discovery', t => { + const jest = (...args) => + run( + process.execPath, + [join(web, 'node_modules/jest/bin/jest.js'), '--runInBand', ...args], + web + ); + const expected = globSync('src/components/quick-chat/**/*.test.tsx', { cwd: web }) + .map(path => join(web, path)) + .sort(); + const discovered = JSON.parse( + jest('--listTests', '--json', '--testPathPatterns', 'src/components/quick-chat/') + ); + assert.deepEqual(discovered.filter(path => path.endsWith('.test.tsx')).sort(), expected); + const { directory, write } = fixture(t, web); + const component = 'src/components/quick-chat/nested/probe.test.tsx'; + const server = 'src/lib/probe.test.ts'; + write( + component, + `/** @jest-environment jsdom */ +import { render, screen } from '@testing-library/react'; +test('renders TSX without a React import', () => { + render(); + expect(screen.getByRole('button', { name: 'Ready' }).textContent).toBe('Ready'); +});` + ); + write( + server, + "test('keeps server tests in Node', () => expect(typeof window).toBe('undefined')); " + ); + write( + 'src/components/unrelated/excluded.test.tsx', + "throw new Error('Unrelated discovery expanded');" + ); + const config = JSON.stringify({ + ...jestConfig, + rootDir: directory, + globalSetup: undefined, + setupFilesAfterEnv: [], + }); + assert.deepEqual( + JSON.parse(jest('--config', config, '--listTests', '--json')).sort(), + [component, server].map(path => join(directory, path)).sort() + ); + jest('--config', config, '--runTestsByPath', join(directory, component), join(directory, server)); +}); diff --git a/scripts/changed-workspaces.sh b/scripts/changed-workspaces.sh index 5aeda1d201..9c3ff21758 100755 --- a/scripts/changed-workspaces.sh +++ b/scripts/changed-workspaces.sh @@ -25,12 +25,18 @@ done # the pushed range. `git merge-base origin/main HEAD` on a push to main # resolves to HEAD, which would produce an empty matrix and skip the # workspace-tests job. -# - `pull_request` event (and locally with no GitHub env): use the merge-base -# against origin/main to preserve prior PR behavior. +# - `pull_request` event: compare the actual head with its target merge-base, +# not origin/main or the synthetic merge checkout. This also handles stacked PRs. +# - Locally with no GitHub env: retain the merge-base against origin/main. # - All-zeros before-sha (force-push / first push / branch creation) or any # invalid/unreachable before-sha falls back to HEAD~1. base="" -if [ "${GITHUB_EVENT_NAME:-}" = "push" ] && [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -f "$GITHUB_EVENT_PATH" ]; then +head="" +if [ "${GITHUB_EVENT_NAME:-}" = "pull_request" ] && [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -f "$GITHUB_EVENT_PATH" ]; then + head=$(jq -er '.pull_request.head.sha' "$GITHUB_EVENT_PATH") + target=$(jq -er '.pull_request.base.sha' "$GITHUB_EVENT_PATH") + base=$(git merge-base "$target" "$head") +elif [ "${GITHUB_EVENT_NAME:-}" = "push" ] && [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -f "$GITHUB_EVENT_PATH" ]; then before=$(jq -r '.before // ""' "$GITHUB_EVENT_PATH" 2>/dev/null || true) if [ -n "$before" ] \ && [ "$before" != "0000000000000000000000000000000000000000" ] \ @@ -43,12 +49,15 @@ else base=$(git merge-base origin/main HEAD 2>/dev/null || true) fi +revisions=("$base") +[ -z "$head" ] || revisions+=("$head") + force_all=false dependent_dirs_file=$(mktemp) trap 'rm -f "$dependent_dirs_file"' EXIT if [ -n "$base" ]; then - if ! git diff --quiet "$base" -- pnpm-lock.yaml pnpm-workspace.yaml 'patches/**'; then - if ! node scripts/changed-dependencies.mjs "$base" > "$dependent_dirs_file"; then + if ! git diff --quiet "${revisions[@]}" -- pnpm-lock.yaml pnpm-workspace.yaml 'patches/**'; then + if ! node scripts/changed-dependencies.mjs "${revisions[@]}" > "$dependent_dirs_file"; then force_all=true elif grep -qxF '*' "$dependent_dirs_file"; then force_all=true @@ -58,7 +67,7 @@ if [ -n "$base" ]; then # List files changed under packages/**. Anything that doesn't match # `packages//` (e.g. `packages/README.md`) is a loose file with no # single owning package — fall back to force_all. - pkg_changes=$(git diff --name-only "$base" -- 'packages/**' || true) + pkg_changes=$(git diff --name-only "${revisions[@]}" -- 'packages/**' || true) if [ -n "$pkg_changes" ]; then loose=$(printf '%s\n' "$pkg_changes" | grep -vE '^packages/[^/]+/' | head -1 || true) if [ -n "$loose" ]; then @@ -128,7 +137,7 @@ for dir in $workspace_dirs; do if [ -s "$dependent_dirs_file" ] && grep -qxF "$dir" "$dependent_dirs_file"; then : else - changed_file=$(git diff --name-only "$base" -- "$dir/" | head -1 || true) + changed_file=$(git diff --name-only "${revisions[@]}" -- "$dir/" | head -1 || true) [ -n "$changed_file" ] || continue fi fi diff --git a/services/agent-harness/package.json b/services/agent-harness/package.json new file mode 100644 index 0000000000..6185622a98 --- /dev/null +++ b/services/agent-harness/package.json @@ -0,0 +1,39 @@ +{ + "name": "@kilocode/agent-harness-worker", + "version": "0.0.1", + "private": true, + "type": "module", + "exports": { + "./*.test": null, + "./*": "./src/*.ts" + }, + "scripts": { + "test": "vitest run", + "typecheck": "tsgo --noEmit", + "lint": "oxlint --config ../../.oxlintrc.json", + "format": "oxfmt" + }, + "dependencies": { + "@ai-sdk/openai-compatible": "3.0.11", + "@cfworker/json-schema": "4.1.1", + "@kilocode/agent-harness": "workspace:*", + "@kilocode/mcp-gateway": "workspace:*", + "@kilocode/worker-utils": "workspace:*", + "@modelcontextprotocol/sdk": "1.30.0", + "ai": "7.0.29", + "drizzle-orm": "catalog:", + "hono": "catalog:", + "jose": "catalog:", + "zod": "catalog:" + }, + "devDependencies": { + "@cloudflare/vitest-pool-workers": "catalog:", + "@cloudflare/workers-types": "catalog:", + "@types/node": "catalog:", + "@typescript/native-preview": "catalog:", + "drizzle-kit": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:", + "wrangler": "catalog:" + } +} diff --git a/services/agent-harness/tsconfig.json b/services/agent-harness/tsconfig.json new file mode 100644 index 0000000000..5d61aa6df8 --- /dev/null +++ b/services/agent-harness/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022"], + "types": ["@cloudflare/workers-types", "node"], + "strict": true, + "skipLibCheck": true, + "noEmit": true, + "isolatedModules": true, + "resolveJsonModule": true + }, + "include": ["src/**/*.ts", "vitest.config.ts", "worker-configuration.d.ts"] +} diff --git a/services/agent-harness/vitest.config.ts b/services/agent-harness/vitest.config.ts new file mode 100644 index 0000000000..3941cf0e5b --- /dev/null +++ b/services/agent-harness/vitest.config.ts @@ -0,0 +1,18 @@ +import { existsSync } from 'node:fs'; +import { URL } from 'node:url'; +import { cloudflareTest } from '@cloudflare/vitest-pool-workers'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [ + cloudflareTest({ + // The deployment config arrives with the Worker entrypoint, not before it. + wrangler: existsSync(new URL('./wrangler.jsonc', import.meta.url)) + ? { configPath: './wrangler.jsonc' } + : undefined, + remoteBindings: false, + miniflare: { compatibilityDate: '2026-06-05', compatibilityFlags: ['nodejs_compat'] }, + }), + ], + test: { include: ['src/**/*.test.ts'], passWithNoTests: true }, +});