@pentoshi/clai 2.0.26 → 2.0.28

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.
Files changed (55) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/context-manager.d.ts +15 -2
  3. package/dist/agent/context-manager.js +41 -70
  4. package/dist/agent/context-manager.js.map +1 -1
  5. package/dist/agent/events.d.ts +1 -1
  6. package/dist/agent/runner.d.ts +38 -1
  7. package/dist/agent/runner.js +719 -135
  8. package/dist/agent/runner.js.map +1 -1
  9. package/dist/agent/session-title.d.ts +27 -0
  10. package/dist/agent/session-title.js +109 -0
  11. package/dist/agent/session-title.js.map +1 -0
  12. package/dist/commands/update.js +1 -1
  13. package/dist/index.js +5 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/llm/http.js +20 -6
  16. package/dist/llm/http.js.map +1 -1
  17. package/dist/modes/agent.d.ts +1 -0
  18. package/dist/modes/agent.js.map +1 -1
  19. package/dist/modes/ask.d.ts +29 -0
  20. package/dist/modes/ask.js +188 -23
  21. package/dist/modes/ask.js.map +1 -1
  22. package/dist/prompts/index.d.ts +2 -2
  23. package/dist/prompts/index.js +32 -9
  24. package/dist/prompts/index.js.map +1 -1
  25. package/dist/repl.js +104 -3
  26. package/dist/repl.js.map +1 -1
  27. package/dist/safety/classifier.js +66 -7
  28. package/dist/safety/classifier.js.map +1 -1
  29. package/dist/store/history.js +68 -48
  30. package/dist/store/history.js.map +1 -1
  31. package/dist/tools/fs.d.ts +4 -0
  32. package/dist/tools/fs.js +40 -2
  33. package/dist/tools/fs.js.map +1 -1
  34. package/dist/tools/registry.d.ts +8 -0
  35. package/dist/tools/registry.js +3 -1
  36. package/dist/tools/registry.js.map +1 -1
  37. package/dist/tui/App.js +242 -33
  38. package/dist/tui/App.js.map +1 -1
  39. package/dist/tui/components/ConfirmModal.js +14 -2
  40. package/dist/tui/components/ConfirmModal.js.map +1 -1
  41. package/dist/tui/components/PickerPanel.d.ts +2 -1
  42. package/dist/tui/components/PickerPanel.js +73 -23
  43. package/dist/tui/components/PickerPanel.js.map +1 -1
  44. package/dist/tui/confirm.d.ts +1 -1
  45. package/dist/tui/confirm.js +8 -0
  46. package/dist/tui/confirm.js.map +1 -1
  47. package/dist/tui/hooks/useAgentRunner.d.ts +27 -2
  48. package/dist/tui/hooks/useAgentRunner.js +149 -18
  49. package/dist/tui/hooks/useAgentRunner.js.map +1 -1
  50. package/dist/tui/render-lines.js +28 -1
  51. package/dist/tui/render-lines.js.map +1 -1
  52. package/dist/tui/state.d.ts +1 -1
  53. package/dist/ui/markdown.js +63 -30
  54. package/dist/ui/markdown.js.map +1 -1
  55. package/package.json +3 -2
package/README.md CHANGED
@@ -59,7 +59,7 @@ clai --classic # start the legacy line-based REPL
59
59
  CLAI_CLASSIC=1 clai # persistent shell-level opt-out (CLAI_TUI=0 also works)
60
60
 
61
61
  # One-shot ask mode (explains but doesn't execute)
62
- clai --mode ask "create a python venv and install requests"
62
+ clai --mode ask "how to create a python venv and install requests"
63
63
 
64
64
  # One-shot agent mode (executes)
65
65
  clai --mode agent "find all PDFs larger than 10MB in ~/Documents"
@@ -22,6 +22,16 @@ export interface CompactResult {
22
22
  afterTokens: number;
23
23
  summarized: boolean;
24
24
  }
25
+ /**
26
+ * Content prefixes that mark a `role:"system"` message as compacted session
27
+ * memory (vs. the main system prompt or transient injected guidance). Exported
28
+ * so history-persistence can KEEP this memory when it drops other system
29
+ * messages — otherwise a resumed session that compacted mid-run would lose all
30
+ * summarized context.
31
+ */
32
+ export declare const COMPACTION_MEMORY_PREFIX = "Session memory from compacted earlier turns:";
33
+ export declare const MECHANICAL_MEMORY_PREFIX = "Earlier turns in this session, summarized";
34
+ export declare function isCompactionMemoryMessage(message: ChatMessage): boolean;
25
35
  /**
26
36
  * Replace older messages with a single condensed "memory" message while
27
37
  * preserving the system prompt and the most recent N messages.
@@ -35,7 +45,10 @@ export interface CompactResult {
35
45
  export declare function compactMessages(messages: ChatMessage[], options?: CompactOptions): ChatMessage[];
36
46
  /**
37
47
  * Compact older turns into a model-written memory while retaining recent
38
- * messages verbatim. If summarization fails, the deterministic compactor is
39
- * used so `/compact` still reduces context without losing the recent tail.
48
+ * messages verbatim. The model summary is the ONLY compaction path: if the
49
+ * model fails to produce a summary we DO NOT fall back to a mechanical dump
50
+ * of the transcript (that historically produced an enormous, low-quality
51
+ * "memory" of tens of thousands of lines). Instead we throw, so the caller
52
+ * can report the failure and the original messages stay untouched.
40
53
  */
41
54
  export declare function compactMessagesWithSummary(messages: ChatMessage[], summarize: (prompt: string) => Promise<string>, options?: CompactOptions, sessionTranscript?: string | undefined): Promise<CompactResult>;
@@ -18,6 +18,20 @@ export function estimateMessagesTokens(messages) {
18
18
  }
19
19
  const DEFAULT_BUDGET_TOKENS = 32_000;
20
20
  const DEFAULT_KEEP_RECENT = 12;
21
+ /**
22
+ * Content prefixes that mark a `role:"system"` message as compacted session
23
+ * memory (vs. the main system prompt or transient injected guidance). Exported
24
+ * so history-persistence can KEEP this memory when it drops other system
25
+ * messages — otherwise a resumed session that compacted mid-run would lose all
26
+ * summarized context.
27
+ */
28
+ export const COMPACTION_MEMORY_PREFIX = "Session memory from compacted earlier turns:";
29
+ export const MECHANICAL_MEMORY_PREFIX = "Earlier turns in this session, summarized";
30
+ export function isCompactionMemoryMessage(message) {
31
+ return (message.role === "system" &&
32
+ (message.content.startsWith(COMPACTION_MEMORY_PREFIX) ||
33
+ message.content.startsWith(MECHANICAL_MEMORY_PREFIX)));
34
+ }
21
35
  /**
22
36
  * Replace older messages with a single condensed "memory" message while
23
37
  * preserving the system prompt and the most recent N messages.
@@ -62,15 +76,18 @@ export function compactMessages(messages, options = {}) {
62
76
  }
63
77
  const memo = {
64
78
  role: "system",
65
- content: `Earlier turns in this session, summarized to fit the context budget. Full artifacts (when produced) are saved on disk and can be expanded with /output.\n\n` +
79
+ content: `${MECHANICAL_MEMORY_PREFIX} to fit the context budget. Full artifacts (when produced) are saved on disk and can be expanded with /output.\n\n` +
66
80
  bullets.join("\n"),
67
81
  };
68
82
  return [...head, memo, ...tail];
69
83
  }
70
84
  /**
71
85
  * Compact older turns into a model-written memory while retaining recent
72
- * messages verbatim. If summarization fails, the deterministic compactor is
73
- * used so `/compact` still reduces context without losing the recent tail.
86
+ * messages verbatim. The model summary is the ONLY compaction path: if the
87
+ * model fails to produce a summary we DO NOT fall back to a mechanical dump
88
+ * of the transcript (that historically produced an enormous, low-quality
89
+ * "memory" of tens of thousands of lines). Instead we throw, so the caller
90
+ * can report the failure and the original messages stay untouched.
74
91
  */
75
92
  export async function compactMessagesWithSummary(messages, summarize, options = {}, sessionTranscript) {
76
93
  const before = messages.length;
@@ -88,6 +105,7 @@ export async function compactMessagesWithSummary(messages, summarize, options =
88
105
  older = messages.slice(start, tailStart);
89
106
  }
90
107
  if (older.length === 0 && !sessionTranscript?.trim()) {
108
+ // Genuinely nothing to compact yet — return a no-op result.
91
109
  return {
92
110
  messages: [...messages],
93
111
  before,
@@ -111,73 +129,26 @@ export async function compactMessagesWithSummary(messages, summarize, options =
111
129
  "",
112
130
  transcript,
113
131
  ].join("\n");
114
- try {
115
- const summary = redactSecrets((await summarize(prompt)).trim());
116
- if (!summary)
117
- throw new Error("empty summary");
118
- const head = start === 1 ? [messages[0]] : [];
119
- const compacted = [
120
- ...head,
121
- { role: "system", content: `Session memory from compacted earlier turns:\n\n${summary}` },
122
- ...messages.slice(tailStart),
123
- ];
124
- const afterTokens = estimateMessagesTokens(compacted);
125
- if (afterTokens >= beforeTokens && !isForced) {
126
- const deterministicCompacted = compactMessages(messages, { ...options, budgetTokens: 0 });
127
- const detTokens = estimateMessagesTokens(deterministicCompacted);
128
- if (detTokens < beforeTokens) {
129
- return {
130
- messages: deterministicCompacted,
131
- before,
132
- after: deterministicCompacted.length,
133
- beforeTokens,
134
- afterTokens: detTokens,
135
- summarized: false,
136
- };
137
- }
138
- return {
139
- messages: [...messages],
140
- before,
141
- after: before,
142
- beforeTokens,
143
- afterTokens: beforeTokens,
144
- summarized: false,
145
- };
146
- }
147
- return {
148
- messages: compacted,
149
- before,
150
- after: compacted.length,
151
- beforeTokens,
152
- afterTokens,
153
- summarized: true,
154
- };
155
- }
156
- catch (error) {
157
- if (error instanceof Error && (error.name === "AbortError" || error.message?.includes("aborted"))) {
158
- throw error;
159
- }
160
- const compacted = compactMessages(messages, { ...options, budgetTokens: 0 });
161
- const afterTokens = estimateMessagesTokens(compacted);
162
- if (afterTokens >= beforeTokens && !isForced) {
163
- return {
164
- messages: [...messages],
165
- before,
166
- after: before,
167
- beforeTokens,
168
- afterTokens: beforeTokens,
169
- summarized: false,
170
- };
171
- }
172
- return {
173
- messages: compacted,
174
- before,
175
- after: compacted.length,
176
- beforeTokens,
177
- afterTokens,
178
- summarized: false,
179
- };
180
- }
132
+ // The summary is the only path. Any failure propagates to the caller —
133
+ // there is deliberately NO deterministic fallback.
134
+ const summary = redactSecrets((await summarize(prompt)).trim());
135
+ if (!summary)
136
+ throw new Error("compaction failed: model returned an empty summary");
137
+ const head = start === 1 ? [messages[0]] : [];
138
+ const compacted = [
139
+ ...head,
140
+ { role: "system", content: `${COMPACTION_MEMORY_PREFIX}\n\n${summary}` },
141
+ ...messages.slice(tailStart),
142
+ ];
143
+ const afterTokens = estimateMessagesTokens(compacted);
144
+ return {
145
+ messages: compacted,
146
+ before,
147
+ after: compacted.length,
148
+ beforeTokens,
149
+ afterTokens,
150
+ summarized: true,
151
+ };
181
152
  }
182
153
  function oneLine(text, maxChars) {
183
154
  const cleaned = text.replace(/\s+/g, " ").trim();
@@ -1 +1 @@
1
- {"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,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;IAC9D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAkBD,MAAM,qBAAqB,GAAG,MAAM,CAAC;AACrC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,8CAA8C,CAAC;AACjD,MAAM,CAAC,MAAM,wBAAwB,GACnC,2CAA2C,CAAC;AAE9C,MAAM,UAAU,yBAAyB,CAAC,OAAoB;IAC5D,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,QAAQ;QACzB,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACnD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAC,CACxD,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAuB,EACvB,UAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,MAAM,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvD,IAAI,sBAAsB,CAAC,QAAQ,CAAC,IAAI,MAAM;QAAE,OAAO,QAAQ,CAAC;IAEhE,oEAAoE;IACpE,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEzC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,QAAQ;QACd,OAAO,EACL,GAAG,wBAAwB,oHAAoH;YAC/I,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;KACrB,CAAC;IAEF,OAAO,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,QAAuB,EACvB,SAA8C,EAC9C,UAA0B,EAAE,EAC5B,iBAAsC;IAEtC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/B,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC;IAE5C,IAAI,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IAC9D,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAE7C,yEAAyE;IACzE,qFAAqF;IACrF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACnE,UAAU,GAAG,CAAC,CAAC;QACf,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAChC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,EAAE,EAAE,CAAC;QACrD,4DAA4D;QAC5D,OAAO;YACL,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC;YACvB,MAAM;YACN,KAAK,EAAE,MAAM;YACb,YAAY;YACZ,WAAW,EAAE,YAAY;YACzB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,iBAAiB,GAAG,KAAK;SAC5B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;SACpF,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,MAAM,UAAU,GAAG,iBAAiB,EAAE,IAAI,EAAE;QAC1C,CAAC,CAAC,aAAa,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC,CAAC,iBAAiB,CAAC;IACtB,MAAM,MAAM,GAAG;QACb,4HAA4H;QAC5H,sNAAsN;QACtN,+JAA+J;QAC/J,mHAAmH;QACnH,EAAE;QACF,UAAU;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,uEAAuE;IACvE,mDAAmD;IACnD,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAEpF,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAkB;QAC/B,GAAG,IAAI;QACP,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,wBAAwB,OAAO,OAAO,EAAE,EAAE;QACxE,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;KAC7B,CAAC;IACF,MAAM,WAAW,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IACtD,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,MAAM;QACN,KAAK,EAAE,SAAS,CAAC,MAAM;QACvB,YAAY;QACZ,WAAW;QACX,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,QAAgB;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC;AAC9C,CAAC"}
@@ -48,7 +48,7 @@ export type AgentEvent = {
48
48
  } | {
49
49
  type: "confirm-request";
50
50
  id: string;
51
- kind: "tool" | "pentest" | "reset" | "continue";
51
+ kind: "tool" | "pentest" | "reset" | "continue" | "plan" | "switch";
52
52
  prompt: string;
53
53
  } | {
54
54
  type: "turn-end";
@@ -14,12 +14,21 @@ export interface SessionPolicy {
14
14
  value: boolean;
15
15
  };
16
16
  }
17
- export declare function createSessionPolicy(): SessionPolicy;
17
+ export declare function createSessionPolicy(sessionId?: string): SessionPolicy;
18
18
  export interface ConfirmPort {
19
19
  confirmTool(call: ToolCall): Promise<boolean>;
20
20
  confirmPentest(): Promise<boolean>;
21
21
  /** Ask the user whether to continue after hitting the step budget. */
22
22
  confirmContinue?(steps: number): Promise<boolean>;
23
+ /**
24
+ * Ask whether to leave ask mode and run an action task in agent mode.
25
+ * Optional so existing ports keep working; ask-mode handoff falls back to a
26
+ * default "no" when a port doesn't implement it.
27
+ */
28
+ confirmAgentSwitch?(info: {
29
+ reason: string;
30
+ tools: string[];
31
+ }): Promise<boolean>;
23
32
  }
24
33
  export interface AgentRunOptions {
25
34
  provider?: ProviderId | undefined;
@@ -32,6 +41,14 @@ export interface AgentRunOptions {
32
41
  onToolStart?: ((call: ToolCall) => void) | undefined;
33
42
  onToolResult?: ((call: ToolCall, result: ToolResult) => void) | undefined;
34
43
  onEvent?: ((event: AgentEvent) => void) | undefined;
44
+ /**
45
+ * Called when a turn ends with the FULL conversation for the turn — the user
46
+ * message, every assistant tool-call, every tool result, and the final
47
+ * answer (system prompts excluded). Callers persist this so a resumed
48
+ * session gives the model back what it actually did (commands, outputs,
49
+ * results), not just its prose answers.
50
+ */
51
+ onMessages?: ((messages: ChatMessage[]) => void) | undefined;
35
52
  confirm?: ConfirmPort | undefined;
36
53
  requestSecret?: ((request: {
37
54
  title: string;
@@ -115,6 +132,25 @@ export declare function countToolFences(text: string): number;
115
132
  export declare function parseAllToolCalls(text: string): ToolCall[];
116
133
  /** Structural equality for two tool calls (name + canonical args JSON). */
117
134
  export declare function sameToolCall(a: ToolCall, b: ToolCall): boolean;
135
+ /**
136
+ * Partition a batch of tool calls (in document order) into execution groups.
137
+ * A run of consecutive parallel-safe calls forms one group to be run
138
+ * concurrently (bounded by maxGroupSize); every non-parallel-safe call is its
139
+ * own single-element group, i.e. a sequential barrier. Because plan updates
140
+ * and side-effecting tools are never parallel-safe, they always split the
141
+ * batch — which keeps parallelism scoped within a single task and prevents
142
+ * plan-state races and overlapping writes.
143
+ */
144
+ export declare function groupToolCallsForExecution(calls: ToolCall[], isParallelSafe: (call: ToolCall) => boolean, maxGroupSize?: number): ToolCall[][];
145
+ /**
146
+ * Build the conversation to hand back to the caller at turn end. Strips system
147
+ * prompts (they're re-added each turn) but keeps the user turn plus every
148
+ * assistant tool-call and tool result, then appends the final answer if it
149
+ * isn't already the last message. Persisting this is what lets a resumed
150
+ * session give the model back what it actually did — commands, outputs, and
151
+ * results — instead of only its prose answers.
152
+ */
153
+ export declare function buildTurnHistory(messages: ChatMessage[], answer: string): ChatMessage[];
118
154
  /**
119
155
  * Collapse pathological repetition before a message is stored in history.
120
156
  * Some models degenerate into emitting the same short phrase hundreds of
@@ -123,6 +159,7 @@ export declare function sameToolCall(a: ToolCall, b: ToolCall): boolean;
123
159
  * copies and note the collapse so the meaning is preserved without the bulk.
124
160
  */
125
161
  export declare function collapseRepeatedText(text: string): string;
162
+ export declare function formatToolArgs(call: ToolCall): string;
126
163
  /**
127
164
  * Detect pentest/security tasks that need the full step budget.
128
165
  * Mirrors looksLikeBuildTask but for security work.