cleanup: small optimizations
This commit is contained in:
@@ -129,7 +129,7 @@ export async function handleIpcRequest(request: OrchestratorRequest): Promise<Or
|
||||
}
|
||||
}
|
||||
|
||||
export function attachIpcInstance(
|
||||
export function openRpcStream(
|
||||
instanceId: string,
|
||||
onResponse: (response: RpcResponse) => void,
|
||||
onSessionEvent: (event: AgentSessionEvent) => void,
|
||||
@@ -140,7 +140,7 @@ export function attachIpcInstance(
|
||||
close(): void;
|
||||
}
|
||||
| undefined {
|
||||
const handle = supervisor.attachInstance(instanceId, onSessionEvent, onUiRequest);
|
||||
const handle = supervisor.openRpcStream(instanceId, onSessionEvent, onUiRequest);
|
||||
if (!handle) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export interface IpcRequestHandler {
|
||||
(request: RpcRequest): Promise<RpcBridgeResponse | ErrorResponse> | RpcBridgeResponse | ErrorResponse;
|
||||
(request: RpcStreamRequest): Promise<RpcReadyResponse | ErrorResponse> | RpcReadyResponse | ErrorResponse;
|
||||
(request: OrchestratorRequest): Promise<OrchestratorResponse> | OrchestratorResponse;
|
||||
attach(
|
||||
openRpcStream(
|
||||
instanceId: string,
|
||||
onResponse: (response: import("@earendil-works/pi-coding-agent").RpcResponse) => void,
|
||||
onSessionEvent: (event: import("@earendil-works/pi-coding-agent").AgentSessionEvent) => void,
|
||||
@@ -72,7 +72,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
|
||||
return;
|
||||
}
|
||||
|
||||
const attachment = handler.attach(
|
||||
const rpcStream = handler.openRpcStream(
|
||||
request.instanceId,
|
||||
(response) => {
|
||||
socket.write(encodeMessage(response));
|
||||
@@ -84,7 +84,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
|
||||
socket.write(encodeMessage(request));
|
||||
},
|
||||
);
|
||||
if (!attachment) {
|
||||
if (!rpcStream) {
|
||||
socket.end(
|
||||
encodeMessage({ type: "error", ok: false, error: `Unknown instance: ${request.instanceId}` }),
|
||||
);
|
||||
@@ -108,7 +108,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
|
||||
void (async () => {
|
||||
try {
|
||||
const rpcRequest = JSON.parse(rpcLine) as RpcClientMessage;
|
||||
await attachment.handleRequest(rpcRequest);
|
||||
await rpcStream.handleRequest(rpcRequest);
|
||||
} catch (rpcError) {
|
||||
socket.write(
|
||||
encodeMessage({
|
||||
@@ -121,7 +121,7 @@ export async function startIpcServer(handler: IpcRequestHandler): Promise<Server
|
||||
})();
|
||||
}
|
||||
});
|
||||
socket.once("close", () => attachment.close());
|
||||
socket.once("close", () => rpcStream.close());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,24 +69,31 @@ export function createRpcProcessInstance(options: { cwd: string }): RpcProcessIn
|
||||
|
||||
const handleLine = (line: string) => {
|
||||
const parsed = JSON.parse(line) as { type?: string; id?: string };
|
||||
if (parsed.type === "response") {
|
||||
if (parsed.id) {
|
||||
|
||||
switch (parsed.type) {
|
||||
case "response": {
|
||||
if (!parsed.id) {
|
||||
return;
|
||||
}
|
||||
const pending = pendingRequests.get(parsed.id);
|
||||
if (pending) {
|
||||
pendingRequests.delete(parsed.id);
|
||||
pending.resolve(parsed as RpcResponse);
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
pendingRequests.delete(parsed.id);
|
||||
pending.resolve(parsed as RpcResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
case "extension_ui_request": {
|
||||
uiRequestHandler?.(parsed as RpcExtensionUIRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
default: {
|
||||
for (const listener of eventListeners) {
|
||||
listener(parsed as AgentSessionEvent);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed.type === "extension_ui_request") {
|
||||
uiRequestHandler?.(parsed as RpcExtensionUIRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const listener of eventListeners) {
|
||||
listener(parsed as AgentSessionEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { existsSync, mkdirSync, unlinkSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
import { getSocketPath } from "./config.ts";
|
||||
import { attachIpcInstance, handleIpcRequest } from "./handler.ts";
|
||||
import { handleIpcRequest, openRpcStream } from "./handler.ts";
|
||||
import { startIpcServer } from "./ipc/server.ts";
|
||||
import { getRadiusOrchestratorBaseUrl, isRadiusEnabled, radiusPresence } from "./radius.ts";
|
||||
import { supervisor } from "./supervisor.ts";
|
||||
@@ -21,7 +21,7 @@ export async function serve(): Promise<void> {
|
||||
}
|
||||
const server = await startIpcServer(
|
||||
Object.assign(handleIpcRequest, {
|
||||
attach: attachIpcInstance,
|
||||
openRpcStream,
|
||||
}),
|
||||
);
|
||||
console.log(`orchestrator listening on ${socketPath}`);
|
||||
|
||||
@@ -25,6 +25,26 @@ function cloneInstance(record: InstanceRecord): InstanceRecord {
|
||||
return { ...record };
|
||||
}
|
||||
|
||||
// Only refresh persisted session metadata after commands that can plausibly change
|
||||
// the instance identity/details we store in instances.json. Most RPCs mutate transient
|
||||
// runtime state only, so forcing a follow-up get_state after every command is wasted IO.
|
||||
//
|
||||
// - new_session / switch_session / fork / clone can change sessionId/sessionFile
|
||||
// - set_session_name changes a persisted session detail we may want reflected externally
|
||||
// - prompt can materialize or advance persisted session state after the child processes it
|
||||
const SESSION_METADATA_COMMANDS: ReadonlySet<RpcCommand["type"]> = new Set([
|
||||
"new_session",
|
||||
"switch_session",
|
||||
"fork",
|
||||
"clone",
|
||||
"set_session_name",
|
||||
"prompt",
|
||||
]);
|
||||
|
||||
function shouldRefreshSessionMetadata(command: RpcCommand): boolean {
|
||||
return SESSION_METADATA_COMMANDS.has(command.type);
|
||||
}
|
||||
|
||||
function isGetStateSuccess(
|
||||
response: RpcResponse,
|
||||
): response is Extract<
|
||||
@@ -86,7 +106,7 @@ export class OrchestratorSupervisor {
|
||||
upsertInstance(instance);
|
||||
}
|
||||
|
||||
attachInstance(
|
||||
openRpcStream(
|
||||
instanceId: string,
|
||||
onEvent: (event: AgentSessionEvent) => void,
|
||||
onUiRequest: (request: RpcExtensionUIRequest) => void,
|
||||
@@ -106,7 +126,9 @@ export class OrchestratorSupervisor {
|
||||
return {
|
||||
handleRpc: async (command) => {
|
||||
const response = await live.rpc.send(command);
|
||||
await this.syncInstanceRecord(live);
|
||||
if (shouldRefreshSessionMetadata(command)) {
|
||||
await this.syncInstanceRecord(live);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
handleUiResponse: (response) => {
|
||||
@@ -204,7 +226,9 @@ export class OrchestratorSupervisor {
|
||||
}
|
||||
|
||||
const response = await live.rpc.send(command);
|
||||
await this.syncInstanceRecord(live);
|
||||
if (shouldRefreshSessionMetadata(command)) {
|
||||
await this.syncInstanceRecord(live);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user