|
|
|
|
@@ -0,0 +1,593 @@
|
|
|
|
|
import { spawn, type ChildProcess } from 'node:child_process';
|
|
|
|
|
import { mkdtemp, rm } from 'node:fs/promises';
|
|
|
|
|
import { tmpdir } from 'node:os';
|
|
|
|
|
import path from 'node:path';
|
|
|
|
|
import { pathToFileURL } from 'node:url';
|
|
|
|
|
|
|
|
|
|
import { createCodingConversationStore } from '../../coding-projects/conversation-store';
|
|
|
|
|
import { createCodingProjectAgent } from '../../coding-projects/project-config';
|
|
|
|
|
import {
|
|
|
|
|
createCodingProjectStore,
|
|
|
|
|
createLocalCodingProject,
|
|
|
|
|
createMemoryCodingProjectStorage,
|
|
|
|
|
} from '../../coding-projects/project-store';
|
|
|
|
|
import type { ProviderAccount } from '../../shared/providers/types';
|
|
|
|
|
import type { PrepareConversationInput } from '../contracts';
|
|
|
|
|
import type { PiProcessError } from './process-errors';
|
|
|
|
|
import { PiManagedExtensionHost } from './extension-host';
|
|
|
|
|
import type {
|
|
|
|
|
PiRpcCommand,
|
|
|
|
|
PiRpcEvent,
|
|
|
|
|
PiRpcResponse,
|
|
|
|
|
} from './rpc-client';
|
|
|
|
|
import {
|
|
|
|
|
PiSubagentScheduler,
|
|
|
|
|
type PiSubagentChild,
|
|
|
|
|
} from './subagent';
|
|
|
|
|
import {
|
|
|
|
|
PiProcessBudget,
|
|
|
|
|
PiWorkerPool,
|
|
|
|
|
type PiConversationWorker,
|
|
|
|
|
} from './worker-pool';
|
|
|
|
|
import { PiProjectWriteLeaseCoordinator, type PiProjectWriteLease } from './write-lease';
|
|
|
|
|
import { createPiManagedWorkerOpener } from './runtime';
|
|
|
|
|
import { PiSessionRegistry } from './session-registry';
|
|
|
|
|
import type { PiRuntimeTelemetryEvent } from './telemetry';
|
|
|
|
|
|
|
|
|
|
type ExtensionHandler = (...arguments_: unknown[]) => Promise<unknown> | unknown;
|
|
|
|
|
type ExtensionTool = {
|
|
|
|
|
name: string;
|
|
|
|
|
execute?: (...arguments_: unknown[]) => Promise<unknown>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type PressureProcess = {
|
|
|
|
|
label: string;
|
|
|
|
|
child: ChildProcess;
|
|
|
|
|
pid: number;
|
|
|
|
|
stop(): Promise<void>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Deferred = {
|
|
|
|
|
promise: Promise<void>;
|
|
|
|
|
resolve(): void;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type PressureRun = {
|
|
|
|
|
active: PiReleasePressureSnapshot;
|
|
|
|
|
finish(): Promise<PiReleasePressureSnapshot>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export interface PiReleasePressureSnapshot {
|
|
|
|
|
parentWorkers: number;
|
|
|
|
|
childWorkers: number;
|
|
|
|
|
liveProcessIds: number[];
|
|
|
|
|
processBudget: { active: number; waiting: number };
|
|
|
|
|
childPermits: { active: number; waiting: number };
|
|
|
|
|
dispatches: { active: number; parents: number };
|
|
|
|
|
writeLeases: { active: number; waiting: number };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface PiReleaseExtensionProof {
|
|
|
|
|
parentToolNames: string[];
|
|
|
|
|
childToolNames: string[];
|
|
|
|
|
subagentStatus: string;
|
|
|
|
|
subagentSummary: string;
|
|
|
|
|
materializedExtension: string;
|
|
|
|
|
managedWorkerMilestones: PiRuntimeTelemetryEvent[];
|
|
|
|
|
released: {
|
|
|
|
|
processBudget: { active: number; waiting: number };
|
|
|
|
|
childPermits: { active: number; waiting: number };
|
|
|
|
|
dispatches: { active: number; parents: number };
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let pressureRun: PressureRun | null = null;
|
|
|
|
|
|
|
|
|
|
function deferred(): Deferred {
|
|
|
|
|
let resolve!: () => void;
|
|
|
|
|
const promise = new Promise<void>((done) => { resolve = done; });
|
|
|
|
|
return { promise, resolve };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function waitFor(predicate: () => boolean, message: string): Promise<void> {
|
|
|
|
|
const deadline = Date.now() + 10_000;
|
|
|
|
|
while (Date.now() < deadline) {
|
|
|
|
|
if (predicate()) return;
|
|
|
|
|
await new Promise((resolveWait) => setTimeout(resolveWait, 20));
|
|
|
|
|
}
|
|
|
|
|
throw new Error(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function spawnPressureProcess(label: string): Promise<PressureProcess> {
|
|
|
|
|
const child = spawn(process.execPath, [
|
|
|
|
|
'-e',
|
|
|
|
|
`process.title=${JSON.stringify(`makelore-pi-proof-${label}`)};setInterval(()=>{},1000)`,
|
|
|
|
|
], {
|
|
|
|
|
env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' },
|
|
|
|
|
stdio: 'ignore',
|
|
|
|
|
windowsHide: true,
|
|
|
|
|
});
|
|
|
|
|
await new Promise<void>((resolveSpawn, rejectSpawn) => {
|
|
|
|
|
child.once('spawn', resolveSpawn);
|
|
|
|
|
child.once('error', rejectSpawn);
|
|
|
|
|
});
|
|
|
|
|
if (!child.pid) throw new Error(`Pressure process ${label} has no pid`);
|
|
|
|
|
let stopFlight: Promise<void> | null = null;
|
|
|
|
|
return {
|
|
|
|
|
label,
|
|
|
|
|
child,
|
|
|
|
|
pid: child.pid,
|
|
|
|
|
stop: () => {
|
|
|
|
|
if (stopFlight) return stopFlight;
|
|
|
|
|
stopFlight = (async () => {
|
|
|
|
|
if (child.exitCode !== null || child.signalCode !== null) return;
|
|
|
|
|
const exited = new Promise<void>((resolveExit) => child.once('exit', () => resolveExit()));
|
|
|
|
|
child.kill('SIGTERM');
|
|
|
|
|
const graceful = await Promise.race([
|
|
|
|
|
exited.then(() => true),
|
|
|
|
|
new Promise<boolean>((resolveTimeout) => setTimeout(() => resolveTimeout(false), 2_000)),
|
|
|
|
|
]);
|
|
|
|
|
if (!graceful && child.exitCode === null && child.signalCode === null) {
|
|
|
|
|
child.kill('SIGKILL');
|
|
|
|
|
await exited;
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
return stopFlight;
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PressureConversationWorker implements PiConversationWorker {
|
|
|
|
|
readonly id: string;
|
|
|
|
|
private readonly eventListeners = new Set<(event: PiRpcEvent) => void>();
|
|
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
|
readonly generation: number,
|
|
|
|
|
readonly process: PressureProcess,
|
|
|
|
|
) {
|
|
|
|
|
this.id = process.label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async request<T = unknown>(command: PiRpcCommand): Promise<PiRpcResponse<T>> {
|
|
|
|
|
return {
|
|
|
|
|
type: 'response',
|
|
|
|
|
id: `${this.id}-${command.type}`,
|
|
|
|
|
command: command.type,
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async send(_command: PiRpcCommand): Promise<void> {}
|
|
|
|
|
|
|
|
|
|
subscribe(listener: (event: PiRpcEvent) => void): () => void {
|
|
|
|
|
this.eventListeners.add(listener);
|
|
|
|
|
return () => this.eventListeners.delete(listener);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subscribeInvalidation(_listener: (error: PiProcessError) => void): () => void {
|
|
|
|
|
return () => undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emitSettled(): void {
|
|
|
|
|
for (const listener of this.eventListeners) listener({ type: 'agent_settled' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async stop() {
|
|
|
|
|
await this.process.stop();
|
|
|
|
|
return { mode: 'forced-tree-kill' as const, code: 0, signal: null };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function conversation(index: number): PrepareConversationInput {
|
|
|
|
|
return {
|
|
|
|
|
conversationId: `release-proof-conversation-${index}`,
|
|
|
|
|
projectId: `release-proof-project-${index}`,
|
|
|
|
|
agentId: 'release-proof-agent',
|
|
|
|
|
title: `Release proof ${index}`,
|
|
|
|
|
model: {
|
|
|
|
|
model: {
|
|
|
|
|
accountId: 'release-proof-account',
|
|
|
|
|
modelId: 'release-proof-model',
|
|
|
|
|
thinkingLevel: 'medium',
|
|
|
|
|
},
|
|
|
|
|
modelResolution: 'resolved',
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pressureSnapshot(
|
|
|
|
|
pool: PiWorkerPool,
|
|
|
|
|
processBudget: PiProcessBudget,
|
|
|
|
|
scheduler: PiSubagentScheduler,
|
|
|
|
|
leases: PiProjectWriteLeaseCoordinator,
|
|
|
|
|
processes: PressureProcess[],
|
|
|
|
|
): PiReleasePressureSnapshot {
|
|
|
|
|
const subagents = scheduler.getDiagnostics();
|
|
|
|
|
return {
|
|
|
|
|
parentWorkers: pool.getDiagnostics().workers.filter(({ state }) => state === 'running').length,
|
|
|
|
|
childWorkers: subagents.activeChildPermits,
|
|
|
|
|
liveProcessIds: processes
|
|
|
|
|
.filter(({ child }) => child.exitCode === null && child.signalCode === null)
|
|
|
|
|
.map(({ pid }) => pid)
|
|
|
|
|
.sort((left, right) => left - right),
|
|
|
|
|
processBudget: { active: processBudget.activeCount, waiting: processBudget.waitingCount },
|
|
|
|
|
childPermits: {
|
|
|
|
|
active: subagents.activeChildPermits,
|
|
|
|
|
waiting: subagents.waitingChildPermits,
|
|
|
|
|
},
|
|
|
|
|
dispatches: {
|
|
|
|
|
active: subagents.activeDispatches,
|
|
|
|
|
parents: subagents.activeParents,
|
|
|
|
|
},
|
|
|
|
|
writeLeases: { active: leases.activeCount, waiting: leases.waitingCount() },
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function startPressureRun(): Promise<PressureRun> {
|
|
|
|
|
const processBudget = new PiProcessBudget(8);
|
|
|
|
|
const processes: PressureProcess[] = [];
|
|
|
|
|
const parentWorkers = new Map<string, PressureConversationWorker>();
|
|
|
|
|
const childGate = deferred();
|
|
|
|
|
const pool = new PiWorkerPool({
|
|
|
|
|
maxRunning: 4,
|
|
|
|
|
maxIdle: 4,
|
|
|
|
|
processBudget,
|
|
|
|
|
openWorker: async ({ conversation: input, generation }) => {
|
|
|
|
|
const pressureProcess = await spawnPressureProcess(`parent-${generation}-${input.conversationId}`);
|
|
|
|
|
processes.push(pressureProcess);
|
|
|
|
|
const worker = new PressureConversationWorker(generation, pressureProcess);
|
|
|
|
|
parentWorkers.set(input.conversationId, worker);
|
|
|
|
|
return {
|
|
|
|
|
worker,
|
|
|
|
|
session: {
|
|
|
|
|
piSessionId: `release-proof-session-${input.conversationId}`,
|
|
|
|
|
sessionKey: `release-proof-session-${input.conversationId}`,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
let childIndex = 0;
|
|
|
|
|
const scheduler = new PiSubagentScheduler({
|
|
|
|
|
processBudget,
|
|
|
|
|
createId: (kind) => `release-proof-${kind}-${++childIndex}`,
|
|
|
|
|
openChild: async (input): Promise<PiSubagentChild> => {
|
|
|
|
|
const pressureProcess = await spawnPressureProcess(`child-${input.taskId}`);
|
|
|
|
|
processes.push(pressureProcess);
|
|
|
|
|
return {
|
|
|
|
|
id: input.taskId,
|
|
|
|
|
async run(_prompt, signal) {
|
|
|
|
|
await Promise.race([
|
|
|
|
|
childGate.promise,
|
|
|
|
|
new Promise<void>((_resolve, reject) => {
|
|
|
|
|
signal.addEventListener('abort', () => reject(new Error('Pressure child aborted')), {
|
|
|
|
|
once: true,
|
|
|
|
|
});
|
|
|
|
|
}),
|
|
|
|
|
]);
|
|
|
|
|
return { summary: `completed ${input.agentId}` };
|
|
|
|
|
},
|
|
|
|
|
async stop() { await pressureProcess.stop(); },
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const writeLeases = new PiProjectWriteLeaseCoordinator();
|
|
|
|
|
const heldWriteLeases: PiProjectWriteLease[] = [];
|
|
|
|
|
const dispatches: Array<Promise<unknown>> = [];
|
|
|
|
|
try {
|
|
|
|
|
const inputs = Array.from({ length: 4 }, (_, index) => conversation(index + 1));
|
|
|
|
|
await Promise.all(inputs.map(async (input) => await pool.prepare(input)));
|
|
|
|
|
await Promise.all(inputs.map(async (input, index) => {
|
|
|
|
|
const ticket = pool.startTopLevel({
|
|
|
|
|
conversationId: input.conversationId,
|
|
|
|
|
runId: `release-proof-parent-run-${index + 1}`,
|
|
|
|
|
command: { type: 'prompt', message: 'release qualification pressure' },
|
|
|
|
|
});
|
|
|
|
|
await ticket.accepted;
|
|
|
|
|
}));
|
|
|
|
|
for (let index = 0; index < 4; index += 1) {
|
|
|
|
|
heldWriteLeases.push(await writeLeases.acquire(
|
|
|
|
|
`release-proof-write-project-${index + 1}`,
|
|
|
|
|
`release-proof-holder-${index + 1}`,
|
|
|
|
|
));
|
|
|
|
|
dispatches.push(scheduler.dispatch({
|
|
|
|
|
conversationId: inputs[index]?.conversationId ?? `release-proof-conversation-${index + 1}`,
|
|
|
|
|
workerGeneration: 1,
|
|
|
|
|
runId: `release-proof-parent-run-${index + 1}`,
|
|
|
|
|
projectId: inputs[index]?.projectId ?? `release-proof-project-${index + 1}`,
|
|
|
|
|
request: {
|
|
|
|
|
mode: 'single',
|
|
|
|
|
tasks: [{
|
|
|
|
|
agentId: `release-proof-child-agent-${index + 1}`,
|
|
|
|
|
task: 'hold one child during UI interaction',
|
|
|
|
|
toolProfile: 'read-only',
|
|
|
|
|
}],
|
|
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
await waitFor(
|
|
|
|
|
() => processBudget.activeCount === 8
|
|
|
|
|
&& scheduler.getDiagnostics().activeChildPermits === 4
|
|
|
|
|
&& processes.length === 8,
|
|
|
|
|
'4 parent + 4 child pressure did not become active',
|
|
|
|
|
);
|
|
|
|
|
const active = pressureSnapshot(pool, processBudget, scheduler, writeLeases, processes);
|
|
|
|
|
if (active.liveProcessIds.length !== 8) {
|
|
|
|
|
throw new Error(`Expected 8 live pressure processes, got ${active.liveProcessIds.length}`);
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
active,
|
|
|
|
|
finish: async () => {
|
|
|
|
|
childGate.resolve();
|
|
|
|
|
await Promise.all(dispatches);
|
|
|
|
|
for (const worker of parentWorkers.values()) worker.emitSettled();
|
|
|
|
|
await scheduler.close();
|
|
|
|
|
await pool.shutdown();
|
|
|
|
|
for (const lease of heldWriteLeases.splice(0)) lease.release();
|
|
|
|
|
await Promise.all(processes.map(async (entry) => await entry.stop()));
|
|
|
|
|
return pressureSnapshot(pool, processBudget, scheduler, writeLeases, processes);
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
childGate.resolve();
|
|
|
|
|
await scheduler.close().catch(() => undefined);
|
|
|
|
|
await pool.shutdown().catch(() => undefined);
|
|
|
|
|
for (const lease of heldWriteLeases.splice(0)) lease.release();
|
|
|
|
|
await Promise.allSettled(processes.map(async (entry) => await entry.stop()));
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function withWorkerEnvironment<T>(
|
|
|
|
|
environment: NodeJS.ProcessEnv,
|
|
|
|
|
operation: () => Promise<T>,
|
|
|
|
|
): Promise<T> {
|
|
|
|
|
const previous = {
|
|
|
|
|
bridge: process.env.MAKELORE_PI_BRIDGE_URL,
|
|
|
|
|
token: process.env.MAKELORE_PI_WORKER_TOKEN,
|
|
|
|
|
context: process.env.MAKELORE_PI_CONTEXT_FILE,
|
|
|
|
|
role: process.env.MAKELORE_PI_WORKER_ROLE,
|
|
|
|
|
};
|
|
|
|
|
Object.assign(process.env, environment);
|
|
|
|
|
try {
|
|
|
|
|
return await operation();
|
|
|
|
|
} finally {
|
|
|
|
|
const values: Array<[keyof typeof previous, string]> = [
|
|
|
|
|
['bridge', 'MAKELORE_PI_BRIDGE_URL'],
|
|
|
|
|
['token', 'MAKELORE_PI_WORKER_TOKEN'],
|
|
|
|
|
['context', 'MAKELORE_PI_CONTEXT_FILE'],
|
|
|
|
|
['role', 'MAKELORE_PI_WORKER_ROLE'],
|
|
|
|
|
];
|
|
|
|
|
for (const [key, environmentKey] of values) {
|
|
|
|
|
const value = previous[key];
|
|
|
|
|
if (value === undefined) delete process.env[environmentKey];
|
|
|
|
|
else process.env[environmentKey] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loadExtension(extensionPath: string, environment: NodeJS.ProcessEnv): Promise<{
|
|
|
|
|
tools: Map<string, ExtensionTool>;
|
|
|
|
|
handlers: Map<string, ExtensionHandler>;
|
|
|
|
|
}> {
|
|
|
|
|
return await withWorkerEnvironment(environment, async () => {
|
|
|
|
|
const module = await import(
|
|
|
|
|
/* @vite-ignore */ `${pathToFileURL(extensionPath).href}?release-proof=${Date.now()}-${Math.random()}`
|
|
|
|
|
) as {
|
|
|
|
|
default(factory: {
|
|
|
|
|
registerTool(tool: ExtensionTool): void;
|
|
|
|
|
on(event: string, handler: ExtensionHandler): void;
|
|
|
|
|
}): void;
|
|
|
|
|
};
|
|
|
|
|
const tools = new Map<string, ExtensionTool>();
|
|
|
|
|
const handlers = new Map<string, ExtensionHandler>();
|
|
|
|
|
module.default({
|
|
|
|
|
registerTool: (tool) => tools.set(tool.name, tool),
|
|
|
|
|
on: (event, handler) => handlers.set(event, handler),
|
|
|
|
|
});
|
|
|
|
|
return { tools, handlers };
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function runManagedWorkerMilestoneProof(
|
|
|
|
|
root: string,
|
|
|
|
|
extensionHost: PiManagedExtensionHost,
|
|
|
|
|
): Promise<PiRuntimeTelemetryEvent[]> {
|
|
|
|
|
const now = new Date().toISOString();
|
|
|
|
|
const projectPath = path.join(root, 'managed-project');
|
|
|
|
|
const userDataDir = path.join(root, 'managed-user-data');
|
|
|
|
|
const projectStore = createCodingProjectStore(createMemoryCodingProjectStorage(), {
|
|
|
|
|
createId: () => 'release-proof-managed-project',
|
|
|
|
|
now: () => now,
|
|
|
|
|
});
|
|
|
|
|
await createLocalCodingProject({ projectPath, now }, projectStore);
|
|
|
|
|
await createCodingProjectAgent(projectPath, {
|
|
|
|
|
id: 'release-proof-agent',
|
|
|
|
|
avatarId: 'avatar-01',
|
|
|
|
|
roleName: 'Release proof',
|
|
|
|
|
name: 'Release proof agent',
|
|
|
|
|
model: {
|
|
|
|
|
accountId: 'release-proof-account',
|
|
|
|
|
modelId: 'release-proof-model',
|
|
|
|
|
thinkingLevel: 'medium',
|
|
|
|
|
},
|
|
|
|
|
modelResolution: 'resolved',
|
|
|
|
|
responsibility: {
|
|
|
|
|
mission: 'Exercise final packaged managed worker composition',
|
|
|
|
|
owns: [],
|
|
|
|
|
boundaries: [],
|
|
|
|
|
collaborators: [],
|
|
|
|
|
principles: [],
|
|
|
|
|
},
|
|
|
|
|
prompt: 'Release qualification only.',
|
|
|
|
|
skillIds: [],
|
|
|
|
|
}, { now });
|
|
|
|
|
const conversationStore = createCodingConversationStore(projectPath, {
|
|
|
|
|
createId: () => 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
|
|
|
|
|
now: () => now,
|
|
|
|
|
});
|
|
|
|
|
const created = await conversationStore.create({
|
|
|
|
|
agentId: 'release-proof-agent',
|
|
|
|
|
title: 'Release proof managed conversation',
|
|
|
|
|
model: {
|
|
|
|
|
accountId: 'release-proof-account',
|
|
|
|
|
modelId: 'release-proof-model',
|
|
|
|
|
thinkingLevel: 'medium',
|
|
|
|
|
},
|
|
|
|
|
modelResolution: 'resolved',
|
|
|
|
|
});
|
|
|
|
|
const input: PrepareConversationInput = {
|
|
|
|
|
conversationId: created.id,
|
|
|
|
|
projectId: 'release-proof-managed-project',
|
|
|
|
|
agentId: 'release-proof-agent',
|
|
|
|
|
title: created.title,
|
|
|
|
|
model: { model: created.model, modelResolution: created.modelResolution },
|
|
|
|
|
};
|
|
|
|
|
const account: ProviderAccount = {
|
|
|
|
|
id: 'release-proof-account',
|
|
|
|
|
vendorId: 'custom',
|
|
|
|
|
label: 'Release proof account',
|
|
|
|
|
authMode: 'api_key',
|
|
|
|
|
apiProtocol: 'openai-completions',
|
|
|
|
|
baseUrl: 'http://127.0.0.1:1/v1',
|
|
|
|
|
model: 'release-proof-model',
|
|
|
|
|
enabled: true,
|
|
|
|
|
isDefault: true,
|
|
|
|
|
createdAt: now,
|
|
|
|
|
updatedAt: now,
|
|
|
|
|
};
|
|
|
|
|
const telemetry: PiRuntimeTelemetryEvent[] = [];
|
|
|
|
|
const opener = createPiManagedWorkerOpener({
|
|
|
|
|
registry: new PiSessionRegistry({ projectStore }),
|
|
|
|
|
executablePath: process.execPath,
|
|
|
|
|
cliPath: path.join(process.resourcesPath, 'pi-runtime', 'dist', 'cli.js'),
|
|
|
|
|
userDataDir,
|
|
|
|
|
bundledSkillsDir: path.join(process.resourcesPath, 'resources', 'coding-skills'),
|
|
|
|
|
extensionHost,
|
|
|
|
|
loadProviderInput: async () => ({ accounts: [account], modelSummaries: [] }),
|
|
|
|
|
resolveCredential: async () => 'release-proof-local-only',
|
|
|
|
|
createSessionKey: () => '8b1a9953-c461-4d88-9c3e-7e1f8f3f2c11',
|
|
|
|
|
onTelemetry: (event) => telemetry.push(event),
|
|
|
|
|
});
|
|
|
|
|
const first = await opener({
|
|
|
|
|
conversation: input,
|
|
|
|
|
generation: 1,
|
|
|
|
|
revision: { provider: 1, resources: 1 },
|
|
|
|
|
});
|
|
|
|
|
try {
|
|
|
|
|
await first.worker.stop();
|
|
|
|
|
const reopened = await opener({
|
|
|
|
|
conversation: input,
|
|
|
|
|
generation: 2,
|
|
|
|
|
revision: { provider: 1, resources: 1 },
|
|
|
|
|
existingSession: first.session,
|
|
|
|
|
});
|
|
|
|
|
await reopened.worker.stop();
|
|
|
|
|
} finally {
|
|
|
|
|
await first.worker.stop().catch(() => undefined);
|
|
|
|
|
}
|
|
|
|
|
const expected = ['resources.ready', 'worker.spawn', 'rpc.ready', 'session.open'];
|
|
|
|
|
for (const cold of [true, false]) {
|
|
|
|
|
const milestones = telemetry.filter((event) => event.cold === cold).map(({ milestone }) => milestone);
|
|
|
|
|
if (JSON.stringify(milestones) !== JSON.stringify(expected)) {
|
|
|
|
|
throw new Error(`Managed worker ${cold ? 'cold' : 'warm'} milestones are incomplete: ${milestones}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return telemetry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function runFinalAsarExtensionProof(): Promise<PiReleaseExtensionProof> {
|
|
|
|
|
const root = await mkdtemp(path.join(tmpdir(), 'makelore-pi-final-asar-extension-'));
|
|
|
|
|
const processBudget = new PiProcessBudget(8);
|
|
|
|
|
const scheduler = new PiSubagentScheduler({
|
|
|
|
|
processBudget,
|
|
|
|
|
openChild: async (input) => ({
|
|
|
|
|
id: input.taskId,
|
|
|
|
|
async run() { return { summary: `done ${input.agentId}` }; },
|
|
|
|
|
async stop() {},
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
const host = new PiManagedExtensionHost();
|
|
|
|
|
host.configureSubagents({ scheduler });
|
|
|
|
|
try {
|
|
|
|
|
const managedWorkerMilestones = await runManagedWorkerMilestoneProof(root, host);
|
|
|
|
|
const parent = await host.registerWorker({
|
|
|
|
|
conversationId: 'release-proof-extension-parent',
|
|
|
|
|
generation: 1,
|
|
|
|
|
projectId: 'release-proof-project',
|
|
|
|
|
extensionsDir: root,
|
|
|
|
|
});
|
|
|
|
|
await host.bindRun('release-proof-extension-parent', 1, 'release-proof-run');
|
|
|
|
|
const parentExtension = await loadExtension(parent.extensionPath, parent.env);
|
|
|
|
|
const updates: unknown[] = [];
|
|
|
|
|
const result = await withWorkerEnvironment(parent.env, async () => (
|
|
|
|
|
await parentExtension.tools.get('subagent')?.execute?.(
|
|
|
|
|
'release-proof-subagent',
|
|
|
|
|
{
|
|
|
|
|
mode: 'single',
|
|
|
|
|
tasks: [{
|
|
|
|
|
agentId: 'release-proof-agent',
|
|
|
|
|
task: 'execute the final materialized extension',
|
|
|
|
|
toolProfile: 'read-only',
|
|
|
|
|
}],
|
|
|
|
|
},
|
|
|
|
|
new AbortController().signal,
|
|
|
|
|
(update: unknown) => updates.push(update),
|
|
|
|
|
)
|
|
|
|
|
)) as { details?: { tasks?: Array<{ status?: string; summary?: string }> } } | undefined;
|
|
|
|
|
const child = await host.registerWorker({
|
|
|
|
|
conversationId: 'release-proof-extension-child',
|
|
|
|
|
generation: 1,
|
|
|
|
|
projectId: 'release-proof-project',
|
|
|
|
|
extensionsDir: root,
|
|
|
|
|
role: 'child',
|
|
|
|
|
runId: 'release-proof-run',
|
|
|
|
|
});
|
|
|
|
|
const childExtension = await loadExtension(child.extensionPath, child.env);
|
|
|
|
|
const task = result?.details?.tasks?.[0];
|
|
|
|
|
if (task?.status !== 'complete' || updates.length === 0) {
|
|
|
|
|
throw new Error('Final materialized extension did not execute its subagent bridge');
|
|
|
|
|
}
|
|
|
|
|
if (childExtension.tools.size !== 0) {
|
|
|
|
|
throw new Error('Final child extension exposed parent-only product tools');
|
|
|
|
|
}
|
|
|
|
|
await scheduler.close();
|
|
|
|
|
const diagnostics = scheduler.getDiagnostics();
|
|
|
|
|
return {
|
|
|
|
|
parentToolNames: [...parentExtension.tools.keys()].sort(),
|
|
|
|
|
childToolNames: [...childExtension.tools.keys()].sort(),
|
|
|
|
|
subagentStatus: task.status,
|
|
|
|
|
subagentSummary: task.summary ?? '',
|
|
|
|
|
materializedExtension: path.basename(parent.extensionPath),
|
|
|
|
|
managedWorkerMilestones,
|
|
|
|
|
released: {
|
|
|
|
|
processBudget: { active: processBudget.activeCount, waiting: processBudget.waitingCount },
|
|
|
|
|
childPermits: {
|
|
|
|
|
active: diagnostics.activeChildPermits,
|
|
|
|
|
waiting: diagnostics.waitingChildPermits,
|
|
|
|
|
},
|
|
|
|
|
dispatches: {
|
|
|
|
|
active: diagnostics.activeDispatches,
|
|
|
|
|
parents: diagnostics.activeParents,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
} finally {
|
|
|
|
|
await scheduler.close().catch(() => undefined);
|
|
|
|
|
await host.close().catch(() => undefined);
|
|
|
|
|
await rm(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function startFinalAsarPressureProof(): Promise<PiReleasePressureSnapshot> {
|
|
|
|
|
if (pressureRun) throw new Error('PI release pressure proof is already running');
|
|
|
|
|
pressureRun = await startPressureRun();
|
|
|
|
|
return pressureRun.active;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function finishFinalAsarPressureProof(): Promise<PiReleasePressureSnapshot> {
|
|
|
|
|
const current = pressureRun;
|
|
|
|
|
if (!current) throw new Error('PI release pressure proof is not running');
|
|
|
|
|
pressureRun = null;
|
|
|
|
|
return await current.finish();
|
|
|
|
|
}
|