























@@ -56,7 +56,11 @@ import {
5656} from "../routing/session-key.js";
5757import { normalizeSessionKeyPreservingOpaquePeerIds } from "../sessions/session-key-utils.js";
5858import type { DB as OpenClawStateKyselyDatabase } from "../state/openclaw-state-db.generated.js";
59-import { runOpenClawStateWriteTransaction } from "../state/openclaw-state-db.js";
59+import {
60+detectOpenClawStateDatabaseSchemaMigrations,
61+repairOpenClawStateDatabaseSchema,
62+runOpenClawStateWriteTransaction,
63+} from "../state/openclaw-state-db.js";
6064import { expandHomePrefix } from "./home-dir.js";
6165import {
6266executeSqliteQuerySync,
@@ -110,6 +114,10 @@ export type LegacyStateDetection = {
110114sourcePath: string;
111115hasLegacy: boolean;
112116};
117+stateSchema: {
118+hasLegacy: boolean;
119+preview: string[];
120+};
113121taskStateSidecars: {
114122taskRunsPath: string;
115123flowRunsPath: string;
@@ -2627,6 +2635,9 @@ export async function detectLegacyStateMigrations(params: {
26272635const hasPluginStateSidecar = fileExists(pluginStateSidecarPath);
26282636const pluginInstallIndexPath = resolveLegacyInstalledPluginIndexStorePath({ stateDir });
26292637const hasPluginInstallIndex = fileExists(pluginInstallIndexPath);
2638+const stateSchemaMigrations = detectOpenClawStateDatabaseSchemaMigrations({
2639+env: { ...env, OPENCLAW_STATE_DIR: stateDir },
2640+});
26302641const taskRunsSidecarPath = resolveLegacyTaskRunsSidecarPath(stateDir);
26312642const flowRunsSidecarPath = resolveLegacyFlowRunsSidecarPath(stateDir);
26322643const hasTaskStateSidecars = fileExists(taskRunsSidecarPath) || fileExists(flowRunsSidecarPath);
@@ -2645,12 +2656,15 @@ export async function detectLegacyStateMigrations(params: {
26452656 stateDir,
26462657 oauthDir,
26472658});
2648-const pluginPlans = await collectPluginDoctorStateMigrationPlans({
2649-cfg: params.cfg,
2650- env,
2651- stateDir,
2652- oauthDir,
2653-});
2659+const pluginPlans =
2660+stateSchemaMigrations.length > 0
2661+ ? []
2662+ : await collectPluginDoctorStateMigrationPlans({
2663+cfg: params.cfg,
2664+ env,
2665+ stateDir,
2666+ oauthDir,
2667+});
2654266826552669const preview: string[] = [];
26562670if (hasLegacySessions) {
@@ -2668,6 +2682,12 @@ export async function detectLegacyStateMigrations(params: {
26682682if (hasPluginInstallIndex) {
26692683preview.push(`- Plugin install index: ${pluginInstallIndexPath} → shared SQLite state`);
26702684}
2685+if (stateSchemaMigrations.length > 0) {
2686+preview.push("- Shared SQLite schema: agent database registry primary key → agent_id,path");
2687+preview.push(
2688+"- Rerun doctor after shared SQLite schema repair to detect plugin state migrations",
2689+);
2690+}
26712691if (fileExists(taskRunsSidecarPath)) {
26722692preview.push(`- Task registry sidecar: ${taskRunsSidecarPath} → shared SQLite state`);
26732693}
@@ -2719,6 +2739,10 @@ export async function detectLegacyStateMigrations(params: {
27192739sourcePath: pluginInstallIndexPath,
27202740hasLegacy: hasPluginInstallIndex,
27212741},
2742+stateSchema: {
2743+hasLegacy: stateSchemaMigrations.length > 0,
2744+preview: stateSchemaMigrations.map((migration) => migration.path),
2745+},
27222746taskStateSidecars: {
27232747taskRunsPath: taskRunsSidecarPath,
27242748flowRunsPath: flowRunsSidecarPath,
@@ -2969,6 +2993,15 @@ async function runPluginDoctorStateMigrationPlans(params: {
29692993return { changes, warnings };
29702994}
297129952996+function migrateLegacyStateSchema(detected: LegacyStateDetection): {
2997+changes: string[];
2998+warnings: string[];
2999+} {
3000+return repairOpenClawStateDatabaseSchema({
3001+env: { ...process.env, OPENCLAW_STATE_DIR: detected.stateDir },
3002+});
3003+}
3004+29723005export async function runLegacyStateMigrations(params: {
29733006detected: LegacyStateDetection;
29743007config?: OpenClawConfig;
@@ -2977,6 +3010,10 @@ export async function runLegacyStateMigrations(params: {
29773010}): Promise<{ changes: string[]; warnings: string[] }> {
29783011const now = params.now ?? (() => Date.now());
29793012const detected = params.detected;
3013+const stateSchema = migrateLegacyStateSchema(detected);
3014+if (detected.stateSchema.hasLegacy && stateSchema.warnings.length > 0) {
3015+return stateSchema;
3016+}
29803017const pluginStateSidecar = await migrateLegacyPluginStateSidecar({
29813018stateDir: detected.stateDir,
29823019});
@@ -2992,10 +3029,12 @@ export async function runLegacyStateMigrations(params: {
29923029const preSessionChannelPlans = await runLegacyMigrationPlans(
29933030detected.channelPlans.plans.filter((plan) => plan.kind === "plugin-state-import"),
29943031);
2995-const pluginPlans = await runPluginDoctorStateMigrationPlans({
2996- detected,
2997-config: params.config ?? ({} as OpenClawConfig),
2998-});
3032+const pluginPlans = detected.stateSchema.hasLegacy
3033+ ? { changes: [], warnings: [] }
3034+ : await runPluginDoctorStateMigrationPlans({
3035+ detected,
3036+config: params.config ?? ({} as OpenClawConfig),
3037+});
29993038const sessions = await migrateLegacySessions(detected, now, {
30003039recoverCorruptTargetStore: params.recoverCorruptTargetStore,
30013040});
@@ -3010,6 +3049,7 @@ export async function runLegacyStateMigrations(params: {
30103049);
30113050return {
30123051changes: [
3052+ ...stateSchema.changes,
30133053 ...pluginStateSidecar.changes,
30143054 ...pluginInstallIndex.changes,
30153055 ...taskStateSidecars.changes,
@@ -3022,6 +3062,7 @@ export async function runLegacyStateMigrations(params: {
30223062 ...channelPlans.changes,
30233063],
30243064warnings: [
3065+ ...stateSchema.warnings,
30253066 ...pluginStateSidecar.warnings,
30263067 ...pluginInstallIndex.warnings,
30273068 ...taskStateSidecars.warnings,
@@ -3306,6 +3347,10 @@ export async function autoMigrateLegacyState(params: {
33063347homedir: params.homedir,
33073348log: params.log,
33083349});
3350+const stateDir = resolveStateDir(env, params.homedir ?? os.homedir);
3351+const stateSchema = repairOpenClawStateDatabaseSchema({
3352+env: { ...env, OPENCLAW_STATE_DIR: stateDir },
3353+});
3309335433103355// Canonicalize orphaned session keys regardless of whether legacy migration
33113356// is needed — the orphan-key bug (#29683) affects all installs with
@@ -3362,6 +3407,7 @@ export async function autoMigrateLegacyState(params: {
33623407});
33633408const changes = [
33643409 ...stateDirResult.changes,
3410+ ...stateSchema.changes,
33653411 ...orphanKeys.changes,
33663412 ...acpSessionMetadata.changes,
33673413 ...pluginStateSidecar.changes,
@@ -3373,6 +3419,7 @@ export async function autoMigrateLegacyState(params: {
33733419];
33743420const warnings = [
33753421 ...stateDirResult.warnings,
3422+ ...stateSchema.warnings,
33763423 ...orphanKeys.warnings,
33773424 ...acpSessionMetadata.warnings,
33783425 ...pluginStateSidecar.warnings,
@@ -3386,6 +3433,7 @@ export async function autoMigrateLegacyState(params: {
33863433return {
33873434migrated:
33883435stateDirResult.migrated ||
3436+stateSchema.changes.length > 0 ||
33893437orphanKeys.changes.length > 0 ||
33903438acpSessionMetadata.changes.length > 0 ||
33913439pluginStateSidecar.changes.length > 0 ||
@@ -3406,23 +3454,27 @@ export async function autoMigrateLegacyState(params: {
34063454!detected.pluginPlans?.hasLegacy &&
34073455!detected.pluginStateSidecar.hasLegacy &&
34083456!detected.pluginInstallIndex.hasLegacy &&
3457+!detected.stateSchema.hasLegacy &&
34093458!detected.taskStateSidecars.hasLegacy &&
34103459!detected.deliveryQueues.hasLegacy
34113460) {
34123461const changes = [
34133462 ...stateDirResult.changes,
3463+ ...stateSchema.changes,
34143464 ...orphanKeys.changes,
34153465 ...acpSessionMetadata.changes,
34163466];
34173467const warnings = [
34183468 ...stateDirResult.warnings,
3469+ ...stateSchema.warnings,
34193470 ...orphanKeys.warnings,
34203471 ...acpSessionMetadata.warnings,
34213472];
34223473logMigrationResults(changes, warnings);
34233474return {
34243475migrated:
34253476stateDirResult.migrated ||
3477+stateSchema.changes.length > 0 ||
34263478orphanKeys.changes.length > 0 ||
34273479acpSessionMetadata.changes.length > 0,
34283480skipped: false,
@@ -3465,6 +3517,7 @@ export async function autoMigrateLegacyState(params: {
34653517);
34663518const changes = [
34673519 ...stateDirResult.changes,
3520+ ...stateSchema.changes,
34683521 ...orphanKeys.changes,
34693522 ...acpSessionMetadata.changes,
34703523 ...pluginStateSidecar.changes,
@@ -3480,6 +3533,7 @@ export async function autoMigrateLegacyState(params: {
34803533];
34813534const warnings = [
34823535 ...stateDirResult.warnings,
3536+ ...stateSchema.warnings,
34833537 ...orphanKeys.warnings,
34843538 ...acpSessionMetadata.warnings,
34853539 ...pluginStateSidecar.warnings,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。