automata-cli 0.1.0-feature-032-message-tool-model.252 → 0.1.0-feature-032-message-tool-model.258

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.
@@ -152,6 +152,8 @@ function ConfigWizard() {
152
152
  );
153
153
  const [doWorkClaudeModel, setDoWorkClaudeModel] = useState(existing.doWork?.models?.claude ?? "");
154
154
  const [doWorkCodexModel, setDoWorkCodexModel] = useState(existing.doWork?.models?.codex ?? "");
155
+ const [doWorkClaudeEffort, setDoWorkClaudeEffort] = useState(existing.doWork?.effort?.claude ?? "");
156
+ const [doWorkCodexEffort, setDoWorkCodexEffort] = useState(existing.doWork?.effort?.codex ?? "");
155
157
  const [doWorkLockStale, setDoWorkLockStale] = useState(
156
158
  String(existing.doWork?.lockStaleMinutes ?? DEFAULT_DO_WORK.lockStaleMinutes)
157
159
  );
@@ -269,13 +271,23 @@ function ConfigWizard() {
269
271
  },
270
272
  "do-work-claude-model": {
271
273
  setValue: setDoWorkClaudeModel,
272
- onSubmit: () => setScreen("do-work-codex-model"),
274
+ onSubmit: () => setScreen("do-work-claude-effort"),
273
275
  onBack: () => setScreen("do-work-executor")
274
276
  },
277
+ "do-work-claude-effort": {
278
+ setValue: setDoWorkClaudeEffort,
279
+ onSubmit: () => setScreen("do-work-codex-model"),
280
+ onBack: () => setScreen("do-work-claude-model")
281
+ },
275
282
  "do-work-codex-model": {
276
283
  setValue: setDoWorkCodexModel,
284
+ onSubmit: () => setScreen("do-work-codex-effort"),
285
+ onBack: () => setScreen("do-work-claude-effort")
286
+ },
287
+ "do-work-codex-effort": {
288
+ setValue: setDoWorkCodexEffort,
277
289
  onSubmit: () => setScreen("do-work-max-runs"),
278
- onBack: () => setScreen("do-work-claude-model")
290
+ onBack: () => setScreen("do-work-codex-model")
279
291
  },
280
292
  "do-work-max-runs": {
281
293
  setValue: (update) => {
@@ -291,7 +303,7 @@ function ConfigWizard() {
291
303
  setValidationError("");
292
304
  setScreen("do-work-lock-stale");
293
305
  },
294
- onBack: () => setScreen("do-work-codex-model")
306
+ onBack: () => setScreen("do-work-codex-effort")
295
307
  },
296
308
  "do-work-lock-stale": {
297
309
  setValue: (update) => {
@@ -317,6 +329,10 @@ function ConfigWizard() {
317
329
  claude: doWorkClaudeModel.trim() || void 0,
318
330
  codex: doWorkCodexModel.trim() || void 0
319
331
  },
332
+ effort: {
333
+ claude: doWorkClaudeEffort.trim() || void 0,
334
+ codex: doWorkCodexEffort.trim() || void 0
335
+ },
320
336
  maxRunsPerTick: maxRuns ?? void 0,
321
337
  lockStaleMinutes: parsed
322
338
  }
@@ -470,12 +486,24 @@ function ConfigWizard() {
470
486
  value: doWorkClaudeModel,
471
487
  hint: `Type model \xB7 Enter to continue \xB7 ${BACK}`
472
488
  },
489
+ "do-work-claude-effort": {
490
+ title: "Do Work \u2014 Claude Effort",
491
+ label: "Default reasoning effort when the executor is Claude (blank = the executor's own default):",
492
+ value: doWorkClaudeEffort,
493
+ hint: `Type effort \xB7 Enter to continue \xB7 ${BACK}`
494
+ },
473
495
  "do-work-codex-model": {
474
496
  title: "Do Work \u2014 Codex Model",
475
497
  label: "Default model when the executor is Codex (blank = the executor's own default):",
476
498
  value: doWorkCodexModel,
477
499
  hint: `Type model \xB7 Enter to continue \xB7 ${BACK}`
478
500
  },
501
+ "do-work-codex-effort": {
502
+ title: "Do Work \u2014 Codex Effort",
503
+ label: "Default reasoning effort when the executor is Codex (blank = the executor's own default):",
504
+ value: doWorkCodexEffort,
505
+ hint: `Type effort \xB7 Enter to continue \xB7 ${BACK}`
506
+ },
479
507
  "do-work-max-runs": {
480
508
  title: "Do Work \u2014 Max Runs Per Tick",
481
509
  label: "Model runs allowed per tick (0 = unlimited):",
package/dist/index.js CHANGED
@@ -34,9 +34,9 @@ function writeDoWork(patch) {
34
34
  writeConfig({ ...current, doWork: { ...current.doWork, ...patch } });
35
35
  }
36
36
  function parseNonNegativeInt(value, label) {
37
- const trimmed = value.trim();
38
- const parsed = Number.parseInt(trimmed, 10);
39
- if (Number.isNaN(parsed) || parsed < 0 || String(parsed) !== trimmed || !Number.isSafeInteger(parsed)) {
37
+ const trimmed2 = value.trim();
38
+ const parsed = Number.parseInt(trimmed2, 10);
39
+ if (Number.isNaN(parsed) || parsed < 0 || String(parsed) !== trimmed2 || !Number.isSafeInteger(parsed)) {
40
40
  process.stderr.write(`Error: ${label} must be a non-negative integer (got "${value}").
41
41
  `);
42
42
  process.exit(1);
@@ -147,6 +147,24 @@ var configSetDoWorkModel = new Command("do-work-model").description("Set the def
147
147
  process.stdout.write(`do-work ${executor} model set to: ${model}
148
148
  `);
149
149
  });
150
+ var configSetDoWorkEffort = new Command("do-work-effort").description("Set the default reasoning effort `do-work` passes to one executor").argument("<executor>", `Executor: ${VALID_EXECUTORS.join(", ")}`).argument("<value>", "Effort level, forwarded to the executor unchanged").action((executor, value) => {
151
+ if (!VALID_EXECUTORS.includes(executor)) {
152
+ process.stderr.write(
153
+ `Error: invalid executor "${executor}". Must be one of: ${VALID_EXECUTORS.join(", ")}
154
+ `
155
+ );
156
+ process.exit(1);
157
+ }
158
+ const effort = value.trim();
159
+ if (effort.length === 0) {
160
+ process.stderr.write("Error: do-work-effort requires a non-empty effort level.\n");
161
+ process.exit(1);
162
+ }
163
+ const current = readRawConfig();
164
+ writeDoWork({ effort: { ...current.doWork?.effort, [executor]: effort } });
165
+ process.stdout.write(`do-work ${executor} effort set to: ${effort}
166
+ `);
167
+ });
150
168
  var configSetDoWorkMaxRuns = new Command("do-work-max-runs").description("Set the maximum number of model runs `do-work` performs per tick (0 = unlimited)").argument("<value>", "Non-negative integer").action((value) => {
151
169
  const maxRunsPerTick = parseNonNegativeInt(value, "do-work-max-runs");
152
170
  writeDoWork({ maxRunsPerTick });
@@ -189,12 +207,12 @@ var configSetDoWorkPrompt = new Command("do-work-prompt").description("Set the t
189
207
  process.stdout.write(`do-work ${turnKind} prompt set.
190
208
  `);
191
209
  });
192
- var configSet = new Command("set").description("Set a configuration value").addCommand(configSetType).addCommand(configSetIssueDiscoveryTechnique).addCommand(configSetIssueDiscoveryValue).addCommand(configSetClaudeSystemPrompt).addCommand(configSetAllowedUsers).addCommand(configSetAgentUser).addCommand(configSetDoWorkBaseBranch).addCommand(configSetDoWorkProtectedBranches).addCommand(configSetDoWorkExecutor).addCommand(configSetDoWorkModel).addCommand(configSetDoWorkMaxRuns).addCommand(configSetDoWorkLockStaleMinutes).addCommand(configSetDoWorkPrompt);
210
+ var configSet = new Command("set").description("Set a configuration value").addCommand(configSetType).addCommand(configSetIssueDiscoveryTechnique).addCommand(configSetIssueDiscoveryValue).addCommand(configSetClaudeSystemPrompt).addCommand(configSetAllowedUsers).addCommand(configSetAgentUser).addCommand(configSetDoWorkBaseBranch).addCommand(configSetDoWorkProtectedBranches).addCommand(configSetDoWorkExecutor).addCommand(configSetDoWorkModel).addCommand(configSetDoWorkEffort).addCommand(configSetDoWorkMaxRuns).addCommand(configSetDoWorkLockStaleMinutes).addCommand(configSetDoWorkPrompt);
193
211
  var configCommand = new Command("config").description("Configure automata settings").addCommand(configSet).action(async () => {
194
212
  const [{ render }, React, { ConfigWizard }] = await Promise.all([
195
213
  import("ink"),
196
214
  import("react"),
197
- import("./ConfigWizard-J67TY22Z.js")
215
+ import("./ConfigWizard-HDHKPY6J.js")
198
216
  ]);
199
217
  const { waitUntilExit } = render(React.createElement(ConfigWizard));
200
218
  await waitUntilExit();
@@ -1539,6 +1557,15 @@ function handleExitCode(status, toolName) {
1539
1557
  process.exit(status);
1540
1558
  }
1541
1559
  }
1560
+ function resolveEffortOption(value) {
1561
+ if (value === void 0) return void 0;
1562
+ const trimmed2 = value.trim();
1563
+ if (trimmed2.length === 0) {
1564
+ process.stderr.write("Error: --effort must be a non-empty level.\n");
1565
+ process.exit(1);
1566
+ }
1567
+ return trimmed2;
1568
+ }
1542
1569
 
1543
1570
  // src/cli/childRegistry.ts
1544
1571
  var active = /* @__PURE__ */ new Set();
@@ -1595,6 +1622,7 @@ function buildClaudeArgs(prompt, options = {}) {
1595
1622
  const args = [];
1596
1623
  if (options.yolo) args.push("--dangerously-skip-permissions");
1597
1624
  if (options.model) args.push("--model", options.model);
1625
+ if (options.effort) args.push("--effort", options.effort);
1598
1626
  if (options.verbose) args.push("--verbose", "--output-format", "stream-json");
1599
1627
  args.push("-p", prompt);
1600
1628
  return args;
@@ -1602,7 +1630,12 @@ function buildClaudeArgs(prompt, options = {}) {
1602
1630
  function runClaude(prompt, options = {}) {
1603
1631
  return new Promise((resolve2, reject) => {
1604
1632
  const claudeBin = resolveCommand("claude");
1605
- const args = buildClaudeArgs(prompt, { yolo: true, model: options.model, verbose: true });
1633
+ const args = buildClaudeArgs(prompt, {
1634
+ yolo: true,
1635
+ model: options.model,
1636
+ effort: options.effort,
1637
+ verbose: true
1638
+ });
1606
1639
  const child = spawn(claudeBin, args, { stdio: ["inherit", "pipe", "inherit"] });
1607
1640
  trackChild(child);
1608
1641
  const rl = createInterface({ input: child.stdout });
@@ -1639,21 +1672,21 @@ function runClaude(prompt, options = {}) {
1639
1672
  }
1640
1673
  function invokeClaudeCode(prompt, options = {}) {
1641
1674
  if (options.verbose) {
1642
- return invokeClaudeCodeVerbose(prompt, options.yolo ?? false, options.model);
1675
+ return invokeClaudeCodeVerbose(prompt, options.yolo ?? false, options.model, options.effort);
1643
1676
  }
1644
- invokeClaudeCodeSync(prompt, options.yolo ?? false, options.model);
1677
+ invokeClaudeCodeSync(prompt, options.yolo ?? false, options.model, options.effort);
1645
1678
  }
1646
- function invokeClaudeCodeSync(prompt, yolo, model) {
1679
+ function invokeClaudeCodeSync(prompt, yolo, model, effort) {
1647
1680
  const claudeBin = resolveCommand("claude");
1648
- const args = buildClaudeArgs(prompt, { yolo, model, verbose: false });
1681
+ const args = buildClaudeArgs(prompt, { yolo, model, effort, verbose: false });
1649
1682
  const result = spawnSync4(claudeBin, args, { encoding: "utf8", stdio: "inherit" });
1650
1683
  handleSpawnError(result.error, "claude");
1651
1684
  handleExitCode(result.status, "Claude Code");
1652
1685
  }
1653
- function invokeClaudeCodeVerbose(prompt, yolo, model) {
1686
+ function invokeClaudeCodeVerbose(prompt, yolo, model, effort) {
1654
1687
  return new Promise((resolve2) => {
1655
1688
  const claudeBin = resolveCommand("claude");
1656
- const args = buildClaudeArgs(prompt, { yolo, model, verbose: true });
1689
+ const args = buildClaudeArgs(prompt, { yolo, model, effort, verbose: true });
1657
1690
  const child = spawn(claudeBin, args, { stdio: ["inherit", "pipe", "inherit"] });
1658
1691
  const rl = createInterface({ input: child.stdout });
1659
1692
  let turnCount = 0;
@@ -1753,10 +1786,14 @@ function summarizeTool(name, input) {
1753
1786
 
1754
1787
  // src/codex/codexService.ts
1755
1788
  import { spawn as spawn2, spawnSync as spawnSync5 } from "child_process";
1789
+ function toTomlBasicString(value) {
1790
+ return JSON.stringify(value);
1791
+ }
1756
1792
  function buildCodexArgs(prompt, options = {}) {
1757
1793
  const args = ["exec"];
1758
1794
  if (options.yolo) args.push("--dangerously-bypass-approvals-and-sandbox");
1759
1795
  if (options.model) args.push("--model", options.model);
1796
+ if (options.effort) args.push("-c", `model_reasoning_effort=${toTomlBasicString(options.effort)}`);
1760
1797
  args.push(prompt);
1761
1798
  return args;
1762
1799
  }
@@ -1764,11 +1801,11 @@ function invokeCodexCode(prompt, options = {}) {
1764
1801
  if (options.verbose) {
1765
1802
  process.stderr.write("Warning: --verbose is not supported for Codex and will be ignored.\n");
1766
1803
  }
1767
- invokeCodexCodeSync(prompt, options.yolo ?? false, options.model);
1804
+ invokeCodexCodeSync(prompt, options.yolo ?? false, options.model, options.effort);
1768
1805
  }
1769
- function invokeCodexCodeSync(prompt, yolo, model) {
1806
+ function invokeCodexCodeSync(prompt, yolo, model, effort) {
1770
1807
  const codexBin = resolveCommand("codex");
1771
- const args = buildCodexArgs(prompt, { yolo, model });
1808
+ const args = buildCodexArgs(prompt, { yolo, model, effort });
1772
1809
  const result = spawnSync5(codexBin, args, { encoding: "utf8", stdio: "inherit" });
1773
1810
  handleSpawnError(result.error, "codex");
1774
1811
  handleExitCode(result.status, "Codex");
@@ -1776,7 +1813,7 @@ function invokeCodexCodeSync(prompt, yolo, model) {
1776
1813
  function runCodex(prompt, options = {}) {
1777
1814
  return new Promise((resolve2, reject) => {
1778
1815
  const codexBin = resolveCommand("codex");
1779
- const args = buildCodexArgs(prompt, { yolo: true, model: options.model });
1816
+ const args = buildCodexArgs(prompt, { yolo: true, model: options.model, effort: options.effort });
1780
1817
  const child = spawn2(codexBin, args, { stdio: "inherit" });
1781
1818
  trackChild(child);
1782
1819
  child.on("error", (err) => {
@@ -1881,7 +1918,7 @@ Title: ${issue.title}
1881
1918
  }
1882
1919
  return issue;
1883
1920
  }
1884
- var implementNextCommand = new Command3("implement-next").description("Find the next open GitHub issue matching the configured filter, claim it, and invoke the AI code assistant (Claude or Codex)").option("--json", "Output issue details as JSON").option("--no-claude", "Skip all AI invocation (Claude or Codex) after claiming the issue").option("--with <executor>", "Executor to use: claude or codex", "claude").option("--query-only", "Print issue content and exit without claiming or invoking any AI tools").option("--yolo", "Launch with --dangerously-skip-permissions (Claude) or --dangerously-bypass-approvals-and-sandbox (Codex)").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--model <string>", "Model identifier to pass to the executor").option("--take-first", "When multiple issues match, pick the first without prompting").option("--limit <n>", "Max issues to fetch and display (default: 10)", "10").option("--ask-copilot-review", "Request a Copilot code review on the PR after AI invocation finishes").action(async (options) => {
1921
+ var implementNextCommand = new Command3("implement-next").description("Find the next open GitHub issue matching the configured filter, claim it, and invoke the AI code assistant (Claude or Codex)").option("--json", "Output issue details as JSON").option("--no-claude", "Skip all AI invocation (Claude or Codex) after claiming the issue").option("--with <executor>", "Executor to use: claude or codex", "claude").option("--query-only", "Print issue content and exit without claiming or invoking any AI tools").option("--yolo", "Launch with --dangerously-skip-permissions (Claude) or --dangerously-bypass-approvals-and-sandbox (Codex)").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--model <string>", "Model identifier to pass to the executor").option("--effort <level>", "Reasoning effort to pass to the executor").option("--take-first", "When multiple issues match, pick the first without prompting").option("--limit <n>", "Max issues to fetch and display (default: 10)", "10").option("--ask-copilot-review", "Request a Copilot code review on the PR after AI invocation finishes").action(async (options) => {
1885
1922
  const config = readConfig();
1886
1923
  validateConfig(config);
1887
1924
  const limit = Number.parseInt(options.limit, 10);
@@ -1919,6 +1956,7 @@ ${issue.body}
1919
1956
  `);
1920
1957
  process.exit(1);
1921
1958
  }
1959
+ const effort = resolveEffortOption(options.effort);
1922
1960
  if (options.claude !== false) {
1923
1961
  const systemPrompt = config.claudeSystemPrompt ?? DEFAULT_CLAUDE_SYSTEM_PROMPT;
1924
1962
  const prompt = `Resolving issue #${issue.number}:
@@ -1930,9 +1968,14 @@ ${issue.body}`;
1930
1968
  if (options.silent) {
1931
1969
  process.stderr.write("Warning: --silent is only supported with Claude and has no effect when used with Codex.\n");
1932
1970
  }
1933
- invokeCodexCode(prompt, { yolo: options.yolo, model: options.model });
1971
+ invokeCodexCode(prompt, { yolo: options.yolo, model: options.model, effort });
1934
1972
  } else {
1935
- await invokeClaudeCode(prompt, { yolo: options.yolo, verbose: !options.silent, model: options.model });
1973
+ await invokeClaudeCode(prompt, {
1974
+ yolo: options.yolo,
1975
+ verbose: !options.silent,
1976
+ model: options.model,
1977
+ effort
1978
+ });
1936
1979
  }
1937
1980
  }
1938
1981
  linkPrToIssue(issue.number, commentUrl, options.askCopilotReview === true);
@@ -2021,7 +2064,7 @@ async function resolvePrompt(options) {
2021
2064
  process.stderr.write("Error: No prompt provided. Use --prompt, --file-prompt, or pipe via stdin.\n");
2022
2065
  process.exit(1);
2023
2066
  }
2024
- var executeCommand = new Command4("execute").description("Delegate work to an AI executor").requiredOption("--with <executor>", "Executor to use: claude or codex").option("--prompt <string>", "Prompt to send to the executor").option("--file-prompt <path>", "Path to a file whose content is used as the prompt").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--model <string>", "Model identifier to pass to the executor").action(async (options) => {
2067
+ var executeCommand = new Command4("execute").description("Delegate work to an AI executor").requiredOption("--with <executor>", "Executor to use: claude or codex").option("--prompt <string>", "Prompt to send to the executor").option("--file-prompt <path>", "Path to a file whose content is used as the prompt").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--model <string>", "Model identifier to pass to the executor").option("--effort <level>", "Reasoning effort to pass to the executor").action(async (options) => {
2025
2068
  const executor = options.with.toLowerCase();
2026
2069
  if (executor !== "claude" && executor !== "codex") {
2027
2070
  process.stderr.write(`Error: --with must be 'claude' or 'codex', got '${options.with}'.
@@ -2029,10 +2072,16 @@ var executeCommand = new Command4("execute").description("Delegate work to an AI
2029
2072
  process.exit(1);
2030
2073
  }
2031
2074
  const prompt = await resolvePrompt(options);
2075
+ const effort = resolveEffortOption(options.effort);
2032
2076
  if (executor === "codex") {
2033
- invokeCodexCode(prompt, { yolo: true, model: options.model });
2077
+ invokeCodexCode(prompt, { yolo: true, model: options.model, effort });
2034
2078
  } else {
2035
- await invokeClaudeCode(prompt, { yolo: true, verbose: !options.silent, model: options.model });
2079
+ await invokeClaudeCode(prompt, {
2080
+ yolo: true,
2081
+ verbose: !options.silent,
2082
+ model: options.model,
2083
+ effort
2084
+ });
2036
2085
  }
2037
2086
  });
2038
2087
 
@@ -2154,7 +2203,7 @@ function pluralSuffix(count) {
2154
2203
  return count === 1 ? "" : "s";
2155
2204
  }
2156
2205
  function addAiOptions(cmd) {
2157
- return cmd.requiredOption("--with <executor>", "Executor to use: claude or codex").option("--model <string>", "Model identifier to pass to the executor").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--push", "Append instruction to commit and push changes after the AI finishes");
2206
+ return cmd.requiredOption("--with <executor>", "Executor to use: claude or codex").option("--model <string>", "Model identifier to pass to the executor").option("--effort <level>", "Reasoning effort to pass to the executor").option("--silent", "Suppress step-by-step Claude output; show only the final summary").option("--push", "Append instruction to commit and push changes after the AI finishes");
2158
2207
  }
2159
2208
  function resolveExecutor2(withOption) {
2160
2209
  const executor = withOption.toLowerCase();
@@ -2166,11 +2215,17 @@ function resolveExecutor2(withOption) {
2166
2215
  return executor;
2167
2216
  }
2168
2217
  function invokeSelectedExecutor(prompt, executor, options) {
2218
+ const effort = resolveEffortOption(options.effort);
2169
2219
  if (executor === "codex") {
2170
- invokeCodexCode(prompt, { yolo: true, model: options.model });
2220
+ invokeCodexCode(prompt, { yolo: true, model: options.model, effort });
2171
2221
  return;
2172
2222
  }
2173
- return invokeClaudeCode(prompt, { yolo: true, verbose: !options.silent, model: options.model });
2223
+ return invokeClaudeCode(prompt, {
2224
+ yolo: true,
2225
+ verbose: !options.silent,
2226
+ model: options.model,
2227
+ effort
2228
+ });
2174
2229
  }
2175
2230
  var executeSonarCmd = addAiOptions(
2176
2231
  new Command5("sonar").description(
@@ -2965,6 +3020,17 @@ function triggeringMessage(item) {
2965
3020
  function isExecutor(value) {
2966
3021
  return VALID_TOOLS.includes(value);
2967
3022
  }
3023
+ function trimmed(value) {
3024
+ if (value === void 0) return void 0;
3025
+ const cleaned = value.trim();
3026
+ return cleaned.length === 0 ? void 0 : cleaned;
3027
+ }
3028
+ function resolvePerExecutor(option, configured, switched) {
3029
+ if (!switched && option !== void 0) return { value: option, source: "option" };
3030
+ const fromConfig = trimmed(configured);
3031
+ if (fromConfig !== void 0) return { value: fromConfig, source: "config" };
3032
+ return { value: void 0, source: "none" };
3033
+ }
2968
3034
  function resolveExecution(input) {
2969
3035
  const { directive, withOption, modelOption, configExecutor, configModels } = input;
2970
3036
  if (directive.tool !== void 0 && !isExecutor(directive.tool)) {
@@ -2975,22 +3041,25 @@ function resolveExecution(input) {
2975
3041
  const executor = directive.tool ?? baseline;
2976
3042
  const executorSource = directive.tool === void 0 ? baselineSource : "message";
2977
3043
  const switched = directive.tool !== void 0 && directive.tool !== baseline;
3044
+ const effort = resolvePerExecutor(input.effortOption, input.configEfforts?.[executor], switched);
3045
+ const common = {
3046
+ ok: true,
3047
+ executor,
3048
+ executorSource,
3049
+ effort: effort.value,
3050
+ effortSource: effort.source
3051
+ };
2978
3052
  if (directive.model !== void 0) {
2979
- return { ok: true, executor, executorSource, model: directive.model, modelSource: "message" };
3053
+ return { ...common, model: directive.model, modelSource: "message" };
2980
3054
  }
2981
- const configModel = configModels?.[executor];
2982
- if (!switched && modelOption !== void 0) {
2983
- return { ok: true, executor, executorSource, model: modelOption, modelSource: "option" };
2984
- }
2985
- if (configModel !== void 0) {
2986
- return { ok: true, executor, executorSource, model: configModel, modelSource: "config" };
2987
- }
2988
- return { ok: true, executor, executorSource, model: void 0, modelSource: "none" };
3055
+ const model = resolvePerExecutor(modelOption, configModels?.[executor], switched);
3056
+ return { ...common, model: model.value, modelSource: model.source };
2989
3057
  }
2990
3058
  function describeExecution(execution) {
2991
3059
  const model = execution.model === void 0 ? " (no model override)" : ` \xB7 model ${execution.model}`;
3060
+ const effort = execution.effort === void 0 ? "" : ` \xB7 effort ${execution.effort}`;
2992
3061
  const fromMessage = execution.executorSource === "message" || execution.modelSource === "message" ? " \u2014 from the message" : "";
2993
- return `${execution.executor}${model}${fromMessage}`;
3062
+ return `${execution.executor}${model}${effort}${fromMessage}`;
2994
3063
  }
2995
3064
  function describeInvalidTool(invalidTool) {
2996
3065
  return `the newest message asks for \`tool:${invalidTool}\`, which is not an executor automata knows (valid values are ${VALID_TOOLS.map((tool) => `\`${tool}\``).join(" and ")})`;
@@ -3341,11 +3410,11 @@ function fail(message) {
3341
3410
  process.exit(1);
3342
3411
  }
3343
3412
  function parsePositiveInt(value, label) {
3344
- const trimmed = value.trim();
3345
- if (!/^\d+$/.test(trimmed)) {
3413
+ const trimmed2 = value.trim();
3414
+ if (!/^\d+$/.test(trimmed2)) {
3346
3415
  fail(`${label} must be a positive integer (got "${value}").`);
3347
3416
  }
3348
- const parsed = Number(trimmed);
3417
+ const parsed = Number(trimmed2);
3349
3418
  if (!Number.isSafeInteger(parsed) || parsed <= 0) {
3350
3419
  fail(`${label} must be a positive integer within the safe range (got "${value}").`);
3351
3420
  }
@@ -3397,6 +3466,12 @@ function resolveSettings(options) {
3397
3466
  modelOption: options.model,
3398
3467
  configExecutor: doWork.executor,
3399
3468
  configModels: doWork.models,
3469
+ // Rejected here rather than per item: an empty `--effort` is an operator
3470
+ // mistake on this invocation, not a property of any one work item. The
3471
+ // configured per-executor defaults are trimmed inside `resolveExecution`,
3472
+ // which is where the executor in use is finally known.
3473
+ effortOption: resolveEffortOption(options.effort),
3474
+ configEfforts: doWork.effort,
3400
3475
  maxRuns: options.maxRuns !== void 0 ? parsePositiveInt(options.maxRuns, "--max-runs") : doWork.maxRunsPerTick ?? DEFAULT_DO_WORK.maxRunsPerTick,
3401
3476
  lockStaleMinutes: doWork.lockStaleMinutes ?? DEFAULT_DO_WORK.lockStaleMinutes,
3402
3477
  limit: parsePositiveInt(options.limit, "--limit"),
@@ -3437,9 +3512,21 @@ function resolveItemExecution(item, settings) {
3437
3512
  modelOption: settings.modelOption,
3438
3513
  configExecutor: settings.configExecutor,
3439
3514
  configModels: settings.configModels,
3515
+ effortOption: settings.effortOption,
3516
+ configEfforts: settings.configEfforts,
3440
3517
  defaultExecutor: DEFAULT_DO_WORK.executor
3441
3518
  });
3442
3519
  }
3520
+ function toExecution(resolved) {
3521
+ return {
3522
+ executor: resolved.executor,
3523
+ executorSource: resolved.executorSource,
3524
+ model: resolved.model,
3525
+ modelSource: resolved.modelSource,
3526
+ effort: resolved.effort,
3527
+ effortSource: resolved.effortSource
3528
+ };
3529
+ }
3443
3530
  function planRun(item, settings, execution) {
3444
3531
  const prompt = composePrompt({
3445
3532
  item,
@@ -3449,7 +3536,12 @@ function planRun(item, settings, execution) {
3449
3536
  frame: settings.prompts[item.turn]
3450
3537
  });
3451
3538
  const bin = resolveCommand(execution.executor === "codex" ? "codex" : "claude");
3452
- const args = execution.executor === "codex" ? buildCodexArgs(prompt, { yolo: true, model: execution.model }) : buildClaudeArgs(prompt, { yolo: true, verbose: true, model: execution.model });
3539
+ const args = execution.executor === "codex" ? buildCodexArgs(prompt, { yolo: true, model: execution.model, effort: execution.effort }) : buildClaudeArgs(prompt, {
3540
+ yolo: true,
3541
+ verbose: true,
3542
+ model: execution.model,
3543
+ effort: execution.effort
3544
+ });
3453
3545
  return { prompt, bin, args, command: [bin, ...args].map(shellQuote).join(" ") };
3454
3546
  }
3455
3547
  function describePlannedRun(item, settings, run5, execution) {
@@ -3526,6 +3618,7 @@ function validateDoWorkConfig(section) {
3526
3618
  validateOptionalInt(section, "lockStaleMinutes", "doWork.lockStaleMinutes", 1, "a positive integer");
3527
3619
  validateProtectedBranches(section["protectedBranches"]);
3528
3620
  validateSettingContainer(section["models"], "models", ["claude", "codex"]);
3621
+ validateSettingContainer(section["effort"], "effort", ["claude", "codex"]);
3529
3622
  validateSettingContainer(section["prompts"], "prompts", ["issueDiscuss", "prWork"]);
3530
3623
  }
3531
3624
  function validateProtectedBranches(value) {
@@ -3760,10 +3853,10 @@ function reportNoAnswer(item, marker, runError) {
3760
3853
  }
3761
3854
  async function invokeExecutor(prompt, execution, silent) {
3762
3855
  if (execution.executor === "codex") {
3763
- await runCodex(prompt, { model: execution.model });
3856
+ await runCodex(prompt, { model: execution.model, effort: execution.effort });
3764
3857
  return;
3765
3858
  }
3766
- await runClaude(prompt, { model: execution.model, printSteps: !silent });
3859
+ await runClaude(prompt, { model: execution.model, effort: execution.effort, printSteps: !silent });
3767
3860
  }
3768
3861
  function repairIssueLink(item, baseBranch) {
3769
3862
  try {
@@ -3895,12 +3988,7 @@ async function processItem(planned, settings, silent) {
3895
3988
  }
3896
3989
  return { ...base, outcome: "failed", detail };
3897
3990
  }
3898
- const execution = {
3899
- executor: resolved.executor,
3900
- executorSource: resolved.executorSource,
3901
- model: resolved.model,
3902
- modelSource: resolved.modelSource
3903
- };
3991
+ const execution = toExecution(resolved);
3904
3992
  let runError = null;
3905
3993
  try {
3906
3994
  await invokeExecutor(prompt, execution, silent);
@@ -3964,13 +4052,18 @@ function toItemJson(report) {
3964
4052
  ranExecutor: report.ranExecutor ?? false,
3965
4053
  executor: report.execution?.executor ?? null,
3966
4054
  model: report.execution?.model ?? null,
4055
+ effort: report.execution?.effort ?? null,
3967
4056
  executorSource: report.execution?.executorSource ?? null,
3968
- modelSource: report.execution?.modelSource ?? null
4057
+ modelSource: report.execution?.modelSource ?? null,
4058
+ effortSource: report.execution?.effortSource ?? null
3969
4059
  };
3970
4060
  }
3971
4061
  var doWorkCommand = new Command6("do-work").description(
3972
4062
  "Run one tick of the autonomous loop: find the issues whose newest authorized message the agent has not answered, and answer them"
3973
- ).option("--with <executor>", "Executor to use: claude or codex (default: from config, else claude)").option("--model <string>", "Model identifier to pass to the executor, overriding the configured default for it").option("--issue <number>", "Restrict the tick to a single issue").option("--limit <n>", "Maximum number of issues to fetch", "10").option("--max-runs <n>", "Maximum number of model runs this tick").option(
4063
+ ).option("--with <executor>", "Executor to use: claude or codex (default: from config, else claude)").option("--model <string>", "Model identifier to pass to the executor, overriding the configured default for it").option(
4064
+ "--effort <level>",
4065
+ "Reasoning effort to pass to the executor, overriding the configured default for it"
4066
+ ).option("--issue <number>", "Restrict the tick to a single issue").option("--limit <n>", "Maximum number of issues to fetch", "10").option("--max-runs <n>", "Maximum number of model runs this tick").option(
3974
4067
  "--dry-run",
3975
4068
  "Print the work plan, plus a summary and the exact command that would be launched for each item, and exit without changing anything"
3976
4069
  ).option("--json", "Emit the work plan and outcomes as JSON on stdout").option("--silent", "Suppress step-by-step Claude output; show only the final summary").action(async (options) => {
@@ -4132,8 +4225,10 @@ function toRunJson(entry) {
4132
4225
  turn: entry.item.turn,
4133
4226
  executor: null,
4134
4227
  model: null,
4228
+ effort: null,
4135
4229
  executorSource: null,
4136
4230
  modelSource: null,
4231
+ effortSource: null,
4137
4232
  refusal: entry.refusal,
4138
4233
  bin: null,
4139
4234
  args: null,
@@ -4146,8 +4241,10 @@ function toRunJson(entry) {
4146
4241
  turn: entry.item.turn,
4147
4242
  executor: entry.execution.executor,
4148
4243
  model: entry.execution.model ?? null,
4244
+ effort: entry.execution.effort ?? null,
4149
4245
  executorSource: entry.execution.executorSource,
4150
4246
  modelSource: entry.execution.modelSource,
4247
+ effortSource: entry.execution.effortSource,
4151
4248
  refusal: null,
4152
4249
  bin: entry.run.bin,
4153
4250
  args: entry.run.args,
@@ -4162,12 +4259,7 @@ function reportDryRun(items, decisions, settings, options) {
4162
4259
  if (!resolved.ok) {
4163
4260
  return { kind: "refused", item, refusal: describeInvalidTool(resolved.invalidTool) };
4164
4261
  }
4165
- const execution = {
4166
- executor: resolved.executor,
4167
- executorSource: resolved.executorSource,
4168
- model: resolved.model,
4169
- modelSource: resolved.modelSource
4170
- };
4262
+ const execution = toExecution(resolved);
4171
4263
  return { kind: "run", item, execution, run: planRun(item, settings, execution) };
4172
4264
  });
4173
4265
  if (options.json) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "automata-cli",
3
- "version": "0.1.0-feature-032-message-tool-model.252",
3
+ "version": "0.1.0-feature-032-message-tool-model.258",
4
4
  "description": "Automata CLI tool",
5
5
  "type": "module",
6
6
  "engines": {