187 lines
5.3 KiB
TypeScript
187 lines
5.3 KiB
TypeScript
import type { ActivateContext, IdeAPluginModule, PluginLayoutProps } from "@idea/plugin-sdk";
|
|
|
|
const COMMAND_ID = "hello-plugin";
|
|
const LAYOUT_TYPE = "hello-plugin.hello-world";
|
|
|
|
let hasLoggedFirstLayoutRender = false;
|
|
|
|
function HelloWorldLayout(props: PluginLayoutProps): string {
|
|
if (!hasLoggedFirstLayoutRender) {
|
|
hasLoggedFirstLayoutRender = true;
|
|
console.info("[hello-plugin] layout first render", {
|
|
projectId: props.projectId,
|
|
nodeId: props.nodeId,
|
|
layoutType: props.layoutType,
|
|
hasState: props.state !== undefined
|
|
});
|
|
}
|
|
|
|
return "hello-world";
|
|
}
|
|
|
|
export function activate(ctx: ActivateContext): void {
|
|
ctx.logger.info("activating hello-plugin", {
|
|
pluginId: ctx.pluginId,
|
|
hasCommands: Boolean(ctx.commands),
|
|
hasLayouts: Boolean(ctx.layouts)
|
|
});
|
|
|
|
const commandDisposable = ctx.commands?.registerCommand(COMMAND_ID, () => {
|
|
ctx.logger.info("command executed", { commandId: COMMAND_ID });
|
|
return "hello-world";
|
|
});
|
|
|
|
if (commandDisposable) {
|
|
ctx.subscriptions.push(commandDisposable);
|
|
ctx.logger.info("command registered", { commandId: COMMAND_ID });
|
|
} else {
|
|
ctx.logger.warn("command registry unavailable", { commandId: COMMAND_ID });
|
|
}
|
|
|
|
const layoutDisposable = ctx.layouts?.register({
|
|
type: LAYOUT_TYPE,
|
|
component: HelloWorldLayout
|
|
});
|
|
|
|
if (layoutDisposable) {
|
|
ctx.subscriptions.push(layoutDisposable);
|
|
ctx.logger.info("layout registered", {
|
|
layoutType: LAYOUT_TYPE,
|
|
component: "hello-world"
|
|
});
|
|
} else {
|
|
ctx.logger.warn("layout registry unavailable", { layoutType: LAYOUT_TYPE });
|
|
}
|
|
|
|
void useWorkspaceSdk(ctx);
|
|
}
|
|
|
|
async function useWorkspaceSdk(ctx: ActivateContext): Promise<void> {
|
|
const workspace = ctx.services?.workspace;
|
|
if (!workspace) return;
|
|
|
|
const project = await workspace.getCurrentProject();
|
|
if (!project) {
|
|
ctx.logger.info("workspace service available without a focused project");
|
|
return;
|
|
}
|
|
|
|
const fixturePath = ".ideai/hello-plugin.txt";
|
|
await workspace.writeTextFile(fixturePath, "hello from @idea/plugin-sdk\n", project.id);
|
|
const file = await workspace.readTextFile(fixturePath, project.id);
|
|
const stat = await workspace.stat(fixturePath, project.id);
|
|
const listing = await workspace.listDirectory(".ideai", project.id);
|
|
const structure = await workspace.queryStructure({
|
|
projectId: project.id,
|
|
maxDepth: 2,
|
|
maxEntries: 100
|
|
});
|
|
|
|
ctx.logger.info("workspace file round-trip complete", {
|
|
projectId: project.id,
|
|
path: file.path,
|
|
bytes: stat.len,
|
|
ideaiEntries: listing.entries.length,
|
|
conventions: structure.conventions.map((convention) => convention.id)
|
|
});
|
|
|
|
const diagnostic = await ctx.services?.tooling.diagnose({
|
|
projectId: project.id,
|
|
tools: [
|
|
{
|
|
id: "echo",
|
|
executable: "echo",
|
|
versionArgs: ["hello-plugin-toolcheck"],
|
|
required: true
|
|
}
|
|
],
|
|
env: [{ name: "PATH", required: true }],
|
|
files: [{ path: fixturePath, kind: "file" }]
|
|
});
|
|
|
|
ctx.logger.info("tooling diagnostic complete", {
|
|
ok: diagnostic?.ok,
|
|
echoVersion: diagnostic?.tools.find((tool) => tool.id === "echo")?.version,
|
|
messages: diagnostic?.messages
|
|
});
|
|
|
|
const configPath = ".ideai/hello-plugin.json";
|
|
await workspace.writeTextFile(
|
|
configPath,
|
|
JSON.stringify({ enabled: true, launches: 0 }, null, 2) + "\n",
|
|
project.id
|
|
);
|
|
const configDocument = await ctx.services?.config.readDocument({
|
|
projectId: project.id,
|
|
path: configPath
|
|
});
|
|
await ctx.services?.config.updateDocument({
|
|
projectId: project.id,
|
|
path: configPath,
|
|
mode: "mergePatch",
|
|
value: { lastFormat: configDocument?.format ?? "json", launches: 1 }
|
|
});
|
|
ctx.logger.info("config document updated", {
|
|
path: configDocument?.path,
|
|
format: configDocument?.format
|
|
});
|
|
|
|
const watch = await workspace.watch(".ideai", (event) => {
|
|
ctx.logger.info("workspace watch event", {
|
|
path: event.path,
|
|
kind: event.kind,
|
|
operation: event.operation
|
|
});
|
|
}, project.id);
|
|
ctx.subscriptions.push(watch);
|
|
|
|
const events = await ctx.services?.events.subscribe(
|
|
{
|
|
projectId: project.id,
|
|
eventTypes: ["backgroundTaskChanged"],
|
|
pollIntervalMs: 2000,
|
|
onDropped: (count) => ctx.logger.warn("plugin events dropped", { count })
|
|
},
|
|
(event) => {
|
|
if (event.type === "backgroundTaskChanged") {
|
|
ctx.logger.info("background task changed", {
|
|
taskId: event.taskId,
|
|
state: event.state
|
|
});
|
|
}
|
|
}
|
|
);
|
|
if (events) ctx.subscriptions.push(events);
|
|
|
|
const ownerAgentId = await ctx.storage?.get<string>("helloPlugin.ownerAgentId");
|
|
if (!ownerAgentId) {
|
|
ctx.logger.info("command task example skipped: no owner agent configured");
|
|
return;
|
|
}
|
|
|
|
const task = await ctx.services?.tasks.runCommand({
|
|
projectId: project.id,
|
|
ownerAgentId,
|
|
label: "Hello plugin command",
|
|
command: "echo",
|
|
args: ["hello from @idea/plugin-sdk"],
|
|
cwd: ".",
|
|
recordOnly: true
|
|
});
|
|
|
|
if (task) {
|
|
const status = await ctx.services?.tasks.getCommandStatus(task.taskId);
|
|
ctx.logger.info("command task launched", {
|
|
taskId: task.taskId,
|
|
state: status?.state ?? task.state,
|
|
exitCode: status?.exitCode ?? task.exitCode
|
|
});
|
|
}
|
|
}
|
|
|
|
const plugin: IdeAPluginModule = {
|
|
activate
|
|
};
|
|
|
|
export default plugin;
|