74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
import {
|
|
filterBootstrapFilesForSession,
|
|
loadExtraBootstrapFilesWithDiagnostics,
|
|
} from "../../../agents/workspace.js";
|
|
import { createSubsystemLogger } from "../../../logging/subsystem.js";
|
|
import { resolveHookConfig } from "../../config.js";
|
|
import { isAgentBootstrapEvent, type HookHandler } from "../../hooks.js";
|
|
|
|
const HOOK_KEY = "bootstrap-extra-files";
|
|
const log = createSubsystemLogger("bootstrap-extra-files");
|
|
|
|
function normalizeStringArray(value: unknown): string[] {
|
|
if (!Array.isArray(value)) {
|
|
return [];
|
|
}
|
|
return value.map((v) => (typeof v === "string" ? v.trim() : "")).filter(Boolean);
|
|
}
|
|
|
|
function resolveExtraBootstrapPatterns(hookConfig: Record<string, unknown>): string[] {
|
|
const fromPaths = normalizeStringArray(hookConfig.paths);
|
|
if (fromPaths.length > 0) {
|
|
return fromPaths;
|
|
}
|
|
const fromPatterns = normalizeStringArray(hookConfig.patterns);
|
|
if (fromPatterns.length > 0) {
|
|
return fromPatterns;
|
|
}
|
|
return normalizeStringArray(hookConfig.files);
|
|
}
|
|
|
|
const bootstrapExtraFilesHook: HookHandler = async (event) => {
|
|
if (!isAgentBootstrapEvent(event)) {
|
|
return;
|
|
}
|
|
|
|
const context = event.context;
|
|
const hookConfig = resolveHookConfig(context.cfg, HOOK_KEY);
|
|
if (!hookConfig || hookConfig.enabled === false) {
|
|
return;
|
|
}
|
|
|
|
const patterns = resolveExtraBootstrapPatterns(hookConfig as Record<string, unknown>);
|
|
if (patterns.length === 0) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const { files: extras, diagnostics } = await loadExtraBootstrapFilesWithDiagnostics(
|
|
context.workspaceDir,
|
|
patterns,
|
|
);
|
|
if (diagnostics.length > 0) {
|
|
log.debug("skipped extra bootstrap candidates", {
|
|
skipped: diagnostics.length,
|
|
reasons: diagnostics.reduce<Record<string, number>>((counts, item) => {
|
|
counts[item.reason] = (counts[item.reason] ?? 0) + 1;
|
|
return counts;
|
|
}, {}),
|
|
});
|
|
}
|
|
if (extras.length === 0) {
|
|
return;
|
|
}
|
|
context.bootstrapFiles = filterBootstrapFilesForSession(
|
|
[...context.bootstrapFiles, ...extras],
|
|
context.sessionKey,
|
|
);
|
|
} catch (err) {
|
|
log.warn(`failed: ${String(err)}`);
|
|
}
|
|
};
|
|
|
|
export default bootstrapExtraFilesHook;
|