@opengeni/runtime 2.5.2 → 2.5.3-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/{agent-Q2VNH5FV.js → agent-RJQLKFIW.js} +2 -2
  2. package/dist/{chunk-LGLJ5PVD.js → chunk-46BFUGFL.js} +2622 -1368
  3. package/dist/chunk-46BFUGFL.js.map +1 -0
  4. package/dist/{chunk-CD22I76N.js → chunk-FHGLYLBL.js} +2 -2
  5. package/dist/{chunk-25B3EQRW.js → chunk-UNICCRW5.js} +4 -4
  6. package/dist/{chunk-GJC7H2FC.js → chunk-VUEWS4GI.js} +494 -95
  7. package/dist/chunk-VUEWS4GI.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/operational-instructions.d.ts +1 -1
  14. package/dist/sandbox/archive-spool.d.ts +14 -0
  15. package/dist/sandbox/host-archive-spool.d.ts +19 -0
  16. package/dist/sandbox/index.d.ts +5 -1
  17. package/dist/sandbox/index.js +7 -3
  18. package/dist/sandbox/routing/backend-resolver.d.ts +1 -0
  19. package/dist/sandbox/selfhosted/file-transfer.d.ts +20 -0
  20. package/dist/sandbox/selfhosted/session.d.ts +7 -0
  21. package/dist/sandbox/workspace-archive.d.ts +7 -0
  22. package/dist/workspace-skills.d.ts +4 -0
  23. package/dist/workspace-tool-gateway.js +4 -4
  24. package/package.json +11 -11
  25. package/src/bundled_default_skills/document-parsing/SKILL.md +36 -0
  26. package/src/bundled_site_skills/opengeni-sites/SKILL.md +1 -1
  27. package/src/index.ts +231 -45
  28. package/src/lazy-tool-transport.ts +2 -0
  29. package/src/mcp-operation-dispatch.ts +144 -0
  30. package/src/mcp-operation-observation.ts +148 -0
  31. package/src/operational-instructions.ts +1 -1
  32. package/src/runtime-skills.ts +7 -2
  33. package/src/sandbox/archive-spool.ts +16 -0
  34. package/src/sandbox/host-archive-spool.ts +1040 -0
  35. package/src/sandbox/index.ts +292 -203
  36. package/src/sandbox/routing/backend-resolver.ts +2 -0
  37. package/src/sandbox/selfhosted/control-rpc.ts +22 -0
  38. package/src/sandbox/selfhosted/fault-rendering.ts +9 -0
  39. package/src/sandbox/selfhosted/file-transfer.ts +160 -0
  40. package/src/sandbox/selfhosted/op-testing.ts +3 -0
  41. package/src/sandbox/selfhosted/session.ts +194 -5
  42. package/src/sandbox/workspace-archive.ts +54 -1
  43. package/src/workspace-skills.ts +171 -31
  44. package/dist/chunk-GJC7H2FC.js.map +0 -1
  45. package/dist/chunk-LGLJ5PVD.js.map +0 -1
  46. /package/dist/{agent-Q2VNH5FV.js.map → agent-RJQLKFIW.js.map} +0 -0
  47. /package/dist/{chunk-CD22I76N.js.map → chunk-FHGLYLBL.js.map} +0 -0
  48. /package/dist/{chunk-25B3EQRW.js.map → chunk-UNICCRW5.js.map} +0 -0
  49. /package/dist/{localSources-Z5IJIIRV.js.map → localSources-PVFCAPN2.js.map} +0 -0
@@ -23,14 +23,17 @@ import {
23
23
  withRunCredentialsClient,
24
24
  withRunCredentialsSession,
25
25
  wrapCapabilityToolsForTurnCancellation
26
- } from "./chunk-LGLJ5PVD.js";
26
+ } from "./chunk-46BFUGFL.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
+ SKILL_READ_MAX_OUTPUT_BYTES,
34
+ SKILL_READ_MAX_PATHS,
33
35
  SkillFileError,
36
+ assertSkillRelativePath,
34
37
  buildPortableSkillArtifact,
35
38
  listSkillPaths,
36
39
  readSkillFiles,
@@ -108,7 +111,7 @@ import {
108
111
  tool,
109
112
  withGenerationSpan,
110
113
  withResponseSpan
111
- } from "./chunk-25B3EQRW.js";
114
+ } from "./chunk-UNICCRW5.js";
112
115
 
113
116
  // src/command-read-refresh.ts
114
117
  async function executeCommandReadWithRefresh(input) {
@@ -203,6 +206,168 @@ function commandSnapshot(result) {
203
206
  }
204
207
  }
205
208
 
209
+ // src/mcp-operation-dispatch.ts
210
+ import { AsyncLocalStorage } from "async_hooks";
211
+ var dispatchContext = new AsyncLocalStorage();
212
+ function hasActiveRecoverableMcpOperation() {
213
+ return dispatchContext.getStore() !== void 0;
214
+ }
215
+ var McpOperationOutcomeUnknownError = class extends Error {
216
+ constructor(operationId, cause) {
217
+ super(
218
+ `MCP operation ${operationId} has an unknown outcome. Read the existing operation result; do not repeat the mutation.`,
219
+ { cause }
220
+ );
221
+ this.operationId = operationId;
222
+ this.name = "McpOperationOutcomeUnknownError";
223
+ }
224
+ code = "mcp_operation_outcome_unknown";
225
+ };
226
+ async function runRecoverableMcpOperation(operation, persistence, execute) {
227
+ const context = {
228
+ operation: { ...operation },
229
+ persistence,
230
+ captureStarted: false,
231
+ captured: false,
232
+ closed: false
233
+ };
234
+ return await dispatchContext.run(context, async () => {
235
+ let result;
236
+ try {
237
+ try {
238
+ result = await execute();
239
+ } catch (error) {
240
+ if (!context.captured) throw error;
241
+ try {
242
+ await persistence.settleOriginal({
243
+ operationId: operation.operationId,
244
+ outcome: "outcome_unknown"
245
+ });
246
+ } catch {
247
+ }
248
+ throw new McpOperationOutcomeUnknownError(operation.operationId, error);
249
+ }
250
+ if (!context.captured) {
251
+ throw new Error("Recoverable MCP execution did not cross its durable capture boundary");
252
+ }
253
+ try {
254
+ await persistence.settleOriginal({
255
+ operationId: operation.operationId,
256
+ outcome: "completed",
257
+ result
258
+ });
259
+ } catch (error) {
260
+ throw new McpOperationOutcomeUnknownError(operation.operationId, error);
261
+ }
262
+ return result;
263
+ } finally {
264
+ context.closed = true;
265
+ }
266
+ });
267
+ }
268
+ async function captureMcpOperationDispatch(input) {
269
+ const context = dispatchContext.getStore();
270
+ if (!context) return;
271
+ const operation = context.operation;
272
+ 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))
273
+ throw new Error("Recoverable MCP dispatch identity does not match its trusted binding");
274
+ if (context.closed || context.captureStarted) {
275
+ throw new Error("MCP operation dispatch is already claimed or closed");
276
+ }
277
+ context.captureStarted = true;
278
+ const result = await context.persistence.capture({
279
+ ...operation,
280
+ authorityDigest: input.authorityDigest
281
+ });
282
+ if (result !== "created")
283
+ throw new Error("MCP operation was already dispatched; read its existing result");
284
+ if (context.closed) throw new Error("MCP operation dispatch closed during capture");
285
+ context.captured = true;
286
+ }
287
+
288
+ // src/mcp-operation-observation.ts
289
+ import { AttemptToolResult } from "@opengeni/contracts";
290
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
291
+ var observationAuthority = new AsyncLocalStorage2();
292
+ async function runMcpOperationObservationWithAuthority(binding, execute) {
293
+ const scope = { binding: { ...binding }, closed: false };
294
+ return await observationAuthority.run(scope, async () => {
295
+ try {
296
+ return await execute();
297
+ } finally {
298
+ scope.closed = true;
299
+ }
300
+ });
301
+ }
302
+ function assertMcpOperationObservationAuthority(actual) {
303
+ const scope = observationAuthority.getStore();
304
+ if (!scope) return;
305
+ const expected = scope.binding;
306
+ if (scope.closed || actual.serverId !== expected.serverId || actual.toolName !== expected.observerTool || actual.destinationDigest !== expected.destinationDigest || actual.authorityDigest !== expected.authorityDigest) {
307
+ throw new Error("MCP operation observation authority changed before provider use");
308
+ }
309
+ }
310
+ var fingerprint = external_exports.object({
311
+ version: external_exports.literal(1),
312
+ algorithm: external_exports.literal("sha256"),
313
+ value: external_exports.string().regex(/^[a-f0-9]{64}$/u)
314
+ }).strict();
315
+ var identity = {
316
+ version: external_exports.literal(1),
317
+ operationRef: external_exports.string().uuid(),
318
+ fingerprint
319
+ };
320
+ var receiptSchema = external_exports.discriminatedUnion("status", [
321
+ external_exports.object({ ...identity, status: external_exports.literal("unknown") }).strict(),
322
+ external_exports.object({
323
+ ...identity,
324
+ status: external_exports.literal("pending"),
325
+ evidenceRevision: external_exports.string().min(1)
326
+ }).strict(),
327
+ external_exports.object({
328
+ ...identity,
329
+ status: external_exports.literal("completed"),
330
+ receiptRevision: external_exports.string().min(1).refine((value) => Buffer.byteLength(value, "utf8") <= 1024, {
331
+ message: "MCP receipt revision must fit the ledger's 1024-byte identity field"
332
+ }),
333
+ result: AttemptToolResult
334
+ }).strict(),
335
+ external_exports.object({ ...identity, status: external_exports.literal("conflict") }).strict()
336
+ ]);
337
+ var bindingSchema = external_exports.object({
338
+ operationId: external_exports.string().uuid(),
339
+ serverId: external_exports.string().min(1),
340
+ originalTool: external_exports.string().min(1),
341
+ observerTool: external_exports.string().min(1),
342
+ argumentDigest: fingerprint.shape.value
343
+ }).strict().refine((value) => value.originalTool !== value.observerTool, {
344
+ message: "The observer must not be the original mutation tool"
345
+ });
346
+ async function observeMcpOperation(input) {
347
+ const binding = bindingSchema.parse(input.binding);
348
+ if (!await input.authorize("before_request")) {
349
+ throw new Error("MCP operation observation is not authorized");
350
+ }
351
+ const response = await input.callObserver(binding.observerTool, {
352
+ version: 1,
353
+ operationRef: binding.operationId,
354
+ originalTool: binding.originalTool,
355
+ fingerprint: { version: 1, algorithm: "sha256", value: binding.argumentDigest }
356
+ });
357
+ if (!await input.authorize("before_delivery")) {
358
+ throw new Error("MCP operation observation is not authorized for delivery");
359
+ }
360
+ const envelope = AttemptToolResult.parse(response);
361
+ if (envelope.isError) {
362
+ throw new Error("MCP operation observer returned an error, not a receipt");
363
+ }
364
+ const receipt = receiptSchema.parse(envelope.structuredContent);
365
+ if (receipt.operationRef !== binding.operationId || receipt.fingerprint.value !== binding.argumentDigest) {
366
+ throw new Error("MCP operation observation receipt identity does not match");
367
+ }
368
+ return receipt;
369
+ }
370
+
206
371
  // src/skill-catalog.ts
207
372
  var SKILL_CATALOG_MAX_BYTES = 32 * 1024;
208
373
  var SKILL_CATALOG_MAX_ENTRIES = 128;
@@ -259,6 +424,7 @@ import {
259
424
  AGENT_INSTRUCTIONS_CORE_PLACEHOLDER,
260
425
  collectSandboxEnvironment,
261
426
  configuredProviders as configuredProviders2,
427
+ McpOperationRecoverySchema,
262
428
  firstPartyMcpInternalBaseUrl,
263
429
  firstPartyMcpInternalWorkspaceUrl as firstPartyMcpInternalWorkspaceUrl2,
264
430
  resolveFirstPartyDelegationSecret as resolveFirstPartyDelegationSecret2,
@@ -299,7 +465,7 @@ import {
299
465
  GenerateVideoToolInput,
300
466
  GetVideoGenerationCapabilitiesToolInput,
301
467
  RequestHumanInputToolInput as RequestHumanInputToolInput2,
302
- AttemptToolResult as AttemptToolResult2
468
+ AttemptToolResult as AttemptToolResult3
303
469
  } from "@opengeni/contracts";
304
470
  import { renderSessionGoalContext as renderSessionGoalContext2 } from "@opengeni/contracts";
305
471
 
@@ -2842,13 +3008,13 @@ function convertToOutputItem(items) {
2842
3008
  };
2843
3009
  return output;
2844
3010
  } else if (item.type === "program") {
2845
- const { id, call_id, code, fingerprint, type: _type, ...providerData } = item;
3011
+ const { id, call_id, code, fingerprint: fingerprint2, type: _type, ...providerData } = item;
2846
3012
  const output = {
2847
3013
  type: "program",
2848
3014
  id,
2849
3015
  callId: call_id,
2850
3016
  code,
2851
- fingerprint,
3017
+ fingerprint: fingerprint2,
2852
3018
  providerData
2853
3019
  };
2854
3020
  return output;
@@ -3763,14 +3929,14 @@ var OpenAIResponsesWSModel = class extends OpenAIResponsesModel {
3763
3929
  return baseURL.toString();
3764
3930
  }
3765
3931
  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()) {
3932
+ const identity2 = this.#getConnectionIdentity(wsURL, headers);
3933
+ if (this.#wsConnection && this.#wsConnectionIdentity && this.#wsConnectionIdentity === identity2 && this.#wsConnection.isReusable()) {
3768
3934
  return { connection: this.#wsConnection, reused: true };
3769
3935
  }
3770
3936
  await this.#dropWebSocketConnection();
3771
3937
  const connectTimeout = this.#resolveWebSocketRequestTimeout(requestTimeoutDeadline, (configuredTimeoutMs) => `Responses websocket connection timed out before opening after ${configuredTimeoutMs}ms.`);
3772
3938
  this.#wsConnection = await ResponsesWebSocketConnection.connect(wsURL, headers, signal, connectTimeout.timeoutMs, connectTimeout.errorMessage, this.#websocketOptions);
3773
- this.#wsConnectionIdentity = identity;
3939
+ this.#wsConnectionIdentity = identity2;
3774
3940
  return { connection: this.#wsConnection, reused: false };
3775
3941
  }
3776
3942
  async #reconnectWebSocketConnection(wsURL, headers, signal, requestTimeoutDeadline) {
@@ -7022,8 +7188,8 @@ function searchToolPool(availableTools, rawArguments) {
7022
7188
  }
7023
7189
 
7024
7190
  // src/model-request-capture.ts
7025
- import { AsyncLocalStorage } from "async_hooks";
7026
- var modelRequestCapture = new AsyncLocalStorage();
7191
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
7192
+ var modelRequestCapture = new AsyncLocalStorage3();
7027
7193
  var captureIndices = /* @__PURE__ */ new WeakMap();
7028
7194
  function nextModelContextCaptureIndex(agent) {
7029
7195
  const index = (captureIndices.get(agent) ?? 0) + 1;
@@ -7160,6 +7326,8 @@ var ALWAYS_VISIBLE_BASE_TOOL_NAMES = /* @__PURE__ */ new Set([
7160
7326
  "apply_patch",
7161
7327
  // The server-backed reader needs neither sandbox setup nor tool search.
7162
7328
  "skill_read",
7329
+ // Repository descriptors route to the live sandbox reader.
7330
+ "repository_skill_read",
7163
7331
  "request_human_input",
7164
7332
  "list_models"
7165
7333
  ]);
@@ -7787,7 +7955,7 @@ var LazyToolModelProvider = class {
7787
7955
 
7788
7956
  // src/mcp-result-custom-data.ts
7789
7957
  import {
7790
- AttemptToolResult
7958
+ AttemptToolResult as AttemptToolResult2
7791
7959
  } from "@opengeni/contracts";
7792
7960
  import { randomUUID } from "crypto";
7793
7961
  var OPENGENI_MCP_RESULT_CUSTOM_DATA_KEY = "__opengeniMcpResultV1";
@@ -7858,7 +8026,7 @@ function normalizeSdkToolOutputCustomData(value) {
7858
8026
  return JSON.parse(JSON.stringify(value));
7859
8027
  }
7860
8028
  function normalizeMcpResult(value) {
7861
- return normalizeProtocolJsonValue(AttemptToolResult.parse(value), "$.mcpResult");
8029
+ return normalizeProtocolJsonValue(AttemptToolResult2.parse(value), "$.mcpResult");
7862
8030
  }
7863
8031
  var McpResultCustomDataBridge = class {
7864
8032
  constructor(input) {
@@ -8048,7 +8216,7 @@ function compactMcpResultCustomDataRunState(serialized) {
8048
8216
  function mcpResultFromCustomData(customData) {
8049
8217
  if (!customData || typeof customData !== "object" || Array.isArray(customData)) return null;
8050
8218
  const marker = customData[OPENGENI_MCP_RESULT_CUSTOM_DATA_KEY];
8051
- const parsed = AttemptToolResult.safeParse(marker);
8219
+ const parsed = AttemptToolResult2.safeParse(marker);
8052
8220
  return parsed.success ? parsed.data : null;
8053
8221
  }
8054
8222
 
@@ -8263,7 +8431,7 @@ import {
8263
8431
  CODEX_ORIGINATOR,
8264
8432
  codexAppsSanitizingFetch
8265
8433
  } from "@opengeni/codex";
8266
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
8434
+ import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
8267
8435
  import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
8268
8436
  import { dirname as dirname2, isAbsolute, join as join2, posix as posixPath2 } from "path";
8269
8437
 
@@ -8856,7 +9024,7 @@ Skills are reusable instructions supplied dynamically for the current session. W
8856
9024
 
8857
9025
  Use \`session_events\` for conversation history: its default returns user and completed assistant messages, not execution noise. Cursors only paginate. Request \`results\` for final outcomes, \`tools\` for tool receipts, or \`debug\` for explicit diagnostics; request large tool bodies only when needed. Use the returned continuation cursor rather than rereading whole pages. Audit reads do not acknowledge command completion.
8858
9026
 
8859
- For a yielded command, use \`command_read\` to read available output and status, or \`command_wait\` to wait briefly using the same command interface. Keep the command ID and output cursor. A terminal read suppresses any still-pending completion notification; a running read does not. Earlier tool results and delivered messages never change. Use \`command_input\` only to send input where supported, not to poll output. An unsupported input capability does not imply output is unavailable. Give foreground commands a realistic requested wait; an internal polling slice is not a reason to return a background handle.
9027
+ For a yielded command, use \`command_read\` to read available output and status, or \`command_wait\` to wait briefly using the same command interface. Keep the command ID and output cursor. A terminal read suppresses any still-pending completion notification; a running read does not. Earlier tool results and delivered messages never change. Use \`command_input\` only to send input where supported, not to poll output. An unsupported input capability does not imply output is unavailable. Give foreground commands a realistic requested wait; default to 10 seconds (yield_time_ms: 10000). An internal polling slice is not a reason to return a background handle.
8860
9028
 
8861
9029
  If the user asks to create, inspect, continue, pause, resume, steer, rename, or otherwise manage a session, use the corresponding session tool. Pause affects the selected workstream and its descendants: pausing an ancestor also stops you, so you cannot then Resume yourself. Coordinate disjoint edits through messages instead of ancestor Pause.
8862
9030
 
@@ -10975,9 +11143,9 @@ function* jsonStringFragments(value) {
10975
11143
  }
10976
11144
 
10977
11145
  // src/model-preparation-diagnostics.ts
10978
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
10979
- var modelPreparationObserver = new AsyncLocalStorage2();
10980
- var modelTransportStartedObserver = new AsyncLocalStorage2();
11146
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
11147
+ var modelPreparationObserver = new AsyncLocalStorage4();
11148
+ var modelTransportStartedObserver = new AsyncLocalStorage4();
10981
11149
  var ModelPreparationTraceProcessor = class {
10982
11150
  async onTraceStart(_trace) {
10983
11151
  }
@@ -11711,6 +11879,7 @@ function configureOpenAI(settings) {
11711
11879
 
11712
11880
  // src/workspace-skills.ts
11713
11881
  import { createHash as createHash4 } from "crypto";
11882
+ import { parseSkillFrontmatter } from "@opengeni/contracts";
11714
11883
  import { SandboxFilesystemNotFoundError } from "modal";
11715
11884
  var SKILL_FILE = "SKILL.md";
11716
11885
  var MAX_DISCOVERED_SKILLS = 256;
@@ -11729,21 +11898,84 @@ var WorkspaceSkillsCapability = class extends Capability {
11729
11898
  }
11730
11899
  type = "workspace-skills";
11731
11900
  discovery;
11732
- async instructions() {
11901
+ bind(session) {
11902
+ if (this._session !== session) delete this.discovery;
11903
+ return super.bind(session);
11904
+ }
11905
+ discover() {
11733
11906
  const session = requireWorkspaceSkillSession(this._session);
11734
- this.discovery ??= discoverWorkspaceSkills(
11907
+ return this.discovery ??= discoverWorkspaceSkills(
11735
11908
  session,
11736
11909
  this.searchPaths,
11737
11910
  this.reservedNames,
11738
11911
  this._runAs,
11739
11912
  this.shadowedNames
11740
11913
  );
11741
- const skills = await this.discovery;
11914
+ }
11915
+ tools() {
11916
+ return [
11917
+ tool({
11918
+ name: "repository_skill_read",
11919
+ description: "Read current repository Skill files from the bound workspace. Use the exact repository: identifier from the Repository skills index. Omit paths for SKILL.md; explicit relative paths read only those files. Set listFiles:true without paths for a bounded file inventory. This reads live files through the sandbox, including Connected Machines.",
11920
+ parameters: external_exports.object({
11921
+ skill: external_exports.string().min(1),
11922
+ paths: external_exports.array(external_exports.string().min(1).max(1024)).min(1).max(SKILL_READ_MAX_PATHS).optional(),
11923
+ listFiles: external_exports.boolean().optional()
11924
+ }),
11925
+ execute: async (request) => {
11926
+ if (request.listFiles && request.paths !== void 0)
11927
+ throw new SkillFileError(
11928
+ "invalid_request",
11929
+ "listFiles:true cannot be combined with paths."
11930
+ );
11931
+ const skill = (await this.discover()).find(
11932
+ (entry) => repositorySkillId(entry) === request.skill
11933
+ );
11934
+ if (!skill)
11935
+ throw new SkillFileError(
11936
+ "missing_file",
11937
+ "Repository Skill is not in this index. Use its exact repository: identifier."
11938
+ );
11939
+ const session = requireWorkspaceSkillSession(this._session);
11940
+ const root = skill.path.slice(0, -SKILL_FILE.length - 1);
11941
+ const result = request.listFiles ? listSkillPaths(
11942
+ await repositorySkillInventory(session, root, this._runAs),
11943
+ MAX_SKILL_ENTRIES
11944
+ ) : readSkillFiles(
11945
+ await repositorySkillFiles(
11946
+ session,
11947
+ root,
11948
+ request.paths ?? [SKILL_FILE],
11949
+ this._runAs
11950
+ ),
11951
+ request.paths
11952
+ );
11953
+ const output = JSON.stringify({
11954
+ skillId: request.skill,
11955
+ source: "repository",
11956
+ root,
11957
+ ...result
11958
+ });
11959
+ if (new TextEncoder().encode(output).byteLength > SKILL_READ_MAX_OUTPUT_BYTES) {
11960
+ throw new SkillFileError(
11961
+ "output_too_large",
11962
+ "Repository Skill response exceeds the read output limit. Request fewer paths."
11963
+ );
11964
+ }
11965
+ return output;
11966
+ }
11967
+ })
11968
+ ];
11969
+ }
11970
+ async instructions() {
11971
+ const skills = await this.discover();
11742
11972
  if (skills.length === 0) return null;
11743
- const available = skills.map((skill) => `- ${skill.name}: ${skill.description} (file: ${skill.path})`).join("\n");
11973
+ const available = skills.map(
11974
+ (skill) => `- ${JSON.stringify({ id: repositorySkillId(skill), name: skill.name, description: skill.description, reader: "repository_skill_read", path: skill.path })}`
11975
+ ).join("\n");
11744
11976
  return `## Repository skills
11745
11977
 
11746
- Repository skills are instructions already present in the live workspace. They do not need to be loaded or copied.
11978
+ Repository skills are instructions already present in the live workspace. Read them with repository_skill_read using the exact repository: id below. The reader returns current live files; ordinary filesystem tools execute referenced scripts and read binary assets. Configured Skills use their separate skill_read index.
11747
11979
 
11748
11980
  ### Available repository skills
11749
11981
  ${available}
@@ -11808,6 +12040,14 @@ async function discoverWorkspaceSkillsUnmeasured(session, searchPaths, reservedN
11808
12040
  const skillMarkdownPath = joinWorkspacePath(entry.path, SKILL_FILE);
11809
12041
  let markdown;
11810
12042
  try {
12043
+ const skillEntries = await session.listDir({
12044
+ path: entry.path,
12045
+ ...runAs ? { runAs } : {}
12046
+ });
12047
+ if (!skillEntries.some(
12048
+ (candidate2) => candidate2.name === SKILL_FILE && candidate2.type === "file"
12049
+ ))
12050
+ continue;
11811
12051
  const content = await session.readFile({
11812
12052
  path: skillMarkdownPath,
11813
12053
  ...runAs ? { runAs } : {}
@@ -11825,7 +12065,7 @@ async function discoverWorkspaceSkillsUnmeasured(session, searchPaths, reservedN
11825
12065
  const key = name.toLowerCase();
11826
12066
  if (shadowedNames.has(key)) continue;
11827
12067
  const description = frontmatter.description?.trim() || "No description provided.";
11828
- if (description.length > 2048 || /[\r\n]/.test(description)) {
12068
+ if (description.length > 2048) {
11829
12069
  throw new Error(`Repository skill "${name}" has an invalid description`);
11830
12070
  }
11831
12071
  if (reservedNames.has(key)) {
@@ -11896,26 +12136,59 @@ async function fingerprintWorkspaceDirectory(session, root, runAs) {
11896
12136
  await visit(root, "");
11897
12137
  return hash.digest("hex");
11898
12138
  }
11899
- function parseSkillFrontmatter(markdown) {
11900
- const lines = markdown.split(/\r?\n/);
11901
- if (lines[0]?.trim() !== "---") return {};
11902
- const end = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
11903
- if (end === -1) return {};
11904
- const values = {};
11905
- for (const line of lines.slice(1, end)) {
11906
- const separator = line.indexOf(":");
11907
- if (separator === -1) continue;
11908
- const key = line.slice(0, separator).trim();
11909
- if (key !== "name" && key !== "description") continue;
11910
- values[key] = unquote(line.slice(separator + 1).trim());
11911
- }
11912
- return values;
11913
- }
11914
- function unquote(value) {
11915
- if (value.length >= 2 && value[0] === value[value.length - 1] && (value[0] === '"' || value[0] === "'")) {
11916
- return value.slice(1, -1);
12139
+ function repositorySkillId(skill) {
12140
+ return `repository:${skill.path}`;
12141
+ }
12142
+ async function repositorySkillFiles(session, root, paths, runAs) {
12143
+ readSkillFiles(
12144
+ paths.map((path) => ({ path, content: "" })),
12145
+ paths
12146
+ );
12147
+ const files = [];
12148
+ for (const path of paths) {
12149
+ let directory = root;
12150
+ const segments = path.split("/");
12151
+ for (const [index, name] of segments.entries()) {
12152
+ const entries = await session.listDir({ path: directory, ...runAs ? { runAs } : {} });
12153
+ const entry = entries.find((candidate) => candidate.name === name);
12154
+ const expected = index === segments.length - 1 ? "file" : "dir";
12155
+ if (entry?.type !== expected)
12156
+ throw new SkillFileError("missing_file", `Repository Skill file is unavailable: ${path}`);
12157
+ directory = joinWorkspacePath(directory, name);
12158
+ }
12159
+ const content = await session.readFile({ path: directory, ...runAs ? { runAs } : {} });
12160
+ files.push({
12161
+ path,
12162
+ content: typeof content === "string" ? content : new TextDecoder("utf-8", { fatal: true }).decode(content)
12163
+ });
12164
+ readSkillFiles(
12165
+ files,
12166
+ files.map((file2) => file2.path)
12167
+ );
12168
+ }
12169
+ return files;
12170
+ }
12171
+ async function repositorySkillInventory(session, root, runAs) {
12172
+ const files = [];
12173
+ let count = 0;
12174
+ async function visit(relative) {
12175
+ const entries = await session.listDir({
12176
+ path: relative ? joinWorkspacePath(root, relative) : root,
12177
+ ...runAs ? { runAs } : {}
12178
+ });
12179
+ for (const entry of entries) {
12180
+ if (++count > MAX_SKILL_ENTRIES)
12181
+ throw new SkillFileError("output_too_large", "Repository Skill inventory is too large.");
12182
+ assertSkillRelativePath(entry.name);
12183
+ if (entry.name.includes("/"))
12184
+ throw new SkillFileError("invalid_path", "Invalid repository directory entry.");
12185
+ const path = relative ? `${relative}/${entry.name}` : entry.name;
12186
+ if (entry.type === "dir") await visit(path);
12187
+ else if (entry.type === "file") files.push({ path, content: "" });
12188
+ }
11917
12189
  }
11918
- return value;
12190
+ await visit("");
12191
+ return files;
11919
12192
  }
11920
12193
  function joinWorkspacePath(parent, child) {
11921
12194
  return `${parent.replace(/\/+$/, "")}/${child}`;
@@ -11933,7 +12206,7 @@ import { existsSync, readdirSync } from "fs";
11933
12206
  // ../sdk/package.json
11934
12207
  var package_default = {
11935
12208
  name: "@opengeni/sdk",
11936
- version: "5.0.3",
12209
+ version: "5.0.5-canary.1",
11937
12210
  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
12211
  license: "Apache-2.0",
11939
12212
  repository: {
@@ -12073,7 +12346,7 @@ var package_default = {
12073
12346
  // ../react/package.json
12074
12347
  var package_default2 = {
12075
12348
  name: "@opengeni/react",
12076
- version: "5.0.4",
12349
+ version: "5.0.5-canary.1",
12077
12350
  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
12351
  license: "Apache-2.0",
12079
12352
  repository: {
@@ -12217,6 +12490,7 @@ var package_default2 = {
12217
12490
  "react-resizable-panels": "^4.11.2",
12218
12491
  "remark-gfm": "^4.0.1",
12219
12492
  "tailwind-merge": "^3.5.0",
12493
+ "thinking-orbs": "^0.3.1",
12220
12494
  virtua: "^0.49.2"
12221
12495
  },
12222
12496
  devDependencies: {
@@ -12325,7 +12599,7 @@ var package_default2 = {
12325
12599
  // ../codemode/package.json
12326
12600
  var package_default3 = {
12327
12601
  name: "@opengeni/codemode",
12328
- version: "0.5.5",
12602
+ version: "0.5.6-canary.1",
12329
12603
  description: "Attempt-frozen programmatic tool catalog and execution authority for OpenGeni.",
12330
12604
  license: "Apache-2.0",
12331
12605
  repository: {
@@ -12374,7 +12648,7 @@ var package_default3 = {
12374
12648
  // ../ogtool/package.json
12375
12649
  var package_default4 = {
12376
12650
  name: "@opengeni/ogtool",
12377
- version: "0.3.37",
12651
+ version: "0.3.38-canary.1",
12378
12652
  description: "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
12379
12653
  license: "Apache-2.0",
12380
12654
  repository: {
@@ -12453,7 +12727,7 @@ var emptyNativeToolSkillSet = Object.freeze({
12453
12727
  videoGeneration: false
12454
12728
  });
12455
12729
  function loadNativeToolSkillArtifacts(nativeTools) {
12456
- const directories = [];
12730
+ const directories = ["bundled_default_skills"];
12457
12731
  if (nativeTools.projects) directories.push("bundled_project_skills");
12458
12732
  if (nativeTools.editableArtifacts) directories.push("bundled_artifact_skills");
12459
12733
  if (nativeTools.sites) directories.push("bundled_site_skills");
@@ -12670,7 +12944,12 @@ function selectionForActivation({
12670
12944
  }
12671
12945
  }
12672
12946
  function nativeToolSkillSources(nativeTools) {
12673
- const sources = [];
12947
+ const sources = [
12948
+ {
12949
+ names: skillDirNames(packagedSkillDirectory("bundled_default_skills")),
12950
+ reason: "included by default"
12951
+ }
12952
+ ];
12674
12953
  if (nativeTools.editableArtifacts) {
12675
12954
  sources.push({
12676
12955
  names: skillDirNames(packagedSkillDirectory("bundled_artifact_skills")),
@@ -16788,7 +17067,8 @@ var ConnectorActionExecutionError = class extends Error {
16788
17067
  this.connectorActionOutcome = outcome;
16789
17068
  }
16790
17069
  };
16791
- var modelToolInvocation = new AsyncLocalStorage3();
17070
+ var modelToolInvocation = new AsyncLocalStorage5();
17071
+ var modelMcpCallIdentity = new AsyncLocalStorage5();
16792
17072
  var agentInputWaitYields = /* @__PURE__ */ new WeakMap();
16793
17073
  function rigInstructions(rig) {
16794
17074
  return [
@@ -17231,6 +17511,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
17231
17511
  agent2,
17232
17512
  options.approvedToolCallId
17233
17513
  );
17514
+ installModelMcpCallIdentity(agent2);
17234
17515
  return agent2;
17235
17516
  }
17236
17517
  if (options.activeSandboxBackend === "selfhosted" && !options.sandboxWorkspaceRoot) {
@@ -17332,6 +17613,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
17332
17613
  agent,
17333
17614
  options.approvedToolCallId
17334
17615
  );
17616
+ installModelMcpCallIdentity(agent);
17335
17617
  return agent;
17336
17618
  }
17337
17619
  function maybeInstallLazyToolTransport(agent, settings, options) {
@@ -17368,6 +17650,35 @@ function sessionMcpApprovalConnectionId(serverId, url) {
17368
17650
  const targetHash = createHash5("sha256").update(url, "utf8").digest("hex");
17369
17651
  return `session-mcp:${serverId}:${targetHash}`;
17370
17652
  }
17653
+ function installModelMcpCallIdentity(agent) {
17654
+ const listMcpTools = agent.getMcpTools.bind(agent);
17655
+ agent.getMcpTools = async (resolutionContext) => (await listMcpTools(resolutionContext)).map((tool2) => {
17656
+ if (tool2.type !== "function") return tool2;
17657
+ const invoke = tool2.invoke.bind(tool2);
17658
+ return {
17659
+ ...tool2,
17660
+ invoke: async (runContext, input, details) => {
17661
+ const callId3 = details?.toolCall?.callId;
17662
+ return await modelMcpCallIdentity.run(
17663
+ typeof callId3 === "string" && callId3.length > 0 ? { modelName: tool2.name, callId: callId3 } : null,
17664
+ async () => await invoke(runContext, input, details)
17665
+ );
17666
+ }
17667
+ };
17668
+ });
17669
+ const clone = agent.clone?.bind(agent);
17670
+ if (clone) {
17671
+ agent.clone = (config) => {
17672
+ const cloned = clone(config);
17673
+ installModelMcpCallIdentity(cloned);
17674
+ return cloned;
17675
+ };
17676
+ }
17677
+ }
17678
+ function modelMcpSourceCallId(modelName) {
17679
+ const identity2 = modelMcpCallIdentity.getStore();
17680
+ return identity2?.modelName === modelName ? identity2.callId : void 0;
17681
+ }
17371
17682
  function installMcpApprovalPolicy(agent, policies, connectorActionPolicy, approvedToolCallId) {
17372
17683
  const approvalRequiredCallIds = /* @__PURE__ */ new Set();
17373
17684
  const preparations = /* @__PURE__ */ new Map();
@@ -17958,24 +18269,30 @@ async function prepareAgentTools(settings, tools, options = {}) {
17958
18269
  }
17959
18270
  const optional2 = tool2.optional === true;
17960
18271
  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
18272
+ server: configureMcpOperationRecovery(
18273
+ new PrefixedMcpServer(
18274
+ local.server,
18275
+ config.id,
18276
+ config.allowedTools,
18277
+ optional2 || Boolean(config.connectionRef),
18278
+ aggregateToolBudget,
18279
+ `${config.id}:${index}`,
18280
+ false,
18281
+ buildConnectorAttachmentAuthority(
18282
+ config,
18283
+ options,
18284
+ resolvedMcpToolConnectionIds,
18285
+ config.url,
18286
+ local.resolvedConnectionId
18287
+ ),
18288
+ tool2.eager !== true,
18289
+ local.preflightCall,
18290
+ local.approvalAuthority
17975
18291
  ),
17976
- tool2.eager !== true,
17977
- local.preflightCall,
17978
- local.approvalAuthority
18292
+ config,
18293
+ options,
18294
+ config.url,
18295
+ false
17979
18296
  ),
17980
18297
  bestEffort: optional2 || Boolean(config.connectionRef),
17981
18298
  optional: optional2,
@@ -18048,20 +18365,26 @@ async function prepareAgentTools(settings, tools, options = {}) {
18048
18365
  clientSessionTimeoutSeconds: Math.ceil(config.timeoutMs / 1e3)
18049
18366
  } : {}
18050
18367
  });
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
18368
+ const server = configureMcpOperationRecovery(
18369
+ new PrefixedMcpServer(
18370
+ innerServer,
18371
+ config.id,
18372
+ config.allowedTools,
18373
+ bestEffort,
18374
+ aggregateToolBudget,
18375
+ `${config.id}:${index}`,
18376
+ firstParty && !bestEffort,
18377
+ buildConnectorAttachmentAuthority(config, options, resolvedMcpToolConnectionIds, url),
18378
+ tool2.eager !== true,
18379
+ void 0,
18380
+ void 0,
18381
+ firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? inputWaitYield : void 0,
18382
+ firstParty && config.id === "opengeni" && !config.connectionRef && !bridge ? options.refreshOwnedCommand : void 0
18383
+ ),
18384
+ config,
18385
+ options,
18386
+ url,
18387
+ Boolean(config.connectionRef) && !bridge && !isCodexAppsMcpServer(config)
18065
18388
  );
18066
18389
  return {
18067
18390
  server,
@@ -18570,17 +18893,39 @@ async function prepareToolGatewayDefinitionsFromServers(servers, registry) {
18570
18893
  ...context.signal ? { signal: context.signal } : {}
18571
18894
  })
18572
18895
  } : {},
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 } : {}
18896
+ execute: async (args, context) => {
18897
+ const execute = async () => await server.executeCatalogTool(
18898
+ toolName,
18899
+ args,
18900
+ {
18901
+ ...context.transportMeta ?? {},
18902
+ opengeniOperationId: context.operationId
18903
+ },
18904
+ {
18905
+ ...context.signal ? { signal: context.signal } : {}
18906
+ }
18907
+ );
18908
+ const recovery = configuredMcpOperationRecovery(server, toolName);
18909
+ if (!recovery) return await execute();
18910
+ if (!recovery.supported || !["model", "codemode"].includes(context.caller.kind)) {
18911
+ throw new Error(
18912
+ "MCP operation recovery requires an exact attempt and remote brokered execution"
18913
+ );
18582
18914
  }
18583
- )
18915
+ return await runRecoverableMcpOperation(
18916
+ {
18917
+ operationId: context.operationId,
18918
+ ...context.sourceCallId === void 0 ? {} : { sourceCallId: context.sourceCallId },
18919
+ serverId: server.registryId,
18920
+ originalTool: toolName,
18921
+ observerTool: recovery.policy[toolName].observerTool,
18922
+ destinationDigest: recovery.destinationDigest,
18923
+ argumentDigest: digestCanonicalJson(args)
18924
+ },
18925
+ recovery.persistence,
18926
+ execute
18927
+ );
18928
+ }
18584
18929
  };
18585
18930
  });
18586
18931
  }
@@ -18594,6 +18939,22 @@ function attemptToolCodemodePath(serverId, toolName) {
18594
18939
  }
18595
18940
  return [serverId, toolName];
18596
18941
  }
18942
+ var mcpOperationRecoveryByServer = /* @__PURE__ */ new WeakMap();
18943
+ function configureMcpOperationRecovery(server, config, options, destinationUrl, brokered) {
18944
+ if (config.operationRecovery && options.mcpOperationPersistence) {
18945
+ mcpOperationRecoveryByServer.set(server, {
18946
+ policy: McpOperationRecoverySchema.parse(config.operationRecovery),
18947
+ persistence: options.mcpOperationPersistence,
18948
+ destinationDigest: digestCanonicalJson(new URL(destinationUrl).toString()),
18949
+ supported: brokered && attemptToolScope(options) !== null
18950
+ });
18951
+ }
18952
+ return server;
18953
+ }
18954
+ function configuredMcpOperationRecovery(server, toolName) {
18955
+ const recovery = mcpOperationRecoveryByServer.get(server);
18956
+ return recovery && Object.hasOwn(recovery.policy, toolName) ? recovery : void 0;
18957
+ }
18597
18958
  function attemptToolSource(serverId) {
18598
18959
  if (serverId === "opengeni" || serverId === "files" || serverId === "docs") {
18599
18960
  return serverId;
@@ -18650,6 +19011,24 @@ function connectionBrokerFetch(baseFetch, config, options, resolvedMcpConnection
18650
19011
  suppressSetupAuthNeeded
18651
19012
  );
18652
19013
  }
19014
+ if (request.method === "tools/call") {
19015
+ assertMcpOperationObservationAuthority({
19016
+ serverId: config.id,
19017
+ ...request.toolName === void 0 ? {} : { toolName: request.toolName },
19018
+ destinationDigest: digestCanonicalJson(destinationUrl),
19019
+ ...first.operationAuthorityDigest === void 0 ? {} : { authorityDigest: first.operationAuthorityDigest }
19020
+ });
19021
+ if (hasActiveRecoverableMcpOperation() && (request.batch || request.id === void 0 || request.id === null || !request.operationId || !request.toolName)) {
19022
+ throw new Error("Recoverable MCP request is missing its exact dispatch identity");
19023
+ }
19024
+ await captureMcpOperationDispatch({
19025
+ operationId: request.operationId ?? "",
19026
+ serverId: config.id,
19027
+ toolName: request.toolName ?? "",
19028
+ destinationDigest: digestCanonicalJson(destinationUrl),
19029
+ authorityDigest: first.operationAuthorityDigest ?? ""
19030
+ });
19031
+ }
18653
19032
  const response = await baseFetch(
18654
19033
  fetchInputForAttempt(input),
18655
19034
  withConnectionHeaders(input, init, first.headers)
@@ -19635,10 +20014,12 @@ var AttemptDefinitionMcpServer = class {
19635
20014
  async callToolResult(toolName, args, meta, options) {
19636
20015
  if (this.closed) throw new Error("local model tool server is closed");
19637
20016
  const environment = await this.requiredAttemptToolEnvironment();
20017
+ const sourceCallId = modelMcpSourceCallId(toolName);
19638
20018
  return await this.resultCustomDataBridge.captureResult(
19639
20019
  args,
19640
20020
  async (cleanArgs) => environment.callModel({
19641
20021
  modelName: toolName,
20022
+ ...sourceCallId === void 0 ? {} : { sourceCallId },
19642
20023
  arguments: cleanArgs ?? {},
19643
20024
  subjectId: this.subjectId,
19644
20025
  ...meta === void 0 ? {} : { transportMeta: meta },
@@ -19888,8 +20269,10 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19888
20269
  }
19889
20270
  return await this.resultCustomDataBridge.captureResult(args, async (cleanArgs) => {
19890
20271
  if (this.attemptToolEnvironment) {
20272
+ const sourceCallId = modelMcpSourceCallId(toolName);
19891
20273
  return await this.attemptToolEnvironment.callModel({
19892
20274
  modelName: toolName,
20275
+ ...sourceCallId === void 0 ? {} : { sourceCallId },
19893
20276
  arguments: cleanArgs ?? {},
19894
20277
  subjectId: this.attemptToolSubjectId,
19895
20278
  ...meta === void 0 ? {} : { transportMeta: meta },
@@ -19909,6 +20292,9 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19909
20292
  if (!this.isAllowed(unprefixed)) {
19910
20293
  throw new Error(`MCP tool ${unprefixed} is not allowed for server ${this.registryId}`);
19911
20294
  }
20295
+ if (configuredMcpOperationRecovery(this, unprefixed) && !hasActiveRecoverableMcpOperation()) {
20296
+ throw new Error("MCP operation recovery requires its trusted attempt execution context");
20297
+ }
19912
20298
  const recordsPhysicalCall = !(this.inner instanceof _PrefixedMcpServer);
19913
20299
  const startedAt = recordsPhysicalCall ? performance.now() : 0;
19914
20300
  let metricRecorded = false;
@@ -19929,7 +20315,7 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19929
20315
  args: args ?? {},
19930
20316
  ...options?.signal ? { signal: options.signal } : {},
19931
20317
  refresh: this.refreshOwnedCommand,
19932
- call: async (callArgs) => AttemptToolResult2.parse(unwrapSdkMcpResultProjection(await physicalCall(callArgs)))
20318
+ call: async (callArgs) => AttemptToolResult3.parse(unwrapSdkMcpResultProjection(await physicalCall(callArgs)))
19933
20319
  }) : await physicalCall(args ?? {});
19934
20320
  const rawOutput = unwrapSdkMcpResultProjection(projectedOutput);
19935
20321
  const connectionId = operationId ? this.connectorAttachmentAuthority?.connectionIdForOperation(operationId) : void 0;
@@ -19954,7 +20340,7 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19954
20340
  });
19955
20341
  }
19956
20342
  });
19957
- const result = AttemptToolResult2.parse(output);
20343
+ const result = AttemptToolResult3.parse(output);
19958
20344
  boundedMcpToolResult(result);
19959
20345
  recordOutcome(result.isError === true ? "provider_declared_error" : "success");
19960
20346
  if (unprefixed === "wait_for_input" && result.isError !== true) {
@@ -19962,6 +20348,12 @@ var PrefixedMcpServer = class _PrefixedMcpServer {
19962
20348
  }
19963
20349
  return result;
19964
20350
  } catch (error) {
20351
+ if (hasActiveRecoverableMcpOperation()) {
20352
+ recordOutcome(
20353
+ isToolOutcomeUncertainMcpError(error) ? "outcome_uncertain" : isAuthNeededMcpError(error) ? "auth_needed" : mcpThrownToolCallOutcome(error, options?.signal)
20354
+ );
20355
+ throw error;
20356
+ }
19965
20357
  if (isToolOutcomeUncertainMcpError(error)) {
19966
20358
  recordOutcome("outcome_uncertain");
19967
20359
  return boundedMcpToolResult({
@@ -22845,6 +23237,13 @@ function sortJson(value) {
22845
23237
  }
22846
23238
 
22847
23239
  export {
23240
+ hasActiveRecoverableMcpOperation,
23241
+ McpOperationOutcomeUnknownError,
23242
+ runRecoverableMcpOperation,
23243
+ captureMcpOperationDispatch,
23244
+ runMcpOperationObservationWithAuthority,
23245
+ assertMcpOperationObservationAuthority,
23246
+ observeMcpOperation,
22848
23247
  formatSkillCatalog,
22849
23248
  OpenAIResponsesModel,
22850
23249
  OpenAIChatCompletionsModel,
@@ -23094,4 +23493,4 @@ export {
23094
23493
  runAzureCliLoginHook,
23095
23494
  renderSessionGoalContext2 as renderSessionGoalContext
23096
23495
  };
23097
- //# sourceMappingURL=chunk-GJC7H2FC.js.map
23496
+ //# sourceMappingURL=chunk-VUEWS4GI.js.map