@opengeni/runtime 2.5.2 → 2.5.3-canary.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.
Files changed (32) hide show
  1. package/dist/{agent-Q2VNH5FV.js → agent-RJQLKFIW.js} +2 -2
  2. package/dist/{chunk-CD22I76N.js → chunk-FHGLYLBL.js} +2 -2
  3. package/dist/{chunk-GJC7H2FC.js → chunk-SD6MDONS.js} +350 -67
  4. package/dist/chunk-SD6MDONS.js.map +1 -0
  5. package/dist/{chunk-25B3EQRW.js → chunk-UNICCRW5.js} +4 -4
  6. package/dist/{chunk-LGLJ5PVD.js → chunk-VVEGJPDR.js} +2309 -1345
  7. package/dist/chunk-VVEGJPDR.js.map +1 -0
  8. package/dist/index.d.ts +7 -0
  9. package/dist/index.js +22 -4
  10. package/dist/{localSources-Z5IJIIRV.js → localSources-PVFCAPN2.js} +3 -3
  11. package/dist/mcp-operation-dispatch.d.ts +45 -0
  12. package/dist/mcp-operation-observation.d.ts +137 -0
  13. package/dist/sandbox/archive-spool.d.ts +14 -0
  14. package/dist/sandbox/host-archive-spool.d.ts +19 -0
  15. package/dist/sandbox/index.d.ts +5 -1
  16. package/dist/sandbox/index.js +7 -3
  17. package/dist/sandbox/workspace-archive.d.ts +7 -0
  18. package/dist/workspace-tool-gateway.js +4 -4
  19. package/package.json +11 -11
  20. package/src/index.ts +231 -45
  21. package/src/mcp-operation-dispatch.ts +144 -0
  22. package/src/mcp-operation-observation.ts +148 -0
  23. package/src/sandbox/archive-spool.ts +16 -0
  24. package/src/sandbox/host-archive-spool.ts +1040 -0
  25. package/src/sandbox/index.ts +292 -203
  26. package/src/sandbox/workspace-archive.ts +54 -1
  27. package/dist/chunk-GJC7H2FC.js.map +0 -1
  28. package/dist/chunk-LGLJ5PVD.js.map +0 -1
  29. /package/dist/{agent-Q2VNH5FV.js.map → agent-RJQLKFIW.js.map} +0 -0
  30. /package/dist/{chunk-CD22I76N.js.map → chunk-FHGLYLBL.js.map} +0 -0
  31. /package/dist/{chunk-25B3EQRW.js.map → chunk-UNICCRW5.js.map} +0 -0
  32. /package/dist/{localSources-Z5IJIIRV.js.map → localSources-PVFCAPN2.js.map} +0 -0
@@ -23,11 +23,11 @@ import {
23
23
  withRunCredentialsClient,
24
24
  withRunCredentialsSession,
25
25
  wrapCapabilityToolsForTurnCancellation
26
- } from "./chunk-LGLJ5PVD.js";
26
+ } from "./chunk-VVEGJPDR.js";
27
27
  import {
28
28
  MemorySession,
29
29
  connectMcpServers
30
- } from "./chunk-CD22I76N.js";
30
+ } from "./chunk-FHGLYLBL.js";
31
31
  import {
32
32
  SKILL_MAX_FILES,
33
33
  SkillFileError,
@@ -108,7 +108,7 @@ import {
108
108
  tool,
109
109
  withGenerationSpan,
110
110
  withResponseSpan
111
- } from "./chunk-25B3EQRW.js";
111
+ } from "./chunk-UNICCRW5.js";
112
112
 
113
113
  // src/command-read-refresh.ts
114
114
  async function executeCommandReadWithRefresh(input) {
@@ -203,6 +203,168 @@ function commandSnapshot(result) {
203
203
  }
204
204
  }
205
205
 
206
+ // src/mcp-operation-dispatch.ts
207
+ import { AsyncLocalStorage } from "async_hooks";
208
+ var dispatchContext = new AsyncLocalStorage();
209
+ function hasActiveRecoverableMcpOperation() {
210
+ return dispatchContext.getStore() !== void 0;
211
+ }
212
+ var McpOperationOutcomeUnknownError = class extends Error {
213
+ constructor(operationId, cause) {
214
+ super(
215
+ `MCP operation ${operationId} has an unknown outcome. Read the existing operation result; do not repeat the mutation.`,
216
+ { cause }
217
+ );
218
+ this.operationId = operationId;
219
+ this.name = "McpOperationOutcomeUnknownError";
220
+ }
221
+ code = "mcp_operation_outcome_unknown";
222
+ };
223
+ async function runRecoverableMcpOperation(operation, persistence, execute) {
224
+ const context = {
225
+ operation: { ...operation },
226
+ persistence,
227
+ captureStarted: false,
228
+ captured: false,
229
+ closed: false
230
+ };
231
+ return await dispatchContext.run(context, async () => {
232
+ let result;
233
+ try {
234
+ try {
235
+ result = await execute();
236
+ } catch (error) {
237
+ if (!context.captured) throw error;
238
+ try {
239
+ await persistence.settleOriginal({
240
+ operationId: operation.operationId,
241
+ outcome: "outcome_unknown"
242
+ });
243
+ } catch {
244
+ }
245
+ throw new McpOperationOutcomeUnknownError(operation.operationId, error);
246
+ }
247
+ if (!context.captured) {
248
+ throw new Error("Recoverable MCP execution did not cross its durable capture boundary");
249
+ }
250
+ try {
251
+ await persistence.settleOriginal({
252
+ operationId: operation.operationId,
253
+ outcome: "completed",
254
+ result
255
+ });
256
+ } catch (error) {
257
+ throw new McpOperationOutcomeUnknownError(operation.operationId, error);
258
+ }
259
+ return result;
260
+ } finally {
261
+ context.closed = true;
262
+ }
263
+ });
264
+ }
265
+ async function captureMcpOperationDispatch(input) {
266
+ const context = dispatchContext.getStore();
267
+ if (!context) return;
268
+ const operation = context.operation;
269
+ if (input.operationId !== operation.operationId || input.serverId !== operation.serverId || input.toolName !== operation.originalTool || input.destinationDigest !== operation.destinationDigest || !/^[a-f0-9]{64}$/u.test(input.authorityDigest))
270
+ throw new Error("Recoverable MCP dispatch identity does not match its trusted binding");
271
+ if (context.closed || context.captureStarted) {
272
+ throw new Error("MCP operation dispatch is already claimed or closed");
273
+ }
274
+ context.captureStarted = true;
275
+ const result = await context.persistence.capture({
276
+ ...operation,
277
+ authorityDigest: input.authorityDigest
278
+ });
279
+ if (result !== "created")
280
+ throw new Error("MCP operation was already dispatched; read its existing result");
281
+ if (context.closed) throw new Error("MCP operation dispatch closed during capture");
282
+ context.captured = true;
283
+ }
284
+
285
+ // src/mcp-operation-observation.ts
286
+ import { AttemptToolResult } from "@opengeni/contracts";
287
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
288
+ var observationAuthority = new AsyncLocalStorage2();
289
+ async function runMcpOperationObservationWithAuthority(binding, execute) {
290
+ const scope = { binding: { ...binding }, closed: false };
291
+ return await observationAuthority.run(scope, async () => {
292
+ try {
293
+ return await execute();
294
+ } finally {
295
+ scope.closed = true;
296
+ }
297
+ });
298
+ }
299
+ function assertMcpOperationObservationAuthority(actual) {
300
+ const scope = observationAuthority.getStore();
301
+ if (!scope) return;
302
+ const expected = scope.binding;
303
+ if (scope.closed || actual.serverId !== expected.serverId || actual.toolName !== expected.observerTool || actual.destinationDigest !== expected.destinationDigest || actual.authorityDigest !== expected.authorityDigest) {
304
+ throw new Error("MCP operation observation authority changed before provider use");
305
+ }
306
+ }
307
+ var fingerprint = external_exports.object({
308
+ version: external_exports.literal(1),
309
+ algorithm: external_exports.literal("sha256"),
310
+ value: external_exports.string().regex(/^[a-f0-9]{64}$/u)
311
+ }).strict();
312
+ var identity = {
313
+ version: external_exports.literal(1),
314
+ operationRef: external_exports.string().uuid(),
315
+ fingerprint
316
+ };
317
+ var receiptSchema = external_exports.discriminatedUnion("status", [
318
+ external_exports.object({ ...identity, status: external_exports.literal("unknown") }).strict(),
319
+ external_exports.object({
320
+ ...identity,
321
+ status: external_exports.literal("pending"),
322
+ evidenceRevision: external_exports.string().min(1)
323
+ }).strict(),
324
+ external_exports.object({
325
+ ...identity,
326
+ status: external_exports.literal("completed"),
327
+ receiptRevision: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= 1024, {
328
+ message: "MCP receipt revision must fit the ledger's 1024-byte identity field"
329
+ }),
330
+ result: AttemptToolResult
331
+ }).strict(),
332
+ external_exports.object({ ...identity, status: external_exports.literal("conflict") }).strict()
333
+ ]);
334
+ var bindingSchema = external_exports.object({
335
+ operationId: external_exports.string().uuid(),
336
+ serverId: external_exports.string().min(1),
337
+ originalTool: external_exports.string().min(1),
338
+ observerTool: external_exports.string().min(1),
339
+ argumentDigest: fingerprint.shape.value
340
+ }).strict().refine((value) => value.originalTool !== value.observerTool, {
341
+ message: "The observer must not be the original mutation tool"
342
+ });
343
+ async function observeMcpOperation(input) {
344
+ const binding = bindingSchema.parse(input.binding);
345
+ if (!await input.authorize("before_request")) {
346
+ throw new Error("MCP operation observation is not authorized");
347
+ }
348
+ const response = await input.callObserver(binding.observerTool, {
349
+ version: 1,
350
+ operationRef: binding.operationId,
351
+ originalTool: binding.originalTool,
352
+ fingerprint: { version: 1, algorithm: "sha256", value: binding.argumentDigest }
353
+ });
354
+ if (!await input.authorize("before_delivery")) {
355
+ throw new Error("MCP operation observation is not authorized for delivery");
356
+ }
357
+ const envelope = AttemptToolResult.parse(response);
358
+ if (envelope.isError) {
359
+ throw new Error("MCP operation observer returned an error, not a receipt");
360
+ }
361
+ const receipt = receiptSchema.parse(envelope.structuredContent);
362
+ if (receipt.operationRef !== binding.operationId || receipt.fingerprint.value !== binding.argumentDigest) {
363
+ throw new Error("MCP operation observation receipt identity does not match");
364
+ }
365
+ return receipt;
366
+ }
367
+
206
368
  // src/skill-catalog.ts
207
369
  var SKILL_CATALOG_MAX_BYTES = 32 * 1024;
208
370
  var SKILL_CATALOG_MAX_ENTRIES = 128;
@@ -259,6 +421,7 @@ import {
259
421
  AGENT_INSTRUCTIONS_CORE_PLACEHOLDER,
260
422
  collectSandboxEnvironment,
261
423
  configuredProviders as configuredProviders2,
424
+ McpOperationRecoverySchema,
262
425
  firstPartyMcpInternalBaseUrl,
263
426
  firstPartyMcpInternalWorkspaceUrl as firstPartyMcpInternalWorkspaceUrl2,
264
427
  resolveFirstPartyDelegationSecret as resolveFirstPartyDelegationSecret2,
@@ -299,7 +462,7 @@ import {
299
462
  GenerateVideoToolInput,
300
463
  GetVideoGenerationCapabilitiesToolInput,
301
464
  RequestHumanInputToolInput as RequestHumanInputToolInput2,
302
- AttemptToolResult as AttemptToolResult2
465
+ AttemptToolResult as AttemptToolResult3
303
466
  } from "@opengeni/contracts";
304
467
  import { renderSessionGoalContext as renderSessionGoalContext2 } from "@opengeni/contracts";
305
468
 
@@ -2842,13 +3005,13 @@ function convertToOutputItem(items) {
2842
3005
  };
2843
3006
  return output;
2844
3007
  } else if (item.type === "program") {
2845
- const { id, call_id, code, fingerprint, type: _type, ...providerData } = item;
3008
+ const { id, call_id, code, fingerprint: fingerprint2, type: _type, ...providerData } = item;
2846
3009
  const output = {
2847
3010
  type: "program",
2848
3011
  id,
2849
3012
  callId: call_id,
2850
3013
  code,
2851
- fingerprint,
3014
+ fingerprint: fingerprint2,
2852
3015
  providerData
2853
3016
  };
2854
3017
  return output;
@@ -3763,14 +3926,14 @@ var OpenAIResponsesWSModel = class extends OpenAIResponsesModel {
3763
3926
  return baseURL.toString();
3764
3927
  }
3765
3928
  async #ensureWebSocketConnection(wsURL, headers, signal, requestTimeoutDeadline) {
3766
- const identity = this.#getConnectionIdentity(wsURL, headers);
3767
- if (this.#wsConnection && this.#wsConnectionIdentity && this.#wsConnectionIdentity === identity && this.#wsConnection.isReusable()) {
3929
+ const identity2 = this.#getConnectionIdentity(wsURL, headers);
3930
+ if (this.#wsConnection && this.#wsConnectionIdentity && this.#wsConnectionIdentity === identity2 && this.#wsConnection.isReusable()) {
3768
3931
  return { connection: this.#wsConnection, reused: true };
3769
3932
  }
3770
3933
  await this.#dropWebSocketConnection();
3771
3934
  const connectTimeout = this.#resolveWebSocketRequestTimeout(requestTimeoutDeadline, (configuredTimeoutMs) => `Responses websocket connection timed out before opening after ${configuredTimeoutMs}ms.`);
3772
3935
  this.#wsConnection = await ResponsesWebSocketConnection.connect(wsURL, headers, signal, connectTimeout.timeoutMs, connectTimeout.errorMessage, this.#websocketOptions);
3773
- this.#wsConnectionIdentity = identity;
3936
+ this.#wsConnectionIdentity = identity2;
3774
3937
  return { connection: this.#wsConnection, reused: false };
3775
3938
  }
3776
3939
  async #reconnectWebSocketConnection(wsURL, headers, signal, requestTimeoutDeadline) {
@@ -7022,8 +7185,8 @@ function searchToolPool(availableTools, rawArguments) {
7022
7185
  }
7023
7186
 
7024
7187
  // src/model-request-capture.ts
7025
- import { AsyncLocalStorage } from "async_hooks";
7026
- var modelRequestCapture = new AsyncLocalStorage();
7188
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
7189
+ var modelRequestCapture = new AsyncLocalStorage3();
7027
7190
  var captureIndices = /* @__PURE__ */ new WeakMap();
7028
7191
  function nextModelContextCaptureIndex(agent) {
7029
7192
  const index = (captureIndices.get(agent) ?? 0) + 1;
@@ -7787,7 +7950,7 @@ var LazyToolModelProvider = class {
7787
7950
 
7788
7951
  // src/mcp-result-custom-data.ts
7789
7952
  import {
7790
- AttemptToolResult
7953
+ AttemptToolResult as AttemptToolResult2
7791
7954
  } from "@opengeni/contracts";
7792
7955
  import { randomUUID } from "crypto";
7793
7956
  var OPENGENI_MCP_RESULT_CUSTOM_DATA_KEY = "__opengeniMcpResultV1";
@@ -7858,7 +8021,7 @@ function normalizeSdkToolOutputCustomData(value) {
7858
8021
  return JSON.parse(JSON.stringify(value));
7859
8022
  }
7860
8023
  function normalizeMcpResult(value) {
7861
- return normalizeProtocolJsonValue(AttemptToolResult.parse(value), "$.mcpResult");
8024
+ return normalizeProtocolJsonValue(AttemptToolResult2.parse(value), "$.mcpResult");
7862
8025
  }
7863
8026
  var McpResultCustomDataBridge = class {
7864
8027
  constructor(input) {
@@ -8048,7 +8211,7 @@ function compactMcpResultCustomDataRunState(serialized) {
8048
8211
  function mcpResultFromCustomData(customData) {
8049
8212
  if (!customData || typeof customData !== "object" || Array.isArray(customData)) return null;
8050
8213
  const marker = customData[OPENGENI_MCP_RESULT_CUSTOM_DATA_KEY];
8051
- const parsed = AttemptToolResult.safeParse(marker);
8214
+ const parsed = AttemptToolResult2.safeParse(marker);
8052
8215
  return parsed.success ? parsed.data : null;
8053
8216
  }
8054
8217
 
@@ -8263,7 +8426,7 @@ import {
8263
8426
  CODEX_ORIGINATOR,
8264
8427
  codexAppsSanitizingFetch
8265
8428
  } from "@opengeni/codex";
8266
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
8429
+ import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
8267
8430
  import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
8268
8431
  import { dirname as dirname2, isAbsolute, join as join2, posix as posixPath2 } from "path";
8269
8432
 
@@ -10975,9 +11138,9 @@ function* jsonStringFragments(value) {
10975
11138
  }
10976
11139
 
10977
11140
  // src/model-preparation-diagnostics.ts
10978
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
10979
- var modelPreparationObserver = new AsyncLocalStorage2();
10980
- var modelTransportStartedObserver = new AsyncLocalStorage2();
11141
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
11142
+ var modelPreparationObserver = new AsyncLocalStorage4();
11143
+ var modelTransportStartedObserver = new AsyncLocalStorage4();
10981
11144
  var ModelPreparationTraceProcessor = class {
10982
11145
  async onTraceStart(_trace) {
10983
11146
  }
@@ -11933,7 +12096,7 @@ import { existsSync, readdirSync } from "fs";
11933
12096
  // ../sdk/package.json
11934
12097
  var package_default = {
11935
12098
  name: "@opengeni/sdk",
11936
- version: "5.0.3",
12099
+ version: "5.0.5-canary.0",
11937
12100
  description: "Framework-agnostic TypeScript SDK for the OpenGeni API: typed client, session lifecycle, SSE event streaming with reconnect + replay-by-sequence, and proxy re-streaming helpers.",
11938
12101
  license: "Apache-2.0",
11939
12102
  repository: {
@@ -12073,7 +12236,7 @@ var package_default = {
12073
12236
  // ../react/package.json
12074
12237
  var package_default2 = {
12075
12238
  name: "@opengeni/react",
12076
- version: "5.0.4",
12239
+ version: "5.0.5-canary.0",
12077
12240
  description: "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views \u2014 token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
12078
12241
  license: "Apache-2.0",
12079
12242
  repository: {
@@ -12325,7 +12488,7 @@ var package_default2 = {
12325
12488
  // ../codemode/package.json
12326
12489
  var package_default3 = {
12327
12490
  name: "@opengeni/codemode",
12328
- version: "0.5.5",
12491
+ version: "0.5.6-canary.0",
12329
12492
  description: "Attempt-frozen programmatic tool catalog and execution authority for OpenGeni.",
12330
12493
  license: "Apache-2.0",
12331
12494
  repository: {
@@ -12374,7 +12537,7 @@ var package_default3 = {
12374
12537
  // ../ogtool/package.json
12375
12538
  var package_default4 = {
12376
12539
  name: "@opengeni/ogtool",
12377
- version: "0.3.37",
12540
+ version: "0.3.38-canary.0",
12378
12541
  description: "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
12379
12542
  license: "Apache-2.0",
12380
12543
  repository: {
@@ -16788,7 +16951,8 @@ var ConnectorActionExecutionError = class extends Error {
16788
16951
  this.connectorActionOutcome = outcome;
16789
16952
  }
16790
16953
  };
16791
- var modelToolInvocation = new AsyncLocalStorage3();
16954
+ var modelToolInvocation = new AsyncLocalStorage5();
16955
+ var modelMcpCallIdentity = new AsyncLocalStorage5();
16792
16956
  var agentInputWaitYields = /* @__PURE__ */ new WeakMap();
16793
16957
  function rigInstructions(rig) {
16794
16958
  return [
@@ -17231,6 +17395,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
17231
17395
  agent2,
17232
17396
  options.approvedToolCallId
17233
17397
  );
17398
+ installModelMcpCallIdentity(agent2);
17234
17399
  return agent2;
17235
17400
  }
17236
17401
  if (options.activeSandboxBackend === "selfhosted" && !options.sandboxWorkspaceRoot) {
@@ -17332,6 +17497,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
17332
17497
  agent,
17333
17498
  options.approvedToolCallId
17334
17499
  );
17500
+ installModelMcpCallIdentity(agent);
17335
17501
  return agent;
17336
17502
  }
17337
17503
  function maybeInstallLazyToolTransport(agent, settings, options) {
@@ -17368,6 +17534,35 @@ function sessionMcpApprovalConnectionId(serverId, url) {
17368
17534
  const targetHash = createHash5("sha256").update(url, "utf8").digest("hex");
17369
17535
  return `session-mcp:${serverId}:${targetHash}`;
17370
17536
  }
17537
+ function installModelMcpCallIdentity(agent) {
17538
+ const listMcpTools = agent.getMcpTools.bind(agent);
17539
+ agent.getMcpTools = async (resolutionContext) => (await listMcpTools(resolutionContext)).map((tool2) => {
17540
+ if (tool2.type !== "function") return tool2;
17541
+ const invoke = tool2.invoke.bind(tool2);
17542
+ return {
17543
+ ...tool2,
17544
+ invoke: async (runContext, input, details) => {
17545
+ const callId3 = details?.toolCall?.callId;
17546
+ return await modelMcpCallIdentity.run(
17547
+ typeof callId3 === "string" && callId3.length > 0 ? { modelName: tool2.name, callId: callId3 } : null,
17548
+ async () => await invoke(runContext, input, details)
17549
+ );
17550
+ }
17551
+ };
17552
+ });
17553
+ const clone = agent.clone?.bind(agent);
17554
+ if (clone) {
17555
+ agent.clone = (config) => {
17556
+ const cloned = clone(config);
17557
+ installModelMcpCallIdentity(cloned);
17558
+ return cloned;
17559
+ };
17560
+ }
17561
+ }
17562
+ function modelMcpSourceCallId(modelName) {
17563
+ const identity2 = modelMcpCallIdentity.getStore();
17564
+ return identity2?.modelName === modelName ? identity2.callId : void 0;
17565
+ }
17371
17566
  function installMcpApprovalPolicy(agent, policies, connectorActionPolicy, approvedToolCallId) {
17372
17567
  const approvalRequiredCallIds = /* @__PURE__ */ new Set();
17373
17568
  const preparations = /* @__PURE__ */ new Map();
@@ -17958,24 +18153,30 @@ async function prepareAgentTools(settings, tools, options = {}) {
17958
18153
  }
17959
18154
  const optional2 = tool2.optional === true;
17960
18155
  return {
17961
- server: new PrefixedMcpServer(
17962
- local.server,
17963
- config.id,
17964
- config.allowedTools,
17965
- optional2 || Boolean(config.connectionRef),
17966
- aggregateToolBudget,
17967
- `${config.id}:${index}`,
17968
- false,
17969
- buildConnectorAttachmentAuthority(
17970
- config,
17971
- options,
17972
- resolvedMcpToolConnectionIds,
17973
- config.url,
17974
- local.resolvedConnectionId
18156
+ server: configureMcpOperationRecovery(
18157
+ new PrefixedMcpServer(
18158
+ local.server,
18159
+ config.id,
18160
+ config.allowedTools,
18161
+ optional2 || Boolean(config.connectionRef),
18162
+ aggregateToolBudget,
18163
+ `${config.id}:${index}`,
18164
+ false,
18165
+ buildConnectorAttachmentAuthority(
18166
+ config,
18167
+ options,
18168
+ resolvedMcpToolConnectionIds,
18169
+ config.url,
18170
+ local.resolvedConnectionId
18171
+ ),
18172
+ tool2.eager !== true,
18173
+ local.preflightCall,
18174
+ local.approvalAuthority
17975
18175
  ),
17976
- tool2.eager !== true,
17977
- local.preflightCall,
17978
- local.approvalAuthority
18176
+ config,
18177
+ options,
18178
+ config.url,
18179
+ false
17979
18180
  ),
17980
18181
  bestEffort: optional2 || Boolean(config.connectionRef),
17981
18182
  optional: optional2,
@@ -18048,20 +18249,26 @@ async function prepareAgentTools(settings, tools, options = {}) {
18048
18249
  clientSessionTimeoutSeconds: Math.ceil(config.timeoutMs / 1e3)
18049
18250
  } : {}
18050
18251
  });
18051
- const server = new PrefixedMcpServer(
18052
- innerServer,
18053
- config.id,
18054
- config.allowedTools,
18055
- bestEffort,
18056
- aggregateToolBudget,
18057
- `${config.id}:${index}`,
18058
- firstParty && !bestEffort,
18059
- buildConnectorAttachmentAuthority(config, options, resolvedMcpToolConnectionIds, url),
18060
- tool2.eager !== true,
18061
- void 0,
18062
- void 0,
18063
- firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? inputWaitYield : void 0,
18064
- firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? options.refreshOwnedCommand : void 0
18252
+ const server = configureMcpOperationRecovery(
18253
+ new PrefixedMcpServer(
18254
+ innerServer,
18255
+ config.id,
18256
+ config.allowedTools,
18257
+ bestEffort,
18258
+ aggregateToolBudget,
18259
+ `${config.id}:${index}`,
18260
+ firstParty && !bestEffort,
18261
+ buildConnectorAttachmentAuthority(config, options, resolvedMcpToolConnectionIds, url),
18262
+ tool2.eager !== true,
18263
+ void 0,
18264
+ void 0,
18265
+ firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? inputWaitYield : void 0,
18266
+ firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? options.refreshOwnedCommand : void 0
18267
+ ),
18268
+ config,
18269
+ options,
18270
+ url,
18271
+ Boolean(config.connectionRef) && !bridge && !isCodexAppsMcpServer(config)
18065
18272
  );
18066
18273
  return {
18067
18274
  server,
@@ -18570,17 +18777,39 @@ async function prepareToolGatewayDefinitionsFromServers(servers, registry) {
18570
18777
  ...context.signal ? { signal: context.signal } : {}
18571
18778
  })
18572
18779
  } : {},
18573
- execute: async (args, context) => await server.executeCatalogTool(
18574
- toolName,
18575
- args,
18576
- {
18577
- ...context.transportMeta ?? {},
18578
- opengeniOperationId: context.operationId
18579
- },
18580
- {
18581
- ...context.signal ? { signal: context.signal } : {}
18780
+ execute: async (args, context) => {
18781
+ const execute = async () => await server.executeCatalogTool(
18782
+ toolName,
18783
+ args,
18784
+ {
18785
+ ...context.transportMeta ?? {},
18786
+ opengeniOperationId: context.operationId
18787
+ },
18788
+ {
18789
+ ...context.signal ? { signal: context.signal } : {}
18790
+ }
18791
+ );
18792
+ const recovery = configuredMcpOperationRecovery(server, toolName);
18793
+ if (!recovery) return await execute();
18794
+ if (!recovery.supported || !["model", "codemode"].includes(context.caller.kind)) {
18795
+ throw new Error(
18796
+ "MCP operation recovery requires an exact attempt and remote brokered execution"
18797
+ );
18582
18798
  }
18583
- )
18799
+ return await runRecoverableMcpOperation(
18800
+ {
18801
+ operationId: context.operationId,
18802
+ ...context.sourceCallId === void 0 ? {} : { sourceCallId: context.sourceCallId },
18803
+ serverId: server.registryId,
18804
+ originalTool: toolName,
18805
+ observerTool: recovery.policy[toolName].observerTool,
18806
+ destinationDigest: recovery.destinationDigest,
18807
+ argumentDigest: digestCanonicalJson(args)
18808
+ },
18809
+ recovery.persistence,
18810
+ execute
18811
+ );
18812
+ }
18584
18813
  };
18585
18814
  });
18586
18815
  }
@@ -18594,6 +18823,22 @@ function attemptToolCodemodePath(serverId, toolName) {
18594
18823
  }
18595
18824
  return [serverId, toolName];
18596
18825
  }
18826
+ var mcpOperationRecoveryByServer = /* @__PURE__ */ new WeakMap();
18827
+ function configureMcpOperationRecovery(server, config, options, destinationUrl, brokered) {
18828
+ if (config.operationRecovery && options.mcpOperationPersistence) {
18829
+ mcpOperationRecoveryByServer.set(server, {
18830
+ policy: McpOperationRecoverySchema.parse(config.operationRecovery),
18831
+ persistence: options.mcpOperationPersistence,
18832
+ destinationDigest: digestCanonicalJson(new URL(destinationUrl).toString()),
18833
+ supported: brokered && attemptToolScope(options) !== null
18834
+ });
18835
+ }
18836
+ return server;
18837
+ }
18838
+ function configuredMcpOperationRecovery(server, toolName) {
18839
+ const recovery = mcpOperationRecoveryByServer.get(server);
18840
+ return recovery && Object.hasOwn(recovery.policy, toolName) ? recovery : void 0;
18841
+ }
18597
18842
  function attemptToolSource(serverId) {
18598
18843
  if (serverId === "opengeni" || serverId === "files" || serverId === "docs") {
18599
18844
  return serverId;
@@ -18650,6 +18895,24 @@ function connectionBrokerFetch(baseFetch, config, options, resolvedMcpConnection
18650
18895
  suppressSetupAuthNeeded
18651
18896
  );
18652
18897
  }
18898
+ if (request.method === "tools/call") {
18899
+ assertMcpOperationObservationAuthority({
18900
+ serverId: config.id,
18901
+ ...request.toolName === void 0 ? {} : { toolName: request.toolName },
18902
+ destinationDigest: digestCanonicalJson(destinationUrl),
18903
+ ...first.operationAuthorityDigest === void 0 ? {} : { authorityDigest: first.operationAuthorityDigest }
18904
+ });
18905
+ if (hasActiveRecoverableMcpOperation() && (request.batch || request.id === void 0 || request.id === null || !request.operationId || !request.toolName)) {
18906
+ throw new Error("Recoverable MCP request is missing its exact dispatch identity");
18907
+ }
18908
+ await captureMcpOperationDispatch({
18909
+ operationId: request.operationId ?? "",
18910
+ serverId: config.id,
18911
+ toolName: request.toolName ?? "",
18912
+ destinationDigest: digestCanonicalJson(destinationUrl),
18913
+ authorityDigest: first.operationAuthorityDigest ?? ""
18914
+ });
18915
+ }
18653
18916
  const response = await baseFetch(
18654
18917
  fetchInputForAttempt(input),
18655
18918
  withConnectionHeaders(input, init, first.headers)
@@ -19635,10 +19898,12 @@ var AttemptDefinitionMcpServer = class {
19635
19898
  async callToolResult(toolName, args, meta, options) {
19636
19899
  if (this.closed) throw new Error("local model tool server is closed");
19637
19900
  const environment = await this.requiredAttemptToolEnvironment();
19901
+ const sourceCallId = modelMcpSourceCallId(toolName);
19638
19902
  return await this.resultCustomDataBridge.captureResult(
19639
19903
  args,
19640
19904
  async (cleanArgs) => environment.callModel({
19641
19905
  modelName: toolName,
19906
+ ...sourceCallId === void 0 ? {} : { sourceCallId },
19642
19907
  arguments: cleanArgs ?? {},
19643
19908
  subjectId: this.subjectId,
19644
19909
  ...meta === void 0 ? {} : { transportMeta: meta },
@@ -19888,8 +20153,10 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19888
20153
  }
19889
20154
  return await this.resultCustomDataBridge.captureResult(args, async (cleanArgs) => {
19890
20155
  if (this.attemptToolEnvironment) {
20156
+ const sourceCallId = modelMcpSourceCallId(toolName);
19891
20157
  return await this.attemptToolEnvironment.callModel({
19892
20158
  modelName: toolName,
20159
+ ...sourceCallId === void 0 ? {} : { sourceCallId },
19893
20160
  arguments: cleanArgs ?? {},
19894
20161
  subjectId: this.attemptToolSubjectId,
19895
20162
  ...meta === void 0 ? {} : { transportMeta: meta },
@@ -19909,6 +20176,9 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19909
20176
  if (!this.isAllowed(unprefixed)) {
19910
20177
  throw new Error(`MCP tool ${unprefixed} is not allowed for server ${this.registryId}`);
19911
20178
  }
20179
+ if (configuredMcpOperationRecovery(this, unprefixed) && !hasActiveRecoverableMcpOperation()) {
20180
+ throw new Error("MCP operation recovery requires its trusted attempt execution context");
20181
+ }
19912
20182
  const recordsPhysicalCall = !(this.inner instanceof _PrefixedMcpServer);
19913
20183
  const startedAt = recordsPhysicalCall ? performance.now() : 0;
19914
20184
  let metricRecorded = false;
@@ -19929,7 +20199,7 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19929
20199
  args: args ?? {},
19930
20200
  ...options?.signal ? { signal: options.signal } : {},
19931
20201
  refresh: this.refreshOwnedCommand,
19932
- call: async (callArgs) => AttemptToolResult2.parse(unwrapSdkMcpResultProjection(await physicalCall(callArgs)))
20202
+ call: async (callArgs) => AttemptToolResult3.parse(unwrapSdkMcpResultProjection(await physicalCall(callArgs)))
19933
20203
  }) : await physicalCall(args ?? {});
19934
20204
  const rawOutput = unwrapSdkMcpResultProjection(projectedOutput);
19935
20205
  const connectionId = operationId ? this.connectorAttachmentAuthority?.connectionIdForOperation(operationId) : void 0;
@@ -19954,7 +20224,7 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19954
20224
  });
19955
20225
  }
19956
20226
  });
19957
- const result = AttemptToolResult2.parse(output);
20227
+ const result = AttemptToolResult3.parse(output);
19958
20228
  boundedMcpToolResult(result);
19959
20229
  recordOutcome(result.isError === true ? "provider_declared_error" : "success");
19960
20230
  if (unprefixed === "wait_for_input" && result.isError !== true) {
@@ -19962,6 +20232,12 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19962
20232
  }
19963
20233
  return result;
19964
20234
  } catch (error) {
20235
+ if (hasActiveRecoverableMcpOperation()) {
20236
+ recordOutcome(
20237
+ isToolOutcomeUncertainMcpError(error) ? "outcome_uncertain" : isAuthNeededMcpError(error) ? "auth_needed" : mcpThrownToolCallOutcome(error, options?.signal)
20238
+ );
20239
+ throw error;
20240
+ }
19965
20241
  if (isToolOutcomeUncertainMcpError(error)) {
19966
20242
  recordOutcome("outcome_uncertain");
19967
20243
  return boundedMcpToolResult({
@@ -22845,6 +23121,13 @@ function sortJson(value) {
22845
23121
  }
22846
23122
 
22847
23123
  export {
23124
+ hasActiveRecoverableMcpOperation,
23125
+ McpOperationOutcomeUnknownError,
23126
+ runRecoverableMcpOperation,
23127
+ captureMcpOperationDispatch,
23128
+ runMcpOperationObservationWithAuthority,
23129
+ assertMcpOperationObservationAuthority,
23130
+ observeMcpOperation,
22848
23131
  formatSkillCatalog,
22849
23132
  OpenAIResponsesModel,
22850
23133
  OpenAIChatCompletionsModel,
@@ -23094,4 +23377,4 @@ export {
23094
23377
  runAzureCliLoginHook,
23095
23378
  renderSessionGoalContext2 as renderSessionGoalContext
23096
23379
  };
23097
- //# sourceMappingURL=chunk-GJC7H2FC.js.map
23380
+ //# sourceMappingURL=chunk-SD6MDONS.js.map