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 { 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("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;