@code-yeongyu/senpi 2026.10.26-1 → 2026.10.26-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/bundle/chunks/{anthropic-messages-M235FJQV.js → anthropic-messages-ODSFJCXR.js} +1 -1
- package/dist/bundle/chunks/{args-FBNJOJSR.js → args-SWKJAYQD.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-YQRTQ7H6.js → azure-openai-responses-REGXS4XO.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
- package/dist/bundle/chunks/chunk-2XF6W6F6.js +410 -0
- package/dist/bundle/chunks/{chunk-DMFAVE5N.js → chunk-4QVORFQ2.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZXHLH4MW.js → chunk-5W3DTM2J.js} +1 -1
- package/dist/bundle/chunks/{chunk-QREKAXKX.js → chunk-6GAMRAVM.js} +5 -5
- package/dist/bundle/chunks/{chunk-MSHRIZGT.js → chunk-7IZH2KQX.js} +3 -3
- package/dist/bundle/chunks/{chunk-PH3JDRB2.js → chunk-ARSENVDY.js} +1 -1
- package/dist/bundle/chunks/{chunk-5KZH6EYQ.js → chunk-CNDPCYNT.js} +1 -1
- package/dist/bundle/chunks/{chunk-DYWIFF2Q.js → chunk-CYOHFREV.js} +1 -1
- package/dist/bundle/chunks/{chunk-3LPWILUZ.js → chunk-DNDZPKIQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZLIVZQDY.js → chunk-EQNUL2WB.js} +1 -1
- package/dist/bundle/chunks/{chunk-5FQMNHXV.js → chunk-ESNSRUW4.js} +1 -1
- package/dist/bundle/chunks/{chunk-LO5MYLGF.js → chunk-FQDARFHT.js} +1 -1
- package/dist/bundle/chunks/{chunk-7KOUQSBX.js → chunk-GPPOPK76.js} +3 -3
- package/dist/bundle/chunks/chunk-I2WFLKZ2.js +5 -0
- package/dist/bundle/chunks/{chunk-I7QWTWVZ.js → chunk-IHKHCWWG.js} +1 -1
- package/dist/bundle/chunks/{chunk-MY4ZD3EW.js → chunk-IY4G44MN.js} +1 -1
- package/dist/bundle/chunks/{chunk-OQ3WDMB3.js → chunk-JH7MVRNJ.js} +1 -1
- package/dist/bundle/chunks/chunk-KBSFTXAT.js +2 -0
- package/dist/bundle/chunks/{chunk-UW6M3EXY.js → chunk-KRO63T4Q.js} +1 -1
- package/dist/bundle/chunks/{chunk-J5FCH7TI.js → chunk-KTDIIF2F.js} +1 -1
- package/dist/bundle/chunks/{chunk-3WP5RFQR.js → chunk-NDNIMC5W.js} +1 -1
- package/dist/bundle/chunks/{chunk-CDQPA4FP.js → chunk-ODRGPC5S.js} +1 -1
- package/dist/bundle/chunks/{chunk-3A3XCLNH.js → chunk-PDG4XWO2.js} +1 -1
- package/dist/bundle/chunks/{chunk-QYFOHFPS.js → chunk-PPECSSWX.js} +1 -1
- package/dist/bundle/chunks/{chunk-5LWUUXMH.js → chunk-PY4ZQHTN.js} +1 -1
- package/dist/bundle/chunks/{chunk-EZP6AYW2.js → chunk-RPW3XQW3.js} +22 -22
- package/dist/bundle/chunks/{chunk-SOXQ42VS.js → chunk-RQ5JTXUC.js} +1 -1
- package/dist/bundle/chunks/{chunk-JFQUWEN7.js → chunk-TQ67PB7U.js} +2 -2
- package/dist/bundle/chunks/{chunk-6U3TBFBA.js → chunk-UJPG4ROT.js} +1 -1
- package/dist/bundle/chunks/{chunk-UDM7VO6O.js → chunk-XM36IFP3.js} +1 -1
- package/dist/bundle/chunks/{chunk-XQ45JMGN.js → chunk-Z6BREXV3.js} +1 -1
- package/dist/bundle/chunks/{chunk-ADQAPDPV.js → chunk-ZP6JJDYV.js} +1 -1
- package/dist/bundle/chunks/{cli-main-55EQA5PS.js → cli-main-Q2GA53XM.js} +1 -1
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZJQGIIRC.js → cloudflare-workers-ai-system-one-WDHT7BBV.js} +1 -1
- package/dist/bundle/chunks/cursor-agent.js +1 -1
- package/dist/bundle/chunks/devin-agent.js +1 -1
- package/dist/bundle/chunks/{dispatch-C2IBP5VV.js → dispatch-5R3TYAYB.js} +3 -3
- package/dist/bundle/chunks/{google-generative-ai-5G4RIQA6.js → google-generative-ai-FHYFXKLA.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-ALD4P27O.js → google-vertex-5DWE5U5K.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-PEIKGCKZ.js → help-fast-path-FETLIF3W.js} +1 -1
- package/dist/bundle/chunks/{host-command-657VCQ34.js → host-command-XEB7SHT3.js} +1 -1
- package/dist/bundle/chunks/{host-session-command-OV5XDOJK.js → host-session-command-FFN52LXJ.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-MLXSYK2H.js → interactive-mode-5DEKY3YW.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-RAE4K2XY.js → mistral-conversations-I2PI7DDF.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-774MACJU.js → multi-session-host-OPR5VBFO.js} +3 -3
- package/dist/bundle/chunks/{openai-codex-responses-3CW4R7TG.js → openai-codex-responses-WSEX6SH7.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-5UIJXQUF.js → openai-completions-YCBHTBSS.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-2BO44MRW.js → openai-responses-GXNSQF4A.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-MZHVCX2S.js → package-manager-cli-W55E3LHP.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-RF6GER4R.js → pi-messages-O6GISIRW.js} +1 -1
- package/dist/bundle/chunks/{role-ETSFSDTS.js → role-SHIZQKK4.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-ZMQB4GPO.js → rotation-stream-2PCZWNKF.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-UJXOIZCW.js → rpc-mode-IDUJTSYS.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-KA7LFFNK.js → schedule-command-B7RRSANU.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-MFWXUR7Z.js → session-control-endpoint-LMZH5JLH.js} +1 -1
- package/dist/bundle/chunks/{session-picker-BP33NRSL.js → session-picker-DTGBOXDR.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +41 -41
- package/dist/bundle/chunks/{typesafe-system-one-GNNZ5O5U.js → typesafe-system-one-XGYJJVSE.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.d.ts +11 -1
- package/dist/core/agent-session.js +19 -2
- package/dist/core/extensions/builtin/compaction/index.js +7 -1
- package/dist/core/extensions/builtin/herdr/index.js +9 -5
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.d.ts +6 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-issuer.js +25 -0
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.d.ts +3 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth-provider.js +50 -19
- package/dist/core/extensions/builtin/mcp/auth/oauth-refresh.js +4 -3
- package/dist/core/extensions/builtin/mcp/auth/oauth.js +19 -12
- package/dist/core/extensions/builtin/mcp/modern/dispatch.js +1 -0
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.d.ts +4 -1
- package/dist/core/extensions/builtin/mcp/modern/parameter-headers.js +33 -35
- package/dist/core/extensions/builtin/mcp/modern/request.js +3 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/modern/transport.js +4 -2
- package/dist/core/extensions/builtin/terminal/extension-state.js +2 -1
- package/dist/core/extensions/builtin/vertex-model-garden/auth.d.ts +9 -0
- package/dist/core/extensions/builtin/vertex-model-garden/auth.js +17 -1
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.d.ts +6 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers/google.js +6 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/lifecycle-children.d.ts +3 -1
- package/dist/core/lifecycle-children.js +79 -15
- package/dist/core/lifecycle-record.js +1 -24
- package/dist/core/lifecycle-session-binding.js +2 -1
- package/dist/core/lifecycle-wait-items.d.ts +17 -0
- package/dist/core/lifecycle-wait-items.js +72 -0
- package/dist/core/model-runtime.js +6 -1
- package/dist/core/provider-api-key-auth.d.ts +6 -1
- package/dist/core/provider-api-key-auth.js +11 -4
- package/dist/core/provider-composer.d.ts +8 -1
- package/dist/core/provider-composer.js +7 -3
- package/dist/core/sdk.js +4 -1
- package/dist/core/session-activity.js +2 -0
- package/dist/core/session-lifecycle-types.d.ts +20 -4
- package/dist/core/session-lifecycle.js +35 -4
- package/dist/core/structured-session-lane.d.ts +33 -0
- package/dist/core/structured-session-lane.js +62 -0
- package/dist/core/work-custody-record.d.ts +2 -1
- package/dist/core/work-custody-record.js +2 -0
- package/dist/core/work-obligations.d.ts +1 -1
- package/dist/core/work-obligations.js +8 -2
- package/dist/modes/json-event.d.ts +79 -1
- package/dist/modes/json-event.js +79 -1
- package/dist/modes/rpc/compact-content-index.d.ts +85 -0
- package/dist/modes/rpc/compact-content-index.js +254 -0
- package/dist/modes/rpc/compact-content-store.d.ts +6 -43
- package/dist/modes/rpc/compact-content-store.js +22 -157
- package/dist/modes/rpc/compact-index-pages.d.ts +12 -0
- package/dist/modes/rpc/compact-index-pages.js +31 -0
- package/dist/modes/rpc/compact-session-state.d.ts +11 -39
- package/dist/modes/rpc/compact-session-state.js +17 -26
- package/dist/modes/rpc/compact-spool-dir.d.ts +4 -1
- package/dist/modes/rpc/compact-spool-dir.js +41 -8
- package/dist/modes/rpc/compact-spool-storage.d.ts +53 -0
- package/dist/modes/rpc/compact-spool-storage.js +162 -0
- package/dist/modes/rpc/compact-storage-io.d.ts +2 -1
- package/dist/modes/rpc/compact-storage-io.js +7 -1
- package/dist/modes/rpc/compact-transition.d.ts +41 -0
- package/dist/modes/rpc/compact-transition.js +12 -0
- package/dist/modes/rpc/connection-handler.d.ts +2 -0
- package/dist/modes/rpc/connection-handler.js +12 -6
- package/dist/modes/rpc/host-ensure-start.js +5 -3
- package/dist/modes/rpc/security-presentations.js +2 -1
- package/dist/modes/rpc/session-binding.js +10 -0
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.js +2 -0
- package/dist/modes/rpc/session-record-stream.d.ts +3 -3
- package/dist/modes/rpc/session-record-stream.js +3 -3
- package/dist/modes/rpc/session-structured-lanes.d.ts +12 -0
- package/dist/modes/rpc/session-structured-lanes.js +24 -0
- package/dist/modes/rpc/session-worker-client.js +6 -5
- package/dist/modes/rpc/structured-session-records.d.ts +12 -0
- package/dist/modes/rpc/structured-session-records.js +88 -0
- package/docs/extensions.md +7 -1
- package/docs/rpc.md +17 -2
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-GQJYNFMO.js +0 -2
- package/dist/bundle/chunks/chunk-VICDRG3J.js +0 -410
- package/dist/bundle/chunks/chunk-VL7O5PO4.js +0 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { loadMcpSdkAuth } from "../sdk.lazy.js";
|
|
2
2
|
import { isInvalidGrant, OAuthFlowError } from "./oauth-errors.js";
|
|
3
3
|
import { oauthFetch } from "./oauth-fetch.js";
|
|
4
|
+
import { validatedAuthorizationServerIssuer } from "./oauth-issuer.js";
|
|
4
5
|
import { assertS256Supported } from "./oauth-refresh.js";
|
|
5
6
|
// Pre-flight: discover the authorization server and REFUSE (typed) if it does
|
|
6
7
|
// not advertise PKCE S256. Runs before any authorize redirect.
|
|
@@ -20,7 +21,7 @@ export async function beginAuthorization(provider, options = {}) {
|
|
|
20
21
|
}
|
|
21
22
|
// Paste flow: validates single-use state itself, then exchanges the code.
|
|
22
23
|
export async function completeAuthorization(provider, redirectInput, options = {}) {
|
|
23
|
-
const { code, state, iss } = parseRedirect(redirectInput, provider
|
|
24
|
+
const { code, state, iss } = parseRedirect(redirectInput, provider);
|
|
24
25
|
if (!provider.consumeState(state)) {
|
|
25
26
|
throw new OAuthFlowError("state_mismatch", `MCP server ${provider.serverName} authorization state did not match (possible CSRF or a stale/replayed link); restart with /mcp auth-start.`, { serverName: provider.serverName });
|
|
26
27
|
}
|
|
@@ -56,15 +57,19 @@ export async function finishAuthorization(provider, code, options = {}, iss) {
|
|
|
56
57
|
// RFC 9207: an authorization response that names another authorization server, or that omits `iss`
|
|
57
58
|
// although this server promises to send it, may have been injected by a mix-up attack; never exchange its code.
|
|
58
59
|
function assertAuthorizationResponseIssuer(provider, iss) {
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
|
|
60
|
+
const discovery = provider.discoveryState();
|
|
61
|
+
if (discovery === undefined) {
|
|
62
|
+
throw new OAuthFlowError("needs_auth", `MCP server ${provider.serverName} has no trusted authorization discovery; restart with /mcp auth-start ${provider.serverName}.`, { serverName: provider.serverName });
|
|
63
|
+
}
|
|
64
|
+
const metadata = discovery.authorizationServerMetadata;
|
|
65
|
+
const issuer = validatedAuthorizationServerIssuer(discovery, provider.serverName);
|
|
62
66
|
// The SDK keeps unknown metadata fields (loose schema) but does not type this RFC 9207 one.
|
|
63
|
-
const promised = metadata
|
|
64
|
-
|
|
67
|
+
const promised = metadata !== undefined &&
|
|
68
|
+
"authorization_response_iss_parameter_supported" in metadata &&
|
|
69
|
+
metadata.authorization_response_iss_parameter_supported === true;
|
|
65
70
|
if (iss === undefined && !promised)
|
|
66
71
|
return;
|
|
67
|
-
if (iss !== undefined && iss ===
|
|
72
|
+
if (iss !== undefined && iss === issuer)
|
|
68
73
|
return;
|
|
69
74
|
throw new OAuthFlowError("needs_auth", iss === undefined
|
|
70
75
|
? `MCP server ${provider.serverName} authorization response has no issuer although its authorization server promises one; restart with /mcp auth-start ${provider.serverName}.`
|
|
@@ -111,19 +116,19 @@ export async function clientCredentialsGrant(provider, options = {}) {
|
|
|
111
116
|
resource: new URL(provider.serverUrl),
|
|
112
117
|
fetchFn: oauthFetch(options.fetchFn),
|
|
113
118
|
});
|
|
114
|
-
await provider.saveTokens({ ...tokens, issuer:
|
|
119
|
+
await provider.saveTokens({ ...tokens, issuer: validatedAuthorizationServerIssuer(info, provider.serverName) });
|
|
115
120
|
}
|
|
116
121
|
export async function logout(provider) {
|
|
117
122
|
await provider.store.clear();
|
|
118
123
|
}
|
|
119
124
|
async function discover(provider, options) {
|
|
120
|
-
if (options.discover !== undefined)
|
|
121
|
-
return options.discover(provider.serverUrl);
|
|
122
125
|
const cached = provider.discoveryState();
|
|
123
126
|
if (cached !== undefined)
|
|
124
127
|
return cached;
|
|
125
128
|
const { discoverOAuthServerInfo } = await loadMcpSdkAuth();
|
|
126
|
-
const info =
|
|
129
|
+
const info = options.discover !== undefined
|
|
130
|
+
? await options.discover(provider.serverUrl)
|
|
131
|
+
: await discoverOAuthServerInfo(provider.serverUrl, { fetchFn: oauthFetch(options.fetchFn) });
|
|
127
132
|
await provider.saveDiscoveryState(toDiscoveryState(info));
|
|
128
133
|
return info;
|
|
129
134
|
}
|
|
@@ -134,7 +139,8 @@ function toDiscoveryState(info) {
|
|
|
134
139
|
resourceMetadata: info.resourceMetadata,
|
|
135
140
|
};
|
|
136
141
|
}
|
|
137
|
-
function parseRedirect(input,
|
|
142
|
+
function parseRedirect(input, provider) {
|
|
143
|
+
const serverName = provider.serverName;
|
|
138
144
|
let url;
|
|
139
145
|
try {
|
|
140
146
|
url = new URL(input.trim());
|
|
@@ -142,6 +148,7 @@ function parseRedirect(input, serverName) {
|
|
|
142
148
|
catch {
|
|
143
149
|
throw new OAuthFlowError("needs_auth", `MCP server ${serverName} received a malformed redirect URL; paste the full http://127.0.0.1/... address from your browser.`, { serverName });
|
|
144
150
|
}
|
|
151
|
+
assertAuthorizationResponseIssuer(provider, url.searchParams.get("iss") ?? undefined);
|
|
145
152
|
const error = url.searchParams.get("error");
|
|
146
153
|
if (error !== null) {
|
|
147
154
|
throw new OAuthFlowError("needs_auth", `MCP server ${serverName} authorization failed: ${error}`, { serverName });
|
|
@@ -39,6 +39,7 @@ export async function materializeNegotiatedTransport(options, serverName, timeou
|
|
|
39
39
|
clientInfo,
|
|
40
40
|
clientCapabilities: {},
|
|
41
41
|
protocolVersion: outcome.version,
|
|
42
|
+
logger,
|
|
42
43
|
}), outcome.discovery, outcome.version);
|
|
43
44
|
const version = outcome.version;
|
|
44
45
|
logVersion(transport, () => version);
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
export declare function encodeMcpHeaderValue(value: string): string;
|
|
3
3
|
/** Configured headers must never supply parameter metadata absent from the request body. */
|
|
4
4
|
export declare function clearMcpParameterHeaders(headers: Headers): void;
|
|
5
|
+
/** A local argument error, not a failed transport or an untrusted server diagnostic. */
|
|
6
|
+
export declare class ParameterHeaderValidationError extends Error {
|
|
7
|
+
}
|
|
5
8
|
/** Connection-local catalog: never shared with another server or transport generation. */
|
|
6
9
|
export declare class ModernParameterHeaders {
|
|
7
10
|
#private;
|
|
8
|
-
filterTools(tools: readonly unknown[], firstPage: boolean): unknown[];
|
|
11
|
+
filterTools(tools: readonly unknown[], firstPage: boolean, warn: (message: string) => void): unknown[];
|
|
9
12
|
append(headers: Headers, name: unknown, args: unknown): void;
|
|
10
13
|
}
|
|
11
14
|
//# sourceMappingURL=parameter-headers.d.ts.map
|
|
@@ -18,22 +18,31 @@ export function clearMcpParameterHeaders(headers) {
|
|
|
18
18
|
function parseParameterHeaders(schema) {
|
|
19
19
|
const headers = [];
|
|
20
20
|
const names = new Set();
|
|
21
|
+
let reason = "";
|
|
21
22
|
const visit = (node, path) => {
|
|
23
|
+
if (Array.isArray(node))
|
|
24
|
+
return node.every((child) => visit(child, undefined));
|
|
22
25
|
if (!isRecord(node))
|
|
23
26
|
return true;
|
|
24
27
|
if (Object.hasOwn(node, "x-mcp-header")) {
|
|
25
28
|
const name = node["x-mcp-header"];
|
|
26
29
|
const type = node.type;
|
|
27
|
-
if (!path?.length
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if (!path?.length)
|
|
31
|
+
reason = "x-mcp-header must be on a properties-only path";
|
|
32
|
+
else if (typeof name !== "string" || !/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(name))
|
|
33
|
+
reason = "x-mcp-header must be a nonempty HTTP field-name token";
|
|
34
|
+
else if (names.has(name.toLowerCase()))
|
|
35
|
+
reason = "x-mcp-header names must be case-insensitively unique";
|
|
36
|
+
else if (type !== "string" && type !== "integer" && type !== "boolean")
|
|
37
|
+
reason = "x-mcp-header type must be string, integer, or boolean";
|
|
38
|
+
else {
|
|
39
|
+
names.add(name.toLowerCase());
|
|
40
|
+
headers.push({ name, path, type });
|
|
41
|
+
}
|
|
42
|
+
if (reason)
|
|
32
43
|
return false;
|
|
33
|
-
names.add(name.toLowerCase());
|
|
34
|
-
headers.push({ name, path, type });
|
|
35
44
|
}
|
|
36
|
-
//
|
|
45
|
+
// "Anywhere else" includes unknown keywords; instance-data keywords are not schemas.
|
|
37
46
|
for (const [keyword, value] of Object.entries(node)) {
|
|
38
47
|
if (["properties", "patternProperties", "$defs", "definitions", "dependentSchemas", "dependencies"].includes(keyword)) {
|
|
39
48
|
if (!isRecord(value))
|
|
@@ -44,46 +53,31 @@ function parseParameterHeaders(schema) {
|
|
|
44
53
|
return false;
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
|
-
else if ([
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"allOf",
|
|
51
|
-
"anyOf",
|
|
52
|
-
"oneOf",
|
|
53
|
-
"additionalItems",
|
|
54
|
-
"additionalProperties",
|
|
55
|
-
"unevaluatedItems",
|
|
56
|
-
"unevaluatedProperties",
|
|
57
|
-
"contains",
|
|
58
|
-
"propertyNames",
|
|
59
|
-
"not",
|
|
60
|
-
"if",
|
|
61
|
-
"then",
|
|
62
|
-
"else",
|
|
63
|
-
"contentSchema",
|
|
64
|
-
].includes(keyword)) {
|
|
65
|
-
for (const child of Array.isArray(value) ? value : [value]) {
|
|
66
|
-
if (!visit(child, undefined))
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
56
|
+
else if (!["examples", "default", "const", "enum"].includes(keyword)) {
|
|
57
|
+
if (!visit(value, undefined))
|
|
58
|
+
return false;
|
|
69
59
|
}
|
|
70
60
|
}
|
|
71
61
|
return true;
|
|
72
62
|
};
|
|
73
|
-
return visit(schema, []) ? headers :
|
|
63
|
+
return visit(schema, []) ? headers : reason;
|
|
64
|
+
}
|
|
65
|
+
/** A local argument error, not a failed transport or an untrusted server diagnostic. */
|
|
66
|
+
export class ParameterHeaderValidationError extends Error {
|
|
74
67
|
}
|
|
75
68
|
/** Connection-local catalog: never shared with another server or transport generation. */
|
|
76
69
|
export class ModernParameterHeaders {
|
|
77
70
|
#tools = new Map();
|
|
78
|
-
filterTools(tools, firstPage) {
|
|
71
|
+
filterTools(tools, firstPage, warn) {
|
|
79
72
|
if (firstPage)
|
|
80
73
|
this.#tools.clear();
|
|
81
74
|
return tools.filter((tool) => {
|
|
82
75
|
if (!isRecord(tool) || typeof tool.name !== "string")
|
|
83
76
|
return true;
|
|
84
77
|
const headers = parseParameterHeaders(tool.inputSchema);
|
|
85
|
-
if (headers ===
|
|
78
|
+
if (typeof headers === "string") {
|
|
86
79
|
this.#tools.delete(tool.name);
|
|
80
|
+
warn(`Rejected MCP tool ${JSON.stringify(tool.name)}: ${headers}`);
|
|
87
81
|
return false;
|
|
88
82
|
}
|
|
89
83
|
this.#tools.set(tool.name, headers);
|
|
@@ -98,11 +92,15 @@ export class ModernParameterHeaders {
|
|
|
98
92
|
for (const key of parameter.path) {
|
|
99
93
|
value = isRecord(value) && Object.hasOwn(value, key) ? value[key] : undefined;
|
|
100
94
|
}
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
continue;
|
|
101
97
|
const valid = (parameter.type === "string" && typeof value === "string") ||
|
|
102
98
|
(parameter.type === "boolean" && typeof value === "boolean") ||
|
|
103
99
|
(parameter.type === "integer" && typeof value === "number" && Number.isSafeInteger(value));
|
|
104
|
-
if (valid)
|
|
105
|
-
|
|
100
|
+
if (!valid) {
|
|
101
|
+
throw new ParameterHeaderValidationError(`MCP tool ${JSON.stringify(name)} argument ${JSON.stringify(parameter.path)} must be ${parameter.type === "integer" ? "a safe integer" : `a ${parameter.type}`}`);
|
|
102
|
+
}
|
|
103
|
+
headers.set(`Mcp-Param-${parameter.name}`, encodeMcpHeaderValue(String(value)));
|
|
106
104
|
}
|
|
107
105
|
}
|
|
108
106
|
}
|
|
@@ -7,6 +7,7 @@ import { isRecord, validateMrtrForm } from "./form-schema.js";
|
|
|
7
7
|
import { McpMrtrError } from "./errors.js";
|
|
8
8
|
import { queuedForm } from "./consent-queue.js";
|
|
9
9
|
import { parseInputs } from "./inputs.js";
|
|
10
|
+
import { ParameterHeaderValidationError } from "./parameter-headers.js";
|
|
10
11
|
export const MAX_MCP_MRTR_ROUNDS = 8;
|
|
11
12
|
const capableMethods = new Set(["tools/call", "resources/read", "prompts/get"]);
|
|
12
13
|
const capabilitiesKey = "io.modelcontextprotocol/clientCapabilities";
|
|
@@ -259,6 +260,8 @@ export function installModernRequestAdapter(client, protocol, clock = mcpElapsed
|
|
|
259
260
|
throw error;
|
|
260
261
|
if (error instanceof AuthError)
|
|
261
262
|
throw error;
|
|
263
|
+
if (error instanceof ParameterHeaderValidationError)
|
|
264
|
+
throw error;
|
|
262
265
|
const remoteCode = isRecord(error) && typeof error.code === "number" ? error.code : undefined;
|
|
263
266
|
throw new McpMrtrError("MCP_MRTR_TRANSPORT_FAILED", remoteCode);
|
|
264
267
|
}
|
|
@@ -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
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|