@saccolabs/pi-claude-cli 0.4.1 → 0.4.2
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/package.json +1 -1
- package/src/provider.ts +48 -8
package/package.json
CHANGED
package/src/provider.ts
CHANGED
|
@@ -81,9 +81,20 @@ export function streamViaCli(
|
|
|
81
81
|
): AssistantMessageEventStream {
|
|
82
82
|
const stream = createAssistantMessageEventStream();
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* One subprocess attempt. Returns "resume-miss" (without touching the
|
|
86
|
+
* stream) when a --resume pointed at a CLI session that does not exist —
|
|
87
|
+
* forks copy pi history into a NEW session id, so the prior-provider-turn
|
|
88
|
+
* heuristic says resume while the CLI cache is keyed to the old id (#2).
|
|
89
|
+
* The driver below retries once with a full-history replay, which also
|
|
90
|
+
* re-registers the CLI cache under the current session id.
|
|
91
|
+
*/
|
|
92
|
+
async function runOnce(
|
|
93
|
+
forceFullReplay: boolean,
|
|
94
|
+
): Promise<"ok" | "resume-miss"> {
|
|
85
95
|
let proc: ReturnType<typeof spawnClaude> | undefined;
|
|
86
96
|
let abortHandler: (() => void) | undefined;
|
|
97
|
+
let resumeMiss = false;
|
|
87
98
|
|
|
88
99
|
try {
|
|
89
100
|
const cwd = options?.cwd ?? process.cwd();
|
|
@@ -102,7 +113,9 @@ export function streamViaCli(
|
|
|
102
113
|
(m?.provider === "pi-claude-cli" || m?.api === "pi-claude-cli"),
|
|
103
114
|
);
|
|
104
115
|
const resumeSessionId =
|
|
105
|
-
options?.sessionId && hasPriorCliTurn
|
|
116
|
+
!forceFullReplay && options?.sessionId && hasPriorCliTurn
|
|
117
|
+
? options.sessionId
|
|
118
|
+
: undefined;
|
|
106
119
|
|
|
107
120
|
// Build prompt: if resuming, only send the latest user turn;
|
|
108
121
|
// otherwise build the full flattened conversation history
|
|
@@ -195,7 +208,7 @@ export function streamViaCli(
|
|
|
195
208
|
|
|
196
209
|
if (options.signal.aborted) {
|
|
197
210
|
abortHandler();
|
|
198
|
-
return;
|
|
211
|
+
return "ok";
|
|
199
212
|
}
|
|
200
213
|
options.signal.addEventListener("abort", abortHandler, { once: true });
|
|
201
214
|
}
|
|
@@ -308,7 +321,18 @@ export function streamViaCli(
|
|
|
308
321
|
(Array.isArray(r.errors) && r.errors.length > 0
|
|
309
322
|
? r.errors.join("; ")
|
|
310
323
|
: `Claude CLI returned ${r.subtype ?? "non-success result"}`);
|
|
311
|
-
|
|
324
|
+
if (
|
|
325
|
+
resumeSessionId &&
|
|
326
|
+
/No conversation found with session ID/i.test(errMsg)
|
|
327
|
+
) {
|
|
328
|
+
// Recoverable: the driver replays full history once. The CLI
|
|
329
|
+
// also exits non-zero after this result — silence this
|
|
330
|
+
// attempt's close/error handlers so the retry owns the stream.
|
|
331
|
+
resumeMiss = true;
|
|
332
|
+
broken = true;
|
|
333
|
+
} else {
|
|
334
|
+
endStreamWithError(errMsg);
|
|
335
|
+
}
|
|
312
336
|
}
|
|
313
337
|
if (!isError) {
|
|
314
338
|
// Authoritative episode usage + final-answer safety net.
|
|
@@ -326,6 +350,8 @@ export function streamViaCli(
|
|
|
326
350
|
rl.on("close", resolve);
|
|
327
351
|
});
|
|
328
352
|
|
|
353
|
+
if (resumeMiss) return "resume-miss";
|
|
354
|
+
|
|
329
355
|
// Push done event after readline closes (async). Pushing synchronously
|
|
330
356
|
// inside handleMessageStop prevents pi from executing tools.
|
|
331
357
|
// Guard with streamEnded to avoid pushing done after an error was already pushed.
|
|
@@ -356,6 +382,24 @@ export function streamViaCli(
|
|
|
356
382
|
});
|
|
357
383
|
stream.end();
|
|
358
384
|
}
|
|
385
|
+
return "ok";
|
|
386
|
+
} finally {
|
|
387
|
+
// Clean up this attempt's abort listener
|
|
388
|
+
if (options?.signal && abortHandler) {
|
|
389
|
+
options.signal.removeEventListener("abort", abortHandler);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
(async () => {
|
|
395
|
+
try {
|
|
396
|
+
const outcome = await runOnce(false);
|
|
397
|
+
if (outcome === "resume-miss") {
|
|
398
|
+
console.error(
|
|
399
|
+
"[pi-claude-cli] CLI session missing for --resume — replaying full history under the current session id",
|
|
400
|
+
);
|
|
401
|
+
await runOnce(true);
|
|
402
|
+
}
|
|
359
403
|
} catch (err: any) {
|
|
360
404
|
stream.push({
|
|
361
405
|
type: "error",
|
|
@@ -364,10 +408,6 @@ export function streamViaCli(
|
|
|
364
408
|
} as any);
|
|
365
409
|
stream.end();
|
|
366
410
|
} finally {
|
|
367
|
-
// Clean up abort listener
|
|
368
|
-
if (options?.signal && abortHandler) {
|
|
369
|
-
options.signal.removeEventListener("abort", abortHandler);
|
|
370
|
-
}
|
|
371
411
|
cleanupSystemPromptFile();
|
|
372
412
|
}
|
|
373
413
|
})();
|