Files
paseo/packages/server/src/server/persistence-hooks.test.ts
T
Mohamed BoudraandGitHub f0eb7cea4b feat(providers): add native options and exact MCP grants (#3025)
* feat(providers): add native options and exact MCP grants

Keep provider policy in provider-owned schemas so unattended Hub runs can grant only requested tools from injected MCP servers. Preserve the native resolved sandbox policy when a workflow override is present, including configured writable roots.

* test(hub): verify real provider tool policy

* test(app): avoid pinning transient restart status
2026-08-08 16:49:29 +02:00

197 lines
5.1 KiB
TypeScript

import { describe, expect, test } from "vitest";
import type { StoredAgentRecord } from "./agent/agent-storage.js";
import {
buildConfigOverrides,
buildSessionConfig,
toAgentPersistenceHandle,
} from "./persistence-hooks.js";
function createRecord(overrides?: Partial<StoredAgentRecord>): StoredAgentRecord {
const now = new Date().toISOString();
return {
id: "agent-record",
provider: "claude",
cwd: "/tmp/project",
createdAt: now,
updatedAt: now,
title: null,
lastStatus: "idle",
lastModeId: "plan",
config: { modeId: "plan", model: "claude-3.5-sonnet" },
persistence: {
provider: "claude",
sessionId: "session-123",
},
...overrides,
};
}
describe("persistence hooks", () => {
test("buildConfigOverrides preserves the complete private launch config", () => {
const record = createRecord({
title: "Voice agent (current)",
config: {
modeId: "default",
model: "gpt-5.4-mini",
thinkingOptionId: "minimal",
providerOptions: {
sandbox_mode: "workspace-write",
sandbox_workspace_write: { writable_roots: ["/tmp/shared"] },
},
toolPolicy: {
preapproved: [{ kind: "mcp", server: "paseo", tool: "report_status" }],
},
systemPrompt: "Use speak first.",
mcpServers: {
paseo: {
type: "stdio",
command: "node",
args: ["/tmp/bridge.mjs", "--socket", "/tmp/agent.sock"],
},
},
},
});
expect(buildConfigOverrides(record)).toMatchObject({
cwd: "/tmp/project",
modeId: "default",
model: "gpt-5.4-mini",
thinkingOptionId: "minimal",
providerOptions: {
sandbox_mode: "workspace-write",
sandbox_workspace_write: { writable_roots: ["/tmp/shared"] },
},
toolPolicy: {
preapproved: [{ kind: "mcp", server: "paseo", tool: "report_status" }],
},
systemPrompt: "Use speak first.",
mcpServers: {
paseo: {
type: "stdio",
command: "node",
args: ["/tmp/bridge.mjs", "--socket", "/tmp/agent.sock"],
},
},
});
});
test("buildSessionConfig keeps an omitted mode omitted on resume", () => {
const record = createRecord({
provider: "codex",
title: "Renamed title",
config: {
model: "gpt-5.4-mini",
systemPrompt: "Confirm and speak first.",
mcpServers: {
paseo: {
type: "stdio",
command: "node",
args: ["/tmp/bridge.mjs", "--socket", "/tmp/agent.sock"],
},
},
},
});
expect(buildSessionConfig(record)).toMatchObject({
provider: "codex",
cwd: "/tmp/project",
modeId: undefined,
model: "gpt-5.4-mini",
systemPrompt: "Confirm and speak first.",
mcpServers: {
paseo: {
type: "stdio",
command: "node",
args: ["/tmp/bridge.mjs", "--socket", "/tmp/agent.sock"],
},
},
});
});
test("buildConfigOverrides drops persisted internal paseo MCP server", () => {
const record = createRecord({
config: {
modeId: "default",
model: "gpt-5.4-mini",
mcpServers: {
paseo: {
type: "http",
url: "http://127.0.0.1:6767/mcp/agents?callerAgentId=stale-agent",
},
custom: {
type: "stdio",
command: "custom-mcp",
},
},
},
});
expect(buildConfigOverrides(record).mcpServers).toEqual({
custom: {
type: "stdio",
command: "custom-mcp",
},
});
});
test("buildConfigOverrides preserves user-provided paseo MCP server", () => {
const record = createRecord({
config: {
modeId: "default",
model: "gpt-5.4-mini",
mcpServers: {
paseo: {
type: "http",
url: "https://example.com/custom-paseo",
},
},
},
});
expect(buildConfigOverrides(record).mcpServers).toEqual({
paseo: {
type: "http",
url: "https://example.com/custom-paseo",
},
});
});
test("buildSessionConfig accepts providers from the canonical manifest", () => {
const record = createRecord({
provider: "claude",
persistence: {
provider: "claude",
sessionId: "session-123",
},
config: {},
});
expect(buildSessionConfig(record)).toMatchObject({
provider: "claude",
cwd: "/tmp/project",
});
});
test("buildSessionConfig skips records whose provider is missing from the registry", () => {
const record = createRecord({
id: "agent-missing-provider",
provider: "zai",
});
expect(
buildSessionConfig(record, {
validProviders: ["claude", "codex"],
}),
).toBeNull();
});
test("toAgentPersistenceHandle rejects handles for unavailable providers", () => {
const handle = toAgentPersistenceHandle(["claude", "codex"], {
provider: "gemini",
sessionId: "session-123",
});
expect(handle).toBeNull();
});
});