@kenkaiiii/ggcoder 5.74.2 → 5.74.3

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.
@@ -188,6 +188,10 @@ export interface AgentSessionOptions {
188
188
  additionalTools?: AgentTool[];
189
189
  /** Mode-owned completion policy; absent in Coder/chat/worker sessions. */
190
190
  completionReview?: CompletionReview;
191
+ /** Remind the agent to submit its plan (exit_plan) when a run is about to
192
+ * stop still in plan mode. Desktop only: an unsubmitted plan there leaves
193
+ * nothing to review. See plan-submission-gate.ts. */
194
+ planSubmissionGate?: boolean;
191
195
  }
192
196
  /** Resolve the per-result cap passed to the agent loop for the active transport. */
193
197
  export declare function resolveSessionToolResultCharLimit(model: string, provider: Provider, accountId?: string): number;
@@ -269,6 +273,8 @@ export declare class AgentSession {
269
273
  private runStartedAt;
270
274
  /** Gate injections spent this run, capped by MAX_PROCESS_GATE_INJECTIONS. */
271
275
  private processGateInjected;
276
+ /** Plan-submission reminders spent this run (plan-submission-gate.ts). */
277
+ private planSubmissionNudges;
272
278
  /** Verification evidence: code edited this run, and what has proved it since.
273
279
  * Passive tracking only — it feeds run status and autopilot, never a turn. */
274
280
  private readonly verificationGate;
@@ -26,6 +26,7 @@ import { createTools, createWebSearchTool, } from "../tools/index.js";
26
26
  import { partitionToolsByTier } from "../tools/tool-tiers.js";
27
27
  import { autoBackgroundedId, REVIEW_REJECTED_BEFORE_START } from "../tools/bash.js";
28
28
  import { buildProcessCompletionFollowUp } from "./process-gate.js";
29
+ import { PLAN_SUBMISSION_NUDGE, shouldNudgePlanSubmission } from "./plan-submission-gate.js";
29
30
  import { buildSubAgentCompletionFollowUp } from "./subagent-manager.js";
30
31
  import { applyAsyncSubagentPolicy } from "./subagent-policy.js";
31
32
  import { resolveResponsesLite, resolveStrictTools, } from "./codex-request-shape.js";
@@ -178,6 +179,8 @@ export class AgentSession {
178
179
  runStartedAt = 0;
179
180
  /** Gate injections spent this run, capped by MAX_PROCESS_GATE_INJECTIONS. */
180
181
  processGateInjected = 0;
182
+ /** Plan-submission reminders spent this run (plan-submission-gate.ts). */
183
+ planSubmissionNudges = 0;
181
184
  /** Verification evidence: code edited this run, and what has proved it since.
182
185
  * Passive tracking only — it feeds run status and autopilot, never a turn. */
183
186
  verificationGate = new VerificationGate();
@@ -1108,6 +1111,7 @@ export class AgentSession {
1108
1111
  };
1109
1112
  this.runStartedAt = Date.now();
1110
1113
  this.processGateInjected = 0;
1114
+ this.planSubmissionNudges = 0;
1111
1115
  this.verificationGate.beginRun();
1112
1116
  const processes = new Set(this.processManager?.list().map((p) => p.id) ?? []);
1113
1117
  for (const id of this.backgroundVerification.keys()) {
@@ -1212,7 +1216,10 @@ export class AgentSession {
1212
1216
  // Only host-observed successful mutations and trustworthy check results
1213
1217
  // affect approval. The model's text is never evidence.
1214
1218
  let verificationChanged = false;
1215
- if (!event.isError && args) {
1219
+ // In plan mode write/edit can only touch `.gg/plans/*.md`; a code-file
1220
+ // write there was refused (refusals return text, not isError). Counting
1221
+ // it as a change left "unverified" work that blocked plan approval.
1222
+ if (!event.isError && args && !this.planModeRef.current) {
1216
1223
  if (name === "edit" || name === "write") {
1217
1224
  // Check-owning files (tsconfig.json, pytest.ini, vitest.config.ts …)
1218
1225
  // are tracked even when they are not source code: editing one
@@ -1770,6 +1777,22 @@ export class AgentSession {
1770
1777
  }
1771
1778
  if (diagnosticMessages.length > 0)
1772
1779
  return diagnosticMessages;
1780
+ if (shouldNudgePlanSubmission({
1781
+ enabled: this.opts.planSubmissionGate === true,
1782
+ planMode: this.planModeRef.current,
1783
+ aborted: this.opts.signal?.aborted === true,
1784
+ nudgesThisRun: this.planSubmissionNudges,
1785
+ })) {
1786
+ this.planSubmissionNudges += 1;
1787
+ log("INFO", "plan-gate", "Run stopping in plan mode without a submitted plan; reminding");
1788
+ return [
1789
+ {
1790
+ role: "user",
1791
+ content: buildNotificationSteeringText([PLAN_SUBMISSION_NUDGE]),
1792
+ provenance: { source: "runtime", kind: "notification", visibility: "hidden" },
1793
+ },
1794
+ ];
1795
+ }
1773
1796
  if (this.opts.completionReview) {
1774
1797
  const followUp = await this.opts.completionReview.followUp((request, signal) => this.callCompletionReviewer(request, signal), this.opts.signal);
1775
1798
  await this.persistCompletionReviewState();
@@ -2788,6 +2811,11 @@ export class AgentSession {
2788
2811
  });
2789
2812
  }
2790
2813
  async newSession(preserveConversation = false) {
2814
+ // A background post-turn compaction replaces `this.messages` when it
2815
+ // lands. Letting it finish after the reset would swap the old history back
2816
+ // into the fresh session (e.g. an accepted plan's build would inherit the
2817
+ // whole planning conversation and lose the approved-plan prompt).
2818
+ await this.settlePostTurnCompaction();
2791
2819
  this.cacheDiagnostics.reset();
2792
2820
  // Approved-plan execution is a clean checkpoint of the same conversation;
2793
2821
  // explicit new sessions reset the conversation identity.