muonroi-cli 1.7.2 → 1.8.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 -21
- package/README.md +122 -122
- package/dist/packages/agent-harness-core/src/event-filter.js +1 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
- package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
- package/dist/packages/agent-harness-core/src/selector.js +2 -2
- package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
- package/dist/packages/agent-harness-opentui/src/install.js +1 -1
- package/dist/src/__test-stubs__/vitest-setup.js +4 -0
- package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
- package/dist/src/agent-harness/mock-model.d.ts +1 -1
- package/dist/src/agent-harness/mock-model.js +32 -3
- package/dist/src/agent-harness/test-spawn.js +3 -1
- package/dist/src/chat/chat-keychain.js +9 -1
- package/dist/src/cli/cost-forensics.js +12 -12
- package/dist/src/cli/keys.d.ts +2 -2
- package/dist/src/cli/keys.js +107 -28
- package/dist/src/cli/usage-report.js +2 -2
- package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
- package/dist/src/council/__tests__/abort-threading.test.js +193 -0
- package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
- package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
- package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
- package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
- package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
- package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
- package/dist/src/council/__tests__/research-tools.test.js +4 -0
- package/dist/src/council/__tests__/round-tools.test.js +6 -0
- package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
- package/dist/src/council/clarifier-question-cap.test.js +73 -0
- package/dist/src/council/clarifier.d.ts +29 -1
- package/dist/src/council/clarifier.js +64 -1
- package/dist/src/council/debate-planner.d.ts +2 -1
- package/dist/src/council/debate-planner.js +5 -3
- package/dist/src/council/debate.d.ts +9 -0
- package/dist/src/council/debate.js +88 -8
- package/dist/src/council/index.d.ts +46 -1
- package/dist/src/council/index.js +125 -19
- package/dist/src/council/llm.js +41 -13
- package/dist/src/council/prompts.js +56 -21
- package/dist/src/council/types.d.ts +14 -1
- package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
- package/dist/src/ee/bridge.d.ts +3 -1
- package/dist/src/ee/bridge.js +9 -3
- package/dist/src/ee/bridge.test.js +1 -2
- package/dist/src/ee/client.js +15 -2
- package/dist/src/ee/recall-ledger.d.ts +20 -0
- package/dist/src/ee/recall-ledger.js +40 -1
- package/dist/src/ee/search.d.ts +25 -0
- package/dist/src/ee/search.js +73 -0
- package/dist/src/ee/types.d.ts +15 -1
- package/dist/src/ee/who-am-i.d.ts +41 -0
- package/dist/src/ee/who-am-i.js +143 -0
- package/dist/src/ee/who-am-i.test.d.ts +1 -0
- package/dist/src/ee/who-am-i.test.js +101 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/headless/council-answers.js +1 -0
- package/dist/src/headless/output.d.ts +30 -1
- package/dist/src/headless/output.js +180 -0
- package/dist/src/headless/output.test.js +61 -1
- package/dist/src/hooks/index.js +48 -2
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +55 -60
- package/dist/src/lsp/client-normalize.test.d.ts +12 -0
- package/dist/src/lsp/client-normalize.test.js +34 -0
- package/dist/src/lsp/client.d.ts +1 -0
- package/dist/src/lsp/client.js +10 -2
- package/dist/src/lsp/manager.d.ts +1 -1
- package/dist/src/lsp/manager.js +2 -2
- package/dist/src/lsp/manager.test.js +2 -2
- package/dist/src/lsp/runtime.d.ts +1 -1
- package/dist/src/lsp/runtime.js +2 -2
- package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
- package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
- package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
- package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
- package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
- package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
- package/dist/src/mcp/client-pool.d.ts +1 -1
- package/dist/src/mcp/client-pool.js +25 -9
- package/dist/src/mcp/ee-tools.d.ts +10 -0
- package/dist/src/mcp/ee-tools.js +34 -0
- 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.js +1 -3
- package/dist/src/mcp/setup-guide-text.js +74 -74
- package/dist/src/mcp/smoke.test.js +43 -43
- package/dist/src/models/catalog-gemini.test.js +12 -10
- package/dist/src/models/catalog.json +106 -38
- package/dist/src/ops/doctor.js +7 -7
- package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
- package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +2 -0
- package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
- package/dist/src/orchestrator/__tests__/message-processor.test.js +1 -0
- package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
- package/dist/src/orchestrator/agent.test.js +5 -2
- package/dist/src/orchestrator/auto-commit.d.ts +110 -0
- package/dist/src/orchestrator/auto-commit.js +364 -0
- package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
- package/dist/src/orchestrator/batch-turn-runner.js +2 -1
- package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
- package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
- package/dist/src/orchestrator/compaction.d.ts +22 -0
- package/dist/src/orchestrator/compaction.js +42 -0
- package/dist/src/orchestrator/delegations.d.ts +1 -0
- package/dist/src/orchestrator/delegations.js +41 -0
- package/dist/src/orchestrator/error-utils.js +27 -2
- package/dist/src/orchestrator/message-processor.d.ts +21 -5
- package/dist/src/orchestrator/message-processor.js +219 -2573
- package/dist/src/orchestrator/orchestrator.d.ts +8 -2
- package/dist/src/orchestrator/orchestrator.js +187 -34
- package/dist/src/orchestrator/preprocessor.d.ts +13 -0
- package/dist/src/orchestrator/preprocessor.js +145 -0
- package/dist/src/orchestrator/prompts.d.ts +8 -0
- package/dist/src/orchestrator/prompts.js +76 -60
- package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
- package/dist/src/orchestrator/safety-askcard.js +74 -0
- package/dist/src/orchestrator/sandbox.test.js +8 -5
- package/dist/src/orchestrator/scope-ceiling.js +1 -1
- package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
- package/dist/src/orchestrator/stall-watchdog.js +23 -0
- package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
- package/dist/src/orchestrator/stream-runner.js +52 -30
- package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
- package/dist/src/orchestrator/subagent-compactor.d.ts +14 -0
- package/dist/src/orchestrator/subagent-compactor.js +83 -10
- package/dist/src/orchestrator/subagent-compactor.spec.js +132 -0
- package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
- package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
- package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
- package/dist/src/orchestrator/tool-args-repair.js +1 -1
- package/dist/src/orchestrator/tool-engine.d.ts +151 -0
- package/dist/src/orchestrator/tool-engine.js +3079 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +1 -0
- package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
- package/dist/src/pil/__tests__/discovery.test.js +89 -145
- package/dist/src/pil/__tests__/dual-run.test.js +2 -0
- package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
- package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
- package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
- package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
- package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
- package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
- package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
- package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
- package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
- package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
- package/dist/src/pil/__tests__/pipeline.test.js +11 -8
- package/dist/src/pil/__tests__/response-tools.test.js +52 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +5 -3
- package/dist/src/pil/agent-operating-contract.test.js +2 -2
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +1 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/config.d.ts +20 -0
- package/dist/src/pil/config.js +35 -0
- package/dist/src/pil/discovery-types.d.ts +32 -9
- package/dist/src/pil/discovery.d.ts +3 -3
- package/dist/src/pil/discovery.js +138 -244
- package/dist/src/pil/index.d.ts +1 -1
- package/dist/src/pil/index.js +1 -1
- package/dist/src/pil/layer1-intent.d.ts +9 -1
- package/dist/src/pil/layer1-intent.js +99 -44
- package/dist/src/pil/layer1-intent.test.js +112 -2
- package/dist/src/pil/layer15-context-scan.js +1 -1
- package/dist/src/pil/layer16-clarity.d.ts +21 -25
- package/dist/src/pil/layer16-clarity.js +52 -88
- package/dist/src/pil/layer18-acceptance.d.ts +13 -3
- package/dist/src/pil/layer18-acceptance.js +1 -75
- package/dist/src/pil/layer2-personality.js +7 -8
- package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
- package/dist/src/pil/layer2_5-ponytail.js +41 -0
- package/dist/src/pil/layer3-ee-injection.js +180 -14
- package/dist/src/pil/layer4-gsd.js +22 -8
- package/dist/src/pil/layer5-context.d.ts +1 -0
- package/dist/src/pil/layer5-context.js +26 -11
- package/dist/src/pil/layer6-output.js +23 -5
- package/dist/src/pil/llm-classify.js +3 -3
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +4 -3
- package/dist/src/pil/pipeline.js +15 -1
- package/dist/src/pil/response-tools.d.ts +16 -0
- package/dist/src/pil/response-tools.js +41 -0
- package/dist/src/pil/schema.d.ts +8 -0
- package/dist/src/pil/schema.js +24 -3
- package/dist/src/pil/task-tier-map.js +7 -7
- package/dist/src/pil/types.d.ts +9 -3
- package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
- package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
- package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
- package/dist/src/product-loop/discovery-interview.d.ts +20 -0
- package/dist/src/product-loop/discovery-interview.js +121 -7
- package/dist/src/product-loop/done-gate.js +3 -3
- package/dist/src/product-loop/gather.js +19 -5
- package/dist/src/product-loop/loop-driver.js +20 -20
- package/dist/src/product-loop/progress-snapshot.js +4 -4
- package/dist/src/product-loop/sprint-self-verify.js +2 -2
- package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
- package/dist/src/providers/auth/gcloud.d.ts +28 -0
- package/dist/src/providers/auth/gcloud.js +102 -0
- package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
- package/dist/src/providers/auth/gemini-oauth.js +292 -105
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
- package/dist/src/providers/auth/grok-oauth.js +1 -1
- package/dist/src/providers/auth/registry.js +28 -6
- package/dist/src/providers/gemini.d.ts +1 -1
- package/dist/src/providers/gemini.js +10 -3
- package/dist/src/providers/keychain.d.ts +2 -2
- package/dist/src/providers/keychain.js +20 -2
- package/dist/src/providers/mcp-vision-bridge.js +48 -48
- package/dist/src/providers/openai.js +5 -1
- package/dist/src/providers/runtime.d.ts +1 -1
- package/dist/src/providers/runtime.js +11 -2
- package/dist/src/providers/siliconflow-sse-repair.js +1 -1
- package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
- package/dist/src/providers/strategies/google.strategy.js +159 -9
- package/dist/src/providers/strategies/thinking-mode.js +19 -6
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/reporter/index.js +1 -1
- package/dist/src/router/decide.test.js +40 -8
- package/dist/src/router/step-router.d.ts +20 -0
- package/dist/src/router/step-router.js +73 -0
- 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 +19 -19
- package/dist/src/self-qa/orchestrator.js +5 -5
- package/dist/src/self-qa/scenario-planner.js +1 -1
- package/dist/src/self-qa/spec-emitter.js +4 -4
- package/dist/src/storage/__tests__/migrations.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 +122 -122
- package/dist/src/storage/session-experience-store.js +4 -4
- package/dist/src/storage/sessions.js +43 -43
- package/dist/src/storage/transcript-view.js +7 -1
- package/dist/src/storage/transcript.d.ts +1 -0
- package/dist/src/storage/transcript.js +55 -0
- package/dist/src/storage/ui-interaction-log.d.ts +17 -0
- package/dist/src/storage/usage.js +14 -14
- package/dist/src/storage/workspaces.js +12 -12
- package/dist/src/tools/__tests__/native-tools.test.js +6 -0
- package/dist/src/tools/bash.d.ts +36 -23
- package/dist/src/tools/bash.js +59 -301
- package/dist/src/tools/bash.test.js +2 -257
- package/dist/src/tools/file-tracker.d.ts +5 -0
- package/dist/src/tools/file-tracker.js +14 -0
- package/dist/src/tools/file.js +2 -0
- package/dist/src/tools/git-safety.d.ts +38 -1
- package/dist/src/tools/git-safety.js +94 -4
- package/dist/src/tools/git-safety.test.js +45 -1
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +56 -0
- package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
- package/dist/src/tools/registry-git-safety.test.js +17 -6
- package/dist/src/tools/registry.d.ts +5 -0
- package/dist/src/tools/registry.js +185 -11
- package/dist/src/types/index.d.ts +7 -1
- package/dist/src/ui/app.d.ts +1 -0
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/components/council-question-card.js +1 -0
- package/dist/src/ui/components/message-view.js +37 -3
- package/dist/src/ui/components/structured-response-view.js +7 -0
- package/dist/src/ui/components/task-list-panel.js +3 -12
- package/dist/src/ui/containers/chat-feed.d.ts +40 -0
- package/dist/src/ui/containers/chat-feed.js +66 -0
- package/dist/src/ui/containers/modals-layer.d.ts +87 -0
- package/dist/src/ui/containers/modals-layer.js +18 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
- package/dist/src/ui/slash/council-inspect.js +4 -4
- package/dist/src/ui/slash/export.js +16 -1
- package/dist/src/ui/slash/menu-items.js +1 -0
- package/dist/src/ui/slash/ponytail.d.ts +2 -0
- package/dist/src/ui/slash/ponytail.js +19 -0
- package/dist/src/ui/status-bar/store.js +0 -1
- package/dist/src/ui/status-bar/store.test.js +2 -2
- package/dist/src/ui/use-app-logic.d.ts +26 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/relaunch.js +1 -1
- package/dist/src/ui/utils/text.d.ts +11 -0
- package/dist/src/ui/utils/text.js +21 -1
- package/dist/src/ui/utils/text.test.js +25 -1
- package/dist/src/ui/utils/tools.js +3 -1
- package/dist/src/usage/cost-log.js +2 -2
- package/dist/src/usage/estimator.d.ts +14 -0
- package/dist/src/usage/estimator.js +22 -0
- package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
- package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
- package/dist/src/utils/clipboard-image.js +23 -23
- package/dist/src/utils/llm-deadline.d.ts +9 -1
- package/dist/src/utils/llm-deadline.js +31 -2
- package/dist/src/utils/permission-mode.d.ts +33 -0
- package/dist/src/utils/permission-mode.js +164 -3
- package/dist/src/utils/permission-mode.test.js +92 -1
- package/dist/src/utils/settings.d.ts +27 -31
- package/dist/src/utils/settings.js +100 -109
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/skills.js +3 -3
- 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
|
|
@@ -54,6 +54,14 @@ const ALLOWED_FIELDS = {
|
|
|
54
54
|
round: "pass",
|
|
55
55
|
correlationId: "pass",
|
|
56
56
|
},
|
|
57
|
+
"council-turn-length": {
|
|
58
|
+
role: "pass",
|
|
59
|
+
round: "pass",
|
|
60
|
+
charCount: "pass",
|
|
61
|
+
wordCount: "pass",
|
|
62
|
+
model: "pass",
|
|
63
|
+
correlationId: "pass",
|
|
64
|
+
},
|
|
57
65
|
"askcard-open": {
|
|
58
66
|
questionId: "pass",
|
|
59
67
|
question: 300, // cap to 300 chars, then scrub
|
|
@@ -46,6 +46,22 @@ export declare function validateStartArgs(args: string[]): {
|
|
|
46
46
|
bad: string;
|
|
47
47
|
};
|
|
48
48
|
export declare function sanitizeEnv(env: Record<string, string>): Record<string, string>;
|
|
49
|
+
/**
|
|
50
|
+
* Opt-in extra cwd roots for tui.start, layered ON TOP of the default
|
|
51
|
+
* {home, repo-root} allowlist. The posture stays deny-by-default: only roots an
|
|
52
|
+
* operator has explicitly listed are added. Two union sources:
|
|
53
|
+
*
|
|
54
|
+
* 1. env `MUONROI_HARNESS_EXTRA_ROOTS` — a path list separated by the OS path
|
|
55
|
+
* separator (";" on win32, ":" elsewhere) and/or commas.
|
|
56
|
+
* 2. `<REPO_ROOT>/.muonroi-harness-roots.json` — `{ "roots": string[] }`.
|
|
57
|
+
*
|
|
58
|
+
* Rationale: the drive-harness needs to dogfood sibling ecosystem repos (e.g.
|
|
59
|
+
* `D:\sources\Core\*`) that live outside both home and the muonroi-cli checkout.
|
|
60
|
+
* Without an explicit opt-in those cwds are rejected, which blocks real-task
|
|
61
|
+
* evaluation. Clean checkouts have neither the env nor the (gitignored) config
|
|
62
|
+
* file, so behaviour is identical to the original home+repo-only boundary.
|
|
63
|
+
*/
|
|
64
|
+
export declare function loadExtraRoots(): string[];
|
|
49
65
|
export declare function validateCwd(cwd: string): {
|
|
50
66
|
ok: true;
|
|
51
67
|
} | {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* fd 3/4, named pipes, WebSocket, …). The consumer (muonroi-cli) provides the
|
|
12
12
|
* spawn implementation via createMcpHarnessServer({ spawn }).
|
|
13
13
|
*/
|
|
14
|
-
import { existsSync, realpathSync } from "node:fs";
|
|
14
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { isAbsolute, resolve } from "node:path";
|
|
17
17
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -50,6 +50,51 @@ export function sanitizeEnv(env) {
|
|
|
50
50
|
return out;
|
|
51
51
|
}
|
|
52
52
|
const REPO_ROOT = process.cwd();
|
|
53
|
+
/**
|
|
54
|
+
* Opt-in extra cwd roots for tui.start, layered ON TOP of the default
|
|
55
|
+
* {home, repo-root} allowlist. The posture stays deny-by-default: only roots an
|
|
56
|
+
* operator has explicitly listed are added. Two union sources:
|
|
57
|
+
*
|
|
58
|
+
* 1. env `MUONROI_HARNESS_EXTRA_ROOTS` — a path list separated by the OS path
|
|
59
|
+
* separator (";" on win32, ":" elsewhere) and/or commas.
|
|
60
|
+
* 2. `<REPO_ROOT>/.muonroi-harness-roots.json` — `{ "roots": string[] }`.
|
|
61
|
+
*
|
|
62
|
+
* Rationale: the drive-harness needs to dogfood sibling ecosystem repos (e.g.
|
|
63
|
+
* `D:\sources\Core\*`) that live outside both home and the muonroi-cli checkout.
|
|
64
|
+
* Without an explicit opt-in those cwds are rejected, which blocks real-task
|
|
65
|
+
* evaluation. Clean checkouts have neither the env nor the (gitignored) config
|
|
66
|
+
* file, so behaviour is identical to the original home+repo-only boundary.
|
|
67
|
+
*/
|
|
68
|
+
export function loadExtraRoots() {
|
|
69
|
+
const roots = [];
|
|
70
|
+
const envVal = process.env.MUONROI_HARNESS_EXTRA_ROOTS;
|
|
71
|
+
if (envVal) {
|
|
72
|
+
// Split on the OS path separator or commas. On win32 the separator is ";"
|
|
73
|
+
// (not ":") so drive letters like "D:\..." stay intact.
|
|
74
|
+
const listSep = process.platform === "win32" ? ";" : ":";
|
|
75
|
+
for (const part of envVal.split(new RegExp(`[${listSep},]`))) {
|
|
76
|
+
const trimmed = part.trim();
|
|
77
|
+
if (trimmed)
|
|
78
|
+
roots.push(trimmed);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const cfgPath = resolve(REPO_ROOT, ".muonroi-harness-roots.json");
|
|
82
|
+
if (existsSync(cfgPath)) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(readFileSync(cfgPath, "utf8"));
|
|
85
|
+
if (Array.isArray(parsed.roots)) {
|
|
86
|
+
for (const r of parsed.roots) {
|
|
87
|
+
if (typeof r === "string" && r.trim())
|
|
88
|
+
roots.push(r.trim());
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.error(`[harness/mcp-server] failed to parse ${cfgPath}: ${err?.message}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return roots;
|
|
97
|
+
}
|
|
53
98
|
export function validateCwd(cwd) {
|
|
54
99
|
let real;
|
|
55
100
|
try {
|
|
@@ -58,16 +103,22 @@ export function validateCwd(cwd) {
|
|
|
58
103
|
catch {
|
|
59
104
|
return { ok: false, reason: "cwd does not exist or unreadable" };
|
|
60
105
|
}
|
|
61
|
-
const home = realpathSync(homedir());
|
|
62
|
-
const root = realpathSync(REPO_ROOT);
|
|
63
106
|
const sep = process.platform === "win32" ? "\\" : "/";
|
|
64
|
-
|
|
65
|
-
|
|
107
|
+
const allowedRoots = [realpathSync(homedir()), realpathSync(REPO_ROOT)];
|
|
108
|
+
for (const extra of loadExtraRoots()) {
|
|
109
|
+
try {
|
|
110
|
+
allowedRoots.push(realpathSync(extra));
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
console.error(`[harness/mcp-server] extra cwd root unresolved, skipping: ${extra} (${err?.message})`);
|
|
114
|
+
}
|
|
66
115
|
}
|
|
67
|
-
|
|
68
|
-
|
|
116
|
+
for (const root of allowedRoots) {
|
|
117
|
+
if (real === root || real.startsWith(root + sep)) {
|
|
118
|
+
return { ok: true };
|
|
119
|
+
}
|
|
69
120
|
}
|
|
70
|
-
return { ok: false, reason: "cwd escapes home and
|
|
121
|
+
return { ok: false, reason: "cwd escapes home, repo root, and configured extra roots" };
|
|
71
122
|
}
|
|
72
123
|
export function validateMockLlmPath(value) {
|
|
73
124
|
const resolved = isAbsolute(value) ? value : resolve(REPO_ROOT, value);
|
|
@@ -255,7 +306,34 @@ export function registerAsyncTools(server, getDriver, deps) {
|
|
|
255
306
|
});
|
|
256
307
|
server.registerTool("tui.last_event", {
|
|
257
308
|
description: "Return the most recent event of the given kind (null if none).",
|
|
258
|
-
|
|
309
|
+
// Full protocol event set (minus the idle sentinel) so an external agent can
|
|
310
|
+
// observe lifecycle events — council/sprint/route/askcard, not just toasts.
|
|
311
|
+
// The Driver accepts any kind; this enum is the MCP-boundary validation.
|
|
312
|
+
inputSchema: {
|
|
313
|
+
kind: z.enum([
|
|
314
|
+
"toast",
|
|
315
|
+
"stream.delta",
|
|
316
|
+
"llm-token",
|
|
317
|
+
"llm-done",
|
|
318
|
+
"council-step",
|
|
319
|
+
"council-speaker",
|
|
320
|
+
"council-turn-length",
|
|
321
|
+
"askcard-open",
|
|
322
|
+
"askcard-answered",
|
|
323
|
+
"askcard-cancel",
|
|
324
|
+
"sprint-stage",
|
|
325
|
+
"sprint-halt",
|
|
326
|
+
"sprint-plan-committed",
|
|
327
|
+
"route-decision",
|
|
328
|
+
"steer-inject",
|
|
329
|
+
"usage",
|
|
330
|
+
"grounding-flag",
|
|
331
|
+
"ee-timeout",
|
|
332
|
+
"ee-error",
|
|
333
|
+
"stream-retry",
|
|
334
|
+
"disconnect",
|
|
335
|
+
]),
|
|
336
|
+
},
|
|
259
337
|
}, async ({ kind }) => {
|
|
260
338
|
const d = getDriver();
|
|
261
339
|
if (!d)
|
|
@@ -353,7 +431,7 @@ export function createMcpHarnessServer({ spawn }) {
|
|
|
353
431
|
}
|
|
354
432
|
if (!finalArgs.includes("--agent-mode"))
|
|
355
433
|
finalArgs.push("--agent-mode");
|
|
356
|
-
const entry = process.cwd()
|
|
434
|
+
const entry = `${process.cwd()}/src/index.ts`;
|
|
357
435
|
// Delegate to the injected spawn implementation — the core package has no
|
|
358
436
|
// knowledge of the concrete transport (fd 3/4, named pipes, WebSocket …).
|
|
359
437
|
let spawnResult;
|
|
@@ -73,6 +73,21 @@ export type LiveEvent = {
|
|
|
73
73
|
round?: number;
|
|
74
74
|
/** Correlation ID linking this speaker event to the enclosing council run. */
|
|
75
75
|
correlationId: string;
|
|
76
|
+
} | {
|
|
77
|
+
t: "event";
|
|
78
|
+
kind: "council-turn-length";
|
|
79
|
+
/** Council role label (e.g. "architect"); matches council-speaker.role. */
|
|
80
|
+
role: string;
|
|
81
|
+
/** Debate round: 0 = opening statements, 1+ = discussion rounds. */
|
|
82
|
+
round: number;
|
|
83
|
+
/** Full character count of the speaker's output (trimmed; never truncated). */
|
|
84
|
+
charCount: number;
|
|
85
|
+
/** Word count of the speaker's output (whitespace-split, empties dropped). */
|
|
86
|
+
wordCount: number;
|
|
87
|
+
/** The speaker's model id, for per-model thrift attribution. */
|
|
88
|
+
model: string;
|
|
89
|
+
/** Correlation ID tying turns to the enclosing council run (= sessionId). */
|
|
90
|
+
correlationId: string;
|
|
76
91
|
} | {
|
|
77
92
|
t: "event";
|
|
78
93
|
kind: "askcard-open";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const _FLAGS = new Set(["focus", "selected", "disabled"]);
|
|
2
2
|
export function parseSelector(input) {
|
|
3
3
|
// First, split by child combinator >>
|
|
4
4
|
const childCombinatorRegex = /\s*>>\s*/;
|
|
@@ -146,7 +146,7 @@ function readField(node, key) {
|
|
|
146
146
|
return node.state;
|
|
147
147
|
if (key.startsWith("props.")) {
|
|
148
148
|
const dot = key.slice("props.".length);
|
|
149
|
-
return
|
|
149
|
+
return node.props?.[dot];
|
|
150
150
|
}
|
|
151
151
|
return undefined;
|
|
152
152
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const MAX_BYTES = 1024 * 1024; // 1 MiB
|
|
2
2
|
function serialize(msg) {
|
|
3
|
-
const line = JSON.stringify(msg)
|
|
3
|
+
const line = `${JSON.stringify(msg)}\n`;
|
|
4
4
|
if (Buffer.byteLength(line, "utf8") > MAX_BYTES) {
|
|
5
5
|
throw new Error(`sidechannel message exceeds 1 MiB cap`);
|
|
6
6
|
}
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { createReadStream, createWriteStream } from "node:fs";
|
|
19
19
|
import { createEventFilter } from "@muonroi/agent-harness-core/event-filter";
|
|
20
|
-
import { createIdleDetector } from "@muonroi/agent-harness-core/idle";
|
|
21
20
|
import { redactEvent } from "@muonroi/agent-harness-core/event-redact";
|
|
21
|
+
import { createIdleDetector } from "@muonroi/agent-harness-core/idle";
|
|
22
22
|
import { createLineSplitter, createSidechannelWriter } from "@muonroi/agent-harness-core/transports/sidechannel";
|
|
23
23
|
import { installOpenTUIHarness } from "./install.js";
|
|
24
24
|
import { createSemanticRegistry } from "./reconciler-hook.js";
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Any module that transitively imports db.ts will resolve to this stub.
|
|
4
4
|
*/
|
|
5
5
|
import { vi } from "vitest";
|
|
6
|
+
// vitest 2+ removed vi.mocked(). This shim restores it for the 93+ call sites across the
|
|
7
|
+
// codebase without a codemod. Safe no-op: vi.mocked(item) just returns item (typed cast).
|
|
8
|
+
// @ts-expect-error — vi.mocked is intentionally absent from vitest 4 types.
|
|
9
|
+
vi.mocked ??= ((item, _options) => item);
|
|
6
10
|
// @opentui/react is a pre-bundled CJS package that requires 'react-reconciler/constants'
|
|
7
11
|
// without the .js extension — this fails in the vitest ESM environment. None of the unit
|
|
8
12
|
// tests exercise OpenTUI hooks directly (those are covered by E2E harness specs), so mocking
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
+
import { APICallError } from "@ai-sdk/provider";
|
|
8
9
|
import { generateObject, stepCountIs, streamText, tool } from "ai";
|
|
9
10
|
import { afterAll, describe, expect, it } from "vitest";
|
|
10
11
|
import { z } from "zod";
|
|
12
|
+
import { humanizeApiError } from "../../orchestrator/error-utils.js";
|
|
11
13
|
import { createMockModel, loadMockModelFromDir, textOnlyStream, toolCallStream } from "../mock-model.js";
|
|
12
14
|
// biome-ignore lint/suspicious/noExplicitAny: streamText result generic is provider-specific
|
|
13
15
|
async function drainStream(result) {
|
|
@@ -188,6 +190,58 @@ describe("loadMockModelFromDir", () => {
|
|
|
188
190
|
});
|
|
189
191
|
expect(object).toEqual({ ok: true, label: "built" });
|
|
190
192
|
});
|
|
193
|
+
it("constructs an APICallError from a structured error fixture (drives the humanizeApiError 5xx branch)", async () => {
|
|
194
|
+
// A pure-JSON fixture cannot otherwise build an APICallError (it arrives as
|
|
195
|
+
// a plain string). buildFixtureError() in mock-model.ts upgrades a structured
|
|
196
|
+
// `error` object carrying a statusCode into a real APICallError so harness/
|
|
197
|
+
// unit specs can exercise the orchestrator's status-aware 5xx path.
|
|
198
|
+
const dir = mkFixtureDir({
|
|
199
|
+
provider: "mock",
|
|
200
|
+
modelId: "mock-gpt",
|
|
201
|
+
stream: [
|
|
202
|
+
[
|
|
203
|
+
{ type: "stream-start", warnings: [] },
|
|
204
|
+
{
|
|
205
|
+
type: "error",
|
|
206
|
+
error: {
|
|
207
|
+
apiCallError: true,
|
|
208
|
+
statusCode: 500,
|
|
209
|
+
message: "AI_APICallError: Request failed",
|
|
210
|
+
responseBody: JSON.stringify({ code: 60000, message: "Request failed: Unknown error." }),
|
|
211
|
+
url: "https://api.siliconflow.cn/v1/chat/completions",
|
|
212
|
+
isRetryable: true,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
type: "finish",
|
|
217
|
+
finishReason: { unified: "error", raw: null },
|
|
218
|
+
usage: {
|
|
219
|
+
inputTokens: { total: 0, noCache: 0, cacheRead: null, cacheWrite: null },
|
|
220
|
+
outputTokens: { total: 0, text: 0, reasoning: null },
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
],
|
|
225
|
+
});
|
|
226
|
+
const handle = await loadMockModelFromDir(dir);
|
|
227
|
+
expect(handle).not.toBeNull();
|
|
228
|
+
const r = streamText({ model: handle.model, prompt: "hi" });
|
|
229
|
+
let errPart = null;
|
|
230
|
+
for await (const part of r.fullStream) {
|
|
231
|
+
if (part.type === "error")
|
|
232
|
+
errPart = part;
|
|
233
|
+
}
|
|
234
|
+
expect(errPart).not.toBeNull();
|
|
235
|
+
expect(APICallError.isInstance(errPart?.error)).toBe(true);
|
|
236
|
+
expect((errPart?.error).statusCode).toBe(500);
|
|
237
|
+
// The 5xx branch must surface the canned actionable text + (HTTP 500) and
|
|
238
|
+
// SUPPRESS the opaque provider body (the SiliconFlow "Unknown error" mask).
|
|
239
|
+
const msg = humanizeApiError(errPart?.error);
|
|
240
|
+
expect(msg).toContain("HTTP 500");
|
|
241
|
+
expect(msg.toLowerCase()).toContain("try again later");
|
|
242
|
+
expect(msg).not.toContain("Unknown error");
|
|
243
|
+
expect(msg).not.toContain("Request failed");
|
|
244
|
+
});
|
|
191
245
|
it("supports multi-round stream arrays from the fixture file", async () => {
|
|
192
246
|
const dir = mkFixtureDir({
|
|
193
247
|
provider: "mock",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* const calls = handle.calls; // LanguageModelV3CallOptions[]
|
|
23
23
|
* expect(calls[0].maxOutputTokens).toBeUndefined();
|
|
24
24
|
*/
|
|
25
|
-
import type
|
|
25
|
+
import { type LanguageModelV3CallOptions, type LanguageModelV3StreamPart } from "@ai-sdk/provider";
|
|
26
26
|
import { MockLanguageModelV3 } from "ai/test";
|
|
27
27
|
export type StreamChunks = LanguageModelV3StreamPart[];
|
|
28
28
|
export interface MockModelFixture {
|