- Rename project config dir from .pi/ to .feynman/ (Pi supports this via piConfig.configDir) - Rename citation agent to verifier across all prompts, agents, skills, and docs - Add website with homepage and 24 doc pages (Astro + Tailwind) - Add skills for all workflows (deep-research, lit, review, audit, replicate, compare, draft, autoresearch, watch, jobs, session-log, agentcomputer) - Add Pi-native prompt frontmatter (args, section, topLevelCli) and read at runtime - Remove sync-docs generation layer — docs are standalone - Remove metadata/prompts.mjs and metadata/packages.mjs — not needed at runtime - Rewrite README and homepage copy - Add environment selection to /replicate before executing - Add prompts/delegate.md and AGENTS.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
import {
|
|
extensionCommandSpecs,
|
|
formatSlashUsage,
|
|
getExtensionCommandSpec,
|
|
livePackageCommandGroups,
|
|
readPromptSpecs,
|
|
} from "../../metadata/commands.mjs";
|
|
import { APP_ROOT } from "./shared.js";
|
|
|
|
type HelpCommand = { usage: string; description: string };
|
|
type HelpSection = { title: string; commands: HelpCommand[] };
|
|
|
|
function buildHelpSections(pi: ExtensionAPI): HelpSection[] {
|
|
const liveCommands = new Map(pi.getCommands().map((command) => [command.name, command]));
|
|
const promptSpecs = readPromptSpecs(APP_ROOT);
|
|
const sections = new Map<string, HelpCommand[]>();
|
|
|
|
for (const command of promptSpecs.filter((entry) => entry.section !== "Internal")) {
|
|
const live = liveCommands.get(command.name);
|
|
if (!live) continue;
|
|
const items = sections.get(command.section) ?? [];
|
|
items.push({
|
|
usage: formatSlashUsage(command),
|
|
description: live.description ?? command.description,
|
|
});
|
|
sections.set(command.section, items);
|
|
}
|
|
|
|
for (const command of extensionCommandSpecs.filter((entry) => entry.publicDocs)) {
|
|
const live = liveCommands.get(command.name);
|
|
if (!live) continue;
|
|
const items = sections.get(command.section) ?? [];
|
|
items.push({
|
|
usage: formatSlashUsage(command),
|
|
description: live.description ?? command.description,
|
|
});
|
|
sections.set(command.section, items);
|
|
}
|
|
|
|
const ownedNames = new Set([
|
|
...promptSpecs.filter((entry) => entry.section !== "Internal").map((entry) => entry.name),
|
|
...extensionCommandSpecs.filter((entry) => entry.publicDocs).map((entry) => entry.name),
|
|
]);
|
|
|
|
for (const group of livePackageCommandGroups) {
|
|
const commands: HelpCommand[] = [];
|
|
for (const spec of group.commands) {
|
|
const command = liveCommands.get(spec.name);
|
|
if (!command || ownedNames.has(command.name)) continue;
|
|
commands.push({
|
|
usage: spec.usage,
|
|
description: command.description ?? "",
|
|
});
|
|
}
|
|
|
|
if (commands.length > 0) {
|
|
sections.set(group.title, commands);
|
|
}
|
|
}
|
|
|
|
return [
|
|
"Research Workflows",
|
|
"Project & Session",
|
|
"Setup",
|
|
"Agents & Delegation",
|
|
"Bundled Package Commands",
|
|
]
|
|
.map((title) => ({ title, commands: sections.get(title) ?? [] }))
|
|
.filter((section) => section.commands.length > 0);
|
|
}
|
|
|
|
export function registerHelpCommand(pi: ExtensionAPI): void {
|
|
pi.registerCommand("help", {
|
|
description:
|
|
getExtensionCommandSpec("help")?.description ??
|
|
"Show grouped Feynman commands and prefill the editor with a selected command.",
|
|
handler: async (_args, ctx) => {
|
|
const sections = buildHelpSections(pi);
|
|
const items = sections.flatMap((section) => [
|
|
`--- ${section.title} ---`,
|
|
...section.commands.map((cmd) => `${cmd.usage} — ${cmd.description}`),
|
|
]);
|
|
|
|
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");
|
|
},
|
|
});
|
|
}
|