mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(agents): preserve fresh workspace hatch (#111553)
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { expect, it } from "vitest";
|
||||
import { closeOpenClawStateDatabaseForTest } from "../state/openclaw-state-db.js";
|
||||
import { createOpenClawTestState } from "../test-utils/openclaw-test-state.js";
|
||||
import { createAgent } from "./agent-create.js";
|
||||
import {
|
||||
DEFAULT_IDENTITY_FILENAME,
|
||||
ensureAgentWorkspace,
|
||||
isWorkspaceBootstrapPending,
|
||||
} from "./workspace.js";
|
||||
|
||||
it("keeps a fresh named workspace pending through the first run setup", async () => {
|
||||
const state = await createOpenClawTestState({
|
||||
layout: "state-only",
|
||||
scenario: "minimal",
|
||||
label: "named-agent-hatch",
|
||||
});
|
||||
const workspace = state.path("named-workspace");
|
||||
|
||||
try {
|
||||
const created = await createAgent({ name: "Researcher", workspace });
|
||||
|
||||
expect(created).toMatchObject({ status: "created", bootstrapPending: true });
|
||||
expect(await isWorkspaceBootstrapPending(workspace)).toBe(true);
|
||||
|
||||
const firstRunWorkspace = await ensureAgentWorkspace({
|
||||
dir: workspace,
|
||||
ensureBootstrapFiles: true,
|
||||
});
|
||||
expect(firstRunWorkspace.bootstrapPending).toBe(true);
|
||||
expect(await isWorkspaceBootstrapPending(workspace)).toBe(true);
|
||||
expect(
|
||||
await fs.readFile(path.join(workspace, DEFAULT_IDENTITY_FILENAME), "utf8"),
|
||||
).not.toContain("Researcher");
|
||||
} finally {
|
||||
closeOpenClawStateDatabaseForTest();
|
||||
await state.cleanup();
|
||||
}
|
||||
});
|
||||
@@ -180,7 +180,25 @@ describe("createAgent", () => {
|
||||
expect(mocks.ensureAgentWorkspace).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it("keeps the template identity while bootstrap is pending", async () => {
|
||||
await createAgent({ name: "researcher" });
|
||||
|
||||
expect(mocks.rootRead).not.toHaveBeenCalled();
|
||||
expect(mocks.rootWrite).not.toHaveBeenCalled();
|
||||
expect(mocks.persisted).toMatchObject({
|
||||
agents: {
|
||||
list: expect.arrayContaining([
|
||||
expect.objectContaining({ identity: { name: "researcher" } }),
|
||||
]),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("does not publish config when identity setup is unsafe", async () => {
|
||||
mocks.ensureAgentWorkspace.mockImplementation(async ({ dir }: { dir: string }) => ({
|
||||
dir,
|
||||
bootstrapPending: false,
|
||||
}));
|
||||
mocks.rootRead.mockRejectedValue(new FsSafeError("invalid-path", "unsafe identity path"));
|
||||
|
||||
await expect(createAgent({ name: "researcher" })).resolves.toMatchObject({
|
||||
|
||||
@@ -161,7 +161,11 @@ export async function createAgent(params: CreateAgentParams): Promise<CreateAgen
|
||||
});
|
||||
}
|
||||
await fs.mkdir(resolveSessionTranscriptsDirForAgent(agentId), { recursive: true });
|
||||
await writeIdentityFile({ workspaceDir: workspace.dir, identity });
|
||||
// A creation-time name is config, not proof that the fresh workspace hatched.
|
||||
// Keep IDENTITY.md templated until BOOTSTRAP completes its first-turn ceremony.
|
||||
if (!workspace.bootstrapPending) {
|
||||
await writeIdentityFile({ workspaceDir: workspace.dir, identity });
|
||||
}
|
||||
|
||||
return {
|
||||
nextConfig,
|
||||
|
||||
Reference in New Issue
Block a user