fix: enforce one Pi runtime per user

This commit is contained in:
2026-07-21 16:13:17 +02:00
parent a040c083cc
commit 00761ae2ca
4 changed files with 125 additions and 19 deletions
+17 -1
View File
@@ -12,6 +12,7 @@ export interface SessionRuntime {
rpc: RpcClient;
bridge: SessionBridge;
child: ChildProcessWithoutNullStreams;
ownerKey?: string;
}
export interface RuntimeOptions {
@@ -102,6 +103,15 @@ export class PiProcessManager {
get(id: string): SessionRuntime | undefined { return this.runtimes.get(id); }
teardownForPrincipal(principal: PrincipalContext): string[] {
const ownerKey = `${principal.issuer}\0${principal.subject}`;
const stopped: string[] = [];
for (const [id, runtime] of [...this.runtimes.entries()]) {
if (runtime.ownerKey === ownerKey && this.teardownIfCurrent(id, runtime)) stopped.push(id);
}
return stopped;
}
/** Spawn and register a runtime synchronously, without starting a model turn. */
createFor(sessionId: string, o: RuntimeOptions = {}): SessionRuntime {
// A duplicate start must never tear down a live session: that used to send
@@ -110,6 +120,7 @@ export class PiProcessManager {
if (existing) {
throw new Error(`session runtime already active: ${sessionId}`);
}
if (o.principal) this.teardownForPrincipal(o.principal);
if (this.runtimes.size >= this.cfg.maxPiProcesses) {
throw new Error("max Pi processes reached");
}
@@ -120,7 +131,12 @@ export class PiProcessManager {
try {
const rpc = new RpcClient(child);
const bridge = new SessionBridge(rpc);
const runtime: SessionRuntime = { rpc, bridge, child };
const runtime: SessionRuntime = {
rpc,
bridge,
child,
ownerKey: o.principal ? `${o.principal.issuer}\0${o.principal.subject}` : undefined,
};
rt = runtime;
bridge.beginTurn();
this.runtimes.set(sessionId, runtime);