@openduo/duoduo 0.4.6 → 0.5.0-rc.1

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/bin/duoduo CHANGED
@@ -14,12 +14,18 @@ done
14
14
  SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)"
15
15
  ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
16
16
 
17
+ # Allow callers to pin a specific Node binary (e.g. distributions that ship
18
+ # their own runtime, agent spawn environments where login-shell rc files
19
+ # reset PATH and drop node out of sight). When unset, behave exactly like
20
+ # before: resolve `node` via PATH. See openduo/duoduo#50.
21
+ NODE_BIN="${DUODUO_NODE_BIN:-node}"
22
+
17
23
  if [[ -f "$ROOT_DIR/dist/release/cli.cjs" ]]; then
18
- exec node "$ROOT_DIR/dist/release/cli.cjs" "$@"
24
+ exec "$NODE_BIN" "$ROOT_DIR/dist/release/cli.cjs" "$@"
19
25
  fi
20
26
 
21
27
  if [[ -f "$ROOT_DIR/dist/release/cli.js" ]]; then
22
- exec node "$ROOT_DIR/dist/release/cli.js" "$@"
28
+ exec "$NODE_BIN" "$ROOT_DIR/dist/release/cli.js" "$@"
23
29
  fi
24
30
 
25
31
  if [[ -x "$ROOT_DIR/node_modules/.bin/tsx" ]]; then
@@ -5,19 +5,30 @@ Duoduo supports two runtime backends:
5
5
  - **Claude** (default) — Claude Agent SDK.
6
6
  - **Codex** (GPT-5.4) — Codex app-server protocol over stdio.
7
7
 
8
- Codex is off by default.
8
+ As of v0.5, Codex is **auto-detected**. No env flag is required. If
9
+ `codex` is installed on PATH and the user has run `codex login`, the
10
+ daemon advertises `runtime: "codex"` in ManageJob tool schemas and
11
+ accepts it in job definitions. Otherwise codex is silently hidden and
12
+ any `runtime: "codex"` request falls back to Claude.
9
13
 
10
14
  ## Prerequisites
11
15
 
12
16
  - `codex` CLI installed and on `$PATH`.
13
- - `codex` authenticated with valid API credentials.
17
+ - `codex login` has been run so `codex login status` reports
18
+ "logged in".
19
+
20
+ Verify with:
21
+
22
+ ```bash
23
+ codex --version
24
+ codex login status
25
+ ```
14
26
 
15
27
  ## Environment Variables
16
28
 
17
- | Variable | Required | Values | Default |
18
- | ---------------------- | -------- | ------------------ | ----------------- |
19
- | `ALADUO_CODEX_ENABLED` | Yes | `1`, `true`, `yes` | off |
20
- | `ALADUO_CODEX_SANDBOX` | No | see below | `workspace-write` |
29
+ | Variable | Required | Values | Default |
30
+ | ---------------------- | -------- | --------- | ----------------- |
31
+ | `ALADUO_CODEX_SANDBOX` | No | see below | `workspace-write` |
21
32
 
22
33
  ### Sandbox Modes
23
34
 
@@ -27,38 +38,21 @@ Codex is off by default.
27
38
  | `read-only` | Read-only | No | Analysis-only tasks. |
28
39
  | `danger-full-access` | Full | Yes | Needed for localhost API or external network. |
29
40
 
30
- ## Enable
41
+ ## Refreshing availability after `codex login`
31
42
 
32
- Add the variables to the daemon's persistent config file and restart:
43
+ The daemon probes codex availability at boot. If you install codex
44
+ or run `codex login` while the daemon is already running, restart
45
+ the daemon to re-probe:
33
46
 
34
47
  ```bash
35
- # ~/.config/duoduo/.env (created if missing)
36
- echo 'ALADUO_CODEX_ENABLED=1' >> ~/.config/duoduo/.env
37
- # optional:
38
- echo 'ALADUO_CODEX_SANDBOX=workspace-write' >> ~/.config/duoduo/.env
39
-
40
48
  duoduo daemon restart
41
49
  ```
42
50
 
43
- > **Note:** The daemon reads `~/.config/duoduo/.env` on startup. Shell-only
44
- > `export` does not persist across launchd/systemd restarts.
45
-
46
- ## Disable
47
-
48
- Remove or comment out `ALADUO_CODEX_ENABLED` from `~/.config/duoduo/.env`,
49
- then restart:
50
-
51
- ```bash
52
- sed -i '' '/^ALADUO_CODEX_ENABLED/d' ~/.config/duoduo/.env
53
- duoduo daemon restart
54
- ```
55
-
56
- Existing `runtime: codex` jobs silently fall back to Claude.
57
-
58
51
  ## Usage
59
52
 
60
- When enabled, the ManageJob tool exposes a `runtime` field (`"claude"` | `"codex"`).
61
- A preflight check runs `codex --version` at job creation and reports errors early.
53
+ When codex is available, the ManageJob tool exposes a `runtime` field
54
+ (`"claude"` | `"codex"`). A preflight check runs `codex --version`
55
+ at job creation and reports errors early.
62
56
 
63
57
  ## Limitations
64
58
 
@@ -683,7 +683,8 @@ body{
683
683
  cortex.forEach(function(s){
684
684
  var color = s.last_error?"alert":s.status==="active"?"running":s.status==="error"?"alert":s.status==="ended"?"off":"standby";
685
685
  var dn = s.display_name || s.session_key;
686
- var tip = dn+(dn!==s.session_key?"\n"+s.session_key:"")+"\n"+s.status+" \u2022 "+(s.health||"ok")+"\nlast: "+timeAgo(s.last_event_at)+"\ncreated: "+timeAgo(s.created_at)+(s.cwd?"\ncwd: "+s.cwd:"")+(s.last_error?"\n\u26A0 error: "+s.last_error.message+" ("+timeAgo(s.last_error.at)+")":"");
686
+ var rt = s.runtime || "claude";
687
+ var tip = dn+(dn!==s.session_key?"\n"+s.session_key:"")+"\n"+s.status+" \u2022 "+(s.health||"ok")+"\nruntime: "+rt+"\nlast: "+timeAgo(s.last_event_at)+"\ncreated: "+timeAgo(s.created_at)+(s.cwd?"\ncwd: "+s.cwd:"")+(s.last_error?"\n\u26A0 error: "+s.last_error.message+" ("+timeAgo(s.last_error.at)+")":"");
687
688
  h+='<div class="ind circle '+color+'" data-key="'+esc(s.session_key)+'" data-tip="'+esc(tip)+'"></div>';
688
689
  });
689
690
  groups.push(h);
@@ -707,7 +708,8 @@ body{
707
708
  }
708
709
  var statusText = isRunning ? "running" : (j.state ? j.state.last_result : "unknown");
709
710
  var cwdRel = j.frontmatter ? j.frontmatter.cwd_rel : null;
710
- var tip = j.id + (isOnce ? " (once)" : "") + "\ncron: "+(j.frontmatter?j.frontmatter.cron:"?") +"\n"+statusText+" \u2022 "+(j.state?j.state.run_count:0)+" runs\nlast: "+timeAgo(j.state?j.state.last_run_at:null)+(cwdRel?"\ncwd: "+cwdRel:"");
711
+ var jobRuntime = j.frontmatter && j.frontmatter.runtime ? j.frontmatter.runtime : "claude";
712
+ var tip = j.id + (isOnce ? " (once)" : "") + "\ncron: "+(j.frontmatter?j.frontmatter.cron:"?") +"\nruntime: "+jobRuntime+"\n"+statusText+" \u2022 "+(j.state?j.state.run_count:0)+" runs\nlast: "+timeAgo(j.state?j.state.last_run_at:null)+(cwdRel?"\ncwd: "+cwdRel:"");
711
713
  h2+='<div class="ind '+shape+' '+color+'" data-key="job:'+esc(j.id)+'" data-tip="'+esc(tip)+'"></div>';
712
714
  });
713
715
  groups.push(h2);