@opengeni/runtime 0.11.0 → 0.13.0
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/dist/{chunk-YUAFQEFY.js → chunk-65UDUFUO.js} +729 -118
- package/dist/chunk-65UDUFUO.js.map +1 -0
- package/dist/chunk-HAN5D27J.js +292 -0
- package/dist/chunk-HAN5D27J.js.map +1 -0
- package/dist/{index-D6yi-JcU.d.ts → index-DGUrY_yR.d.ts} +37 -7
- package/dist/index.d.ts +81 -10
- package/dist/index.js +696 -93
- package/dist/index.js.map +1 -1
- package/dist/mcp-network.d.ts +78 -0
- package/dist/mcp-network.js +62 -0
- package/dist/mcp-network.js.map +1 -0
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +1 -1
- package/package.json +9 -4
- package/src/codex-tool-search.ts +20 -1
- package/src/index.ts +487 -83
- package/src/mcp-network.ts +330 -0
- package/src/sandbox/channel-a.ts +3 -28
- package/src/sandbox/display-stack.ts +860 -23
- package/src/sandbox/exec-banner.ts +67 -0
- package/src/sandbox/index.ts +7 -0
- package/src/sandbox/providers/modal.ts +29 -2
- package/src/sandbox-computer.ts +3 -1
- package/src/usage-telemetry.ts +495 -51
- package/dist/chunk-YUAFQEFY.js.map +0 -1
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// src/mcp-network.ts
|
|
2
|
+
import {
|
|
3
|
+
isNonPublicAddress,
|
|
4
|
+
pinnedFetch,
|
|
5
|
+
resolvePinnedDestination
|
|
6
|
+
} from "@opengeni/network";
|
|
7
|
+
import { undiciFetch } from "@opengeni/network";
|
|
8
|
+
var MCP_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
9
|
+
var MCP_MAX_INBOUND_REQUEST_BYTES = 1024 * 1024;
|
|
10
|
+
var MCP_MAX_TOOL_DEFINITION_BYTES = 128 * 1024;
|
|
11
|
+
var MCP_MAX_TOOL_LIST_BYTES = 4 * 1024 * 1024;
|
|
12
|
+
var MCP_MAX_TOOL_LIST_ENTRIES = 1e3;
|
|
13
|
+
var MCP_MAX_TOOL_RESULT_BYTES = 1024 * 1024;
|
|
14
|
+
var MCP_MAX_TOOL_SEARCH_DISCLOSURE_BYTES = 256 * 1024;
|
|
15
|
+
var MCP_MAX_SELECTED_SERVERS = 64;
|
|
16
|
+
var MCP_MAX_CONCURRENT_SERVER_OPERATIONS = 8;
|
|
17
|
+
var MCP_MAX_AGGREGATE_TOOL_LIST_ENTRIES = 4096;
|
|
18
|
+
var MCP_MAX_AGGREGATE_TOOL_LIST_BYTES = 16 * 1024 * 1024;
|
|
19
|
+
var MCP_MAX_TOOL_SEARCH_SOURCES = 64;
|
|
20
|
+
var MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH = 120;
|
|
21
|
+
var MCP_MAX_TOOL_SEARCH_DESCRIPTION_BYTES = 16 * 1024;
|
|
22
|
+
var McpPayloadTooLargeError = class extends Error {
|
|
23
|
+
constructor(label, actualBytes, maxBytes) {
|
|
24
|
+
super(`${label} exceeds the ${maxBytes}-byte safety limit`);
|
|
25
|
+
this.label = label;
|
|
26
|
+
this.actualBytes = actualBytes;
|
|
27
|
+
this.maxBytes = maxBytes;
|
|
28
|
+
this.name = "McpPayloadTooLargeError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function mcpSerializedSizeBytes(value) {
|
|
32
|
+
let serialized;
|
|
33
|
+
try {
|
|
34
|
+
serialized = JSON.stringify(value) ?? "null";
|
|
35
|
+
} catch {
|
|
36
|
+
throw new Error("MCP payload is not JSON serializable");
|
|
37
|
+
}
|
|
38
|
+
return Buffer.byteLength(serialized);
|
|
39
|
+
}
|
|
40
|
+
function assertMcpPayloadWithinBytes(value, maxBytes, label) {
|
|
41
|
+
const actualBytes = mcpSerializedSizeBytes(value);
|
|
42
|
+
if (actualBytes > maxBytes) {
|
|
43
|
+
throw new McpPayloadTooLargeError(label, actualBytes, maxBytes);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function assertMcpToolListWithinBounds(tools) {
|
|
47
|
+
if (tools.length > MCP_MAX_TOOL_LIST_ENTRIES) {
|
|
48
|
+
throw new McpPayloadTooLargeError("MCP tool list", tools.length, MCP_MAX_TOOL_LIST_ENTRIES);
|
|
49
|
+
}
|
|
50
|
+
for (const tool of tools) {
|
|
51
|
+
const toolBytes = mcpSerializedSizeBytes(tool);
|
|
52
|
+
if (toolBytes > MCP_MAX_TOOL_DEFINITION_BYTES) {
|
|
53
|
+
throw new McpPayloadTooLargeError(
|
|
54
|
+
"MCP tool definition",
|
|
55
|
+
toolBytes,
|
|
56
|
+
MCP_MAX_TOOL_DEFINITION_BYTES
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const totalBytes = mcpSerializedSizeBytes(tools);
|
|
61
|
+
if (totalBytes > MCP_MAX_TOOL_LIST_BYTES) {
|
|
62
|
+
throw new McpPayloadTooLargeError("MCP tool list", totalBytes, MCP_MAX_TOOL_LIST_BYTES);
|
|
63
|
+
}
|
|
64
|
+
return tools;
|
|
65
|
+
}
|
|
66
|
+
function assertMcpServerSelectionWithinBounds(servers) {
|
|
67
|
+
if (servers.length > MCP_MAX_SELECTED_SERVERS) {
|
|
68
|
+
throw new McpPayloadTooLargeError(
|
|
69
|
+
"selected MCP server count",
|
|
70
|
+
servers.length,
|
|
71
|
+
MCP_MAX_SELECTED_SERVERS
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return servers;
|
|
75
|
+
}
|
|
76
|
+
var McpAggregateToolListBudget = class {
|
|
77
|
+
constructor(label = "aggregate MCP tool list", maxEntries = MCP_MAX_AGGREGATE_TOOL_LIST_ENTRIES, maxBytes = MCP_MAX_AGGREGATE_TOOL_LIST_BYTES) {
|
|
78
|
+
this.label = label;
|
|
79
|
+
this.maxEntries = maxEntries;
|
|
80
|
+
this.maxBytes = maxBytes;
|
|
81
|
+
}
|
|
82
|
+
contributions = /* @__PURE__ */ new Map();
|
|
83
|
+
totalEntries = 0;
|
|
84
|
+
totalBytes = 0;
|
|
85
|
+
replace(sourceId, tools) {
|
|
86
|
+
assertMcpToolListWithinBounds(tools);
|
|
87
|
+
const contribution = {
|
|
88
|
+
entries: tools.length,
|
|
89
|
+
// Conservatively account each server as its complete serialized array.
|
|
90
|
+
// Summing these arrays slightly over-counts the brackets relative to one
|
|
91
|
+
// flattened array, which is intentional for a fail-closed hard ceiling.
|
|
92
|
+
bytes: mcpSerializedSizeBytes(tools)
|
|
93
|
+
};
|
|
94
|
+
const previous = this.contributions.get(sourceId) ?? { entries: 0, bytes: 0 };
|
|
95
|
+
const nextEntries = this.totalEntries - previous.entries + contribution.entries;
|
|
96
|
+
if (nextEntries > this.maxEntries) {
|
|
97
|
+
throw new McpPayloadTooLargeError(this.label, nextEntries, this.maxEntries);
|
|
98
|
+
}
|
|
99
|
+
const nextBytes = this.totalBytes - previous.bytes + contribution.bytes;
|
|
100
|
+
if (nextBytes > this.maxBytes) {
|
|
101
|
+
throw new McpPayloadTooLargeError(this.label, nextBytes, this.maxBytes);
|
|
102
|
+
}
|
|
103
|
+
this.contributions.set(sourceId, contribution);
|
|
104
|
+
this.totalEntries = nextEntries;
|
|
105
|
+
this.totalBytes = nextBytes;
|
|
106
|
+
return tools;
|
|
107
|
+
}
|
|
108
|
+
remove(sourceId) {
|
|
109
|
+
const previous = this.contributions.get(sourceId);
|
|
110
|
+
if (!previous) return;
|
|
111
|
+
this.contributions.delete(sourceId);
|
|
112
|
+
this.totalEntries -= previous.entries;
|
|
113
|
+
this.totalBytes -= previous.bytes;
|
|
114
|
+
}
|
|
115
|
+
snapshot() {
|
|
116
|
+
return { entries: this.totalEntries, bytes: this.totalBytes };
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
async function boundedParallelMap(values, concurrency, mapper) {
|
|
120
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
121
|
+
throw new Error("bounded parallel map concurrency must be a positive integer");
|
|
122
|
+
}
|
|
123
|
+
if (values.length === 0) return [];
|
|
124
|
+
const results = new Array(values.length);
|
|
125
|
+
const errors = [];
|
|
126
|
+
let nextIndex = 0;
|
|
127
|
+
let stopped = false;
|
|
128
|
+
const worker = async () => {
|
|
129
|
+
while (!stopped) {
|
|
130
|
+
const index = nextIndex;
|
|
131
|
+
if (index >= values.length) return;
|
|
132
|
+
nextIndex += 1;
|
|
133
|
+
try {
|
|
134
|
+
results[index] = await mapper(values[index], index);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
errors.push({ index, error });
|
|
137
|
+
stopped = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, values.length) }, () => worker()));
|
|
142
|
+
if (errors.length > 0) {
|
|
143
|
+
errors.sort((left, right) => left.index - right.index);
|
|
144
|
+
throw errors[0].error;
|
|
145
|
+
}
|
|
146
|
+
return results;
|
|
147
|
+
}
|
|
148
|
+
function guardedMcpFetch(settings, fetchImpl, options = {}) {
|
|
149
|
+
return async (input, init) => {
|
|
150
|
+
const response = await pinnedFetch(input, init, settings, {
|
|
151
|
+
fetchImpl,
|
|
152
|
+
...options.dnsLookup ? { dnsLookup: options.dnsLookup } : {},
|
|
153
|
+
label: "MCP endpoint",
|
|
154
|
+
requireHttpsOutsideLocalTest: options.requireHttpsOutsideLocalTest ?? true
|
|
155
|
+
});
|
|
156
|
+
return boundMcpResponseBody(response, options.maxResponseBytes ?? MCP_MAX_RESPONSE_BYTES);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function boundMcpResponseBody(response, maxBytes) {
|
|
160
|
+
const declaredLength = Number(response.headers.get("content-length"));
|
|
161
|
+
if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
|
|
162
|
+
void response.body?.cancel().catch(() => void 0);
|
|
163
|
+
throw new McpPayloadTooLargeError("MCP response", declaredLength, maxBytes);
|
|
164
|
+
}
|
|
165
|
+
if (!response.body) {
|
|
166
|
+
return response;
|
|
167
|
+
}
|
|
168
|
+
const reader = response.body.getReader();
|
|
169
|
+
let receivedBytes = 0;
|
|
170
|
+
const body = new ReadableStream({
|
|
171
|
+
async pull(controller) {
|
|
172
|
+
try {
|
|
173
|
+
const chunk = await reader.read();
|
|
174
|
+
if (chunk.done) {
|
|
175
|
+
controller.close();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
receivedBytes += chunk.value.byteLength;
|
|
179
|
+
if (receivedBytes > maxBytes) {
|
|
180
|
+
await reader.cancel().catch(() => void 0);
|
|
181
|
+
controller.error(new McpPayloadTooLargeError("MCP response", receivedBytes, maxBytes));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
controller.enqueue(chunk.value);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
controller.error(error);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
async cancel(reason) {
|
|
190
|
+
await reader.cancel(reason).catch(() => void 0);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
const bounded = new Response(body, {
|
|
194
|
+
status: response.status,
|
|
195
|
+
statusText: response.statusText,
|
|
196
|
+
headers: response.headers
|
|
197
|
+
});
|
|
198
|
+
Object.defineProperties(bounded, {
|
|
199
|
+
redirected: { value: response.redirected },
|
|
200
|
+
type: { value: response.type },
|
|
201
|
+
url: { value: response.url }
|
|
202
|
+
});
|
|
203
|
+
return bounded;
|
|
204
|
+
}
|
|
205
|
+
async function cancelMcpResponseBody(response) {
|
|
206
|
+
await response.body?.cancel().catch(() => void 0);
|
|
207
|
+
}
|
|
208
|
+
async function boundedMcpRequest(request, maxBytes = MCP_MAX_INBOUND_REQUEST_BYTES) {
|
|
209
|
+
const declared = request.headers.get("content-length");
|
|
210
|
+
if (declared !== null) {
|
|
211
|
+
const normalized = declared.trim();
|
|
212
|
+
if (!/^\d+$/.test(normalized)) {
|
|
213
|
+
await request.body?.cancel().catch(() => void 0);
|
|
214
|
+
throw new McpPayloadTooLargeError("MCP request", 0, maxBytes);
|
|
215
|
+
}
|
|
216
|
+
const declaredBytes = Number(normalized);
|
|
217
|
+
if (!Number.isSafeInteger(declaredBytes) || declaredBytes > maxBytes) {
|
|
218
|
+
await request.body?.cancel().catch(() => void 0);
|
|
219
|
+
throw new McpPayloadTooLargeError("MCP request", declaredBytes, maxBytes);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (!request.body) {
|
|
223
|
+
return request;
|
|
224
|
+
}
|
|
225
|
+
const reader = request.body.getReader();
|
|
226
|
+
const chunks = [];
|
|
227
|
+
let receivedBytes = 0;
|
|
228
|
+
try {
|
|
229
|
+
for (; ; ) {
|
|
230
|
+
const result = await reader.read();
|
|
231
|
+
if (result.done) break;
|
|
232
|
+
receivedBytes += result.value.byteLength;
|
|
233
|
+
if (receivedBytes > maxBytes) {
|
|
234
|
+
await reader.cancel().catch(() => void 0);
|
|
235
|
+
throw new McpPayloadTooLargeError("MCP request", receivedBytes, maxBytes);
|
|
236
|
+
}
|
|
237
|
+
chunks.push(result.value);
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
await reader.cancel().catch(() => void 0);
|
|
241
|
+
throw error;
|
|
242
|
+
} finally {
|
|
243
|
+
reader.releaseLock();
|
|
244
|
+
}
|
|
245
|
+
const body = new Uint8Array(receivedBytes);
|
|
246
|
+
let offset = 0;
|
|
247
|
+
for (const chunk of chunks) {
|
|
248
|
+
body.set(chunk, offset);
|
|
249
|
+
offset += chunk.byteLength;
|
|
250
|
+
}
|
|
251
|
+
return new Request(request, { body, headers: request.headers });
|
|
252
|
+
}
|
|
253
|
+
async function assertMcpDestinationAllowed(rawUrl, settings, options = {}) {
|
|
254
|
+
await resolvePinnedDestination(rawUrl, settings, {
|
|
255
|
+
...options.dnsLookup ? { dnsLookup: options.dnsLookup } : {},
|
|
256
|
+
label: "MCP endpoint",
|
|
257
|
+
requireHttpsOutsideLocalTest: true
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
var isNonPublicMcpAddress = isNonPublicAddress;
|
|
261
|
+
|
|
262
|
+
export {
|
|
263
|
+
MCP_MAX_RESPONSE_BYTES,
|
|
264
|
+
MCP_MAX_INBOUND_REQUEST_BYTES,
|
|
265
|
+
MCP_MAX_TOOL_DEFINITION_BYTES,
|
|
266
|
+
MCP_MAX_TOOL_LIST_BYTES,
|
|
267
|
+
MCP_MAX_TOOL_LIST_ENTRIES,
|
|
268
|
+
MCP_MAX_TOOL_RESULT_BYTES,
|
|
269
|
+
MCP_MAX_TOOL_SEARCH_DISCLOSURE_BYTES,
|
|
270
|
+
MCP_MAX_SELECTED_SERVERS,
|
|
271
|
+
MCP_MAX_CONCURRENT_SERVER_OPERATIONS,
|
|
272
|
+
MCP_MAX_AGGREGATE_TOOL_LIST_ENTRIES,
|
|
273
|
+
MCP_MAX_AGGREGATE_TOOL_LIST_BYTES,
|
|
274
|
+
MCP_MAX_TOOL_SEARCH_SOURCES,
|
|
275
|
+
MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH,
|
|
276
|
+
MCP_MAX_TOOL_SEARCH_DESCRIPTION_BYTES,
|
|
277
|
+
McpPayloadTooLargeError,
|
|
278
|
+
mcpSerializedSizeBytes,
|
|
279
|
+
assertMcpPayloadWithinBytes,
|
|
280
|
+
assertMcpToolListWithinBounds,
|
|
281
|
+
assertMcpServerSelectionWithinBounds,
|
|
282
|
+
McpAggregateToolListBudget,
|
|
283
|
+
boundedParallelMap,
|
|
284
|
+
guardedMcpFetch,
|
|
285
|
+
boundMcpResponseBody,
|
|
286
|
+
cancelMcpResponseBody,
|
|
287
|
+
boundedMcpRequest,
|
|
288
|
+
assertMcpDestinationAllowed,
|
|
289
|
+
isNonPublicMcpAddress,
|
|
290
|
+
undiciFetch
|
|
291
|
+
};
|
|
292
|
+
//# sourceMappingURL=chunk-HAN5D27J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp-network.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport {\n isNonPublicAddress,\n pinnedFetch,\n resolvePinnedDestination,\n type DnsLookup,\n type FetchLike,\n} from \"@opengeni/network\";\n\nexport { undiciFetch } from \"@opengeni/network\";\n\nexport const MCP_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;\nexport const MCP_MAX_INBOUND_REQUEST_BYTES = 1024 * 1024;\nexport const MCP_MAX_TOOL_DEFINITION_BYTES = 128 * 1024;\nexport const MCP_MAX_TOOL_LIST_BYTES = 4 * 1024 * 1024;\nexport const MCP_MAX_TOOL_LIST_ENTRIES = 1_000;\nexport const MCP_MAX_TOOL_RESULT_BYTES = 1024 * 1024;\nexport const MCP_MAX_TOOL_SEARCH_DISCLOSURE_BYTES = 256 * 1024;\nexport const MCP_MAX_SELECTED_SERVERS = 64;\nexport const MCP_MAX_CONCURRENT_SERVER_OPERATIONS = 8;\nexport const MCP_MAX_AGGREGATE_TOOL_LIST_ENTRIES = 4_096;\nexport const MCP_MAX_AGGREGATE_TOOL_LIST_BYTES = 16 * 1024 * 1024;\nexport const MCP_MAX_TOOL_SEARCH_SOURCES = 64;\nexport const MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH = 120;\nexport const MCP_MAX_TOOL_SEARCH_DESCRIPTION_BYTES = 16 * 1024;\n\nexport class McpPayloadTooLargeError extends Error {\n constructor(\n readonly label: string,\n readonly actualBytes: number,\n readonly maxBytes: number,\n ) {\n super(`${label} exceeds the ${maxBytes}-byte safety limit`);\n this.name = \"McpPayloadTooLargeError\";\n }\n}\n\nexport function mcpSerializedSizeBytes(value: unknown): number {\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? \"null\";\n } catch {\n throw new Error(\"MCP payload is not JSON serializable\");\n }\n return Buffer.byteLength(serialized);\n}\n\nexport function assertMcpPayloadWithinBytes(value: unknown, maxBytes: number, label: string): void {\n const actualBytes = mcpSerializedSizeBytes(value);\n if (actualBytes > maxBytes) {\n throw new McpPayloadTooLargeError(label, actualBytes, maxBytes);\n }\n}\n\nexport function assertMcpToolListWithinBounds<T>(tools: readonly T[]): readonly T[] {\n if (tools.length > MCP_MAX_TOOL_LIST_ENTRIES) {\n throw new McpPayloadTooLargeError(\"MCP tool list\", tools.length, MCP_MAX_TOOL_LIST_ENTRIES);\n }\n for (const tool of tools) {\n const toolBytes = mcpSerializedSizeBytes(tool);\n if (toolBytes > MCP_MAX_TOOL_DEFINITION_BYTES) {\n throw new McpPayloadTooLargeError(\n \"MCP tool definition\",\n toolBytes,\n MCP_MAX_TOOL_DEFINITION_BYTES,\n );\n }\n }\n // Measure the complete JSON array, including brackets and separators. Summing\n // definitions alone under-counts by one byte per separator plus the array\n // delimiters and makes the advertised serialized-byte ceiling porous.\n const totalBytes = mcpSerializedSizeBytes(tools);\n if (totalBytes > MCP_MAX_TOOL_LIST_BYTES) {\n throw new McpPayloadTooLargeError(\"MCP tool list\", totalBytes, MCP_MAX_TOOL_LIST_BYTES);\n }\n return tools;\n}\n\nexport function assertMcpServerSelectionWithinBounds<T>(servers: readonly T[]): readonly T[] {\n if (servers.length > MCP_MAX_SELECTED_SERVERS) {\n throw new McpPayloadTooLargeError(\n \"selected MCP server count\",\n servers.length,\n MCP_MAX_SELECTED_SERVERS,\n );\n }\n return servers;\n}\n\ntype McpToolListContribution = {\n entries: number;\n bytes: number;\n};\n\n/**\n * Atomic aggregate accounting shared by every exposed tools/list in one run.\n * A repeated list for the same source REPLACES its prior contribution, so\n * cache invalidation/relisting cannot ratchet the budget upward. Failed\n * replacements leave the previous accounting intact.\n */\nexport class McpAggregateToolListBudget {\n private readonly contributions = new Map<string, McpToolListContribution>();\n private totalEntries = 0;\n private totalBytes = 0;\n\n constructor(\n private readonly label = \"aggregate MCP tool list\",\n private readonly maxEntries = MCP_MAX_AGGREGATE_TOOL_LIST_ENTRIES,\n private readonly maxBytes = MCP_MAX_AGGREGATE_TOOL_LIST_BYTES,\n ) {}\n\n replace<T>(sourceId: string, tools: readonly T[]): readonly T[] {\n assertMcpToolListWithinBounds(tools);\n const contribution = {\n entries: tools.length,\n // Conservatively account each server as its complete serialized array.\n // Summing these arrays slightly over-counts the brackets relative to one\n // flattened array, which is intentional for a fail-closed hard ceiling.\n bytes: mcpSerializedSizeBytes(tools),\n };\n const previous = this.contributions.get(sourceId) ?? { entries: 0, bytes: 0 };\n const nextEntries = this.totalEntries - previous.entries + contribution.entries;\n if (nextEntries > this.maxEntries) {\n throw new McpPayloadTooLargeError(this.label, nextEntries, this.maxEntries);\n }\n const nextBytes = this.totalBytes - previous.bytes + contribution.bytes;\n if (nextBytes > this.maxBytes) {\n throw new McpPayloadTooLargeError(this.label, nextBytes, this.maxBytes);\n }\n this.contributions.set(sourceId, contribution);\n this.totalEntries = nextEntries;\n this.totalBytes = nextBytes;\n return tools;\n }\n\n remove(sourceId: string): void {\n const previous = this.contributions.get(sourceId);\n if (!previous) return;\n this.contributions.delete(sourceId);\n this.totalEntries -= previous.entries;\n this.totalBytes -= previous.bytes;\n }\n\n snapshot(): Readonly<McpToolListContribution> {\n return { entries: this.totalEntries, bytes: this.totalBytes };\n }\n}\n\n/** Stable-order parallel map with a hard in-flight ceiling and fail-stop drain. */\nexport async function boundedParallelMap<T, R>(\n values: readonly T[],\n concurrency: number,\n mapper: (value: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new Error(\"bounded parallel map concurrency must be a positive integer\");\n }\n if (values.length === 0) return [];\n\n const results = new Array<R>(values.length);\n const errors: Array<{ index: number; error: unknown }> = [];\n let nextIndex = 0;\n let stopped = false;\n const worker = async () => {\n while (!stopped) {\n const index = nextIndex;\n if (index >= values.length) return;\n nextIndex += 1;\n try {\n results[index] = await mapper(values[index]!, index);\n } catch (error) {\n errors.push({ index, error });\n stopped = true;\n }\n }\n };\n await Promise.all(Array.from({ length: Math.min(concurrency, values.length) }, () => worker()));\n if (errors.length > 0) {\n errors.sort((left, right) => left.index - right.index);\n throw errors[0]!.error;\n }\n return results;\n}\n\n/**\n * Guard normal MCP traffic with the same deployment policy as OAuth traffic.\n * The pinned transport resolves and policy-checks the destination after the\n * caller has composed any credential headers, then performs the final network\n * call through the vetted Agent. It forces manual redirects, so an\n * Authorization-bearing request never follows a provider-controlled Location\n * to an unvalidated host.\n *\n * This module is deliberately agent-loop-free. API code imports the explicit\n * `@opengeni/runtime/mcp-network` leaf rather than the runtime root barrel.\n */\nexport function guardedMcpFetch<TInput extends string | URL | Request>(\n settings: Pick<Settings, \"environment\" | \"integrationsAllowPrivateNetworkTargets\">,\n fetchImpl: (input: TInput, init?: RequestInit) => Promise<Response>,\n options: {\n maxResponseBytes?: number;\n dnsLookup?: DnsLookup;\n requireHttpsOutsideLocalTest?: boolean;\n } = {},\n): (input: TInput, init?: RequestInit) => Promise<Response> {\n return async (input: TInput, init?: RequestInit) => {\n const response = await pinnedFetch(input, init, settings, {\n fetchImpl: fetchImpl as FetchLike,\n ...(options.dnsLookup ? { dnsLookup: options.dnsLookup } : {}),\n label: \"MCP endpoint\",\n requireHttpsOutsideLocalTest: options.requireHttpsOutsideLocalTest ?? true,\n });\n return boundMcpResponseBody(response, options.maxResponseBytes ?? MCP_MAX_RESPONSE_BYTES);\n };\n}\n\nexport function boundMcpResponseBody(response: Response, maxBytes: number): Response {\n const declaredLength = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {\n void response.body?.cancel().catch(() => undefined);\n throw new McpPayloadTooLargeError(\"MCP response\", declaredLength, maxBytes);\n }\n if (!response.body) {\n return response;\n }\n\n const reader = response.body.getReader();\n let receivedBytes = 0;\n const body = new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const chunk = await reader.read();\n if (chunk.done) {\n controller.close();\n return;\n }\n receivedBytes += chunk.value.byteLength;\n if (receivedBytes > maxBytes) {\n await reader.cancel().catch(() => undefined);\n controller.error(new McpPayloadTooLargeError(\"MCP response\", receivedBytes, maxBytes));\n return;\n }\n controller.enqueue(chunk.value);\n } catch (error) {\n controller.error(error);\n }\n },\n async cancel(reason) {\n await reader.cancel(reason).catch(() => undefined);\n },\n });\n const bounded = new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n });\n Object.defineProperties(bounded, {\n redirected: { value: response.redirected },\n type: { value: response.type },\n url: { value: response.url },\n });\n return bounded;\n}\n\nexport async function cancelMcpResponseBody(response: Response): Promise<void> {\n await response.body?.cancel().catch(() => undefined);\n}\n\n/** Read and rebuild an inbound MCP request before the SDK parses it. */\nexport async function boundedMcpRequest(\n request: Request,\n maxBytes = MCP_MAX_INBOUND_REQUEST_BYTES,\n): Promise<Request> {\n const declared = request.headers.get(\"content-length\");\n if (declared !== null) {\n const normalized = declared.trim();\n if (!/^\\d+$/.test(normalized)) {\n await request.body?.cancel().catch(() => undefined);\n throw new McpPayloadTooLargeError(\"MCP request\", 0, maxBytes);\n }\n const declaredBytes = Number(normalized);\n if (!Number.isSafeInteger(declaredBytes) || declaredBytes > maxBytes) {\n await request.body?.cancel().catch(() => undefined);\n throw new McpPayloadTooLargeError(\"MCP request\", declaredBytes, maxBytes);\n }\n }\n if (!request.body) {\n return request;\n }\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let receivedBytes = 0;\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n receivedBytes += result.value.byteLength;\n if (receivedBytes > maxBytes) {\n await reader.cancel().catch(() => undefined);\n throw new McpPayloadTooLargeError(\"MCP request\", receivedBytes, maxBytes);\n }\n chunks.push(result.value);\n }\n } catch (error) {\n await reader.cancel().catch(() => undefined);\n throw error;\n } finally {\n reader.releaseLock();\n }\n const body = new Uint8Array(receivedBytes);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new Request(request, { body, headers: request.headers });\n}\n\nexport async function assertMcpDestinationAllowed(\n rawUrl: string,\n settings: Pick<Settings, \"environment\" | \"integrationsAllowPrivateNetworkTargets\">,\n options: { dnsLookup?: DnsLookup } = {},\n): Promise<void> {\n await resolvePinnedDestination(rawUrl, settings, {\n ...(options.dnsLookup ? { dnsLookup: options.dnsLookup } : {}),\n label: \"MCP endpoint\",\n requireHttpsOutsideLocalTest: true,\n });\n}\n\nexport const isNonPublicMcpAddress = isNonPublicAddress;\n"],"mappings":"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","names":[]}
|
|
@@ -120,6 +120,7 @@ type ModalOrphanSweepResult = {
|
|
|
120
120
|
terminated: ModalOrphanSweepTermination[];
|
|
121
121
|
skipped: number;
|
|
122
122
|
};
|
|
123
|
+
type RevalidateModalOrphanTermination = (candidate: ModalOrphanSweepTermination) => Promise<boolean>;
|
|
123
124
|
declare function modalSandboxAttributionEnvironment(input: ModalSandboxAttribution): Record<string, string>;
|
|
124
125
|
declare function modalSandboxAttributionTags(input: ModalSandboxAttribution): Record<string, string>;
|
|
125
126
|
type ModalModule = typeof modal;
|
|
@@ -142,6 +143,9 @@ declare function sweepModalOrphanSandboxes(settings: Settings, liveLeases: LiveM
|
|
|
142
143
|
maxTerminations?: number;
|
|
143
144
|
unattributedGraceMs?: number;
|
|
144
145
|
client?: ModalClientLike;
|
|
146
|
+
/** Re-read durable ownership immediately before provider termination. A
|
|
147
|
+
* false result or callback failure skips the destructive action. */
|
|
148
|
+
revalidateTermination?: RevalidateModalOrphanTermination;
|
|
145
149
|
}): Promise<ModalOrphanSweepResult>;
|
|
146
150
|
|
|
147
151
|
interface NegotiationContext {
|
|
@@ -319,7 +323,7 @@ declare const DEFAULT_DESKTOP_GEOMETRY: DesktopGeometry;
|
|
|
319
323
|
* value to viewers by the caller; this error is for diagnostics. */
|
|
320
324
|
declare class DisplayStackError extends Error {
|
|
321
325
|
readonly exitCode: number;
|
|
322
|
-
readonly stage: "xvfb" | "x11vnc" | "websockify" | "paint" | "unknown";
|
|
326
|
+
readonly stage: "xvfb" | "x11vnc" | "websockify" | "paint" | "lock" | "timeout" | "unknown";
|
|
323
327
|
constructor(exitCode: number, output: string);
|
|
324
328
|
}
|
|
325
329
|
/** Thrown when the provider session cannot run commands (a headless-only
|
|
@@ -328,12 +332,39 @@ declare class DisplayStackError extends Error {
|
|
|
328
332
|
declare class DisplayStackUnsupportedError extends Error {
|
|
329
333
|
constructor(message: string);
|
|
330
334
|
}
|
|
335
|
+
type DisplayStackCallerKind = "viewer" | "computer" | "unknown";
|
|
336
|
+
type DisplayStackClassification = "cold" | "already_ready" | "contention" | "unknown";
|
|
337
|
+
type DisplayStackTelemetryStatus = "started" | "waiting" | "completed" | "failed";
|
|
338
|
+
/** Secret-free, bounded-cardinality stage observation. Provider/sandbox IDs are
|
|
339
|
+
* log correlation fields, never metric labels. */
|
|
340
|
+
type DisplayStackTelemetryEvent = {
|
|
341
|
+
type: "display_stack.stage";
|
|
342
|
+
requestId: string;
|
|
343
|
+
stage: string;
|
|
344
|
+
status: DisplayStackTelemetryStatus;
|
|
345
|
+
elapsedMs: number;
|
|
346
|
+
source: "host" | "sandbox";
|
|
347
|
+
classification: DisplayStackClassification;
|
|
348
|
+
callerKind: DisplayStackCallerKind;
|
|
349
|
+
sandboxId?: string;
|
|
350
|
+
leaseEpoch?: number;
|
|
351
|
+
providerSessionId?: number;
|
|
352
|
+
};
|
|
353
|
+
type DisplayStackTelemetryContext = {
|
|
354
|
+
callerKind: DisplayStackCallerKind;
|
|
355
|
+
sandboxId?: string;
|
|
356
|
+
leaseEpoch?: number;
|
|
357
|
+
};
|
|
331
358
|
type EnsureDisplayStackOptions = {
|
|
332
359
|
geometry?: DesktopGeometry;
|
|
333
360
|
/** The exposed stream port; defaults to 6080. */
|
|
334
361
|
port?: number;
|
|
335
|
-
/**
|
|
362
|
+
/** Whole-operation wall-clock timeout; defaults to DISPLAY_STACK_TIMEOUT_MS. */
|
|
336
363
|
timeoutMs?: number;
|
|
364
|
+
/** Caller correlation. Supplying it enables the default structured log sink. */
|
|
365
|
+
telemetryContext?: DisplayStackTelemetryContext;
|
|
366
|
+
/** Optional non-blocking telemetry sink (tests/embedders may replace logging). */
|
|
367
|
+
onTelemetry?: (event: DisplayStackTelemetryEvent) => void | Promise<void>;
|
|
337
368
|
};
|
|
338
369
|
type EnsureDisplayStackResult = {
|
|
339
370
|
/** The exposed port the stack listens on (websockify/noVNC). */
|
|
@@ -685,6 +716,9 @@ declare function deleteRecordingArtifacts(session: unknown, proc: RecordingProce
|
|
|
685
716
|
/** The storage object key for a recording artifact (parallels the file-asset layout). */
|
|
686
717
|
declare function recordingStorageKey(workspaceId: string, sessionId: string, recordingId: string, codec: RecordingCodec): string;
|
|
687
718
|
|
|
719
|
+
declare function parseExecBannerSessionId(raw: string): number | null;
|
|
720
|
+
declare function parseExecBannerExitCode(raw: string): number | null;
|
|
721
|
+
|
|
688
722
|
type ChannelAExecResult = {
|
|
689
723
|
output?: string;
|
|
690
724
|
stdout?: string;
|
|
@@ -863,10 +897,6 @@ declare class SandboxChannelAService {
|
|
|
863
897
|
}
|
|
864
898
|
declare function stripExecBanner(raw: string): string;
|
|
865
899
|
declare function isExecSessionLostBanner(out: string, execSessionId: number): boolean;
|
|
866
|
-
declare function parseExecBannerSessionId(raw: string): number | null;
|
|
867
|
-
/** Recover a completed execCommand fallback's exit status from its banner.
|
|
868
|
-
* Only the banner region is inspected, so command output cannot spoof success. */
|
|
869
|
-
declare function parseExecBannerExitCode(raw: string): number | null;
|
|
870
900
|
declare function assertSafeRelPath(p: string): string;
|
|
871
901
|
declare function parsePorcelainV2(z: string): Omit<GitStatusResponse, "revision">;
|
|
872
902
|
type NumstatEntry = {
|
|
@@ -2571,4 +2601,4 @@ declare function establishSandboxSessionFromEnvelope(settings: Settings, envelop
|
|
|
2571
2601
|
*/
|
|
2572
2602
|
declare function serializeEstablishedSandboxEnvelope(established: EstablishedSandboxSession): Promise<Record<string, unknown> | null>;
|
|
2573
2603
|
|
|
2574
|
-
export {
|
|
2604
|
+
export { type NegotiationContext as $, type ActiveBackendResolverDeps as A, type BackendUnresolvableCode as B, ChannelAConflictError as C, DEFAULT_DESKTOP_GEOMETRY as D, type EnsureDisplayStackOptions as E, type ExposeStreamPortResult as F, type ExposedPortEndpoint as G, FAULT_FIELD_WHAT_HAPPENED as H, FAULT_FIELD_WHAT_PRESERVED as I, FAULT_FIELD_WHAT_TO_TRY as J, FAULT_FIELD_WHICH_LAYER as K, type LiveModalSandboxLeaseAttribution as L, type MaterializeRunCredentialsOptions as M, type MintStreamTokenInput as N, MockAgentResponder as O, type MockAgentResponderOptions as P, type MockExecHandler as Q, type RunCredentialSessionReady as R, type ModalModuleLoader as S, type ModalOrphanSweepResult as T, type ModalOrphanSweepTermination as U, type ModalSandboxAttribution as V, NEVER_SENT_DETAIL_KEY as W, NatsControlRpc as X, type NatsOpStreamConnection as Y, NatsOpStreamTransport as Z, type NatsRequestConnection as _, type RuntimeMetricsHooks as a, type SelfhostedNegotiationInput as a$, type NormalizedRunCredentialMaterial as a0, type NumstatEntry as a1, OP_STREAM_ACK_INTERVAL_MS as a2, OP_STREAM_DEFAULT_WINDOW_BYTES as a3, OP_STREAM_RECONNECT_HOLD_MS as a4, OP_STREAM_SILENCE_TIMEOUT_MS as a5, type OpStreamExecOutcome as a6, type OpStreamJournal as a7, type OpStreamSubscription as a8, type OpStreamTransport as a9, SELFHOSTED_DRAINING_MAX_RETRIES as aA, SELFHOSTED_EXEC_DRAINING_MAX_RETRIES as aB, SELFHOSTED_IDEMPOTENT_READONLY_OPS as aC, SELFHOSTED_INFRASTRUCTURE_FAULT_CLASSES as aD, SELFHOSTED_NEVER_SENT_MAX_RETRIES as aE, SELFHOSTED_RECONNECT_WINDOW_MS as aF, SELFHOSTED_RELAY_STREAM_PATH as aG, SELFHOSTED_RETRY_BACKOFF_BASE_MS as aH, SELFHOSTED_RETRY_BACKOFF_CAP_MS as aI, SELFHOSTED_RETRY_BACKOFF_FACTOR as aJ, SELFHOSTED_TIMEOUT_MAX_RETRIES as aK, STREAM_PORT as aL, STREAM_TOKEN_DEFAULT_TTL_SECONDS as aM, SandboxChannelAService as aN, type SandboxChannelAServiceOptions as aO, SandboxConfigError as aP, type SandboxCreatedCallback as aQ, SandboxProviderUnavailableError as aR, SandboxResumeStateUnavailableError as aS, type SelfhostedApplyDiff as aT, SelfhostedControlError as aU, type SelfhostedEditor as aV, type SelfhostedEnrollment as aW, type SelfhostedExecArgs as aX, type SelfhostedExecResult as aY, type SelfhostedImageOutput as aZ, type SelfhostedLivenessState as a_, OpStreamUnavailableError as aa, PROVIDER_REGISTRY as ab, type ProviderConstructionContext as ac, type ProviderRegistration as ad, REPOSITORY_DISCOVERY_LIMIT as ae, type RecordingArtifactMetadata as af, type RecordingCodec as ag, type RecordingContentType as ah, RecordingError as ai, type RecordingProcess as aj, RecordingUnavailableError as ak, type RepositoryDiscoveryDegradedReason as al, type RepositoryDiscoveryResult as am, type ResolvedActiveBackend as an, type RevalidateModalOrphanTermination as ao, type RoutableBackendSession as ap, type RoutableSandbox as aq, RoutingSandboxSession as ar, type RoutingSandboxSessionDeps as as, type RoutingTransitionEvent as at, RoutingUnsupportedError as au, type RunCredentialCommandRunner as av, type RunCredentialCommandSession as aw, type RunCredentialExpectedScope as ax, RunCredentialValidationError as ay, SELFHOSTED_DEFAULT_TIMEOUT_MS as az, ActiveBackendUnresolvableError as b, offlineControlResponse as b$, type SelfhostedOpObservation as b0, type SelfhostedOpObserver as b1, type SelfhostedOpStreamDeps as b2, type SelfhostedRelayConfig as b3, type SelfhostedRetryClock as b4, type SelfhostedRetryDecision as b5, SelfhostedSandboxClient as b6, SelfhostedSession as b7, type SelfhostedSessionBuild as b8, type SelfhostedSessionDeps as b9, deletePriorPersistedSnapshot as bA, deleteRecordingArtifacts as bB, deserializeSandboxSessionStateEnvelope as bC, desktopCapableBackend as bD, drainingExhaustedError as bE, drainingMessage as bF, ensureDisplayStack as bG, ensureModalRegistryImage as bH, ensureTerminalServer as bI, establishSandboxSessionFromEnvelope as bJ, execDeadlineHint as bK, exposeStreamPort as bL, extForCodec as bM, inspectRecordingArtifact as bN, isExecSessionLostBanner as bO, isProviderSandboxNotFoundError as bP, isSelfhostedProviderNotFoundError as bQ, makeActiveBackendResolver as bR, materializeRunCredentials as bS, mintStreamToken as bT, modalSandboxAttributionEnvironment as bU, modalSandboxAttributionTags as bV, negotiateCapabilities as bW, negotiateSelfhostedCapabilities as bX, nextDurableOpId as bY, normalizeRunCredentialsResolution as bZ, offlineAgentError as b_, type SelfhostedSessionState as ba, type SelfhostedUnavailableReason as bb, type StartRecordingInput as bc, StreamPortUnavailableError as bd, type SwapTargetEstablishability as be, TERMINAL_SERVER_TIMEOUT_MS as bf, TerminalServerError as bg, TerminalServerUnsupportedError as bh, ToolspaceTokenPathError as bi, agentErrorToControlError as bj, assertDescriptorRegistryInvariants as bk, assertProviderRegistryInvariants as bl, assertSafeRelPath as bm, backendSupportsOs as bn, buildDisplayStackScript as bo, buildSelfhostedBackendSession as bp, buildStreamUrl as bq, buildTerminalServerScript as br, clearRunCredentials as bs, clearRunCredentialsForAttempt as bt, contentTypeForCodec as bu, createSandboxClient as bv, createSandboxClientForBackend as bw, decideSelfhostedRetry as bx, decodeModalSnapshotId as by, defaultSelfhostedRetryClock as bz, type ActivePointer as c, opAckSubject as c0, opFrameSubject as c1, parseExecBannerExitCode as c2, parseExecBannerSessionId as c3, parseNumstatZ as c4, parsePorcelainV2 as c5, parseUnifiedPatch as c6, payloadTooLargeMessage as c7, readWorkspaceArchiveFromEnvelopeSessionState as c8, recordingStorageKey as c9, toolspaceTokenFileFromEnvironment as cA, uploadRecordingArtifact as cB, verifyStreamToken as cC, withRunCredentialEnvironment as cD, withRunCredentialsClient as cE, withRunCredentialsSession as cF, withToolspaceTokenClient as cG, withToolspaceTokenEnvironment as cH, withToolspaceTokenSession as cI, renderSelfhostedFault as ca, restoredSandboxSessionStateFromEntry as cb, runCredentialPointerFile as cc, runCredentialRoot as cd, runWithToolCallCorrelation as ce, sandboxStateEntryFromRunState as cf, sanitizeOpIdToken as cg, selectBackend as ch, selfhostedFaultClass as ci, selfhostedLiveness as cj, selfhostedRetryBackoffMs as ck, serializeEstablishedSandboxEnvelope as cl, setSelfhostedApplyDiff as cm, startRecording as cn, stopRecording as co, stripExecBanner as cp, subjectFor as cq, swapTargetEstablishability as cr, sweepModalOrphanSandboxes as cs, tagModalSandbox as ct, tearDownDisplayStack as cu, tearDownTerminalServer as cv, terminateModalSandboxById as cw, timeoutAgentError as cx, timeoutControlResponse as cy, toolspaceTokenFileForSession as cz, type ChannelAEmitter as d, type ChannelAExecArgs as e, type ChannelAExecResult as f, ChannelANotFoundError as g, type ChannelASession as h, ChannelAUnavailableError as i, ChannelAUnsupportedError as j, ChannelAValidationError as k, type ControlRpc as l, DISPLAY_STACK_TIMEOUT_MS as m, type DesktopGeometry as n, type DisplayStackCallerKind as o, type DisplayStackClassification as p, DisplayStackError as q, type DisplayStackTelemetryContext as r, type DisplayStackTelemetryEvent as s, type DisplayStackTelemetryStatus as t, DisplayStackUnsupportedError as u, type EnsureDisplayStackResult as v, type EnsureTerminalServerOptions as w, type EnsureTerminalServerResult as x, type EstablishedSandboxSession as y, type ExposeStreamPortInput as z };
|