mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
A manager on the p2 server owns every MCP connection and process. Session workers hold one view each and lease the locations their conversations work at; the manager runs the owner's mcp.json servers there (stdio per session and location, or shared; HTTP shared by default) and offers their tools as deferred Durable tools found through tool_search. Stdio servers on an environment start through its pi-env daemon, one connection per environment shared by its instances, through cmd.exe on Windows. A project's .pi/mcp.json, read by the worker at each location, may add stdio servers that run there and switch the owner's servers on or off; the manager refuses everything else. A lease gets servers only on environments its session works on.
44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
// The supervisor's pi-env connections to environments: one per environment and configuration revision, shared by every
|
|
// instance running there and closed with the last one. A connection lost meanwhile starts again at its next request
|
|
// (pi-env); the daemon killed the programs it ran, and their instances reconnect.
|
|
|
|
import type { Connection } from "@earendil-works/pi-env";
|
|
import { envRevision } from "@p2/app/v1/node";
|
|
import type { EnvConfig } from "../envs/config.ts";
|
|
|
|
/** A connection to environment `name` configured as `config`, which starts at its first request. */
|
|
export type ConnectEnv = (name: string, config: EnvConfig) => Connection;
|
|
|
|
/** One instance's use of an environment's connection; released once, when the instance closes. */
|
|
export type EnvLease = { readonly connection: Connection; release(): void };
|
|
|
|
/** The open connections by environment and revision, with how many instances use each. */
|
|
export class EnvConnections {
|
|
readonly #connect: ConnectEnv;
|
|
readonly #open = new Map<string, { readonly connection: Connection; users: number }>();
|
|
|
|
constructor(connect: ConnectEnv) {
|
|
this.#connect = connect;
|
|
}
|
|
|
|
/** The connection to `name` as configured now (opened for its first user); release it once done. */
|
|
acquire(name: string, config: EnvConfig): EnvLease {
|
|
const key = JSON.stringify([name, envRevision(config)]);
|
|
let entry = this.#open.get(key);
|
|
if (entry === undefined) {
|
|
entry = { connection: this.#connect(name, config), users: 0 };
|
|
this.#open.set(key, entry);
|
|
}
|
|
const used = entry;
|
|
used.users++;
|
|
return {
|
|
connection: used.connection,
|
|
release: () => {
|
|
used.users--;
|
|
if (used.users > 0) return;
|
|
this.#open.delete(key);
|
|
used.connection.close();
|
|
},
|
|
};
|
|
}
|
|
}
|