4da48555ee
Handle OpenCode session events that carry the session ID under properties.info.id or properties.info.sessionID so background tasks and continuation hooks do not miss idle/error/delete events. Add regression coverage for nested session.idle events completing background tasks and waking continuation hooks.
81 lines
2.1 KiB
TypeScript
81 lines
2.1 KiB
TypeScript
import type { PluginInput } from "@opencode-ai/plugin";
|
|
|
|
import { createDynamicTruncator } from "../../shared/dynamic-truncator";
|
|
import { resolveSessionEventID } from "../../shared/event-session-id";
|
|
import { processFilePathForAgentsInjection } from "./injector";
|
|
import { clearInjectedPaths } from "./storage";
|
|
|
|
interface ToolExecuteInput {
|
|
tool: string;
|
|
sessionID: string;
|
|
callID: string;
|
|
}
|
|
|
|
interface ToolExecuteOutput {
|
|
title: string;
|
|
output: string;
|
|
metadata: unknown;
|
|
}
|
|
|
|
interface DirectoryAgentsInjectorHook {
|
|
"tool.execute.before"?: (input: ToolExecuteInput, output: { args: unknown }) => Promise<void>;
|
|
"tool.execute.after": (input: ToolExecuteInput, output: ToolExecuteOutput) => Promise<void>;
|
|
event: (input: EventInput) => Promise<void>;
|
|
}
|
|
|
|
interface EventInput {
|
|
event: {
|
|
type: string;
|
|
properties?: unknown;
|
|
};
|
|
}
|
|
|
|
export function createDirectoryAgentsInjectorHook(
|
|
ctx: PluginInput,
|
|
modelCacheState?: { anthropicContext1MEnabled: boolean },
|
|
): DirectoryAgentsInjectorHook {
|
|
const sessionCaches = new Map<string, Set<string>>();
|
|
const truncator = createDynamicTruncator(ctx, modelCacheState);
|
|
|
|
const toolExecuteAfter = async (input: ToolExecuteInput, output: ToolExecuteOutput) => {
|
|
const toolName = input.tool.toLowerCase();
|
|
|
|
if (toolName === "read") {
|
|
await processFilePathForAgentsInjection({
|
|
ctx,
|
|
truncator,
|
|
sessionCaches,
|
|
filePath: output.title,
|
|
sessionID: input.sessionID,
|
|
output,
|
|
});
|
|
return;
|
|
}
|
|
};
|
|
|
|
const eventHandler = async ({ event }: EventInput) => {
|
|
const props = event.properties as Record<string, unknown> | undefined;
|
|
|
|
if (event.type === "session.deleted") {
|
|
const sessionID = resolveSessionEventID(props);
|
|
if (sessionID) {
|
|
sessionCaches.delete(sessionID);
|
|
clearInjectedPaths(sessionID);
|
|
}
|
|
}
|
|
|
|
if (event.type === "session.compacted") {
|
|
const sessionID = resolveSessionEventID(props);
|
|
if (sessionID) {
|
|
sessionCaches.delete(sessionID);
|
|
clearInjectedPaths(sessionID);
|
|
}
|
|
}
|
|
};
|
|
|
|
return {
|
|
"tool.execute.after": toolExecuteAfter,
|
|
event: eventHandler,
|
|
};
|
|
}
|