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

View File

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

View File

@ -32,8 +32,8 @@ export class GeminiProvider implements LLMProvider {
constructor(config?: Partial<GeminiConfig>) { constructor(config?: Partial<GeminiConfig>) {
this.config = { this.config = {
apiKey: config?.apiKey || process.env.GEMINI_API_KEY || '', apiKey: config?.apiKey ?? process.env.GEMINI_API_KEY ?? '',
model: config?.model || process.env.GEMINI_MODEL || 'gemini-1.5-flash', 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) version: 9.39.2(jiti@2.6.1)
eslint-config-next: eslint-config-next:
specifier: 16.1.6 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: husky:
specifier: ^9.0.0 specifier: ^9.0.0
version: 9.1.7 version: 9.1.7
@ -339,7 +339,7 @@ importers:
version: 9.39.2(jiti@2.6.1) version: 9.39.2(jiti@2.6.1)
eslint-config-next: eslint-config-next:
specifier: 16.1.6 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: husky:
specifier: ^9.0.0 specifier: ^9.0.0
version: 9.1.7 version: 9.1.7
@ -5910,20 +5910,6 @@ packages:
peerDependencies: peerDependencies:
'@redis/client': ^1.0.0 '@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': '@rollup/pluginutils@5.3.0':
resolution: resolution:
{ {
@ -6205,12 +6191,6 @@ packages:
integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==,
} }
'@standard-schema/utils@0.3.0':
resolution:
{
integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==,
}
'@storybook/addon-a11y@8.6.18': '@storybook/addon-a11y@8.6.18':
resolution: resolution:
{ {
@ -7027,60 +7007,6 @@ packages:
integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==, 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': '@types/debug@4.1.12':
resolution: resolution:
{ {
@ -9024,83 +8950,6 @@ packages:
integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, 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: damerau-levenshtein@1.0.8:
resolution: resolution:
{ {
@ -9176,12 +9025,6 @@ packages:
supports-color: supports-color:
optional: true optional: true
decimal.js-light@2.5.1:
resolution:
{
integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==,
}
decimal.js@10.6.0: decimal.js@10.6.0:
resolution: resolution:
{ {
@ -9605,12 +9448,6 @@ packages:
} }
engines: { node: '>= 0.4' } engines: { node: '>= 0.4' }
es-toolkit@1.44.0:
resolution:
{
integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==,
}
esbuild-register@3.6.0: esbuild-register@3.6.0:
resolution: resolution:
{ {
@ -10977,18 +10814,6 @@ packages:
engines: { node: '>=16.x' } engines: { node: '>=16.x' }
hasBin: true 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: import-fresh@2.0.0:
resolution: resolution:
{ {
@ -11049,13 +10874,6 @@ packages:
} }
engines: { node: '>= 0.4' } engines: { node: '>= 0.4' }
internmap@2.0.3:
resolution:
{
integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==,
}
engines: { node: '>=12' }
invariant@2.2.4: invariant@2.2.4:
resolution: resolution:
{ {
@ -14173,21 +13991,6 @@ packages:
'@types/react': '@types/react':
optional: true 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: react-refresh@0.14.2:
resolution: resolution:
{ {
@ -14282,17 +14085,6 @@ packages:
} }
engines: { node: '>= 4' } 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: redent@3.0.0:
resolution: resolution:
{ {
@ -14306,20 +14098,6 @@ packages:
integrity: sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==, 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: reflect.getprototypeof@1.0.10:
resolution: resolution:
{ {
@ -14411,12 +14189,6 @@ packages:
} }
engines: { node: '>=0.10.0' } engines: { node: '>=0.10.0' }
reselect@5.1.1:
resolution:
{
integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==,
}
resolve-from@3.0.0: resolve-from@3.0.0:
resolution: resolution:
{ {
@ -15963,12 +15735,6 @@ packages:
integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==, integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==,
} }
victory-vendor@37.3.6:
resolution:
{
integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==,
}
vite-node@3.2.4: vite-node@3.2.4:
resolution: resolution:
{ {
@ -20143,18 +19909,6 @@ snapshots:
dependencies: dependencies:
'@redis/client': 1.6.1 '@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)': '@rollup/pluginutils@5.3.0(rollup@4.57.1)':
dependencies: dependencies:
'@types/estree': 1.0.8 '@types/estree': 1.0.8
@ -20272,8 +20026,6 @@ snapshots:
'@standard-schema/spec@1.1.0': {} '@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))': '@storybook/addon-a11y@8.6.18(storybook@8.6.18(prettier@3.8.1))':
dependencies: dependencies:
'@storybook/addon-highlight': 8.6.18(storybook@8.6.18(prettier@3.8.1)) '@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 '@types/deep-eql': 4.0.2
assertion-error: 2.0.1 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': '@types/debug@4.1.12':
dependencies: dependencies:
'@types/ms': 2.1.0 '@types/ms': 2.1.0
@ -22186,44 +21914,6 @@ snapshots:
csstype@3.2.3: {} 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: {} damerau-levenshtein@1.0.8: {}
data-uri-to-buffer@4.0.1: {} data-uri-to-buffer@4.0.1: {}
@ -22266,8 +21956,6 @@ snapshots:
dependencies: dependencies:
ms: 2.1.3 ms: 2.1.3
decimal.js-light@2.5.1: {}
decimal.js@10.6.0: decimal.js@10.6.0:
optional: true optional: true
@ -22531,8 +22219,6 @@ snapshots:
is-date-object: 1.1.0 is-date-object: 1.1.0
is-symbol: 1.1.1 is-symbol: 1.1.1
es-toolkit@1.44.0: {}
esbuild-register@3.6.0(esbuild@0.25.12): esbuild-register@3.6.0(esbuild@0.25.12):
dependencies: dependencies:
debug: 4.4.3 debug: 4.4.3
@ -22664,7 +22350,7 @@ snapshots:
'@next/eslint-plugin-next': 16.1.6 '@next/eslint-plugin-next': 16.1.6
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9 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-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-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)) eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1))
@ -22687,7 +22373,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - 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: dependencies:
'@nolyfill/is-core-module': 1.0.39 '@nolyfill/is-core-module': 1.0.39
debug: 4.4.3 debug: 4.4.3
@ -22702,6 +22388,21 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - 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)): 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: dependencies:
debug: 3.2.7 debug: 3.2.7
@ -22713,14 +22414,14 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - 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: dependencies:
debug: 3.2.7 debug: 3.2.7
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 8.56.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@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-import-resolver-node: 0.3.9 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: transitivePeerDependencies:
- supports-color - supports-color
@ -22764,7 +22465,7 @@ snapshots:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9 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 hasown: 2.0.2
is-core-module: 2.16.1 is-core-module: 2.16.1
is-glob: 4.0.3 is-glob: 4.0.3
@ -23653,10 +23354,6 @@ snapshots:
dependencies: dependencies:
queue: 6.0.2 queue: 6.0.2
immer@10.2.0: {}
immer@11.1.4: {}
import-fresh@2.0.0: import-fresh@2.0.0:
dependencies: dependencies:
caller-path: 2.0.0 caller-path: 2.0.0
@ -23688,8 +23385,6 @@ snapshots:
hasown: 2.0.2 hasown: 2.0.2
side-channel: 1.1.0 side-channel: 1.1.0
internmap@2.0.3: {}
invariant@2.2.4: invariant@2.2.4:
dependencies: dependencies:
loose-envify: 1.4.0 loose-envify: 1.4.0
@ -26068,15 +25763,6 @@ snapshots:
- supports-color - supports-color
- utf-8-validate - 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-refresh@0.14.2: {}
react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.3): 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 tiny-invariant: 1.3.3
tslib: 2.8.1 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: redent@3.0.0:
dependencies: dependencies:
indent-string: 4.0.0 indent-string: 4.0.0
@ -26204,12 +25870,6 @@ snapshots:
'@redis/search': 1.2.0(@redis/client@1.6.1) '@redis/search': 1.2.0(@redis/client@1.6.1)
'@redis/time-series': 1.1.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: reflect.getprototypeof@1.0.10:
dependencies: dependencies:
call-bind: 1.0.8 call-bind: 1.0.8
@ -26291,8 +25951,6 @@ snapshots:
require-from-string@2.0.2: {} require-from-string@2.0.2: {}
reselect@5.1.1: {}
resolve-from@3.0.0: {} resolve-from@3.0.0: {}
resolve-from@4.0.0: {} resolve-from@4.0.0: {}
@ -27331,23 +26989,6 @@ snapshots:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
vfile-message: 4.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): 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: dependencies:
cac: 6.7.14 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} //${GITEA_NPM_HOST:-localhost}/api/packages/${GITEA_NPM_OWNER:-learning_ai_user}/npm/:_authToken=${GITEA_NPM_TOKEN}
strict-ssl=false strict-ssl=false
link-workspace-packages=true link-workspace-packages=true

View File

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