@nathapp/nax 0.18.5 → 0.18.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +3 -3
- package/CHANGELOG.md +7 -0
- package/docs/ROADMAP.md +2 -1
- package/package.json +1 -1
- package/src/agents/claude.ts +19 -9
- package/src/tui/hooks/usePty.ts +20 -9
package/.gitlab-ci.yml
CHANGED
|
@@ -17,7 +17,7 @@ test:
|
|
|
17
17
|
stage: test
|
|
18
18
|
image:
|
|
19
19
|
name: nathapp/node-bun:22.21.0-1.3.9-alpine
|
|
20
|
-
pull_policy:
|
|
20
|
+
pull_policy: always
|
|
21
21
|
before_script:
|
|
22
22
|
- apk add --no-cache git
|
|
23
23
|
- git config --global safe.directory '*'
|
|
@@ -47,7 +47,7 @@ release:
|
|
|
47
47
|
stage: release
|
|
48
48
|
image:
|
|
49
49
|
name: nathapp/node-bun:22.21.0-1.3.9-alpine
|
|
50
|
-
pull_policy:
|
|
50
|
+
pull_policy: always
|
|
51
51
|
cache:
|
|
52
52
|
key:
|
|
53
53
|
files:
|
|
@@ -86,7 +86,7 @@ notify:
|
|
|
86
86
|
stage: notify
|
|
87
87
|
image:
|
|
88
88
|
name: registry-intl.cn-hongkong.aliyuncs.com/gkci/node:22.14.0-alpine-ci
|
|
89
|
-
pull_policy:
|
|
89
|
+
pull_policy: always
|
|
90
90
|
needs: [release]
|
|
91
91
|
script:
|
|
92
92
|
- VERSION=$(node -e "console.log(require('./package.json').version)")
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.18.6] - 2026-03-04
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **BUG-2:** Infinite PTY respawn loop in `usePty` hook by destructuring object-identity dependencies.
|
|
12
|
+
- **MEM-1 & MEM-3:** Prevented child process hangs on full `stderr` pipes by switching to `stderr: "inherit"`.
|
|
13
|
+
- **BUG-21 & BUG-22:** Added missing error handling and `.catch()` chains to process `stdout` streaming and exit handlers.
|
|
14
|
+
|
|
8
15
|
## [0.18.5] - 2026-03-04
|
|
9
16
|
|
|
10
17
|
### Changed
|
package/docs/ROADMAP.md
CHANGED
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
|
|
135
135
|
---
|
|
136
136
|
|
|
137
|
-
## v0.19.0 —
|
|
137
|
+
## v0.19.0 — Hardening & Compliance
|
|
138
138
|
|
|
139
139
|
**Theme:** Eliminate duplicate test runs, deferred regression gate, structured escalation context
|
|
140
140
|
**Status:** 🔲 Planned
|
|
@@ -166,6 +166,7 @@
|
|
|
166
166
|
| Version | Theme | Date | Details |
|
|
167
167
|
|:---|:---|:---|:---|
|
|
168
168
|
| v0.18.1 | Type Safety + CI Pipeline | 2026-03-03 | 60 TS errors + 12 lint errors fixed, GitLab CI green (1952/56/0) |
|
|
169
|
+
| v0.19.0 | Hardening & Compliance | TBD | SEC-1 to SEC-5, BUG-1, Node.js API removal, _deps rollout |
|
|
169
170
|
| v0.18.5 | Bun PTY Migration | 2026-03-04 | BUN-001: node-pty → Bun.spawn, CI cleanup, flaky test fix |
|
|
170
171
|
| v0.18.4 | Routing Stability | 2026-03-04 | BUG-031 keyword drift, BUG-033 LLM retry, pre-commit hook |
|
|
171
172
|
| v0.18.3 | Execution Reliability + Smart Runner | 2026-03-04 | BUG-026/028/029/030/032 + SFC-001/002 + STR-007, all items complete |
|
package/package.json
CHANGED
package/src/agents/claude.ts
CHANGED
|
@@ -172,7 +172,7 @@ export class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
172
172
|
const proc = Bun.spawn(cmd, {
|
|
173
173
|
cwd: options.workdir,
|
|
174
174
|
stdout: "pipe",
|
|
175
|
-
stderr: "
|
|
175
|
+
stderr: "inherit", // MEM-3: Inherit stderr to avoid blocking on unread pipe
|
|
176
176
|
env: this.buildAllowedEnv(options),
|
|
177
177
|
});
|
|
178
178
|
|
|
@@ -255,7 +255,7 @@ export class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
255
255
|
const proc = Bun.spawn(cmd, {
|
|
256
256
|
cwd: options.workdir,
|
|
257
257
|
stdout: "pipe",
|
|
258
|
-
stderr: "
|
|
258
|
+
stderr: "inherit", // MEM-3: Inherit stderr to avoid blocking on unread pipe
|
|
259
259
|
env: this.buildAllowedEnv({
|
|
260
260
|
workdir: options.workdir,
|
|
261
261
|
modelDef: options.modelDef || { provider: "anthropic", model: "claude-sonnet-4-5", env: {} },
|
|
@@ -295,7 +295,7 @@ export class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
295
295
|
env: { ...this.buildAllowedEnv(options), TERM: "xterm-256color", FORCE_COLOR: "1" },
|
|
296
296
|
stdin: "pipe",
|
|
297
297
|
stdout: "pipe",
|
|
298
|
-
stderr: "
|
|
298
|
+
stderr: "inherit", // MEM-3: Inherit stderr to avoid blocking on unread pipe
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
const pidRegistry = this.getPidRegistry(options.workdir);
|
|
@@ -303,16 +303,26 @@ export class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
303
303
|
|
|
304
304
|
// Stream stdout to onOutput callback
|
|
305
305
|
(async () => {
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
try {
|
|
307
|
+
for await (const chunk of proc.stdout) {
|
|
308
|
+
options.onOutput(Buffer.from(chunk));
|
|
309
|
+
}
|
|
310
|
+
} catch (err) {
|
|
311
|
+
// BUG-21: Handle stream errors to avoid unhandled rejections
|
|
312
|
+
getLogger()?.error("agent", "runInteractive stdout error", { err });
|
|
308
313
|
}
|
|
309
314
|
})();
|
|
310
315
|
|
|
311
316
|
// Fire onExit when process completes
|
|
312
|
-
proc.exited
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
proc.exited
|
|
318
|
+
.then((code) => {
|
|
319
|
+
pidRegistry.unregister(proc.pid).catch(() => {});
|
|
320
|
+
options.onExit(code ?? 1);
|
|
321
|
+
})
|
|
322
|
+
.catch((err) => {
|
|
323
|
+
// BUG-22: Guard against onExit or unregister throws
|
|
324
|
+
getLogger()?.error("agent", "runInteractive exit error", { err });
|
|
325
|
+
});
|
|
316
326
|
|
|
317
327
|
return {
|
|
318
328
|
write: (data: string) => {
|
package/src/tui/hooks/usePty.ts
CHANGED
|
@@ -84,19 +84,25 @@ export function usePty(options: PtySpawnOptions | null): PtyState & { handle: Pt
|
|
|
84
84
|
const [ptyProcess, setPtyProcess] = useState<ReturnType<typeof Bun.spawn> | null>(null);
|
|
85
85
|
|
|
86
86
|
// Spawn PTY process
|
|
87
|
+
// BUG-2: Destructure options to prevent infinite respawn loop due to object identity
|
|
88
|
+
const command = options?.command;
|
|
89
|
+
const argsJson = JSON.stringify(options?.args);
|
|
90
|
+
const cwd = options?.cwd;
|
|
91
|
+
const envJson = JSON.stringify(options?.env);
|
|
92
|
+
|
|
87
93
|
useEffect(() => {
|
|
88
|
-
if (!
|
|
94
|
+
if (!command) {
|
|
89
95
|
return;
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
// BUN-001: Replaced node-pty with Bun.spawn (piped stdio).
|
|
93
99
|
// TERM + FORCE_COLOR preserve Claude Code output formatting.
|
|
94
|
-
const proc = Bun.spawn([
|
|
95
|
-
cwd:
|
|
96
|
-
env: { ...process.env, ...
|
|
100
|
+
const proc = Bun.spawn([command, ...(JSON.parse(argsJson) || [])], {
|
|
101
|
+
cwd: cwd || process.cwd(),
|
|
102
|
+
env: { ...process.env, ...JSON.parse(envJson), TERM: "xterm-256color", FORCE_COLOR: "1" },
|
|
97
103
|
stdin: "pipe",
|
|
98
104
|
stdout: "pipe",
|
|
99
|
-
stderr: "
|
|
105
|
+
stderr: "inherit", // MEM-1: Inherit stderr to avoid blocking on unread pipe
|
|
100
106
|
});
|
|
101
107
|
|
|
102
108
|
setPtyProcess(proc);
|
|
@@ -128,9 +134,14 @@ export function usePty(options: PtySpawnOptions | null): PtyState & { handle: Pt
|
|
|
128
134
|
})();
|
|
129
135
|
|
|
130
136
|
// Handle exit
|
|
131
|
-
proc.exited
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
proc.exited
|
|
138
|
+
.then((code) => {
|
|
139
|
+
setState((prev) => ({ ...prev, isRunning: false, exitCode: code ?? undefined }));
|
|
140
|
+
})
|
|
141
|
+
.catch(() => {
|
|
142
|
+
// BUG-22: Guard against setState throws (e.g. on unmount)
|
|
143
|
+
setState((prev) => ({ ...prev, isRunning: false }));
|
|
144
|
+
});
|
|
134
145
|
|
|
135
146
|
// Create handle
|
|
136
147
|
const ptyHandle: PtyHandle = {
|
|
@@ -152,7 +163,7 @@ export function usePty(options: PtySpawnOptions | null): PtyState & { handle: Pt
|
|
|
152
163
|
return () => {
|
|
153
164
|
proc.kill();
|
|
154
165
|
};
|
|
155
|
-
}, [
|
|
166
|
+
}, [command, argsJson, cwd, envJson]);
|
|
156
167
|
|
|
157
168
|
// Handle terminal resize
|
|
158
169
|
// resize is a no-op with Bun.spawn (no PTY) — kept for API compatibility
|