feat: add the snippets plugin (B2)

This commit is contained in:
LukeGus committed 2026-09-23 08:59:16 -05:00
1 parent 1eac0f54b0
commit 3656caf168
29 files changed
+5293

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
import { Play } from "lucide-react";
import type { PanelProps, TermixApp } from "@termix/plugin-sdk/frontend";
import { SnippetsPanel } from "./SnippetsPanel";
import { createSnippetsApi } from "./snippets-api";
import { resolveSnippetContent, hasSnippetInputs } from "./snippet-variables";
export function activate(app: TermixApp): void {
app.registerRailItem({
id: "snippets",
icon: Play,
titleKey: "nav.snippets",
permission: "view",
});
app.registerPanel("snippets", (props: PanelProps) => (
<SnippetsPanel {...props} />
));
app.registerPaletteEntry({
id: "snippets.run",
titleKey: "nav.snippets",
scope: "global",
icon: Play,
run: async (shell) => {
shell.openRailView("snippets");
},
});
app.registerSlotContribution("onboarding.features", {
actionId: "snippets.feature",
titleKey: "onboarding.feature_snippets",
descriptionKey: "onboarding.feature_snippets_desc",
icon: Play,
});
// Resolves a snippet by id for core's terminal (startup snippet, custom
// keybindings), so core never imports snippet code or data directly.
app.registerAction("snippets.resolveForTerminal", (async (
snippetId: number,
host: {
ip?: string;
username?: string;
port?: number;
name?: string;
} | null,
inputValues?: Record<string, string>,
) => {
const api = createSnippetsApi(app.api);
const snippet = await api.get(snippetId).catch(() => null);
if (!snippet) return null;
if (
hasSnippetInputs(snippet.content) &&
(!inputValues || Object.keys(inputValues).length === 0)
) {
return {
needsInputs: true,
content: snippet.content,
isNote: snippet.isNote,
};
}
return {
needsInputs: false,
content: resolveSnippetContent(snippet.content, host, inputValues ?? {}),
isNote: snippet.isNote,
};
}) as never);
}