Phase 11: footer status line on·N — SPEC §7.2.
Update skill-reinject status after toggles, clear, skill tracking, and session restore. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+26
-4
@@ -1,7 +1,7 @@
|
|||||||
import type { ExtensionAPI, ExtensionCommandContext, Skill } from "@earendil-works/pi-coding-agent";
|
import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, Skill } from "@earendil-works/pi-coding-agent";
|
||||||
import { resolveDeliveryMode } from "./auto-compact.js";
|
import { resolveDeliveryMode } from "./auto-compact.js";
|
||||||
import { reinjectNow } from "./reinject.js";
|
import { reinjectNow } from "./reinject.js";
|
||||||
import { readSettings, writeGlobalSettings, type SkillReinjectSettings } from "./settings.js";
|
import { effectiveEnabled, readSettings, writeGlobalSettings, type SkillReinjectSettings } from "./settings.js";
|
||||||
import type { AutoCompactIntegration, ExtensionState, RuntimeFlags } from "./state.js";
|
import type { AutoCompactIntegration, ExtensionState, RuntimeFlags } from "./state.js";
|
||||||
|
|
||||||
export interface SkillReinjectCommandDeps {
|
export interface SkillReinjectCommandDeps {
|
||||||
@@ -12,6 +12,20 @@ export interface SkillReinjectCommandDeps {
|
|||||||
persistState: () => void;
|
persistState: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Footer status `on·N` / `off·N` (SPEC §7.2). */
|
||||||
|
export function updateSkillReinjectStatusLine(
|
||||||
|
ctx: ExtensionContext,
|
||||||
|
state: ExtensionState,
|
||||||
|
settings?: SkillReinjectSettings,
|
||||||
|
): void {
|
||||||
|
if (!ctx.hasUI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const resolvedSettings = settings ?? readSettings(ctx);
|
||||||
|
const label = effectiveEnabled(state.sessionOverride, resolvedSettings) ? "on" : "off";
|
||||||
|
ctx.ui.setStatus("skill-reinject", `${label}·${state.skills.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
const SKILL_REINJECT_COMMAND_NAMES = ["skill-reinject", "sr", "skills-reinject"] as const;
|
const SKILL_REINJECT_COMMAND_NAMES = ["skill-reinject", "sr", "skills-reinject"] as const;
|
||||||
|
|
||||||
export function registerSkillReinjectCommand(pi: ExtensionAPI, deps: SkillReinjectCommandDeps): void {
|
export function registerSkillReinjectCommand(pi: ExtensionAPI, deps: SkillReinjectCommandDeps): void {
|
||||||
@@ -93,6 +107,7 @@ function showSkillReinjectStatus(ctx: ExtensionCommandContext, deps: SkillReinje
|
|||||||
}
|
}
|
||||||
const settings = readSettings(ctx);
|
const settings = readSettings(ctx);
|
||||||
ctx.ui.notify(formatSkillReinjectStatus(deps.state, settings, deps.runtime, deps.state.sessionIntegrationOverride), "info");
|
ctx.ui.notify(formatSkillReinjectStatus(deps.state, settings, deps.runtime, deps.state.sessionIntegrationOverride), "info");
|
||||||
|
updateSkillReinjectStatusLine(ctx, deps.state, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSkillReinjectCommand(
|
async function handleSkillReinjectCommand(
|
||||||
@@ -112,7 +127,7 @@ async function handleSkillReinjectCommand(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subcommand === "global") {
|
if (subcommand === "global") {
|
||||||
handleGlobalToggle(trimmed, ctx);
|
handleGlobalToggle(trimmed, ctx, deps);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subcommand === "list") {
|
if (subcommand === "list") {
|
||||||
@@ -160,9 +175,14 @@ function handleSessionToggle(
|
|||||||
const settings = readSettings(ctx);
|
const settings = readSettings(ctx);
|
||||||
const enabledLine = formatEnabledLine(deps.state.sessionOverride, settings);
|
const enabledLine = formatEnabledLine(deps.state.sessionOverride, settings);
|
||||||
ctx.ui.notify(enabledLine, "info");
|
ctx.ui.notify(enabledLine, "info");
|
||||||
|
updateSkillReinjectStatusLine(ctx, deps.state, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGlobalToggle(args: string, ctx: ExtensionCommandContext): void {
|
function handleGlobalToggle(
|
||||||
|
args: string,
|
||||||
|
ctx: ExtensionCommandContext,
|
||||||
|
deps: SkillReinjectCommandDeps,
|
||||||
|
): void {
|
||||||
const parts = args.trim().split(/\s+/);
|
const parts = args.trim().split(/\s+/);
|
||||||
const action = parts[1];
|
const action = parts[1];
|
||||||
if (action !== "on" && action !== "off") {
|
if (action !== "on" && action !== "off") {
|
||||||
@@ -176,6 +196,7 @@ function handleGlobalToggle(args: string, ctx: ExtensionCommandContext): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.ui.notify(`skill-reinject: global ${action}`, "info");
|
ctx.ui.notify(`skill-reinject: global ${action}`, "info");
|
||||||
|
updateSkillReinjectStatusLine(ctx, deps.state, readSettings(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTrackedSkillsList(ctx: ExtensionCommandContext, deps: SkillReinjectCommandDeps): void {
|
function showTrackedSkillsList(ctx: ExtensionCommandContext, deps: SkillReinjectCommandDeps): void {
|
||||||
@@ -199,6 +220,7 @@ function handleClearTrackedSkills(ctx: ExtensionCommandContext, deps: SkillReinj
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.ui.notify("skill-reinject: cleared tracked skills", "info");
|
ctx.ui.notify("skill-reinject: cleared tracked skills", "info");
|
||||||
|
updateSkillReinjectStatusLine(ctx, deps.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTEGRATION_VALUES: readonly AutoCompactIntegration[] = ["auto", "defer", "immediate", "off"];
|
const INTEGRATION_VALUES: readonly AutoCompactIntegration[] = ["auto", "defer", "immediate", "off"];
|
||||||
|
|||||||
+9
-4
@@ -7,7 +7,7 @@ import {
|
|||||||
type Skill,
|
type Skill,
|
||||||
} from "@earendil-works/pi-coding-agent";
|
} from "@earendil-works/pi-coding-agent";
|
||||||
import { detectAndCachePiAutoCompact, resolveDeliveryMode } from "./auto-compact.js";
|
import { detectAndCachePiAutoCompact, resolveDeliveryMode } from "./auto-compact.js";
|
||||||
import { registerSkillReinjectCommand } from "./commands.js";
|
import { registerSkillReinjectCommand, updateSkillReinjectStatusLine } from "./commands.js";
|
||||||
import {
|
import {
|
||||||
consumeCompactionOnSessionCompact,
|
consumeCompactionOnSessionCompact,
|
||||||
createCompactionRuntime,
|
createCompactionRuntime,
|
||||||
@@ -53,9 +53,12 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
persistState,
|
persistState,
|
||||||
});
|
});
|
||||||
|
|
||||||
function trackSkillAndPersist(input: TrackSkillInput): void {
|
function trackSkillAndPersist(input: TrackSkillInput, ctx?: ExtensionContext): void {
|
||||||
trackSkill(state, input);
|
trackSkill(state, input);
|
||||||
persistState();
|
persistState();
|
||||||
|
if (ctx) {
|
||||||
|
updateSkillReinjectStatusLine(ctx, state, readSettings(ctx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function trackReadSkillPath(path: string, ctx: ExtensionContext): void {
|
function trackReadSkillPath(path: string, ctx: ExtensionContext): void {
|
||||||
@@ -70,7 +73,7 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
filePath: matched.filePath,
|
filePath: matched.filePath,
|
||||||
baseDir: matched.baseDir,
|
baseDir: matched.baseDir,
|
||||||
source: "read",
|
source: "read",
|
||||||
});
|
}, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreSessionState(ctx: ExtensionContext): void {
|
function restoreSessionState(ctx: ExtensionContext): void {
|
||||||
@@ -82,6 +85,7 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
rescanSkillsFromBranch(state, branch, ctx.cwd, registeredSkills, settings.trackReadPaths);
|
rescanSkillsFromBranch(state, branch, ctx.cwd, registeredSkills, settings.trackReadPaths);
|
||||||
}
|
}
|
||||||
|
updateSkillReinjectStatusLine(ctx, state, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSessionCompact(event: SessionCompactEvent, ctx: ExtensionContext): void {
|
function handleSessionCompact(event: SessionCompactEvent, ctx: ExtensionContext): void {
|
||||||
@@ -169,7 +173,7 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
filePath: skill.filePath,
|
filePath: skill.filePath,
|
||||||
baseDir: skill.baseDir,
|
baseDir: skill.baseDir,
|
||||||
source: "slash",
|
source: "slash",
|
||||||
});
|
}, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +201,7 @@ export default function skillReinject(pi: ExtensionAPI): void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
persistState();
|
persistState();
|
||||||
|
updateSkillReinjectStatusLine(ctx, state, readSettings(ctx));
|
||||||
});
|
});
|
||||||
|
|
||||||
pi.on("tool_call", async (event, ctx) => {
|
pi.on("tool_call", async (event, ctx) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user