Merge PR #648: Change getAllTools() to return ToolInfo[]

Breaking change: pi.getAllTools() now returns ToolInfo[] (with name and description) instead of string[].
Extensions that only need names can use .map(t => t.name).

Closes #648
Fixes #647
This commit is contained in:
Mario Zechner 2026-01-12 17:18:48 +01:00
commit a60cd42d40
12 changed files with 34 additions and 19 deletions

View file

@ -2,6 +2,10 @@
## [Unreleased]
### Breaking Changes
- `pi.getAllTools()` now returns `ToolInfo[]` (with `name` and `description`) instead of `string[]`. Extensions that only need names can use `.map(t => t.name)`. ([#648](https://github.com/badlogic/pi-mono/pull/648) by [@carsonfarmer](https://github.com/carsonfarmer))
### Added
- Session naming: `/name <name>` command sets a display name shown in the session selector instead of the first message. Useful for distinguishing forked sessions. Extensions can use `pi.setSessionName()` and `pi.getSessionName()`. ([#650](https://github.com/badlogic/pi-mono/pull/650) by [@scutifer](https://github.com/scutifer))

View file

@ -887,6 +887,8 @@ Manage active tools.
```typescript
const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
const all = pi.getAllTools(); // [{ name: "read", description: "Read file contents..." }, ...]
const names = all.map(t => t.name); // Just names if needed
pi.setActiveTools(["read", "bash"]); // Switch to read-only
```

View file

@ -133,9 +133,9 @@ export default function presetExtension(pi: ExtensionAPI) {
// Apply tools if specified
if (preset.tools && preset.tools.length > 0) {
const allTools = pi.getAllTools();
const validTools = preset.tools.filter((t) => allTools.includes(t));
const invalidTools = preset.tools.filter((t) => !allTools.includes(t));
const allToolNames = pi.getAllTools().map((t) => t.name);
const validTools = preset.tools.filter((t) => allToolNames.includes(t));
const invalidTools = preset.tools.filter((t) => !allToolNames.includes(t));
if (invalidTools.length > 0) {
ctx.ui.notify(`Preset "${name}": Unknown tools: ${invalidTools.join(", ")}`, "warning");

View file

@ -9,7 +9,7 @@
* 2. Use /tools to open the tool selector
*/
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
import type { ExtensionAPI, ExtensionContext, ToolInfo } from "@mariozechner/pi-coding-agent";
import { getSettingsListTheme } from "@mariozechner/pi-coding-agent";
import { Container, type SettingItem, SettingsList } from "@mariozechner/pi-tui";
@ -21,7 +21,7 @@ interface ToolsState {
export default function toolsExtension(pi: ExtensionAPI) {
// Track enabled tools
let enabledTools: Set<string> = new Set();
let allTools: string[] = [];
let allTools: ToolInfo[] = [];
// Persist current state
function persistState() {
@ -54,7 +54,8 @@ export default function toolsExtension(pi: ExtensionAPI) {
if (savedTools) {
// Restore saved tool selection (filter to only tools that still exist)
enabledTools = new Set(savedTools.filter((t: string) => allTools.includes(t)));
const allToolNames = allTools.map((t) => t.name);
enabledTools = new Set(savedTools.filter((t: string) => allToolNames.includes(t)));
applyTools();
} else {
// No saved state - sync with currently active tools
@ -72,9 +73,9 @@ export default function toolsExtension(pi: ExtensionAPI) {
await ctx.ui.custom((tui, theme, _kb, done) => {
// Build settings items for each tool
const items: SettingItem[] = allTools.map((tool) => ({
id: tool,
label: tool,
currentValue: enabledTools.has(tool) ? "enabled" : "disabled",
id: tool.name,
label: tool.name,
currentValue: enabledTools.has(tool.name) ? "enabled" : "disabled",
values: ["enabled", "disabled"],
}));

View file

@ -459,10 +459,13 @@ export class AgentSession {
}
/**
* Get all configured tool names (built-in via --tools or default, plus custom tools).
* Get all configured tools with name and description.
*/
getAllToolNames(): string[] {
return Array.from(this._toolRegistry.keys());
getAllTools(): Array<{ name: string; description: string }> {
return Array.from(this._toolRegistry.values()).map((t) => ({
name: t.name,
description: t.description,
}));
}
/**

View file

@ -99,6 +99,7 @@ export type {
ToolCallEventResult,
// Tools
ToolDefinition,
ToolInfo,
ToolRenderResultOptions,
ToolResultEvent,
ToolResultEventResult,

View file

@ -187,7 +187,7 @@ function createExtensionAPI(
return runtime.getActiveTools();
},
getAllTools(): string[] {
getAllTools() {
return runtime.getAllTools();
},

View file

@ -743,8 +743,8 @@ export interface ExtensionAPI {
/** Get the list of currently active tool names. */
getActiveTools(): string[];
/** Get all configured tools (built-in + extension tools). */
getAllTools(): string[];
/** Get all configured tools with name and description. */
getAllTools(): ToolInfo[];
/** Set the active tools by name. */
setActiveTools(toolNames: string[]): void;
@ -813,7 +813,10 @@ export type GetSessionNameHandler = () => string | undefined;
export type GetActiveToolsHandler = () => string[];
export type GetAllToolsHandler = () => string[];
/** Tool info with name and description */
export type ToolInfo = Pick<ToolDefinition, "name" | "description">;
export type GetAllToolsHandler = () => ToolInfo[];
export type SetActiveToolsHandler = (toolNames: string[]) => void;

View file

@ -79,6 +79,7 @@ export type {
SessionTreeEvent,
ToolCallEvent,
ToolDefinition,
ToolInfo,
ToolRenderResultOptions,
ToolResultEvent,
TurnEndEvent,

View file

@ -685,7 +685,7 @@ export class InteractiveMode {
return this.sessionManager.getSessionName();
},
getActiveTools: () => this.session.getActiveToolNames(),
getAllTools: () => this.session.getAllToolNames(),
getAllTools: () => this.session.getAllTools(),
setActiveTools: (toolNames) => this.session.setActiveToolsByName(toolNames),
setModel: async (model) => {
const key = await this.session.modelRegistry.getApiKey(model);

View file

@ -55,7 +55,7 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
return session.sessionManager.getSessionName();
},
getActiveTools: () => session.getActiveToolNames(),
getAllTools: () => session.getAllToolNames(),
getAllTools: () => session.getAllTools(),
setActiveTools: (toolNames: string[]) => session.setActiveToolsByName(toolNames),
setModel: async (model) => {
const key = await session.modelRegistry.getApiKey(model);

View file

@ -274,7 +274,7 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
return session.sessionManager.getSessionName();
},
getActiveTools: () => session.getActiveToolNames(),
getAllTools: () => session.getAllToolNames(),
getAllTools: () => session.getAllTools(),
setActiveTools: (toolNames: string[]) => session.setActiveToolsByName(toolNames),
setModel: async (model) => {
const key = await session.modelRegistry.getApiKey(model);