mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 23:49:41 +02:00
feat: inject effort as soft default via CLI flags instead of env var (#104)
CLAUDE_CODE_EFFORT_LEVEL hard-locks effort for the whole session and makes
Claude reject in-session /effort switching (incl. ultracode). Carry effort
as a dedicated payload field instead, injected at spawn as a soft default:
- regular levels (incl. max) -> claude --effort <level>
(the settings effortLevel key is enum([low,medium,high,xhigh]) with
.catch(undefined), so max would be silently dropped there)
- ultracode -> claude --settings '{"ultracode":true}'
(dedicated boolean settings key, rejected by the --effort flag)
Changes:
- add effort enum field to create/quick-start/ralph-loop schemas and thread
it through Session -> CreateSessionOptions/RespawnPaneOptions -> spawn
- buildEffortCliArgs() in session-cli-builder, shared by tmux spawn command
and direct-PTY fallback args
- frontend: buildEnvOverrides() no longer emits CLAUDE_CODE_EFFORT_LEVEL;
validated effort goes into payloads via getEffortSetting()
- settings UI: add Ultracode option to the Thinking Effort dropdown
- legacy migration: Session constructor extracts CLAUDE_CODE_EFFORT_LEVEL
from persisted envOverrides; applyEnvOverrides() unsets the stale tmux
session var so respawned panes are no longer locked
- tests: test/effort-injection.test.ts (13 cases)
Co-authored-by: Teigen <teigenzhang@gmail.com>
This commit is contained in:
@@ -22,12 +22,24 @@ Object.assign(CodemanApp.prototype, {
|
||||
if (caseSettings?.agentTeams || globalSettings?.agentTeamsEnabled) {
|
||||
env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';
|
||||
}
|
||||
if (globalSettings?.thinkingEffort) {
|
||||
env.CLAUDE_CODE_EFFORT_LEVEL = globalSettings.thinkingEffort;
|
||||
}
|
||||
// NOTE: thinkingEffort is intentionally NOT emitted as CLAUDE_CODE_EFFORT_LEVEL —
|
||||
// the env var hard-locks effort and blocks in-session /effort switching (e.g.,
|
||||
// ultracode). It flows as the dedicated `effort` payload field instead, which the
|
||||
// backend injects as a `--settings` soft default. See getEffortSetting().
|
||||
return env;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resolve the effort level for new sessions from global settings.
|
||||
* Returns a valid effort string or undefined (= no override, CLI default).
|
||||
* Sent as the `effort` payload field — backend turns it into `claude --settings ...`.
|
||||
*/
|
||||
getEffortSetting(globalSettings) {
|
||||
const effort = globalSettings?.thinkingEffort;
|
||||
const valid = ['low', 'medium', 'high', 'xhigh', 'max', 'ultracode'];
|
||||
return valid.includes(effort) ? effort : undefined;
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// Quick Start
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
@@ -337,6 +349,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
const globalSettings = this.loadAppSettingsFromStorage();
|
||||
const envOverrides = this.buildEnvOverrides(caseSettings, globalSettings);
|
||||
const hasEnvOverrides = Object.keys(envOverrides).length > 0;
|
||||
const effort = this.getEffortSetting(globalSettings);
|
||||
const useOpus1m = caseSettings.opusContext1m || globalSettings.opusContext1mEnabled;
|
||||
const modelOverride = useOpus1m ? 'opus[1m]' : '';
|
||||
|
||||
@@ -349,6 +362,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
body: JSON.stringify({
|
||||
workingDir, name,
|
||||
...(hasEnvOverrides ? { envOverrides } : {}),
|
||||
...(effort ? { effort } : {}),
|
||||
...(modelOverride !== undefined ? { modelOverride } : {}),
|
||||
})
|
||||
}).then(r => r.json())
|
||||
@@ -538,7 +552,8 @@ Object.assign(CodemanApp.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
// Quick-start with opencode mode (auto-allow tools by default)
|
||||
// Quick-start with opencode mode (auto-allow tools by default).
|
||||
// No `effort` field — it's Claude-specific (OpenCode has no /effort).
|
||||
const envOverrides = this.buildEnvOverrides(this.getCaseSettings(caseName), this.loadAppSettingsFromStorage());
|
||||
const res = await fetch('/api/quick-start', {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user