mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
AIX: support operation-level retrier with reassembly wipe #869
This commit is contained in:
@@ -256,6 +256,9 @@ export class ContentReassembler {
|
||||
case 'issue':
|
||||
this.onCGIssue(op);
|
||||
break;
|
||||
case 'retry-reset':
|
||||
this.onRetryReset(op);
|
||||
break;
|
||||
case 'set-metrics':
|
||||
this.onMetrics(op);
|
||||
break;
|
||||
@@ -658,6 +661,23 @@ export class ContentReassembler {
|
||||
this.currentTextFragmentIndex = null;
|
||||
}
|
||||
|
||||
private onRetryReset({ attempt, maxAttempts, delayMs, reason, shallClear }: Extract<AixWire_Particles.ChatGenerateOp, { cg: 'retry-reset' }>): void {
|
||||
// operation-level retry likely requires a wipe
|
||||
if (shallClear) {
|
||||
this.currentTextFragmentIndex = null;
|
||||
this.accumulator.fragments = [];
|
||||
delete this.accumulator.genTokenStopReason;
|
||||
// keep metrics/model/handle intact - may be useful for debugging retries
|
||||
|
||||
// discard any pending particles from the failed attempt
|
||||
this.wireParticlesBacklog.length = 0;
|
||||
}
|
||||
|
||||
// -> ph: show operation-level retry status
|
||||
const retryMessage = `Retrying [${attempt}/${maxAttempts}] in ${Math.round(delayMs / 1000)}s - ${reason}`;
|
||||
this.accumulator.fragments.push(createPlaceholderVoidFragment(retryMessage, 'ec-retry-srv-op'));
|
||||
}
|
||||
|
||||
private onMetrics({ metrics }: Extract<AixWire_Particles.ChatGenerateOp, { cg: 'set-metrics' }>): void {
|
||||
// type check point for AixWire_Particles.CGSelectMetrics -> DMetricsChatGenerate_Lg
|
||||
this.accumulator.genMetricsLg = metrics;
|
||||
|
||||
@@ -573,6 +573,7 @@ export namespace AixWire_Particles {
|
||||
// | { cg: 'start' } // not really used for now
|
||||
| { cg: 'end', reason: CGEndReason, tokenStopReason: GCTokenStopReason }
|
||||
| { cg: 'issue', issueId: CGIssueId, issueText: string }
|
||||
| { cg: 'retry-reset', attempt: number, maxAttempts: number, delayMs: number, reason: string, shallClear: boolean }
|
||||
| { cg: 'set-metrics', metrics: CGSelectMetrics }
|
||||
| { cg: 'set-model', name: string }
|
||||
| { cg: 'set-upstream-handle', handle: { uht: 'vnd.oai.responses', responseId: string, expiresAt: number | null } }
|
||||
|
||||
@@ -19,6 +19,7 @@ const AIX_DEBUG_OPERATION_RETRY = true; // prints the execution retries
|
||||
*/
|
||||
export class RequestRetryError extends Error {
|
||||
override readonly name = 'RequestRetryError';
|
||||
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
Object.setPrototypeOf(this, RequestRetryError.prototype);
|
||||
@@ -64,7 +65,7 @@ export async function* executeChatGenerateWithRetry(
|
||||
throw error; // unexpected
|
||||
}
|
||||
|
||||
// sanity: exhausted attempts - must be a Parser error
|
||||
// sanity: exhausted attempts - must be a Parser error - as it shall have not thrown in this case
|
||||
if (attemptNumber >= maxAttempts) {
|
||||
if (AIX_DEBUG_OPERATION_RETRY)
|
||||
console.warn(`[operation.retrier] ⚠️ Retry error on final attempt (parser bug?) - ${error?.message || error}`);
|
||||
@@ -78,6 +79,9 @@ export async function* executeChatGenerateWithRetry(
|
||||
|
||||
attemptNumber++;
|
||||
|
||||
// Emit retry-reset particle to signal client to clear accumulator and show placeholder
|
||||
yield { cg: 'retry-reset', attempt: attemptNumber, maxAttempts: maxAttempts, delayMs: delayMs, reason: error?.message || 'Unknown retry error', shallClear: true };
|
||||
|
||||
// If aborted during delay, let next attempt detect it and create proper terminating particle
|
||||
// (throwing here would bypass executor's particle-based messaging contract)
|
||||
await abortableDelay(delayMs, abortSignal);
|
||||
|
||||
Reference in New Issue
Block a user