fix(pi): resolve packaged proxy token lazily
This commit is contained in:
@@ -129,6 +129,51 @@ function assertManagedTurns(extension) {
|
||||
}
|
||||
}
|
||||
|
||||
function assertProxyStatus(status) {
|
||||
if (status?.currentHostTokenAvailable !== true
|
||||
|| status?.realTurnVerified !== false
|
||||
|| status?.activeProviderRequests?.child !== 1
|
||||
|| status?.providerRequests?.parent < 1
|
||||
|| status?.providerRequests?.child !== 1
|
||||
|| status?.processes?.supported !== true
|
||||
|| status?.processes?.parent?.length !== 1
|
||||
|| status?.processes?.child?.length !== 1
|
||||
|| Object.values(status?.tokenSafety ?? {}).some((safe) => safe !== true)) {
|
||||
throw new Error(`Packaged Main proxy status is incomplete: ${JSON.stringify(status)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function assertProxyProof(proof) {
|
||||
if (proof?.providerMode !== 'loopback-through-authenticated-host-proxy'
|
||||
|| proof?.realTurnVerified !== false
|
||||
|| proof?.firstConversation?.count !== 1
|
||||
|| proof?.firstConversation?.bindingEstablished !== true
|
||||
|| proof?.firstConversation?.workerStatus !== 'ready'
|
||||
|| proof?.firstConversation?.runStatus !== 'idle'
|
||||
|| proof?.firstConversation?.userInputProjected !== true
|
||||
|| proof?.firstConversation?.parentResponseProjected !== true
|
||||
|| proof?.currentHostTokenUsedBy?.join(',') !== 'parent,child'
|
||||
|| proof?.released?.workers !== 0
|
||||
|| Object.values(proof?.tokenSafety ?? {}).some((safe) => safe !== true)) {
|
||||
throw new Error(`Packaged Main proxy proof failed: ${JSON.stringify(proof)}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForActiveProxyProof(electronApplication) {
|
||||
const deadline = Date.now() + 30_000;
|
||||
let latest;
|
||||
while (Date.now() < deadline) {
|
||||
latest = await evaluateProof(electronApplication, 'proxy.status');
|
||||
if (latest?.proxy?.activeProviderRequests?.child === 1
|
||||
&& latest?.proxy?.processes?.parent?.length === 1
|
||||
&& latest?.proxy?.processes?.child?.length === 1) {
|
||||
return latest;
|
||||
}
|
||||
await new Promise((resolveWait) => setTimeout(resolveWait, 200));
|
||||
}
|
||||
throw new Error(`Packaged Main proxy child did not become active: ${JSON.stringify(latest?.proxy)}`);
|
||||
}
|
||||
|
||||
async function evaluateProof(electronApplication, action) {
|
||||
return await electronApplication.evaluate(async (_electron, requestedAction) => {
|
||||
const proof = globalThis.__niancodeRunPiReleaseProofE2E;
|
||||
@@ -157,6 +202,7 @@ export async function runPackagedProductProof(options) {
|
||||
const hostApiPort = await allocatePort();
|
||||
let electronApplication;
|
||||
let pressureActive = false;
|
||||
let proxyActive = false;
|
||||
try {
|
||||
electronApplication = await electron.launch({
|
||||
executablePath: options.electronExecutable,
|
||||
@@ -234,6 +280,53 @@ export async function runPackagedProductProof(options) {
|
||||
};
|
||||
}
|
||||
|
||||
const proxyStart = await evaluateProof(electronApplication, 'proxy.start');
|
||||
proxyActive = true;
|
||||
assertPackagedMain(proxyStart);
|
||||
if (proxyStart?.proxy?.providerMode !== 'works_square_ai_gateway_proxy'
|
||||
|| proxyStart?.proxy?.currentHostTokenAvailable !== true
|
||||
|| proxyStart?.proxy?.realTurnVerified !== false) {
|
||||
throw new Error(`Packaged Main proxy setup failed: ${JSON.stringify(proxyStart?.proxy)}`);
|
||||
}
|
||||
|
||||
await page.reload();
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
const moduleSelection = page.getByTestId('ai-module-selection-page');
|
||||
if (await moduleSelection.count()) {
|
||||
await page.getByTestId('ai-module-option-programming').click();
|
||||
await page.getByTestId('main-layout').waitFor({ state: 'visible', timeout: 10_000 });
|
||||
}
|
||||
await page.evaluate(() => { window.location.hash = '/chat'; });
|
||||
const composer = page.getByRole('textbox');
|
||||
await composer.waitFor({ state: 'visible', timeout: 30_000 });
|
||||
await composer.fill('Exercise the packaged Main proxy Conversation');
|
||||
if (!await composer.isEnabled()) throw new Error('Packaged proxy first Conversation composer is disabled');
|
||||
const beforeSubmitText = await page.locator('body').innerText();
|
||||
if (beforeSubmitText.includes('本地编程运行时暂时不可用')
|
||||
|| beforeSubmitText.includes('正在重新连接本地 Agent')) {
|
||||
throw new Error(`Packaged proxy first Conversation exposed a runtime banner: ${beforeSubmitText}`);
|
||||
}
|
||||
await page.getByTestId('coding-message-composer').evaluate(
|
||||
(form) => form.requestSubmit(),
|
||||
);
|
||||
|
||||
const proxyStatus = await waitForActiveProxyProof(electronApplication);
|
||||
assertPackagedMain(proxyStatus);
|
||||
assertProxyStatus(proxyStatus.proxy);
|
||||
await evaluateProof(electronApplication, 'proxy.release-child');
|
||||
await page.getByText('REAL_PARENT_COMPLETE').waitFor({ state: 'visible', timeout: 30_000 });
|
||||
const afterTurnText = await page.locator('body').innerText();
|
||||
if (afterTurnText.includes('本地编程运行时暂时不可用')
|
||||
|| afterTurnText.includes('正在重新连接本地 Agent')) {
|
||||
throw new Error(`Packaged proxy Conversation did not leave recovery cleanly: ${afterTurnText}`);
|
||||
}
|
||||
if (!await composer.isEnabled()) throw new Error('Packaged proxy composer is not editable after the turn');
|
||||
|
||||
const proxyFinish = await evaluateProof(electronApplication, 'proxy.finish');
|
||||
proxyActive = false;
|
||||
assertPackagedMain(proxyFinish);
|
||||
assertProxyProof(proxyFinish.proxy);
|
||||
|
||||
const report = {
|
||||
schemaVersion: 1,
|
||||
generatedAt: new Date().toISOString(),
|
||||
@@ -252,6 +345,18 @@ export async function runPackagedProductProof(options) {
|
||||
released: pressureFinish.pressure,
|
||||
...(failureCleanup ? { failureCleanup } : {}),
|
||||
},
|
||||
proxy: {
|
||||
setup: proxyStart.proxy,
|
||||
active: proxyStatus.proxy,
|
||||
completed: proxyFinish.proxy,
|
||||
ui: {
|
||||
firstConversationEditable: true,
|
||||
inputSubmitted: true,
|
||||
runtimeUnavailableBanner: false,
|
||||
permanentRecovering: false,
|
||||
},
|
||||
realTurnVerified: false,
|
||||
},
|
||||
result: 'pass',
|
||||
};
|
||||
if (options.reportPath) {
|
||||
@@ -263,6 +368,10 @@ export async function runPackagedProductProof(options) {
|
||||
if (electronApplication && pressureActive) {
|
||||
await evaluateProof(electronApplication, 'pressure.finish').catch(() => undefined);
|
||||
}
|
||||
if (electronApplication && proxyActive) {
|
||||
await evaluateProof(electronApplication, 'proxy.release-child').catch(() => undefined);
|
||||
await evaluateProof(electronApplication, 'proxy.finish').catch(() => undefined);
|
||||
}
|
||||
if (electronApplication) await closeApplication(electronApplication);
|
||||
await rm(scratchRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user