Files
paseo/packages/server/src/server/agent/providers/pi/runtime.ts
T
Mohamed Boudra a56442976a fix(pi): restore complete active-branch chat history
Replay the saved transcript ancestry instead of the compacted model context so older messages retain their native rewind identities and Fork chat boundaries.
2026-11-02 05:08:30 +01:00

158 lines
4.3 KiB
TypeScript

import type { PiTranscript } from "./transcript.js";
import type {
PiModel,
PiPromptAck,
PiRpcSlashCommand,
PiRuntimeEvent,
PiSessionState,
PiSessionStats,
} from "./rpc-types.js";
import type { ProviderRuntimeSettings } from "../../provider-launch-config.js";
export interface PiRuntimeLaunch {
cwd: string;
argv: string[];
env?: Record<string, string>;
protocolMode?: "rpc" | "rpc-ui";
model?: string;
thinkingOptionId?: string;
modeId?: string;
session?: string;
noSession?: boolean;
mcpConfigPath?: string;
extensionPaths?: string[];
extraArgs?: string[];
}
export interface PiStartSessionInput {
cwd: string;
signal?: AbortSignal;
env?: Record<string, string>;
protocolMode?: "rpc" | "rpc-ui";
model?: string;
thinkingOptionId?: string;
modeId?: string;
session?: string;
noSession?: boolean;
mcpConfigPath?: string;
extensionPaths?: string[];
extraArgs?: string[];
}
export interface PiRuntimeSession {
readonly environment: Record<string, string>;
onEvent(callback: (event: PiRuntimeEvent) => void): () => void;
prompt(
message: string,
images?: Array<{ type: "image"; data: string; mimeType: string }>,
): Promise<PiPromptAck>;
steer(
message: string,
images?: Array<{ type: "image"; data: string; mimeType: string }>,
): Promise<void>;
clearQueue(): Promise<void>;
compact(customInstructions?: string): Promise<void>;
setAutoCompaction(enabled: boolean): Promise<void>;
abort(): Promise<void>;
getState(): Promise<PiSessionState>;
getHistory(): Promise<PiTranscript>;
getAvailableModels(timeoutMs?: number | null): Promise<PiModel[]>;
setModel(provider: string, modelId: string): Promise<PiModel>;
setThinkingLevel(level: string): Promise<void>;
getSessionStats(): Promise<PiSessionStats>;
getCommands(): Promise<PiRpcSlashCommand[]>;
request(
command: { type: string; [key: string]: unknown },
timeoutMs?: number | null,
): Promise<unknown>;
sendRawFrame(frame: object & { type: string }): void;
respondToExtensionUiRequest(
id: string,
response: { value?: string; confirmed?: boolean; cancelled?: boolean },
): void;
cancelExtensionUiRequest(id: string): void;
close(): Promise<void>;
}
export interface PiRuntime {
startSession(input: PiStartSessionInput): Promise<PiRuntimeSession>;
}
export function buildPiLaunch(input: {
command: [string, ...string[]];
runtimeSettings?: ProviderRuntimeSettings;
session: PiStartSessionInput;
}): PiRuntimeLaunch {
const command =
input.runtimeSettings?.command?.mode === "replace" && input.runtimeSettings.command.argv[0]
? input.runtimeSettings.command.argv
: input.command;
const argv = [...command];
const protocolMode = input.session.protocolMode ?? "rpc";
appendPiLaunchArgs(argv, input.session, protocolMode);
return {
cwd: input.session.cwd,
argv,
env:
input.runtimeSettings?.env || input.session.env
? {
...input.runtimeSettings?.env,
...input.session.env,
}
: undefined,
model: input.session.model,
thinkingOptionId: input.session.thinkingOptionId,
protocolMode,
modeId: input.session.modeId,
session: input.session.session,
noSession: input.session.noSession,
mcpConfigPath: input.session.mcpConfigPath,
extensionPaths: input.session.extensionPaths,
extraArgs: input.session.extraArgs,
};
}
function appendPiLaunchArgs(
argv: string[],
session: PiStartSessionInput,
protocolMode: "rpc" | "rpc-ui",
): void {
if (!hasModeFlag(argv)) {
argv.push("--mode", protocolMode);
}
if (session.extraArgs?.length) {
argv.push(...session.extraArgs);
}
if (session.model) {
argv.push("--model", session.model);
}
if (session.thinkingOptionId) {
argv.push("--thinking", session.thinkingOptionId);
}
if (session.noSession) {
argv.push("--no-session");
} else if (session.session) {
argv.push("--session", session.session);
}
if (session.mcpConfigPath) {
argv.push("--mcp-config", session.mcpConfigPath);
}
for (const extensionPath of session.extensionPaths ?? []) {
argv.push("--extension", extensionPath);
}
}
function hasModeFlag(argv: string[]): boolean {
for (let i = 0; i < argv.length; i += 1) {
if (argv[i] === "--mode") {
return true;
}
if (argv[i]?.startsWith("--mode=")) {
return true;
}
}
return false;
}