dsh-context-fold 0.1.4 → 0.1.5

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 (2) hide show
  1. package/lib/index.js +13 -6
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -1351,19 +1351,26 @@ function counterfactualOf(folds, steps, options = {}) {
1351
1351
  const savedTokenRate = cacheReadShare === void 0 ? price.uncachedInput : cacheReadShare * price.cacheRead + (1 - cacheReadShare) * price.uncachedInput;
1352
1352
  const grossSaving = tokensSavedPerStep * remainingSteps * savedTokenRate;
1353
1353
  let invalidationCost = 0;
1354
- if (foldSteps !== void 0) for (const foldStep of foldSteps) {
1355
- const at = steps.find((step) => step.step >= foldStep);
1356
- if (at === void 0) continue;
1357
- const prompt = promptTokensOf(at);
1358
- invalidationCost += prompt * (price.uncachedInput - price.cacheRead);
1354
+ if (foldSteps !== void 0) {
1355
+ const distinct = [...new Set(foldSteps)];
1356
+ for (const foldStep of distinct) {
1357
+ const at = steps.find((step) => step.step >= foldStep);
1358
+ if (at === void 0) continue;
1359
+ const prompt = promptTokensOf(at);
1360
+ invalidationCost += prompt * (price.uncachedInput - price.cacheRead);
1361
+ }
1359
1362
  }
1360
1363
  const counterfactualPromptCost = actualPromptCost + tokensSavedPerStep * remainingSteps * savedTokenRate;
1361
1364
  const assumptions = [];
1362
1365
  assumptions.push(hasRealUsage ? `Prices are DeepSeek ratios (cache read ${price.cacheRead}×, write ${price.cacheWrite}×, uncached ${price.uncachedInput}×), applied to this session's observed usage.` : "This session reported no provider usage, so even the \"actual\" figures are heuristic token counts, not billed amounts.");
1363
1366
  if (cacheReadShare !== void 0) assumptions.push(`Saved tokens are priced at this session's observed cache-read share (${(cacheReadShare * 100).toFixed(1)}%), not at the uncached rate.`);
1364
1367
  if (foldSteps === void 0 || foldSteps.length === 0) assumptions.push("Fold step numbers were unavailable, so every observed step is credited with the saving. Treat the figure as an upper bound.");
1365
- else assumptions.push(`Each fold is charged one prefix invalidation: the whole prompt after it re-billed from cache-read to uncached once.`);
1368
+ else {
1369
+ const distinctFoldSteps = new Set(foldSteps).size;
1370
+ assumptions.push(`Each of the ${String(distinctFoldSteps)} distinct fold step(s) is charged one prefix invalidation: the prompt after it re-billed from cache-read to uncached once. Folds sharing a step share that charge, because they invalidate the same prefix.`);
1371
+ }
1366
1372
  assumptions.push("The counterfactual assumes the same number of steps and the same cache behaviour as the real session — a folded prompt might have hit cache differently.");
1373
+ assumptions.push("\"Saving per step\" is the total prompt reduction on the surface, not a per-fold figure: it is multiplied by the steps that followed each fold.");
1367
1374
  return {
1368
1375
  tokensNow,
1369
1376
  tokensIfUnfolded,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context-fold",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "dsh-context-fold: stage-boundary folding of completed tool results into a conclusion plus a spill path, deterministic and replay-safe.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",