fix(pi): keep active runs alive during background sleep

This commit is contained in:
2026-08-25 20:56:17 +08:00
parent 92f4c91088
commit 621ebb1781
22 changed files with 1061 additions and 68 deletions

View File

@@ -101,6 +101,7 @@ export class BackgroundLifecycleController extends EventEmitter {
this.stopping = true;
try {
await this.options.onSleep();
if (!this.shouldSleep() || this.leases.size > 0) return;
await this.options.onStopRuntime();
this.emit('sleep');
} finally {

View File

@@ -90,14 +90,17 @@ import {
} from '../api/coding-composition';
import {
abortFinalAsarResilienceTarget,
disposeFinalAsarResilienceTarget,
finishFinalAsarProxyCompositionProof,
finishFinalAsarPressureProof,
finishFinalAsarResilienceProof,
getFinalAsarProxyCompositionStatus,
getFinalAsarResilienceIdleStatus,
getFinalAsarResilienceStatus,
injectFinalAsarResilienceFailure,
releaseFinalAsarProxyCompositionChild,
releaseFinalAsarResilienceParents,
restartFinalAsarResilienceOther,
runFinalAsarExtensionProof,
startFinalAsarProxyCompositionProof,
startFinalAsarPressureProof,
@@ -524,12 +527,13 @@ async function initialize(): Promise<void> {
// Register IPC handlers
backgroundLifecycle = new BackgroundLifecycleController({
...(isE2EMode ? { idleStopMs: 250 } : {}),
onSleep: () => {
if (!window.isDestroyed() && !window.webContents.isDestroyed()) {
window.webContents.send('lifecycle:sleep');
}
},
onStopRuntime: async () => await codingProducts?.sleep(),
onStopRuntime: async () => await codingProducts?.sleep('background_sleep'),
});
const releaseUtilityPreparer = createReleaseUtilityPreparer({
runtimeContext: {
@@ -557,6 +561,7 @@ async function initialize(): Promise<void> {
projectStore: codingProjectStore,
browser: agentBrowser,
getLocalProxyCredential: () => getHostApiToken() || undefined,
acquireBackgroundLease: (lease) => backgroundLifecycle!.acquireLease(lease),
paths: {
...resolveCodingPiRuntimePaths({
isPackaged: app.isPackaged,
@@ -898,6 +903,9 @@ type PiReleaseProofAction =
| 'proxy.finish'
| 'resilience.start'
| 'resilience.status'
| 'resilience.idle-status'
| 'resilience.restart-other'
| 'resilience.dispose-target'
| 'resilience.inject-exit'
| 'resilience.inject-protocol'
| 'resilience.abort-after-exit'
@@ -961,6 +969,15 @@ export async function runPiReleaseProofE2E(action: PiReleaseProofAction) {
if (action === 'resilience.status') {
return { action, packagedMain, resilience: await getFinalAsarResilienceStatus() };
}
if (action === 'resilience.idle-status') {
return { action, packagedMain, resilience: await getFinalAsarResilienceIdleStatus() };
}
if (action === 'resilience.restart-other') {
return { action, packagedMain, resilience: await restartFinalAsarResilienceOther() };
}
if (action === 'resilience.dispose-target') {
return { action, packagedMain, resilience: await disposeFinalAsarResilienceTarget() };
}
if (action === 'resilience.inject-exit' || action === 'resilience.inject-protocol') {
return {
action,