Add plannotator extension v0.19.10

This commit is contained in:
2026-05-07 11:38:14 +10:00
parent e914bc59c9
commit f37e4565ff
91 changed files with 35103 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
import type { ExtensionContext } from "@mariozechner/pi-coding-agent";
type AssistantTextBlock = { type?: string; text?: string };
type AssistantMessageLike = {
role?: unknown;
content?: unknown;
};
type SessionEntryLike = {
id: string;
type: string;
message?: AssistantMessageLike;
};
export type LastAssistantMessageSnapshot = {
entryId: string;
text: string;
};
function isAssistantMessage(message: AssistantMessageLike): message is { role: "assistant"; content: AssistantTextBlock[] } {
return message.role === "assistant" && Array.isArray(message.content);
}
function getTextContent(message: { content: AssistantTextBlock[] }): string {
return message.content
.filter((block): block is { type: "text"; text: string } => block.type === "text")
.map((block) => block.text)
.join("\n");
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
export function getAssistantMessageText(message: unknown): string | null {
if (!isRecord(message)) return null;
const candidate = { role: message.role, content: message.content };
if (!isAssistantMessage(candidate)) return null;
const text = getTextContent(candidate);
return text.trim() ? text : null;
}
function getCurrentBranch(ctx: ExtensionContext): SessionEntryLike[] {
return ctx.sessionManager.getBranch() as SessionEntryLike[];
}
export function getLastAssistantMessageSnapshot(ctx: ExtensionContext): LastAssistantMessageSnapshot | null {
// "Last" means the active conversation branch, not the newest message anywhere
// in the append-only session file.
const branch = getCurrentBranch(ctx);
for (let i = branch.length - 1; i >= 0; i--) {
const entry = branch[i];
if (entry.type === "message" && entry.message) {
const text = getAssistantMessageText(entry.message);
if (text) return { entryId: entry.id, text };
}
}
return null;
}
export function getLastAssistantMessageText(ctx: ExtensionContext): string | null {
return getLastAssistantMessageSnapshot(ctx)?.text ?? null;
}
export function hasSessionMovedPastEntry(ctx: ExtensionContext, entryId: string): boolean {
if (!ctx.isIdle()) return true;
const branch = getCurrentBranch(ctx);
const index = branch.findIndex((entry) => entry.id === entryId);
if (index === -1) return true;
return branch.slice(index + 1).some((entry) => entry.type === "message");
}