mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 23:01:30 +00:00
Add ExtensionAPI methods, preset example, and TUI documentation improvements
- ExtensionAPI: setModel(), getThinkingLevel(), setThinkingLevel() methods - New preset.ts example with plan/implement presets for model/thinking/tools switching - Export all UI components from pi-coding-agent for extension use - docs/tui.md: Common Patterns section with copy-paste code for SelectList, BorderedLoader, SettingsList, setStatus, setWidget, setFooter - docs/tui.md: Key Rules section for extension UI development - docs/extensions.md: Exhaustive example links for all ExtensionAPI methods and events - System prompt now references docs/tui.md for TUI development Fixes #509, relates to #347
This commit is contained in:
parent
c35a18b2b3
commit
59d8b7948c
14 changed files with 850 additions and 13 deletions
|
|
@ -39,6 +39,7 @@ export type {
|
|||
FindToolResultEvent,
|
||||
GetActiveToolsHandler,
|
||||
GetAllToolsHandler,
|
||||
GetThinkingLevelHandler,
|
||||
GrepToolResultEvent,
|
||||
LoadExtensionsResult,
|
||||
// Loaded Extension
|
||||
|
|
@ -70,6 +71,8 @@ export type {
|
|||
SessionSwitchEvent,
|
||||
SessionTreeEvent,
|
||||
SetActiveToolsHandler,
|
||||
SetModelHandler,
|
||||
SetThinkingLevelHandler,
|
||||
// Events - Tool
|
||||
ToolCallEvent,
|
||||
ToolCallEventResult,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import type {
|
|||
ExtensionUIContext,
|
||||
GetActiveToolsHandler,
|
||||
GetAllToolsHandler,
|
||||
GetThinkingLevelHandler,
|
||||
LoadExtensionsResult,
|
||||
LoadedExtension,
|
||||
MessageRenderer,
|
||||
|
|
@ -31,6 +32,8 @@ import type {
|
|||
SendMessageHandler,
|
||||
SendUserMessageHandler,
|
||||
SetActiveToolsHandler,
|
||||
SetModelHandler,
|
||||
SetThinkingLevelHandler,
|
||||
ToolDefinition,
|
||||
} from "./types.js";
|
||||
|
||||
|
|
@ -124,6 +127,9 @@ function createExtensionAPI(
|
|||
setGetActiveToolsHandler: (handler: GetActiveToolsHandler) => void;
|
||||
setGetAllToolsHandler: (handler: GetAllToolsHandler) => void;
|
||||
setSetActiveToolsHandler: (handler: SetActiveToolsHandler) => void;
|
||||
setSetModelHandler: (handler: SetModelHandler) => void;
|
||||
setGetThinkingLevelHandler: (handler: GetThinkingLevelHandler) => void;
|
||||
setSetThinkingLevelHandler: (handler: SetThinkingLevelHandler) => void;
|
||||
setFlagValue: (name: string, value: boolean | string) => void;
|
||||
} {
|
||||
let sendMessageHandler: SendMessageHandler = () => {};
|
||||
|
|
@ -132,6 +138,9 @@ function createExtensionAPI(
|
|||
let getActiveToolsHandler: GetActiveToolsHandler = () => [];
|
||||
let getAllToolsHandler: GetAllToolsHandler = () => [];
|
||||
let setActiveToolsHandler: SetActiveToolsHandler = () => {};
|
||||
let setModelHandler: SetModelHandler = async () => false;
|
||||
let getThinkingLevelHandler: GetThinkingLevelHandler = () => "off";
|
||||
let setThinkingLevelHandler: SetThinkingLevelHandler = () => {};
|
||||
|
||||
const messageRenderers = new Map<string, MessageRenderer>();
|
||||
const commands = new Map<string, RegisteredCommand>();
|
||||
|
|
@ -213,6 +222,18 @@ function createExtensionAPI(
|
|||
setActiveToolsHandler(toolNames);
|
||||
},
|
||||
|
||||
setModel(model) {
|
||||
return setModelHandler(model);
|
||||
},
|
||||
|
||||
getThinkingLevel() {
|
||||
return getThinkingLevelHandler();
|
||||
},
|
||||
|
||||
setThinkingLevel(level) {
|
||||
setThinkingLevelHandler(level);
|
||||
},
|
||||
|
||||
events: eventBus,
|
||||
} as ExtensionAPI;
|
||||
|
||||
|
|
@ -241,6 +262,15 @@ function createExtensionAPI(
|
|||
setSetActiveToolsHandler: (handler: SetActiveToolsHandler) => {
|
||||
setActiveToolsHandler = handler;
|
||||
},
|
||||
setSetModelHandler: (handler: SetModelHandler) => {
|
||||
setModelHandler = handler;
|
||||
},
|
||||
setGetThinkingLevelHandler: (handler: GetThinkingLevelHandler) => {
|
||||
getThinkingLevelHandler = handler;
|
||||
},
|
||||
setSetThinkingLevelHandler: (handler: SetThinkingLevelHandler) => {
|
||||
setThinkingLevelHandler = handler;
|
||||
},
|
||||
setFlagValue: (name: string, value: boolean | string) => {
|
||||
flagValues.set(name, value);
|
||||
},
|
||||
|
|
@ -277,6 +307,9 @@ async function loadExtensionWithBun(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
} = createExtensionAPI(handlers, tools, cwd, extensionPath, eventBus, sharedUI);
|
||||
|
||||
|
|
@ -299,6 +332,9 @@ async function loadExtensionWithBun(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
},
|
||||
error: null,
|
||||
|
|
@ -359,6 +395,9 @@ async function loadExtension(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
} = createExtensionAPI(handlers, tools, cwd, extensionPath, eventBus, sharedUI);
|
||||
|
||||
|
|
@ -381,6 +420,9 @@ async function loadExtension(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
},
|
||||
error: null,
|
||||
|
|
@ -416,6 +458,9 @@ export function loadExtensionFromFactory(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
} = createExtensionAPI(handlers, tools, cwd, name, eventBus, sharedUI);
|
||||
|
||||
|
|
@ -437,6 +482,9 @@ export function loadExtensionFromFactory(
|
|||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setSetModelHandler,
|
||||
setGetThinkingLevelHandler,
|
||||
setSetThinkingLevelHandler,
|
||||
setFlagValue,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import type {
|
|||
ExtensionUIContext,
|
||||
GetActiveToolsHandler,
|
||||
GetAllToolsHandler,
|
||||
GetThinkingLevelHandler,
|
||||
LoadedExtension,
|
||||
MessageRenderer,
|
||||
RegisteredCommand,
|
||||
|
|
@ -32,6 +33,8 @@ import type {
|
|||
SessionBeforeCompactResult,
|
||||
SessionBeforeTreeResult,
|
||||
SetActiveToolsHandler,
|
||||
SetModelHandler,
|
||||
SetThinkingLevelHandler,
|
||||
ToolCallEvent,
|
||||
ToolCallEventResult,
|
||||
ToolResultEventResult,
|
||||
|
|
@ -115,6 +118,9 @@ export class ExtensionRunner {
|
|||
getActiveToolsHandler: GetActiveToolsHandler;
|
||||
getAllToolsHandler: GetAllToolsHandler;
|
||||
setActiveToolsHandler: SetActiveToolsHandler;
|
||||
setModelHandler: SetModelHandler;
|
||||
getThinkingLevelHandler: GetThinkingLevelHandler;
|
||||
setThinkingLevelHandler: SetThinkingLevelHandler;
|
||||
newSessionHandler?: NewSessionHandler;
|
||||
branchHandler?: BranchHandler;
|
||||
navigateTreeHandler?: NavigateTreeHandler;
|
||||
|
|
@ -148,6 +154,9 @@ export class ExtensionRunner {
|
|||
ext.setGetActiveToolsHandler(options.getActiveToolsHandler);
|
||||
ext.setGetAllToolsHandler(options.getAllToolsHandler);
|
||||
ext.setSetActiveToolsHandler(options.setActiveToolsHandler);
|
||||
ext.setSetModelHandler(options.setModelHandler);
|
||||
ext.setGetThinkingLevelHandler(options.getThinkingLevelHandler);
|
||||
ext.setSetThinkingLevelHandler(options.setThinkingLevelHandler);
|
||||
}
|
||||
|
||||
this.uiContext = options.uiContext ?? noOpUIContext;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@
|
|||
* - Interact with the user via UI primitives
|
||||
*/
|
||||
|
||||
import type { AgentMessage, AgentToolResult, AgentToolUpdateCallback } from "@mariozechner/pi-agent-core";
|
||||
import type {
|
||||
AgentMessage,
|
||||
AgentToolResult,
|
||||
AgentToolUpdateCallback,
|
||||
ThinkingLevel,
|
||||
} from "@mariozechner/pi-agent-core";
|
||||
import type { ImageContent, Model, TextContent, ToolResultMessage } from "@mariozechner/pi-ai";
|
||||
import type { Component, KeyId, TUI } from "@mariozechner/pi-tui";
|
||||
import type { Static, TSchema } from "@sinclair/typebox";
|
||||
|
|
@ -619,6 +624,19 @@ export interface ExtensionAPI {
|
|||
/** Set the active tools by name. */
|
||||
setActiveTools(toolNames: string[]): void;
|
||||
|
||||
// =========================================================================
|
||||
// Model and Thinking Level
|
||||
// =========================================================================
|
||||
|
||||
/** Set the current model. Returns false if no API key available. */
|
||||
setModel(model: Model<any>): Promise<boolean>;
|
||||
|
||||
/** Get current thinking level. */
|
||||
getThinkingLevel(): ThinkingLevel;
|
||||
|
||||
/** Set thinking level (clamped to model capabilities). */
|
||||
setThinkingLevel(level: ThinkingLevel): void;
|
||||
|
||||
/** Shared event bus for extension communication. */
|
||||
events: EventBus;
|
||||
}
|
||||
|
|
@ -670,6 +688,12 @@ export type GetAllToolsHandler = () => string[];
|
|||
|
||||
export type SetActiveToolsHandler = (toolNames: string[]) => void;
|
||||
|
||||
export type SetModelHandler = (model: Model<any>) => Promise<boolean>;
|
||||
|
||||
export type GetThinkingLevelHandler = () => ThinkingLevel;
|
||||
|
||||
export type SetThinkingLevelHandler = (level: ThinkingLevel) => void;
|
||||
|
||||
/** Loaded extension with all registered items. */
|
||||
export interface LoadedExtension {
|
||||
path: string;
|
||||
|
|
@ -687,6 +711,9 @@ export interface LoadedExtension {
|
|||
setGetActiveToolsHandler: (handler: GetActiveToolsHandler) => void;
|
||||
setGetAllToolsHandler: (handler: GetAllToolsHandler) => void;
|
||||
setSetActiveToolsHandler: (handler: SetActiveToolsHandler) => void;
|
||||
setSetModelHandler: (handler: SetModelHandler) => void;
|
||||
setGetThinkingLevelHandler: (handler: GetThinkingLevelHandler) => void;
|
||||
setSetThinkingLevelHandler: (handler: SetThinkingLevelHandler) => void;
|
||||
setFlagValue: (name: string, value: boolean | string) => void;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ Documentation:
|
|||
- Main documentation: ${readmePath}
|
||||
- Additional docs: ${docsPath}
|
||||
- Examples: ${examplesPath} (extensions, custom tools, SDK)
|
||||
- When asked to create: custom models/providers (README.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/theme.md), skills (docs/skills.md)
|
||||
- When asked to create: custom models/providers (README.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/theme.md), skills (docs/skills.md), TUI components (docs/tui.md - has copy-paste patterns)
|
||||
- Always read the doc, examples, AND follow .md cross-references before implementing`;
|
||||
|
||||
if (appendSection) {
|
||||
|
|
|
|||
|
|
@ -525,6 +525,14 @@ export class InteractiveMode {
|
|||
|
||||
return { cancelled: false };
|
||||
},
|
||||
setModelHandler: async (model) => {
|
||||
const key = await this.session.modelRegistry.getApiKey(model);
|
||||
if (!key) return false;
|
||||
await this.session.setModel(model);
|
||||
return true;
|
||||
},
|
||||
getThinkingLevelHandler: () => this.session.thinkingLevel,
|
||||
setThinkingLevelHandler: (level) => this.session.setThinkingLevel(level),
|
||||
isIdle: () => !this.session.isStreaming,
|
||||
waitForIdle: () => this.session.agent.waitForIdle(),
|
||||
abort: () => {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,14 @@ export async function runPrintMode(
|
|||
getActiveToolsHandler: () => session.getActiveToolNames(),
|
||||
getAllToolsHandler: () => session.getAllToolNames(),
|
||||
setActiveToolsHandler: (toolNames: string[]) => session.setActiveToolsByName(toolNames),
|
||||
setModelHandler: async (model) => {
|
||||
const key = await session.modelRegistry.getApiKey(model);
|
||||
if (!key) return false;
|
||||
await session.setModel(model);
|
||||
return true;
|
||||
},
|
||||
getThinkingLevelHandler: () => session.thinkingLevel,
|
||||
setThinkingLevelHandler: (level) => session.setThinkingLevel(level),
|
||||
});
|
||||
extensionRunner.onError((err) => {
|
||||
console.error(`Extension error (${err.extensionPath}): ${err.error}`);
|
||||
|
|
|
|||
|
|
@ -244,6 +244,14 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|||
getActiveToolsHandler: () => session.getActiveToolNames(),
|
||||
getAllToolsHandler: () => session.getAllToolNames(),
|
||||
setActiveToolsHandler: (toolNames: string[]) => session.setActiveToolsByName(toolNames),
|
||||
setModelHandler: async (model) => {
|
||||
const key = await session.modelRegistry.getApiKey(model);
|
||||
if (!key) return false;
|
||||
await session.setModel(model);
|
||||
return true;
|
||||
},
|
||||
getThinkingLevelHandler: () => session.thinkingLevel,
|
||||
setThinkingLevelHandler: (level) => session.setThinkingLevel(level),
|
||||
uiContext: createExtensionUIContext(),
|
||||
hasUI: false,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue