import { readdir, stat } from "node:fs/promises"; import { join } from "node:path"; import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; import { buildArtifactPaths } from "./artifact.js"; import { describeNativeCompaction, type NativeCompactionStatus, type NativeCompactionView, type ResolvedContinuityConfig, } from "./config.js"; import { PRODUCT_NAME } from "./constants.js"; import type { HandoffState } from "./handoff.js"; export interface StalePendingArtifact { path: string; modifiedMs: number; } export async function findStalePendingArtifacts( artifactDirectory: string, sessionId: string, ): Promise { const paths = buildArtifactPaths(artifactDirectory, sessionId, "placeholder"); try { const names = await readdir(paths.pendingDir); const artifacts = await Promise.all( names .filter((name) => name.endsWith(".md")) .map(async (name) => { const path = join(paths.pendingDir, name); const info = await stat(path); return { path, modifiedMs: info.mtimeMs }; }), ); return artifacts.sort((a, b) => b.modifiedMs - a.modifiedMs); } catch (error) { if ( error && typeof error === "object" && "code" in error && (error as { code?: string }).code === "ENOENT" ) { return []; } throw error; } } function tokenLabel(value: number): string { return value.toLocaleString("en-US"); } function percentLabel(value: number): string { return `${value.toFixed(1)}%`; } export function nativeViewForStatus( native: NativeCompactionStatus, contextWindow: number, ): NativeCompactionView { const view = describeNativeCompaction(native, contextWindow); return { ...view, errors: [...native.errors, ...view.errors], valid: native.errors.length === 0 && view.valid, }; } export function statusHeadlineForConfig( config: ResolvedContinuityConfig, native: NativeCompactionView, ): string { if (!config.trusted) return `${PRODUCT_NAME}: automatic behavior disabled because project is not trusted.`; if (!config.valid) return `${PRODUCT_NAME} disabled: invalid configuration in ${config.configPath}.`; if (!config.enabled) return `${PRODUCT_NAME}: disabled by configuration.`; if (!native.valid) return `${PRODUCT_NAME} refused: native compaction settings are invalid for the current model.`; return `${PRODUCT_NAME}: armed · trigger ${tokenLabel(native.triggerTokens)} tokens (approximately ${percentLabel(native.effectiveTriggerPercent)}) · keep ${tokenLabel(native.keepRecentTokens)} tokens.`; } export function formatStatus( config: ResolvedContinuityConfig, native: NativeCompactionView, settingsPath: string, state: HandoffState, modelId: string, stalePendingPath?: string, restartRequired = false, pendingNative?: NativeCompactionView, ): string { const lines = [ statusHeadlineForConfig(config, native), "", `Status: ${config.enabled && config.valid && config.trusted && native.valid ? "armed" : "refused/disabled"}`, `- Model: ${modelId}`, `- Context window: ${tokenLabel(native.contextWindow)}`, `- Reserve: ${tokenLabel(native.reserveTokens)}`, `- Effective trigger: ${tokenLabel(native.triggerTokens)} (approximately ${percentLabel(native.effectiveTriggerPercent)})`, `- Keep recent: ${tokenLabel(native.keepRecentTokens)} (approximately ${percentLabel(native.effectiveKeepRecentPercent)})`, `- Native compaction: ${native.enabled ? "enabled" : "disabled"}`, `- Restart required: ${restartRequired ? "yes" : "no"}`, `- Synthesis model: ${config.synthesisModel}`, `- Synthesis effort: ${config.synthesisEffort}`, `- Pi settings: ${settingsPath}`, `- Extension config: ${config.configPath}`, `- Artifacts: ${config.artifactDirectoryPath}`, `- Active operation: ${state.activeOperation ?? "none"}`, `- Last checkpoint: ${state.lastCheckpointAt ?? "none"}`, `- Last artifact: ${state.lastArtifactPath ?? "none"}`, `- Last failure: ${state.lastFailure ?? "none"}`, ]; if (config.disabledReason) lines.push(`- Disabled reason: ${config.disabledReason}`); if (native.errors.length > 0) lines.push(`- Native settings errors: ${native.errors.join("; ")}`); if (restartRequired && pendingNative) { lines.push( `- Pending restart reserve: ${tokenLabel(pendingNative.reserveTokens)}`, `- Pending restart trigger: ${tokenLabel(pendingNative.triggerTokens)} (approximately ${percentLabel(pendingNative.effectiveTriggerPercent)})`, `- Pending restart keep recent: ${tokenLabel(pendingNative.keepRecentTokens)} (approximately ${percentLabel(pendingNative.effectiveKeepRecentPercent)})`, ); } if (stalePendingPath) lines.push(`- Stale pending artifact: ${stalePendingPath}`); return lines.join("\n"); } export function formatSettings( config: ResolvedContinuityConfig, native: NativeCompactionView, settingsPath: string, pendingNative?: NativeCompactionView, ): string { const lines = [ `${PRODUCT_NAME}: settings`, "", "Extension", `- Enabled: ${config.enabled ? "on" : "off"}`, `- Synthesis model: ${config.synthesisModel}`, `- Synthesis effort: ${config.synthesisEffort}`, `- Artifact directory: ${config.artifactDirectory}`, `- Extension config: ${config.configPath}`, "", "Native Pi compaction", `- Enabled: ${native.enabled ? "on" : "off"}`, `- Reserve tokens: ${tokenLabel(native.reserveTokens)}`, `- Trigger tokens: ${tokenLabel(native.triggerTokens)} (approximately ${percentLabel(native.effectiveTriggerPercent)})`, `- Keep recent tokens: ${tokenLabel(native.keepRecentTokens)} (approximately ${percentLabel(native.effectiveKeepRecentPercent)})`, `- Pi settings: ${settingsPath}`, "- Native token changes require a full Pi restart.", ]; if (pendingNative) { lines.push( "", "Pending restart", `- Reserve tokens: ${tokenLabel(pendingNative.reserveTokens)}`, `- Trigger tokens: ${tokenLabel(pendingNative.triggerTokens)} (approximately ${percentLabel(pendingNative.effectiveTriggerPercent)})`, `- Keep recent tokens: ${tokenLabel(pendingNative.keepRecentTokens)} (approximately ${percentLabel(pendingNative.effectiveKeepRecentPercent)})`, ); } return lines.join("\n"); } export function notificationLevelForMessage( message: string, ): "info" | "warning" { const headline = message.split("\n")[0]?.toLowerCase() ?? ""; return headline.includes("disabled") || headline.includes("failed") || headline.includes("invalid") || headline.includes("untrusted") || headline.includes("refused") || headline.includes("restart required") ? "warning" : "info"; } export function footerStatusForMessage(message: string): string { const headline = message.split("\n")[0] ?? ""; const triggerPercent = headline.match( /trigger [\d,]+ tokens \(approximately ([\d.]+%)\)/, ); if (triggerPercent) return `Continuity @ ~${triggerPercent[1]}`; const normalized = headline.toLowerCase(); if (normalized.includes("failed")) return "PSC failed"; if (normalized.includes("disabled") || normalized.includes("refused")) return "PSC refused"; if (normalized.includes("settings")) return "PSC settings"; if (normalized.includes("checkpoint") || normalized.includes("handoff")) return "PSC handoff"; return "PSC ready"; } export function notifyStatus(ctx: ExtensionContext, message: string): void { ctx.ui.setWidget("session-continuity", undefined); ctx.ui.notify(message, notificationLevelForMessage(message)); ctx.ui.setStatus("session-continuity", footerStatusForMessage(message)); }