fix(pi): recover from Works prompt rejection

This commit is contained in:
2026-08-25 14:50:10 +08:00
parent 4580568384
commit 5f0ef761ea
9 changed files with 439 additions and 31 deletions

View File

@@ -43,6 +43,7 @@ export interface PiProviderModelDescriptor {
compat?: {
thinkingFormat?: 'deepseek' | 'openrouter';
sessionAffinityFormat?: 'openrouter';
supportsDeveloperRole?: boolean;
requiresReasoningContentOnAssistantMessages?: boolean;
};
thinkingLevelMap?: Partial<Record<ProductModelRef['thinkingLevel'], string | null>>;
@@ -291,6 +292,7 @@ function modelDescriptor(
summaries: readonly ModelSummary[],
compat: PiProviderModelDescriptor['compat'],
backendModels: Map<string, ProviderModelEntry>,
enforcedCompat: PiProviderModelDescriptor['compat'],
): PiProviderModelDescriptor {
const summary = summaries.find((candidate) => (
candidate.id === modelId
@@ -320,8 +322,8 @@ function modelDescriptor(
|| backend?.reasoning === true,
...(contextWindow ? { contextWindow } : {}),
...(maxOutputTokens ? { maxOutputTokens } : {}),
...(compat || profile?.pi?.compat
? { compat: { ...compat, ...profile?.pi?.compat } }
...(compat || profile?.pi?.compat || enforcedCompat
? { compat: { ...compat, ...profile?.pi?.compat, ...enforcedCompat } }
: {}),
...(profile?.pi?.thinkingLevelMap
? { thinkingLevelMap: { ...profile.pi.thinkingLevelMap } }
@@ -367,12 +369,19 @@ function descriptorForAccount(
);
}
const apiKeyEnv = apiKeyEnvForAccount(account.id);
const credentialMode = account.metadata?.worksSquareCredentialMode;
const enforcedCompat: PiProviderModelDescriptor['compat'] = mapping.api === 'openai-completions'
&& (credentialMode === WORKS_SQUARE_AI_GATEWAY_CREDENTIAL_MODE
|| credentialMode === WORKS_SQUARE_AI_GATEWAY_PROXY_CREDENTIAL_MODE)
? { supportsDeveloperRole: false }
: undefined;
const models = modelIdsForAccount(account).map((modelId) => modelDescriptor(
account,
modelId,
summaries,
mapping.compat,
backendModelEntries(account),
enforcedCompat,
));
if (models.length === 0) {
throw new PiProviderConfigError(

View File

@@ -36,7 +36,7 @@ import { PiProcessBudget, PiWorkerPool, type PiWorkerPoolEvent } from './worker-
import { PiProjectWriteLeaseCoordinator, type PiProjectWriteLease } from './write-lease';
type ProofWorkerRole = 'parent' | 'child';
type ProofProviderMode = 'subagent' | 'pressure' | 'resilience';
type ProofProviderMode = 'subagent' | 'pressure' | 'resilience' | 'submit-rejection';
type ProofMilestone = PiRuntimeTelemetryEvent['milestone'] | 'agent.start' | 'provider.first_event';
type ProofMilestoneSource = 'main.telemetry' | 'pi.agent_start' | 'pi.assistant_message_start';
@@ -56,6 +56,8 @@ type ProviderRequest = {
role: ProofWorkerRole;
toolNames: string[];
hasToolResult: boolean;
firstMessageRole: string | null;
outcome: 'accepted' | 'controlled_rejection' | 'developer_role_rejection';
};
type HeldProviderResponse = {
@@ -66,6 +68,7 @@ type HeldProviderResponse = {
type LocalProofProvider = {
baseUrl: string;
requests: ProviderRequest[];
roleContract: { developerRejected: boolean; systemAccepted: boolean } | null;
activeCounts(): { parent: number; child: number };
releaseChildren(): void;
releaseParents(): void;
@@ -184,6 +187,13 @@ export interface PiReleaseProxyCompositionStatus {
logs: boolean;
diagnostics: boolean;
};
providerCompatibility: {
roleContract: { developerRejected: boolean; systemAccepted: boolean };
requestRoles: string[];
developerRoleRequests: number;
systemRoleRequests: number;
controlledDefiniteRejections: number;
};
realTurnVerified: false;
}
@@ -196,6 +206,8 @@ export interface PiReleaseProxyCompositionProof extends PiReleaseProxyCompositio
runStatus: string;
userInputProjected: boolean;
parentResponseProjected: boolean;
definiteRejectionObserved: boolean;
retryAccepted: boolean;
};
currentHostTokenUsedBy: ProofWorkerRole[];
released: { workers: number };
@@ -247,6 +259,7 @@ export interface PiReleaseResilienceProof extends PiReleaseResilienceStatus {
const PROOF_ACCOUNT_ID = 'release-proof-account';
const PROOF_AGENT_ID = 'release-proof-agent';
const PROOF_MODEL_ID = 'release-proof-model';
const PROXY_PROOF_MODEL_ID = 'deepseek-v4-pro';
const PROOF_PROVIDER_FIRST_EVENT_DELAY_MS = 75;
const EXPECTED_TURN_MILESTONES: readonly ProofMilestone[] = [
'worker.queue_wait',
@@ -327,6 +340,19 @@ function hasToolResult(body: Record<string, unknown>): boolean {
));
}
function firstMessageRole(body: Record<string, unknown>): string | null {
if (!Array.isArray(body.messages)) return null;
const first = body.messages[0];
if (!first || typeof first !== 'object' || Array.isArray(first)) return null;
const role = (first as { role?: unknown }).role;
return typeof role === 'string' ? role : null;
}
function rejectProofRequest(response: ServerResponse, message: string): void {
response.writeHead(400, { 'content-type': 'application/json' });
response.end(JSON.stringify({ error: { message } }));
}
function writeChunk(
response: ServerResponse,
model: string,
@@ -422,6 +448,7 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
const held = new Set<HeldProviderResponse>();
let closed = false;
let closeFlight: Promise<void> | null = null;
let controlledSubmitRejectionIssued = false;
const server: Server = createServer(async (request, response) => {
response.once('error', () => undefined);
try {
@@ -431,10 +458,43 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
}
const body = await readRequestBody(request);
const model = typeof body.model === 'string' ? body.model : PROOF_MODEL_ID;
const leadingRole = firstMessageRole(body);
if (request.headers['x-makelore-release-proof-role-canary'] === '1') {
if (leadingRole === 'developer') {
rejectProofRequest(response, 'developer role is unsupported by the controlled endpoint');
} else if (leadingRole === 'system') {
response.writeHead(204).end();
} else {
rejectProofRequest(response, 'role canary requires a leading system or developer message');
}
return;
}
const toolNames = toolNamesFrom(body);
const role: ProofWorkerRole = toolNames.includes('subagent') ? 'parent' : 'child';
const toolResult = hasToolResult(body);
requests.push({ role, toolNames, hasToolResult: toolResult });
const providerRequest: ProviderRequest = {
role,
toolNames,
hasToolResult: toolResult,
firstMessageRole: leadingRole,
outcome: 'accepted',
};
requests.push(providerRequest);
if (mode === 'submit-rejection' && leadingRole === 'developer') {
providerRequest.outcome = 'developer_role_rejection';
rejectProofRequest(response, 'developer role is unsupported by the controlled endpoint');
return;
}
if (mode === 'submit-rejection'
&& role === 'parent'
&& !toolResult
&& !controlledSubmitRejectionIssued) {
controlledSubmitRejectionIssued = true;
providerRequest.outcome = 'controlled_rejection';
rejectProofRequest(response, 'controlled definite model rejection');
return;
}
if (mode === 'resilience') {
if (role === 'child') {
@@ -470,12 +530,12 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
return;
}
if (mode === 'subagent' && role === 'parent' && !toolResult) {
if ((mode === 'subagent' || mode === 'submit-rejection') && role === 'parent' && !toolResult) {
await delay(PROOF_PROVIDER_FIRST_EVENT_DELAY_MS);
respondWithSubagentCall(response, model);
return;
}
if (mode === 'subagent' && role === 'parent') {
if ((mode === 'subagent' || mode === 'submit-rejection') && role === 'parent') {
await delay(PROOF_PROVIDER_FIRST_EVENT_DELAY_MS);
respondWithText(response, model, 'REAL_PARENT_COMPLETE');
return;
@@ -506,6 +566,33 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
if (!address || typeof address === 'string') {
throw new Error('Release proof Provider did not bind a loopback port');
}
const baseUrl = `http://127.0.0.1:${address.port}/v1`;
let roleContract: LocalProofProvider['roleContract'] = null;
if (mode === 'submit-rejection') {
const probe = async (role: 'developer' | 'system'): Promise<number> => {
const response = await fetch(`${baseUrl}/chat/completions`, {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-makelore-release-proof-role-canary': '1',
},
body: JSON.stringify({
model: PROXY_PROOF_MODEL_ID,
messages: [{ role, content: 'role canary' }],
}),
});
await response.text();
return response.status;
};
const [developerStatus, systemStatus] = await Promise.all([
probe('developer'),
probe('system'),
]);
roleContract = {
developerRejected: developerStatus === 400,
systemAccepted: systemStatus === 204,
};
}
const release = (role?: ProofWorkerRole) => {
for (const entry of [...held]) {
if (role && entry.role !== role) continue;
@@ -514,8 +601,9 @@ async function startLocalProofProvider(mode: ProofProviderMode): Promise<LocalPr
}
};
return {
baseUrl: `http://127.0.0.1:${address.port}/v1`,
baseUrl,
requests,
roleContract,
activeCounts: () => ({
parent: [...held].filter(({ role }) => role === 'parent').length,
child: [...held].filter(({ role }) => role === 'child').length,
@@ -782,13 +870,14 @@ async function inspectWindowsPiProcesses(hostToken: string): Promise<{
return { supported: true, processes };
}
function proxyProviderAccount(baseUrl: string): ProviderAccount {
function proxyProviderAccount(baseUrl: string, modelId = PROOF_MODEL_ID): ProviderAccount {
return {
...providerAccount(baseUrl),
model: modelId,
label: 'Authenticated Host proxy release proof',
metadata: {
worksSquareCredentialMode: 'works_square_ai_gateway_proxy',
customModels: [PROOF_MODEL_ID],
customModels: [modelId],
},
};
}
@@ -811,6 +900,24 @@ async function proxyCompositionStatus(
directoryContainsValue(logsDirectory, run.hostToken),
]);
const providerRequests = providerRequestCounts(run.provider);
const providerCompatibility = {
roleContract: run.provider.roleContract ?? {
developerRejected: false,
systemAccepted: false,
},
requestRoles: run.provider.requests.flatMap(({ firstMessageRole }) => (
firstMessageRole ? [firstMessageRole] : []
)),
developerRoleRequests: run.provider.requests.filter(({ firstMessageRole }) => (
firstMessageRole === 'developer'
)).length,
systemRoleRequests: run.provider.requests.filter(({ firstMessageRole }) => (
firstMessageRole === 'system'
)).length,
controlledDefiniteRejections: run.provider.requests.filter(({ outcome }) => (
outcome === 'controlled_rejection'
)).length,
};
const parent = processInspection.processes
.filter(({ role }) => role === 'parent')
.map(({ processId }) => processId)
@@ -832,6 +939,7 @@ async function proxyCompositionStatus(
logs: !logsContainToken,
diagnostics: !JSON.stringify(diagnostics).includes(run.hostToken),
},
providerCompatibility,
realTurnVerified: false,
};
}
@@ -1256,7 +1364,7 @@ export async function startFinalAsarProxyCompositionProof(input: {
if (proxyCompositionRun) throw new Error('PI proxy composition proof is already running');
const hostToken = input.hostToken.trim();
if (!hostToken) throw new Error('Current Main Host token is unavailable');
const provider = await startLocalProofProvider('subagent');
const provider = await startLocalProofProvider('submit-rejection');
let projectId: string | null = null;
try {
seedWorksSquareAIGatewayCredential({
@@ -1264,7 +1372,10 @@ export async function startFinalAsarProxyCompositionProof(input: {
oneApiBaseUrl: provider.baseUrl,
});
const providerService = getProviderService();
await providerService.createAccount(proxyProviderAccount(input.hostProxyBaseUrl));
await providerService.createAccount(proxyProviderAccount(
input.hostProxyBaseUrl,
PROXY_PROOF_MODEL_ID,
));
await providerService.setDefaultAccount(PROOF_ACCOUNT_ID);
const project = await input.composition.projects.createProject({ projectPath: input.projectPath });
projectId = project.project.id;
@@ -1275,8 +1386,8 @@ export async function startFinalAsarProxyCompositionProof(input: {
name: 'Packaged proxy proof agent',
model: {
accountId: PROOF_ACCOUNT_ID,
modelId: PROOF_MODEL_ID,
thinkingLevel: 'medium',
modelId: PROXY_PROOF_MODEL_ID,
thinkingLevel: 'high',
},
modelResolution: 'resolved',
responsibility: {
@@ -1366,6 +1477,15 @@ export async function finishFinalAsarProxyCompositionProof(): Promise<PiReleaseP
if (!binding?.piSessionId || !binding.sessionKey) {
throw new Error('First proxy Conversation did not persist its Pi session binding');
}
if (!finalStatus.providerCompatibility.roleContract.developerRejected
|| !finalStatus.providerCompatibility.roleContract.systemAccepted
|| finalStatus.providerCompatibility.developerRoleRequests !== 0
|| finalStatus.providerCompatibility.systemRoleRequests < 2
|| finalStatus.providerCompatibility.controlledDefiniteRejections !== 1) {
throw new Error(
`Works Provider role compatibility proof failed: ${JSON.stringify(finalStatus.providerCompatibility)}`,
);
}
const tokenSafety = {
argv: activeStatus.tokenSafety.argv && finalStatus.tokenSafety.argv,
modelsJson: activeStatus.tokenSafety.modelsJson && finalStatus.tokenSafety.modelsJson,
@@ -1387,8 +1507,10 @@ export async function finishFinalAsarProxyCompositionProof(): Promise<PiReleaseP
bindingEstablished: true,
workerStatus: snapshot.worker.status,
runStatus: snapshot.run.status,
userInputProjected: serializedNodes.includes('Exercise the packaged Main proxy Conversation'),
userInputProjected: serializedNodes.includes('Retry the packaged Main proxy Conversation'),
parentResponseProjected: serializedNodes.includes('REAL_PARENT_COMPLETE'),
definiteRejectionObserved: finalStatus.providerCompatibility.controlledDefiniteRejections === 1,
retryAccepted: finalStatus.providerCompatibility.systemRoleRequests >= 2,
},
currentHostTokenUsedBy,
};