@ask-llm/plugin 0.14.0 → 0.16.2
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/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +25 -0
- package/CHANGELOG.md +966 -0
- package/README.md +49 -9
- package/agents/brainstorm-coordinator.md +70 -25
- package/agents/gemini-reviewer.md +1 -1
- package/dist/antigravity-run.js +0 -0
- package/dist/brainstorm-panel.d.ts +46 -0
- package/dist/brainstorm-panel.d.ts.map +1 -0
- package/dist/brainstorm-panel.js +247 -0
- package/dist/brainstorm-panel.js.map +1 -0
- package/dist/brainstorm-run.d.ts +3 -0
- package/dist/brainstorm-run.d.ts.map +1 -0
- package/dist/brainstorm-run.js +51 -0
- package/dist/brainstorm-run.js.map +1 -0
- package/dist/codex-run.js +0 -0
- package/dist/grok-run.js +0 -0
- package/dist/ollama-run.js +0 -0
- package/dist/run.js +0 -0
- package/mcp.json +11 -0
- package/package.json +18 -15
- package/pi/extensions/provider-tools.ts +8 -1
- package/scripts/benchmark/README.md +114 -0
- package/scripts/benchmark/fixtures/README.md +29 -0
- package/scripts/codex-pair-debounce-worker.mjs +0 -0
- package/scripts/codex-pair-log.mjs +4 -13
- package/scripts/codex-pair-prompt-drain.mjs +1 -1
- package/scripts/codex-pair-session.mjs +2 -2
- package/scripts/codex-pair-stop-gate.mjs +8 -8
- package/scripts/codex-pair-watch.mjs +20 -39
- package/skills/brainstorm/SKILL.md +62 -39
- package/skills/codex-pair/SKILL.md +44 -2
- package/skills/gemini-review/SKILL.md +1 -1
- package/skills/grok-pair/SKILL.md +115 -0
- package/skills/pairing-contract.md +40 -0
- package/scripts/lib/broker-lifecycle.mjs +0 -575
- package/scripts/lib/broker-rpc.mjs +0 -203
- package/scripts/lib/broker-transport.mjs +0 -407
- package/scripts/lib/broker.mjs +0 -537
- package/scripts/lib/debounce-state.mjs +0 -208
- package/scripts/lib/parser.d.mts +0 -12
- package/scripts/lib/parser.mjs +0 -229
- package/scripts/lib/process.mjs +0 -56
- package/scripts/lib/prompt.d.mts +0 -8
- package/scripts/lib/prompt.mjs +0 -41
- package/scripts/lib/session-registry.mjs +0 -162
- package/scripts/lib/state.d.mts +0 -58
- package/scripts/lib/state.mjs +0 -733
- package/scripts/lib/stop-gate.mjs +0 -134
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
**Canonical Claude Code
|
|
5
|
+
**Canonical Claude Code, Cursor Agent, and Pi host package for AI-to-AI collaboration**
|
|
6
6
|
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
|
-
One publishable package that adds multi-provider code review, comparison, brainstorming, verification, image, and pairing workflows to [Claude Code](https://code.claude.com/docs/en/plugins) and [Pi](https://pi.dev).
|
|
9
|
+
One publishable package that adds multi-provider code review, comparison, brainstorming, verification, image, and pairing workflows to [Claude Code](https://code.claude.com/docs/en/plugins), [Cursor Agent](https://cursor.com/docs/skills), and [Pi](https://pi.dev). The hosts consume one skill corpus and package version; host-specific behavior is kept in explicit adapters.
|
|
10
10
|
|
|
11
11
|
Part of the [Ask LLM](https://github.com/Lykhoyda/ask-llm) monorepo.
|
|
12
12
|
|
|
@@ -23,9 +23,16 @@ Part of the [Ask LLM](https://github.com/Lykhoyda/ask-llm) monorepo.
|
|
|
23
23
|
|
|
24
24
|
### MCP Servers
|
|
25
25
|
|
|
26
|
-
The plugin bundles the
|
|
26
|
+
The plugin bundles only the Codex MCP registration under Claude Code's plugin namespace. After installation or upgrade, fully restart Claude Code and run `/mcp`; `plugin:ask-llm:codex` should be connected. `/sol-review` selects `ask-codex`.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
`/grok-pair` does not add servers to the plugin. Register the unified Ask LLM server at user scope (the recommended install: it exposes `ask-cursor-agent` for the Cursor Agent route plus the unified `ask-llm` tool, which pair skills call only fully pinned) and, optionally, the split Grok server for the `ask-grok` leaf:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
claude mcp add --scope user ask-llm -- npx -y @ask-llm/mcp
|
|
32
|
+
claude mcp add --scope user grok -- npx -y @ask-llm/grok-mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Existing user-scoped Codex registrations remain compatible and keep their shorter names. Other providers are registered explicitly at user scope:
|
|
29
36
|
|
|
30
37
|
```bash
|
|
31
38
|
claude mcp add --scope user gemini -- npx -y @ask-llm/gemini-mcp
|
|
@@ -33,6 +40,16 @@ claude mcp add --scope user ollama -- npx -y @ask-llm/ollama-mcp
|
|
|
33
40
|
claude mcp add --scope user antigravity -- npx -y @ask-llm/antigravity-mcp
|
|
34
41
|
```
|
|
35
42
|
|
|
43
|
+
### Cursor Agent
|
|
44
|
+
|
|
45
|
+
Cursor's supported Agent Skills surface exposes exactly `/codex-pair` and `/grok-pair` (the manifest sets `agents: []`, `commands: []`, and `hooks: {}` so Claude agents and the Claude-format hooks file are never auto-discovered, and the other skills stay Claude/Pi-only until they get Cursor adapters); its MCP surface is `mcp.json`, which bundles only the unified `ask-llm` server. For a source checkout:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
agent --plugin-dir ./packages/claude-plugin
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`/codex-pair` requires explicit `model=` and `effort=` values before consent, then uses a separately user-installed `ask-codex` leaf when exposed, otherwise the bundled unified `ask-llm` fully pinned (`provider: "codex"`, model, effort, include directories, session), with resumable Thread ID, cancellation, and result relay. It never guesses MCP-process environment defaults and does not pretend Claude-only hooks are active. `/grok-pair` gives Cursor-native `.cursor/mcp.json` and Tools & MCP reload guidance; it never sends Cursor users to `claude mcp add`. If installing only MCP configuration, the recommended minimal entry is `ask-llm` → `npx -y @ask-llm/mcp` in project `.cursor/mcp.json` or user `~/.cursor/mcp.json` (keep one registration per server — do not duplicate it when the plugin is loaded); add `codex` → `@ask-llm/codex-mcp` or `grok` → `@ask-llm/grok-mcp` only when you specifically want their `ask-codex`/`ask-grok` leaves, then reload MCP/restart Cursor Agent. When Cursor hosts `/grok-pair`, it never recursively invokes Cursor Agent.
|
|
52
|
+
|
|
36
53
|
If Codex is missing entirely, register it explicitly with `claude mcp add --scope user codex -- npx -y @ask-llm/codex-mcp`. If `/mcp` shows the bundled registration but it is disconnected, run `npx -y @ask-llm/mcp doctor` and restart Claude Code. `/sol-review` preserves source-plugin and session-local MCP/settings context when reading the active `claude mcp list` inventory, reports missing and unavailable states separately, and discloses the explicit `codex exec` fallback after failed health or MCP transport failure.
|
|
37
54
|
|
|
38
55
|
### Pi
|
|
@@ -42,7 +59,9 @@ pi install npm:@ask-llm/plugin
|
|
|
42
59
|
pi list
|
|
43
60
|
```
|
|
44
61
|
|
|
45
|
-
Pi discovers the portable skills as `/skill:<name>` commands and registers native `ask-codex`, `ask-gemini`, `ask-grok`, `ask-ollama`, `ask-antigravity`, model-neutral `ask-cursor-agent`, and bounded concurrent `ask-multi` tools. Pi intentionally has no built-in MCP client; do not configure these as MCP servers in Pi. `fable-review`
|
|
62
|
+
Pi discovers the portable skills as `/skill:<name>` commands and registers native `ask-codex`, `ask-gemini`, `ask-grok`, `ask-ollama`, `ask-antigravity`, model-neutral `ask-cursor-agent`, and bounded concurrent `ask-multi` tools. Pi intentionally has no built-in MCP client; do not configure these as MCP servers in Pi. `fable-review` and `grok-pair` are excluded from Pi discovery; Grok pairing currently has Claude/Cursor adapters, while Pi retains its dedicated Codex pairing lifecycle.
|
|
63
|
+
|
|
64
|
+
The plugin's `ask-gemini-run`, Gemini reviewer agent/skill, and Pi `ask-gemini` tool all delegate to the canonical Gemini executor: `gemini-3.1-pro-preview` remains primary and quota errors fall back to `gemini-3.8-flash` unless `ASK_GEMINI_FALLBACK_MODEL` overrides it.
|
|
46
65
|
|
|
47
66
|
For codex-pair, create `.codex-pair/context.md`, ensure Pi trusts the project, then run interactive `/codex-pair` to grant user-owned canonical-project consent. The marker alone never authorizes data transfer/cost. Revoke with `/codex-pair revoke`. Pi findings are non-blocking; blocking Stop-gate and one-shot print parity are not available.
|
|
48
67
|
|
|
@@ -63,11 +82,31 @@ See the [Pi host guide](https://lykhoyda.github.io/ask-llm/plugin/pi) for securi
|
|
|
63
82
|
| `/fable-review` | Isolated, read-only review requesting native Fable, with runtime verification limits disclosed |
|
|
64
83
|
| `/sol-review` | Model-pinned GPT-5.6 Sol review through the bundled `ask-codex` MCP tool; missing registration and service unavailability are diagnosed separately before the explicit CLI fallback |
|
|
65
84
|
| `/ollama-review` | Local review — no data leaves your machine |
|
|
66
|
-
| `/brainstorm` |
|
|
85
|
+
| `/brainstorm` | Explicit multi-model brainstorm (default external: Antigravity + Codex); supports an exact no-Gemini Grok + GPT-5.6 Sol panel through Cursor Agent |
|
|
67
86
|
| `/grok-review` | Grok review through explicit xAI API or Grok CLI harness; no fallback |
|
|
87
|
+
| `/grok-pair` | Consent-gated iterative Grok reviewer through exact Cursor Agent, xAI API, or Grok CLI route; no fallback |
|
|
88
|
+
| `/codex-pair` | Claude/Pi per-edit pairing dashboard; Cursor on-demand session adapter with explicit Thread ID continuity |
|
|
68
89
|
| `/brainstorm-all` | Brainstorm with all five external providers (Gemini, Codex, Grok, Ollama, Antigravity) + Claude Opus research |
|
|
69
90
|
| `/compare` | Side-by-side raw responses from multiple providers (no synthesis, no consensus extraction) |
|
|
70
91
|
|
|
92
|
+
### Exact Grok + GPT-5.6 Sol brainstorm
|
|
93
|
+
|
|
94
|
+
The preferred architect panel routes both models through the model-neutral Cursor Agent harness with provider and exact account-catalog ID kept separate:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
/brainstorm grok@cursor-agent:cursor-grok-4.6-high,codex@cursor-agent:gpt-5.6-sol-high "review this architecture"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
This panel calls exactly Grok and GPT-5.6 Sol—never Gemini. Cursor `Auto`, model rewriting, and harness/provider fallback are forbidden. If one participant fails, the result is partial and cannot be presented as two-model consensus. Catalogs are account-specific; confirm these exact IDs with `agent --list-models` and replace an unavailable ID explicitly.
|
|
101
|
+
|
|
102
|
+
Official Grok Build remains an explicit alternative when its installed headless contract is supported:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
/brainstorm grok@grok-cli:grok-build,codex@cursor-agent:gpt-5.6-sol-high "review this architecture"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
A Grok CLI failure remains a Grok CLI failure; the workflow does not pivot to Cursor or xAI.
|
|
109
|
+
|
|
71
110
|
## Agents
|
|
72
111
|
|
|
73
112
|
| Agent | Color | Description |
|
|
@@ -77,7 +116,7 @@ See the [Pi host guide](https://lykhoyda.github.io/ask-llm/plugin/pi) for securi
|
|
|
77
116
|
| fable-reviewer | purple | Fable-requested review with source-verified findings |
|
|
78
117
|
| sol-reviewer | blue | GPT-5.6 Sol review through Codex with source validation |
|
|
79
118
|
| ollama-reviewer | yellow | 4-phase: context, prompt, synthesis, validation (local) |
|
|
80
|
-
| brainstorm-coordinator | magenta |
|
|
119
|
+
| brainstorm-coordinator | magenta | Source-grounded research + parallel multi-model consultation; exact two-model mode keeps the host non-voting and partial failures out of consensus |
|
|
81
120
|
|
|
82
121
|
## Hooks
|
|
83
122
|
|
|
@@ -127,10 +166,11 @@ To disable:
|
|
|
127
166
|
|
|
128
167
|
## Requirements
|
|
129
168
|
|
|
130
|
-
- **Claude Code or Pi 0.83.0+** installed
|
|
169
|
+
- **Claude Code, Cursor Agent, or Pi 0.83.0+** installed
|
|
131
170
|
- **Claude Code** installed for marketplace agents, hooks, independent Fable review, and the blocking Stop gate
|
|
132
171
|
- **Gemini CLI** authenticated — required for hooks and Gemini features
|
|
133
|
-
- **Codex CLI** — required for `/codex-review` and brainstorm
|
|
172
|
+
- **Codex CLI** — required for `/codex-review` and direct-Codex brainstorm routes
|
|
173
|
+
- **Cursor Agent CLI** authenticated with exact catalog IDs — required only for `@cursor-agent` brainstorm routes
|
|
134
174
|
- **Ollama** running locally — required for `/ollama-review`
|
|
135
175
|
|
|
136
176
|
## Documentation
|
|
@@ -32,18 +32,20 @@ The frontmatter and detailed implementation below define Claude Code subagent ex
|
|
|
32
32
|
|
|
33
33
|
You are a brainstorming coordinator powered by Claude Opus. You have two jobs:
|
|
34
34
|
|
|
35
|
-
1. **
|
|
36
|
-
2. **
|
|
35
|
+
1. **Research independently before dispatch.** Perform deep analysis of the topic — read the actual files, trace real code paths, and factor in framework-specific semantics. In standard mode this is a peer participant. In the exact Grok + GPT-5.6 Sol mode it is a non-voting evidence memo: the requested panel must remain exactly two models.
|
|
36
|
+
2. **Orchestrate explicit consultations.** Dispatch only the selected external participants (Antigravity, Codex, Grok, Ollama, Gemini — default: antigravity,codex) via a **single blocking foreground Bash call**, collect responses, and synthesize with provider, harness, requested model, independently observed served model (direct xAI API / Grok CLI only), and Cursor display label kept separate; a harness-echoed requested ID is selected-only and is never presented as the actual model.
|
|
37
37
|
|
|
38
|
-
You run on Opus and
|
|
38
|
+
You run on Opus and have filesystem access. Never skip the independent research phase, but never count it as a third panel vote in exact two-model mode.
|
|
39
39
|
|
|
40
40
|
## Core Principles
|
|
41
41
|
|
|
42
|
-
1. **Sequential phases, internal parallelism** — Phase 3B (Claude research) runs first, then Phase 3A (external dispatch) runs via
|
|
42
|
+
1. **Sequential phases, internal parallelism** — Phase 3B (Claude research) runs first, then Phase 3A (external dispatch) runs via one blocking Bash call. Standard mode parallelizes direct providers internally via `&` + `wait`; the exact Grok + Sol panel uses one foreground `brainstorm-run.js` process that owns both concurrent Cursor/direct children. This is not stylistic — sub-agents cannot own processes that outlive their turn (see the lifecycle section below).
|
|
43
43
|
2. **Blindness to external responses is load-bearing** — Phase 3B must complete *before* Phase 3A dispatches external providers, otherwise Claude will anchor on external findings and stop being an independent participant. The sequential ordering enforces this structurally.
|
|
44
44
|
3. **Verified findings outrank inferred ones** — when Claude has Read the actual files and traced real code, those findings carry more weight than an external LLM pattern-matching from a topic description alone.
|
|
45
|
-
4. **Preserve unique perspectives** —
|
|
46
|
-
5. **
|
|
45
|
+
4. **Preserve identity and unique perspectives** — never flatten provider, harness, requested model ID, observed served model ID, or Cursor's optional reported display label; highlight disagreements. Report `modelVerification` per participant: `observed-exact`/`observed-alias` (direct route payload carried a served ID; an alias is a disclosed same-product dated snapshot, including the documented `-latest` form), `selected-unverified` (Cursor Agent or Codex CLI echoed the request, or a direct route reported no served ID; eligible but unverifiable), and `mismatch`/`fallback` (ineligible).
|
|
46
|
+
5. **Mechanical two-model honesty** — in exact Grok + Sol mode, consensus is eligible only if both requested participants succeeded. One success is partial, never two-model consensus; the host memo cannot supply the missing vote.
|
|
47
|
+
6. **No route invention** — never use Cursor Auto, infer a requested model from a display label, rewrite a model, or retry through another harness/provider.
|
|
48
|
+
7. **Actionable synthesis** — the output should help the user make decisions, not just list opinions.
|
|
47
49
|
|
|
48
50
|
## How to Operate
|
|
49
51
|
|
|
@@ -62,7 +64,8 @@ Understand what needs brainstorming:
|
|
|
62
64
|
Intent:
|
|
63
65
|
- User request:
|
|
64
66
|
- Brainstorm mode:
|
|
65
|
-
-
|
|
67
|
+
- Participants: <provider via harness, exact requested model for each>
|
|
68
|
+
- Explicitly excluded:
|
|
66
69
|
|
|
67
70
|
Scope:
|
|
68
71
|
- Changed/referenced files:
|
|
@@ -102,8 +105,8 @@ Your own deep research phase. Do NOT skip this. Do NOT delegate it to a sub-agen
|
|
|
102
105
|
1. **Read the actual artifacts.** If the topic references specific files, skills, or code, Read them. Don't reason about what you assume they contain — verify. Use Glob and Grep to find supporting context.
|
|
103
106
|
2. **Trace through the real behavior.** If the topic involves a pipeline, effect, state machine, or control flow, mentally execute the code with the repo's actual conventions in mind. Factor in framework-specific semantics (React Compiler, XState, RTK Query, etc.) that a generic reviewer might miss.
|
|
104
107
|
3. **Use WebFetch/WebSearch when the topic references external docs.** If the topic mentions a library, framework, RFC, or public URL, fetch the current docs — don't rely on training data.
|
|
105
|
-
4. **Form independent findings** structured identically to
|
|
106
|
-
5. **Update the Context Brief.** Record
|
|
108
|
+
4. **Form independent findings** structured identically to external output: numbered points, pros/cons, priorities. In exact Grok + Sol mode label this a **non-voting verification memo**, not a participant answer.
|
|
109
|
+
5. **Update the Context Brief.** Record verified files/docs, intentionally excluded artifacts, unverified assumptions, and every exact participant identity before dispatch. For exact mode, explicitly record Gemini and all unselected routes as excluded.
|
|
107
110
|
6. **Record confidence per finding.** Mark each finding as:
|
|
108
111
|
- **Verified** — backed by an actual file Read, code trace, or fetched document (highest confidence)
|
|
109
112
|
- **Inferred** — reasoned from the topic description without direct verification (lower confidence)
|
|
@@ -118,9 +121,43 @@ The user specifies which external providers to use. Default is `antigravity,code
|
|
|
118
121
|
- `antigravity` — Google Antigravity, subscription-backed via your Google AI Pro/Ultra plan, via the `agy` CLI (experimental; requires `agy` >=1.1.5 installed + logged in)
|
|
119
122
|
- `gemini` — Google Gemini (large context, strong at analysis) via the `gemini` CLI
|
|
120
123
|
- `codex` — OpenAI Codex (strong at code reasoning) via `codex exec --sandbox read-only`
|
|
121
|
-
- `grok` — Grok
|
|
124
|
+
- `grok` — bare Grok remains the compatible canonical-runner path with explicit `ASK_GROK_HARNESS` (`xai-api` default or `grok-cli`); routed Grok uses the exact selected harness/model and never falls back
|
|
122
125
|
- `ollama` — Local Ollama (private, no data leaves machine) via the `ollama` CLI
|
|
123
126
|
|
|
127
|
+
Participant specs use `provider@harness:exact-model-id`. The preferred Grok route is Cursor Agent. The supported exact architect panel is:
|
|
128
|
+
|
|
129
|
+
- `grok@cursor-agent:cursor-grok-4.6-high`
|
|
130
|
+
- `codex@cursor-agent:gpt-5.6-sol-high`
|
|
131
|
+
|
|
132
|
+
Account catalogs can change; an unavailable exact ID is a clear failure, not permission to choose Auto or another ID. Grok Build remains explicit as `grok@grok-cli:grok-build` when the installed CLI supports the canonical contract. The exact panel contains no Gemini and must never launch a Gemini process/tool.
|
|
133
|
+
|
|
134
|
+
A list that mixes routed specs with bare provider names (for example `grok@cursor-agent:cursor-grok-4.6-high,antigravity`) is unsupported: stop before Phase 3A, report `Mixed brainstorm participant lists are not supported: routed "<spec>" cannot be combined with bare "<provider>". Use either an all-bare provider list or the exact routed Grok + GPT-5.6 Sol panel. No participant was substituted, rerouted, or dispatched.`, and dispatch nothing. Never downgrade a routed spec to `grok-run.js`/`codex-run.js` or promote a bare name into a routed spec; `brainstorm-run.js` refuses such lists with the same error. Generalized mixed panels are deferred to a future ADR.
|
|
135
|
+
|
|
136
|
+
**Exact Grok + GPT-5.6 Sol branch (preferred architect workflow):**
|
|
137
|
+
|
|
138
|
+
Use this branch instead of the generic template whenever the selected providers are exactly Grok and Codex with explicit route specs. Validate both specs first, then make one foreground call:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
set +e
|
|
142
|
+
workdir=$(mktemp -d /tmp/brainstorm-XXXXXX)
|
|
143
|
+
trap 'rm -rf "$workdir"' EXIT
|
|
144
|
+
cat > "$workdir/prompt.md" <<'PROMPT_EOF'
|
|
145
|
+
<INSERT THE PHASE 2 PROMPT HERE>
|
|
146
|
+
PROMPT_EOF
|
|
147
|
+
|
|
148
|
+
node "${CLAUDE_PLUGIN_ROOT}/dist/brainstorm-run.js" \
|
|
149
|
+
--participant 'grok@cursor-agent:cursor-grok-4.6-high' \
|
|
150
|
+
--participant 'codex@cursor-agent:gpt-5.6-sol-high' \
|
|
151
|
+
< "$workdir/prompt.md" > "$workdir/panel.json" 2> "$workdir/panel.err"
|
|
152
|
+
rc_panel=$?
|
|
153
|
+
echo "===== GROK + GPT-5.6 SOL PANEL (rc=$rc_panel) ====="
|
|
154
|
+
cat "$workdir/panel.json"
|
|
155
|
+
echo "===== PANEL STDERR ====="
|
|
156
|
+
cat "$workdir/panel.err"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Substitute only user-supplied, grammar-validated exact specs. For the explicit Grok Build alternative, substitute only the Grok spec with `grok@grok-cli:grok-build`; do not change the Sol route. `brainstorm-run.js` starts both participants concurrently, preserves input order and identity, returns `complete | partial | failed`, and exits 2 for partial/failed participant execution. Parse its JSON even when rc=2. It does not know or support Gemini, and it does not pivot routes.
|
|
160
|
+
|
|
124
161
|
**Required Bash tool call parameters:**
|
|
125
162
|
- `timeout: 600000` — 10 minutes, the Bash tool maximum. The default 2 minutes will kill Codex at high reasoning effort mid-response, recreating the same silent-failure class this phase is designed to avoid.
|
|
126
163
|
- Do NOT set `run_in_background: true`. This call MUST be foreground-blocking.
|
|
@@ -189,12 +226,12 @@ pid_codex=$!
|
|
|
189
226
|
|
|
190
227
|
# Only include this block if grok was requested. The canonical runner preserves
|
|
191
228
|
# explicit API-vs-CLI harness selection, key redaction, timeout/cancellation,
|
|
192
|
-
#
|
|
229
|
+
# served-model attribution, and the no-fallback contract.
|
|
193
230
|
node "${CLAUDE_PLUGIN_ROOT}/dist/grok-run.js" "$(cat "$workdir/prompt.md")" > "$workdir/grok.out" 2> "$workdir/grok.err" &
|
|
194
231
|
pid_grok=$!
|
|
195
232
|
|
|
196
233
|
# Only include this line if ollama was requested:
|
|
197
|
-
ollama run "${ASK_OLLAMA_MODEL:-qwen3.
|
|
234
|
+
ollama run "${ASK_OLLAMA_MODEL:-qwen3.8:27b}" < "$workdir/prompt.md" > "$workdir/ollama.out" 2> "$workdir/ollama.err" &
|
|
198
235
|
pid_ollama=$!
|
|
199
236
|
|
|
200
237
|
# Wait for each by PID so we capture per-provider exit codes independently.
|
|
@@ -236,7 +273,14 @@ cat "$workdir/ollama.err" 2>/dev/null
|
|
|
236
273
|
|
|
237
274
|
### Phase 4: Synthesis
|
|
238
275
|
|
|
239
|
-
Now, and only now, parse the Phase 3A
|
|
276
|
+
Now, and only now, parse the Phase 3A output and combine it with Phase 3B evidence. In exact Grok + Sol mode, first apply the runner's deterministic gate:
|
|
277
|
+
|
|
278
|
+
- `complete` + `consensusEligible:true`: both exact participants answered; a point may be called two-model consensus only if both independently stated it. Carry each participant's `requestedModel`, `observedModel` (direct routes only), `reportedModel` (Cursor label), `modelVerification`, and `attributionNote` into the participant list verbatim.
|
|
279
|
+
- `partial`: name the failed participant with provider/harness/requested model/error, attribute surviving insights only to the successful participant, and do not create a Consensus section claiming panel agreement.
|
|
280
|
+
- `failed`: report both failures and provide no panel-derived synthesis.
|
|
281
|
+
- The non-voting Claude evidence memo may verify, reject, or contextualize a claim, but cannot turn one external answer into two-model consensus.
|
|
282
|
+
|
|
283
|
+
Then produce the structured synthesis.
|
|
240
284
|
|
|
241
285
|
**Cross-check high-confidence external claims first.** Before promoting any external-provider finding to "Consensus," spot-check it against the source if it cites a specific file/line/symbol. External providers can return high-confidence claims that are factually wrong — for example, on 2026-04-17 Gemini returned two findings at 95/100 confidence that were contradicted by the actual `.d.ts` and an existing fallback path. A 30-second `Read` or `Grep` is the difference between recommending a real fix and recommending a non-fix. Mark each cross-checked finding as **Verified** (matches source), **Rejected** (false positive — exclude from synthesis), or **Unverifiable** (no source citation or external-only knowledge — present as-is with a note).
|
|
242
286
|
|
|
@@ -267,22 +311,21 @@ Surface this grade as the first line of the synthesis output (see Output Format
|
|
|
267
311
|
**Synthesis confidence:** [PERFECT | VERIFIED | PARTIAL | FAILED] — [one-line reason citing what was/wasn't verified]
|
|
268
312
|
|
|
269
313
|
### Participants Consulted
|
|
270
|
-
-
|
|
271
|
-
- ✅
|
|
272
|
-
- ✅ Codex
|
|
273
|
-
-
|
|
314
|
+
- ℹ️ Claude Opus: non-voting evidence verifier (exact two-model mode; verified against real files: path/to/a, path/to/b)
|
|
315
|
+
- ✅ Grok via Cursor Agent — requested `cursor-grok-4.6-high` (selected-unverified: Cursor echoes the requested ID); reported display label `Cursor Grok 4.6` (label, not a catalog ID)
|
|
316
|
+
- ✅ Codex via Cursor Agent — requested `gpt-5.6-sol-high` (selected-unverified); reported display label `GPT-5.6 Sol 1M High`
|
|
317
|
+
- (direct route example) ✅ Grok via xAI API — requested `grok-4.6`; observed served `grok-4.6-<snapshot>` (observed-alias, disclosed same-product resolution)
|
|
318
|
+
- 🚫 Gemini: explicitly excluded (not called)
|
|
274
319
|
|
|
275
|
-
### Consensus (high confidence)
|
|
276
|
-
1. [Point] — agreed by
|
|
277
|
-
2. [Point] — agreed by Gemini and Codex
|
|
320
|
+
### Consensus (high confidence; omit for a partial exact panel)
|
|
321
|
+
1. [Point] — independently agreed by <name both successful panel participants with provider/harness/model>
|
|
278
322
|
|
|
279
323
|
### Unique Insights
|
|
280
|
-
-
|
|
281
|
-
- **
|
|
282
|
-
- **Codex**: [Insight and why it matters]
|
|
324
|
+
- **<Provider via harness — exact model>**: [Insight and why it matters]
|
|
325
|
+
- **Claude Opus evidence memo** (non-voting in exact mode): [Source-backed verification or rejection]
|
|
283
326
|
|
|
284
327
|
### Contradictions
|
|
285
|
-
- [Topic]:
|
|
328
|
+
- [Topic]: <participant A identity> says X; <participant B identity> says Y. Evidence assessment: [verified source and conclusion].
|
|
286
329
|
|
|
287
330
|
### Recommendations
|
|
288
331
|
1. [Highest priority action]
|
|
@@ -310,7 +353,9 @@ The only place background jobs persist across turns is the **main conversation c
|
|
|
310
353
|
- **Never skip Phase 3B.** It's what makes you a participant instead of a relay. If you skip it, the user gets exactly the same result they'd get from calling the providers directly — the Opus budget is wasted.
|
|
311
354
|
- **Phase 3B runs BEFORE Phase 3A.** The ordering is how blindness is enforced *and* how the sub-agent background-job lifecycle bug is avoided. Do not reorder.
|
|
312
355
|
- **Phase 3A is a single foreground blocking Bash call** with `timeout: 600000` — see the "Critical: Sub-Agent Background Job Lifecycle" section. Violating this reintroduces issue #23 silently.
|
|
313
|
-
- **Never fabricate a provider's response.** If a
|
|
356
|
+
- **Never fabricate a provider's response.** If a participant exits non-zero or produces empty output, report provider, harness, requested model, and error honestly.
|
|
357
|
+
- **Never misstate partial consensus.** One successful member of a two-model panel is one perspective, even when Claude's evidence agrees.
|
|
358
|
+
- **Never route implicitly.** Cursor Auto, display-label inference, model rewriting, and cross-harness/provider retries are forbidden.
|
|
314
359
|
- **Don't bias the prompt toward any particular answer** — let participants form independent opinions.
|
|
315
360
|
- **Verified findings outrank inferred ones in consensus scoring** — but external providers can still win when they catch domain patterns from their training data that aren't in the local repo.
|
|
316
361
|
- **Keep the synthesis concise and actionable.** The user wants decisions, not essays.
|
|
@@ -14,7 +14,7 @@ tools:
|
|
|
14
14
|
<!-- PORTABLE-CONTRACT:START -->
|
|
15
15
|
## Portable contract
|
|
16
16
|
|
|
17
|
-
Review only the supplied changes and context. Ask Gemini for concrete correctness, security, and regression concerns; validate every candidate against source; require file/line evidence and reproduction for behavior claims; omit style-only or speculative findings; report provider failures explicitly.
|
|
17
|
+
Review only the supplied changes and context. Ask Gemini for concrete correctness, security, and regression concerns; validate every candidate against source; require file/line evidence and reproduction for behavior claims; omit style-only or speculative findings; report provider failures explicitly. Preserve the canonical `gemini-3.1-pro-preview` → `gemini-3.8-flash` quota fallback and disclose when fallback occurs.
|
|
18
18
|
<!-- PORTABLE-CONTRACT:END -->
|
|
19
19
|
|
|
20
20
|
<!-- HOST-ADAPTER:CLAUDE-CODE:START -->
|
package/dist/antigravity-run.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const BRAINSTORM_PANEL_PROVIDERS: readonly ["grok", "codex"];
|
|
2
|
+
export type BrainstormPanelProvider = (typeof BRAINSTORM_PANEL_PROVIDERS)[number];
|
|
3
|
+
export type BrainstormPanelHarness = "cursor-agent" | "grok-cli" | "xai-api" | "codex-cli";
|
|
4
|
+
export declare const BARE_BRAINSTORM_PROVIDERS: readonly ["gemini", "codex", "grok", "ollama", "antigravity"];
|
|
5
|
+
export type BareBrainstormProvider = (typeof BARE_BRAINSTORM_PROVIDERS)[number];
|
|
6
|
+
export type BrainstormParticipantList = {
|
|
7
|
+
mode: "bare";
|
|
8
|
+
providers: BareBrainstormProvider[];
|
|
9
|
+
} | {
|
|
10
|
+
mode: "exact";
|
|
11
|
+
participants: BrainstormParticipant[];
|
|
12
|
+
};
|
|
13
|
+
export type BrainstormModelVerification = "observed-exact" | "observed-alias" | "selected-unverified" | "mismatch" | "fallback";
|
|
14
|
+
export interface BrainstormParticipant {
|
|
15
|
+
provider: BrainstormPanelProvider;
|
|
16
|
+
harness: BrainstormPanelHarness;
|
|
17
|
+
model: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BrainstormParticipantResult extends BrainstormParticipant {
|
|
20
|
+
status: "fulfilled" | "rejected";
|
|
21
|
+
requestedModel: string;
|
|
22
|
+
observedModel?: string;
|
|
23
|
+
reportedModel?: string;
|
|
24
|
+
modelVerification?: BrainstormModelVerification;
|
|
25
|
+
attributionNote?: string;
|
|
26
|
+
response?: string;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface BrainstormPanelReport {
|
|
30
|
+
panel: "grok+gpt-5.6-sol";
|
|
31
|
+
status: "complete" | "partial" | "failed";
|
|
32
|
+
consensusEligible: boolean;
|
|
33
|
+
synthesisRule: string;
|
|
34
|
+
participants: BrainstormParticipantResult[];
|
|
35
|
+
}
|
|
36
|
+
export declare function parseBrainstormParticipant(spec: string): BrainstormParticipant;
|
|
37
|
+
export declare function parseBrainstormParticipantList(specs: string[]): BrainstormParticipantList;
|
|
38
|
+
export declare function validateBrainstormPanel(participants: BrainstormParticipant[]): void;
|
|
39
|
+
export declare function isSameProductResolution(requested: string, observed: string): boolean;
|
|
40
|
+
export declare function runBrainstormPanel(options: {
|
|
41
|
+
prompt: string;
|
|
42
|
+
participants: BrainstormParticipant[];
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
onProgress?: (message: string) => void;
|
|
45
|
+
}): Promise<BrainstormPanelReport>;
|
|
46
|
+
//# sourceMappingURL=brainstorm-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brainstorm-panel.d.ts","sourceRoot":"","sources":["../src/brainstorm-panel.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,0BAA0B,YAAI,MAAM,EAAE,OAAO,CAAU,CAAC;AACrE,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAClF,MAAM,MAAM,sBAAsB,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;AAC3F,eAAO,MAAM,yBAAyB,YAAI,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAU,CAAC;AACvG,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,sBAAsB,EAAE,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,qBAAqB,EAAE,CAAA;CAAE,CAAC;AAE7D,MAAM,MAAM,2BAA2B,GACnC,gBAAgB,GAChB,gBAAgB,GAChB,qBAAqB,GACrB,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,uBAAuB,CAAC;IAClC,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA4B,SAAQ,qBAAqB;IACxE,MAAM,EAAE,WAAW,GAAG,UAAU,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,2BAA2B,CAAC;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC1C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,2BAA2B,EAAE,CAAC;CAC7C;AAYD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,CAqB9E;AAMD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,yBAAyB,CAoBzF;AAED,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,IAAI,CA4BnF;AAID,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CASpF;AAuLD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAiBjC"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { executeCodexCLI } from "@ask-llm/codex-mcp/executor";
|
|
2
|
+
import { executeGrok } from "@ask-llm/grok-mcp/executor";
|
|
3
|
+
import { executeCursorAgent } from "@ask-llm/mcp/cursor";
|
|
4
|
+
export const BRAINSTORM_PANEL_PROVIDERS = ["grok", "codex"];
|
|
5
|
+
export const BARE_BRAINSTORM_PROVIDERS = ["gemini", "codex", "grok", "ollama", "antigravity"];
|
|
6
|
+
const SYNTHESIS_RULE = "Call a point two-model consensus only when both requested participants fulfilled successfully and independently stated it. On any participant failure, label the run partial and attribute surviving insights to that participant only.";
|
|
7
|
+
function routeAllowed(participant) {
|
|
8
|
+
if (participant.provider === "grok") {
|
|
9
|
+
return ["cursor-agent", "grok-cli", "xai-api"].includes(participant.harness);
|
|
10
|
+
}
|
|
11
|
+
return ["cursor-agent", "codex-cli"].includes(participant.harness);
|
|
12
|
+
}
|
|
13
|
+
export function parseBrainstormParticipant(spec) {
|
|
14
|
+
const match = spec.match(/^(grok|codex)@(cursor-agent|grok-cli|xai-api|codex-cli):(.+)$/);
|
|
15
|
+
if (!match) {
|
|
16
|
+
throw new Error(`Invalid brainstorm participant "${spec}". Use provider@harness:exact-model-id (for example grok@cursor-agent:cursor-grok-4.6-high).`);
|
|
17
|
+
}
|
|
18
|
+
const participant = {
|
|
19
|
+
provider: match[1],
|
|
20
|
+
harness: match[2],
|
|
21
|
+
model: match[3].trim(),
|
|
22
|
+
};
|
|
23
|
+
if (!participant.model || participant.model.toLowerCase() === "auto") {
|
|
24
|
+
throw new Error(`Participant "${spec}" requires an exact non-Auto model ID from the selected harness catalog.`);
|
|
25
|
+
}
|
|
26
|
+
if (!routeAllowed(participant)) {
|
|
27
|
+
throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. Harness, provider, and model are not interchangeable; no substitute route was selected.`);
|
|
28
|
+
}
|
|
29
|
+
return participant;
|
|
30
|
+
}
|
|
31
|
+
function isBareProvider(spec) {
|
|
32
|
+
return BARE_BRAINSTORM_PROVIDERS.includes(spec);
|
|
33
|
+
}
|
|
34
|
+
export function parseBrainstormParticipantList(specs) {
|
|
35
|
+
const trimmed = specs.map((spec) => spec.trim()).filter(Boolean);
|
|
36
|
+
if (trimmed.length === 0)
|
|
37
|
+
throw new Error("The brainstorm participant list is empty.");
|
|
38
|
+
const bare = trimmed.filter((spec) => !spec.includes("@"));
|
|
39
|
+
const routed = trimmed.filter((spec) => spec.includes("@"));
|
|
40
|
+
if (bare.length > 0 && routed.length > 0) {
|
|
41
|
+
throw new Error(`Mixed brainstorm participant lists are not supported: routed ${routed.map((spec) => `"${spec}"`).join(", ")} cannot be combined with bare ${bare.map((spec) => `"${spec}"`).join(", ")}. Use either an all-bare provider list or the exact routed Grok + GPT-5.6 Sol panel. No participant was substituted, rerouted, or dispatched.`);
|
|
42
|
+
}
|
|
43
|
+
if (routed.length > 0) {
|
|
44
|
+
return { mode: "exact", participants: routed.map(parseBrainstormParticipant) };
|
|
45
|
+
}
|
|
46
|
+
const unknown = bare.find((spec) => !isBareProvider(spec));
|
|
47
|
+
if (unknown) {
|
|
48
|
+
throw new Error(`Unknown brainstorm provider "${unknown}". Supported bare providers: ${BARE_BRAINSTORM_PROVIDERS.join(", ")}; routed participants use provider@harness:exact-model-id. No substitute was selected.`);
|
|
49
|
+
}
|
|
50
|
+
return { mode: "bare", providers: bare.filter(isBareProvider) };
|
|
51
|
+
}
|
|
52
|
+
export function validateBrainstormPanel(participants) {
|
|
53
|
+
if (participants.length !== 2) {
|
|
54
|
+
throw new Error("The Grok + GPT-5.6 Sol panel requires exactly two participants.");
|
|
55
|
+
}
|
|
56
|
+
const providers = participants.map(({ provider }) => provider);
|
|
57
|
+
if (new Set(providers).size !== providers.length) {
|
|
58
|
+
throw new Error("The Grok + GPT-5.6 Sol panel requires one Grok participant and one Codex participant.");
|
|
59
|
+
}
|
|
60
|
+
for (const required of BRAINSTORM_PANEL_PROVIDERS) {
|
|
61
|
+
if (!providers.includes(required)) {
|
|
62
|
+
throw new Error(`The Grok + GPT-5.6 Sol panel is missing provider "${required}".`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
for (const participant of participants) {
|
|
66
|
+
if (!participant.model.trim() || participant.model.toLowerCase() === "auto") {
|
|
67
|
+
throw new Error(`${participant.provider}@${participant.harness} requires an exact non-Auto model ID.`);
|
|
68
|
+
}
|
|
69
|
+
if (!routeAllowed(participant)) {
|
|
70
|
+
throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. No provider or harness fallback was attempted.`);
|
|
71
|
+
}
|
|
72
|
+
if (participant.provider === "codex" && !participant.model.toLowerCase().includes("gpt-5.6-sol")) {
|
|
73
|
+
throw new Error(`The Codex participant must request an exact GPT-5.6 Sol model ID; received "${participant.model}". No model substitution was attempted.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const LATEST_ALIAS_SUFFIX = "-latest";
|
|
78
|
+
export function isSameProductResolution(requested, observed) {
|
|
79
|
+
const requestedId = requested.trim().toLowerCase();
|
|
80
|
+
const observedId = observed.trim().toLowerCase();
|
|
81
|
+
if (requestedId === observedId)
|
|
82
|
+
return true;
|
|
83
|
+
const productId = requestedId.endsWith(LATEST_ALIAS_SUFFIX)
|
|
84
|
+
? requestedId.slice(0, -LATEST_ALIAS_SUFFIX.length)
|
|
85
|
+
: requestedId;
|
|
86
|
+
if (!productId || !observedId.startsWith(`${productId}-`))
|
|
87
|
+
return false;
|
|
88
|
+
return /^[0-9][0-9.-]*$/.test(observedId.slice(productId.length + 1));
|
|
89
|
+
}
|
|
90
|
+
function classifyObservedModel(participant, observedModel) {
|
|
91
|
+
const identity = `${participant.provider} via ${participant.harness}`;
|
|
92
|
+
if (observedModel.trim().toLowerCase() === participant.model.trim().toLowerCase()) {
|
|
93
|
+
return {
|
|
94
|
+
modelVerification: "observed-exact",
|
|
95
|
+
attributionNote: `${identity} reported served model "${observedModel}", matching the requested ID.`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (isSameProductResolution(participant.model, observedModel)) {
|
|
99
|
+
return {
|
|
100
|
+
modelVerification: "observed-alias",
|
|
101
|
+
attributionNote: `${identity} served "${observedModel}" for requested "${participant.model}" (disclosed provider-side alias/snapshot resolution of the same model; the requested ID was sent unchanged and was not rewritten).`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`${identity} requested exact model "${participant.model}" but reported "${observedModel}". The response is excluded from two-model consensus; no additional route was attempted.`);
|
|
105
|
+
}
|
|
106
|
+
function selectedOnlyNote(participant, detail) {
|
|
107
|
+
return `${participant.provider} via ${participant.harness} ran the requested ID "${participant.model}" (${detail}); the harness does not independently confirm the served catalog model, so this attribution is selected-only and unverifiable, not an observed actual model.`;
|
|
108
|
+
}
|
|
109
|
+
async function invokeParticipant(participant, prompt, signal, onProgress) {
|
|
110
|
+
const identity = `${participant.provider} via ${participant.harness} (${participant.model})`;
|
|
111
|
+
const progress = onProgress ? (message) => onProgress(`[${identity}] ${message}`) : undefined;
|
|
112
|
+
const base = { ...participant, requestedModel: participant.model };
|
|
113
|
+
let observedModel;
|
|
114
|
+
let reportedModel;
|
|
115
|
+
let modelVerification;
|
|
116
|
+
try {
|
|
117
|
+
if (participant.harness === "cursor-agent") {
|
|
118
|
+
const result = await executeCursorAgent({
|
|
119
|
+
provider: participant.provider,
|
|
120
|
+
model: participant.model,
|
|
121
|
+
prompt,
|
|
122
|
+
signal,
|
|
123
|
+
onProgress: progress,
|
|
124
|
+
});
|
|
125
|
+
reportedModel = result.reportedModel;
|
|
126
|
+
if (result.usage.fellBack) {
|
|
127
|
+
modelVerification = "fallback";
|
|
128
|
+
throw new Error(`Cursor Agent reported a model fallback for requested "${participant.model}". The response is excluded from two-model consensus.`);
|
|
129
|
+
}
|
|
130
|
+
if (result.model !== participant.model) {
|
|
131
|
+
modelVerification = "mismatch";
|
|
132
|
+
throw new Error(`Cursor Agent ran "${result.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
|
|
133
|
+
}
|
|
134
|
+
modelVerification = "selected-unverified";
|
|
135
|
+
return {
|
|
136
|
+
...base,
|
|
137
|
+
reportedModel,
|
|
138
|
+
modelVerification,
|
|
139
|
+
attributionNote: selectedOnlyNote(participant, reportedModel
|
|
140
|
+
? `Cursor echoed the requested ID and reported display label "${reportedModel}", which is a label and not a catalog ID`
|
|
141
|
+
: "Cursor echoed the requested ID and reported no display label"),
|
|
142
|
+
response: result.response,
|
|
143
|
+
status: "fulfilled",
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (participant.provider === "grok") {
|
|
147
|
+
if (participant.harness !== "grok-cli" && participant.harness !== "xai-api") {
|
|
148
|
+
throw new Error(`Unsupported brainstorm route ${participant.provider}@${participant.harness}. No fallback was attempted.`);
|
|
149
|
+
}
|
|
150
|
+
const result = await executeGrok({
|
|
151
|
+
prompt,
|
|
152
|
+
model: participant.model,
|
|
153
|
+
harness: participant.harness,
|
|
154
|
+
reasoningEffort: "high",
|
|
155
|
+
signal,
|
|
156
|
+
onProgress: progress,
|
|
157
|
+
});
|
|
158
|
+
if (result.usage?.fellBack) {
|
|
159
|
+
modelVerification = "fallback";
|
|
160
|
+
throw new Error(`${participant.harness} reported a model fallback for requested "${participant.model}". The response is excluded from two-model consensus.`);
|
|
161
|
+
}
|
|
162
|
+
if (!result.reportedModel) {
|
|
163
|
+
if (result.model !== participant.model) {
|
|
164
|
+
modelVerification = "mismatch";
|
|
165
|
+
throw new Error(`${participant.provider} via ${participant.harness} ran "${result.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
|
|
166
|
+
}
|
|
167
|
+
modelVerification = "selected-unverified";
|
|
168
|
+
return {
|
|
169
|
+
...base,
|
|
170
|
+
modelVerification,
|
|
171
|
+
attributionNote: selectedOnlyNote(participant, `${participant.harness} reported no served model ID, so only the requested ID is known`),
|
|
172
|
+
response: result.response,
|
|
173
|
+
status: "fulfilled",
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
observedModel = result.reportedModel;
|
|
177
|
+
let observed;
|
|
178
|
+
try {
|
|
179
|
+
observed = classifyObservedModel(participant, observedModel);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
modelVerification = "mismatch";
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
modelVerification = observed.modelVerification;
|
|
186
|
+
return {
|
|
187
|
+
...base,
|
|
188
|
+
observedModel,
|
|
189
|
+
modelVerification,
|
|
190
|
+
attributionNote: observed.attributionNote,
|
|
191
|
+
response: result.response,
|
|
192
|
+
status: "fulfilled",
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const result = await executeCodexCLI({
|
|
196
|
+
prompt,
|
|
197
|
+
model: participant.model,
|
|
198
|
+
reasoningEffort: "high",
|
|
199
|
+
sandbox: "read-only",
|
|
200
|
+
signal,
|
|
201
|
+
onProgress: progress,
|
|
202
|
+
});
|
|
203
|
+
if (result.usage?.fellBack) {
|
|
204
|
+
modelVerification = "fallback";
|
|
205
|
+
throw new Error(`Codex CLI reported a model fallback to "${result.usage.model}" for requested "${participant.model}". The response is excluded from two-model consensus.`);
|
|
206
|
+
}
|
|
207
|
+
if (result.usage && result.usage.model !== participant.model) {
|
|
208
|
+
modelVerification = "mismatch";
|
|
209
|
+
throw new Error(`Codex CLI ran "${result.usage.model}" instead of requested "${participant.model}". The response is excluded from two-model consensus; no additional route was attempted.`);
|
|
210
|
+
}
|
|
211
|
+
modelVerification = "selected-unverified";
|
|
212
|
+
return {
|
|
213
|
+
...base,
|
|
214
|
+
modelVerification,
|
|
215
|
+
attributionNote: selectedOnlyNote(participant, result.usage
|
|
216
|
+
? "Codex CLI echoed the requested ID with no fallback"
|
|
217
|
+
: "served from the Codex response cache keyed by the requested ID, which stores only no-fallback responses"),
|
|
218
|
+
response: result.response,
|
|
219
|
+
status: "fulfilled",
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
return {
|
|
224
|
+
...base,
|
|
225
|
+
observedModel,
|
|
226
|
+
reportedModel,
|
|
227
|
+
modelVerification,
|
|
228
|
+
status: "rejected",
|
|
229
|
+
error: error instanceof Error ? error.message : String(error),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
export async function runBrainstormPanel(options) {
|
|
234
|
+
if (!options.prompt.trim())
|
|
235
|
+
throw new Error("The brainstorm panel requires a non-empty prompt.");
|
|
236
|
+
validateBrainstormPanel(options.participants);
|
|
237
|
+
const participants = await Promise.all(options.participants.map((participant) => invokeParticipant(participant, options.prompt, options.signal, options.onProgress)));
|
|
238
|
+
const successCount = participants.filter(({ status }) => status === "fulfilled").length;
|
|
239
|
+
return {
|
|
240
|
+
panel: "grok+gpt-5.6-sol",
|
|
241
|
+
status: successCount === 2 ? "complete" : successCount === 1 ? "partial" : "failed",
|
|
242
|
+
consensusEligible: successCount === 2,
|
|
243
|
+
synthesisRule: SYNTHESIS_RULE,
|
|
244
|
+
participants,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=brainstorm-panel.js.map
|