diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84c5b3e..09a9498 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,9 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + # Need Node 22+ for fs.promises.glob (used by GlobTool). + # @deepcode/core's `package.json` engines field requires >=22 too. + node-version: '22' cache: 'pnpm' - name: Install dependencies diff --git a/.nvmrc b/.nvmrc index 209e3ef..2bd5a0a 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 +22 diff --git a/apps/cli/package.json b/apps/cli/package.json index 1a61894..96d1056 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -30,6 +30,6 @@ "vitest": "^2.1.0" }, "engines": { - "node": ">=20" + "node": ">=22" } } diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a912a6f..5bebc4b 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -21,6 +21,6 @@ "typescript": "^5.7.0" }, "engines": { - "node": ">=20" + "node": ">=22" } } diff --git a/package.json b/package.json index 09b053a..43ce69d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "DeepCode — Claude Code 的 DeepSeek 版(monorepo root)", "license": "MIT", "engines": { - "node": ">=20", + "node": ">=22", "pnpm": ">=9" }, "packageManager": "pnpm@9.12.0", diff --git a/packages/core/src/hooks/dispatcher.ts b/packages/core/src/hooks/dispatcher.ts index a11b6f2..3b290c0 100644 --- a/packages/core/src/hooks/dispatcher.ts +++ b/packages/core/src/hooks/dispatcher.ts @@ -148,9 +148,22 @@ export function runCommand( resolveResult({ stdout, stderr, exitCode }); }); + // Suppress EPIPE / EBADF when the child closes stdin before our write + // completes (handlers that don't read stdin are common and harmless). + child.stdin.on('error', () => { + // swallow + }); if (opts.stdin) { - child.stdin.write(opts.stdin); + try { + child.stdin.write(opts.stdin); + } catch { + // pipe already closed — fine + } + } + try { child.stdin.end(); + } catch { + // already ended — fine } }); } diff --git a/packages/core/src/tools/bash.test.ts b/packages/core/src/tools/bash.test.ts index da247f9..fed3183 100644 --- a/packages/core/src/tools/bash.test.ts +++ b/packages/core/src/tools/bash.test.ts @@ -42,9 +42,8 @@ describe('BashTool', () => { it('runs in the given cwd', async () => { const r = await BashTool.execute({ command: 'pwd' }, { cwd: tmp }); - // macOS resolves /private/var symlinks for /tmp paths; tolerate that - expect(r.content).toMatch( - new RegExp(tmp.replace(/^\/tmp/, '(/private)?/tmp').replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')), - ); + // macOS resolves /tmp → /private/tmp via symlink. Check just the suffix to be portable. + const suffix = tmp.replace(/^\/tmp\//, '').replace(/^\/private\/tmp\//, ''); + expect(r.content).toContain(suffix); }); });