import type { OpenClawConfig } from "../config/config.js"; import { getOrLoadBootstrapFiles } from "./bootstrap-cache.js"; import { applyBootstrapHookOverrides } from "./bootstrap-hooks.js"; import type { EmbeddedContextFile } from "./pi-embedded-helpers.js"; import { buildBootstrapContextFiles, resolveBootstrapMaxChars, resolveBootstrapTotalMaxChars, } from "./pi-embedded-helpers.js"; import { filterBootstrapFilesForSession, loadWorkspaceBootstrapFiles, type WorkspaceBootstrapFile, } from "./workspace.js"; export function makeBootstrapWarn(params: { sessionLabel: string; warn?: (message: string) => void; }): ((message: string) => void) | undefined { if (!params.warn) { return undefined; } return (message: string) => params.warn?.(`${message} (sessionKey=${params.sessionLabel})`); } function sanitizeBootstrapFiles( files: WorkspaceBootstrapFile[], warn?: (message: string) => void, ): WorkspaceBootstrapFile[] { const sanitized: WorkspaceBootstrapFile[] = []; for (const file of files) { const pathValue = typeof file.path === "string" ? file.path.trim() : ""; if (!pathValue) { warn?.( `skipping bootstrap file "${file.name}" — missing or invalid "path" field (hook may have used "filePath" instead)`, ); continue; } sanitized.push({ ...file, path: pathValue }); } return sanitized; } export async function resolveBootstrapFilesForRun(params: { workspaceDir: string; config?: OpenClawConfig; sessionKey?: string; sessionId?: string; agentId?: string; warn?: (message: string) => void; }): Promise { const sessionKey = params.sessionKey ?? params.sessionId; const rawFiles = params.sessionKey ? await getOrLoadBootstrapFiles({ workspaceDir: params.workspaceDir, sessionKey: params.sessionKey, }) : await loadWorkspaceBootstrapFiles(params.workspaceDir); const bootstrapFiles = filterBootstrapFilesForSession(rawFiles, sessionKey); const updated = await applyBootstrapHookOverrides({ files: bootstrapFiles, workspaceDir: params.workspaceDir, config: params.config, sessionKey: params.sessionKey, sessionId: params.sessionId, agentId: params.agentId, }); return sanitizeBootstrapFiles(updated, params.warn); } export async function resolveBootstrapContextForRun(params: { workspaceDir: string; config?: OpenClawConfig; sessionKey?: string; sessionId?: string; agentId?: string; warn?: (message: string) => void; }): Promise<{ bootstrapFiles: WorkspaceBootstrapFile[]; contextFiles: EmbeddedContextFile[]; }> { const bootstrapFiles = await resolveBootstrapFilesForRun(params); const contextFiles = buildBootstrapContextFiles(bootstrapFiles, { maxChars: resolveBootstrapMaxChars(params.config), totalMaxChars: resolveBootstrapTotalMaxChars(params.config), warn: params.warn, }); return { bootstrapFiles, contextFiles }; }