@tormentalabs/claude-code-wire-compat 0.1.0 → 0.2.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 +65 -0
- package/README.md +14 -1
- package/dist/betas.d.ts +37 -0
- package/dist/betas.d.ts.map +1 -1
- package/dist/betas.js +55 -23
- package/dist/betas.js.map +1 -1
- package/dist/build-request.d.ts +11 -0
- package/dist/build-request.d.ts.map +1 -1
- package/dist/build-request.js +133 -11
- package/dist/build-request.js.map +1 -1
- package/dist/contracts.d.ts +53 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/fingerprint.d.ts +29 -2
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +60 -7
- package/dist/fingerprint.js.map +1 -1
- package/dist/headers.d.ts.map +1 -1
- package/dist/headers.js +12 -4
- package/dist/headers.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/model-capabilities.d.ts +31 -3
- package/dist/model-capabilities.d.ts.map +1 -1
- package/dist/model-capabilities.js +145 -12
- package/dist/model-capabilities.js.map +1 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +8 -4
- package/dist/models.js.map +1 -1
- package/dist/profile-behaviors.d.ts +61 -0
- package/dist/profile-behaviors.d.ts.map +1 -0
- package/dist/profile-behaviors.js +53 -0
- package/dist/profile-behaviors.js.map +1 -0
- package/dist/profiles/beta-registry-2.1.233.d.ts +140 -0
- package/dist/profiles/beta-registry-2.1.233.d.ts.map +1 -0
- package/dist/profiles/beta-registry-2.1.233.js +183 -0
- package/dist/profiles/beta-registry-2.1.233.js.map +1 -0
- package/dist/profiles/claude-code-2.1.195.d.ts.map +1 -1
- package/dist/profiles/claude-code-2.1.195.js +14 -0
- package/dist/profiles/claude-code-2.1.195.js.map +1 -1
- package/dist/profiles/claude-code-2.1.233.d.ts +3 -0
- package/dist/profiles/claude-code-2.1.233.d.ts.map +1 -0
- package/dist/profiles/claude-code-2.1.233.js +235 -0
- package/dist/profiles/claude-code-2.1.233.js.map +1 -0
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +14 -1
- package/dist/redaction.js.map +1 -1
- package/dist/request-body.d.ts.map +1 -1
- package/dist/request-body.js +12 -10
- package/dist/request-body.js.map +1 -1
- package/dist/thinking.d.ts +33 -7
- package/dist/thinking.d.ts.map +1 -1
- package/dist/thinking.js +105 -36
- package/dist/thinking.js.map +1 -1
- package/package.json +9 -2
- package/src/betas.ts +106 -23
- package/src/build-request.ts +155 -11
- package/src/contracts.ts +53 -0
- package/src/fingerprint.ts +78 -8
- package/src/headers.ts +10 -4
- package/src/index.ts +1 -0
- package/src/model-capabilities.ts +171 -13
- package/src/models.ts +8 -4
- package/src/profile-behaviors.ts +114 -0
- package/src/profiles/beta-registry-2.1.233.ts +200 -0
- package/src/profiles/claude-code-2.1.195.ts +14 -0
- package/src/profiles/claude-code-2.1.233.ts +240 -0
- package/src/redaction.ts +16 -1
- package/src/request-body.ts +16 -9
- package/src/thinking.ts +119 -39
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.0] - 2026-08-15
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- **The default protocol profile is now Claude Code 2.1.233 (SDK 0.112.1).** Any
|
|
10
|
+
call to `buildClaudeCodeRequest`, `buildClaudeCodeCountTokensRequest` or
|
|
11
|
+
`parseBuiltClaudeCodeRequest` that does not pass `profile` explicitly now
|
|
12
|
+
produces the 2.1.233 wire shape instead of the 2.1.195 one. Concretely, a
|
|
13
|
+
default-profile request changes in all of the following ways:
|
|
14
|
+
|
|
15
|
+
- the user agent becomes `claude-cli/2.1.233 (external, cli)`;
|
|
16
|
+
- `x-stainless-package-version` becomes `0.112.1`;
|
|
17
|
+
- `anthropic-beta` is selected from the 2.1.233 beta registry (31 entries).
|
|
18
|
+
`summarize-connector-text-2026-03-13` no longer exists upstream, so
|
|
19
|
+
`betaPolicy.narrationSummariesEnabled` is inert under the default profile —
|
|
20
|
+
it is still accepted, and still effective under the 2.1.195 profile;
|
|
21
|
+
- the model catalogue has 17 entries, adding `claude-sonnet-5`,
|
|
22
|
+
`claude-opus-5` and `claude-mythos-5`;
|
|
23
|
+
- the canonical billing block announces `cc_version=2.1.233.<fp>`.
|
|
24
|
+
|
|
25
|
+
**To keep the previous behaviour, pass the exported
|
|
26
|
+
`CLAUDE_CODE_2_1_195_PROFILE` singleton as `profile`.** Its output is
|
|
27
|
+
byte-identical to `0.1.0` — headers, body and evidence digest — so pinning it
|
|
28
|
+
is a complete rollback of this change with no other edit required.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`CLAUDE_CODE_2_1_233_PROFILE`**, exported from the package root and from the
|
|
33
|
+
new `./profiles/claude-code-2.1.233` subpath, alongside the existing
|
|
34
|
+
`CLAUDE_CODE_2_1_195_PROFILE` and `./profiles/claude-code-2.1.195`. Both are
|
|
35
|
+
pinned singletons: the fail-closed rule is unchanged, and any other object —
|
|
36
|
+
including a structurally identical clone — is still rejected with
|
|
37
|
+
`INVALID_INPUT`.
|
|
38
|
+
- **`ClaudeCodeRequestInput.previousRequestId` and
|
|
39
|
+
`ClaudeCodeRequestInput.promptId`**, both optional. Under the 2.1.233 profile
|
|
40
|
+
they are emitted as the `cc_prev_req` and `cc_prompt_id` segments of the
|
|
41
|
+
canonical billing block. A value whose format is not recognised is omitted
|
|
42
|
+
silently rather than rejected, matching the genuine client, and neither field
|
|
43
|
+
is emitted under the 2.1.195 profile.
|
|
44
|
+
- **A request-derived upper bound on output tokens under 2.1.233.** A request
|
|
45
|
+
asking for `maxTokens >= 4096` raises the ceiling applied to `max_tokens`
|
|
46
|
+
instead of being clamped to the model's default limit, mirroring upstream.
|
|
47
|
+
The 2.1.195 profile keeps the previous clamp.
|
|
48
|
+
- **`maxOutputTokens` on catalogue entries.** Every model entry now carries its
|
|
49
|
+
own output-token limit, so the limit a request is clamped against is readable
|
|
50
|
+
from the profile rather than implied.
|
|
51
|
+
- Per-version behaviour is data-driven: a profile is data, and the behaviour it
|
|
52
|
+
selects is internal. Selecting a profile is therefore the only supported way
|
|
53
|
+
to select a protocol version, and adding a version does not change any
|
|
54
|
+
existing one.
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **Capabilities and token limits are resolved from the active profile's
|
|
59
|
+
catalogue** rather than from a single pinned table. Requests built with
|
|
60
|
+
`CLAUDE_CODE_2_1_195_PROFILE` are byte-identical to `0.1.0`, which
|
|
61
|
+
`npm run test:pack` confirms by an unchanged consumer digest.
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- **Evidence parsing follows the profile it was given.** `parseBuiltClaudeCodeRequest`
|
|
66
|
+
validated evidence against the pinned profile regardless of which profile
|
|
67
|
+
built the request, so a round trip through a non-default profile failed. It
|
|
68
|
+
now reads the validated profile, and every profile round-trips.
|
|
69
|
+
|
|
5
70
|
## [0.1.0] - 2026-07-28
|
|
6
71
|
|
|
7
72
|
First stable release.
|
package/README.md
CHANGED
|
@@ -16,7 +16,19 @@ 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
|
+
Two pinned profiles are exported:
|
|
20
|
+
|
|
21
|
+
- `CLAUDE_CODE_2_1_233_PROFILE` — Claude Code 2.1.233 with SDK 0.112.1. This is the profile used when `profile` is omitted.
|
|
22
|
+
- `CLAUDE_CODE_2_1_195_PROFILE` — the previous pin, Claude Code 2.1.195 with SDK 0.94.0.
|
|
23
|
+
|
|
24
|
+
Either can be selected explicitly by passing the singleton as the `profile` argument, from the package root or from its own subpath export:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { CLAUDE_CODE_2_1_195_PROFILE } from "@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.195";
|
|
28
|
+
import { CLAUDE_CODE_2_1_233_PROFILE } from "@tormentalabs/claude-code-wire-compat/profiles/claude-code-2.1.233";
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
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.
|
|
20
32
|
|
|
21
33
|
## Protocol documentation
|
|
22
34
|
|
|
@@ -68,6 +80,7 @@ required](./docs/protocol/versions/README.md):
|
|
|
68
80
|
- [Claude Code 2.1.150](./docs/protocol/versions/claude-code-2.1.150-analysis.md)
|
|
69
81
|
- [Claude Code 2.1.159](./docs/protocol/versions/claude-code-2.1.159-analysis.md)
|
|
70
82
|
- [Claude Code 2.1.195](./docs/protocol/versions/claude-code-2.1.195-analysis.md)
|
|
83
|
+
- [Claude Code 2.1.233](./docs/protocol/versions/claude-code-2.1.233-analysis.md)
|
|
71
84
|
— the release this package's profile pins.
|
|
72
85
|
|
|
73
86
|
## Development
|
package/dist/betas.d.ts
CHANGED
|
@@ -1,4 +1,40 @@
|
|
|
1
1
|
import type { ClaudeCodeCapabilities, ClaudeCodeProtocolProfile } from "./contracts.js";
|
|
2
|
+
/** Structural shape of a registry entry, shared by every registry version. */
|
|
3
|
+
interface BetaRegistryEntry {
|
|
4
|
+
readonly featureKey: string;
|
|
5
|
+
readonly header: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The entries the push sites below require, as a structural contract rather
|
|
9
|
+
* than a reference to one concrete registry.
|
|
10
|
+
*
|
|
11
|
+
* Registry versions have different key sets. Every key here except
|
|
12
|
+
* `NARRATION_SUMMARIES` is present in all of them, so those push sites index
|
|
13
|
+
* directly. `NARRATION_SUMMARIES` is optional because upstream removed it after
|
|
14
|
+
* 2.1.195 (see `src/profiles/beta-registry-2.1.233.ts`): its push site survives
|
|
15
|
+
* and becomes inert when the resolved registry has no entry to push. Making the
|
|
16
|
+
* optionality part of the TYPE is what forces every future registry to be
|
|
17
|
+
* checked against the push sites at compile time instead of at runtime.
|
|
18
|
+
*/
|
|
19
|
+
export interface ComposableBetaRegistry {
|
|
20
|
+
readonly CLAUDE_CODE: BetaRegistryEntry;
|
|
21
|
+
readonly OAUTH_AUTH: BetaRegistryEntry;
|
|
22
|
+
readonly LONG_CONTEXT: BetaRegistryEntry;
|
|
23
|
+
readonly INTERLEAVED_THINKING: BetaRegistryEntry;
|
|
24
|
+
readonly REDACT_THINKING: BetaRegistryEntry;
|
|
25
|
+
readonly THINKING_TOKEN_COUNT: BetaRegistryEntry;
|
|
26
|
+
readonly CONTEXT_MANAGEMENT: BetaRegistryEntry;
|
|
27
|
+
readonly STRUCTURED_OUTPUTS: BetaRegistryEntry;
|
|
28
|
+
readonly PROMPT_CACHING_SCOPE: BetaRegistryEntry;
|
|
29
|
+
readonly MID_CONVERSATION_SYSTEM: BetaRegistryEntry;
|
|
30
|
+
readonly EFFORT: BetaRegistryEntry;
|
|
31
|
+
readonly SPEED: BetaRegistryEntry;
|
|
32
|
+
readonly AFK_MODE: BetaRegistryEntry;
|
|
33
|
+
readonly EXTENDED_CACHE_TTL: BetaRegistryEntry;
|
|
34
|
+
readonly CONTEXT_HINT: BetaRegistryEntry;
|
|
35
|
+
readonly CACHE_DIAGNOSIS: BetaRegistryEntry;
|
|
36
|
+
readonly NARRATION_SUMMARIES?: BetaRegistryEntry;
|
|
37
|
+
}
|
|
2
38
|
export interface ComposeBetasInput {
|
|
3
39
|
readonly rawModel: string;
|
|
4
40
|
readonly normalizedId: string;
|
|
@@ -39,4 +75,5 @@ export interface ComposedBetas {
|
|
|
39
75
|
}
|
|
40
76
|
export declare function composeBetas(input: ComposeBetasInput, profile?: ClaudeCodeProtocolProfile): readonly string[];
|
|
41
77
|
export declare function composeBetasWithAudit(input: ComposeBetasInput, profile?: ClaudeCodeProtocolProfile): ComposedBetas;
|
|
78
|
+
export {};
|
|
42
79
|
//# sourceMappingURL=betas.d.ts.map
|
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":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC;AA2BxB,8EAA8E;AAC9E,UAAU,iBAAiB;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,oBAAoB,EAAE,iBAAiB,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,iBAAiB,CAAC;IAC5C,QAAQ,CAAC,oBAAoB,EAAE,iBAAiB,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;IAC/C,QAAQ,CAAC,oBAAoB,EAAE,iBAAiB,CAAC;IACjD,QAAQ,CAAC,uBAAuB,EAAE,iBAAiB,CAAC;IACpD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,iBAAiB,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,iBAAiB,CAAC;CAClD;AAwBD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD;AAkCD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,yBAAuD,GAC/D,SAAS,MAAM,EAAE,CAEnB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,yBAAuD,GAC/D,aAAa,CA8Hf"}
|
package/dist/betas.js
CHANGED
|
@@ -2,7 +2,26 @@
|
|
|
2
2
|
import { BETA_REGISTRY } from "./beta-registry.js";
|
|
3
3
|
import { ClaudeCodeWireError } from "./contracts.js";
|
|
4
4
|
import { supportsMidConversationSystem, supportsStructuredOutputs, } from "./model-capabilities.js";
|
|
5
|
+
import { BETA_REGISTRY_2_1_233 } from "./profiles/beta-registry-2.1.233.js";
|
|
5
6
|
import { CLAUDE_CODE_2_1_195_PROFILE } from "./profiles/claude-code-2.1.195.js";
|
|
7
|
+
import { CLAUDE_CODE_2_1_233_PROFILE } from "./profiles/claude-code-2.1.233.js";
|
|
8
|
+
const PROFILE_BETA_REGISTRIES = new Map([
|
|
9
|
+
[CLAUDE_CODE_2_1_195_PROFILE.id, BETA_REGISTRY],
|
|
10
|
+
[CLAUDE_CODE_2_1_233_PROFILE.id, BETA_REGISTRY_2_1_233],
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* Selects the registry a profile composes against.
|
|
14
|
+
*
|
|
15
|
+
* An unrecognised id falls back to the 2.1.195 registry rather than throwing.
|
|
16
|
+
* Rejecting unknown profiles is the request builder's job -- it validates the
|
|
17
|
+
* profile before any of this runs -- and duplicating that rejection here would
|
|
18
|
+
* give `composeBetas` a second, differently-worded opinion about profile
|
|
19
|
+
* validity. Standalone callers keep the 2.1.195 behaviour they had before
|
|
20
|
+
* profiles were a parameter.
|
|
21
|
+
*/
|
|
22
|
+
function resolveBetaRegistry(profile) {
|
|
23
|
+
return PROFILE_BETA_REGISTRIES.get(profile.id) ?? BETA_REGISTRY;
|
|
24
|
+
}
|
|
6
25
|
/**
|
|
7
26
|
* Bounds a caller-supplied beta list (`additionalBetas` and `suppressBetas`
|
|
8
27
|
* share these rules verbatim). The header is a comma-joined single
|
|
@@ -37,65 +56,78 @@ export function composeBetasWithAudit(input, profile = CLAUDE_CODE_2_1_195_PROFI
|
|
|
37
56
|
const out = [];
|
|
38
57
|
const policy = profile.betaPolicy;
|
|
39
58
|
const experimental = policy.experimentalBetasEnabled;
|
|
59
|
+
const registry = resolveBetaRegistry(profile);
|
|
40
60
|
if (!input.normalizedId.includes("haiku"))
|
|
41
|
-
out.push(
|
|
61
|
+
out.push(registry.CLAUDE_CODE.header);
|
|
42
62
|
if (policy.oauthAuthenticated)
|
|
43
|
-
out.push(
|
|
63
|
+
out.push(registry.OAUTH_AUTH.header);
|
|
44
64
|
// Package extension: `use1MContextOverride` replaces the model-marker gate
|
|
45
65
|
// for this request. The profile gate still applies, so an override cannot
|
|
46
66
|
// enable a beta the pinned profile declares unavailable.
|
|
47
67
|
const oneMillionRequested = input.use1MContextOverride ?? /\[1m\]/iu.test(input.rawModel);
|
|
48
68
|
if (policy.oneMillionContextEnabled && oneMillionRequested) {
|
|
49
|
-
out.push(
|
|
69
|
+
out.push(registry.LONG_CONTEXT.header);
|
|
50
70
|
}
|
|
51
71
|
if (policy.interleavedThinkingEnabled &&
|
|
52
72
|
input.capabilities.interleavedThinking) {
|
|
53
|
-
out.push(
|
|
73
|
+
out.push(registry.INTERLEAVED_THINKING.header);
|
|
54
74
|
}
|
|
55
75
|
if (experimental &&
|
|
56
76
|
input.capabilities.interleavedThinking &&
|
|
57
77
|
policy.interactive &&
|
|
58
78
|
!policy.thinkingSummariesShown &&
|
|
59
79
|
!input.thinkingDisplayActive) {
|
|
60
|
-
out.push(
|
|
80
|
+
out.push(registry.REDACT_THINKING.header);
|
|
61
81
|
}
|
|
62
82
|
if (policy.thinkingTokenCountEnabled &&
|
|
63
83
|
experimental &&
|
|
64
84
|
input.capabilities.interleavedThinking) {
|
|
65
|
-
out.push(
|
|
85
|
+
out.push(registry.THINKING_TOKEN_COUNT.header);
|
|
86
|
+
}
|
|
87
|
+
/*
|
|
88
|
+
* The narration push site keeps its position in the sequence even when the
|
|
89
|
+
* resolved registry dropped the entry. Upstream removed the beta after
|
|
90
|
+
* 2.1.195, so a registry without it emits nothing here and the surrounding
|
|
91
|
+
* order closes up with no gap; the gates are still evaluated first so a
|
|
92
|
+
* profile that enables narration against a registry that has it behaves
|
|
93
|
+
* exactly as it did before.
|
|
94
|
+
*/
|
|
95
|
+
const narrationSummaries = registry.NARRATION_SUMMARIES;
|
|
96
|
+
if (experimental &&
|
|
97
|
+
policy.narrationSummariesEnabled &&
|
|
98
|
+
narrationSummaries !== undefined) {
|
|
99
|
+
out.push(narrationSummaries.header);
|
|
66
100
|
}
|
|
67
|
-
if (experimental && policy.narrationSummariesEnabled)
|
|
68
|
-
out.push(BETA_REGISTRY.NARRATION_SUMMARIES.header);
|
|
69
101
|
if (experimental && input.capabilities.contextManagement)
|
|
70
|
-
out.push(
|
|
102
|
+
out.push(registry.CONTEXT_MANAGEMENT.header);
|
|
71
103
|
if (experimental &&
|
|
72
104
|
supportsStructuredOutputs(input.normalizedId) &&
|
|
73
105
|
policy.structuredOutputsEnabled) {
|
|
74
|
-
out.push(
|
|
106
|
+
out.push(registry.STRUCTURED_OUTPUTS.header);
|
|
75
107
|
}
|
|
76
108
|
// No web-search beta: upstream pushes it only for vertex and foundry.
|
|
77
109
|
if (experimental)
|
|
78
|
-
out.push(
|
|
79
|
-
if (supportsMidConversationSystem(input.normalizedId))
|
|
80
|
-
out.push(
|
|
110
|
+
out.push(registry.PROMPT_CACHING_SCOPE.header);
|
|
111
|
+
if (supportsMidConversationSystem(input.normalizedId, profile))
|
|
112
|
+
out.push(registry.MID_CONVERSATION_SYSTEM.header);
|
|
81
113
|
if (input.capabilities.effort)
|
|
82
|
-
out.push(
|
|
83
|
-
if (input.speed === "fast" && !out.includes(
|
|
84
|
-
out.push(
|
|
114
|
+
out.push(registry.EFFORT.header);
|
|
115
|
+
if (input.speed === "fast" && !out.includes(registry.SPEED.header)) {
|
|
116
|
+
out.push(registry.SPEED.header);
|
|
85
117
|
}
|
|
86
|
-
if (policy.afkModeEnabled && !out.includes(
|
|
87
|
-
out.push(
|
|
118
|
+
if (policy.afkModeEnabled && !out.includes(registry.AFK_MODE.header)) {
|
|
119
|
+
out.push(registry.AFK_MODE.header);
|
|
88
120
|
}
|
|
89
121
|
if (input.cacheTtl === "1h" &&
|
|
90
122
|
experimental &&
|
|
91
|
-
!out.includes(
|
|
92
|
-
out.push(
|
|
123
|
+
!out.includes(registry.EXTENDED_CACHE_TTL.header)) {
|
|
124
|
+
out.push(registry.EXTENDED_CACHE_TTL.header);
|
|
93
125
|
}
|
|
94
126
|
if (profile.contextHintEnabled)
|
|
95
|
-
out.push(
|
|
127
|
+
out.push(registry.CONTEXT_HINT.header);
|
|
96
128
|
if (policy.cacheDiagnosisEnabled &&
|
|
97
|
-
!out.includes(
|
|
98
|
-
out.push(
|
|
129
|
+
!out.includes(registry.CACHE_DIAGNOSIS.header)) {
|
|
130
|
+
out.push(registry.CACHE_DIAGNOSIS.header);
|
|
99
131
|
}
|
|
100
132
|
// No advisor-tool beta: upstream has no observed unconditional push site.
|
|
101
133
|
// Package extension. Canonical, upstream-derived identifiers always precede
|
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,2BAA2B,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"betas.js","sourceRoot":"","sources":["../src/betas.ts"],"names":[],"mappings":"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"}
|
package/dist/build-request.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { BuiltClaudeCodeCountTokensRequest, BuiltClaudeCodeRequest, ClaudeCodeProtocolProfile, ClaudeCodeCountTokensInput, ClaudeCodeRequestInput } from "./contracts.js";
|
|
2
|
+
/**
|
|
3
|
+
* The profile every public entry point resolves to when the caller supplies
|
|
4
|
+
* none. Declared once so that the default is a single, greppable seam: a test
|
|
5
|
+
* that means "whatever the default is" reads THIS instead of naming a
|
|
6
|
+
* version, which keeps a default switch to a one-line diff and keeps tests
|
|
7
|
+
* that genuinely mean 2.1.195 honest about saying so.
|
|
8
|
+
*
|
|
9
|
+
* Exported for tests, which deep-import it. It is deliberately NOT re-exported
|
|
10
|
+
* from `src/index.ts`: the public runtime surface stays closed.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_PROFILE: ClaudeCodeProtocolProfile;
|
|
2
13
|
/** Builds a canonical Claude Code count-tokens request. */
|
|
3
14
|
export declare function buildClaudeCodeCountTokensRequest(input: ClaudeCodeCountTokensInput, profile?: ClaudeCodeProtocolProfile): Promise<BuiltClaudeCodeCountTokensRequest>;
|
|
4
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../src/build-request.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iCAAiC,EACjC,sBAAsB,EAMtB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EAGvB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../src/build-request.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,iCAAiC,EACjC,sBAAsB,EAMtB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EAGvB,MAAM,gBAAgB,CAAC;AAsUxB;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,yBACD,CAAC;AAqiC9B,2DAA2D;AAC3D,wBAAsB,iCAAiC,CACrD,KAAK,EAAE,0BAA0B,EACjC,OAAO,GAAE,yBAA2C,GACnD,OAAO,CAAC,iCAAiC,CAAC,CAiF5C;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,sBAAsB,EAC7B,OAAO,GAAE,yBAA2C,GACnD,OAAO,CAAC,sBAAsB,CAAC,CAgLjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,yBAA2C,GACnD,sBAAsB,CA+FxB"}
|
package/dist/build-request.js
CHANGED
|
@@ -7,6 +7,7 @@ import { buildOrderedHeaderPlan, buildOrderedHeaders } from "./headers.js";
|
|
|
7
7
|
import { buildCorrelatedMetadata, validateRuntimeIdentity, } from "./metadata.js";
|
|
8
8
|
import { resolveModel } from "./models.js";
|
|
9
9
|
import { CLAUDE_CODE_2_1_195_PROFILE } from "./profiles/claude-code-2.1.195.js";
|
|
10
|
+
import { CLAUDE_CODE_2_1_233_PROFILE } from "./profiles/claude-code-2.1.233.js";
|
|
10
11
|
import { buildRedactedEvidence, toSafeErrorDetails } from "./redaction.js";
|
|
11
12
|
import { buildCanonicalBody, canonicalCountTokensLists, } from "./request-body.js";
|
|
12
13
|
import { sha256Hex } from "./sha256.js";
|
|
@@ -60,6 +61,8 @@ const INPUT_KEYS = new Set([
|
|
|
60
61
|
"metadataOverrides",
|
|
61
62
|
"extraHeaders",
|
|
62
63
|
"extraHeaderPolicy",
|
|
64
|
+
"previousRequestId",
|
|
65
|
+
"promptId",
|
|
63
66
|
"crypto",
|
|
64
67
|
]);
|
|
65
68
|
const BETA_OVERRIDE_KEYS = new Set(["use1MContext"]);
|
|
@@ -145,6 +148,7 @@ const MODEL_KEYS = new Set([
|
|
|
145
148
|
"family",
|
|
146
149
|
"context",
|
|
147
150
|
"capabilities",
|
|
151
|
+
"maxOutputTokens",
|
|
148
152
|
"defaultEffort",
|
|
149
153
|
]);
|
|
150
154
|
const BETA_POLICY_KEYS = new Set([
|
|
@@ -275,8 +279,41 @@ function containsString(value, target) {
|
|
|
275
279
|
? containsString(ownValue(value, key), target)
|
|
276
280
|
: false);
|
|
277
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* The profiles this package will assemble a request for. Two entries: the
|
|
284
|
+
* 2.1.195 default and the 2.1.233 profile, which callers must pass
|
|
285
|
+
* explicitly. Admitting a profile is exactly this list -- `validateProfile`
|
|
286
|
+
* did not change to accept the second one.
|
|
287
|
+
*
|
|
288
|
+
* Membership is by REFERENCE, deliberately. A structural check would accept a
|
|
289
|
+
* caller-built object that merely looks like a pinned profile, and every wire
|
|
290
|
+
* guarantee this package makes -- the sealed golden fixtures, the packed
|
|
291
|
+
* consumer digests -- is a statement about the exact frozen singletons, not
|
|
292
|
+
* about anything shaped like them. `Set.prototype.has` uses SameValueZero, so
|
|
293
|
+
* `{ ...CLAUDE_CODE_2_1_195_PROFILE }` is rejected exactly as it was by the
|
|
294
|
+
* `!==` this replaced.
|
|
295
|
+
*
|
|
296
|
+
* Not exported and not frozen-with-teeth: `Object.freeze` on a `Set` blocks
|
|
297
|
+
* property assignment but NOT `add`, so freezing it would advertise a
|
|
298
|
+
* guarantee it cannot keep. Module scope is the real protection.
|
|
299
|
+
*/
|
|
300
|
+
const ACCEPTED_PROFILES = new Set([
|
|
301
|
+
CLAUDE_CODE_2_1_195_PROFILE,
|
|
302
|
+
CLAUDE_CODE_2_1_233_PROFILE,
|
|
303
|
+
]);
|
|
304
|
+
/**
|
|
305
|
+
* The profile every public entry point resolves to when the caller supplies
|
|
306
|
+
* none. Declared once so that the default is a single, greppable seam: a test
|
|
307
|
+
* that means "whatever the default is" reads THIS instead of naming a
|
|
308
|
+
* version, which keeps a default switch to a one-line diff and keeps tests
|
|
309
|
+
* that genuinely mean 2.1.195 honest about saying so.
|
|
310
|
+
*
|
|
311
|
+
* Exported for tests, which deep-import it. It is deliberately NOT re-exported
|
|
312
|
+
* from `src/index.ts`: the public runtime surface stays closed.
|
|
313
|
+
*/
|
|
314
|
+
export const DEFAULT_PROFILE = CLAUDE_CODE_2_1_233_PROFILE;
|
|
278
315
|
function validateProfile(profile) {
|
|
279
|
-
if (profile
|
|
316
|
+
if (!ACCEPTED_PROFILES.has(profile))
|
|
280
317
|
fail();
|
|
281
318
|
return profile;
|
|
282
319
|
}
|
|
@@ -313,6 +350,32 @@ function parseCatalogueCapabilities(value) {
|
|
|
313
350
|
}
|
|
314
351
|
return Object.freeze([...value]);
|
|
315
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Validates a catalogue entry's `maxOutputTokens`. Both fields are required
|
|
355
|
+
* when the object is present: a half-populated entry would silently fall back
|
|
356
|
+
* to the legacy limit table for the missing half, which is exactly the drift
|
|
357
|
+
* `modelOutputTokenLimits` is structured to prevent.
|
|
358
|
+
*/
|
|
359
|
+
function parseCatalogueMaxOutputTokens(value) {
|
|
360
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
361
|
+
throw new ClaudeCodeWireError("INVALID_INPUT");
|
|
362
|
+
}
|
|
363
|
+
const keys = Reflect.ownKeys(value);
|
|
364
|
+
if (keys.some((key) => typeof key !== "string" || (key !== "default" && key !== "upper"))) {
|
|
365
|
+
throw new ClaudeCodeWireError("INVALID_INPUT");
|
|
366
|
+
}
|
|
367
|
+
const defaultLimit = Reflect.get(value, "default");
|
|
368
|
+
const upper = Reflect.get(value, "upper");
|
|
369
|
+
if (typeof defaultLimit !== "number" ||
|
|
370
|
+
!Number.isSafeInteger(defaultLimit) ||
|
|
371
|
+
defaultLimit <= 0 ||
|
|
372
|
+
typeof upper !== "number" ||
|
|
373
|
+
!Number.isSafeInteger(upper) ||
|
|
374
|
+
upper <= 0) {
|
|
375
|
+
throw new ClaudeCodeWireError("INVALID_INPUT");
|
|
376
|
+
}
|
|
377
|
+
return Object.freeze({ default: defaultLimit, upper });
|
|
378
|
+
}
|
|
316
379
|
function parseCatalogueContext(value) {
|
|
317
380
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
318
381
|
throw new ClaudeCodeWireError("INVALID_INPUT");
|
|
@@ -399,6 +462,11 @@ function parseSupportedModels(value) {
|
|
|
399
462
|
? { context: parseCatalogueContext(ownValue(model, "context")) }
|
|
400
463
|
: {}),
|
|
401
464
|
capabilities: parseCatalogueCapabilities(ownValue(model, "capabilities")),
|
|
465
|
+
...(Object.hasOwn(model, "maxOutputTokens")
|
|
466
|
+
? {
|
|
467
|
+
maxOutputTokens: parseCatalogueMaxOutputTokens(ownValue(model, "maxOutputTokens")),
|
|
468
|
+
}
|
|
469
|
+
: {}),
|
|
402
470
|
...(Object.hasOwn(model, "defaultEffort")
|
|
403
471
|
? {
|
|
404
472
|
defaultEffort: parseDefaultEffort(ownValue(model, "defaultEffort")),
|
|
@@ -609,6 +677,12 @@ function validateInput(input) {
|
|
|
609
677
|
const preserveThinkingBlockCacheControl = Object.hasOwn(input, "preserveThinkingBlockCacheControl")
|
|
610
678
|
? validatePreserveThinkingBlockCacheControl(ownValue(input, "preserveThinkingBlockCacheControl"))
|
|
611
679
|
: false;
|
|
680
|
+
const previousRequestId = Object.hasOwn(input, "previousRequestId")
|
|
681
|
+
? validateBillingChainId(ownValue(input, "previousRequestId"))
|
|
682
|
+
: undefined;
|
|
683
|
+
const promptId = Object.hasOwn(input, "promptId")
|
|
684
|
+
? validateBillingChainId(ownValue(input, "promptId"))
|
|
685
|
+
: undefined;
|
|
612
686
|
return {
|
|
613
687
|
source: input,
|
|
614
688
|
clientRequestId,
|
|
@@ -619,8 +693,30 @@ function validateInput(input) {
|
|
|
619
693
|
suppressBillingBlock,
|
|
620
694
|
suppressIdentityBlock,
|
|
621
695
|
preserveThinkingBlockCacheControl,
|
|
696
|
+
previousRequestId,
|
|
697
|
+
promptId,
|
|
622
698
|
};
|
|
623
699
|
}
|
|
700
|
+
/**
|
|
701
|
+
* Type check only. The FORMAT of these two ids is deliberately not checked
|
|
702
|
+
* here: upstream guards them at the point of emission and drops a value it
|
|
703
|
+
* cannot vouch for, silently, so rejecting one here would make this package
|
|
704
|
+
* fail where the genuine client succeeds. `createBillingBlock` owns the
|
|
705
|
+
* patterns. A non-string is still a caller bug and fails like every other
|
|
706
|
+
* mistyped field.
|
|
707
|
+
*
|
|
708
|
+
* There is deliberately no `undefined` arm: `inspectGraph` has already rejected
|
|
709
|
+
* an explicitly-undefined value for every key but `crypto` by the time this
|
|
710
|
+
* runs, so such an arm would be unreachable. An explicitly-undefined id is
|
|
711
|
+
* therefore `INVALID_INPUT` here, as it is for every other field, and is NOT
|
|
712
|
+
* equivalent to omitting the key — unlike at the `createBillingBlock` seam,
|
|
713
|
+
* which does treat the two alike. `billing-prev-req.test.ts` pins both halves.
|
|
714
|
+
*/
|
|
715
|
+
function validateBillingChainId(value) {
|
|
716
|
+
if (typeof value !== "string")
|
|
717
|
+
fail();
|
|
718
|
+
return value;
|
|
719
|
+
}
|
|
624
720
|
function validateCountTokensInput(input) {
|
|
625
721
|
if (!isRecord(input))
|
|
626
722
|
fail();
|
|
@@ -797,7 +893,16 @@ function parseCapabilityDecisions(value) {
|
|
|
797
893
|
rejectsDisabledThinking: readBoolean("rejectsDisabledThinking"),
|
|
798
894
|
};
|
|
799
895
|
}
|
|
800
|
-
|
|
896
|
+
/**
|
|
897
|
+
* Validates evidence against the profile the request was parsed under, not
|
|
898
|
+
* against a hardcoded singleton. `parseBuiltClaudeCodeRequest` already
|
|
899
|
+
* validates `url` against `pinnedProfile.endpoint`; the profile id is the one
|
|
900
|
+
* remaining field where the two pinned profiles differ, so it has to follow
|
|
901
|
+
* the same source or a request built with a non-default profile could never
|
|
902
|
+
* be re-parsed. Still fail-closed: the profile reaching here has already
|
|
903
|
+
* passed `validateProfile`.
|
|
904
|
+
*/
|
|
905
|
+
function parseEvidence(value, pinnedProfile) {
|
|
801
906
|
if (!isRecord(value))
|
|
802
907
|
fail();
|
|
803
908
|
assertExactKeys(value, EVIDENCE_KEYS);
|
|
@@ -814,8 +919,8 @@ function parseEvidence(value) {
|
|
|
814
919
|
const bodyByteLength = ownValue(value, "bodyByteLength");
|
|
815
920
|
const messageCount = ownValue(value, "messageCount");
|
|
816
921
|
const systemBlockCount = ownValue(value, "systemBlockCount");
|
|
817
|
-
if (ownValue(value, "profileId") !==
|
|
818
|
-
ownValue(value, "url") !==
|
|
922
|
+
if (ownValue(value, "profileId") !== pinnedProfile.id ||
|
|
923
|
+
ownValue(value, "url") !== pinnedProfile.endpoint ||
|
|
819
924
|
ownValue(value, "method") !== METHOD ||
|
|
820
925
|
typeof bodySha256 !== "string" ||
|
|
821
926
|
!/^[0-9a-f]{64}$/u.test(bodySha256) ||
|
|
@@ -828,8 +933,8 @@ function parseEvidence(value) {
|
|
|
828
933
|
fail();
|
|
829
934
|
}
|
|
830
935
|
return {
|
|
831
|
-
profileId:
|
|
832
|
-
url:
|
|
936
|
+
profileId: pinnedProfile.id,
|
|
937
|
+
url: pinnedProfile.endpoint,
|
|
833
938
|
method: METHOD,
|
|
834
939
|
modelFamily,
|
|
835
940
|
logicalHeaderNames: parseStringArray(ownValue(value, "logicalHeaderNames")),
|
|
@@ -1073,7 +1178,7 @@ function countTokensEvidenceRequest(input, capabilities) {
|
|
|
1073
1178
|
};
|
|
1074
1179
|
}
|
|
1075
1180
|
/** Builds a canonical Claude Code count-tokens request. */
|
|
1076
|
-
export async function buildClaudeCodeCountTokensRequest(input, profile =
|
|
1181
|
+
export async function buildClaudeCodeCountTokensRequest(input, profile = DEFAULT_PROFILE) {
|
|
1077
1182
|
try {
|
|
1078
1183
|
const pinnedProfile = validateProfile(profile);
|
|
1079
1184
|
const validated = validateCountTokensInput(input);
|
|
@@ -1135,7 +1240,7 @@ export async function buildClaudeCodeCountTokensRequest(input, profile = CLAUDE_
|
|
|
1135
1240
|
* `INVALID_INPUT`. This deliberate fail-closed behaviour prevents callers from
|
|
1136
1241
|
* substituting an unpinned protocol profile.
|
|
1137
1242
|
*/
|
|
1138
|
-
export async function buildClaudeCodeRequest(input, profile =
|
|
1243
|
+
export async function buildClaudeCodeRequest(input, profile = DEFAULT_PROFILE) {
|
|
1139
1244
|
try {
|
|
1140
1245
|
const pinnedProfile = validateProfile(profile);
|
|
1141
1246
|
const validated = validateInput(input);
|
|
@@ -1147,7 +1252,24 @@ export async function buildClaudeCodeRequest(input, profile = CLAUDE_CODE_2_1_19
|
|
|
1147
1252
|
...resolvedModel,
|
|
1148
1253
|
capabilities,
|
|
1149
1254
|
});
|
|
1150
|
-
|
|
1255
|
+
/*
|
|
1256
|
+
* The previous turn's request id is the CALLER's to supply. Upstream
|
|
1257
|
+
* derives it by scanning the conversation for the last assistant message
|
|
1258
|
+
* and reading a `requestId` it stored alongside it — a field of the
|
|
1259
|
+
* client's own transcript, not of the Messages API wire format. Modelling
|
|
1260
|
+
* that would mean adding a non-wire property to `Message` and having this
|
|
1261
|
+
* package infer conversation state it does not own. A documented
|
|
1262
|
+
* divergence of convenience: the value is the same, the plumbing is the
|
|
1263
|
+
* consumer's.
|
|
1264
|
+
*/
|
|
1265
|
+
const billing = await createBillingBlock(fingerprintText(validated.source), effectiveProfile, validated.crypto, {
|
|
1266
|
+
...(validated.previousRequestId !== undefined && {
|
|
1267
|
+
previousRequestId: validated.previousRequestId,
|
|
1268
|
+
}),
|
|
1269
|
+
...(validated.promptId !== undefined && {
|
|
1270
|
+
promptId: validated.promptId,
|
|
1271
|
+
}),
|
|
1272
|
+
});
|
|
1151
1273
|
const metadata = buildCorrelatedMetadata(identity, validated.source.metadata, validated.source.metadataOverrides);
|
|
1152
1274
|
const system = buildCanonicalSystem(validated.source.system, billing, identity, validated.suppressBillingBlock, validated.suppressIdentityBlock);
|
|
1153
1275
|
const canonicalBody = buildCanonicalBody(evidenceRequest(validated.source, validated.source.model), effectiveModel, system, metadata, effectiveProfile);
|
|
@@ -1260,7 +1382,7 @@ export async function buildClaudeCodeRequest(input, profile = CLAUDE_CODE_2_1_19
|
|
|
1260
1382
|
* `INVALID_INPUT`. This deliberate fail-closed behaviour prevents callers from
|
|
1261
1383
|
* substituting an unpinned protocol profile.
|
|
1262
1384
|
*/
|
|
1263
|
-
export function parseBuiltClaudeCodeRequest(value, profile =
|
|
1385
|
+
export function parseBuiltClaudeCodeRequest(value, profile = DEFAULT_PROFILE) {
|
|
1264
1386
|
try {
|
|
1265
1387
|
const pinnedProfile = validateProfile(profile);
|
|
1266
1388
|
inspectGraph(value);
|
|
@@ -1276,7 +1398,7 @@ export function parseBuiltClaudeCodeRequest(value, profile = CLAUDE_CODE_2_1_195
|
|
|
1276
1398
|
fail();
|
|
1277
1399
|
const parsedBody = parseBody(body);
|
|
1278
1400
|
const headers = parseHeaders(ownValue(value, "headers"));
|
|
1279
|
-
const evidence = parseEvidence(ownValue(value, "evidence"));
|
|
1401
|
+
const evidence = parseEvidence(ownValue(value, "evidence"), pinnedProfile);
|
|
1280
1402
|
// Reading evidence is not trusting evidence. A claim that the seam
|
|
1281
1403
|
// preserved a marker is confirmed against the body, and it is confirmed
|
|
1282
1404
|
// HERE — before the byte-length and digest checks — so that a forgery which
|