@code-yeongyu/senpi 2026.10.26-1 → 2026.10.27-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.
Files changed (179) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/bundle/chunks/{anthropic-messages-M235FJQV.js → anthropic-messages-ODSFJCXR.js} +1 -1
  3. package/dist/bundle/chunks/{args-FBNJOJSR.js → args-SWKJAYQD.js} +1 -1
  4. package/dist/bundle/chunks/{azure-openai-responses-YQRTQ7H6.js → azure-openai-responses-REGXS4XO.js} +1 -1
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  6. package/dist/bundle/chunks/{chunk-DMFAVE5N.js → chunk-4QVORFQ2.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-ZXHLH4MW.js → chunk-5W3DTM2J.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-QYFOHFPS.js → chunk-6CJC6JY4.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-QREKAXKX.js → chunk-6GAMRAVM.js} +5 -5
  10. package/dist/bundle/chunks/{chunk-MSHRIZGT.js → chunk-7IZH2KQX.js} +3 -3
  11. package/dist/bundle/chunks/{chunk-PH3JDRB2.js → chunk-ARSENVDY.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-5KZH6EYQ.js → chunk-CNDPCYNT.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-DYWIFF2Q.js → chunk-CYOHFREV.js} +1 -1
  14. package/dist/bundle/chunks/{chunk-3LPWILUZ.js → chunk-DNDZPKIQ.js} +1 -1
  15. package/dist/bundle/chunks/{chunk-ZLIVZQDY.js → chunk-EQNUL2WB.js} +1 -1
  16. package/dist/bundle/chunks/{chunk-LO5MYLGF.js → chunk-FQDARFHT.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-7KOUQSBX.js → chunk-GPPOPK76.js} +3 -3
  18. package/dist/bundle/chunks/{chunk-I7QWTWVZ.js → chunk-IHKHCWWG.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-MY4ZD3EW.js → chunk-IY4G44MN.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-OQ3WDMB3.js → chunk-JH7MVRNJ.js} +1 -1
  21. package/dist/bundle/chunks/chunk-KBSFTXAT.js +2 -0
  22. package/dist/bundle/chunks/{chunk-UW6M3EXY.js → chunk-KRO63T4Q.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-J5FCH7TI.js → chunk-KTDIIF2F.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-3WP5RFQR.js → chunk-NDNIMC5W.js} +1 -1
  25. package/dist/bundle/chunks/chunk-NXQFBAUI.js +2 -0
  26. package/dist/bundle/chunks/{chunk-CDQPA4FP.js → chunk-ODRGPC5S.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-5FQMNHXV.js → chunk-P5E4EVQF.js} +1 -1
  28. package/dist/bundle/chunks/{chunk-3A3XCLNH.js → chunk-PDG4XWO2.js} +1 -1
  29. package/dist/bundle/chunks/{chunk-5LWUUXMH.js → chunk-PY4ZQHTN.js} +1 -1
  30. package/dist/bundle/chunks/chunk-Q2A2V6NT.js +5 -0
  31. package/dist/bundle/chunks/{chunk-SOXQ42VS.js → chunk-RQ5JTXUC.js} +1 -1
  32. package/dist/bundle/chunks/{chunk-JPGT64RV.js → chunk-TV3UI63P.js} +1 -1
  33. package/dist/bundle/chunks/{chunk-JFQUWEN7.js → chunk-TWHF52G6.js} +4 -4
  34. package/dist/bundle/chunks/{chunk-6U3TBFBA.js → chunk-UJPG4ROT.js} +1 -1
  35. package/dist/bundle/chunks/{chunk-UDM7VO6O.js → chunk-XM36IFP3.js} +1 -1
  36. package/dist/bundle/chunks/{chunk-XQ45JMGN.js → chunk-Z6BREXV3.js} +1 -1
  37. package/dist/bundle/chunks/chunk-ZAS4NBVK.js +410 -0
  38. package/dist/bundle/chunks/{chunk-ADQAPDPV.js → chunk-ZP6JJDYV.js} +1 -1
  39. package/dist/bundle/chunks/{chunk-EZP6AYW2.js → chunk-ZXIAVLJV.js} +88 -88
  40. package/dist/bundle/chunks/{cli-main-55EQA5PS.js → cli-main-36FRZ7ZB.js} +1 -1
  41. package/dist/bundle/chunks/client-CBDPMWZJ.js +2 -0
  42. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZJQGIIRC.js → cloudflare-workers-ai-system-one-WDHT7BBV.js} +1 -1
  43. package/dist/bundle/chunks/cursor-agent.js +1 -1
  44. package/dist/bundle/chunks/devin-agent.js +1 -1
  45. package/dist/bundle/chunks/{dispatch-C2IBP5VV.js → dispatch-W5PENPZM.js} +3 -3
  46. package/dist/bundle/chunks/{google-generative-ai-5G4RIQA6.js → google-generative-ai-FHYFXKLA.js} +1 -1
  47. package/dist/bundle/chunks/{google-vertex-ALD4P27O.js → google-vertex-5DWE5U5K.js} +1 -1
  48. package/dist/bundle/chunks/{help-fast-path-PEIKGCKZ.js → help-fast-path-FETLIF3W.js} +1 -1
  49. package/dist/bundle/chunks/{host-command-657VCQ34.js → host-command-XEB7SHT3.js} +1 -1
  50. package/dist/bundle/chunks/{host-session-command-OV5XDOJK.js → host-session-command-FFN52LXJ.js} +1 -1
  51. package/dist/bundle/chunks/{interactive-mode-MLXSYK2H.js → interactive-mode-5S7NNV2Z.js} +1 -1
  52. package/dist/bundle/chunks/{mistral-conversations-RAE4K2XY.js → mistral-conversations-I2PI7DDF.js} +1 -1
  53. package/dist/bundle/chunks/{multi-session-host-774MACJU.js → multi-session-host-E3OPE6HJ.js} +3 -3
  54. package/dist/bundle/chunks/{openai-codex-responses-3CW4R7TG.js → openai-codex-responses-WSEX6SH7.js} +1 -1
  55. package/dist/bundle/chunks/{openai-completions-5UIJXQUF.js → openai-completions-YCBHTBSS.js} +1 -1
  56. package/dist/bundle/chunks/{openai-responses-2BO44MRW.js → openai-responses-GXNSQF4A.js} +1 -1
  57. package/dist/bundle/chunks/{package-manager-cli-MZHVCX2S.js → package-manager-cli-3XO456VE.js} +1 -1
  58. package/dist/bundle/chunks/{pi-messages-RF6GER4R.js → pi-messages-O6GISIRW.js} +1 -1
  59. package/dist/bundle/chunks/protocol-GLNWYI5G.js +2 -0
  60. package/dist/bundle/chunks/{role-ETSFSDTS.js → role-SHIZQKK4.js} +1 -1
  61. package/dist/bundle/chunks/{rotation-stream-ZMQB4GPO.js → rotation-stream-2PCZWNKF.js} +1 -1
  62. package/dist/bundle/chunks/{rpc-mode-UJXOIZCW.js → rpc-mode-GLWKLTMA.js} +1 -1
  63. package/dist/bundle/chunks/{schedule-command-KA7LFFNK.js → schedule-command-B7RRSANU.js} +1 -1
  64. package/dist/bundle/chunks/{session-control-endpoint-MFWXUR7Z.js → session-control-endpoint-KLE2X4RR.js} +1 -1
  65. package/dist/bundle/chunks/{session-picker-BP33NRSL.js → session-picker-DTGBOXDR.js} +1 -1
  66. package/dist/bundle/chunks/session-worker.js +131 -131
  67. package/dist/bundle/chunks/{typesafe-system-one-GNNZ5O5U.js → typesafe-system-one-XGYJJVSE.js} +1 -1
  68. package/dist/bundle/cli.js +2 -2
  69. package/dist/bundle/index.js +1 -1
  70. package/dist/bundle/rpc-entry.js +1 -1
  71. package/dist/bundle/runtime-manifest.json +1 -1
  72. package/dist/core/agent-session.d.ts +11 -1
  73. package/dist/core/agent-session.js +19 -2
  74. package/dist/core/extensions/builtin/anthropic-subscription/account-context.d.ts +15 -0
  75. package/dist/core/extensions/builtin/anthropic-subscription/account-context.js +53 -0
  76. package/dist/core/extensions/builtin/anthropic-subscription/auth-attempt.d.ts +3 -0
  77. package/dist/core/extensions/builtin/anthropic-subscription/auth-attempt.js +26 -9
  78. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane-boundary.d.ts +16 -0
  79. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane-boundary.js +27 -0
  80. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.d.ts +2 -13
  81. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +3 -26
  82. package/dist/core/extensions/builtin/anthropic-subscription/errors.js +3 -2
  83. package/dist/core/extensions/builtin/anthropic-subscription/guidance.d.ts +6 -1
  84. package/dist/core/extensions/builtin/anthropic-subscription/guidance.js +1 -1
  85. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +13 -2
  86. package/dist/core/extensions/builtin/compaction/index.js +7 -1
  87. package/dist/core/extensions/builtin/herdr/index.js +9 -5
  88. package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +6 -0
  89. package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +25 -0
  90. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +3 -3
  91. package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +50 -19
  92. package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +4 -3
  93. package/dist/core/extensions/builtin/mcp/auth/oauth.js +19 -12
  94. package/dist/core/extensions/builtin/mcp/modern/consent-queue.js +1 -0
  95. package/dist/core/extensions/builtin/mcp/modern/dispatch.js +1 -0
  96. package/dist/core/extensions/builtin/mcp/modern/parameter-headers.d.ts +4 -1
  97. package/dist/core/extensions/builtin/mcp/modern/parameter-headers.js +33 -35
  98. package/dist/core/extensions/builtin/mcp/modern/request.js +6 -2
  99. package/dist/core/extensions/builtin/mcp/modern/transport.d.ts +2 -0
  100. package/dist/core/extensions/builtin/mcp/modern/transport.js +4 -2
  101. package/dist/core/extensions/builtin/mcp/sdk.lazy.d.ts +2 -0
  102. package/dist/core/extensions/builtin/mcp/sdk.lazy.js +2 -0
  103. package/dist/core/extensions/builtin/mcp/transport-sdk.js +12 -1
  104. package/dist/core/extensions/builtin/terminal/extension-state.js +2 -1
  105. package/dist/core/extensions/builtin/vertex-model-garden/auth.d.ts +9 -0
  106. package/dist/core/extensions/builtin/vertex-model-garden/auth.js +17 -1
  107. package/dist/core/extensions/builtin/websearch/websearch/providers/google.d.ts +6 -0
  108. package/dist/core/extensions/builtin/websearch/websearch/providers/google.js +6 -1
  109. package/dist/core/extensions/types.d.ts +2 -0
  110. package/dist/core/lifecycle-children.d.ts +3 -1
  111. package/dist/core/lifecycle-children.js +79 -15
  112. package/dist/core/lifecycle-record.js +1 -24
  113. package/dist/core/lifecycle-session-binding.js +2 -1
  114. package/dist/core/lifecycle-wait-items.d.ts +17 -0
  115. package/dist/core/lifecycle-wait-items.js +72 -0
  116. package/dist/core/model-runtime.js +6 -1
  117. package/dist/core/provider-api-key-auth.d.ts +6 -1
  118. package/dist/core/provider-api-key-auth.js +11 -4
  119. package/dist/core/provider-composer.d.ts +8 -1
  120. package/dist/core/provider-composer.js +7 -3
  121. package/dist/core/sdk.js +4 -1
  122. package/dist/core/session-activity.js +2 -0
  123. package/dist/core/session-lifecycle-types.d.ts +20 -4
  124. package/dist/core/session-lifecycle.js +35 -4
  125. package/dist/core/structured-session-lane.d.ts +33 -0
  126. package/dist/core/structured-session-lane.js +62 -0
  127. package/dist/core/work-custody-record.d.ts +2 -1
  128. package/dist/core/work-custody-record.js +2 -0
  129. package/dist/core/work-obligations.d.ts +1 -1
  130. package/dist/core/work-obligations.js +8 -2
  131. package/dist/modes/interactive/interactive-mode.d.ts +2 -1
  132. package/dist/modes/interactive/interactive-mode.js +2 -1
  133. package/dist/modes/json-event.d.ts +79 -1
  134. package/dist/modes/json-event.js +79 -1
  135. package/dist/modes/rpc/compact-commit-dependencies.d.ts +13 -0
  136. package/dist/modes/rpc/compact-commit-dependencies.js +48 -0
  137. package/dist/modes/rpc/compact-content-index.d.ts +84 -0
  138. package/dist/modes/rpc/compact-content-index.js +243 -0
  139. package/dist/modes/rpc/compact-content-store.d.ts +10 -43
  140. package/dist/modes/rpc/compact-content-store.js +61 -163
  141. package/dist/modes/rpc/compact-index-pages.d.ts +12 -0
  142. package/dist/modes/rpc/compact-index-pages.js +31 -0
  143. package/dist/modes/rpc/compact-read-lease.d.ts +15 -0
  144. package/dist/modes/rpc/compact-read-lease.js +40 -0
  145. package/dist/modes/rpc/compact-session-state.d.ts +14 -63
  146. package/dist/modes/rpc/compact-session-state.js +69 -51
  147. package/dist/modes/rpc/compact-spool-dir.d.ts +4 -1
  148. package/dist/modes/rpc/compact-spool-dir.js +41 -8
  149. package/dist/modes/rpc/compact-spool-storage.d.ts +58 -0
  150. package/dist/modes/rpc/compact-spool-storage.js +195 -0
  151. package/dist/modes/rpc/compact-storage-io.d.ts +2 -1
  152. package/dist/modes/rpc/compact-storage-io.js +7 -1
  153. package/dist/modes/rpc/compact-text-roots.d.ts +22 -0
  154. package/dist/modes/rpc/compact-text-roots.js +138 -0
  155. package/dist/modes/rpc/compact-text-view.d.ts +22 -0
  156. package/dist/modes/rpc/compact-text-view.js +16 -0
  157. package/dist/modes/rpc/compact-transition.d.ts +41 -0
  158. package/dist/modes/rpc/compact-transition.js +12 -0
  159. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  160. package/dist/modes/rpc/connection-handler.js +12 -6
  161. package/dist/modes/rpc/host-ensure-start.js +5 -3
  162. package/dist/modes/rpc/security-presentations.js +2 -1
  163. package/dist/modes/rpc/session-binding.js +10 -0
  164. package/dist/modes/rpc/session-event-writer.d.ts +2 -0
  165. package/dist/modes/rpc/session-event-writer.js +2 -0
  166. package/dist/modes/rpc/session-record-stream.d.ts +3 -3
  167. package/dist/modes/rpc/session-record-stream.js +3 -3
  168. package/dist/modes/rpc/session-structured-lanes.d.ts +12 -0
  169. package/dist/modes/rpc/session-structured-lanes.js +24 -0
  170. package/dist/modes/rpc/session-worker-client.js +6 -5
  171. package/dist/modes/rpc/structured-session-records.d.ts +12 -0
  172. package/dist/modes/rpc/structured-session-records.js +88 -0
  173. package/docs/extensions.md +7 -1
  174. package/docs/rpc.md +17 -2
  175. package/package.json +6 -6
  176. package/dist/bundle/chunks/chunk-GQJYNFMO.js +0 -2
  177. package/dist/bundle/chunks/chunk-VICDRG3J.js +0 -410
  178. package/dist/bundle/chunks/chunk-VL7O5PO4.js +0 -5
  179. package/dist/bundle/chunks/client-LOS6GSEW.js +0 -2
@@ -1,6 +1,7 @@
1
1
  import type { FetchLike, Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
2
2
  import { type JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
3
3
  import { type ModernClientInfo } from "./wire.ts";
4
+ import type { McpLogger } from "../log.ts";
4
5
  export type ModernHttpTransportOptions = {
5
6
  readonly url: string | URL;
6
7
  readonly fetch: FetchLike;
@@ -8,6 +9,7 @@ export type ModernHttpTransportOptions = {
8
9
  readonly clientCapabilities: Readonly<Record<string, unknown>>;
9
10
  readonly protocolVersion?: string;
10
11
  readonly headers?: RequestInit["headers"];
12
+ readonly logger?: Pick<McpLogger, "warn">;
11
13
  };
12
14
  export declare class ModernTransportError extends Error {
13
15
  constructor(message: string);
@@ -4,7 +4,7 @@ import { AuthError } from "../errors.js";
4
4
  import { sanitizeModernMessage } from "./diagnostics.js";
5
5
  import { McpMrtrError } from "./errors.js";
6
6
  import { getModernDispatchGuard, modernDispatchGuard } from "./request.js";
7
- import { clearMcpParameterHeaders, ModernParameterHeaders } from "./parameter-headers.js";
7
+ import { clearMcpParameterHeaders, ModernParameterHeaders, ParameterHeaderValidationError, } from "./parameter-headers.js";
8
8
  export class ModernTransportError extends Error {
9
9
  constructor(message) {
10
10
  super(message);
@@ -119,6 +119,8 @@ export class ModernHttpTransport {
119
119
  }
120
120
  }
121
121
  catch (error) {
122
+ if (error instanceof ParameterHeaderValidationError)
123
+ throw error;
122
124
  const failure = error instanceof McpMrtrError || error instanceof AuthError
123
125
  ? error
124
126
  : new McpMrtrError("MCP_MRTR_TRANSPORT_FAILED");
@@ -142,7 +144,7 @@ export class ModernHttpTransport {
142
144
  ...incoming,
143
145
  result: {
144
146
  ...result,
145
- tools: this.#parameterHeaders.filterTools(result.tools, this.#toolLists.get(incoming.id) === true),
147
+ tools: this.#parameterHeaders.filterTools(result.tools, this.#toolLists.get(incoming.id) === true, (message) => this.#options.logger?.warn(message)),
146
148
  },
147
149
  };
148
150
  }
@@ -21,6 +21,8 @@ export declare const loadMcpSdkZodCompat: () => Promise<typeof import("@modelcon
21
21
  export declare const loadMcpSdkStdioTransport: () => Promise<typeof import("@modelcontextprotocol/sdk/client/stdio.js")>;
22
22
  /** SDK-owned protocol schemas for elicitation and modern request results. */
23
23
  export declare const loadMcpSdkTypes: () => Promise<typeof import("@modelcontextprotocol/sdk/types.js")>;
24
+ /** SDK-owned request defaults, loaded only by negotiated modern operations. */
25
+ export declare const loadMcpSdkProtocol: () => Promise<typeof import("@modelcontextprotocol/sdk/shared/protocol.js")>;
24
26
  /** OAuth 2.1 discovery, authorization, token exchange and refresh. */
25
27
  export declare const loadMcpSdkAuth: () => Promise<typeof import("@modelcontextprotocol/sdk/client/auth.js")>;
26
28
  /**
@@ -42,6 +42,8 @@ export const loadMcpSdkZodCompat = memoizeLoader(() => import("@modelcontextprot
42
42
  export const loadMcpSdkStdioTransport = memoizeLoader(() => import("@modelcontextprotocol/sdk/client/stdio.js"));
43
43
  /** SDK-owned protocol schemas for elicitation and modern request results. */
44
44
  export const loadMcpSdkTypes = memoizeLoader(() => import("@modelcontextprotocol/sdk/types.js"));
45
+ /** SDK-owned request defaults, loaded only by negotiated modern operations. */
46
+ export const loadMcpSdkProtocol = memoizeLoader(() => import("@modelcontextprotocol/sdk/shared/protocol.js"));
45
47
  let authModule;
46
48
  /** OAuth 2.1 discovery, authorization, token exchange and refresh. */
47
49
  export const loadMcpSdkAuth = memoizeLoader(async () => {
@@ -89,6 +89,17 @@ function pipeStderr(transport, logger, sink, protocol) {
89
89
  const stderr = transport.stderr;
90
90
  if (stderr === undefined || stderr === null)
91
91
  return;
92
+ const start = transport.start.bind(transport);
93
+ transport.start = async () => {
94
+ const onclose = transport.onclose;
95
+ transport.onclose = () => {
96
+ stderrEnded = true;
97
+ if (protocol.version === undefined)
98
+ protocol.resolveStdioDiagnostics?.(false);
99
+ onclose?.();
100
+ };
101
+ await start();
102
+ };
92
103
  const logLine = (line) => {
93
104
  // Arbitrary server text may echo private messages, schemas, or answers. Keep diagnostic
94
105
  // events and allowlisted system error codes, never untrusted payload text under enforcement.
@@ -127,7 +138,7 @@ function pipeStderr(transport, logger, sink, protocol) {
127
138
  return;
128
139
  const text = Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk;
129
140
  if (!protocol.legacy && !protocol.privateForms) {
130
- // Only legacy-positive negotiation may release startup diagnostics.
141
+ // Release only after legacy classification or an unclassified child's exit.
131
142
  undecided += text.slice(0, Math.max(0, 512 * 1024 - undecided.length));
132
143
  return;
133
144
  }
@@ -58,8 +58,9 @@ export function bundleSinks(pi, state) {
58
58
  pi.events?.emit(WAKE_SOURCE_STATE_EVENT, {
59
59
  source: "terminal-monitors",
60
60
  activeCount: snapshot.length,
61
+ // The stable "mon_" id: runtime ids churn on restore, and item ids feed the custody signature.
61
62
  monitors: snapshot.map((entry) => ({
62
- id: entry.id,
63
+ id: entry.monitorId ?? entry.id,
63
64
  description: entry.description,
64
65
  startedAtMs: entry.startedAtMs,
65
66
  })),
@@ -8,9 +8,18 @@ export declare const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application defaul
8
8
  * gcloud tooling too, so the lane is selectable but never outranks a provider the
9
9
  * user configured, and it reports nothing while the chain is absent — the failure
10
10
  * belongs at selection time, not at the first request.
11
+ *
12
+ * The target project is resolved here so it rides the ambient auth result into
13
+ * the request env: process env first, then the sibling google-vertex profile,
14
+ * which shares this ADC chain and already names the project the user entered at
15
+ * its login. With neither source the lane stays available and the request-time
16
+ * ADC fallbacks (quota project, discovered project) decide, so a missing project
17
+ * remains a first-request failure with the actionable error, not a hidden lane.
11
18
  */
12
19
  export declare function resolveVertexModelGardenAmbient(input: {
13
20
  ctx: AuthContext;
14
21
  signal: AbortSignal;
22
+ /** Read-only env of another provider's stored credential; routing metadata only, never keys. */
23
+ storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
15
24
  }): Promise<AuthResult | undefined>;
16
25
  //# sourceMappingURL=auth.d.ts.map
@@ -7,6 +7,13 @@ export const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application default creden
7
7
  * gcloud tooling too, so the lane is selectable but never outranks a provider the
8
8
  * user configured, and it reports nothing while the chain is absent — the failure
9
9
  * belongs at selection time, not at the first request.
10
+ *
11
+ * The target project is resolved here so it rides the ambient auth result into
12
+ * the request env: process env first, then the sibling google-vertex profile,
13
+ * which shares this ADC chain and already names the project the user entered at
14
+ * its login. With neither source the lane stays available and the request-time
15
+ * ADC fallbacks (quota project, discovered project) decide, so a missing project
16
+ * remains a first-request failure with the actionable error, not a hidden lane.
10
17
  */
11
18
  export async function resolveVertexModelGardenAmbient(input) {
12
19
  input.signal.throwIfAborted();
@@ -14,6 +21,15 @@ export async function resolveVertexModelGardenAmbient(input) {
14
21
  input.signal.throwIfAborted();
15
22
  if (!(await input.ctx.fileExists(path)))
16
23
  return undefined;
17
- return { auth: {}, source: VERTEX_MODEL_GARDEN_ADC_SOURCE, ambient: true };
24
+ input.signal.throwIfAborted();
25
+ const project = (await input.ctx.env("GOOGLE_CLOUD_PROJECT")) ??
26
+ (await input.ctx.env("GCLOUD_PROJECT")) ??
27
+ (await input.storedProviderEnv?.("google-vertex"))?.GOOGLE_CLOUD_PROJECT;
28
+ return {
29
+ auth: {},
30
+ ...(project ? { env: { GOOGLE_CLOUD_PROJECT: project } } : {}),
31
+ source: VERTEX_MODEL_GARDEN_ADC_SOURCE,
32
+ ambient: true,
33
+ };
18
34
  }
19
35
  //# sourceMappingURL=auth.js.map
@@ -1,3 +1,9 @@
1
1
  import type { ProviderModule } from "./shared.ts";
2
+ /**
3
+ * Catalog GA flash alias: it tracks the current stable flash model, so the default
4
+ * cannot age into a retired generation (gemini-2.5-flash 404s for new accounts).
5
+ * An entry-level `model` still overrides it.
6
+ */
7
+ export declare const DEFAULT_MODEL = "gemini-flash-latest";
2
8
  export declare const googleProvider: ProviderModule;
3
9
  //# sourceMappingURL=google.d.ts.map
@@ -1,6 +1,11 @@
1
1
  import { providerUrl } from "../provider-endpoints.js";
2
2
  import { appendDomainFilters, collect, contentHeaders, getArray, getNumber, getObject, getString, result, withConfigHeaders, } from "./shared.js";
3
- const DEFAULT_MODEL = "gemini-2.5-flash";
3
+ /**
4
+ * Catalog GA flash alias: it tracks the current stable flash model, so the default
5
+ * cannot age into a retired generation (gemini-2.5-flash 404s for new accounts).
6
+ * An entry-level `model` still overrides it.
7
+ */
8
+ export const DEFAULT_MODEL = "gemini-flash-latest";
4
9
  function generateContentUrl(config) {
5
10
  const root = providerUrl(config).replace(/\/+$/, "");
6
11
  if (root.endsWith(":generateContent"))
@@ -2369,6 +2369,8 @@ export interface ProviderConfig {
2369
2369
  resolve(input: {
2370
2370
  ctx: AuthContext;
2371
2371
  signal: AbortSignal;
2372
+ /** Read-only env of another provider's stored credential; routing metadata only, never keys. */
2373
+ storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
2372
2374
  }): Promise<AuthResult | undefined>;
2373
2375
  };
2374
2376
  /** OAuth provider for /login support. The `id` is set automatically from the provider name. */
@@ -1,4 +1,4 @@
1
- import type { ChildLifecycleReport, SessionLifecycleState } from "./session-lifecycle-types.ts";
1
+ import type { ChildLifecycleReport, LifecycleWaits, SessionLifecycleState } from "./session-lifecycle-types.ts";
2
2
  import type { SessionEntry } from "./session-manager.ts";
3
3
  export interface ChildLifecycleStore {
4
4
  readonly entries: readonly SessionEntry[];
@@ -15,4 +15,6 @@ export declare class LifecycleChildren {
15
15
  private accept;
16
16
  }
17
17
  export declare function readLifecycleState(value: unknown): SessionLifecycleState | undefined;
18
+ /** The one reader of a durable or reported `waitingOn`; named detail never invalidates the counts. */
19
+ export declare function readWaits(value: unknown): LifecycleWaits | undefined;
18
20
  //# sourceMappingURL=lifecycle-children.d.ts.map
@@ -1,3 +1,5 @@
1
+ import { readHumanWait } from "./lifecycle-attention.js";
2
+ import { readWaitItems } from "./lifecycle-wait-items.js";
1
3
  import { isRecord } from "./work-custody-record.js";
2
4
  export class LifecycleChildren {
3
5
  constructor(store) {
@@ -60,6 +62,80 @@ export function readLifecycleState(value) {
60
62
  return undefined;
61
63
  }
62
64
  }
65
+ /** The one reader of a durable or reported `waitingOn`; named detail never invalidates the counts. */
66
+ export function readWaits(value) {
67
+ if (!isRecord(value) || typeof value.children !== "number")
68
+ return undefined;
69
+ const background = [];
70
+ if (Array.isArray(value.background)) {
71
+ for (const source of value.background) {
72
+ if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
73
+ continue;
74
+ background.push({
75
+ source: source.source,
76
+ activeCount: source.activeCount,
77
+ ...readWaitItems(source.items, source.omittedItems),
78
+ ...(typeof source.retryAtMs === "number" ? { retryAtMs: source.retryAtMs } : {}),
79
+ });
80
+ }
81
+ }
82
+ const human = Array.isArray(value.human)
83
+ ? value.human.flatMap((request) => {
84
+ const wait = readHumanWait(request);
85
+ return wait ? [wait] : [];
86
+ })
87
+ : [];
88
+ const childSources = [];
89
+ if (Array.isArray(value.childSources))
90
+ for (const source of value.childSources) {
91
+ if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
92
+ continue;
93
+ childSources.push({
94
+ source: source.source,
95
+ activeCount: source.activeCount,
96
+ ...readWaitItems(source.items, source.omittedItems),
97
+ });
98
+ }
99
+ const reports = [];
100
+ if (Array.isArray(value.childReports))
101
+ for (const report of value.childReports) {
102
+ if (!isRecord(report))
103
+ continue;
104
+ const state = readLifecycleState(report.state);
105
+ if (!state ||
106
+ typeof report.taskId !== "string" ||
107
+ typeof report.childSessionId !== "string" ||
108
+ typeof report.runEpoch !== "number" ||
109
+ !Number.isSafeInteger(report.runEpoch) ||
110
+ report.runEpoch < 0)
111
+ continue;
112
+ reports.push({
113
+ taskId: report.taskId,
114
+ childSessionId: report.childSessionId,
115
+ runEpoch: report.runEpoch,
116
+ state,
117
+ ...(typeof report.label === "string" ? { label: report.label } : {}),
118
+ ...(typeof report.since === "string" && Number.isFinite(Date.parse(report.since))
119
+ ? { since: report.since }
120
+ : {}),
121
+ });
122
+ }
123
+ reports.sort((a, b) => (a.taskId < b.taskId ? -1 : a.taskId > b.taskId ? 1 : 0));
124
+ const childReportsOmitted = Math.max(0, reports.length - 32) +
125
+ (typeof value.childReportsOmitted === "number" &&
126
+ Number.isSafeInteger(value.childReportsOmitted) &&
127
+ value.childReportsOmitted > 0
128
+ ? value.childReportsOmitted
129
+ : 0);
130
+ return {
131
+ children: value.children,
132
+ background,
133
+ human,
134
+ ...(childSources.length ? { childSources } : {}),
135
+ ...(reports.length ? { childReports: reports.slice(0, 32) } : {}),
136
+ ...(childReportsOmitted ? { childReportsOmitted } : {}),
137
+ };
138
+ }
63
139
  function readChildReport(value) {
64
140
  if (!isRecord(value))
65
141
  return undefined;
@@ -75,27 +151,15 @@ function readChildReport(value) {
75
151
  value.generation < 0)
76
152
  return undefined;
77
153
  const terminal = readTerminal(value.terminal);
78
- let waitingOn;
79
- if (isRecord(value.waitingOn) && typeof value.waitingOn.children === "number") {
80
- const background = [];
81
- if (Array.isArray(value.waitingOn.background))
82
- for (const item of value.waitingOn.background) {
83
- if (!isRecord(item) || typeof item.source !== "string" || typeof item.activeCount !== "number")
84
- continue;
85
- background.push({
86
- source: item.source,
87
- activeCount: item.activeCount,
88
- ...(typeof item.retryAtMs === "number" ? { retryAtMs: item.retryAtMs } : {}),
89
- });
90
- }
91
- waitingOn = { children: value.waitingOn.children, background, human: [] };
92
- }
154
+ const waitingOn = readWaits(value.waitingOn);
93
155
  return {
94
156
  taskId: value.taskId,
95
157
  childSessionId: value.childSessionId,
96
158
  runEpoch: value.runEpoch,
97
159
  generation: value.generation,
98
160
  state,
161
+ ...(typeof value.label === "string" ? { label: value.label } : {}),
162
+ ...(typeof value.since === "string" && Number.isFinite(Date.parse(value.since)) ? { since: value.since } : {}),
99
163
  ...(waitingOn ? { waitingOn } : {}),
100
164
  ...(terminal === undefined ? {} : { terminal }),
101
165
  };
@@ -1,5 +1,5 @@
1
1
  import { readHumanWait } from "./lifecycle-attention.js";
2
- import { readLifecycleState } from "./lifecycle-children.js";
2
+ import { readLifecycleState, readWaits } from "./lifecycle-children.js";
3
3
  import { readLastStop } from "./lifecycle-stop.js";
4
4
  import { isRecord } from "./work-custody-record.js";
5
5
  /** Restore the wire snapshot and its private high-water marks from owned JSONL. */
@@ -97,29 +97,6 @@ function readTurnEnd(value) {
97
97
  return undefined;
98
98
  }
99
99
  }
100
- function readWaits(value) {
101
- if (!isRecord(value) || typeof value.children !== "number")
102
- return undefined;
103
- const background = [];
104
- if (Array.isArray(value.background)) {
105
- for (const source of value.background) {
106
- if (!isRecord(source) || typeof source.source !== "string" || typeof source.activeCount !== "number")
107
- continue;
108
- background.push({
109
- source: source.source,
110
- activeCount: source.activeCount,
111
- ...(typeof source.retryAtMs === "number" ? { retryAtMs: source.retryAtMs } : {}),
112
- });
113
- }
114
- }
115
- const human = Array.isArray(value.human)
116
- ? value.human.flatMap((request) => {
117
- const wait = readHumanWait(request);
118
- return wait ? [wait] : [];
119
- })
120
- : [];
121
- return { children: value.children, background, human };
122
- }
123
100
  function readHolds(value) {
124
101
  if (!Array.isArray(value))
125
102
  return undefined;
@@ -9,6 +9,7 @@ import { lifecycleHistory } from "./lifecycle-history.js";
9
9
  import { bindLifecycleHumanInput } from "./lifecycle-human-input.js";
10
10
  import { readLifecycleRuntimeFacts } from "./lifecycle-runtime-facts.js";
11
11
  import { goalGuardAfter } from "./lifecycle-stop.js";
12
+ import { wakeSourceItems } from "./lifecycle-wait-items.js";
12
13
  import { SessionLifecycleController } from "./session-lifecycle.js";
13
14
  import { isRecord } from "./work-custody-record.js";
14
15
  /** Attaches durable lifecycle to the real session event/admission boundaries. */
@@ -310,7 +311,7 @@ export class LifecycleSessionBinding {
310
311
  return;
311
312
  if (!Number.isFinite(data.activeCount))
312
313
  return;
313
- this.controller.obligations.syncSource(data.source, data.kind === "children" ? "children" : "background", data.activeCount);
314
+ this.controller.obligations.syncSource(data.source, data.kind === "children" ? "children" : "background", data.activeCount, wakeSourceItems(data));
314
315
  }
315
316
  dispose() {
316
317
  this.disposed = true;
@@ -0,0 +1,17 @@
1
+ import type { WakeSourceStateItem } from "./extensions/builtin/monitor-state-event.ts";
2
+ import type { LifecycleWaitItem } from "./session-lifecycle-types.ts";
3
+ export interface WaitSourceItems {
4
+ readonly items?: readonly WakeSourceStateItem[];
5
+ readonly omittedItems?: number;
6
+ }
7
+ /** Optional producer detail never determines custody. Lists are snapshots, bounded independently of activeCount. */
8
+ export declare function normalizeWaitItems(value: unknown, omitted?: unknown): WaitSourceItems;
9
+ /** The one rule for a wake_source_state producer's item list: `items` when set, else the legacy `monitors`. */
10
+ export declare function wakeSourceItems(data: object): unknown;
11
+ export declare function waitItemSignature(detail: WaitSourceItems): string;
12
+ export declare function projectWaitItems(detail: WaitSourceItems): {
13
+ readonly items?: readonly LifecycleWaitItem[];
14
+ readonly omittedItems?: number;
15
+ };
16
+ export declare function readWaitItems(value: unknown, omitted?: unknown): ReturnType<typeof projectWaitItems>;
17
+ //# sourceMappingURL=lifecycle-wait-items.d.ts.map
@@ -0,0 +1,72 @@
1
+ /** Optional producer detail never determines custody. Lists are snapshots, bounded independently of activeCount. */
2
+ export function normalizeWaitItems(value, omitted) {
3
+ const byId = new Map();
4
+ if (Array.isArray(value)) {
5
+ for (const entry of value) {
6
+ if (typeof entry !== "object" || entry === null || !("id" in entry))
7
+ continue;
8
+ if (typeof entry.id !== "string" || entry.id.trim().length === 0)
9
+ continue;
10
+ const item = {
11
+ id: entry.id,
12
+ ...("description" in entry && typeof entry.description === "string"
13
+ ? { description: entry.description }
14
+ : {}),
15
+ ...("startedAtMs" in entry &&
16
+ typeof entry.startedAtMs === "number" &&
17
+ Number.isFinite(entry.startedAtMs) &&
18
+ Math.abs(entry.startedAtMs) <= 8.64e15
19
+ ? { startedAtMs: entry.startedAtMs }
20
+ : {}),
21
+ };
22
+ const previous = byId.get(item.id);
23
+ if (!previous || JSON.stringify(item) < JSON.stringify(previous))
24
+ byId.set(item.id, item);
25
+ }
26
+ }
27
+ const items = [...byId.values()].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
28
+ const omittedItems = Math.max(0, items.length - 32) +
29
+ (typeof omitted === "number" && Number.isSafeInteger(omitted) && omitted > 0 ? omitted : 0);
30
+ return {
31
+ ...(items.length ? { items: items.slice(0, 32) } : {}),
32
+ ...(omittedItems ? { omittedItems } : {}),
33
+ };
34
+ }
35
+ /** The one rule for a wake_source_state producer's item list: `items` when set, else the legacy `monitors`. */
36
+ export function wakeSourceItems(data) {
37
+ return ("items" in data ? data.items : undefined) ?? ("monitors" in data ? data.monitors : undefined);
38
+ }
39
+ export function waitItemSignature(detail) {
40
+ return JSON.stringify([detail.items?.map((item) => [item.id, item.description]), detail.omittedItems]);
41
+ }
42
+ export function projectWaitItems(detail) {
43
+ return {
44
+ ...(detail.items
45
+ ? {
46
+ items: detail.items.map((item) => ({
47
+ id: item.id,
48
+ ...(item.description === undefined ? {} : { label: item.description }),
49
+ ...(item.startedAtMs === undefined ? {} : { startedAt: new Date(item.startedAtMs).toISOString() }),
50
+ })),
51
+ }
52
+ : {}),
53
+ ...(detail.omittedItems ? { omittedItems: detail.omittedItems } : {}),
54
+ };
55
+ }
56
+ export function readWaitItems(value, omitted) {
57
+ const items = Array.isArray(value)
58
+ ? value.map((item) => {
59
+ if (typeof item !== "object" || item === null)
60
+ return item;
61
+ return {
62
+ ...("id" in item ? { id: item.id } : {}),
63
+ ...("label" in item ? { description: item.label } : {}),
64
+ ...("startedAt" in item && typeof item.startedAt === "string"
65
+ ? { startedAtMs: Date.parse(item.startedAt) }
66
+ : {}),
67
+ };
68
+ })
69
+ : undefined;
70
+ return projectWaitItems(normalizeWaitItems(items, omitted));
71
+ }
72
+ //# sourceMappingURL=lifecycle-wait-items.js.map
@@ -245,7 +245,12 @@ export class ModelRuntime {
245
245
  return base;
246
246
  }
247
247
  try {
248
- const provider = composeModelProvider(providerId, base, this.config, extension);
248
+ // The reader runs only inside ambient auth resolution; composition itself stays credential-free.
249
+ const storedProviderEnv = async (sourceId) => {
250
+ const credential = await this.credentials.read(sourceId);
251
+ return credential?.type === "api_key" && credential.env ? { ...credential.env } : undefined;
252
+ };
253
+ const provider = composeModelProvider(providerId, base, this.config, extension, { storedProviderEnv });
249
254
  this.compositionErrors.delete(providerId);
250
255
  return provider;
251
256
  }
@@ -1,11 +1,14 @@
1
1
  import { type ApiKeyAuth, type AuthContext, type AuthResult, type ModelAuth, type Provider, type ProviderHeaders } from "@earendil-works/pi-ai";
2
2
  import type { ConfigValue } from "@earendil-works/pi-ai/utils/config-reference";
3
3
  import type { ModelsJsonProvider } from "./model-config.ts";
4
+ /** Reads another provider's stored credential env: routing metadata only, never keys. */
5
+ export type StoredProviderEnvReader = (providerId: string) => Promise<Record<string, string> | undefined>;
4
6
  interface AmbientAuthExtensionInput {
5
7
  name?: string;
6
8
  resolve(input: {
7
9
  ctx: AuthContext;
8
10
  signal: AbortSignal;
11
+ storedProviderEnv?: StoredProviderEnvReader;
9
12
  }): Promise<AuthResult | undefined>;
10
13
  }
11
14
  interface ProviderAuthExtensionInput {
@@ -19,7 +22,9 @@ interface ProviderAuthExtensionInput {
19
22
  oauth?: unknown;
20
23
  ambientAuth?: AmbientAuthExtensionInput;
21
24
  }
22
- export declare function composeApiKeyAuth(providerId: string, base: Provider | undefined, config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): ApiKeyAuth | undefined;
25
+ export declare function composeApiKeyAuth(providerId: string, base: Provider | undefined, config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined, options?: {
26
+ storedProviderEnv?: StoredProviderEnvReader;
27
+ }): ApiKeyAuth | undefined;
23
28
  export declare function configuredApiKey(config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): ConfigValue | undefined;
24
29
  export declare function configuredHeaders(config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): Record<string, ConfigValue> | undefined;
25
30
  export declare function withConfiguredAuth(auth: ModelAuth, headers: ProviderHeaders | undefined, authHeader: boolean): ModelAuth;
@@ -2,7 +2,7 @@ import { hasCredentialHeaders, } from "@earendil-works/pi-ai";
2
2
  import { assertConfigReferenceAuthority } from "./config-reference-resolver.js";
3
3
  import { checkConfiguredHeaderAuth, headerAuthResolutionSource } from "./provider-header-auth.js";
4
4
  import { getConfigValueEnvVarNames, isCommandConfigValue, resolveConfigValueOrThrow, resolveHeadersOrThrow, } from "./resolve-config-value.js";
5
- export function composeApiKeyAuth(providerId, base, config, extension) {
5
+ export function composeApiKeyAuth(providerId, base, config, extension, options) {
6
6
  const inherited = base?.auth.apiKey;
7
7
  const rawKey = configuredApiKey(config, extension);
8
8
  const oauth = extension?.oauth ?? base?.auth.oauth;
@@ -15,7 +15,7 @@ export function composeApiKeyAuth(providerId, base, config, extension) {
15
15
  // explicitly configured key, credential headers, or a base provider still
16
16
  // win, and a resolution marked ambient never outranks a configured
17
17
  // provider in automatic default selection (senpi#2327).
18
- return ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader);
18
+ return ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader, options?.storedProviderEnv);
19
19
  }
20
20
  if (!inherited && rawKey === undefined && !headerSource && oauth) {
21
21
  // An OAuth provider with no key, no credential headers and no base normally
@@ -119,16 +119,23 @@ function ambientOnlyAuth(providerId, oauth, rawHeaders, headerSource, authHeader
119
119
  * is the only source — and `Models.checkAuth` resolves this auth, so the
120
120
  * `ambient` marker reaches the provider's auth status.
121
121
  */
122
- function ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader) {
122
+ function ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader, storedProviderEnv) {
123
123
  const resolve = async (input) => {
124
- const result = await ambient.resolve({ ctx: input.ctx, signal: input.signal });
124
+ const result = await ambient.resolve({
125
+ ctx: input.ctx,
126
+ signal: input.signal,
127
+ ...(storedProviderEnv ? { storedProviderEnv } : {}),
128
+ });
125
129
  if (!result)
126
130
  return undefined;
127
131
  const explicitEnv = { ...(input.credential?.env ?? {}), ...(result.env ?? {}) };
128
132
  const headerEnv = await configContextEnv(Object.values(rawHeaders ?? {}), input.ctx, explicitEnv);
129
133
  const headers = await resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, headerEnv);
134
+ // Stored-then-env (helpers.ts invariant): the provider's own stored env wins over ambient-resolved env.
135
+ const env = result.env || input.credential?.env ? { ...(result.env ?? {}), ...(input.credential?.env ?? {}) } : undefined;
130
136
  return {
131
137
  ...result,
138
+ ...(env ? { env } : {}),
132
139
  auth: withConfiguredAuth(result.auth, headers, authHeader),
133
140
  source: result.source ?? headerSource,
134
141
  };
@@ -1,6 +1,7 @@
1
1
  import { type AnyModel, type Api, type AssistantMessageEventStream, type AuthCheck, type AuthContext, type AuthResult, type ClassifierApi, type ImageApi, type Model, type OAuthCredential, type OAuthCredentials, type OAuthLoginCallbacks, type Provider, type ProviderClassifier, type ProviderImages, type RefreshModelsContext, type SimpleStreamOptions, type TranscriptContext } from "@earendil-works/pi-ai";
2
2
  import type { RetryPolicyProfile } from "@earendil-works/pi-ai/utils/retry-profile/types";
3
3
  import type { ModelConfig, ModelsJsonProvider } from "./model-config.ts";
4
+ import { type StoredProviderEnvReader } from "./provider-api-key-auth.ts";
4
5
  import type { HeaderAuthStatusSource } from "./provider-header-auth.ts";
5
6
  import { clearConfigValueCache } from "./resolve-config-value.ts";
6
7
  export interface ExtensionOAuthConfig {
@@ -120,6 +121,8 @@ export interface ProviderAmbientAuth {
120
121
  resolve(input: {
121
122
  ctx: AuthContext;
122
123
  signal: AbortSignal;
124
+ /** Read-only env of another provider's stored credential; routing metadata only, never keys. */
125
+ storedProviderEnv?(providerId: string): Promise<Record<string, string> | undefined>;
123
126
  }): Promise<AuthResult | undefined>;
124
127
  }
125
128
  export type AuthStatus = {
@@ -133,7 +136,11 @@ export { configuredRequestAuthStatus, resolveCompatibilityRequestHeaders, resolv
133
136
  export declare const clearApiKeyCache: typeof clearConfigValueCache;
134
137
  export declare function validateExtensionProvider(providerId: string, base: Provider | undefined, modelsConfig: ModelsJsonProvider | undefined, extension: ProviderConfigInput): void;
135
138
  /** Compose built-in, models.json, and extension layers without reading credentials. */
136
- export declare function composeModelProvider(providerId: string, base: Provider | undefined, modelConfig: ModelConfig, extension: ProviderConfigInput | undefined): Provider;
139
+ export declare function composeModelProvider(providerId: string, base: Provider | undefined, modelConfig: ModelConfig, extension: ProviderConfigInput | undefined,
140
+ /** Deferred ambient reads; the reader runs during auth resolution, never at composition. */
141
+ options?: {
142
+ storedProviderEnv?: StoredProviderEnvReader;
143
+ }): Provider;
137
144
  /**
138
145
  * Request shape a compatibility provider needs beside its credential. Headers are NOT
139
146
  * part of it: a configured header value can be a `!command`, and resolving one requires
@@ -1,6 +1,6 @@
1
1
  import { getApiProvider, getCurrentTools, getProtocol, getToolCallFormat, isModelType, lazyStream, transformContext, wrapStreamWithToolCallMiddleware, } from "@earendil-works/pi-ai";
2
2
  import { classifierErrorResult, imageErrorResult } from "@earendil-works/pi-ai/utils/model-operations";
3
- import { composeApiKeyAuth, configuredHeaders, withConfiguredAuth } from "./provider-api-key-auth.js";
3
+ import { composeApiKeyAuth, configuredHeaders, withConfiguredAuth, } from "./provider-api-key-auth.js";
4
4
  import { clearConfigValueCache, resolveHeadersOrThrow } from "./resolve-config-value.js";
5
5
  export { configuredRequestAuthStatus, resolveCompatibilityRequestHeaders, resolveConfiguredModelHeaders, } from "./provider-request-auth.js";
6
6
  export const clearApiKeyCache = clearConfigValueCache;
@@ -286,7 +286,9 @@ export function validateExtensionProvider(providerId, base, modelsConfig, extens
286
286
  applyExtension(providerId, applyModelsJson(providerId, getAllProviderModels(base), modelsConfig, extension), extension, new Set((modelsConfig?.models ?? []).map((definition) => definition.id)));
287
287
  }
288
288
  /** Compose built-in, models.json, and extension layers without reading credentials. */
289
- export function composeModelProvider(providerId, base, modelConfig, extension) {
289
+ export function composeModelProvider(providerId, base, modelConfig, extension,
290
+ /** Deferred ambient reads; the reader runs during auth resolution, never at composition. */
291
+ options) {
290
292
  const config = modelConfig.getProvider(providerId);
291
293
  let extensionOAuthCredential;
292
294
  let refreshedExtensionModels;
@@ -309,7 +311,9 @@ export function composeModelProvider(providerId, base, modelConfig, extension) {
309
311
  };
310
312
  // Validate eagerly so registration/reload reports structural errors immediately.
311
313
  getAllModels();
312
- const apiKey = composeApiKeyAuth(providerId, base, config, extension);
314
+ const apiKey = composeApiKeyAuth(providerId, base, config, extension, {
315
+ storedProviderEnv: options?.storedProviderEnv,
316
+ });
313
317
  const oauth = composeOAuthAuth(providerId, base, config, extension);
314
318
  if (!apiKey && !oauth)
315
319
  throw new Error(`Provider ${providerId}: no authentication method configured.`);
package/dist/core/sdk.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { Agent, setDefaultStreamFn } from "@earendil-works/pi-agent-core";
2
+ import { Agent, createInternalAgentChannel, setDefaultStreamFn, } from "@earendil-works/pi-agent-core";
3
3
  import { modelsAreEqual, streamSimple } from "@earendil-works/pi-ai/compat";
4
4
  import { getAgentDir } from "../config.js";
5
5
  import { resolvePath } from "../utils/paths.js";
@@ -283,7 +283,9 @@ export async function createAgentSession(options = {}) {
283
283
  model: model.id,
284
284
  });
285
285
  };
286
+ const internalChannel = createInternalAgentChannel();
286
287
  agent = new Agent({
288
+ internalChannel,
287
289
  initialState: {
288
290
  systemPrompt: "",
289
291
  model,
@@ -382,6 +384,7 @@ export async function createAgentSession(options = {}) {
382
384
  : options.sessionStartEvent;
383
385
  const session = new AgentSession({
384
386
  agent,
387
+ internalChannel,
385
388
  serviceTier: options.serviceTier,
386
389
  sessionManager,
387
390
  settingsManager,