muonroi-cli 1.8.0 → 1.8.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/LICENSE +21 -21
- package/README.md +122 -122
- package/dist/src/agent-harness/mock-model.js +112 -4
- package/dist/src/cli/cost-forensics.js +17 -14
- package/dist/src/council/prompts.js +20 -20
- package/dist/src/flow/compaction/index.d.ts +1 -0
- package/dist/src/flow/compaction/index.js +4 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/index.js +4 -2
- package/dist/src/lsp/manager.js +11 -3
- package/dist/src/lsp/manager.test.js +39 -0
- package/dist/src/mcp/auto-setup.js +0 -8
- package/dist/src/mcp/oauth-callback.js +2 -2
- package/dist/src/mcp/parse-headers.test.js +14 -14
- package/dist/src/mcp/self-verify-jobs.d.ts +1 -0
- package/dist/src/mcp/self-verify-runner.js +1 -1
- package/dist/src/mcp/setup-guide-text.js +74 -74
- package/dist/src/mcp/smoke.test.js +43 -43
- package/dist/src/ops/doctor.js +7 -7
- package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +1 -0
- package/dist/src/orchestrator/__tests__/message-processor.test.js +1 -0
- package/dist/src/orchestrator/__tests__/prompts.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/prompts.test.js +88 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.js +507 -0
- package/dist/src/orchestrator/auto-commit.js +9 -7
- package/dist/src/orchestrator/message-processor.d.ts +2 -0
- package/dist/src/orchestrator/message-processor.js +7 -0
- package/dist/src/orchestrator/orchestrator.d.ts +3 -0
- package/dist/src/orchestrator/orchestrator.js +362 -28
- package/dist/src/orchestrator/pending-calls.js +2 -1
- package/dist/src/orchestrator/preprocessor.js +3 -2
- package/dist/src/orchestrator/prompts.d.ts +8 -0
- package/dist/src/orchestrator/prompts.js +65 -18
- package/dist/src/orchestrator/sub-agent-cap.d.ts +2 -0
- package/dist/src/orchestrator/sub-agent-cap.js +12 -4
- package/dist/src/orchestrator/subagent-compactor.d.ts +7 -0
- package/dist/src/orchestrator/subagent-compactor.js +65 -14
- package/dist/src/orchestrator/subagent-compactor.spec.js +125 -9
- package/dist/src/orchestrator/tool-engine.d.ts +2 -0
- package/dist/src/orchestrator/tool-engine.js +80 -21
- package/dist/src/orchestrator/turn-runner-deps.d.ts +2 -0
- package/dist/src/pil/__tests__/llm-classify.test.js +79 -1
- package/dist/src/pil/layer1-intent.js +37 -37
- package/dist/src/pil/layer2_5-ponytail.js +8 -8
- package/dist/src/pil/llm-classify.d.ts +11 -0
- package/dist/src/pil/llm-classify.js +193 -0
- package/dist/src/product-loop/done-gate.js +3 -3
- package/dist/src/product-loop/loop-driver.js +18 -18
- package/dist/src/product-loop/progress-snapshot.js +4 -4
- package/dist/src/providers/mcp-vision-bridge.js +48 -48
- package/dist/src/reporter/index.js +1 -1
- package/dist/src/scaffold/bb-ecosystem-apply.js +47 -47
- package/dist/src/scaffold/bb-quality-gate.js +5 -5
- package/dist/src/scaffold/continuation-prompt.js +60 -60
- package/dist/src/scaffold/init-new.js +453 -453
- package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
- package/dist/src/self-qa/agentic-loop.js +11 -2
- package/dist/src/storage/__tests__/hierarchical-session.test.d.ts +1 -0
- package/dist/src/storage/__tests__/hierarchical-session.test.js +161 -0
- package/dist/src/storage/__tests__/migrations.test.js +2 -2
- package/dist/src/storage/__tests__/sweep-stale-pending.test.js +2 -2
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/interaction-log.js +5 -5
- package/dist/src/storage/migrations.js +135 -123
- package/dist/src/storage/session-experience-store.js +4 -4
- package/dist/src/storage/sessions.js +43 -43
- package/dist/src/storage/transcript-response-entry.test.js +18 -5
- package/dist/src/storage/transcript.d.ts +2 -0
- package/dist/src/storage/transcript.js +223 -97
- package/dist/src/storage/usage.js +34 -17
- package/dist/src/storage/workspaces.js +12 -12
- package/dist/src/tools/native-tools.js +10 -1
- package/dist/src/tools/registry.d.ts +1 -0
- package/dist/src/tools/registry.js +30 -2
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/slash/council-inspect.js +4 -4
- package/dist/src/ui/slash/expand.js +14 -1
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/utils/__tests__/compaction-caps.test.js +9 -9
- package/dist/src/utils/__tests__/llm-deadline.test.js +16 -4
- package/dist/src/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/src/utils/__tests__/logger.test.js +115 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.d.ts +1 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.js +48 -0
- package/dist/src/utils/clipboard-image.js +23 -23
- package/dist/src/utils/install-manager.d.ts +1 -0
- package/dist/src/utils/install-manager.js +76 -7
- package/dist/src/utils/install-manager.test.js +43 -1
- package/dist/src/utils/logger.d.ts +28 -0
- package/dist/src/utils/logger.js +171 -0
- package/dist/src/utils/settings.d.ts +9 -1
- package/dist/src/utils/settings.js +59 -22
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/skills.js +3 -3
- package/dist/src/utils/update-checker.test.js +5 -1
- package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
- package/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 muonroi
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 muonroi
|
|
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
CHANGED
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<h1 align="center">muonroi-cli</h1>
|
|
3
|
-
<p align="center">
|
|
4
|
-
<em>An AI coding agent where models argue with each other before answering.</em>
|
|
5
|
-
</p>
|
|
6
|
-
<p align="center">
|
|
7
|
-
<a href="https://github.com/muonroi/muonroi-cli/actions/workflows/ci-matrix.yml"><img alt="CI" src="https://github.com/muonroi/muonroi-cli/actions/workflows/ci-matrix.yml/badge.svg"></a>
|
|
8
|
-
<a href="https://www.npmjs.com/package/muonroi-cli"><img alt="npm" src="https://img.shields.io/npm/v/muonroi-cli.svg"></a>
|
|
9
|
-
<img alt="Providers" src="https://img.shields.io/badge/providers-7%20supported-blue">
|
|
10
|
-
<img alt="License" src="https://img.shields.io/badge/license-MIT-yellow">
|
|
11
|
-
<img alt="Runtime" src="https://img.shields.io/badge/runtime-Bun%201.3%2B-orange">
|
|
12
|
-
</p>
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
> Routes each task to the optimal model, runs adversarial multi-model debates for high-stakes decisions, and persists behavioral memory across sessions. Bring your own API keys. Total cost: ~$5/month.
|
|
18
|
-
|
|
19
|
-
<p align="center">
|
|
20
|
-
<img src="https://raw.githubusercontent.com/muonroi/muonroi-cli/master/docs/demo.gif" alt="Council debate — REST vs gRPC decision" width="840" />
|
|
21
|
-
</p>
|
|
22
|
-
|
|
23
|
-
## Quick Start
|
|
24
|
-
|
|
25
|
-
### Install
|
|
26
|
-
|
|
27
|
-
**Recommended — prebuilt standalone binary (zero runtime deps, no prereqs):**
|
|
28
|
-
|
|
29
|
-
Linux / macOS:
|
|
30
|
-
```bash
|
|
31
|
-
curl -fsSL https://raw.githubusercontent.com/muonroi/muonroi-cli/master/install.sh | bash
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Windows PowerShell:
|
|
35
|
-
```powershell
|
|
36
|
-
irm https://raw.githubusercontent.com/muonroi/muonroi-cli/master/install.ps1 | iex
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
The installers download a `bun --compile` binary from GitHub Releases — single executable, all native deps bundled, no Node/Bun/build tools required.
|
|
40
|
-
|
|
41
|
-
**Bun runtime (requires Bun ≥ 1.x):**
|
|
42
|
-
```bash
|
|
43
|
-
bun add -g muonroi-cli
|
|
44
|
-
muonroi-cli
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
> **⚠ Why no `npm install -g`?** The TUI engine (`@opentui/core`) uses Bun-only `import ... with { type: "file" }` for Tree-sitter syntax highlight queries (`.scm` files). Node ESM cannot load these, so running under bare Node throws `ERR_UNKNOWN_FILE_EXTENSION`. Use the standalone installer (above) or `bun add -g`.
|
|
48
|
-
|
|
49
|
-
### First run
|
|
50
|
-
|
|
51
|
-
On first launch the CLI shows a wizard that:
|
|
52
|
-
1. Lists supported providers (currently **DeepSeek** and **SiliconFlow**).
|
|
53
|
-
2. Offers four ways to add credentials: paste an API key, import an encrypted bundle (`keys export`/`keys import`), sync from Bitwarden, or skip and add later via `/providers` inside the TUI.
|
|
54
|
-
|
|
55
|
-
After setup, role routing auto-balances across enabled providers:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
// ~/.muonroi-cli/user-settings.json (generated by the wizard — edit if needed)
|
|
59
|
-
{
|
|
60
|
-
"defaultProvider": "deepseek",
|
|
61
|
-
"providers": {
|
|
62
|
-
"deepseek": { "enabled": true },
|
|
63
|
-
"siliconflow": { "enabled": true }
|
|
64
|
-
},
|
|
65
|
-
"roleModels": {
|
|
66
|
-
"leader": "deepseek-v4-pro",
|
|
67
|
-
"implement": "deepseek-v4-flash",
|
|
68
|
-
"verify": "deepseek-v4-pro",
|
|
69
|
-
"research": "deepseek-v4-flash"
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Moving keys between devices
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# Source device — encrypts every stored key into one passphrase-protected file
|
|
78
|
-
muonroi-cli keys export ~/muonroi-keys.json
|
|
79
|
-
|
|
80
|
-
# Move the file via any channel (USB, Drive, AirDrop, email...)
|
|
81
|
-
|
|
82
|
-
# Target device — same passphrase rehydrates the OS keychain
|
|
83
|
-
muonroi-cli keys import ~/muonroi-keys.json
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Inside the TUI press `/providers` then `B` to sync directly from a Bitwarden vault instead.
|
|
87
|
-
|
|
88
|
-
### Updates
|
|
89
|
-
|
|
90
|
-
The CLI checks npm once per day on startup and prompts when a newer version is available. Set `autoUpdate: true` in `user-settings.json` to skip the prompt and update silently. Manual: `muonroi-cli update`.
|
|
91
|
-
|
|
92
|
-
## Documentation
|
|
93
|
-
|
|
94
|
-
Full documentation at **[docs.muonroi.com/docs/cli](https://docs.muonroi.com/docs/cli/overview)**
|
|
95
|
-
|
|
96
|
-
| Topic | Link |
|
|
97
|
-
|---|---|
|
|
98
|
-
| Overview & architecture | [CLI Overview](https://docs.muonroi.com/docs/cli/overview) |
|
|
99
|
-
| Multi-Model Council | [Council Debate Guide](https://docs.muonroi.com/docs/cli/guides/council-debate) |
|
|
100
|
-
| Prompt Intelligence Layer | [PIL Pipeline Guide](https://docs.muonroi.com/docs/cli/guides/pil-pipeline) |
|
|
101
|
-
| Experience Engine | [Experience Engine Guide](https://docs.muonroi.com/docs/cli/guides/experience-engine) |
|
|
102
|
-
| Agent Harness | [Agent Harness Guide](https://docs.muonroi.com/docs/cli/guides/agent-harness) |
|
|
103
|
-
| Settings reference | [CLI Settings Reference](https://docs.muonroi.com/docs/cli/reference/cli-settings-reference) |
|
|
104
|
-
| Commands reference | [Commands Reference](https://docs.muonroi.com/docs/cli/reference/commands-reference) |
|
|
105
|
-
| Providers reference | [Providers Reference](https://docs.muonroi.com/docs/cli/reference/providers-reference) |
|
|
106
|
-
|
|
107
|
-
## Development
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
git clone https://github.com/muonroi/muonroi-cli.git
|
|
111
|
-
cd muonroi-cli && bun install
|
|
112
|
-
|
|
113
|
-
bun run dev # run from source
|
|
114
|
-
bun run typecheck # type check
|
|
115
|
-
bun run test # vitest
|
|
116
|
-
bun run lint # biome check
|
|
117
|
-
bun run build:binary # standalone binary
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## License
|
|
121
|
-
|
|
122
|
-
MIT
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">muonroi-cli</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
<em>An AI coding agent where models argue with each other before answering.</em>
|
|
5
|
+
</p>
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://github.com/muonroi/muonroi-cli/actions/workflows/ci-matrix.yml"><img alt="CI" src="https://github.com/muonroi/muonroi-cli/actions/workflows/ci-matrix.yml/badge.svg"></a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/muonroi-cli"><img alt="npm" src="https://img.shields.io/npm/v/muonroi-cli.svg"></a>
|
|
9
|
+
<img alt="Providers" src="https://img.shields.io/badge/providers-7%20supported-blue">
|
|
10
|
+
<img alt="License" src="https://img.shields.io/badge/license-MIT-yellow">
|
|
11
|
+
<img alt="Runtime" src="https://img.shields.io/badge/runtime-Bun%201.3%2B-orange">
|
|
12
|
+
</p>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
> Routes each task to the optimal model, runs adversarial multi-model debates for high-stakes decisions, and persists behavioral memory across sessions. Bring your own API keys. Total cost: ~$5/month.
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="https://raw.githubusercontent.com/muonroi/muonroi-cli/master/docs/demo.gif" alt="Council debate — REST vs gRPC decision" width="840" />
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Install
|
|
26
|
+
|
|
27
|
+
**Recommended — prebuilt standalone binary (zero runtime deps, no prereqs):**
|
|
28
|
+
|
|
29
|
+
Linux / macOS:
|
|
30
|
+
```bash
|
|
31
|
+
curl -fsSL https://raw.githubusercontent.com/muonroi/muonroi-cli/master/install.sh | bash
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Windows PowerShell:
|
|
35
|
+
```powershell
|
|
36
|
+
irm https://raw.githubusercontent.com/muonroi/muonroi-cli/master/install.ps1 | iex
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The installers download a `bun --compile` binary from GitHub Releases — single executable, all native deps bundled, no Node/Bun/build tools required.
|
|
40
|
+
|
|
41
|
+
**Bun runtime (requires Bun ≥ 1.x):**
|
|
42
|
+
```bash
|
|
43
|
+
bun add -g muonroi-cli
|
|
44
|
+
muonroi-cli
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **⚠ Why no `npm install -g`?** The TUI engine (`@opentui/core`) uses Bun-only `import ... with { type: "file" }` for Tree-sitter syntax highlight queries (`.scm` files). Node ESM cannot load these, so running under bare Node throws `ERR_UNKNOWN_FILE_EXTENSION`. Use the standalone installer (above) or `bun add -g`.
|
|
48
|
+
|
|
49
|
+
### First run
|
|
50
|
+
|
|
51
|
+
On first launch the CLI shows a wizard that:
|
|
52
|
+
1. Lists supported providers (currently **DeepSeek** and **SiliconFlow**).
|
|
53
|
+
2. Offers four ways to add credentials: paste an API key, import an encrypted bundle (`keys export`/`keys import`), sync from Bitwarden, or skip and add later via `/providers` inside the TUI.
|
|
54
|
+
|
|
55
|
+
After setup, role routing auto-balances across enabled providers:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
// ~/.muonroi-cli/user-settings.json (generated by the wizard — edit if needed)
|
|
59
|
+
{
|
|
60
|
+
"defaultProvider": "deepseek",
|
|
61
|
+
"providers": {
|
|
62
|
+
"deepseek": { "enabled": true },
|
|
63
|
+
"siliconflow": { "enabled": true }
|
|
64
|
+
},
|
|
65
|
+
"roleModels": {
|
|
66
|
+
"leader": "deepseek-v4-pro",
|
|
67
|
+
"implement": "deepseek-v4-flash",
|
|
68
|
+
"verify": "deepseek-v4-pro",
|
|
69
|
+
"research": "deepseek-v4-flash"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Moving keys between devices
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Source device — encrypts every stored key into one passphrase-protected file
|
|
78
|
+
muonroi-cli keys export ~/muonroi-keys.json
|
|
79
|
+
|
|
80
|
+
# Move the file via any channel (USB, Drive, AirDrop, email...)
|
|
81
|
+
|
|
82
|
+
# Target device — same passphrase rehydrates the OS keychain
|
|
83
|
+
muonroi-cli keys import ~/muonroi-keys.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Inside the TUI press `/providers` then `B` to sync directly from a Bitwarden vault instead.
|
|
87
|
+
|
|
88
|
+
### Updates
|
|
89
|
+
|
|
90
|
+
The CLI checks npm once per day on startup and prompts when a newer version is available. Set `autoUpdate: true` in `user-settings.json` to skip the prompt and update silently. Manual: `muonroi-cli update`.
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
Full documentation at **[docs.muonroi.com/docs/cli](https://docs.muonroi.com/docs/cli/overview)**
|
|
95
|
+
|
|
96
|
+
| Topic | Link |
|
|
97
|
+
|---|---|
|
|
98
|
+
| Overview & architecture | [CLI Overview](https://docs.muonroi.com/docs/cli/overview) |
|
|
99
|
+
| Multi-Model Council | [Council Debate Guide](https://docs.muonroi.com/docs/cli/guides/council-debate) |
|
|
100
|
+
| Prompt Intelligence Layer | [PIL Pipeline Guide](https://docs.muonroi.com/docs/cli/guides/pil-pipeline) |
|
|
101
|
+
| Experience Engine | [Experience Engine Guide](https://docs.muonroi.com/docs/cli/guides/experience-engine) |
|
|
102
|
+
| Agent Harness | [Agent Harness Guide](https://docs.muonroi.com/docs/cli/guides/agent-harness) |
|
|
103
|
+
| Settings reference | [CLI Settings Reference](https://docs.muonroi.com/docs/cli/reference/cli-settings-reference) |
|
|
104
|
+
| Commands reference | [Commands Reference](https://docs.muonroi.com/docs/cli/reference/commands-reference) |
|
|
105
|
+
| Providers reference | [Providers Reference](https://docs.muonroi.com/docs/cli/reference/providers-reference) |
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
git clone https://github.com/muonroi/muonroi-cli.git
|
|
111
|
+
cd muonroi-cli && bun install
|
|
112
|
+
|
|
113
|
+
bun run dev # run from source
|
|
114
|
+
bun run typecheck # type check
|
|
115
|
+
bun run test # vitest
|
|
116
|
+
bun run lint # biome check
|
|
117
|
+
bun run build:binary # standalone binary
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
|
@@ -199,13 +199,121 @@ export function toolCallStream(opts) {
|
|
|
199
199
|
* string payloads here so the rest of the pipeline sees a uniform shape.
|
|
200
200
|
*/
|
|
201
201
|
function normalizeStreamChunks(chunks) {
|
|
202
|
-
|
|
203
|
-
if (c
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
const normalized = chunks.map((c) => {
|
|
203
|
+
if (!c)
|
|
204
|
+
return c;
|
|
205
|
+
const part = c;
|
|
206
|
+
if (part.type === "error") {
|
|
207
|
+
const raw = part.error;
|
|
208
|
+
return { ...part, error: buildFixtureError(raw) };
|
|
209
|
+
}
|
|
210
|
+
if (part.type === "text-delta") {
|
|
211
|
+
const delta = part.delta ?? part.textDelta ?? part.text ?? "";
|
|
212
|
+
const id = part.id ?? "txt-0";
|
|
213
|
+
return { ...part, id, delta };
|
|
214
|
+
}
|
|
215
|
+
if (part.type === "reasoning-delta") {
|
|
216
|
+
const delta = part.delta ?? part.textDelta ?? part.text ?? "";
|
|
217
|
+
const id = part.id ?? "reasoning-0";
|
|
218
|
+
return { ...part, id, delta };
|
|
206
219
|
}
|
|
207
220
|
return c;
|
|
208
221
|
});
|
|
222
|
+
const result = [];
|
|
223
|
+
const textIds = new Set();
|
|
224
|
+
const reasoningIds = new Set();
|
|
225
|
+
for (const part of normalized) {
|
|
226
|
+
if (!part)
|
|
227
|
+
continue;
|
|
228
|
+
const p = part;
|
|
229
|
+
if (p.type === "text-delta") {
|
|
230
|
+
textIds.add(p.id ?? "txt-0");
|
|
231
|
+
}
|
|
232
|
+
else if (p.type === "reasoning-delta") {
|
|
233
|
+
reasoningIds.add(p.id ?? "reasoning-0");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const seenTextStart = new Set();
|
|
237
|
+
const seenTextEnd = new Set();
|
|
238
|
+
const seenReasoningStart = new Set();
|
|
239
|
+
const seenReasoningEnd = new Set();
|
|
240
|
+
for (const part of normalized) {
|
|
241
|
+
if (!part)
|
|
242
|
+
continue;
|
|
243
|
+
const p = part;
|
|
244
|
+
if (p.type === "text-start") {
|
|
245
|
+
seenTextStart.add(p.id);
|
|
246
|
+
}
|
|
247
|
+
else if (p.type === "text-end") {
|
|
248
|
+
seenTextEnd.add(p.id);
|
|
249
|
+
}
|
|
250
|
+
else if (p.type === "reasoning-start") {
|
|
251
|
+
seenReasoningStart.add(p.id);
|
|
252
|
+
}
|
|
253
|
+
else if (p.type === "reasoning-end") {
|
|
254
|
+
seenReasoningEnd.add(p.id);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const firstTextDeltaIdx = new Map();
|
|
258
|
+
const lastTextDeltaIdx = new Map();
|
|
259
|
+
const firstReasoningDeltaIdx = new Map();
|
|
260
|
+
const lastReasoningDeltaIdx = new Map();
|
|
261
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
262
|
+
const p = normalized[i];
|
|
263
|
+
if (!p)
|
|
264
|
+
continue;
|
|
265
|
+
if (p.type === "text-delta") {
|
|
266
|
+
const id = p.id ?? "txt-0";
|
|
267
|
+
if (!firstTextDeltaIdx.has(id))
|
|
268
|
+
firstTextDeltaIdx.set(id, i);
|
|
269
|
+
lastTextDeltaIdx.set(id, i);
|
|
270
|
+
}
|
|
271
|
+
else if (p.type === "reasoning-delta") {
|
|
272
|
+
const id = p.id ?? "reasoning-0";
|
|
273
|
+
if (!firstReasoningDeltaIdx.has(id))
|
|
274
|
+
firstReasoningDeltaIdx.set(id, i);
|
|
275
|
+
lastReasoningDeltaIdx.set(id, i);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
279
|
+
const p = normalized[i];
|
|
280
|
+
if (!p) {
|
|
281
|
+
result.push(p);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (p.type === "text-delta") {
|
|
285
|
+
const id = p.id ?? "txt-0";
|
|
286
|
+
if (firstTextDeltaIdx.get(id) === i && !seenTextStart.has(id)) {
|
|
287
|
+
result.push({ type: "text-start", id });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else if (p.type === "reasoning-delta") {
|
|
291
|
+
const id = p.id ?? "reasoning-0";
|
|
292
|
+
if (firstReasoningDeltaIdx.get(id) === i && !seenReasoningStart.has(id)) {
|
|
293
|
+
result.push({ type: "reasoning-start", id });
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (p.type === "finish") {
|
|
297
|
+
const usage = p.usage ?? buildUsage(10, 10);
|
|
298
|
+
result.push({ ...p, usage });
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
result.push(p);
|
|
302
|
+
}
|
|
303
|
+
if (p.type === "text-delta") {
|
|
304
|
+
const id = p.id ?? "txt-0";
|
|
305
|
+
if (lastTextDeltaIdx.get(id) === i && !seenTextEnd.has(id)) {
|
|
306
|
+
result.push({ type: "text-end", id });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else if (p.type === "reasoning-delta") {
|
|
310
|
+
const id = p.id ?? "reasoning-0";
|
|
311
|
+
if (lastReasoningDeltaIdx.get(id) === i && !seenReasoningEnd.has(id)) {
|
|
312
|
+
result.push({ type: "reasoning-end", id });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return result;
|
|
209
317
|
}
|
|
210
318
|
/**
|
|
211
319
|
* Turn a fixture `error` payload into the right runtime shape:
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { getProviderCapabilities } from "../providers/capabilities.js";
|
|
12
12
|
import { detectProviderForModel } from "../providers/runtime.js";
|
|
13
13
|
import { getDatabase } from "../storage/db.js";
|
|
14
|
+
import { getSessionChain } from "../storage/index.js";
|
|
14
15
|
import { selectSessionExperience } from "../storage/session-experience-store.js";
|
|
15
16
|
function resolveSessionId(prefix) {
|
|
16
17
|
const rows = getDatabase()
|
|
@@ -42,24 +43,26 @@ export function collectCostForensics(sessionId) {
|
|
|
42
43
|
const session = db.prepare(`SELECT id, model, created_at FROM sessions WHERE id = ?`).get(sessionId);
|
|
43
44
|
if (!session)
|
|
44
45
|
throw new Error(`Session not found: ${sessionId}`);
|
|
46
|
+
const chain = getSessionChain(sessionId);
|
|
47
|
+
const placeholders = chain.map(() => "?").join(",");
|
|
45
48
|
const rows = db
|
|
46
|
-
.prepare(`
|
|
47
|
-
SELECT id, source, model, message_seq, input_tokens, output_tokens,
|
|
48
|
-
cache_read_tokens, cache_creation_tokens, cost_micros, created_at,
|
|
49
|
-
provider_options_shape
|
|
50
|
-
FROM usage_events
|
|
51
|
-
WHERE session_id
|
|
52
|
-
ORDER BY id ASC
|
|
49
|
+
.prepare(`
|
|
50
|
+
SELECT id, source, model, message_seq, input_tokens, output_tokens,
|
|
51
|
+
cache_read_tokens, cache_creation_tokens, cost_micros, created_at,
|
|
52
|
+
provider_options_shape
|
|
53
|
+
FROM usage_events
|
|
54
|
+
WHERE session_id IN (${placeholders})
|
|
55
|
+
ORDER BY id ASC
|
|
53
56
|
`)
|
|
54
|
-
.all(
|
|
57
|
+
.all(...chain);
|
|
55
58
|
const counts = db
|
|
56
|
-
.prepare(`
|
|
57
|
-
SELECT event_type, COUNT(*) AS c
|
|
58
|
-
FROM interaction_logs
|
|
59
|
-
WHERE session_id
|
|
60
|
-
GROUP BY event_type
|
|
59
|
+
.prepare(`
|
|
60
|
+
SELECT event_type, COUNT(*) AS c
|
|
61
|
+
FROM interaction_logs
|
|
62
|
+
WHERE session_id IN (${placeholders})
|
|
63
|
+
GROUP BY event_type
|
|
61
64
|
`)
|
|
62
|
-
.all(
|
|
65
|
+
.all(...chain);
|
|
63
66
|
const countMap = new Map(counts.map((r) => [r.event_type, r.c]));
|
|
64
67
|
const events = rows.map((r) => ({
|
|
65
68
|
id: r.id,
|
|
@@ -548,33 +548,33 @@ export function buildSynthesisPrompt(ctx) {
|
|
|
548
548
|
}
|
|
549
549
|
let extraContext = "";
|
|
550
550
|
if (ctx.refineContext) {
|
|
551
|
-
extraContext += `
|
|
552
|
-
## User Refinements
|
|
553
|
-
${ctx.refineContext}
|
|
551
|
+
extraContext += `
|
|
552
|
+
## User Refinements
|
|
553
|
+
${ctx.refineContext}
|
|
554
554
|
`;
|
|
555
555
|
}
|
|
556
556
|
if (ctx.planEmphasis) {
|
|
557
|
-
extraContext += `
|
|
558
|
-
## Additional Instruction
|
|
559
|
-
The user has requested a concrete action plan with executable steps. Each action item MUST be an object with these fields:
|
|
560
|
-
{
|
|
561
|
-
"step": "<imperative action>",
|
|
562
|
-
"owner_lens": "<which stance owns this — frontend / backend / architecture / etc>",
|
|
563
|
-
"time_estimate": "<rough — e.g. '2h', '1d', '~30min'>",
|
|
564
|
-
"depends_on": ["<step keys this requires>"] or [],
|
|
565
|
-
"acceptance_criteria": "<how we know it's done>"
|
|
566
|
-
}
|
|
567
|
-
Order action items by dependency: predecessors first, dependents after.
|
|
568
|
-
Risks MUST be objects with: {"description", "severity": "High|Medium|Low", "mitigation"}.
|
|
569
|
-
Do NOT emit loose strings for these fields — the user needs structured plan output.
|
|
557
|
+
extraContext += `
|
|
558
|
+
## Additional Instruction
|
|
559
|
+
The user has requested a concrete action plan with executable steps. Each action item MUST be an object with these fields:
|
|
560
|
+
{
|
|
561
|
+
"step": "<imperative action>",
|
|
562
|
+
"owner_lens": "<which stance owns this — frontend / backend / architecture / etc>",
|
|
563
|
+
"time_estimate": "<rough — e.g. '2h', '1d', '~30min'>",
|
|
564
|
+
"depends_on": ["<step keys this requires>"] or [],
|
|
565
|
+
"acceptance_criteria": "<how we know it's done>"
|
|
566
|
+
}
|
|
567
|
+
Order action items by dependency: predecessors first, dependents after.
|
|
568
|
+
Risks MUST be objects with: {"description", "severity": "High|Medium|Low", "mitigation"}.
|
|
569
|
+
Do NOT emit loose strings for these fields — the user needs structured plan output.
|
|
570
570
|
`;
|
|
571
571
|
}
|
|
572
572
|
return {
|
|
573
573
|
system,
|
|
574
|
-
prompt: `Final positions:
|
|
575
|
-
${ctx.finalPositions}
|
|
576
|
-
|
|
577
|
-
Full discussion:
|
|
574
|
+
prompt: `Final positions:
|
|
575
|
+
${ctx.finalPositions}
|
|
576
|
+
|
|
577
|
+
Full discussion:
|
|
578
578
|
${ctx.allExchanges}${extraContext}`,
|
|
579
579
|
};
|
|
580
580
|
}
|
|
@@ -49,6 +49,9 @@ export async function deliberateCompact(flowDir, messages, systemPrompt, tokenBu
|
|
|
49
49
|
const historyPath = path.join(historyDir, `${timestamp}.md`);
|
|
50
50
|
const fullSerialized = serializeConversation(messages);
|
|
51
51
|
await atomicWriteText(historyPath, fullSerialized);
|
|
52
|
+
// Save full JSON history next to the md file for exact expand/restore
|
|
53
|
+
const jsonPath = path.join(historyDir, `${timestamp}.json`);
|
|
54
|
+
await atomicWriteText(jsonPath, JSON.stringify(messages, null, 2));
|
|
52
55
|
// Token estimation before
|
|
53
56
|
const tokensBefore = estimateConversationTokens(systemPrompt, messages);
|
|
54
57
|
// Pass 2: Compress
|
|
@@ -58,6 +61,7 @@ export async function deliberateCompact(flowDir, messages, systemPrompt, tokenBu
|
|
|
58
61
|
tokensBeforeCompress: tokensBefore,
|
|
59
62
|
tokensAfterCompress: compressed.tokensAfter,
|
|
60
63
|
historyPath,
|
|
64
|
+
summary: compressed.summary,
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "1.8.
|
|
1
|
+
export declare const PACKAGE_VERSION = "1.8.1";
|
|
2
2
|
export declare const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/sync-version.cjs. DO NOT EDIT BY HAND.
|
|
2
2
|
// Sourced from package.json at build time so it survives bun --compile bundling.
|
|
3
|
-
export const PACKAGE_VERSION = "1.8.
|
|
3
|
+
export const PACKAGE_VERSION = "1.8.1";
|
|
4
4
|
export const PACKAGE_DESCRIPTION = "BYOK AI coding agent with multi-model council debate, role-based routing, and auto-compact.";
|
|
5
5
|
//# sourceMappingURL=version.js.map
|
package/dist/src/index.js
CHANGED
|
@@ -51,6 +51,7 @@ process.on("SIGTERM", exitCleanlyOnSigterm);
|
|
|
51
51
|
let _tuiActive = false;
|
|
52
52
|
export function setTuiActive(active) {
|
|
53
53
|
_tuiActive = active;
|
|
54
|
+
globalThis.__muonroiTuiActive = active;
|
|
54
55
|
}
|
|
55
56
|
export function appendCrashLog(label, msg) {
|
|
56
57
|
try {
|
|
@@ -972,7 +973,8 @@ program
|
|
|
972
973
|
console.log("Checking for updates...");
|
|
973
974
|
const result = await runUpdate(packageJson.version);
|
|
974
975
|
console.log(result.output);
|
|
975
|
-
process.
|
|
976
|
+
process.exitCode = result.success ? 0 : 1;
|
|
977
|
+
return;
|
|
976
978
|
}
|
|
977
979
|
changeDirectoryOrExit(options.directory);
|
|
978
980
|
// Boot model registry BEFORE any key resolution path runs —
|
|
@@ -1159,7 +1161,7 @@ program
|
|
|
1159
1161
|
console.log("Checking for updates...");
|
|
1160
1162
|
const result = await runUpdate(packageJson.version);
|
|
1161
1163
|
console.log(result.output);
|
|
1162
|
-
process.
|
|
1164
|
+
process.exitCode = result.success ? 0 : 1;
|
|
1163
1165
|
});
|
|
1164
1166
|
program
|
|
1165
1167
|
.command("uninstall")
|
package/dist/src/lsp/manager.js
CHANGED
|
@@ -64,8 +64,16 @@ export function createWorkspaceLspManager(cwd, settings, options = {}) {
|
|
|
64
64
|
return resolved.filter((value) => value !== null);
|
|
65
65
|
}
|
|
66
66
|
async function touchFile(filePath, waitForDiagnostics = true) {
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
try {
|
|
68
|
+
const content = await readFile(filePath, "utf8");
|
|
69
|
+
return await syncFile(filePath, content, false, waitForDiagnostics);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err instanceof Error && err.code === "ENOENT") {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
69
77
|
}
|
|
70
78
|
async function syncFile(filePath, content, save = true, waitForDiagnostics = true, diagnosticsTimeoutMs) {
|
|
71
79
|
const records = await getClientsForFile(filePath);
|
|
@@ -104,7 +112,7 @@ export function createWorkspaceLspManager(cwd, settings, options = {}) {
|
|
|
104
112
|
output: `No LSP server available for ${path.extname(normalizedPath) || "this file type"}.`,
|
|
105
113
|
};
|
|
106
114
|
}
|
|
107
|
-
const lspDiagnostics = await touchFile(normalizedPath, true);
|
|
115
|
+
const lspDiagnostics = input.operation === "workspaceSymbol" ? [] : await touchFile(normalizedPath, true);
|
|
108
116
|
const params = createOperationParams(input, normalizedPath);
|
|
109
117
|
const timeoutMs = settings.requestTimeoutMs;
|
|
110
118
|
const results = (await Promise.all(records.map(async ({ key, client }) => {
|