fix(pi): recover from Works prompt rejection
This commit is contained in:
@@ -143,6 +143,11 @@ function assertProxyStatus(status) {
|
||||
|| status?.processes?.supported !== true
|
||||
|| status?.processes?.parent?.length !== 1
|
||||
|| status?.processes?.child?.length !== 1
|
||||
|| status?.providerCompatibility?.roleContract?.developerRejected !== true
|
||||
|| status?.providerCompatibility?.roleContract?.systemAccepted !== true
|
||||
|| status?.providerCompatibility?.developerRoleRequests !== 0
|
||||
|| status?.providerCompatibility?.systemRoleRequests < 2
|
||||
|| status?.providerCompatibility?.controlledDefiniteRejections !== 1
|
||||
|| Object.values(status?.tokenSafety ?? {}).some((safe) => safe !== true)) {
|
||||
throw new Error(`Packaged Main proxy status is incomplete: ${JSON.stringify(status)}`);
|
||||
}
|
||||
@@ -157,6 +162,10 @@ function assertProxyProof(proof) {
|
||||
|| proof?.firstConversation?.runStatus !== 'idle'
|
||||
|| proof?.firstConversation?.userInputProjected !== true
|
||||
|| proof?.firstConversation?.parentResponseProjected !== true
|
||||
|| proof?.firstConversation?.definiteRejectionObserved !== true
|
||||
|| proof?.firstConversation?.retryAccepted !== true
|
||||
|| proof?.providerCompatibility?.developerRoleRequests !== 0
|
||||
|| proof?.providerCompatibility?.controlledDefiniteRejections !== 1
|
||||
|| proof?.currentHostTokenUsedBy?.join(',') !== 'parent,child'
|
||||
|| proof?.released?.workers !== 0
|
||||
|| Object.values(proof?.tokenSafety ?? {}).some((safe) => safe !== true)) {
|
||||
@@ -164,19 +173,25 @@ function assertProxyProof(proof) {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForActiveProxyProof(electronApplication) {
|
||||
async function waitForProxyProof(electronApplication, predicate, message) {
|
||||
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;
|
||||
}
|
||||
if (predicate(latest?.proxy)) return latest;
|
||||
await new Promise((resolveWait) => setTimeout(resolveWait, 200));
|
||||
}
|
||||
throw new Error(`Packaged Main proxy child did not become active: ${JSON.stringify(latest?.proxy)}`);
|
||||
throw new Error(`${message}: ${JSON.stringify(latest?.proxy)}`);
|
||||
}
|
||||
|
||||
async function waitForActiveProxyProof(electronApplication) {
|
||||
return await waitForProxyProof(
|
||||
electronApplication,
|
||||
(status) => status?.activeProviderRequests?.child === 1
|
||||
&& status?.processes?.parent?.length === 1
|
||||
&& status?.processes?.child?.length === 1,
|
||||
'Packaged Main proxy child did not become active',
|
||||
);
|
||||
}
|
||||
|
||||
async function waitForResilienceProof(electronApplication, predicate, message) {
|
||||
@@ -380,7 +395,9 @@ export async function runPackagedProductProof(options) {
|
||||
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');
|
||||
const rejectedPrompt = 'Exercise the packaged Main proxy rejection';
|
||||
const retryPrompt = 'Retry the packaged Main proxy Conversation';
|
||||
await composer.fill(rejectedPrompt);
|
||||
if (!await composer.isEnabled()) throw new Error('Packaged proxy first Conversation composer is disabled');
|
||||
const beforeSubmitText = await page.locator('body').innerText();
|
||||
if (beforeSubmitText.includes('本地编程运行时暂时不可用')
|
||||
@@ -389,6 +406,42 @@ export async function runPackagedProductProof(options) {
|
||||
}
|
||||
await page.getByRole('button', { name: '发送' }).click({ timeout: 30_000 });
|
||||
|
||||
const rejectedProxy = await waitForProxyProof(
|
||||
electronApplication,
|
||||
(status) => status?.providerCompatibility?.controlledDefiniteRejections === 1,
|
||||
'Packaged Main did not observe the controlled definite rejection',
|
||||
);
|
||||
const draftDeadline = Date.now() + 10_000;
|
||||
while (Date.now() < draftDeadline && await composer.inputValue() !== rejectedPrompt) {
|
||||
await new Promise((resolveWait) => setTimeout(resolveWait, 100));
|
||||
}
|
||||
const draftRestored = await composer.inputValue() === rejectedPrompt;
|
||||
const rejectionText = await page.locator('body').innerText();
|
||||
const submissionErrorSafe = !rejectionText.includes('controlled definite model rejection')
|
||||
&& !rejectionText.includes('developer role is unsupported')
|
||||
&& !rejectionText.includes('X-Works-Square-AI-Token')
|
||||
&& !rejectionText.includes('Authorization');
|
||||
if (!draftRestored || !submissionErrorSafe) {
|
||||
throw new Error(
|
||||
`Packaged definite rejection did not restore a safe draft: ${JSON.stringify({ draftRestored, submissionErrorSafe })}`,
|
||||
);
|
||||
}
|
||||
if (await page.getByRole('button', { name: '重试' }).count()) {
|
||||
throw new Error('Packaged definite submission rejection was exposed as a runtime recovery error');
|
||||
}
|
||||
await composer.fill(retryPrompt);
|
||||
const sendButton = page.getByRole('button', { name: '发送' });
|
||||
const retryDeadline = Date.now() + 10_000;
|
||||
while (Date.now() < retryDeadline && !await sendButton.isEnabled()) {
|
||||
await new Promise((resolveWait) => setTimeout(resolveWait, 100));
|
||||
}
|
||||
const retryAfterEditEnabled = await sendButton.isEnabled();
|
||||
if (!retryAfterEditEnabled) {
|
||||
const bodyText = await page.locator('body').innerText();
|
||||
throw new Error(`Packaged proxy retry stayed disabled after editing: ${bodyText}`);
|
||||
}
|
||||
await sendButton.click({ timeout: 30_000 });
|
||||
|
||||
let proxyStatus;
|
||||
try {
|
||||
proxyStatus = await waitForActiveProxyProof(electronApplication);
|
||||
@@ -590,11 +643,16 @@ export async function runPackagedProductProof(options) {
|
||||
},
|
||||
proxy: {
|
||||
setup: proxyStart.proxy,
|
||||
rejected: rejectedProxy.proxy,
|
||||
active: proxyStatus.proxy,
|
||||
completed: proxyFinish.proxy,
|
||||
ui: {
|
||||
firstConversationEditable: true,
|
||||
inputSubmitted: true,
|
||||
definiteRejectionObserved: true,
|
||||
draftRestored,
|
||||
submissionErrorSafe,
|
||||
retryAfterEditEnabled,
|
||||
retrySubmitted: true,
|
||||
runtimeUnavailableBanner: false,
|
||||
permanentRecovering: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user