muonroi-cli 1.7.1 → 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 +143 -104
- 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.d.ts +6 -0
- package/dist/src/storage/sessions.js +49 -42
- 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 +2 -1
- 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/modals/session-picker-modal.js +14 -9
- package/dist/src/ui/modals/update-modal.js +2 -1
- 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/types.d.ts +7 -0
- 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.d.ts +17 -0
- package/dist/src/ui/utils/relaunch.js +28 -4
- package/dist/src/ui/utils/relaunch.test.js +50 -0
- 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
|
@@ -36,32 +36,23 @@ function ItemRow({ item, t }) {
|
|
|
36
36
|
let glyph;
|
|
37
37
|
let glyphColor;
|
|
38
38
|
let textColor;
|
|
39
|
-
|
|
39
|
+
const label = item.status === "in_progress" ? (item.activeForm ?? item.subject) : item.subject;
|
|
40
40
|
if (item.status === "completed") {
|
|
41
41
|
glyph = "✓";
|
|
42
42
|
glyphColor = t.diffAddedFg;
|
|
43
43
|
textColor = t.textMuted;
|
|
44
|
-
// Strikethrough via U+0336 combining mark. OpenTUI doesn't expose CSS
|
|
45
|
-
// text-decoration so we synthesise it character-by-character — matches the
|
|
46
|
-
// visual goal in the spec.
|
|
47
|
-
label = item.subject
|
|
48
|
-
.split("")
|
|
49
|
-
.map((c) => `${c}̶`)
|
|
50
|
-
.join("");
|
|
51
44
|
}
|
|
52
45
|
else if (item.status === "in_progress") {
|
|
53
46
|
glyph = "◉";
|
|
54
47
|
glyphColor = t.accent;
|
|
55
48
|
textColor = t.text;
|
|
56
|
-
label = item.activeForm ?? item.subject;
|
|
57
49
|
}
|
|
58
50
|
else {
|
|
59
51
|
glyph = "○";
|
|
60
52
|
glyphColor = t.textMuted;
|
|
61
53
|
textColor = t.text;
|
|
62
|
-
label = item.subject;
|
|
63
54
|
}
|
|
64
|
-
return (_jsx(Semantic, { id: `task-${item.id}`, role: "listitem", name: label, state: item.status, children: _jsxs("text", { children: [_jsx("span", { style: { fg: glyphColor }, children: `${glyph} ` }),
|
|
55
|
+
return (_jsx(Semantic, { id: `task-${item.id}`, role: "listitem", name: label, state: item.status, children: _jsx("box", { width: "100%", children: _jsxs("text", { fg: textColor, children: [_jsx("span", { style: { fg: glyphColor }, children: `${glyph} ` }), trunc(label, 70)] }) }) }));
|
|
65
56
|
}
|
|
66
57
|
export function TaskListPanel({ snapshot, t, expanded }) {
|
|
67
58
|
if (snapshot.items.length === 0)
|
|
@@ -78,7 +69,7 @@ export function TaskListPanel({ snapshot, t, expanded }) {
|
|
|
78
69
|
if (pending > 0)
|
|
79
70
|
footerParts.push(`${pending} queued`);
|
|
80
71
|
const footer = footerParts.length > 0 ? footerParts.join(" · ") : "0 todos";
|
|
81
|
-
return (_jsx(Semantic, { id: "task-list", role: "listbox", name: "Todos", children: _jsxs("box", { border: true, borderColor: t.border, paddingLeft: 2, paddingRight: 2, paddingTop: 0, paddingBottom: 0, marginBottom: 1, flexDirection: "column", children: [_jsx("
|
|
72
|
+
return (_jsx(Semantic, { id: "task-list", role: "listbox", name: "Todos", children: _jsxs("box", { border: true, borderColor: t.border, paddingLeft: 2, paddingRight: 2, paddingTop: 0, paddingBottom: 0, marginBottom: 1, flexDirection: "column", children: [_jsx("box", { paddingBottom: 1, children: _jsx("text", { fg: t.textMuted, children: _jsx("b", { children: "Todos" }) }) }), _jsx("box", { flexDirection: "column", children: visible.map((it) => (_jsx(ItemRow, { item: it, t: t }, it.id))) }), overflow > 0 && (_jsx("box", { marginTop: 1, children: _jsx("text", { fg: t.textMuted, children: `… +${overflow} more (ctrl+e to expand)` }) })), _jsx("box", { marginTop: 1, paddingTop: 1, border: ["top"], borderColor: t.border, children: _jsx("text", { fg: t.textDim, children: footer }) })] }) }));
|
|
82
73
|
}
|
|
83
74
|
export const __TEST_ONLY__ = { sortItems, MAX_VISIBLE };
|
|
84
75
|
//# sourceMappingURL=task-list-panel.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface ChatFeedProps {
|
|
3
|
+
getSide: any;
|
|
4
|
+
getPartnerLast: any;
|
|
5
|
+
resolveStyle: any;
|
|
6
|
+
scrollRef: any;
|
|
7
|
+
messages: any;
|
|
8
|
+
expandedMessages: any;
|
|
9
|
+
liveTurnSourceLabel: any;
|
|
10
|
+
activeToolCalls: any;
|
|
11
|
+
streamContent: any;
|
|
12
|
+
isProcessing: any;
|
|
13
|
+
activeSubagent: any;
|
|
14
|
+
councilPhases: any;
|
|
15
|
+
productStatus: any;
|
|
16
|
+
councilStatuses: any;
|
|
17
|
+
councilInfoCards: any;
|
|
18
|
+
councilMessages: any;
|
|
19
|
+
councilPlaceholders: any;
|
|
20
|
+
reasoningActive: any;
|
|
21
|
+
lastReasoningElapsedMs: any;
|
|
22
|
+
streamReasoning: any;
|
|
23
|
+
showPlanPanel: any;
|
|
24
|
+
planQuestions: any;
|
|
25
|
+
pqs: any;
|
|
26
|
+
pendingPaymentApproval: any;
|
|
27
|
+
activeHaltCard: any;
|
|
28
|
+
haltSelectedIndex: any;
|
|
29
|
+
initNewForm: any;
|
|
30
|
+
pointToExistingForm: any;
|
|
31
|
+
councilProgress: any;
|
|
32
|
+
pendingCouncilQuestion: any;
|
|
33
|
+
councilCardState: any;
|
|
34
|
+
pendingCouncilPreflight: any;
|
|
35
|
+
preflightCardState: any;
|
|
36
|
+
t: any;
|
|
37
|
+
width: any;
|
|
38
|
+
modeInfo: any;
|
|
39
|
+
}
|
|
40
|
+
export declare function ChatFeed(props: ChatFeedProps): React.ReactNode;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { Semantic } from "@muonroi/agent-harness-opentui";
|
|
3
|
+
import { ProductStatusCard } from "../cards/product-status-card.js";
|
|
4
|
+
import { makePairKey } from "../components/bubble-layout.js";
|
|
5
|
+
import { CouncilInfoCardView } from "../components/council-info-card.js";
|
|
6
|
+
import { CouncilLeaderBubble } from "../components/council-leader-bubble.js";
|
|
7
|
+
import { CouncilMessageBubble } from "../components/council-message-bubble.js";
|
|
8
|
+
import { CouncilPhaseTimeline } from "../components/council-phase-timeline.js";
|
|
9
|
+
import { CouncilPlaceholderBubble } from "../components/council-placeholder-bubble.js";
|
|
10
|
+
import { CouncilQuestionCard } from "../components/council-question-card.js";
|
|
11
|
+
import { CouncilStatusList } from "../components/council-status-list.js";
|
|
12
|
+
import { CouncilSynthesisBanner } from "../components/council-synthesis-banner.js";
|
|
13
|
+
import { HaltRecoveryCard } from "../components/halt-recovery-card.js";
|
|
14
|
+
import { InitNewFormCard } from "../components/init-new-form-card.js";
|
|
15
|
+
import { computeMcpRunInfo, MessageView } from "../components/message-view.js";
|
|
16
|
+
import { PointToExistingFormCard } from "../components/point-to-existing-form-card.js";
|
|
17
|
+
import { DelegationTaskLine, InlineTool, ShimmerText, SubagentActivity, SubagentTaskLine, } from "../components/tool-result-views.js";
|
|
18
|
+
import { Markdown } from "../markdown.js";
|
|
19
|
+
import { PaymentApprovalPanel } from "../modals/wallet-picker-modal.js";
|
|
20
|
+
import { PlanQuestionsPanel } from "../plan.js";
|
|
21
|
+
import { buildPreflightQuestion } from "../utils/format.js";
|
|
22
|
+
import { toolArgs, toolLabel, tryParseArg } from "../utils/tools.js";
|
|
23
|
+
export function ChatFeed(props) {
|
|
24
|
+
const { modeInfo, getSide, getPartnerLast, resolveStyle, scrollRef, messages, expandedMessages, liveTurnSourceLabel, activeToolCalls, streamContent, isProcessing, activeSubagent, councilPhases, productStatus, councilStatuses, councilInfoCards, councilMessages, councilPlaceholders, reasoningActive, lastReasoningElapsedMs, streamReasoning, showPlanPanel, planQuestions, pqs, pendingPaymentApproval, activeHaltCard, haltSelectedIndex, initNewForm, pointToExistingForm, councilProgress, pendingCouncilQuestion, councilCardState, pendingCouncilPreflight, preflightCardState, t, width, } = props;
|
|
25
|
+
return (_jsx(Semantic, { id: "log", role: "log", props: { scrollTop: scrollRef.current?.scrollTop ?? 0 }, children: _jsxs("scrollbox", { ref: scrollRef, flexGrow: 1, stickyScroll: true, stickyStart: "bottom", children: [(() => {
|
|
26
|
+
const mcpRuns = computeMcpRunInfo(messages);
|
|
27
|
+
// Phase 5 F7 — index of the last assistant message so
|
|
28
|
+
// MessageView can skip auto-collapse on it (final answer
|
|
29
|
+
// should always be fully visible, not hidden behind
|
|
30
|
+
// "ctrl+e expand").
|
|
31
|
+
let _lastAssistantIdx = -1;
|
|
32
|
+
for (let _i = messages.length - 1; _i >= 0; _i--) {
|
|
33
|
+
if (messages[_i]?.type === "assistant") {
|
|
34
|
+
_lastAssistantIdx = _i;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return messages.map((msg, i) => (
|
|
39
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: append-only message log; index is part of the stable semantic id
|
|
40
|
+
_jsx(Semantic, { id: `msg-${i}`, role: "listitem", name: `${msg.type ?? "msg"}:${String(msg.content ?? "").slice(0, 40)}`, children: _jsx(MessageView, { entry: msg, index: i, t: t, modeColor: modeInfo.color, expandedMessages: expandedMessages, mcpRun: mcpRuns[i], isFinalAssistant: i === _lastAssistantIdx }, `${msg.timestamp?.getTime?.() ?? i}-${msg.type}-${msg.remoteKey ?? ""}-${String(msg.content ?? "").slice(0, 24)}`) }, `sem-${msg.timestamp?.getTime?.() ?? i}-${i}`)));
|
|
41
|
+
})(), liveTurnSourceLabel && (activeToolCalls.length > 0 || streamContent || isProcessing) && (_jsx("box", { paddingLeft: 3, marginTop: 1, flexShrink: 0, children: _jsx("text", { fg: t.textMuted, children: liveTurnSourceLabel }) })), activeToolCalls.map((tc) => tc.function.name === "task" ? (_jsx(SubagentTaskLine, { t: t, agent: tryParseArg(tc, "agent") || "sub-agent", label: toolArgs(tc) || "Working", pending: true }, tc.id)) : tc.function.name === "delegate" ? (_jsx(DelegationTaskLine, { t: t, label: toolArgs(tc) || "Background research", pending: true, id: undefined }, tc.id)) : (_jsx(InlineTool, { t: t, pending: true, children: toolLabel(tc) }, tc.id))), activeSubagent && _jsx(SubagentActivity, { t: t, status: activeSubagent }), councilPhases.length > 0 && (_jsx(Semantic, { id: "council-phases", role: "listbox", name: "Council Phases", children: _jsx(CouncilPhaseTimeline, { phases: councilPhases, theme: t }) })), productStatus && _jsx(ProductStatusCard, { data: productStatus, theme: t }), councilStatuses.length > 0 && (_jsx(Semantic, { id: "council-status", role: "listbox", name: "Council Status", children: _jsx(CouncilStatusList, { statuses: councilStatuses, theme: t }) })), councilInfoCards.map((card, idx) => (_jsx(Semantic, { id: `council-card-${idx}`, role: "listitem", name: card.title || `Council card ${idx}`, children: _jsx(CouncilInfoCardView, { card: card, terminalCols: width, theme: t }, `info-card-${idx}-${card.title}`) }, `sem-info-${idx}-${card.title}`))), councilMessages.map((cm, idx) => {
|
|
42
|
+
const side = cm.kind === "debate" && cm.partner
|
|
43
|
+
? getSide(makePairKey(cm.speaker.role, cm.partner.role), cm.speaker.role)
|
|
44
|
+
: "left";
|
|
45
|
+
const semName = `${cm.kind}:${cm.speaker?.role ?? "?"}`;
|
|
46
|
+
if (cm.kind === "leader") {
|
|
47
|
+
return (_jsx(Semantic, { id: `council-msg-${idx}`, role: "listitem", name: semName, value: cm.text, children: _jsx(CouncilLeaderBubble, { msg: cm, terminalCols: width }, idx) }, `sem-cm-${idx}`));
|
|
48
|
+
}
|
|
49
|
+
if (cm.kind === "synthesis") {
|
|
50
|
+
return (_jsx(Semantic, { id: `council-msg-${idx}`, role: "listitem", name: semName, value: cm.text, children: _jsx(CouncilSynthesisBanner, { msg: cm }, idx) }, `sem-cm-${idx}`));
|
|
51
|
+
}
|
|
52
|
+
const pairKey = cm.partner ? makePairKey(cm.speaker.role, cm.partner.role) : `solo::${cm.speaker.role}`;
|
|
53
|
+
const partnerLastText = cm.partner ? getPartnerLast(pairKey, cm.partner.role) : undefined;
|
|
54
|
+
return (_jsx(Semantic, { id: `council-msg-${idx}`, role: "listitem", name: semName, value: cm.text, children: _jsx(CouncilMessageBubble, { msg: cm, terminalCols: width, side: side, resolveStyle: resolveStyle, partnerLastText: partnerLastText, partnerRole: cm.partner?.role, theme: t }, idx) }, `sem-cm-${idx}`));
|
|
55
|
+
}), Array.from(councilPlaceholders.entries()).map(([id, p]) => (_jsx(CouncilPlaceholderBubble, { role: p.role, side: p.side, terminalCols: width, color: p.color, theme: t, variant: p.variant }, id))), (reasoningActive || lastReasoningElapsedMs > 0) && (_jsxs("box", { paddingLeft: 3, marginTop: 1, flexShrink: 0, flexDirection: "column", children: [_jsx("text", { fg: t.textMuted, children: reasoningActive ? "[Thought] Thinking..." : `[Thought] Thought for ${(lastReasoningElapsedMs / 1000).toFixed(1)}s` }), streamReasoning ? (_jsx("box", { border: ["left"], borderColor: t.textMuted, paddingLeft: 2, marginTop: 1, flexDirection: "column", children: reasoningActive ? (
|
|
56
|
+
// While actively streaming, render only the last 3
|
|
57
|
+
// non-empty lines as plain text to avoid Markdown
|
|
58
|
+
// re-parse overhead every 150ms.
|
|
59
|
+
_jsx("text", { fg: t.textMuted, children: streamReasoning
|
|
60
|
+
.split("\n")
|
|
61
|
+
.filter((l) => l.trim().length > 0)
|
|
62
|
+
.slice(-3)
|
|
63
|
+
.join(" · ") })) : (_jsx(Markdown, { content: streamReasoning, t: t })) })) : null] })), streamContent && (_jsx("box", { paddingLeft: 3, marginTop: 1, flexShrink: 0, children: _jsx(Markdown, { content: streamContent, t: t }) })), isProcessing && !streamContent && activeToolCalls.length === 0 && (_jsx(ShimmerText, { t: t, text: "Planning next moves" })), showPlanPanel && _jsx(PlanQuestionsPanel, { t: t, questions: planQuestions, state: pqs }), pendingPaymentApproval && _jsx(PaymentApprovalPanel, { t: t, payment: pendingPaymentApproval }), activeHaltCard && (_jsx(HaltRecoveryCard, { halt: activeHaltCard, selectedIndex: haltSelectedIndex, terminalCols: width, theme: t })), initNewForm && _jsx(InitNewFormCard, { state: initNewForm, terminalCols: width, theme: t }), pointToExistingForm && _jsx(PointToExistingFormCard, { state: pointToExistingForm, terminalCols: width, theme: t }), councilProgress && (_jsx(Semantic, { id: "continue-as-council-progress", role: "log", name: "Council brainstorm", children: _jsx("box", { flexDirection: "column", borderStyle: "single", borderColor: councilProgress.status === "error" ? t.initFormError : t.text, padding: 1, marginTop: 1, children: _jsxs("text", { fg: t.text, children: [councilProgress.status === "running" && "Council brainstorming — writing spec.md...", councilProgress.status === "done" &&
|
|
64
|
+
`Council brainstorm complete: ${councilProgress.specPath}${councilProgress.hasContent ? "" : " (no content — production council wiring deferred)"}`, councilProgress.status === "error" && `Council brainstorm failed: ${councilProgress.error}`] }) }) })), pendingCouncilQuestion && councilCardState && (_jsx(CouncilQuestionCard, { question: pendingCouncilQuestion, theme: t, state: councilCardState })), pendingCouncilPreflight && preflightCardState && (_jsx(CouncilQuestionCard, { question: buildPreflightQuestion(pendingCouncilPreflight), theme: t, state: preflightCardState }))] }) }));
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=chat-feed.js.map
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export interface ModalsLayerProps {
|
|
2
|
+
agentRows: any;
|
|
3
|
+
agentsEditorDraft: any;
|
|
4
|
+
agentsEditorError: any;
|
|
5
|
+
agentsEditorField: any;
|
|
6
|
+
agentsEditorModelIndex: any;
|
|
7
|
+
agentsEditorSyncKey: any;
|
|
8
|
+
agentsModalIndex: any;
|
|
9
|
+
agentsSearchQuery: any;
|
|
10
|
+
apiKeyError: any;
|
|
11
|
+
apiKeyInputRef: any;
|
|
12
|
+
apiKeyPrompt: any;
|
|
13
|
+
bwSync: any;
|
|
14
|
+
configuredProviders: any;
|
|
15
|
+
connectModalIndex: any;
|
|
16
|
+
defaultProvider: any;
|
|
17
|
+
disabledModels: any;
|
|
18
|
+
disabledProviders: any;
|
|
19
|
+
editingMcpId: any;
|
|
20
|
+
editingSubagent: any;
|
|
21
|
+
filteredModels: any;
|
|
22
|
+
height: any;
|
|
23
|
+
mcpArgsRef: any;
|
|
24
|
+
mcpCommandRef: any;
|
|
25
|
+
mcpCwdRef: any;
|
|
26
|
+
mcpEditorDraft: any;
|
|
27
|
+
mcpEditorError: any;
|
|
28
|
+
mcpEditorField: any;
|
|
29
|
+
mcpEditorSyncKey: any;
|
|
30
|
+
mcpEnvRef: any;
|
|
31
|
+
mcpHeadersRef: any;
|
|
32
|
+
mcpLabelRef: any;
|
|
33
|
+
mcpModalIndex: any;
|
|
34
|
+
mcpRows: any;
|
|
35
|
+
mcpSearchQuery: any;
|
|
36
|
+
mcpUrlRef: any;
|
|
37
|
+
model: any;
|
|
38
|
+
modelPickerFocus: any;
|
|
39
|
+
modelPickerIndex: any;
|
|
40
|
+
modelSearchQuery: any;
|
|
41
|
+
providerChipIndex: any;
|
|
42
|
+
providersWithKey: any;
|
|
43
|
+
reasoningEffortByModel: any;
|
|
44
|
+
sandboxMode: any;
|
|
45
|
+
sandboxSettings: any;
|
|
46
|
+
sandboxSettingsEditBuffer: any;
|
|
47
|
+
sandboxSettingsEditing: any;
|
|
48
|
+
sandboxSettingsFocusIndex: any;
|
|
49
|
+
scheduleModalIndex: any;
|
|
50
|
+
scheduleRows: any;
|
|
51
|
+
scheduleSearchQuery: any;
|
|
52
|
+
sessionPickerIndex: any;
|
|
53
|
+
sessionPickerList: any;
|
|
54
|
+
showAgentsEditor: any;
|
|
55
|
+
showAgentsModal: any;
|
|
56
|
+
showApiKeyModal: any;
|
|
57
|
+
showConnectModal: any;
|
|
58
|
+
showMcpEditor: any;
|
|
59
|
+
showMcpModal: any;
|
|
60
|
+
showModelPicker: any;
|
|
61
|
+
showSandboxPicker: any;
|
|
62
|
+
showScheduleModal: any;
|
|
63
|
+
showSessionPicker: any;
|
|
64
|
+
showTelegramPairModal: any;
|
|
65
|
+
showTelegramTokenModal: any;
|
|
66
|
+
showUpdateModal: any;
|
|
67
|
+
showWalletPicker: any;
|
|
68
|
+
startupConfig: any;
|
|
69
|
+
subagentInstructionRef: any;
|
|
70
|
+
subagentNameRef: any;
|
|
71
|
+
submitApiKey: any;
|
|
72
|
+
submitMcpEditor: any;
|
|
73
|
+
submitSubagentEditor: any;
|
|
74
|
+
submitTelegramPair: any;
|
|
75
|
+
submitTelegramToken: any;
|
|
76
|
+
t: any;
|
|
77
|
+
telegramPairError: any;
|
|
78
|
+
telegramPairInputRef: any;
|
|
79
|
+
telegramTokenError: any;
|
|
80
|
+
telegramTokenInputRef: any;
|
|
81
|
+
updateInfo: any;
|
|
82
|
+
walletDisplayInfo: any;
|
|
83
|
+
walletFocusIndex: any;
|
|
84
|
+
walletSettings: any;
|
|
85
|
+
width: any;
|
|
86
|
+
}
|
|
87
|
+
export declare function ModalsLayer(props: ModalsLayerProps): import("react").ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { formatSubagentName } from "../../utils/subagent-display.js";
|
|
3
|
+
import { SubagentEditorModal, SubagentsBrowserModal } from "../agents-modal.js";
|
|
4
|
+
import { CONNECT_CHANNELS } from "../constants.js";
|
|
5
|
+
import { McpBrowserModal, McpEditorModal } from "../mcp-modal.js";
|
|
6
|
+
import { ApiKeyModal } from "../modals/api-key-modal.js";
|
|
7
|
+
import { ConnectModal, TelegramPairModal, TelegramTokenModal } from "../modals/connect-modal.js";
|
|
8
|
+
import { ModelPickerModal } from "../modals/model-picker-modal.js";
|
|
9
|
+
import { SandboxPickerModal } from "../modals/sandbox-picker-modal.js";
|
|
10
|
+
import { SessionPickerModal } from "../modals/session-picker-modal.js";
|
|
11
|
+
import { UpdateModal } from "../modals/update-modal.js";
|
|
12
|
+
import { WalletPickerModal } from "../modals/wallet-picker-modal.js";
|
|
13
|
+
import { ScheduleBrowserModal } from "../schedule-modal.js";
|
|
14
|
+
export function ModalsLayer(props) {
|
|
15
|
+
const { agentRows, agentsEditorDraft, agentsEditorError, agentsEditorField, agentsEditorModelIndex, agentsEditorSyncKey, agentsModalIndex, agentsSearchQuery, apiKeyError, apiKeyInputRef, apiKeyPrompt, bwSync, configuredProviders, connectModalIndex, defaultProvider, disabledModels, disabledProviders, editingMcpId, editingSubagent, filteredModels, height, mcpArgsRef, mcpCommandRef, mcpCwdRef, mcpEditorDraft, mcpEditorError, mcpEditorField, mcpEditorSyncKey, mcpEnvRef, mcpHeadersRef, mcpLabelRef, mcpModalIndex, mcpRows, mcpSearchQuery, mcpUrlRef, model, modelPickerFocus, modelPickerIndex, modelSearchQuery, providerChipIndex, providersWithKey, reasoningEffortByModel, sandboxMode, sandboxSettings, sandboxSettingsEditBuffer, sandboxSettingsEditing, sandboxSettingsFocusIndex, scheduleModalIndex, scheduleRows, scheduleSearchQuery, sessionPickerIndex, sessionPickerList, showAgentsEditor, showAgentsModal, showApiKeyModal, showConnectModal, showMcpEditor, showMcpModal, showModelPicker, showSandboxPicker, showScheduleModal, showSessionPicker, showTelegramPairModal, showTelegramTokenModal, showUpdateModal, showWalletPicker, startupConfig, subagentInstructionRef, subagentNameRef, submitApiKey, submitMcpEditor, submitSubagentEditor, submitTelegramPair, submitTelegramToken, t, telegramPairError, telegramPairInputRef, telegramTokenError, telegramTokenInputRef, updateInfo, walletDisplayInfo, walletFocusIndex, walletSettings, width, } = props;
|
|
16
|
+
return (_jsxs(_Fragment, { children: [showApiKeyModal && (_jsx(ApiKeyModal, { t: t, width: width, height: height, inputRef: apiKeyInputRef, error: apiKeyError, onSubmit: submitApiKey })), showUpdateModal && updateInfo && (_jsx(UpdateModal, { t: t, width: width, height: height, currentVersion: startupConfig.version, latestVersion: updateInfo.latestVersion })), showMcpModal && !showMcpEditor && (_jsx(McpBrowserModal, { t: t, width: width, height: height, selectedIndex: mcpModalIndex, searchQuery: mcpSearchQuery, rows: mcpRows })), showMcpEditor && (_jsx(McpEditorModal, { t: t, width: width, height: height, draft: mcpEditorDraft, focusedField: mcpEditorField, syncKey: mcpEditorSyncKey, error: mcpEditorError, title: editingMcpId ? "Edit MCP Server" : "Add MCP Server", labelRef: mcpLabelRef, urlRef: mcpUrlRef, headersRef: mcpHeadersRef, commandRef: mcpCommandRef, argsRef: mcpArgsRef, cwdRef: mcpCwdRef, envRef: mcpEnvRef, onSubmit: submitMcpEditor })), showScheduleModal && (_jsx(ScheduleBrowserModal, { t: t, width: width, height: height, selectedIndex: scheduleModalIndex, searchQuery: scheduleSearchQuery, rows: scheduleRows })), showAgentsModal && !showAgentsEditor && (_jsx(SubagentsBrowserModal, { t: t, width: width, height: height, selectedIndex: agentsModalIndex, searchQuery: agentsSearchQuery, rows: agentRows })), showAgentsEditor && (_jsx(SubagentEditorModal, { t: t, width: width, height: height, draft: agentsEditorDraft, focusedField: agentsEditorField, modelIndex: agentsEditorModelIndex, error: agentsEditorError, title: editingSubagent ? `Edit sub-agent: ${formatSubagentName(editingSubagent.name)}` : "Add sub-agent", nameRef: subagentNameRef, instructionRef: subagentInstructionRef, onSubmit: submitSubagentEditor, showRemoveHint: !!editingSubagent }, `subagent-editor-${agentsEditorSyncKey}`)), showModelPicker && (_jsx(ModelPickerModal, { t: t, currentModel: model, selectedIndex: modelPickerIndex, width: width, height: height, searchQuery: modelSearchQuery, filteredModels: filteredModels, reasoningEffortByModel: reasoningEffortByModel, configuredProviders: configuredProviders, disabledProviders: disabledProviders, disabledModels: disabledModels, defaultProvider: defaultProvider, focus: modelPickerFocus, providerChipIndex: providerChipIndex, providersWithKey: providersWithKey, apiKeyPrompt: apiKeyPrompt, bwSync: bwSync })), showSessionPicker && (_jsx(SessionPickerModal, { t: t, sessions: sessionPickerList, focusIndex: sessionPickerIndex, width: width, height: height })), showWalletPicker && (_jsx(WalletPickerModal, { t: t, settings: walletSettings, walletInfo: walletDisplayInfo, focusIndex: walletFocusIndex, width: width, height: height })), showSandboxPicker && (_jsx(SandboxPickerModal, { t: t, currentMode: sandboxMode, settings: sandboxSettings, focusIndex: sandboxSettingsFocusIndex, editing: sandboxSettingsEditing, editBuffer: sandboxSettingsEditBuffer, width: width, height: height })), showConnectModal && (_jsx(ConnectModal, { t: t, width: width, height: height, selectedIndex: connectModalIndex, channels: CONNECT_CHANNELS })), showTelegramTokenModal && (_jsx(TelegramTokenModal, { t: t, width: width, height: height, inputRef: telegramTokenInputRef, error: telegramTokenError, onSubmit: submitTelegramToken })), showTelegramPairModal && (_jsx(TelegramPairModal, { t: t, width: width, height: height, inputRef: telegramPairInputRef, error: telegramPairError, onSubmit: () => void submitTelegramPair() }))] }));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=modals-layer.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { Semantic } from "@muonroi/agent-harness-opentui";
|
|
2
3
|
import { bottomAlignedModalTop } from "../utils/modal.js";
|
|
3
4
|
/**
|
|
4
5
|
* Recent-sessions picker. Opened by `/sessions` or `/session`. Selecting a
|
|
@@ -14,15 +15,19 @@ export function SessionPickerModal({ t, sessions, focusIndex, width, height, })
|
|
|
14
15
|
const panelHeight = Math.min(contentHeight, maxH);
|
|
15
16
|
const top = bottomAlignedModalTop(height, panelHeight);
|
|
16
17
|
const overlayBg = "#000000cc";
|
|
17
|
-
return (_jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Resume session" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("scrollbox", { flexGrow: 1, minHeight: 0, children: sessions.length === 0 ? (_jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "No prior sessions in this workspace." }) })) : (sessions.map((s, idx) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
return (_jsx(Semantic, { id: "session-picker", role: "dialog", name: "Resume session", isModal: true, children: _jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Resume session" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("scrollbox", { flexGrow: 1, minHeight: 0, children: sessions.length === 0 ? (_jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "No prior sessions in this workspace." }) })) : (sessions.map((s, idx) => {
|
|
19
|
+
const focused = idx === focusIndex;
|
|
20
|
+
const ts = formatTimestamp(s.updatedAt);
|
|
21
|
+
const titleRaw = s.title?.trim() || "(untitled)";
|
|
22
|
+
const titleMax = Math.max(8, panelWidth - 38);
|
|
23
|
+
const title = titleRaw.length > titleMax ? `${titleRaw.slice(0, titleMax - 1)}…` : titleRaw;
|
|
24
|
+
// Show the FULL session id (not slice(-8)). The resumed-session
|
|
25
|
+
// header displays the full id, so a truncated id here made users
|
|
26
|
+
// think they had resumed a "different" session when it was the
|
|
27
|
+
// same one shown in two formats.
|
|
28
|
+
const idLabel = s.id;
|
|
29
|
+
return (_jsx(Semantic, { id: `session-item-${idx}`, role: "listitem", name: `${title} ${idLabel}`, value: s.id, selected: focused || undefined, children: _jsxs("box", { backgroundColor: focused ? t.selectedBg : undefined, paddingLeft: 2, paddingRight: 2, width: "100%", flexDirection: "row", justifyContent: "space-between", children: [_jsx("text", { fg: focused ? t.selected : t.text, children: `${ts} ${title}` }), _jsx("text", { fg: focused ? t.primary : t.textMuted, children: `${s.model} ${idLabel}` })] }) }, s.id));
|
|
30
|
+
})) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "↑↓ navigate · enter resume (restarts CLI) · esc cancel" }) })] }) }) }));
|
|
26
31
|
}
|
|
27
32
|
/**
|
|
28
33
|
* Compact MM-DD HH:MM timestamp for the picker rows. Trades the year for
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { Semantic } from "@muonroi/agent-harness-opentui";
|
|
2
3
|
import { bottomAlignedModalTop } from "../utils/modal.js";
|
|
3
4
|
export function UpdateModal({ t, width, height, currentVersion, latestVersion, }) {
|
|
4
5
|
const overlayBg = "#000000cc";
|
|
5
6
|
const panelWidth = Math.min(60, width - 6);
|
|
6
7
|
const panelHeight = 9;
|
|
7
8
|
const top = bottomAlignedModalTop(height, panelHeight);
|
|
8
|
-
return (_jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: "#f59e0b", children: _jsx("b", { children: "Update Available" }) }), _jsx("text", { fg: t.textMuted, children: "esc to dismiss" })] }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsxs("text", { fg: t.text, children: ["A new version of muonroi-cli is available: ", _jsxs("span", { style: { fg: t.textMuted }, children: ["v", currentVersion] }), " → ", _jsxs("span", { style: { fg: "#22c55e" }, children: ["v", latestVersion] })] }) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "Press enter to update now, or esc to dismiss" }) })] }) }));
|
|
9
|
+
return (_jsx(Semantic, { id: "update-modal", role: "dialog", name: "Update Available", isModal: true, children: _jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: "#f59e0b", children: _jsx("b", { children: "Update Available" }) }), _jsx("text", { fg: t.textMuted, children: "esc to dismiss" })] }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsxs("text", { fg: t.text, children: ["A new version of muonroi-cli is available: ", _jsxs("span", { style: { fg: t.textMuted }, children: ["v", currentVersion] }), " → ", _jsxs("span", { style: { fg: "#22c55e" }, children: ["v", latestVersion] })] }) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "Press enter to update now, or esc to dismiss" }) })] }) }) }));
|
|
9
10
|
}
|
|
10
11
|
//# sourceMappingURL=update-modal.js.map
|
|
@@ -26,6 +26,7 @@ import "../council-inspect.js";
|
|
|
26
26
|
import "../ideal.js";
|
|
27
27
|
import "../route.js";
|
|
28
28
|
import "../status.js";
|
|
29
|
+
import "../ponytail.js";
|
|
29
30
|
describe("slash menu / registry parity", () => {
|
|
30
31
|
it("every registered slash command has a menu entry", () => {
|
|
31
32
|
const menuIds = new Set(SLASH_MENU_ITEMS.map((m) => m.id));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { handlePonytailSlash } from "../ponytail.js";
|
|
3
|
+
describe("handlePonytailSlash", () => {
|
|
4
|
+
const originalEnv = process.env.MUONROI_PONYTAIL_DISABLE;
|
|
5
|
+
const dummyCtx = {
|
|
6
|
+
cwd: "/",
|
|
7
|
+
tenantId: "test",
|
|
8
|
+
defaultProvider: "openai",
|
|
9
|
+
defaultModel: "gpt-4",
|
|
10
|
+
};
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
if (originalEnv === undefined) {
|
|
13
|
+
delete process.env.MUONROI_PONYTAIL_DISABLE;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
process.env.MUONROI_PONYTAIL_DISABLE = originalEnv;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
it("should enable ponytail mode and modify process.env", async () => {
|
|
20
|
+
process.env.MUONROI_PONYTAIL_DISABLE = "1";
|
|
21
|
+
const response = await handlePonytailSlash(["on"], dummyCtx);
|
|
22
|
+
expect(process.env.MUONROI_PONYTAIL_DISABLE).toBe("0");
|
|
23
|
+
expect(response).toContain("Ponytail Mode enabled");
|
|
24
|
+
});
|
|
25
|
+
it("should disable ponytail mode and modify process.env", async () => {
|
|
26
|
+
process.env.MUONROI_PONYTAIL_DISABLE = "0";
|
|
27
|
+
const response = await handlePonytailSlash(["off"], dummyCtx);
|
|
28
|
+
expect(process.env.MUONROI_PONYTAIL_DISABLE).toBe("1");
|
|
29
|
+
expect(response).toContain("Ponytail Mode disabled");
|
|
30
|
+
});
|
|
31
|
+
it("should return status when no args are provided", async () => {
|
|
32
|
+
process.env.MUONROI_PONYTAIL_DISABLE = "0";
|
|
33
|
+
const response = await handlePonytailSlash([], dummyCtx);
|
|
34
|
+
expect(response).toContain("ON (enabled)");
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=ponytail.test.js.map
|
|
@@ -37,10 +37,10 @@ export const handleCouncilInspectSlash = async (args) => {
|
|
|
37
37
|
}
|
|
38
38
|
// Load all system messages for this session — parameterized query prevents SQL injection (T-17-04)
|
|
39
39
|
const rows = db
|
|
40
|
-
.prepare(`SELECT role, message_json, seq, created_at
|
|
41
|
-
FROM messages
|
|
42
|
-
WHERE session_id = ?
|
|
43
|
-
AND role = 'system'
|
|
40
|
+
.prepare(`SELECT role, message_json, seq, created_at
|
|
41
|
+
FROM messages
|
|
42
|
+
WHERE session_id = ?
|
|
43
|
+
AND role = 'system'
|
|
44
44
|
ORDER BY seq ASC`)
|
|
45
45
|
.all(sessionId);
|
|
46
46
|
if (rows.length === 0) {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as fs from "node:fs";
|
|
20
20
|
import * as path from "node:path";
|
|
21
|
+
import { appendCrashLog } from "../../index.js";
|
|
21
22
|
import { getDatabase } from "../../storage/db.js";
|
|
22
23
|
import { buildChatEntries } from "../../storage/transcript.js";
|
|
23
24
|
import { registerSlash } from "./registry.js";
|
|
@@ -251,7 +252,21 @@ export const handleExportSlash = async (_args, ctx) => {
|
|
|
251
252
|
if (!sessionId) {
|
|
252
253
|
return "No active session. Start a conversation first.";
|
|
253
254
|
}
|
|
254
|
-
|
|
255
|
+
let dbEntries = [];
|
|
256
|
+
try {
|
|
257
|
+
dbEntries = buildChatEntries(sessionId);
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
// A DB read failure here (SQLite busy/locked right after a council turn,
|
|
261
|
+
// schema drift, a corrupt page) used to throw out of this async handler.
|
|
262
|
+
// With no .catch on the dispatchSlash call site that became an
|
|
263
|
+
// unhandledRejection → process.exit(1) → the user kicked out of the TUI.
|
|
264
|
+
// Degrade instead: export the live TUI scrollback + interaction timeline.
|
|
265
|
+
// Logged to crash.log, NOT console (console.error corrupts the OpenTUI
|
|
266
|
+
// framebuffer while the renderer owns the terminal).
|
|
267
|
+
appendCrashLog("EXPORT", `buildChatEntries failed for session ${sessionId}: ${err instanceof Error ? err.stack || err.message : String(err)}`);
|
|
268
|
+
dbEntries = [];
|
|
269
|
+
}
|
|
255
270
|
const liveEntries = ctx.getLiveEntries?.() ?? [];
|
|
256
271
|
const timeline = selectInteractionTimeline(sessionId);
|
|
257
272
|
if (dbEntries.length === 0 && liveEntries.length === 0 && timeline.length === 0) {
|
|
@@ -87,6 +87,7 @@ export const SLASH_MENU_ITEMS = [
|
|
|
87
87
|
{ id: "ee-context-status", label: "ee-context status", description: "Show current BB-context setting", hidden: true },
|
|
88
88
|
{ id: "export", label: "export", description: "Export entire conversation to a .txt file", hidden: true },
|
|
89
89
|
{ id: "status", label: "status", description: "Show Agile sprint progress dashboard", hidden: true },
|
|
90
|
+
{ id: "ponytail", label: "ponytail", description: "Toggle Lazy Senior AI Mode (on/off/status)", hidden: false },
|
|
90
91
|
];
|
|
91
92
|
/** Items shown in the splash autocomplete + /help listing. */
|
|
92
93
|
export const VISIBLE_SLASH_MENU_ITEMS = SLASH_MENU_ITEMS.filter((m) => !m.hidden);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { isPonytailModeEnabled } from "../../pil/config.js";
|
|
2
|
+
import { registerSlash } from "./registry.js";
|
|
3
|
+
export const handlePonytailSlash = async (args, _ctx) => {
|
|
4
|
+
const arg = args[0]?.toLowerCase();
|
|
5
|
+
if (arg === "on") {
|
|
6
|
+
process.env.MUONROI_PONYTAIL_DISABLE = "0";
|
|
7
|
+
return "✅ Ponytail Mode enabled (Lazy Senior mode). The agent will enforce YAGNI and prioritize standard libraries.";
|
|
8
|
+
}
|
|
9
|
+
if (arg === "off") {
|
|
10
|
+
process.env.MUONROI_PONYTAIL_DISABLE = "1";
|
|
11
|
+
return "❌ Ponytail Mode disabled. The agent is free to propose complex architectures and dependencies.";
|
|
12
|
+
}
|
|
13
|
+
// Status check
|
|
14
|
+
const status = isPonytailModeEnabled() ? "ON (enabled)" : "OFF (disabled)";
|
|
15
|
+
return `Ponytail Mode is currently: **${status}**\nUsage: \`/ponytail on\` or \`/ponytail off\``;
|
|
16
|
+
};
|
|
17
|
+
// Self-register on module import
|
|
18
|
+
registerSlash("ponytail", handlePonytailSlash);
|
|
19
|
+
//# sourceMappingURL=ponytail.js.map
|
|
@@ -87,7 +87,7 @@ describe("wireStatusBar", () => {
|
|
|
87
87
|
expect(s.model).toBe("claude-3-5-sonnet-latest");
|
|
88
88
|
off();
|
|
89
89
|
});
|
|
90
|
-
it("threshold event updates
|
|
90
|
+
it("threshold event updates month_usd (not session_usd)", () => {
|
|
91
91
|
const off = wireStatusBar();
|
|
92
92
|
thresholdCallback({
|
|
93
93
|
level: 80,
|
|
@@ -97,8 +97,8 @@ describe("wireStatusBar", () => {
|
|
|
97
97
|
atMs: 1,
|
|
98
98
|
});
|
|
99
99
|
const s = statusBarStore.getState();
|
|
100
|
-
expect(s.session_usd).toBe(12.5);
|
|
101
100
|
expect(s.month_usd).toBe(12.5);
|
|
101
|
+
expect(s.session_usd).toBe(0); // orchestrator owns session_usd, not thresholds
|
|
102
102
|
off();
|
|
103
103
|
});
|
|
104
104
|
it("downgrade event updates model", () => {
|
package/dist/src/ui/types.d.ts
CHANGED
|
@@ -69,6 +69,13 @@ export interface AppProps {
|
|
|
69
69
|
startupConfig: AppStartupConfig;
|
|
70
70
|
initialMessage?: string;
|
|
71
71
|
onExit?: () => void;
|
|
72
|
+
/**
|
|
73
|
+
* Restart the CLI bound to a different session id (used by the /sessions
|
|
74
|
+
* picker). Routes through the same terminal teardown as onExit and supervises
|
|
75
|
+
* the child process, so resuming never strands the user at a corrupted shell
|
|
76
|
+
* prompt.
|
|
77
|
+
*/
|
|
78
|
+
onRelaunch?: (sessionId: string) => void;
|
|
72
79
|
}
|
|
73
80
|
export interface ActiveTurnState {
|
|
74
81
|
kind: "local" | "telegram";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import "./slash/route.js";
|
|
2
|
+
import "./slash/optimize.js";
|
|
3
|
+
import "./slash/discuss.js";
|
|
4
|
+
import "./slash/plan.js";
|
|
5
|
+
import "./slash/execute.js";
|
|
6
|
+
import "./slash/compact.js";
|
|
7
|
+
import "./slash/expand.js";
|
|
8
|
+
import "./slash/clear.js";
|
|
9
|
+
import "./slash/pin.js";
|
|
10
|
+
import "./slash/cost.js";
|
|
11
|
+
import "./slash/ee.js";
|
|
12
|
+
import "./slash/debug.js";
|
|
13
|
+
import "./slash/council.js";
|
|
14
|
+
import "./slash/ideal.js";
|
|
15
|
+
import "./slash/export.js";
|
|
16
|
+
import "./slash/status.js";
|
|
17
|
+
import "./slash/ponytail.js";
|
|
18
|
+
export type { AppStartupConfig } from "./types.js";
|
|
19
|
+
export interface AppLogicProps {
|
|
20
|
+
agent: any;
|
|
21
|
+
startupConfig: any;
|
|
22
|
+
initialMessage?: any;
|
|
23
|
+
onExit: any;
|
|
24
|
+
onRelaunch: any;
|
|
25
|
+
}
|
|
26
|
+
export declare function useAppLogic(props: AppLogicProps): any;
|
|
Binary file
|
|
@@ -27,6 +27,23 @@ export interface RelaunchOptions {
|
|
|
27
27
|
onExit?: (code: number) => void;
|
|
28
28
|
/** Injected spawn for tests. Defaults to the real node:child_process spawn. */
|
|
29
29
|
spawnFn?: typeof spawn;
|
|
30
|
+
/**
|
|
31
|
+
* Run immediately before the spawn — used to tear down the current TUI
|
|
32
|
+
* (renderer.destroy, restore raw mode / mouse tracking / alt-screen) so the
|
|
33
|
+
* child inherits a CLEAN terminal. Without this the child (and the shell, if
|
|
34
|
+
* the parent exits) inherit a terminal still in mouse-tracking/alt-screen
|
|
35
|
+
* mode, and stray escape bytes get parsed by the shell as a command
|
|
36
|
+
* ("'…' is not recognized as an internal or external command").
|
|
37
|
+
*/
|
|
38
|
+
beforeSpawn?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* When true, the parent stays alive and supervises the child: it exits with
|
|
41
|
+
* the child's exit code instead of exiting the instant the child spawns.
|
|
42
|
+
* This keeps any intermediate launcher (a `bun run` wrapper, the bun bin
|
|
43
|
+
* shim) alive so the shell does NOT regain the terminal foreground while the
|
|
44
|
+
* child is running. Required for a correct in-terminal restart on Windows.
|
|
45
|
+
*/
|
|
46
|
+
supervise?: boolean;
|
|
30
47
|
}
|
|
31
48
|
/**
|
|
32
49
|
* Spawn a fresh CLI process bound to {sessionId} and exit the current one.
|