orcastrator 0.2.19 → 0.2.23

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 CHANGED
@@ -109,7 +109,7 @@ orca pr publish --last
109
109
 
110
110
  Orca auto-discovers config in this order:
111
111
 
112
- 1. `~/.orca/config.js`
112
+ 1. Global config: `~/.orca/config.ts` (preferred when both exist) or `~/.orca/config.js`
113
113
  2. Project config: `./orca.config.ts` (preferred when both exist) or `./orca.config.js`
114
114
  3. `--config <path>` (if passed)
115
115
 
@@ -120,20 +120,12 @@ Later entries override earlier ones.
120
120
  import { defineOrcaConfig } from "orcastrator";
121
121
 
122
122
  export default defineOrcaConfig({
123
- executor: "codex",
124
- anthropicApiKey: process.env.ANTHROPIC_API_KEY,
125
- openaiApiKey: process.env.OPENAI_API_KEY,
123
+ executor: "codex", openaiApiKey: process.env.OPENAI_API_KEY,
126
124
  runsDir: "./.orca/runs",
127
125
  sessionLogs: "./session-logs",
128
126
  skills: ["./.orca/skills"],
129
127
  maxRetries: 1,
130
- claude: {
131
- model: "claude-sonnet-4-20250514",
132
- effort: "medium",
133
- useV2Preview: true,
134
- maxTurnsPerTask: 12,
135
- allowTextJsonFallback: false
136
- },
128
+
137
129
  codex: {
138
130
  enabled: true,
139
131
  model: "gpt-5.3-codex",
@@ -186,11 +178,10 @@ export default defineOrcaConfig({
186
178
 
187
179
  ### Config field reference (OrcaConfig)
188
180
 
189
- Top-level: `executor`, `anthropicApiKey`, `openaiApiKey`, `runsDir`, `sessionLogs`, `skills`, `maxRetries`, `hooks`, `hookCommands`, `pr`, `review`, `claude`, `codex`.
181
+ Top-level: `executor`, `openaiApiKey`, `runsDir`, `sessionLogs`, `skills`, `maxRetries`, `hooks`, `hookCommands`, `pr`, `review`, `codex`.
190
182
 
191
183
  - `pr.enabled`, `pr.requireConfirmation`
192
184
  - `maxRetries` is part of `OrcaConfig`; current planner-generated task retries remain fixed in task graph contracts
193
- - `claude.model`, `claude.effort`, `claude.useV2Preview`, `claude.maxTurnsPerTask`, `claude.allowTextJsonFallback`
194
185
  - `codex.enabled`, `codex.model`, `codex.effort`, `codex.command`, `codex.timeoutMs`, `codex.multiAgent`, `codex.perCwdExtraUserRoots`
195
186
  - `review.plan.enabled`, `review.plan.onInvalid`
196
187
  - `review.execution.enabled`, `review.execution.maxCycles`, `review.execution.onFindings`, `review.execution.validator.auto`, `review.execution.validator.commands`, `review.execution.prompt`
@@ -229,9 +220,7 @@ Global:
229
220
  - `--plan <path>`
230
221
  - `--config <path>`
231
222
  - `--codex-only` (force Codex executor for this run)
232
- - `--claude-only` (force Claude executor for this run)
233
223
  - `--codex-effort <low|medium|high>`
234
- - `--claude-effort <low|medium|high|max>`
235
224
  - `--on-milestone <cmd>`
236
225
  - `--on-task-complete <cmd>`
237
226
  - `--on-task-fail <cmd>`
@@ -259,9 +248,7 @@ Global:
259
248
  - `--last`
260
249
  - `--config <path>`
261
250
  - `--codex-only`
262
- - `--claude-only`
263
251
  - `--codex-effort <low|medium|high>`
264
- - `--claude-effort <low|medium|high|max>`
265
252
 
266
253
  `orca cancel`:
267
254
 
@@ -297,13 +284,13 @@ Global:
297
284
 
298
285
  `orca setup`:
299
286
 
300
- - `--anthropic-key <key>` — override Anthropic API key (written to config)
287
+ - auto-detect is default
301
288
  - `--openai-key <key>` — override OpenAI API key (written to config)
302
- - `--executor <codex|claude>` — explicitly set executor in written config
303
- - `--global` — save to `~/.orca/config.js` (default)
304
- - `--project` — save to `./orca.config.js`
305
- - `--project-config-template` — write typed project hook template to `./orca.config.ts`
306
- - `--skip-project-config` skip project config prompt
289
+ - `--executor <codex>` — explicitly set executor in written config
290
+ - `--ts` — write TS config output (`~/.orca/config.ts` / `./orca.config.ts`)
291
+ - `--global` — save to global config (`~/.orca/config.js` by default, or `.ts` with `--ts`)
292
+ - `--project` — save to project config (`./orca.config.js` by default, or `.ts` with `--ts`)
293
+ - `--project-config-template` / `--skip-project-config` removed
307
294
 
308
295
  `orca help`:
309
296
 
@@ -342,8 +329,8 @@ Run IDs are generated as:
342
329
 
343
330
  ### Config File Locations
344
331
 
345
- - Global: `~/.orca/config.js`
346
- - Project: `./orca.config.js` or `./orca.config.ts`
332
+ - Global: `~/.orca/config.ts` (preferred when both exist) or `~/.orca/config.js`
333
+ - Project: `./orca.config.ts` (preferred when both exist) or `./orca.config.js`
347
334
  - Explicit: `--config <path>`
348
335
 
349
336
  ### Project Instruction Files
@@ -351,11 +338,8 @@ Run IDs are generated as:
351
338
  During planning, Orca automatically injects project instruction files when present:
352
339
 
353
340
  1. `AGENTS.md`
354
- 2. `CLAUDE.md`
355
-
356
- Files are discovered from the project root (nearest `.git` from the spec/task context) and injected in that order.
357
341
 
358
- If both filenames resolve to the same underlying file (for example, `CLAUDE.md` symlinked to `AGENTS.md`), Orca injects that content only once and keeps the first entry in order (`AGENTS.md`).
342
+ Files are discovered from the project root (nearest `.git` from the spec/task context) and injected when present.
359
343
 
360
344
  ### Project Skills
361
345
 
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsGzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqB1D"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4EzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiB1D"}
@@ -11,7 +11,7 @@ function printSection(title, entries) {
11
11
  console.log("");
12
12
  }
13
13
  function printStyledHelpPage() {
14
- console.log("orca — coordinated agent run harness");
14
+ console.log("orca — coordinated codex run harness");
15
15
  console.log("");
16
16
  printSection("RUNNING", [
17
17
  { command: 'orca "add auth to the app"', description: "run with inline goal" },
@@ -33,34 +33,15 @@ function printStyledHelpPage() {
33
33
  { command: "orca pr publish --run <id>", description: "publish draft → ready for review" },
34
34
  { command: "orca pr status --run <id>", description: "check PR state and CI" }
35
35
  ]);
36
- printSection("SETUP", [
37
- { command: "orca setup", description: "first-time setup and environment checks" }
38
- ]);
36
+ printSection("SETUP", [{ command: "orca setup", description: "first-time setup and Codex environment checks" }]);
39
37
  printSection("FLAGS", [
40
38
  { command: "-p, --prompt <text>", description: "inline task goal (alias: --task)" },
41
39
  { command: "--plan, --spec <path>", description: "path to spec or plan file" },
42
40
  { command: "--run <id>", description: "specify run by ID" },
43
41
  { command: "--last", description: "use the most recent run" },
44
- {
45
- command: "--config <path>",
46
- description: "explicit config file (auto-discovered by default)"
47
- },
48
- {
49
- command: "--codex-only",
50
- description: "override executor to Codex for the current run"
51
- },
52
- {
53
- command: "--claude-only",
54
- description: "override executor to Claude for the current run"
55
- },
56
- {
57
- command: "--codex-effort <value>",
58
- description: "override Codex effort for the current run"
59
- },
60
- {
61
- command: "--claude-effort <value>",
62
- description: "override Claude effort for the current run"
63
- },
42
+ { command: "--config <path>", description: "explicit config file (auto-discovered by default)" },
43
+ { command: "--codex-only", description: "override executor to Codex for the current run" },
44
+ { command: "--codex-effort <value>", description: "override Codex effort for the current run" },
64
45
  { command: "--full-auto", description: "skip all questions, proceed autonomously" },
65
46
  { command: "--on-complete <cmd>", description: "shell hook on run complete" },
66
47
  { command: "--on-error <cmd>", description: "shell hook on run error" },
@@ -69,25 +50,18 @@ function printStyledHelpPage() {
69
50
  ]);
70
51
  }
71
52
  function findCommand(program, pathText) {
72
- const segments = pathText
73
- .split(" ")
74
- .map((segment) => segment.trim())
75
- .filter((segment) => segment.length > 0);
53
+ const segments = pathText.split(" ").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
76
54
  let current = program;
77
55
  for (const segment of segments) {
78
56
  current = current.commands.find((command) => command.name() === segment);
79
- if (!current) {
57
+ if (!current)
80
58
  return undefined;
81
- }
82
59
  }
83
60
  return current;
84
61
  }
85
62
  export function registerHelpCommand(program) {
86
63
  program.addHelpCommand(false);
87
- program
88
- .command("help [command]")
89
- .description("display help for command")
90
- .action((commandPath) => {
64
+ program.command("help [command]").description("display help for command").action((commandPath) => {
91
65
  if (!commandPath) {
92
66
  printStyledHelpPage();
93
67
  return;
@@ -1,13 +1,11 @@
1
1
  import { type Command } from "commander";
2
- import { type ClaudeEffort, type CodexEffort } from "../../types/effort.js";
2
+ import { type CodexEffort } from "../../types/effort.js";
3
3
  export interface ResumeCommandOptions {
4
4
  run?: string;
5
5
  last?: boolean;
6
6
  config?: string;
7
7
  codexOnly?: boolean;
8
- claudeOnly?: boolean;
9
8
  codexEffort?: CodexEffort;
10
- claudeEffort?: ClaudeEffort;
11
9
  }
12
10
  export declare function resumeCommandHandler(options: ResumeCommandOptions): Promise<void>;
13
11
  export declare function registerResumeCommand(program: Command): void;
@@ -1 +1 @@
1
- {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/resume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAM/D,OAAO,EAAuC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGjH,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AA4DD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEvF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmB5D"}
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/resume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAM/D,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAgDD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmEvF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiB5D"}
@@ -2,7 +2,7 @@ import { InvalidArgumentError } from "commander";
2
2
  import { resolveConfig } from "../../core/config-loader.js";
3
3
  import { runTaskRunner } from "../../core/task-runner.js";
4
4
  import { RunStore } from "../../state/store.js";
5
- import { parseClaudeEffort, parseCodexEffort } from "../../types/effort.js";
5
+ import { parseCodexEffort } from "../../types/effort.js";
6
6
  import { getLastRun } from "../../utils/last-run.js";
7
7
  function createStore() {
8
8
  const runsDir = process.env.ORCA_RUNS_DIR;
@@ -25,34 +25,20 @@ function parseCodexEffortOption(value) {
25
25
  throw new InvalidArgumentError(error instanceof Error ? error.message : String(error));
26
26
  }
27
27
  }
28
- function parseClaudeEffortOption(value) {
29
- try {
30
- return parseClaudeEffort(value);
31
- }
32
- catch (error) {
33
- throw new InvalidArgumentError(error instanceof Error ? error.message : String(error));
34
- }
35
- }
36
28
  function applyExecutorOverrideForResume(config, options) {
37
29
  const nextConfig = { ...config };
38
- if (options.codexOnly || options.claudeOnly) {
39
- nextConfig.executor = options.codexOnly ? "codex" : "claude";
30
+ if (options.codexOnly) {
31
+ nextConfig.executor = "codex";
40
32
  }
41
33
  if (options.codexEffort !== undefined) {
42
34
  nextConfig.codex = { ...nextConfig.codex, effort: options.codexEffort };
43
35
  }
44
- if (options.claudeEffort !== undefined) {
45
- nextConfig.claude = { ...nextConfig.claude, effort: options.claudeEffort };
46
- }
47
36
  if (config === undefined && Object.keys(nextConfig).length === 0) {
48
37
  return undefined;
49
38
  }
50
39
  return nextConfig;
51
40
  }
52
41
  export async function resumeCommandHandler(options) {
53
- if (options.codexOnly && options.claudeOnly) {
54
- throw new Error("--codex-only and --claude-only are mutually exclusive; choose only one executor override.");
55
- }
56
42
  const store = createStore();
57
43
  const resolvedConfig = await resolveConfig(options.config);
58
44
  const effectiveConfig = applyExecutorOverrideForResume(resolvedConfig, options);
@@ -116,9 +102,7 @@ export function registerResumeCommand(program) {
116
102
  .option("--last", "Use the most recent run")
117
103
  .option("--config <path>", "Path to orca config file")
118
104
  .option("--codex-only", "Force Codex executor for this resumed run (overrides config)")
119
- .option("--claude-only", "Force Claude executor for this resumed run (overrides config)")
120
105
  .option("--codex-effort <value>", "Codex effort override for this resumed run", parseCodexEffortOption)
121
- .option("--claude-effort <value>", "Claude effort override for this resumed run", parseClaudeEffortOption)
122
106
  .action(async (options) => {
123
107
  try {
124
108
  await resumeCommandHandler(options);
@@ -1 +1 @@
1
- {"version":3,"file":"run-command.test-harness.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run-command.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,IAAI,EAAE,MAAM,UAAU,CAAC;AAMvD,KAAK,SAAS,GAAG,cAAc,UAAU,CAAC,CAAC;AAE3C,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,OAAO,CAAC;QAC3B,SAAS,EAAE,SAAS,CAAC;QACrB,cAAc,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QACxC,iBAAiB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAC3C,sBAAsB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAChD,yBAAyB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QACnD,gBAAgB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1C,oBAAoB,EAAE,KAAK,KAAK,EAAE,SAAS,GAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;KACnF,CAAC,CAAC;IACH,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,CA0IrF"}
1
+ {"version":3,"file":"run-command.test-harness.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run-command.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,IAAI,EAAE,MAAM,UAAU,CAAC;AAMvD,KAAK,SAAS,GAAG,cAAc,UAAU,CAAC,CAAC;AAE3C,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,OAAO,CAAC;QAC3B,SAAS,EAAE,SAAS,CAAC;QACrB,cAAc,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QACxC,iBAAiB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAC3C,sBAAsB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAChD,yBAAyB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QACnD,gBAAgB,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1C,oBAAoB,EAAE,KAAK,KAAK,EAAE,SAAS,GAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;KACnF,CAAC,CAAC;IACH,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAgJrF"}
@@ -7,10 +7,12 @@ export function createRunCommandTestHarness(tempPrefix) {
7
7
  let tempDir = "";
8
8
  const originalRunsDir = process.env.ORCA_RUNS_DIR;
9
9
  const originalSkipValidators = process.env.ORCA_SKIP_VALIDATORS;
10
+ const originalOpenaiApiKey = process.env.OPENAI_API_KEY;
10
11
  beforeEach(async () => {
11
12
  tempDir = await mkdtemp(path.join(os.tmpdir(), tempPrefix));
12
13
  process.env.ORCA_RUNS_DIR = path.join(tempDir, "runs");
13
14
  process.env.ORCA_SKIP_VALIDATORS = "1";
15
+ process.env.OPENAI_API_KEY = "test-openai-key";
14
16
  process.exitCode = 0;
15
17
  });
16
18
  afterEach(async () => {
@@ -28,6 +30,12 @@ export function createRunCommandTestHarness(tempPrefix) {
28
30
  else {
29
31
  process.env.ORCA_SKIP_VALIDATORS = originalSkipValidators;
30
32
  }
33
+ if (originalOpenaiApiKey === undefined) {
34
+ delete process.env.OPENAI_API_KEY;
35
+ }
36
+ else {
37
+ process.env.OPENAI_API_KEY = originalOpenaiApiKey;
38
+ }
31
39
  await rm(tempDir, { recursive: true, force: true });
32
40
  });
33
41
  async function loadRunModule() {
@@ -1,5 +1,5 @@
1
1
  import { type Command } from "commander";
2
- import { type ClaudeEffort, type CodexEffort } from "../../types/effort.js";
2
+ import { type CodexEffort } from "../../types/effort.js";
3
3
  export interface RunCommandOptions {
4
4
  spec?: string;
5
5
  plan?: string;
@@ -8,9 +8,7 @@ export interface RunCommandOptions {
8
8
  goal?: string;
9
9
  config?: string;
10
10
  codexOnly?: boolean;
11
- claudeOnly?: boolean;
12
11
  codexEffort?: CodexEffort;
13
- claudeEffort?: ClaudeEffort;
14
12
  onMilestone?: string;
15
13
  onTaskComplete?: string;
16
14
  onTaskFail?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAQA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAa/D,OAAO,EAAuC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA4BjH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuDD,wBAAsB,+BAA+B,CAAC,OAAO,GAAE,MAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBnG;AA8MD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkRjF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkEzD"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAQA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAa/D,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA6B3E,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+CD,wBAAsB,+BAA+B,CAAC,OAAO,GAAE,MAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBnG;AAoND,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2QjF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0DzD"}
@@ -16,8 +16,9 @@ import { createOpenclawHookHandler, detectOpenclawAvailability } from "../../hoo
16
16
  import { createStdoutHookHandler } from "../../hooks/adapters/stdout.js";
17
17
  import { HookDispatcher } from "../../hooks/dispatcher.js";
18
18
  import { RunStore } from "../../state/store.js";
19
- import { parseClaudeEffort, parseCodexEffort } from "../../types/effort.js";
19
+ import { parseCodexEffort } from "../../types/effort.js";
20
20
  import { generateRunId } from "../../utils/ids.js";
21
+ import { readCodexAuthJson } from "./setup.js";
21
22
  const exec = promisify(execCallback);
22
23
  const ExecutionReviewPayloadSchema = z.object({
23
24
  summary: z.string().min(1),
@@ -53,14 +54,6 @@ function parseCodexEffortOption(value) {
53
54
  throw new InvalidArgumentError(error instanceof Error ? error.message : String(error));
54
55
  }
55
56
  }
56
- function parseClaudeEffortOption(value) {
57
- try {
58
- return parseClaudeEffort(value);
59
- }
60
- catch (error) {
61
- throw new InvalidArgumentError(error instanceof Error ? error.message : String(error));
62
- }
63
- }
64
57
  function createStore() {
65
58
  const runsDir = process.env.ORCA_RUNS_DIR;
66
59
  return runsDir ? new RunStore(runsDir) : new RunStore();
@@ -75,17 +68,19 @@ async function pathExists(filePath) {
75
68
  }
76
69
  }
77
70
  export async function maybeCreateFirstRunGlobalConfig(homedir = os.homedir()) {
78
- const globalConfigPath = path.join(homedir, ".orca", "config.js");
71
+ const globalJsConfigPath = path.join(homedir, ".orca", "config.js");
72
+ const globalTsConfigPath = path.join(homedir, ".orca", "config.ts");
79
73
  const projectJsConfigPath = path.join(process.cwd(), "orca.config.js");
80
74
  const projectTsConfigPath = path.join(process.cwd(), "orca.config.ts");
81
- const hasAnyConfig = (await pathExists(globalConfigPath))
75
+ const hasAnyConfig = (await pathExists(globalJsConfigPath))
76
+ || (await pathExists(globalTsConfigPath))
82
77
  || (await pathExists(projectJsConfigPath))
83
78
  || (await pathExists(projectTsConfigPath));
84
79
  if (hasAnyConfig) {
85
80
  return;
86
81
  }
87
- await mkdir(path.dirname(globalConfigPath), { recursive: true });
88
- await writeFile(globalConfigPath, "export default {\n executor: \"codex\"\n};\n", "utf8");
82
+ await mkdir(path.dirname(globalJsConfigPath), { recursive: true });
83
+ await writeFile(globalJsConfigPath, "export default {\n executor: \"codex\"\n};\n", "utf8");
89
84
  console.log("✓ Created ~/.orca/config.js (first run defaults)");
90
85
  }
91
86
  function computeFinalStatus(overallStatus, allTasksDone) {
@@ -108,17 +103,22 @@ function buildCliCommandHooks(options) {
108
103
  ...(options.onError ? { onError: options.onError } : {})
109
104
  };
110
105
  }
106
+ function isCodexAvailableForRun(env = process.env) {
107
+ const envOpenai = env.ORCA_OPENAI_API_KEY ?? env.OPENAI_API_KEY;
108
+ if (typeof envOpenai === "string" && envOpenai.trim().length > 0) {
109
+ return true;
110
+ }
111
+ const homeDir = typeof env.HOME === "string" && env.HOME.trim().length > 0 ? env.HOME : os.homedir();
112
+ return Boolean(readCodexAuthJson(homeDir));
113
+ }
111
114
  function applyExecutorOverrideForRun(config, options) {
112
115
  const nextConfig = { ...config };
113
- if (options.codexOnly || options.claudeOnly) {
114
- nextConfig.executor = options.codexOnly ? "codex" : "claude";
116
+ if (options.codexOnly) {
117
+ nextConfig.executor = "codex";
115
118
  }
116
119
  if (options.codexEffort !== undefined) {
117
120
  nextConfig.codex = { ...nextConfig.codex, effort: options.codexEffort };
118
121
  }
119
- if (options.claudeEffort !== undefined) {
120
- nextConfig.claude = { ...nextConfig.claude, effort: options.claudeEffort };
121
- }
122
122
  if (config === undefined && Object.keys(nextConfig).length === 0) {
123
123
  return undefined;
124
124
  }
@@ -249,9 +249,6 @@ async function requestStructuredExecutionReview(runPrompt, cycleIndex, basePromp
249
249
  };
250
250
  }
251
251
  export async function runCommandHandler(options) {
252
- if (options.codexOnly && options.claudeOnly) {
253
- throw new Error("--codex-only and --claude-only are mutually exclusive; choose only one executor override.");
254
- }
255
252
  const inlineTask = options.task ?? options.prompt ?? options.goal;
256
253
  const inputSpecPath = options.spec ?? options.plan;
257
254
  if (options.goal !== undefined && (options.task || options.prompt)) {
@@ -280,6 +277,11 @@ export async function runCommandHandler(options) {
280
277
  await maybeCreateFirstRunGlobalConfig();
281
278
  const orcaConfig = await resolveConfig(options.config);
282
279
  const effectiveConfig = applyExecutorOverrideForRun(orcaConfig, options);
280
+ if (!isCodexAvailableForRun()) {
281
+ console.error("Codex is unavailable. Set OPENAI_API_KEY (or ORCA_OPENAI_API_KEY) or configure ~/.codex/auth.json.");
282
+ process.exitCode = 1;
283
+ return;
284
+ }
283
285
  const runId = generateRunId(specPath);
284
286
  console.log(`Run ID: ${runId}`);
285
287
  const store = createStore();
@@ -346,8 +348,7 @@ export async function runCommandHandler(options) {
346
348
  mode: "run",
347
349
  overallStatus: "running"
348
350
  });
349
- const executor = effectiveConfig?.executor ?? "codex";
350
- if (executor === "codex") {
351
+ {
351
352
  const cwd = process.cwd();
352
353
  const multiAgentResult = await ensureCodexMultiAgent(effectiveConfig);
353
354
  if (multiAgentResult.action === "created" || multiAgentResult.action === "appended") {
@@ -441,15 +442,6 @@ export async function runCommandHandler(options) {
441
442
  await codexSession.disconnect();
442
443
  }
443
444
  }
444
- else {
445
- console.log("Phase 4: Skipping Codex consultation because executor is set to Claude.");
446
- await runTaskRunner({
447
- runId,
448
- store,
449
- ...(effectiveConfig ? { config: effectiveConfig } : {}),
450
- emitHook
451
- });
452
- }
453
445
  const run = await store.getRun(runId);
454
446
  if (!run) {
455
447
  throw new Error(`Run not found after execution: ${runId}`);
@@ -483,9 +475,7 @@ export function registerRunCommand(program) {
483
475
  .option("-p, --prompt <text>", "Inline task text (alias for --task)")
484
476
  .option("--config <path>", "Path to orca config file")
485
477
  .option("--codex-only", "Force Codex executor for this run (overrides config)")
486
- .option("--claude-only", "Force Claude executor for this run (overrides config)")
487
478
  .option("--codex-effort <value>", "Codex effort override for this run", parseCodexEffortOption)
488
- .option("--claude-effort <value>", "Claude effort override for this run", parseClaudeEffortOption)
489
479
  .option("--on-milestone <cmd>", "Shell hook command for onMilestone")
490
480
  .option("--on-task-complete <cmd>", "Shell hook command for onTaskComplete")
491
481
  .option("--on-task-fail <cmd>", "Shell hook command for onTaskFail")
@@ -499,11 +489,6 @@ export function registerRunCommand(program) {
499
489
  ...commandOptions,
500
490
  ...(goal !== undefined ? { goal } : {})
501
491
  };
502
- if (normalizedOptions.codexOnly && normalizedOptions.claudeOnly) {
503
- console.error("Error: --codex-only and --claude-only are mutually exclusive; choose only one.");
504
- process.exitCode = 1;
505
- return;
506
- }
507
492
  const inlineTask = normalizedOptions.task ?? normalizedOptions.prompt ?? normalizedOptions.goal;
508
493
  const inputSpecPath = normalizedOptions.spec ?? normalizedOptions.plan;
509
494
  if (normalizedOptions.goal !== undefined && (normalizedOptions.task || normalizedOptions.prompt)) {
@@ -1,18 +1,16 @@
1
1
  import { type Command } from "commander";
2
2
  export interface SetupCommandOptions {
3
- anthropicKey?: string;
4
3
  openaiKey?: string;
5
4
  global?: boolean;
6
5
  project?: boolean;
7
- executor?: "codex" | "claude";
6
+ ts?: boolean;
7
+ executor?: "codex";
8
8
  projectConfigTemplate?: boolean;
9
9
  skipProjectConfig?: boolean;
10
10
  }
11
- type PackageManager = "brew" | "apt" | "winget";
12
11
  type ApiKeyConfig = {
13
- anthropicApiKey?: string;
14
12
  openaiApiKey?: string;
15
- executor?: "codex" | "claude";
13
+ executor?: "codex";
16
14
  };
17
15
  type ResolveApiKeyOptions = {
18
16
  openclawConfigPath?: string;
@@ -21,9 +19,7 @@ type ResolveApiKeyOptions = {
21
19
  export declare function resolveApiKey(flagValue: string | undefined, envVarName: string, openclawConfigPathOrOptions?: string | ResolveApiKeyOptions, maybeOptions?: ResolveApiKeyOptions): string | undefined;
22
20
  export declare function readCodexAuthJson(homedir?: string): string | undefined;
23
21
  export declare function readClaudeCodeKeychain(): string | undefined;
24
- export declare function detectPackageManager(exists?: (command: string) => boolean): PackageManager | null;
25
- export declare function buildConfigModule({ anthropicApiKey, openaiApiKey, executor }: ApiKeyConfig): string;
26
- export declare function buildProjectConfigTemplate(): string;
22
+ export declare function buildConfigModule({ openaiApiKey, executor }: ApiKeyConfig): string;
27
23
  export declare function setupCommandHandler(options: SetupCommandOptions): Promise<void>;
28
24
  export declare function registerSetupCommand(program: Command): void;
29
25
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AASA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAI/D,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,KAAK,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEhD,KAAK,YAAY,GAAG;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC/B,CAAC;AA8DF,KAAK,oBAAoB,GAAG;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA0DF,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,EAClB,2BAA2B,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAC3D,YAAY,CAAC,EAAE,oBAAoB,GAClC,MAAM,GAAG,SAAS,CAEpB;AA2CD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,MAAqB,GAAG,MAAM,GAAG,SAAS,CAepF;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CA0B3D;AAUD,wBAAgB,oBAAoB,CAClC,MAAM,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAuB,GACnD,cAAc,GAAG,IAAI,CAcvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,YAAY,GAAG,MAAM,CAiBnG;AAMD,wBAAgB,0BAA0B,IAAI,MAAM,CA6DnD;AA0LD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkHrF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAc3D"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AASA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAI/D,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAID,KAAK,YAAY,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAGlE,KAAK,oBAAoB,GAAG;IAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,MAAM,EAClB,2BAA2B,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAC3D,YAAY,CAAC,EAAE,oBAAoB,GAClC,MAAM,GAAG,SAAS,CAsBpB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,MAAqB,GAAG,MAAM,GAAG,SAAS,CAUpF;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAE3D;AAOD,wBAAgB,iBAAiB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,YAAY,GAAG,MAAM,CAMlF;AA6DD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDrF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAY3D"}