fix(rpc): route command update frames
This commit is contained in:
@@ -13,6 +13,7 @@ import type { FileSink } from "bun";
|
||||
import type { BashResult } from "../../exec/bash-executor";
|
||||
import type { AgentSessionEvent, SessionStats } from "../../session/agent-session";
|
||||
import type {
|
||||
RpcAvailableCommandsUpdateFrame,
|
||||
RpcAvailableSlashCommand,
|
||||
RpcCommand,
|
||||
RpcExtensionUIRequest,
|
||||
@@ -64,6 +65,7 @@ export type RpcSessionEventListener = (event: AgentSessionEvent) => void;
|
||||
export type RpcSubagentLifecycleListener = (payload: RpcSubagentLifecycleFrame["payload"]) => void;
|
||||
export type RpcSubagentProgressListener = (payload: RpcSubagentProgressFrame["payload"]) => void;
|
||||
export type RpcSubagentEventListener = (payload: RpcSubagentEventFrame["payload"]) => void;
|
||||
export type RpcAvailableCommandsUpdateListener = (commands: RpcAvailableSlashCommand[]) => void;
|
||||
|
||||
export interface RpcClientToolContext<TDetails = unknown> {
|
||||
toolCallId: string;
|
||||
@@ -162,6 +164,11 @@ function isRpcSubagentEventFrame(value: unknown): value is RpcSubagentEventFrame
|
||||
return value.type === "subagent_event" && isRecord(value.payload);
|
||||
}
|
||||
|
||||
function isRpcAvailableCommandsUpdateFrame(value: unknown): value is RpcAvailableCommandsUpdateFrame {
|
||||
if (!isRecord(value)) return false;
|
||||
return value.type === "available_commands_update" && Array.isArray(value.commands);
|
||||
}
|
||||
|
||||
function isRpcHostToolCallRequest(value: unknown): value is RpcHostToolCallRequest {
|
||||
if (!isRecord(value)) return false;
|
||||
return (
|
||||
@@ -203,6 +210,7 @@ export class RpcClient {
|
||||
#subagentLifecycleListeners = new Set<RpcSubagentLifecycleListener>();
|
||||
#subagentProgressListeners = new Set<RpcSubagentProgressListener>();
|
||||
#subagentEventListeners = new Set<RpcSubagentEventListener>();
|
||||
#availableCommandsUpdateListeners = new Set<RpcAvailableCommandsUpdateListener>();
|
||||
#pendingRequests: Map<string, { resolve: (response: RpcResponse) => void; reject: (error: Error) => void }> =
|
||||
new Map();
|
||||
#customTools: RpcClientCustomTool[] = [];
|
||||
@@ -378,6 +386,14 @@ export class RpcClient {
|
||||
return () => this.#subagentEventListeners.delete(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to slash-command availability updates emitted by the RPC server.
|
||||
*/
|
||||
onAvailableCommandsUpdate(listener: RpcAvailableCommandsUpdateListener): () => void {
|
||||
this.#availableCommandsUpdateListeners.add(listener);
|
||||
return () => this.#availableCommandsUpdateListeners.delete(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get collected stderr output (useful for debugging).
|
||||
*/
|
||||
@@ -834,6 +850,13 @@ export class RpcClient {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRpcAvailableCommandsUpdateFrame(data)) {
|
||||
for (const listener of this.#availableCommandsUpdateListeners) {
|
||||
listener(data.commands);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAgentSessionEvent(data)) return;
|
||||
|
||||
for (const listener of this.#sessionEventListeners) {
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
*/
|
||||
import { getOAuthProviders } from "@oh-my-pi/pi-ai/oauth";
|
||||
import { $env, readJsonl, Snowflake } from "@oh-my-pi/pi-utils";
|
||||
import { reset as resetCapabilities } from "../../capability";
|
||||
import { clearPluginRootsAndCaches, resolveActiveProjectRegistryPath } from "../../discovery/helpers";
|
||||
import {
|
||||
type ExtensionUIContext,
|
||||
type ExtensionUIDialogOptions,
|
||||
@@ -19,6 +21,7 @@ import {
|
||||
type ExtensionWidgetOptions,
|
||||
getExtensionUISelectOptionLabel,
|
||||
} from "../../extensibility/extensions";
|
||||
import { loadSlashCommands } from "../../extensibility/slash-commands";
|
||||
import { type Theme, theme } from "../../modes/theme/theme";
|
||||
import type { AgentSession } from "../../session/agent-session";
|
||||
import { executeAcpBuiltinSlashCommand } from "../../slash-commands/acp-builtins";
|
||||
@@ -514,6 +517,15 @@ export async function runRpcMode(
|
||||
});
|
||||
|
||||
const getAvailableCommands = async () => buildAvailableSlashCommands(session);
|
||||
const reloadPluginState = async () => {
|
||||
const cwd = session.sessionManager.getCwd();
|
||||
const projectPath = await resolveActiveProjectRegistryPath(cwd);
|
||||
clearPluginRootsAndCaches(projectPath ? [projectPath] : undefined);
|
||||
resetCapabilities();
|
||||
session.setSlashCommands(await loadSlashCommands({ cwd }));
|
||||
await session.refreshSshTool({ activateIfAvailable: true });
|
||||
await emitAvailableCommandsUpdate();
|
||||
};
|
||||
const emitAvailableCommandsUpdate = async () => {
|
||||
output({ type: "available_commands_update", commands: await getAvailableCommands() });
|
||||
};
|
||||
@@ -536,7 +548,7 @@ export async function runRpcMode(
|
||||
cwd: session.sessionManager.getCwd(),
|
||||
output: text => output({ type: "command_output", text }),
|
||||
refreshCommands: emitAvailableCommandsUpdate,
|
||||
reloadPlugins: async () => {},
|
||||
reloadPlugins: reloadPluginState,
|
||||
notifyTitleChanged: async () => {},
|
||||
notifyConfigChanged: async () => {},
|
||||
});
|
||||
|
||||
@@ -121,6 +121,11 @@ export interface RpcAvailableSlashCommand {
|
||||
source: AvailableSlashCommandSource;
|
||||
}
|
||||
|
||||
export interface RpcAvailableCommandsUpdateFrame {
|
||||
type: "available_commands_update";
|
||||
commands: RpcAvailableSlashCommand[];
|
||||
}
|
||||
|
||||
export interface RpcHandoffResult {
|
||||
savedPath?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user