mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-16 15:15:35 +02:00
Keep unexpected provider loss failed while retaining input fallback
This commit is contained in:
1 parent
1998fd7ae9
commit
bb7ab1cbfa
5 files changed
+65
-15
No files matched your search
@@ -4813,6 +4813,16 @@ describe("native governed waits", () => {
|
||||
payload: { kind: "dynamicToolCall" },
|
||||
};
|
||||
|
||||
// The durable fallback preserves the question after provider loss, but
|
||||
// cannot turn that lost execution into a successful governed wait.
|
||||
const providerLost = { ...replayedEvent, eventType: "runtime_request.expired" as const,
|
||||
payload: { reason: "provider_process_lost", replayAllowed: false } };
|
||||
const lostObservation = createGovernedWaitEventObservation(async () => waitResult);
|
||||
await lostObservation.observe(providerLost, true);
|
||||
expect(lostObservation.consume(providerLost)).toBeNull();
|
||||
await lostObservation.observe(replayedEvent, true);
|
||||
expect(lostObservation.consume(replayedEvent)).toBeNull();
|
||||
|
||||
// The event consumer can lag the provider: a commentary event emitted
|
||||
// before the tool began may be processed after its approval exists in DB.
|
||||
// It is not proof that the approval-creating tool response has settled.
|
||||
|
||||
@@ -1213,6 +1213,7 @@ export function createGovernedWaitEventObservation(
|
||||
resolvePending: () => Promise<PrpStructuredRunResult | null>,
|
||||
) {
|
||||
const pendingTools = new Set<string>();
|
||||
let providerLost = false;
|
||||
let generation = 0;
|
||||
let observation: {
|
||||
sourceInstanceId: string;
|
||||
@@ -1226,6 +1227,7 @@ export function createGovernedWaitEventObservation(
|
||||
const currentGeneration = ++generation;
|
||||
observation = null;
|
||||
const payload = record(event.payload);
|
||||
providerLost ||= event.eventType === "runtime_request.expired" && payload.reason === "provider_process_lost";
|
||||
const kind = payload.kind;
|
||||
const tool = ["dynamicToolCall", "mcpToolCall", "commandExecution"].includes(String(kind));
|
||||
if (event.itemId) {
|
||||
@@ -1241,7 +1243,9 @@ export function createGovernedWaitEventObservation(
|
||||
if (event.eventType === "item.completed" && (
|
||||
pendingTools.size > 0 || (!tool && !(kind === "agentMessage" && payload.channel === "final"))
|
||||
)) return;
|
||||
if (!eligible) return;
|
||||
// A replacement question preserves human input after a provider crash;
|
||||
// it does not authorize a successful suspension of the failed execution.
|
||||
if (providerLost || !eligible) return;
|
||||
const result = await resolvePending();
|
||||
if (generation !== currentGeneration || result === null) return;
|
||||
// If the interaction is answered after this read, parking remains the
|
||||
|
||||
Reference in new issue
Block a user