second-advisor 0.1.0
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/LICENSE +21 -0
- package/README.md +334 -0
- package/package.json +70 -0
- package/src/advisors.ts +205 -0
- package/src/config.ts +118 -0
- package/src/index.ts +86 -0
- package/src/models.ts +87 -0
- package/src/process.ts +47 -0
- package/src/routing.ts +19 -0
- package/src/ui.ts +554 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kenryu42
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# Second Advisor
|
|
2
|
+
|
|
3
|
+
[](https://github.com/kenryu42/second-advisor/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/kenryu42/second-advisor)
|
|
5
|
+
[](#supported-advisors)
|
|
6
|
+
[](#supported-advisors)
|
|
7
|
+
[](#supported-advisors)
|
|
8
|
+
[](#supported-advisors)
|
|
9
|
+
[](#supported-advisors)
|
|
10
|
+
[](#supported-advisors)
|
|
11
|
+
[](#supported-advisors)
|
|
12
|
+
[](#supported-advisors)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
|
|
15
|
+
`second-advisor` is a small CLI that sends a prompt to another coding CLI for a second opinion. It is intended for review-oriented workflows where your primary agent or editor can ask a configured advisor to inspect substantial work before a final response.
|
|
16
|
+
|
|
17
|
+
The CLI stores one configured advisor, model or mode, and thinking/effort setting, then builds the correct non-interactive command for that advisor.
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- Interactive initialization with installed advisor detection.
|
|
22
|
+
- Prompt forwarding to supported coding CLIs.
|
|
23
|
+
- Short command alias: `sa`.
|
|
24
|
+
- Debug output for the raw command that will be executed.
|
|
25
|
+
- Doctor command for checking config and advisor executables.
|
|
26
|
+
- Model/mode listing for advisors that expose model discovery.
|
|
27
|
+
- Setup command that appends second-advisor workflow instructions to `AGENTS.md` and/or `CLAUDE.md`.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- Bun
|
|
32
|
+
- At least one supported coding CLI installed on `PATH`
|
|
33
|
+
|
|
34
|
+
The command entrypoint is `src/index.ts` with `#!/usr/bin/env bun`, so Bun must be available on `PATH` even when using a linked command.
|
|
35
|
+
|
|
36
|
+
Supported advisors:
|
|
37
|
+
|
|
38
|
+
| Advisor | Executable | Notes |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| Claude | `claude` | Uses built-in aliases: `haiku`, `sonnet`, `opus`. |
|
|
41
|
+
| Codex | `codex` | Lists bundled models with `codex debug models --bundled`. |
|
|
42
|
+
| opencode | `opencode` | Lists models with `opencode models`. |
|
|
43
|
+
| Grok | `grok` | Lists models with `grok models`. |
|
|
44
|
+
| Pi | `pi` | Lists models with `pi --list-models`. |
|
|
45
|
+
| Droid | `droid` | Extracts models from `droid exec --help`. |
|
|
46
|
+
| Amp | `amp` | Uses modes: `rush`, `smart`, `deep`. |
|
|
47
|
+
| Kimi | `kimi` | Lists models with `kimi provider list --json`; no thinking setting. |
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
Install dependencies:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
bun install
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Run locally:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
bun run src/index.ts
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For local command usage, link the package so the `bin` entries are available:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
bun link
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Depending on your Bun setup, you may also need Bun's global bin directory on `PATH`.
|
|
70
|
+
|
|
71
|
+
After linking, both commands point to the same CLI:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
second-advisor --help
|
|
75
|
+
sa --help
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
Initialize the advisor config:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
second-advisor init
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Send a prompt:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
second-advisor "review this implementation for correctness and missed edge cases"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Use the short alias:
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
sa "say hi"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Print the raw advisor command before running it:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
second-advisor "say hi" --debug
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Example debug output:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
amp --mode rush --effort low --execute 'say hi'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Commands
|
|
111
|
+
|
|
112
|
+
### `second-advisor`
|
|
113
|
+
|
|
114
|
+
With no arguments, opens the interactive menu. If no config exists, the menu offers initialization. If a config exists, the menu shows current setup and lets you change advisor, model/mode, thinking/effort, list models, or run doctor.
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
second-advisor
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `second-advisor init`
|
|
121
|
+
|
|
122
|
+
Creates or replaces the config at:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
~/.config/second-advisor/config.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The initializer detects supported CLIs on `PATH`, asks which advisor to use, then prompts for a model/mode and thinking/effort setting when applicable.
|
|
129
|
+
|
|
130
|
+
### `second-advisor "<prompt>"`
|
|
131
|
+
|
|
132
|
+
Runs the configured advisor with the given prompt. The prompt is formed by joining all non-command arguments with spaces.
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
second-advisor "what risks do you see in this change?"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
If no config exists, the command exits with an error and asks you to run `second-advisor init`.
|
|
139
|
+
|
|
140
|
+
The first argument is reserved when it is one of the command names: `init`, `doctor`, `models`, `setup`, or `status`. For example, `second-advisor init` runs initialization instead of sending `init` as a prompt.
|
|
141
|
+
|
|
142
|
+
### `second-advisor "<prompt>" --debug`
|
|
143
|
+
|
|
144
|
+
Prints the exact advisor command before executing it.
|
|
145
|
+
|
|
146
|
+
```sh
|
|
147
|
+
second-advisor "review this diff" --debug
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The debug line is written to stderr so advisor stdout remains usable.
|
|
151
|
+
|
|
152
|
+
### `second-advisor status`
|
|
153
|
+
|
|
154
|
+
Shows the current config, config file path, and whether the configured advisor executable is present on `PATH`.
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
second-advisor status
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `second-advisor doctor`
|
|
161
|
+
|
|
162
|
+
Checks installed advisor CLI versions, loads the config, confirms the configured executable exists, and verifies Amp mode validity.
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
second-advisor doctor
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `second-advisor models [advisor]`
|
|
169
|
+
|
|
170
|
+
Lists models or modes for an advisor.
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
second-advisor models
|
|
174
|
+
second-advisor models amp
|
|
175
|
+
second-advisor models codex
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If no advisor is passed, the command uses the configured advisor. Claude and Amp are listed from built-in aliases/modes. Other supported advisors use their model-list commands when available.
|
|
179
|
+
|
|
180
|
+
During interactive setup, advisors with model-list commands fall back to manual model entry if model discovery does not return choices.
|
|
181
|
+
|
|
182
|
+
### `second-advisor setup`
|
|
183
|
+
|
|
184
|
+
Looks for `AGENTS.md` and `CLAUDE.md` in the current working directory and appends the Second Advisor Review instructions to each file found.
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
second-advisor setup
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Behavior:
|
|
191
|
+
|
|
192
|
+
- Updates both files if both exist.
|
|
193
|
+
- Skips a file if it already contains `## Second Advisor Review`.
|
|
194
|
+
- Exits with code `1` if neither `AGENTS.md` nor `CLAUDE.md` exists in the current directory.
|
|
195
|
+
- Does not search parent directories.
|
|
196
|
+
|
|
197
|
+
The appended block tells agents to ask for a second opinion after substantial work and to use:
|
|
198
|
+
|
|
199
|
+
```sh
|
|
200
|
+
second-advisor "<review prompt>"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Configuration
|
|
204
|
+
|
|
205
|
+
Config is stored at:
|
|
206
|
+
|
|
207
|
+
```text
|
|
208
|
+
~/.config/second-advisor/config.json
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Example Amp config:
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"advisor": "amp",
|
|
216
|
+
"model": "rush",
|
|
217
|
+
"thinking": "low"
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Example Kimi config:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"advisor": "kimi",
|
|
226
|
+
"model": "kimi-k2"
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Validation rules:
|
|
231
|
+
|
|
232
|
+
- `advisor` must be one of the supported advisors.
|
|
233
|
+
- Most advisors require `model` and `thinking`.
|
|
234
|
+
- Kimi requires `model` and does not support `thinking`.
|
|
235
|
+
- Claude models must be one of `haiku`, `sonnet`, or `opus`.
|
|
236
|
+
- Claude thinking must be one of `low`, `medium`, `high`, `xhigh`, or `max`.
|
|
237
|
+
- Codex thinking must be one of `low`, `medium`, `high`, or `xhigh`.
|
|
238
|
+
- Pi thinking must be one of `off`, `minimal`, `low`, `medium`, `high`, or `xhigh`.
|
|
239
|
+
- Amp modes must be one of `rush`, `smart`, or `deep`.
|
|
240
|
+
- Amp `rush` supports only `none`, `minimal`, `low`, and `medium` effort.
|
|
241
|
+
|
|
242
|
+
## Exit Codes
|
|
243
|
+
|
|
244
|
+
- Prompt execution forwards the configured advisor command's exit code.
|
|
245
|
+
- Prompt execution exits with code `1` when no config exists.
|
|
246
|
+
- `setup` exits with code `1` when neither `AGENTS.md` nor `CLAUDE.md` exists in the current working directory.
|
|
247
|
+
- Unhandled config parse errors are printed by the CLI and exit with code `1`.
|
|
248
|
+
|
|
249
|
+
## Advisor Command Mapping
|
|
250
|
+
|
|
251
|
+
`second-advisor` runs advisors non-interactively:
|
|
252
|
+
|
|
253
|
+
| Advisor | Command shape |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| Claude | `claude --model <model> --effort <thinking> -p <prompt>` |
|
|
256
|
+
| Codex | `codex exec -m <model> --config model_reasoning_effort=<thinking> <prompt>` |
|
|
257
|
+
| opencode | `opencode run -m <model> --variant <thinking> <prompt>` |
|
|
258
|
+
| Grok | `grok -m <model> --reasoning-effort <thinking> -p <prompt>` |
|
|
259
|
+
| Pi | `pi --model <model> --thinking <thinking> -p <prompt>` |
|
|
260
|
+
| Droid | `droid exec -m <model> --reasoning-effort <thinking> <prompt>` |
|
|
261
|
+
| Amp | `amp --mode <mode> --effort <thinking> --execute <prompt>` |
|
|
262
|
+
| Kimi | `kimi -m <model> -p <prompt>` |
|
|
263
|
+
|
|
264
|
+
Use `--debug` to inspect the exact command for your current config.
|
|
265
|
+
|
|
266
|
+
## Development
|
|
267
|
+
|
|
268
|
+
Install dependencies:
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
bun install
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Run the CLI during development:
|
|
275
|
+
|
|
276
|
+
```sh
|
|
277
|
+
bun run src/index.ts
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Or use the project script:
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
bun run sa
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Run the full verification suite:
|
|
287
|
+
|
|
288
|
+
```sh
|
|
289
|
+
bun run check
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`bun run check` runs typecheck, Biome lint, Knip, copy-paste detection, and tests.
|
|
293
|
+
|
|
294
|
+
Useful scripts:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
bun run test
|
|
298
|
+
bun run test:watch
|
|
299
|
+
bun run typecheck
|
|
300
|
+
bun run lint
|
|
301
|
+
bun run publish:dry-run
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Troubleshooting
|
|
305
|
+
|
|
306
|
+
### `second-advisor is not initialized`
|
|
307
|
+
|
|
308
|
+
Run:
|
|
309
|
+
|
|
310
|
+
```sh
|
|
311
|
+
second-advisor init
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Advisor executable is missing
|
|
315
|
+
|
|
316
|
+
Make sure the configured advisor CLI is installed and available on `PATH`, then run:
|
|
317
|
+
|
|
318
|
+
```sh
|
|
319
|
+
second-advisor doctor
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
If `second-advisor init` reports that no supported coding CLI was found, install one of the supported advisor CLIs or fix your `PATH`.
|
|
323
|
+
|
|
324
|
+
### Model listing fails
|
|
325
|
+
|
|
326
|
+
Some advisors depend on their own CLI model-list command. Confirm that advisor is authenticated and that its model-list command works directly.
|
|
327
|
+
|
|
328
|
+
### Setup cannot find instruction files
|
|
329
|
+
|
|
330
|
+
`second-advisor setup` only checks the current working directory. Run it from the directory that contains `AGENTS.md` or `CLAUDE.md`.
|
|
331
|
+
|
|
332
|
+
## License
|
|
333
|
+
|
|
334
|
+
MIT. See `LICENSE`.
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "second-advisor",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ask another coding CLI for a second opinion.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"second-advisor": "src/index.ts",
|
|
8
|
+
"sa": "src/index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"ai",
|
|
15
|
+
"agent",
|
|
16
|
+
"cli",
|
|
17
|
+
"code-review",
|
|
18
|
+
"codex"
|
|
19
|
+
],
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "J Liew",
|
|
22
|
+
"email": "jliew@420024lab.com"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/kenryu42/second-advisor.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/kenryu42/second-advisor/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/kenryu42/second-advisor#readme",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"bun": ">=1.3.0"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"sa": "bun run src/index.ts",
|
|
41
|
+
"test": "bun test",
|
|
42
|
+
"test:watch": "bun test --watch",
|
|
43
|
+
"coverage": "bun test --coverage",
|
|
44
|
+
"lint": "biome check .",
|
|
45
|
+
"lint:ci": "biome ci .",
|
|
46
|
+
"lint:staged": "biome check --write --",
|
|
47
|
+
"format": "biome check --write .",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"prepare": "lefthook install",
|
|
50
|
+
"hooks:install": "lefthook install",
|
|
51
|
+
"knip": "knip",
|
|
52
|
+
"cpd": "cpd src tests --reporters ai --exit-code 1 --no-tips",
|
|
53
|
+
"check": "bun run typecheck && bun run lint && bun run knip && bun run cpd && AGENT=1 bun test",
|
|
54
|
+
"check:ci": "bun run typecheck && bun run lint:ci && bun run knip && bun run cpd && AGENT=1 bun test --coverage --coverage-reporter=lcov",
|
|
55
|
+
"publish:dry-run": "bun scripts/publish.ts --dry-run",
|
|
56
|
+
"changelog": "bun scripts/changelog.ts"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@biomejs/biome": "latest",
|
|
60
|
+
"@types/bun": "latest",
|
|
61
|
+
"cpd": "latest",
|
|
62
|
+
"knip": "latest",
|
|
63
|
+
"lefthook": "latest",
|
|
64
|
+
"typescript": "latest"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@clack/prompts": "^1.6.0",
|
|
68
|
+
"commander": "^15.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/advisors.ts
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
export const advisorChoices = [
|
|
2
|
+
"claude",
|
|
3
|
+
"codex",
|
|
4
|
+
"opencode",
|
|
5
|
+
"grok",
|
|
6
|
+
"pi",
|
|
7
|
+
"droid",
|
|
8
|
+
"amp",
|
|
9
|
+
"kimi",
|
|
10
|
+
] as const;
|
|
11
|
+
|
|
12
|
+
export const ampModes = ["rush", "smart", "deep"] as const;
|
|
13
|
+
export const ampThinking = [
|
|
14
|
+
"none",
|
|
15
|
+
"minimal",
|
|
16
|
+
"low",
|
|
17
|
+
"medium",
|
|
18
|
+
"high",
|
|
19
|
+
"xhigh",
|
|
20
|
+
"max",
|
|
21
|
+
] as const;
|
|
22
|
+
export const ampThinkingByMode = {
|
|
23
|
+
deep: ampThinking,
|
|
24
|
+
rush: ["none", "minimal", "low", "medium"],
|
|
25
|
+
smart: ampThinking,
|
|
26
|
+
} as const;
|
|
27
|
+
export const claudeModels = ["haiku", "sonnet", "opus"] as const;
|
|
28
|
+
export const claudeThinking = [
|
|
29
|
+
"low",
|
|
30
|
+
"medium",
|
|
31
|
+
"high",
|
|
32
|
+
"xhigh",
|
|
33
|
+
"max",
|
|
34
|
+
] as const;
|
|
35
|
+
export const codexThinking = ["low", "medium", "high", "xhigh"] as const;
|
|
36
|
+
export const piThinking = [
|
|
37
|
+
"off",
|
|
38
|
+
"minimal",
|
|
39
|
+
"low",
|
|
40
|
+
"medium",
|
|
41
|
+
"high",
|
|
42
|
+
"xhigh",
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
45
|
+
export type Advisor = (typeof advisorChoices)[number];
|
|
46
|
+
export type CommandSpec = { command: string; args: string[] };
|
|
47
|
+
type ConfigBase<T extends Advisor> = { advisor: T; model: string };
|
|
48
|
+
type ConfigWithThinking<T extends Advisor, U extends string> = ConfigBase<T> & {
|
|
49
|
+
thinking: U;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type Config =
|
|
53
|
+
| (ConfigWithThinking<"claude", (typeof claudeThinking)[number]> & {
|
|
54
|
+
model: (typeof claudeModels)[number];
|
|
55
|
+
})
|
|
56
|
+
| ConfigWithThinking<"codex", (typeof codexThinking)[number]>
|
|
57
|
+
| ConfigWithThinking<"opencode", string>
|
|
58
|
+
| ConfigWithThinking<"grok", string>
|
|
59
|
+
| ConfigWithThinking<"pi", (typeof piThinking)[number]>
|
|
60
|
+
| ConfigWithThinking<"droid", string>
|
|
61
|
+
| {
|
|
62
|
+
advisor: "amp";
|
|
63
|
+
model: (typeof ampModes)[number];
|
|
64
|
+
thinking: (typeof ampThinking)[number];
|
|
65
|
+
}
|
|
66
|
+
| ConfigBase<"kimi">;
|
|
67
|
+
|
|
68
|
+
export function getModelListCommand(advisor: Advisor): CommandSpec | null {
|
|
69
|
+
if (advisor === "codex")
|
|
70
|
+
return { command: "codex", args: ["debug", "models", "--bundled"] };
|
|
71
|
+
if (advisor === "opencode") return { command: "opencode", args: ["models"] };
|
|
72
|
+
if (advisor === "grok") return { command: "grok", args: ["models"] };
|
|
73
|
+
if (advisor === "pi") return { command: "pi", args: ["--list-models"] };
|
|
74
|
+
if (advisor === "droid")
|
|
75
|
+
return { command: "droid", args: ["exec", "--help"] };
|
|
76
|
+
if (advisor === "kimi")
|
|
77
|
+
return { command: "kimi", args: ["provider", "list", "--json"] };
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function buildAdvisorCommand(
|
|
82
|
+
config: Config,
|
|
83
|
+
prompt: string,
|
|
84
|
+
): CommandSpec {
|
|
85
|
+
if (config.advisor === "claude") {
|
|
86
|
+
return {
|
|
87
|
+
command: "claude",
|
|
88
|
+
args: [
|
|
89
|
+
"--model",
|
|
90
|
+
config.model,
|
|
91
|
+
"--effort",
|
|
92
|
+
config.thinking,
|
|
93
|
+
"-p",
|
|
94
|
+
prompt,
|
|
95
|
+
],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (config.advisor === "codex") {
|
|
100
|
+
return {
|
|
101
|
+
command: "codex",
|
|
102
|
+
args: [
|
|
103
|
+
"exec",
|
|
104
|
+
"-m",
|
|
105
|
+
config.model,
|
|
106
|
+
"--config",
|
|
107
|
+
`model_reasoning_effort=${config.thinking}`,
|
|
108
|
+
prompt,
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (config.advisor === "opencode") {
|
|
114
|
+
return {
|
|
115
|
+
command: "opencode",
|
|
116
|
+
args: ["run", "-m", config.model, "--variant", config.thinking, prompt],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (config.advisor === "grok") {
|
|
121
|
+
return {
|
|
122
|
+
command: "grok",
|
|
123
|
+
args: [
|
|
124
|
+
"-m",
|
|
125
|
+
config.model,
|
|
126
|
+
"--reasoning-effort",
|
|
127
|
+
config.thinking,
|
|
128
|
+
"-p",
|
|
129
|
+
prompt,
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (config.advisor === "pi") {
|
|
135
|
+
return {
|
|
136
|
+
command: "pi",
|
|
137
|
+
args: [
|
|
138
|
+
"--model",
|
|
139
|
+
config.model,
|
|
140
|
+
"--thinking",
|
|
141
|
+
config.thinking,
|
|
142
|
+
"-p",
|
|
143
|
+
prompt,
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (config.advisor === "droid") {
|
|
149
|
+
return {
|
|
150
|
+
command: "droid",
|
|
151
|
+
args: [
|
|
152
|
+
"exec",
|
|
153
|
+
"-m",
|
|
154
|
+
config.model,
|
|
155
|
+
"--reasoning-effort",
|
|
156
|
+
config.thinking,
|
|
157
|
+
prompt,
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (config.advisor === "amp") {
|
|
163
|
+
return {
|
|
164
|
+
command: "amp",
|
|
165
|
+
args: [
|
|
166
|
+
"--mode",
|
|
167
|
+
config.model,
|
|
168
|
+
"--effort",
|
|
169
|
+
config.thinking,
|
|
170
|
+
"--execute",
|
|
171
|
+
prompt,
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return { command: "kimi", args: ["-m", config.model, "-p", prompt] };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function summarizeConfig(config: Config) {
|
|
180
|
+
if (config.advisor === "amp") {
|
|
181
|
+
return `advisor amp, mode ${config.model}, thinking ${config.thinking}`;
|
|
182
|
+
}
|
|
183
|
+
if (config.advisor === "kimi") return `advisor kimi, model ${config.model}`;
|
|
184
|
+
return `advisor ${config.advisor}, model ${config.model}, thinking ${config.thinking}`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function getThinkingOptions(
|
|
188
|
+
advisor: Exclude<Advisor, "kimi">,
|
|
189
|
+
model?: string,
|
|
190
|
+
) {
|
|
191
|
+
if (advisor === "claude") return [...claudeThinking];
|
|
192
|
+
if (advisor === "codex") return [...codexThinking];
|
|
193
|
+
if (advisor === "pi") return [...piThinking];
|
|
194
|
+
if (advisor === "amp") {
|
|
195
|
+
if (model && model in ampThinkingByMode) {
|
|
196
|
+
return [...ampThinkingByMode[model as keyof typeof ampThinkingByMode]];
|
|
197
|
+
}
|
|
198
|
+
return [...ampThinking];
|
|
199
|
+
}
|
|
200
|
+
return ["low", "medium", "high", "xhigh"];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function isAdvisor(value: unknown): value is Advisor {
|
|
204
|
+
return typeof value === "string" && advisorChoices.includes(value as Advisor);
|
|
205
|
+
}
|