moa-cli 0.3.2__tar.gz → 0.3.3__tar.gz
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: moa-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Ask one question to multiple local AI coding CLIs in parallel and collect their answers.
|
|
5
5
|
Keywords: llm,agents,cli,claude,codex,agy,opencode,peer-review
|
|
6
6
|
Author: Paul-Louis Pröve
|
|
@@ -50,7 +50,7 @@ A single model gives you one perspective. Asking three frontier models the same
|
|
|
50
50
|
|
|
51
51
|
```text
|
|
52
52
|
$ moa ask "Is Postgres or SQLite better for a desktop app?"
|
|
53
|
-
Asking claude, codex, agy (timeout
|
|
53
|
+
Asking claude, codex, agy (timeout 900s, read-only)
|
|
54
54
|
|
|
55
55
|
──────────────── claude (opus) · OK · 3.2s ────────────────
|
|
56
56
|
|
|
@@ -103,11 +103,16 @@ is enforced by spawning each CLI with its own read-only flags:
|
|
|
103
103
|
|
|
104
104
|
| Provider | Read-only (default) | Reads files | Web research |
|
|
105
105
|
| ---------- | -------------------------- | ----------- | ------------------------- |
|
|
106
|
-
| `claude` | `--permission-mode
|
|
106
|
+
| `claude` | `--permission-mode default` | yes | yes |
|
|
107
107
|
| `codex` | `-s read-only` | yes | **no** (sandbox blocks network) |
|
|
108
108
|
| `opencode` | `--agent plan` | yes | yes |
|
|
109
109
|
| `agy` | `--sandbox` (partial: shell only - can still edit files) | yes | yes |
|
|
110
110
|
|
|
111
|
+
`claude`'s `--permission-mode default` is read-only in moa's non-interactive use: it reads
|
|
112
|
+
files and researches online with the full toolset, but any write or edit needs an interactive
|
|
113
|
+
approval that never comes under `-p`, so all mutations are denied. (`plan` mode is **not**
|
|
114
|
+
usable headless - it emits a plan and waits for approval instead of answering.)
|
|
115
|
+
|
|
111
116
|
`codex`'s read-only mode is a kernel sandbox that also blocks network, so codex does no
|
|
112
117
|
web research in the default mode (it still reads local files). `agy` has **no true
|
|
113
118
|
read-only mode**: its `--sandbox` flag restricts agy's terminal/shell but does **not** stop
|
|
@@ -39,7 +39,7 @@ A single model gives you one perspective. Asking three frontier models the same
|
|
|
39
39
|
|
|
40
40
|
```text
|
|
41
41
|
$ moa ask "Is Postgres or SQLite better for a desktop app?"
|
|
42
|
-
Asking claude, codex, agy (timeout
|
|
42
|
+
Asking claude, codex, agy (timeout 900s, read-only)
|
|
43
43
|
|
|
44
44
|
──────────────── claude (opus) · OK · 3.2s ────────────────
|
|
45
45
|
|
|
@@ -92,11 +92,16 @@ is enforced by spawning each CLI with its own read-only flags:
|
|
|
92
92
|
|
|
93
93
|
| Provider | Read-only (default) | Reads files | Web research |
|
|
94
94
|
| ---------- | -------------------------- | ----------- | ------------------------- |
|
|
95
|
-
| `claude` | `--permission-mode
|
|
95
|
+
| `claude` | `--permission-mode default` | yes | yes |
|
|
96
96
|
| `codex` | `-s read-only` | yes | **no** (sandbox blocks network) |
|
|
97
97
|
| `opencode` | `--agent plan` | yes | yes |
|
|
98
98
|
| `agy` | `--sandbox` (partial: shell only - can still edit files) | yes | yes |
|
|
99
99
|
|
|
100
|
+
`claude`'s `--permission-mode default` is read-only in moa's non-interactive use: it reads
|
|
101
|
+
files and researches online with the full toolset, but any write or edit needs an interactive
|
|
102
|
+
approval that never comes under `-p`, so all mutations are denied. (`plan` mode is **not**
|
|
103
|
+
usable headless - it emits a plan and waits for approval instead of answering.)
|
|
104
|
+
|
|
100
105
|
`codex`'s read-only mode is a kernel sandbox that also blocks network, so codex does no
|
|
101
106
|
web research in the default mode (it still reads local files). `agy` has **no true
|
|
102
107
|
read-only mode**: its `--sandbox` flag restricts agy's terminal/shell but does **not** stop
|
|
@@ -143,7 +143,11 @@ def _opencode(
|
|
|
143
143
|
PROVIDERS: dict[str, Provider] = {
|
|
144
144
|
"claude": Provider(
|
|
145
145
|
"claude", "claude", "opus", _claude,
|
|
146
|
-
|
|
146
|
+
# In headless `-p`, `default` keeps the full toolset (Read, read-only Bash
|
|
147
|
+
# like git/grep, WebFetch) but has no way to approve a write/edit, so
|
|
148
|
+
# mutations are denied: effectively read-only with all tools. (`plan` mode
|
|
149
|
+
# instead emits a plan-approval stub and never answers under `-p`.)
|
|
150
|
+
readonly=("--permission-mode", "default"),
|
|
147
151
|
yolo=("--permission-mode", "bypassPermissions"),
|
|
148
152
|
unset_env=("CLAUDECODE",),
|
|
149
153
|
),
|
|
@@ -170,7 +174,10 @@ PROVIDERS: dict[str, Provider] = {
|
|
|
170
174
|
"opencode": Provider(
|
|
171
175
|
"opencode", "opencode", "", _opencode,
|
|
172
176
|
readonly=("--agent", "plan"),
|
|
173
|
-
|
|
177
|
+
# Bare `build` (the default agent) still gates doom_loop/external_directory
|
|
178
|
+
# as `ask`, which auto-rejects headless - so true full access needs the
|
|
179
|
+
# explicit skip-permissions flag. (Verified on opencode 1.17.8.)
|
|
180
|
+
yolo=("--dangerously-skip-permissions",),
|
|
174
181
|
# Verified against installed opencode: `--variant <value>` is the
|
|
175
182
|
# "model variant (provider-specific reasoning effort, e.g., high)" flag
|
|
176
183
|
# (`opencode run --help`). The value is pasted verbatim.
|
|
@@ -754,7 +761,7 @@ _MODERATOR_MODES: tuple[str, ...] = ("auto",)
|
|
|
754
761
|
# serialize_config renders them back as `[providers.<name>]` blocks.
|
|
755
762
|
_CONFIG_DEFAULTS: dict = {
|
|
756
763
|
"num": 3,
|
|
757
|
-
"timeout":
|
|
764
|
+
"timeout": 900.0,
|
|
758
765
|
"synthesizer": "auto",
|
|
759
766
|
"moderator": "auto",
|
|
760
767
|
"exclude": [],
|
|
@@ -1144,7 +1151,7 @@ def resolve_run(
|
|
|
1144
1151
|
raise typer.BadParameter(f"{config_path()}: {exc}") from exc
|
|
1145
1152
|
|
|
1146
1153
|
num = resolve_option(num, "num", config, default_num)
|
|
1147
|
-
timeout = resolve_option(timeout, "timeout", config,
|
|
1154
|
+
timeout = resolve_option(timeout, "timeout", config, 900.0)
|
|
1148
1155
|
# Repeatable flags are an empty list when omitted, not None, so treat empty
|
|
1149
1156
|
# as "fall back to config" for exclude.
|
|
1150
1157
|
exclude_names = tuple(exclude) if exclude else tuple(config.get("exclude", ()))
|