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
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ModelMessage } from "ai";
|
|
2
2
|
import { type ProviderId } from "../providers/types.js";
|
|
3
3
|
import { type ScheduleDaemonStatus, type StoredSchedule } from "../tools/schedule.js";
|
|
4
|
-
import type { AgentMode, ChatEntry, SessionInfo, SessionSnapshot, StreamChunk, SubagentStatus, TaskRequest, ToolResult, VerifyRecipe } from "../types/index.js";
|
|
4
|
+
import type { AgentMode, ChatEntry, SessionInfo, SessionSnapshot, StreamChunk, SubagentStatus, TaskListSnapshot, TaskRequest, ToolResult, VerifyRecipe } from "../types/index.js";
|
|
5
5
|
import { type SandboxMode, type SandboxSettings } from "../utils/settings.js";
|
|
6
6
|
import { type SideQuestionResult } from "../utils/side-question.js";
|
|
7
7
|
import { type AgentOptions, type ProcessMessageObserver } from "./agent-options.js";
|
|
8
|
+
import type { SafetyOverrideAskInfo, SafetyOverrideVerdict } from "./safety-askcard.js";
|
|
8
9
|
import type { ToolLoopCapAsk } from "./tool-loop-cap.js";
|
|
9
10
|
export declare class Agent {
|
|
10
11
|
private provider;
|
|
@@ -111,7 +112,7 @@ export declare class Agent {
|
|
|
111
112
|
setModel(model: string): void;
|
|
112
113
|
getMode(): AgentMode;
|
|
113
114
|
getSandboxMode(): SandboxMode;
|
|
114
|
-
setSandboxMode(
|
|
115
|
+
setSandboxMode(_mode: SandboxMode): void;
|
|
115
116
|
getSandboxSettings(): SandboxSettings;
|
|
116
117
|
setSandboxSettings(settings: SandboxSettings): void;
|
|
117
118
|
setMode(mode: AgentMode): void;
|
|
@@ -140,6 +141,8 @@ export declare class Agent {
|
|
|
140
141
|
cleanup(): Promise<void>;
|
|
141
142
|
private _toolLoopCapHandler;
|
|
142
143
|
setToolLoopCapHandler(fn: ToolLoopCapAsk | null): void;
|
|
144
|
+
private _safetyOverrideHandler;
|
|
145
|
+
setSafetyOverrideHandler(fn: ((block: SafetyOverrideAskInfo) => Promise<SafetyOverrideVerdict>) | null): void;
|
|
143
146
|
respondToToolApproval(approvalId: string, approved: boolean): void;
|
|
144
147
|
clearHistory(): Promise<void>;
|
|
145
148
|
startNewSession(): SessionSnapshot | null;
|
|
@@ -161,6 +164,7 @@ export declare class Agent {
|
|
|
161
164
|
unpinMessageBySeq(seq: number): boolean;
|
|
162
165
|
getPinnedSeqs(): number[];
|
|
163
166
|
getChatEntries(): ChatEntry[];
|
|
167
|
+
getLastTodoSnapshot(): TaskListSnapshot | null;
|
|
164
168
|
getSessionSnapshot(): SessionSnapshot | null;
|
|
165
169
|
onSubagentStatus(listener: (status: SubagentStatus | null) => void): () => void;
|
|
166
170
|
private emitSubagentStatus;
|
|
@@ -183,6 +187,7 @@ export declare class Agent {
|
|
|
183
187
|
private runDelegation;
|
|
184
188
|
private readDelegation;
|
|
185
189
|
private listDelegations;
|
|
190
|
+
private killDelegation;
|
|
186
191
|
private getCompactionSettings;
|
|
187
192
|
private _resolveCompactModel;
|
|
188
193
|
private _resolveModelForTask;
|
|
@@ -225,6 +230,7 @@ export declare class Agent {
|
|
|
225
230
|
* allocation cost is negligible against the batch polling spend.
|
|
226
231
|
*/
|
|
227
232
|
private _buildBatchTurnRunnerDeps;
|
|
233
|
+
private appendMidTurnMessages;
|
|
228
234
|
private appendCompletedTurn;
|
|
229
235
|
private fireHook;
|
|
230
236
|
processMessage(userMessage: string, observer?: ProcessMessageObserver, images?: Array<{
|
|
@@ -14,22 +14,24 @@ import { apiBaseFor } from "../providers/endpoints.js";
|
|
|
14
14
|
import { loadKeyForProvider } from "../providers/keychain.js";
|
|
15
15
|
import { createProviderFactory, createProviderFactoryAsync, detectProviderForModel, requireRuntimeProvider, resolveModelRuntime as resolveRuntime, } from "../providers/runtime.js";
|
|
16
16
|
import { ALL_PROVIDER_IDS } from "../providers/types.js";
|
|
17
|
-
import { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getNextMessageSequence, getSessionTotalTokens, loadTranscript, loadTranscriptState, logInteraction, markMessageCompleted, recordUsageEvent, SessionStore, } from "../storage/index.js";
|
|
17
|
+
import { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastTodoWriteArgs, getNextMessageSequence, getSessionTotalTokens, loadTranscript, loadTranscriptState, logInteraction, markMessageCompleted, recordUsageEvent, SessionStore, } from "../storage/index.js";
|
|
18
18
|
import { BashTool } from "../tools/bash.js";
|
|
19
19
|
import { createBuiltinTools } from "../tools/registry.js";
|
|
20
20
|
import { ScheduleManager } from "../tools/schedule.js";
|
|
21
|
+
import { snapshotFromTodoWriteArgs } from "../tools/todo-write-snapshot.js";
|
|
21
22
|
import { statusBarStore } from "../ui/status-bar/store.js";
|
|
22
23
|
import { appendCostLog } from "../usage/cost-log.js";
|
|
23
24
|
import { appendDecisionLog } from "../usage/decision-log.js";
|
|
24
|
-
import { projectCostUSD } from "../usage/estimator.js";
|
|
25
|
+
import { projectCostUSD, sanitizeInputTokens } from "../usage/estimator.js";
|
|
25
26
|
import { getAutoCompactThresholdPct, getCouncilRounds, getCurrentModel, getCurrentShellSettings, getModeSpecificModel, getRoleModel, getRoleModels, isAutoCompactAfterTurnEnabled, isCouncilMultiProviderPreferred, isProviderDisabled, } from "../utils/settings.js";
|
|
26
27
|
import { runSideQuestion } from "../utils/side-question.js";
|
|
27
28
|
import { buildVerifyDetectPrompt, normalizeVerifyRecipe } from "../verify/entrypoint.js";
|
|
28
29
|
import { runVerifyOrchestration } from "../verify/orchestrator.js";
|
|
29
30
|
import { COUNCIL_COLOR_BG, COUNCIL_COLOR_RESET, COUNCIL_ROLE_COLORS, } from "./agent-options.js";
|
|
31
|
+
import { AUTO_COMMIT_ATTRIBUTION, isAutoCommitEnabled, maybeAutoCommitTurn, snapshotDirtyPaths, } from "./auto-commit.js";
|
|
30
32
|
import { BatchTurnRunner } from "./batch-turn-runner.js";
|
|
31
33
|
import { accumulateUsage, buildAssistantBatchMessage, buildBatchChatCompletionRequest, buildBatchName, buildToolBatchMessage, extractJsonObject, getBatchUsage, hasUsage, parseToolArgumentsOrRaw, toLocalToolCall, } from "./batch-utils.js";
|
|
32
|
-
import { createCompactionSummaryMessage, DEFAULT_KEEP_RECENT_TOKENS, DEFAULT_RESERVE_TOKENS, estimateConversationTokens, extractUserContent, generateCompactionSummary, POST_TURN_MIN_TOKENS, prepareCompaction, shouldCompactContext, } from "./compaction.js";
|
|
34
|
+
import { createCompactionSummaryMessage, DEFAULT_KEEP_RECENT_TOKENS, DEFAULT_RESERVE_TOKENS, estimateConversationTokens, extractUserContent, generateCompactionSummary, POST_TURN_MIN_TOKENS, prepareCompaction, proposeCompaction, shouldCompactContext, } from "./compaction.js";
|
|
33
35
|
import { CouncilManager } from "./council-manager.js";
|
|
34
36
|
import { CrossTurnDedup, isCrossTurnDedupEnabled } from "./cross-turn-dedup.js";
|
|
35
37
|
import { DelegationManager } from "./delegations.js";
|
|
@@ -105,6 +107,7 @@ function createTools(_bash, _provider, _mode, _opts) {
|
|
|
105
107
|
runDelegation: _opts?.runDelegation,
|
|
106
108
|
readDelegation: _opts?.readDelegation,
|
|
107
109
|
listDelegations: _opts?.listDelegations,
|
|
110
|
+
killDelegation: _opts?.killDelegation,
|
|
108
111
|
modelId: _opts?.modelId,
|
|
109
112
|
});
|
|
110
113
|
}
|
|
@@ -355,10 +358,12 @@ export class Agent {
|
|
|
355
358
|
return this.mode;
|
|
356
359
|
}
|
|
357
360
|
getSandboxMode() {
|
|
361
|
+
// Sandbox has been removed; BashTool.getSandboxMode() always returns "off".
|
|
358
362
|
return this.bash.getSandboxMode();
|
|
359
363
|
}
|
|
360
|
-
setSandboxMode(
|
|
361
|
-
|
|
364
|
+
setSandboxMode(_mode) {
|
|
365
|
+
// No-op: sandbox has been removed. BashTool no longer has a mutable sandbox mode.
|
|
366
|
+
// Will be re-implemented when the new sandbox is ready.
|
|
362
367
|
}
|
|
363
368
|
getSandboxSettings() {
|
|
364
369
|
return this.bash.getSandboxSettings();
|
|
@@ -516,6 +521,15 @@ export class Agent {
|
|
|
516
521
|
setToolLoopCapHandler(fn) {
|
|
517
522
|
this._toolLoopCapHandler = fn;
|
|
518
523
|
}
|
|
524
|
+
// Safety-override handler — set by the UI (app.tsx) at startup. Invoked
|
|
525
|
+
// from the message-processor tool-result pipeline when a safety block
|
|
526
|
+
// (catastrophic, dangerous, git-safety, empty-bash) is detected. The UI
|
|
527
|
+
// surfaces an askcard ("Allow once / Allow session / Block") and resolves
|
|
528
|
+
// with the verdict. When unset, blocks pass through as normal errors.
|
|
529
|
+
_safetyOverrideHandler = null;
|
|
530
|
+
setSafetyOverrideHandler(fn) {
|
|
531
|
+
this._safetyOverrideHandler = fn;
|
|
532
|
+
}
|
|
519
533
|
respondToToolApproval(approvalId, approved) {
|
|
520
534
|
const toolApprovalResponse = {
|
|
521
535
|
role: "tool",
|
|
@@ -640,6 +654,14 @@ export class Agent {
|
|
|
640
654
|
return [];
|
|
641
655
|
return buildChatEntries(this.session.id);
|
|
642
656
|
}
|
|
657
|
+
getLastTodoSnapshot() {
|
|
658
|
+
if (!this.session)
|
|
659
|
+
return null;
|
|
660
|
+
const argsJson = getLastTodoWriteArgs(this.session.id);
|
|
661
|
+
if (!argsJson)
|
|
662
|
+
return null;
|
|
663
|
+
return snapshotFromTodoWriteArgs(argsJson);
|
|
664
|
+
}
|
|
643
665
|
getSessionSnapshot() {
|
|
644
666
|
if (!this.session || !this.workspace)
|
|
645
667
|
return null;
|
|
@@ -765,6 +787,10 @@ export class Agent {
|
|
|
765
787
|
// where orchestrator/task/title traffic is actually spending.
|
|
766
788
|
// Best-effort: failures inside appendCostLog are swallowed (see cost-log.ts).
|
|
767
789
|
const breakdown = source === "message" ? (this._lastPromptBreakdown ?? undefined) : undefined;
|
|
790
|
+
// Sanitize actualInputTokens for providers (e.g. SiliconFlow) that return
|
|
791
|
+
// implausibly low prompt_tokens (e.g. 10) regardless of prompt size.
|
|
792
|
+
const estIn = breakdown ? Math.ceil(((breakdown.systemChars ?? 0) + (breakdown.messagesChars ?? 0)) / 4) : 0;
|
|
793
|
+
const actualInput = sanitizeInputTokens(totalInput, estIn);
|
|
768
794
|
appendCostLog({
|
|
769
795
|
ts: Date.now(),
|
|
770
796
|
provider: this.providerId,
|
|
@@ -772,7 +798,7 @@ export class Agent {
|
|
|
772
798
|
estimatedUsd: turnCostMicros / 1_000_000,
|
|
773
799
|
callsite: `orchestrator.${source}`,
|
|
774
800
|
phase: source,
|
|
775
|
-
actualInputTokens:
|
|
801
|
+
actualInputTokens: actualInput,
|
|
776
802
|
actualOutputTokens: output,
|
|
777
803
|
cachedInputTokens: cacheRead,
|
|
778
804
|
systemChars: breakdown?.systemChars,
|
|
@@ -1162,15 +1188,29 @@ export class Agent {
|
|
|
1162
1188
|
};
|
|
1163
1189
|
}
|
|
1164
1190
|
}
|
|
1191
|
+
async killDelegation(id) {
|
|
1192
|
+
try {
|
|
1193
|
+
return await this.delegations.kill(id);
|
|
1194
|
+
}
|
|
1195
|
+
catch (err) {
|
|
1196
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1197
|
+
return {
|
|
1198
|
+
success: false,
|
|
1199
|
+
output: `Failed to terminate delegation: ${msg}`,
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1165
1203
|
getCompactionSettings(contextWindow) {
|
|
1166
1204
|
let keepRecentTokens = DEFAULT_KEEP_RECENT_TOKENS;
|
|
1167
1205
|
// For models with very large context windows, keep more recent tokens
|
|
1168
1206
|
if (contextWindow && contextWindow > 200_000) {
|
|
1169
1207
|
keepRecentTokens = Math.min(100_000, Math.max(20_000, Math.floor(contextWindow * 0.1)));
|
|
1170
1208
|
}
|
|
1171
|
-
//
|
|
1209
|
+
// For long sessions, reduce keepRecentTokens slightly to slow context growth
|
|
1210
|
+
// (0.85 instead of old 0.75 — session bf58d0f46b51 showed 0.75 created a
|
|
1211
|
+
// tight compact-loop: keep 15K → add 50K tool results → re-compact immediately).
|
|
1172
1212
|
if (this._compactionStats.count >= 2) {
|
|
1173
|
-
keepRecentTokens = Math.floor(keepRecentTokens * 0.
|
|
1213
|
+
keepRecentTokens = Math.floor(keepRecentTokens * 0.85);
|
|
1174
1214
|
}
|
|
1175
1215
|
return {
|
|
1176
1216
|
reserveTokens: Math.max(this.maxTokens, DEFAULT_RESERVE_TOKENS),
|
|
@@ -1186,12 +1226,28 @@ export class Agent {
|
|
|
1186
1226
|
async compactForContext(provider, system, contextWindow, signal, settings = this.getCompactionSettings(contextWindow), force = false) {
|
|
1187
1227
|
if (!this.session)
|
|
1188
1228
|
return false;
|
|
1229
|
+
// Phase 1: ask the compaction proposer model whether to compact and what to keep/drop.
|
|
1230
|
+
// Only compact if the model says yes. On error/skip, fall back to heuristic.
|
|
1231
|
+
const compactModelId = this._resolveCompactModel();
|
|
1232
|
+
const proposal = await proposeCompaction(provider, compactModelId, this.messages, signal);
|
|
1233
|
+
if (proposal !== null) {
|
|
1234
|
+
// Model decided — compact only if model says shouldCompact
|
|
1235
|
+
if (force) {
|
|
1236
|
+
// force always proceeds; the proposer's actions still guide what to keep/drop
|
|
1237
|
+
}
|
|
1238
|
+
else if (!proposal.shouldCompact) {
|
|
1239
|
+
return false;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
else {
|
|
1243
|
+
// Proposer unavailable — fall back to heuristic token-threshold check
|
|
1244
|
+
if (!force && !shouldCompactContext(estimateConversationTokens(system, this.messages), contextWindow, settings)) {
|
|
1245
|
+
return false;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1189
1248
|
const preparation = prepareCompaction(this.messages, system, settings);
|
|
1190
1249
|
if (!preparation)
|
|
1191
1250
|
return false;
|
|
1192
|
-
if (!force && !shouldCompactContext(preparation.tokensBefore, contextWindow, settings)) {
|
|
1193
|
-
return false;
|
|
1194
|
-
}
|
|
1195
1251
|
const trigger = force ? "manual" : "auto";
|
|
1196
1252
|
// Fire-and-forget: notify EE of stale suggestions before compaction
|
|
1197
1253
|
const { surfacedIds, timestamp } = getLastSurfacedState();
|
|
@@ -1219,7 +1275,6 @@ export class Agent {
|
|
|
1219
1275
|
await this.fireHook(preCompactInput, signal).catch(() => { });
|
|
1220
1276
|
const keptSeqs = this.messageSeqs.slice(preparation.firstKeptIndex);
|
|
1221
1277
|
const firstKeptSeq = keptSeqs.find((seq) => seq !== null) ?? getNextMessageSequence(this.session.id);
|
|
1222
|
-
const compactModelId = this._resolveCompactModel();
|
|
1223
1278
|
const compactStartedAt = Date.now();
|
|
1224
1279
|
const { summary, usage: compactUsage } = await generateCompactionSummary(provider, compactModelId, preparation, undefined, signal);
|
|
1225
1280
|
// Record compaction call in cost-log — bypasses recordUsage because
|
|
@@ -1285,11 +1340,15 @@ export class Agent {
|
|
|
1285
1340
|
.catch(() => { });
|
|
1286
1341
|
// Mark as surfaced for prompt-stale reconciliation (per plan Phase 1).
|
|
1287
1342
|
updateLastSurfacedState([`compact-checkpoint-${this._compactionStats.count + 1}`]);
|
|
1288
|
-
// Track compaction stats —
|
|
1343
|
+
// Track compaction stats — report the GROSS context reduction, NOT net-after-compact-cost.
|
|
1344
|
+
// Rationale: the compaction call's own prompt/completion tokens ARE already counted in
|
|
1345
|
+
// in_tokens/out_tokens/session_usd (updateStatusBar at line 986). Subtracting them here
|
|
1346
|
+
// would double-penalize: the user sees the real cost in the token counter AND sees
|
|
1347
|
+
// "0 saved" because compactCost >= grossSaved (the compact prompt is the full conversation).
|
|
1348
|
+
// grossSaved tells the user how many context tokens were reclaimed — a real benefit that
|
|
1349
|
+
// reduces subsequent turn costs.
|
|
1289
1350
|
const tokensAfter = estimateConversationTokens(system, this.messages);
|
|
1290
|
-
const
|
|
1291
|
-
const compactCost = compactUsage.promptTokens + compactUsage.completionTokens;
|
|
1292
|
-
const saved = Math.max(0, grossSaved - compactCost);
|
|
1351
|
+
const saved = Math.max(0, preparation.tokensBefore - tokensAfter);
|
|
1293
1352
|
const pct = preparation.tokensBefore > 0 ? ((saved / preparation.tokensBefore) * 100).toFixed(1) : "0.0";
|
|
1294
1353
|
this._compactionStats.count++;
|
|
1295
1354
|
this._compactionStats.totalSaved += saved;
|
|
@@ -1317,8 +1376,6 @@ export class Agent {
|
|
|
1317
1376
|
tokensBefore: preparation.tokensBefore,
|
|
1318
1377
|
tokensAfter,
|
|
1319
1378
|
saved,
|
|
1320
|
-
grossSaved,
|
|
1321
|
-
compactCost,
|
|
1322
1379
|
pct,
|
|
1323
1380
|
isLongSession,
|
|
1324
1381
|
},
|
|
@@ -1383,23 +1440,67 @@ export class Agent {
|
|
|
1383
1440
|
const councilStats = { calls: 0, startMs: Date.now(), phases: [] };
|
|
1384
1441
|
const llm = createCouncilLLM(this.bash, this.mode, this.session?.id, councilStats);
|
|
1385
1442
|
const processMessageFn = (message) => this.processMessage(message, options?.observer);
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1443
|
+
// Ensure a turn-scoped AbortController exists so Esc → agent.abort() →
|
|
1444
|
+
// this.abortController.abort() actually cancels the council. Two entry points
|
|
1445
|
+
// reach here: the auto-council path runs INSIDE processMessage, which already
|
|
1446
|
+
// set this.abortController; the /council SLASH path calls runCouncilV2
|
|
1447
|
+
// directly with NONE set — so before this guard, pressing Esc during an
|
|
1448
|
+
// explicit /council run was a no-op (abort() hit a null controller) and the
|
|
1449
|
+
// multi-minute debate ran to completion regardless. Create one when absent
|
|
1450
|
+
// so the user-abort signal threads into every council generate/debate/
|
|
1451
|
+
// research call for BOTH entry points. Only tear down a controller we own.
|
|
1452
|
+
const ownsController = !this.abortController;
|
|
1453
|
+
if (ownsController) {
|
|
1454
|
+
this.abortController = new AbortController();
|
|
1455
|
+
}
|
|
1456
|
+
const signal = this.abortController?.signal;
|
|
1457
|
+
// B1: Resolve a run directory so runCouncil persists decisions.lock.md after
|
|
1458
|
+
// synthesis. The auto-council/sprint paths get a runDir from their own flow
|
|
1459
|
+
// wiring, but the explicit /council SLASH path never did — so its outcome was
|
|
1460
|
+
// never written to disk (no audit trail, nothing for a later /ideal to read).
|
|
1461
|
+
// Reuse the session's active flow run; create one if the session never booted
|
|
1462
|
+
// a flow. Fail-open: a runDir-resolution error must not block the council.
|
|
1463
|
+
let runDir;
|
|
1464
|
+
try {
|
|
1465
|
+
const nodePath = await import("node:path");
|
|
1466
|
+
const flowDir = await ensureFlowDir(this.bash.getCwd());
|
|
1467
|
+
let runId = this._activeRunId ?? (await getActiveRunId(flowDir));
|
|
1468
|
+
if (!runId) {
|
|
1469
|
+
runId = (await createRun(flowDir)).id;
|
|
1470
|
+
await setActiveRunId(flowDir, runId);
|
|
1471
|
+
this._activeRunId = runId;
|
|
1472
|
+
}
|
|
1473
|
+
runDir = nodePath.join(flowDir, "runs", runId);
|
|
1474
|
+
}
|
|
1475
|
+
catch (err) {
|
|
1476
|
+
console.error(`[council] runDir resolution failed (decisions.lock will be skipped): ${err?.message}`);
|
|
1477
|
+
}
|
|
1478
|
+
try {
|
|
1479
|
+
const gen = runCouncil(topic, this.modelId, this.messages, this.session?.id, llm, this.councilManager.createQuestionResponder(), this.councilManager.createPreflightResponder(), processMessageFn, {
|
|
1480
|
+
skipClarification: options?.skipClarification,
|
|
1481
|
+
userModelMessage: options?.userModelMessage,
|
|
1482
|
+
cwd: this.bash.getCwd(),
|
|
1483
|
+
councilStats, // NEW — share orchestrator's stats object with runCouncil (Phase 14 CQ-01)
|
|
1484
|
+
signal,
|
|
1485
|
+
runDir, // B1 — persist decisions.lock.md for the /council slash path
|
|
1486
|
+
});
|
|
1487
|
+
let result;
|
|
1488
|
+
do {
|
|
1489
|
+
result = await gen.next();
|
|
1490
|
+
if (!result.done && result.value) {
|
|
1491
|
+
yield result.value;
|
|
1492
|
+
}
|
|
1493
|
+
} while (!result.done);
|
|
1494
|
+
const synthesis = result.value;
|
|
1495
|
+
this.councilManager.setLastSynthesis(synthesis);
|
|
1496
|
+
if (options?.userModelMessage && synthesis) {
|
|
1497
|
+
this.appendCompletedTurn(options.userModelMessage, [{ role: "assistant", content: synthesis }]);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
finally {
|
|
1501
|
+
if (ownsController && this.abortController?.signal === signal) {
|
|
1502
|
+
this.abortController = null;
|
|
1397
1503
|
}
|
|
1398
|
-
} while (!result.done);
|
|
1399
|
-
const synthesis = result.value;
|
|
1400
|
-
this.councilManager.setLastSynthesis(synthesis);
|
|
1401
|
-
if (options?.userModelMessage && synthesis) {
|
|
1402
|
-
this.appendCompletedTurn(options.userModelMessage, [{ role: "assistant", content: synthesis }]);
|
|
1403
1504
|
}
|
|
1404
1505
|
}
|
|
1405
1506
|
// ========================================================================
|
|
@@ -1930,12 +2031,27 @@ export class Agent {
|
|
|
1930
2031
|
runDelegation: (request, signal) => self.runDelegation(request, signal),
|
|
1931
2032
|
readDelegation: (id) => self.readDelegation(id),
|
|
1932
2033
|
listDelegations: () => self.listDelegations(),
|
|
2034
|
+
killDelegation: (id) => self.killDelegation(id),
|
|
1933
2035
|
executeBatchToolCall: (tools, toolCall, messages, signal) => self.executeBatchToolCall(tools, toolCall, messages, signal),
|
|
1934
2036
|
appendCompletedTurn: (user, asst) => self.appendCompletedTurn(user, asst),
|
|
1935
2037
|
discardAbortedTurn: (user) => self.discardAbortedTurn(user),
|
|
1936
2038
|
recordUsage: (usage, source, model, shape) => self.recordUsage(usage, source, model, shape),
|
|
1937
2039
|
};
|
|
1938
2040
|
}
|
|
2041
|
+
appendMidTurnMessages(newMessages) {
|
|
2042
|
+
if (newMessages.length === 0)
|
|
2043
|
+
return;
|
|
2044
|
+
if (!this.sessionStore || !this.session) {
|
|
2045
|
+
this.messages.push(...newMessages);
|
|
2046
|
+
this.messageSeqs.push(...newMessages.map(() => null));
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
const insertedSeqs = appendMessages(this.session.id, newMessages);
|
|
2050
|
+
this.messages.push(...newMessages);
|
|
2051
|
+
this.messageSeqs.push(...insertedSeqs);
|
|
2052
|
+
this.sessionStore.touchSession(this.session.id, this.bash.getCwd());
|
|
2053
|
+
this.session = this.sessionStore.getRequiredSession(this.session.id);
|
|
2054
|
+
}
|
|
1939
2055
|
appendCompletedTurn(userMessage, newMessages) {
|
|
1940
2056
|
if (newMessages.length === 0)
|
|
1941
2057
|
return;
|
|
@@ -1987,7 +2103,28 @@ export class Agent {
|
|
|
1987
2103
|
// ========================================================================
|
|
1988
2104
|
async *processMessage(userMessage, observer, images) {
|
|
1989
2105
|
const processor = new MessageProcessor(this._buildMessageProcessorDeps());
|
|
2106
|
+
// Deterministic "task done -> commit" (auto-commit): snapshot the dirty set
|
|
2107
|
+
// before the turn so we can commit ONLY the files the agent changes during it
|
|
2108
|
+
// (and never the user's pre-existing work-in-progress). Gated off under tests
|
|
2109
|
+
// and via MUONROI_AUTO_COMMIT=0.
|
|
2110
|
+
const autoCommitOn = isAutoCommitEnabled();
|
|
2111
|
+
const cwd = this.bash.getCwd();
|
|
2112
|
+
const dirtyBefore = autoCommitOn ? await snapshotDirtyPaths(cwd) : new Set();
|
|
1990
2113
|
yield* processor.run(userMessage, observer, images);
|
|
2114
|
+
// Reached only when the turn completed normally (an abort/throw propagates
|
|
2115
|
+
// through yield* and skips this) — exactly when committing is appropriate.
|
|
2116
|
+
if (autoCommitOn) {
|
|
2117
|
+
const auto = await maybeAutoCommitTurn({ cwd, dirtyBefore, userMessage }).catch((err) => {
|
|
2118
|
+
console.error(`[auto-commit] unexpected failure: ${err?.message}`);
|
|
2119
|
+
return { committed: false };
|
|
2120
|
+
});
|
|
2121
|
+
if (auto.committed) {
|
|
2122
|
+
yield {
|
|
2123
|
+
type: "content",
|
|
2124
|
+
content: `\n✓ Auto-committed ${auto.fileCount} file(s) → ${auto.sha} (${AUTO_COMMIT_ATTRIBUTION})\n`,
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
1991
2128
|
}
|
|
1992
2129
|
/**
|
|
1993
2130
|
* Build the DI surface MessageProcessor (Phase 12.4) needs to reach back
|
|
@@ -2133,7 +2270,9 @@ export class Agent {
|
|
|
2133
2270
|
runDelegation: (request, signal) => self.runDelegation(request, signal),
|
|
2134
2271
|
readDelegation: (id) => self.readDelegation(id),
|
|
2135
2272
|
listDelegations: () => self.listDelegations(),
|
|
2273
|
+
killDelegation: (id) => self.killDelegation(id),
|
|
2136
2274
|
drainSteerMessages: () => self.steerDrain?.() ?? [],
|
|
2275
|
+
appendMidTurnMessages: (msgs) => self.appendMidTurnMessages(msgs),
|
|
2137
2276
|
appendCompletedTurn: (user, asst) => self.appendCompletedTurn(user, asst),
|
|
2138
2277
|
discardAbortedTurn: (user) => self.discardAbortedTurn(user),
|
|
2139
2278
|
recordUsage: (usage, source, model, shape) => self.recordUsage(usage, source, model, shape),
|
|
@@ -2150,6 +2289,20 @@ export class Agent {
|
|
|
2150
2289
|
return "stop";
|
|
2151
2290
|
}
|
|
2152
2291
|
},
|
|
2292
|
+
askSafetyOverride: async (info) => {
|
|
2293
|
+
const h = self._safetyOverrideHandler;
|
|
2294
|
+
if (!h) {
|
|
2295
|
+
console.warn(`[Agent] askSafetyOverride called but no handler registered — blocking ${info.kind}: ${info.reason}`);
|
|
2296
|
+
return { action: "block" };
|
|
2297
|
+
}
|
|
2298
|
+
try {
|
|
2299
|
+
return await h(info);
|
|
2300
|
+
}
|
|
2301
|
+
catch (err) {
|
|
2302
|
+
console.error(`[Agent] askSafetyOverride crashed: ${err?.message ?? err}`);
|
|
2303
|
+
return { action: "block" };
|
|
2304
|
+
}
|
|
2305
|
+
},
|
|
2153
2306
|
runCouncilV2: (msg, opts) => self.runCouncilV2(msg, opts),
|
|
2154
2307
|
processMessage: (msg, obs, imgs) => self.processMessage(msg, obs, imgs),
|
|
2155
2308
|
processMessageBatchTurn: (args) => self.processMessageBatchTurn(args),
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { runPipeline } from "../pil/pipeline.js";
|
|
2
|
+
import type { StreamChunk } from "../types/index.js";
|
|
3
|
+
import type { MessageProcessorDeps } from "./message-processor.js";
|
|
4
|
+
import { type ComplexitySize } from "./scope-ceiling.js";
|
|
5
|
+
export interface PreprocessorResult {
|
|
6
|
+
pilCtx: Awaited<ReturnType<typeof runPipeline>>;
|
|
7
|
+
_stepCeiling: number;
|
|
8
|
+
_pilStart: number;
|
|
9
|
+
_naturalCeiling: number;
|
|
10
|
+
_ceilingTaskType: string;
|
|
11
|
+
_ceilingSize: ComplexitySize;
|
|
12
|
+
}
|
|
13
|
+
export declare function prepareTurnContext(deps: MessageProcessorDeps, userMessage: string, _budgetOverride: any): AsyncGenerator<StreamChunk, PreprocessorResult, unknown>;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { runPipeline } from "../pil/pipeline.js";
|
|
2
|
+
import { getSessionLastTask, recordSessionLastTask, resolveCeiling } from "./scope-ceiling.js";
|
|
3
|
+
export async function* prepareTurnContext(deps, userMessage, _budgetOverride) {
|
|
4
|
+
// PIL: enrich prompt before pushing to messages (D-01, D-03, D-04)
|
|
5
|
+
// Promise.race timeout of 200ms is inside runPipeline — fail-open guaranteed
|
|
6
|
+
// --- PIL with discovery (interactive path) ---
|
|
7
|
+
const pilChunkQueue = [];
|
|
8
|
+
const pilResponder = deps.councilManager.createQuestionResponder();
|
|
9
|
+
const discoveryHandler = {
|
|
10
|
+
askQuestion: async (question) => {
|
|
11
|
+
pilChunkQueue.push({
|
|
12
|
+
type: "council_question",
|
|
13
|
+
content: question.question,
|
|
14
|
+
councilQuestion: question,
|
|
15
|
+
});
|
|
16
|
+
const text = await pilResponder(question.questionId);
|
|
17
|
+
return { questionId: question.questionId, text, kind: "choice" };
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const _pilStart = Date.now();
|
|
21
|
+
let pilCtxResolved = null;
|
|
22
|
+
let pilDone = false;
|
|
23
|
+
const pilTask = (async () => {
|
|
24
|
+
try {
|
|
25
|
+
// Build Pass 4 LLM fallback closure using the orchestrator's already-
|
|
26
|
+
// constructed provider factory + current model. PIL stays ignorant of
|
|
27
|
+
// provider wiring — it just receives a `classify(prompt)` callback.
|
|
28
|
+
let llmFallback;
|
|
29
|
+
try {
|
|
30
|
+
const { createLlmClassifier } = await import("../pil/llm-classify.js");
|
|
31
|
+
llmFallback = createLlmClassifier(deps.requireProvider(), deps.modelId);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error(`[pil] LLM fallback wiring failed: ${err?.message}`);
|
|
35
|
+
}
|
|
36
|
+
// Model-driven clarification proposer (for discovery interview).
|
|
37
|
+
// The actual task model (via the same provider + modelId) generates the
|
|
38
|
+
// questions based on raw + CLI enrichment. Then discovery asks user.
|
|
39
|
+
let clarificationProposer;
|
|
40
|
+
try {
|
|
41
|
+
const { createModelClarificationProposer } = await import("../pil/discovery.js");
|
|
42
|
+
clarificationProposer = createModelClarificationProposer(deps.requireProvider(), deps.modelId);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error(`[pil] clarification proposer wiring failed: ${err?.message}`);
|
|
46
|
+
}
|
|
47
|
+
pilCtxResolved = await runPipeline(userMessage, {
|
|
48
|
+
resumeDigest: deps.getResumeDigest(),
|
|
49
|
+
activeRunId: deps.getActiveRunId(),
|
|
50
|
+
sessionId: deps.session?.id ?? null,
|
|
51
|
+
interactionHandler: discoveryHandler,
|
|
52
|
+
llmFallback,
|
|
53
|
+
clarificationProposer,
|
|
54
|
+
recentTurnsSummary: deps.buildRecentTurnsSummary(),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
pilCtxResolved = {
|
|
59
|
+
raw: userMessage,
|
|
60
|
+
enriched: userMessage,
|
|
61
|
+
taskType: null,
|
|
62
|
+
domain: null,
|
|
63
|
+
confidence: 0,
|
|
64
|
+
outputStyle: null,
|
|
65
|
+
tokenBudget: 500,
|
|
66
|
+
metrics: null,
|
|
67
|
+
layers: [],
|
|
68
|
+
gsdPhase: null,
|
|
69
|
+
activeRunId: null,
|
|
70
|
+
intentKind: null,
|
|
71
|
+
fallbackReason: err instanceof Error ? `orchestrator-catch:${err.name}` : "orchestrator-catch:unknown",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
pilDone = true;
|
|
76
|
+
}
|
|
77
|
+
})();
|
|
78
|
+
while (!pilDone) {
|
|
79
|
+
while (pilChunkQueue.length > 0) {
|
|
80
|
+
yield pilChunkQueue.shift();
|
|
81
|
+
}
|
|
82
|
+
if (!pilDone) {
|
|
83
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
while (pilChunkQueue.length > 0) {
|
|
87
|
+
yield pilChunkQueue.shift();
|
|
88
|
+
}
|
|
89
|
+
await pilTask;
|
|
90
|
+
const pilCtx = pilCtxResolved;
|
|
91
|
+
// Phase 4 Plan 04 (4B) — resolve per-session step ceiling using
|
|
92
|
+
// (task_type × complexitySize) matrix. Override (from --budget-rounds N
|
|
93
|
+
// parsed earlier) wins. When the override differs from the natural
|
|
94
|
+
// ceiling, emit info toast so the user sees the explicit cap.
|
|
95
|
+
//
|
|
96
|
+
// Phase 5 Fix 2 — continuation phrases ("tiếp tục" / "continue") are
|
|
97
|
+
// classified `general/chitchat` by PIL Layer 1 Pass 0. Resolving the
|
|
98
|
+
// ceiling from that label collapses the budget to general × small = 5,
|
|
99
|
+
// which is wrong: the user wants the agent to RESUME the prior task,
|
|
100
|
+
// not start a generic chitchat. When this session has a recorded
|
|
101
|
+
// non-chitchat task row, inherit it for ceiling resolution. The Pass 0
|
|
102
|
+
// classification itself stays general so downstream code (style /
|
|
103
|
+
// chitchat skip / tools-empty optimization in `BUG-A guard`) reads the
|
|
104
|
+
// correct intent; only the ceiling row is borrowed.
|
|
105
|
+
const _pilTaskType = pilCtx.taskType ?? "general";
|
|
106
|
+
const _pilSize = pilCtx.complexitySize?.size ?? "medium";
|
|
107
|
+
const _sessionIdForLastTask = deps.session?.id ?? "";
|
|
108
|
+
const _isContinuationChitchat = _pilTaskType === "general" && pilCtx.intentKind === "chitchat" && _sessionIdForLastTask !== "";
|
|
109
|
+
const _lastTask = _isContinuationChitchat ? getSessionLastTask(_sessionIdForLastTask) : null;
|
|
110
|
+
const _ceilingTaskType = _lastTask?.taskType ?? _pilTaskType;
|
|
111
|
+
const _ceilingSize = _lastTask?.size ?? _pilSize;
|
|
112
|
+
const _naturalCeiling = resolveCeiling(_ceilingTaskType, _ceilingSize);
|
|
113
|
+
// Phase 5 Fix 4 (Option A) — make ceiling mutable so the stopWhen
|
|
114
|
+
// closure can bump it on auto-continue checkpoints. See checkpoint
|
|
115
|
+
// logic at dynamicStopWhen below for the bump policy.
|
|
116
|
+
const _stepCeiling = _budgetOverride.override ?? _naturalCeiling;
|
|
117
|
+
// Record this turn's task row for future continuation inheritance.
|
|
118
|
+
// Only non-chitchat task turns update the slot.
|
|
119
|
+
if (_sessionIdForLastTask && _pilTaskType !== "general" && pilCtx.intentKind === "task") {
|
|
120
|
+
recordSessionLastTask(_sessionIdForLastTask, _pilTaskType, _pilSize);
|
|
121
|
+
}
|
|
122
|
+
if (_budgetOverride.override !== undefined && _budgetOverride.override !== _naturalCeiling) {
|
|
123
|
+
try {
|
|
124
|
+
const _ar = globalThis.__muonroiAgentRuntime;
|
|
125
|
+
_ar?.emitEvent({
|
|
126
|
+
t: "event",
|
|
127
|
+
kind: "toast",
|
|
128
|
+
level: "info",
|
|
129
|
+
text: `override active: ceiling ${_budgetOverride.override}, default was ${_naturalCeiling} (task=${_ceilingTaskType}/size=${_ceilingSize})`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
/* best-effort */
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
pilCtx,
|
|
138
|
+
_stepCeiling,
|
|
139
|
+
_pilStart,
|
|
140
|
+
_naturalCeiling,
|
|
141
|
+
_ceilingTaskType,
|
|
142
|
+
_ceilingSize: _ceilingSize,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=preprocessor.js.map
|
|
@@ -55,6 +55,12 @@ export interface SystemPromptOptions {
|
|
|
55
55
|
* PIL Layer 1 (intentKind === "chitchat").
|
|
56
56
|
*/
|
|
57
57
|
chitchat?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* When true (sub-agent), skip CUSTOM INSTRUCTIONS, skills catalog, and
|
|
60
|
+
* native capabilities — sub-agents don't need project-level instructions
|
|
61
|
+
* and can't run the full toolset anyway. Cuts ~6K tokens per sub-agent turn.
|
|
62
|
+
*/
|
|
63
|
+
subAgent?: boolean;
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
60
66
|
* Render the LIVE per-turn MCP tool roster as a system-prompt block.
|
|
@@ -76,6 +82,8 @@ export interface SystemPromptOptions {
|
|
|
76
82
|
*/
|
|
77
83
|
export declare function buildMcpCapabilityBlock(toolNames: readonly string[]): string;
|
|
78
84
|
export declare function buildSystemPromptParts(cwd: string, mode: AgentMode, sandboxMode: SandboxMode, planContext?: string | null, subagents?: CustomSubagentConfig[], sandboxSettings?: SandboxSettings, providerId?: string, resumeDigest?: string | null, options?: SystemPromptOptions): SystemPromptParts;
|
|
85
|
+
/** Reset the static prefix cache (for tests). */
|
|
86
|
+
export declare function resetStaticPrefixCache(): void;
|
|
79
87
|
export declare function buildSystemPrompt(cwd: string, mode: AgentMode, sandboxMode: SandboxMode, planContext?: string | null, subagents?: CustomSubagentConfig[], sandboxSettings?: SandboxSettings, providerId?: string, resumeDigest?: string | null, options?: SystemPromptOptions): string;
|
|
80
88
|
export declare function buildSubagentPrompt(request: TaskRequest, cwd: string, custom: CustomSubagentConfig | null, sandboxMode: SandboxMode, subagents?: CustomSubagentConfig[], sandboxSettings?: SandboxSettings, providerId?: string): string;
|
|
81
89
|
export declare function formatSandboxPromptSection(sandboxMode: SandboxMode, settings?: SandboxSettings): string;
|