fix(core): present the project dir to the model as the App Data Dir in the default system prompt (#61)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
14b5e6384f
commit
816a823b75
24 files changed
+423
-68
No files matched your search
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* POST /api/projects/:projectId/agents/:agentId/config/reset — overwrites
|
||||
* system_config.yaml with the current code defaults, keeping only the identity fields
|
||||
* (name / description / version); the config-side analogue of a skill update. Same
|
||||
* member-level authorization as PUT config; a non-member gets 404 without a write.
|
||||
*/
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { defaultSystemConfig } from "@prismshadow/penguin-core";
|
||||
import type { AgentConfigResponse, ProjectCreateResponse } from "../src/api/types.js";
|
||||
import { apiClient, createTestApp, provisionUser } from "./helpers.js";
|
||||
import type { TestApp } from "./helpers.js";
|
||||
|
||||
describe("POST agent config reset", () => {
|
||||
let t: TestApp;
|
||||
let alice: ReturnType<typeof apiClient>;
|
||||
let projectId: string;
|
||||
const configUrl = () => `/api/projects/${projectId}/agents/default_agent/config`;
|
||||
|
||||
beforeEach(async () => {
|
||||
t = await createTestApp();
|
||||
const a = await provisionUser(t.app, "alice");
|
||||
alice = apiClient(t.app, a.cookie);
|
||||
// Project ids are username-prefixed (`alice-…`), same as the other route tests.
|
||||
const created = (await (
|
||||
await alice.post("/api/projects", { projectId: "alice-reset", name: "Reset project" })
|
||||
).json()) as ProjectCreateResponse;
|
||||
projectId = created.project.projectId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await t.cleanup();
|
||||
});
|
||||
|
||||
it("restores the defaults while preserving name / description / version", async () => {
|
||||
// Customize everything the reset is supposed to overwrite, plus the kept fields.
|
||||
const put = await alice.put(configUrl(), {
|
||||
config: {
|
||||
name: "Custom Name",
|
||||
description: "Custom description",
|
||||
systemPrompt: "CUSTOM PROMPT",
|
||||
maxTurns: 3,
|
||||
model: { maxTokens: 1234 },
|
||||
compaction: { mode: "discard" },
|
||||
toolsBuiltin: [],
|
||||
mcpServers: [{ name: "custom-mcp", config: {} }],
|
||||
},
|
||||
});
|
||||
expect(put.status).toBe(200);
|
||||
|
||||
const res = await alice.post(`${configUrl()}/reset`);
|
||||
expect(res.status).toBe(200);
|
||||
const body = (await res.json()) as AgentConfigResponse;
|
||||
const defaults = defaultSystemConfig();
|
||||
|
||||
// Identity fields survive.
|
||||
expect(body.config.name).toBe("Custom Name");
|
||||
expect(body.config.description).toBe("Custom description");
|
||||
expect(body.config.version).toBe(1);
|
||||
// Everything else is back to the current defaults.
|
||||
expect(body.config.systemPrompt).toBe(defaults.system_prompt);
|
||||
expect(body.config.systemPrompt).toContain("App Data Dir: {{PROJECT_DIR}}");
|
||||
expect(body.config.maxTurns).toBe(defaults.max_turns);
|
||||
expect(body.config.model?.maxTokens).toBe(defaults.model?.max_tokens);
|
||||
expect(body.config.compaction?.mode).toBe("summarize");
|
||||
expect(body.config.toolsBuiltin.map((tool) => tool.name)).toEqual(
|
||||
(defaults.tools?.builtin ?? []).map((tool) => tool.name),
|
||||
);
|
||||
expect(body.config.mcpServers).toEqual([]);
|
||||
|
||||
// A later GET sees the same reset state (it was persisted, not just echoed).
|
||||
const got = (await (await alice.get(configUrl())).json()) as AgentConfigResponse;
|
||||
expect(got.config.systemPrompt).toBe(defaults.system_prompt);
|
||||
expect(got.config.name).toBe("Custom Name");
|
||||
});
|
||||
|
||||
it("404 for a nonexistent agent (no initialization side effect)", async () => {
|
||||
const res = await alice.post(`/api/projects/${projectId}/agents/ghost/config/reset`);
|
||||
expect(res.status).toBe(404);
|
||||
});
|
||||
|
||||
it("404 for a non-member; the config is not modified", async () => {
|
||||
const before = (await (await alice.get(configUrl())).json()) as AgentConfigResponse;
|
||||
const m = await provisionUser(t.app, "mallory");
|
||||
const mallory = apiClient(t.app, m.cookie);
|
||||
const res = await mallory.post(`${configUrl()}/reset`);
|
||||
expect(res.status).toBe(404);
|
||||
const after = (await (await alice.get(configUrl())).json()) as AgentConfigResponse;
|
||||
expect(after.systemConfigYaml).toBe(before.systemConfigYaml);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user