claude-code-infinite 1.0.11 → 1.0.16
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/README.md +214 -47
- package/dist/cc-request.d.ts +94 -0
- package/dist/cc-request.d.ts.map +1 -0
- package/dist/cc-request.js +194 -0
- package/dist/cc-request.js.map +1 -0
- package/dist/claude-env.d.ts +30 -0
- package/dist/claude-env.d.ts.map +1 -0
- package/dist/claude-env.js +55 -0
- package/dist/claude-env.js.map +1 -0
- package/dist/cli-args.d.ts +32 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +72 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-lifecycle.d.ts +17 -0
- package/dist/cli-lifecycle.d.ts.map +1 -0
- package/dist/cli-lifecycle.js +30 -0
- package/dist/cli-lifecycle.js.map +1 -0
- package/dist/cli-main.d.ts +15 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +464 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/cli.js +13 -178
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -3
- package/dist/config.js.map +1 -1
- package/dist/count-tokens.d.ts +78 -0
- package/dist/count-tokens.d.ts.map +1 -0
- package/dist/count-tokens.js +277 -0
- package/dist/count-tokens.js.map +1 -0
- package/dist/final-index.d.ts +10 -0
- package/dist/final-index.d.ts.map +1 -0
- package/dist/final-index.js +37 -0
- package/dist/final-index.js.map +1 -0
- package/dist/hooks.d.ts +239 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +618 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/memtree-fetch.d.ts +24 -0
- package/dist/memtree-fetch.d.ts.map +1 -0
- package/dist/memtree-fetch.js +121 -0
- package/dist/memtree-fetch.js.map +1 -0
- package/dist/memtree-finder.d.ts +99 -0
- package/dist/memtree-finder.d.ts.map +1 -0
- package/dist/memtree-finder.js +235 -0
- package/dist/memtree-finder.js.map +1 -0
- package/dist/memtree-links.d.ts +16 -0
- package/dist/memtree-links.d.ts.map +1 -0
- package/dist/memtree-links.js +66 -0
- package/dist/memtree-links.js.map +1 -0
- package/dist/memtree-mcp-config.d.ts +28 -0
- package/dist/memtree-mcp-config.d.ts.map +1 -0
- package/dist/memtree-mcp-config.js +121 -0
- package/dist/memtree-mcp-config.js.map +1 -0
- package/dist/memtree-mcp.d.ts +265 -0
- package/dist/memtree-mcp.d.ts.map +1 -0
- package/dist/memtree-mcp.js +667 -0
- package/dist/memtree-mcp.js.map +1 -0
- package/dist/memtree-newest.d.ts +74 -0
- package/dist/memtree-newest.d.ts.map +1 -0
- package/dist/memtree-newest.js +217 -0
- package/dist/memtree-newest.js.map +1 -0
- package/dist/memtree-tools.d.ts +105 -0
- package/dist/memtree-tools.d.ts.map +1 -0
- package/dist/memtree-tools.js +408 -0
- package/dist/memtree-tools.js.map +1 -0
- package/dist/memtree.d.ts +430 -0
- package/dist/memtree.d.ts.map +1 -0
- package/dist/memtree.js +1286 -0
- package/dist/memtree.js.map +1 -0
- package/dist/notices.d.ts +177 -0
- package/dist/notices.d.ts.map +1 -0
- package/dist/notices.js +469 -0
- package/dist/notices.js.map +1 -0
- package/dist/payment-gate.d.ts +53 -0
- package/dist/payment-gate.d.ts.map +1 -0
- package/dist/payment-gate.js +97 -0
- package/dist/payment-gate.js.map +1 -0
- package/dist/project-meta.d.ts +15 -0
- package/dist/project-meta.d.ts.map +1 -0
- package/dist/project-meta.js +80 -0
- package/dist/project-meta.js.map +1 -0
- package/dist/prompt-accounting.d.ts +12 -0
- package/dist/prompt-accounting.d.ts.map +1 -0
- package/dist/prompt-accounting.js +70 -0
- package/dist/prompt-accounting.js.map +1 -0
- package/dist/proxy.d.ts +204 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +4299 -0
- package/dist/proxy.js.map +1 -0
- package/dist/reqlog.d.ts +427 -0
- package/dist/reqlog.d.ts.map +1 -0
- package/dist/reqlog.js +146 -0
- package/dist/reqlog.js.map +1 -0
- package/dist/request-sizing.d.ts +74 -0
- package/dist/request-sizing.d.ts.map +1 -0
- package/dist/request-sizing.js +121 -0
- package/dist/request-sizing.js.map +1 -0
- package/dist/resume-repair-file.d.ts +17 -0
- package/dist/resume-repair-file.d.ts.map +1 -0
- package/dist/resume-repair-file.js +100 -0
- package/dist/resume-repair-file.js.map +1 -0
- package/dist/resume-repair.d.ts +27 -0
- package/dist/resume-repair.d.ts.map +1 -0
- package/dist/resume-repair.js +198 -0
- package/dist/resume-repair.js.map +1 -0
- package/dist/route-cache.d.ts +5 -0
- package/dist/route-cache.d.ts.map +1 -0
- package/dist/route-cache.js +63 -0
- package/dist/route-cache.js.map +1 -0
- package/dist/route-fallback.d.ts +67 -0
- package/dist/route-fallback.d.ts.map +1 -0
- package/dist/route-fallback.js +126 -0
- package/dist/route-fallback.js.map +1 -0
- package/dist/route-identity.d.ts +6 -0
- package/dist/route-identity.d.ts.map +1 -0
- package/dist/route-identity.js +100 -0
- package/dist/route-identity.js.map +1 -0
- package/dist/transcript-usage.d.ts +57 -0
- package/dist/transcript-usage.d.ts.map +1 -0
- package/dist/transcript-usage.js +570 -0
- package/dist/transcript-usage.js.map +1 -0
- package/dist/turns.d.ts +77 -0
- package/dist/turns.d.ts.map +1 -0
- package/dist/turns.js +330 -0
- package/dist/turns.js.map +1 -0
- package/dist/update-check.d.ts +38 -0
- package/dist/update-check.d.ts.map +1 -0
- package/dist/update-check.js +67 -0
- package/dist/update-check.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client for the polychat.co MemTree API (/v1/context_memory).
|
|
3
|
+
*
|
|
4
|
+
* Two modes, mirroring the server's lazy-compression path (cc_api.py):
|
|
5
|
+
* - Tool turns: fire-and-forget indexing POST, off the response path.
|
|
6
|
+
* - User turns: blocking compression call with a hard timeout; the caller
|
|
7
|
+
* degrades to transparent pass-through on any failure (including 402 —
|
|
8
|
+
* compression is the paid feature, the user's own Anthropic call is never
|
|
9
|
+
* gated on it). A 402 from either mode additionally records
|
|
10
|
+
* payment-required state (paymentRequiredDetail) so the proxy can tell the
|
|
11
|
+
* user WHY MemTree is off instead of implying a transient outage; any later
|
|
12
|
+
* successful call clears it (the user paid mid-session).
|
|
13
|
+
*
|
|
14
|
+
* Compression work is deduped per complete request key, while background
|
|
15
|
+
* indexing is deduped per messages hash. Claude Code retries therefore cannot
|
|
16
|
+
* amplify identical HTTP calls, and budget-changing inputs never reuse a
|
|
17
|
+
* stale compression result.
|
|
18
|
+
*/
|
|
19
|
+
import { type FinalReplyReader } from "./final-index.js";
|
|
20
|
+
import type { MessageTimes, MessageUsage } from "./transcript-usage.js";
|
|
21
|
+
import type { RequestLogSink } from "./reqlog.js";
|
|
22
|
+
import { type Message } from "./turns.js";
|
|
23
|
+
export declare const CLIENT_NAME = "cc-infinite";
|
|
24
|
+
export declare const CLIENT_VERSION: string;
|
|
25
|
+
/**
|
|
26
|
+
* A main-lane Stop followed by this long without a new request is taken as the
|
|
27
|
+
* session's end, and its final index goes out (exit sends it at once). Shorter
|
|
28
|
+
* pauses spend the server's once-per-30-minutes final index mid-session.
|
|
29
|
+
*/
|
|
30
|
+
export declare const FINAL_INDEX_IDLE_MS: number;
|
|
31
|
+
/** Sessions finalized at exit at most (newest first), inside the 2 s drain. */
|
|
32
|
+
export declare const FINAL_INDEX_EXIT_SESSIONS = 3;
|
|
33
|
+
export interface MemtreeOptions {
|
|
34
|
+
baseUrl: string;
|
|
35
|
+
apiKey: string;
|
|
36
|
+
compressTimeoutMs?: number;
|
|
37
|
+
debug?: boolean;
|
|
38
|
+
/** Always-on JSONL diagnostics; every MemTree call logs one line. */
|
|
39
|
+
reqlog?: RequestLogSink;
|
|
40
|
+
/**
|
|
41
|
+
* `x-memtree-tools` on compress calls: the memtree MCP tools this Claude
|
|
42
|
+
* Code session has (e.g. "search,read_node,read_lines"), so the server can
|
|
43
|
+
* tell the model how to use them in the memory it returns. Set only when
|
|
44
|
+
* the `memtree` MCP server is configured for the session (memtree-mcp-config.ts).
|
|
45
|
+
*/
|
|
46
|
+
memtreeTools?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Request metadata forwarded to the server so it can resolve a model-based
|
|
50
|
+
* memory budget (e.g. the 800k whole-request target for Fable / Opus 5).
|
|
51
|
+
* Without `model` the server can only apply its static 50k fallback.
|
|
52
|
+
*/
|
|
53
|
+
export interface CompressRequestMeta {
|
|
54
|
+
model?: string;
|
|
55
|
+
tools?: unknown[];
|
|
56
|
+
/**
|
|
57
|
+
* Explicit whole-request target (server `compression_target_tokens`),
|
|
58
|
+
* overriding the model-based budget. Set by `/memtree-compact` so a session
|
|
59
|
+
* is compressed even while it would still fit the model's window.
|
|
60
|
+
*/
|
|
61
|
+
compressionTargetTokens?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Server `compression_threshold_tokens`: compress only when the whole
|
|
64
|
+
* request exceeds this many tokens, and then to `compressionTargetTokens`.
|
|
65
|
+
* Without it the target is also the threshold. Servers that predate the
|
|
66
|
+
* field ignore it (they also omit `model_budget_tokens`, which is how the
|
|
67
|
+
* proxy tells them apart).
|
|
68
|
+
*/
|
|
69
|
+
compressionThresholdTokens?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Server `client_input_tokens`: the proxy's own estimate of the request's
|
|
72
|
+
* input tokens, the one its fallback gate refuses over-budget input by.
|
|
73
|
+
* Over the budget, the server compresses even when its char estimate says
|
|
74
|
+
* the request fits, so the two cannot disagree into a stuck session
|
|
75
|
+
* (2026-10-05). Part of the cache key: a different estimate can flip the
|
|
76
|
+
* server's verdict for the same messages.
|
|
77
|
+
*/
|
|
78
|
+
clientInputTokens?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Each assistant message's response usage (output, thinking, input), keyed
|
|
81
|
+
* by its position in the messages sent. Archived by the server for the
|
|
82
|
+
* MemTree page; never hashed, never part of the compression cache key.
|
|
83
|
+
*/
|
|
84
|
+
messageUsage?: MessageUsage;
|
|
85
|
+
/**
|
|
86
|
+
* When Claude Code wrote each message (ISO), keyed like messageUsage. The
|
|
87
|
+
* server records a time range per MemTree input block; never hashed, never
|
|
88
|
+
* part of the compression cache key.
|
|
89
|
+
*/
|
|
90
|
+
messageTimes?: MessageTimes;
|
|
91
|
+
/**
|
|
92
|
+
* Claude Code's session id, sent as `x-claude-code-session-id` so the
|
|
93
|
+
* server can list a session's MemTree pages by it. Also scopes cached pages.
|
|
94
|
+
*/
|
|
95
|
+
sessionId?: string;
|
|
96
|
+
/** Sent as `x-client-meta`; stored on the usage row. Not part of the cache key. */
|
|
97
|
+
clientMeta?: Record<string, string>;
|
|
98
|
+
}
|
|
99
|
+
export interface CompressResult {
|
|
100
|
+
/** Processed (compressed) messages from the server; system role may be included. */
|
|
101
|
+
messages: Message[];
|
|
102
|
+
/**
|
|
103
|
+
* The server-side flatten of `messages`: exactly one user message whose
|
|
104
|
+
* string content is the whole compressed conversation, produced by the
|
|
105
|
+
* server's `flatten_to_single_user_message` (the single implementation of
|
|
106
|
+
* the flatten format). Returned when the request asked for `flatten: true`;
|
|
107
|
+
* pre-flatten servers omit it. The client treats these bytes as opaque —
|
|
108
|
+
* it no longer has a flatten of its own — so a result without this field
|
|
109
|
+
* cannot be forwarded compressed (see serverFlattenedMessages).
|
|
110
|
+
*/
|
|
111
|
+
flattened_messages?: Message[];
|
|
112
|
+
/**
|
|
113
|
+
* Explicit server verdict on whether the conversation was rewritten. False
|
|
114
|
+
* on a passthrough (request already under the model budget, or no index
|
|
115
|
+
* yet), where `messages` is the conversation as-is and the server also
|
|
116
|
+
* omits `flattened_messages`. Older servers omit this field; callers fall
|
|
117
|
+
* back to the cached_tokens heuristic (see didMemtreeCompress).
|
|
118
|
+
*/
|
|
119
|
+
compressed?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* The model's whole-request budget the server computed (tokens), whatever
|
|
122
|
+
* target the request set. Servers that predate it omit the field.
|
|
123
|
+
*/
|
|
124
|
+
model_budget_tokens?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Optional explicit unfolded index, consumed only by the memoryChars
|
|
127
|
+
* reqlog diagnostic. Older servers omit it; callers fall back to the first
|
|
128
|
+
* non-system processed message, which is the current server layout.
|
|
129
|
+
*/
|
|
130
|
+
unfolded_memory?: string;
|
|
131
|
+
usage?: unknown;
|
|
132
|
+
/** Client-observed latency of the underlying HTTP call (survives retry dedupe). */
|
|
133
|
+
clientLatencyMs?: number;
|
|
134
|
+
/**
|
|
135
|
+
* The per-request MemTree page (`X-Polychat-Memtree-Url`), when the server
|
|
136
|
+
* sent one. `.json` on the same path is the machine-readable tree.
|
|
137
|
+
*/
|
|
138
|
+
memtreeUrl?: string;
|
|
139
|
+
/**
|
|
140
|
+
* The completed index this turn was compressed against
|
|
141
|
+
* (`X-Polychat-Memtree-Index`); absent on index-only acks and servers that
|
|
142
|
+
* predate it. A new value means a new index finished and is now in use.
|
|
143
|
+
*/
|
|
144
|
+
memtreeIndex?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Proposed server field: true when messages in this request are not yet in
|
|
147
|
+
* the tree it answered from and an indexing job will cover them. Absent on
|
|
148
|
+
* current servers, which then report no lag (see indexBehind).
|
|
149
|
+
*/
|
|
150
|
+
index_pending?: boolean;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The server-flattened single user message of a compressed result, or null
|
|
154
|
+
* when the server did not provide a valid one (a pre-flatten server, or a
|
|
155
|
+
* malformed field). The flatten format lives server-side ONLY — the client
|
|
156
|
+
* must never re-derive or post-process it — so a null here means the result
|
|
157
|
+
* cannot be forwarded in compressed form and the caller degrades to the
|
|
158
|
+
* original history. Returns a fresh single-message array so callers may
|
|
159
|
+
* embed it in a request body without sharing structure with the result.
|
|
160
|
+
*/
|
|
161
|
+
export declare function serverFlattenedMessages(result: CompressResult): Message[] | null;
|
|
162
|
+
/**
|
|
163
|
+
* Whether the server actually rewrote the conversation. A successful
|
|
164
|
+
* context_memory response is not enough: the endpoint returns the messages
|
|
165
|
+
* as-is while an index is still warming AND whenever the request already fits
|
|
166
|
+
* the model budget. The server's explicit `compressed` verdict is
|
|
167
|
+
* authoritative. The cached_tokens fallback only covers servers that predate
|
|
168
|
+
* it: cached_tokens is a billing prediction, not a compression signal, and is
|
|
169
|
+
* > 0 on most under-budget passthroughs — so on such servers those turns are
|
|
170
|
+
* flattened and Anthropic's prefix cache misses every human turn.
|
|
171
|
+
*/
|
|
172
|
+
export declare function didMemtreeCompress(result: CompressResult): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Number of original prompt tokens covered by the index MemTree selected.
|
|
175
|
+
*
|
|
176
|
+
* Prefers `usage.indexed_tokens`: since 2026-10-04 the server bills a
|
|
177
|
+
* passthrough's covered input at nothing, so `cached_tokens` is 0 there even
|
|
178
|
+
* when a tree covers the prompt. Older servers only send `cached_tokens`.
|
|
179
|
+
*/
|
|
180
|
+
export declare function cachedPromptTokenCount(result: CompressResult): number | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Whether the server says its index trails this conversation (`index_pending`):
|
|
183
|
+
* unindexed messages stay verbatim, so a compress once indexing catches up can
|
|
184
|
+
* shrink what this one could not. Usage counters cannot say this —
|
|
185
|
+
* `indexed_tokens` is a billing figure that counts a still-running job as
|
|
186
|
+
* covered — so a server without the field reports no lag.
|
|
187
|
+
*/
|
|
188
|
+
export declare function indexBehind(result: CompressResult): boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Evidence that MemTree's index has not caught up with this conversation:
|
|
191
|
+
* the server says so, or it passed the conversation through with nothing
|
|
192
|
+
* indexed and a page for the tree it is building.
|
|
193
|
+
*/
|
|
194
|
+
export declare function indexLagEvidence(result: CompressResult): boolean;
|
|
195
|
+
/** The server-reported model budget, when present and sane. */
|
|
196
|
+
export declare function modelBudgetTokens(result: CompressResult): number | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* MemTree's informational estimate of the original, pre-consolidation prompt.
|
|
199
|
+
* Newer servers include images as visual-token estimates and deliberately keep
|
|
200
|
+
* this value separate from billable Context Memory usage.
|
|
201
|
+
*/
|
|
202
|
+
export declare function rawPromptTokenCount(result: CompressResult): number | undefined;
|
|
203
|
+
/**
|
|
204
|
+
* Minimum conversation content, beyond any verbatim echo of the current turn,
|
|
205
|
+
* that a compressed response must carry before we will send it to Anthropic in
|
|
206
|
+
* place of the real history.
|
|
207
|
+
*
|
|
208
|
+
* Sized well below any useful memory (the server's own semantic floor is 15k
|
|
209
|
+
* chars) and well above an empty answer, so this fires only on genuine context
|
|
210
|
+
* loss and never on a legitimately aggressive compression.
|
|
211
|
+
*/
|
|
212
|
+
export declare const MIN_RETAINED_HISTORY_CHARS = 2000;
|
|
213
|
+
export interface CompressedHistoryCheck {
|
|
214
|
+
/** Flattened conversation characters, falling back to structured messages. */
|
|
215
|
+
retainedChars: number;
|
|
216
|
+
/** Characters in the turn that prompted this request (as sent). */
|
|
217
|
+
currentTurnChars: number;
|
|
218
|
+
/** Non-system characters of prior conversation we asked it to compress. */
|
|
219
|
+
priorHistoryChars: number;
|
|
220
|
+
/** False when the response carries no usable prior conversation. */
|
|
221
|
+
usable: boolean;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Decide whether a compressed response still contains the conversation.
|
|
225
|
+
*
|
|
226
|
+
* This is deliberately NOT derived from `usage`. Every usage-derived signal —
|
|
227
|
+
* `cached_tokens` and the `raw - cached` tail — measures how much of the prompt
|
|
228
|
+
* the server's INDEX covered, not how much context it put in the response. A
|
|
229
|
+
* server that indexes every message and then allocates zero characters to
|
|
230
|
+
* memory (because fixed system+tool overhead exceeded its whole-request budget)
|
|
231
|
+
* reports perfect coverage while returning nothing at all, and the tail metric
|
|
232
|
+
* scores that empty answer as the best possible result. Only the body itself
|
|
233
|
+
* says what the model will actually see.
|
|
234
|
+
*
|
|
235
|
+
* "Retained prior conversation" is measured as the result's conversation
|
|
236
|
+
* characters minus only the part that verbatim-echoes the SENT current turn —
|
|
237
|
+
* not minus the current turn's full size. A turn the server itself shrank
|
|
238
|
+
* (e.g. a 100k-char pasted log returned as a 5k summary) leaves no verbatim
|
|
239
|
+
* echo, so its compressed rendering counts as retained context instead of
|
|
240
|
+
* sinking the score below zero and disabling compression on exactly the turns
|
|
241
|
+
* that need it. The failure the floor exists to catch — the server echoing the
|
|
242
|
+
* current turn back with essentially nothing of the prior conversation — still
|
|
243
|
+
* scores ~0, because every verbatim echo (whole, truncated, or embedded in a
|
|
244
|
+
* larger message) is fully subtracted, and a double echo — the turn embedded
|
|
245
|
+
* in the memory block AND replayed as the tail, or carried twice within one
|
|
246
|
+
* memory blob — is charged for every copy rather than netting out to a
|
|
247
|
+
* single turn's worth of "retained" text. An echo fragmented across
|
|
248
|
+
* consecutive text blocks is caught by re-checking each run of adjacent
|
|
249
|
+
* plain-text pieces as one coalesced passage. Fragments below a small length
|
|
250
|
+
* floor are never counted as echo, so a turn that quotes prior messages
|
|
251
|
+
* cannot sink the genuine memory that contains those same fragments. A rewritten-but-still-empty answer can
|
|
252
|
+
* in principle slip through; the trade is deliberate, since rewriting proves
|
|
253
|
+
* the server did compression work rather than dropping context.
|
|
254
|
+
*/
|
|
255
|
+
export declare function checkCompressedHistory(result: CompressResult, sentMessages: Message[], minRetainedChars?: number): CompressedHistoryCheck;
|
|
256
|
+
/**
|
|
257
|
+
* Remove model-specific reasoning blocks from the copy sent to MemTree.
|
|
258
|
+
*
|
|
259
|
+
* Claude Code does not reliably replay prior-turn thinking after a model
|
|
260
|
+
* change or process resume. Thinking text, redacted payloads, and signatures
|
|
261
|
+
* are required when present in the live Anthropic request, but none is stable
|
|
262
|
+
* conversation identity for indexing.
|
|
263
|
+
*
|
|
264
|
+
* Scope this narrowly to assistant thinking blocks. A field named `signature`
|
|
265
|
+
* inside tool input/result data can be real user data and must remain intact.
|
|
266
|
+
* The original request is never mutated and still goes to Anthropic verbatim.
|
|
267
|
+
*/
|
|
268
|
+
export declare function normalizeMessagesForMemtree(messages: Message[]): Message[];
|
|
269
|
+
export declare class MemtreeClient {
|
|
270
|
+
private baseUrl;
|
|
271
|
+
private apiKey;
|
|
272
|
+
private compressTimeoutMs;
|
|
273
|
+
private debug;
|
|
274
|
+
private reqlog;
|
|
275
|
+
private memtreeTools;
|
|
276
|
+
/** Complete compression request key → in-flight/settled promise (retry dedupe). */
|
|
277
|
+
private compressCache;
|
|
278
|
+
/** When a cached compress result stops answering (expireCompressResult). */
|
|
279
|
+
private readonly compressExpiry;
|
|
280
|
+
private readonly compressResultKeys;
|
|
281
|
+
/** Message hashes already submitted for background indexing. */
|
|
282
|
+
private indexedHashes;
|
|
283
|
+
/** In-flight index-only calls, tracked so shutdown cannot outrun their logs. */
|
|
284
|
+
private backgroundIndexes;
|
|
285
|
+
/** Once draining begins, no later request may create another log producer. */
|
|
286
|
+
private backgroundClosing;
|
|
287
|
+
/** Session → its main lane's latest conversation, for the final index. */
|
|
288
|
+
private readonly mainConversations;
|
|
289
|
+
/** Session → its final index waiting for the session to stay idle. */
|
|
290
|
+
private readonly pendingFinals;
|
|
291
|
+
/** Session → hash of the conversation its last final index sent. */
|
|
292
|
+
private readonly finalIndexed;
|
|
293
|
+
private readonly finalPreparing;
|
|
294
|
+
private finalDrainDeadline;
|
|
295
|
+
/** FastAPI `detail` text from the most recent 402, or null while paid. */
|
|
296
|
+
private unpaidDetail;
|
|
297
|
+
/** Complete compression request key → whether its latest failure arms fuse. */
|
|
298
|
+
private compressFailureArming;
|
|
299
|
+
/**
|
|
300
|
+
* Non-null when the server last answered 402 (unpaid MemTree key): the
|
|
301
|
+
* server's human-readable detail text. Set by both compression and
|
|
302
|
+
* background-indexing calls; cleared by any subsequent success.
|
|
303
|
+
*/
|
|
304
|
+
get paymentRequiredDetail(): string | null;
|
|
305
|
+
/**
|
|
306
|
+
* The blocking-compress abort budget. Exposed so the proxy's request log
|
|
307
|
+
* can label a failed compress that consumed (roughly) the whole budget as a
|
|
308
|
+
* timeout rather than a fast server error.
|
|
309
|
+
*/
|
|
310
|
+
get compressBudgetMs(): number;
|
|
311
|
+
/** Change the `x-memtree-tools` value for later calls (undefined: none). */
|
|
312
|
+
setMemtreeTools(value: string | undefined): void;
|
|
313
|
+
/**
|
|
314
|
+
* GET a MemTree view path (`/usage/memtree/<id>[.json][?share=…]`) on the
|
|
315
|
+
* polychat host with this client's key. Backs the loopback `/memtree/*`
|
|
316
|
+
* passthrough, so an agent inside a ccc session reads the user's own tree
|
|
317
|
+
* through ANTHROPIC_BASE_URL without ever handling the key.
|
|
318
|
+
*/
|
|
319
|
+
fetchMemTree(pathAndQuery: string, accept?: string, signal?: AbortSignal, extraHeaders?: Record<string, string>): Promise<{
|
|
320
|
+
status: number;
|
|
321
|
+
contentType: string;
|
|
322
|
+
body: Buffer;
|
|
323
|
+
}>;
|
|
324
|
+
constructor(opts: MemtreeOptions);
|
|
325
|
+
static hashMessages(messages: Message[]): string;
|
|
326
|
+
/**
|
|
327
|
+
* Whether compress(hash, limit, meta) would answer without contacting the server: an
|
|
328
|
+
* already-settled success, or a leg another caller has in flight. Callers
|
|
329
|
+
* that read a compress result as evidence about the SERVER's health must
|
|
330
|
+
* consult this first — a memoized answer proves only that the server was
|
|
331
|
+
* alive whenever that entry was created, which may be many minutes and one
|
|
332
|
+
* outage ago. In-flight entries count as cached here even though they are
|
|
333
|
+
* real round trips: conservatively discarding live evidence only forgoes an
|
|
334
|
+
* optimization, whereas trusting a stale one suppresses a real outage.
|
|
335
|
+
*/
|
|
336
|
+
hasCachedCompress(hash: string, modelContextLimit: number, meta?: CompressRequestMeta): boolean;
|
|
337
|
+
/**
|
|
338
|
+
* Fuse classification for the most recent live compress failure of `hash`.
|
|
339
|
+
* The entry is recorded before the failed promise settles null, and a
|
|
340
|
+
* concurrent same-request retry MAY overwrite it with a different class — so
|
|
341
|
+
* callers must sample at their own leg's settle (a .then on the compress
|
|
342
|
+
* promise), not after awaiting other work; only that keeps the read paired
|
|
343
|
+
* with the failure it describes.
|
|
344
|
+
* Arming failures are evidence about the SERVER's health: no response at
|
|
345
|
+
* all (network error or the abort-budget timeout), any 5xx, and 402 —
|
|
346
|
+
* unpaid is global and persistent, so it must keep arming. Any other 4xx
|
|
347
|
+
* came from a responsive server rejecting this one request and must not
|
|
348
|
+
* open the shared fuse. Unclassified failures default to arming: muting
|
|
349
|
+
* the fuse needs positive evidence of a responsive server.
|
|
350
|
+
*/
|
|
351
|
+
lastCompressFailureArming(hash: string, modelContextLimit: number, meta?: CompressRequestMeta): boolean;
|
|
352
|
+
/**
|
|
353
|
+
* Blocking user-turn compression. Returns null on ANY failure (timeout,
|
|
354
|
+
* network, 4xx/5xx including 402) — the caller must degrade to passthrough.
|
|
355
|
+
* On 402 the failure is additionally recorded in paymentRequiredDetail so
|
|
356
|
+
* the caller can distinguish "unpaid" from "outage".
|
|
357
|
+
*/
|
|
358
|
+
compress(hash: string, messages: Message[], modelContextLimit: number, signal?: AbortSignal, meta?: CompressRequestMeta): Promise<CompressResult | null>;
|
|
359
|
+
/**
|
|
360
|
+
* Let `result` answer identical requests for `afterMs` more, then ask the
|
|
361
|
+
* server again: an answer from a lagging index goes stale once indexing
|
|
362
|
+
* catches up. In-flight calls are untouched (still deduplicated), and an
|
|
363
|
+
* earlier expiry is kept, so retries cannot postpone the refresh.
|
|
364
|
+
*/
|
|
365
|
+
expireCompressResult(result: CompressResult, afterMs: number): void;
|
|
366
|
+
/** The cached compress promise for `key`, dropping one past its expiry. */
|
|
367
|
+
private liveCompress;
|
|
368
|
+
/**
|
|
369
|
+
* Fire-and-forget background indexing for tool and first-user turns. Keeps
|
|
370
|
+
* the server index fed during tool loops; adds zero latency to the response
|
|
371
|
+
* path. A tool turn whose route-miss recovery got any non-null compress()
|
|
372
|
+
* response skips this: that call already submitted the same history. A
|
|
373
|
+
* recovery that returned null skips it too when the client has already
|
|
374
|
+
* disconnected, or on shutdown/402 — only an ordinary failure with a live
|
|
375
|
+
* client keeps the longer-budget background retry.
|
|
376
|
+
*/
|
|
377
|
+
indexInBackground(hash: string, messages: Message[], modelContextLimit: number, sessionId?: string, clientMeta?: Record<string, string>,
|
|
378
|
+
/** Times for retained original messages, in the positions actually sent. */
|
|
379
|
+
messageTimesFor?: (messages: Message[]) => MessageTimes): void;
|
|
380
|
+
/**
|
|
381
|
+
* The main lane's latest conversation for a session, kept for its final
|
|
382
|
+
* index (scheduleFinalIndex). A new request also means the session did not
|
|
383
|
+
* end at the last Stop: its pending final index is cancelled.
|
|
384
|
+
*/
|
|
385
|
+
noteMainConversation(sessionId: string | undefined, conversation: MainConversation): void;
|
|
386
|
+
/**
|
|
387
|
+
* After a main-lane Stop: once the session has been idle `delayMs` (or at
|
|
388
|
+
* shutdown, flushFinalIndexes), send its conversation plus the reply it
|
|
389
|
+
* ended with as one index-only call flagged final_index, so the server
|
|
390
|
+
* indexes the tail even below its 10k-token minimum (at most once per
|
|
391
|
+
* conversation per 30 minutes, server-side). Every per-request index call
|
|
392
|
+
* lacks that reply: it only appears in the next request. `readReply` reads
|
|
393
|
+
* it from the transcript when the call goes out, not inside the hook.
|
|
394
|
+
*/
|
|
395
|
+
scheduleFinalIndex(sessionId: string | undefined, readReply: FinalReplyReader, delayMs?: number): void;
|
|
396
|
+
/**
|
|
397
|
+
* At shutdown, before drainBackground: finalize at most the three newest
|
|
398
|
+
* sessions, including sessions that never had a Stop (`-p`
|
|
399
|
+
* and non-TTY runs install no hooks). Never throws: a failure here must not
|
|
400
|
+
* change ccc's exit code. The calls share drainBackground's bounded wait.
|
|
401
|
+
*/
|
|
402
|
+
flushFinalIndexes(timeoutMs?: number): void;
|
|
403
|
+
private cancelFinalIndex;
|
|
404
|
+
private fireFinalIndex;
|
|
405
|
+
private sendFinalIndex;
|
|
406
|
+
private submitIndexOnly;
|
|
407
|
+
/**
|
|
408
|
+
* Stop accepting background indexes and wait boundedly for those already in
|
|
409
|
+
* flight. Calls still running after the grace period are aborted, and this
|
|
410
|
+
* method does not return until their final request-log records are produced.
|
|
411
|
+
* The boolean is true for a graceful drain and false when abort was needed.
|
|
412
|
+
*/
|
|
413
|
+
drainBackground(timeoutMs?: number): Promise<boolean>;
|
|
414
|
+
private compressKey;
|
|
415
|
+
private remember;
|
|
416
|
+
private callContextMemory;
|
|
417
|
+
private log;
|
|
418
|
+
}
|
|
419
|
+
/** What noteMainConversation keeps: the last main-lane request as sent to MemTree. */
|
|
420
|
+
export interface MainConversation {
|
|
421
|
+
messages: Message[];
|
|
422
|
+
modelContextLimit: number;
|
|
423
|
+
clientMeta?: Record<string, string>;
|
|
424
|
+
messageTimesFor?: (messages: Message[]) => MessageTimes;
|
|
425
|
+
/** The reply the session ended with (Claude Code's transcript), for a final index at exit. */
|
|
426
|
+
readReply?: FinalReplyReader;
|
|
427
|
+
}
|
|
428
|
+
/** The conversation plus the reply that ended it, unless it already ends with a reply. */
|
|
429
|
+
export declare function withFinalReply(messages: Message[], reply: Message | undefined): Message[];
|
|
430
|
+
//# sourceMappingURL=memtree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memtree.d.ts","sourceRoot":"","sources":["../src/memtree.ts"],"names":[],"mappings":"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"}
|