feat: enhance bootstrap hook with detailed logging and internal hook configuration

This commit is contained in:
Lauren ten Hoor
2026-02-16 15:43:53 +08:00
parent 6be920c31a
commit 1464fa82d2
2 changed files with 26 additions and 5 deletions

View File

@@ -106,10 +106,14 @@ export async function loadRoleInstructions(
export function registerBootstrapHook(api: OpenClawPluginApi): void {
api.registerHook("agent:bootstrap", async (event) => {
const sessionKey = event.sessionKey;
api.logger.debug(`Bootstrap hook fired: sessionKey=${sessionKey ?? "undefined"}, event keys=${Object.keys(event).join(",")}`);
if (!sessionKey) return;
const parsed = parseDevClawSessionKey(sessionKey);
if (!parsed) return;
if (!parsed) {
api.logger.debug(`Bootstrap hook: not a DevClaw session key: ${sessionKey}`);
return;
}
const context = event.context as {
workspaceDir?: string;
@@ -122,10 +126,16 @@ export function registerBootstrapHook(api: OpenClawPluginApi): void {
};
const workspaceDir = context.workspaceDir;
if (!workspaceDir || typeof workspaceDir !== "string") return;
if (!workspaceDir || typeof workspaceDir !== "string") {
api.logger.warn(`Bootstrap hook: no workspaceDir in context for ${sessionKey}`);
return;
}
const bootstrapFiles = context.bootstrapFiles;
if (!Array.isArray(bootstrapFiles)) return;
if (!Array.isArray(bootstrapFiles)) {
api.logger.warn(`Bootstrap hook: no bootstrapFiles array in context for ${sessionKey}`);
return;
}
const { content, source } = await loadRoleInstructions(
workspaceDir,
@@ -134,7 +144,10 @@ export function registerBootstrapHook(api: OpenClawPluginApi): void {
{ withSource: true },
);
if (!content) return;
if (!content) {
api.logger.warn(`Bootstrap hook: no content found for ${parsed.role} in project "${parsed.projectName}" (workspace: ${workspaceDir})`);
return;
}
// Inject as a virtual bootstrap file. OpenClaw includes these in the
// agent's system prompt automatically (via buildBootstrapContextFiles).
@@ -148,5 +161,5 @@ export function registerBootstrapHook(api: OpenClawPluginApi): void {
api.logger.info(
`Bootstrap hook: injected ${parsed.role} instructions for project "${parsed.projectName}" from ${source}`,
);
});
}, { name: "devclaw-worker-instructions", description: "Injects role-specific instructions into DevClaw worker sessions" } as any);
}

View File

@@ -35,6 +35,7 @@ export async function writePluginConfig(
// Clean up legacy models from openclaw.json (moved to workflow.yaml)
delete (config as any).plugins.entries.devclaw.config.models;
ensureInternalHooks(config);
ensureHeartbeatDefaults(config);
configureSubagentCleanup(config);
@@ -77,6 +78,13 @@ function addToolRestrictions(config: Record<string, unknown>, agentId: string):
}
}
function ensureInternalHooks(config: Record<string, unknown>): void {
if (!config.hooks) config.hooks = {};
const hooks = config.hooks as Record<string, unknown>;
if (!hooks.internal) hooks.internal = {};
(hooks.internal as Record<string, unknown>).enabled = true;
}
function ensureHeartbeatDefaults(config: Record<string, unknown>): void {
const devclaw = (config as any).plugins.entries.devclaw.config;
if (!devclaw.work_heartbeat) {