mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
chore: initialize my-pi extension bundle
This commit is contained in:
@@ -0,0 +1,586 @@
|
||||
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
||||
import type { SettingItem } from "@earendil-works/pi-tui";
|
||||
import { toOnOff } from "./boolean-format.js";
|
||||
import type { RtkIntegrationController } from "./command-register.js";
|
||||
import { ZellijModal, ZellijSettingsModal } from "./zellij-modal.js";
|
||||
import {
|
||||
DEFAULT_RTK_INTEGRATION_CONFIG,
|
||||
RTK_SOURCE_FILTER_LEVELS,
|
||||
type RtkIntegrationConfig,
|
||||
type RuntimeStatus,
|
||||
} from "./types.js";
|
||||
|
||||
interface SettingValueSyncTarget {
|
||||
updateValue(id: string, value: string): void;
|
||||
}
|
||||
|
||||
const ON_OFF = ["on", "off"];
|
||||
const MODE_VALUES = ["rewrite", "suggest"];
|
||||
const SOURCE_FILTER_VALUES = [...RTK_SOURCE_FILTER_LEVELS];
|
||||
const TRUNCATE_MAX_CHAR_VALUES = ["4000", "8000", "12000", "20000", "50000", "100000", "200000"];
|
||||
const SMART_TRUNCATE_LINE_VALUES = ["40", "80", "120", "160", "220", "320", "500", "1000", "2000", "4000"];
|
||||
const RTK_USAGE_TEXT =
|
||||
"Usage: /rtk [show|path|verify|stats|clear-stats|reset|help] (or run /rtk with no args to open settings modal)";
|
||||
const SETTINGS_TAB_DEFINITIONS = [
|
||||
{
|
||||
label: "General",
|
||||
settingIds: ["enabled", "mode", "showRewriteNotifications", "guardWhenRtkMissing"],
|
||||
},
|
||||
{
|
||||
label: "Compaction",
|
||||
settingIds: [
|
||||
"outputCompactionEnabled",
|
||||
"outputStripAnsi",
|
||||
"outputAggregateTestOutput",
|
||||
"outputFilterBuildOutput",
|
||||
"outputCompactGitOutput",
|
||||
"outputAggregateLinterOutput",
|
||||
"outputGroupSearchOutput",
|
||||
"outputTrackSavings",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Read & Source",
|
||||
settingIds: [
|
||||
"outputReadCompactionEnabled",
|
||||
"outputSourceFilteringEnabled",
|
||||
"outputSourceFiltering",
|
||||
"outputPreserveExactSkillReads",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Truncation",
|
||||
settingIds: [
|
||||
"outputTruncateEnabled",
|
||||
"outputTruncateMaxChars",
|
||||
"outputSmartTruncate",
|
||||
"outputSmartTruncateMaxLines",
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
|
||||
function buildTabbedSettingGroups(settings: SettingItem[]): Array<{ label: string; settings: SettingItem[] }> {
|
||||
const byId = new Map(settings.map((setting) => [setting.id, setting]));
|
||||
const assignedIds = new Set<string>();
|
||||
|
||||
const tabs = SETTINGS_TAB_DEFINITIONS.map(({ label, settingIds }) => ({
|
||||
label,
|
||||
settings: settingIds.map((id) => {
|
||||
const setting = byId.get(id);
|
||||
if (!setting) {
|
||||
throw new Error(`Missing setting item for tab '${label}': ${id}`);
|
||||
}
|
||||
if (assignedIds.has(id)) {
|
||||
throw new Error(`Setting item assigned to multiple tabs: ${id}`);
|
||||
}
|
||||
assignedIds.add(id);
|
||||
return setting;
|
||||
}),
|
||||
}));
|
||||
|
||||
const unassignedIds = settings.map((setting) => setting.id).filter((id) => !assignedIds.has(id));
|
||||
if (unassignedIds.length > 0) {
|
||||
throw new Error(`Unassigned setting items: ${unassignedIds.join(", ")}`);
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
function parseSourceFilterLevel(
|
||||
value: string,
|
||||
): RtkIntegrationConfig["outputCompaction"]["sourceCodeFiltering"] | undefined {
|
||||
return SOURCE_FILTER_VALUES.includes(value as (typeof SOURCE_FILTER_VALUES)[number])
|
||||
? (value as RtkIntegrationConfig["outputCompaction"]["sourceCodeFiltering"])
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function parseIntegerInRange(value: string, min: number, max: number): number | undefined {
|
||||
if (!/^\d+$/.test(value)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const parsed = Number.parseInt(value, 10);
|
||||
if (!Number.isFinite(parsed) || parsed < min || parsed > max) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function summarizeRuntimeStatus(runtimeStatus: RuntimeStatus): string {
|
||||
const runtime = runtimeStatus.rtkAvailable
|
||||
? "rtk=available"
|
||||
: `rtk=missing${runtimeStatus.lastError ? ` (${runtimeStatus.lastError})` : ""}`;
|
||||
const executable = runtimeStatus.rtkExecutablePath
|
||||
? `, rtkPath=${runtimeStatus.rtkExecutablePath}`
|
||||
: runtimeStatus.rtkExecutableResolutionWarning
|
||||
? `, rtkPath=unresolved (${runtimeStatus.rtkExecutableResolutionWarning})`
|
||||
: "";
|
||||
|
||||
return `${runtime}${executable}`;
|
||||
}
|
||||
|
||||
function summarizeConfig(config: RtkIntegrationConfig, runtimeStatus: RuntimeStatus): string {
|
||||
return `enabled=${config.enabled}, commandRewriting=${config.commandRewritingEnabled}, mode=${config.mode}, rewriteSource=rtk, rewriteNotice=${config.showRewriteNotifications}, compaction=${config.outputCompaction.enabled}, readCompaction=${config.outputCompaction.readCompaction.enabled}, sourceFilterEnabled=${config.outputCompaction.sourceCodeFilteringEnabled}, preserveSkillReads=${config.outputCompaction.preserveExactSkillReads}, sourceFilter=${config.outputCompaction.sourceCodeFiltering}, ${summarizeRuntimeStatus(runtimeStatus)}`;
|
||||
}
|
||||
|
||||
function buildSettingItems(config: RtkIntegrationConfig): SettingItem[] {
|
||||
return [
|
||||
{
|
||||
id: "enabled",
|
||||
label: "RTK integration enabled",
|
||||
description: "Master switch for rewrite, suggestions, and output compaction",
|
||||
currentValue: toOnOff(config.enabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "commandRewritingEnabled",
|
||||
label: "RTK command rewriting",
|
||||
description: "Optional RTK CLI command rewriting; off keeps FFF in full control of search",
|
||||
currentValue: toOnOff(config.commandRewritingEnabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "mode",
|
||||
label: "Rewrite mode",
|
||||
description: "rewrite = auto-rewrite bash commands, suggest = notify only",
|
||||
currentValue: config.mode,
|
||||
values: MODE_VALUES,
|
||||
},
|
||||
{
|
||||
id: "showRewriteNotifications",
|
||||
label: "Show rewrite notifications",
|
||||
description: "Show 'RTK rewrite: old -> new' notice in TUI",
|
||||
currentValue: toOnOff(config.showRewriteNotifications),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "guardWhenRtkMissing",
|
||||
label: "Guard when rtk missing",
|
||||
description: "If on, raw commands run unchanged when rtk binary is unavailable",
|
||||
currentValue: toOnOff(config.guardWhenRtkMissing),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputCompactionEnabled",
|
||||
label: "Output compaction enabled",
|
||||
description: "Compact bash/read tool results to reduce token usage; search results are untouched",
|
||||
currentValue: toOnOff(config.outputCompaction.enabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputStripAnsi",
|
||||
label: "Strip ANSI in output",
|
||||
description: "Remove color/control codes from tool output before further compaction",
|
||||
currentValue: toOnOff(config.outputCompaction.stripAnsi),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputReadCompactionEnabled",
|
||||
label: "Read compaction enabled",
|
||||
description: "If off, read tool output stays exact; build/test/git/grep compaction can still run",
|
||||
currentValue: toOnOff(config.outputCompaction.readCompaction.enabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputTruncateEnabled",
|
||||
label: "Hard truncation enabled",
|
||||
description: "Apply max character cap after other compaction techniques",
|
||||
currentValue: toOnOff(config.outputCompaction.truncate.enabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputTruncateMaxChars",
|
||||
label: "Hard truncation max chars",
|
||||
description: "Maximum characters kept when hard truncation is enabled",
|
||||
currentValue: String(config.outputCompaction.truncate.maxChars),
|
||||
values: TRUNCATE_MAX_CHAR_VALUES,
|
||||
},
|
||||
{
|
||||
id: "outputSourceFilteringEnabled",
|
||||
label: "Read source filtering enabled",
|
||||
description: "If off, read output skips source-code filtering regardless of selected level",
|
||||
currentValue: toOnOff(config.outputCompaction.sourceCodeFilteringEnabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputPreserveExactSkillReads",
|
||||
label: "Preserve exact skill reads",
|
||||
description: "If on, read results under the global Pi skills directory (default: ~/.pi/agent/skills, respects PI_CODING_AGENT_DIR), ~/.agents/skills, .pi/skills, and ancestor .agents/skills skip read compaction",
|
||||
currentValue: toOnOff(config.outputCompaction.preserveExactSkillReads),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputSourceFiltering",
|
||||
label: "Read source filtering",
|
||||
description: "none|minimal|aggressive for read output compaction",
|
||||
currentValue: config.outputCompaction.sourceCodeFiltering,
|
||||
values: SOURCE_FILTER_VALUES,
|
||||
},
|
||||
{
|
||||
id: "outputSmartTruncate",
|
||||
label: "Read smart truncation",
|
||||
description: "Keep signatures/imports when read output has many lines",
|
||||
currentValue: toOnOff(config.outputCompaction.smartTruncate.enabled),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputSmartTruncateMaxLines",
|
||||
label: "Read smart truncation max lines",
|
||||
description: "Target max lines for smart truncation in read outputs",
|
||||
currentValue: String(config.outputCompaction.smartTruncate.maxLines),
|
||||
values: SMART_TRUNCATE_LINE_VALUES,
|
||||
},
|
||||
{
|
||||
id: "outputAggregateTestOutput",
|
||||
label: "Aggregate test output",
|
||||
description: "Summarize test command output to failures and key totals",
|
||||
currentValue: toOnOff(config.outputCompaction.aggregateTestOutput),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputFilterBuildOutput",
|
||||
label: "Filter build output",
|
||||
description: "Reduce build noise and keep key error/warning lines",
|
||||
currentValue: toOnOff(config.outputCompaction.filterBuildOutput),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputCompactGitOutput",
|
||||
label: "Compact git output",
|
||||
description: "Condense git command output for lower token usage",
|
||||
currentValue: toOnOff(config.outputCompaction.compactGitOutput),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputAggregateLinterOutput",
|
||||
label: "Aggregate linter output",
|
||||
description: "Summarize linter output by file and issue type",
|
||||
currentValue: toOnOff(config.outputCompaction.aggregateLinterOutput),
|
||||
values: ON_OFF,
|
||||
},
|
||||
{
|
||||
id: "outputTrackSavings",
|
||||
label: "Track output savings",
|
||||
description: "Collect in-session compaction metrics for /rtk stats",
|
||||
currentValue: toOnOff(config.outputCompaction.trackSavings),
|
||||
values: ON_OFF,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function applySetting(config: RtkIntegrationConfig, id: string, value: string): RtkIntegrationConfig {
|
||||
switch (id) {
|
||||
case "enabled":
|
||||
return { ...config, enabled: value === "on" };
|
||||
case "commandRewritingEnabled":
|
||||
return { ...config, commandRewritingEnabled: value === "on" };
|
||||
case "mode":
|
||||
return { ...config, mode: value === "suggest" ? "suggest" : "rewrite" };
|
||||
case "showRewriteNotifications":
|
||||
return { ...config, showRewriteNotifications: value === "on" };
|
||||
case "guardWhenRtkMissing":
|
||||
return { ...config, guardWhenRtkMissing: value === "on" };
|
||||
case "outputCompactionEnabled":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: { ...config.outputCompaction, enabled: value === "on" },
|
||||
};
|
||||
case "outputStripAnsi":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: { ...config.outputCompaction, stripAnsi: value === "on" },
|
||||
};
|
||||
case "outputReadCompactionEnabled":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
readCompaction: { enabled: value === "on" },
|
||||
},
|
||||
};
|
||||
case "outputTruncateEnabled":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
truncate: {
|
||||
...config.outputCompaction.truncate,
|
||||
enabled: value === "on",
|
||||
},
|
||||
},
|
||||
};
|
||||
case "outputTruncateMaxChars": {
|
||||
const parsed = parseIntegerInRange(value, 1_000, 200_000);
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
truncate: {
|
||||
...config.outputCompaction.truncate,
|
||||
maxChars: parsed ?? config.outputCompaction.truncate.maxChars,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case "outputSourceFilteringEnabled":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
sourceCodeFilteringEnabled: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputPreserveExactSkillReads":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
preserveExactSkillReads: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputSourceFiltering": {
|
||||
const parsedValue = parseSourceFilterLevel(value);
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
sourceCodeFiltering: parsedValue ?? config.outputCompaction.sourceCodeFiltering,
|
||||
},
|
||||
};
|
||||
}
|
||||
case "outputSmartTruncate":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
smartTruncate: {
|
||||
...config.outputCompaction.smartTruncate,
|
||||
enabled: value === "on",
|
||||
},
|
||||
},
|
||||
};
|
||||
case "outputSmartTruncateMaxLines": {
|
||||
const parsed = parseIntegerInRange(value, 40, 4_000);
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
smartTruncate: {
|
||||
...config.outputCompaction.smartTruncate,
|
||||
maxLines: parsed ?? config.outputCompaction.smartTruncate.maxLines,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case "outputAggregateTestOutput":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
aggregateTestOutput: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputFilterBuildOutput":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
filterBuildOutput: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputCompactGitOutput":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
compactGitOutput: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputAggregateLinterOutput":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
aggregateLinterOutput: value === "on",
|
||||
},
|
||||
};
|
||||
case "outputTrackSavings":
|
||||
return {
|
||||
...config,
|
||||
outputCompaction: {
|
||||
...config.outputCompaction,
|
||||
trackSavings: value === "on",
|
||||
},
|
||||
};
|
||||
default:
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
function syncSettingValues(settingsList: SettingValueSyncTarget, config: RtkIntegrationConfig): void {
|
||||
settingsList.updateValue("enabled", toOnOff(config.enabled));
|
||||
settingsList.updateValue("commandRewritingEnabled", toOnOff(config.commandRewritingEnabled));
|
||||
settingsList.updateValue("mode", config.mode);
|
||||
settingsList.updateValue("showRewriteNotifications", toOnOff(config.showRewriteNotifications));
|
||||
settingsList.updateValue("guardWhenRtkMissing", toOnOff(config.guardWhenRtkMissing));
|
||||
settingsList.updateValue("outputCompactionEnabled", toOnOff(config.outputCompaction.enabled));
|
||||
settingsList.updateValue("outputStripAnsi", toOnOff(config.outputCompaction.stripAnsi));
|
||||
settingsList.updateValue("outputReadCompactionEnabled", toOnOff(config.outputCompaction.readCompaction.enabled));
|
||||
settingsList.updateValue("outputTruncateEnabled", toOnOff(config.outputCompaction.truncate.enabled));
|
||||
settingsList.updateValue("outputTruncateMaxChars", String(config.outputCompaction.truncate.maxChars));
|
||||
settingsList.updateValue("outputSourceFilteringEnabled", toOnOff(config.outputCompaction.sourceCodeFilteringEnabled));
|
||||
settingsList.updateValue("outputPreserveExactSkillReads", toOnOff(config.outputCompaction.preserveExactSkillReads));
|
||||
settingsList.updateValue("outputSourceFiltering", config.outputCompaction.sourceCodeFiltering);
|
||||
settingsList.updateValue("outputSmartTruncate", toOnOff(config.outputCompaction.smartTruncate.enabled));
|
||||
settingsList.updateValue("outputSmartTruncateMaxLines", String(config.outputCompaction.smartTruncate.maxLines));
|
||||
settingsList.updateValue("outputAggregateTestOutput", toOnOff(config.outputCompaction.aggregateTestOutput));
|
||||
settingsList.updateValue("outputFilterBuildOutput", toOnOff(config.outputCompaction.filterBuildOutput));
|
||||
settingsList.updateValue("outputCompactGitOutput", toOnOff(config.outputCompaction.compactGitOutput));
|
||||
settingsList.updateValue("outputAggregateLinterOutput", toOnOff(config.outputCompaction.aggregateLinterOutput));
|
||||
settingsList.updateValue("outputTrackSavings", toOnOff(config.outputCompaction.trackSavings));
|
||||
}
|
||||
|
||||
async function openSettingsModal(ctx: ExtensionCommandContext, controller: RtkIntegrationController): Promise<void> {
|
||||
const overlayOptions = { anchor: "center" as const, width: 86, maxHeight: "85%" as const, margin: 1 };
|
||||
|
||||
await ctx.ui.custom<void>(
|
||||
(tui, theme, _keybindings, done) => {
|
||||
let current = controller.getConfig();
|
||||
let settingsModal: ZellijSettingsModal | null = null;
|
||||
const allSettings = buildSettingItems(current);
|
||||
const tabs = buildTabbedSettingGroups(allSettings);
|
||||
|
||||
settingsModal = new ZellijSettingsModal(
|
||||
{
|
||||
title: "Pi RTK Optimizer",
|
||||
tabs,
|
||||
activeTabIndex: 0,
|
||||
onChange: (id, newValue) => {
|
||||
current = applySetting(current, id, newValue);
|
||||
controller.setConfig(current, ctx);
|
||||
current = controller.getConfig();
|
||||
if (settingsModal) {
|
||||
syncSettingValues(settingsModal, current);
|
||||
}
|
||||
},
|
||||
onClose: () => done(),
|
||||
helpText: `Config: ${controller.getConfigPath()}`,
|
||||
enableSearch: true,
|
||||
},
|
||||
theme,
|
||||
);
|
||||
|
||||
const modal = new ZellijModal(
|
||||
settingsModal,
|
||||
{
|
||||
borderStyle: "rounded",
|
||||
titleBar: {
|
||||
left: "Pi RTK Optimizer",
|
||||
},
|
||||
helpUndertitle: {
|
||||
variants: [
|
||||
"←/→ tabs • Type to search • Enter/Space change • Esc close",
|
||||
"←/→ tabs • Type to search • Esc close",
|
||||
"←/→ tabs • Esc close",
|
||||
],
|
||||
color: "dim",
|
||||
},
|
||||
overlay: overlayOptions,
|
||||
},
|
||||
theme,
|
||||
);
|
||||
|
||||
return {
|
||||
render(width: number) {
|
||||
return modal.renderModal(width).lines;
|
||||
},
|
||||
invalidate() {
|
||||
modal.invalidate();
|
||||
},
|
||||
handleInput(data: string) {
|
||||
modal.handleInput(data);
|
||||
tui.requestRender();
|
||||
},
|
||||
};
|
||||
},
|
||||
{ overlay: true, overlayOptions },
|
||||
);
|
||||
}
|
||||
|
||||
async function handleArgs(
|
||||
args: string,
|
||||
ctx: ExtensionCommandContext,
|
||||
controller: RtkIntegrationController,
|
||||
): Promise<boolean> {
|
||||
const normalized = (args ?? "").trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (normalized === "help") {
|
||||
ctx.ui.notify(RTK_USAGE_TEXT, "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "show") {
|
||||
ctx.ui.notify(`rtk: ${summarizeConfig(controller.getConfig(), controller.getRuntimeStatus())}`, "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "path") {
|
||||
ctx.ui.notify(`rtk config: ${controller.getConfigPath()}`, "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "verify") {
|
||||
const runtimeStatus = await controller.refreshRuntimeStatus();
|
||||
if (runtimeStatus.rtkAvailable) {
|
||||
const pathDetail = runtimeStatus.rtkExecutablePath ? ` at ${runtimeStatus.rtkExecutablePath}` : "";
|
||||
ctx.ui.notify(`RTK binary is available${pathDetail}.`, "info");
|
||||
} else {
|
||||
ctx.ui.notify(
|
||||
`RTK binary is not available${runtimeStatus.lastError ? `: ${runtimeStatus.lastError}` : ""}.`,
|
||||
"warning",
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "stats") {
|
||||
ctx.ui.notify(controller.getMetricsSummary(), "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "clear-stats") {
|
||||
controller.clearMetrics();
|
||||
ctx.ui.notify("RTK metrics cleared.", "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (normalized === "reset") {
|
||||
controller.setConfig({ ...DEFAULT_RTK_INTEGRATION_CONFIG }, ctx);
|
||||
ctx.ui.notify("RTK integration settings reset to defaults.", "info");
|
||||
return true;
|
||||
}
|
||||
|
||||
ctx.ui.notify(RTK_USAGE_TEXT, "warning");
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function handleRtkIntegrationCommand(
|
||||
args: string,
|
||||
ctx: ExtensionCommandContext,
|
||||
controller: RtkIntegrationController,
|
||||
): Promise<void> {
|
||||
if (await handleArgs(args, ctx, controller)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx.hasUI) {
|
||||
ctx.ui.notify("/rtk requires interactive TUI mode.", "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
await openSettingsModal(ctx, controller);
|
||||
}
|
||||
Reference in New Issue
Block a user