fix(kiroide): adopt workspace v1 hooks

This commit is contained in:
ZacharyZhang-NY committed 2026-07-20 16:58:49 -04:00
1 parent 3cfd0a5187
commit 5889b09a09
11 files changed
+1535 -74

No files matched your search

+52 -73
View File
@@ -1,94 +1,73 @@
import fsp from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
import type { AgentPlugin, InstallConfig, PluginStatus } from './base.js';
import {
AGENT_KEY,
buildKiroIdeHook,
kiroIdeRuntimeContracts,
renderKiroIdeDocument,
requireAvailableKiroIdeHooks,
withoutManagedKiroIdeHooks,
} from './kiroide-contract.js';
import {
commitKiroIdeInstallation,
commitKiroIdeUninstall,
preflightKiroIdeInstallation,
prepareKiroIdeInstallation,
prepareKiroIdeUninstall,
} from './kiroide-installation.js';
import { readKiroIdeSources, runtimeFilesExist } from './kiroide-io.js';
import { SUPPORTED_AGENTS } from './registry.js';
const AGENT_KEY = 'kiroide';
const entry = SUPPORTED_AGENTS.get(AGENT_KEY)!;
function resolveConfigDir(): string {
// .kiro/hooks is project-relative, but for global install use home dir
return path.join(os.homedir(), entry.configDir);
}
function resolveConfigPath(): string {
return path.join(resolveConfigDir(), entry.configFile);
}
export const kiroidePlugin: AgentPlugin = {
async install(config: InstallConfig): Promise<void> {
const configDir = resolveConfigDir();
await fsp.mkdir(configDir, { recursive: true });
managesRuntime: true,
const configPath = resolveConfigPath();
const hookConfig = {
name: 'Elydora Audit',
description: 'Sends tool-use events to the Elydora tamper-evident audit platform',
version: '1.0.0',
hooks: {
pre_tool_use: {
command: `node "${config.guardScriptPath}"`,
timeout_ms: 5000,
},
post_tool_use: {
command: `node "${config.hookScriptPath}"`,
timeout_ms: 5000,
},
},
};
await fsp.writeFile(configPath, JSON.stringify(hookConfig, null, 2) + '\n', 'utf-8');
async preflightInstall(config: InstallConfig): Promise<void> {
const sources = await readKiroIdeSources();
requireAvailableKiroIdeHooks(sources.document.hooks);
await preflightKiroIdeInstallation(config, sources.paths);
},
async uninstall(_agentId?: string): Promise<void> {
const configPath = resolveConfigPath();
try {
await fsp.unlink(configPath);
} catch {
// Already removed
}
async install(config: InstallConfig): Promise<void> {
const sources = await readKiroIdeSources();
requireAvailableKiroIdeHooks(sources.document.hooks);
const paths = await preflightKiroIdeInstallation(config, sources.paths);
const hooks = withoutManagedKiroIdeHooks(sources.document.hooks);
const rendered = renderKiroIdeDocument(sources.document, [
...hooks,
buildKiroIdeHook('elydora-guard', paths.guardPath),
buildKiroIdeHook('elydora-audit', paths.auditPath),
]);
const prepared = await prepareKiroIdeInstallation(config, sources, rendered);
await commitKiroIdeInstallation(prepared);
console.log(` Kiro IDE workspace hooks: ${sources.paths.configPath}`);
console.log(' Kiro IDE verification: confirm Elydora hooks in the Agent Hooks panel.');
},
async uninstall(agentId?: string): Promise<void> {
const sources = await readKiroIdeSources();
const rendered = renderKiroIdeDocument(
sources.document,
withoutManagedKiroIdeHooks(sources.document.hooks, agentId),
);
const prepared = await prepareKiroIdeUninstall(sources, rendered, agentId);
await commitKiroIdeUninstall(prepared);
},
async status(): Promise<PluginStatus> {
const configPath = resolveConfigPath();
let hookConfigured = false;
let hookScriptPath = '';
try {
const raw = await fsp.readFile(configPath, 'utf-8');
const config = JSON.parse(raw);
hookConfigured = !!(config.hooks && config.hooks.pre_tool_use && config.hooks.post_tool_use);
// Extract hook script path from post_tool_use command
if (hookConfigured && config.hooks.post_tool_use) {
const cmd = config.hooks.post_tool_use.command as string;
if (cmd && cmd.includes('elydora')) {
hookScriptPath = cmd.replace(/^node\s+"?/, '').replace(/"?\s*$/, '');
}
}
} catch {
// Config not readable
}
let hookScriptExists = false;
if (hookScriptPath) {
try {
await fsp.access(hookScriptPath);
hookScriptExists = true;
} catch {
// File doesn't exist
}
}
const sources = await readKiroIdeSources();
requireAvailableKiroIdeHooks(sources.document.hooks);
const contracts = kiroIdeRuntimeContracts(sources.document.hooks);
const hookConfigured = contracts.length > 0;
const hookScriptExists = hookConfigured
&& (await Promise.all(contracts.map(runtimeFilesExist))).every(Boolean);
return {
installed: hookConfigured && hookScriptExists,
agentName: AGENT_KEY,
displayName: entry.name,
hookConfigured,
hookScriptExists,
configPath,
configPath: sources.paths.configPath,
};
},
};