@yanlinglabs/winter-runtime-sdk 0.0.1 → 0.0.2
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/README.md +68 -15
- package/dist/door.d.ts +62 -1
- package/dist/errors.d.ts +8 -0
- package/dist/index.d.ts +2 -4
- package/dist/index.js +376 -298
- package/dist/messaging/index.d.ts +1 -3
- package/dist/messaging/router.d.ts +1 -12
- package/dist/official/aliases.d.ts +6 -2
- package/dist/official/index.d.ts +2 -2
- package/dist/official/mcp-descriptors.d.ts +59 -47
- package/dist/sdk.d.ts +90 -5
- package/dist/version-matrix.d.ts +44 -4
- package/package.json +5 -5
- package/dist/messaging/handlers.d.ts +0 -56
- package/dist/native-args.d.ts +0 -76
package/README.md
CHANGED
|
@@ -14,19 +14,33 @@ Decision record: WS-00 D19 (2026-09-05). Boundaries that do not move:
|
|
|
14
14
|
builtin-path containment, Winter MCP plugin registration), shared session-store wiring, the
|
|
15
15
|
cross-runtime handoff barrier with the materialized-resume decoration doors, and the runtime
|
|
16
16
|
directory plus cross-runtime messaging router.
|
|
17
|
+
- **It owns NO TOOL** (the user's tool-ownership ruling, R-8-1). The default tools — `SendMessage`,
|
|
18
|
+
`ListAgents`, `ReadNotifications`, `advisor` — are DECLARED once in
|
|
19
|
+
`@yanlinglabs/winter-agent-sdk/tools` and BOUND here, under the official runtime's own built-in
|
|
20
|
+
names; the capability tools (computer, browser, office) are the HOST's, handed over as MCP servers
|
|
21
|
+
and forwarded to both legs unchanged. This package re-exports no tool surface of its own.
|
|
17
22
|
- The host vendors all three packages directly (`winter-runtime-sdk`, `winter-agent-sdk`,
|
|
18
23
|
`claude-agent-sdk`); this package declares the two SDKs as peer dependencies and receives their
|
|
19
24
|
module instances by injection, so a host that never creates a Claude session never loads the
|
|
20
25
|
official runtime and no SDK is ever instantiated twice.
|
|
21
26
|
- A `brand` profile flows through unchanged (Winter defaults); Claude Code's own literals stay fixed.
|
|
22
27
|
|
|
23
|
-
Status: Phase 7b
|
|
24
|
-
contract re-export, the `createRuntimeSdk` constructor
|
|
25
|
-
harness and CI) and the four lanes behind those seams —
|
|
26
|
-
directory and messaging router, the store wiring and handoff
|
|
27
|
-
`main`, with WS-17's eighteen router-owned rows proven and
|
|
28
|
-
`docs/architecture.md` for the ownership map, the pinned
|
|
29
|
-
|
|
28
|
+
Status: Phase 7b landed all four lanes and routed the door; `0.0.2` is the Phase-8b prerequisite
|
|
29
|
+
release. The spine (the package scaffold, the contract re-export, the `createRuntimeSdk` constructor
|
|
30
|
+
with its version matrix, the seams, the test harness and CI) and the four lanes behind those seams —
|
|
31
|
+
the official-SDK adapter, the runtime directory and messaging router, the store wiring and handoff
|
|
32
|
+
barrier, and runtime selection — are on `main`, with WS-17's eighteen router-owned rows proven and
|
|
33
|
+
cited in `docs/conformance-rows.md`. See `docs/architecture.md` for the ownership map, the pinned
|
|
34
|
+
interfaces and how this package consumes the Winter SDK.
|
|
35
|
+
|
|
36
|
+
**What `0.0.2` changes** (peer floor: `@yanlinglabs/winter-agent-sdk >=0.0.3 <0.1.0`):
|
|
37
|
+
|
|
38
|
+
| | |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `peerVersions` | A host DECLARES its peers' versions — the only door inside a compiled binary, where `require.resolve` cannot see out of the bundle to read a manifest. |
|
|
41
|
+
| `capabilities` + `toInputShape` | The host's own MCP servers, forwarded to BOTH legs: by reference into the Winter leg's `Options.mcpServers`, and registered into the official runtime from the same declaration. One declaration, two registrations, identical canonical names. |
|
|
42
|
+
| `advisor` | The standing server carries Winter's four default tools, `advisor` among them, bound under the official runtime's built-in names (measured: the pin honours an alias key that is not one of its own built-ins — `docs/probes/advisor-alias.md`). `advisor` supplies the REVIEWER; the tool is always registered. |
|
|
43
|
+
| no tool ownership | `src/native-args.ts` and the router's messaging handlers are gone: the definitions, schemas, acceptors, handler factories and the advisor all come from `@yanlinglabs/winter-agent-sdk/tools`, and this package re-exports none of them. |
|
|
30
44
|
|
|
31
45
|
---
|
|
32
46
|
|
|
@@ -36,8 +50,22 @@ Winter SDK before its first publish.
|
|
|
36
50
|
runtime's handle untouched.
|
|
37
51
|
|
|
38
52
|
```ts
|
|
53
|
+
// The host owns the capability tools and hands them over as MCP SERVERS; the router forwards the same
|
|
54
|
+
// servers to BOTH legs and rewrites nothing else (R-8-1). `toInputShape` is the one line of glue the
|
|
55
|
+
// official branch needs — its in-process server constructor takes schemas in its own validator's shape,
|
|
56
|
+
// and this package deliberately depends on no validator.
|
|
57
|
+
const sdk = createRuntimeSdk({
|
|
58
|
+
peers,
|
|
59
|
+
keychain,
|
|
60
|
+
vendoredOfficialRuntime,
|
|
61
|
+
capabilities: [computerServer, browserServer, officeServer], // your own `{ type: "sdk", name, tools, instance }`
|
|
62
|
+
toInputShape: (schema) => jsonSchemaToZodRawShape(schema), // one line, over the validator you already have
|
|
63
|
+
});
|
|
64
|
+
|
|
39
65
|
// The Winter leg: exactly what it always was. No runtime input, so nothing is decided and nothing
|
|
40
|
-
// is stripped — the caller's own `options` object is forwarded by reference
|
|
66
|
+
// is stripped — the caller's own `options` object is forwarded by reference (with no `capabilities`
|
|
67
|
+
// configured, by IDENTITY; with them, a copy whose every other member is still your own object, plus
|
|
68
|
+
// your servers under `mcpServers`).
|
|
41
69
|
for await (const message of sdk.query({ prompt: "hello" })) { /* SdkMessage */ }
|
|
42
70
|
|
|
43
71
|
// The official leg: a `claude-agent` selection, plus what only a host can answer.
|
|
@@ -51,7 +79,13 @@ const query = sdk.query({
|
|
|
51
79
|
official: {
|
|
52
80
|
sessionId: "s-42", // its directory row is `session:s-42`
|
|
53
81
|
base: minimalOsEnvironmentFrom(process.env),
|
|
54
|
-
|
|
82
|
+
// OPTIONAL SINCE 0.0.2: the router materializes the standing server and your capability
|
|
83
|
+
// servers itself. This stays as the escape hatch, and its reach is exactly one key: an entry
|
|
84
|
+
// under the BRAND's own standing-server name replaces the router's (that key reaches no other
|
|
85
|
+
// leg, so overriding it diverges from nothing); an entry naming a forwarded CAPABILITY is a
|
|
86
|
+
// typed refusal on BOTH legs, because that name is on both and a silent override would leave
|
|
87
|
+
// the two branches running different tools under one canonical name.
|
|
88
|
+
// mcpServers: officialMcpServers({ /* … */ }),
|
|
55
89
|
},
|
|
56
90
|
},
|
|
57
91
|
},
|
|
@@ -134,12 +168,19 @@ at all.
|
|
|
134
168
|
**The official branch disables the runtime's remote feature configuration by default** (R-7b-11).
|
|
135
169
|
Every official child gets `TRAFFIC_OPT_OUT_VARIABLES` — the four names are exported, so read them
|
|
136
170
|
rather than trusting this sentence. Measured on the pin, same binary and same options: 25 advertised
|
|
137
|
-
tools with the fetch, 21 without; `DesignSync`, `Monitor`, `PushNotification` and
|
|
138
|
-
`advisor_20260301:advisor` appear only when a CDN answers
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
`RuntimeDirectoryEntry.remoteConfig`.
|
|
171
|
+
tools with the fetch, 21 without; `DesignSync`, `Monitor`, `PushNotification` and Anthropic's own
|
|
172
|
+
API-side `advisor_20260301:advisor` appear only when a CDN answers — that one is the vendor's server
|
|
173
|
+
tool, orthogonal to what follows. A tool surface that moves with no version moving is not a pinned
|
|
174
|
+
artifact, so this is on unless you say otherwise: `remoteConfig: "allow"` (per query on
|
|
175
|
+
`runtime.official`, or deployment-wide on `createRuntimeSdk({ official: { env: { … } } })`) opts back
|
|
176
|
+
in, and the choice is recorded on the session's directory row as `RuntimeDirectoryEntry.remoteConfig`.
|
|
177
|
+
|
|
178
|
+
**Winter's own `advisor` is registered on the official branch too (R-8-1), backing Anthropic's rather
|
|
179
|
+
than being refused.** WS-14 §11's standing MCP server used to throw if a capability list named
|
|
180
|
+
`advisor` — each branch was meant to have its own, unrelated advisor. The user's tool-ownership ruling
|
|
181
|
+
reverses that: `mcp__<brand>__advisor` is reachable on the official branch exactly like
|
|
182
|
+
`send_message`/`list_agents`, independent of whether the CDN-gated API-side one above is present that
|
|
183
|
+
session. `docs/probes/d29-advisor.md` §6 has the full reversal and what it does and does not change.
|
|
143
184
|
|
|
144
185
|
**The materialized-resume PREFERRED door is open for the pinned runtime, by measurement** (R-7b-12).
|
|
145
186
|
WS-17 §8's four probes pass against 0.3.250 on darwin-arm64 and linux-x64, so a handle over that peer
|
|
@@ -242,6 +283,18 @@ was handed, the `claude-resume-<uuid>` staging root SURVIVES — the destination
|
|
|
242
283
|
deleting a live child's `CLAUDE_CONFIG_DIR` is worse than leaving a directory behind. It is locatable
|
|
243
284
|
at `outcome.target.stagingRoot` and belongs to your retention pass.
|
|
244
285
|
|
|
286
|
+
**Compiled hosts must declare their peers' versions.** The version matrix's second probe
|
|
287
|
+
(`resolved-manifest`) resolves a peer's `package.json` by walking up from `createRequire(...).resolve()`
|
|
288
|
+
— which cannot see outside a compiled binary's own bundle (`file:///$bunfs/...`). A host that
|
|
289
|
+
self-spawns its own compiled artifact and whose injected peer exports no version identity of its own
|
|
290
|
+
has nothing left for the matrix to read, and construction refuses. `createRuntimeSdk({ peerVersions:
|
|
291
|
+
{ winterAgentSdk, claudeAgentSdk } })` is the door: supply both from your own vendored
|
|
292
|
+
`VERSIONS.json`, stamped at your own build time (WS-02 §7.1). A declared version is checked FIRST —
|
|
293
|
+
it wins even over a peer that exports its own identity — and still has to satisfy the same
|
|
294
|
+
range/exact-pin checks as either probe; it changes how the identity was discovered, not what counts
|
|
295
|
+
as supported. A host that runs uncompiled (plain `bun`/`node`, source or an ordinary install) never
|
|
296
|
+
needs this field.
|
|
297
|
+
|
|
245
298
|
**"Exactly one runtime owns a session" is a convention here, not a mechanism.** The barrier moves
|
|
246
299
|
ownership only after the destination confirms, and the transcript's producer record is authoritative —
|
|
247
300
|
but the store's writer lease is re-entrant per pid and this router hosts both branches in one process,
|
package/dist/door.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { BrandProfile, CredentialRef, Options, ProviderSelection, Query } from "@yanlinglabs/winter-agent-sdk";
|
|
2
2
|
import type { GlobalMessagingHandle } from "./messaging/router.js";
|
|
3
|
+
import { type ReviewerResolver } from "@yanlinglabs/winter-agent-sdk/tools";
|
|
3
4
|
import type { ContainmentPolicy } from "./official/containment.js";
|
|
4
5
|
import { type OfficialPermissionMode } from "./official/callbacks.js";
|
|
5
6
|
import { type OfficialEnvPolicy } from "./official/env-allowlist.js";
|
|
6
7
|
import { type AuthCredentialPlan } from "./official/auth.js";
|
|
7
8
|
import { type OptionsTemplatePolicy } from "./official/options-template.js";
|
|
9
|
+
import { type InputShapeFactory, type OfficialMcpModule, type WinterMcpServerDescriptor } from "./official/mcp-descriptors.js";
|
|
8
10
|
import type { RuntimeDirectory } from "./seams/directory.js";
|
|
9
11
|
import type { OfficialAdapter, RemoteConfigPolicy } from "./seams/official-adapter.js";
|
|
10
12
|
import type { OfficialQuery, OfficialUserMessage } from "./seams/official-sdk-shapes.js";
|
|
@@ -81,7 +83,24 @@ export interface RouterOfficialInput {
|
|
|
81
83
|
projectKey?: string;
|
|
82
84
|
/** §3's `CLAUDE_CODE_TMPDIR` — the shared per-user temp root the host derives from the brand. */
|
|
83
85
|
sharedTempRoot?: string;
|
|
84
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* §11's servers, already materialized by the host (`officialMcpServers`) — THE ESCAPE HATCH, AND
|
|
88
|
+
* EXACTLY HOW FAR IT REACHES (review r1).
|
|
89
|
+
*
|
|
90
|
+
* Since R-8 the router materializes the standing server and the constructor's capability servers
|
|
91
|
+
* itself (`RuntimeSdkOptions.capabilities` + `toInputShape`), so most hosts never fill this in.
|
|
92
|
+
*
|
|
93
|
+
* * THE STANDING-SERVER KEY (`brand.mcpServerName`): THE HOST WINS. A host that built its own
|
|
94
|
+
* standing server means that server, and the router replacing it would be the translation layer
|
|
95
|
+
* this package is not — the same precedence `remoteConfig` (`:148-149`) and `options` (`:153`)
|
|
96
|
+
* have. It is also a key the OTHER leg never receives from the router, so one branch overriding
|
|
97
|
+
* it diverges from nothing.
|
|
98
|
+
* * A FORWARDED CAPABILITY'S NAME: REFUSED, with the same `RuntimeLaunchInputError` the Winter leg
|
|
99
|
+
* raises for the identical collision, before any runtime is launched. `capabilities` are
|
|
100
|
+
* forwarded to BOTH legs, so a per-key override here would leave this branch running the host's
|
|
101
|
+
* server and the Winter branch running the daemon's under one name — two different tools, one
|
|
102
|
+
* canonical name, no error anywhere.
|
|
103
|
+
*/
|
|
85
104
|
mcpServers?: Readonly<Record<string, unknown>>;
|
|
86
105
|
/** §1 profile 2's staging root. Defaults to the vendor's own `<tmpdir>/claude-resume-<resume id>`. */
|
|
87
106
|
stagingRoot?: string;
|
|
@@ -160,6 +179,48 @@ export interface OfficialLegDeps {
|
|
|
160
179
|
transcriptProjectKey: (cwd: string) => string;
|
|
161
180
|
/** WS-14 §5.1's vendored runtime, from the constructor. A per-query `Options` value wins over it. */
|
|
162
181
|
vendoredOfficialRuntime?: string;
|
|
182
|
+
/**
|
|
183
|
+
* The daemon's capability servers, as DESCRIPTORS (R-8 / R-8-1).
|
|
184
|
+
*
|
|
185
|
+
* DESCRIPTORS RATHER THAN THE WINTER INSTANCES, because this branch does not consume a server — it
|
|
186
|
+
* REGISTERS one, through its own runtime's in-process constructor. `createRuntimeSdk` reads the
|
|
187
|
+
* host's declaration once (`capabilityServerDescriptors`) and the leg materializes it per session,
|
|
188
|
+
* beside the standing server it builds from `messaging`.
|
|
189
|
+
*
|
|
190
|
+
* PER SERVER, UNDER ITS OWN NAME, so `mcp__<server>__<tool>` is the same canonical name on both legs
|
|
191
|
+
* — which is the whole of WS-14 §11's "registered identically into BOTH branches".
|
|
192
|
+
*/
|
|
193
|
+
capabilities?: readonly WinterMcpServerDescriptor[];
|
|
194
|
+
/**
|
|
195
|
+
* The host's JSON-Schema → validator-shape bridge (`RuntimeSdkOptions.toInputShape`).
|
|
196
|
+
*
|
|
197
|
+
* IT IS WHAT SWITCHES THE ROUTER-BUILT SERVERS ON. With it, this leg registers the standing server
|
|
198
|
+
* (the messaging tools) and every capability server itself, and a host stops hand-materializing.
|
|
199
|
+
* Without it and WITH capabilities configured, the leg REFUSES: a session whose capability tools
|
|
200
|
+
* exist on the Winter branch and silently not on this one is the divergence §11 exists to prevent.
|
|
201
|
+
*/
|
|
202
|
+
toInputShape?: InputShapeFactory;
|
|
203
|
+
/**
|
|
204
|
+
* The injected official peer, duck-typed to §11's surface (`createSdkMcpServer`/`tool`).
|
|
205
|
+
*
|
|
206
|
+
* THE SAME OBJECT `peers.claude` ALREADY IS — the seam declares only `query`, because that is all
|
|
207
|
+
* the launch path needs, and this is the one other member of it this package uses. A module without
|
|
208
|
+
* the constructor is `OfficialMcpError`, thrown where the server would have been built.
|
|
209
|
+
*/
|
|
210
|
+
mcpModule?: OfficialMcpModule;
|
|
211
|
+
/**
|
|
212
|
+
* What the host supplies for the STANDING ADVISOR — the reviewer, never the tool (interim review I-5).
|
|
213
|
+
*
|
|
214
|
+
* The advisor is registered on this branch whether or not a host fills this in, because the Winter
|
|
215
|
+
* runtime always advertises `advisor` and two legs whose advertised sets differ by a host option is
|
|
216
|
+
* exactly the divergence WS-14 §11 forbids. What this supplies is the REVIEWER: absent, the default
|
|
217
|
+
* resolver answers `undefined`, which is WS-06 §4's ordinary tool error ("no reviewer configured"),
|
|
218
|
+
* not a throw and not a missing tool.
|
|
219
|
+
*/
|
|
220
|
+
advisor?: {
|
|
221
|
+
resolveReviewer?: ReviewerResolver;
|
|
222
|
+
maxChars?: number;
|
|
223
|
+
};
|
|
163
224
|
/** The adapter's own policy, so a host's `env`/`containment` choices reach the door's own builders. */
|
|
164
225
|
policy?: RouterOfficialPolicy;
|
|
165
226
|
/**
|
package/dist/errors.d.ts
CHANGED
|
@@ -38,12 +38,20 @@ export declare class RuntimeHandoffRequiredError extends RuntimeSdkError {
|
|
|
38
38
|
* cannot run. This one is about the DOOR's own inputs: the session id its directory row is addressed
|
|
39
39
|
* by, the credential its auth family needs, the vendored runtime path §5.1 will not guess. A host
|
|
40
40
|
* catching it knows to fix a call site, not a configuration.
|
|
41
|
+
*
|
|
42
|
+
* THE PREFIX IS LEG-NEUTRAL, AND IT HAD TO BECOME SO (interim review I-7). It read "the official leg
|
|
43
|
+
* needs `<field>`" for as long as the official leg was the only caller — and then R-8 gave the class
|
|
44
|
+
* three refusals that are not: `capabilities` at CONSTRUCTION (before any leg exists, and fatal to a
|
|
45
|
+
* Winter-only host), and `mcpServers` on the WINTER leg. A host with no official peer at all reading
|
|
46
|
+
* "the official leg needs `mcpServers`" is told to look at the one branch it does not use. `leg` names
|
|
47
|
+
* the branch when there IS one, so nothing is lost where the old sentence was right.
|
|
41
48
|
*/
|
|
42
49
|
export declare class RuntimeLaunchInputError extends RuntimeSdkError {
|
|
43
50
|
readonly field: string;
|
|
44
51
|
constructor(args: {
|
|
45
52
|
field: string;
|
|
46
53
|
reason: string;
|
|
54
|
+
leg?: "official" | "winter";
|
|
47
55
|
});
|
|
48
56
|
}
|
|
49
57
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -14,12 +14,10 @@ export { RESUME_STAGING_PREFIX, isResumeStagingRoot, resumeStagingRoot } from ".
|
|
|
14
14
|
export { MATERIALIZED_RESUME_PROBE_REPORTS, materializedResumeReportForPin } from "./store/pinned-probes.js";
|
|
15
15
|
export { EXECUTION_INDIRECTION_ENV_NAMES, EXECUTION_INDIRECTION_ENV_PREFIXES, isExecutionIndirectionVariable } from "./official/env-allowlist.js";
|
|
16
16
|
export { TRAFFIC_OPT_OUT_VARIABLES, TRAFFIC_OPT_OUT_VARIABLE_NAMES } from "./official/env-allowlist.js";
|
|
17
|
-
export { LIST_AGENTS_FIELD_MAX, NATIVE_LIST_AGENTS_OUTPUT_SCHEMA, NATIVE_LIST_AGENTS_SCHEMA, NATIVE_SEND_MESSAGE_SCHEMA, SEND_MESSAGE_SUMMARY_MAX, SEND_MESSAGE_TO_MAX, acceptNativeListAgentsArgs, acceptNativeSendMessageArgs, } from "./native-args.js";
|
|
18
|
-
export type { NativeArgsResult, NativeListAgentsArgs, NativeSendMessageArgs } from "./native-args.js";
|
|
19
17
|
export * from "./seams/index.js";
|
|
20
18
|
export { NotImplementedYet, RuntimeHandoffRequiredError, RuntimeLaunchInputError, RuntimeSdkDisposedError, RuntimeSdkError, RuntimeSdkVersionError, UnaddressableEntryError } from "./errors.js";
|
|
21
19
|
export { createOfficialInputStream, isOfficialQuery, officialCredentialPlan, officialConnectionEnv, officialUserTurn } from "./door.js";
|
|
22
20
|
export type { OfficialInputStream, RouterOfficialInput, RouterOfficialPolicy, RouterQuery } from "./door.js";
|
|
23
21
|
export type { LaneId } from "./errors.js";
|
|
24
|
-
export { createRuntimeMessaging,
|
|
25
|
-
export type { AttachedOfficialSession, AttachedSession, AttachedSessionRegistry, AttachedWinterSession, DirectorySnapshot, GlobalMessagingHandle, GlobalMessagingOptions,
|
|
22
|
+
export { createRuntimeMessaging, createAttachedSessionRegistry } from "./messaging/index.js";
|
|
23
|
+
export type { AttachedOfficialSession, AttachedSession, AttachedSessionRegistry, AttachedWinterSession, DirectorySnapshot, GlobalMessagingHandle, GlobalMessagingOptions, ReplyRequest, RouterMessagingAdapter, RuntimeDirectoryHandle, RuntimeDirectoryOptions, RuntimeDirectoryRecoveryHooks, } from "./messaging/index.js";
|