mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 17:52:49 +00:00
* feat(plugins): support provider status, launch resolution, and config overrides * fix(plugins): defer override warnings until provider startup settles
124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import type { JsonValue } from "@getpaseo/protocol/agent-types";
|
|
import type {
|
|
ProviderCatalog,
|
|
ProviderCommand,
|
|
ProviderConfigState,
|
|
ProviderNotice,
|
|
ProviderRegistration,
|
|
ProviderTimelineItem,
|
|
} from "./provider.js";
|
|
import { createAcpProviderConnection } from "./acp-internal/connection.js";
|
|
|
|
interface RunAcpProviderBaseOptions {
|
|
id: string;
|
|
label: string;
|
|
description?: string;
|
|
icon?: string;
|
|
acpOptions?: AcpOptions;
|
|
transformers?: readonly AcpTransformer[];
|
|
}
|
|
|
|
export type RunAcpProviderOptions = RunAcpProviderBaseOptions &
|
|
(
|
|
| { command: readonly [string, ...string[]]; connector?: never }
|
|
| { connector: AcpConnector; command?: never }
|
|
);
|
|
|
|
export type AcpStreamMessage =
|
|
| { jsonrpc: "2.0"; id: string | number | null; method: string; params?: unknown }
|
|
| { jsonrpc: "2.0"; method: string; params?: unknown }
|
|
| { jsonrpc: "2.0"; id: string | number | null; result: unknown }
|
|
| {
|
|
jsonrpc: "2.0";
|
|
id: string | number | null;
|
|
error: { code: number; message: string; data?: unknown };
|
|
};
|
|
|
|
export interface AcpStream {
|
|
writable: WritableStream<AcpStreamMessage>;
|
|
readable: ReadableStream<AcpStreamMessage>;
|
|
}
|
|
|
|
export type AcpConnector = () => AcpStream | Promise<AcpStream>;
|
|
|
|
export interface AcpOptions {
|
|
protocol?: "auto" | "v1";
|
|
startupTimeoutMs?: number;
|
|
waitForInitialCommands?: boolean;
|
|
initialCommandsTimeoutMs?: number;
|
|
}
|
|
|
|
export interface AcpContext {
|
|
sessionId: string;
|
|
}
|
|
|
|
export interface AcpConfigAccess {
|
|
read(): Promise<Readonly<Record<string, JsonValue>>>;
|
|
set(id: string, value: JsonValue): Promise<void>;
|
|
}
|
|
|
|
export interface AcpDiscoveryContext extends AcpContext {
|
|
config: AcpConfigAccess;
|
|
}
|
|
|
|
export interface AcpConfigureContext extends AcpContext {
|
|
config: AcpConfigAccess;
|
|
}
|
|
|
|
export type AcpConfigChange =
|
|
| { target: "model"; value: string | null }
|
|
| { target: "mode"; value: string | null }
|
|
| { target: "thinking"; value: string | null }
|
|
| { target: "setting"; id: string; value: JsonValue };
|
|
|
|
export interface AcpToolCallSnapshot {
|
|
id: string;
|
|
name?: string;
|
|
title: string;
|
|
kind?: string;
|
|
status: "pending" | "in_progress" | "completed" | "failed";
|
|
input: JsonValue;
|
|
output: JsonValue;
|
|
locations: readonly string[];
|
|
}
|
|
|
|
export type AcpVendorUpdate =
|
|
| { type: "commands"; commands: readonly ProviderCommand[] }
|
|
| { type: "config"; config: ProviderConfigState }
|
|
| { type: "timeline"; item: ProviderTimelineItem }
|
|
| { type: "notice"; notice: ProviderNotice };
|
|
|
|
export interface AcpTransformer {
|
|
discover?(
|
|
catalog: ProviderCatalog,
|
|
context: AcpDiscoveryContext,
|
|
): Promise<ProviderCatalog> | ProviderCatalog;
|
|
configure?(change: AcpConfigChange, context: AcpConfigureContext): Promise<"handled" | "pass">;
|
|
notification?(
|
|
notification: { method: string; params: JsonValue },
|
|
context: AcpContext,
|
|
): AcpVendorUpdate | readonly AcpVendorUpdate[] | null;
|
|
toolCall?(toolCall: AcpToolCallSnapshot, context: AcpContext): AcpToolCallSnapshot;
|
|
}
|
|
|
|
export function runAcpProvider(options: RunAcpProviderOptions): ProviderRegistration {
|
|
const hasCommand = options.command !== undefined;
|
|
const hasConnector = options.connector !== undefined;
|
|
if (hasCommand === hasConnector) {
|
|
throw new Error("ACP provider requires exactly one command or SDK connector");
|
|
}
|
|
if (options.command && (options.command.length === 0 || options.command[0].trim().length === 0)) {
|
|
throw new Error("ACP provider command must contain an executable");
|
|
}
|
|
return {
|
|
id: options.id,
|
|
label: options.label,
|
|
description: options.description,
|
|
icon: options.icon,
|
|
command: options.command,
|
|
connect(request) {
|
|
return createAcpProviderConnection(options, request);
|
|
},
|
|
};
|
|
}
|