mcp-context-cost 0.3.0 → 0.5.0
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 +202 -43
- package/dist/audit/audit.d.ts +101 -0
- package/dist/audit/audit.js +492 -16
- package/dist/audit/config.d.ts +38 -0
- package/dist/audit/config.js +64 -0
- package/dist/audit/deferral.d.ts +346 -0
- package/dist/audit/deferral.js +376 -0
- package/dist/audit/diff.d.ts +124 -0
- package/dist/audit/diff.js +318 -0
- package/dist/audit/run.d.ts +34 -0
- package/dist/audit/run.js +45 -2
- package/dist/cli.d.ts +21 -0
- package/dist/cli.js +141 -7
- package/dist/core/adoption.d.ts +226 -0
- package/dist/core/adoption.js +432 -0
- package/dist/core/canonical.d.ts +6 -0
- package/dist/core/canonical.js +3 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/session-start.d.ts +102 -0
- package/dist/core/session-start.js +186 -0
- package/dist/core/types.d.ts +8 -0
- package/dist/sweep/client.d.ts +6 -1
- package/dist/sweep/client.js +1 -0
- package/dist/sweep/dashboard.d.ts +18 -0
- package/dist/sweep/dashboard.js +74 -10
- package/dist/sweep/docker.d.ts +31 -0
- package/dist/sweep/docker.js +20 -11
- package/dist/sweep/harness-guard.d.ts +57 -0
- package/dist/sweep/harness-guard.js +144 -0
- package/dist/sweep/history.d.ts +33 -1
- package/dist/sweep/history.js +60 -5
- package/dist/sweep/regen.js +6 -1
- package/dist/sweep/report.d.ts +18 -0
- package/dist/sweep/report.js +79 -5
- package/dist/sweep/run.d.ts +43 -0
- package/dist/sweep/run.js +135 -37
- package/dist/sweep/server-pages.js +31 -6
- package/dist/sweep/session-start.d.ts +3 -0
- package/dist/sweep/session-start.js +103 -0
- package/dist/sweep/shard.d.ts +41 -0
- package/dist/sweep/shard.js +58 -0
- package/dist/sweep/sweep-all.js +57 -2
- package/package.json +3 -1
package/dist/audit/config.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { existsSync, readFileSync } from 'node:fs';
|
|
20
20
|
import { join } from 'node:path';
|
|
21
|
+
import { TOOL_SEARCH_VARS, } from './deferral.js';
|
|
21
22
|
/**
|
|
22
23
|
* JSON with comments and trailing commas — VS Code's mcp.json allows both, and
|
|
23
24
|
* hand-edited Claude/Cursor configs often pick up a trailing comma too. String
|
|
@@ -177,3 +178,66 @@ export function loadConfigs(candidates, cwd) {
|
|
|
177
178
|
}
|
|
178
179
|
return out;
|
|
179
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Every settings file Claude Code takes environment variables from, highest
|
|
183
|
+
* precedence first.
|
|
184
|
+
*
|
|
185
|
+
* A client config says which servers there are; these say how the client
|
|
186
|
+
* behaves — including whether it defers their tool definitions. They are a
|
|
187
|
+
* different set of files from `configCandidates` above and are read for a
|
|
188
|
+
* different question, so they are listed separately rather than folded in.
|
|
189
|
+
*
|
|
190
|
+
* Order is Claude Code's documented settings precedence (enterprise managed
|
|
191
|
+
* policy, then project-local, then project, then user), read 2026-08-20. Paths
|
|
192
|
+
* in, candidates out — nothing here touches a disk.
|
|
193
|
+
*/
|
|
194
|
+
export function settingsCandidates(env) {
|
|
195
|
+
const { home, cwd, platform } = env;
|
|
196
|
+
const managed = platform === 'darwin'
|
|
197
|
+
? '/Library/Application Support/ClaudeCode/managed-settings.json'
|
|
198
|
+
: platform === 'win32'
|
|
199
|
+
? join(env.programData ?? 'C:\\ProgramData', 'ClaudeCode', 'managed-settings.json')
|
|
200
|
+
: '/etc/claude-code/managed-settings.json';
|
|
201
|
+
return [
|
|
202
|
+
{ scope: 'managed-settings', path: managed },
|
|
203
|
+
{ scope: 'local-settings', path: join(cwd, '.claude', 'settings.local.json') },
|
|
204
|
+
{ scope: 'project-settings', path: join(cwd, '.claude', 'settings.json') },
|
|
205
|
+
{ scope: 'user-settings', path: join(home, '.claude', 'settings.json') },
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Read what each settings file sets, of the variables that decide deferral.
|
|
210
|
+
*
|
|
211
|
+
* Every candidate comes back, present or not, because "this file is not on the
|
|
212
|
+
* machine" and "this file was never opened" are different answers to the
|
|
213
|
+
* question the report asks, and only one of them means the default stands.
|
|
214
|
+
*
|
|
215
|
+
* Only the three tool-search variables are picked out; the rest of an `env`
|
|
216
|
+
* block — which is where a person keeps their API keys — is left where it is.
|
|
217
|
+
* A file that exists but cannot be parsed is `unreadable`, never silently
|
|
218
|
+
* treated as setting nothing.
|
|
219
|
+
*/
|
|
220
|
+
export function loadSettingsSources(candidates) {
|
|
221
|
+
return candidates.map((c) => {
|
|
222
|
+
if (!existsSync(c.path))
|
|
223
|
+
return { scope: c.scope, source: c.path, state: 'absent', vars: {} };
|
|
224
|
+
try {
|
|
225
|
+
const doc = parseJsonc(readFileSync(c.path, 'utf8'));
|
|
226
|
+
if (!doc || typeof doc !== 'object' || Array.isArray(doc))
|
|
227
|
+
throw new Error('not a settings object');
|
|
228
|
+
const block = doc.env;
|
|
229
|
+
const vars = {};
|
|
230
|
+
if (block && typeof block === 'object' && !Array.isArray(block)) {
|
|
231
|
+
for (const name of TOOL_SEARCH_VARS) {
|
|
232
|
+
const v = block[name];
|
|
233
|
+
if (typeof v === 'string')
|
|
234
|
+
vars[name] = v;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return { scope: c.scope, source: c.path, state: 'read', vars };
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return { scope: c.scope, source: c.path, state: 'unreadable', vars: {} };
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the client reading this config loads MCP tool definitions up front —
|
|
3
|
+
* or defers them until the model reaches for one.
|
|
4
|
+
*
|
|
5
|
+
* The headline audit number is what a session pays to put every tool definition
|
|
6
|
+
* in the context window. Whether it pays that is a property of the client and
|
|
7
|
+
* of the machine it runs on, not of the servers. So this module answers with
|
|
8
|
+
* three separate things, because collapsing them is how the first version of
|
|
9
|
+
* this got the common case wrong:
|
|
10
|
+
*
|
|
11
|
+
* 1. **What mode is in force.** Claude Code's default is to defer EVERY MCP
|
|
12
|
+
* tool definition, unconditionally — there is no threshold in the default
|
|
13
|
+
* case. A threshold exists only in the opt-in `auto` mode, and `auto:N`
|
|
14
|
+
* lets that percentage be anything from 0 to 100. Which mode is in force
|
|
15
|
+
* is decided by environment variables on the machine being audited, so
|
|
16
|
+
* they are read rather than assumed.
|
|
17
|
+
* 2. **Where the threshold sits**, when there is one at all.
|
|
18
|
+
* 3. **Which side of it this stack falls on** — as a range, not a point,
|
|
19
|
+
* because the audit's number and the threshold are counted in different
|
|
20
|
+
* units (see `wireToClientRatio` below).
|
|
21
|
+
*
|
|
22
|
+
* Sources, and their dates, because these are claims about someone else's
|
|
23
|
+
* product and they will rot:
|
|
24
|
+
*
|
|
25
|
+
* - Claude Code MCP documentation, §"Scale with MCP tool search", read
|
|
26
|
+
* 2026-08-20. "Tool search is enabled by default. MCP tools are deferred
|
|
27
|
+
* rather than loaded into context upfront." The `ENABLE_TOOL_SEARCH` table:
|
|
28
|
+
* unset → "All MCP tools deferred and loaded on demand"; `true` → all
|
|
29
|
+
* deferred; `auto` → "Threshold mode: Claude Code loads the tools it would
|
|
30
|
+
* otherwise defer upfront while their definitions total less than 10% of
|
|
31
|
+
* the context window, and defers all of them once the definitions reach
|
|
32
|
+
* 10%"; `auto:N` → "Threshold mode with a custom percentage, where `N` is
|
|
33
|
+
* 0-100"; `false` → "All MCP tools loaded upfront, no deferral". Deferral
|
|
34
|
+
* also falls back to upfront loading behind a non-first-party
|
|
35
|
+
* `ANTHROPIC_BASE_URL`, on a Microsoft Foundry deployment hosted on Azure,
|
|
36
|
+
* and on Google Cloud Agent Platform models earlier than the Claude 4.5
|
|
37
|
+
* generation; `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` "keeps tool search
|
|
38
|
+
* off. You can't override it by setting `ENABLE_TOOL_SEARCH` yourself."
|
|
39
|
+
* A server with `alwaysLoad: true` loads at session start regardless.
|
|
40
|
+
*
|
|
41
|
+
* No default deferral is on record here for the other four clients this tool
|
|
42
|
+
* discovers. That is an absence of a record, not a measurement of those
|
|
43
|
+
* clients, and it is printed as such — the same rule the rest of this project
|
|
44
|
+
* follows for a value it has not observed.
|
|
45
|
+
*/
|
|
46
|
+
import type { DivergenceRun } from '../core/divergence.js';
|
|
47
|
+
/** Share of the context window at which deferral activates under `auto`. */
|
|
48
|
+
export declare const TOOL_SEARCH_AUTO_SHARE = 0.1;
|
|
49
|
+
/** The variables that decide whether this machine's Claude Code defers. */
|
|
50
|
+
export declare const TOOL_SEARCH_VARS: readonly ['ENABLE_TOOL_SEARCH', 'CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS', 'ANTHROPIC_BASE_URL'];
|
|
51
|
+
export type ToolSearchVar = (typeof TOOL_SEARCH_VARS)[number];
|
|
52
|
+
/** The env vars that decide whether this machine's Claude Code defers. */
|
|
53
|
+
export interface ToolSearchEnv {
|
|
54
|
+
ENABLE_TOOL_SEARCH?: string;
|
|
55
|
+
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS?: string;
|
|
56
|
+
ANTHROPIC_BASE_URL?: string;
|
|
57
|
+
}
|
|
58
|
+
/** Pick the three variables that matter out of a process environment. */
|
|
59
|
+
export declare function toolSearchEnv(env: Record<string, string | undefined>): ToolSearchEnv;
|
|
60
|
+
/**
|
|
61
|
+
* A place the audited machine can set those variables.
|
|
62
|
+
*
|
|
63
|
+
* Two kinds, because Claude Code reads two kinds: the environment of the shell
|
|
64
|
+
* it was started in, and the `env` block of its own settings files. Reading
|
|
65
|
+
* only the first is how this reported the documented default — "these tokens
|
|
66
|
+
* are NOT loaded up front at any size" — at a machine that had switched
|
|
67
|
+
* deferral off in `~/.claude/settings.json`.
|
|
68
|
+
*/
|
|
69
|
+
export type ToolSearchScope = 'shell' | 'managed-settings' | 'local-settings' | 'project-settings' | 'user-settings';
|
|
70
|
+
/** What `source` says for the process environment, which has no path. */
|
|
71
|
+
export declare const SHELL_SOURCE = "(shell environment)";
|
|
72
|
+
export interface ToolSearchSource {
|
|
73
|
+
scope: ToolSearchScope;
|
|
74
|
+
/** Path of the settings file, or `SHELL_SOURCE`. */
|
|
75
|
+
source: string;
|
|
76
|
+
/**
|
|
77
|
+
* `read` — consulted, and `vars` is what it sets.
|
|
78
|
+
* `absent` — not on this machine, so it sets nothing.
|
|
79
|
+
* `unreadable` — it exists and could not be read: what it sets is UNKNOWN,
|
|
80
|
+
* which is not the same as nothing and is never resolved as though it were.
|
|
81
|
+
*/
|
|
82
|
+
state: 'read' | 'absent' | 'unreadable';
|
|
83
|
+
/** What this place sets, of the three. Values are read here, never reported. */
|
|
84
|
+
vars: ToolSearchEnv;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A source as it appears in a report: names of what it sets, never values.
|
|
88
|
+
*
|
|
89
|
+
* This is the record that lets a reader tell "nothing is set anywhere" from
|
|
90
|
+
* "that place was never opened" — the two states `readFromMachine: false`
|
|
91
|
+
* cannot distinguish on its own.
|
|
92
|
+
*/
|
|
93
|
+
export interface ToolSearchSourceRecord {
|
|
94
|
+
scope: ToolSearchScope;
|
|
95
|
+
source: string;
|
|
96
|
+
state: ToolSearchSource['state'];
|
|
97
|
+
/** Variable NAMES set here. A value can be a base URL carrying a credential. */
|
|
98
|
+
sets: ToolSearchVar[];
|
|
99
|
+
}
|
|
100
|
+
/** A source as it is published: what it sets, by name. */
|
|
101
|
+
export declare function toolSearchSourceRecord(s: ToolSearchSource): ToolSearchSourceRecord;
|
|
102
|
+
export type DeferralMode =
|
|
103
|
+
/** Every MCP tool definition is deferred, at any size. No threshold applies. */
|
|
104
|
+
'defers-all'
|
|
105
|
+
/** Deferral activates only once the definitions reach a share of the window. */
|
|
106
|
+
| 'threshold'
|
|
107
|
+
/** Deferral is off here: every definition is in context at session start. */
|
|
108
|
+
| 'loads-upfront'
|
|
109
|
+
/** ENABLE_TOOL_SEARCH holds a value Claude Code does not document. */
|
|
110
|
+
| 'setting-unrecognized'
|
|
111
|
+
/** More than one place sets the variable, or one of them could not be read. */
|
|
112
|
+
| 'setting-unresolved'
|
|
113
|
+
/** A client we know about, with no default deferral on record. */
|
|
114
|
+
| 'no-deferral-on-record'
|
|
115
|
+
/** `--config <path>`: the file was read, but which client reads it is unknown. */
|
|
116
|
+
| 'client-unknown';
|
|
117
|
+
/** How the mode was decided — printed, so a reader can check it against their own shell. */
|
|
118
|
+
export interface ToolSearchSetting {
|
|
119
|
+
/** The variable that decided it, or null when nothing was set and the default stands. */
|
|
120
|
+
variable: string | null;
|
|
121
|
+
/**
|
|
122
|
+
* What is printed for that variable. Null when the decision came from the
|
|
123
|
+
* documented default.
|
|
124
|
+
*
|
|
125
|
+
* This is the value as read for `ENABLE_TOOL_SEARCH` and
|
|
126
|
+
* `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`, whose values are settings and not
|
|
127
|
+
* secrets. For `ANTHROPIC_BASE_URL` it is the hostname alone — never the
|
|
128
|
+
* value — because a base URL routed through a proxy commonly carries a
|
|
129
|
+
* credential in its userinfo or query, and a report is a thing meant to be
|
|
130
|
+
* shared (`examples/github-actions.yml` runs it in CI, `--baseline` reads a
|
|
131
|
+
* committed one). Same rule as `config.ts`: values are read, never written to
|
|
132
|
+
* a report.
|
|
133
|
+
*/
|
|
134
|
+
value: string | null;
|
|
135
|
+
/** True when a variable on the audited machine decided this, false for the default. */
|
|
136
|
+
readFromMachine: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Which place the deciding value was read from — a settings file's path, or
|
|
139
|
+
* `SHELL_SOURCE`. Null when nothing was set anywhere and the documented
|
|
140
|
+
* default stands.
|
|
141
|
+
*/
|
|
142
|
+
source: string | null;
|
|
143
|
+
/**
|
|
144
|
+
* Every place that was consulted, in the order Claude Code would take them,
|
|
145
|
+
* and what each one sets — by name. Printed and serialized so a reader can
|
|
146
|
+
* see what was opened, and a `--json` consumer can tell a variable that is
|
|
147
|
+
* set nowhere from a place this audit never read.
|
|
148
|
+
*/
|
|
149
|
+
sources: ToolSearchSourceRecord[];
|
|
150
|
+
/** Set only in `setting-unresolved`: why no mode could be read off them. */
|
|
151
|
+
unresolved?: 'sources-disagree' | 'source-unreadable';
|
|
152
|
+
}
|
|
153
|
+
interface ResolvedToolSearch extends Omit<ToolSearchSetting, 'sources'> {
|
|
154
|
+
mode: Extract<DeferralMode, 'defers-all' | 'threshold' | 'loads-upfront' | 'setting-unrecognized' | 'setting-unresolved'>;
|
|
155
|
+
thresholdShare: number | null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Read the tool-search setting out of ONE environment. Values are matched
|
|
159
|
+
* exactly as documented: an unrecognized value produces `setting-unrecognized`
|
|
160
|
+
* rather than a guess, because guessing here would print a definite verdict
|
|
161
|
+
* about tokens the reader may or may not be paying.
|
|
162
|
+
*
|
|
163
|
+
* `source` is left null here: this function is given one environment and has no
|
|
164
|
+
* way to say which of the machine's places it came from. `resolveToolSearchSources`,
|
|
165
|
+
* which does, fills it in.
|
|
166
|
+
*/
|
|
167
|
+
export declare function resolveToolSearch(env: ToolSearchEnv): ResolvedToolSearch;
|
|
168
|
+
/**
|
|
169
|
+
* Read the posture from every place the audited machine can set it.
|
|
170
|
+
*
|
|
171
|
+
* Claude Code takes these variables from the shell it was started in AND from
|
|
172
|
+
* the `env` block of its own settings files, so an audit that reads only the
|
|
173
|
+
* shell answers the machine's question with someone else's environment. The
|
|
174
|
+
* case that made this necessary: `~/.claude/settings.json` sets
|
|
175
|
+
* `ENABLE_TOOL_SEARCH: "false"`, the shell running the audit sets nothing, and
|
|
176
|
+
* every request on that machine pays for every tool definition while the report
|
|
177
|
+
* calls it the documented default and says the tokens are not loaded at all.
|
|
178
|
+
*
|
|
179
|
+
* Among the settings files the order is Claude Code's documented precedence —
|
|
180
|
+
* enterprise managed policy, then project-local, then project, then user
|
|
181
|
+
* (Claude Code settings documentation, §"Settings files", read 2026-08-20) — so
|
|
182
|
+
* the first of them that sets a variable is the one that would win.
|
|
183
|
+
*
|
|
184
|
+
* Between the settings files and the shell there is NO order on record here, so
|
|
185
|
+
* a disagreement is refused rather than resolved: `setting-unresolved` names the
|
|
186
|
+
* variable and every place, and no verdict is given. A place that exists and
|
|
187
|
+
* could not be read is the same refusal for the same reason — what it sets is
|
|
188
|
+
* unknown, and an unknown that could flip the answer is not a default.
|
|
189
|
+
*
|
|
190
|
+
* Not visible from here at all, and so not claimed: a variable set on Claude
|
|
191
|
+
* Code's own command line.
|
|
192
|
+
*/
|
|
193
|
+
export declare function resolveToolSearchSources(sources: ToolSearchSource[]): ResolvedToolSearch;
|
|
194
|
+
/**
|
|
195
|
+
* The factor between the number this audit counts and the number the threshold
|
|
196
|
+
* is counted in.
|
|
197
|
+
*
|
|
198
|
+
* The audit's total is o200k_base over the bytes a server puts on the wire. The
|
|
199
|
+
* threshold is a share of the context window measured in what the client
|
|
200
|
+
* actually sends to the API — the name/description/input_schema projection,
|
|
201
|
+
* counted by Anthropic's tokenizer, plus the tool framework overhead. Those are
|
|
202
|
+
* not the same number and the gap is not small: across the published
|
|
203
|
+
* divergence run it runs from 0.20× to 1.92×, so a single stack total maps to a
|
|
204
|
+
* range roughly ten times as wide as itself. Comparing the wire number directly
|
|
205
|
+
* against the threshold understates the deferrable side for schema-heavy
|
|
206
|
+
* servers and overstates it for metadata-heavy ones, in one direction each.
|
|
207
|
+
*/
|
|
208
|
+
export interface WireToClientRatio {
|
|
209
|
+
low: number;
|
|
210
|
+
high: number;
|
|
211
|
+
/** How many servers the band was measured across, for the printed caveat. */
|
|
212
|
+
servers: number;
|
|
213
|
+
/** The run it came from, so a reader can date it. */
|
|
214
|
+
source: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The band as published in this repository's own `results/divergence.json`
|
|
218
|
+
* (claude-opus-5, 2026-08-19, 20 servers). Used when no divergence run was
|
|
219
|
+
* supplied; `--claude` recomputes it from the run it fetched.
|
|
220
|
+
*/
|
|
221
|
+
export declare const PUBLISHED_WIRE_TO_CLIENT_RATIO: WireToClientRatio;
|
|
222
|
+
/** Derive the band from a supplied divergence run, falling back to the published one. */
|
|
223
|
+
export declare function wireToClientRatio(run?: DivergenceRun | null): WireToClientRatio;
|
|
224
|
+
/** One measured server, as the deferral arithmetic needs it. */
|
|
225
|
+
export interface DeferralServer {
|
|
226
|
+
/** o200k tokens over the wire capture — the audit's own unit. */
|
|
227
|
+
tokens: number;
|
|
228
|
+
/**
|
|
229
|
+
* Anthropic's own count for this server from a current divergence row, when
|
|
230
|
+
* `--claude` supplied one. `null` means no current match, `undefined` means
|
|
231
|
+
* the join was not requested — either way it is converted through the band.
|
|
232
|
+
*/
|
|
233
|
+
claudeTokens?: number | null;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* The configs one session of one client loads together.
|
|
237
|
+
*
|
|
238
|
+
* Claude Code reads both `~/.claude.json` and `<cwd>/.mcp.json` into a single
|
|
239
|
+
* session, so they get one verdict against their sum rather than two verdicts
|
|
240
|
+
* each judged alone. The report still totals each config file separately — a
|
|
241
|
+
* context window belongs to one session, which is the argument for adding these
|
|
242
|
+
* two together, not for adding one client's servers to another's.
|
|
243
|
+
*/
|
|
244
|
+
export interface DeferralScope {
|
|
245
|
+
client: string;
|
|
246
|
+
/** Every config file this verdict covers. */
|
|
247
|
+
sources: string[];
|
|
248
|
+
servers: DeferralServer[];
|
|
249
|
+
/** Entries discovered across those configs that produced no number. */
|
|
250
|
+
skippedCount: number;
|
|
251
|
+
/**
|
|
252
|
+
* Entries here whose number came from a measurement shared with another entry
|
|
253
|
+
* that differs only in its environment.
|
|
254
|
+
*
|
|
255
|
+
* Measurements are cached per command line, so two entries running the same
|
|
256
|
+
* command under different environments are launched once and both carry the
|
|
257
|
+
* one number. Environment decides what a server serves — `GITHUB_TOOLSETS` on
|
|
258
|
+
* `github-mcp-server` selects which toolsets it lists — so that number belongs
|
|
259
|
+
* to at most one of them, and which one is not knowable from here.
|
|
260
|
+
*
|
|
261
|
+
* Counted rather than flagged so the report can say how much of the stack it
|
|
262
|
+
* covers. Every entry sharing such a measurement counts, including whichever
|
|
263
|
+
* one was really launched.
|
|
264
|
+
*/
|
|
265
|
+
sharedMeasurements: number;
|
|
266
|
+
}
|
|
267
|
+
/** What the client would count for this stack, as a range. */
|
|
268
|
+
export interface ClientSideEstimate {
|
|
269
|
+
low: number;
|
|
270
|
+
high: number;
|
|
271
|
+
/** Servers taken from a published Anthropic count rather than converted. */
|
|
272
|
+
exact: number;
|
|
273
|
+
/** Servers converted through the ratio band. */
|
|
274
|
+
estimated: number;
|
|
275
|
+
}
|
|
276
|
+
export interface DeferralVerdict {
|
|
277
|
+
client: string;
|
|
278
|
+
mode: DeferralMode;
|
|
279
|
+
/** What the client calls the mechanism, for a reader who wants to look it up. */
|
|
280
|
+
mechanism: string | null;
|
|
281
|
+
/** Every config file this one verdict covers. */
|
|
282
|
+
sources: string[];
|
|
283
|
+
/** Which variable decided the mode, and whether it was read or defaulted. */
|
|
284
|
+
setting: ToolSearchSetting | null;
|
|
285
|
+
/** Null whenever no threshold applies — which includes the default case. */
|
|
286
|
+
thresholdShare: number | null;
|
|
287
|
+
thresholdTokens: number | null;
|
|
288
|
+
/**
|
|
289
|
+
* o200k tokens summed across the scope — what this audit measured.
|
|
290
|
+
*
|
|
291
|
+
* Read together with `sharedMeasurements`: where that is non-zero this sum
|
|
292
|
+
* counts one measurement for several entries, so it is not the stack's total
|
|
293
|
+
* and nothing here is derived from it.
|
|
294
|
+
*/
|
|
295
|
+
wireTokens: number;
|
|
296
|
+
/** Null when there is no threshold to compare against, or no total to convert. */
|
|
297
|
+
clientTokens: ClientSideEstimate | null;
|
|
298
|
+
ratio: WireToClientRatio | null;
|
|
299
|
+
/**
|
|
300
|
+
* True when the stack total is a lower bound rather than a count — some
|
|
301
|
+
* server in this scope could not be measured, and a session would still load
|
|
302
|
+
* whatever it serves. Absent is unknown, never zero.
|
|
303
|
+
*/
|
|
304
|
+
isFloor: boolean;
|
|
305
|
+
/** clientTokens − thresholdTokens, at each end of the range. Positive is over. */
|
|
306
|
+
distanceTokens: {
|
|
307
|
+
low: number;
|
|
308
|
+
high: number;
|
|
309
|
+
} | null;
|
|
310
|
+
/**
|
|
311
|
+
* true = deferral activates, false = it does not, null = cannot be said.
|
|
312
|
+
* Null has four causes, all of them real: there is no threshold rule to be
|
|
313
|
+
* on a side of, the unit conversion straddles the threshold, an unmeasured
|
|
314
|
+
* server could carry an under-threshold stack over, or the stack has no
|
|
315
|
+
* established total at all (`sharedMeasurements`).
|
|
316
|
+
*/
|
|
317
|
+
crosses: boolean | null;
|
|
318
|
+
/**
|
|
319
|
+
* How many entries in this scope carry a number measured for a twin that
|
|
320
|
+
* differs only in environment. Non-zero means the sum above is not this
|
|
321
|
+
* stack's total, in either direction, so no side of the threshold is claimed.
|
|
322
|
+
*/
|
|
323
|
+
sharedMeasurements: number;
|
|
324
|
+
/** Conditions this cannot read, under which a deferring client pays in full. */
|
|
325
|
+
exceptions: string[];
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Read one session's deferral position. Pure arithmetic over a built scope — no
|
|
329
|
+
* config file is re-read and no server is launched. The environment is passed
|
|
330
|
+
* in rather than read here, so the answer is reproducible from its inputs.
|
|
331
|
+
*/
|
|
332
|
+
export declare function evaluateDeferral(scope: DeferralScope, opts: {
|
|
333
|
+
contextWindow: number;
|
|
334
|
+
/** The audited machine's SHELL variables. Omitted means the shell set nothing. */
|
|
335
|
+
env?: ToolSearchEnv;
|
|
336
|
+
/**
|
|
337
|
+
* The Claude Code settings files read on that machine, highest precedence
|
|
338
|
+
* first — the other place these variables come from. Omitted means they
|
|
339
|
+
* were not read here, which is published as such rather than as an absence
|
|
340
|
+
* of settings: see `ToolSearchSetting.sources`.
|
|
341
|
+
*/
|
|
342
|
+
settings?: ToolSearchSource[];
|
|
343
|
+
/** Supplied by `--claude`; sharpens the unit conversion where rows match. */
|
|
344
|
+
divergence?: DivergenceRun | null;
|
|
345
|
+
}): DeferralVerdict;
|
|
346
|
+
export {};
|