@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 +3 -3
- package/package.json +1 -1
- package/release-notes/jaypie/1.2.114.md +9 -0
- package/release-notes/jaypie/1.2.115.md +9 -0
- package/release-notes/llm/1.3.55.md +53 -0
- package/release-notes/llm/1.3.56.md +26 -0
- package/release-notes/mcp/0.8.178.md +10 -0
- package/release-notes/mcp/0.8.179.md +10 -0
- package/release-notes/testkit/1.2.79.md +9 -0
- package/skills/llm.md +37 -14
package/dist/assets.js
CHANGED
|
@@ -55,11 +55,11 @@ function getMcpAssetPaths() {
|
|
|
55
55
|
*/
|
|
56
56
|
function getMcpBuildInfo() {
|
|
57
57
|
return {
|
|
58
|
-
commit: "
|
|
58
|
+
commit: "4e0d56bd"
|
|
59
59
|
,
|
|
60
|
-
version: "0.8.
|
|
60
|
+
version: "0.8.179"
|
|
61
61
|
,
|
|
62
|
-
versionString: "@jaypie/mcp@0.8.
|
|
62
|
+
versionString: "@jaypie/mcp@0.8.179#4e0d56bd"
|
|
63
63
|
,
|
|
64
64
|
};
|
|
65
65
|
}
|
package/package.json
CHANGED
|
@@ -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,
|
|
72
|
+
import { Llm, LLM, tokenCost } from "@jaypie/llm";
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
const dollars =
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
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
|
|
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
|
|
1189
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|