Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/JAVA/Openclaw/src/infra/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 7 kB image not shown  

Quelle  state-migrations.orphan-keys.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import { withTempDir } from "../test-helpers/temp-dir.js";
import { migrateOrphanedSessionKeys } from "./state-migrations.js";

function writeStore(storePath: string, store: Record<string, unknown>): void {
  fs.mkdirSync(path.dirname(storePath), { recursive: true });
  fs.writeFileSync(storePath, JSON.stringify(store));
}

function readStore(storePath: string): Record<string, unknown> {
  return JSON.parse(fs.readFileSync(storePath, "utf-8"));
}

async function withStateFixture(
  run: (params: { tmpDir: string; stateDir: string }) => Promise<void>,
): Promise<void> {
  await withTempDir({ prefix: "orphan-keys-test-" }, async (tmpDir) => {
    const stateDir = path.join(tmpDir, ".openclaw");
    fs.mkdirSync(stateDir, { recursive: true });
    await run({ tmpDir, stateDir });
  });
}

const OPS_WORK_CONFIG = {
  session: { mainKey: "work" },
  agents: { list: [{ id: "ops", default: true }] },
} as OpenClawConfig;

function opsSessionStorePath(stateDir: string): string {
  return path.join(stateDir, "agents", "ops", "sessions", "sessions.json");
}

function sharedMainOpsConfig(sharedStorePath: string): OpenClawConfig {
  return {
    session: { mainKey: "work", store: sharedStorePath },
    agents: { list: [{ id: "main" }, { id: "ops", default: true }] },
  } as OpenClawConfig;
}

async function migrateFixtureState(stateDir: string, cfg: OpenClawConfig = OPS_WORK_CONFIG) {
  return migrateOrphanedSessionKeys({
    cfg,
    env: { OPENCLAW_STATE_DIR: stateDir },
  });
}

describe("migrateOrphanedSessionKeys", () => {
  it("renames orphaned raw key to canonical form", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const storePath = opsSessionStorePath(stateDir);
      writeStore(storePath, {
        "agent:main:main": { sessionId: "abc-123", updatedAt: 1000 },
      });

      const result = await migrateFixtureState(stateDir);

      expect(result.changes.length).toBeGreaterThan(0);
      const store = readStore(storePath);
      expect(store["agent:ops:work"]).toBeDefined();
      expect((store["agent:ops:work"] as { sessionId: string }).sessionId).toBe("abc-123");
      expect(store["agent:main:main"]).toBeUndefined();
    });
  });

  it("keeps most recently updated entry when both orphan and canonical exist", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const storePath = opsSessionStorePath(stateDir);
      writeStore(storePath, {
        "agent:main:main": { sessionId: "old-orphan", updatedAt: 500 },
        "agent:ops:work": { sessionId: "current", updatedAt: 2000 },
      });

      await migrateFixtureState(stateDir);

      const store = readStore(storePath);
      expect((store["agent:ops:work"] as { sessionId: string }).sessionId).toBe("current");
      expect(store["agent:main:main"]).toBeUndefined();
    });
  });

  it("skips stores that are already fully canonical", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const storePath = opsSessionStorePath(stateDir);
      writeStore(storePath, {
        "agent:ops:work": { sessionId: "abc-123", updatedAt: 1000 },
      });

      const result = await migrateFixtureState(stateDir);

      expect(result.changes).toHaveLength(0);
      expect(result.warnings).toHaveLength(0);
    });
  });

  it("handles missing store files gracefully", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const result = await migrateFixtureState(stateDir);

      expect(result.changes).toHaveLength(0);
      expect(result.warnings).toHaveLength(0);
    });
  });

  it("is idempotent — running twice produces same result", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const storePath = opsSessionStorePath(stateDir);
      writeStore(storePath, {
        "agent:main:main": { sessionId: "abc-123", updatedAt: 1000 },
      });

      const env = { OPENCLAW_STATE_DIR: stateDir };
      await migrateOrphanedSessionKeys({ cfg: OPS_WORK_CONFIG, env });
      const result2 = await migrateOrphanedSessionKeys({ cfg: OPS_WORK_CONFIG, env });

      expect(result2.changes).toHaveLength(0);
      const store = readStore(storePath);
      expect((store["agent:ops:work"] as { sessionId: string }).sessionId).toBe("abc-123");
    });
  });

  it("preserves legitimate agent:main:* keys in shared stores with both main and non-main agents", async () => {
    await withStateFixture(async ({ tmpDir, stateDir }) => {
      // When session.store lacks {agentId}, all agents resolve to the same file.
      // The "main" agent's keys must not be remapped into the "ops" namespace.
      const sharedStorePath = path.join(tmpDir, "shared-sessions.json");
      writeStore(sharedStorePath, {
        "agent:main:main": { sessionId: "main-session", updatedAt: 2000 },
        "agent:ops:work": { sessionId: "ops-session", updatedAt: 1000 },
      });

      await migrateFixtureState(stateDir, sharedMainOpsConfig(sharedStorePath));

      const store = readStore(sharedStorePath);
      // main agent's session is canonicalised to use configured mainKey ("work"),
      // but stays in the "main" agent namespace — NOT remapped into "ops".
      expect(store["agent:main:work"]).toBeDefined();
      expect((store["agent:main:work"] as { sessionId: string }).sessionId).toBe("main-session");
      expect(store["agent:ops:work"]).toBeDefined();
      expect((store["agent:ops:work"] as { sessionId: string }).sessionId).toBe("ops-session");
      // The key must NOT have been merged into ops namespace
      expect(Object.keys(store).filter((k) => k.startsWith("agent:ops:")).length).toBe(1);
    });
  });

  it("lets the main agent claim bare main aliases in shared stores", async () => {
    await withStateFixture(async ({ tmpDir, stateDir }) => {
      const sharedStorePath = path.join(tmpDir, "shared-sessions.json");
      writeStore(sharedStorePath, {
        main: { sessionId: "main-session", updatedAt: 2000 },
        "agent:ops:work": { sessionId: "ops-session", updatedAt: 1000 },
      });

      await migrateFixtureState(stateDir, sharedMainOpsConfig(sharedStorePath));

      const store = readStore(sharedStorePath);
      expect(store["agent:main:work"]).toBeDefined();
      expect((store["agent:main:work"] as { sessionId: string }).sessionId).toBe("main-session");
      expect(store.main).toBeUndefined();
      expect(store["agent:ops:work"]).toBeDefined();
    });
  });

  it("no-ops when default agentId is main and mainKey is main", async () => {
    await withStateFixture(async ({ stateDir }) => {
      const storePath = path.join(stateDir, "agents", "main", "sessions", "sessions.json");
      writeStore(storePath, {
        "agent:main:main": { sessionId: "abc-123", updatedAt: 1000 },
      });

      const cfg = {} as OpenClawConfig;

      const result = await migrateOrphanedSessionKeys({
        cfg,
        env: { OPENCLAW_STATE_DIR: stateDir },
      });

      expect(result.changes).toHaveLength(0);
      const store = readStore(storePath);
      expect(store["agent:main:main"]).toBeDefined();
    });
  });
});

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.