Files
paseo/packages/app/src/plugins/client-runtime.ts
T
Mohamed Boudra 0b3d82a469 feat(plugin): add shared header buttons and composer controls (#4577)
* feat(plugin): add shared header buttons and composer controls

* fix(plugin): isolate button registration imports and settle captures

* test(plugin): express button journeys through domain helpers
2026-09-09 15:39:12 +02:00

71 lines
2.5 KiB
TypeScript

import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
import type { PluginClientOpenPanelOptions } from "@getpaseo/plugin/client";
import {
createPluginAgentActionContext,
createPluginCapabilities,
createPluginWorkspaceActionContext,
} from "./actions";
import { createPluginClientStateSource } from "./client-state/source";
import type { PluginClientRuntime } from "./evaluate";
import { createPluginNavigation } from "./navigation";
import { pluginButtonStore } from "./buttons";
import { createPluginSurfaceRuntime } from "./surface-runtime";
import type { InstalledPlugin } from "./types";
export function createPluginClientRuntime(
installation: InstalledPlugin,
daemonClient: DaemonClient,
): PluginClientRuntime {
const runtime = createPluginSurfaceRuntime(daemonClient, installation.id);
if (!runtime) throw new Error("Plugin host is offline");
const state = createPluginClientStateSource(installation.serverId);
const capabilities = createPluginCapabilities(
installation,
runtime,
createPluginNavigation({ serverId: installation.serverId, workspaceId: null }),
);
return {
...capabilities,
addComposerPill(contribution) {
return pluginButtonStore.addComposerPill(installation, contribution);
},
addHeaderButton(contribution) {
return pluginButtonStore.addHeaderButton(installation, contribution);
},
openPanel(panelId, options) {
openClientPanel({ installation, runtime, state, panelId, options });
},
};
}
function openClientPanel(input: {
installation: InstalledPlugin;
runtime: NonNullable<ReturnType<typeof createPluginSurfaceRuntime>>;
state: ReturnType<typeof createPluginClientStateSource>;
panelId: string;
options: PluginClientOpenPanelOptions;
}): void {
const { installation, runtime, state, panelId, options } = input;
const workspaceId = options.workspaceId.trim();
const agentId = options.agentId?.trim();
const navigation = createPluginNavigation({ serverId: installation.serverId, workspaceId });
const action = agentId
? createPluginAgentActionContext({
plugin: installation,
runtime,
navigation,
state,
workspaceId,
agentId,
})
: createPluginWorkspaceActionContext({
plugin: installation,
runtime,
navigation,
state,
workspaceId,
});
if (!action) throw new Error("Plugin panel context is unavailable");
action.openPanel(panelId, { location: options.location });
}