@selesai/code 0.5.28 → 0.5.29
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/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +117 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -3
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +11 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +10 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/llama/provider.d.ts.map +1 -1
- package/dist/core/llama/provider.js +8 -3
- package/dist/core/llama/provider.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +20 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +13 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +24 -11
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +15 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +66 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
- package/dist/extensions/pi-intercom/README.md +102 -39
- package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
- package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
- package/dist/extensions/pi-intercom/broker/client.ts +315 -12
- package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
- package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
- package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
- package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
- package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
- package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
- package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
- package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
- package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
- package/dist/extensions/pi-intercom/config.test.ts +93 -0
- package/dist/extensions/pi-intercom/config.ts +55 -6
- package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
- package/dist/extensions/pi-intercom/cwd.ts +31 -0
- package/dist/extensions/pi-intercom/extension-api.ts +44 -0
- package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
- package/dist/extensions/pi-intercom/format-context.ts +32 -0
- package/dist/extensions/pi-intercom/index.ts +742 -145
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
- package/dist/extensions/pi-intercom/package.json +15 -5
- package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
- package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
- package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
- package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
- package/dist/extensions/pi-intercom/types.ts +94 -4
- package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
- package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
- package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
- package/dist/extensions/pi-subagents/CHANGELOG.md +85 -0
- package/dist/extensions/pi-subagents/LICENSE +21 -0
- package/dist/extensions/pi-subagents/README.md +146 -52
- package/dist/extensions/pi-subagents/agents/architect.md +1 -0
- package/dist/extensions/pi-subagents/agents/builder.md +1 -0
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +3 -3
- package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +21 -989
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +256 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +430 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +282 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +71 -30
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
- package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
- package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +16 -12
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +17 -7
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -6
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +8 -7
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +63 -16
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +29 -4
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +29 -6
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +372 -28
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +143 -43
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +527 -247
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +426 -123
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +15 -7
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
- package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
- package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +155 -10
- package/dist/extensions/pi-subagents/src/shared/utils.ts +73 -4
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +5 -0
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
- package/dist/extensions/pi-subagents/src/tui/render.ts +27 -28
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +348 -7
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +213 -13
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +118 -12
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +850 -7
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +102 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +11 -11
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +10 -2
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +46 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +34 -2
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +3 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +43 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +10 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +4 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -64
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +14 -5
- package/docs/environment-variables.md +86 -0
- package/docs/extensions.md +15 -5
- package/docs/index.md +1 -0
- package/docs/models.md +9 -2
- package/docs/providers.md +21 -2
- package/docs/rpc.md +23 -6
- package/docs/session-format.md +2 -0
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -13
- package/examples/extensions/custom-compaction.ts +5 -2
- package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +11 -3
- package/examples/extensions/message-renderer.ts +3 -3
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +5 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/12-full-control.ts +3 -1
- package/package.json +15 -6
- package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
watchdogWarningFromLspDiagnostics,
|
|
10
10
|
type WatchdogLspDiagnosticsFunction,
|
|
11
11
|
} from "./lsp-diagnostics.ts";
|
|
12
|
+
import { WatchdogScopeArtifact, isWatchdogAutoFollowPromptEvent } from "./scope.ts";
|
|
12
13
|
import { resolveWatchdogConfig } from "./settings.ts";
|
|
13
14
|
import { formatWatchdogTurnDelta } from "./turn-delta.ts";
|
|
14
15
|
import {
|
|
@@ -34,6 +35,7 @@ export interface WatchdogReviewResult {
|
|
|
34
35
|
export interface WatchdogReviewRequest {
|
|
35
36
|
delta: string;
|
|
36
37
|
epoch: number;
|
|
38
|
+
hasScope: boolean;
|
|
37
39
|
reviewId: number;
|
|
38
40
|
config: ResolvedWatchdogConfig;
|
|
39
41
|
emitWarning(warning: WatchdogWarning): boolean;
|
|
@@ -60,7 +62,9 @@ export interface WatchdogRuntimeSnapshot {
|
|
|
60
62
|
staleReviews: number;
|
|
61
63
|
reviewConnected: boolean;
|
|
62
64
|
reviewDescription: string;
|
|
63
|
-
autoFollowQueued:
|
|
65
|
+
autoFollowQueued: boolean;
|
|
66
|
+
autoFollowAttempts: number;
|
|
67
|
+
autoFollowStalemate: boolean;
|
|
64
68
|
reviewTrigger: "turn-delta" | "repo-edits";
|
|
65
69
|
changedPaths?: string[];
|
|
66
70
|
lsp: WatchdogLspRuntimeSnapshot;
|
|
@@ -76,7 +80,8 @@ interface MainWatchdogRuntimeOptions {
|
|
|
76
80
|
resolveConfig?: (cwd: string, options?: { session?: Record<string, unknown> }) => WatchdogSettingsResult;
|
|
77
81
|
review?: WatchdogReviewFunction;
|
|
78
82
|
reviewDescription?: string;
|
|
79
|
-
displayWarning?: (warning: WatchdogWarningDetails) => void;
|
|
83
|
+
displayWarning?: (warning: WatchdogWarningDetails, options?: { deliverAs?: "steer" }) => void;
|
|
84
|
+
sendUserMessage?: (message: string) => void | Promise<void>;
|
|
80
85
|
reviewChangesOnly?: boolean;
|
|
81
86
|
lspDiagnostics?: WatchdogLspDiagnosticsFunction;
|
|
82
87
|
repoChangeSignature?: typeof computeWatchdogRepoChangeSignature;
|
|
@@ -111,11 +116,13 @@ export class MainWatchdogRuntime {
|
|
|
111
116
|
private readonly review: WatchdogReviewFunction;
|
|
112
117
|
private readonly reviewConnected: boolean;
|
|
113
118
|
private readonly reviewDescription: string;
|
|
114
|
-
private readonly displayWarning: ((warning: WatchdogWarningDetails) => void) | undefined;
|
|
119
|
+
private readonly displayWarning: ((warning: WatchdogWarningDetails, options?: { deliverAs?: "steer" }) => void) | undefined;
|
|
120
|
+
private readonly sendUserMessage: ((message: string) => void | Promise<void>) | undefined;
|
|
115
121
|
private readonly reviewChangesOnly: boolean;
|
|
116
122
|
private readonly lspDiagnostics: WatchdogLspDiagnosticsFunction;
|
|
117
123
|
private readonly repoChangeSignature: typeof computeWatchdogRepoChangeSignature;
|
|
118
124
|
private readonly lspLedger = new WatchdogLspDiagnosticsLedger();
|
|
125
|
+
private readonly scope = new WatchdogScopeArtifact();
|
|
119
126
|
private configResult: WatchdogSettingsResult;
|
|
120
127
|
private sessionOverrideEnabled: boolean | undefined;
|
|
121
128
|
private sessionModelOverride: Partial<Pick<WatchdogEndpointConfig, "model" | "thinking">> | undefined;
|
|
@@ -138,6 +145,7 @@ export class MainWatchdogRuntime {
|
|
|
138
145
|
private userPrompt: string | undefined;
|
|
139
146
|
private waiters: Waiter[] = [];
|
|
140
147
|
private lastWarning: WatchdogWarningDetails | undefined;
|
|
148
|
+
private displayedWarningSequence = 0;
|
|
141
149
|
private lastError: string | undefined;
|
|
142
150
|
private lastReviewInputSignature: string | undefined;
|
|
143
151
|
private turnStartChangeSignature: WatchdogRepoChangeSignature | undefined;
|
|
@@ -145,6 +153,16 @@ export class MainWatchdogRuntime {
|
|
|
145
153
|
private currentChangedPaths: string[] | undefined;
|
|
146
154
|
private lastLspSnapshot: WatchdogLspRuntimeSnapshot | undefined;
|
|
147
155
|
private observedRepoEditThisTurn = false;
|
|
156
|
+
private toolResultsThisRun = 0;
|
|
157
|
+
private midRunReviewing = false;
|
|
158
|
+
private autoFollowQueued = false;
|
|
159
|
+
private autoFollowAttempts = 0;
|
|
160
|
+
private consecutiveAutoFollowIdentity: string | undefined;
|
|
161
|
+
private consecutiveAutoFollowRepeats = 0;
|
|
162
|
+
private autoFollowStalemate = false;
|
|
163
|
+
private pendingAutoFollowPrompts: string[] = [];
|
|
164
|
+
private midRunGeneration = 0;
|
|
165
|
+
private activeReviewAbortController: AbortController | undefined;
|
|
148
166
|
private failedReviews = 0;
|
|
149
167
|
private staleReviews = 0;
|
|
150
168
|
|
|
@@ -155,6 +173,7 @@ export class MainWatchdogRuntime {
|
|
|
155
173
|
this.reviewConnected = Boolean(options.review);
|
|
156
174
|
this.reviewDescription = options.reviewDescription ?? (options.review ? "injected seam" : "not wired");
|
|
157
175
|
this.displayWarning = options.displayWarning;
|
|
176
|
+
this.sendUserMessage = options.sendUserMessage;
|
|
158
177
|
this.reviewChangesOnly = options.reviewChangesOnly === true;
|
|
159
178
|
this.lspDiagnostics = options.lspDiagnostics ?? collectWatchdogLspDiagnostics;
|
|
160
179
|
this.repoChangeSignature = options.repoChangeSignature ?? computeWatchdogRepoChangeSignature;
|
|
@@ -170,7 +189,7 @@ export class MainWatchdogRuntime {
|
|
|
170
189
|
this.sessionOverrideEnabled = undefined;
|
|
171
190
|
this.sessionModelOverride = undefined;
|
|
172
191
|
this.refreshConfig(ctx.cwd);
|
|
173
|
-
this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true });
|
|
192
|
+
this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true, clearScope: true, resetAutoFollow: true });
|
|
174
193
|
}
|
|
175
194
|
|
|
176
195
|
refreshConfig(cwd = this.cwd): WatchdogSettingsResult {
|
|
@@ -228,7 +247,7 @@ export class MainWatchdogRuntime {
|
|
|
228
247
|
return this.getSnapshot();
|
|
229
248
|
}
|
|
230
249
|
|
|
231
|
-
reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean } = {}): void {
|
|
250
|
+
reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean; clearScope?: boolean; resetAutoFollow?: boolean } = {}): void {
|
|
232
251
|
this.abortActiveAgentEnd();
|
|
233
252
|
this.epoch++;
|
|
234
253
|
this.status = "idle";
|
|
@@ -242,10 +261,18 @@ export class MainWatchdogRuntime {
|
|
|
242
261
|
this.lastError = undefined;
|
|
243
262
|
this.currentChangedPaths = undefined;
|
|
244
263
|
this.observedRepoEditThisTurn = false;
|
|
264
|
+
this.toolResultsThisRun = 0;
|
|
265
|
+
this.midRunReviewing = false;
|
|
266
|
+
this.autoFollowQueued = false;
|
|
245
267
|
if (options.clearLspLedger) {
|
|
246
268
|
this.lspLedger.reset();
|
|
247
269
|
this.lastLspSnapshot = undefined;
|
|
248
270
|
}
|
|
271
|
+
if (options.clearScope) {
|
|
272
|
+
this.scope.reset();
|
|
273
|
+
this.pendingAutoFollowPrompts = [];
|
|
274
|
+
}
|
|
275
|
+
if (options.resetAutoFollow) this.resetAutoFollowState();
|
|
249
276
|
if (options.clearReviewInputSignature) this.lastReviewInputSignature = undefined;
|
|
250
277
|
if (options.resetChangeSignature) this.resetRepoChangeBaseline({ reviewed: true });
|
|
251
278
|
this.guard.reset();
|
|
@@ -266,16 +293,31 @@ export class MainWatchdogRuntime {
|
|
|
266
293
|
this.currentChangedPaths = undefined;
|
|
267
294
|
this.lastLspSnapshot = undefined;
|
|
268
295
|
this.lspLedger.reset();
|
|
296
|
+
this.scope.reset();
|
|
269
297
|
this.observedRepoEditThisTurn = false;
|
|
298
|
+
this.toolResultsThisRun = 0;
|
|
299
|
+
this.midRunReviewing = false;
|
|
300
|
+
this.autoFollowQueued = false;
|
|
270
301
|
this.resolveWaiters(false);
|
|
271
302
|
}
|
|
272
303
|
|
|
273
304
|
handleBeforeAgentStart(event: unknown, ctx: ContextLike): void {
|
|
274
305
|
if (this.disposed) return;
|
|
275
|
-
|
|
306
|
+
const incomingPrompt = promptFromBeforeAgentStart(event);
|
|
307
|
+
// Only exact queued auto-follow text is treated as an auto-follow turn; a real user
|
|
308
|
+
// prompt racing in ahead of one stays real and the pending matches survive for later.
|
|
309
|
+
const pendingIndex = incomingPrompt === undefined ? -1 : this.pendingAutoFollowPrompts.indexOf(incomingPrompt);
|
|
310
|
+
const autoFollowPrompt = pendingIndex >= 0 || isWatchdogAutoFollowPromptEvent(event);
|
|
311
|
+
if (pendingIndex >= 0) this.pendingAutoFollowPrompts.splice(pendingIndex, 1);
|
|
312
|
+
this.reset("before_agent_start", { resetAutoFollow: !autoFollowPrompt });
|
|
276
313
|
this.refreshConfig(ctx.cwd);
|
|
277
|
-
this.userPrompt =
|
|
278
|
-
|
|
314
|
+
this.userPrompt = incomingPrompt;
|
|
315
|
+
if (!autoFollowPrompt && this.userPrompt?.trim()) {
|
|
316
|
+
this.includeUserPromptInNextDelta = true;
|
|
317
|
+
this.scope.addPrompt(this.userPrompt);
|
|
318
|
+
} else {
|
|
319
|
+
this.includeUserPromptInNextDelta = false;
|
|
320
|
+
}
|
|
279
321
|
this.resetRepoChangeBaseline();
|
|
280
322
|
}
|
|
281
323
|
|
|
@@ -300,7 +342,21 @@ export class MainWatchdogRuntime {
|
|
|
300
342
|
enqueueDelta(delta: string): void {
|
|
301
343
|
if (this.disposed || !delta.trim() || !this.isEnabled()) return;
|
|
302
344
|
this.appendBoundedDelta(delta);
|
|
303
|
-
if (!this.reviewing && !this.waitingAtAgentEnd) this.status = "queued";
|
|
345
|
+
if (!this.reviewing && !this.waitingAtAgentEnd && !this.midRunReviewing) this.status = "queued";
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
handleToolResult(ctx: ContextLike): void {
|
|
349
|
+
if (this.disposed) return;
|
|
350
|
+
this.refreshConfig(ctx.cwd);
|
|
351
|
+
if (!this.isEnabled()) return;
|
|
352
|
+
const everyNTools = this.configResult.config.cadence.everyNTools;
|
|
353
|
+
if (everyNTools === null) return;
|
|
354
|
+
this.toolResultsThisRun++;
|
|
355
|
+
if (this.toolResultsThisRun % everyNTools !== 0) return;
|
|
356
|
+
if (this.reviewing || this.waitingAtAgentEnd || this.midRunReviewing) return;
|
|
357
|
+
const delta = this.buildReviewInput(undefined, "");
|
|
358
|
+
if (!delta.trim()) return;
|
|
359
|
+
void this.reviewMidRunDelta(delta);
|
|
304
360
|
}
|
|
305
361
|
|
|
306
362
|
async handleAgentEnd(_event: unknown, ctx: ContextLike): Promise<void> {
|
|
@@ -320,12 +376,15 @@ export class MainWatchdogRuntime {
|
|
|
320
376
|
this.resolveWaiters(true);
|
|
321
377
|
return;
|
|
322
378
|
}
|
|
379
|
+
this.cancelMidRunReview();
|
|
323
380
|
this.waitingAtAgentEnd = true;
|
|
324
381
|
const agentEndEpoch = this.epoch;
|
|
325
382
|
const agentEndId = ++this.agentEndIdCounter;
|
|
326
383
|
const lspAbortController = new AbortController();
|
|
327
384
|
this.activeAgentEndId = agentEndId;
|
|
328
385
|
this.activeAgentEndAbortController = lspAbortController;
|
|
386
|
+
let displayedDuringAgentEnd: WatchdogWarningDetails | undefined;
|
|
387
|
+
const previousDisplayedSequence = this.displayedWarningSequence;
|
|
329
388
|
try {
|
|
330
389
|
this.guard.startModelUpdate();
|
|
331
390
|
const lspBlock = await this.collectLspDiagnostics(changeSignature, {
|
|
@@ -366,6 +425,8 @@ export class MainWatchdogRuntime {
|
|
|
366
425
|
this.currentChangedPaths = changeSignature?.changedPaths;
|
|
367
426
|
this.status = "idle";
|
|
368
427
|
}
|
|
428
|
+
displayedDuringAgentEnd = this.displayedWarningSequence !== previousDisplayedSequence ? this.lastWarning : undefined;
|
|
429
|
+
this.queueAutoFollowIfNeeded(displayedDuringAgentEnd);
|
|
369
430
|
this.resolveWaiters(true);
|
|
370
431
|
} finally {
|
|
371
432
|
if (this.activeAgentEndAbortController === lspAbortController) this.activeAgentEndAbortController = undefined;
|
|
@@ -399,7 +460,9 @@ export class MainWatchdogRuntime {
|
|
|
399
460
|
staleReviews: this.staleReviews,
|
|
400
461
|
reviewConnected: this.reviewConnected,
|
|
401
462
|
reviewDescription: this.reviewDescription,
|
|
402
|
-
autoFollowQueued:
|
|
463
|
+
autoFollowQueued: this.autoFollowQueued,
|
|
464
|
+
autoFollowAttempts: this.autoFollowAttempts,
|
|
465
|
+
autoFollowStalemate: this.autoFollowStalemate,
|
|
403
466
|
reviewTrigger: this.reviewChangesOnly ? "repo-edits" : "turn-delta",
|
|
404
467
|
...(this.currentChangedPaths?.length ? { changedPaths: [...this.currentChangedPaths] } : {}),
|
|
405
468
|
lsp: this.lspSnapshot(),
|
|
@@ -428,8 +491,12 @@ export class MainWatchdogRuntime {
|
|
|
428
491
|
return !this.disposed && this.epoch === epoch && this.activeReviewId === reviewId;
|
|
429
492
|
}
|
|
430
493
|
|
|
494
|
+
private warningMeetsThreshold(warning: WatchdogWarning): boolean {
|
|
495
|
+
return this.configResult.config.severityThreshold === "concern" || warning.severity === "blocker";
|
|
496
|
+
}
|
|
497
|
+
|
|
431
498
|
private acceptWarning(epoch: number, reviewId: number, warning: WatchdogWarning): boolean {
|
|
432
|
-
if (!this.isCurrent(epoch, reviewId) || !this.isEnabled()) return false;
|
|
499
|
+
if (!this.isCurrent(epoch, reviewId) || !this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
|
|
433
500
|
const decision = this.guard.evaluate(warning);
|
|
434
501
|
if (!decision.accepted) return false;
|
|
435
502
|
const details = normalizeWatchdogWarningDetails(warning, {
|
|
@@ -443,7 +510,7 @@ export class MainWatchdogRuntime {
|
|
|
443
510
|
}
|
|
444
511
|
|
|
445
512
|
private displayBoundaryWarning(warning: WatchdogWarning): boolean {
|
|
446
|
-
if (!this.isEnabled()) return false;
|
|
513
|
+
if (!this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
|
|
447
514
|
const decision = this.guard.evaluate(warning);
|
|
448
515
|
if (!decision.accepted) return false;
|
|
449
516
|
const details = normalizeWatchdogWarningDetails(warning, {
|
|
@@ -453,6 +520,7 @@ export class MainWatchdogRuntime {
|
|
|
453
520
|
displayedAt: new Date().toISOString(),
|
|
454
521
|
});
|
|
455
522
|
this.lastWarning = details;
|
|
523
|
+
this.displayedWarningSequence++;
|
|
456
524
|
this.displayWarning?.(details);
|
|
457
525
|
return true;
|
|
458
526
|
}
|
|
@@ -468,7 +536,41 @@ export class MainWatchdogRuntime {
|
|
|
468
536
|
this.activeReviewWarning = undefined;
|
|
469
537
|
}
|
|
470
538
|
|
|
471
|
-
private async
|
|
539
|
+
private async reviewMidRunDelta(delta: string): Promise<void> {
|
|
540
|
+
if (this.midRunReviewing || this.reviewing || this.waitingAtAgentEnd || this.disposed) return;
|
|
541
|
+
this.midRunReviewing = true;
|
|
542
|
+
const generation = this.midRunGeneration;
|
|
543
|
+
try {
|
|
544
|
+
const outcome = await this.reviewDelta(delta, this.configResult.config.agentEndTimeoutMs, { correction: true });
|
|
545
|
+
if (generation !== this.midRunGeneration) return;
|
|
546
|
+
if (outcome === "timeout") {
|
|
547
|
+
this.staleReviews++;
|
|
548
|
+
this.status = "stale";
|
|
549
|
+
this.markLastWarningStale();
|
|
550
|
+
}
|
|
551
|
+
} finally {
|
|
552
|
+
if (generation === this.midRunGeneration) {
|
|
553
|
+
this.midRunReviewing = false;
|
|
554
|
+
if (this.status === "reviewing") this.status = this.pendingDeltas.length ? "queued" : "idle";
|
|
555
|
+
this.resolveWaiters(this.isSettled());
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// The agent-end boundary review is authoritative; an in-flight cadence review is superseded.
|
|
561
|
+
private cancelMidRunReview(): void {
|
|
562
|
+
if (!this.midRunReviewing) return;
|
|
563
|
+
this.midRunGeneration++;
|
|
564
|
+
this.activeReviewAbortController?.abort();
|
|
565
|
+
this.activeReviewAbortController = undefined;
|
|
566
|
+
this.staleReviews++;
|
|
567
|
+
this.reviewing = false;
|
|
568
|
+
this.midRunReviewing = false;
|
|
569
|
+
this.activeReviewId = undefined;
|
|
570
|
+
this.activeReviewWarning = undefined;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private async reviewDelta(delta: string, timeoutMs: number, options: { correction?: boolean } = {}): Promise<ReviewDeltaOutcome> {
|
|
472
574
|
if (this.reviewing || this.disposed) return "stale";
|
|
473
575
|
this.reviewing = true;
|
|
474
576
|
const reviewEpoch = this.epoch;
|
|
@@ -478,11 +580,13 @@ export class MainWatchdogRuntime {
|
|
|
478
580
|
this.status = "reviewing";
|
|
479
581
|
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
480
582
|
const abortController = new AbortController();
|
|
583
|
+
this.activeReviewAbortController = abortController;
|
|
481
584
|
const reviewPromise = Promise.resolve().then(() => this.review({
|
|
482
585
|
delta,
|
|
483
586
|
epoch: reviewEpoch,
|
|
484
587
|
reviewId,
|
|
485
588
|
config: this.configResult.config,
|
|
589
|
+
hasScope: this.scopeBlock().trim().length > 0,
|
|
486
590
|
signal: abortController.signal,
|
|
487
591
|
emitWarning: (warning) => this.acceptWarning(reviewEpoch, reviewId, warning),
|
|
488
592
|
}));
|
|
@@ -503,7 +607,7 @@ export class MainWatchdogRuntime {
|
|
|
503
607
|
this.fail(`Watchdog review ended with stop reason '${result.stopReason}'.`);
|
|
504
608
|
return "completed";
|
|
505
609
|
}
|
|
506
|
-
this.displayAcceptedReviewWarning();
|
|
610
|
+
this.displayAcceptedReviewWarning(options.correction);
|
|
507
611
|
return "completed";
|
|
508
612
|
} catch (error) {
|
|
509
613
|
if (this.isCurrent(reviewEpoch, reviewId)) {
|
|
@@ -513,6 +617,7 @@ export class MainWatchdogRuntime {
|
|
|
513
617
|
return "stale";
|
|
514
618
|
} finally {
|
|
515
619
|
if (timeout) clearTimeout(timeout);
|
|
620
|
+
if (this.activeReviewAbortController === abortController) this.activeReviewAbortController = undefined;
|
|
516
621
|
if (this.epoch === reviewEpoch && this.activeReviewId === reviewId) {
|
|
517
622
|
this.reviewing = false;
|
|
518
623
|
this.activeReviewId = undefined;
|
|
@@ -522,7 +627,7 @@ export class MainWatchdogRuntime {
|
|
|
522
627
|
}
|
|
523
628
|
}
|
|
524
629
|
|
|
525
|
-
private displayAcceptedReviewWarning(): void {
|
|
630
|
+
private displayAcceptedReviewWarning(correction = false): void {
|
|
526
631
|
if (!this.activeReviewWarning) return;
|
|
527
632
|
const details: WatchdogWarningDetails = {
|
|
528
633
|
...this.activeReviewWarning,
|
|
@@ -530,7 +635,50 @@ export class MainWatchdogRuntime {
|
|
|
530
635
|
displayedAt: new Date().toISOString(),
|
|
531
636
|
};
|
|
532
637
|
this.lastWarning = details;
|
|
533
|
-
this.
|
|
638
|
+
this.displayedWarningSequence++;
|
|
639
|
+
this.displayWarning?.(details, correction ? { deliverAs: "steer" } : undefined);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
private resetAutoFollowState(): void {
|
|
643
|
+
this.autoFollowQueued = false;
|
|
644
|
+
this.autoFollowAttempts = 0;
|
|
645
|
+
this.consecutiveAutoFollowIdentity = undefined;
|
|
646
|
+
this.consecutiveAutoFollowRepeats = 0;
|
|
647
|
+
this.autoFollowStalemate = false;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
private queueAutoFollowIfNeeded(warning: WatchdogWarningDetails | undefined): void {
|
|
651
|
+
if (!warning || warning.severity !== "blocker" || warning.stale || !this.configResult.config.autoFollow.blockers || !this.isEnabled()) return;
|
|
652
|
+
const identity = warning.identity ?? reviewInputSignature([warning.severity, warning.summary, warning.evidence].join("\n"));
|
|
653
|
+
if (this.consecutiveAutoFollowIdentity === identity) this.consecutiveAutoFollowRepeats++;
|
|
654
|
+
else {
|
|
655
|
+
this.consecutiveAutoFollowIdentity = identity;
|
|
656
|
+
this.consecutiveAutoFollowRepeats = 1;
|
|
657
|
+
}
|
|
658
|
+
if (this.consecutiveAutoFollowRepeats >= this.configResult.config.autoFollow.stalemateRepeats) {
|
|
659
|
+
this.autoFollowStalemate = true;
|
|
660
|
+
this.lastWarning = { ...warning, state: "stalemate", stalemateRepeats: this.consecutiveAutoFollowRepeats };
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
const maxAttempts = this.configResult.config.autoFollow.maxAttempts;
|
|
664
|
+
if (maxAttempts !== null && this.autoFollowAttempts >= maxAttempts) return;
|
|
665
|
+
if (!this.sendUserMessage) return;
|
|
666
|
+
this.autoFollowAttempts++;
|
|
667
|
+
this.autoFollowQueued = true;
|
|
668
|
+
const prompt = [
|
|
669
|
+
"Watchdog auto-follow: address this blocker before continuing.",
|
|
670
|
+
`Summary: ${warning.summary}`,
|
|
671
|
+
`Evidence: ${warning.evidence}`,
|
|
672
|
+
`Recommended action: ${warning.recommendedAction}`,
|
|
673
|
+
].join("\n");
|
|
674
|
+
this.pendingAutoFollowPrompts.push(prompt);
|
|
675
|
+
if (this.pendingAutoFollowPrompts.length > 8) this.pendingAutoFollowPrompts.shift();
|
|
676
|
+
void Promise.resolve(this.sendUserMessage(prompt)).catch((error) => {
|
|
677
|
+
this.autoFollowQueued = false;
|
|
678
|
+
const index = this.pendingAutoFollowPrompts.indexOf(prompt);
|
|
679
|
+
if (index >= 0) this.pendingAutoFollowPrompts.splice(index, 1);
|
|
680
|
+
this.lastError = `Watchdog auto-follow failed: ${errorMessage(error)}`;
|
|
681
|
+
});
|
|
534
682
|
}
|
|
535
683
|
|
|
536
684
|
private currentRepoChangeSignature(cwd = this.cwd): WatchdogRepoChangeSignature | undefined {
|
|
@@ -645,10 +793,11 @@ export class MainWatchdogRuntime {
|
|
|
645
793
|
|
|
646
794
|
private buildReviewInput(changeSignature?: WatchdogRepoChangeSignature, lspBlock = ""): string {
|
|
647
795
|
const input = this.pendingDeltas.join(REVIEW_DELTA_SEPARATOR);
|
|
796
|
+
const scopeBlock = this.scopeBlock();
|
|
648
797
|
const changes = changeSignature?.changedPaths.length
|
|
649
798
|
? ["Changed repo paths:", ...changeSignature.changedPaths.slice(0, 200).map((file) => `- ${file}`)].join("\n")
|
|
650
799
|
: "";
|
|
651
|
-
const contextPieces = [changes, lspBlock].filter(Boolean);
|
|
800
|
+
const contextPieces = [scopeBlock, changes, lspBlock].filter(Boolean);
|
|
652
801
|
if (!contextPieces.length) return input.length > MAX_REVIEW_INPUT_CHARS ? input.slice(-MAX_REVIEW_INPUT_CHARS) : input;
|
|
653
802
|
|
|
654
803
|
const maxContextLength = Math.floor(MAX_REVIEW_INPUT_CHARS / 2);
|
|
@@ -666,6 +815,10 @@ export class MainWatchdogRuntime {
|
|
|
666
815
|
return [boundedContext, boundedInput].filter(Boolean).join(REVIEW_DELTA_SEPARATOR);
|
|
667
816
|
}
|
|
668
817
|
|
|
818
|
+
private scopeBlock(): string {
|
|
819
|
+
return this.configResult.config.scope.enabled ? this.scope.render() : "";
|
|
820
|
+
}
|
|
821
|
+
|
|
669
822
|
private clearPendingDeltas(): void {
|
|
670
823
|
this.pendingDeltas = [];
|
|
671
824
|
this.pendingDeltaChars = 0;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER = Symbol("subagent-watchdog-auto-follow-prompt");
|
|
2
|
+
|
|
3
|
+
const MAX_SCOPE_ENTRIES = 8;
|
|
4
|
+
const MAX_SCOPE_ENTRY_CHARS = 2_000;
|
|
5
|
+
const MAX_SCOPE_TOTAL_CHARS = 16_000;
|
|
6
|
+
|
|
7
|
+
export interface WatchdogScopeEntry {
|
|
8
|
+
prompt: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class WatchdogScopeArtifact {
|
|
13
|
+
private entries: WatchdogScopeEntry[] = [];
|
|
14
|
+
|
|
15
|
+
addPrompt(prompt: string, options: { createdAt?: string } = {}): void {
|
|
16
|
+
const normalized = prompt.trim();
|
|
17
|
+
if (!normalized) return;
|
|
18
|
+
this.entries.push({
|
|
19
|
+
prompt: normalized.length > MAX_SCOPE_ENTRY_CHARS ? normalized.slice(0, MAX_SCOPE_ENTRY_CHARS) : normalized,
|
|
20
|
+
createdAt: options.createdAt ?? new Date().toISOString(),
|
|
21
|
+
});
|
|
22
|
+
this.trim();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
reset(): void {
|
|
26
|
+
this.entries = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
snapshot(): WatchdogScopeEntry[] {
|
|
30
|
+
return this.entries.map((entry) => ({ ...entry }));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
render(): string {
|
|
34
|
+
if (!this.entries.length) return "";
|
|
35
|
+
return [
|
|
36
|
+
"Current scope:",
|
|
37
|
+
"The following real user prompts are the current scope record, newest last. Newer prompts supersede and mutate older prompts: they may add, modify, or remove requirements. Flag work that serves no current scope item as category 'scope-drift'.",
|
|
38
|
+
...this.entries.map((entry, index) => [
|
|
39
|
+
`Scope prompt ${index + 1} (${entry.createdAt}):`,
|
|
40
|
+
entry.prompt,
|
|
41
|
+
].join("\n")),
|
|
42
|
+
].join("\n\n");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private trim(): void {
|
|
46
|
+
while (this.entries.length > MAX_SCOPE_ENTRIES) this.entries.shift();
|
|
47
|
+
let total = this.entries.reduce((sum, entry) => sum + entry.prompt.length, 0);
|
|
48
|
+
while (this.entries.length > 1 && total > MAX_SCOPE_TOTAL_CHARS) {
|
|
49
|
+
const removed = this.entries.shift();
|
|
50
|
+
if (removed) total -= removed.prompt.length;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isWatchdogAutoFollowPromptEvent(event: unknown): boolean {
|
|
56
|
+
return Boolean(event && typeof event === "object" && (event as { [WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER]?: unknown })[WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER]);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function markWatchdogAutoFollowPromptEvent<T extends object>(event: T): T {
|
|
60
|
+
Object.defineProperty(event, WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER, { value: true });
|
|
61
|
+
return event;
|
|
62
|
+
}
|
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
type WatchdogChildrenConfig,
|
|
14
14
|
type WatchdogDeliveryMode,
|
|
15
15
|
type WatchdogEndpointConfig,
|
|
16
|
+
type WatchdogCadenceConfig,
|
|
16
17
|
type WatchdogGuidanceConfig,
|
|
17
18
|
type WatchdogLateWarningPolicy,
|
|
19
|
+
type WatchdogScopeConfig,
|
|
18
20
|
type WatchdogLspConfig,
|
|
19
21
|
type WatchdogSettingsError,
|
|
20
22
|
type WatchdogSettingsResult,
|
|
@@ -25,6 +27,8 @@ import {
|
|
|
25
27
|
|
|
26
28
|
type WatchdogAutoFollowPatch = Partial<WatchdogAutoFollowConfig>;
|
|
27
29
|
type WatchdogGuidancePatch = Partial<WatchdogGuidanceConfig>;
|
|
30
|
+
type WatchdogScopePatch = Partial<WatchdogScopeConfig>;
|
|
31
|
+
type WatchdogCadencePatch = Partial<WatchdogCadenceConfig>;
|
|
28
32
|
type WatchdogEndpointPatch = Partial<WatchdogEndpointConfig>;
|
|
29
33
|
type WatchdogChildOverridePatch = Partial<WatchdogChildOverrideConfig>;
|
|
30
34
|
type WatchdogChildrenPatch = Partial<Omit<WatchdogChildrenConfig, "autoFollow" | "overrides">> & {
|
|
@@ -48,9 +52,11 @@ export interface WatchdogModelSettingsWrite {
|
|
|
48
52
|
thinking?: ThinkingLevel | false | null;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
type WatchdogConfigPatch = Partial<Omit<ResolvedWatchdogConfig, "guidance" | "autoFollow" | "main" | "children" | "asyncCompletion" | "lsp">> & {
|
|
55
|
+
type WatchdogConfigPatch = Partial<Omit<ResolvedWatchdogConfig, "guidance" | "autoFollow" | "scope" | "cadence" | "main" | "children" | "asyncCompletion" | "lsp">> & {
|
|
52
56
|
guidance?: WatchdogGuidancePatch;
|
|
53
57
|
autoFollow?: WatchdogAutoFollowPatch;
|
|
58
|
+
scope?: WatchdogScopePatch;
|
|
59
|
+
cadence?: WatchdogCadencePatch;
|
|
54
60
|
main?: WatchdogEndpointPatch;
|
|
55
61
|
children?: WatchdogChildrenPatch;
|
|
56
62
|
asyncCompletion?: WatchdogAsyncCompletionPatch;
|
|
@@ -80,6 +86,12 @@ export const DEFAULT_WATCHDOG_CONFIG: ResolvedWatchdogConfig = {
|
|
|
80
86
|
maxAttempts: 3,
|
|
81
87
|
stalemateRepeats: 3,
|
|
82
88
|
},
|
|
89
|
+
scope: {
|
|
90
|
+
enabled: true,
|
|
91
|
+
},
|
|
92
|
+
cadence: {
|
|
93
|
+
everyNTools: null,
|
|
94
|
+
},
|
|
83
95
|
main: {
|
|
84
96
|
enabled: false,
|
|
85
97
|
},
|
|
@@ -119,6 +131,8 @@ const WATCHDOG_FIELDS = new Set([
|
|
|
119
131
|
"maxWarnings",
|
|
120
132
|
"guidance",
|
|
121
133
|
"autoFollow",
|
|
134
|
+
"scope",
|
|
135
|
+
"cadence",
|
|
122
136
|
"main",
|
|
123
137
|
"children",
|
|
124
138
|
"asyncCompletion",
|
|
@@ -129,6 +143,8 @@ const WATCHDOG_FIELDS = new Set([
|
|
|
129
143
|
]);
|
|
130
144
|
const GUIDANCE_FIELDS = new Set(["watchdogMd", "systemPromptPath"]);
|
|
131
145
|
const AUTO_FOLLOW_FIELDS = new Set(["blockers", "maxAttempts", "stalemateRepeats"]);
|
|
146
|
+
const SCOPE_FIELDS = new Set(["enabled"]);
|
|
147
|
+
const CADENCE_FIELDS = new Set(["everyNTools"]);
|
|
132
148
|
const ENDPOINT_FIELDS = new Set(["enabled", "model", "thinking"]);
|
|
133
149
|
const CHILDREN_FIELDS = new Set(["enabled", "model", "thinking", "watchdogTailTimeoutMs", "autoFollow", "overrides"]);
|
|
134
150
|
const CHILD_OVERRIDE_FIELDS = new Set(["enabled", "model", "thinking"]);
|
|
@@ -140,6 +156,8 @@ function cloneDefaultConfig(): ResolvedWatchdogConfig {
|
|
|
140
156
|
...DEFAULT_WATCHDOG_CONFIG,
|
|
141
157
|
guidance: { ...DEFAULT_WATCHDOG_CONFIG.guidance },
|
|
142
158
|
autoFollow: { ...DEFAULT_WATCHDOG_CONFIG.autoFollow },
|
|
159
|
+
scope: { ...DEFAULT_WATCHDOG_CONFIG.scope },
|
|
160
|
+
cadence: { ...DEFAULT_WATCHDOG_CONFIG.cadence },
|
|
143
161
|
main: { ...DEFAULT_WATCHDOG_CONFIG.main },
|
|
144
162
|
children: {
|
|
145
163
|
...DEFAULT_WATCHDOG_CONFIG.children,
|
|
@@ -241,6 +259,26 @@ function parseAutoFollowPatch(value: unknown, field: string, meta: ParseMeta): W
|
|
|
241
259
|
return patch;
|
|
242
260
|
}
|
|
243
261
|
|
|
262
|
+
function parseScopePatch(value: unknown, field: string, meta: ParseMeta): WatchdogScopePatch {
|
|
263
|
+
const input = parseObject(value, field, meta);
|
|
264
|
+
assertKnownFields(input, SCOPE_FIELDS, field, meta);
|
|
265
|
+
const patch: WatchdogScopePatch = {};
|
|
266
|
+
if ("enabled" in input) patch.enabled = parseBoolean(input.enabled, `${field}.enabled`, meta);
|
|
267
|
+
return patch;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function parseCadencePatch(value: unknown, field: string, meta: ParseMeta): WatchdogCadencePatch {
|
|
271
|
+
const input = parseObject(value, field, meta);
|
|
272
|
+
assertKnownFields(input, CADENCE_FIELDS, field, meta);
|
|
273
|
+
const patch: WatchdogCadencePatch = {};
|
|
274
|
+
if ("everyNTools" in input) {
|
|
275
|
+
patch.everyNTools = input.everyNTools === null
|
|
276
|
+
? null
|
|
277
|
+
: parseInteger(input.everyNTools, `${field}.everyNTools`, meta, "null or an integer >= 5", (candidate) => candidate >= 5);
|
|
278
|
+
}
|
|
279
|
+
return patch;
|
|
280
|
+
}
|
|
281
|
+
|
|
244
282
|
function parseEndpointPatch(value: unknown, field: string, meta: ParseMeta): WatchdogEndpointPatch {
|
|
245
283
|
const input = parseObject(value, field, meta);
|
|
246
284
|
assertKnownFields(input, ENDPOINT_FIELDS, field, meta);
|
|
@@ -325,6 +363,8 @@ function parseWatchdogPatch(value: unknown, field: string, meta: ParseMeta): Wat
|
|
|
325
363
|
}
|
|
326
364
|
if ("guidance" in input) patch.guidance = parseGuidancePatch(input.guidance, `${field}.guidance`, meta);
|
|
327
365
|
if ("autoFollow" in input) patch.autoFollow = parseAutoFollowPatch(input.autoFollow, `${field}.autoFollow`, meta);
|
|
366
|
+
if ("scope" in input) patch.scope = parseScopePatch(input.scope, `${field}.scope`, meta);
|
|
367
|
+
if ("cadence" in input) patch.cadence = parseCadencePatch(input.cadence, `${field}.cadence`, meta);
|
|
328
368
|
if ("main" in input) patch.main = parseEndpointPatch(input.main, `${field}.main`, meta);
|
|
329
369
|
if ("children" in input) patch.children = parseChildrenPatch(input.children, `${field}.children`, meta);
|
|
330
370
|
if ("asyncCompletion" in input) patch.asyncCompletion = parseAsyncCompletionPatch(input.asyncCompletion, `${field}.asyncCompletion`, meta);
|
|
@@ -92,6 +92,14 @@ export interface WatchdogGuidanceConfig {
|
|
|
92
92
|
systemPromptPath: string | null;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
export interface WatchdogScopeConfig {
|
|
96
|
+
enabled: boolean;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface WatchdogCadenceConfig {
|
|
100
|
+
everyNTools: number | null;
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
export interface WatchdogEndpointConfig {
|
|
96
104
|
enabled: boolean;
|
|
97
105
|
model?: string;
|
|
@@ -159,6 +167,8 @@ export interface ResolvedWatchdogConfig {
|
|
|
159
167
|
maxWarnings: number | null;
|
|
160
168
|
guidance: WatchdogGuidanceConfig;
|
|
161
169
|
autoFollow: WatchdogAutoFollowConfig;
|
|
170
|
+
scope: WatchdogScopeConfig;
|
|
171
|
+
cadence: WatchdogCadenceConfig;
|
|
162
172
|
main: WatchdogEndpointConfig;
|
|
163
173
|
children: WatchdogChildrenConfig;
|
|
164
174
|
asyncCompletion: WatchdogAsyncCompletionConfig;
|
|
@@ -191,12 +191,12 @@ Report active tools.`;
|
|
|
191
191
|
|
|
192
192
|
try {
|
|
193
193
|
run = await runRealSubagentSession({
|
|
194
|
-
prompt: "Delegate to a
|
|
194
|
+
prompt: "Delegate to a builder and report its exact result.",
|
|
195
195
|
childText: CHILD_MARKER,
|
|
196
196
|
respond: routeParentThroughSubagent({
|
|
197
197
|
childMarker: CHILD_MARKER,
|
|
198
198
|
subagentArgs: {
|
|
199
|
-
agent: "
|
|
199
|
+
agent: "builder",
|
|
200
200
|
task: "Return the marker from the faux child provider.",
|
|
201
201
|
context: "fresh",
|
|
202
202
|
agentScope: "project",
|