@evo-dev/evodev 0.0.1-alpha.5 → 0.0.1-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.claude-plugin/marketplace.json +2 -2
- package/dist/index.js +2222 -2369
- package/dist/plugins/evodev/.claude-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/.codex-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/hooks/hooks.ts +55 -2
- package/dist/plugins/evodev/hooks/runtime.ts +7 -1
- package/dist/plugins/evodev/package.json +1 -1
- package/dist/ui/app.js +9 -9
- package/dist/ui/styles.css +2 -1507
- package/package.json +1 -1
- package/dist/.agents/skills/evodev-release/SKILL.md +0 -183
- package/dist/.agents/skills/grilling/SKILL.md +0 -10
|
@@ -158,7 +158,7 @@ export function planClaudeHookInstallDryRun(
|
|
|
158
158
|
action: "merge-with-backup",
|
|
159
159
|
targetPath: paths.settingsPath,
|
|
160
160
|
reason:
|
|
161
|
-
"would
|
|
161
|
+
"would reconcile EvoDev-managed user-level hook entries with Claude plugin ownership without touching user-owned hooks",
|
|
162
162
|
},
|
|
163
163
|
],
|
|
164
164
|
warnings: ["Project .claude, .codex, CLAUDE.md, and AGENTS.md are not targeted."],
|
|
@@ -191,12 +191,34 @@ export async function installClaudeHooks(input: {
|
|
|
191
191
|
paths?: ClaudePaths;
|
|
192
192
|
now?: string;
|
|
193
193
|
pluginSelector?: string;
|
|
194
|
+
pluginManaged?: boolean;
|
|
194
195
|
}): Promise<HookInstallResult> {
|
|
195
196
|
const paths = input.paths ?? resolveClaudePaths({ homeDir: input.homeDir });
|
|
196
197
|
const existing = await readTextIfExists(paths.settingsPath);
|
|
198
|
+
const pluginSelector = input.pluginSelector ?? DEFAULT_CLAUDE_PLUGIN_SELECTOR;
|
|
199
|
+
if (input.pluginManaged === true || isClaudePluginEnabled(existing, pluginSelector)) {
|
|
200
|
+
const next = removeClaudeManagedUserHooks(existing);
|
|
201
|
+
if (next === null) {
|
|
202
|
+
return {
|
|
203
|
+
target: "claude",
|
|
204
|
+
targetPath: paths.settingsPath,
|
|
205
|
+
backupPath: null,
|
|
206
|
+
changed: false,
|
|
207
|
+
warnings: [],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return writeMergedConfig({
|
|
211
|
+
target: "claude",
|
|
212
|
+
path: paths.settingsPath,
|
|
213
|
+
existing,
|
|
214
|
+
next,
|
|
215
|
+
now: input.now,
|
|
216
|
+
warnings: [],
|
|
217
|
+
});
|
|
218
|
+
}
|
|
197
219
|
const runtimeCommand = await resolveClaudeUserHookRuntimeCommand({
|
|
198
220
|
paths,
|
|
199
|
-
pluginSelector
|
|
221
|
+
pluginSelector,
|
|
200
222
|
});
|
|
201
223
|
const next = mergeClaudeSettingsHooks(existing, createClaudeHookConfig(runtimeCommand).hooks);
|
|
202
224
|
return writeMergedConfig({
|
|
@@ -497,6 +519,37 @@ function mergeClaudeSettingsHooks(
|
|
|
497
519
|
return `${JSON.stringify({ ...settings, hooks: nextHooks }, null, 2)}\n`;
|
|
498
520
|
}
|
|
499
521
|
|
|
522
|
+
function isClaudePluginEnabled(existing: string | null, pluginSelector: string): boolean {
|
|
523
|
+
if (existing === null) return false;
|
|
524
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
525
|
+
const enabledPlugins = isRecord(settings.enabledPlugins) ? settings.enabledPlugins : {};
|
|
526
|
+
return enabledPlugins[pluginSelector] === true;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function removeClaudeManagedUserHooks(existing: string | null): string | null {
|
|
530
|
+
if (existing === null) return null;
|
|
531
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
532
|
+
if (!isRecord(settings.hooks)) return existing;
|
|
533
|
+
|
|
534
|
+
const nextHooks: Record<string, unknown> = {};
|
|
535
|
+
let changed = false;
|
|
536
|
+
for (const [eventName, groups] of Object.entries(settings.hooks)) {
|
|
537
|
+
if (!Array.isArray(groups)) {
|
|
538
|
+
nextHooks[eventName] = groups;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
const retained = groups.filter((group) => !isEvoDevHookGroup(group, "claude"));
|
|
542
|
+
changed ||= retained.length !== groups.length;
|
|
543
|
+
if (retained.length > 0 || groups.length === 0) nextHooks[eventName] = retained;
|
|
544
|
+
}
|
|
545
|
+
if (!changed) return existing;
|
|
546
|
+
|
|
547
|
+
const nextSettings = { ...settings };
|
|
548
|
+
if (Object.keys(nextHooks).length === 0) nextSettings.hooks = undefined;
|
|
549
|
+
else nextSettings.hooks = nextHooks;
|
|
550
|
+
return `${JSON.stringify(nextSettings, null, 2)}\n`;
|
|
551
|
+
}
|
|
552
|
+
|
|
500
553
|
function parseJsonConfig(existing: string | null, label: string): Record<string, unknown> {
|
|
501
554
|
if (existing === null || existing.trim() === "") return {};
|
|
502
555
|
const parsed = JSON.parse(existing) as unknown;
|
|
@@ -184,6 +184,12 @@ async function appendExecutionEventSafely(input: {
|
|
|
184
184
|
environment: input.environment,
|
|
185
185
|
payload: input.payload,
|
|
186
186
|
});
|
|
187
|
+
const cwd =
|
|
188
|
+
input.payload !== null && typeof input.payload.cwd === "string" ? input.payload.cwd : null;
|
|
189
|
+
const workspace =
|
|
190
|
+
team === null && cwd !== null
|
|
191
|
+
? await input.core.resolveProjectWorkspaceFromCwd({ homeDir: input.homeDir, cwd })
|
|
192
|
+
: null;
|
|
187
193
|
const traceRefId = await recordTraceRefSafely(input);
|
|
188
194
|
await input.core.appendEvoDevExecutionEvent(
|
|
189
195
|
input.homeDir,
|
|
@@ -192,7 +198,7 @@ async function appendExecutionEventSafely(input: {
|
|
|
192
198
|
target: input.target,
|
|
193
199
|
eventType: input.event?.type ?? runtimePhaseEventType(input.phase),
|
|
194
200
|
sessionKey,
|
|
195
|
-
projectKey: team?.projectKey ?? null,
|
|
201
|
+
projectKey: team?.projectKey ?? workspace?.projectKey ?? null,
|
|
196
202
|
runId: team?.runId ?? null,
|
|
197
203
|
roleId: team?.roleId ?? null,
|
|
198
204
|
taskId: input.event?.scope.taskId ?? null,
|