@yanlinglabs/winter-runtime-sdk 0.0.1
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/LICENSE +21 -0
- package/README.md +249 -0
- package/dist/directory/directory.d.ts +55 -0
- package/dist/directory/entries.d.ts +82 -0
- package/dist/directory/recovery.d.ts +49 -0
- package/dist/door.d.ts +247 -0
- package/dist/errors.d.ts +104 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +6679 -0
- package/dist/messaging/attribution.d.ts +47 -0
- package/dist/messaging/dispatch.d.ts +78 -0
- package/dist/messaging/handlers.d.ts +56 -0
- package/dist/messaging/inbound.d.ts +110 -0
- package/dist/messaging/index.d.ts +39 -0
- package/dist/messaging/official-adapter.d.ts +36 -0
- package/dist/messaging/router.d.ts +101 -0
- package/dist/messaging/sessions.d.ts +49 -0
- package/dist/messaging/winter-adapter.d.ts +47 -0
- package/dist/native-args.d.ts +76 -0
- package/dist/official/adapter.d.ts +88 -0
- package/dist/official/aliases.d.ts +48 -0
- package/dist/official/auth.d.ts +117 -0
- package/dist/official/branding.d.ts +31 -0
- package/dist/official/callbacks.d.ts +143 -0
- package/dist/official/containment.d.ts +130 -0
- package/dist/official/env-allowlist.d.ts +237 -0
- package/dist/official/env-registry-rule.d.ts +12 -0
- package/dist/official/env-registry.d.ts +3 -0
- package/dist/official/errors.d.ts +250 -0
- package/dist/official/index.d.ts +31 -0
- package/dist/official/mcp-descriptors.d.ts +130 -0
- package/dist/official/options-template.d.ts +110 -0
- package/dist/official/spawn-proxy.d.ts +144 -0
- package/dist/official/spool.d.ts +80 -0
- package/dist/official/supervision.d.ts +49 -0
- package/dist/official/sweep.d.ts +65 -0
- package/dist/sdk.d.ts +214 -0
- package/dist/seams/context.d.ts +26 -0
- package/dist/seams/directory-store.d.ts +274 -0
- package/dist/seams/directory.d.ts +46 -0
- package/dist/seams/global-messaging.d.ts +30 -0
- package/dist/seams/handoff.d.ts +77 -0
- package/dist/seams/index.d.ts +11 -0
- package/dist/seams/keychain.d.ts +11 -0
- package/dist/seams/materialized-resume.d.ts +46 -0
- package/dist/seams/messaging-contract.d.ts +29 -0
- package/dist/seams/official-adapter.d.ts +125 -0
- package/dist/seams/official-sdk-shapes.d.ts +126 -0
- package/dist/seams/stubs.d.ts +34 -0
- package/dist/selection/child-runtime.d.ts +81 -0
- package/dist/selection/runtime-selection.d.ts +217 -0
- package/dist/selection/select-runtime.d.ts +213 -0
- package/dist/store/handoff-barrier.d.ts +238 -0
- package/dist/store/index.d.ts +11 -0
- package/dist/store/materialized-resume.d.ts +100 -0
- package/dist/store/pinned-probes.d.ts +17 -0
- package/dist/store/reconcile.d.ts +157 -0
- package/dist/store/temp-continuity.d.ts +92 -0
- package/dist/store/wiring.d.ts +250 -0
- package/dist/vendor-paths.d.ts +21 -0
- package/dist/version-matrix.d.ts +84 -0
- package/docs/conformance-rows.md +195 -0
- package/package.json +65 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { SessionKey } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import type { RuntimeKind, RuntimeSelection, SelectionRefusal } from "../selection/runtime-selection.js";
|
|
3
|
+
import type { SelectionReview } from "../selection/select-runtime.js";
|
|
4
|
+
/**
|
|
5
|
+
* WHAT THE DESTINATION BRANCH WOULD ACTUALLY RUN — Lane D's door, consulted at plan time.
|
|
6
|
+
*
|
|
7
|
+
* WHY THE PLAN CARRIES THIS AT ALL. The barrier moves a session between two runtimes that do not
|
|
8
|
+
* serve the same providers, and until this field existed the plan simply carried the SOURCE's
|
|
9
|
+
* persisted provider fields with the destination's `runtimeKind` stamped over them. That is a plan a
|
|
10
|
+
* host can confirm and a destination must then refuse — a `gemini` row handed to the official
|
|
11
|
+
* runtime, or a Claude OAuth credential handed to Winter, which D28 says never routes there. The
|
|
12
|
+
* refusal arrived at the destination's `confirmInit`, after the lease, the drain and the staging.
|
|
13
|
+
*
|
|
14
|
+
* `refused` IS A TYPED REFUSAL, NEVER A SUBSTITUTION. The barrier does not invent a provider the
|
|
15
|
+
* destination can serve — "deciding a session serves a different provider is the selector's
|
|
16
|
+
* business" (WS-00 §2's D13) — so the plan says why, `plan.steps[7]` carries the same sentence as
|
|
17
|
+
* `knownUnprovable`, and `execute()` offers the visibly lossy fork WS-05 §12 asks for instead of
|
|
18
|
+
* moving ownership.
|
|
19
|
+
*
|
|
20
|
+
* `unreviewed` IS THE HONEST DEFAULT when the host supplies no catalog to review against: nothing was
|
|
21
|
+
* checked, the persisted record travels as it always did, and the plan says so rather than implying a
|
|
22
|
+
* check that did not happen.
|
|
23
|
+
*/
|
|
24
|
+
export type HandoffSelection = {
|
|
25
|
+
kind: "servable";
|
|
26
|
+
selection: RuntimeSelection;
|
|
27
|
+
review: SelectionReview;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "refused";
|
|
30
|
+
refusal: SelectionRefusal;
|
|
31
|
+
detail: string;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "unreviewed";
|
|
34
|
+
selection: RuntimeSelection;
|
|
35
|
+
detail: string;
|
|
36
|
+
};
|
|
37
|
+
/** WS-05 §12's eight steps, by number, so an outcome can name exactly where it stopped. */
|
|
38
|
+
export type HandoffStepNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
39
|
+
export interface HandoffStep {
|
|
40
|
+
step: HandoffStepNumber;
|
|
41
|
+
/** The step's own name, e.g. "acquire the handoff lease" / "compare the canonical tail". */
|
|
42
|
+
name: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether this step is known to be unprovable BEFORE execution starts — a plan a host can be shown
|
|
45
|
+
* honestly ("this will be a fork, here is why") rather than one that looks clean and then refuses.
|
|
46
|
+
*/
|
|
47
|
+
knownUnprovable?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface HandoffPlan {
|
|
50
|
+
session: SessionKey;
|
|
51
|
+
from: RuntimeKind;
|
|
52
|
+
to: RuntimeKind;
|
|
53
|
+
/** The eight steps, in order. */
|
|
54
|
+
steps: HandoffStep[];
|
|
55
|
+
/** WS-13 §8.2's two doors: decorations in the materialized copy, or one labelled handoff entry. */
|
|
56
|
+
decorationDoor: "preferred" | "fallback";
|
|
57
|
+
/** WS-05 §12 step 7 / §9.1: destination Winter ADOPTS the temp root; destination Claude gets a CLONE-COPY. */
|
|
58
|
+
tempContinuity: "adopt" | "clone-copy";
|
|
59
|
+
/** What the DESTINATION would run this session on, or the typed refusal that says it cannot. */
|
|
60
|
+
selection: HandoffSelection;
|
|
61
|
+
}
|
|
62
|
+
export type HandoffOutcome = {
|
|
63
|
+
kind: "resumed";
|
|
64
|
+
selection: RuntimeSelection;
|
|
65
|
+
} | {
|
|
66
|
+
kind: "lossy-fork-offered";
|
|
67
|
+
reason: string;
|
|
68
|
+
step: HandoffStepNumber;
|
|
69
|
+
} | {
|
|
70
|
+
kind: "blocked";
|
|
71
|
+
reason: "repair-required" | "mirror-error" | "lease-held";
|
|
72
|
+
};
|
|
73
|
+
/** WS-05 §12's mechanics. Lane C implements; the spine pins the signature. */
|
|
74
|
+
export interface HandoffBarrier {
|
|
75
|
+
plan(session: SessionKey, to: RuntimeKind): Promise<HandoffPlan>;
|
|
76
|
+
execute(plan: HandoffPlan): Promise<HandoffOutcome>;
|
|
77
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { SeamContext, SeamContextWithDirectory } from "./context.js";
|
|
2
|
+
export type { RuntimeDirectory, DirectoryResolution, DirectoryResolutionContext, RuntimeDirectoryRecovery, RuntimeDirectoryRecoveryStep } from "./directory.js";
|
|
3
|
+
export type { CursorStore, DeliveryRecord, DeliveryRecordStore, HeldMessageRecord, IdleSubscriptionRecord, IdleSubscriptionStore, MailboxStore, NameLeaseRecord, NameLeaseStore, RuntimeDirectoryEntry, RuntimeDirectoryStore, RuntimeTransport, } from "./directory-store.js";
|
|
4
|
+
export { createInMemoryRuntimeDirectoryStore } from "./directory-store.js";
|
|
5
|
+
export type { GlobalMessaging, SendMessageRequest } from "./global-messaging.js";
|
|
6
|
+
export type { HandoffBarrier, HandoffOutcome, HandoffPlan, HandoffStep, HandoffStepNumber } from "./handoff.js";
|
|
7
|
+
export type { KeychainSeam } from "./keychain.js";
|
|
8
|
+
export type { MaterializedResumeDecorator, MaterializedResumeDoor, MaterializedResumeInput, MaterializedResumeProbeId, MaterializedResumeProbeReport, MaterializedResumeProbeResult, MaterializedResumeResult, } from "./materialized-resume.js";
|
|
9
|
+
export type { DeliveryOutcome, GlobalAgentMessage, ListedRuntimeObject, PermissionClassLabel, RuntimeAddress, RuntimeMessagingAdapter, RuntimeObjectKind, SerializedRuntimeAddress, } from "./messaging-contract.js";
|
|
10
|
+
export type { OfficialSdkModule, OfficialSpawnOptions, OfficialSpawnedProcess, } from "./official-sdk-shapes.js";
|
|
11
|
+
export type { EnvInput, OfficialAdapter, OfficialLaunchPlan, OfficialLaunchProfile, OfficialOptions, OfficialQuery, OfficialResumePlan, OfficialSession, OfficialSpawnClaudeCodeProcess, OfficialUserMessage, OptionsTemplateInput, } from "./official-adapter.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CredentialRef } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
export interface KeychainSeam {
|
|
3
|
+
/**
|
|
4
|
+
* The credential material for `ref`, or `undefined` when the host has none for it.
|
|
5
|
+
*
|
|
6
|
+
* `undefined` is a normal answer, not an error: the selector's own `CredentialPresence` is what
|
|
7
|
+
* decides whether a route is available, and a missing credential at spawn is a typed refusal
|
|
8
|
+
* (WS-10's `child-provider-unavailable`), never a throw from the middle of a launch.
|
|
9
|
+
*/
|
|
10
|
+
read(ref: CredentialRef): Promise<string | undefined>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { SessionKey } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import type { RuntimeKind } from "../selection/runtime-selection.js";
|
|
3
|
+
export type MaterializedResumeDoor = "preferred" | "fallback";
|
|
4
|
+
/** The four probes that gate PREFERRED (WS-17 §8's row-129 narrative). */
|
|
5
|
+
export type MaterializedResumeProbeId = "neighbor-file-survival" | "no-wash-back" | "sidecar-round-trip" | "crash-pairs";
|
|
6
|
+
export interface MaterializedResumeProbeResult {
|
|
7
|
+
probe: MaterializedResumeProbeId;
|
|
8
|
+
passed: boolean;
|
|
9
|
+
/** What was observed — recorded whether it passed or not, so "enabled" is always attributable. */
|
|
10
|
+
evidence: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MaterializedResumeProbeReport {
|
|
13
|
+
/** PREFERRED is open only when every probe passed. */
|
|
14
|
+
door: MaterializedResumeDoor;
|
|
15
|
+
results: MaterializedResumeProbeResult[];
|
|
16
|
+
/** ISO-8601. */
|
|
17
|
+
probedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MaterializedResumeInput {
|
|
20
|
+
session: SessionKey;
|
|
21
|
+
/** The runtime the resumed generation will run on — it decides what a decoration may say. */
|
|
22
|
+
to: RuntimeKind;
|
|
23
|
+
/** Path of the materialized copy the destination runtime will read. */
|
|
24
|
+
materializedPath: string;
|
|
25
|
+
/** The handoff note the destination's first generation should see. */
|
|
26
|
+
decoration: {
|
|
27
|
+
kind: "handoff";
|
|
28
|
+
from: RuntimeKind;
|
|
29
|
+
at: string;
|
|
30
|
+
text: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface MaterializedResumeResult {
|
|
34
|
+
door: MaterializedResumeDoor;
|
|
35
|
+
/** The file the destination runtime is pointed at (the materialized copy under PREFERRED). */
|
|
36
|
+
resumePath: string;
|
|
37
|
+
/** True when the canonical transcript was NOT written to — the property PREFERRED exists for. */
|
|
38
|
+
canonicalUntouched: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** WS-13 §8.2's decoration doors. Lane C implements; the spine pins the signature. */
|
|
41
|
+
export interface MaterializedResumeDecorator {
|
|
42
|
+
/** Which door is currently open, per the last probe run. */
|
|
43
|
+
readonly door: MaterializedResumeDoor;
|
|
44
|
+
probe(): Promise<MaterializedResumeProbeReport>;
|
|
45
|
+
decorate(input: MaterializedResumeInput): Promise<MaterializedResumeResult>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RuntimeKind } from "../selection/runtime-selection.js";
|
|
2
|
+
export type { RuntimeKind };
|
|
3
|
+
export type {
|
|
4
|
+
/** WS-10 §11 (messaging companion §4). */
|
|
5
|
+
RuntimeObjectKind,
|
|
6
|
+
/** WS-10 §11's addressing record. `winterSessionId` is the product id (`s_<hex>`, WS-01 §4). */
|
|
7
|
+
RuntimeAddress,
|
|
8
|
+
/** WS-10 §10.2's listing element. */
|
|
9
|
+
ListedRuntimeObject,
|
|
10
|
+
/** WS-15 §6.2 / WS-10 §12's outcome union — ten arms, no eleventh. */
|
|
11
|
+
DeliveryOutcome,
|
|
12
|
+
/** WS-10 §13's inbound classes. */
|
|
13
|
+
PermissionClassLabel,
|
|
14
|
+
/** The fully-resolved, ADDRESSED envelope — never the model-facing `SendMessage` input schema. */
|
|
15
|
+
GlobalAgentMessage,
|
|
16
|
+
/** WS-10 §15's runtime adapter contract. Lane B implements two of these. */
|
|
17
|
+
RuntimeMessagingAdapter, } from "@yanlinglabs/winter-agent-sdk/messaging";
|
|
18
|
+
/**
|
|
19
|
+
* WS-10 §11's opaque serialization: `session:<winterSessionId>` / `agent:<parent>:<childId>`.
|
|
20
|
+
*
|
|
21
|
+
* Runtime kind and backend ids live in the directory record, never trusted from user or model text —
|
|
22
|
+
* which is why a router that parses one of these must overlay `runtimeKind` from its own entry (the
|
|
23
|
+
* subpath's own barrel says so at length; `resolveTarget` does it wherever a listing row is at hand).
|
|
24
|
+
*
|
|
25
|
+
* DECLARED HERE rather than re-exported: the subpath types a serialized address as the bare `string`
|
|
26
|
+
* on `ListedRuntimeObject.address`, and this alias is the router's name for that string — the key
|
|
27
|
+
* every `RuntimeDirectoryStore` method takes.
|
|
28
|
+
*/
|
|
29
|
+
export type SerializedRuntimeAddress = string;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { BrandProfile, SessionStore } from "@yanlinglabs/winter-agent-sdk";
|
|
2
|
+
import type { SerializedRuntimeAddress } from "./messaging-contract.js";
|
|
3
|
+
import type { OfficialOptions, OfficialQuery, OfficialSpawnClaudeCodeProcess, OfficialUserMessage } from "./official-sdk-shapes.js";
|
|
4
|
+
import type { RuntimeSelection } from "../selection/runtime-selection.js";
|
|
5
|
+
export type { OfficialOptions, OfficialQuery, OfficialSpawnClaudeCodeProcess, OfficialUserMessage };
|
|
6
|
+
/**
|
|
7
|
+
* WS-14 §1: `CLAUDE_CONFIG_DIR` has TWO values by launch profile.
|
|
8
|
+
*
|
|
9
|
+
* `fresh-spool` — `<winterHome>/runtimes/official-agent-spool`, the spool a fresh or spool-resident
|
|
10
|
+
* generation lives in. `store-backed-resume` — `<tmpdir>/claude-resume-<uuid>`, a throwaway root for
|
|
11
|
+
* a generation resumed out of the shared session store.
|
|
12
|
+
*/
|
|
13
|
+
export type OfficialLaunchProfile = "fresh-spool" | "store-backed-resume";
|
|
14
|
+
/**
|
|
15
|
+
* R-7b-11: whether this session lets the pinned runtime fetch its REMOTE FEATURE CONFIGURATION.
|
|
16
|
+
*
|
|
17
|
+
* `"deny"` IS THE DEFAULT AND IT IS A PIN QUESTION, not a privacy preference. Measured on 0.3.250,
|
|
18
|
+
* same binary, same options, same endpoint: with the four traffic opt-outs unset the runtime
|
|
19
|
+
* advertises 25 tools; with them set, 21 — `DesignSync`, `Monitor`, `PushNotification` and
|
|
20
|
+
* `advisor_20260301:advisor` appear only when a feature-flag CDN answers. So "the official branch's
|
|
21
|
+
* tool surface" is a property of the artifact ONLY when that fetch is off; with it on, one pin has as
|
|
22
|
+
* many tool surfaces as the CDN has days, and WS-02 §6.1's "a new official version is a reviewed
|
|
23
|
+
* compatibility event" is defeated without any version changing.
|
|
24
|
+
*
|
|
25
|
+
* `"allow"` is the host saying it wants the runtime's own remote configuration anyway — a deliberate,
|
|
26
|
+
* documented choice (WS-14 §3's "unless explicitly configured"), and one that is RECORDED on the
|
|
27
|
+
* session's directory entry (`RuntimeDirectoryEntry.remoteConfig`) so a later reader can tell which
|
|
28
|
+
* of the two surfaces a session actually ran with.
|
|
29
|
+
*/
|
|
30
|
+
export type RemoteConfigPolicy = "deny" | "allow";
|
|
31
|
+
/** What `buildOptions` is given. Every field is something WS-14 §2/§5 pins as normative. */
|
|
32
|
+
export interface OptionsTemplateInput {
|
|
33
|
+
mode: "code" | "dispatch" | "chat";
|
|
34
|
+
selection: RuntimeSelection;
|
|
35
|
+
cwd: string;
|
|
36
|
+
/** The ONE shared store instance/version both branches consume (WS-05 §6, WS-14 §5). */
|
|
37
|
+
sessionStore: SessionStore;
|
|
38
|
+
/** The one shared auto-memory directory, identical for both branches (WS-14 §2). */
|
|
39
|
+
autoMemoryDirectory: string;
|
|
40
|
+
/** Winter-owned names come from here; Claude-mirroring literals stay fixed (WS-01 §5 / D16). */
|
|
41
|
+
brand: BrandProfile;
|
|
42
|
+
/** WS-14 §5.1: the VENDORED runtime — never the user's installed Claude binary. */
|
|
43
|
+
pathToClaudeCodeExecutable: string;
|
|
44
|
+
spawnProxy: OfficialSpawnClaudeCodeProcess;
|
|
45
|
+
profile: OfficialLaunchProfile;
|
|
46
|
+
/** The value this generation is CONFIGURED with; §6's observed value is what gets recorded. */
|
|
47
|
+
configDir: string;
|
|
48
|
+
}
|
|
49
|
+
/** What `buildChildEnv` is given. WS-14 §3: the child env is a REPLACEMENT built from an allowlist. */
|
|
50
|
+
export interface EnvInput {
|
|
51
|
+
selection: RuntimeSelection;
|
|
52
|
+
configDir: string;
|
|
53
|
+
/**
|
|
54
|
+
* The RESOLVED brand profile (I2). Every Winter-owned name in the child environment derives from
|
|
55
|
+
* it — `envName(brand, …)` for anything this branch is told to pass, and the spool/home segments
|
|
56
|
+
* WS-14 §1 builds. Never a literal: the brand gate forbids one, and a reuser's child would
|
|
57
|
+
* otherwise be handed Winter's names.
|
|
58
|
+
*/
|
|
59
|
+
brand: BrandProfile;
|
|
60
|
+
/**
|
|
61
|
+
* Exactly one auth family's variables, fetched from the host's Keychain seam AT SPAWN and never
|
|
62
|
+
* written to disk (WS-14 §12). The adapter must not retain them (§6).
|
|
63
|
+
*/
|
|
64
|
+
credentials: Readonly<Record<string, string>>;
|
|
65
|
+
/** The minimal OS variables the child needs (PATH, HOME, …). Nothing is inherited implicitly. */
|
|
66
|
+
base?: Readonly<Record<string, string>>;
|
|
67
|
+
}
|
|
68
|
+
export interface OfficialLaunchPlan {
|
|
69
|
+
/**
|
|
70
|
+
* The session's canonical directory address (P7b fix round 1, review r1 M3 — a granted seam edit).
|
|
71
|
+
*
|
|
72
|
+
* WITHOUT IT THE DEFAULT ADAPTER RECORDS NOTHING. §6 rule 2's durable record is written onto this
|
|
73
|
+
* session's `RuntimeDirectoryEntry` (`configDir`, `processIdentity`), and the entry is addressed —
|
|
74
|
+
* so an adapter built with no explicit sink had nowhere to write and silently defaulted to a no-op.
|
|
75
|
+
* Carrying the address on the plan is what lets `createOfficialAdapter(context)` default its sink to
|
|
76
|
+
* the directory store the spine already hands it.
|
|
77
|
+
*/
|
|
78
|
+
address: SerializedRuntimeAddress;
|
|
79
|
+
selection: RuntimeSelection;
|
|
80
|
+
prompt: string | AsyncIterable<OfficialUserMessage>;
|
|
81
|
+
options: OfficialOptions;
|
|
82
|
+
profile: OfficialLaunchProfile;
|
|
83
|
+
configDir: string;
|
|
84
|
+
cwd: string;
|
|
85
|
+
/**
|
|
86
|
+
* R-7b-11's choice for THIS session. Absent = `"deny"`, the shipped default.
|
|
87
|
+
*
|
|
88
|
+
* It travels on the plan rather than on the adapter's policy because it is a per-SESSION fact that
|
|
89
|
+
* has to be recorded on the session's own directory row — and because the env this plan carries was
|
|
90
|
+
* built with the same answer, so the two cannot drift apart without the plan saying so.
|
|
91
|
+
*/
|
|
92
|
+
remoteConfig?: RemoteConfigPolicy;
|
|
93
|
+
}
|
|
94
|
+
export interface OfficialResumePlan extends OfficialLaunchPlan {
|
|
95
|
+
/** The backend session id to resume (WS-05 §7's resolution rules apply to finding it). */
|
|
96
|
+
resume: string;
|
|
97
|
+
/** A visible fork rather than a resume (WS-00 §2 D13's "never a silent rewrite"). */
|
|
98
|
+
forkSession?: boolean;
|
|
99
|
+
}
|
|
100
|
+
/** A live official generation. The `query` is the official SDK's own — the stream passes through. */
|
|
101
|
+
export interface OfficialSession {
|
|
102
|
+
readonly query: OfficialQuery;
|
|
103
|
+
/**
|
|
104
|
+
* The `CLAUDE_CONFIG_DIR` this generation actually got, read from `SpawnOptions.env` — never the
|
|
105
|
+
* value that was configured (WS-14 §6 rule 2).
|
|
106
|
+
*
|
|
107
|
+
* THE DURABLE HALF OF THAT RULE IS `RuntimeDirectoryEntry.configDir`, and this field is the live
|
|
108
|
+
* copy beside it. Until fix round 2 this doc comment promised a record with no sink behind it;
|
|
109
|
+
* recording it is Lane A's spawn proxy's job, before the process is returned, and the seam that
|
|
110
|
+
* receives it is the directory store's.
|
|
111
|
+
*/
|
|
112
|
+
readonly configDir: string;
|
|
113
|
+
readonly profile: OfficialLaunchProfile;
|
|
114
|
+
readonly selection: RuntimeSelection;
|
|
115
|
+
/** R-7b-11: which of the pin's two tool surfaces this generation was configured for. */
|
|
116
|
+
readonly remoteConfig: RemoteConfigPolicy;
|
|
117
|
+
}
|
|
118
|
+
/** WS-14 §1–§13. Lane A implements; the spine pins the signature. */
|
|
119
|
+
export interface OfficialAdapter {
|
|
120
|
+
launch(plan: OfficialLaunchPlan): OfficialSession;
|
|
121
|
+
resume(plan: OfficialResumePlan): OfficialSession;
|
|
122
|
+
buildOptions(input: OptionsTemplateInput): OfficialOptions;
|
|
123
|
+
buildChildEnv(input: EnvInput): Record<string, string>;
|
|
124
|
+
readonly spawnProxy: OfficialSpawnClaudeCodeProcess;
|
|
125
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One message in a streaming prompt handed to the official runtime.
|
|
3
|
+
*
|
|
4
|
+
* An open record on purpose: the router never reads a field of one. The real `SDKUserMessage` is a
|
|
5
|
+
* type alias of an object literal, so it carries an implicit index signature and is assignable here.
|
|
6
|
+
*/
|
|
7
|
+
export type OfficialUserMessage = {
|
|
8
|
+
readonly [key: string]: unknown;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The official runtime's query handle, reduced to what the router's own surface touches: the message
|
|
12
|
+
* stream (passed through verbatim — the router never re-shapes it) and WS-14 §9's interrupt.
|
|
13
|
+
*/
|
|
14
|
+
export interface OfficialQuery extends AsyncIterable<unknown> {
|
|
15
|
+
/**
|
|
16
|
+
* WS-14 §9: stops the foreground turn while preserving background agents/workflows.
|
|
17
|
+
*
|
|
18
|
+
* `Promise<unknown>` and not `Promise<void>`: the pinned 0.3.250 resolves an interrupt RESPONSE
|
|
19
|
+
* (`Promise<SDKControlInterruptResponse | undefined>`), which the conformance test caught the first
|
|
20
|
+
* time it ran. The router never reads it, so the seam names it `unknown` rather than re-declaring a
|
|
21
|
+
* response shape it has no use for.
|
|
22
|
+
*/
|
|
23
|
+
interrupt(): Promise<unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** WS-14 §6's spawn options — the ONE member the spec makes load-bearing is `env`. */
|
|
26
|
+
export interface OfficialSpawnOptions {
|
|
27
|
+
command: string;
|
|
28
|
+
args: string[];
|
|
29
|
+
cwd?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The child environment the official runtime is about to use. WS-14 §1/§6: "the host MUST treat the
|
|
32
|
+
* value observed in `SpawnOptions.env.CLAUDE_CONFIG_DIR` as authoritative for the generation, not
|
|
33
|
+
* the value it configured", and it must be durably recorded BEFORE the process is returned.
|
|
34
|
+
*/
|
|
35
|
+
env: Record<string, string | undefined>;
|
|
36
|
+
signal: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The process handle the official runtime expects back.
|
|
40
|
+
*
|
|
41
|
+
* `stdin`/`stdout` are the runtime's own Node stream types and are deliberately NOT re-declared: a
|
|
42
|
+
* hand-written structural stand-in for `Writable`/`Readable` would be both wrong and unnecessary.
|
|
43
|
+
* Lane A holds the precise types inside `src/official/**`, where the optional peer may be imported.
|
|
44
|
+
*/
|
|
45
|
+
export interface OfficialSpawnedProcess {
|
|
46
|
+
stdin: unknown;
|
|
47
|
+
stdout: unknown;
|
|
48
|
+
readonly killed: boolean;
|
|
49
|
+
readonly exitCode: number | null;
|
|
50
|
+
kill(signal: string): boolean;
|
|
51
|
+
on(event: "exit", listener: (code: number | null, signal: string | null) => void): void;
|
|
52
|
+
on(event: "error", listener: (error: Error) => void): void;
|
|
53
|
+
}
|
|
54
|
+
/** WS-14 §6 / D12: the supervised spawn proxy, in the shape the official runtime's own option takes. */
|
|
55
|
+
export type OfficialSpawnClaudeCodeProcess = (options: OfficialSpawnOptions) => OfficialSpawnedProcess;
|
|
56
|
+
/**
|
|
57
|
+
* The official runtime's `Options`, carrying WS-14 §2's normative fields by name and everything else
|
|
58
|
+
* through the index signature.
|
|
59
|
+
*
|
|
60
|
+
* THE INDEX SIGNATURE IS THE POINT: the router pins the fields the SPEC pins and stays out of the way
|
|
61
|
+
* of the ~200 it does not. Lane A builds one of these; nothing ever assigns Anthropic's own `Options`
|
|
62
|
+
* INTO the router (the injected module is typed by `OfficialSdkModule` below), so this type is the
|
|
63
|
+
* contract on both sides of the seam.
|
|
64
|
+
*/
|
|
65
|
+
export interface OfficialOptions {
|
|
66
|
+
[key: string]: unknown;
|
|
67
|
+
/**
|
|
68
|
+
* WS-14 §2: `[]` — the official branch reads no real settings file at any tier.
|
|
69
|
+
*
|
|
70
|
+
* NARROWED TO THE RUNTIME'S OWN THREE VALUES (review r2, NEW-2). `string[]` was WIDER than the
|
|
71
|
+
* runtime accepts, at a field the spec pins normatively: nothing stopped a lane writing
|
|
72
|
+
* `settingSources: ["flag"]`, the compiler was happy and the runtime would not have been. The union
|
|
73
|
+
* is independently authored (three ordinary words), not an Anthropic artifact, and
|
|
74
|
+
* `official-shapes-conformance.test.ts` now pins BOTH directions on it.
|
|
75
|
+
*/
|
|
76
|
+
settingSources?: Array<"user" | "project" | "local">;
|
|
77
|
+
/** WS-14 §2: `{ type: "local", path: "<cwd>/<projectDir>", skipMcpDiscovery: true }`. */
|
|
78
|
+
plugins?: unknown;
|
|
79
|
+
/** WS-14 §2: `{ preset: "claude_code" }` — a Claude-mirroring literal, fixed (WS-01 §5 / D16). */
|
|
80
|
+
systemPrompt?: unknown;
|
|
81
|
+
plansDirectory?: string;
|
|
82
|
+
/** WS-14 §2: `true`, with the ONE shared `autoMemoryDirectory` — identical for both branches. */
|
|
83
|
+
autoMemoryEnabled?: boolean;
|
|
84
|
+
autoMemoryDirectory?: string;
|
|
85
|
+
strictMcpConfig?: boolean;
|
|
86
|
+
/** WS-05 §6 / WS-14 §5: the shared filesystem store instance. Typed `unknown` here because the two SDKs' store types are each other's business; Lane A passes the Winter store through. */
|
|
87
|
+
sessionStore?: unknown;
|
|
88
|
+
/** WS-14 §7: `SendMessage` / `ListAgents` redirected onto the Winter MCP server's handlers. */
|
|
89
|
+
toolAliases?: Record<string, string>;
|
|
90
|
+
/** WS-14 §6: the supervised proxy. */
|
|
91
|
+
spawnClaudeCodeProcess?: OfficialSpawnClaudeCodeProcess;
|
|
92
|
+
/** WS-14 §5.1: the VENDORED runtime — never the user's installed binary. */
|
|
93
|
+
pathToClaudeCodeExecutable?: string;
|
|
94
|
+
cwd?: string;
|
|
95
|
+
/**
|
|
96
|
+
* WS-14 §3: a REPLACEMENT built from an allowlist; nothing is inherited.
|
|
97
|
+
*
|
|
98
|
+
* The value type carries `| undefined` because the pinned runtime's own does — measured by the
|
|
99
|
+
* conformance test, which refused `Record<string, string>`.
|
|
100
|
+
*/
|
|
101
|
+
env?: Record<string, string | undefined>;
|
|
102
|
+
resume?: string;
|
|
103
|
+
forkSession?: boolean;
|
|
104
|
+
/** WS-14 §5.1: MUST NOT be combined with `sessionStore`. */
|
|
105
|
+
persistSession?: boolean;
|
|
106
|
+
/** WS-14 §5.1: MUST NOT be set at all. */
|
|
107
|
+
enableFileCheckpointing?: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The injected official-SDK module, reduced to what the router calls on it.
|
|
111
|
+
*
|
|
112
|
+
* A structural interface rather than `typeof import("@anthropic-ai/claude-agent-sdk")` — see this
|
|
113
|
+
* file's header. **This is a documented departure from the plan's pinned `RuntimeSdkPeers`**, forced
|
|
114
|
+
* by the same optionality the plan itself declares: a `typeof import(…)` of an OPTIONAL peer is a
|
|
115
|
+
* required resolution.
|
|
116
|
+
*
|
|
117
|
+
* GROWING IT IS A SPINE EDIT: a lane that needs another member of the injected module (Lane A will
|
|
118
|
+
* want the MCP-server constructor for WS-14 §11) adds it here, and the conformance test proves the
|
|
119
|
+
* real module still satisfies it.
|
|
120
|
+
*/
|
|
121
|
+
export interface OfficialSdkModule {
|
|
122
|
+
query(params: {
|
|
123
|
+
prompt: string | AsyncIterable<OfficialUserMessage>;
|
|
124
|
+
options?: OfficialOptions;
|
|
125
|
+
}): OfficialQuery;
|
|
126
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SeamContext, SeamContextWithDirectory } from "./context.js";
|
|
2
|
+
import type { RuntimeDirectory } from "./directory.js";
|
|
3
|
+
import type { GlobalMessaging } from "./global-messaging.js";
|
|
4
|
+
import type { HandoffBarrier } from "./handoff.js";
|
|
5
|
+
import type { MaterializedResumeDecorator } from "./materialized-resume.js";
|
|
6
|
+
import type { OfficialAdapter } from "./official-adapter.js";
|
|
7
|
+
/**
|
|
8
|
+
* WS-14 §1–§13 — Lane A.
|
|
9
|
+
*
|
|
10
|
+
* Takes the full context because its real factory needs three things from it that nothing else in the
|
|
11
|
+
* spine reaches: the injected `peers.claude` (to construct a query at all), the `KeychainSeam` (WS-14
|
|
12
|
+
* §12's "fetched at spawn" — `EnvInput.credentials` arrives already built, so the fetch is Lane A's),
|
|
13
|
+
* and the resolved `brand`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function stubOfficialAdapter(context: SeamContextWithDirectory): OfficialAdapter;
|
|
16
|
+
/**
|
|
17
|
+
* WS-15 §6.1 — Lane B.
|
|
18
|
+
*
|
|
19
|
+
* Built FIRST, from the context without a directory in it, because everything else takes the
|
|
20
|
+
* directory. That ordering is why `createRuntimeSdk` hoists it out of the handle's object literal.
|
|
21
|
+
*/
|
|
22
|
+
export declare function stubRuntimeDirectory(context: SeamContext): RuntimeDirectory;
|
|
23
|
+
/** WS-15 §6.2–6.4 — Lane B. Needs the directory (resolution) and the store's new durable sinks (I1). */
|
|
24
|
+
export declare function stubGlobalMessaging(context: SeamContextWithDirectory): GlobalMessaging;
|
|
25
|
+
/** WS-05 §12 — Lane C. Needs the directory and the store to compute `HandoffPlan.from`. */
|
|
26
|
+
export declare function stubHandoffBarrier(context: SeamContextWithDirectory): HandoffBarrier;
|
|
27
|
+
/**
|
|
28
|
+
* WS-13 §8.2 — Lane C.
|
|
29
|
+
*
|
|
30
|
+
* `door` is `"fallback"` and not a throw, deliberately: WS-13 §8.2 makes FALLBACK the always-available
|
|
31
|
+
* door and PREFERRED the one that four probes must open. "Which door is open" therefore has a correct
|
|
32
|
+
* answer before the lane lands, and it is this one — reporting `"preferred"` would be the lie.
|
|
33
|
+
*/
|
|
34
|
+
export declare function stubMaterializedResumeDecorator(context: SeamContextWithDirectory): MaterializedResumeDecorator;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ChildSelectionInput, RuntimeSelection, SelectionRefusal } from "./runtime-selection.js";
|
|
2
|
+
/**
|
|
3
|
+
* R-7b-1: the child's runtime, decided by the CHILD's slot, never inherited from the parent.
|
|
4
|
+
*
|
|
5
|
+
* The `parent` argument is read for nothing at all in this function — see
|
|
6
|
+
* `selectChildRuntimePairing` for the one thing it IS for. It stays in the signature because the
|
|
7
|
+
* plan, the spine's pinned interface and every call site name it, and because a caller holding a
|
|
8
|
+
* parent record is exactly the caller who must be told, at the type level, that the parent does not
|
|
9
|
+
* decide.
|
|
10
|
+
*/
|
|
11
|
+
export declare function selectChildRuntime(parent: RuntimeSelection, child: ChildSelectionInput): RuntimeSelection | SelectionRefusal;
|
|
12
|
+
/**
|
|
13
|
+
* How a parent and its child can talk (WS-15 §6.1, R-7b-1's last clause).
|
|
14
|
+
*
|
|
15
|
+
* `channel` is the bit Lane B's messaging router branches on: a same-runtime pair reaches its child
|
|
16
|
+
* through that runtime's own adapter (a Winter session's `Query.messaging` facet, an official
|
|
17
|
+
* session's own child handles), while a CROSS-RUNTIME pair "talks only through the RuntimeDirectory"
|
|
18
|
+
* — neither runtime can see into the other, so the address must be resolved centrally and the
|
|
19
|
+
* delivery must go through the router's own adapter for the child's runtime.
|
|
20
|
+
*/
|
|
21
|
+
export interface ChildRuntimePairing {
|
|
22
|
+
/** The child's own record — the thing that gets persisted with the child. */
|
|
23
|
+
child: RuntimeSelection;
|
|
24
|
+
/** The parent's runtime at spawn time, recorded for the pairing only. */
|
|
25
|
+
parentRuntime: RuntimeSelection["runtimeKind"];
|
|
26
|
+
/** True when parent and child ended up on different runtimes. */
|
|
27
|
+
crossRuntime: boolean;
|
|
28
|
+
/** `directory` exactly when `crossRuntime` — the two are one fact, spelled for the two readers. */
|
|
29
|
+
channel: "in-runtime" | "directory";
|
|
30
|
+
}
|
|
31
|
+
/** `selectChildRuntime` plus the cross-runtime bit, for the messaging lane. */
|
|
32
|
+
export declare function selectChildRuntimePairing(parent: RuntimeSelection, child: ChildSelectionInput): ChildRuntimePairing | SelectionRefusal;
|
|
33
|
+
/** WS-10's Phase 6.6 amendment: the exact reason prefix a drifted or credential-less child reports. */
|
|
34
|
+
export declare const CHILD_PROVIDER_UNAVAILABLE = "child-provider-unavailable";
|
|
35
|
+
/**
|
|
36
|
+
* The answer to "can this child be resumed on its own record?" (WS-13c §8, WS-10 §15 amendment).
|
|
37
|
+
*
|
|
38
|
+
* `resumed` carries the child's OWN persisted record, by identity — a resume never re-decides and
|
|
39
|
+
* never rewrites. `unavailable` is `retryable: false` because the two things that produce it (a
|
|
40
|
+
* credential that is gone, a mapping that drifted to a different provider) are not transient, and
|
|
41
|
+
* Lane B maps it straight onto `DeliveryOutcome`'s `{ status: "unavailable"; retryable: false; reason }`
|
|
42
|
+
* with NO generation started.
|
|
43
|
+
*/
|
|
44
|
+
export type ChildResumeOutcome = {
|
|
45
|
+
kind: "resumed";
|
|
46
|
+
selection: RuntimeSelection;
|
|
47
|
+
} | {
|
|
48
|
+
kind: "unavailable";
|
|
49
|
+
retryable: false;
|
|
50
|
+
reason: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Re-resolves a child under its OWN recorded model and provider, for a resume or a SendMessage.
|
|
54
|
+
*
|
|
55
|
+
* WHAT IT ASKS, precisely: "is the row this child is RECORDED on still servable?" — not "which row
|
|
56
|
+
* would a fresh decision pick". WS-10's Phase 6.6 amendment requires that "the resolved provider id
|
|
57
|
+
* must equal the recorded one", and the recorded provider is PINNED into the resolution
|
|
58
|
+
* (`provider: record.providerId`), so `candidatesFor` drops every other provider's rows before this
|
|
59
|
+
* function ever sees them: provider equality is enforced by the pin, not by a comparison afterwards.
|
|
60
|
+
* (It used to be a comparison afterwards, which review r1's M1 measured as unreachable — a live-looking
|
|
61
|
+
* guard that no drifted catalog could fire.)
|
|
62
|
+
*
|
|
63
|
+
* The two things the pin does NOT enforce, and which this function therefore checks:
|
|
64
|
+
*
|
|
65
|
+
* 1. THE ROW ITSELF. One provider can serve two rows for one canonical model, so "the pinned
|
|
66
|
+
* provider still serves this model" is weaker than "the recorded row is still there". The
|
|
67
|
+
* recorded `modelRef` is a provider-qualified row key (row 17's whole point), and it must appear
|
|
68
|
+
* among the servable candidates.
|
|
69
|
+
* 2. THE FAMILY. A row key can move between families across a catalog regeneration, and continuing
|
|
70
|
+
* a `claude` child on a row that is now in another family would be "a substitution… a different
|
|
71
|
+
* family", which WS-13c §4 forbids in exactly those words.
|
|
72
|
+
*
|
|
73
|
+
* Either miss is a refusal, never a fall-back onto whichever sibling row still has a credential — that
|
|
74
|
+
* silent re-routing is what would strand a session's continuation on a backend it never ran on.
|
|
75
|
+
*
|
|
76
|
+
* THE RUNTIME IS NEVER RE-DECIDED EITHER. Even when the resolution succeeds, the returned selection is
|
|
77
|
+
* the persisted record, not a new one — "resume and SendMessage follow the child's record, never the
|
|
78
|
+
* parent's current runtime" (R-7b-1), and a resume that re-ran the D13 table could move a live child
|
|
79
|
+
* between runtimes on a credential change.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resumeChildSelection(record: RuntimeSelection, context: Omit<ChildSelectionInput, "slot" | "model" | "provider">): ChildResumeOutcome;
|