pi-subagents 0.63.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -1
- package/docs/watchdog.md +92 -114
- package/package.json +1 -1
- package/skills/pi-subagents/references/execution-controls.md +4 -3
- package/src/runs/background/async-execution.ts +3 -0
- package/src/runs/background/notify.ts +41 -2
- package/src/runs/background/subagent-runner.ts +23 -1
- package/src/runs/foreground/execution.ts +7 -1
- package/src/runs/foreground/subagent-executor.ts +21 -1
- package/src/runs/shared/acceptance.ts +10 -0
- package/src/runs/shared/async-status-projection.ts +11 -43
- package/src/runs/shared/pi-args.ts +1 -4
- package/src/runs/shared/subagent-control.ts +4 -2
- package/src/shared/types.ts +9 -2
- package/src/tui/render.ts +5 -0
- package/src/watchdog/child-status.ts +54 -33
- package/src/watchdog/diff-tool.ts +77 -0
- package/src/watchdog/emission-guard.ts +5 -3
- package/src/watchdog/guidance.ts +20 -0
- package/src/watchdog/register-child.ts +16 -13
- package/src/watchdog/register-main.ts +10 -9
- package/src/watchdog/render.ts +4 -5
- package/src/watchdog/review.ts +15 -4
- package/src/watchdog/rules.ts +70 -0
- package/src/watchdog/runtime.ts +75 -92
- package/src/watchdog/scope.ts +0 -11
- package/src/watchdog/settings.ts +48 -104
- package/src/watchdog/types.ts +18 -32
- package/src/watchdog/warning-format.ts +0 -1
- package/src/workflows/chat-progress.ts +3 -2
- package/src/workflows/workflow-checklist.ts +10 -12
- package/src/workflows/workflow-preflight.ts +28 -1
package/src/watchdog/runtime.ts
CHANGED
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
watchdogWarningFromLspDiagnostics,
|
|
10
10
|
type WatchdogLspDiagnosticsFunction,
|
|
11
11
|
} from "./lsp-diagnostics.ts";
|
|
12
|
-
import {
|
|
12
|
+
import { ruleViolationWarning, type WatchdogRuleViolation } from "./rules.ts";
|
|
13
|
+
import { WatchdogScopeArtifact } from "./scope.ts";
|
|
13
14
|
import { resolveWatchdogConfig } from "./settings.ts";
|
|
14
15
|
import { formatWatchdogTurnDelta } from "./turn-delta.ts";
|
|
15
16
|
import {
|
|
@@ -62,9 +63,8 @@ export interface WatchdogRuntimeSnapshot {
|
|
|
62
63
|
staleReviews: number;
|
|
63
64
|
reviewConnected: boolean;
|
|
64
65
|
reviewDescription: string;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
autoFollowStalemate: boolean;
|
|
66
|
+
boundaryRepeats: number;
|
|
67
|
+
stalemate: boolean;
|
|
68
68
|
reviewTrigger: "turn-delta" | "repo-edits";
|
|
69
69
|
changedPaths?: string[];
|
|
70
70
|
lsp: WatchdogLspRuntimeSnapshot;
|
|
@@ -80,20 +80,29 @@ interface MainWatchdogRuntimeOptions {
|
|
|
80
80
|
resolveConfig?: (cwd: string, options?: { session?: Record<string, unknown> }) => WatchdogSettingsResult;
|
|
81
81
|
review?: WatchdogReviewFunction;
|
|
82
82
|
reviewDescription?: string;
|
|
83
|
-
displayWarning?: (warning: WatchdogWarningDetails, options?:
|
|
84
|
-
sendUserMessage?: (message: string) => void | Promise<void>;
|
|
83
|
+
displayWarning?: (warning: WatchdogWarningDetails, options?: WatchdogWarningSendOptions) => void;
|
|
85
84
|
reviewChangesOnly?: boolean;
|
|
86
85
|
lspDiagnostics?: WatchdogLspDiagnosticsFunction;
|
|
87
86
|
repoChangeSignature?: typeof computeWatchdogRepoChangeSignature;
|
|
88
87
|
}
|
|
89
88
|
|
|
89
|
+
export type WatchdogWarningSendOptions = { deliverAs: "steer" } | { triggerTurn: false };
|
|
90
|
+
|
|
90
91
|
type ContextLike = Pick<ExtensionContext, "cwd">;
|
|
91
92
|
type ReviewDeltaOutcome = "completed" | "timeout" | "stale";
|
|
92
93
|
|
|
93
94
|
const DEFAULT_REVIEW: WatchdogReviewFunction = () => ({ warnings: [] });
|
|
94
95
|
const MAX_REVIEW_INPUT_CHARS = 24_000;
|
|
96
|
+
const REVIEW_INPUT_HEAD_CHARS = 6_000;
|
|
95
97
|
const REVIEW_DELTA_SEPARATOR = "\n\n---\n\n";
|
|
96
98
|
|
|
99
|
+
export function boundWatchdogReviewText(text: string, cap = MAX_REVIEW_INPUT_CHARS): string {
|
|
100
|
+
if (text.length <= cap) return text;
|
|
101
|
+
const head = Math.min(REVIEW_INPUT_HEAD_CHARS, Math.floor(cap / 4));
|
|
102
|
+
const marker = `\n\n[... about ${text.length - cap} characters omitted ...]\n\n`;
|
|
103
|
+
return `${text.slice(0, head)}${marker}${text.slice(text.length - (cap - head - marker.length))}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
97
106
|
function errorMessage(error: unknown): string {
|
|
98
107
|
return error instanceof Error ? error.message : String(error);
|
|
99
108
|
}
|
|
@@ -116,8 +125,7 @@ export class MainWatchdogRuntime {
|
|
|
116
125
|
private readonly review: WatchdogReviewFunction;
|
|
117
126
|
private readonly reviewConnected: boolean;
|
|
118
127
|
private readonly reviewDescription: string;
|
|
119
|
-
private readonly displayWarning: ((warning: WatchdogWarningDetails, options?:
|
|
120
|
-
private readonly sendUserMessage: ((message: string) => void | Promise<void>) | undefined;
|
|
128
|
+
private readonly displayWarning: ((warning: WatchdogWarningDetails, options?: WatchdogWarningSendOptions) => void) | undefined;
|
|
121
129
|
private readonly reviewChangesOnly: boolean;
|
|
122
130
|
private readonly lspDiagnostics: WatchdogLspDiagnosticsFunction;
|
|
123
131
|
private readonly repoChangeSignature: typeof computeWatchdogRepoChangeSignature;
|
|
@@ -145,7 +153,6 @@ export class MainWatchdogRuntime {
|
|
|
145
153
|
private userPrompt: string | undefined;
|
|
146
154
|
private waiters: Waiter[] = [];
|
|
147
155
|
private lastWarning: WatchdogWarningDetails | undefined;
|
|
148
|
-
private displayedWarningSequence = 0;
|
|
149
156
|
private lastError: string | undefined;
|
|
150
157
|
private lastReviewInputSignature: string | undefined;
|
|
151
158
|
private turnStartChangeSignature: WatchdogRepoChangeSignature | undefined;
|
|
@@ -155,12 +162,10 @@ export class MainWatchdogRuntime {
|
|
|
155
162
|
private observedRepoEditThisTurn = false;
|
|
156
163
|
private toolResultsThisRun = 0;
|
|
157
164
|
private midRunReviewing = false;
|
|
158
|
-
private
|
|
159
|
-
private
|
|
160
|
-
private
|
|
161
|
-
private
|
|
162
|
-
private autoFollowStalemate = false;
|
|
163
|
-
private pendingAutoFollowPrompts: string[] = [];
|
|
165
|
+
private lastBoundaryIdentity: string | undefined;
|
|
166
|
+
private boundaryRepeats = 0;
|
|
167
|
+
private stalemate = false;
|
|
168
|
+
private ruleWarningsThisRun = new Set<string>();
|
|
164
169
|
private midRunGeneration = 0;
|
|
165
170
|
private activeReviewAbortController: AbortController | undefined;
|
|
166
171
|
private failedReviews = 0;
|
|
@@ -173,7 +178,6 @@ export class MainWatchdogRuntime {
|
|
|
173
178
|
this.reviewConnected = Boolean(options.review);
|
|
174
179
|
this.reviewDescription = options.reviewDescription ?? (options.review ? "injected seam" : "not wired");
|
|
175
180
|
this.displayWarning = options.displayWarning;
|
|
176
|
-
this.sendUserMessage = options.sendUserMessage;
|
|
177
181
|
this.reviewChangesOnly = options.reviewChangesOnly === true;
|
|
178
182
|
this.lspDiagnostics = options.lspDiagnostics ?? collectWatchdogLspDiagnostics;
|
|
179
183
|
this.repoChangeSignature = options.repoChangeSignature ?? computeWatchdogRepoChangeSignature;
|
|
@@ -189,7 +193,8 @@ export class MainWatchdogRuntime {
|
|
|
189
193
|
this.sessionOverrideEnabled = undefined;
|
|
190
194
|
this.sessionModelOverride = undefined;
|
|
191
195
|
this.refreshConfig(ctx.cwd);
|
|
192
|
-
this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true, clearScope: true
|
|
196
|
+
this.reset("session_start", { clearReviewInputSignature: true, resetChangeSignature: true, clearLspLedger: true, clearScope: true });
|
|
197
|
+
this.resetBoundaryRepeats();
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
refreshConfig(cwd = this.cwd): WatchdogSettingsResult {
|
|
@@ -247,7 +252,7 @@ export class MainWatchdogRuntime {
|
|
|
247
252
|
return this.getSnapshot();
|
|
248
253
|
}
|
|
249
254
|
|
|
250
|
-
reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean; clearScope?: boolean
|
|
255
|
+
reset(_reason = "reset", options: { clearReviewInputSignature?: boolean; resetChangeSignature?: boolean; clearLspLedger?: boolean; clearScope?: boolean } = {}): void {
|
|
251
256
|
this.abortActiveAgentEnd();
|
|
252
257
|
this.epoch++;
|
|
253
258
|
this.status = "idle";
|
|
@@ -263,16 +268,12 @@ export class MainWatchdogRuntime {
|
|
|
263
268
|
this.observedRepoEditThisTurn = false;
|
|
264
269
|
this.toolResultsThisRun = 0;
|
|
265
270
|
this.midRunReviewing = false;
|
|
266
|
-
this.
|
|
271
|
+
this.ruleWarningsThisRun.clear();
|
|
267
272
|
if (options.clearLspLedger) {
|
|
268
273
|
this.lspLedger.reset();
|
|
269
274
|
this.lastLspSnapshot = undefined;
|
|
270
275
|
}
|
|
271
|
-
if (options.clearScope)
|
|
272
|
-
this.scope.reset();
|
|
273
|
-
this.pendingAutoFollowPrompts = [];
|
|
274
|
-
}
|
|
275
|
-
if (options.resetAutoFollow) this.resetAutoFollowState();
|
|
276
|
+
if (options.clearScope) this.scope.reset();
|
|
276
277
|
if (options.clearReviewInputSignature) this.lastReviewInputSignature = undefined;
|
|
277
278
|
if (options.resetChangeSignature) this.resetRepoChangeBaseline({ reviewed: true });
|
|
278
279
|
this.guard.reset();
|
|
@@ -297,22 +298,17 @@ export class MainWatchdogRuntime {
|
|
|
297
298
|
this.observedRepoEditThisTurn = false;
|
|
298
299
|
this.toolResultsThisRun = 0;
|
|
299
300
|
this.midRunReviewing = false;
|
|
300
|
-
this.autoFollowQueued = false;
|
|
301
301
|
this.resolveWaiters(false);
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
handleBeforeAgentStart(event: unknown, ctx: ContextLike): void {
|
|
305
305
|
if (this.disposed) return;
|
|
306
306
|
const incomingPrompt = promptFromBeforeAgentStart(event);
|
|
307
|
-
|
|
308
|
-
|
|
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 });
|
|
307
|
+
this.reset("before_agent_start");
|
|
308
|
+
this.resetBoundaryRepeats();
|
|
313
309
|
this.refreshConfig(ctx.cwd);
|
|
314
310
|
this.userPrompt = incomingPrompt;
|
|
315
|
-
if (
|
|
311
|
+
if (this.userPrompt?.trim()) {
|
|
316
312
|
this.includeUserPromptInNextDelta = true;
|
|
317
313
|
this.scope.addPrompt(this.userPrompt);
|
|
318
314
|
} else {
|
|
@@ -383,8 +379,6 @@ export class MainWatchdogRuntime {
|
|
|
383
379
|
const lspAbortController = new AbortController();
|
|
384
380
|
this.activeAgentEndId = agentEndId;
|
|
385
381
|
this.activeAgentEndAbortController = lspAbortController;
|
|
386
|
-
let displayedDuringAgentEnd: WatchdogWarningDetails | undefined;
|
|
387
|
-
const previousDisplayedSequence = this.displayedWarningSequence;
|
|
388
382
|
try {
|
|
389
383
|
this.guard.startModelUpdate();
|
|
390
384
|
const lspBlock = await this.collectLspDiagnostics(changeSignature, {
|
|
@@ -425,8 +419,6 @@ export class MainWatchdogRuntime {
|
|
|
425
419
|
this.currentChangedPaths = changeSignature?.changedPaths;
|
|
426
420
|
this.status = "idle";
|
|
427
421
|
}
|
|
428
|
-
displayedDuringAgentEnd = this.displayedWarningSequence !== previousDisplayedSequence ? this.lastWarning : undefined;
|
|
429
|
-
this.queueAutoFollowIfNeeded(displayedDuringAgentEnd);
|
|
430
422
|
this.resolveWaiters(true);
|
|
431
423
|
} finally {
|
|
432
424
|
if (this.activeAgentEndAbortController === lspAbortController) this.activeAgentEndAbortController = undefined;
|
|
@@ -434,6 +426,14 @@ export class MainWatchdogRuntime {
|
|
|
434
426
|
}
|
|
435
427
|
}
|
|
436
428
|
|
|
429
|
+
displayRuleWarning(violation: WatchdogRuleViolation): void {
|
|
430
|
+
if (this.disposed || this.ruleWarningsThisRun.has(violation.summary)) return;
|
|
431
|
+
this.ruleWarningsThisRun.add(violation.summary);
|
|
432
|
+
const details = normalizeWatchdogWarningDetails(ruleViolationWarning(violation), { state: "displayed", displayedAt: new Date().toISOString() });
|
|
433
|
+
this.lastWarning = details;
|
|
434
|
+
this.displayWarning?.(details, { deliverAs: "steer" });
|
|
435
|
+
}
|
|
436
|
+
|
|
437
437
|
recordDisplayedWarning(warning: WatchdogWarning): WatchdogWarningDetails {
|
|
438
438
|
const details = normalizeWatchdogWarningDetails(warning, { state: "displayed", source: warning.source ?? "main" });
|
|
439
439
|
this.lastWarning = details;
|
|
@@ -460,9 +460,8 @@ export class MainWatchdogRuntime {
|
|
|
460
460
|
staleReviews: this.staleReviews,
|
|
461
461
|
reviewConnected: this.reviewConnected,
|
|
462
462
|
reviewDescription: this.reviewDescription,
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
autoFollowStalemate: this.autoFollowStalemate,
|
|
463
|
+
boundaryRepeats: this.boundaryRepeats,
|
|
464
|
+
stalemate: this.stalemate,
|
|
466
465
|
reviewTrigger: this.reviewChangesOnly ? "repo-edits" : "turn-delta",
|
|
467
466
|
...(this.currentChangedPaths?.length ? { changedPaths: [...this.currentChangedPaths] } : {}),
|
|
468
467
|
lsp: this.lspSnapshot(),
|
|
@@ -497,7 +496,7 @@ export class MainWatchdogRuntime {
|
|
|
497
496
|
|
|
498
497
|
private acceptWarning(epoch: number, reviewId: number, warning: WatchdogWarning): boolean {
|
|
499
498
|
if (!this.isCurrent(epoch, reviewId) || !this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
|
|
500
|
-
const decision = this.guard.evaluate(warning);
|
|
499
|
+
const decision = this.guard.evaluate(warning, { allowRepeatOf: this.repeatableBoundaryIdentity() });
|
|
501
500
|
if (!decision.accepted) return false;
|
|
502
501
|
const details = normalizeWatchdogWarningDetails(warning, {
|
|
503
502
|
state: "candidate",
|
|
@@ -511,7 +510,7 @@ export class MainWatchdogRuntime {
|
|
|
511
510
|
|
|
512
511
|
private displayBoundaryWarning(warning: WatchdogWarning): boolean {
|
|
513
512
|
if (!this.isEnabled() || !this.warningMeetsThreshold(warning)) return false;
|
|
514
|
-
const decision = this.guard.evaluate(warning);
|
|
513
|
+
const decision = this.guard.evaluate(warning, { allowRepeatOf: this.repeatableBoundaryIdentity() });
|
|
515
514
|
if (!decision.accepted) return false;
|
|
516
515
|
const details = normalizeWatchdogWarningDetails(warning, {
|
|
517
516
|
state: "displayed",
|
|
@@ -519,9 +518,7 @@ export class MainWatchdogRuntime {
|
|
|
519
518
|
identity: decision.identity,
|
|
520
519
|
displayedAt: new Date().toISOString(),
|
|
521
520
|
});
|
|
522
|
-
this.
|
|
523
|
-
this.displayedWarningSequence++;
|
|
524
|
-
this.displayWarning?.(details);
|
|
521
|
+
this.deliverBoundaryWarning(details);
|
|
525
522
|
return true;
|
|
526
523
|
}
|
|
527
524
|
|
|
@@ -635,51 +632,41 @@ export class MainWatchdogRuntime {
|
|
|
635
632
|
state: "displayed",
|
|
636
633
|
displayedAt: new Date().toISOString(),
|
|
637
634
|
};
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
this.autoFollowQueued = false;
|
|
645
|
-
this.autoFollowAttempts = 0;
|
|
646
|
-
this.consecutiveAutoFollowIdentity = undefined;
|
|
647
|
-
this.consecutiveAutoFollowRepeats = 0;
|
|
648
|
-
this.autoFollowStalemate = false;
|
|
635
|
+
if (correction) {
|
|
636
|
+
this.lastWarning = details;
|
|
637
|
+
this.displayWarning?.(details, { deliverAs: "steer" });
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
this.deliverBoundaryWarning(details);
|
|
649
641
|
}
|
|
650
642
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
643
|
+
// A displayed boundary warning continues the run; the same identity back from consecutive
|
|
644
|
+
// boundaries means no progress, so it is shown held instead of continuing again.
|
|
645
|
+
private deliverBoundaryWarning(details: WatchdogWarningDetails): void {
|
|
646
|
+
const identity = details.identity ?? reviewInputSignature([details.severity, details.summary, details.evidence].join("\n"));
|
|
647
|
+
if (this.lastBoundaryIdentity === identity) this.boundaryRepeats++;
|
|
655
648
|
else {
|
|
656
|
-
this.
|
|
657
|
-
this.
|
|
658
|
-
}
|
|
659
|
-
if (this.consecutiveAutoFollowRepeats >= this.configResult.config.autoFollow.stalemateRepeats) {
|
|
660
|
-
this.autoFollowStalemate = true;
|
|
661
|
-
this.lastWarning = { ...warning, state: "stalemate", stalemateRepeats: this.consecutiveAutoFollowRepeats };
|
|
662
|
-
return;
|
|
649
|
+
this.lastBoundaryIdentity = identity;
|
|
650
|
+
this.boundaryRepeats = 1;
|
|
663
651
|
}
|
|
664
|
-
const
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
this.
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
this.
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
});
|
|
652
|
+
const stalemate = this.boundaryRepeats >= this.configResult.config.stalemateRepeats;
|
|
653
|
+
const delivered: WatchdogWarningDetails = stalemate
|
|
654
|
+
? { ...details, state: "stalemate", stalemateRepeats: this.boundaryRepeats }
|
|
655
|
+
: details;
|
|
656
|
+
this.stalemate = stalemate;
|
|
657
|
+
this.lastWarning = delivered;
|
|
658
|
+
this.displayWarning?.(delivered, stalemate ? { triggerTurn: false } : undefined);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// The previous boundary finding is a repeat to count, not a duplicate, until stalemate.
|
|
662
|
+
private repeatableBoundaryIdentity(): string | undefined {
|
|
663
|
+
return this.waitingAtAgentEnd && !this.stalemate ? this.lastBoundaryIdentity : undefined;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private resetBoundaryRepeats(): void {
|
|
667
|
+
this.lastBoundaryIdentity = undefined;
|
|
668
|
+
this.boundaryRepeats = 0;
|
|
669
|
+
this.stalemate = false;
|
|
683
670
|
}
|
|
684
671
|
|
|
685
672
|
private currentRepoChangeSignature(cwd = this.cwd): WatchdogRepoChangeSignature | undefined {
|
|
@@ -783,7 +770,7 @@ export class MainWatchdogRuntime {
|
|
|
783
770
|
private appendBoundedDelta(delta: string): void {
|
|
784
771
|
let entry = delta.trim();
|
|
785
772
|
if (!entry) return;
|
|
786
|
-
if (entry.length > MAX_REVIEW_INPUT_CHARS) entry = entry
|
|
773
|
+
if (entry.length > MAX_REVIEW_INPUT_CHARS) entry = boundWatchdogReviewText(entry);
|
|
787
774
|
this.pendingDeltas.push(entry);
|
|
788
775
|
this.pendingDeltaChars += entry.length;
|
|
789
776
|
while (this.pendingDeltas.length > 1 && this.pendingDeltaChars + (this.pendingDeltas.length - 1) * REVIEW_DELTA_SEPARATOR.length > MAX_REVIEW_INPUT_CHARS) {
|
|
@@ -799,7 +786,7 @@ export class MainWatchdogRuntime {
|
|
|
799
786
|
? ["Changed repo paths:", ...changeSignature.changedPaths.slice(0, 200).map((file) => `- ${file}`)].join("\n")
|
|
800
787
|
: "";
|
|
801
788
|
const contextPieces = [scopeBlock, changes, lspBlock].filter(Boolean);
|
|
802
|
-
if (!contextPieces.length) return input
|
|
789
|
+
if (!contextPieces.length) return boundWatchdogReviewText(input);
|
|
803
790
|
|
|
804
791
|
const maxContextLength = Math.floor(MAX_REVIEW_INPUT_CHARS / 2);
|
|
805
792
|
const maxPieceLength = Math.max(1_000, Math.floor(maxContextLength / contextPieces.length));
|
|
@@ -808,11 +795,7 @@ export class MainWatchdogRuntime {
|
|
|
808
795
|
: piece).join(REVIEW_DELTA_SEPARATOR);
|
|
809
796
|
const separatorLength = input ? REVIEW_DELTA_SEPARATOR.length : 0;
|
|
810
797
|
const inputBudget = MAX_REVIEW_INPUT_CHARS - boundedContext.length - separatorLength;
|
|
811
|
-
const boundedInput = inputBudget <= 0
|
|
812
|
-
? ""
|
|
813
|
-
: input.length > inputBudget
|
|
814
|
-
? input.slice(-inputBudget)
|
|
815
|
-
: input;
|
|
798
|
+
const boundedInput = inputBudget <= 0 ? "" : boundWatchdogReviewText(input, inputBudget);
|
|
816
799
|
return [boundedContext, boundedInput].filter(Boolean).join(REVIEW_DELTA_SEPARATOR);
|
|
817
800
|
}
|
|
818
801
|
|
package/src/watchdog/scope.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export const WATCHDOG_AUTO_FOLLOW_PROMPT_MARKER = Symbol("subagent-watchdog-auto-follow-prompt");
|
|
2
|
-
|
|
3
1
|
const MAX_SCOPE_ENTRIES = 8;
|
|
4
2
|
const MAX_SCOPE_ENTRY_CHARS = 2_000;
|
|
5
3
|
const MAX_SCOPE_TOTAL_CHARS = 16_000;
|
|
@@ -51,12 +49,3 @@ export class WatchdogScopeArtifact {
|
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
}
|
|
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
|
-
}
|