feat(plugins): reach a running agent's composer by reference

useComposers(selector) in any plugin component and composers(selector) on every command context return the composer of a running agent, named by id or by focus, whether or not its tab is open.

A running agent now has one store-backed composer model apart from any mounted tab. The mounted composer plugs its cursor-aware insert in while mounted; otherwise insertText and setPrompt write the agent's saved prompt. model and thinking resolve through the provider catalog with the picker's own function, so a read equals what the picker shows.

The host reads one ComposerModel from context and no longer knows whether it is in an agent, a draft or New workspace. The daemon rejects an unlisted model or thinking option for a running agent, replacing the app-side guard.
This commit is contained in:
Mohamed Boudra
2026-11-05 23:25:42 +01:00
parent 03580ce50b
commit f665cc697c
42 changed files with 1621 additions and 272 deletions
+7 -1
View File
@@ -4,7 +4,11 @@ import type { PaseoApi } from "@getpaseo/client";
import type { AgentTimelineItem, JsonValue } from "@getpaseo/protocol/agent-types";
import type { ZodType, input as ZodInput, output as ZodOutput } from "zod";
import type { PluginFile } from "./file.js";
import type { PluginComposerItemContribution } from "./composer.js";
import type {
PluginComposer,
PluginComposerItemContribution,
PluginComposerSelector,
} from "./composer.js";
import type { PluginNewWorkspaceItemContribution } from "./new-workspace.js";
import type {
PluginRpcContract,
@@ -318,6 +322,8 @@ export interface PluginCommandCapabilities {
input: PluginWireInput<ZodInput<InputSchema>>,
): Promise<ZodOutput<OutputSchema>>;
openScreen(input: PluginOpenScreenInput): void;
/** The composers `selector` names, whether or not their tabs are open; see `useComposers`. */
composers(selector: PluginComposerSelector): readonly PluginComposer[];
/** @deprecated Use `openScreen`. */
openSurface(id: string): void;
openSettings(id: string): void;