


























@@ -18,8 +18,7 @@ import {
1818resolveMainSessionKey,
1919} from "../config/sessions/main-session.js";
2020import { resolveStorePath } from "../config/sessions/paths.js";
21-import { loadSessionStore, updateSessionStore } from "../config/sessions/store.js";
22-import type { SessionEntry } from "../config/sessions/types.js";
21+import { preserveTemporarySessionMapping } from "../config/sessions/session-accessor.js";
2322import type { OpenClawConfig } from "../config/types.openclaw.js";
2423import { formatErrorMessage } from "../infra/errors.js";
2524import { createSubsystemLogger } from "../logging/subsystem.js";
@@ -33,14 +32,6 @@ function generateBootSessionId(): string {
3332return `boot-${ts}-${suffix}`;
3433}
353436-type SessionMappingSnapshot = {
37-storePath: string;
38-sessionKey: string;
39-canRestore: boolean;
40-hadEntry: boolean;
41-entry?: SessionEntry;
42-};
43-4435const log = createSubsystemLogger("gateway/boot");
4536const BOOT_FILENAME = "BOOT.md";
4637@@ -101,68 +92,6 @@ async function loadBootFile(
10192}
10293}
10394104-function snapshotSessionMapping(params: {
105-cfg: OpenClawConfig;
106-sessionKey: string;
107-}): SessionMappingSnapshot {
108-const agentId = resolveAgentIdFromSessionKey(params.sessionKey);
109-const storePath = resolveStorePath(params.cfg.session?.store, { agentId });
110-try {
111-const store = loadSessionStore(storePath, { skipCache: true });
112-const entry = store[params.sessionKey];
113-if (!entry) {
114-return {
115- storePath,
116-sessionKey: params.sessionKey,
117-canRestore: true,
118-hadEntry: false,
119-};
120-}
121-return {
122- storePath,
123-sessionKey: params.sessionKey,
124-canRestore: true,
125-hadEntry: true,
126-entry: structuredClone(entry),
127-};
128-} catch (err) {
129-log.debug("boot: could not snapshot session mapping", {
130-sessionKey: params.sessionKey,
131-error: String(err),
132-});
133-return {
134- storePath,
135-sessionKey: params.sessionKey,
136-canRestore: false,
137-hadEntry: false,
138-};
139-}
140-}
141-142-async function restoreSessionMapping(
143-snapshot: SessionMappingSnapshot,
144-): Promise<string | undefined> {
145-if (!snapshot.canRestore) {
146-return undefined;
147-}
148-try {
149-await updateSessionStore(
150-snapshot.storePath,
151-(store) => {
152-if (snapshot.hadEntry && snapshot.entry) {
153-store[snapshot.sessionKey] = snapshot.entry;
154-return;
155-}
156-delete store[snapshot.sessionKey];
157-},
158-{ activeSessionKey: snapshot.sessionKey },
159-);
160-return undefined;
161-} catch (err) {
162-return formatErrorMessage(err);
163-}
164-}
165-16695export async function runBootOnce(params: {
16796cfg: OpenClawConfig;
16897deps: CliDeps;
@@ -193,39 +122,49 @@ export async function runBootOnce(params: {
193122const sessionKey = resolveBootSessionKey(mainSessionKey);
194123const message = buildBootPrompt(result.content ?? "");
195124const sessionId = generateBootSessionId();
196-const mappingSnapshot = snapshotSessionMapping({
197-cfg: params.cfg,
198- sessionKey,
199-});
125+const agentId = resolveAgentIdFromSessionKey(sessionKey);
126+const storePath = resolveStorePath(params.cfg.session?.store, { agentId });
200127201-// Register the boot prompt for the message-tool echo guard so the
202-// tool layer can drop fallback-model echoes that copy substantial
203-// BOOT.md content without preserving the wrapper markers above.
204-// Always cleared in finally so a failed run does not leave a stale
205-// entry that mis-fires on an unrelated subsequent run reusing the
206-// same session key. Refs #53732.
207-setBootEchoContextForSession(sessionKey, message);
208-let agentFailure: string | undefined;
209-try {
210-await agentCommand(
211-{
212- message,
213- sessionKey,
214- sessionId,
215-deliver: false,
216-suppressPromptPersistence: true,
217-},
218-bootRuntime,
219-params.deps,
220-);
221-} catch (err) {
222-agentFailure = formatErrorMessage(err);
223-log.error(`boot: agent run failed: ${agentFailure}`);
224-} finally {
225-clearBootEchoContextForSession(sessionKey);
128+const mappingPreservation = await preserveTemporarySessionMapping(
129+{ storePath, sessionKey },
130+async () => {
131+// Register the boot prompt for the message-tool echo guard so the
132+// tool layer can drop fallback-model echoes that copy substantial
133+// BOOT.md content without preserving the wrapper markers above.
134+// Always cleared in finally so a failed run does not leave a stale
135+// entry that mis-fires on an unrelated subsequent run reusing the
136+// same session key. Refs #53732.
137+setBootEchoContextForSession(sessionKey, message);
138+try {
139+await agentCommand(
140+{
141+ message,
142+ sessionKey,
143+ sessionId,
144+deliver: false,
145+suppressPromptPersistence: true,
146+},
147+bootRuntime,
148+params.deps,
149+);
150+return undefined;
151+} catch (err) {
152+const failure = formatErrorMessage(err);
153+log.error(`boot: agent run failed: ${failure}`);
154+return failure;
155+} finally {
156+clearBootEchoContextForSession(sessionKey);
157+}
158+},
159+);
160+const agentFailure = mappingPreservation.result;
161+if (mappingPreservation.snapshotFailure) {
162+log.debug("boot: could not snapshot session mapping", {
163+ sessionKey,
164+error: mappingPreservation.snapshotFailure,
165+});
226166}
227-228-const mappingRestoreFailure = await restoreSessionMapping(mappingSnapshot);
167+const mappingRestoreFailure = mappingPreservation.restoreFailure;
229168if (mappingRestoreFailure) {
230169log.error(`boot: failed to restore session mapping: ${mappingRestoreFailure}`);
231170}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。