@jaypie/mcp 0.8.177 → 0.8.179

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/dist/assets.js CHANGED
@@ -55,11 +55,11 @@ function getMcpAssetPaths() {
55
55
  */
56
56
  function getMcpBuildInfo() {
57
57
  return {
58
- commit: "962b054a"
58
+ commit: "4e0d56bd"
59
59
  ,
60
- version: "0.8.177"
60
+ version: "0.8.179"
61
61
  ,
62
- versionString: "@jaypie/mcp@0.8.177#962b054a"
62
+ versionString: "@jaypie/mcp@0.8.179#4e0d56bd"
63
63
  ,
64
64
  };
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaypie/mcp",
3
- "version": "0.8.177",
3
+ "version": "0.8.179",
4
4
  "description": "Jaypie MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,9 @@
1
+ ---
2
+ version: 1.2.114
3
+ date: 2026-09-28
4
+ summary: Pulls @jaypie/llm 1.3.55
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - **`@jaypie/llm` 1.3.55**: usage reports one contract across every provider, with Gemini `output` including thinking tokens (#599); `tokenCost` is exported and bills each token once at its cache TTL; prompt caching defaults to a one-hour TTL; Google, OpenRouter, Fireworks, and Mistral stop sending the system prompt twice; `MODEL.SONNET` moves to Claude Sonnet 5.5.
@@ -0,0 +1,9 @@
1
+ ---
2
+ version: 1.2.115
3
+ date: 2026-09-28
4
+ summary: Pulls @jaypie/llm 1.3.56
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - **`@jaypie/llm` 1.3.56**: failing over down a fallback chain logs at `debug` instead of `error` and `warn`; the report tally counts `failures` and `fallbacks`.
@@ -0,0 +1,53 @@
1
+ ---
2
+ version: 1.3.55
3
+ date: 2026-09-28
4
+ summary: Usage reports one contract across every provider (reasoning within output, cache within input), tokenCost is exported and bills each token once at its cache TTL, prompt caching defaults to a one-hour TTL, and MODEL.SONNET moves to Claude Sonnet 5.5
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ ### Usage contract
10
+
11
+ `LlmUsageItem` now means the same thing for every provider, on both `operate()` and `stream()`: `input` counts all prompt tokens with `cacheRead`/`cacheWrite` as subsets of it, `output` counts all billed output with `reasoning` as a subset of it, and `total` is `input + output`.
12
+
13
+ - **Gemini** `output` includes `thoughtsTokenCount` (#599). A thinking-heavy `gemini-3.8-flash` call reported 27% of its billed output. `input` also includes `toolUsePromptTokenCount`, and `cachedContentTokenCount` surfaces as `cacheRead`. The streamed `total` now comes from `totalTokenCount`.
14
+ - **Anthropic** and **Bedrock** `input` include their cache reads and writes, which their APIs report outside `input_tokens`/`inputTokens`
15
+ - **Streaming** carries `cacheRead`/`cacheWrite` on every provider. OpenRouter and Fireworks streams report `reasoning` (it was always `0`). Anthropic streams read cumulative `message_delta` usage.
16
+ - **OpenAI, xAI, and Meta streams** emit usage. The done chunk waited for a `response.done` event the Responses API never sends, so a live stream reported no usage. It now follows the stream's end.
17
+ - **Bedrock streams** emit usage. ConverseStream sends `metadata` after `messageStop`, and the done chunk fired at `messageStop` with zeros. It now follows the stream's end.
18
+ - **Bedrock** `operate()` usage names the requested model. Converse responses do not echo the model id, so every item was labeled with the default (`amazon.nova-pro-v1:0`), and a Claude route was priced at Nova rates.
19
+ - OpenRouter, Fireworks, and Mistral share one chat-completions usage mapper (camelCase and snake_case)
20
+
21
+ ### Token cost
22
+
23
+ `tokenCost(usage, { model?, ttl? })` is exported (and re-exported by the testkit mock), along with the `LlmUsage`, `LlmUsageItem`, and `LlmCacheWriteTtl` types. It returns USD for `response.usage`, or `undefined` when any item is unpriced.
24
+
25
+ - Bills each token once: `input` less cache tokens at the input rate, cache tokens at their cache rates, `output` less `reasoning` at the output rate, and `reasoning` at its own rate. It previously billed reasoning twice for Anthropic, OpenAI, and Fireworks, and cached input twice for OpenAI-compatible providers. Emulated OCR on Gemini now prices thinking once.
26
+ - Bills cache writes at the TTL they were written with. It previously billed every write at the five-minute rate, which underpriced Anthropic's default one-hour writes by 37.5%.
27
+
28
+ ### Prompt-cache TTL
29
+
30
+ - `cache: true` (or omitted) now writes with a one-hour TTL everywhere a provider accepts one: Anthropic (unchanged), OpenRouter (was five minutes), and Bedrock Claude 4.5+ routes (`cachePoint.ttl`, was Bedrock's five-minute default). `cache: "5m"` still selects five minutes. Nova, older Bedrock Claude, and providers without a TTL cache on their own schedule.
31
+ - `LlmUsageItem.cacheWriteTtl` splits `cacheWrite` by TTL from Anthropic `usage.cache_creation` and Bedrock `usage.cacheDetails`. Pricing bills each TTL at its rate; writes the provider does not split bill at the `ttl` option (default `"1h"`).
32
+
33
+ ### System prompt sent once
34
+
35
+ Google, OpenRouter, Fireworks, and Mistral sent the system prompt twice: once as the top-level system field and again from history, where the operate loop also places it. Every call with a system prompt paid for it twice (a 7,216-token system prompt billed as 14,432 on OpenRouter). Each now skips the history copy; a different system message elsewhere in history is kept.
36
+
37
+ ### Cache option on later turns
38
+
39
+ Tool-loop turns after the first rebuilt the request without `cache`, so `cache: false` and `cache: "5m"` applied only to the first turn. `operate()` and `stream()` now carry it on every turn.
40
+
41
+ ### Anthropic structured-output fallback
42
+
43
+ The tool-emulation fallback (used only when a model rejects native `output_config.format`) sent `tool_choice: { type: "any" }`, which Fable 5.1, Mythos 5.1, Opus 5.5, Sonnet 5.5, and later reject with a 400. Those models now get `{ type: "auto" }`; earlier models keep `any`.
44
+
45
+ ### Claude Sonnet 5.5
46
+
47
+ - `MODEL.SONNET` is `claude-sonnet-5-5`, and so is `PROVIDER.ANTHROPIC.DEFAULT` through it. `MODEL.OPENROUTER.SONNET` is `anthropic/claude-sonnet-5.5`.
48
+ - `COST["claude-sonnet-5-5"]`: $2 input, $10 output, $0.20 cache read, $2.50/$4.00 cache write (5m/1h). `claude-sonnet-5` keeps its entry.
49
+ - Temperature is stripped for `claude-sonnet-5` and later up front, as it is for Opus 4.7+, instead of after a 400
50
+
51
+ ## Testing
52
+
53
+ - `npm run test -w packages/llm`: new specs cover Gemini operate and stream usage (the #599 fixture), Anthropic and Bedrock cache folding in operate and stream, the Bedrock `metadata`-after-`messageStop` order, an OpenAI stream ending without `response.done`, the chat-completions mapper, single-billing of reasoning and cached input in `tokenCost`, emulated Gemini OCR cost, Sonnet 5 temperature stripping, per-TTL cache-write pricing and the `ttl` option, the Anthropic `cache_creation` and Bedrock `cacheDetails` splits, the one-hour default on OpenRouter and Bedrock Claude routes, the fallback `tool_choice` per model, Bedrock usage attributed to the requested model, the system prompt sent once on Google, OpenRouter, Fireworks, and Mistral, and `cache` on later loop turns
@@ -0,0 +1,26 @@
1
+ ---
2
+ version: 1.3.56
3
+ date: 2026-09-28
4
+ summary: Failing over down a fallback chain logs at debug instead of error and warn, and the report tally counts failures and fallbacks
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ ### Failover logging
10
+
11
+ A timeout (or any failure) on a fail-fast attempt down a fallback chain logged `API call failed after 0 retries` at `error` and `Provider X failed` at `warn`, although the next model took over as designed.
12
+
13
+ - `RetryExecutor` logs a zero-budget failure at `debug`: `API call timed out after 60000ms; not retrying` for a timeout, `API call failed; not retrying` or `API call rate limited; not retrying` otherwise. Exhausting a nonzero budget still logs `error`.
14
+ - `runWithFallback` logs `Provider X failed; failing over` at `debug` when another model remains. Only the failure that reaches the caller (a lone model, or the linger pass) logs at `warn`. Both carry `kind` (`timeout` or the `LlmError` category).
15
+ - A timeout that retries on the transient budget names its deadline in the retry `debug` line.
16
+
17
+ ### Report tally
18
+
19
+ Inside a Jaypie handler, `operate()`, `ocr()`, and `question()` tally each failed provider attempt onto the `llm` report key:
20
+
21
+ - `failures`: counts by `provider:model` and kind, e.g. `{ "openai:gpt-5.5": { "timeout": 1 } }`
22
+ - `fallbacks`: counts each hand-off to another model, including the linger pass back to the primary
23
+
24
+ ## Testing
25
+
26
+ - `npm run test -w packages/llm`: new `tallyFailure` and `runWithFallback` specs cover failure kinds, key resolution, the fallback count, and the debug/warn split; `RetryExecutor` specs cover the zero-budget debug lines for transient, rate-limit, and timeout failures
@@ -0,0 +1,10 @@
1
+ ---
2
+ version: 0.8.178
3
+ date: 2026-09-28
4
+ summary: Release notes for @jaypie/llm 1.3.55, @jaypie/testkit 1.2.79, and jaypie 1.2.114; llm skill documents the usage contract, tokenCost, and cache TTLs
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - **Release notes**: `@jaypie/llm` 1.3.55, `@jaypie/testkit` 1.2.79, and `jaypie` 1.2.114
10
+ - **`llm` skill**: documents the normalized usage contract (`reasoning` within `output`, `cacheRead`/`cacheWrite` within `input`), prices usage with the exported `tokenCost`, and describes the one-hour default cache TTL and `cacheWriteTtl`
@@ -0,0 +1,10 @@
1
+ ---
2
+ version: 0.8.179
3
+ date: 2026-09-28
4
+ summary: Release notes for @jaypie/llm 1.3.56 and jaypie 1.2.115; llm skill documents failover logging and the failures/fallbacks tally
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - **Release notes**: `@jaypie/llm` 1.3.56 and `jaypie` 1.2.115
10
+ - **`llm` skill**: documents the `failures` and `fallbacks` report totals and the debug-level failover logging under Attempt Timeout
@@ -0,0 +1,9 @@
1
+ ---
2
+ version: 1.2.79
3
+ date: 2026-09-28
4
+ summary: Re-exports tokenCost from the llm mock
5
+ ---
6
+
7
+ ## Changes
8
+
9
+ - `tokenCost` re-exported from `@jaypie/llm` alongside the other pure utilities, so specs that mock `@jaypie/llm` still price usage with the real function.
package/skills/llm.md CHANGED
@@ -69,17 +69,32 @@ LlamaCloud serves LlamaParse, which extracts documents and generates no text. Th
69
69
  `LLM.COST` maps a literal model id to its standard list price per **million** tokens (`LlmModelCost`). Keys are string literals, not `MODEL.*` references, so a model retired from the catalog keeps its price and historic usage stays replayable. **Provider aliases are never priced.** A `-latest` id has no stable rate — the provider can repoint it at any time, and an entry under the alias would keep returning the old price with nothing to signal the move. `MODEL.MISTRAL.*` names aliases, so `COST[MODEL.MISTRAL.LARGE]` returns `undefined` by design: resolve the alias to the id the API echoes on the response (`response.model`) and price that.
70
70
 
71
71
  ```typescript
72
- import { LLM, type LlmModelCost } from "@jaypie/llm";
72
+ import { Llm, LLM, tokenCost } from "@jaypie/llm";
73
73
 
74
- const rate: LlmModelCost | undefined = LLM.COST[response.model];
75
- const dollars = rate
76
- ? (usage.input * rate.input + usage.output * rate.output) / 1e6
77
- : 0;
74
+ const response = await Llm.operate(input, { model: LLM.MODEL.SONNET });
75
+ const dollars: number | undefined = tokenCost(response.usage, {
76
+ model: LLM.MODEL.SONNET, // fallback price when an item's echoed id is unpriced
77
+ });
78
78
  ```
79
79
 
80
+ `tokenCost(usage, { model?, ttl? })` returns USD for a usage list, or `undefined` when the list is empty or any item is unpriced, so "free" and "unknown" stay distinct. It bills each token once. Usage is normalized across every provider and both `operate()` and `stream()`: `input` counts all prompt tokens with `cacheRead`/`cacheWrite` as subsets of it, `output` counts all billed output with `reasoning` (thinking) as a subset of it, and `total` is `input + output`. Per item:
81
+
82
+ | Tokens | Rate |
83
+ | --------------------------------------- | -------------------------------------------------------- |
84
+ | `input − cacheRead − cacheWrite` | `input` |
85
+ | `cacheRead` | `cachedInputRead` (else `input`) |
86
+ | `cacheWriteTtl["1h"]`, `["5m"]` | `cachedInputWrite` at that TTL (scalar rates ignore TTL) |
87
+ | `cacheWrite` the provider did not split | `cachedInputWrite` at the `ttl` option (default `"1h"`) |
88
+ | `output − reasoning` | `output` |
89
+ | `reasoning` | `reasoning` (else `output`) |
90
+
91
+ Anthropic and Bedrock report writes per TTL (`cacheWriteTtl`); pass `ttl: "5m"` when the call used `cache: "5m"` on a provider that does not. `Llm.ocr` prices emulated calls with `tokenCost`.
92
+
93
+ `LlmModelCost` fields (USD per million tokens):
94
+
80
95
  | Field | Meaning |
81
96
  | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
82
- | `input` | Uncached input tokens |
97
+ | `input` | Uncached input tokens (`usage.input` less `cacheRead` and `cacheWrite`) |
83
98
  | `output` | Output tokens |
84
99
  | `cachedInputRead` | Cache-read (hit) tokens. Omitted when the provider does not price reads separately |
85
100
  | `cachedInputWrite` | Cache-write tokens. Scalar when TTL-invariant (`0` where the provider publishes a free write, as Bedrock does for Nova), or keyed `{ "5m", "1h" }` matching `LlmCache`. Omitted means writes bill at `input` (a TTL-keyed premium is Anthropic-only) |
@@ -112,7 +127,7 @@ const response = await Llm.operate(input, {
112
127
  // Response structure
113
128
  response.content; // string | object (structured output)
114
129
  response.history; // LlmHistory - for follow-up calls
115
- response.usage; // Token usage per turn
130
+ response.usage; // Token usage per turn: { input, output, reasoning, total, cacheRead?, cacheWrite?, cacheWriteTtl? }; reasoning ⊂ output, cache ⊂ input; price with tokenCost()
116
131
  response.reasoning; // Extended thinking (if available)
117
132
  response.status; // "completed" | "incomplete" | "in_progress"
118
133
  ```
@@ -849,6 +864,7 @@ const response = await llm.operate(input, {
849
864
  - `stream()` treats `timeout` as an idle timeout: it restarts with every chunk and pauses while the consumer holds one. A stall after partial output yields an error chunk.
850
865
  - No default applies; unset means no deadline. Size it above the slowest legitimate non-streaming response (long reasoning runs take minutes).
851
866
  - `Llm.ocr` keeps `timeout` as the LlamaParse job deadline.
867
+ - A timeout that hands off to the next model logs at `debug` (`API call timed out after 60000ms; not retrying`, then `Provider openai failed; failing over`). Only the failure that reaches the caller logs at `warn`. The report tally counts it under `failures` and `fallbacks`.
852
868
 
853
869
  ### Fallback Response Metadata
854
870
 
@@ -907,6 +923,8 @@ Inside a Jaypie handler (`expressHandler`, `lambdaHandler`, and stream variants)
907
923
  ```json
908
924
  {
909
925
  "llm": {
926
+ "failures": { "openai:gpt-5.5": { "timeout": 1 } },
927
+ "fallbacks": 1,
910
928
  "operates": 2,
911
929
  "toolCalls": 3,
912
930
  "tools": { "get_weather": 2, "roll": 1 },
@@ -926,6 +944,8 @@ Inside a Jaypie handler (`expressHandler`, `lambdaHandler`, and stream variants)
926
944
  - `operates` counts loop executions; repeated calls sum every number
927
945
  - `usage` is keyed `provider:model` — fallback providers appear as separate keys
928
946
  - `tools` appears only when tools were called
947
+ - `failures` counts failed provider attempts by `provider:model` and kind (`timeout`, `rate_limit`, `retryable`, `quota`, `unrecoverable`, `unknown`), from `operate()`, `ocr()`, and `question()`
948
+ - `fallbacks` counts hand-offs to another model, including the final retry of the primary once a chain is spent
929
949
  - Outside a handler session the tally is skipped entirely (guarded on `log.sessionActive`), so a CLI or script calling `operate()` directly emits nothing
930
950
 
931
951
  ## LLM Observability (Datadog)
@@ -1071,7 +1091,7 @@ describe("LLM Integration", () => {
1071
1091
 
1072
1092
  ```typescript
1073
1093
  interface LlmOperateOptions {
1074
- cache?: boolean | 0 | "5m" | "1h"; // Prompt caching (default on: 1h Anthropic, 5m elsewhere; false/0 disables)
1094
+ cache?: boolean | 0 | "5m" | "1h"; // Prompt caching (default on at 1h; false/0 disables)
1075
1095
  data?: Record<string, any>; // Placeholder substitution data
1076
1096
  effort?: LlmEffort; // Provider-neutral reasoning effort (lowest|low|medium|high|highest)
1077
1097
  fallback?: LlmFallbackConfig[] | false; // Fallback provider chain
@@ -1180,21 +1200,24 @@ tool-calling loop is billed at the provider's cache-read rate (~0.1x input)
1180
1200
  after the first write. Control with the scalar `cache` option:
1181
1201
 
1182
1202
  ```typescript
1183
- await Llm.operate(input, { system: SYSTEM }); // cached (1h Anthropic, else 5m)
1203
+ await Llm.operate(input, { system: SYSTEM }); // cached @ 1h
1184
1204
  await Llm.operate(input, { system: SYSTEM, cache: "5m" }); // cached @ 5m
1185
1205
  await Llm.operate(input, { system: SYSTEM, cache: false }); // opt out
1186
1206
  ```
1187
1207
 
1188
- `true`/omitted = enabled at the adapter default (`"1h"` on Anthropic, `"5m"`
1189
- elsewhere); `false`/`0` = disabled; `"5m"`/`"1h"` = that TTL.
1208
+ `true`/omitted = enabled at `"1h"`; `false`/`0` = disabled; `"5m"`/`"1h"` =
1209
+ that TTL. A one-hour write costs more than a five-minute one (2x input vs
1210
+ 1.25x on Anthropic) but reads cost the same, so it pays for itself after about
1211
+ three reads and survives the gaps between turns.
1190
1212
 
1191
1213
  Per provider: Anthropic `cache_control` on system + last tool; Bedrock
1192
1214
  `cachePoint` blocks (model-gated, auto-denylisted and retried without on a 400;
1193
- 5m only); OpenAI/xAI/Meta automatic caching + a stable `prompt_cache_key`; OpenRouter
1215
+ `ttl` sent on Claude 4.5+ routes, Nova and older Claude cache for 5m); OpenAI/xAI/Meta automatic caching + a stable `prompt_cache_key`; OpenRouter
1194
1216
  `cache_control` on the system message (forwarded to Anthropic/Gemini backends);
1195
- Google implicit caching only (Gemini 2.5+). TTL applies to Anthropic/OpenRouter;
1217
+ Google implicit caching only (Gemini 2.5+; `cachedContentTokenCount` surfaces as `cacheRead`). TTL applies to Anthropic, OpenRouter, and Bedrock Claude 4.5+;
1196
1218
  others use provider defaults. Sub-threshold prefixes silently no-op. Cache
1197
- tokens surface as `cacheRead`/`cacheWrite` on usage, in the exchange envelope
1219
+ tokens surface as `cacheRead`/`cacheWrite` on usage (with `cacheWriteTtl`
1220
+ splitting writes by TTL on Anthropic and Bedrock), in the exchange envelope
1198
1221
  `usageTotals`, and in the report tally.
1199
1222
 
1200
1223
  ## Provider Options and Output Limits