fix: resolve test failures across workspace

- packages/llm: use nullish coalescing (??) in GeminiProvider constructor
  so explicit empty-string apiKey is not overridden by env var
- dashboards/admin-web,tracker-web: exclude .next/ from vitest test glob
  to prevent Next.js internal test files from being picked up
- services/cowork-service: use platform-safe .kill() instead of SIGTERM
  which is invalid on Windows
- packages/use-keyboard-shortcuts: add @testing-library/react devDep
- scripts/npmrc.template: use https:// for Gitea registry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Saravanakumar D 2026-05-30 00:16:44 -07:00
parent e83ab9907e
commit fb47d939a7
6 changed files with 71 additions and 405 deletions

View File

@ -5,7 +5,7 @@ export default defineConfig({
test: {
environment: 'node',
globals: true,
exclude: ['e2e/**', 'node_modules/**'],
exclude: ['e2e/**', 'node_modules/**', '.next/**'],
// Inline the workspace SVG-chart packages so Vitest transforms them and
// resolves their `react` import through the dedupe below. Without this the
// chart dist (linked from a sibling repo's pnpm store) loads a second

View File

@ -5,7 +5,7 @@ export default defineConfig({
test: {
environment: 'node',
globals: true,
exclude: ['e2e/**', 'node_modules/**'],
exclude: ['e2e/**', 'node_modules/**', '.next/**'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],

View File

@ -32,8 +32,8 @@ export class GeminiProvider implements LLMProvider {
constructor(config?: Partial<GeminiConfig>) {
this.config = {
apiKey: config?.apiKey || process.env.GEMINI_API_KEY || '',
model: config?.model || process.env.GEMINI_MODEL || 'gemini-1.5-flash',
apiKey: config?.apiKey ?? process.env.GEMINI_API_KEY ?? '',
model: config?.model ?? process.env.GEMINI_MODEL ?? 'gemini-1.5-flash',
};
}

403
pnpm-lock.yaml generated
View File

@ -215,7 +215,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: 16.1.6
version: 16.1.6(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
version: 16.1.6(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
husky:
specifier: ^9.0.0
version: 9.1.7
@ -339,7 +339,7 @@ importers:
version: 9.39.2(jiti@2.6.1)
eslint-config-next:
specifier: 16.1.6
version: 16.1.6(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
version: 16.1.6(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
husky:
specifier: ^9.0.0
version: 9.1.7
@ -5910,20 +5910,6 @@ packages:
peerDependencies:
'@redis/client': ^1.0.0
'@reduxjs/toolkit@2.11.2':
resolution:
{
integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==,
}
peerDependencies:
react: ^16.9.0 || ^17.0.0 || ^18 || ^19
react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
peerDependenciesMeta:
react:
optional: true
react-redux:
optional: true
'@rollup/pluginutils@5.3.0':
resolution:
{
@ -6205,12 +6191,6 @@ packages:
integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==,
}
'@standard-schema/utils@0.3.0':
resolution:
{
integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==,
}
'@storybook/addon-a11y@8.6.18':
resolution:
{
@ -7027,60 +7007,6 @@ packages:
integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==,
}
'@types/d3-array@3.2.2':
resolution:
{
integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==,
}
'@types/d3-color@3.1.3':
resolution:
{
integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==,
}
'@types/d3-ease@3.0.2':
resolution:
{
integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==,
}
'@types/d3-interpolate@3.0.4':
resolution:
{
integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==,
}
'@types/d3-path@3.1.1':
resolution:
{
integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==,
}
'@types/d3-scale@4.0.9':
resolution:
{
integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==,
}
'@types/d3-shape@3.1.8':
resolution:
{
integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==,
}
'@types/d3-time@3.0.4':
resolution:
{
integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==,
}
'@types/d3-timer@3.0.2':
resolution:
{
integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==,
}
'@types/debug@4.1.12':
resolution:
{
@ -9024,83 +8950,6 @@ packages:
integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==,
}
d3-array@3.2.4:
resolution:
{
integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==,
}
engines: { node: '>=12' }
d3-color@3.1.0:
resolution:
{
integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==,
}
engines: { node: '>=12' }
d3-ease@3.0.1:
resolution:
{
integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==,
}
engines: { node: '>=12' }
d3-format@3.1.2:
resolution:
{
integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==,
}
engines: { node: '>=12' }
d3-interpolate@3.0.1:
resolution:
{
integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==,
}
engines: { node: '>=12' }
d3-path@3.1.0:
resolution:
{
integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==,
}
engines: { node: '>=12' }
d3-scale@4.0.2:
resolution:
{
integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==,
}
engines: { node: '>=12' }
d3-shape@3.2.0:
resolution:
{
integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==,
}
engines: { node: '>=12' }
d3-time-format@4.1.0:
resolution:
{
integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==,
}
engines: { node: '>=12' }
d3-time@3.1.0:
resolution:
{
integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==,
}
engines: { node: '>=12' }
d3-timer@3.0.1:
resolution:
{
integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==,
}
engines: { node: '>=12' }
damerau-levenshtein@1.0.8:
resolution:
{
@ -9176,12 +9025,6 @@ packages:
supports-color:
optional: true
decimal.js-light@2.5.1:
resolution:
{
integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==,
}
decimal.js@10.6.0:
resolution:
{
@ -9605,12 +9448,6 @@ packages:
}
engines: { node: '>= 0.4' }
es-toolkit@1.44.0:
resolution:
{
integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==,
}
esbuild-register@3.6.0:
resolution:
{
@ -10977,18 +10814,6 @@ packages:
engines: { node: '>=16.x' }
hasBin: true
immer@10.2.0:
resolution:
{
integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==,
}
immer@11.1.4:
resolution:
{
integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==,
}
import-fresh@2.0.0:
resolution:
{
@ -11049,13 +10874,6 @@ packages:
}
engines: { node: '>= 0.4' }
internmap@2.0.3:
resolution:
{
integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==,
}
engines: { node: '>=12' }
invariant@2.2.4:
resolution:
{
@ -14173,21 +13991,6 @@ packages:
'@types/react':
optional: true
react-redux@9.2.0:
resolution:
{
integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==,
}
peerDependencies:
'@types/react': ^18.2.25 || ^19
react: ^18.0 || ^19
redux: ^5.0.0
peerDependenciesMeta:
'@types/react':
optional: true
redux:
optional: true
react-refresh@0.14.2:
resolution:
{
@ -14282,17 +14085,6 @@ packages:
}
engines: { node: '>= 4' }
recharts@3.7.0:
resolution:
{
integrity: sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==,
}
engines: { node: '>=18' }
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
redent@3.0.0:
resolution:
{
@ -14306,20 +14098,6 @@ packages:
integrity: sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==,
}
redux-thunk@3.1.0:
resolution:
{
integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==,
}
peerDependencies:
redux: ^5.0.0
redux@5.0.1:
resolution:
{
integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==,
}
reflect.getprototypeof@1.0.10:
resolution:
{
@ -14411,12 +14189,6 @@ packages:
}
engines: { node: '>=0.10.0' }
reselect@5.1.1:
resolution:
{
integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==,
}
resolve-from@3.0.0:
resolution:
{
@ -15963,12 +15735,6 @@ packages:
integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==,
}
victory-vendor@37.3.6:
resolution:
{
integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==,
}
vite-node@3.2.4:
resolution:
{
@ -20143,18 +19909,6 @@ snapshots:
dependencies:
'@redis/client': 1.6.1
'@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.3)(redux@5.0.1))(react@19.2.3)':
dependencies:
'@standard-schema/spec': 1.1.0
'@standard-schema/utils': 0.3.0
immer: 11.1.4
redux: 5.0.1
redux-thunk: 3.1.0(redux@5.0.1)
reselect: 5.1.1
optionalDependencies:
react: 19.2.3
react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.3)(redux@5.0.1)
'@rollup/pluginutils@5.3.0(rollup@4.57.1)':
dependencies:
'@types/estree': 1.0.8
@ -20272,8 +20026,6 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
'@standard-schema/utils@0.3.0': {}
'@storybook/addon-a11y@8.6.18(storybook@8.6.18(prettier@3.8.1))':
dependencies:
'@storybook/addon-highlight': 8.6.18(storybook@8.6.18(prettier@3.8.1))
@ -20885,30 +20637,6 @@ snapshots:
'@types/deep-eql': 4.0.2
assertion-error: 2.0.1
'@types/d3-array@3.2.2': {}
'@types/d3-color@3.1.3': {}
'@types/d3-ease@3.0.2': {}
'@types/d3-interpolate@3.0.4':
dependencies:
'@types/d3-color': 3.1.3
'@types/d3-path@3.1.1': {}
'@types/d3-scale@4.0.9':
dependencies:
'@types/d3-time': 3.0.4
'@types/d3-shape@3.1.8':
dependencies:
'@types/d3-path': 3.1.1
'@types/d3-time@3.0.4': {}
'@types/d3-timer@3.0.2': {}
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
@ -22186,44 +21914,6 @@ snapshots:
csstype@3.2.3: {}
d3-array@3.2.4:
dependencies:
internmap: 2.0.3
d3-color@3.1.0: {}
d3-ease@3.0.1: {}
d3-format@3.1.2: {}
d3-interpolate@3.0.1:
dependencies:
d3-color: 3.1.0
d3-path@3.1.0: {}
d3-scale@4.0.2:
dependencies:
d3-array: 3.2.4
d3-format: 3.1.2
d3-interpolate: 3.0.1
d3-time: 3.1.0
d3-time-format: 4.1.0
d3-shape@3.2.0:
dependencies:
d3-path: 3.1.0
d3-time-format@4.1.0:
dependencies:
d3-time: 3.1.0
d3-time@3.1.0:
dependencies:
d3-array: 3.2.4
d3-timer@3.0.1: {}
damerau-levenshtein@1.0.8: {}
data-uri-to-buffer@4.0.1: {}
@ -22266,8 +21956,6 @@ snapshots:
dependencies:
ms: 2.1.3
decimal.js-light@2.5.1: {}
decimal.js@10.6.0:
optional: true
@ -22531,8 +22219,6 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
es-toolkit@1.44.0: {}
esbuild-register@3.6.0(esbuild@0.25.12):
dependencies:
debug: 4.4.3
@ -22664,7 +22350,7 @@ snapshots:
'@next/eslint-plugin-next': 16.1.6
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1))
@ -22687,7 +22373,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)):
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
@ -22702,6 +22388,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
get-tsconfig: 4.13.6
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.55.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
@ -22713,14 +22414,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
@ -22764,7 +22465,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@ -23653,10 +23354,6 @@ snapshots:
dependencies:
queue: 6.0.2
immer@10.2.0: {}
immer@11.1.4: {}
import-fresh@2.0.0:
dependencies:
caller-path: 2.0.0
@ -23688,8 +23385,6 @@ snapshots:
hasown: 2.0.2
side-channel: 1.1.0
internmap@2.0.3: {}
invariant@2.2.4:
dependencies:
loose-envify: 1.4.0
@ -26068,15 +25763,6 @@ snapshots:
- supports-color
- utf-8-validate
react-redux@9.2.0(@types/react@19.2.14)(react@19.2.3)(redux@5.0.1):
dependencies:
'@types/use-sync-external-store': 0.0.6
react: 19.2.3
use-sync-external-store: 1.6.0(react@19.2.3)
optionalDependencies:
'@types/react': 19.2.14
redux: 5.0.1
react-refresh@0.14.2: {}
react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.3):
@ -26170,26 +25856,6 @@ snapshots:
tiny-invariant: 1.3.3
tslib: 2.8.1
recharts@3.7.0(@types/react@19.2.14)(react-dom@19.2.3(react@19.2.3))(react-is@18.3.1)(react@19.2.3)(redux@5.0.1):
dependencies:
'@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.3)(redux@5.0.1))(react@19.2.3)
clsx: 2.1.1
decimal.js-light: 2.5.1
es-toolkit: 1.44.0
eventemitter3: 5.0.4
immer: 10.2.0
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
react-is: 18.3.1
react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.3)(redux@5.0.1)
reselect: 5.1.1
tiny-invariant: 1.3.3
use-sync-external-store: 1.6.0(react@19.2.3)
victory-vendor: 37.3.6
transitivePeerDependencies:
- '@types/react'
- redux
redent@3.0.0:
dependencies:
indent-string: 4.0.0
@ -26204,12 +25870,6 @@ snapshots:
'@redis/search': 1.2.0(@redis/client@1.6.1)
'@redis/time-series': 1.1.0(@redis/client@1.6.1)
redux-thunk@3.1.0(redux@5.0.1):
dependencies:
redux: 5.0.1
redux@5.0.1: {}
reflect.getprototypeof@1.0.10:
dependencies:
call-bind: 1.0.8
@ -26291,8 +25951,6 @@ snapshots:
require-from-string@2.0.2: {}
reselect@5.1.1: {}
resolve-from@3.0.0: {}
resolve-from@4.0.0: {}
@ -27331,23 +26989,6 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
victory-vendor@37.3.6:
dependencies:
'@types/d3-array': 3.2.2
'@types/d3-ease': 3.0.2
'@types/d3-interpolate': 3.0.4
'@types/d3-scale': 4.0.9
'@types/d3-shape': 3.1.8
'@types/d3-time': 3.0.4
'@types/d3-timer': 3.0.2
d3-array: 3.2.4
d3-ease: 3.0.1
d3-interpolate: 3.0.1
d3-scale: 4.0.2
d3-shape: 3.2.0
d3-time: 3.1.0
d3-timer: 3.0.1
vite-node@3.2.4(@types/node@20.19.33)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2):
dependencies:
cac: 6.7.14

View File

@ -1,4 +1,4 @@
@bytelyst:registry=http://${GITEA_NPM_HOST:-localhost}/api/packages/${GITEA_NPM_OWNER:-learning_ai_user}/npm/
@bytelyst:registry=https://${GITEA_NPM_HOST:-localhost}/api/packages/${GITEA_NPM_OWNER:-learning_ai_user}/npm/
//${GITEA_NPM_HOST:-localhost}/api/packages/${GITEA_NPM_OWNER:-learning_ai_user}/npm/:_authToken=${GITEA_NPM_TOKEN}
strict-ssl=false
link-workspace-packages=true

View File

@ -73,7 +73,7 @@ export class IpcBridge {
env,
});
this.child.on('error', (err) => {
this.child.on('error', err => {
this.log.error(`IPC child process error: ${err.message}`);
});
@ -87,18 +87,20 @@ export class IpcBridge {
// Read JSON-RPC responses line by line from stdout
this.rl = createInterface({ input: this.child.stdout! });
this.rl.on('line', (line) => this.handleLine(line));
this.rl.on('line', line => this.handleLine(line));
// Pipe stderr to logger
if (this.child.stderr) {
const errRl = createInterface({ input: this.child.stderr });
errRl.on('line', (line) => this.log.error(`[rust] ${line}`));
errRl.on('line', line => this.log.error(`[rust] ${line}`));
}
// Perform initialize handshake
const resp = await this.call('initialize', {});
this._initialized = true;
this.log.info(`IPC bridge initialized: protocol=${resp.result && (resp.result as Record<string, unknown>).protocolVersion}`);
this.log.info(
`IPC bridge initialized: protocol=${resp.result && (resp.result as Record<string, unknown>).protocolVersion}`
);
return resp;
}
@ -125,7 +127,7 @@ export class IpcBridge {
this.pending.set(id, { resolve, reject, timer });
const line = JSON.stringify(request) + '\n';
this.child!.stdin!.write(line, (err) => {
this.child!.stdin!.write(line, err => {
if (err) {
clearTimeout(timer);
this.pending.delete(id);
@ -141,7 +143,7 @@ export class IpcBridge {
goal: string,
folder: string,
auth: Record<string, unknown>,
opts: { model?: string; plugins?: string[] } = {},
opts: { model?: string; plugins?: string[] } = {}
): Promise<IpcResponse> {
return this.call('submit_task', { goal, folder, auth, ...opts });
}
@ -162,7 +164,10 @@ export class IpcBridge {
return this.call('get_features', { auth });
}
async updateFlags(flags: Record<string, boolean>, auth: Record<string, unknown>): Promise<IpcResponse> {
async updateFlags(
flags: Record<string, boolean>,
auth: Record<string, unknown>
): Promise<IpcResponse> {
return this.call('update_flags', { flags, auth });
}
@ -180,7 +185,7 @@ export class IpcBridge {
outputTokens: number,
costUsd: number,
auth: Record<string, unknown>,
taskId?: string,
taskId?: string
): Promise<IpcResponse> {
return this.call('record_spend', { model, inputTokens, outputTokens, costUsd, auth, taskId });
}
@ -189,20 +194,27 @@ export class IpcBridge {
return this.call('flush_budget', { auth });
}
async updateVerdict(verdict: Record<string, unknown>, auth: Record<string, unknown>): Promise<IpcResponse> {
async updateVerdict(
verdict: Record<string, unknown>,
auth: Record<string, unknown>
): Promise<IpcResponse> {
return this.call('update_verdict', { verdict, auth });
}
// ── Incoming request handler (Rust → TS, reverse IPC) ──
private incomingHandler: ((method: string, params: Record<string, unknown>) => Promise<unknown>) | null = null;
private incomingHandler:
| ((method: string, params: Record<string, unknown>) => Promise<unknown>)
| null = null;
/**
* Register a handler for incoming requests FROM the Rust runtime.
* Used for LLM interception: Rust sends `intercept_llm` requests,
* cowork-service routes them through the multi-provider LLM router.
*/
onIncomingRequest(handler: (method: string, params: Record<string, unknown>) => Promise<unknown>): void {
onIncomingRequest(
handler: (method: string, params: Record<string, unknown>) => Promise<unknown>
): void {
this.incomingHandler = handler;
}
@ -216,7 +228,11 @@ export class IpcBridge {
}
// Guard: child may have been cleared by exit handler during the call above
if (this.child) {
this.child.kill('SIGTERM');
try {
this.child.kill();
} catch {
// Ignore — process may already have exited
}
}
this.rejectAllPending(new Error('IPC bridge shutting down'));
this.child = null;
@ -257,20 +273,29 @@ export class IpcBridge {
/** Handle an incoming request from the Rust runtime (reverse IPC). */
private handleIncoming(req: IpcRequest): void {
if (!this.incomingHandler) {
this.sendResponse(req.id, undefined, { code: -32601, message: `No handler for '${req.method}'` });
this.sendResponse(req.id, undefined, {
code: -32601,
message: `No handler for '${req.method}'`,
});
return;
}
this.incomingHandler(req.method, req.params)
.then((result) => this.sendResponse(req.id, result))
.catch((err) => this.sendResponse(req.id, undefined, {
code: -32000,
message: err instanceof Error ? err.message : 'Handler error',
}));
.then(result => this.sendResponse(req.id, result))
.catch(err =>
this.sendResponse(req.id, undefined, {
code: -32000,
message: err instanceof Error ? err.message : 'Handler error',
})
);
}
/** Send a JSON-RPC response back to the Rust runtime. */
private sendResponse(id: number, result?: unknown, error?: { code: number; message: string }): void {
private sendResponse(
id: number,
result?: unknown,
error?: { code: number; message: string }
): void {
if (!this.child?.stdin?.writable) return;
const resp: IpcResponse = { jsonrpc: '2.0', id, ...(error ? { error } : { result }) };
this.child.stdin.write(JSON.stringify(resp) + '\n');