import type { CanonicalMessage } from "../../model/index.js";
import { HookRuntime } from "../../extension/hooks/execution/HookRuntime.js";
import { createHookInput } from "../../extension/hooks/protocol/input.js";
import type { LifecycleDispatchInput, LifecycleDispatchResult } from "../protocol/payloads.js";
import { emptyLifecycleDispatchResult } from "../protocol/payloads.js";
export class LifecycleRuntime {
constructor(private readonly hooks = new HookRuntime()) {}
async dispatch(input: LifecycleDispatchInput): Promise<LifecycleDispatchResult> {
const hookInput = createHookInput(input.event, input.baseInput, input.payload);
const hookResult = await this.hooks.run({
event: input.event,
hookInput,
matchQuery: input.matchQuery,
cwd: input.baseInput.cwd,
env: input.env,
signal: input.signal,
});
return {
effects: hookResult.effects,
messages: createMessagesFromEffects(hookResult.effects),
events: hookResult.events,
blockingErrors: hookResult.blockingErrors,
nonBlockingErrors: hookResult.nonBlockingErrors,
};
}
}
export class NullLifecycleRuntime extends LifecycleRuntime {
constructor() {
super(new HookRuntime({}));
}
override async dispatch(): Promise<LifecycleDispatchResult> {
return emptyLifecycleDispatchResult();
}
}
function createMessagesFromEffects(effects: LifecycleDispatchResult["effects"]): CanonicalMessage[] {
const messages: CanonicalMessage[] = [];
for (const effect of effects) {
if (effect.type === "additional_context") {
messages.push({
role: "user",
content: [
{
type: "text",
text: `<hook_context source="${effect.source}">\n${effect.content}\n</hook_context>`,
},
],
});
}
}
return messages;
}