mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 13:22:37 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df081a06ed | ||
|
|
c6a4ae81c9 |
@@ -1117,6 +1117,42 @@ describe("Codex app-server provider", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("starts a session without a model on the project's Codex model and effort", async () => {
|
||||
const cwd = "/workspace/project";
|
||||
const appServer = createFakeCodexAppServer({
|
||||
"config/read": (params) => ({
|
||||
config:
|
||||
(params as { cwd?: unknown }).cwd === cwd
|
||||
? { model: "project-model", model_reasoning_effort: "high" }
|
||||
: { model: "global-model", model_reasoning_effort: "low" },
|
||||
}),
|
||||
getUserSavedConfig: () => ({
|
||||
config: { model: "global-model", modelReasoningEffort: "low" },
|
||||
}),
|
||||
});
|
||||
const session = new CodexAppServerAgentSession(
|
||||
createConfig({ cwd, model: undefined }),
|
||||
null,
|
||||
createTestLogger(),
|
||||
async () => appServer.child,
|
||||
);
|
||||
|
||||
try {
|
||||
await session.startTurn("use project defaults");
|
||||
|
||||
await expect(appServer.waitForRequest("thread/start")).resolves.toMatchObject({
|
||||
model: "project-model",
|
||||
});
|
||||
await expect(appServer.waitForTurnStart()).resolves.toMatchObject({
|
||||
model: "project-model",
|
||||
effort: "high",
|
||||
});
|
||||
appServer.assertNoErrors();
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("preserves cwd-resolved Codex writable roots under an explicit workflow mode", async () => {
|
||||
const appServer = createFakeCodexAppServer({
|
||||
"config/read": () => ({
|
||||
|
||||
@@ -3100,10 +3100,32 @@ const CodexNotificationSchema = z.union([
|
||||
),
|
||||
]);
|
||||
|
||||
// config/read resolves the effective layered config, including a trusted project's
|
||||
// .codex/config.toml when given its cwd; getUserSavedConfig predates it.
|
||||
async function readCodexConfiguredDefaults(
|
||||
client: CodexAppServerClient,
|
||||
logger: Logger,
|
||||
cwd: string | null,
|
||||
): Promise<CodexConfiguredDefaults> {
|
||||
let configReadDefaults: CodexConfiguredDefaults = {};
|
||||
try {
|
||||
const response = toObjectRecord(await client.request("config/read", { cwd }));
|
||||
const config = toObjectRecord(response?.config);
|
||||
const modelValue = typeof config?.model === "string" ? config.model : undefined;
|
||||
const thinkingOptionValue =
|
||||
typeof config?.model_reasoning_effort === "string" ? config.model_reasoning_effort : null;
|
||||
configReadDefaults = {
|
||||
model: normalizeCodexModelId(modelValue),
|
||||
thinkingOptionId: normalizeCodexThinkingOptionId(thinkingOptionValue),
|
||||
};
|
||||
} catch (error) {
|
||||
logger.debug({ error }, "Failed to read Codex config defaults");
|
||||
}
|
||||
|
||||
if (configReadDefaults.model && configReadDefaults.thinkingOptionId) {
|
||||
return configReadDefaults;
|
||||
}
|
||||
|
||||
let savedConfigDefaults: CodexConfiguredDefaults = {};
|
||||
try {
|
||||
const response = toObjectRecord(await client.request("getUserSavedConfig", {}));
|
||||
@@ -3119,26 +3141,7 @@ async function readCodexConfiguredDefaults(
|
||||
logger.debug({ error }, "Failed to read Codex saved config defaults");
|
||||
}
|
||||
|
||||
if (savedConfigDefaults.model && savedConfigDefaults.thinkingOptionId) {
|
||||
return savedConfigDefaults;
|
||||
}
|
||||
|
||||
let configReadDefaults: CodexConfiguredDefaults = {};
|
||||
try {
|
||||
const response = toObjectRecord(await client.request("config/read", {}));
|
||||
const config = toObjectRecord(response?.config);
|
||||
const modelValue = typeof config?.model === "string" ? config.model : undefined;
|
||||
const thinkingOptionValue =
|
||||
typeof config?.model_reasoning_effort === "string" ? config.model_reasoning_effort : null;
|
||||
configReadDefaults = {
|
||||
model: normalizeCodexModelId(modelValue),
|
||||
thinkingOptionId: normalizeCodexThinkingOptionId(thinkingOptionValue),
|
||||
};
|
||||
} catch (error) {
|
||||
logger.debug({ error }, "Failed to read Codex config defaults");
|
||||
}
|
||||
|
||||
return mergeCodexConfiguredDefaults(savedConfigDefaults, configReadDefaults);
|
||||
return mergeCodexConfiguredDefaults(configReadDefaults, savedConfigDefaults);
|
||||
}
|
||||
|
||||
interface CodexSkillPromptBlock {
|
||||
@@ -5119,7 +5122,11 @@ export class CodexAppServerAgentSession implements AgentSession {
|
||||
let model = this.config.model;
|
||||
let thinkingOptionId = normalizeCodexThinkingOptionId(this.config.thinkingOptionId);
|
||||
if (!model || !thinkingOptionId) {
|
||||
configuredDefaults = await readCodexConfiguredDefaults(this.client, this.logger);
|
||||
configuredDefaults = await readCodexConfiguredDefaults(
|
||||
this.client,
|
||||
this.logger,
|
||||
this.config.cwd ?? null,
|
||||
);
|
||||
}
|
||||
if (!model) {
|
||||
model = configuredDefaults.model;
|
||||
@@ -7323,7 +7330,7 @@ export class CodexAppServerAgentClient implements AgentClient {
|
||||
const parsedResponse = CodexModelListResponseSchema.safeParse(rawResponse);
|
||||
const models = parsedResponse.success ? (parsedResponse.data.data ?? []) : [];
|
||||
const configuredDefaults = await runProviderRefreshActivity(context, "config/read", () =>
|
||||
readCodexConfiguredDefaults(client!, this.logger),
|
||||
readCodexConfiguredDefaults(client!, this.logger, null),
|
||||
);
|
||||
const configuredDefaultModelId = configuredDefaults.model;
|
||||
const configuredDefaultThinkingOptionId = configuredDefaults.thinkingOptionId;
|
||||
|
||||
@@ -355,7 +355,8 @@ test.each([
|
||||
await resumed?.close();
|
||||
await original?.close();
|
||||
await client.shutdown();
|
||||
await rm(root, { recursive: true, force: true });
|
||||
// OpenCode can still hold its ripgrep download open on Windows right after shutdown.
|
||||
await rm(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 });
|
||||
}
|
||||
},
|
||||
240_000,
|
||||
|
||||
Reference in New Issue
Block a user