@nexrall/code-core 1.4.66 → 1.4.67

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 (75) hide show
  1. package/dist/agent/agentTypes.d.ts +6 -2
  2. package/dist/agent/agentTypes.d.ts.map +1 -1
  3. package/dist/agent/agentTypes.js +13 -4
  4. package/dist/agent/askOnce.d.ts +12 -0
  5. package/dist/agent/askOnce.d.ts.map +1 -0
  6. package/dist/agent/askOnce.js +41 -0
  7. package/dist/agent/compaction.d.ts +244 -0
  8. package/dist/agent/compaction.d.ts.map +1 -0
  9. package/dist/agent/compaction.js +976 -0
  10. package/dist/agent/fileLocks.d.ts +34 -0
  11. package/dist/agent/fileLocks.d.ts.map +1 -0
  12. package/dist/agent/fileLocks.js +114 -0
  13. package/dist/agent/hooks.d.ts +324 -0
  14. package/dist/agent/hooks.d.ts.map +1 -0
  15. package/dist/agent/hooks.js +1228 -0
  16. package/dist/agent/iterationPolicy.d.ts +121 -0
  17. package/dist/agent/iterationPolicy.d.ts.map +1 -0
  18. package/dist/agent/iterationPolicy.js +297 -0
  19. package/dist/agent/lifecycleHost.d.ts +55 -0
  20. package/dist/agent/lifecycleHost.d.ts.map +1 -0
  21. package/dist/agent/lifecycleHost.js +294 -0
  22. package/dist/agent/loop.d.ts +11 -491
  23. package/dist/agent/loop.d.ts.map +1 -1
  24. package/dist/agent/loop.js +417 -3031
  25. package/dist/agent/planMode.d.ts.map +1 -1
  26. package/dist/agent/planMode.js +1 -0
  27. package/dist/agent/sharedTasks.d.ts +7 -0
  28. package/dist/agent/sharedTasks.d.ts.map +1 -1
  29. package/dist/agent/sharedTasks.js +16 -0
  30. package/dist/agent/subAgentBudget.d.ts +65 -0
  31. package/dist/agent/subAgentBudget.d.ts.map +1 -0
  32. package/dist/agent/subAgentBudget.js +269 -0
  33. package/dist/agent/subTask.d.ts +6 -0
  34. package/dist/agent/subTask.d.ts.map +1 -0
  35. package/dist/agent/subTask.js +713 -0
  36. package/dist/agent/subTaskSupport.d.ts +156 -0
  37. package/dist/agent/subTaskSupport.d.ts.map +1 -0
  38. package/dist/agent/subTaskSupport.js +409 -0
  39. package/dist/agent/toolDescriptions.d.ts +3 -0
  40. package/dist/agent/toolDescriptions.d.ts.map +1 -0
  41. package/dist/agent/toolDescriptions.js +116 -0
  42. package/dist/api/client.d.ts.map +1 -1
  43. package/dist/api/client.js +17 -0
  44. package/dist/index.d.ts +3 -0
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +3 -0
  47. package/dist/mcp/client.d.ts +104 -0
  48. package/dist/mcp/client.d.ts.map +1 -1
  49. package/dist/mcp/client.js +136 -2
  50. package/dist/mcp/httpClient.d.ts +17 -1
  51. package/dist/mcp/httpClient.d.ts.map +1 -1
  52. package/dist/mcp/httpClient.js +120 -19
  53. package/dist/mcp/manager.d.ts +77 -2
  54. package/dist/mcp/manager.d.ts.map +1 -1
  55. package/dist/mcp/manager.js +275 -9
  56. package/dist/mcp/sseClient.d.ts +7 -1
  57. package/dist/mcp/sseClient.d.ts.map +1 -1
  58. package/dist/mcp/sseClient.js +45 -1
  59. package/dist/mcp/stats.d.ts +41 -0
  60. package/dist/mcp/stats.d.ts.map +1 -0
  61. package/dist/mcp/stats.js +108 -0
  62. package/dist/permissions/destructive.d.ts +2 -0
  63. package/dist/permissions/destructive.d.ts.map +1 -1
  64. package/dist/permissions/destructive.js +6 -2
  65. package/dist/permissions/destructiveTokens.d.ts +5 -0
  66. package/dist/permissions/destructiveTokens.d.ts.map +1 -1
  67. package/dist/permissions/destructiveTokens.js +9 -3
  68. package/dist/permissions/modePolicy.d.ts.map +1 -1
  69. package/dist/permissions/modePolicy.js +5 -2
  70. package/dist/permissions/rules.d.ts +4 -1
  71. package/dist/permissions/rules.d.ts.map +1 -1
  72. package/dist/permissions/rules.js +29 -0
  73. package/dist/types.d.ts +45 -1
  74. package/dist/types.d.ts.map +1 -1
  75. package/package.json +1 -1
@@ -82,8 +82,12 @@ export interface AgentType {
82
82
  hooks?: AgentHooks;
83
83
  }
84
84
  export interface AgentHookDef {
85
- type: 'command';
86
- command: string;
85
+ type: 'command' | 'http';
86
+ command?: string;
87
+ /** `type:"http"`: POST the hook payload here. */
88
+ url?: string;
89
+ headers?: Record<string, string>;
90
+ allowedEnvVars?: string[];
87
91
  timeout_ms?: number;
88
92
  }
89
93
  export interface AgentHookEntry {
@@ -1 +1 @@
1
- {"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agentTypes.d.ts","sourceRoot":"","sources":["../../src/agent/agentTypes.ts"],"names":[],"mappings":"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"}
@@ -588,12 +588,21 @@ function parseAgentHooks(raw) {
588
588
  throw new Error(`${where}: expected a list of hooks`);
589
589
  return list.map((h, i) => {
590
590
  const o = h;
591
- if (!o || o.type !== 'command' || typeof o.command !== 'string' || !o.command.trim()) {
592
- throw new Error(`${where}[${i}]: each hook needs type: command and a command`);
593
- }
594
591
  const ms = typeof o.timeout_ms === 'number' ? o.timeout_ms
595
592
  : typeof o.timeout === 'number' ? o.timeout * 1000 : undefined;
596
- return { type: 'command', command: o.command, ...(ms && ms > 0 ? { timeout_ms: ms } : {}) };
593
+ const timeout = ms && ms > 0 ? { timeout_ms: ms } : {};
594
+ if (o && o.type === 'http' && typeof o.url === 'string' && o.url.trim()) {
595
+ if (!/^https?:\/\//i.test(o.url.trim()))
596
+ throw new Error(`${where}[${i}]: http hooks need an http(s) url`);
597
+ const headers = o.headers && typeof o.headers === 'object' && !Array.isArray(o.headers)
598
+ ? o.headers : undefined;
599
+ const allowed = Array.isArray(o.allowedEnvVars) ? o.allowedEnvVars.filter((v) => typeof v === 'string') : undefined;
600
+ return { type: 'http', url: o.url.trim(), ...(headers ? { headers } : {}), ...(allowed ? { allowedEnvVars: allowed } : {}), ...timeout };
601
+ }
602
+ if (!o || o.type !== 'command' || typeof o.command !== 'string' || !o.command.trim()) {
603
+ throw new Error(`${where}[${i}]: each hook needs type: command and a command, or type: http and a url`);
604
+ }
605
+ return { type: 'command', command: o.command, ...timeout };
597
606
  });
598
607
  };
599
608
  const entries = (list, ev) => {
@@ -0,0 +1,12 @@
1
+ import type { EnvContext } from '../types';
2
+ export interface AskOnceOptions {
3
+ model: string;
4
+ cwd: string;
5
+ env?: EnvContext;
6
+ timeoutMs?: number;
7
+ abortSignal?: {
8
+ aborted: boolean;
9
+ };
10
+ }
11
+ export declare function askModelOnce(prompt: string, opts: AskOnceOptions): Promise<string | null>;
12
+ //# sourceMappingURL=askOnce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"askOnce.d.ts","sourceRoot":"","sources":["../../src/agent/askOnce.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,UAAU,EAAW,MAAM,UAAU,CAAC;AAKlE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACpC;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwB/F"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // A single tool-less model call: send one prompt, get the text back. Used by small
3
+ // judges (e.g. the CLI's /goal) that need an answer, not an agent loop. It never
4
+ // runs tools, never throws on a model/network failure (returns null) and never
5
+ // outlives its timeout, so a judge can never hang or crash the turn that asked.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.askModelOnce = askModelOnce;
8
+ const client_1 = require("../api/client");
9
+ /** The same marker prompt hooks use: matches no tool, so the backend sends none. */
10
+ const NO_TOOLS_MARKER = '\u0000hook-no-tools';
11
+ async function askModelOnce(prompt, opts) {
12
+ const ctl = { aborted: false };
13
+ const timer = setTimeout(() => { ctl.aborted = true; }, Math.max(1000, opts.timeoutMs ?? 45000));
14
+ const poll = opts.abortSignal
15
+ ? setInterval(() => { if (opts.abortSignal?.aborted)
16
+ ctl.aborted = true; }, 100)
17
+ : undefined;
18
+ try {
19
+ if (opts.abortSignal?.aborted)
20
+ return null;
21
+ const messages = [{ role: 'user', content: [{ type: 'text', text: prompt }] }];
22
+ const msg = await (0, client_1.streamChat)(messages, {
23
+ model: opts.model,
24
+ env: opts.env ?? { cwd: opts.cwd },
25
+ abortSignal: ctl,
26
+ toolAllowlist: [NO_TOOLS_MARKER],
27
+ }, () => { });
28
+ const blocks = Array.isArray(msg.content) ? msg.content : [];
29
+ const text = blocks.filter((b) => b.type === 'text' && typeof b.text === 'string').map((b) => b.text).join('\n');
30
+ return ctl.aborted ? null : text;
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ finally {
36
+ clearTimeout(timer);
37
+ if (poll)
38
+ clearInterval(poll);
39
+ }
40
+ }
41
+ //# sourceMappingURL=askOnce.js.map
@@ -0,0 +1,244 @@
1
+ import type { Message, AgentLoopOptions, EnvContext } from '../types';
2
+ import { streamChat } from '../api/client';
3
+ import { type MemoryScope } from './memory';
4
+ export declare const MODEL_CONTEXT_TOKENS: Record<string, number>;
5
+ /**
6
+ * Context window (tokens) for a model alias or real model id.
7
+ *
8
+ * Checks the LIVE catalogue (GET /api/code/models, modelCatalogue.ts) first —
9
+ * populated once per process by whichever client fetched it (CLI at session
10
+ * start, VS Code via _postModelCatalogue, desktop via its main-process
11
+ * fetch) — falling back to this hard-coded table when no live data exists yet
12
+ * (offline, older backend, or the catalogue simply hasn't been fetched by
13
+ * this call site). This is what lets a model added to the backend registry
14
+ * (services/providers/modelRegistry.js) get the CORRECT context window here
15
+ * even before this table is updated by hand for a new nexrall-code release —
16
+ * exactly the class of bug GPT-5.6's 922K-vs-1.05M mismatch was (see
17
+ * modelRegistry.js's own comment on that row).
18
+ *
19
+ * The static-table fallback is deliberately the SMALLEST window in the table
20
+ * rather than the largest. An unknown model is most likely a newly added one
21
+ * this client build predates, and guessing high is the failure that cannot be
22
+ * recovered from: the turn hits a provider 400 with no chance to compact.
23
+ * Guessing low only costs an earlier, lossy compaction — annoying, not broken.
24
+ */
25
+ export declare function contextWindowFor(model?: string): number;
26
+ /** Token counts at which auto-prune and auto-compact (summarise) fire for a model window. */
27
+ export declare function compactionLimits(contextWindow: number, settingsRaw?: Record<string, unknown>): {
28
+ prune: number;
29
+ compact: number;
30
+ };
31
+ /** Auto-prune / auto-compact thresholds as fractions of the context window — for UI display (e.g. `/context`). */
32
+ export declare function compactionThresholds(contextWindow?: number, settingsRaw?: Record<string, unknown>): {
33
+ prune: number;
34
+ compact: number;
35
+ };
36
+ export declare const PRUNE_MIN_RECLAIM_BYTES: number;
37
+ export declare const _lastApiCallEndedAt: Map<string, number>;
38
+ export declare function pruneReclaimFloor(lastCallEndedAt: number | undefined, now?: number): number;
39
+ export declare const COMPACT_KEEP_MIN = 6;
40
+ /**
41
+ * Bytes a compaction must reclaim to count as productive.
42
+ *
43
+ * Deliberately much smaller than PRUNE_MIN_RECLAIM_BYTES: a prune declines when the
44
+ * gain isn't worth busting the prompt cache, whereas by the time we are summarising
45
+ * we are already committed to rewriting the prefix — the only question is whether the
46
+ * summariser is making ANY headway. 32 KB is small enough that a genuinely useful
47
+ * compaction always clears it, large enough that shuffling a few bytes doesn't.
48
+ */
49
+ export declare const COMPACT_MIN_RECLAIM_BYTES: number;
50
+ /**
51
+ * Consecutive non-productive compaction attempts before auto-compaction is switched
52
+ * off for the rest of the run.
53
+ *
54
+ * 3 rather than 1 because the failure is often transient — a summariser stream that
55
+ * blipped will usually succeed on the next turn, and giving up instantly would lose
56
+ * the safety net for a whole long session over one network hiccup. 3 also bounds the
57
+ * wasted spend: at most three summariser calls, not hundreds.
58
+ */
59
+ export declare const COMPACT_MAX_FAILURES = 3;
60
+ export declare const MAX_BODY_BYTES: number;
61
+ /** Approximate serialised request-body size (bytes) for the messages array. */
62
+ export declare function estimateBodyBytes(messages: Message[]): number;
63
+ export declare function resolveAutoCompact(fromOptions: boolean | undefined, rawSettings: Record<string, unknown>): boolean;
64
+ /** Opt-out for the one-shot verification nudge (GAP D). Defaults to on. */
65
+ export declare function resolveVerificationNudge(rawSettings: Record<string, unknown>): boolean;
66
+ /** Tools that mutate the filesystem — used by the verification nudge (GAP D). */
67
+ export declare const WRITE_TOOL_NAMES: Set<string>;
68
+ /**
69
+ * May an agent restricted to `testFilesOnly` perform this tool call?
70
+ *
71
+ * A tool allowlist is all-or-nothing per tool: granting `edit_file` grants it for
72
+ * every path in the repo. A user-defined test-writer agent needs write access to produce
73
+ * tests, but must NOT be able to "fix" production source so a failing test goes
74
+ * green — the single most common way a test-writing agent destroys the signal it
75
+ * was asked to create. Its prompt says so; this makes it a refusal rather than a
76
+ * request.
77
+ *
78
+ * Pure + exported so the rules are testable directly, without running a real
79
+ * sub-agent.
80
+ *
81
+ * KNOWN LIMIT, stated rather than hidden: this gates the file TOOLS, not `bash`.
82
+ * A determined model could still write source via `bash: echo ... > src/x.ts`.
83
+ * Closing that means parsing shell redirection, which is not reliably doable — so
84
+ * this is a strong guardrail against the realistic failure mode, not a sandbox.
85
+ * Real isolation is the sandbox config (tools/sandbox.ts), a separate mechanism.
86
+ */
87
+ export declare function allowsTestOnlyWrite(tool: string, input: Record<string, unknown> | undefined): boolean;
88
+ /** Heuristic: does a bash command look like it's running tests/build/lint/typecheck? (GAP D) */
89
+ export declare const VERIFY_CMD_RE: RegExp;
90
+ /**
91
+ * Find the latest index ≤ maxIdx where history can be cut safely.
92
+ *
93
+ * A safe cut point is a **turn boundary**: an assistant message (which always
94
+ * begins a fresh turn after a user message). Cutting there guarantees that
95
+ * `messages[cut..]` starts with an assistant whose `tool_use` blocks are all
96
+ * answered by `tool_result`s that remain in the kept slice — so we never orphan
97
+ * a tool_result (which the API rejects). We deliberately allow cutting across
98
+ * tool_result-bearing user messages: the OLD implementation only cut at a
99
+ * *non*-tool_result user message, which never exists inside a single long
100
+ * agentic run (every user turn is a tool_result), so compaction was a no-op
101
+ * exactly when a long task needs it most.
102
+ */
103
+ export declare function findSafeCutIndex(messages: Message[], maxIdx: number): number;
104
+ /**
105
+ * Render messages to a plain-text transcript for the summariser (tool noise
106
+ * truncated per-block AND the whole transcript hard-capped). When the transcript
107
+ * would exceed MAX_TRANSCRIPT_CHARS we keep the HEAD (original task + early
108
+ * decisions) and the TAIL (most-recent, highest-signal context) and drop the
109
+ * middle — a middle-out elision that preserves both "what we set out to do" and
110
+ * "where we are now", which is what the continuation summary needs most.
111
+ */
112
+ /**
113
+ * Appends the backend-announced runtime-context block to the user message it was
114
+ * attached to. No-op if that message is not a user turn or already ends with the
115
+ * identical block. Exported for tests.
116
+ */
117
+ export declare function persistRuntimeContext(messages: Message[], idx: number, text: string): boolean;
118
+ export declare function transcriptOf(messages: Message[]): string;
119
+ export interface ProgressLedger {
120
+ filesTouched: Map<string, {
121
+ tool: string;
122
+ edits: number;
123
+ }>;
124
+ /**
125
+ * DISTINCT paths ever touched, including any since evicted from `filesTouched`.
126
+ *
127
+ * The Map is bounded (see ledgerRecord), so `filesTouched.size` is a window, not a
128
+ * total. The preamble states "FILES CHANGED THIS SESSION (N)" as a fact the model
129
+ * reasons about, so N must not silently shrink when eviction kicks in on a very long
130
+ * run — that would tell the model less work happened than actually did.
131
+ */
132
+ filesTouchedTotal: number;
133
+ verifications: Array<{
134
+ cmd: string;
135
+ ok: boolean;
136
+ epoch: number;
137
+ }>;
138
+ /** Test-integrity findings (reward-hacking signals) that must survive compaction. */
139
+ testIntegrity: Array<{
140
+ path: string;
141
+ reason: string;
142
+ }>;
143
+ /**
144
+ * TOTAL test-integrity findings ever recorded, including ones since trimmed.
145
+ *
146
+ * `testIntegrity` is a bounded window (older entries are spliced off once it grows
147
+ * past 2×LEDGER_MAX_NOTES), so its `.length` STOPS being a running total after the
148
+ * first trim. The one-shot nudge compares "how many findings exist" against "how
149
+ * many I've already surfaced", and comparing against a window that shrinks meant the
150
+ * count could never move ahead again — silently disabling the reward-hacking warning
151
+ * for the remainder of a long session, i.e. exactly when it matters most.
152
+ *
153
+ * This counter only ever increases, so it is a safe basis for that comparison.
154
+ */
155
+ testIntegrityTotal: number;
156
+ /**
157
+ * Monotonic mutation epoch: incremented on every successful source write. Two
158
+ * verification runs sharing an epoch had NO edit between them, so a PASS↔FAIL
159
+ * flip across that boundary proves the test is flaky (see detectFlaky).
160
+ */
161
+ epoch: number;
162
+ }
163
+ export declare function createLedger(): ProgressLedger;
164
+ /** Record one tool call's effect on the ledger (deterministic, no model call). */
165
+ export declare function ledgerRecord(ledger: ProgressLedger, toolName: string, input: Record<string, unknown> | undefined, ok: boolean, output?: string, exitCode?: number): void;
166
+ /** Render the ledger as a compact, verbatim block for the compaction preamble. */
167
+ export declare function ledgerSummary(ledger: ProgressLedger): string;
168
+ export declare const PRUNE_KEEP_RECENT = 8;
169
+ /**
170
+ * Lossy-but-structure-preserving prune: shrink OLD, large tool_result blocks in
171
+ * place, keeping the last PRUNE_KEEP_RECENT messages untouched. This is tried
172
+ * BEFORE summarisation because it:
173
+ * • keeps every turn and every tool_use/tool_result pair (API stays valid),
174
+ * • never makes an extra model call (summarisation does — cost + latency),
175
+ * • degrades gracefully on repeat (summarise-of-summarise loses the most on
176
+ * long runs; pruning just trims already-consumed output further).
177
+ *
178
+ * IMPORTANT: pruned state is encoded in the content string (PRUNE_MARKER_TAIL
179
+ * suffix), NOT as an extra property on the block — a stray field on a content
180
+ * block is rejected by the Anthropic API as an unknown key (400). This keeps the
181
+ * serialised body schema-clean while remaining idempotent across repeat calls.
182
+ *
183
+ * Returns the number of bytes reclaimed (0 if nothing was prunable).
184
+ *
185
+ * `minReclaimBytes` (default 0): if the TOTAL prunable amount is below this, the
186
+ * function makes NO changes and returns 0. This is a cache-safety gate — pruning
187
+ * even one old block changes the request prefix and invalidates the message-level
188
+ * prompt cache, so a tiny prune would bust the cache (re-write at 1.25×) for
189
+ * almost no size win. Measuring first, then applying only if worthwhile, keeps
190
+ * the "don't bust cache for a trivial gain" contract truly atomic (the old code
191
+ * mutated first and let the caller decide, which had already invalidated the
192
+ * cache by the time the caller declined).
193
+ */
194
+ export declare function pruneOldToolResults(messages: Message[], minReclaimBytes?: number): number;
195
+ /**
196
+ * The summariser's own model call failed — as opposed to running fine but not
197
+ * shrinking anything.
198
+ *
199
+ * These two outcomes used to be one `return false`, and collapsing them was a
200
+ * real bug: the in-loop circuit breaker disables auto-compaction permanently
201
+ * after COMPACT_MAX_FAILURES, on the sound theory that a compaction which cannot
202
+ * reclaim bytes will never start. But a summariser that THREW says nothing about
203
+ * whether compaction would help — only that the network/provider was unavailable
204
+ * for a moment. Feeding those into the same counter meant three transient blips
205
+ * (a 529 burst, a brief outage, a rate-limit spike) permanently switched off the
206
+ * one mechanism keeping the context under control, and the run then died at the
207
+ * context wall minutes later with its own recovery already disabled.
208
+ */
209
+ export declare class CompactionUnavailableError extends Error {
210
+ constructor();
211
+ }
212
+ /**
213
+ * Summarises the WHOLE conversation by appending the instruction to its final user
214
+ * message and sending it with the conversation's own request options — Claude Code's
215
+ * approach. The prefix is byte-identical to the previous request, so the history is a
216
+ * cache READ (0.10×) instead of a fresh uncached transcript of up to 600K chars.
217
+ * Returns '' when it cannot be used (last turn is not the user's) or yields no text.
218
+ */
219
+ export type CachedSummarizer = (instruction: string) => Promise<string>;
220
+ export declare function makeCachedSummarizer(messages: Message[], requestOptions: () => Parameters<typeof streamChat>[1], abortSignal?: {
221
+ aborted: boolean;
222
+ }): CachedSummarizer;
223
+ export declare function autoCompactMessages(messages: Message[], options: AgentLoopOptions, ledger?: ProgressLedger, summarizeCached?: CachedSummarizer): Promise<boolean>;
224
+ export declare function maybeCompactMemory(scope: MemoryScope, options: AgentLoopOptions): Promise<void>;
225
+ /** Rough token estimate for a resumed transcript — no API round-trip needed. */
226
+ export declare function estimateTokensRough(messages: Message[]): number;
227
+ /**
228
+ * Proactively compact `messages` in place if resuming this session would blow
229
+ * past the auto-compact threshold on the very first turn. Returns true if any
230
+ * compaction happened (so the caller can surface a one-line notice to the
231
+ * user). Safe to call on any message array, including empty/small ones (no-op).
232
+ *
233
+ * `model` picks the right context window (mirrors runAgentLoop's own lookup);
234
+ * `onNotice` is optional — pass it to show the same "auto-compacted" message
235
+ * the in-loop path shows, so the behaviour is visually consistent.
236
+ */
237
+ export declare function compactMessagesForResume(messages: Message[], opts: {
238
+ model?: string;
239
+ workDir: string;
240
+ clientType?: string;
241
+ env?: EnvContext;
242
+ onNotice?: (text: string) => void;
243
+ }): Promise<boolean>;
244
+ //# sourceMappingURL=compaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/agent/compaction.ts"],"names":[],"mappings":"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"}