@yanlinglabs/winter-runtime-sdk 0.0.1 → 0.0.3

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.
@@ -8,7 +8,7 @@ import type { RuntimeSdkPeers } from "./sdk.js";
8
8
  * not a range that quietly widens.
9
9
  */
10
10
  export declare const SUPPORTED: {
11
- readonly winterAgentSdk: ">=0.0.2 <0.1.0";
11
+ readonly winterAgentSdk: ">=0.0.3 <0.1.0";
12
12
  readonly claudeAgentSdk: "0.3.250";
13
13
  };
14
14
  /**
@@ -18,7 +18,7 @@ export declare const SUPPORTED: {
18
18
  */
19
19
  export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly ["1.0"];
20
20
  /** Where a peer's package version came from. See this module's header. */
21
- export type PeerVersionSource = "peer-export" | "resolved-manifest";
21
+ export type PeerVersionSource = "host-declared" | "peer-export" | "resolved-manifest";
22
22
  export interface PeerVersionIdentity {
23
23
  /** The package name the identity was read for. */
24
24
  packageName: string;
@@ -70,8 +70,23 @@ export declare function readExportedVersion(namespace: unknown): string | undefi
70
70
  * own manifest as a subpath. Every failure mode — no such package, a manifest that will not parse, a
71
71
  * manifest with no `version` — returns `undefined`, which the caller turns into the loud refusal.
72
72
  * Never throws: a missing OPTIONAL peer must not crash the matrix on its way to reporting itself.
73
+ *
74
+ * `resolveEntry` is an injectable seam (R2), defaulting to the real
75
+ * `createRequire(import.meta.url).resolve` — NOT deleted, still the only resolver this package ever
76
+ * uses on its own. It exists so a test can simulate the one condition this package cannot otherwise
77
+ * reproduce on demand: a compiled binary, where that resolve call cannot see outside the bundle
78
+ * (`file:///$bunfs/...`) and always throws. Production code never passes a second argument.
79
+ */
80
+ export declare function readResolvedManifestVersion(packageName: string, resolveEntry?: (name: string) => string): string | undefined;
81
+ /**
82
+ * The seams `resolveVersionMatrix` accepts. `resolveEntry`, when given, REPLACES probe 2's resolver
83
+ * end to end (through `identityFor` into `readResolvedManifestVersion`) — the only way a test can make
84
+ * that probe genuinely fail rather than merely be irrelevant because `declared` or peer-export already
85
+ * answered. Production code (`assertVersionMatrix`) never supplies one.
73
86
  */
74
- export declare function readResolvedManifestVersion(packageName: string): string | undefined;
87
+ export interface VersionMatrixSeams {
88
+ resolveEntry?: (name: string) => string;
89
+ }
75
90
  /**
76
91
  * Reads each injected peer's version identity and refuses loudly on a miss.
77
92
  *
@@ -79,6 +94,31 @@ export declare function readResolvedManifestVersion(packageName: string): string
79
94
  * Winter-only host injects `{ winter }` and never loads the official runtime (that is the whole
80
95
  * point of the optional peer), so "no claude peer" is a valid, fully-supported configuration and the
81
96
  * report simply omits the row.
97
+ *
98
+ * `declared` is `RuntimeSdkOptions.peerVersions` (R2), optional — the one-arg call
99
+ * (`assertVersionMatrix(peers)`) stays legal and behaves exactly as before: with nothing declared,
100
+ * every peer's identity comes from probe 1 or probe 2, unchanged.
101
+ *
102
+ * `seams` is test-only (R2 review r1): NOT exposed here — `resolveVersionMatrix` below is where a test
103
+ * reaches it. A public seam parameter on this function is a production call site that could pass a
104
+ * broken resolver by accident, for a capability real hosts never need.
105
+ */
106
+ export declare function assertVersionMatrix(peers: RuntimeSdkPeers, declared?: {
107
+ winterAgentSdk?: string;
108
+ claudeAgentSdk?: string;
109
+ }): VersionMatrixReport;
110
+ /**
111
+ * `assertVersionMatrix`'s full implementation, with an injectable `seams` (R2 review r1, `test/spine/
112
+ * version-matrix.test.ts`'s test (d)). NOT on the package barrel (`src/index.ts`) — deliberately: a
113
+ * real host has no reason to override how this package resolves ITS OWN peers' manifests, so this
114
+ * function exists only so a test can force probe 2 (`resolved-manifest`) to GENUINELY fail — the one
115
+ * condition a test cannot otherwise reproduce on demand (in an ordinary dev checkout the real peers
116
+ * really are resolvable, so a test that never overrides the resolver cannot tell "declared won" from
117
+ * "resolved-manifest would have answered the same value anyway"). `assertVersionMatrix` is the public,
118
+ * one-line delegation with the real (default) seams.
82
119
  */
83
- export declare function assertVersionMatrix(peers: RuntimeSdkPeers): VersionMatrixReport;
120
+ export declare function resolveVersionMatrix(peers: RuntimeSdkPeers, declared?: {
121
+ winterAgentSdk?: string;
122
+ claudeAgentSdk?: string;
123
+ }, seams?: VersionMatrixSeams): VersionMatrixReport;
84
124
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yanlinglabs/winter-runtime-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "One door over the Winter Agent SDK and the official Claude Agent SDK: runtime selection, the official-SDK adapter, the shared session store, the handoff barrier and the cross-runtime messaging router.",
@@ -21,6 +21,10 @@
21
21
  ".": {
22
22
  "types": "./dist/index.d.ts",
23
23
  "default": "./dist/index.js"
24
+ },
25
+ "./testing": {
26
+ "types": "./dist/testing/host.d.ts",
27
+ "default": "./dist/testing/host.js"
24
28
  }
25
29
  },
26
30
  "files": [
@@ -39,20 +43,28 @@
39
43
  },
40
44
  "peerDependencies": {
41
45
  "@anthropic-ai/claude-agent-sdk": "0.3.250",
42
- "@yanlinglabs/winter-agent-sdk": ">=0.0.2 <0.1.0"
46
+ "@yanlinglabs/winter-agent-sdk": ">=0.0.3 <0.1.0",
47
+ "@yanlinglabs/winter-conformance": ">=0.0.3 <0.1.0",
48
+ "@yanlinglabs/winter-provider-conformance": ">=0.0.3 <0.1.0"
43
49
  },
44
50
  "peerDependenciesMeta": {
45
51
  "@anthropic-ai/claude-agent-sdk": {
46
52
  "optional": true
53
+ },
54
+ "@yanlinglabs/winter-conformance": {
55
+ "optional": true
56
+ },
57
+ "@yanlinglabs/winter-provider-conformance": {
58
+ "optional": true
47
59
  }
48
60
  },
49
61
  "devDependencies": {
50
62
  "@anthropic-ai/claude-agent-sdk": "0.3.250",
51
63
  "@types/bun": "^1.3.0",
52
64
  "@types/node": "^26.4.0",
53
- "@yanlinglabs/winter-agent-sdk": "^0.0.2",
54
- "@yanlinglabs/winter-conformance": "^0.0.2",
55
- "@yanlinglabs/winter-provider-conformance": "^0.0.2",
65
+ "@yanlinglabs/winter-agent-sdk": "^0.0.3",
66
+ "@yanlinglabs/winter-conformance": "^0.0.3",
67
+ "@yanlinglabs/winter-provider-conformance": "^0.0.3",
56
68
  "typescript": "^5.9.0"
57
69
  },
58
70
  "scripts": {
@@ -1,56 +0,0 @@
1
- import { type GlobalMessagingHandle } from "./router.js";
2
- /** The MCP result shape both branches return — structurally the descriptor's own (WS-14 §11). */
3
- export interface MessagingToolResult {
4
- content: Array<{
5
- type: "text";
6
- text: string;
7
- }>;
8
- isError?: boolean;
9
- }
10
- export type MessagingToolHandler = (args: unknown, extra?: unknown) => Promise<MessagingToolResult>;
11
- /**
12
- * WS-10 §12's RETRY KEY, on the official branch — and it exists, which was not known until it was
13
- * measured (item 15; `test/official/runtime-aliases.test.ts` is the measurement).
14
- *
15
- * §12 wants a message id derived from (sender session, TOOL-CALL id) so "a retry allocates the SAME
16
- * id" and returns the stored outcome instead of starting a second turn. On the Winter branch the
17
- * caller binds `toolUseId` at registration. On the official branch the handler is inside the vendor's
18
- * in-process MCP server, where the only per-call channel is the second argument the vendor passes —
19
- * and the reasonable expectation was that it carries MCP request context (a JSON-RPC request id,
20
- * `_meta`) rather than an Anthropic-API `tool_use_id`, which is one layer up.
21
- *
22
- * THE PINNED RUNTIME BRIDGES THEM. Measured on 0.3.250: `extra._meta["claudecode/toolUseId"]` is the
23
- * exact id the model emitted. So the official branch gets a real §12 key rather than depending on the
24
- * rapid-repeat guard, and the vendor's own namespaced `_meta` name is read rather than guessed at.
25
- *
26
- * A VENDOR-NAMESPACED KEY IS NEVER REBRANDED (WS-01 §5): `claudecode/toolUseId` is the vendor's name
27
- * for the vendor's field, exactly like `CLAUDE_CONFIG_DIR`. It is read defensively — an absent or
28
- * non-string value simply falls back to the bound caller's id — because a future pin may move it, and
29
- * losing the key must degrade to today's behaviour rather than to a crash.
30
- */
31
- export declare const VENDOR_TOOL_USE_ID_META_KEY = "claudecode/toolUseId";
32
- export declare function toolUseIdFromExtra(extra: unknown): string | undefined;
33
- export interface MessagingToolHandlers {
34
- sendMessage: MessagingToolHandler;
35
- listAgents: MessagingToolHandler;
36
- }
37
- /**
38
- * WHO IS CALLING — bound at registration, never read out of the arguments.
39
- *
40
- * The standing MCP server is materialized per session (WS-14 §11), so the caller is known when the
41
- * handler is built. Taking it from the ARGUMENTS instead would make the sender's identity something a
42
- * model could write, and every fence in this package — the owning-parent rule, the self-target
43
- * refusal, WS-10 §13's sender class, WS-15 §6.2's dedupe key — is keyed on it.
44
- *
45
- * `toolUseId` is the second half of WS-10 §12's retry key. It is OPTIONAL because on the official
46
- * branch it is not available: the in-process MCP server hands a tool handler its arguments, and the
47
- * router's own materialization does not forward the vendor's `extra` (which is where a request id
48
- * would be). A caller that cannot supply one gets no dedupe — stated at the door rather than faked
49
- * with a stable-looking key that would make two different messages one.
50
- */
51
- export interface MessagingToolCaller {
52
- sessionId: string;
53
- agentId?: string;
54
- toolUseId?: string;
55
- }
56
- export declare function createMessagingToolHandlers(messaging: GlobalMessagingHandle, caller: MessagingToolCaller | (() => MessagingToolCaller)): MessagingToolHandlers;
@@ -1,76 +0,0 @@
1
- /** WS-10 §10.1's bounds. `to`'s own limit is the subpath's; this is the copy the SCHEMA advertises. */
2
- export declare const SEND_MESSAGE_TO_MAX = 300;
3
- export declare const SEND_MESSAGE_SUMMARY_MAX = 200;
4
- /** WS-10 §10.2's bound on both reserved `ListAgents` fields. */
5
- export declare const LIST_AGENTS_FIELD_MAX = 256;
6
- export declare const NATIVE_SEND_MESSAGE_SCHEMA: {
7
- readonly type: "object";
8
- readonly properties: {
9
- readonly to: {
10
- readonly type: "string";
11
- readonly maxLength: 300;
12
- readonly description: "no newline, no \"*\" broadcast";
13
- };
14
- readonly message: {
15
- readonly type: "string";
16
- readonly description: "required; defaults \"\" for pure idle subscription";
17
- };
18
- readonly summary: {
19
- readonly type: "string";
20
- readonly maxLength: 200;
21
- };
22
- readonly notify_when_idle: {
23
- readonly type: "boolean";
24
- readonly description: "one-shot; main conversation -> same-machine session only";
25
- };
26
- };
27
- readonly required: readonly ["to", "message"];
28
- };
29
- export declare const NATIVE_LIST_AGENTS_SCHEMA: {
30
- readonly type: "object";
31
- readonly properties: {
32
- readonly channel: {
33
- readonly type: "string";
34
- readonly maxLength: 256;
35
- readonly description: "reserved";
36
- };
37
- readonly q: {
38
- readonly type: "string";
39
- readonly maxLength: 256;
40
- readonly description: "reserved";
41
- };
42
- };
43
- };
44
- /** WS-10 §10.2: "`ListAgents` output is EXACTLY `{ listing: string }`." */
45
- export declare const NATIVE_LIST_AGENTS_OUTPUT_SCHEMA: {
46
- readonly type: "object";
47
- readonly properties: {
48
- readonly listing: {
49
- readonly type: "string";
50
- };
51
- };
52
- readonly required: readonly ["listing"];
53
- };
54
- /** The native `SendMessage` arguments (WS-10 §10.1), after validation. */
55
- export interface NativeSendMessageArgs {
56
- to: string;
57
- message: string;
58
- summary?: string;
59
- notify_when_idle?: boolean;
60
- }
61
- /** The native `ListAgents` arguments (WS-10 §10.2). Both fields are reserved in the pinned build. */
62
- export interface NativeListAgentsArgs {
63
- channel?: string;
64
- q?: string;
65
- }
66
- export type NativeArgsResult<T> = {
67
- ok: true;
68
- args: T;
69
- } | {
70
- ok: false;
71
- reason: string;
72
- };
73
- /** Accepts the native `SendMessage` arguments EXACTLY — no more, no less. */
74
- export declare function acceptNativeSendMessageArgs(input: unknown): NativeArgsResult<NativeSendMessageArgs>;
75
- /** The same treatment for `ListAgents`: two reserved optional fields, both capped, nothing else. */
76
- export declare function acceptNativeListAgentsArgs(input: unknown): NativeArgsResult<NativeListAgentsArgs>;