@yanlinglabs/winter-agent-runtime 0.0.29 → 0.0.30

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.
Files changed (41) hide show
  1. package/dist/embedded-worker.js +6 -4
  2. package/dist/embedded.js +6 -4
  3. package/dist/engine.d.ts +16 -0
  4. package/dist/{index-jz5d90c6.js → index-51673qbw.js} +151 -120
  5. package/dist/{index-gmxxtqpe.js → index-9df1q7j4.js} +30 -12
  6. package/dist/{index-8jgwp1px.js → index-9s68t0pd.js} +170 -11
  7. package/dist/index-bgeqc7ax.js +52 -0
  8. package/dist/{index-eyddzcgs.js → index-wsfqsrh5.js} +2 -2
  9. package/dist/index-z6s3r4xm.js +903 -0
  10. package/dist/index.js +4 -2
  11. package/dist/mcp/client.d.ts +20 -1
  12. package/dist/mcp/lifecycle.d.ts +8 -0
  13. package/dist/mcp/transports/http.d.ts +10 -1
  14. package/dist/mcp/transports/sse.d.ts +4 -2
  15. package/dist/mcp-auth/account.d.ts +33 -0
  16. package/dist/mcp-auth/config.d.ts +6 -0
  17. package/dist/mcp-auth/constants.d.ts +30 -0
  18. package/dist/mcp-auth/discovery.d.ts +72 -0
  19. package/dist/mcp-auth/engine-wiring.d.ts +52 -0
  20. package/dist/mcp-auth/errors.d.ts +37 -0
  21. package/dist/mcp-auth/fetch-policy.d.ts +33 -0
  22. package/dist/mcp-auth/login.d.ts +59 -0
  23. package/dist/mcp-auth/records.d.ts +73 -0
  24. package/dist/mcp-auth/refresh.d.ts +34 -0
  25. package/dist/mcp-auth/revoke.d.ts +15 -0
  26. package/dist/mcp-auth/session-provider.d.ts +55 -0
  27. package/dist/mcp-auth/store.d.ts +85 -0
  28. package/dist/mcp-auth/test-fixture-as.d.ts +72 -0
  29. package/dist/mcp-auth.d.ts +14 -0
  30. package/dist/mcp-auth.js +493 -0
  31. package/dist/mcp-client.d.ts +12 -2
  32. package/dist/mcp-client.js +15 -2
  33. package/dist/production-wiring.d.ts +6 -0
  34. package/dist/provider/host-credentials.d.ts +48 -0
  35. package/dist/provider/keychain-store.d.ts +29 -1
  36. package/dist/provider/session-provider.d.ts +1 -1
  37. package/dist/store/dialect.d.ts +1 -1
  38. package/dist/testing.js +5 -3
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/package.json +8 -4
@@ -1,14 +1,17 @@
1
- import type { McpServerConfigForProcessTransport } from "@yanlinglabs/winter-agent-sdk";
1
+ import { type McpServerConfigForProcessTransport } from "@yanlinglabs/winter-agent-sdk";
2
2
  import { type ConnectedMcpClient } from "./mcp/client.js";
3
3
  import type { ElicitationAsker } from "./mcp/elicitation.js";
4
+ import type { McpOAuthStore } from "./mcp-auth/store.js";
4
5
  export { McpConnectError, resolveVersionNegotiation, type ConnectedMcpClient, type McpConnectErrorCode, type McpToolInfo, type McpToolAnnotationsInfo, type McpResourceInfo, type McpResourceContent, type McpToolCallResult, } from "./mcp/client.js";
6
+ export type { McpOAuthStore } from "./mcp-auth/store.js";
5
7
  export { createElicitationAsker, type ElicitationAction, type ElicitationAsker, type ElicitationRequestPayload, type ElicitationResultPayload, type ElicitationSender, } from "./mcp/elicitation.js";
6
8
  /**
7
9
  * What a HOST connects with -- deliberately narrower than the runtime's own options: no in-process
8
10
  * (`type: "sdk"`) server (a host that has the server object in hand does not need a protocol client to
9
11
  * reach it), no redirect refusal (the runtime's web search backend's concern) and no list-changed hook
10
12
  * (the runtime's lifecycle owns re-registration). Everything it references is exported from here or from
11
- * `@yanlinglabs/winter-agent-sdk`, so this subpath's declarations reach into nothing private.
13
+ * `@yanlinglabs/winter-agent-sdk` (WS-25's `McpOAuthStore` is re-exported here for `oauthStore`), so this
14
+ * subpath's declarations reach into nothing private.
12
15
  */
13
16
  export interface ConnectMcpServerOptions {
14
17
  /** The server's name: prefixes its diagnostics and is `ConnectedMcpClient.serverName`. */
@@ -23,6 +26,13 @@ export interface ConnectMcpServerOptions {
23
26
  elicitationAsk: ElicitationAsker;
24
27
  /** REQUIRED for a stdio server: the directory it starts in (never the host process's cwd by default). */
25
28
  cwd?: string;
29
+ /**
30
+ * WS-25 (MCP OAuth), narrow: the HOST's sign-in store. Present, an `http`/`sse` server without a static
31
+ * `Authorization` header connects with the stored bearer (from `@yanlinglabs/winter-agent-runtime/mcp-auth`'s
32
+ * records), and a dead sign-in rejects `needs_auth` without a request. A host IS the refresher, so an
33
+ * expired token with a refresh token is refreshed IN THIS PROCESS (single-flight, generation-checked).
34
+ */
35
+ oauthStore?: McpOAuthStore;
26
36
  }
27
37
  /** Connect ONE MCP server and return its live client. Rejects with a typed `McpConnectError` (see its `code`). */
28
38
  export declare function connectMcpServer(opts: ConnectMcpServerOptions): Promise<ConnectedMcpClient>;
@@ -1,20 +1,33 @@
1
1
  import {
2
2
  createElicitationAsker2,
3
+ createSessionAuthProvider,
4
+ mcpSignInHint,
3
5
  McpConnectError2,
4
6
  resolveVersionNegotiation2,
5
7
  connectMcpServer2
6
- } from "./index-8jgwp1px.js";
8
+ } from "./index-9s68t0pd.js";
9
+ import"./index-z6s3r4xm.js";
7
10
 
8
11
  // src/mcp-client.ts
12
+ import { WINTER_BRAND } from "@yanlinglabs/winter-agent-sdk";
9
13
  function connectMcpServer(opts) {
10
14
  return connectMcpServer2({
11
15
  name: opts.name,
12
16
  config: opts.config,
13
17
  connectTimeoutMs: opts.connectTimeoutMs,
14
18
  elicitationAsk: opts.elicitationAsk,
15
- ...opts.cwd !== undefined ? { cwd: opts.cwd } : {}
19
+ ...opts.cwd !== undefined ? { cwd: opts.cwd } : {},
20
+ ...hostAuth(opts)
16
21
  });
17
22
  }
23
+ function hostAuth(opts) {
24
+ const { config, oauthStore } = opts;
25
+ if (oauthStore === undefined || config.type !== "http" && config.type !== "sse")
26
+ return {};
27
+ if (Object.keys(config.headers ?? {}).some((h) => h.toLowerCase() === "authorization"))
28
+ return {};
29
+ return { auth: createSessionAuthProvider({ serverName: opts.name, serverUrl: config.url, oauth: { store: oauthStore, signInHint: (name) => mcpSignInHint(WINTER_BRAND, name) } }) };
30
+ }
18
31
  export {
19
32
  McpConnectError2 as McpConnectError,
20
33
  connectMcpServer,
@@ -11,6 +11,8 @@ import type { CompactionController } from "./compaction/seam.js";
11
11
  import type { StructuredOutputSeam } from "./structured/seam.js";
12
12
  import type { FileCheckpointSink } from "./checkpoint/seam.js";
13
13
  import { type SessionProviderOptions, type SessionProviderWiring } from "./provider/session-provider.js";
14
+ import { type HostCredentialChannel } from "./provider/host-credentials.js";
15
+ import { type McpOAuthStore } from "./mcp-auth/store.js";
14
16
  import type { ProviderStateRecordInput } from "./store/provider-state.js";
15
17
  import type { ClassifierInterface } from "./permissions/auto/engine.js";
16
18
  import { type SlotProviderResolution } from "./provider/slots.js";
@@ -219,6 +221,10 @@ export interface ProductionWiring {
219
221
  workflowsPaths?: readonly string[];
220
222
  }[];
221
223
  extraMcpServerSources: readonly McpServerSource[];
224
+ /** WS-25: where the session reads its MCP sign-ins (the session's Keychain service; the test seam's file under `verify:mcp-oauth`; the host, §7). */
225
+ mcpOAuthStore: McpOAuthStore;
226
+ /** WS-25 §7: present when the host resolves credentials; `runEngine` binds it to its control bridge. */
227
+ hostCredentialChannel?: HostCredentialChannel;
222
228
  initSlashCommands: readonly string[];
223
229
  initSkills: readonly string[];
224
230
  initPlugins: readonly InitPluginInfo[];
@@ -0,0 +1,48 @@
1
+ import { type CredentialRef } from "@yanlinglabs/winter-agent-sdk";
2
+ import { type CredentialMaterial, type CredentialStore } from "@yanlinglabs/winter-provider-runtime";
3
+ import { type KeychainSecretReader } from "./keychain-store.js";
4
+ type KeychainRef = Extract<CredentialRef, {
5
+ kind: "keychain";
6
+ }>;
7
+ /** The narrow bridge shape this needs (the runtime's `RpcBridge` satisfies it). */
8
+ export interface HostRequestSender {
9
+ request<T = unknown>(subtype: string, payload: unknown, opts?: {
10
+ timeoutMs?: number;
11
+ }): Promise<T>;
12
+ }
13
+ /**
14
+ * The session's line to its host, BOUND LATE: production wiring builds the credential stores before the
15
+ * engine exists, and the engine's control bridge is created inside `runEngine`, which binds it here
16
+ * first thing. A request made before the bind waits for it (bounded).
17
+ */
18
+ export interface HostCredentialChannel extends HostRequestSender {
19
+ bind(sender: HostRequestSender): void;
20
+ }
21
+ /** How long one `credential_resolve` may take (the host may be refreshing). */
22
+ export declare const HOST_CREDENTIAL_TIMEOUT_MS = 60000;
23
+ /** How long a request waits for the engine to bind the channel before failing typed. */
24
+ export declare const HOST_CREDENTIAL_BIND_TIMEOUT_MS = 30000;
25
+ export declare function createHostCredentialChannel(opts?: {
26
+ bindTimeoutMs?: number;
27
+ }): HostCredentialChannel;
28
+ export interface HostResolved {
29
+ material: string;
30
+ generation: number;
31
+ expiresAt?: number;
32
+ }
33
+ /**
34
+ * ONE `credential_resolve` round trip. `null` for `not_found` (the session behaves as with an empty
35
+ * Keychain); every other failure throws a typed, ref-named error -- never the material, never the host's
36
+ * own error text.
37
+ */
38
+ export declare function resolveFromHost(sender: HostRequestSender, ref: KeychainRef, minGeneration?: number): Promise<HostResolved | null>;
39
+ /**
40
+ * The Keychain MEMBER of a host-brokered session's credential store. Serves `keychain` refs only (every
41
+ * other kind is `unsupported`, so the composite asks the env/file/inline members as before).
42
+ */
43
+ export declare function createHostBrokeredCredentialStore(sender: HostRequestSender): CredentialStore & {
44
+ refresh(ref: KeychainRef): Promise<CredentialMaterial>;
45
+ };
46
+ /** A host-brokered session's RAW tool-secret reader (the Exa key and friends): the item's string, uninterpreted. */
47
+ export declare function createHostBrokeredSecretReader(sender: HostRequestSender): KeychainSecretReader;
48
+ export {};
@@ -1,4 +1,4 @@
1
- import type { CredentialStore } from "@yanlinglabs/winter-provider-runtime";
1
+ import type { CredentialMaterial, CredentialStore } from "@yanlinglabs/winter-provider-runtime";
2
2
  import { DEFAULT_KEYCHAIN_SERVICE, type CredentialRef } from "@yanlinglabs/winter-agent-sdk";
3
3
  export { DEFAULT_KEYCHAIN_SERVICE };
4
4
  /**
@@ -55,5 +55,33 @@ export type KeychainSecretReader = (ref: Extract<CredentialRef, {
55
55
  * The ref's own `service` wins over the session's, exactly as in `get`.
56
56
  */
57
57
  export declare function createKeychainSecretReader(service?: string, opts?: KeychainCredentialStoreOptions): KeychainSecretReader;
58
+ /**
59
+ * WS-25 (MCP OAuth): a RAW string store over ONE Keychain service -- `read`/`write`/`remove` of an
60
+ * uninterpreted value under an account name. It is the default `McpOAuthStore` (`mcp-auth/store.ts`):
61
+ * an MCP sign-in record is JSON this SDK writes and validates itself (`mcp-auth/records.ts`), not a
62
+ * provider's `CredentialMaterial`, so neither `get` above (which insists on material) nor the reader
63
+ * (read-only) fits. It lives HERE for the same reason the reader does: this is the one file allowed to
64
+ * name the secrets backend.
65
+ *
66
+ * Every failure is the same typed, account-named `io` error the rest of this file raises; the value is
67
+ * never quoted, and neither is the backend's own message (it can quote the item).
68
+ *
69
+ * SIZE (WS-25 spec §4.1, measured -- `mcp-auth/size-gate.test.ts`, opt-in): `Bun.secrets` round-trips a
70
+ * 4 MiB value intact on macOS 26, so an item's size is not what splits a sign-in into two items (an
71
+ * access + refresh token record is a few KiB at most). The 4096-byte limit Claude Code hit is the
72
+ * `security -i` command line's, a tool Winter never drives.
73
+ */
74
+ export interface KeychainRawStore {
75
+ read(account: string): Promise<string | null>;
76
+ write(account: string, value: string): Promise<void>;
77
+ remove(account: string): Promise<void>;
78
+ }
79
+ export declare function createKeychainRawStore(service?: string, opts?: KeychainCredentialStoreOptions): KeychainRawStore;
58
80
  /** `account = "<providerId>:<accountId>"` (R6-10). One helper, so a caller never assembles the key by hand and drifts. */
59
81
  export declare function keychainAccountName(providerId: string, accountId: string): string;
82
+ /**
83
+ * WS-25 §7: the SAME interpretation `get` applies to a Keychain item's string, for a value that arrived
84
+ * another way (a host-brokered session receives the item's string from its host). Typed errors name the
85
+ * ref, never the value.
86
+ */
87
+ export declare function parseStoredCredentialMaterial(raw: string, ref: CredentialRef): CredentialMaterial;
@@ -317,7 +317,7 @@ export declare const DEFAULT_PROVIDER_ACCOUNT_ID = "default";
317
317
  * `keychain-store.ts` resolves `Bun.secrets` LAZILY — a session with no keychain ref never touches
318
318
  * it, and a runtime without it reports a typed failure at the point of use rather than at import.
319
319
  */
320
- export declare function createProductionCredentialStore(config: RuntimeConfig, env: Record<string, string | undefined>, home: string): CredentialStore;
320
+ export declare function createProductionCredentialStore(config: RuntimeConfig, env: Record<string, string | undefined>, home: string, keychainMember?: CredentialStore): CredentialStore;
321
321
  /**
322
322
  * The connection profile for one resolved provider.
323
323
  *
@@ -478,7 +478,7 @@ export declare class TranscriptWriter implements SessionPersistence {
478
478
  private dialectRecord;
479
479
  static readBack(store: SessionStore, key: SessionKey): Promise<SessionStoreEntry[]>;
480
480
  }
481
- export declare const RUNTIME_ENGINE_VERSION = "0.0.29";
481
+ export declare const RUNTIME_ENGINE_VERSION = "0.0.30";
482
482
  export interface ResolvedEngineSession {
483
483
  config: RuntimeConfig;
484
484
  store: SessionPersistence | undefined;
package/dist/testing.js CHANGED
@@ -3,8 +3,10 @@ import {
3
3
  runEngine2,
4
4
  echoProvider2,
5
5
  resolveEngineSession2
6
- } from "./index-jz5d90c6.js";
7
- import"./index-8jgwp1px.js";
6
+ } from "./index-51673qbw.js";
7
+ import"./index-9s68t0pd.js";
8
+ import"./index-z6s3r4xm.js";
9
+ import"./index-bgeqc7ax.js";
8
10
  import"./index-bef62z3r.js";
9
11
  import {
10
12
  registerDefaultChildEngineFactory,
@@ -12,7 +14,7 @@ import {
12
14
  buildProductionWiring,
13
15
  withAutoSkillPermissions,
14
16
  restoreChildRoster
15
- } from "./index-gmxxtqpe.js";
17
+ } from "./index-9df1q7j4.js";
16
18
  import {
17
19
  Queue
18
20
  } from "./index-97t2rmtf.js";
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const RUNTIME_VERSION = "0.0.29";
1
+ export declare const RUNTIME_VERSION = "0.0.30";
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var RUNTIME_VERSION = "0.0.29";
2
+ var RUNTIME_VERSION = "0.0.30";
3
3
  export {
4
4
  RUNTIME_VERSION
5
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yanlinglabs/winter-agent-runtime",
3
- "version": "0.0.29",
3
+ "version": "0.0.30",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "engines": {
@@ -49,6 +49,10 @@
49
49
  "./mcp-client": {
50
50
  "types": "./dist/mcp-client.d.ts",
51
51
  "default": "./dist/mcp-client.js"
52
+ },
53
+ "./mcp-auth": {
54
+ "types": "./dist/mcp-auth.d.ts",
55
+ "default": "./dist/mcp-auth.js"
52
56
  }
53
57
  },
54
58
  "files": [
@@ -69,9 +73,9 @@
69
73
  "@modelcontextprotocol/client": "^2.1.0",
70
74
  "ajv": "^8.20.0",
71
75
  "ignore": "7.0.5",
72
- "@yanlinglabs/winter-agent-sdk": "0.0.29",
73
- "@yanlinglabs/winter-provider-catalog": "0.0.29",
74
- "@yanlinglabs/winter-provider-runtime": "0.0.29"
76
+ "@yanlinglabs/winter-agent-sdk": "0.0.30",
77
+ "@yanlinglabs/winter-provider-runtime": "0.0.30",
78
+ "@yanlinglabs/winter-provider-catalog": "0.0.30"
75
79
  },
76
80
  "devDependencies": {
77
81
  "@modelcontextprotocol/server": "^2.1.0"