diff --git a/src/auto-reply/reply/commands-compact.ts b/src/auto-reply/reply/commands-compact.ts index ad2756a3bc9..6866a994afa 100644 --- a/src/auto-reply/reply/commands-compact.ts +++ b/src/auto-reply/reply/commands-compact.ts @@ -70,6 +70,8 @@ export const handleCompactCommand: CommandHandler = async (params) => { await waitForEmbeddedPiRunEnd(sessionId, 15_000); } + const thinkLevel = params.resolvedThinkLevel ?? (await params.resolveDefaultThinkingLevel()); + const learnResult = await runLearnForSession({ sessionId, sessionKey: params.sessionKey, @@ -92,13 +94,15 @@ export const handleCompactCommand: CommandHandler = async (params) => { skillsSnapshot: params.sessionEntry.skillsSnapshot, provider: params.provider, model: params.model, - thinkLevel: params.resolvedThinkLevel ?? (await params.resolveDefaultThinkingLevel()), + thinkLevel, customFocus: "What insights and lessons should be remembered before context compaction?", senderIsOwner: params.command.senderIsOwner, ownerNumbers: params.command.ownerList.length > 0 ? params.command.ownerList : undefined, }); if (learnResult.ok) { logVerbose(`Pre-compaction learning completed for session ${params.sessionKey}`); + } else { + logVerbose(`Pre-compaction learning failed for session ${params.sessionKey}: ${learnResult.message ?? "unknown error"}`); } const customInstructions = extractCompactInstructions({ @@ -130,7 +134,7 @@ export const handleCompactCommand: CommandHandler = async (params) => { skillsSnapshot: params.sessionEntry.skillsSnapshot, provider: params.provider, model: params.model, - thinkLevel: params.resolvedThinkLevel ?? (await params.resolveDefaultThinkingLevel()), + thinkLevel, bashElevated: { enabled: false, allowed: false, diff --git a/src/auto-reply/reply/commands-core.ts b/src/auto-reply/reply/commands-core.ts index a42bd7018b0..a16e7be2be6 100644 --- a/src/auto-reply/reply/commands-core.ts +++ b/src/auto-reply/reply/commands-core.ts @@ -13,7 +13,7 @@ import { handleApproveCommand } from "./commands-approve.js"; import { handleBashCommand } from "./commands-bash.js"; import { handleCompactCommand } from "./commands-compact.js"; import { handleConfigCommand, handleDebugCommand } from "./commands-config.js"; -import { handleLearnCommand } from "./commands-learn.js"; +import { handleLearnCommand, runLearnForSession } from "./commands-learn.js"; import { handleCommandsListCommand, handleContextCommand, @@ -41,7 +41,6 @@ import type { HandleCommandsParams, } from "./commands-types.js"; import { routeReply } from "./route-reply.js"; -import { runLearnForSession } from "./commands-learn.js"; import { resolveSessionFilePath, resolveSessionFilePathOptions, @@ -213,40 +212,6 @@ export async function handleCommands(params: HandleCommandsParams): Promise 0 ? params.command.ownerList : undefined, - }); - if (learnResult.ok) { - logVerbose(`Pre-reset learning completed for session ${params.sessionKey}`); - } - } - // Trigger internal hook for reset/new commands if (resetRequested && params.command.isAuthorizedSender) { const commandAction: ResetCommandAction = resetMatch?.[1] === "reset" ? "reset" : "new"; @@ -259,6 +224,48 @@ export async function handleCommands(params: HandleCommandsParams): Promise 0 ? params.command.ownerList : undefined, + }); + if (learnResult.ok) { + logVerbose(`Pre-reset learning completed for session ${targetSessionKey}`); + } else { + logVerbose(`Pre-reset learning failed for session ${targetSessionKey}: ${learnResult.message ?? "unknown error"}`); + } + } if (boundAcpKey) { const resetResult = await resetAcpSessionInPlace({ cfg: params.cfg, diff --git a/src/auto-reply/reply/commands-learn.ts b/src/auto-reply/reply/commands-learn.ts index 4d200b91abc..6ae3e9b0cd8 100644 --- a/src/auto-reply/reply/commands-learn.ts +++ b/src/auto-reply/reply/commands-learn.ts @@ -1,4 +1,4 @@ -import { compactEmbeddedPiSession } from "../../agents/pi-embedded.js"; +import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js"; import type { OpenClawConfig } from "../../config/config.js"; import { resolveSessionFilePath, @@ -16,14 +16,8 @@ const LEARN_DEFAULT_PROMPT = [ "What important insights, lessons, or information should be remembered from this session?", ].join(" "); -function extractLearnFocus(params: { - rawBody?: string; - ctx: import("../templating.js").MsgContext; - cfg: OpenClawConfig; - agentId?: string; - isGroup: boolean; -}): string | undefined { - const trimmed = params.rawBody?.trim() ?? ""; +function extractLearnFocus(rawBody?: string): string | undefined { + const trimmed = rawBody?.trim() ?? ""; if (!trimmed) { return undefined; } @@ -59,42 +53,50 @@ export async function runLearnForSession(params: { senderIsOwner: boolean; ownerNumbers?: string[]; }): Promise<{ ok: boolean; message?: string }> { - const customInstructions = params.customFocus + const prompt = params.customFocus ? `Focus area: ${params.customFocus}. ${LEARN_DEFAULT_PROMPT}` : LEARN_DEFAULT_PROMPT; - const result = await compactEmbeddedPiSession({ - sessionId: params.sessionId, - sessionKey: params.sessionKey, - messageChannel: params.messageChannel, - groupId: params.groupId, - groupChannel: params.groupChannel, - groupSpace: params.groupSpace, - spawnedBy: params.spawnedBy, - sessionFile: params.sessionFile, - workspaceDir: params.workspaceDir, - agentDir: params.agentDir, - config: params.config, - skillsSnapshot: params.skillsSnapshot, - provider: params.provider, - model: params.model, - thinkLevel: params.thinkLevel ?? "medium", - bashElevated: { - enabled: false, - allowed: false, - defaultLevel: "off", - }, - customInstructions, - extraSystemPrompt: LEARN_SYSTEM_PROMPT, - trigger: "manual", - senderIsOwner: params.senderIsOwner, - ownerNumbers: params.ownerNumbers, - }); + const sessionFilePath = resolveSessionFilePath( + params.sessionId, + { sessionId: params.sessionId, sessionFile: params.sessionFile }, + resolveSessionFilePathOptions({ agentId: undefined, storePath: undefined }), + ); + + try { + await runEmbeddedPiAgent({ + sessionId: params.sessionId, + sessionKey: params.sessionKey, + sessionFile: sessionFilePath, + messageChannel: params.messageChannel, + groupId: params.groupId, + groupChannel: params.groupChannel, + groupSpace: params.groupSpace, + spawnedBy: params.spawnedBy, + workspaceDir: params.workspaceDir, + agentDir: params.agentDir, + config: params.config, + skillsSnapshot: params.skillsSnapshot, + provider: params.provider, + model: params.model, + thinkLevel: params.thinkLevel ?? "medium", + bashElevated: { + enabled: false, + allowed: false, + defaultLevel: "off", + }, + prompt, + extraSystemPrompt: LEARN_SYSTEM_PROMPT, + trigger: "memory", + senderIsOwner: params.senderIsOwner, + ownerNumbers: params.ownerNumbers, + }); - if (result.ok) { return { ok: true, message: "Learning completed. Insights saved to memory." }; + } catch (err) { + logVerbose(`Learning failed for session ${params.sessionKey}: ${String(err)}`); + return { ok: false, message: String(err) }; } - return { ok: false, message: result.reason ?? "Learning failed" }; } export const handleLearnCommand = async ( @@ -123,13 +125,7 @@ export const handleLearnCommand = async ( } const sessionId = params.sessionEntry.sessionId; - const customFocus = extractLearnFocus({ - rawBody: params.ctx.CommandBody ?? params.ctx.RawBody ?? params.ctx.Body, - ctx: params.ctx, - cfg: params.cfg, - agentId: params.agentId, - isGroup: params.isGroup, - }); + const customFocus = extractLearnFocus(params.ctx.CommandBody ?? params.ctx.RawBody ?? params.ctx.Body); const result = await runLearnForSession({ sessionId,