@mnemom/mnemom 0.17.7 → 0.17.8
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 +31 -13
- package/dist/commands/agent.d.ts +7 -6
- package/dist/commands/agent.js +78 -20
- package/dist/index.js +1 -1
- package/dist/lib/agent-ledger.d.ts +22 -3
- package/dist/lib/agent-ledger.js +23 -0
- package/dist/lib/agent.d.ts +71 -41
- package/dist/lib/agent.js +90 -42
- package/dist/lib/first-run/backtest.d.ts +23 -3
- package/dist/lib/first-run/backtest.js +35 -4
- package/dist/lib/first-run/index.d.ts +35 -14
- package/dist/lib/first-run/index.js +82 -37
- package/dist/lib/first-run/replay.d.ts +86 -0
- package/dist/lib/first-run/replay.js +162 -0
- package/dist/lib/first-run/screen.d.ts +67 -31
- package/dist/lib/first-run/screen.js +260 -104
- package/dist/lib/launcher-config.d.ts +5 -4
- package/dist/lib/launcher-config.js +1 -1
- package/package.json +1 -1
|
@@ -1,27 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The first-run screen: one plain terminal screen (at most 22 lines of at most 78
|
|
3
|
-
* columns, ASCII
|
|
3
|
+
* columns, ASCII; with the command's blank line above and below, 24 rows) built from
|
|
4
|
+
* the backtest numbers. Pure — no I/O — so every layout is
|
|
4
5
|
* unit-tested. Every number on it is recorded in the audit with its raw value and
|
|
5
6
|
* method.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* saved you, and what it would have saved on the rest (operator 2026-10-02).
|
|
14
|
-
* B small >= $5 of usage at API prices but a smaller saving: the usage, the honest
|
|
15
|
-
* "wouldn't have changed that much" line, and the forward line.
|
|
16
|
-
* C none too little history: the forward line only.
|
|
17
|
-
* All three end with the price line and the live lines.
|
|
8
|
+
* Sessions come in two buckets (index.ts): THROUGH Mnemom (launch ledger, a window / env
|
|
9
|
+
* signal, or fold evidence), whose saving is REALIZED (replay.ts: stock Claude Code
|
|
10
|
+
* replayed at its default window, can be negative), and NOT through Mnemom, whose saving
|
|
11
|
+
* is the POTENTIAL one (backtest.ts: the flat S46 rule, 23.8% of every request at or
|
|
12
|
+
* above 60k, for dollars and for tokens alike). Tokens and dollars are both shown
|
|
13
|
+
* (operator 2026-10-02). Percentages drop their decimals (rounded DOWN).
|
|
18
14
|
*
|
|
19
|
-
*
|
|
20
|
-
* -
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
15
|
+
* Variations; every number has one source and no two lines make the same claim:
|
|
16
|
+
* A no through-Mnemom usage, and the potential saving qualifies: the usage in
|
|
17
|
+
* tokens and at API prices, the cut with Mnemom, the biggest session.
|
|
18
|
+
* mixed both buckets have usage: one block per bucket, each with its saving line
|
|
19
|
+
* only if that BUCKET's saving qualifies, then the largest dollar saving
|
|
20
|
+
* across the shown buckets, worded by its bucket ("biggest saving ... of"
|
|
21
|
+
* through, "biggest session ... less with Mnemom" not through).
|
|
22
|
+
* through only through-Mnemom usage: its block alone, then its biggest saving.
|
|
23
|
+
* B >= $5 of usage but no saving line qualifies: the usage, the honest "wouldn't
|
|
24
|
+
* have changed that much" line (no through usage) or the bucket usage lines,
|
|
25
|
+
* and the forward line.
|
|
26
|
+
* C too little history: the forward line only.
|
|
27
|
+
* A saving qualifies iff it rounds DOWN to >= $5 and its token percent to >= 5%. A
|
|
28
|
+
* Team / Enterprise subscriber also gets the subscription line whenever a saving line is
|
|
29
|
+
* shown; its overage clause only when the account has extra usage enabled. All end with
|
|
30
|
+
* the price line and the live lines.
|
|
31
|
+
*
|
|
32
|
+
* Layout (operator 2026-10-02): a blank line between every block (each bucket's usage
|
|
33
|
+
* and saving lines, the biggest line, the subscriber lines, the price line, the live
|
|
34
|
+
* lines); the saving lines are not indented.
|
|
35
|
+
*
|
|
36
|
+
* Operator rulings (2026-09-30 .. 2026-10-02), binding:
|
|
37
|
+
* - Cost and usage only. Nothing about conduct ("habits", "caught", "checked").
|
|
38
|
+
* - Round DOWN, never overstate. A through session's saving may be negative: the
|
|
39
|
+
* bucket total is the honest sum, never floored per session.
|
|
40
|
+
* - Every session is priced at API list prices whatever it was billed on, and the
|
|
41
|
+
* screen says "at API prices". A subscriber never gets a seat bill, an overage dollar
|
|
42
|
+
* figure or a limit-hit count.
|
|
25
43
|
* - No live counter is promised: `mnemom agent` has no status bar today.
|
|
26
44
|
*/
|
|
27
45
|
import { ESTIMATOR_METHOD } from "./backtest.js";
|
|
@@ -29,7 +47,7 @@ export const WIDTH = 78;
|
|
|
29
47
|
export const MAX_LINES = 22;
|
|
30
48
|
/** Less history than this (API prices, in the window) is too little to backtest. */
|
|
31
49
|
export const MIN_HISTORY_USD = 5;
|
|
32
|
-
/**
|
|
50
|
+
/** A saving line is shown iff its saving rounds to at least this many dollars and percent. */
|
|
33
51
|
export const STRONG_MIN_USD = 5;
|
|
34
52
|
export const STRONG_MIN_PCT = 5;
|
|
35
53
|
export const DAYS = 30;
|
|
@@ -45,6 +63,17 @@ const FORWARD_SOURCE = "operator 2026-10-02: S46 C2n total bill -20.9% [-25.6, -
|
|
|
45
63
|
/** Prices, promotions and plan allocations move; the saving is in usage (operator 2026-10-01). */
|
|
46
64
|
export const PRICE_LINE = "Prices and plan limits change. Mnemom cuts what you use, so you stay ahead.";
|
|
47
65
|
/** What `mnemom agent` does today: routes through the gateway, records, keeps context lean. */
|
|
66
|
+
/**
|
|
67
|
+
* The subscriber lines, fixed like the live lines: the operator's break, so the overage
|
|
68
|
+
* form reads as two lines and never as one 78-column line.
|
|
69
|
+
*/
|
|
70
|
+
export const SUB_LINES = {
|
|
71
|
+
limit: ["On your subscription, fewer tokens means more work before you hit a limit."],
|
|
72
|
+
overage: [
|
|
73
|
+
"On your subscription, fewer tokens means more work before you hit a",
|
|
74
|
+
"limit, and less overage when you go past it.",
|
|
75
|
+
],
|
|
76
|
+
};
|
|
48
77
|
export const LIVE_LINES = [
|
|
49
78
|
"From now on it's live: your sessions run through Mnemom, which keeps long",
|
|
50
79
|
"conversations lean and puts each tool call your agent makes on the record.",
|
|
@@ -87,6 +116,26 @@ export function day(t) {
|
|
|
87
116
|
export function usd(n) {
|
|
88
117
|
return `$${Math.floor(n).toLocaleString("en-US")}`;
|
|
89
118
|
}
|
|
119
|
+
/** A token count rounded DOWN to 2 significant figures (the number it stands for). */
|
|
120
|
+
export function tokShown(n) {
|
|
121
|
+
return n >= 1 ? sig2(n) : 0;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* A token count in words, 2 significant figures DOWN: "9.0 billion", "39 billion",
|
|
125
|
+
* "450 million", "12 thousand"; below a thousand, the plain number.
|
|
126
|
+
*/
|
|
127
|
+
export function tokens(n) {
|
|
128
|
+
const v = tokShown(n);
|
|
129
|
+
for (const [u, w] of [
|
|
130
|
+
[1e9, "billion"],
|
|
131
|
+
[1e6, "million"],
|
|
132
|
+
[1e3, "thousand"],
|
|
133
|
+
]) {
|
|
134
|
+
if (v >= u)
|
|
135
|
+
return `${v >= 10 * u ? String(v / u) : (v / u).toFixed(1)} ${w}`;
|
|
136
|
+
}
|
|
137
|
+
return String(v);
|
|
138
|
+
}
|
|
90
139
|
// ── output hygiene ───────────────────────────────────────────────────────────
|
|
91
140
|
const SECRETS = /(sk-[A-Za-z0-9_-]{6,}|ghp_[A-Za-z0-9]{6,}|mnm_[A-Za-z0-9_-]{6,}|op:\/\/\S+|Bearer\s+\S+|\b[0-9a-f]{40,}\b|\b[A-Za-z0-9+/]{48,}={0,2})/g;
|
|
92
141
|
const PATHISH = /(\/Users\/\S+|\/home\/\S+|\/private\/\S+|~\/\S+)/g;
|
|
@@ -119,27 +168,45 @@ export function wrap(text, width = WIDTH) {
|
|
|
119
168
|
out.push(cur);
|
|
120
169
|
return out;
|
|
121
170
|
}
|
|
122
|
-
const SPENT_METHOD = "transcript usage x Claude Code 2.1.285's price table, deduped by message id,
|
|
123
|
-
"
|
|
124
|
-
"
|
|
171
|
+
const SPENT_METHOD = "transcript usage x Claude Code 2.1.285's price table, deduped by message id, the bucket's " +
|
|
172
|
+
"requests in the last 30 days, priced at API list prices whatever they were billed on; 3 sig " +
|
|
173
|
+
"figs DOWN; a lower bound (side calls not in transcripts are missing)";
|
|
174
|
+
const TOKENS_METHOD = "Σ (input + cache read + cache write 5m + cache write 1h + output) over the same requests; " +
|
|
175
|
+
"2 sig figs DOWN";
|
|
125
176
|
const SAVED_METHOD = `backtest.estimate(): ${ESTIMATOR_METHOD}; 2 sig figs DOWN`;
|
|
177
|
+
const SAVED_TOKENS_METHOD = "backtest.estimate(): ruleRate(prompt) x prompt per request (the same flat rule as the " +
|
|
178
|
+
"dollars); 2 sig figs DOWN";
|
|
179
|
+
const REALIZED_METHOD = "replay.replayStock(): stock Claude Code at its default window for the session's dominant " +
|
|
180
|
+
"main-thread model, replayed on the client size rebuilt from the fold drops; Σ per session, " +
|
|
181
|
+
"negative sessions kept; 2 sig figs DOWN";
|
|
182
|
+
function sum(ses) {
|
|
183
|
+
const b = { n: ses.length, usd: 0, tokens: 0, saved: 0, savedTokens: 0 };
|
|
184
|
+
for (const r of ses) {
|
|
185
|
+
b.usd += r.actual;
|
|
186
|
+
b.tokens += r.tokens;
|
|
187
|
+
b.saved += r.saved;
|
|
188
|
+
b.savedTokens += r.savedTokens;
|
|
189
|
+
}
|
|
190
|
+
return b;
|
|
191
|
+
}
|
|
192
|
+
/** The shown saving of a bucket, or null when it does not qualify. */
|
|
193
|
+
function qualifying(saved, savedTokens, base) {
|
|
194
|
+
const u = sig2(Math.max(saved, 0));
|
|
195
|
+
const pct = pctDown(savedTokens, base);
|
|
196
|
+
if (u < STRONG_MIN_USD || pct < STRONG_MIN_PCT)
|
|
197
|
+
return null;
|
|
198
|
+
// pct >= 5 implies base > 0.
|
|
199
|
+
return { usd: u, tok: tokShown(savedTokens), pct, rawPct: (100 * savedTokens) / base };
|
|
200
|
+
}
|
|
126
201
|
function subLines(sub, A) {
|
|
127
202
|
if (!sub)
|
|
128
203
|
return [];
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return [];
|
|
134
|
-
}
|
|
135
|
-
A("sub_usage_pct", {
|
|
136
|
-
shown: p,
|
|
137
|
-
raw,
|
|
138
|
-
method: "saving / API-price cost over the subscription sessions in the window (all sessions if " +
|
|
139
|
-
"none is tagged); cost-weighted, decimals dropped",
|
|
204
|
+
A("sub_overage_clause", {
|
|
205
|
+
shown: sub.extraUsage,
|
|
206
|
+
raw: sub.extraUsage,
|
|
207
|
+
method: "the account's hasExtraUsageEnabled (authShape().extraUsage); never a dollar figure",
|
|
140
208
|
});
|
|
141
|
-
return
|
|
142
|
-
"overage if you use extra usage.");
|
|
209
|
+
return sub.extraUsage ? SUB_LINES.overage : SUB_LINES.limit;
|
|
143
210
|
}
|
|
144
211
|
/** -> the screen lines, the variation and the audit of every number on them. */
|
|
145
212
|
export function buildScreen(inp) {
|
|
@@ -148,88 +215,176 @@ export function buildScreen(inp) {
|
|
|
148
215
|
audit[k] = e;
|
|
149
216
|
};
|
|
150
217
|
const ses = inp.sessions;
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
218
|
+
const all = sum(ses);
|
|
219
|
+
const thr = sum(ses.filter((r) => r.through));
|
|
220
|
+
const not = sum(ses.filter((r) => !r.through));
|
|
221
|
+
// A bucket "has usage" when it shows at least $1 at API prices.
|
|
222
|
+
const hasThr = sig3(thr.usd) >= 1;
|
|
223
|
+
const hasNot = sig3(not.usd) >= 1;
|
|
224
|
+
const enough = all.usd >= MIN_HISTORY_USD;
|
|
225
|
+
// Through: the base is the without-Mnemom total (used + saved). Not: what was used.
|
|
226
|
+
const qThr = hasThr ? qualifying(thr.saved, thr.savedTokens, thr.tokens + thr.savedTokens) : null;
|
|
227
|
+
const qNot = hasNot ? qualifying(not.saved, not.savedTokens, not.tokens) : null;
|
|
228
|
+
const variation = !enough
|
|
229
|
+
? "C"
|
|
230
|
+
: !qThr && !qNot
|
|
231
|
+
? "B"
|
|
232
|
+
: !hasThr
|
|
233
|
+
? "A"
|
|
234
|
+
: hasNot
|
|
235
|
+
? "mixed"
|
|
236
|
+
: "through";
|
|
237
|
+
A("variation", {
|
|
238
|
+
shown: variation,
|
|
239
|
+
raw: { through: thr, not_through: not },
|
|
240
|
+
method: "see screen.ts header; raw = each bucket's honest sums (negative sessions kept)",
|
|
241
|
+
});
|
|
158
242
|
const L = ["Welcome to Mnemom.", ""];
|
|
159
243
|
L.push(...(variation === "C"
|
|
160
244
|
? wrap("We didn't find enough Claude Code history on this machine to look at.")
|
|
161
245
|
: wrap(`We looked at your last ${DAYS} days of Claude Code. It all stayed on this machine.`)));
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
A("saved_pct", {
|
|
166
|
-
shown: p,
|
|
167
|
-
raw: (100 * saved) / actual,
|
|
168
|
-
method: "decimals dropped (rounded DOWN)",
|
|
169
|
-
});
|
|
170
|
-
const viaRaw = ses.reduce((t, r) => t + (r.viaMnemom ? r.saved : 0), 0);
|
|
171
|
-
const via = sig2(viaRaw);
|
|
172
|
-
const rest = sig2(saved - viaRaw);
|
|
173
|
-
if (via < 1) {
|
|
174
|
-
A("saved_usd", { shown: s, raw: saved, method: SAVED_METHOD });
|
|
175
|
-
A("with_mnemom_usd", { shown: e, raw: actual - saved, method: "spent shown - saved shown" });
|
|
176
|
-
L.push(...wrap(`At API prices that usage cost about ${usd(a)}. With Mnemom: about ${usd(e)}.`));
|
|
246
|
+
/** Start a block: one blank line after whatever came before. */
|
|
247
|
+
const gap = () => {
|
|
248
|
+
if (L[L.length - 1] !== "")
|
|
177
249
|
L.push("");
|
|
178
|
-
|
|
250
|
+
};
|
|
251
|
+
const usage = (key, b) => {
|
|
252
|
+
A(`${key}_tokens`, { shown: tokShown(b.tokens), raw: b.tokens, method: TOKENS_METHOD });
|
|
253
|
+
A(`${key}_usd`, { shown: sig3(b.usd), raw: b.usd, method: SPENT_METHOD });
|
|
254
|
+
return { t: tokens(b.tokens), u: usd(sig3(b.usd)) };
|
|
255
|
+
};
|
|
256
|
+
const saving = (key, b, q, method, tokMethod, base) => {
|
|
257
|
+
A(`${key}_saved_tokens`, { shown: q.tok, raw: b.savedTokens, method: tokMethod });
|
|
258
|
+
A(`${key}_saved_pct`, {
|
|
259
|
+
shown: q.pct,
|
|
260
|
+
raw: q.rawPct,
|
|
261
|
+
method: `${base}; decimals dropped (rounded DOWN)`,
|
|
262
|
+
});
|
|
263
|
+
A(`${key}_saved_usd`, { shown: q.usd, raw: b.saved, method });
|
|
264
|
+
};
|
|
265
|
+
/** The per-bucket lines; only called when the through bucket has usage. */
|
|
266
|
+
const bucketBlock = () => {
|
|
267
|
+
gap();
|
|
268
|
+
const { t, u } = usage("through", thr);
|
|
269
|
+
L.push(...wrap(`Through Mnemom: ${t} tokens, about ${u} at API prices.`));
|
|
270
|
+
if (qThr) {
|
|
271
|
+
saving("through", thr, qThr, REALIZED_METHOD, REALIZED_METHOD, "saved tokens / (used + saved)");
|
|
272
|
+
L.push(...wrap(`That saved about ${tokens(thr.savedTokens)} tokens (${qThr.pct}%), about ${usd(qThr.usd)}.`));
|
|
179
273
|
}
|
|
180
274
|
else {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
275
|
+
A("through_saved_not_shown", {
|
|
276
|
+
shown: null,
|
|
277
|
+
raw: { usd: thr.saved, tokens: thr.savedTokens },
|
|
278
|
+
method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (hasNot) {
|
|
282
|
+
gap();
|
|
283
|
+
const { t, u } = usage("not_through", not);
|
|
284
|
+
L.push(...wrap(`Not through Mnemom: ${t} tokens, about ${u} at API prices.`));
|
|
285
|
+
if (qNot) {
|
|
286
|
+
saving("not_through", not, qNot, SAVED_METHOD, SAVED_TOKENS_METHOD, "saved tokens / used");
|
|
287
|
+
L.push(...wrap(`Mnemom would have cut about ${tokens(not.savedTokens)} tokens (${qNot.pct}%), ` +
|
|
288
|
+
`about ${usd(qNot.usd)}.`));
|
|
187
289
|
}
|
|
188
290
|
else {
|
|
189
|
-
A("
|
|
190
|
-
shown:
|
|
191
|
-
raw: saved
|
|
192
|
-
method:
|
|
291
|
+
A("not_through_saved_not_shown", {
|
|
292
|
+
shown: null,
|
|
293
|
+
raw: { usd: not.saved, tokens: not.savedTokens },
|
|
294
|
+
method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
|
|
193
295
|
});
|
|
194
|
-
L.push(...wrap(`Mnemom saved you about ${usd(via)} of it, and would have saved about ${usd(rest)} ` +
|
|
195
|
-
"more on the sessions that didn't run through it."));
|
|
196
296
|
}
|
|
197
297
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
298
|
+
};
|
|
299
|
+
/** The session with the largest dollar saving, if it rounds to >= $5. */
|
|
300
|
+
const biggest = (pool) => {
|
|
301
|
+
let big = null;
|
|
302
|
+
for (const r of pool)
|
|
303
|
+
if (!big || r.saved > big.saved)
|
|
304
|
+
big = r;
|
|
305
|
+
return big && sig2(big.saved) >= STRONG_MIN_USD ? big : null;
|
|
306
|
+
};
|
|
307
|
+
const where = (r) => r.label ? `${r.label} on ${day(r.end)}` : `on ${day(r.end)}`;
|
|
308
|
+
/**
|
|
309
|
+
* The biggest line, worded by the session's bucket (operator 2026-10-02): through, the
|
|
310
|
+
* realized saving of what it would have cost without Mnemom (used + saved); not
|
|
311
|
+
* through, what it cost and the would-have saving.
|
|
312
|
+
*/
|
|
313
|
+
const biggestLine = (big) => {
|
|
314
|
+
gap();
|
|
315
|
+
if (big.through) {
|
|
316
|
+
const without = big.actual + big.saved;
|
|
317
|
+
const ba = sig3(without);
|
|
318
|
+
const bs = Math.min(sig2(big.saved), ba);
|
|
319
|
+
A("biggest_saving_usd", {
|
|
320
|
+
shown: bs,
|
|
321
|
+
raw: big.saved,
|
|
322
|
+
method: `the session with the largest dollar saving (${REALIZED_METHOD})`,
|
|
323
|
+
});
|
|
324
|
+
A("biggest_saving_of_usd", {
|
|
325
|
+
shown: ba,
|
|
326
|
+
raw: without,
|
|
327
|
+
method: "that session's cost without Mnemom at API prices (used + saved), 3 sig figs DOWN",
|
|
328
|
+
});
|
|
329
|
+
L.push(...wrap(`Your biggest saving, ${where(big)}: about ${usd(bs)} of ${usd(ba)}.`));
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
const ba = sig3(big.actual);
|
|
333
|
+
const bs = Math.min(sig2(big.saved), ba);
|
|
334
|
+
A("biggest_session_usd", {
|
|
335
|
+
shown: ba,
|
|
336
|
+
raw: big.actual,
|
|
337
|
+
method: "the session with the largest saving; its API-price cost, 3 sig figs DOWN",
|
|
338
|
+
});
|
|
339
|
+
A("biggest_session_saved_usd", {
|
|
340
|
+
shown: bs,
|
|
341
|
+
raw: big.saved,
|
|
342
|
+
method: `${SAVED_METHOD}; that session`,
|
|
343
|
+
});
|
|
344
|
+
L.push(...wrap(`Your biggest session, ${where(big)}: ${usd(ba)}, about ${usd(bs)} less with Mnemom.`));
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
if (variation === "A") {
|
|
348
|
+
gap();
|
|
349
|
+
const { t, u } = usage("spent", not);
|
|
350
|
+
L.push(...wrap(`You used about ${t} tokens, about ${u} at API prices.`));
|
|
351
|
+
const q = qNot;
|
|
352
|
+
saving("spent", not, q, SAVED_METHOD, SAVED_TOKENS_METHOD, "saved tokens / used");
|
|
353
|
+
L.push(...wrap(`With Mnemom: about ${tokens(not.savedTokens)} fewer tokens (${q.pct}%), about ` +
|
|
354
|
+
`${usd(q.usd)} less.`));
|
|
355
|
+
const big = biggest(ses.filter((r) => !r.through));
|
|
356
|
+
if (big)
|
|
357
|
+
biggestLine(big);
|
|
358
|
+
gap();
|
|
359
|
+
L.push(...subLines(inp.sub, A));
|
|
360
|
+
}
|
|
361
|
+
else if (variation === "mixed" || variation === "through") {
|
|
362
|
+
bucketBlock();
|
|
363
|
+
// The largest dollar saving across the buckets whose saving line is shown.
|
|
364
|
+
const big = biggest(ses.filter((r) => (r.through ? qThr : qNot)));
|
|
365
|
+
if (big)
|
|
366
|
+
biggestLine(big);
|
|
367
|
+
gap();
|
|
368
|
+
L.push(...subLines(inp.sub, A));
|
|
219
369
|
}
|
|
220
370
|
else {
|
|
221
371
|
if (variation === "B") {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
372
|
+
if (hasThr) {
|
|
373
|
+
bucketBlock();
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const { t, u } = usage("spent", all);
|
|
377
|
+
A("saved_not_shown", {
|
|
378
|
+
shown: null,
|
|
379
|
+
raw: { usd: all.saved, tokens: all.savedTokens },
|
|
380
|
+
method: `below $${STRONG_MIN_USD} or ${STRONG_MIN_PCT}% after rounding DOWN`,
|
|
381
|
+
});
|
|
382
|
+
gap();
|
|
383
|
+
L.push(...wrap(`Your sessions used about ${t} tokens, about ${u} at API prices. They stayed ` +
|
|
384
|
+
"small, so Mnemom wouldn't have changed that much."));
|
|
385
|
+
}
|
|
230
386
|
}
|
|
231
|
-
|
|
232
|
-
L.push("");
|
|
387
|
+
gap();
|
|
233
388
|
L.push(...wrap(FORWARD_LINE));
|
|
234
389
|
A("forward_range_pct", {
|
|
235
390
|
shown: "15 to 25",
|
|
@@ -237,11 +392,12 @@ export function buildScreen(inp) {
|
|
|
237
392
|
method: FORWARD_SOURCE,
|
|
238
393
|
});
|
|
239
394
|
}
|
|
240
|
-
|
|
395
|
+
gap();
|
|
396
|
+
L.push(PRICE_LINE, "", ...LIVE_LINES);
|
|
241
397
|
A("sessions", {
|
|
242
398
|
shown: null,
|
|
243
|
-
raw:
|
|
244
|
-
method: "
|
|
399
|
+
raw: { all: all.n, through: thr.n, not_through: not.n },
|
|
400
|
+
method: "sessions with requests in the window, by bucket",
|
|
245
401
|
});
|
|
246
402
|
return { lines: L.map(clean), audit, variation };
|
|
247
403
|
}
|
|
@@ -56,10 +56,11 @@ export interface LauncherConfig {
|
|
|
56
56
|
*/
|
|
57
57
|
compactionIntercept?: boolean;
|
|
58
58
|
/**
|
|
59
|
-
* How the gateway folds each session's context (
|
|
60
|
-
* compaction to the coding agent, `balanced` keeps more
|
|
61
|
-
* folds earlier with a tighter working set, `adaptive`
|
|
62
|
-
* (none below 200k tokens, aggressive up to 1M, balanced
|
|
59
|
+
* How the gateway folds each session's context (unset: nothing is sent, the gateway cell's
|
|
60
|
+
* own default decides): `off` leaves compaction to the coding agent, `balanced` keeps more
|
|
61
|
+
* earlier work verbatim, `aggressive` folds earlier with a tighter working set, `adaptive`
|
|
62
|
+
* sizes the fold to the conversation (none below 200k tokens, aggressive up to 1M, balanced
|
|
63
|
+
* above). `--context-profile` overrides it for one launch without saving anything.
|
|
63
64
|
*/
|
|
64
65
|
contextProfile?: ContextProfile;
|
|
65
66
|
/**
|
|
@@ -215,7 +215,7 @@ export const CONFIG_KEYS = [
|
|
|
215
215
|
},
|
|
216
216
|
{
|
|
217
217
|
key: "context_profile",
|
|
218
|
-
describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")};
|
|
218
|
+
describe: `How the gateway folds each session's context (${CONTEXT_PROFILES.join("|")}; unset = the gateway cell's default)`,
|
|
219
219
|
get: (c) => c.contextProfile,
|
|
220
220
|
set: (c, v) => {
|
|
221
221
|
c.contextProfile = parseContextProfile(v, "context_profile");
|