@pentoshi/clai 3.8.15 → 3.8.17
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/agent/compaction-summary.d.ts +6 -1
- package/dist/agent/compaction-summary.js +11 -19
- package/dist/agent/compaction-summary.js.map +1 -1
- package/dist/agent/context-manager.d.ts +12 -0
- package/dist/agent/context-manager.js +15 -1
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/plan-implement-compact.d.ts +40 -0
- package/dist/agent/plan-implement-compact.js +78 -0
- package/dist/agent/plan-implement-compact.js.map +1 -0
- package/dist/agent/plan-mode-reminders.d.ts +42 -0
- package/dist/agent/plan-mode-reminders.js +61 -0
- package/dist/agent/plan-mode-reminders.js.map +1 -0
- package/dist/agent/runner.js +45 -9
- package/dist/agent/runner.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.js +2 -2
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/quiet-meta-tools.d.ts +8 -0
- package/dist/app/adapters/quiet-meta-tools.js +18 -0
- package/dist/app/adapters/quiet-meta-tools.js.map +1 -0
- package/dist/app/controllers/session-compact-helper.d.ts +9 -0
- package/dist/app/controllers/session-compact-helper.js +36 -0
- package/dist/app/controllers/session-compact-helper.js.map +1 -0
- package/dist/app/controllers/session-controller.d.ts +7 -1
- package/dist/app/controllers/session-controller.js +12 -39
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/prompts/embedded.js +1 -1
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.js +16 -11
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +5 -1
- package/dist/tui-v2/app/plan-lifecycle.js +59 -0
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/components/toast/toast-anim.d.ts +4 -4
- package/dist/tui-v2/components/toast/toast-anim.js +4 -4
- package/dist/tui-v2/components/toast/toast-host.js +35 -20
- package/dist/tui-v2/components/toast/toast-host.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.js +3 -1
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +4 -5
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/controllers/toast-controller.d.ts +2 -0
- package/dist/tui-v2/controllers/toast-controller.js +3 -1
- package/dist/tui-v2/controllers/toast-controller.js.map +1 -1
- package/dist/tui-v2/rendering/theme.d.ts +5 -0
- package/dist/tui-v2/rendering/theme.js +4 -0
- package/dist/tui-v2/rendering/theme.js.map +1 -1
- package/dist/tui-v2/state/transcript-hydrate.js +13 -3
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -1
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/package.json +1 -1
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
* Prompts and helpers for LLM-based context compaction.
|
|
3
3
|
* The model produces structured continuation memory — not a raw transcript dump.
|
|
4
4
|
*/
|
|
5
|
-
export declare const COMPACTION_SYSTEM_PROMPT = "You are a session-memory compressor for an autonomous coding and security agent.\n\nWrite a dense, accurate CONTINUATION MEMORY for another assistant that will resume this work with no other history.\n\nRules:\n- Fidelity over style. Never invent tool results, file contents, findings, URLs, ports, or completions.\n- Prefer concrete artifacts: absolute paths, commands (short form), exit outcomes, HTTP status, plan task ids/states, job ids, open ports, confirmed vs unconfirmed findings.\n- Omit secrets, API keys, passwords, tokens, and full credential material. Say \"[redacted]\" if present.\n- Omit progress bars, repeated failures, and decorative chatter.\n- Do not wrap the whole answer in markdown code fences.\n- If something is unknown, omit it rather than guessing.";
|
|
5
|
+
export declare const COMPACTION_SYSTEM_PROMPT = "You are a session-memory compressor for an autonomous coding and security agent.\n\nWrite a dense, accurate CONTINUATION MEMORY for another assistant that will resume this work with no other history.\n\nRules:\n- Fidelity over style. Never invent tool results, file contents, findings, URLs, ports, or completions.\n- Prefer concrete artifacts: absolute paths, commands (short form), exit outcomes, HTTP status, plan task ids/states, job ids, open ports, confirmed vs unconfirmed findings.\n- Omit secrets, API keys, passwords, tokens, and full credential material. Say \"[redacted]\" if present.\n- Omit progress bars, repeated failures, and decorative chatter.\n- Do not wrap the whole answer in markdown code fences.\n- If something is unknown, omit it rather than guessing.\n- PHASE AWARENESS: Temporary UI/mode gates (plan-mode gather-only, \"await accept\", \"do not implement yet\") are HISTORICAL context \u2014 never rewrite them as permanent forever-rules for the resuming agent. Durable user/engagement policy (scope, non-destructive default, stay on remote target when that is the engagement) may still apply.";
|
|
6
6
|
export interface CompactionPromptParts {
|
|
7
7
|
visualTranscript?: string | undefined;
|
|
8
8
|
messageTranscript: string;
|
|
9
9
|
/** Optional live plan / session state to prioritize. */
|
|
10
10
|
durableState?: string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* When "plan-implement", bias the summarizer toward recon evidence and
|
|
13
|
+
* remaining work so agent mode can execute the accepted plan.
|
|
14
|
+
*/
|
|
15
|
+
purpose?: "default" | "plan-implement" | undefined;
|
|
11
16
|
}
|
|
12
17
|
/** User message fed to the summarizer model. */
|
|
13
18
|
export declare function buildCompactionUserPrompt(parts: CompactionPromptParts): string;
|
|
@@ -12,12 +12,14 @@ Rules:
|
|
|
12
12
|
- Omit secrets, API keys, passwords, tokens, and full credential material. Say "[redacted]" if present.
|
|
13
13
|
- Omit progress bars, repeated failures, and decorative chatter.
|
|
14
14
|
- Do not wrap the whole answer in markdown code fences.
|
|
15
|
-
- If something is unknown, omit it rather than guessing
|
|
15
|
+
- If something is unknown, omit it rather than guessing.
|
|
16
|
+
- PHASE AWARENESS: Temporary UI/mode gates (plan-mode gather-only, "await accept", "do not implement yet") are HISTORICAL context — never rewrite them as permanent forever-rules for the resuming agent. Durable user/engagement policy (scope, non-destructive default, stay on remote target when that is the engagement) may still apply.`;
|
|
16
17
|
/** User message fed to the summarizer model. */
|
|
17
18
|
export function buildCompactionUserPrompt(parts) {
|
|
18
19
|
const visual = parts.visualTranscript?.trim() ?? "";
|
|
19
20
|
const fromMessages = parts.messageTranscript.trim();
|
|
20
21
|
const durable = parts.durableState?.trim() ?? "";
|
|
22
|
+
const planImplement = parts.purpose === "plan-implement";
|
|
21
23
|
let transcript = "";
|
|
22
24
|
if (visual && fromMessages) {
|
|
23
25
|
transcript = `${visual}\n\n---\n\nOLDER MODEL TURNS:\n\n${fromMessages}`;
|
|
@@ -25,24 +27,14 @@ export function buildCompactionUserPrompt(parts) {
|
|
|
25
27
|
else {
|
|
26
28
|
transcript = visual || fromMessages;
|
|
27
29
|
}
|
|
28
|
-
const sections = [
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"## User goals",
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"## Commands/tools and results",
|
|
37
|
-
"## Current state",
|
|
38
|
-
"## Remaining work",
|
|
39
|
-
"## Open risks / failures",
|
|
40
|
-
"",
|
|
41
|
-
"Preserve: user intentions, decisions, constraints, paths, stack/package manager,",
|
|
42
|
-
"commands and key results, plan task states, errors and failed approaches,",
|
|
43
|
-
"servers/jobs still running, and exactly what remains.",
|
|
44
|
-
"Be concise but specific. No secrets. No fabricated successes.",
|
|
45
|
-
];
|
|
30
|
+
const sections = [];
|
|
31
|
+
if (planImplement) {
|
|
32
|
+
sections.push("Create a complete but compact HANDOFF MEMORY from PLAN-MODE RESEARCH for an agent that will EXECUTE the accepted plan next.", "The material below was gathered mostly under plan mode (research/roadmap). The next phase is agent implement — not gather-only.", "", "Organize under these exact section headings (skip a section only if empty):", "## User goals", "## Research evidence (facts from plan-mode tools)", "## Durable engagement rules (still apply in agent mode)", "## Plan-mode-only notes (historical — not current agent gates)", "## Commands/tools and results", "## Current state", "## Remaining work (post-accept tasks)", "## Open risks / failures", "", "CRITICAL separation:", "- Put EVIDENCE in Research evidence: targets, stack, ports, findings, artifact paths, OpenAPI notes, credentials status.", "- Durable engagement rules ONLY if they still bind implement (e.g. stay on remote target/scope, authorized testing, non-destructive default, do not treat clai workspace as the target).", "- Plan-mode-only notes: gather-only, await accept, do not exploit/implement yet, scaffold/write freezes that applied BEFORE accept. Label them explicitly as historical plan-mode — the implementer is past that phase.", "- Do NOT list plan-mode gather-only / read-only / no-mutate gates as if they still block approved task execution.", "- Live ACTIVE PLAN + task states will be re-injected separately; still preserve task progress and what research already covered so work is not repeated blindly.", "", "Preserve: recon evidence, fingerprinted stack, confirmed vs unconfirmed findings,", "targets/hosts in scope, credential/auth status, interesting features still to test,", "artifact paths, and anything the implementer needs that is not already in the live plan document.");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
sections.push("Create a complete but compact continuation memory of the session below.", "Treat resumed history and newer turns as one continuous conversation.", "", "Organize under these exact section headings (skip a section only if empty):", "## User goals", "## Decisions and constraints", "## Work completed", "## Commands/tools and results", "## Current state", "## Remaining work", "## Open risks / failures", "", "Preserve: user intentions, decisions, constraints, paths, stack/package manager,", "commands and key results, plan task states, errors and failed approaches,", "servers/jobs still running, and exactly what remains.", "", "PHASE AWARENESS under Decisions and constraints:", "- If earlier turns were plan-mode research, do not elevate gather-only / await-accept / no-implement rules as permanent forever-constraints for agent execution.", "- Durable engagement policy (scope, remote target, non-destructive default) may still be listed as current.", "- Prefer labeling historical plan-mode gates as \"(plan-mode only; superseded after accept)\" when they appear in the material.");
|
|
36
|
+
}
|
|
37
|
+
sections.push("Be concise but specific. No secrets. No fabricated successes.");
|
|
46
38
|
if (durable) {
|
|
47
39
|
sections.push("", "DURABLE STATE (trust this over older chatter):", durable);
|
|
48
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction-summary.js","sourceRoot":"","sources":["../../src/agent/compaction-summary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG
|
|
1
|
+
{"version":3,"file":"compaction-summary.js","sourceRoot":"","sources":["../../src/agent/compaction-summary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;;;;;;8UAWsS,CAAC;AAc/U,gDAAgD;AAChD,MAAM,UAAU,yBAAyB,CAAC,KAA4B;IACpE,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjD,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,KAAK,gBAAgB,CAAC;IAEzD,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;QAC3B,UAAU,GAAG,GAAG,MAAM,oCAAoC,YAAY,EAAE,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,MAAM,IAAI,YAAY,CAAC;IACtC,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,aAAa,EAAE,CAAC;QAClB,QAAQ,CAAC,IAAI,CACX,6HAA6H,EAC7H,iIAAiI,EACjI,EAAE,EACF,6EAA6E,EAC7E,eAAe,EACf,mDAAmD,EACnD,yDAAyD,EACzD,gEAAgE,EAChE,+BAA+B,EAC/B,kBAAkB,EAClB,uCAAuC,EACvC,0BAA0B,EAC1B,EAAE,EACF,sBAAsB,EACtB,0HAA0H,EAC1H,0LAA0L,EAC1L,yNAAyN,EACzN,mHAAmH,EACnH,kKAAkK,EAClK,EAAE,EACF,mFAAmF,EACnF,qFAAqF,EACrF,mGAAmG,CACpG,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CACX,yEAAyE,EACzE,uEAAuE,EACvE,EAAE,EACF,6EAA6E,EAC7E,eAAe,EACf,8BAA8B,EAC9B,mBAAmB,EACnB,+BAA+B,EAC/B,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,EAAE,EACF,kFAAkF,EAClF,2EAA2E,EAC3E,uDAAuD,EACvD,EAAE,EACF,kDAAkD,EAClD,kKAAkK,EAClK,6GAA6G,EAC7G,iIAAiI,CAClI,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAE/E,IAAI,OAAO,EAAE,CAAC;QACZ,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,gDAAgD,EAAE,OAAO,CAAC,CAAC;IAC/E,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,iCAAiC,GAAG,MAAM,CAAC;AAExD,oEAAoE;AACpE,MAAM,UAAU,2BAA2B,CACzC,UAAkB,EAClB,MAAM,GAAG,iCAAiC;IAE1C,IAAI,UAAU,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,UAAU,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,OAAO,CACL,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QACzB,wDAAwD;QACxD,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CACxB,CAAC;AACJ,CAAC"}
|
|
@@ -18,6 +18,11 @@ export interface CompactOptions {
|
|
|
18
18
|
budgetTokens?: number | undefined;
|
|
19
19
|
/** Keep this many trailing messages (system + user/assistant pairs). */
|
|
20
20
|
keepRecent?: number | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Bias summarizer prompt (e.g. plan-implement preserves recon evidence).
|
|
23
|
+
* Does not change accept/reject heuristics.
|
|
24
|
+
*/
|
|
25
|
+
purpose?: "default" | "plan-implement" | undefined;
|
|
21
26
|
}
|
|
22
27
|
export interface CompactResult {
|
|
23
28
|
messages: ChatMessage[];
|
|
@@ -35,8 +40,15 @@ export interface CompactResult {
|
|
|
35
40
|
* summarized context.
|
|
36
41
|
*/
|
|
37
42
|
export declare const COMPACTION_MEMORY_PREFIX = "Session memory from compacted earlier turns:";
|
|
43
|
+
/**
|
|
44
|
+
* Plan-mode research handoff memory (pre-implement compact). Distinct so the
|
|
45
|
+
* agent does not treat plan-mode gather-only history as permanent gates.
|
|
46
|
+
*/
|
|
47
|
+
export declare const PLAN_IMPLEMENT_MEMORY_PREFIX = "Session memory from plan-mode research (handoff to agent implement \u2014 gather-only phase is over; execute approved tasks):";
|
|
38
48
|
export declare const MECHANICAL_MEMORY_PREFIX = "Earlier turns in this session, summarized";
|
|
39
49
|
export declare function isCompactionMemoryMessage(message: ChatMessage): boolean;
|
|
50
|
+
/** Prefix used when writing a compacted memory system message. */
|
|
51
|
+
export declare function compactionMemoryPrefixForPurpose(purpose?: "default" | "plan-implement" | undefined): string;
|
|
40
52
|
/**
|
|
41
53
|
* Replace older messages with a single condensed "memory" message while
|
|
42
54
|
* preserving the system prompt and the most recent N messages.
|
|
@@ -38,12 +38,24 @@ const DEFAULT_KEEP_RECENT = 6;
|
|
|
38
38
|
* summarized context.
|
|
39
39
|
*/
|
|
40
40
|
export const COMPACTION_MEMORY_PREFIX = "Session memory from compacted earlier turns:";
|
|
41
|
+
/**
|
|
42
|
+
* Plan-mode research handoff memory (pre-implement compact). Distinct so the
|
|
43
|
+
* agent does not treat plan-mode gather-only history as permanent gates.
|
|
44
|
+
*/
|
|
45
|
+
export const PLAN_IMPLEMENT_MEMORY_PREFIX = "Session memory from plan-mode research (handoff to agent implement — gather-only phase is over; execute approved tasks):";
|
|
41
46
|
export const MECHANICAL_MEMORY_PREFIX = "Earlier turns in this session, summarized";
|
|
42
47
|
export function isCompactionMemoryMessage(message) {
|
|
43
48
|
return (message.role === "system" &&
|
|
44
49
|
(message.content.startsWith(COMPACTION_MEMORY_PREFIX) ||
|
|
50
|
+
message.content.startsWith(PLAN_IMPLEMENT_MEMORY_PREFIX) ||
|
|
45
51
|
message.content.startsWith(MECHANICAL_MEMORY_PREFIX)));
|
|
46
52
|
}
|
|
53
|
+
/** Prefix used when writing a compacted memory system message. */
|
|
54
|
+
export function compactionMemoryPrefixForPurpose(purpose) {
|
|
55
|
+
return purpose === "plan-implement"
|
|
56
|
+
? PLAN_IMPLEMENT_MEMORY_PREFIX
|
|
57
|
+
: COMPACTION_MEMORY_PREFIX;
|
|
58
|
+
}
|
|
47
59
|
/**
|
|
48
60
|
* Replace older messages with a single condensed "memory" message while
|
|
49
61
|
* preserving the system prompt and the most recent N messages.
|
|
@@ -184,6 +196,7 @@ export async function compactMessagesWithSummary(messages, summarize, options =
|
|
|
184
196
|
visualTranscript: visual || undefined,
|
|
185
197
|
messageTranscript,
|
|
186
198
|
durableState: durableBits || undefined,
|
|
199
|
+
purpose: options.purpose,
|
|
187
200
|
});
|
|
188
201
|
const prompt = trimTranscriptForCompaction(rawCombined);
|
|
189
202
|
const rawSummary = redactSecrets((await summarize(prompt)).trim());
|
|
@@ -200,9 +213,10 @@ export async function compactMessagesWithSummary(messages, summarize, options =
|
|
|
200
213
|
}
|
|
201
214
|
return msg;
|
|
202
215
|
});
|
|
216
|
+
const memoryPrefix = compactionMemoryPrefixForPurpose(options.purpose);
|
|
203
217
|
const compacted = [
|
|
204
218
|
...head,
|
|
205
|
-
{ role: "system", content: `${
|
|
219
|
+
{ role: "system", content: `${memoryPrefix}\n\n${summary}` },
|
|
206
220
|
...tail,
|
|
207
221
|
];
|
|
208
222
|
const afterTokens = estimateMessagesTokens(compacted);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EACL,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAuB;IAC5D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB;QAC5D,gEAAgE;QAChE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accept-by-default gate for plan-implement research compaction.
|
|
3
|
+
*
|
|
4
|
+
* Prefer keeping a good free-form model summary. Reject only clear structural
|
|
5
|
+
* failures (empty summary, orphan tool pairs, catastrophic stub) — never on
|
|
6
|
+
* missing headings, missing hostnames, or token-% taste checks.
|
|
7
|
+
*/
|
|
8
|
+
import type { ChatMessage } from "../types.js";
|
|
9
|
+
/** Summary body shorter than this after a large history is treated as a stub. */
|
|
10
|
+
export declare const CATASTROPHIC_SUMMARY_MIN_CHARS = 120;
|
|
11
|
+
/**
|
|
12
|
+
* Only apply catastrophic-stub check when pre-compact history was at least
|
|
13
|
+
* this many estimated tokens (small sessions may legitimately shrink a lot).
|
|
14
|
+
*/
|
|
15
|
+
export declare const CATASTROPHIC_BEFORE_TOKENS_MIN = 8000;
|
|
16
|
+
/** After-tokens ratio below this vs large before + tiny body → reject. */
|
|
17
|
+
export declare const CATASTROPHIC_AFTER_RATIO = 0.05;
|
|
18
|
+
export interface AcceptPlanImplementCompactionInput {
|
|
19
|
+
readonly summarized: boolean;
|
|
20
|
+
/** Memory body without the COMPACTION_MEMORY_PREFIX header (or full text). */
|
|
21
|
+
readonly summaryBody: string;
|
|
22
|
+
readonly beforeTokens: number;
|
|
23
|
+
readonly afterTokens: number;
|
|
24
|
+
readonly afterMessages: readonly ChatMessage[];
|
|
25
|
+
}
|
|
26
|
+
export type AcceptPlanImplementCompactionResult = {
|
|
27
|
+
readonly accept: true;
|
|
28
|
+
} | {
|
|
29
|
+
readonly accept: false;
|
|
30
|
+
readonly reason: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Accept unless a clear structural failure is proven.
|
|
34
|
+
* Does not inspect plan.goal keywords or markdown section headings.
|
|
35
|
+
*/
|
|
36
|
+
export declare function acceptPlanImplementCompaction(input: AcceptPlanImplementCompactionInput): AcceptPlanImplementCompactionResult;
|
|
37
|
+
/** Extract summary body from compacted messages for the accept gate. */
|
|
38
|
+
export declare function extractCompactionSummaryBody(messages: readonly ChatMessage[]): string;
|
|
39
|
+
/** Skip compact when history is already small (no toast). */
|
|
40
|
+
export declare const PLAN_IMPLEMENT_COMPACT_MIN_TOKENS = 6000;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accept-by-default gate for plan-implement research compaction.
|
|
3
|
+
*
|
|
4
|
+
* Prefer keeping a good free-form model summary. Reject only clear structural
|
|
5
|
+
* failures (empty summary, orphan tool pairs, catastrophic stub) — never on
|
|
6
|
+
* missing headings, missing hostnames, or token-% taste checks.
|
|
7
|
+
*/
|
|
8
|
+
import { hasOrphanToolMessages } from "./tool-history.js";
|
|
9
|
+
import { COMPACTION_MEMORY_PREFIX, PLAN_IMPLEMENT_MEMORY_PREFIX, } from "./context-manager.js";
|
|
10
|
+
/** Summary body shorter than this after a large history is treated as a stub. */
|
|
11
|
+
export const CATASTROPHIC_SUMMARY_MIN_CHARS = 120;
|
|
12
|
+
const MEMORY_PREFIXES = [
|
|
13
|
+
PLAN_IMPLEMENT_MEMORY_PREFIX,
|
|
14
|
+
COMPACTION_MEMORY_PREFIX,
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Only apply catastrophic-stub check when pre-compact history was at least
|
|
18
|
+
* this many estimated tokens (small sessions may legitimately shrink a lot).
|
|
19
|
+
*/
|
|
20
|
+
export const CATASTROPHIC_BEFORE_TOKENS_MIN = 8_000;
|
|
21
|
+
/** After-tokens ratio below this vs large before + tiny body → reject. */
|
|
22
|
+
export const CATASTROPHIC_AFTER_RATIO = 0.05;
|
|
23
|
+
function summaryBodyText(raw) {
|
|
24
|
+
const t = raw.trim();
|
|
25
|
+
for (const prefix of MEMORY_PREFIXES) {
|
|
26
|
+
if (t.startsWith(prefix)) {
|
|
27
|
+
return t.slice(prefix.length).replace(/^\s+/, "");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return t;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Accept unless a clear structural failure is proven.
|
|
34
|
+
* Does not inspect plan.goal keywords or markdown section headings.
|
|
35
|
+
*/
|
|
36
|
+
export function acceptPlanImplementCompaction(input) {
|
|
37
|
+
if (!input.summarized) {
|
|
38
|
+
return { accept: false, reason: "compaction did not produce a summary" };
|
|
39
|
+
}
|
|
40
|
+
const body = summaryBodyText(input.summaryBody);
|
|
41
|
+
if (!body) {
|
|
42
|
+
return { accept: false, reason: "empty compaction summary" };
|
|
43
|
+
}
|
|
44
|
+
if (hasOrphanToolMessages([...input.afterMessages])) {
|
|
45
|
+
return {
|
|
46
|
+
accept: false,
|
|
47
|
+
reason: "compacted history has orphan tool messages",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Catastrophic stub: huge history collapsed to almost nothing + tiny body.
|
|
51
|
+
// Normal dense free-form summaries are hundreds+ chars — never reject those.
|
|
52
|
+
const before = Math.max(0, input.beforeTokens);
|
|
53
|
+
const after = Math.max(0, input.afterTokens);
|
|
54
|
+
if (before >= CATASTROPHIC_BEFORE_TOKENS_MIN &&
|
|
55
|
+
body.length < CATASTROPHIC_SUMMARY_MIN_CHARS &&
|
|
56
|
+
after < before * CATASTROPHIC_AFTER_RATIO) {
|
|
57
|
+
return {
|
|
58
|
+
accept: false,
|
|
59
|
+
reason: "compaction summary is too thin for a large research session",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { accept: true };
|
|
63
|
+
}
|
|
64
|
+
/** Extract summary body from compacted messages for the accept gate. */
|
|
65
|
+
export function extractCompactionSummaryBody(messages) {
|
|
66
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
67
|
+
const m = messages[i];
|
|
68
|
+
if (m.role !== "system" || typeof m.content !== "string")
|
|
69
|
+
continue;
|
|
70
|
+
if (MEMORY_PREFIXES.some((p) => m.content.startsWith(p))) {
|
|
71
|
+
return summaryBodyText(m.content);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
/** Skip compact when history is already small (no toast). */
|
|
77
|
+
export const PLAN_IMPLEMENT_COMPACT_MIN_TOKENS = 6_000;
|
|
78
|
+
//# sourceMappingURL=plan-implement-compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-implement-compact.js","sourceRoot":"","sources":["../../src/agent/plan-implement-compact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft plan-mode research reminders.
|
|
3
|
+
*
|
|
4
|
+
* Attached to existing tool-result payloads at milestones (15, 25, 35, …).
|
|
5
|
+
* Informational only — never aborts the turn, never forbids more tools,
|
|
6
|
+
* never injects as a separate user message (keeps tool-call pairs intact).
|
|
7
|
+
*/
|
|
8
|
+
/** First reminder after this many productive tool steps. */
|
|
9
|
+
export declare const PLAN_REMINDER_FIRST_STEP = 15;
|
|
10
|
+
/** Subsequent reminders every N productive steps. */
|
|
11
|
+
export declare const PLAN_REMINDER_STEP_INTERVAL = 10;
|
|
12
|
+
export interface PlanReminderGate {
|
|
13
|
+
readonly isPlanMode: boolean;
|
|
14
|
+
readonly planApproved: boolean;
|
|
15
|
+
/** True when a draft plan with tasks already exists (stop nags after plan.create). */
|
|
16
|
+
readonly hasDraftPlan: boolean;
|
|
17
|
+
/** Productive tool-step index after recording this result (1-based). */
|
|
18
|
+
readonly productiveStep: number;
|
|
19
|
+
/** Milestones already fired this turn. */
|
|
20
|
+
readonly alreadyRemindedAt: ReadonlySet<number>;
|
|
21
|
+
}
|
|
22
|
+
/** True when this productive step is a reminder milestone (15, 25, 35, …). */
|
|
23
|
+
export declare function isPlanReminderMilestone(step: number): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to append a plan-mode research note to this tool result.
|
|
26
|
+
* Call once per completed productive step; track `alreadyRemindedAt` in the turn.
|
|
27
|
+
*/
|
|
28
|
+
export declare function shouldAttachPlanModeReminder(opts: PlanReminderGate): boolean;
|
|
29
|
+
export interface PlanReminderTextOpts {
|
|
30
|
+
readonly step: number;
|
|
31
|
+
readonly kindHint?: "pentest" | "coding" | "general" | undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Short, calm note — not a stop order. Appended under the tool result body.
|
|
35
|
+
* Kept well under ~400 chars to avoid context bloat.
|
|
36
|
+
*/
|
|
37
|
+
export declare function planModeResearchReminder(opts: PlanReminderTextOpts): string;
|
|
38
|
+
/** Append reminder suffix when the gate passes; otherwise return content unchanged. */
|
|
39
|
+
export declare function maybeAppendPlanModeReminder(toolContent: string, opts: PlanReminderGate & PlanReminderTextOpts): {
|
|
40
|
+
content: string;
|
|
41
|
+
reminded: boolean;
|
|
42
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft plan-mode research reminders.
|
|
3
|
+
*
|
|
4
|
+
* Attached to existing tool-result payloads at milestones (15, 25, 35, …).
|
|
5
|
+
* Informational only — never aborts the turn, never forbids more tools,
|
|
6
|
+
* never injects as a separate user message (keeps tool-call pairs intact).
|
|
7
|
+
*/
|
|
8
|
+
/** First reminder after this many productive tool steps. */
|
|
9
|
+
export const PLAN_REMINDER_FIRST_STEP = 15;
|
|
10
|
+
/** Subsequent reminders every N productive steps. */
|
|
11
|
+
export const PLAN_REMINDER_STEP_INTERVAL = 10;
|
|
12
|
+
/** True when this productive step is a reminder milestone (15, 25, 35, …). */
|
|
13
|
+
export function isPlanReminderMilestone(step) {
|
|
14
|
+
if (!Number.isFinite(step) || step < PLAN_REMINDER_FIRST_STEP)
|
|
15
|
+
return false;
|
|
16
|
+
return (step - PLAN_REMINDER_FIRST_STEP) % PLAN_REMINDER_STEP_INTERVAL === 0;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Whether to append a plan-mode research note to this tool result.
|
|
20
|
+
* Call once per completed productive step; track `alreadyRemindedAt` in the turn.
|
|
21
|
+
*/
|
|
22
|
+
export function shouldAttachPlanModeReminder(opts) {
|
|
23
|
+
if (!opts.isPlanMode)
|
|
24
|
+
return false;
|
|
25
|
+
if (opts.planApproved)
|
|
26
|
+
return false;
|
|
27
|
+
if (opts.hasDraftPlan)
|
|
28
|
+
return false;
|
|
29
|
+
if (!isPlanReminderMilestone(opts.productiveStep))
|
|
30
|
+
return false;
|
|
31
|
+
if (opts.alreadyRemindedAt.has(opts.productiveStep))
|
|
32
|
+
return false;
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Short, calm note — not a stop order. Appended under the tool result body.
|
|
37
|
+
* Kept well under ~400 chars to avoid context bloat.
|
|
38
|
+
*/
|
|
39
|
+
export function planModeResearchReminder(opts) {
|
|
40
|
+
const step = Math.max(0, Math.floor(opts.step));
|
|
41
|
+
const pentest = opts.kindHint === "pentest"
|
|
42
|
+
? " Map surfaces/stack/interesting areas; put remaining auth’d tests, exploits, and report polish in tasks."
|
|
43
|
+
: "";
|
|
44
|
+
return (`\n\n[plan-mode note · step ${step}] ` +
|
|
45
|
+
`Research may continue as long as useful. Plan mode’s deliverable is a comprehensive plan.create ` +
|
|
46
|
+
`(goal, evidence-backed detail, ordered tasks for post-accept work). ` +
|
|
47
|
+
`When you have enough context to design that roadmap, present the plan and await accept.` +
|
|
48
|
+
pentest);
|
|
49
|
+
}
|
|
50
|
+
/** Append reminder suffix when the gate passes; otherwise return content unchanged. */
|
|
51
|
+
export function maybeAppendPlanModeReminder(toolContent, opts) {
|
|
52
|
+
if (!shouldAttachPlanModeReminder(opts)) {
|
|
53
|
+
return { content: toolContent, reminded: false };
|
|
54
|
+
}
|
|
55
|
+
const note = planModeResearchReminder({
|
|
56
|
+
step: opts.productiveStep,
|
|
57
|
+
kindHint: opts.kindHint,
|
|
58
|
+
});
|
|
59
|
+
return { content: toolContent + note, reminded: true };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=plan-mode-reminders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-mode-reminders.js","sourceRoot":"","sources":["../../src/agent/plan-mode-reminders.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAC3C,qDAAqD;AACrD,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAa9C,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,wBAAwB;QAAE,OAAO,KAAK,CAAC;IAC5E,OAAO,CAAC,IAAI,GAAG,wBAAwB,CAAC,GAAG,2BAA2B,KAAK,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAsB;IACjE,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,cAAc,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,IAAI,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC;QAAE,OAAO,KAAK,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAA0B;IACjE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,MAAM,OAAO,GACX,IAAI,CAAC,QAAQ,KAAK,SAAS;QACzB,CAAC,CAAC,0GAA0G;QAC5G,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,CACL,8BAA8B,IAAI,IAAI;QACtC,kGAAkG;QAClG,sEAAsE;QACtE,yFAAyF;QACzF,OAAO,CACR,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,2BAA2B,CACzC,WAAmB,EACnB,IAA6C;IAE7C,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACnD,CAAC;IACD,MAAM,IAAI,GAAG,wBAAwB,CAAC;QACpC,IAAI,EAAE,IAAI,CAAC,cAAc;QACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC"}
|
package/dist/agent/runner.js
CHANGED
|
@@ -14,7 +14,7 @@ import { availableToolNames, normalizeToolCall, runToolCall, BATCH_SAFE_TOOLS, }
|
|
|
14
14
|
import { getToolDefinitions, getCompactToolDefinitions, PLAN_TOOL_NAMES, } from "../tools/definitions.js";
|
|
15
15
|
import { appendAssistantWithTools, appendToolResult, assertValidToolProtocol, fillMissingToolResults, } from "./tool-history.js";
|
|
16
16
|
import { formatViewportHint, registerViewport } from "../ui/output-pane.js";
|
|
17
|
-
import { compactMessagesWithSummary, estimateMessagesTokens, AUTO_COMPACT_TOKEN_BUDGET, COMPACTION_MEMORY_PREFIX, } from "./context-manager.js";
|
|
17
|
+
import { compactMessagesWithSummary, estimateMessagesTokens, AUTO_COMPACT_TOKEN_BUDGET, COMPACTION_MEMORY_PREFIX, PLAN_IMPLEMENT_MEMORY_PREFIX, isCompactionMemoryMessage, } from "./context-manager.js";
|
|
18
18
|
import { auditLog } from "../store/logs.js";
|
|
19
19
|
import { loadProjectContext } from "../store/project.js";
|
|
20
20
|
import { loadScope, isScopeActive } from "../store/scope.js";
|
|
@@ -27,6 +27,7 @@ import { analyzeTask, formatTaskAnalysisHint, isNarrowExplicitNmapOperation, } f
|
|
|
27
27
|
import { computeMaxIterations, computeStepBudget } from "./step-budget.js";
|
|
28
28
|
import { isScratchOnlyWrite } from "./scratch-write.js";
|
|
29
29
|
import { COMPACTION_SYSTEM_PROMPT, } from "./compaction-summary.js";
|
|
30
|
+
import { maybeAppendPlanModeReminder } from "./plan-mode-reminders.js";
|
|
30
31
|
import { LoopGuard } from "./loop-guard.js";
|
|
31
32
|
import { loadPlan, savePlan, markTask, readyPlanTasks, isPlanTerminal, isPlanSuccessful, } from "../store/plan.js";
|
|
32
33
|
import { fsWrite, isOutsideWorkingDirectory, resolveFsToolPath, } from "../tools/fs.js";
|
|
@@ -510,7 +511,14 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
510
511
|
],
|
|
511
512
|
}).content;
|
|
512
513
|
const fullSystemPrompt = composeCurrentSystemPrompt(nativeToolsActive);
|
|
513
|
-
|
|
514
|
+
// Backend-only directives (implement, displayPrompt=null) stay in model
|
|
515
|
+
// history but must never become a YOU bubble on live or /history hydrate.
|
|
516
|
+
const hideUserBubble = options.displayPrompt === null || options.displayPrompt === "";
|
|
517
|
+
const userMessage = {
|
|
518
|
+
role: "user",
|
|
519
|
+
content: prompt,
|
|
520
|
+
...(hideUserBubble ? { internal: true } : {}),
|
|
521
|
+
};
|
|
514
522
|
if (options.images && options.images.length > 0) {
|
|
515
523
|
userMessage.images = options.images;
|
|
516
524
|
}
|
|
@@ -1924,11 +1932,14 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
1924
1932
|
estimatedTokens: afterTokens,
|
|
1925
1933
|
reason,
|
|
1926
1934
|
});
|
|
1927
|
-
const insertedSummary = messages.find((m) => m
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1935
|
+
const insertedSummary = messages.find((m) => isCompactionMemoryMessage(m))?.content ?? "";
|
|
1936
|
+
const summaryText = insertedSummary.startsWith(`${PLAN_IMPLEMENT_MEMORY_PREFIX}\n\n`)
|
|
1937
|
+
? insertedText(insertedSummary, `${PLAN_IMPLEMENT_MEMORY_PREFIX}\n\n`)
|
|
1938
|
+
: insertedSummary.startsWith(`${COMPACTION_MEMORY_PREFIX}\n\n`)
|
|
1939
|
+
? insertedText(insertedSummary, `${COMPACTION_MEMORY_PREFIX}\n\n`)
|
|
1940
|
+
: insertedText(insertedSummary, insertedSummary.startsWith(PLAN_IMPLEMENT_MEMORY_PREFIX)
|
|
1941
|
+
? PLAN_IMPLEMENT_MEMORY_PREFIX
|
|
1942
|
+
: COMPACTION_MEMORY_PREFIX);
|
|
1932
1943
|
// Card shows pre/post of the summarization; plan re-injection is noted.
|
|
1933
1944
|
writeCompacted(summaryText, beforeTokens, compactedTokens);
|
|
1934
1945
|
const planNote = afterTokens > compactedTokens
|
|
@@ -2910,6 +2921,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2910
2921
|
let awaitingPlanApproval = false;
|
|
2911
2922
|
/** Native tool_call ids that already have a role:tool history entry. */
|
|
2912
2923
|
const recordedNativeIds = new Set();
|
|
2924
|
+
/** Plan-mode soft reminders already attached this turn (by step). */
|
|
2925
|
+
const planRemindedAt = new Set();
|
|
2926
|
+
/** True after a successful plan.create this turn (activePlan is turn-start snapshot). */
|
|
2927
|
+
let planCreatedThisTurn = Boolean(activePlan && activePlan.tasks.length > 0);
|
|
2913
2928
|
/**
|
|
2914
2929
|
* Record a tool result into history. Failures / user declines are
|
|
2915
2930
|
* always returned to the model — we never cancel later siblings or
|
|
@@ -2918,7 +2933,29 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2918
2933
|
*/
|
|
2919
2934
|
const recordResult = (boundCall, res) => {
|
|
2920
2935
|
recordedNativeIds.add(boundCall.id);
|
|
2921
|
-
|
|
2936
|
+
if (res.ok && res.call.name === "plan.create") {
|
|
2937
|
+
planCreatedThisTurn = true;
|
|
2938
|
+
}
|
|
2939
|
+
productiveSteps += 1;
|
|
2940
|
+
// Soft plan-mode note on tool payloads only (never a user message).
|
|
2941
|
+
// Stop once a plan with tasks exists so we don't nag after plan.create.
|
|
2942
|
+
let toolContent = `Tool ${res.call.name} result (exit=${res.result.exitCode ?? 0}, ok=${res.result.ok}):\n${res.contextOutput}`;
|
|
2943
|
+
const reminded = maybeAppendPlanModeReminder(toolContent, {
|
|
2944
|
+
isPlanMode,
|
|
2945
|
+
planApproved: session.planApproved.value,
|
|
2946
|
+
hasDraftPlan: planCreatedThisTurn,
|
|
2947
|
+
productiveStep: productiveSteps,
|
|
2948
|
+
alreadyRemindedAt: planRemindedAt,
|
|
2949
|
+
step: productiveSteps,
|
|
2950
|
+
kindHint: activePlan?.kind === "pentest" || pentestLikeTurn
|
|
2951
|
+
? "pentest"
|
|
2952
|
+
: activePlan?.kind === "coding"
|
|
2953
|
+
? "coding"
|
|
2954
|
+
: "general",
|
|
2955
|
+
});
|
|
2956
|
+
toolContent = reminded.content;
|
|
2957
|
+
if (reminded.reminded)
|
|
2958
|
+
planRemindedAt.add(productiveSteps);
|
|
2922
2959
|
if (historyNativeCalls.length) {
|
|
2923
2960
|
appendToolResult(messages, boundCall.id, toolContent, res.call.name, res.result.ok);
|
|
2924
2961
|
}
|
|
@@ -2928,7 +2965,6 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2928
2965
|
content: toolContent,
|
|
2929
2966
|
});
|
|
2930
2967
|
}
|
|
2931
|
-
productiveSteps += 1;
|
|
2932
2968
|
// Reset retry counters — they track consecutive failures, not cumulative.
|
|
2933
2969
|
truncatedToolRetries = 0;
|
|
2934
2970
|
malformedFenceRetries = 0;
|