Remove flask ASCII art and update harness internals
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,16 +44,7 @@ const FEYNMAN_AGENT_LOGO = [
|
|||||||
"╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝",
|
"╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝",
|
||||||
];
|
];
|
||||||
|
|
||||||
const FEYNMAN_MARK_ART = [
|
const FEYNMAN_MARK_ART: string[] = [];
|
||||||
" .-.",
|
|
||||||
" /___\\\\",
|
|
||||||
" |:::|",
|
|
||||||
" |:::|",
|
|
||||||
" .-'`:::::`'-.",
|
|
||||||
" /:::::::::::::\\\\",
|
|
||||||
" \\\\:::::::::::://",
|
|
||||||
" '-.______.-'",
|
|
||||||
];
|
|
||||||
|
|
||||||
const FEYNMAN_RESEARCH_TOOLS = [
|
const FEYNMAN_RESEARCH_TOOLS = [
|
||||||
"alpha_search",
|
"alpha_search",
|
||||||
@@ -754,34 +745,6 @@ Recommended contents:
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
type HelpCommand = {
|
|
||||||
usage: string;
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildFeynmanHelpSections(pi: ExtensionAPI): Array<{ title: string; commands: HelpCommand[] }> {
|
|
||||||
const commands = pi.getCommands();
|
|
||||||
const promptCommands = sortCommands(commands.filter((command) => command.source === "prompt")).map((command) => ({
|
|
||||||
usage: `/${command.name}`,
|
|
||||||
description: command.description ?? "Prompt workflow",
|
|
||||||
}));
|
|
||||||
const extensionCommands = sortCommands(commands.filter((command) => command.source === "extension")).map((command) => ({
|
|
||||||
usage: `/${command.name}`,
|
|
||||||
description: command.description ?? "Extension command",
|
|
||||||
}));
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
title: "Prompt Workflows",
|
|
||||||
commands: promptCommands,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Commands",
|
|
||||||
commands: extensionCommands,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function researchTools(pi: ExtensionAPI): void {
|
export default function researchTools(pi: ExtensionAPI): void {
|
||||||
let skillSummaryPromise: Promise<CatalogSummary> | undefined;
|
let skillSummaryPromise: Promise<CatalogSummary> | undefined;
|
||||||
let agentSummaryPromise: Promise<CatalogSummary> | undefined;
|
let agentSummaryPromise: Promise<CatalogSummary> | undefined;
|
||||||
@@ -801,186 +764,168 @@ export default function researchTools(pi: ExtensionAPI): void {
|
|||||||
ctx.ui.setHeader((_tui, theme) => ({
|
ctx.ui.setHeader((_tui, theme) => ({
|
||||||
render(width: number): string[] {
|
render(width: number): string[] {
|
||||||
const maxAvailableWidth = Math.max(width - 2, 1);
|
const maxAvailableWidth = Math.max(width - 2, 1);
|
||||||
const preferredWidth = Math.min(136, Math.max(72, maxAvailableWidth));
|
const preferredWidth = Math.min(136, Math.max(72, maxAvailableWidth));
|
||||||
const cardWidth = Math.min(maxAvailableWidth, preferredWidth);
|
const cardWidth = Math.min(maxAvailableWidth, preferredWidth);
|
||||||
const innerWidth = cardWidth - 2;
|
const innerWidth = cardWidth - 2;
|
||||||
const outerPadding = " ".repeat(Math.max(0, Math.floor((width - cardWidth) / 2)));
|
const outerPadding = " ".repeat(Math.max(0, Math.floor((width - cardWidth) / 2)));
|
||||||
const title = truncateForWidth(` Feynman Research Agent v${FEYNMAN_VERSION} `, innerWidth);
|
const title = truncateForWidth(` Feynman Research Agent v${FEYNMAN_VERSION} `, innerWidth);
|
||||||
const titledBorder = buildTitledBorder(innerWidth, title);
|
const titledBorder = buildTitledBorder(innerWidth, title);
|
||||||
const modelLabel = getCurrentModelLabel(ctx);
|
const modelLabel = getCurrentModelLabel(ctx);
|
||||||
const sessionLabel = ctx.sessionManager.getSessionName()?.trim() || ctx.sessionManager.getSessionId();
|
const sessionLabel = ctx.sessionManager.getSessionName()?.trim() || ctx.sessionManager.getSessionId();
|
||||||
const directoryLabel = formatHeaderPath(ctx.cwd);
|
const directoryLabel = formatHeaderPath(ctx.cwd);
|
||||||
const recentActivity = getRecentActivitySummary(ctx);
|
const recentActivity = getRecentActivitySummary(ctx);
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
|
|
||||||
const push = (line: string): void => {
|
const push = (line: string): void => {
|
||||||
lines.push(`${outerPadding}${line}`);
|
lines.push(`${outerPadding}${line}`);
|
||||||
};
|
|
||||||
|
|
||||||
const renderBoxLine = (content: string): string =>
|
|
||||||
`${theme.fg("borderMuted", "│")}${content}${theme.fg("borderMuted", "│")}`;
|
|
||||||
const renderDivider = (): string =>
|
|
||||||
`${theme.fg("borderMuted", "├")}${theme.fg("borderMuted", "─".repeat(innerWidth))}${theme.fg("borderMuted", "┤")}`;
|
|
||||||
const styleAccentCell = (text: string, cellWidth: number): string =>
|
|
||||||
theme.fg("accent", theme.bold(padCell(text, cellWidth)));
|
|
||||||
const styleMutedCell = (text: string, cellWidth: number): string =>
|
|
||||||
theme.fg("muted", padCell(text, cellWidth));
|
|
||||||
const styleSuccessCell = (text: string, cellWidth: number): string =>
|
|
||||||
theme.fg("success", theme.bold(padCell(text, cellWidth)));
|
|
||||||
const styleWarningCell = (text: string, cellWidth: number): string =>
|
|
||||||
theme.fg("warning", theme.bold(padCell(text, cellWidth)));
|
|
||||||
|
|
||||||
push("");
|
|
||||||
for (const logoLine of FEYNMAN_AGENT_LOGO) {
|
|
||||||
push(theme.fg("accent", theme.bold(centerText(logoLine, cardWidth))));
|
|
||||||
}
|
|
||||||
push("");
|
|
||||||
push(
|
|
||||||
theme.fg("borderMuted", `╭${titledBorder.left}`) +
|
|
||||||
theme.fg("accent", theme.bold(title)) +
|
|
||||||
theme.fg("borderMuted", `${titledBorder.right}╮`),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (innerWidth < 72) {
|
|
||||||
const activityLines = wrapForWidth(recentActivity, innerWidth, 2);
|
|
||||||
push(renderBoxLine(padCell("", innerWidth)));
|
|
||||||
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Research session ready", innerWidth)))));
|
|
||||||
push(renderBoxLine(padCell(`model: ${modelLabel}`, innerWidth)));
|
|
||||||
push(renderBoxLine(padCell(`session: ${sessionLabel}`, innerWidth)));
|
|
||||||
push(renderBoxLine(padCell(`directory: ${directoryLabel}`, innerWidth)));
|
|
||||||
push(renderDivider());
|
|
||||||
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Available tools", innerWidth)))));
|
|
||||||
for (const toolLine of toolSummary.lines.slice(0, 4)) {
|
|
||||||
push(renderBoxLine(padCell(toolLine, innerWidth)));
|
|
||||||
}
|
|
||||||
push(renderDivider());
|
|
||||||
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Slash Commands", innerWidth)))));
|
|
||||||
for (const commandLine of commandSummary.lines.slice(0, 4)) {
|
|
||||||
push(renderBoxLine(padCell(commandLine, innerWidth)));
|
|
||||||
}
|
|
||||||
push(renderDivider());
|
|
||||||
push(renderBoxLine(theme.fg("success", theme.bold(padCell("Research Skills", innerWidth)))));
|
|
||||||
for (const skillLine of skillSummary.lines.slice(0, 4)) {
|
|
||||||
push(renderBoxLine(padCell(skillLine, innerWidth)));
|
|
||||||
}
|
|
||||||
if (agentSummary.lines.length > 0) {
|
|
||||||
push(renderDivider());
|
|
||||||
push(renderBoxLine(theme.fg("warning", theme.bold(padCell("Project Agents", innerWidth)))));
|
|
||||||
for (const agentLine of agentSummary.lines.slice(0, 3)) {
|
|
||||||
push(renderBoxLine(padCell(agentLine, innerWidth)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
push(renderDivider());
|
|
||||||
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Recent activity", innerWidth)))));
|
|
||||||
for (const activityLine of activityLines.length > 0 ? activityLines : ["No messages yet in this session."]) {
|
|
||||||
push(renderBoxLine(padCell(activityLine, innerWidth)));
|
|
||||||
}
|
|
||||||
push(renderDivider());
|
|
||||||
push(
|
|
||||||
renderBoxLine(
|
|
||||||
padCell(
|
|
||||||
`${toolSummary.count} tools · ${commandSummary.count} commands · ${skillSummary.count} skills · /help`,
|
|
||||||
innerWidth,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const leftWidth = Math.min(44, Math.max(30, Math.floor(innerWidth * 0.36)));
|
|
||||||
const rightWidth = innerWidth - leftWidth - 3;
|
|
||||||
const activityLines = wrapForWidth(recentActivity, innerWidth, 2);
|
|
||||||
const wrappedToolLines = toolSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 3));
|
|
||||||
const wrappedCommandLines = commandSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
|
||||||
const wrappedSkillLines = skillSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
|
||||||
const wrappedAgentLines = agentSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
|
||||||
const wrappedModelLines = wrapForWidth(`model: ${modelLabel}`, leftWidth, 2);
|
|
||||||
const wrappedDirectoryLines = wrapForWidth(`directory: ${directoryLabel}`, leftWidth, 2);
|
|
||||||
const wrappedSessionLines = wrapForWidth(`session: ${sessionLabel}`, leftWidth, 2);
|
|
||||||
const wrappedFooterLines = wrapForWidth(
|
|
||||||
`${toolSummary.count} tools · ${commandSummary.count} commands · ${skillSummary.count} skills · /help`,
|
|
||||||
leftWidth,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
const leftLines = [
|
|
||||||
...FEYNMAN_MARK_ART.map((line) => centerText(line, leftWidth)),
|
|
||||||
"",
|
|
||||||
centerText("Research shell ready", leftWidth),
|
|
||||||
"",
|
|
||||||
...wrappedModelLines,
|
|
||||||
...wrappedDirectoryLines,
|
|
||||||
...wrappedSessionLines,
|
|
||||||
"",
|
|
||||||
...wrappedFooterLines,
|
|
||||||
];
|
|
||||||
const rightLines = [
|
|
||||||
"Available Tools",
|
|
||||||
...wrappedToolLines,
|
|
||||||
"",
|
|
||||||
"Slash Commands",
|
|
||||||
...wrappedCommandLines,
|
|
||||||
"",
|
|
||||||
"Research Skills",
|
|
||||||
...wrappedSkillLines,
|
|
||||||
...(wrappedAgentLines.length > 0 ? ["", "Project Agents", ...wrappedAgentLines] : []),
|
|
||||||
"",
|
|
||||||
"Recent Activity",
|
|
||||||
...(activityLines.length > 0 ? activityLines : ["No messages yet in this session."]),
|
|
||||||
];
|
|
||||||
const row = (
|
|
||||||
left: string,
|
|
||||||
right: string,
|
|
||||||
options?: { leftAccent?: boolean; rightAccent?: boolean; leftMuted?: boolean; rightMuted?: boolean },
|
|
||||||
): string => {
|
|
||||||
const leftCell = options?.leftAccent
|
|
||||||
? styleAccentCell(left, leftWidth)
|
|
||||||
: options?.leftMuted
|
|
||||||
? styleMutedCell(left, leftWidth)
|
|
||||||
: padCell(left, leftWidth);
|
|
||||||
const rightCell = options?.rightAccent
|
|
||||||
? styleAccentCell(right, rightWidth)
|
|
||||||
: options?.rightMuted
|
|
||||||
? styleMutedCell(right, rightWidth)
|
|
||||||
: padCell(right, rightWidth);
|
|
||||||
return renderBoxLine(`${leftCell}${theme.fg("borderMuted", " │ ")}${rightCell}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
push(renderBoxLine(padCell("", innerWidth)));
|
const renderBoxLine = (content: string): string =>
|
||||||
for (let index = 0; index < Math.max(leftLines.length, rightLines.length); index += 1) {
|
`${theme.fg("borderMuted", "│")}${content}${theme.fg("borderMuted", "│")}`;
|
||||||
const left = leftLines[index] ?? "";
|
const renderDivider = (): string =>
|
||||||
const right = rightLines[index] ?? "";
|
`${theme.fg("borderMuted", "├")}${theme.fg("borderMuted", "─".repeat(innerWidth))}${theme.fg("borderMuted", "┤")}`;
|
||||||
const isLogoLine = index < FEYNMAN_MARK_ART.length;
|
const styleAccentCell = (text: string, cellWidth: number): string =>
|
||||||
const isRightSectionHeading =
|
theme.fg("accent", theme.bold(padCell(text, cellWidth)));
|
||||||
right === "Available Tools" || right === "Slash Commands" || right === "Research Skills" || right === "Project Agents" ||
|
const styleMutedCell = (text: string, cellWidth: number): string =>
|
||||||
right === "Recent Activity";
|
theme.fg("muted", padCell(text, cellWidth));
|
||||||
const isResearchHeading = right === "Research Skills";
|
const styleSuccessCell = (text: string, cellWidth: number): string =>
|
||||||
const isAgentHeading = right === "Project Agents";
|
theme.fg("success", theme.bold(padCell(text, cellWidth)));
|
||||||
const isFooterLine = left.includes("/help");
|
const styleWarningCell = (text: string, cellWidth: number): string =>
|
||||||
push(
|
theme.fg("warning", theme.bold(padCell(text, cellWidth)));
|
||||||
(() => {
|
|
||||||
const leftCell = isLogoLine
|
|
||||||
? styleAccentCell(left, leftWidth)
|
|
||||||
: !isFooterLine && index >= FEYNMAN_MARK_ART.length + 2
|
|
||||||
? styleMutedCell(left, leftWidth)
|
|
||||||
: padCell(left, leftWidth);
|
|
||||||
const rightCell = isResearchHeading
|
|
||||||
? styleSuccessCell(right, rightWidth)
|
|
||||||
: isAgentHeading
|
|
||||||
? styleWarningCell(right, rightWidth)
|
|
||||||
: isRightSectionHeading
|
|
||||||
? styleAccentCell(right, rightWidth)
|
|
||||||
: right.length > 0
|
|
||||||
? styleMutedCell(right, rightWidth)
|
|
||||||
: padCell(right, rightWidth);
|
|
||||||
return renderBoxLine(`${leftCell}${theme.fg("borderMuted", " │ ")}${rightCell}`);
|
|
||||||
})(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push(theme.fg("borderMuted", `╰${"─".repeat(innerWidth)}╯`));
|
push("");
|
||||||
push("");
|
for (const logoLine of FEYNMAN_AGENT_LOGO) {
|
||||||
return lines;
|
push(theme.fg("accent", theme.bold(centerText(logoLine, cardWidth))));
|
||||||
},
|
}
|
||||||
invalidate() {},
|
push("");
|
||||||
|
push(
|
||||||
|
theme.fg("borderMuted", `╭${titledBorder.left}`) +
|
||||||
|
theme.fg("accent", theme.bold(title)) +
|
||||||
|
theme.fg("borderMuted", `${titledBorder.right}╮`),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (innerWidth < 72) {
|
||||||
|
const activityLines = wrapForWidth(recentActivity, innerWidth, 2);
|
||||||
|
push(renderBoxLine(padCell("", innerWidth)));
|
||||||
|
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Research session ready", innerWidth)))));
|
||||||
|
push(renderBoxLine(padCell(`model: ${modelLabel}`, innerWidth)));
|
||||||
|
push(renderBoxLine(padCell(`session: ${sessionLabel}`, innerWidth)));
|
||||||
|
push(renderBoxLine(padCell(`directory: ${directoryLabel}`, innerWidth)));
|
||||||
|
push(renderDivider());
|
||||||
|
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Available tools", innerWidth)))));
|
||||||
|
for (const toolLine of toolSummary.lines.slice(0, 4)) {
|
||||||
|
push(renderBoxLine(padCell(toolLine, innerWidth)));
|
||||||
|
}
|
||||||
|
push(renderDivider());
|
||||||
|
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Slash Commands", innerWidth)))));
|
||||||
|
for (const commandLine of commandSummary.lines.slice(0, 4)) {
|
||||||
|
push(renderBoxLine(padCell(commandLine, innerWidth)));
|
||||||
|
}
|
||||||
|
push(renderDivider());
|
||||||
|
push(renderBoxLine(theme.fg("success", theme.bold(padCell("Research Skills", innerWidth)))));
|
||||||
|
for (const skillLine of skillSummary.lines.slice(0, 4)) {
|
||||||
|
push(renderBoxLine(padCell(skillLine, innerWidth)));
|
||||||
|
}
|
||||||
|
if (agentSummary.lines.length > 0) {
|
||||||
|
push(renderDivider());
|
||||||
|
push(renderBoxLine(theme.fg("warning", theme.bold(padCell("Project Agents", innerWidth)))));
|
||||||
|
for (const agentLine of agentSummary.lines.slice(0, 3)) {
|
||||||
|
push(renderBoxLine(padCell(agentLine, innerWidth)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push(renderDivider());
|
||||||
|
push(renderBoxLine(theme.fg("accent", theme.bold(padCell("Recent activity", innerWidth)))));
|
||||||
|
for (const activityLine of activityLines.length > 0 ? activityLines : ["No messages yet in this session."]) {
|
||||||
|
push(renderBoxLine(padCell(activityLine, innerWidth)));
|
||||||
|
}
|
||||||
|
push(renderDivider());
|
||||||
|
push(
|
||||||
|
renderBoxLine(
|
||||||
|
padCell(
|
||||||
|
`${toolSummary.count} tools · ${commandSummary.count} commands · ${skillSummary.count} skills`,
|
||||||
|
innerWidth,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const leftWidth = Math.min(44, Math.max(30, Math.floor(innerWidth * 0.36)));
|
||||||
|
const rightWidth = innerWidth - leftWidth - 3;
|
||||||
|
const activityLines = wrapForWidth(recentActivity, innerWidth, 2);
|
||||||
|
const wrappedToolLines = toolSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 3));
|
||||||
|
const wrappedCommandLines = commandSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
||||||
|
const wrappedSkillLines = skillSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
||||||
|
const wrappedAgentLines = agentSummary.lines.flatMap((line) => wrapForWidth(line, rightWidth, 4));
|
||||||
|
const wrappedModelLines = wrapForWidth(`model: ${modelLabel}`, leftWidth, 2);
|
||||||
|
const wrappedDirectoryLines = wrapForWidth(`directory: ${directoryLabel}`, leftWidth, 2);
|
||||||
|
const wrappedSessionLines = wrapForWidth(`session: ${sessionLabel}`, leftWidth, 2);
|
||||||
|
const wrappedFooterLines = wrapForWidth(
|
||||||
|
`${toolSummary.count} tools · ${commandSummary.count} commands · ${skillSummary.count} skills`,
|
||||||
|
leftWidth,
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
const leftLines = [
|
||||||
|
...FEYNMAN_MARK_ART.map((line) => centerText(line, leftWidth)),
|
||||||
|
"",
|
||||||
|
centerText("Research shell ready", leftWidth),
|
||||||
|
"",
|
||||||
|
...wrappedModelLines,
|
||||||
|
...wrappedDirectoryLines,
|
||||||
|
...wrappedSessionLines,
|
||||||
|
"",
|
||||||
|
...wrappedFooterLines,
|
||||||
|
];
|
||||||
|
const rightLines = [
|
||||||
|
"Available Tools",
|
||||||
|
...wrappedToolLines,
|
||||||
|
"",
|
||||||
|
"Slash Commands",
|
||||||
|
...wrappedCommandLines,
|
||||||
|
"",
|
||||||
|
"Research Skills",
|
||||||
|
...wrappedSkillLines,
|
||||||
|
...(wrappedAgentLines.length > 0 ? ["", "Project Agents", ...wrappedAgentLines] : []),
|
||||||
|
"",
|
||||||
|
"Recent Activity",
|
||||||
|
...(activityLines.length > 0 ? activityLines : ["No messages yet in this session."]),
|
||||||
|
];
|
||||||
|
|
||||||
|
push(renderBoxLine(padCell("", innerWidth)));
|
||||||
|
for (let index = 0; index < Math.max(leftLines.length, rightLines.length); index += 1) {
|
||||||
|
const left = leftLines[index] ?? "";
|
||||||
|
const right = rightLines[index] ?? "";
|
||||||
|
const isLogoLine = index < FEYNMAN_MARK_ART.length;
|
||||||
|
const isRightSectionHeading =
|
||||||
|
right === "Available Tools" || right === "Slash Commands" || right === "Research Skills" || right === "Project Agents" ||
|
||||||
|
right === "Recent Activity";
|
||||||
|
const isResearchHeading = right === "Research Skills";
|
||||||
|
const isAgentHeading = right === "Project Agents";
|
||||||
|
push(
|
||||||
|
(() => {
|
||||||
|
const leftCell = isLogoLine
|
||||||
|
? styleAccentCell(left, leftWidth)
|
||||||
|
: index >= FEYNMAN_MARK_ART.length + 2
|
||||||
|
? styleMutedCell(left, leftWidth)
|
||||||
|
: padCell(left, leftWidth);
|
||||||
|
const rightCell = isResearchHeading
|
||||||
|
? styleSuccessCell(right, rightWidth)
|
||||||
|
: isAgentHeading
|
||||||
|
? styleWarningCell(right, rightWidth)
|
||||||
|
: isRightSectionHeading
|
||||||
|
? styleAccentCell(right, rightWidth)
|
||||||
|
: right.length > 0
|
||||||
|
? styleMutedCell(right, rightWidth)
|
||||||
|
: padCell(right, rightWidth);
|
||||||
|
return renderBoxLine(`${leftCell}${theme.fg("borderMuted", " │ ")}${rightCell}`);
|
||||||
|
})(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
push(theme.fg("borderMuted", `╰${"─".repeat(innerWidth)}╯`));
|
||||||
|
push("");
|
||||||
|
return lines;
|
||||||
|
},
|
||||||
|
invalidate() {},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,31 +973,6 @@ export default function researchTools(pi: ExtensionAPI): void {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
pi.registerCommand("help", {
|
|
||||||
description: "Show grouped Feynman commands and prefill the editor with a selected command.",
|
|
||||||
handler: async (_args, ctx) => {
|
|
||||||
const sections = buildFeynmanHelpSections(pi);
|
|
||||||
const items = sections.flatMap((section) => [
|
|
||||||
`--- ${section.title} ---`,
|
|
||||||
...section.commands.map((command) => `${command.usage} — ${command.description}`),
|
|
||||||
]).filter((item, index, array) => {
|
|
||||||
if (!item.startsWith("---")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return array[index + 1] !== undefined && !array[index + 1].startsWith("---");
|
|
||||||
});
|
|
||||||
|
|
||||||
const selected = await ctx.ui.select("Feynman Help", items);
|
|
||||||
if (!selected || selected.startsWith("---")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const usage = selected.split(" — ")[0];
|
|
||||||
ctx.ui.setEditorText(usage);
|
|
||||||
ctx.ui.notify(`Prefilled ${usage}`, "info");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
pi.registerCommand("init", {
|
pi.registerCommand("init", {
|
||||||
description: "Initialize AGENTS.md and session-log folders for a research project.",
|
description: "Initialize AGENTS.md and session-log folders for a research project.",
|
||||||
handler: async (_args, ctx) => {
|
handler: async (_args, ctx) => {
|
||||||
|
|||||||
68
package-lock.json
generated
68
package-lock.json
generated
@@ -10,21 +10,21 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@companion-ai/alpha-hub": "^0.1.2",
|
"@companion-ai/alpha-hub": "^0.1.2",
|
||||||
"@mariozechner/pi-ai": "^0.56.1",
|
"@mariozechner/pi-ai": "^0.62.0",
|
||||||
"@mariozechner/pi-coding-agent": "^0.56.1",
|
"@mariozechner/pi-coding-agent": "^0.62.0",
|
||||||
"@sinclair/typebox": "^0.34.41",
|
"@sinclair/typebox": "^0.34.48",
|
||||||
"dotenv": "^16.4.7"
|
"dotenv": "^17.3.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"feynman": "bin/feynman.js"
|
"feynman": "bin/feynman.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^25.5.0",
|
||||||
"tsx": "^4.20.5",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.6.0"
|
"node": ">=20.18.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../alpha-hub/cli": {
|
"../alpha-hub/cli": {
|
||||||
@@ -1441,21 +1441,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mariozechner/pi-agent-core": {
|
"node_modules/@mariozechner/pi-agent-core": {
|
||||||
"version": "0.56.3",
|
"version": "0.62.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mariozechner/pi-agent-core/-/pi-agent-core-0.56.3.tgz",
|
"resolved": "https://registry.npmjs.org/@mariozechner/pi-agent-core/-/pi-agent-core-0.62.0.tgz",
|
||||||
"integrity": "sha512-TsI1zENf3wqqKPaERnj486Q4i6Y/y6lAZipLNcfDYUDxDrLwNfQ9EW9xukkbJfTZ8zjG3VZ2pBZe3C7wM51dVQ==",
|
"integrity": "sha512-SBjqgDrgKOaC+IGzFGB3jXQErv9H1QMYnWFvUg6ra6dG0ZgWFBUZb6unidngWLsmaxSDWes6KeKiVFMsr2VSEQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/pi-ai": "^0.56.3"
|
"@mariozechner/pi-ai": "^0.62.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mariozechner/pi-ai": {
|
"node_modules/@mariozechner/pi-ai": {
|
||||||
"version": "0.56.3",
|
"version": "0.62.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mariozechner/pi-ai/-/pi-ai-0.56.3.tgz",
|
"resolved": "https://registry.npmjs.org/@mariozechner/pi-ai/-/pi-ai-0.62.0.tgz",
|
||||||
"integrity": "sha512-l4J+cVyVeBLAlGOY/osGDvsbTz0DySCQmR171G6SdbPvIeLGhIi6siZ+zHwq91GJYjv/wtu/08M08ag2mGZKeA==",
|
"integrity": "sha512-mJgryZ5RgBQG++tiETMtCQQJoH2MAhKetCfqI98NMvGydu7L9x2qC2JekQlRaAgIlTgv4MRH1UXHMEs4UweE/Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "^0.73.0",
|
"@anthropic-ai/sdk": "^0.73.0",
|
||||||
@@ -1480,15 +1480,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mariozechner/pi-coding-agent": {
|
"node_modules/@mariozechner/pi-coding-agent": {
|
||||||
"version": "0.56.3",
|
"version": "0.62.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mariozechner/pi-coding-agent/-/pi-coding-agent-0.56.3.tgz",
|
"resolved": "https://registry.npmjs.org/@mariozechner/pi-coding-agent/-/pi-coding-agent-0.62.0.tgz",
|
||||||
"integrity": "sha512-yHgnadye+TT/4NWKBirZUjw/LWdNWTa7M4HJdX2RxRbwuj4q7RZ0Aqy+lQbOHEPDQYhxK3kZb9hjiAbbGficZQ==",
|
"integrity": "sha512-f1NnExqsHuA6w8UVlBtPsvTBhdkMc0h1JD9SzGCdWTLou5GHJr2JIP6DlwV9IKWAnM+sAelaoFez+14wLP2zOQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/jiti": "^2.6.2",
|
"@mariozechner/jiti": "^2.6.2",
|
||||||
"@mariozechner/pi-agent-core": "^0.56.3",
|
"@mariozechner/pi-agent-core": "^0.62.0",
|
||||||
"@mariozechner/pi-ai": "^0.56.3",
|
"@mariozechner/pi-ai": "^0.62.0",
|
||||||
"@mariozechner/pi-tui": "^0.56.3",
|
"@mariozechner/pi-tui": "^0.62.0",
|
||||||
"@silvia-odwyer/photon-node": "^0.3.4",
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
||||||
"chalk": "^5.5.0",
|
"chalk": "^5.5.0",
|
||||||
"cli-highlight": "^2.1.11",
|
"cli-highlight": "^2.1.11",
|
||||||
@@ -1516,9 +1516,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mariozechner/pi-tui": {
|
"node_modules/@mariozechner/pi-tui": {
|
||||||
"version": "0.56.3",
|
"version": "0.62.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mariozechner/pi-tui/-/pi-tui-0.56.3.tgz",
|
"resolved": "https://registry.npmjs.org/@mariozechner/pi-tui/-/pi-tui-0.62.0.tgz",
|
||||||
"integrity": "sha512-eZ1P9QRKHp78hwx+lITr/mujZqe+eCwL/bOS9vXXkFP070RW4VYum0j7TJ4BrFEH/nNkXRS1tYCXYU05une1bA==",
|
"integrity": "sha512-/At11PPe8l319MnUoK4wN5L/uVCU6bDdiIUzH8Ez0stOkjSF6isRXScZ+RMM+6iCKsD4muBTX8Cmcif+3/UWHA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mime-types": "^2.1.4",
|
"@types/mime-types": "^2.1.4",
|
||||||
@@ -2307,12 +2307,12 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.12.0",
|
"version": "25.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
|
||||||
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
|
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/retry": {
|
"node_modules/@types/retry": {
|
||||||
@@ -2647,9 +2647,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "16.6.1",
|
"version": "17.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
|
||||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
"integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@@ -3947,9 +3947,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "7.16.0",
|
"version": "7.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/web-streams-polyfill": {
|
"node_modules/web-streams-polyfill": {
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -47,18 +47,18 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@companion-ai/alpha-hub": "^0.1.2",
|
"@companion-ai/alpha-hub": "^0.1.2",
|
||||||
"@mariozechner/pi-ai": "^0.56.1",
|
"@mariozechner/pi-ai": "^0.62.0",
|
||||||
"@mariozechner/pi-coding-agent": "^0.56.1",
|
"@mariozechner/pi-coding-agent": "^0.62.0",
|
||||||
"@sinclair/typebox": "^0.34.41",
|
"@sinclair/typebox": "^0.34.48",
|
||||||
"dotenv": "^16.4.7"
|
"dotenv": "^17.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^25.5.0",
|
||||||
"tsx": "^4.20.5",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.6.0"
|
"node": ">=20.18.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const appRoot = resolve(here, "..");
|
|||||||
const piPackageRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-coding-agent");
|
const piPackageRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-coding-agent");
|
||||||
const packageJsonPath = resolve(piPackageRoot, "package.json");
|
const packageJsonPath = resolve(piPackageRoot, "package.json");
|
||||||
const cliPath = resolve(piPackageRoot, "dist", "cli.js");
|
const cliPath = resolve(piPackageRoot, "dist", "cli.js");
|
||||||
|
const bunCliPath = resolve(piPackageRoot, "dist", "bun", "cli.js");
|
||||||
const interactiveModePath = resolve(piPackageRoot, "dist", "modes", "interactive", "interactive-mode.js");
|
const interactiveModePath = resolve(piPackageRoot, "dist", "modes", "interactive", "interactive-mode.js");
|
||||||
const interactiveThemePath = resolve(piPackageRoot, "dist", "modes", "interactive", "theme", "theme.js");
|
const interactiveThemePath = resolve(piPackageRoot, "dist", "modes", "interactive", "theme", "theme.js");
|
||||||
const piTuiRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-tui");
|
const piTuiRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-tui");
|
||||||
@@ -85,10 +86,14 @@ if (existsSync(packageJsonPath)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsSync(cliPath)) {
|
for (const entryPath of [cliPath, bunCliPath]) {
|
||||||
const cliSource = readFileSync(cliPath, "utf8");
|
if (!existsSync(entryPath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cliSource = readFileSync(entryPath, "utf8");
|
||||||
if (cliSource.includes('process.title = "pi";')) {
|
if (cliSource.includes('process.title = "pi";')) {
|
||||||
writeFileSync(cliPath, cliSource.replace('process.title = "pi";', 'process.title = "feynman";'), "utf8");
|
writeFileSync(entryPath, cliSource.replace('process.title = "pi";', 'process.title = "feynman";'), "utf8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +117,7 @@ if (existsSync(interactiveThemePath)) {
|
|||||||
" return {",
|
" return {",
|
||||||
' borderColor: (text) => " ".repeat(text.length),',
|
' borderColor: (text) => " ".repeat(text.length),',
|
||||||
' bgColor: (text) => theme.bg("userMessageBg", text),',
|
' bgColor: (text) => theme.bg("userMessageBg", text),',
|
||||||
' placeholderText: "Type your message or /help for commands",',
|
' placeholderText: "Type your message",',
|
||||||
' placeholder: (text) => theme.fg("dim", text),',
|
' placeholder: (text) => theme.fg("dim", text),',
|
||||||
" selectList: getSelectListTheme(),",
|
" selectList: getSelectListTheme(),",
|
||||||
" };",
|
" };",
|
||||||
@@ -127,9 +132,11 @@ if (existsSync(interactiveThemePath)) {
|
|||||||
|
|
||||||
if (existsSync(editorPath)) {
|
if (existsSync(editorPath)) {
|
||||||
let editorSource = readFileSync(editorPath, "utf8");
|
let editorSource = readFileSync(editorPath, "utf8");
|
||||||
const importOriginal = 'import { getSegmenter, isPunctuationChar, isWhitespaceChar, visibleWidth } from "../utils.js";';
|
const importOriginal =
|
||||||
const importReplacement = 'import { applyBackgroundToLine, getSegmenter, isPunctuationChar, isWhitespaceChar, visibleWidth } from "../utils.js";';
|
'import { getSegmenter, isPunctuationChar, isWhitespaceChar, truncateToWidth, visibleWidth } from "../utils.js";';
|
||||||
if (!editorSource.includes("applyBackgroundToLine") && editorSource.includes(importOriginal)) {
|
const importReplacement =
|
||||||
|
'import { applyBackgroundToLine, getSegmenter, isPunctuationChar, isWhitespaceChar, truncateToWidth, visibleWidth } from "../utils.js";';
|
||||||
|
if (editorSource.includes(importOriginal)) {
|
||||||
editorSource = editorSource.replace(importOriginal, importReplacement);
|
editorSource = editorSource.replace(importOriginal, importReplacement);
|
||||||
}
|
}
|
||||||
const desiredRender = [
|
const desiredRender = [
|
||||||
@@ -168,6 +175,13 @@ if (existsSync(editorPath)) {
|
|||||||
" const result = [];",
|
" const result = [];",
|
||||||
' const leftPadding = " ".repeat(paddingX);',
|
' const leftPadding = " ".repeat(paddingX);',
|
||||||
" const rightPadding = leftPadding;",
|
" const rightPadding = leftPadding;",
|
||||||
|
" const renderBorderLine = (indicator) => {",
|
||||||
|
" const remaining = width - visibleWidth(indicator);",
|
||||||
|
" if (remaining >= 0) {",
|
||||||
|
' return this.borderColor(indicator + "─".repeat(remaining));',
|
||||||
|
" }",
|
||||||
|
" return this.borderColor(truncateToWidth(indicator, width));",
|
||||||
|
" };",
|
||||||
" // Render top padding row. When background fill is active, mimic the user-message block",
|
" // Render top padding row. When background fill is active, mimic the user-message block",
|
||||||
" // instead of the stock editor chrome.",
|
" // instead of the stock editor chrome.",
|
||||||
" if (bgColor) {",
|
" if (bgColor) {",
|
||||||
@@ -181,8 +195,7 @@ if (existsSync(editorPath)) {
|
|||||||
" }",
|
" }",
|
||||||
" else if (this.scrollOffset > 0) {",
|
" else if (this.scrollOffset > 0) {",
|
||||||
" const indicator = `─── ↑ ${this.scrollOffset} more `;",
|
" const indicator = `─── ↑ ${this.scrollOffset} more `;",
|
||||||
" const remaining = width - visibleWidth(indicator);",
|
" result.push(renderBorderLine(indicator));",
|
||||||
' result.push(this.borderColor(indicator + "─".repeat(Math.max(0, remaining))));',
|
|
||||||
" }",
|
" }",
|
||||||
" else {",
|
" else {",
|
||||||
" result.push(horizontal.repeat(width));",
|
" result.push(horizontal.repeat(width));",
|
||||||
@@ -205,7 +218,7 @@ if (existsSync(editorPath)) {
|
|||||||
" if (isPlaceholderLine) {",
|
" if (isPlaceholderLine) {",
|
||||||
" const marker = emitCursorMarker ? CURSOR_MARKER : \"\";",
|
" const marker = emitCursorMarker ? CURSOR_MARKER : \"\";",
|
||||||
" const rawPlaceholder = this.theme.placeholderText;",
|
" const rawPlaceholder = this.theme.placeholderText;",
|
||||||
" const graphemes = [...segmenter.segment(rawPlaceholder)];",
|
" const graphemes = [...this.segment(rawPlaceholder)];",
|
||||||
' const firstGrapheme = graphemes[0]?.segment ?? " ";',
|
' const firstGrapheme = graphemes[0]?.segment ?? " ";',
|
||||||
" const restRaw = rawPlaceholder.slice(firstGrapheme.length);",
|
" const restRaw = rawPlaceholder.slice(firstGrapheme.length);",
|
||||||
' const restStyled = typeof this.theme.placeholder === "function"',
|
' const restStyled = typeof this.theme.placeholder === "function"',
|
||||||
@@ -222,7 +235,7 @@ if (existsSync(editorPath)) {
|
|||||||
" if (after.length > 0) {",
|
" if (after.length > 0) {",
|
||||||
" // Cursor is on a character (grapheme) - replace it with highlighted version",
|
" // Cursor is on a character (grapheme) - replace it with highlighted version",
|
||||||
" // Get the first grapheme from 'after'",
|
" // Get the first grapheme from 'after'",
|
||||||
" const afterGraphemes = [...segmenter.segment(after)];",
|
" const afterGraphemes = [...this.segment(after)];",
|
||||||
' const firstGrapheme = afterGraphemes[0]?.segment || "";',
|
' const firstGrapheme = afterGraphemes[0]?.segment || "";',
|
||||||
" const restAfter = after.slice(firstGrapheme.length);",
|
" const restAfter = after.slice(firstGrapheme.length);",
|
||||||
' const cursor = `\\x1b[7m${firstGrapheme}\\x1b[27m`;',
|
' const cursor = `\\x1b[7m${firstGrapheme}\\x1b[27m`;',
|
||||||
@@ -260,8 +273,7 @@ if (existsSync(editorPath)) {
|
|||||||
" }",
|
" }",
|
||||||
" else if (linesBelow > 0) {",
|
" else if (linesBelow > 0) {",
|
||||||
" const indicator = `─── ↓ ${linesBelow} more `;",
|
" const indicator = `─── ↓ ${linesBelow} more `;",
|
||||||
" const remaining = width - visibleWidth(indicator);",
|
" const bottomLine = renderBorderLine(indicator);",
|
||||||
' const bottomLine = this.borderColor(indicator + "─".repeat(Math.max(0, remaining)));',
|
|
||||||
" result.push(bottomLine);",
|
" result.push(bottomLine);",
|
||||||
" }",
|
" }",
|
||||||
" else {",
|
" else {",
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ function printHelp(): void {
|
|||||||
printInfo("--alpha-logout Clear alphaXiv auth and exit");
|
printInfo("--alpha-logout Clear alphaXiv auth and exit");
|
||||||
printInfo("--alpha-status Show alphaXiv auth status and exit");
|
printInfo("--alpha-status Show alphaXiv auth status and exit");
|
||||||
printInfo("--model provider:model Force a specific model");
|
printInfo("--model provider:model Force a specific model");
|
||||||
printInfo("--thinking level off | low | medium | high");
|
printInfo("--thinking level off | minimal | low | medium | high | xhigh");
|
||||||
printInfo("--cwd /path/to/workdir Working directory for tools");
|
printInfo("--cwd /path/to/workdir Working directory for tools");
|
||||||
printInfo("--session-dir /path Session storage directory");
|
printInfo("--session-dir /path Session storage directory");
|
||||||
printInfo("--doctor Alias for `feynman doctor`");
|
printInfo("--doctor Alias for `feynman doctor`");
|
||||||
@@ -113,7 +113,6 @@ function printHelp(): void {
|
|||||||
|
|
||||||
printSection("REPL");
|
printSection("REPL");
|
||||||
printInfo("Inside the REPL, slash workflows come from the live prompt-template and extension command set.");
|
printInfo("Inside the REPL, slash workflows come from the live prompt-template and extension command set.");
|
||||||
printInfo("Use `/help` in chat to browse the commands actually loaded in this session.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleAlphaCommand(action: string | undefined): Promise<void> {
|
async function handleAlphaCommand(action: string | undefined): Promise<void> {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { dirname } from "node:path";
|
|||||||
|
|
||||||
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
||||||
|
|
||||||
export type ThinkingLevel = "off" | "low" | "medium" | "high";
|
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
||||||
|
|
||||||
export function parseModelSpec(spec: string, modelRegistry: ModelRegistry) {
|
export function parseModelSpec(spec: string, modelRegistry: ModelRegistry) {
|
||||||
const trimmed = spec.trim();
|
const trimmed = spec.trim();
|
||||||
@@ -27,7 +27,14 @@ export function normalizeThinkingLevel(value: string | undefined): ThinkingLevel
|
|||||||
}
|
}
|
||||||
|
|
||||||
const normalized = value.toLowerCase();
|
const normalized = value.toLowerCase();
|
||||||
if (normalized === "off" || normalized === "low" || normalized === "medium" || normalized === "high") {
|
if (
|
||||||
|
normalized === "off" ||
|
||||||
|
normalized === "minimal" ||
|
||||||
|
normalized === "low" ||
|
||||||
|
normalized === "medium" ||
|
||||||
|
normalized === "high" ||
|
||||||
|
normalized === "xhigh"
|
||||||
|
) {
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
tests/pi-settings.test.ts
Normal file
18
tests/pi-settings.test.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import assert from "node:assert/strict";
|
||||||
|
import test from "node:test";
|
||||||
|
|
||||||
|
import { normalizeThinkingLevel } from "../src/pi/settings.js";
|
||||||
|
|
||||||
|
test("normalizeThinkingLevel accepts the latest Pi thinking levels", () => {
|
||||||
|
assert.equal(normalizeThinkingLevel("off"), "off");
|
||||||
|
assert.equal(normalizeThinkingLevel("minimal"), "minimal");
|
||||||
|
assert.equal(normalizeThinkingLevel("low"), "low");
|
||||||
|
assert.equal(normalizeThinkingLevel("medium"), "medium");
|
||||||
|
assert.equal(normalizeThinkingLevel("high"), "high");
|
||||||
|
assert.equal(normalizeThinkingLevel("xhigh"), "xhigh");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("normalizeThinkingLevel rejects unknown values", () => {
|
||||||
|
assert.equal(normalizeThinkingLevel("turbo"), undefined);
|
||||||
|
assert.equal(normalizeThinkingLevel(undefined), undefined);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user