e9888367d1
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers. - Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies. - Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
106 lines
3.7 KiB
TypeScript
106 lines
3.7 KiB
TypeScript
import type { AvailableCommand } from "@oh-my-pi/pi-utils/acp";
|
|
import type { SkillsSettings } from "../config/settings";
|
|
import type { LoadedCustomCommand } from "../extensibility/custom-commands";
|
|
import type { ExtensionRunner } from "../extensibility/extensions";
|
|
import { getSkillSlashCommandName, type Skill } from "../extensibility/skills";
|
|
import { type FileSlashCommand, loadSlashCommands } from "../extensibility/slash-commands";
|
|
import { ACP_BUILTIN_RESERVED_NAMES, isAcpBuiltinShadowedName } from "./acp-builtins";
|
|
import { BUILTIN_SLASH_COMMANDS_INTERNAL } from "./builtin-registry";
|
|
|
|
export type AvailableSlashCommandSource = "builtin" | "skill" | "extension" | "custom" | "mcp_prompt" | "file";
|
|
|
|
export interface InternalAvailableSlashCommand {
|
|
name: string;
|
|
aliases?: string[];
|
|
description?: string;
|
|
input?: { hint: string };
|
|
subcommands?: Array<{ name: string; description?: string; usage?: string }>;
|
|
source: AvailableSlashCommandSource;
|
|
}
|
|
|
|
export interface AvailableCommandsSession {
|
|
readonly extensionRunner?: ExtensionRunner;
|
|
readonly customCommands: ReadonlyArray<LoadedCustomCommand>;
|
|
readonly mcpPromptCommands?: ReadonlyArray<LoadedCustomCommand>;
|
|
readonly skills: ReadonlyArray<Skill>;
|
|
readonly skillsSettings?: SkillsSettings;
|
|
setSlashCommands(slashCommands: FileSlashCommand[]): void;
|
|
sessionManager: { getCwd(): string };
|
|
}
|
|
|
|
export async function buildAvailableSlashCommands(
|
|
session: AvailableCommandsSession,
|
|
loadFileCommands: (cwd: string) => Promise<FileSlashCommand[]> = cwd => loadSlashCommands({ cwd }),
|
|
): Promise<InternalAvailableSlashCommand[]> {
|
|
const commands: InternalAvailableSlashCommand[] = [];
|
|
const seenNames = new Set<string>();
|
|
const appendCommand = (command: InternalAvailableSlashCommand): void => {
|
|
if (seenNames.has(command.name)) return;
|
|
seenNames.add(command.name);
|
|
commands.push(command);
|
|
};
|
|
|
|
for (const command of BUILTIN_SLASH_COMMANDS_INTERNAL) {
|
|
if (!command.handle) continue;
|
|
const hint = command.acpInputHint ?? command.inlineHint;
|
|
appendCommand({
|
|
name: command.name,
|
|
aliases: command.aliases,
|
|
description: command.acpDescription ?? command.description,
|
|
input: hint ? { hint } : undefined,
|
|
subcommands: command.subcommands,
|
|
source: "builtin",
|
|
});
|
|
}
|
|
|
|
if (session.skillsSettings?.enableSkillCommands) {
|
|
for (const skill of session.skills) {
|
|
appendCommand({
|
|
name: getSkillSlashCommandName(skill),
|
|
description: skill.description || `Run ${skill.name} skill`,
|
|
input: { hint: "arguments" },
|
|
source: "skill",
|
|
});
|
|
}
|
|
}
|
|
|
|
const runner = session.extensionRunner;
|
|
if (runner) {
|
|
for (const command of runner.getRegisteredCommands(ACP_BUILTIN_RESERVED_NAMES)) {
|
|
if (isAcpBuiltinShadowedName(command.name)) continue;
|
|
appendCommand({
|
|
name: command.name,
|
|
description: command.description ?? "(extension command)",
|
|
input: { hint: "arguments" },
|
|
source: "extension",
|
|
});
|
|
}
|
|
}
|
|
|
|
for (const command of session.customCommands) {
|
|
const source: AvailableSlashCommandSource = command.path?.startsWith("mcp:") ? "mcp_prompt" : "custom";
|
|
appendCommand({
|
|
name: command.command.name,
|
|
description: command.command.description,
|
|
input: { hint: "arguments" },
|
|
source,
|
|
});
|
|
}
|
|
|
|
const fileCommands = await loadFileCommands(session.sessionManager.getCwd());
|
|
session.setSlashCommands(fileCommands);
|
|
for (const command of fileCommands) {
|
|
appendCommand({ name: command.name, description: command.description, source: "file" });
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
export function toAcpAvailableCommands(commands: readonly InternalAvailableSlashCommand[]): AvailableCommand[] {
|
|
return commands.map(command => ({
|
|
name: command.name,
|
|
description: command.description ?? "",
|
|
input: command.input,
|
|
}));
|
|
}
|