@tormentalabs/claude-code-wire-compat 0.4.0 → 0.6.0
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/CHANGELOG.md +217 -0
- package/README.md +51 -7
- package/dist/betas.d.ts +65 -7
- package/dist/betas.d.ts.map +1 -1
- package/dist/betas.js +143 -2
- package/dist/betas.js.map +1 -1
- package/dist/build-request.d.ts +12 -6
- package/dist/build-request.d.ts.map +1 -1
- package/dist/build-request.js +44 -15
- package/dist/build-request.js.map +1 -1
- package/dist/contracts.d.ts +7 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +5 -0
- package/dist/fingerprint.js.map +1 -1
- package/dist/headers.d.ts.map +1 -1
- package/dist/headers.js +5 -2
- package/dist/headers.js.map +1 -1
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/model-capabilities.d.ts +3 -3
- package/dist/model-capabilities.d.ts.map +1 -1
- package/dist/model-capabilities.js +55 -19
- package/dist/model-capabilities.js.map +1 -1
- package/dist/model-identity.d.ts +9 -1
- package/dist/model-identity.d.ts.map +1 -1
- package/dist/model-identity.js +33 -2
- package/dist/model-identity.js.map +1 -1
- package/dist/model-queries.d.ts +89 -0
- package/dist/model-queries.d.ts.map +1 -0
- package/dist/model-queries.js +232 -0
- package/dist/model-queries.js.map +1 -0
- package/dist/models.js +1 -1
- package/dist/models.js.map +1 -1
- package/dist/profiles/beta-registry-2.1.280.d.ts +211 -0
- package/dist/profiles/beta-registry-2.1.280.d.ts.map +1 -0
- package/dist/profiles/beta-registry-2.1.280.js +292 -0
- package/dist/profiles/beta-registry-2.1.280.js.map +1 -0
- package/dist/profiles/claude-code-2.1.280.d.ts +3 -0
- package/dist/profiles/claude-code-2.1.280.d.ts.map +1 -0
- package/dist/profiles/claude-code-2.1.280.js +359 -0
- package/dist/profiles/claude-code-2.1.280.js.map +1 -0
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +3 -0
- package/dist/redaction.js.map +1 -1
- package/dist/request-body.d.ts +1 -1
- package/dist/request-body.d.ts.map +1 -1
- package/dist/request-body.js +16 -5
- package/dist/request-body.js.map +1 -1
- package/dist/thinking.d.ts +53 -2
- package/dist/thinking.d.ts.map +1 -1
- package/dist/thinking.js +124 -26
- package/dist/thinking.js.map +1 -1
- package/package.json +6 -3
- package/src/betas.ts +208 -9
- package/src/build-request.ts +54 -21
- package/src/contracts.ts +7 -2
- package/src/fingerprint.ts +5 -0
- package/src/headers.ts +4 -2
- package/src/index.ts +28 -3
- package/src/model-capabilities.ts +55 -19
- package/src/model-identity.ts +29 -2
- package/src/model-queries.ts +273 -0
- package/src/models.ts +1 -1
- package/src/profiles/beta-registry-2.1.280.ts +309 -0
- package/src/profiles/claude-code-2.1.280.ts +364 -0
- package/src/redaction.ts +3 -0
- package/src/request-body.ts +25 -3
- package/src/thinking.ts +148 -26
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,223 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.6.0] - 2026-09-24
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **The default protocol profile is now Claude Code 2.1.280 with SDK
|
|
10
|
+
0.112.1** (profile id `claude-code-2.1.280-sdk-0.112.1`). A caller that does
|
|
11
|
+
not pin a profile now emits different bytes: the version strings, beta
|
|
12
|
+
header, fingerprint and model catalogue all follow the new release.
|
|
13
|
+
|
|
14
|
+
Rollback: pin the previous profile singleton explicitly.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import {
|
|
18
|
+
CLAUDE_CODE_2_1_233_PROFILE,
|
|
19
|
+
buildClaudeCodeCountTokensRequest,
|
|
20
|
+
buildClaudeCodeRequest,
|
|
21
|
+
parseBuiltClaudeCodeRequest,
|
|
22
|
+
} from "@tormentalabs/claude-code-wire-compat";
|
|
23
|
+
|
|
24
|
+
const built = await buildClaudeCodeRequest(
|
|
25
|
+
input,
|
|
26
|
+
CLAUDE_CODE_2_1_233_PROFILE,
|
|
27
|
+
);
|
|
28
|
+
const counted = await buildClaudeCodeCountTokensRequest(
|
|
29
|
+
countInput,
|
|
30
|
+
CLAUDE_CODE_2_1_233_PROFILE,
|
|
31
|
+
);
|
|
32
|
+
const parsed = parseBuiltClaudeCodeRequest(
|
|
33
|
+
persisted,
|
|
34
|
+
CLAUDE_CODE_2_1_233_PROFILE,
|
|
35
|
+
);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The pin has to be passed on every call to each of the three entry points
|
|
39
|
+
that read the default seam — `buildClaudeCodeRequest`,
|
|
40
|
+
`buildClaudeCodeCountTokensRequest` and `parseBuiltClaudeCodeRequest`.
|
|
41
|
+
Pinning the builders alone is not enough: `parseBuiltClaudeCodeRequest`
|
|
42
|
+
recomputes the expected headers under the profile it is given, so a
|
|
43
|
+
`BuiltClaudeCodeRequest` persisted under the old default and parsed unpinned
|
|
44
|
+
after upgrading is rejected with `ClaudeCodeWireError` code `INVALID_INPUT`.
|
|
45
|
+
|
|
46
|
+
Pinning restores the previous profile's data, not every byte it used to
|
|
47
|
+
produce. Three behaviours in this release are shared by every profile, the
|
|
48
|
+
previous pin included, and pinning does not undo them: the model-id
|
|
49
|
+
normalizer rungs and the extended-thinking budget floor and caller-type guard
|
|
50
|
+
(both under Fixed), and the `tool_choice` `any` demotion (under Changed).
|
|
51
|
+
|
|
52
|
+
- **`ClaudeCodeCapabilities` gains two required booleans**,
|
|
53
|
+
`midConvToolChange` and `perTurnEffort`. Because
|
|
54
|
+
`ClaudeCodeCapabilityDecisions` is keyed off that type,
|
|
55
|
+
`evidence.capabilityDecisions` gains the same two required keys.
|
|
56
|
+
|
|
57
|
+
Compatibility: callers supplying capabilities on input are unaffected,
|
|
58
|
+
because `ClaudeCodeRequestInput.capabilities` is a `Partial` of that type.
|
|
59
|
+
Only code that constructs a complete `ClaudeCodeCapabilities` value, or that
|
|
60
|
+
exhaustively destructures `evidence.capabilityDecisions`, needs updating.
|
|
61
|
+
|
|
62
|
+
Persisted artefacts: a `BuiltClaudeCodeRequest` persisted by 0.5.0 or
|
|
63
|
+
earlier is rejected by `parseBuiltClaudeCodeRequest` with
|
|
64
|
+
`ClaudeCodeWireError` code `INVALID_INPUT` under every profile, including
|
|
65
|
+
the previous pin, because its `evidence.capabilityDecisions` lacks the two
|
|
66
|
+
new keys. The parser requires the decisions record to carry exactly the
|
|
67
|
+
expected key set and reads both new booleans as mandatory. Re-build those
|
|
68
|
+
requests, or keep parsing them with 0.5.0. The rollback snippet above
|
|
69
|
+
restores the previous profile for new builds; it does not restore
|
|
70
|
+
parseability of artefacts persisted before this version.
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- **Claude Code 2.1.280 protocol profile**, extracted from the release binary
|
|
75
|
+
rather than inferred:
|
|
76
|
+
- a 40-entry beta registry, nine of whose entries are new to this release;
|
|
77
|
+
- three auxiliary beta sets;
|
|
78
|
+
- five new beta push sites plus one coupled removal: when the
|
|
79
|
+
thinking-display-updates site fires it also removes the previously composed
|
|
80
|
+
redact-thinking identifier;
|
|
81
|
+
- a 20-model catalogue, adding `claude-opus-5-5`, `claude-fable-5-1` and
|
|
82
|
+
`claude-mythos-5-1`.
|
|
83
|
+
|
|
84
|
+
- **New exports for 2.1.280**: the profile singleton
|
|
85
|
+
`CLAUDE_CODE_2_1_280_PROFILE` and its ordered beta registry
|
|
86
|
+
`BETA_REGISTRY_2_1_280`, both from the package entry point, plus the subpath
|
|
87
|
+
export `@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.280`.
|
|
88
|
+
|
|
89
|
+
- **A third frozen packed-consumer digest**, pinned across node, bun and
|
|
90
|
+
workerd from the packed tarball:
|
|
91
|
+
`9a531ed01ddd3440ce5b7f25c6caf5f045a9b4e78d885b5317508e21a22ada90`.
|
|
92
|
+
|
|
93
|
+
- **Fingerprint known-answer vectors for 2.1.280**, computed independently
|
|
94
|
+
outside this package so they prove the formula rather than the code's
|
|
95
|
+
consistency with itself.
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- **`cacheDiagnosisEnabled` is `true` for the 2.1.280 profile.** The 2.1.233
|
|
100
|
+
profile is deliberately unchanged: whether its `false` was always wrong
|
|
101
|
+
cannot be settled without that release's binary.
|
|
102
|
+
- **`tool_choice` of type `any` is demoted to `{type:"auto"}` while extended
|
|
103
|
+
thinking is active**, on every profile, alongside the existing `tool`
|
|
104
|
+
demotion. Upstream demotes only `tool`; this is a deliberate, recorded
|
|
105
|
+
divergence (2.1.280 analysis §6.6 amendment, `MEMORY.md` 2026-09-24)
|
|
106
|
+
because the Messages API rejects forced tool use under extended thinking.
|
|
107
|
+
A caller that previously received an HTTP 400 for `any` under thinking now
|
|
108
|
+
gets an `auto` request; `disable_parallel_tool_use` on the demoted `any` is
|
|
109
|
+
dropped, as it already was for `tool`. `auto`/`none`, and `any` with
|
|
110
|
+
thinking inactive, are unchanged. No sealed fixture or frozen digest moved.
|
|
111
|
+
|
|
112
|
+
### Removed
|
|
113
|
+
|
|
114
|
+
- **The `drift:check` maintainer script is retired**, and the packed-consumer
|
|
115
|
+
canary script now builds before it packs. Neither is consumer-facing: the
|
|
116
|
+
scripts directory is not published in the package.
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- **The packed-consumer pack-policy test accepts npm 12's output shape.**
|
|
121
|
+
|
|
122
|
+
- **Model-id normalizer**: new rungs for `claude-fable-5-1`,
|
|
123
|
+
`claude-mythos-5-1`, `claude-opus-5-5`, `claude-opus-5` and
|
|
124
|
+
`claude-sonnet-5`. `claude-fable-5-1` and `claude-mythos-5-1` previously
|
|
125
|
+
collapsed onto their base ids, which silently suppressed the per-turn-control
|
|
126
|
+
push site for `claude-fable-5-1`. Both now normalise to their own ids, so
|
|
127
|
+
`isFable5Model("claude-fable-5-1")` now answers `false` for every caller,
|
|
128
|
+
pinned or not.
|
|
129
|
+
|
|
130
|
+
Compatibility: the `claude-opus-5` and `claude-sonnet-5` rungs also change
|
|
131
|
+
how decorated forms of those ids, already catalogued in the previous pin
|
|
132
|
+
since 2.1.233, resolve — a decorated form being a `-latest` suffix, a vendor
|
|
133
|
+
prefix or an unlisted minor version. Bare ids and date-suffixed ids are
|
|
134
|
+
unaffected. The wire `model` field is never affected, because the wire id
|
|
135
|
+
comes from the marker-stripping helper, not from the normalizer. Because the
|
|
136
|
+
ladder is shared by every profile, the new rungs also reach the previous pin:
|
|
137
|
+
under `CLAUDE_CODE_2_1_233_PROFILE`, `claude-mythos-5-1` previously collapsed
|
|
138
|
+
onto `claude-mythos-5` and now keeps its own id, which adds three beta
|
|
139
|
+
identifiers to the header (`context-management-2025-06-27`,
|
|
140
|
+
`mid-conversation-system-2026-04-07` and `effort-2025-11-24`) and changes the
|
|
141
|
+
emitted thinking object from a budgeted one to an adaptive one. The ids
|
|
142
|
+
concerned are not in that pin's own model catalogue, so this affects only a
|
|
143
|
+
caller naming a model that release never shipped.
|
|
144
|
+
|
|
145
|
+
- **The extended-thinking budget follows the transcribed upstream
|
|
146
|
+
computation.** When the emitted `thinking` block is `enabled`,
|
|
147
|
+
`budget_tokens` now has a floor of 1024, applied after the clamp to
|
|
148
|
+
`max_tokens` minus one, so the floor wins when the two conflict; a small
|
|
149
|
+
`max_tokens` previously produced a budget of zero or a negative number that
|
|
150
|
+
no client sends. The caller's `budgetTokens` is now honoured only when the
|
|
151
|
+
caller itself declared an `enabled` request: an `adaptive` request downgraded
|
|
152
|
+
to `enabled` on a model without adaptive thinking now uses the default budget
|
|
153
|
+
(the model's upper limit minus one, then clamped and floored) instead of its
|
|
154
|
+
own.
|
|
155
|
+
|
|
156
|
+
Compatibility: only the 2.1.280 analysis transcribes this computation, so the
|
|
157
|
+
floor and the guard are evidenced for the newest pin only. They are applied
|
|
158
|
+
to every profile as one shared behaviour rather than gated, because gating
|
|
159
|
+
would assert that older clients lacked them. Under every pin, `budget_tokens`
|
|
160
|
+
therefore changes for an `enabled` block whose clamped budget was below 1024,
|
|
161
|
+
including a caller `budgetTokens` below 1024, and for a downgraded `adaptive`
|
|
162
|
+
request that carried a budget. No sealed fixture or frozen digest moved.
|
|
163
|
+
|
|
164
|
+
- **`isAdaptiveThinkingModel` covers every catalogue-adaptive id.** It was a
|
|
165
|
+
union of six named predicates and answered `false` for `claude-opus-5`,
|
|
166
|
+
`claude-opus-5-5` and `claude-sonnet-5`, while the builder emitted an
|
|
167
|
+
adaptive `thinking` block for the same model. The omission predates this
|
|
168
|
+
release: two of those ids are catalogued adaptive in the 2.1.233 pin as
|
|
169
|
+
well. The union now covers every id any pinned profile's catalogue marks
|
|
170
|
+
`adaptive_thinking`. No new symbol is exported from the entry point.
|
|
171
|
+
|
|
172
|
+
## [0.5.0] - 2026-08-16
|
|
173
|
+
|
|
174
|
+
### Added
|
|
175
|
+
|
|
176
|
+
- **Model-query surface**, fourteen exports from the package entry point:
|
|
177
|
+
the generic `modelCapability(model, capability, profile)`, which reads the
|
|
178
|
+
verbatim upstream capability string off the active catalogue, plus the named
|
|
179
|
+
identity predicates `isOpus46Model`, `isOpus47Model`, `isOpus48Model`,
|
|
180
|
+
`isSonnet46Model`, `isFable5Model`, `isMythos5Model`, `isHaikuModel`,
|
|
181
|
+
`isClaude3Model`, `isAdaptiveThinkingModel`, `hasOneMillionContext`,
|
|
182
|
+
`isEligibleFor1MContext`, `supportsStructuredOutputs` and
|
|
183
|
+
`supportsWebSearch`.
|
|
184
|
+
|
|
185
|
+
The predicates are written over the existing `normalizeModelId` /
|
|
186
|
+
`modelFamilyOf` pair rather than over new family regexes, so a model id
|
|
187
|
+
classifies the same way here as it does everywhere else in the package. They
|
|
188
|
+
answer `false` for an empty or non-string id instead of throwing.
|
|
189
|
+
|
|
190
|
+
Motivation: consumers were re-deriving model identity from ad hoc substring
|
|
191
|
+
matches, which drifts from the catalogue the package already carries.
|
|
192
|
+
|
|
193
|
+
- **`normalizeModelId` accepts dotted model version ids.** A digit-dot-digit
|
|
194
|
+
run is rewritten to the hyphenated wire form before the upstream branch
|
|
195
|
+
ladder, so `claude-opus-4.7` classifies identically to `claude-opus-4-7`.
|
|
196
|
+
|
|
197
|
+
Compatibility: ids without a dotted version (`gpt-4o`, the empty string,
|
|
198
|
+
`vendor.example/model-x`) normalise byte-identically to before.
|
|
199
|
+
|
|
200
|
+
- **Beta registries are public**: `BETA_REGISTRY` (28 entries),
|
|
201
|
+
`BETA_REGISTRY_2_1_233` (31 entries) and `TOKEN_COUNTING_BETA`. They are
|
|
202
|
+
protocol constants transcribed from the genuine client, so a consumer that
|
|
203
|
+
reads a beta header off the registry cannot drift from the package that
|
|
204
|
+
emits it. Reading a header is not emitting one — composition, gating and
|
|
205
|
+
push order stay inside the package, and the policy sets
|
|
206
|
+
(`THIRD_PARTY_ALLOWED_BETAS`, `BEDROCK_UNSUPPORTED_BETAS`,
|
|
207
|
+
`COUNT_TOKENS_BETAS`) remain private.
|
|
208
|
+
|
|
209
|
+
### Documentation
|
|
210
|
+
|
|
211
|
+
- **Endpoint URL contract** (README, "Endpoint URL and custom base URLs"):
|
|
212
|
+
`built.url` is the profile's pinned, literal-typed endpoint. A host with a
|
|
213
|
+
custom base substitutes protocol, hostname and port while preserving the
|
|
214
|
+
package's `pathname` and `search`. The input deliberately gains no `baseUrl`
|
|
215
|
+
field — widening the literal `url` type is a breaking change for consumers
|
|
216
|
+
that pin the endpoint, the field would duplicate what `URL` already does,
|
|
217
|
+
and the only observed consumer case is an origin override.
|
|
218
|
+
|
|
219
|
+
No breaking changes: every surface above is additive, and the golden fixtures
|
|
220
|
+
re-seal to the same bytes.
|
|
221
|
+
|
|
5
222
|
## [0.4.0] - 2026-08-16
|
|
6
223
|
|
|
7
224
|
### Added
|
package/README.md
CHANGED
|
@@ -16,20 +16,58 @@ The package targets Node.js 20 or newer and is designed to remain portable to Bu
|
|
|
16
16
|
|
|
17
17
|
## Protocol profile
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
The pinned profiles are exported:
|
|
20
20
|
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
21
|
+
- `CLAUDE_CODE_2_1_280_PROFILE` — Claude Code 2.1.280 with SDK 0.112.1. This is the profile the request-building entry points use when `profile` is omitted.
|
|
22
|
+
- `CLAUDE_CODE_2_1_233_PROFILE` — the previous pin, Claude Code 2.1.233 with SDK 0.112.1.
|
|
23
|
+
- `CLAUDE_CODE_2_1_195_PROFILE` — the oldest pin, Claude Code 2.1.195 with SDK 0.94.0.
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
The model-query helpers (`modelCapability`, `isEligibleFor1MContext`) and the anti-verbosity helpers (`antiVerbosityText`, `selectAntiVerbositySection`) keep their own separately declared default and are not governed by that seam; a caller relying on them for a newer model must pass the profile explicitly.
|
|
26
|
+
|
|
27
|
+
Any of them can be selected explicitly by passing the singleton as the `profile` argument, from the package root or from its own subpath export:
|
|
25
28
|
|
|
26
29
|
```ts
|
|
27
30
|
import { CLAUDE_CODE_2_1_195_PROFILE } from "@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.195";
|
|
28
31
|
import { CLAUDE_CODE_2_1_233_PROFILE } from "@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.233";
|
|
32
|
+
import { CLAUDE_CODE_2_1_280_PROFILE } from "@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.280";
|
|
29
33
|
```
|
|
30
34
|
|
|
35
|
+
Rollback: a consumer who wants the previous default's bytes must pass `CLAUDE_CODE_2_1_233_PROFILE` explicitly on every call to each entry point that reads the default seam — `buildClaudeCodeRequest`, `buildClaudeCodeCountTokensRequest`, and `parseBuiltClaudeCodeRequest`. Pinning the builders alone is not enough: `parseBuiltClaudeCodeRequest` recomputes the expected headers under the profile it is given, so a request built under the old default and parsed unpinned after upgrading is rejected with `ClaudeCodeWireError` code `INVALID_INPUT`.
|
|
36
|
+
|
|
31
37
|
The fail-closed rule is unchanged: only these exported singletons are accepted. Any other object, even a structurally identical clone, is rejected with `ClaudeCodeWireError` code `INVALID_INPUT`. This prevents callers from substituting an unpinned protocol profile.
|
|
32
38
|
|
|
39
|
+
## Endpoint URL and custom base URLs
|
|
40
|
+
|
|
41
|
+
`built.url` is the **pinned endpoint of the profile**, not a suggestion. It is literal-typed, so the type is part of the contract:
|
|
42
|
+
|
|
43
|
+
- `buildClaudeCodeRequest` → `"https://api.anthropic.com/v1/messages?beta=true"`
|
|
44
|
+
- `buildClaudeCodeCountTokensRequest` → `"https://api.anthropic.com/v1/messages/count_tokens?beta=true"`
|
|
45
|
+
|
|
46
|
+
A host that talks to a proxy, a gateway, or a regional endpoint **overrides the origin and nothing else**: replace protocol, hostname and port; keep the package's `pathname` and `search` verbatim. The `?beta=true` query and the `/v1/messages` path are wire contract — dropping either changes what the server does, and the golden fixtures no longer describe the request that was sent.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const built = await buildClaudeCodeRequest(input);
|
|
50
|
+
|
|
51
|
+
// Origin override. `pathname` and `search` come from the package, untouched.
|
|
52
|
+
const target = new URL(built.url);
|
|
53
|
+
const base = new URL(hostBaseUrl); // whatever the host resolved, e.g. from its own config
|
|
54
|
+
target.protocol = base.protocol;
|
|
55
|
+
target.hostname = base.hostname;
|
|
56
|
+
target.port = base.port;
|
|
57
|
+
|
|
58
|
+
await fetch(target, {
|
|
59
|
+
method: built.method,
|
|
60
|
+
headers: built.headers,
|
|
61
|
+
body: built.body,
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**The input will not gain a `baseUrl` field.** Three reasons, recorded so the request does not come back:
|
|
66
|
+
|
|
67
|
+
1. `BuiltClaudeCodeRequest["url"]` is a string literal type. Widening it to `string` to accommodate an arbitrary base is a breaking change at the type level for every consumer that pins the endpoint.
|
|
68
|
+
2. Speculative surface is not added to this package. A host that has a base URL already has a URL library; a package field would be a second way to do the same thing, with a validation and normalisation burden this package would then own.
|
|
69
|
+
3. The only real consumer case observed is an origin override, which the four lines above express exactly — including the case where the base URL carries a path prefix, which a naive `baseUrl + pathname` concatenation gets wrong.
|
|
70
|
+
|
|
33
71
|
## Protocol documentation
|
|
34
72
|
|
|
35
73
|
The wire contract this package pins was reverse engineered before it was
|
|
@@ -58,8 +96,10 @@ Protocol knowledge corpus:
|
|
|
58
96
|
tool_result pairing in practice.
|
|
59
97
|
- [Code comparison reference](./docs/protocol/code-comparison-reference.md) —
|
|
60
98
|
side-by-side comparison against the genuine client.
|
|
61
|
-
- [Divergence analysis](./docs/protocol/divergence-analysis.md) —
|
|
62
|
-
|
|
99
|
+
- [Divergence analysis](./docs/protocol/divergence-analysis.md) — ported
|
|
100
|
+
analysis of system-prompt block construction, genuine client versus the
|
|
101
|
+
earlier plugin. Package-level divergences are recorded in each version
|
|
102
|
+
analysis's port table and in `MEMORY.md`.
|
|
63
103
|
- [Divergence executive summary](./docs/protocol/divergence-executive-summary.md)
|
|
64
104
|
— the condensed version of that analysis.
|
|
65
105
|
- [Quick reference](./docs/protocol/quick-reference.md) — condensed lookup of
|
|
@@ -81,7 +121,11 @@ required](./docs/protocol/versions/README.md):
|
|
|
81
121
|
- [Claude Code 2.1.159](./docs/protocol/versions/claude-code-2.1.159-analysis.md)
|
|
82
122
|
- [Claude Code 2.1.195](./docs/protocol/versions/claude-code-2.1.195-analysis.md)
|
|
83
123
|
- [Claude Code 2.1.233](./docs/protocol/versions/claude-code-2.1.233-analysis.md)
|
|
84
|
-
— the
|
|
124
|
+
— the previous pin; its profile is still exported and selectable.
|
|
125
|
+
- [Claude Code 2.1.280](./docs/protocol/versions/claude-code-2.1.280-analysis.md)
|
|
126
|
+
— the release this package's default profile pins; records the build-shape
|
|
127
|
+
change that breaks the old carving rule, nine new betas, three new models,
|
|
128
|
+
and the first wire-visible `thinking` sub-fields since 2.1.222.
|
|
85
129
|
|
|
86
130
|
## Development
|
|
87
131
|
|
package/dist/betas.d.ts
CHANGED
|
@@ -8,13 +8,22 @@ interface BetaRegistryEntry {
|
|
|
8
8
|
* The entries the push sites below require, as a structural contract rather
|
|
9
9
|
* than a reference to one concrete registry.
|
|
10
10
|
*
|
|
11
|
-
* Registry versions have different key sets. Every key here
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* optionality part of the TYPE is what forces every future registry
|
|
17
|
-
* checked against the push sites at compile time instead of at runtime.
|
|
11
|
+
* Registry versions have different key sets. Every REQUIRED key here is present
|
|
12
|
+
* in all of them, so those push sites index directly. The optional ones are
|
|
13
|
+
* optional because they exist in some registry versions and not others, and a
|
|
14
|
+
* push site whose key is absent becomes inert: it evaluates its gates, finds no
|
|
15
|
+
* entry, pushes nothing, and the surrounding order closes up with no gap.
|
|
16
|
+
* Making the optionality part of the TYPE is what forces every future registry
|
|
17
|
+
* to be checked against the push sites at compile time instead of at runtime.
|
|
18
|
+
*
|
|
19
|
+
* `NARRATION_SUMMARIES` is optional in the older direction -- upstream removed
|
|
20
|
+
* it after 2.1.195 (see `src/profiles/beta-registry-2.1.233.ts`). The keys
|
|
21
|
+
* added for 2.1.280 -- the remaining optional members declared below -- are
|
|
22
|
+
* optional in the newer direction: they are absent from the 2.1.195 registry,
|
|
23
|
+
* and all but `PER_MESSAGE_EFFORT` are absent from the 2.1.233 one. `PER_MESSAGE_EFFORT` IS declared by the 2.1.233 registry, so
|
|
24
|
+
* registry absence does not keep its site inert there; what does is the
|
|
25
|
+
* catalogue, because no 2.1.233 model declares the backing capability. The two
|
|
26
|
+
* mechanisms are not interchangeable and both are load-bearing.
|
|
18
27
|
*/
|
|
19
28
|
export interface ComposableBetaRegistry {
|
|
20
29
|
readonly CLAUDE_CODE: BetaRegistryEntry;
|
|
@@ -27,7 +36,12 @@ export interface ComposableBetaRegistry {
|
|
|
27
36
|
readonly STRUCTURED_OUTPUTS: BetaRegistryEntry;
|
|
28
37
|
readonly PROMPT_CACHING_SCOPE: BetaRegistryEntry;
|
|
29
38
|
readonly MID_CONVERSATION_SYSTEM: BetaRegistryEntry;
|
|
39
|
+
readonly PER_MESSAGE_EFFORT?: BetaRegistryEntry;
|
|
40
|
+
readonly MID_CONV_TOOL_CHANGE?: BetaRegistryEntry;
|
|
41
|
+
readonly MID_CONVERSATION_SYSTEM_CLEAR_AT?: BetaRegistryEntry;
|
|
30
42
|
readonly EFFORT: BetaRegistryEntry;
|
|
43
|
+
readonly THINKING_BINDING_CONTROLS?: BetaRegistryEntry;
|
|
44
|
+
readonly THINKING_DISPLAY_UPDATES?: BetaRegistryEntry;
|
|
31
45
|
readonly SPEED: BetaRegistryEntry;
|
|
32
46
|
readonly AFK_MODE: BetaRegistryEntry;
|
|
33
47
|
readonly EXTENDED_CACHE_TTL: BetaRegistryEntry;
|
|
@@ -35,11 +49,42 @@ export interface ComposableBetaRegistry {
|
|
|
35
49
|
readonly CACHE_DIAGNOSIS: BetaRegistryEntry;
|
|
36
50
|
readonly NARRATION_SUMMARIES?: BetaRegistryEntry;
|
|
37
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Selects the registry a profile composes against.
|
|
54
|
+
*
|
|
55
|
+
* An unrecognised id falls back to the 2.1.195 registry rather than throwing.
|
|
56
|
+
* Rejecting unknown profiles is the request builder's job -- it validates the
|
|
57
|
+
* profile before any of this runs -- and duplicating that rejection here would
|
|
58
|
+
* give `composeBetas` a second, differently-worded opinion about profile
|
|
59
|
+
* validity. Standalone callers keep the 2.1.195 behaviour they had before
|
|
60
|
+
* profiles were a parameter.
|
|
61
|
+
*
|
|
62
|
+
* Exported for tests only, and deliberately NOT re-exported from
|
|
63
|
+
* `src/index.ts`: the public runtime surface stays closed. That fallback is
|
|
64
|
+
* precisely why a test needs to reach this function. A profile bound to the
|
|
65
|
+
* wrong registry, or to none, silently composes against 2.1.195 instead of
|
|
66
|
+
* failing, and every required key of `ComposableBetaRegistry` currently
|
|
67
|
+
* carries an identical header in all three registries -- so a mis-binding
|
|
68
|
+
* changes no emitted byte and no behavioural suite can see it. Asking this
|
|
69
|
+
* function directly is the only way to observe the binding at all.
|
|
70
|
+
*/
|
|
71
|
+
export declare function resolveBetaRegistry(profile: ClaudeCodeProtocolProfile): ComposableBetaRegistry;
|
|
38
72
|
export interface ComposeBetasInput {
|
|
39
73
|
readonly rawModel: string;
|
|
40
74
|
readonly normalizedId: string;
|
|
41
75
|
readonly capabilities: ClaudeCodeCapabilities;
|
|
42
76
|
readonly thinkingDisplayActive: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Whether a `thinking` object of type `adaptive` or `enabled` will reach the
|
|
79
|
+
* wire for this request AND the model is interleaved-thinking capable, i.e.
|
|
80
|
+
* upstream `ac` minus its `Fg()` term. Compute it with `isThinkingActive`
|
|
81
|
+
* from `./thinking.js`; never re-derive it at a call site.
|
|
82
|
+
*
|
|
83
|
+
* Required rather than optional: it is a total function of inputs every call
|
|
84
|
+
* site already holds, and requiring it is what forces a new call site to
|
|
85
|
+
* decide rather than silently inherit a default.
|
|
86
|
+
*/
|
|
87
|
+
readonly thinkingActive: boolean;
|
|
43
88
|
readonly cacheTtl?: "5m" | "1h" | null;
|
|
44
89
|
readonly speed?: "standard" | "fast" | null;
|
|
45
90
|
/**
|
|
@@ -72,6 +117,19 @@ export interface ComposeBetasInput {
|
|
|
72
117
|
export interface ComposedBetas {
|
|
73
118
|
readonly betas: readonly string[];
|
|
74
119
|
readonly suppressedBetaNames: readonly string[];
|
|
120
|
+
/**
|
|
121
|
+
* Present only when push site 12b fired. This is the body-side half of a
|
|
122
|
+
* beta/body pair: the site pushes the display-updates beta AND decides that
|
|
123
|
+
* the body's `thinking` object carries `display: "updates"`. The consumer is
|
|
124
|
+
* the canonical body builder (`buildCanonicalBody`), which hands it to
|
|
125
|
+
* `resolveThinking`.
|
|
126
|
+
*
|
|
127
|
+
* `suppressBetas` cannot unset it. Suppressing the beta identifier removes
|
|
128
|
+
* the HEADER only; the body keeps `display: "updates"`. That matches the
|
|
129
|
+
* existing coupled pair where suppressing `effort-2025-11-24` leaves
|
|
130
|
+
* `output_config.effort` in the body.
|
|
131
|
+
*/
|
|
132
|
+
readonly thinkingDisplayOverride?: "updates";
|
|
75
133
|
}
|
|
76
134
|
export declare function composeBetas(input: ComposeBetasInput, profile?: ClaudeCodeProtocolProfile): readonly string[];
|
|
77
135
|
export declare function composeBetasWithAudit(input: ComposeBetasInput, profile?: ClaudeCodeProtocolProfile): ComposedBetas;
|
package/dist/betas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"betas.d.ts","sourceRoot":"","sources":["../src/betas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"betas.d.ts","sourceRoot":"","sources":["../src/betas.ts"],"names":[],"mappings":"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"}
|
package/dist/betas.js
CHANGED
|
@@ -3,11 +3,14 @@ import { BETA_REGISTRY } from "./beta-registry.js";
|
|
|
3
3
|
import { ClaudeCodeWireError } from "./contracts.js";
|
|
4
4
|
import { supportsMidConversationSystem, supportsStructuredOutputs, } from "./model-capabilities.js";
|
|
5
5
|
import { BETA_REGISTRY_2_1_233 } from "./profiles/beta-registry-2.1.233.js";
|
|
6
|
+
import { BETA_REGISTRY_2_1_280 } from "./profiles/beta-registry-2.1.280.js";
|
|
6
7
|
import { CLAUDE_CODE_2_1_195_PROFILE } from "./profiles/claude-code-2.1.195.js";
|
|
7
8
|
import { CLAUDE_CODE_2_1_233_PROFILE } from "./profiles/claude-code-2.1.233.js";
|
|
9
|
+
import { CLAUDE_CODE_2_1_280_PROFILE } from "./profiles/claude-code-2.1.280.js";
|
|
8
10
|
const PROFILE_BETA_REGISTRIES = new Map([
|
|
9
11
|
[CLAUDE_CODE_2_1_195_PROFILE.id, BETA_REGISTRY],
|
|
10
12
|
[CLAUDE_CODE_2_1_233_PROFILE.id, BETA_REGISTRY_2_1_233],
|
|
13
|
+
[CLAUDE_CODE_2_1_280_PROFILE.id, BETA_REGISTRY_2_1_280],
|
|
11
14
|
]);
|
|
12
15
|
/**
|
|
13
16
|
* Selects the registry a profile composes against.
|
|
@@ -18,8 +21,17 @@ const PROFILE_BETA_REGISTRIES = new Map([
|
|
|
18
21
|
* give `composeBetas` a second, differently-worded opinion about profile
|
|
19
22
|
* validity. Standalone callers keep the 2.1.195 behaviour they had before
|
|
20
23
|
* profiles were a parameter.
|
|
24
|
+
*
|
|
25
|
+
* Exported for tests only, and deliberately NOT re-exported from
|
|
26
|
+
* `src/index.ts`: the public runtime surface stays closed. That fallback is
|
|
27
|
+
* precisely why a test needs to reach this function. A profile bound to the
|
|
28
|
+
* wrong registry, or to none, silently composes against 2.1.195 instead of
|
|
29
|
+
* failing, and every required key of `ComposableBetaRegistry` currently
|
|
30
|
+
* carries an identical header in all three registries -- so a mis-binding
|
|
31
|
+
* changes no emitted byte and no behavioural suite can see it. Asking this
|
|
32
|
+
* function directly is the only way to observe the binding at all.
|
|
21
33
|
*/
|
|
22
|
-
function resolveBetaRegistry(profile) {
|
|
34
|
+
export function resolveBetaRegistry(profile) {
|
|
23
35
|
return PROFILE_BETA_REGISTRIES.get(profile.id) ?? BETA_REGISTRY;
|
|
24
36
|
}
|
|
25
37
|
/**
|
|
@@ -108,10 +120,131 @@ export function composeBetasWithAudit(input, profile = CLAUDE_CODE_2_1_195_PROFI
|
|
|
108
120
|
// No web-search beta: upstream pushes it only for vertex and foundry.
|
|
109
121
|
if (experimental)
|
|
110
122
|
out.push(registry.PROMPT_CACHING_SCOPE.header);
|
|
111
|
-
|
|
123
|
+
/*
|
|
124
|
+
* Upstream `jR`. The local boolean below records that this site PUSHED, which
|
|
125
|
+
* is what sites 11b and 11c gate on -- upstream reads `Ee.includes(jR)`, the
|
|
126
|
+
* composed array, not the registry. Asking the registry instead would fire
|
|
127
|
+
* those two sites for a model this one skipped.
|
|
128
|
+
*/
|
|
129
|
+
const midConversationSystemFired = supportsMidConversationSystem(input.normalizedId, profile);
|
|
130
|
+
if (midConversationSystemFired) {
|
|
112
131
|
out.push(registry.MID_CONVERSATION_SYSTEM.header);
|
|
132
|
+
}
|
|
133
|
+
/*
|
|
134
|
+
* Site 11a. Upstream `wRt`, which reduces to
|
|
135
|
+
* `Fg() && mD(provider) && catalogue-declares-per_turn_effort`; the provider
|
|
136
|
+
* term is first-party here by construction.
|
|
137
|
+
*/
|
|
138
|
+
const perMessageEffort = registry.PER_MESSAGE_EFFORT;
|
|
139
|
+
if (experimental &&
|
|
140
|
+
input.capabilities.perTurnEffort &&
|
|
141
|
+
perMessageEffort !== undefined) {
|
|
142
|
+
out.push(perMessageEffort.header);
|
|
143
|
+
}
|
|
144
|
+
/*
|
|
145
|
+
* Site 11b. Upstream `oQt() && Tue(model)`. `Tue` opens with
|
|
146
|
+
* `if (!Fg() || !kue(e)) return false`, so the experimental gate is upstream's
|
|
147
|
+
* and not an addition. Step 3 of `Tue` -- which sends the beta for any model
|
|
148
|
+
* with NO catalogue entry -- is deliberately not ported; see the analysis
|
|
149
|
+
* document's divergence record.
|
|
150
|
+
*/
|
|
151
|
+
const midConvToolChange = registry.MID_CONV_TOOL_CHANGE;
|
|
152
|
+
if (experimental &&
|
|
153
|
+
midConversationSystemFired &&
|
|
154
|
+
input.capabilities.midConvToolChange &&
|
|
155
|
+
midConvToolChange !== undefined) {
|
|
156
|
+
out.push(midConvToolChange.header);
|
|
157
|
+
}
|
|
158
|
+
/*
|
|
159
|
+
* Site 11c. Upstream `Mo`, which is the one site whose experimental gate is
|
|
160
|
+
* invisible at the statement level -- `Mo` names no `Fg()` at all. The gate is
|
|
161
|
+
* reached three calls deep instead: `Mee` is `oRt(model) !== "off"`, `oRt`
|
|
162
|
+
* wraps `fur`, and `fur` opens by returning `"off"` when `Fg()` is false. So
|
|
163
|
+
* `experimental` is upstream's own conjunct here exactly as it is at 11a and
|
|
164
|
+
* 11b, and a reader who checks only the `Mo` expression will wrongly conclude
|
|
165
|
+
* it was invented. It was not.
|
|
166
|
+
*
|
|
167
|
+
* `Mo`'s remaining conjuncts are constants for this package. `!l7(querySource)`
|
|
168
|
+
* holds because `l7` is true only for the two auto-mode query sources. `!Vr`
|
|
169
|
+
* holds because `Vr` is a per-session latch, and a stateless package composes
|
|
170
|
+
* every request as a first request. `Mee`'s other terms are fixed on the
|
|
171
|
+
* first-party path. What is left is `Ee.includes(jR)`, which is precisely the
|
|
172
|
+
* `midConversationSystemFired` outcome recorded at site 11.
|
|
173
|
+
*/
|
|
174
|
+
const midConversationSystemClearAt = registry.MID_CONVERSATION_SYSTEM_CLEAR_AT;
|
|
175
|
+
if (experimental &&
|
|
176
|
+
midConversationSystemFired &&
|
|
177
|
+
midConversationSystemClearAt !== undefined) {
|
|
178
|
+
out.push(midConversationSystemClearAt.header);
|
|
179
|
+
}
|
|
180
|
+
// Site 12.
|
|
113
181
|
if (input.capabilities.effort)
|
|
114
182
|
out.push(registry.EFFORT.header);
|
|
183
|
+
/*
|
|
184
|
+
* Site 12a. Upstream `er && Fg()` with the latch write, which on the pinned
|
|
185
|
+
* first-party path collapses to thinking-active AND experimental.
|
|
186
|
+
* The coupled body field `thinking.block_binding` is NOT emitted: it needs a
|
|
187
|
+
* host override this package cannot observe.
|
|
188
|
+
*/
|
|
189
|
+
const thinkingBindingControls = registry.THINKING_BINDING_CONTROLS;
|
|
190
|
+
if (experimental &&
|
|
191
|
+
input.thinkingActive &&
|
|
192
|
+
thinkingBindingControls !== undefined) {
|
|
193
|
+
out.push(thinkingBindingControls.header);
|
|
194
|
+
}
|
|
195
|
+
/*
|
|
196
|
+
* Site 12b. Upstream guards the push with
|
|
197
|
+
* `(yc?.type === "adaptive" || yc?.type === "enabled") && ac && firstParty
|
|
198
|
+
* && !callerSuppliedDisplay && ...` plus the simulate-proxy environment
|
|
199
|
+
* variable and a per-session latch. The reachable remainder of that guard is
|
|
200
|
+
* modelled below: `experimental` is upstream's `Fg()` term inside `ac`,
|
|
201
|
+
* `input.thinkingActive` is the thinking-type test together with the rest of
|
|
202
|
+
* `ac`, and `!input.thinkingDisplayActive` is the caller-supplied-display
|
|
203
|
+
* test. First-party is not modelled because this package only builds the
|
|
204
|
+
* first-party path, the simulate-proxy env var is not modelled because the
|
|
205
|
+
* package reads no environment, and the per-session latch is always empty in
|
|
206
|
+
* a stateless package that composes every request as a first request.
|
|
207
|
+
*
|
|
208
|
+
* The branch is additionally reached only when the display-mode resolver
|
|
209
|
+
* `Gxt` returns its connector-text result; its other results break out
|
|
210
|
+
* before the push. `!policy.thinkingSummariesShown` is that resolver's
|
|
211
|
+
* `sQt()` term, mapped onto the profile flag exactly as at the
|
|
212
|
+
* redact-thinking site above. See the 2.1.280 analysis document, §6.4, for
|
|
213
|
+
* the resolver itself.
|
|
214
|
+
*
|
|
215
|
+
* The resolver's other two diverting branches are already covered by
|
|
216
|
+
* `!thinkingDisplayActive`. A caller display of `"summarized"` takes the
|
|
217
|
+
* first branch, and `"omitted"` takes the second whenever the
|
|
218
|
+
* explicit-display flag is falsy, which is the only state this package can
|
|
219
|
+
* express -- it models no equivalent of that flag. Under a truthy
|
|
220
|
+
* explicit-display flag upstream would fall through and overwrite an
|
|
221
|
+
* explicit `"omitted"` with `"updates"`; that input is unreachable here, and
|
|
222
|
+
* is recorded rather than modelled.
|
|
223
|
+
*
|
|
224
|
+
* The site is coupled: it pushes the beta, records `display: "updates"` for
|
|
225
|
+
* the body builder, and removes the previously composed redact-thinking beta
|
|
226
|
+
* (upstream `qu()`).
|
|
227
|
+
*
|
|
228
|
+
* The splice sits INSIDE this block and is deliberately the LAST thing it
|
|
229
|
+
* does. At this point `out` holds only canonical pushes, because the caller
|
|
230
|
+
* `additionalBetas` merge runs later. So a caller who explicitly supplies
|
|
231
|
+
* `redact-thinking-2026-02-12` in `additionalBetas` still gets it, precisely
|
|
232
|
+
* because the merge's `if (!out.includes(beta))` test now succeeds. Moving
|
|
233
|
+
* the splice after the merge would silently eat that caller's entry.
|
|
234
|
+
*/
|
|
235
|
+
const thinkingDisplayUpdates = registry.THINKING_DISPLAY_UPDATES;
|
|
236
|
+
let thinkingDisplayOverride;
|
|
237
|
+
if (experimental &&
|
|
238
|
+
input.thinkingActive &&
|
|
239
|
+
!policy.thinkingSummariesShown &&
|
|
240
|
+
!input.thinkingDisplayActive &&
|
|
241
|
+
thinkingDisplayUpdates !== undefined) {
|
|
242
|
+
out.push(thinkingDisplayUpdates.header);
|
|
243
|
+
thinkingDisplayOverride = "updates";
|
|
244
|
+
const redactIndex = out.indexOf(registry.REDACT_THINKING.header);
|
|
245
|
+
if (redactIndex !== -1)
|
|
246
|
+
out.splice(redactIndex, 1);
|
|
247
|
+
}
|
|
115
248
|
if (input.speed === "fast" && !out.includes(registry.SPEED.header)) {
|
|
116
249
|
out.push(registry.SPEED.header);
|
|
117
250
|
}
|
|
@@ -149,6 +282,9 @@ export function composeBetasWithAudit(input, profile = CLAUDE_CODE_2_1_195_PROFI
|
|
|
149
282
|
return Object.freeze({
|
|
150
283
|
betas: Object.freeze(out),
|
|
151
284
|
suppressedBetaNames: NO_SUPPRESSED_BETAS,
|
|
285
|
+
...(thinkingDisplayOverride === undefined
|
|
286
|
+
? {}
|
|
287
|
+
: { thinkingDisplayOverride }),
|
|
152
288
|
});
|
|
153
289
|
}
|
|
154
290
|
const suppressed = new Set(validateAdditionalBetas(input.suppressBetas));
|
|
@@ -163,6 +299,11 @@ export function composeBetasWithAudit(input, profile = CLAUDE_CODE_2_1_195_PROFI
|
|
|
163
299
|
return Object.freeze({
|
|
164
300
|
betas: Object.freeze(kept),
|
|
165
301
|
suppressedBetaNames: Object.freeze(removed),
|
|
302
|
+
// The suppression filter above touches only the header list; the body
|
|
303
|
+
// half of the site-12b pair survives it by design.
|
|
304
|
+
...(thinkingDisplayOverride === undefined
|
|
305
|
+
? {}
|
|
306
|
+
: { thinkingDisplayOverride }),
|
|
166
307
|
});
|
|
167
308
|
}
|
|
168
309
|
//# sourceMappingURL=betas.js.map
|
package/dist/betas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"betas.js","sourceRoot":"","sources":["../src/betas.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"betas.js","sourceRoot":"","sources":["../src/betas.ts"],"names":[],"mappings":"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"}
|