muonroi-cli 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +143 -6
- 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 +7 -4
- 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 +36 -1
- 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/flow/compaction/index.d.ts +1 -0
- package/dist/src/flow/compaction/index.js +4 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/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 +59 -62
- 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 +13 -5
- package/dist/src/lsp/manager.test.js +41 -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/auto-setup.js +0 -8
- 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/self-verify-jobs.d.ts +1 -0
- package/dist/src/mcp/self-verify-jobs.js +1 -3
- package/dist/src/mcp/self-verify-runner.js +1 -1
- package/dist/src/models/catalog-gemini.test.js +12 -10
- package/dist/src/models/catalog.json +106 -38
- 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 +3 -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 +2 -0
- package/dist/src/orchestrator/__tests__/prompts.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/prompts.test.js +88 -0
- package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.js +507 -0
- package/dist/src/orchestrator/agent.test.js +5 -2
- package/dist/src/orchestrator/auto-commit.d.ts +110 -0
- package/dist/src/orchestrator/auto-commit.js +366 -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 +23 -5
- package/dist/src/orchestrator/message-processor.js +226 -2573
- package/dist/src/orchestrator/orchestrator.d.ts +11 -2
- package/dist/src/orchestrator/orchestrator.js +530 -43
- package/dist/src/orchestrator/pending-calls.js +2 -1
- package/dist/src/orchestrator/preprocessor.d.ts +13 -0
- package/dist/src/orchestrator/preprocessor.js +146 -0
- package/dist/src/orchestrator/prompts.d.ts +16 -0
- package/dist/src/orchestrator/prompts.js +130 -67
- 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-cap.d.ts +2 -0
- package/dist/src/orchestrator/sub-agent-cap.js +12 -4
- package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
- package/dist/src/orchestrator/subagent-compactor.d.ts +21 -0
- package/dist/src/orchestrator/subagent-compactor.js +148 -24
- package/dist/src/orchestrator/subagent-compactor.spec.js +249 -1
- 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 +153 -0
- package/dist/src/orchestrator/tool-engine.js +3138 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +3 -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__/llm-classify.test.js +79 -1
- 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 +62 -7
- 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.d.ts +11 -0
- package/dist/src/pil/llm-classify.js +196 -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/gather.js +19 -5
- package/dist/src/product-loop/loop-driver.js +2 -2
- 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/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/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/self-qa/agentic-loop.js +30 -21
- 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__/hierarchical-session.test.d.ts +1 -0
- package/dist/src/storage/__tests__/hierarchical-session.test.js +161 -0
- package/dist/src/storage/__tests__/sweep-stale-pending.test.js +2 -2
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/migrations.js +13 -1
- package/dist/src/storage/transcript-response-entry.test.js +18 -5
- package/dist/src/storage/transcript-view.js +7 -1
- package/dist/src/storage/transcript.d.ts +3 -0
- package/dist/src/storage/transcript.js +254 -73
- package/dist/src/storage/ui-interaction-log.d.ts +17 -0
- package/dist/src/storage/usage.js +22 -5
- 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 +66 -1
- 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 +6 -0
- package/dist/src/tools/registry.js +215 -13
- package/dist/src/types/index.d.ts +8 -2
- 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/expand.js +14 -1
- 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/__tests__/llm-deadline.test.js +16 -4
- package/dist/src/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/src/utils/__tests__/logger.test.js +115 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.d.ts +1 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.js +48 -0
- package/dist/src/utils/install-manager.d.ts +1 -0
- package/dist/src/utils/install-manager.js +76 -7
- package/dist/src/utils/install-manager.test.js +43 -1
- package/dist/src/utils/llm-deadline.d.ts +9 -1
- package/dist/src/utils/llm-deadline.js +31 -2
- package/dist/src/utils/logger.d.ts +28 -0
- package/dist/src/utils/logger.js +171 -0
- 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 +36 -32
- package/dist/src/utils/settings.js +151 -123
- package/dist/src/utils/update-checker.test.js +5 -1
- package/package.json +1 -1
|
@@ -22,6 +22,7 @@ import * as crypto from "node:crypto";
|
|
|
22
22
|
import { promises as fs } from "node:fs";
|
|
23
23
|
import * as path from "node:path";
|
|
24
24
|
import { getSessionDir } from "../storage/session-dir.js";
|
|
25
|
+
import { logger } from "../utils/logger.js";
|
|
25
26
|
// ─── stableCallId ─────────────────────────────────────────────────────────────
|
|
26
27
|
/**
|
|
27
28
|
* Derives a deterministic call_id from (turnId, toolName, input).
|
|
@@ -160,7 +161,7 @@ export function createPendingCallsLog(sessionId) {
|
|
|
160
161
|
void finalExists;
|
|
161
162
|
}
|
|
162
163
|
catch (err) {
|
|
163
|
-
|
|
164
|
+
logger.warn("orchestrator", `reconcile: could not clean staged path ${tmp}`, { error: err });
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
// Mark the entry as abandoned in the log.
|
|
@@ -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,146 @@
|
|
|
1
|
+
import { runPipeline } from "../pil/pipeline.js";
|
|
2
|
+
import { getSessionLastTask, recordSessionLastTask, resolveCeiling } from "./scope-ceiling.js";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
export async function* prepareTurnContext(deps, userMessage, _budgetOverride) {
|
|
5
|
+
// PIL: enrich prompt before pushing to messages (D-01, D-03, D-04)
|
|
6
|
+
// Promise.race timeout of 200ms is inside runPipeline — fail-open guaranteed
|
|
7
|
+
// --- PIL with discovery (interactive path) ---
|
|
8
|
+
const pilChunkQueue = [];
|
|
9
|
+
const pilResponder = deps.councilManager.createQuestionResponder();
|
|
10
|
+
const discoveryHandler = {
|
|
11
|
+
askQuestion: async (question) => {
|
|
12
|
+
pilChunkQueue.push({
|
|
13
|
+
type: "council_question",
|
|
14
|
+
content: question.question,
|
|
15
|
+
councilQuestion: question,
|
|
16
|
+
});
|
|
17
|
+
const text = await pilResponder(question.questionId);
|
|
18
|
+
return { questionId: question.questionId, text, kind: "choice" };
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
const _pilStart = Date.now();
|
|
22
|
+
let pilCtxResolved = null;
|
|
23
|
+
let pilDone = false;
|
|
24
|
+
const pilTask = (async () => {
|
|
25
|
+
try {
|
|
26
|
+
// Build Pass 4 LLM fallback closure using the orchestrator's already-
|
|
27
|
+
// constructed provider factory + current model. PIL stays ignorant of
|
|
28
|
+
// provider wiring — it just receives a `classify(prompt)` callback.
|
|
29
|
+
let llmFallback;
|
|
30
|
+
try {
|
|
31
|
+
const { createLlmClassifier } = await import("../pil/llm-classify.js");
|
|
32
|
+
llmFallback = createLlmClassifier(deps.requireProvider(), deps.modelId);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
logger.error("pil", "LLM fallback wiring failed", { error: err });
|
|
36
|
+
}
|
|
37
|
+
// Model-driven clarification proposer (for discovery interview).
|
|
38
|
+
// The actual task model (via the same provider + modelId) generates the
|
|
39
|
+
// questions based on raw + CLI enrichment. Then discovery asks user.
|
|
40
|
+
let clarificationProposer;
|
|
41
|
+
try {
|
|
42
|
+
const { createModelClarificationProposer } = await import("../pil/discovery.js");
|
|
43
|
+
clarificationProposer = createModelClarificationProposer(deps.requireProvider(), deps.modelId);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
logger.error("pil", "clarification proposer wiring failed", { error: err });
|
|
47
|
+
}
|
|
48
|
+
pilCtxResolved = await runPipeline(userMessage, {
|
|
49
|
+
resumeDigest: deps.getResumeDigest(),
|
|
50
|
+
activeRunId: deps.getActiveRunId(),
|
|
51
|
+
sessionId: deps.session?.id ?? null,
|
|
52
|
+
interactionHandler: discoveryHandler,
|
|
53
|
+
llmFallback,
|
|
54
|
+
clarificationProposer,
|
|
55
|
+
recentTurnsSummary: deps.buildRecentTurnsSummary(),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
pilCtxResolved = {
|
|
60
|
+
raw: userMessage,
|
|
61
|
+
enriched: userMessage,
|
|
62
|
+
taskType: null,
|
|
63
|
+
domain: null,
|
|
64
|
+
confidence: 0,
|
|
65
|
+
outputStyle: null,
|
|
66
|
+
tokenBudget: 500,
|
|
67
|
+
metrics: null,
|
|
68
|
+
layers: [],
|
|
69
|
+
gsdPhase: null,
|
|
70
|
+
activeRunId: null,
|
|
71
|
+
intentKind: null,
|
|
72
|
+
fallbackReason: err instanceof Error ? `orchestrator-catch:${err.name}` : "orchestrator-catch:unknown",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
pilDone = true;
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
while (!pilDone) {
|
|
80
|
+
while (pilChunkQueue.length > 0) {
|
|
81
|
+
yield pilChunkQueue.shift();
|
|
82
|
+
}
|
|
83
|
+
if (!pilDone) {
|
|
84
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
while (pilChunkQueue.length > 0) {
|
|
88
|
+
yield pilChunkQueue.shift();
|
|
89
|
+
}
|
|
90
|
+
await pilTask;
|
|
91
|
+
const pilCtx = pilCtxResolved;
|
|
92
|
+
// Phase 4 Plan 04 (4B) — resolve per-session step ceiling using
|
|
93
|
+
// (task_type × complexitySize) matrix. Override (from --budget-rounds N
|
|
94
|
+
// parsed earlier) wins. When the override differs from the natural
|
|
95
|
+
// ceiling, emit info toast so the user sees the explicit cap.
|
|
96
|
+
//
|
|
97
|
+
// Phase 5 Fix 2 — continuation phrases ("tiếp tục" / "continue") are
|
|
98
|
+
// classified `general/chitchat` by PIL Layer 1 Pass 0. Resolving the
|
|
99
|
+
// ceiling from that label collapses the budget to general × small = 5,
|
|
100
|
+
// which is wrong: the user wants the agent to RESUME the prior task,
|
|
101
|
+
// not start a generic chitchat. When this session has a recorded
|
|
102
|
+
// non-chitchat task row, inherit it for ceiling resolution. The Pass 0
|
|
103
|
+
// classification itself stays general so downstream code (style /
|
|
104
|
+
// chitchat skip / tools-empty optimization in `BUG-A guard`) reads the
|
|
105
|
+
// correct intent; only the ceiling row is borrowed.
|
|
106
|
+
const _pilTaskType = pilCtx.taskType ?? "general";
|
|
107
|
+
const _pilSize = pilCtx.complexitySize?.size ?? "medium";
|
|
108
|
+
const _sessionIdForLastTask = deps.session?.id ?? "";
|
|
109
|
+
const _isContinuationChitchat = _pilTaskType === "general" && pilCtx.intentKind === "chitchat" && _sessionIdForLastTask !== "";
|
|
110
|
+
const _lastTask = _isContinuationChitchat ? getSessionLastTask(_sessionIdForLastTask) : null;
|
|
111
|
+
const _ceilingTaskType = _lastTask?.taskType ?? _pilTaskType;
|
|
112
|
+
const _ceilingSize = _lastTask?.size ?? _pilSize;
|
|
113
|
+
const _naturalCeiling = resolveCeiling(_ceilingTaskType, _ceilingSize);
|
|
114
|
+
// Phase 5 Fix 4 (Option A) — make ceiling mutable so the stopWhen
|
|
115
|
+
// closure can bump it on auto-continue checkpoints. See checkpoint
|
|
116
|
+
// logic at dynamicStopWhen below for the bump policy.
|
|
117
|
+
const _stepCeiling = _budgetOverride.override ?? _naturalCeiling;
|
|
118
|
+
// Record this turn's task row for future continuation inheritance.
|
|
119
|
+
// Only non-chitchat task turns update the slot.
|
|
120
|
+
if (_sessionIdForLastTask && _pilTaskType !== "general" && pilCtx.intentKind === "task") {
|
|
121
|
+
recordSessionLastTask(_sessionIdForLastTask, _pilTaskType, _pilSize);
|
|
122
|
+
}
|
|
123
|
+
if (_budgetOverride.override !== undefined && _budgetOverride.override !== _naturalCeiling) {
|
|
124
|
+
try {
|
|
125
|
+
const _ar = globalThis.__muonroiAgentRuntime;
|
|
126
|
+
_ar?.emitEvent({
|
|
127
|
+
t: "event",
|
|
128
|
+
kind: "toast",
|
|
129
|
+
level: "info",
|
|
130
|
+
text: `override active: ceiling ${_budgetOverride.override}, default was ${_naturalCeiling} (task=${_ceilingTaskType}/size=${_ceilingSize})`,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
/* best-effort */
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
pilCtx,
|
|
139
|
+
_stepCeiling,
|
|
140
|
+
_pilStart,
|
|
141
|
+
_naturalCeiling,
|
|
142
|
+
_ceilingTaskType,
|
|
143
|
+
_ceilingSize: _ceilingSize,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=preprocessor.js.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { AgentMode, TaskRequest } from "../types/index.js";
|
|
2
2
|
import { type CustomSubagentConfig, type SandboxMode, type SandboxSettings } from "../utils/settings.js";
|
|
3
3
|
export declare const MAX_TOOL_ROUNDS: number;
|
|
4
|
+
export declare const HARD_MAX_TOOL_ROUNDS: number;
|
|
5
|
+
export declare const MAX_LLM_CALLS_PER_TURN: number;
|
|
4
6
|
export declare const VISION_MODEL = "grok-4-1-fast-reasoning";
|
|
5
7
|
export declare const COMPUTER_MODEL = "grok-4.20-0309-reasoning";
|
|
6
8
|
/**
|
|
@@ -55,6 +57,18 @@ export interface SystemPromptOptions {
|
|
|
55
57
|
* PIL Layer 1 (intentKind === "chitchat").
|
|
56
58
|
*/
|
|
57
59
|
chitchat?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* When true (sub-agent), skip CUSTOM INSTRUCTIONS, skills catalog, and
|
|
62
|
+
* native capabilities — sub-agents don't need project-level instructions
|
|
63
|
+
* and can't run the full toolset anyway. Cuts ~6K tokens per sub-agent turn.
|
|
64
|
+
*/
|
|
65
|
+
subAgent?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* When true (tool-turn, i.e. second+ LLM call in the same user-turn tool
|
|
68
|
+
* loop), skip native-capabilities and skills sections that were already
|
|
69
|
+
* shown in the first call. Cuts ~4K tokens per tool round-trip.
|
|
70
|
+
*/
|
|
71
|
+
toolTurn?: boolean;
|
|
58
72
|
}
|
|
59
73
|
/**
|
|
60
74
|
* Render the LIVE per-turn MCP tool roster as a system-prompt block.
|
|
@@ -76,6 +90,8 @@ export interface SystemPromptOptions {
|
|
|
76
90
|
*/
|
|
77
91
|
export declare function buildMcpCapabilityBlock(toolNames: readonly string[]): string;
|
|
78
92
|
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;
|
|
93
|
+
/** Reset the static prefix cache (for tests). */
|
|
94
|
+
export declare function resetStaticPrefixCache(): void;
|
|
79
95
|
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
96
|
export declare function buildSubagentPrompt(request: TaskRequest, cwd: string, custom: CustomSubagentConfig | null, sandboxMode: SandboxMode, subagents?: CustomSubagentConfig[], sandboxSettings?: SandboxSettings, providerId?: string): string;
|
|
81
97
|
export declare function formatSandboxPromptSection(sandboxMode: SandboxMode, settings?: SandboxSettings): string;
|
|
@@ -4,22 +4,67 @@ import { buildContractSection } from "../pil/agent-operating-contract.js";
|
|
|
4
4
|
import { buildNativeCapabilitiesSection } from "../pil/native-capabilities-workbook.js";
|
|
5
5
|
import { getProviderCapabilities } from "../providers/capabilities.js";
|
|
6
6
|
import { loadCustomInstructions } from "../utils/instructions.js";
|
|
7
|
-
import {
|
|
7
|
+
import { logger } from "../utils/logger.js";
|
|
8
|
+
import { loadUserSettings, loadValidSubAgents, } from "../utils/settings.js";
|
|
8
9
|
import { resolveShell } from "../utils/shell.js";
|
|
9
10
|
import { discoverSkills, formatSkillsForPrompt } from "../utils/skills.js";
|
|
10
|
-
//
|
|
11
|
-
// after session
|
|
12
|
-
//
|
|
11
|
+
// F3a — hard cap on tool rounds per user turn. Reduced 100 → 40
|
|
12
|
+
// after session 526a83cf22df logged 2.44M input tokens over 46 LLM calls
|
|
13
|
+
// with 3 turns (seq 33/81/1) consuming 82% of tokens.
|
|
14
|
+
// Env override allowed range 10..400.
|
|
15
|
+
// Env override allowed range 10..400 (or up to 2000 in agent-first).
|
|
13
16
|
function readMaxToolRoundsFromEnv() {
|
|
14
|
-
const
|
|
17
|
+
const settings = loadUserSettings();
|
|
18
|
+
const agentFirst = settings.agentFirst !== false &&
|
|
19
|
+
process.env.MUONROI_AGENT_FIRST !== "0" &&
|
|
20
|
+
process.env.MUONROI_AGENT_FIRST !== "false";
|
|
21
|
+
const raw = process.env.MUONROI_MAX_TOOL_ROUNDS || settings.maxToolRounds;
|
|
15
22
|
if (!raw)
|
|
16
|
-
return
|
|
23
|
+
return agentFirst ? 200 : 40;
|
|
17
24
|
const n = Number(raw);
|
|
18
25
|
if (!Number.isFinite(n))
|
|
19
|
-
return
|
|
20
|
-
|
|
26
|
+
return agentFirst ? 200 : 40;
|
|
27
|
+
const maxLimit = agentFirst ? 2000 : 400;
|
|
28
|
+
return Math.max(10, Math.min(maxLimit, Math.floor(n)));
|
|
21
29
|
}
|
|
22
30
|
export const MAX_TOOL_ROUNDS = readMaxToolRoundsFromEnv();
|
|
31
|
+
// F3b — HARD cap: absolute non-bumpable ceiling per user turn.
|
|
32
|
+
// Fires AFTER the soft cap has been bumped by the user.
|
|
33
|
+
// Env override allowed range 20..400 (or up to 3000 in agent-first).
|
|
34
|
+
function readHardMaxToolRoundsFromEnv() {
|
|
35
|
+
const settings = loadUserSettings();
|
|
36
|
+
const agentFirst = settings.agentFirst !== false &&
|
|
37
|
+
process.env.MUONROI_AGENT_FIRST !== "0" &&
|
|
38
|
+
process.env.MUONROI_AGENT_FIRST !== "false";
|
|
39
|
+
const raw = process.env.MUONROI_HARD_MAX_TOOL_ROUNDS || settings.hardMaxToolRounds;
|
|
40
|
+
if (!raw)
|
|
41
|
+
return agentFirst ? 300 : 60;
|
|
42
|
+
const n = Number(raw);
|
|
43
|
+
if (!Number.isFinite(n))
|
|
44
|
+
return agentFirst ? 300 : 60;
|
|
45
|
+
const maxLimit = agentFirst ? 3000 : 400;
|
|
46
|
+
return Math.max(20, Math.min(maxLimit, Math.floor(n)));
|
|
47
|
+
}
|
|
48
|
+
export const HARD_MAX_TOOL_ROUNDS = readHardMaxToolRoundsFromEnv();
|
|
49
|
+
// F3c — per-turn LLM call cap: how many streamText() invocations are
|
|
50
|
+
// allowed per user turn.
|
|
51
|
+
// Default 12 (or 100 in agent-first).
|
|
52
|
+
// Env override MUONROI_MAX_LLM_CALLS_PER_TURN, range 3..100 (or up to 500 in agent-first).
|
|
53
|
+
function readMaxLlmCallsPerTurn() {
|
|
54
|
+
const settings = loadUserSettings();
|
|
55
|
+
const agentFirst = settings.agentFirst !== false &&
|
|
56
|
+
process.env.MUONROI_AGENT_FIRST !== "0" &&
|
|
57
|
+
process.env.MUONROI_AGENT_FIRST !== "false";
|
|
58
|
+
const raw = process.env.MUONROI_MAX_LLM_CALLS_PER_TURN || settings.maxLlmCallsPerTurn;
|
|
59
|
+
if (!raw)
|
|
60
|
+
return agentFirst ? 100 : 12;
|
|
61
|
+
const n = Number(raw);
|
|
62
|
+
if (!Number.isFinite(n))
|
|
63
|
+
return agentFirst ? 100 : 12;
|
|
64
|
+
const maxLimit = agentFirst ? 500 : 100;
|
|
65
|
+
return Math.max(3, Math.min(maxLimit, Math.floor(n)));
|
|
66
|
+
}
|
|
67
|
+
export const MAX_LLM_CALLS_PER_TURN = readMaxLlmCallsPerTurn();
|
|
23
68
|
export const VISION_MODEL = "grok-4-1-fast-reasoning";
|
|
24
69
|
export const COMPUTER_MODEL = "grok-4.20-0309-reasoning";
|
|
25
70
|
/**
|
|
@@ -62,9 +107,7 @@ export function detectProjectStack(cwd) {
|
|
|
62
107
|
// Best-effort enrichment: a missing/unreadable cwd simply omits the stack
|
|
63
108
|
// line (the ENVIRONMENT cwd line already surfaces "<unknown>"). Debug-gated
|
|
64
109
|
// so prompt assembly never corrupts the TUI at startup.
|
|
65
|
-
|
|
66
|
-
console.error(`[orchestrator/prompts] detectProjectStack failed for ${cwd}: ${err?.message}`);
|
|
67
|
-
}
|
|
110
|
+
logger.error("orchestrator", `detectProjectStack failed for ${cwd}`, { error: err });
|
|
68
111
|
return "";
|
|
69
112
|
}
|
|
70
113
|
const has = (name) => entries.includes(name);
|
|
@@ -143,6 +186,7 @@ function buildEnvironmentBlock() {
|
|
|
143
186
|
if (platform === "win32") {
|
|
144
187
|
shellRules.push('- When a Windows-native command is genuinely needed, invoke it explicitly: `cmd.exe /c "command"` or `powershell -NoProfile -Command "command"`.');
|
|
145
188
|
}
|
|
189
|
+
shellRules.push("- CRITICAL: Batch independent commands in ONE call with `&&` or `;` instead of N sequential calls — each extra call adds ~500 tokens of overhead and prevents cross-request cache reuse. Examples: `ls && cat file` or `a; b; c; d` instead of four separate bash calls.");
|
|
146
190
|
}
|
|
147
191
|
else if (shell.kind === "powershell") {
|
|
148
192
|
shellRules.push("- The bash tool runs PowerShell. Use PowerShell cmdlets: Get-ChildItem, Select-String, Measure-Object, ConvertTo-Json, $env:VAR.", "- DO NOT use POSIX-only commands: grep, sed, awk, wc (use Select-String / Measure-Object / -split instead).", "- For pipe redirection, use PowerShell syntax: `cmd | Select-Object -First 10`, not `cmd | head -10`.");
|
|
@@ -272,11 +316,28 @@ IMPORTANT:
|
|
|
272
316
|
- Use write_file only for new files or when most of the file is changing. For very large files (>500 lines), split into multiple edit_file calls or write smaller chunks.
|
|
273
317
|
- Use read_file instead of cat/head/tail for reading files.
|
|
274
318
|
- When the user asks for an automated recurring or one-time run, use the schedule tools instead of only describing the setup.
|
|
275
|
-
-
|
|
276
|
-
-
|
|
319
|
+
- If you have worked for a long time or hit a tool execution limit, DO NOT tell the user to move to a new session. Instead, advise them to run the \`/compact\` command to free up memory before continuing.
|
|
320
|
+
- Use the experience brain actively (it is how you stop repeating mistakes across sessions): at the start of an unfamiliar or risky step call ee_query to recall past lessons, and after acting on a recalled \`[id col]\` rate it with ee_feedback. The MOMENT you hit a mistake / error / dead-end and find the working fix, call ee_write to save the lesson (the pitfall AND the fix, concise and generalizable) — it is embedded immediately and recallable via ee_query in this and future sessions. Saving a hard-won fix is part of doing the work, not optional.
|
|
321
|
+
- Commit your own work as you go (in any git repo, without being asked): use the git_commit tool — YOU write the commit message — the moment a cohesive, working chunk passes its checks, and after EACH step of a multi-step plan. Prefer several small, logically-scoped commits with clear messages (describe WHAT changed) over one catch-all at the end. git_commit stages only the files you wrote, excludes secrets/artifacts, and appends the "Coding by - Muonroi-CLI" attribution for you. (Any commit you instead make by hand via bash must still end with that attribution line, verbatim, on its own final line.)
|
|
277
322
|
- After creating a recurring schedule, check the daemon status and start it with \`schedule_daemon_start\` if needed.
|
|
278
323
|
|
|
279
|
-
|
|
324
|
+
|
|
325
|
+
Be direct. Execute, don't just describe. Show results, not plans.
|
|
326
|
+
|
|
327
|
+
TOKEN BUDGET:
|
|
328
|
+
- Each tool round sends ~17K system prompt tokens + accumulated tool results to the model.
|
|
329
|
+
- Task(explore) / task(general) isolates context in a sub-agent — much cheaper than 5+ top-level rounds.
|
|
330
|
+
- Consider: 1-2 rounds → direct; 3-5 rounds → consider task(explore); >5 rounds → should use task(explore).
|
|
331
|
+
WORKFLOW RULES:
|
|
332
|
+
- RESEARCH FIRST: Always prioritize research before proposing edits. DeepSeek and other models have knowledge cutoffs; do not assume you know the exact codebase structure or latest external libraries. Use 'grep', 'lsp', and 'read_file' to search the local codebase. Use MCP tools (like web search or documentation readers) to research external knowledge, APIs, or libraries. Use 'delegate' for deep background research. Read before you write.
|
|
333
|
+
- CLARIFY GRAY AREAS: If the user's request is ambiguous or leaves critical design decisions unspecified, STOP and ask the user for clarification before writing code. Do not hallucinate requirements.
|
|
334
|
+
|
|
335
|
+
SELF-LIMIT:
|
|
336
|
+
- When you've read 5+ files and haven't concluded, summarize findings and propose next step instead of reading more.
|
|
337
|
+
- BATCH TOOL CALLS: You MUST combine and invoke independent tool calls in parallel (e.g. read multiple files, or run grep and read a file concurrently) in a SINGLE turn. Do not wait for the result of one tool call before invoking another if you already know both are needed. This dramatically reduces conversation turns, roundtrip latency, and input token accumulation.
|
|
338
|
+
- BATCH BASH COMMANDS: Combine independent commands into ONE bash call (a; b; c) rather than sequential single calls — each separate call adds ~500 tokens of overhead and prevents prompt-cache reuse across the session.
|
|
339
|
+
- Read only specific file sections (start_line/end_line) instead of whole files.
|
|
340
|
+
- When a clear direction emerges from the first 2-3 tool results, act on it — don't over-investigate.`,
|
|
280
341
|
plan: `You are muonroi-cli in Plan mode — you analyze and plan but DO NOT execute changes.
|
|
281
342
|
|
|
282
343
|
${ENVIRONMENT}
|
|
@@ -386,40 +447,64 @@ export function buildMcpCapabilityBlock(toolNames) {
|
|
|
386
447
|
"to bash or hand-write JSON-RPC to reach an MCP server:\n" +
|
|
387
448
|
lines.join("\n"));
|
|
388
449
|
}
|
|
389
|
-
|
|
390
|
-
|
|
450
|
+
const _staticPrefixCache = new Map();
|
|
451
|
+
const STATIC_PREFIX_CACHE_TTL_MS = 300_000; // 5 min — ample; inputs are session-stable
|
|
452
|
+
function staticPrefixCacheKey(cwd, mode, providerId, isChitchat, subagentsHash, subAgent = false, toolTurn = false) {
|
|
453
|
+
return `${cwd}|${mode}|${providerId}|${isChitchat}|${subagentsHash}|${subAgent}|${toolTurn}`;
|
|
454
|
+
}
|
|
455
|
+
function computeStaticPrefix(cwd, mode, subagents, providerId, chitchat, subAgent = false, toolTurn = false) {
|
|
391
456
|
const custom = loadCustomInstructions(cwd);
|
|
392
|
-
const customSection = custom
|
|
393
|
-
?
|
|
394
|
-
:
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
const skillsText = chitchat ? "" : formatSkillsForPrompt(discoverSkills(cwd));
|
|
457
|
+
const customSection = subAgent || !custom
|
|
458
|
+
? ""
|
|
459
|
+
: `\n\nCUSTOM INSTRUCTIONS:\n${custom}\n\nFollow the above alongside standard instructions.\n`;
|
|
460
|
+
// Tool-turn: skip agent-skills catalog (~2K tokens) and native-capabilities block (~2K tokens).
|
|
461
|
+
// The agent was already shown these in the first call of this turn and does not need
|
|
462
|
+
// to re-read them on every tool round-trip.
|
|
463
|
+
const skillsText = chitchat || subAgent || toolTurn ? "" : formatSkillsForPrompt(discoverSkills(cwd));
|
|
399
464
|
const skillsSection = skillsText ? `\n\n${skillsText}\n` : "";
|
|
400
465
|
const subagentsSection = chitchat ? "" : formatCustomSubagentsPromptSection(subagents ?? loadValidSubAgents());
|
|
401
|
-
const sandboxSection = formatSandboxPromptSection(sandboxMode, sandboxSettings);
|
|
402
466
|
let modePrompt = MODE_PROMPTS[mode];
|
|
403
|
-
// Phase 12.2-G5: defer the "is this an anthropic-style prompt or not?"
|
|
404
|
-
// decision to the provider capability. Default (no providerId) keeps the
|
|
405
|
-
// pre-G5 behaviour by treating the prompt as anthropic-native.
|
|
406
467
|
if (!providerId)
|
|
407
468
|
throw new Error("providerId is required to build system prompt — cannot determine prompt style.");
|
|
408
469
|
const promptStyle = getProviderCapabilities(providerId).systemPromptStyle();
|
|
409
470
|
if (promptStyle !== "anthropic") {
|
|
410
471
|
modePrompt = stripToolsSection(modePrompt) + NON_ANTHROPIC_TOOL_PREAMBLE;
|
|
411
472
|
}
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
473
|
+
// Agent mode: strip tool descriptions for tools rarely needed in coding tasks
|
|
474
|
+
// to reduce system-prompt bloat. The tools remain available via API.
|
|
475
|
+
if (mode === "agent") {
|
|
476
|
+
modePrompt = modePrompt.replace(/\n- (wallet_|paid_|fetch_payment|schedule_|generate_|computer_|search_x).*/g, "");
|
|
477
|
+
}
|
|
416
478
|
const contractSection = buildContractSection({ chitchat });
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const
|
|
479
|
+
const nativeCapabilitiesSection = toolTurn ? "" : buildNativeCapabilitiesSection({ mode, chitchat });
|
|
480
|
+
const prefix = `${contractSection}${nativeCapabilitiesSection}${modePrompt}${customSection}${skillsSection}${subagentsSection}`;
|
|
481
|
+
return { prefix };
|
|
482
|
+
}
|
|
483
|
+
export function buildSystemPromptParts(cwd, mode, sandboxMode, planContext, subagents, sandboxSettings, providerId, resumeDigest, options) {
|
|
484
|
+
const chitchat = options?.chitchat === true;
|
|
485
|
+
const subAgent = options?.subAgent ?? false;
|
|
486
|
+
const toolTurn = options?.toolTurn === true;
|
|
487
|
+
const pid = providerId ?? "default";
|
|
488
|
+
// Subagents rarely change mid-session, but when they do we need a cache miss.
|
|
489
|
+
// JSON-stable stringify is fast for typical configs (< 10 entries, no circular refs).
|
|
490
|
+
const subagentsHash = subagents ? JSON.stringify(subagents) : "none";
|
|
491
|
+
// Try cache for the static prefix
|
|
492
|
+
const key = staticPrefixCacheKey(cwd, mode, pid, chitchat, subagentsHash, subAgent, toolTurn);
|
|
493
|
+
const now = Date.now();
|
|
494
|
+
const cached = _staticPrefixCache.get(key);
|
|
495
|
+
let staticPrefix;
|
|
496
|
+
if (cached && now - cached.cachedAt < STATIC_PREFIX_CACHE_TTL_MS) {
|
|
497
|
+
staticPrefix = cached.prefix;
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
// Cache miss — compute and store
|
|
501
|
+
const result = computeStaticPrefix(cwd, mode, subagents, pid, chitchat, subAgent, toolTurn);
|
|
502
|
+
staticPrefix = result.prefix;
|
|
503
|
+
_staticPrefixCache.set(key, {
|
|
504
|
+
prefix: staticPrefix,
|
|
505
|
+
cachedAt: now,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
423
508
|
const planSection = planContext
|
|
424
509
|
? `\n\nAPPROVED PLAN:\nThe following plan has been approved by the user. Execute it now.\n${planContext}\n`
|
|
425
510
|
: "";
|
|
@@ -429,6 +514,10 @@ export function buildSystemPromptParts(cwd, mode, sandboxMode, planContext, suba
|
|
|
429
514
|
const dynamicSuffix = `${planSection}${resumeSection}\n\nCurrent working directory: ${cwd}`;
|
|
430
515
|
return { staticPrefix, dynamicSuffix };
|
|
431
516
|
}
|
|
517
|
+
/** Reset the static prefix cache (for tests). */
|
|
518
|
+
export function resetStaticPrefixCache() {
|
|
519
|
+
_staticPrefixCache.clear();
|
|
520
|
+
}
|
|
432
521
|
export function buildSystemPrompt(cwd, mode, sandboxMode, planContext, subagents, sandboxSettings, providerId, resumeDigest, options) {
|
|
433
522
|
const { staticPrefix, dynamicSuffix } = buildSystemPromptParts(cwd, mode, sandboxMode, planContext, subagents, sandboxSettings, providerId, resumeDigest, options);
|
|
434
523
|
return `${staticPrefix}${dynamicSuffix}`;
|
|
@@ -556,39 +645,13 @@ export function buildSubagentPrompt(request, cwd, custom, sandboxMode, subagents
|
|
|
556
645
|
"",
|
|
557
646
|
`Delegated task: ${request.description}`,
|
|
558
647
|
"",
|
|
559
|
-
buildSystemPrompt(cwd, mode, sandboxMode, undefined, subagents, sandboxSettings, providerId
|
|
648
|
+
buildSystemPrompt(cwd, mode, sandboxMode, undefined, subagents, sandboxSettings, providerId, undefined, {
|
|
649
|
+
subAgent: true,
|
|
650
|
+
}),
|
|
560
651
|
].join("\n");
|
|
561
652
|
}
|
|
562
653
|
export function formatSandboxPromptSection(sandboxMode, settings) {
|
|
563
|
-
|
|
564
|
-
return "";
|
|
565
|
-
const s = settings ?? {};
|
|
566
|
-
let networkLine;
|
|
567
|
-
if (s.allowNet) {
|
|
568
|
-
networkLine = s.allowedHosts?.length
|
|
569
|
-
? `- Network access is restricted to: ${s.allowedHosts.join(", ")}.`
|
|
570
|
-
: "- Network access is enabled.";
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
networkLine = "- Network is disabled.";
|
|
574
|
-
}
|
|
575
|
-
const lines = [
|
|
576
|
-
"",
|
|
577
|
-
"SANDBOX MODE:",
|
|
578
|
-
"- Bash commands run inside a Shuru sandbox.",
|
|
579
|
-
networkLine,
|
|
580
|
-
"- The current workspace is mounted inside the sandbox at `/workspace`.",
|
|
581
|
-
"- Shell-side workspace file changes do not persist back to the host in this version.",
|
|
582
|
-
"- Use `read_file`, `edit_file`, and `write_file` for durable source edits.",
|
|
583
|
-
"- If a task needs a host-persistent shell mutation, explain that sandbox mode blocks that workflow and ask whether to disable sandbox mode.",
|
|
584
|
-
];
|
|
585
|
-
if (s.ports?.length) {
|
|
586
|
-
lines.push(`- Port forwards: ${s.ports.join(", ")}.`);
|
|
587
|
-
}
|
|
588
|
-
if (s.from) {
|
|
589
|
-
lines.push(`- Starting from checkpoint: ${s.from}.`);
|
|
590
|
-
}
|
|
591
|
-
return lines.join("\n");
|
|
654
|
+
return "";
|
|
592
655
|
}
|
|
593
656
|
export function applyModelConstraints(system, modelId) {
|
|
594
657
|
const modelInfo = getModelInfo(modelId);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/orchestrator/safety-askcard.ts
|
|
3
|
+
*
|
|
4
|
+
* Plans an askcard layout when a tool call is blocked by the safety filter
|
|
5
|
+
* (catastrophic, dangerous, git-safety, empty-bash).
|
|
6
|
+
*
|
|
7
|
+
* The askcard gives the user a choice: allow the block once, or confirm the block.
|
|
8
|
+
*
|
|
9
|
+
* Pure — no React, no side effects. Unit-testable in isolation.
|
|
10
|
+
*/
|
|
11
|
+
export type SafetyBlockKind = "catastrophic" | "dangerous" | "git-safety" | "empty-bash";
|
|
12
|
+
export interface SafetyBlockInfo {
|
|
13
|
+
kind: SafetyBlockKind;
|
|
14
|
+
/** The blocked command or tool call description */
|
|
15
|
+
blockedItem: string;
|
|
16
|
+
/** Human-readable reason from the filter */
|
|
17
|
+
reason: string;
|
|
18
|
+
/** Suggested "safe" alternative, if any */
|
|
19
|
+
alternative?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SafetyAskcardLayout {
|
|
22
|
+
/** Question shown in the dialog title */
|
|
23
|
+
question: string;
|
|
24
|
+
/** Detail text shown below the question */
|
|
25
|
+
detail: string;
|
|
26
|
+
/** Options in render order. First = default (Enter applies). */
|
|
27
|
+
options: SafetyAskcardOption[];
|
|
28
|
+
/** Index of the default-selected option (0 = first). */
|
|
29
|
+
defaultIndex: number;
|
|
30
|
+
}
|
|
31
|
+
export interface SafetyAskcardOption {
|
|
32
|
+
label: string;
|
|
33
|
+
value: SafetyAskResult;
|
|
34
|
+
description?: string;
|
|
35
|
+
}
|
|
36
|
+
export type SafetyAskResult = "allow-once" | "allow-session" | "block";
|
|
37
|
+
/**
|
|
38
|
+
* Plan the askcard layout for a safety block.
|
|
39
|
+
* Pure function — easy to unit test and swap UI strategies.
|
|
40
|
+
*/
|
|
41
|
+
export declare function planSafetyAskcard(info: SafetyBlockInfo): SafetyAskcardLayout;
|
|
42
|
+
/** Info passed to the safety-override handler when a tool block is detected. */
|
|
43
|
+
export interface SafetyOverrideAskInfo {
|
|
44
|
+
kind: SafetyBlockKind;
|
|
45
|
+
/** The blocked tool name (e.g. "bash", "edit_file"). */
|
|
46
|
+
toolName: string;
|
|
47
|
+
/** The command/args that were blocked. */
|
|
48
|
+
blockedItem: string;
|
|
49
|
+
/** Human-readable reason from the filter. */
|
|
50
|
+
reason: string;
|
|
51
|
+
/** Source block kind tag for the agent to decide retry. */
|
|
52
|
+
source: "bash.execute" | "registry.precheck";
|
|
53
|
+
}
|
|
54
|
+
/** Verdict the UI returns after the user answers the askcard. */
|
|
55
|
+
export type SafetyOverrideVerdict = {
|
|
56
|
+
action: "allow-once";
|
|
57
|
+
} | {
|
|
58
|
+
action: "allow-session";
|
|
59
|
+
} | {
|
|
60
|
+
action: "block";
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Build a safe alternative suggestion for a blocked command.
|
|
64
|
+
* Returns null when no canned alternative exists.
|
|
65
|
+
*/
|
|
66
|
+
export declare function suggestAlternative(kind: SafetyBlockKind, command: string): string | undefined;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/orchestrator/safety-askcard.ts
|
|
3
|
+
*
|
|
4
|
+
* Plans an askcard layout when a tool call is blocked by the safety filter
|
|
5
|
+
* (catastrophic, dangerous, git-safety, empty-bash).
|
|
6
|
+
*
|
|
7
|
+
* The askcard gives the user a choice: allow the block once, or confirm the block.
|
|
8
|
+
*
|
|
9
|
+
* Pure — no React, no side effects. Unit-testable in isolation.
|
|
10
|
+
*/
|
|
11
|
+
const CATEGORY_LABELS = {
|
|
12
|
+
catastrophic: "Lỗi bảo mật nghiêm trọng",
|
|
13
|
+
dangerous: "Lệnh nguy hiểm",
|
|
14
|
+
"git-safety": "Git safety gate",
|
|
15
|
+
"empty-bash": "Bash call trống",
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Plan the askcard layout for a safety block.
|
|
19
|
+
* Pure function — easy to unit test and swap UI strategies.
|
|
20
|
+
*/
|
|
21
|
+
export function planSafetyAskcard(info) {
|
|
22
|
+
const kindLabel = CATEGORY_LABELS[info.kind];
|
|
23
|
+
const cmdPreview = info.blockedItem.length > 120 ? `${info.blockedItem.slice(0, 117)}...` : info.blockedItem;
|
|
24
|
+
const question = `⚠️ ${kindLabel}: Cho phép thực thi?`;
|
|
25
|
+
const detailLines = [`Lệnh bị chặn: \`${cmdPreview}\``, `Lý do: ${info.reason}`];
|
|
26
|
+
if (info.alternative) {
|
|
27
|
+
detailLines.push(`Gợi ý thay thế: ${info.alternative}`);
|
|
28
|
+
}
|
|
29
|
+
const options = [
|
|
30
|
+
{
|
|
31
|
+
label: "Cho phép 1 lần (Allow once)",
|
|
32
|
+
value: "allow-once",
|
|
33
|
+
description: "Chỉ chạy lệnh này một lần duy nhất",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "Chặn (Block)",
|
|
37
|
+
value: "block",
|
|
38
|
+
description: "Không chạy lệnh này, trả về lỗi cho agent",
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
// Allow-session only for less severe blocks
|
|
42
|
+
if (info.kind !== "catastrophic") {
|
|
43
|
+
options.splice(1, 0, {
|
|
44
|
+
label: "Cho phép cả phiên (Allow session)",
|
|
45
|
+
value: "allow-session",
|
|
46
|
+
description: "Cho phép tất cả lệnh tương tự trong phiên này",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
question,
|
|
51
|
+
detail: detailLines.join("\n"),
|
|
52
|
+
options,
|
|
53
|
+
defaultIndex: options.findIndex((o) => o.value === "block"),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Build a safe alternative suggestion for a blocked command.
|
|
58
|
+
* Returns null when no canned alternative exists.
|
|
59
|
+
*/
|
|
60
|
+
export function suggestAlternative(kind, command) {
|
|
61
|
+
if (kind === "empty-bash") {
|
|
62
|
+
return 'Provide a real command, e.g. {"command":"ls -la"}';
|
|
63
|
+
}
|
|
64
|
+
// sqlite3 / .db access on Windows
|
|
65
|
+
if (/sqlite3|\.db\b/i.test(command)) {
|
|
66
|
+
return "Use the filesystem MCP or write_file to read the DB file instead of shelling sqlite3";
|
|
67
|
+
}
|
|
68
|
+
// rm -rf patterns
|
|
69
|
+
if (/rm\s+-rf/i.test(command)) {
|
|
70
|
+
return "Explicitly list files to remove, or use move to trash";
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=safety-askcard.js.map
|