vibe-coding-master 0.3.3 → 0.3.4
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.
|
@@ -33,16 +33,22 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
33
33
|
startedAt: now(),
|
|
34
34
|
exitCode: null
|
|
35
35
|
};
|
|
36
|
+
const logWriter = createTerminalLogWriter(deps.fs, input.logPath, deps.onLogWriteError ?? defaultLogWriteErrorHandler);
|
|
36
37
|
const entry = {
|
|
37
38
|
input,
|
|
38
39
|
session,
|
|
39
40
|
process: child,
|
|
40
|
-
listeners: new Set()
|
|
41
|
+
listeners: new Set(),
|
|
42
|
+
logWriter,
|
|
43
|
+
disposed: false
|
|
41
44
|
};
|
|
42
45
|
entries.set(session.id, entry);
|
|
43
46
|
child.onData((data) => {
|
|
47
|
+
if (entry.disposed) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
44
50
|
entry.session.lastOutputAt = now();
|
|
45
|
-
|
|
51
|
+
entry.logWriter.append(data);
|
|
46
52
|
emit(entry, {
|
|
47
53
|
sessionId: session.id,
|
|
48
54
|
taskSlug: input.taskSlug,
|
|
@@ -52,8 +58,13 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
52
58
|
});
|
|
53
59
|
});
|
|
54
60
|
child.onExit(({ exitCode }) => {
|
|
61
|
+
if (entry.disposed) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
entry.disposed = true;
|
|
55
65
|
entry.session.status = exitCode === 0 ? "exited" : "crashed";
|
|
56
66
|
entry.session.exitCode = exitCode;
|
|
67
|
+
void entry.logWriter.close();
|
|
57
68
|
emit(entry, {
|
|
58
69
|
sessionId: session.id,
|
|
59
70
|
taskSlug: input.taskSlug,
|
|
@@ -102,12 +113,16 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
102
113
|
},
|
|
103
114
|
async stop(sessionId) {
|
|
104
115
|
const entry = getEntry(entries, sessionId);
|
|
116
|
+
entry.disposed = true;
|
|
105
117
|
entry.session.status = "exited";
|
|
106
118
|
entry.process.kill();
|
|
119
|
+
await entry.logWriter.close();
|
|
107
120
|
},
|
|
108
121
|
async restart(sessionId) {
|
|
109
122
|
const entry = getEntry(entries, sessionId);
|
|
123
|
+
entry.disposed = true;
|
|
110
124
|
entry.process.kill();
|
|
125
|
+
await entry.logWriter.close();
|
|
111
126
|
return create(entry.input, sessionId);
|
|
112
127
|
},
|
|
113
128
|
subscribe(sessionId, listener, options = {}) {
|
|
@@ -139,12 +154,40 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
139
154
|
}
|
|
140
155
|
};
|
|
141
156
|
}
|
|
157
|
+
export function createTerminalLogWriter(fs, logPath, onError) {
|
|
158
|
+
let closed = false;
|
|
159
|
+
let pending = Promise.resolve();
|
|
160
|
+
return {
|
|
161
|
+
append(data) {
|
|
162
|
+
if (closed || !data) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
pending = pending
|
|
166
|
+
.then(() => fs.appendText(logPath, data))
|
|
167
|
+
.catch((error) => {
|
|
168
|
+
try {
|
|
169
|
+
onError(error, logPath);
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Logging must never break terminal output delivery or future log writes.
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
async close() {
|
|
177
|
+
closed = true;
|
|
178
|
+
await pending.catch(() => undefined);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
142
182
|
async function readTerminalReplayText(fs, logPath) {
|
|
143
183
|
const data = fs.readTextTail
|
|
144
184
|
? await fs.readTextTail(logPath, TERMINAL_REPLAY_TAIL_LIMIT_BYTES)
|
|
145
185
|
: tailTerminalReplay(await fs.readText(logPath));
|
|
146
186
|
return tailTerminalReplay(data);
|
|
147
187
|
}
|
|
188
|
+
function defaultLogWriteErrorHandler(error, logPath) {
|
|
189
|
+
console.warn(`[VCM] Failed to append terminal log: ${logPath}`, error);
|
|
190
|
+
}
|
|
148
191
|
export function tailTerminalReplay(data, limitBytes = TERMINAL_REPLAY_TAIL_LIMIT_BYTES) {
|
|
149
192
|
if (limitBytes <= 0 || Buffer.byteLength(data, "utf8") <= limitBytes) {
|
|
150
193
|
return data;
|