@skein-code/cli 0.3.21 → 0.3.22
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 +5 -3
- package/dist/cli.js +97 -27
- package/dist/cli.js.map +1 -1
- package/docs/NEXT_STEPS.md +12 -3
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -57,8 +57,10 @@ inspectable index for code retrieval and no retrieval service dependency.
|
|
|
57
57
|
artifact for bounded readback.
|
|
58
58
|
- **Measurable token economy:** every model request records a privacy-safe
|
|
59
59
|
receipt for stable, dynamic, history, retrieval, tool-result, and tool-schema
|
|
60
|
-
estimates, alongside actual provider usage when available.
|
|
61
|
-
|
|
60
|
+
estimates, alongside actual provider usage when available. OpenAI, Anthropic,
|
|
61
|
+
and Gemini cache/reasoning counters are normalized into session totals and
|
|
62
|
+
structured events when the provider reports them. Receipts retain only counts
|
|
63
|
+
and runtime decisions, never prompt or source content.
|
|
62
64
|
- **Reversible work:** Skein snapshots affected files before mutation without
|
|
63
65
|
touching your Git history.
|
|
64
66
|
- **Resumable by default:** conversations, tasks, usage, and changed files live
|
|
@@ -94,7 +96,7 @@ To build, verify, and install a local package artifact from this checkout:
|
|
|
94
96
|
|
|
95
97
|
```bash
|
|
96
98
|
npm run verify:package -- --output-dir artifacts/package
|
|
97
|
-
npm install -g ./artifacts/package/skein-code-cli-0.3.
|
|
99
|
+
npm install -g ./artifacts/package/skein-code-cli-0.3.22.tgz
|
|
98
100
|
```
|
|
99
101
|
|
|
100
102
|
To install the published package from npm:
|
package/dist/cli.js
CHANGED
|
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "@skein-code/cli",
|
|
223
|
-
version: "0.3.
|
|
223
|
+
version: "0.3.22",
|
|
224
224
|
description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
225
225
|
type: "module",
|
|
226
226
|
license: "MIT",
|
|
@@ -236,6 +236,9 @@ var package_default = {
|
|
|
236
236
|
},
|
|
237
237
|
skein: {
|
|
238
238
|
releaseNotes: [
|
|
239
|
+
"OpenAI, Anthropic, and Gemini usage now normalizes cached input, cache-write input, and reasoning tokens when reported",
|
|
240
|
+
"Token Ledger, session totals, and structured usage events preserve provider cache and reasoning counts without prompt content",
|
|
241
|
+
"Streaming, non-streaming, explicit-zero, and legacy-session compatibility paths are covered without claiming cache activation",
|
|
239
242
|
"Failed configured verification output yields bounded current-run diagnostic ranking without persisting paths",
|
|
240
243
|
"Diagnostic hints cannot create zero-relevance hits and are cleared on success or the next agent run",
|
|
241
244
|
"Python absolute and relative module imports now contribute deterministic offline graph adjacency",
|
|
@@ -5349,10 +5352,7 @@ var AnthropicProvider = class {
|
|
|
5349
5352
|
name: block.name ?? "unknown",
|
|
5350
5353
|
arguments: safeJsonArguments(block.input)
|
|
5351
5354
|
})),
|
|
5352
|
-
usage:
|
|
5353
|
-
...data.usage?.input_tokens !== void 0 ? { inputTokens: data.usage.input_tokens } : {},
|
|
5354
|
-
...data.usage?.output_tokens !== void 0 ? { outputTokens: data.usage.output_tokens } : {}
|
|
5355
|
-
},
|
|
5355
|
+
usage: normalizeAnthropicUsage(data.usage),
|
|
5356
5356
|
...data.stop_reason ? { stopReason: data.stop_reason } : {}
|
|
5357
5357
|
};
|
|
5358
5358
|
}
|
|
@@ -5393,6 +5393,8 @@ var AnthropicProvider = class {
|
|
|
5393
5393
|
let content = "";
|
|
5394
5394
|
let inputTokens;
|
|
5395
5395
|
let outputTokens;
|
|
5396
|
+
let cachedInputTokens;
|
|
5397
|
+
let cacheWriteInputTokens;
|
|
5396
5398
|
let stopReason;
|
|
5397
5399
|
const calls = /* @__PURE__ */ new Map();
|
|
5398
5400
|
for await (const event of parseServerSentEvents(response)) {
|
|
@@ -5402,6 +5404,13 @@ var AnthropicProvider = class {
|
|
|
5402
5404
|
}
|
|
5403
5405
|
if (chunk.usage?.input_tokens !== void 0) inputTokens = chunk.usage.input_tokens;
|
|
5404
5406
|
if (chunk.usage?.output_tokens !== void 0) outputTokens = chunk.usage.output_tokens;
|
|
5407
|
+
const usage = chunk.usage ?? chunk.message?.usage;
|
|
5408
|
+
if (usage?.cache_read_input_tokens !== void 0) {
|
|
5409
|
+
cachedInputTokens = usage.cache_read_input_tokens;
|
|
5410
|
+
}
|
|
5411
|
+
if (usage?.cache_creation_input_tokens !== void 0) {
|
|
5412
|
+
cacheWriteInputTokens = usage.cache_creation_input_tokens;
|
|
5413
|
+
}
|
|
5405
5414
|
if (chunk.delta?.stop_reason) stopReason = chunk.delta.stop_reason;
|
|
5406
5415
|
const index = chunk.index ?? 0;
|
|
5407
5416
|
if (chunk.type === "content_block_start" && chunk.content_block?.type === "text") {
|
|
@@ -5440,7 +5449,9 @@ var AnthropicProvider = class {
|
|
|
5440
5449
|
})),
|
|
5441
5450
|
usage: {
|
|
5442
5451
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
5443
|
-
...outputTokens !== void 0 ? { outputTokens } : {}
|
|
5452
|
+
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
5453
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
5454
|
+
...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {}
|
|
5444
5455
|
},
|
|
5445
5456
|
...stopReason ? { stopReason } : {}
|
|
5446
5457
|
}
|
|
@@ -5456,13 +5467,18 @@ function normalizeAnthropicResponse(data) {
|
|
|
5456
5467
|
name: block.name ?? "unknown",
|
|
5457
5468
|
arguments: safeJsonArguments(block.input)
|
|
5458
5469
|
})),
|
|
5459
|
-
usage:
|
|
5460
|
-
...data.usage?.input_tokens !== void 0 ? { inputTokens: data.usage.input_tokens } : {},
|
|
5461
|
-
...data.usage?.output_tokens !== void 0 ? { outputTokens: data.usage.output_tokens } : {}
|
|
5462
|
-
},
|
|
5470
|
+
usage: normalizeAnthropicUsage(data.usage),
|
|
5463
5471
|
...data.stop_reason ? { stopReason: data.stop_reason } : {}
|
|
5464
5472
|
};
|
|
5465
5473
|
}
|
|
5474
|
+
function normalizeAnthropicUsage(usage) {
|
|
5475
|
+
return {
|
|
5476
|
+
...usage?.input_tokens !== void 0 ? { inputTokens: usage.input_tokens } : {},
|
|
5477
|
+
...usage?.output_tokens !== void 0 ? { outputTokens: usage.output_tokens } : {},
|
|
5478
|
+
...usage?.cache_read_input_tokens !== void 0 ? { cachedInputTokens: usage.cache_read_input_tokens } : {},
|
|
5479
|
+
...usage?.cache_creation_input_tokens !== void 0 ? { cacheWriteInputTokens: usage.cache_creation_input_tokens } : {}
|
|
5480
|
+
};
|
|
5481
|
+
}
|
|
5466
5482
|
function toAnthropicMessage(message2) {
|
|
5467
5483
|
if (message2.role === "tool") {
|
|
5468
5484
|
return {
|
|
@@ -5536,10 +5552,7 @@ var GeminiProvider = class {
|
|
|
5536
5552
|
name: part.functionCall?.name ?? "unknown",
|
|
5537
5553
|
arguments: safeJsonArguments(part.functionCall?.args)
|
|
5538
5554
|
})),
|
|
5539
|
-
usage:
|
|
5540
|
-
...data.usageMetadata?.promptTokenCount !== void 0 ? { inputTokens: data.usageMetadata.promptTokenCount } : {},
|
|
5541
|
-
...data.usageMetadata?.candidatesTokenCount !== void 0 ? { outputTokens: data.usageMetadata.candidatesTokenCount } : {}
|
|
5542
|
-
},
|
|
5555
|
+
usage: normalizeGeminiUsage(data.usageMetadata),
|
|
5543
5556
|
...candidate?.finishReason ? { stopReason: candidate.finishReason } : {}
|
|
5544
5557
|
};
|
|
5545
5558
|
}
|
|
@@ -5579,6 +5592,8 @@ var GeminiProvider = class {
|
|
|
5579
5592
|
let content = "";
|
|
5580
5593
|
let inputTokens;
|
|
5581
5594
|
let outputTokens;
|
|
5595
|
+
let cachedInputTokens;
|
|
5596
|
+
let reasoningTokens;
|
|
5582
5597
|
let stopReason;
|
|
5583
5598
|
const toolCalls = [];
|
|
5584
5599
|
for await (const event of parseServerSentEvents(response)) {
|
|
@@ -5590,6 +5605,12 @@ var GeminiProvider = class {
|
|
|
5590
5605
|
if (chunk.usageMetadata?.candidatesTokenCount !== void 0) {
|
|
5591
5606
|
outputTokens = chunk.usageMetadata.candidatesTokenCount;
|
|
5592
5607
|
}
|
|
5608
|
+
if (chunk.usageMetadata?.cachedContentTokenCount !== void 0) {
|
|
5609
|
+
cachedInputTokens = chunk.usageMetadata.cachedContentTokenCount;
|
|
5610
|
+
}
|
|
5611
|
+
if (chunk.usageMetadata?.thoughtsTokenCount !== void 0) {
|
|
5612
|
+
reasoningTokens = chunk.usageMetadata.thoughtsTokenCount;
|
|
5613
|
+
}
|
|
5593
5614
|
const candidate = chunk.candidates?.[0];
|
|
5594
5615
|
if (candidate?.finishReason) stopReason = candidate.finishReason;
|
|
5595
5616
|
for (const part of candidate?.content?.parts ?? []) {
|
|
@@ -5613,7 +5634,9 @@ var GeminiProvider = class {
|
|
|
5613
5634
|
toolCalls,
|
|
5614
5635
|
usage: {
|
|
5615
5636
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
5616
|
-
...outputTokens !== void 0 ? { outputTokens } : {}
|
|
5637
|
+
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
5638
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
5639
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
5617
5640
|
},
|
|
5618
5641
|
...stopReason ? { stopReason } : {}
|
|
5619
5642
|
}
|
|
@@ -5630,13 +5653,18 @@ function normalizeGeminiResponse(data) {
|
|
|
5630
5653
|
name: part.functionCall?.name ?? "unknown",
|
|
5631
5654
|
arguments: safeJsonArguments(part.functionCall?.args)
|
|
5632
5655
|
})),
|
|
5633
|
-
usage:
|
|
5634
|
-
...data.usageMetadata?.promptTokenCount !== void 0 ? { inputTokens: data.usageMetadata.promptTokenCount } : {},
|
|
5635
|
-
...data.usageMetadata?.candidatesTokenCount !== void 0 ? { outputTokens: data.usageMetadata.candidatesTokenCount } : {}
|
|
5636
|
-
},
|
|
5656
|
+
usage: normalizeGeminiUsage(data.usageMetadata),
|
|
5637
5657
|
...candidate?.finishReason ? { stopReason: candidate.finishReason } : {}
|
|
5638
5658
|
};
|
|
5639
5659
|
}
|
|
5660
|
+
function normalizeGeminiUsage(usage) {
|
|
5661
|
+
return {
|
|
5662
|
+
...usage?.promptTokenCount !== void 0 ? { inputTokens: usage.promptTokenCount } : {},
|
|
5663
|
+
...usage?.candidatesTokenCount !== void 0 ? { outputTokens: usage.candidatesTokenCount } : {},
|
|
5664
|
+
...usage?.cachedContentTokenCount !== void 0 ? { cachedInputTokens: usage.cachedContentTokenCount } : {},
|
|
5665
|
+
...usage?.thoughtsTokenCount !== void 0 ? { reasoningTokens: usage.thoughtsTokenCount } : {}
|
|
5666
|
+
};
|
|
5667
|
+
}
|
|
5640
5668
|
function toGeminiMessage(message2) {
|
|
5641
5669
|
if (message2.role === "tool") {
|
|
5642
5670
|
return {
|
|
@@ -5764,6 +5792,8 @@ var OpenAIProvider = class {
|
|
|
5764
5792
|
let content = "";
|
|
5765
5793
|
let inputTokens;
|
|
5766
5794
|
let outputTokens;
|
|
5795
|
+
let cachedInputTokens;
|
|
5796
|
+
let reasoningTokens;
|
|
5767
5797
|
let stopReason;
|
|
5768
5798
|
const calls = /* @__PURE__ */ new Map();
|
|
5769
5799
|
for await (const event of parseServerSentEvents(response)) {
|
|
@@ -5771,6 +5801,12 @@ var OpenAIProvider = class {
|
|
|
5771
5801
|
const chunk = JSON.parse(event.data);
|
|
5772
5802
|
if (chunk.usage?.prompt_tokens !== void 0) inputTokens = chunk.usage.prompt_tokens;
|
|
5773
5803
|
if (chunk.usage?.completion_tokens !== void 0) outputTokens = chunk.usage.completion_tokens;
|
|
5804
|
+
if (chunk.usage?.prompt_tokens_details?.cached_tokens !== void 0) {
|
|
5805
|
+
cachedInputTokens = chunk.usage.prompt_tokens_details.cached_tokens;
|
|
5806
|
+
}
|
|
5807
|
+
if (chunk.usage?.completion_tokens_details?.reasoning_tokens !== void 0) {
|
|
5808
|
+
reasoningTokens = chunk.usage.completion_tokens_details.reasoning_tokens;
|
|
5809
|
+
}
|
|
5774
5810
|
const choice = chunk.choices?.[0];
|
|
5775
5811
|
if (choice?.finish_reason) stopReason = choice.finish_reason;
|
|
5776
5812
|
const delta = choice?.delta;
|
|
@@ -5798,7 +5834,9 @@ var OpenAIProvider = class {
|
|
|
5798
5834
|
})),
|
|
5799
5835
|
usage: {
|
|
5800
5836
|
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
5801
|
-
...outputTokens !== void 0 ? { outputTokens } : {}
|
|
5837
|
+
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
5838
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
5839
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {}
|
|
5802
5840
|
},
|
|
5803
5841
|
...stopReason ? { stopReason } : {}
|
|
5804
5842
|
}
|
|
@@ -5816,13 +5854,18 @@ function normalizeOpenAIResponse(data) {
|
|
|
5816
5854
|
name: call.function?.name ?? "unknown",
|
|
5817
5855
|
arguments: safeJsonArguments(call.function?.arguments)
|
|
5818
5856
|
})),
|
|
5819
|
-
usage:
|
|
5820
|
-
...data.usage?.prompt_tokens !== void 0 ? { inputTokens: data.usage.prompt_tokens } : {},
|
|
5821
|
-
...data.usage?.completion_tokens !== void 0 ? { outputTokens: data.usage.completion_tokens } : {}
|
|
5822
|
-
},
|
|
5857
|
+
usage: normalizeOpenAIUsage(data.usage),
|
|
5823
5858
|
...choice?.finish_reason ? { stopReason: choice.finish_reason } : {}
|
|
5824
5859
|
};
|
|
5825
5860
|
}
|
|
5861
|
+
function normalizeOpenAIUsage(usage) {
|
|
5862
|
+
return {
|
|
5863
|
+
...usage?.prompt_tokens !== void 0 ? { inputTokens: usage.prompt_tokens } : {},
|
|
5864
|
+
...usage?.completion_tokens !== void 0 ? { outputTokens: usage.completion_tokens } : {},
|
|
5865
|
+
...usage?.prompt_tokens_details?.cached_tokens !== void 0 ? { cachedInputTokens: usage.prompt_tokens_details.cached_tokens } : {},
|
|
5866
|
+
...usage?.completion_tokens_details?.reasoning_tokens !== void 0 ? { reasoningTokens: usage.completion_tokens_details.reasoning_tokens } : {}
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5826
5869
|
function toOpenAIMessage(message2) {
|
|
5827
5870
|
if (message2.role === "tool") {
|
|
5828
5871
|
return {
|
|
@@ -6399,6 +6442,9 @@ var sessionSchema = z5.object({
|
|
|
6399
6442
|
outputSource: z5.enum(["actual", "estimated", "mixed", "unknown"]).optional(),
|
|
6400
6443
|
actualInputTokens: z5.number().nonnegative().optional(),
|
|
6401
6444
|
actualOutputTokens: z5.number().nonnegative().optional(),
|
|
6445
|
+
actualCachedInputTokens: z5.number().nonnegative().optional(),
|
|
6446
|
+
actualCacheWriteInputTokens: z5.number().nonnegative().optional(),
|
|
6447
|
+
actualReasoningTokens: z5.number().nonnegative().optional(),
|
|
6402
6448
|
estimatedInputTokens: z5.number().nonnegative().optional(),
|
|
6403
6449
|
estimatedOutputTokens: z5.number().nonnegative().optional()
|
|
6404
6450
|
}).strict(),
|
|
@@ -6419,7 +6465,10 @@ var sessionSchema = z5.object({
|
|
|
6419
6465
|
}).strict(),
|
|
6420
6466
|
actual: z5.object({
|
|
6421
6467
|
inputTokens: z5.number().nonnegative().optional(),
|
|
6422
|
-
outputTokens: z5.number().nonnegative().optional()
|
|
6468
|
+
outputTokens: z5.number().nonnegative().optional(),
|
|
6469
|
+
cachedInputTokens: z5.number().nonnegative().optional(),
|
|
6470
|
+
cacheWriteInputTokens: z5.number().nonnegative().optional(),
|
|
6471
|
+
reasoningTokens: z5.number().nonnegative().optional()
|
|
6423
6472
|
}).strict(),
|
|
6424
6473
|
inputSource: z5.enum(["actual", "estimated"]),
|
|
6425
6474
|
outputSource: z5.enum(["actual", "estimated"]),
|
|
@@ -10830,6 +10879,9 @@ var AgentRunner = class {
|
|
|
10830
10879
|
const { inputTokens, outputTokens } = turnUsage;
|
|
10831
10880
|
const actualInputTokens = validTokenCount(response.usage?.inputTokens);
|
|
10832
10881
|
const actualOutputTokens = validTokenCount(response.usage?.outputTokens);
|
|
10882
|
+
const actualCachedInputTokens = validTokenCount(response.usage?.cachedInputTokens);
|
|
10883
|
+
const actualCacheWriteInputTokens = validTokenCount(response.usage?.cacheWriteInputTokens);
|
|
10884
|
+
const actualReasoningTokens = validTokenCount(response.usage?.reasoningTokens);
|
|
10833
10885
|
const receipt = recordTokenLedger(this.session, {
|
|
10834
10886
|
requestId: userMessage.id,
|
|
10835
10887
|
turn,
|
|
@@ -10840,7 +10892,10 @@ var AgentRunner = class {
|
|
|
10840
10892
|
},
|
|
10841
10893
|
actual: {
|
|
10842
10894
|
...actualInputTokens === void 0 ? {} : { inputTokens: actualInputTokens },
|
|
10843
|
-
...actualOutputTokens === void 0 ? {} : { outputTokens: actualOutputTokens }
|
|
10895
|
+
...actualOutputTokens === void 0 ? {} : { outputTokens: actualOutputTokens },
|
|
10896
|
+
...actualCachedInputTokens === void 0 ? {} : { cachedInputTokens: actualCachedInputTokens },
|
|
10897
|
+
...actualCacheWriteInputTokens === void 0 ? {} : { cacheWriteInputTokens: actualCacheWriteInputTokens },
|
|
10898
|
+
...actualReasoningTokens === void 0 ? {} : { reasoningTokens: actualReasoningTokens }
|
|
10844
10899
|
},
|
|
10845
10900
|
inputSource: actualInputTokens === void 0 ? "estimated" : "actual",
|
|
10846
10901
|
outputSource: actualOutputTokens === void 0 ? "estimated" : "actual",
|
|
@@ -10859,7 +10914,10 @@ var AgentRunner = class {
|
|
|
10859
10914
|
outputSource: this.session.usage.outputSource ?? "unknown",
|
|
10860
10915
|
actual: {
|
|
10861
10916
|
inputTokens: this.session.usage.actualInputTokens ?? 0,
|
|
10862
|
-
outputTokens: this.session.usage.actualOutputTokens ?? 0
|
|
10917
|
+
outputTokens: this.session.usage.actualOutputTokens ?? 0,
|
|
10918
|
+
...this.session.usage.actualCachedInputTokens === void 0 ? {} : { cachedInputTokens: this.session.usage.actualCachedInputTokens },
|
|
10919
|
+
...this.session.usage.actualCacheWriteInputTokens === void 0 ? {} : { cacheWriteInputTokens: this.session.usage.actualCacheWriteInputTokens },
|
|
10920
|
+
...this.session.usage.actualReasoningTokens === void 0 ? {} : { reasoningTokens: this.session.usage.actualReasoningTokens }
|
|
10863
10921
|
},
|
|
10864
10922
|
estimated: {
|
|
10865
10923
|
inputTokens: this.session.usage.estimatedInputTokens ?? 0,
|
|
@@ -11560,6 +11618,18 @@ function recordTokenUsage(session, providerUsage, estimatedInputTokens, estimate
|
|
|
11560
11618
|
} else {
|
|
11561
11619
|
session.usage.estimatedOutputTokens = (session.usage.estimatedOutputTokens ?? 0) + outputTokens;
|
|
11562
11620
|
}
|
|
11621
|
+
const cachedInputActual = validTokenCount(providerUsage?.cachedInputTokens);
|
|
11622
|
+
const cacheWriteInputActual = validTokenCount(providerUsage?.cacheWriteInputTokens);
|
|
11623
|
+
const reasoningActual = validTokenCount(providerUsage?.reasoningTokens);
|
|
11624
|
+
if (cachedInputActual !== void 0) {
|
|
11625
|
+
session.usage.actualCachedInputTokens = (session.usage.actualCachedInputTokens ?? 0) + cachedInputActual;
|
|
11626
|
+
}
|
|
11627
|
+
if (cacheWriteInputActual !== void 0) {
|
|
11628
|
+
session.usage.actualCacheWriteInputTokens = (session.usage.actualCacheWriteInputTokens ?? 0) + cacheWriteInputActual;
|
|
11629
|
+
}
|
|
11630
|
+
if (reasoningActual !== void 0) {
|
|
11631
|
+
session.usage.actualReasoningTokens = (session.usage.actualReasoningTokens ?? 0) + reasoningActual;
|
|
11632
|
+
}
|
|
11563
11633
|
session.usage.inputSource = mergeMeasurementSource(
|
|
11564
11634
|
priorInputSource,
|
|
11565
11635
|
inputActual === void 0 ? "estimated" : "actual",
|