@open-mercato/cezar 0.9.1-pr725.892 → 0.9.1-pr726.896
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/agent-config/catalog.d.ts +4 -0
- package/dist/agent-config/catalog.js +14 -0
- package/dist/agent-config/catalog.js.map +1 -1
- package/dist/agent-config/models.d.ts +5 -0
- package/dist/agent-config/models.js +80 -0
- package/dist/agent-config/models.js.map +1 -0
- package/dist/core/agent-model-policy.d.ts +5 -0
- package/dist/core/agent-model-policy.js +8 -0
- package/dist/core/agent-model-policy.js.map +1 -0
- package/dist/server/server.d.ts +36 -36
- package/dist/server/server.js +44 -19
- package/dist/server/server.js.map +1 -1
- package/dist/workflows/run.d.ts +16 -3
- package/dist/workflows/run.js +165 -43
- package/dist/workflows/run.js.map +1 -1
- package/package.json +2 -2
- package/web/dist/assets/{compare-variants-BnhCYsfo.js → compare-variants-DXfFTtfr.js} +1 -1
- package/web/dist/assets/{diff-BYWScKEf2.js → diff-CQY9DbEX2.js} +2 -2
- package/web/dist/assets/{diff-view-DQrWNV7l.js → diff-view-D1LKO1xk.js} +1 -1
- package/web/dist/assets/{git-toolbar-BWUVZ6yR.js → git-toolbar-BP1Y3NuC.js} +1 -1
- package/web/dist/assets/{github-Ox8fCBdG.js → github-BpU1rlah.js} +1 -1
- package/web/dist/assets/{index-D-0AJo1h.js → index-CUuvs-FD.js} +4 -4
- package/web/dist/assets/new-task-form-B-ifwpi0.js +1 -0
- package/web/dist/assets/{repo-git-CKp7XJDH.js → repo-git-3NyrzWNb.js} +1 -1
- package/web/dist/assets/{run-diff-Dclf6QqY.js → run-diff-BSEQ5brJ.js} +1 -1
- package/web/dist/assets/{run-header-DqjqwW-M.js → run-header-BIRLEI8K.js} +1 -1
- package/web/dist/assets/{skills-B6JggT7B.js → skills-CO8z1733.js} +1 -1
- package/web/dist/assets/{task-changes-D3WZw6Wm.js → task-changes-CylE3sZ0.js} +1 -1
- package/web/dist/assets/{task-commits-kzQcMB61.js → task-commits-D9u9HWm3.js} +1 -1
- package/web/dist/assets/{task-files-BuEzgMvG.js → task-files-nYjxrDpA.js} +1 -1
- package/web/dist/assets/{task-thread-YqnMa71e.js → task-thread-oz1-VMfl.js} +2 -2
- package/web/dist/assets/{use-desktop-CRwfloSK.js → use-desktop-FJpraByx.js} +1 -1
- package/web/dist/assets/{workflows-FiXcWMoj.js → workflows-BDnGBDS2.js} +1 -1
- package/web/dist/index.html +2 -2
- package/web/dist/assets/new-task-form-umhQeDuQ.js +0 -1
package/README.md
CHANGED
|
@@ -426,6 +426,7 @@ Useful environment variables:
|
|
|
426
426
|
| Var | Effect |
|
|
427
427
|
|---|---|
|
|
428
428
|
| `CEZ_DRY_RUN=1` | Use the bundled mock instead of the real `claude` CLI — the entire cockpit works offline, for demos and development. |
|
|
429
|
+
| `CEZ_AGENT_MODELS_LOCKED=1` | Lock model selection to the models configured in native Claude/Codex/OpenCode settings. Existing Cezar presets are preserved but ignored; only `1` enables it, and a restart is required. |
|
|
429
430
|
| `CEZ_APPROVAL_GATE=1` | Opt into Claude's interactive approval UI; by default, unapproved tools are denied without interrupting the run. |
|
|
430
431
|
| `CEZ_FOLLOWUPS=1` | Turn on the global follow-up **Inbox**: agents are asked to leave follow-ups in `todos.json` when they finish, and the Inbox view appears. Off by default — each task's own **Notes** handoff journal runs either way. |
|
|
431
432
|
| `CEZ_AUTOSAVE=1` | Re-enable the periodic (90 s) autosave commit in task worktrees. Off by default (#471) — turn-end and pre-PR flushes always run, so branches still end complete. Every autosave names its trigger in the commit subject (`cezar autosave (periodic)` vs `(turn end)` / `(run finalize)` / `(pre-PR)`), so the flushes you keep are distinguishable from the timer you disabled. |
|
|
@@ -47,6 +47,10 @@ export interface ConfigFileDef {
|
|
|
47
47
|
seeded?: boolean;
|
|
48
48
|
/** True when this file holds MCP server definitions (drives the MCP section's filter). */
|
|
49
49
|
holdsMcp?: boolean;
|
|
50
|
+
/** Top-level native setting that supplies the agent's new-session model, when present. */
|
|
51
|
+
modelKey?: string;
|
|
52
|
+
/** Higher values win when resolving a native default model across config scopes. */
|
|
53
|
+
modelPriority?: number;
|
|
50
54
|
/** VERBATIM from the vendor docs. Never computed, never generic. */
|
|
51
55
|
precedence: string;
|
|
52
56
|
/** Documented mid-run reload behaviour, or undefined when the vendor is silent. */
|
|
@@ -21,6 +21,8 @@ export const CONFIG_FILES = [
|
|
|
21
21
|
label: '~/.claude/settings.json',
|
|
22
22
|
format: 'json',
|
|
23
23
|
tracked: 'outside-repo',
|
|
24
|
+
modelKey: 'model',
|
|
25
|
+
modelPriority: 1,
|
|
24
26
|
precedence: 'Lowest priority. Project and local settings override it key by key — except permission rules, which merge across all scopes.',
|
|
25
27
|
hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
|
|
26
28
|
docsUrl: CLAUDE_SETTINGS_DOCS,
|
|
@@ -34,6 +36,8 @@ export const CONFIG_FILES = [
|
|
|
34
36
|
label: '.claude/settings.json',
|
|
35
37
|
format: 'json',
|
|
36
38
|
tracked: 'tracked',
|
|
39
|
+
modelKey: 'model',
|
|
40
|
+
modelPriority: 2,
|
|
37
41
|
precedence: 'Overrides user settings key by key (permission rules merge). Local settings override this.',
|
|
38
42
|
hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
|
|
39
43
|
docsUrl: CLAUDE_SETTINGS_DOCS,
|
|
@@ -48,6 +52,8 @@ export const CONFIG_FILES = [
|
|
|
48
52
|
format: 'json',
|
|
49
53
|
tracked: 'gitignored',
|
|
50
54
|
seeded: true,
|
|
55
|
+
modelKey: 'model',
|
|
56
|
+
modelPriority: 3,
|
|
51
57
|
precedence: 'Highest of the file scopes — overrides project and user (permission rules merge). Git-ignored; copied into each run’s worktree so it takes effect immediately.',
|
|
52
58
|
hotReload: 'Edits to most keys — including permissions and hooks — apply to a running session without a restart.',
|
|
53
59
|
docsUrl: CLAUDE_SETTINGS_DOCS,
|
|
@@ -113,6 +119,8 @@ export const CONFIG_FILES = [
|
|
|
113
119
|
format: 'toml',
|
|
114
120
|
tracked: 'outside-repo',
|
|
115
121
|
holdsMcp: true,
|
|
122
|
+
modelKey: 'model',
|
|
123
|
+
modelPriority: 1,
|
|
116
124
|
precedence: 'User-level defaults. A trusted project’s .codex/config.toml overrides these; some keys (provider, auth, telemetry) cannot be overridden at project scope. MCP servers live here under [mcp_servers.<id>].',
|
|
117
125
|
docsUrl: CODEX_CONFIG_DOCS,
|
|
118
126
|
},
|
|
@@ -125,6 +133,8 @@ export const CONFIG_FILES = [
|
|
|
125
133
|
label: '.codex/config.toml',
|
|
126
134
|
format: 'toml',
|
|
127
135
|
tracked: 'tracked',
|
|
136
|
+
modelKey: 'model',
|
|
137
|
+
modelPriority: 2,
|
|
128
138
|
holdsMcp: true,
|
|
129
139
|
precedence: 'Applies only in projects you have trusted. Some keys (provider, auth, telemetry) cannot be overridden here. MCP servers go under [mcp_servers.<id>]. Runs read the committed copy.',
|
|
130
140
|
docsUrl: CODEX_CONFIG_DOCS,
|
|
@@ -152,6 +162,8 @@ export const CONFIG_FILES = [
|
|
|
152
162
|
format: 'jsonc',
|
|
153
163
|
tracked: 'outside-repo',
|
|
154
164
|
holdsMcp: true,
|
|
165
|
+
modelKey: 'model',
|
|
166
|
+
modelPriority: 1,
|
|
155
167
|
precedence: 'Global config. Merged with the project config, not replaced — later configs override earlier ones only for conflicting keys. MCP servers live under the "mcp" key.',
|
|
156
168
|
docsUrl: OPENCODE_CONFIG_DOCS,
|
|
157
169
|
},
|
|
@@ -165,6 +177,8 @@ export const CONFIG_FILES = [
|
|
|
165
177
|
format: 'jsonc',
|
|
166
178
|
tracked: 'tracked',
|
|
167
179
|
holdsMcp: true,
|
|
180
|
+
modelKey: 'model',
|
|
181
|
+
modelPriority: 2,
|
|
168
182
|
precedence: 'Merged over the global config per conflicting key (not a wholesale replace). MCP servers live under the "mcp" key. Runs read the committed copy.',
|
|
169
183
|
docsUrl: OPENCODE_CONFIG_DOCS,
|
|
170
184
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/agent-config/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/agent-config/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RunnerId } from '../core/agent-runner.js';
|
|
2
|
+
/** The model defaults exposed by the coding agents' own settings files. */
|
|
3
|
+
export type AgentModelDefaults = Partial<Record<RunnerId, string>>;
|
|
4
|
+
/** Read the current default model for each installed/configured coding agent. */
|
|
5
|
+
export declare function readAgentModelDefaults(repoRoot: string, env?: NodeJS.ProcessEnv): Promise<AgentModelDefaults>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { parse as parseToml } from 'smol-toml';
|
|
2
|
+
import { CONFIG_FILES } from './catalog.js';
|
|
3
|
+
import { readConfigFile } from './files.js';
|
|
4
|
+
import { stripJsonComments } from './validate.js';
|
|
5
|
+
/**
|
|
6
|
+
* Native settings are read in the same order in which each agent applies them:
|
|
7
|
+
* the first valid model wins. Cezar deliberately only reads the settings files
|
|
8
|
+
* it already exposes in Settings → Agent config; managed/CLI/environment
|
|
9
|
+
* overrides stay with the agent process itself.
|
|
10
|
+
*/
|
|
11
|
+
/** Remove JSONC trailing commas without touching commas inside string values. */
|
|
12
|
+
function stripJsonTrailingCommas(input) {
|
|
13
|
+
let out = '';
|
|
14
|
+
let inString = false;
|
|
15
|
+
let escaped = false;
|
|
16
|
+
for (let i = 0; i < input.length; i++) {
|
|
17
|
+
const ch = input[i];
|
|
18
|
+
if (inString) {
|
|
19
|
+
out += ch;
|
|
20
|
+
if (escaped)
|
|
21
|
+
escaped = false;
|
|
22
|
+
else if (ch === '\\')
|
|
23
|
+
escaped = true;
|
|
24
|
+
else if (ch === '"')
|
|
25
|
+
inString = false;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (ch === '"') {
|
|
29
|
+
inString = true;
|
|
30
|
+
out += ch;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (ch === ',') {
|
|
34
|
+
let next = i + 1;
|
|
35
|
+
while (/\s/.test(input[next] ?? ''))
|
|
36
|
+
next++;
|
|
37
|
+
if (input[next] === '}' || input[next] === ']')
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
out += ch;
|
|
41
|
+
}
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
function modelFromContent(content, format, key) {
|
|
45
|
+
try {
|
|
46
|
+
const parsed = format === 'toml'
|
|
47
|
+
? parseToml(content)
|
|
48
|
+
: JSON.parse(format === 'jsonc' ? stripJsonTrailingCommas(stripJsonComments(content)) : content);
|
|
49
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
50
|
+
return undefined;
|
|
51
|
+
const model = parsed[key];
|
|
52
|
+
return typeof model === 'string' && model.trim() ? model.trim() : undefined;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// A malformed higher-precedence file must not prevent a usable lower-level
|
|
56
|
+
// default from appearing in the cockpit.
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function readRunnerModel(runner, repoRoot, env) {
|
|
61
|
+
const modelFiles = CONFIG_FILES.filter((def) => def.kind === 'settings' &&
|
|
62
|
+
def.runners.includes(runner) &&
|
|
63
|
+
def.modelKey !== undefined &&
|
|
64
|
+
def.modelPriority !== undefined).sort((a, b) => (b.modelPriority ?? 0) - (a.modelPriority ?? 0));
|
|
65
|
+
for (const def of modelFiles) {
|
|
66
|
+
const file = await readConfigFile(def.id, repoRoot, env);
|
|
67
|
+
if (!file || 'error' in file || !file.exists)
|
|
68
|
+
continue;
|
|
69
|
+
const model = modelFromContent(file.content, def.format, def.modelKey);
|
|
70
|
+
if (model)
|
|
71
|
+
return model;
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/** Read the current default model for each installed/configured coding agent. */
|
|
76
|
+
export async function readAgentModelDefaults(repoRoot, env = process.env) {
|
|
77
|
+
const entries = await Promise.all(['claude', 'codex', 'opencode'].map(async (runner) => [runner, await readRunnerModel(runner, repoRoot, env)]));
|
|
78
|
+
return Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/agent-config/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The server-side switch that makes native agent settings authoritative. */
|
|
2
|
+
export declare const AGENT_MODELS_LOCKED_ENV = "CEZ_AGENT_MODELS_LOCKED";
|
|
3
|
+
/** Only the exact value `1` enables the lock; unset keeps the current behavior. */
|
|
4
|
+
export declare function agentModelsLocked(env?: NodeJS.ProcessEnv): boolean;
|
|
5
|
+
export declare const AGENT_MODELS_LOCKED_ERROR = "agent models are locked \u2014 configure the model in the native coding-agent settings";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The server-side switch that makes native agent settings authoritative. */
|
|
2
|
+
export const AGENT_MODELS_LOCKED_ENV = 'CEZ_AGENT_MODELS_LOCKED';
|
|
3
|
+
/** Only the exact value `1` enables the lock; unset keeps the current behavior. */
|
|
4
|
+
export function agentModelsLocked(env = process.env) {
|
|
5
|
+
return env[AGENT_MODELS_LOCKED_ENV] === '1';
|
|
6
|
+
}
|
|
7
|
+
export const AGENT_MODELS_LOCKED_ERROR = 'agent models are locked — configure the model in the native coding-agent settings';
|
|
8
|
+
//# sourceMappingURL=agent-model-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-model-policy.js","sourceRoot":"","sources":["../../src/core/agent-model-policy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAEjE,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IACpE,OAAO,GAAG,CAAC,uBAAuB,CAAC,KAAK,GAAG,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GACpC,mFAAmF,CAAC"}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -306,10 +306,14 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
306
306
|
"/agent-config/:id": {
|
|
307
307
|
$put: {
|
|
308
308
|
output: {
|
|
309
|
-
|
|
309
|
+
id: string;
|
|
310
|
+
path: string;
|
|
311
|
+
exists: boolean;
|
|
312
|
+
content: string;
|
|
313
|
+
version: string | null;
|
|
310
314
|
};
|
|
311
315
|
outputFormat: "json";
|
|
312
|
-
status:
|
|
316
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
313
317
|
input: {
|
|
314
318
|
param: {
|
|
315
319
|
id: string;
|
|
@@ -317,14 +321,10 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
317
321
|
};
|
|
318
322
|
} | {
|
|
319
323
|
output: {
|
|
320
|
-
|
|
321
|
-
path: string;
|
|
322
|
-
exists: boolean;
|
|
323
|
-
content: string;
|
|
324
|
-
version: string | null;
|
|
324
|
+
error: string;
|
|
325
325
|
};
|
|
326
326
|
outputFormat: "json";
|
|
327
|
-
status:
|
|
327
|
+
status: 404;
|
|
328
328
|
input: {
|
|
329
329
|
param: {
|
|
330
330
|
id: string;
|
|
@@ -381,14 +381,6 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
381
381
|
} & {
|
|
382
382
|
"/workflows": {
|
|
383
383
|
$post: {
|
|
384
|
-
output: {
|
|
385
|
-
path: string;
|
|
386
|
-
name: string;
|
|
387
|
-
};
|
|
388
|
-
outputFormat: "json";
|
|
389
|
-
status: 201;
|
|
390
|
-
input: {};
|
|
391
|
-
} | {
|
|
392
384
|
output: {
|
|
393
385
|
error: string;
|
|
394
386
|
};
|
|
@@ -410,6 +402,14 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
410
402
|
outputFormat: "json";
|
|
411
403
|
status: 500;
|
|
412
404
|
input: {};
|
|
405
|
+
} | {
|
|
406
|
+
output: {
|
|
407
|
+
path: string;
|
|
408
|
+
name: string;
|
|
409
|
+
};
|
|
410
|
+
outputFormat: "json";
|
|
411
|
+
status: 201;
|
|
412
|
+
input: {};
|
|
413
413
|
};
|
|
414
414
|
};
|
|
415
415
|
} & {
|
|
@@ -419,7 +419,7 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
419
419
|
error: string;
|
|
420
420
|
};
|
|
421
421
|
outputFormat: "json";
|
|
422
|
-
status:
|
|
422
|
+
status: 404;
|
|
423
423
|
input: {
|
|
424
424
|
param: {
|
|
425
425
|
name: string;
|
|
@@ -430,7 +430,7 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
430
430
|
error: string;
|
|
431
431
|
};
|
|
432
432
|
outputFormat: "json";
|
|
433
|
-
status:
|
|
433
|
+
status: 400;
|
|
434
434
|
input: {
|
|
435
435
|
param: {
|
|
436
436
|
name: string;
|
|
@@ -583,10 +583,14 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
583
583
|
"/agent-config/:id": {
|
|
584
584
|
$put: {
|
|
585
585
|
output: {
|
|
586
|
-
|
|
586
|
+
id: string;
|
|
587
|
+
path: string;
|
|
588
|
+
exists: boolean;
|
|
589
|
+
content: string;
|
|
590
|
+
version: string | null;
|
|
587
591
|
};
|
|
588
592
|
outputFormat: "json";
|
|
589
|
-
status:
|
|
593
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
590
594
|
input: {
|
|
591
595
|
param: {
|
|
592
596
|
id: string;
|
|
@@ -594,14 +598,10 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
594
598
|
};
|
|
595
599
|
} | {
|
|
596
600
|
output: {
|
|
597
|
-
|
|
598
|
-
path: string;
|
|
599
|
-
exists: boolean;
|
|
600
|
-
content: string;
|
|
601
|
-
version: string | null;
|
|
601
|
+
error: string;
|
|
602
602
|
};
|
|
603
603
|
outputFormat: "json";
|
|
604
|
-
status:
|
|
604
|
+
status: 404;
|
|
605
605
|
input: {
|
|
606
606
|
param: {
|
|
607
607
|
id: string;
|
|
@@ -658,14 +658,6 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
658
658
|
} & {
|
|
659
659
|
"/workflows": {
|
|
660
660
|
$post: {
|
|
661
|
-
output: {
|
|
662
|
-
path: string;
|
|
663
|
-
name: string;
|
|
664
|
-
};
|
|
665
|
-
outputFormat: "json";
|
|
666
|
-
status: 201;
|
|
667
|
-
input: {};
|
|
668
|
-
} | {
|
|
669
661
|
output: {
|
|
670
662
|
error: string;
|
|
671
663
|
};
|
|
@@ -687,6 +679,14 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
687
679
|
outputFormat: "json";
|
|
688
680
|
status: 500;
|
|
689
681
|
input: {};
|
|
682
|
+
} | {
|
|
683
|
+
output: {
|
|
684
|
+
path: string;
|
|
685
|
+
name: string;
|
|
686
|
+
};
|
|
687
|
+
outputFormat: "json";
|
|
688
|
+
status: 201;
|
|
689
|
+
input: {};
|
|
690
690
|
};
|
|
691
691
|
};
|
|
692
692
|
} & {
|
|
@@ -696,7 +696,7 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
696
696
|
error: string;
|
|
697
697
|
};
|
|
698
698
|
outputFormat: "json";
|
|
699
|
-
status:
|
|
699
|
+
status: 404;
|
|
700
700
|
input: {
|
|
701
701
|
param: {
|
|
702
702
|
name: string;
|
|
@@ -707,7 +707,7 @@ export declare function createApp(deps: ServerDeps): import("hono/hono-base").Ho
|
|
|
707
707
|
error: string;
|
|
708
708
|
};
|
|
709
709
|
outputFormat: "json";
|
|
710
|
-
status:
|
|
710
|
+
status: 400;
|
|
711
711
|
input: {
|
|
712
712
|
param: {
|
|
713
713
|
name: string;
|
package/dist/server/server.js
CHANGED
|
@@ -9,6 +9,7 @@ import { streamSSE } from 'hono/streaming';
|
|
|
9
9
|
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { detectEnvironment } from '../core/backend-detect.js';
|
|
12
|
+
import { AGENT_MODELS_LOCKED_ERROR, agentModelsLocked } from '../core/agent-model-policy.js';
|
|
12
13
|
import { discoverCodexModels } from '../core/codex-model-catalog.js';
|
|
13
14
|
import { PROVIDER_IDS, ProviderAuthService, } from '../core/provider-auth.js';
|
|
14
15
|
import { applyProviderEnablement } from '../core/provider-availability.js';
|
|
@@ -30,6 +31,7 @@ import { collectChanges, collectCommitChanges, collectRunCommits, commitAll, cre
|
|
|
30
31
|
import { gatedSkillsRepos, loadConfig, resolveWorktreeRetention } from '../config.js';
|
|
31
32
|
import { findConfigFile } from '../agent-config/catalog.js';
|
|
32
33
|
import { readConfigFile, writeConfigFile } from '../agent-config/files.js';
|
|
34
|
+
import { readAgentModelDefaults } from '../agent-config/models.js';
|
|
33
35
|
import { listAgentConfig } from '../agent-config/service.js';
|
|
34
36
|
import { PROJECT_ID_RE, defaultWorkspaceConfig, effectiveSkillsAutoUpdate, loadWorkspaceConfig, mergeWriteWorkspaceConfig, effectiveComposerDefault, } from '../workspace/config.js';
|
|
35
37
|
import { allocateProjectSlug, listProjects, probeProjectStatus, registerProject, removeProject, shouldRegisterProject, } from '../workspace/projects.js';
|
|
@@ -1942,6 +1944,9 @@ export function createApp(deps) {
|
|
|
1942
1944
|
if (!parsed.success) {
|
|
1943
1945
|
return c.json({ error: parsed.error.issues.map((i) => i.message).join('; ') }, 400);
|
|
1944
1946
|
}
|
|
1947
|
+
if (agentModelsLocked() && parsed.data?.model?.trim()) {
|
|
1948
|
+
return c.json({ error: AGENT_MODELS_LOCKED_ERROR }, 409);
|
|
1949
|
+
}
|
|
1945
1950
|
let workflow;
|
|
1946
1951
|
if (parsed.data.steps) {
|
|
1947
1952
|
// Inline chain (spec 008): an approved plan runs as an ad-hoc workflow.
|
|
@@ -2293,6 +2298,9 @@ export function createApp(deps) {
|
|
|
2293
2298
|
if (!parsed.success) {
|
|
2294
2299
|
return c.json({ error: parsed.error.issues.map((i) => i.message).join('; ') }, 400);
|
|
2295
2300
|
}
|
|
2301
|
+
if (agentModelsLocked() && parsed.data?.model?.trim()) {
|
|
2302
|
+
return c.json({ error: AGENT_MODELS_LOCKED_ERROR }, 409);
|
|
2303
|
+
}
|
|
2296
2304
|
const blocked = await providerActionError([providerForExistingRun(run, parsed.data.runner)]);
|
|
2297
2305
|
if (blocked)
|
|
2298
2306
|
return c.json({ error: blocked }, 409);
|
|
@@ -2768,6 +2776,9 @@ export function createApp(deps) {
|
|
|
2768
2776
|
if (!parsed.success) {
|
|
2769
2777
|
return c.json({ error: parsed.error.issues.map((i) => i.message).join('; ') }, 400);
|
|
2770
2778
|
}
|
|
2779
|
+
if (agentModelsLocked() && parsed.data?.model?.trim()) {
|
|
2780
|
+
return c.json({ error: AGENT_MODELS_LOCKED_ERROR }, 409);
|
|
2781
|
+
}
|
|
2771
2782
|
if (todo.startedTaskId)
|
|
2772
2783
|
return c.json({ error: 'already started' }, 409);
|
|
2773
2784
|
let task = todoTaskText(todo);
|
|
@@ -3168,24 +3179,35 @@ export function createApp(deps) {
|
|
|
3168
3179
|
});
|
|
3169
3180
|
// The Settings → Agents knobs in one read (R6 Step 1.5) — an ADDITIVE
|
|
3170
3181
|
// sibling of PUT /api/config below; /api/health keeps its protected shape.
|
|
3171
|
-
const configAnswer = (config) =>
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3182
|
+
const configAnswer = async (repoRoot, config) => {
|
|
3183
|
+
const nativeModels = await readAgentModelDefaults(repoRoot);
|
|
3184
|
+
return {
|
|
3185
|
+
baseBranch: config.baseBranch ?? null,
|
|
3186
|
+
defaultRunner: config.defaultRunner,
|
|
3187
|
+
systemPrompt: config.systemPrompt ?? null,
|
|
3188
|
+
// Native settings are the initial/default source. In locked mode they are
|
|
3189
|
+
// authoritative; otherwise a Cezar preset remains an explicit override.
|
|
3190
|
+
defaultModels: agentModelsLocked()
|
|
3191
|
+
? nativeModels
|
|
3192
|
+
: { ...nativeModels, ...(config.defaultModels ?? {}) },
|
|
3193
|
+
modelsLocked: agentModelsLocked(),
|
|
3194
|
+
maxParallel: config.maxParallel,
|
|
3195
|
+
memoryLimitMb: config.memoryLimitMb ?? null,
|
|
3196
|
+
// Count-based worktree retention (#483): keep the last N finished worktrees
|
|
3197
|
+
// on disk. 0 = unlimited. Always materialized (schema default 10).
|
|
3198
|
+
worktreeRetention: config.worktreeRetention,
|
|
3199
|
+
// Live title updates (task auto-naming spec): tri-state — null means "no
|
|
3200
|
+
// config key, the CEZ_TITLE_UPDATES env default (ON) decides".
|
|
3201
|
+
liveTitleUpdates: config.liveTitleUpdates ?? null,
|
|
3202
|
+
// Optional review gate (#489): tri-state — null means "no config key, the
|
|
3203
|
+
// CEZ_REVIEW_GATE env default (OFF) decides".
|
|
3204
|
+
reviewGate: config.reviewGate ?? null,
|
|
3205
|
+
};
|
|
3206
|
+
};
|
|
3207
|
+
api.get('/config', async (c) => {
|
|
3208
|
+
const repoRoot = c.get('project').root;
|
|
3209
|
+
return c.json(await configAnswer(repoRoot, await loadConfig(repoRoot)));
|
|
3210
|
+
});
|
|
3189
3211
|
// Set/clear the agents' config knobs (Settings → Agents; the Repo tab's
|
|
3190
3212
|
// base-branch picker). Merges into the RAW config.json so user keys
|
|
3191
3213
|
// (skillsRepos…) survive and schema defaults are never materialized into
|
|
@@ -3224,6 +3246,9 @@ export function createApp(deps) {
|
|
|
3224
3246
|
if (!parsed.success) {
|
|
3225
3247
|
return c.json({ error: parsed.error.issues.map((i) => i.message).join('; ') }, 400);
|
|
3226
3248
|
}
|
|
3249
|
+
if (agentModelsLocked() && parsed.data.defaultModels !== undefined) {
|
|
3250
|
+
return c.json({ error: AGENT_MODELS_LOCKED_ERROR }, 409);
|
|
3251
|
+
}
|
|
3227
3252
|
const configPath = join(dataDir, 'config.json');
|
|
3228
3253
|
let raw = {};
|
|
3229
3254
|
try {
|
|
@@ -3308,7 +3333,7 @@ export function createApp(deps) {
|
|
|
3308
3333
|
return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
|
|
3309
3334
|
}
|
|
3310
3335
|
// Pre-R6 answer shape ({baseBranch, defaultRunner}) + additive R6 fields.
|
|
3311
|
-
return c.json(configAnswer(await loadConfig(repoRoot)));
|
|
3336
|
+
return c.json(await configAnswer(repoRoot, await loadConfig(repoRoot)));
|
|
3312
3337
|
});
|
|
3313
3338
|
const setAgentConfigSchema = z.object({
|
|
3314
3339
|
content: z.string().max(2_000_000),
|