feat: add /thinking slash command for toggling thinking level (#129)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d9548cdf26
commit
bb10aacb23
3 changed files with 61 additions and 4 deletions
|
|
@ -34,5 +34,6 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|||
{ name: "compact", description: "Manually compact the session context" },
|
||||
{ name: "resume", description: "Resume a different session" },
|
||||
{ name: "reload", description: "Reload extensions, skills, prompts, and themes" },
|
||||
{ name: "thinking", description: "Set thinking level (off/minimal/low/medium/high/xhigh)" },
|
||||
{ name: "quit", description: "Quit pi" },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
import { getSelectListTheme, getSettingsListTheme, theme } from "../theme/theme.js";
|
||||
import { DynamicBorder } from "./dynamic-border.js";
|
||||
|
||||
const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
|
||||
export const THINKING_DESCRIPTIONS: Record<ThinkingLevel, string> = {
|
||||
off: "No reasoning",
|
||||
minimal: "Very brief reasoning (~1k tokens)",
|
||||
low: "Light reasoning (~2k tokens)",
|
||||
|
|
@ -73,7 +73,7 @@ export interface SettingsCallbacks {
|
|||
/**
|
||||
* A submenu component for selecting from a list of options.
|
||||
*/
|
||||
class SelectSubmenu extends Container {
|
||||
export class SelectSubmenu extends Container {
|
||||
private selectList: SelectList;
|
||||
|
||||
constructor(
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import * as crypto from "node:crypto";
|
|||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
import type { AgentMessage } from "@gsd/pi-agent-core";
|
||||
import type { AgentMessage, ThinkingLevel } from "@gsd/pi-agent-core";
|
||||
import type { AssistantMessage, ImageContent, Message, Model, OAuthProviderId } from "@gsd/pi-ai";
|
||||
import type {
|
||||
AutocompleteItem,
|
||||
|
|
@ -85,7 +85,7 @@ import { ModelSelectorComponent } from "./components/model-selector.js";
|
|||
import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
||||
import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
|
||||
import { SessionSelectorComponent } from "./components/session-selector.js";
|
||||
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
||||
import { SelectSubmenu, SettingsSelectorComponent, THINKING_DESCRIPTIONS } from "./components/settings-selector.js";
|
||||
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
||||
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
||||
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
||||
|
|
@ -2015,6 +2015,12 @@ export class InteractiveMode {
|
|||
await this.handleReloadCommand();
|
||||
return;
|
||||
}
|
||||
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
||||
const arg = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
|
||||
this.editor.setText("");
|
||||
this.handleThinkingCommand(arg);
|
||||
return;
|
||||
}
|
||||
if (text === "/debug") {
|
||||
this.handleDebugCommand();
|
||||
this.editor.setText("");
|
||||
|
|
@ -2745,6 +2751,56 @@ export class InteractiveMode {
|
|||
}
|
||||
}
|
||||
|
||||
private handleThinkingCommand(arg?: string): void {
|
||||
const availableLevels = this.session.getAvailableThinkingLevels();
|
||||
if (availableLevels.length === 0) {
|
||||
this.showStatus("Current model does not support thinking");
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg) {
|
||||
const level = arg.toLowerCase() as ThinkingLevel;
|
||||
if (!availableLevels.includes(level)) {
|
||||
this.showStatus(`Invalid thinking level "${arg}". Available: ${availableLevels.join(", ")}`);
|
||||
return;
|
||||
}
|
||||
this.session.setThinkingLevel(level);
|
||||
this.footer.invalidate();
|
||||
this.updateEditorBorderColor();
|
||||
this.showStatus(`Thinking level: ${level}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.showThinkingSelector();
|
||||
}
|
||||
|
||||
private showThinkingSelector(): void {
|
||||
const availableLevels = this.session.getAvailableThinkingLevels();
|
||||
this.showSelector((done) => {
|
||||
const selector = new SelectSubmenu(
|
||||
"Thinking Level",
|
||||
"Select reasoning depth for thinking-capable models",
|
||||
availableLevels.map((level) => ({
|
||||
value: level,
|
||||
label: level,
|
||||
description: THINKING_DESCRIPTIONS[level],
|
||||
})),
|
||||
this.session.thinkingLevel,
|
||||
(value) => {
|
||||
this.session.setThinkingLevel(value as ThinkingLevel);
|
||||
this.footer.invalidate();
|
||||
this.updateEditorBorderColor();
|
||||
done();
|
||||
this.showStatus(`Thinking level: ${value}`);
|
||||
},
|
||||
() => {
|
||||
done();
|
||||
},
|
||||
);
|
||||
return { component: selector, focus: selector };
|
||||
});
|
||||
}
|
||||
|
||||
private async cycleModel(direction: "forward" | "backward"): Promise<void> {
|
||||
try {
|
||||
const result = await this.session.cycleModel(direction);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue