@opengeni/runtime 4.3.0 → 4.4.0-canary.36927100590001

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 (117) hide show
  1. package/dist/agent-instructions/base-behavior.d.ts +8 -0
  2. package/dist/agent-instructions/compose.d.ts +59 -0
  3. package/dist/agent-instructions/identity.d.ts +21 -0
  4. package/dist/agent-instructions/index.d.ts +6 -0
  5. package/dist/agent-instructions/modules/admin.d.ts +3 -0
  6. package/dist/agent-instructions/modules/artifacts.d.ts +7 -0
  7. package/dist/agent-instructions/modules/attachments.d.ts +3 -0
  8. package/dist/agent-instructions/modules/environment.d.ts +11 -0
  9. package/dist/agent-instructions/modules/goals.d.ts +3 -0
  10. package/dist/agent-instructions/modules/knowledge.d.ts +6 -0
  11. package/dist/agent-instructions/modules/machines.d.ts +3 -0
  12. package/dist/agent-instructions/modules/renderer-markdown.d.ts +6 -0
  13. package/dist/agent-instructions/modules/repositories.d.ts +7 -0
  14. package/dist/agent-instructions/modules/sandbox.d.ts +3 -0
  15. package/dist/agent-instructions/modules/skills.d.ts +3 -0
  16. package/dist/agent-instructions/modules/subagents.d.ts +3 -0
  17. package/dist/agent-instructions/runtime-mechanics.d.ts +7 -0
  18. package/dist/agent-instructions/types.d.ts +55 -0
  19. package/dist/assets/codemode-client.json +1 -1
  20. package/dist/{chunk-JUFVYQCY.js → chunk-VDXKKMMD.js} +457 -165
  21. package/dist/chunk-VDXKKMMD.js.map +1 -0
  22. package/dist/{chunk-22M75RJF.js → chunk-ZY655LYR.js} +1636 -709
  23. package/dist/chunk-ZY655LYR.js.map +1 -0
  24. package/dist/claude-subscription-usage.d.ts +3 -1
  25. package/dist/first-party-client.d.ts +1 -0
  26. package/dist/index.d.ts +37 -28
  27. package/dist/index.js +28 -2
  28. package/dist/input-wait-yield.d.ts +4 -0
  29. package/dist/interaction-tools.d.ts +1 -0
  30. package/dist/lazy-tool-transport.d.ts +6 -2
  31. package/dist/mcp-run-credentials.d.ts +3 -2
  32. package/dist/mcp-transport-logger.d.ts +10 -0
  33. package/dist/model-context-inspector.d.ts +17 -1
  34. package/dist/model-preparation-diagnostics.d.ts +9 -0
  35. package/dist/model-provider-routing.d.ts +4 -0
  36. package/dist/model-provider.d.ts +1 -0
  37. package/dist/model-request-capture.d.ts +9 -0
  38. package/dist/replayable-json-body.d.ts +2 -1
  39. package/dist/responses-terminal-error.d.ts +17 -0
  40. package/dist/sandbox/codemode-authority.d.ts +1 -0
  41. package/dist/sandbox/index.d.ts +3 -3
  42. package/dist/sandbox/index.js +5 -1
  43. package/dist/sandbox/provider-command-session.d.ts +6 -0
  44. package/dist/sandbox/providers/modal-command-control.d.ts +7 -0
  45. package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
  46. package/dist/sandbox/providers/modal-command-session.d.ts +2 -1
  47. package/dist/sandbox/providers/modal-command-start-errors.d.ts +9 -0
  48. package/dist/sandbox/providers/modal.d.ts +3 -0
  49. package/dist/sandbox/routing/routing-session.d.ts +5 -4
  50. package/dist/workspace-tool-gateway.js +2 -2
  51. package/package.json +12 -12
  52. package/src/agent-instructions/PROMPT_CHANGELOG.md +149 -0
  53. package/src/agent-instructions/base-behavior.ts +120 -0
  54. package/src/agent-instructions/compose.ts +153 -0
  55. package/src/agent-instructions/identity.ts +42 -0
  56. package/src/agent-instructions/index.ts +24 -0
  57. package/src/agent-instructions/modules/admin.ts +25 -0
  58. package/src/agent-instructions/modules/artifacts.ts +39 -0
  59. package/src/agent-instructions/modules/attachments.ts +12 -0
  60. package/src/agent-instructions/modules/environment.ts +60 -0
  61. package/src/agent-instructions/modules/goals.ts +15 -0
  62. package/src/agent-instructions/modules/knowledge.ts +21 -0
  63. package/src/agent-instructions/modules/machines.ts +17 -0
  64. package/src/agent-instructions/modules/renderer-markdown.ts +17 -0
  65. package/src/agent-instructions/modules/repositories.ts +28 -0
  66. package/src/agent-instructions/modules/sandbox.ts +63 -0
  67. package/src/agent-instructions/modules/skills.ts +19 -0
  68. package/src/agent-instructions/modules/subagents.ts +42 -0
  69. package/src/agent-instructions/runtime-mechanics.ts +55 -0
  70. package/src/agent-instructions/types.ts +83 -0
  71. package/src/bundled_default_skills/opengeni-client/SKILL.md +116 -37
  72. package/src/bundled_default_skills/opengeni-client/references/agent-recipes.md +18 -8
  73. package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +24 -4
  74. package/src/bundled_default_skills/opengeni-client/references/chat-facade-fallback.md +23 -4
  75. package/src/bundled_default_skills/opengeni-client/references/compatibility-and-troubleshooting.md +34 -1
  76. package/src/bundled_default_skills/opengeni-client/references/configure-the-agent.md +248 -0
  77. package/src/bundled_default_skills/opengeni-client/references/customer-skill-template.md +2 -1
  78. package/src/bundled_default_skills/opengeni-client/references/data-tools-and-credentials.md +15 -4
  79. package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +2 -2
  80. package/src/bundled_default_skills/opengeni-client/references/isolation-and-authorization.md +5 -3
  81. package/src/bundled_default_skills/opengeni-client/references/product-integration-shapes.md +6 -5
  82. package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +36 -3
  83. package/src/bundled_default_skills/opengeni-client/references/proxy-from-any-backend.md +170 -0
  84. package/src/bundled_default_skills/opengeni-client/references/session-history-import.md +147 -0
  85. package/src/bundled_default_skills/opengeni-client/references/usage-allowances.md +189 -0
  86. package/src/bundled_default_skills/opengeni-help/SKILL.md +1 -1
  87. package/src/claude-subscription-usage.ts +23 -4
  88. package/src/first-party-client.ts +4 -0
  89. package/src/index.ts +260 -146
  90. package/src/input-wait-yield.ts +7 -0
  91. package/src/interaction-tools.ts +16 -2
  92. package/src/lazy-tool-transport.ts +46 -16
  93. package/src/mcp-run-credentials.ts +18 -3
  94. package/src/mcp-transport-logger.ts +46 -0
  95. package/src/model-context-inspector.ts +37 -3
  96. package/src/model-preparation-diagnostics.ts +48 -1
  97. package/src/model-provider-client.ts +5 -1
  98. package/src/model-provider-routing.ts +95 -1
  99. package/src/model-provider.ts +1 -0
  100. package/src/model-request-capture.ts +28 -1
  101. package/src/provider-history-adapter.ts +24 -3
  102. package/src/replayable-json-body.ts +19 -2
  103. package/src/responses-terminal-error.ts +136 -0
  104. package/src/sandbox/codemode-authority.ts +4 -0
  105. package/src/sandbox/codemode-client.ts +18 -16
  106. package/src/sandbox/index.ts +45 -9
  107. package/src/sandbox/provider-command-session.ts +12 -0
  108. package/src/sandbox/providers/modal-command-control.ts +118 -12
  109. package/src/sandbox/providers/modal-command-router-wire.ts +40 -4
  110. package/src/sandbox/providers/modal-command-session.ts +36 -1
  111. package/src/sandbox/providers/modal-command-start-errors.ts +27 -0
  112. package/src/sandbox/providers/modal-legacy-command-control.ts +60 -30
  113. package/src/sandbox/providers/modal.ts +43 -2
  114. package/src/sandbox/routing/routing-session.ts +61 -6
  115. package/src/sandbox/turn-tool-cancellation.ts +8 -1
  116. package/dist/chunk-22M75RJF.js.map +0 -1
  117. package/dist/chunk-JUFVYQCY.js.map +0 -1
@@ -8,11 +8,13 @@ import {
8
8
  createTurnToolCancellationController,
9
9
  installManagedCodemodeClient,
10
10
  isDefinitePathNotFoundError,
11
+ isModalCommandStartOutcomeUnknownError,
11
12
  isModalTaskExecStartPreDispatchUnavailableError,
12
13
  isRoutingMutationOutcomeUnknownError,
13
14
  loadManagedCodemodeClient,
14
15
  managedCodemodeClientDirectory,
15
16
  normalizeProtocolJsonValue,
17
+ renderRoutingMutationOutcomeUnknownToolResult,
16
18
  repairSerializedRunStateExposedPorts,
17
19
  restoredSandboxSessionStateFromEntry,
18
20
  runWithToolCallCorrelation,
@@ -27,7 +29,7 @@ import {
27
29
  withRunCredentialsClient,
28
30
  withRunCredentialsSession,
29
31
  wrapCapabilityToolsForTurnCancellation
30
- } from "./chunk-JUFVYQCY.js";
32
+ } from "./chunk-VDXKKMMD.js";
31
33
  import {
32
34
  MemorySession,
33
35
  connectMcpServers
@@ -121,6 +123,44 @@ import {
121
123
  // src/index.ts
122
124
  import { measureMcpPhase } from "@opengeni/observability";
123
125
 
126
+ // src/mcp-transport-logger.ts
127
+ var CLEANUP_MESSAGES = /* @__PURE__ */ new Set([
128
+ "Failed to terminate MCP session:",
129
+ "Failed to close MCP client:",
130
+ "Failed to close MCP transport:",
131
+ ...[
132
+ "failed MCP reconnect",
133
+ "stale MCP",
134
+ "discarded MCP",
135
+ "replaced MCP",
136
+ "reconnected MCP"
137
+ ].flatMap((name) => [`Failed to close ${name} client:`, `Failed to terminate ${name} session:`])
138
+ ]);
139
+ function createMcpTransportLogger(serverId, errorFields) {
140
+ const logFailure = (message, ...args) => {
141
+ const cleanup = CLEANUP_MESSAGES.has(message);
142
+ let error;
143
+ for (let index = args.length - 1; index >= 0; index--) {
144
+ if (args[index] instanceof Error) {
145
+ error = args[index];
146
+ break;
147
+ }
148
+ }
149
+ console.warn(
150
+ cleanup ? "[mcp] cleanup operation failed" : "[mcp] transport operation failed",
151
+ errorFields(error, cleanup ? "mcp_cleanup_failed" : "mcp_transport_failed", serverId)
152
+ );
153
+ };
154
+ return {
155
+ namespace: "opengeni:mcp-transport",
156
+ debug: () => void 0,
157
+ error: logFailure,
158
+ warn: logFailure,
159
+ dontLogModelData: true,
160
+ dontLogToolData: true
161
+ };
162
+ }
163
+
124
164
  // src/prepared-compaction-request.ts
125
165
  import { AsyncLocalStorage } from "async_hooks";
126
166
 
@@ -143,14 +183,14 @@ function toolCallIdFromSdkItem(item) {
143
183
  if (!item || typeof item !== "object" || Array.isArray(item)) {
144
184
  return void 0;
145
185
  }
146
- const record = item;
147
- if (typeof record.callId === "string" && record.callId.length > 0) {
148
- return record.callId;
186
+ const record2 = item;
187
+ if (typeof record2.callId === "string" && record2.callId.length > 0) {
188
+ return record2.callId;
149
189
  }
150
- if (typeof record.call_id === "string" && record.call_id.length > 0) {
151
- return record.call_id;
190
+ if (typeof record2.call_id === "string" && record2.call_id.length > 0) {
191
+ return record2.call_id;
152
192
  }
153
- const provider = record.providerData;
193
+ const provider = record2.providerData;
154
194
  if (provider && typeof provider === "object") {
155
195
  if (typeof provider.call_id === "string" && provider.call_id.length > 0) {
156
196
  return provider.call_id;
@@ -447,12 +487,12 @@ function projectRejectedProviderArtifactsFromSerializedRunState(serialized) {
447
487
  }
448
488
  function hasOpaqueProviderArtifact(item) {
449
489
  if (!item || typeof item !== "object") return false;
450
- const record = item;
451
- if (record.type !== "reasoning" && record.type !== "compaction") return false;
452
- if (typeof record.encrypted_content === "string" && record.encrypted_content.length > 0) {
490
+ const record2 = item;
491
+ if (record2.type !== "reasoning" && record2.type !== "compaction") return false;
492
+ if (typeof record2.encrypted_content === "string" && record2.encrypted_content.length > 0) {
453
493
  return true;
454
494
  }
455
- const providerData = record.providerData && typeof record.providerData === "object" ? record.providerData : null;
495
+ const providerData = record2.providerData && typeof record2.providerData === "object" ? record2.providerData : null;
456
496
  return Boolean(
457
497
  providerData && (typeof providerData.encrypted_content === "string" && providerData.encrypted_content.length > 0 || typeof providerData.encryptedContent === "string" && providerData.encryptedContent.length > 0)
458
498
  );
@@ -493,11 +533,11 @@ function normalizeComputerCallActions(items) {
493
533
  }
494
534
  function normalizeComputerCallAction(item) {
495
535
  if (itemType(item) !== "computer_call") return item;
496
- const record = item;
497
- const hasAction = record.action !== void 0 && record.action !== null;
498
- const hasActions = Array.isArray(record.actions) && record.actions.length > 0;
536
+ const record2 = item;
537
+ const hasAction = record2.action !== void 0 && record2.action !== null;
538
+ const hasActions = Array.isArray(record2.actions) && record2.actions.length > 0;
499
539
  if (!hasAction || !hasActions) return item;
500
- const { action: _droppedAction, ...rest } = record;
540
+ const { action: _droppedAction, ...rest } = record2;
501
541
  return rest;
502
542
  }
503
543
  function rewriteComputerCallsToActionsOnly(body) {
@@ -513,22 +553,22 @@ function rewriteComputerCallsToActionsOnly(body) {
513
553
  if (!item || typeof item !== "object") {
514
554
  continue;
515
555
  }
516
- const record = item;
517
- if (record.type !== "computer_call") {
556
+ const record2 = item;
557
+ if (record2.type !== "computer_call") {
518
558
  continue;
519
559
  }
520
- const existingActions = Array.isArray(record.actions) && record.actions.length > 0 ? record.actions : void 0;
521
- const actions = existingActions ?? (record.action !== void 0 && record.action !== null ? [record.action] : void 0);
560
+ const existingActions = Array.isArray(record2.actions) && record2.actions.length > 0 ? record2.actions : void 0;
561
+ const actions = existingActions ?? (record2.action !== void 0 && record2.action !== null ? [record2.action] : void 0);
522
562
  if (actions === void 0) {
523
563
  continue;
524
564
  }
525
- const hadAction = "action" in record;
565
+ const hadAction = "action" in record2;
526
566
  const actionsAlreadyExact = existingActions !== void 0 && !hadAction;
527
567
  if (actionsAlreadyExact) {
528
568
  continue;
529
569
  }
530
- delete record.action;
531
- record.actions = actions;
570
+ delete record2.action;
571
+ record2.actions = actions;
532
572
  changed = true;
533
573
  }
534
574
  return changed;
@@ -546,11 +586,11 @@ function rewriteEmptyComputerCallOutputImageUrls(body) {
546
586
  if (!item || typeof item !== "object") {
547
587
  continue;
548
588
  }
549
- const record = item;
550
- if (record.type !== "computer_call_output") {
589
+ const record2 = item;
590
+ if (record2.type !== "computer_call_output") {
551
591
  continue;
552
592
  }
553
- const output = record.output;
593
+ const output = record2.output;
554
594
  if (!output || typeof output !== "object") {
555
595
  continue;
556
596
  }
@@ -863,13 +903,13 @@ var MAX_NATIVE_IMAGE_TOKENS = 8192;
863
903
  function finitePositiveInteger(value) {
864
904
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : null;
865
905
  }
866
- function dimensionsFromRecord(record) {
867
- const width = finitePositiveInteger(record.width);
868
- const height = finitePositiveInteger(record.height);
906
+ function dimensionsFromRecord(record2) {
907
+ const width = finitePositiveInteger(record2.width);
908
+ const height = finitePositiveInteger(record2.height);
869
909
  if (width && height) return [width, height];
870
- if (Array.isArray(record.dimensions) && record.dimensions.length >= 2) {
871
- const dimensionsWidth = finitePositiveInteger(record.dimensions[0]);
872
- const dimensionsHeight = finitePositiveInteger(record.dimensions[1]);
910
+ if (Array.isArray(record2.dimensions) && record2.dimensions.length >= 2) {
911
+ const dimensionsWidth = finitePositiveInteger(record2.dimensions[0]);
912
+ const dimensionsHeight = finitePositiveInteger(record2.dimensions[1]);
873
913
  if (dimensionsWidth && dimensionsHeight) return [dimensionsWidth, dimensionsHeight];
874
914
  }
875
915
  return null;
@@ -959,11 +999,11 @@ function dimensionsFromImageSource(source) {
959
999
  return bytes ? dimensionsFromImageBytes(bytes) : null;
960
1000
  }
961
1001
  if (!source || typeof source !== "object") return null;
962
- const record = source;
963
- const rawData = record.data;
964
- const mediaType = record.mediaType ?? record.media_type;
1002
+ const record2 = source;
1003
+ const rawData = record2.data;
1004
+ const mediaType = record2.mediaType ?? record2.media_type;
965
1005
  const rawDataDimensions = rawData instanceof Uint8Array ? dimensionsFromImageBytes(rawData) : typeof rawData === "string" && typeof mediaType === "string" && mediaType.toLowerCase().startsWith("image/") ? dimensionsFromImageBytes(base64BytesPrefix(rawData) ?? new Uint8Array()) : null;
966
- return dimensionsFromRecord(record) ?? rawDataDimensions ?? dimensionsFromImageSource(record.url) ?? dimensionsFromImageSource(rawData);
1006
+ return dimensionsFromRecord(record2) ?? rawDataDimensions ?? dimensionsFromImageSource(record2.url) ?? dimensionsFromImageSource(rawData);
967
1007
  }
968
1008
  function highDetailImageTokens(width, height) {
969
1009
  let scaledWidth = width;
@@ -1013,19 +1053,19 @@ function estimateNativeImageTokens(input) {
1013
1053
  reason: "dimensions"
1014
1054
  };
1015
1055
  }
1016
- function imageDescriptor(record) {
1017
- const type = typeof record.type === "string" ? record.type : "";
1056
+ function imageDescriptor(record2) {
1057
+ const type = typeof record2.type === "string" ? record2.type : "";
1018
1058
  if (!(/* @__PURE__ */ new Set(["input_image", "image_url", "image", "computer_screenshot"])).has(type)) {
1019
1059
  return null;
1020
1060
  }
1021
- const imageUrl = record.image_url;
1061
+ const imageUrl = record2.image_url;
1022
1062
  const nestedImageUrl = imageUrl && typeof imageUrl === "object" ? imageUrl.url : imageUrl;
1023
- const source = record.image ?? record.imageUrl ?? nestedImageUrl ?? record.data ?? record.url ?? record.fileId ?? record.file_id ?? record.artifact ?? record.artifactReference;
1063
+ const source = record2.image ?? record2.imageUrl ?? nestedImageUrl ?? record2.data ?? record2.url ?? record2.fileId ?? record2.file_id ?? record2.artifact ?? record2.artifactReference;
1024
1064
  const nestedDetail = imageUrl && typeof imageUrl === "object" ? imageUrl.detail : void 0;
1025
- const dimensions = dimensionsFromRecord(record) ?? (source && typeof source === "object" ? dimensionsFromRecord(source) : null);
1065
+ const dimensions = dimensionsFromRecord(record2) ?? (source && typeof source === "object" ? dimensionsFromRecord(source) : null);
1026
1066
  return {
1027
1067
  source,
1028
- detail: typeof record.detail === "string" ? record.detail : typeof nestedDetail === "string" ? nestedDetail : "auto",
1068
+ detail: typeof record2.detail === "string" ? record2.detail : typeof nestedDetail === "string" ? nestedDetail : "auto",
1029
1069
  width: dimensions?.[0] ?? null,
1030
1070
  height: dimensions?.[1] ?? null
1031
1071
  };
@@ -1052,8 +1092,8 @@ function projectNativeImages(value, seen) {
1052
1092
  seen.delete(value);
1053
1093
  return { value: projected2, imageTokens: imageTokens2, imageCount: imageCount2, imageFallbackCount: imageFallbackCount2 };
1054
1094
  }
1055
- const record = value;
1056
- const descriptor = imageDescriptor(record);
1095
+ const record2 = value;
1096
+ const descriptor = imageDescriptor(record2);
1057
1097
  if (descriptor) {
1058
1098
  const estimate = estimateNativeImageTokens(descriptor);
1059
1099
  const projected2 = {};
@@ -1068,7 +1108,7 @@ function projectNativeImages(value, seen) {
1068
1108
  "artifact",
1069
1109
  "artifactReference"
1070
1110
  ]);
1071
- for (const [key, entry] of Object.entries(record)) {
1111
+ for (const [key, entry] of Object.entries(record2)) {
1072
1112
  projected2[key] = payloadKeys.has(key) ? "[native image]" : entry;
1073
1113
  }
1074
1114
  projected2.image_estimate = {
@@ -1089,7 +1129,7 @@ function projectNativeImages(value, seen) {
1089
1129
  let imageCount = 0;
1090
1130
  let imageFallbackCount = 0;
1091
1131
  const projected = {};
1092
- for (const [key, entry] of Object.entries(record)) {
1132
+ for (const [key, entry] of Object.entries(record2)) {
1093
1133
  const result = projectNativeImages(entry, seen);
1094
1134
  projected[key] = result.value;
1095
1135
  imageTokens += result.imageTokens;
@@ -1109,13 +1149,13 @@ function estimateOpaqueEncryptedTokens(encodedLen) {
1109
1149
  }
1110
1150
  function opaqueEncryptedContentLength(item) {
1111
1151
  if (!item || typeof item !== "object") return null;
1112
- const record = item;
1113
- const type = typeof record.type === "string" ? record.type : "";
1114
- if ((type === "compaction" || type === "context_compaction" || type === "reasoning") && typeof record.encrypted_content === "string" && record.encrypted_content.length > 0) {
1115
- return record.encrypted_content.length;
1152
+ const record2 = item;
1153
+ const type = typeof record2.type === "string" ? record2.type : "";
1154
+ if ((type === "compaction" || type === "context_compaction" || type === "reasoning") && typeof record2.encrypted_content === "string" && record2.encrypted_content.length > 0) {
1155
+ return record2.encrypted_content.length;
1116
1156
  }
1117
1157
  if (type === "reasoning") {
1118
- const providerData = record.providerData && typeof record.providerData === "object" ? record.providerData : null;
1158
+ const providerData = record2.providerData && typeof record2.providerData === "object" ? record2.providerData : null;
1119
1159
  const nested = providerData && typeof providerData.encrypted_content === "string" ? providerData.encrypted_content : providerData && typeof providerData.encryptedContent === "string" ? providerData.encryptedContent : null;
1120
1160
  if (nested && nested.length > 0) return nested.length;
1121
1161
  }
@@ -1400,8 +1440,8 @@ function findCompactionNeededError(error, seen = /* @__PURE__ */ new WeakSet())
1400
1440
  return null;
1401
1441
  }
1402
1442
  seen.add(error);
1403
- const record = error;
1404
- return findCompactionNeededError(record.cause, seen) ?? findCompactionNeededError(record.error, seen);
1443
+ const record2 = error;
1444
+ return findCompactionNeededError(record2.cause, seen) ?? findCompactionNeededError(record2.error, seen);
1405
1445
  }
1406
1446
  function buildCompactionPromptInput(items) {
1407
1447
  return [
@@ -1473,9 +1513,9 @@ function remoteCompactionShellOutputIsMinimal(output) {
1473
1513
  if (!Array.isArray(output) || output.length !== 1) return false;
1474
1514
  const result = output[0];
1475
1515
  if (!result || typeof result !== "object" || Array.isArray(result)) return false;
1476
- const record = result;
1477
- const outcome = record.outcome;
1478
- return record.stdout === "" && record.stderr === REMOTE_COMPACTION_TOOL_RESULT_OMISSION && outcome !== null && typeof outcome === "object" && !Array.isArray(outcome) && outcome.type === "exit" && outcome.exitCode === null && Object.keys(record).length === 3 && Object.keys(outcome).length === 2;
1516
+ const record2 = result;
1517
+ const outcome = record2.outcome;
1518
+ return record2.stdout === "" && record2.stderr === REMOTE_COMPACTION_TOOL_RESULT_OMISSION && outcome !== null && typeof outcome === "object" && !Array.isArray(outcome) && outcome.type === "exit" && outcome.exitCode === null && Object.keys(record2).length === 3 && Object.keys(outcome).length === 2;
1479
1519
  }
1480
1520
  function omitOpaqueArtifactsFromPortableCompactionHistory(items) {
1481
1521
  let changed = false;
@@ -1596,8 +1636,8 @@ function buildCompactionReplacementHistory(items, summaryBody, retainedItemToken
1596
1636
  }
1597
1637
  function isRemoteCompactionItem(item) {
1598
1638
  if (!item || typeof item !== "object") return false;
1599
- const record = item;
1600
- return record.type === "compaction" && typeof record.encrypted_content === "string" && record.encrypted_content.length > 0;
1639
+ const record2 = item;
1640
+ return record2.type === "compaction" && typeof record2.encrypted_content === "string" && record2.encrypted_content.length > 0;
1601
1641
  }
1602
1642
  function isRetainedRemoteV2Message(item) {
1603
1643
  if (isCompactionSummary(item) || isAttachmentCatalog(item) || itemType2(item) === "compaction") {
@@ -1689,8 +1729,8 @@ function extractRemoteCompactionV2OutputItem(response) {
1689
1729
  if (!response || typeof response !== "object") {
1690
1730
  throw new EmptyCompactionSummaryError({ stage: "remote_v2_extract", reason: "no_response" });
1691
1731
  }
1692
- const record = response;
1693
- const output = Array.isArray(record.output) ? record.output : [];
1732
+ const record2 = response;
1733
+ const output = Array.isArray(record2.output) ? record2.output : [];
1694
1734
  const compactionItems = output.filter(isRemoteCompactionItem);
1695
1735
  if (compactionItems.length !== 1) {
1696
1736
  throw new EmptyCompactionSummaryError({
@@ -1830,12 +1870,12 @@ function messageText(item) {
1830
1870
  if (Array.isArray(content)) {
1831
1871
  return content.map((part) => {
1832
1872
  if (part && typeof part === "object") {
1833
- const record = part;
1834
- if (typeof record.text === "string") {
1835
- return record.text;
1873
+ const record2 = part;
1874
+ if (typeof record2.text === "string") {
1875
+ return record2.text;
1836
1876
  }
1837
- if (typeof record.content === "string") {
1838
- return record.content;
1877
+ if (typeof record2.content === "string") {
1878
+ return record2.content;
1839
1879
  }
1840
1880
  }
1841
1881
  return "";
@@ -3906,10 +3946,10 @@ function getProviderDataField(providerData, keys) {
3906
3946
  if (!providerData || typeof providerData !== "object" || Array.isArray(providerData)) {
3907
3947
  return void 0;
3908
3948
  }
3909
- const record = providerData;
3949
+ const record2 = providerData;
3910
3950
  for (const key of keys) {
3911
- if (typeof record[key] !== "undefined") {
3912
- return record[key];
3951
+ if (typeof record2[key] !== "undefined") {
3952
+ return record2[key];
3913
3953
  }
3914
3954
  }
3915
3955
  return void 0;
@@ -7543,11 +7583,11 @@ function stripConversationPersistenceMetadata(items) {
7543
7583
  if (Array.isArray(item) || item === null || typeof item !== "object") {
7544
7584
  return [item];
7545
7585
  }
7546
- const record = item;
7547
- if (isUnpersistableReasoningItem(record)) {
7586
+ const record2 = item;
7587
+ if (isUnpersistableReasoningItem(record2)) {
7548
7588
  return [];
7549
7589
  }
7550
- const { providerData: _providerData, provider_data: _provider_data, ...rest } = record;
7590
+ const { providerData: _providerData, provider_data: _provider_data, ...rest } = record2;
7551
7591
  if (rest.type !== "reasoning") {
7552
7592
  delete rest.id;
7553
7593
  }
@@ -7561,11 +7601,11 @@ function stripAssistantReplayMetadata(item) {
7561
7601
  if (Array.isArray(item) || item === null || typeof item !== "object") {
7562
7602
  return item;
7563
7603
  }
7564
- const record = item;
7565
- if (record.type !== "message" || record.role !== "assistant") {
7604
+ const record2 = item;
7605
+ if (record2.type !== "message" || record2.role !== "assistant") {
7566
7606
  return item;
7567
7607
  }
7568
- const { id: _id, providerData, provider_data: _provider_data, ...rest } = record;
7608
+ const { id: _id, providerData, provider_data: _provider_data, ...rest } = record2;
7569
7609
  if (typeof rest.phase === "undefined" && providerData && typeof providerData === "object" && !Array.isArray(providerData) && typeof providerData.phase !== "undefined") {
7570
7610
  rest.phase = providerData.phase;
7571
7611
  }
@@ -8646,8 +8686,8 @@ function imageSource(value) {
8646
8686
  }
8647
8687
  function contentBlocks(value) {
8648
8688
  if (typeof value === "string") return value ? [{ type: "text", text: value }] : [];
8649
- const blocks = Array.isArray(value) ? value : [value];
8650
- return blocks.map((entry) => {
8689
+ const blocks2 = Array.isArray(value) ? value : [value];
8690
+ return blocks2.map((entry) => {
8651
8691
  const block = object(entry);
8652
8692
  if (["text", "input_text", "output_text", "refusal"].includes(block.type)) {
8653
8693
  return { type: "text", text: text(block.text ?? block.refusal, "text") };
@@ -9010,7 +9050,7 @@ var AnthropicMessagesModel = class {
9010
9050
  async *getStreamedResponse(request) {
9011
9051
  const response = await this.send(request, true);
9012
9052
  if (!response.body) throw new AnthropicProtocolError("Claude returned an empty stream");
9013
- const blocks = /* @__PURE__ */ new Map();
9053
+ const blocks2 = /* @__PURE__ */ new Map();
9014
9054
  let message;
9015
9055
  let finalDelta = false;
9016
9056
  for await (const event of anthropicSse(
@@ -9045,12 +9085,12 @@ var AnthropicMessagesModel = class {
9045
9085
  yield { type: "response_started" };
9046
9086
  break;
9047
9087
  case "content_block_start":
9048
- if (!message || blocks.has(event.index) || finalDelta)
9088
+ if (!message || blocks2.has(event.index) || finalDelta)
9049
9089
  throw new AnthropicProtocolError("Invalid Claude block start");
9050
- blocks.set(event.index, { block: object(event.content_block), json: "", stopped: false });
9090
+ blocks2.set(event.index, { block: object(event.content_block), json: "", stopped: false });
9051
9091
  break;
9052
9092
  case "content_block_delta": {
9053
- const state = blocks.get(event.index);
9093
+ const state = blocks2.get(event.index);
9054
9094
  if (!state || state.stopped)
9055
9095
  throw new AnthropicProtocolError("Claude delta has no open block");
9056
9096
  const delta = object(event.delta);
@@ -9083,7 +9123,7 @@ var AnthropicMessagesModel = class {
9083
9123
  break;
9084
9124
  }
9085
9125
  case "content_block_stop": {
9086
- const state = blocks.get(event.index);
9126
+ const state = blocks2.get(event.index);
9087
9127
  if (!state || state.stopped)
9088
9128
  throw new AnthropicProtocolError("Invalid Claude block stop");
9089
9129
  if (state.block.type === "tool_use" && state.json)
@@ -9098,9 +9138,9 @@ var AnthropicMessagesModel = class {
9098
9138
  finalDelta = true;
9099
9139
  break;
9100
9140
  case "message_stop": {
9101
- if (!message || !finalDelta || [...blocks.values()].some((state) => !state.stopped))
9141
+ if (!message || !finalDelta || [...blocks2.values()].some((state) => !state.stopped))
9102
9142
  throw new AnthropicProtocolError("Claude response ended before its blocks completed");
9103
- message.content = [...blocks.entries()].sort(([a], [b]) => a - b).map(([, state]) => state.block);
9143
+ message.content = [...blocks2.entries()].sort(([a], [b]) => a - b).map(([, state]) => state.block);
9104
9144
  const result = anthropicResponse(
9105
9145
  message,
9106
9146
  response.headers.get("request-id") ?? void 0,
@@ -9340,10 +9380,10 @@ function azureModelRequestPolicy({
9340
9380
  if (!containsComputerProtocol) return void 0;
9341
9381
  const projectedInput = input.map((item) => {
9342
9382
  if (!item || typeof item !== "object" || Array.isArray(item)) return item;
9343
- const record = item;
9344
- if (record.type === "computer_call") return { ...record };
9345
- if (record.type === "computer_call_output" && record.output && typeof record.output === "object" && !Array.isArray(record.output)) {
9346
- return { ...record, output: { ...record.output } };
9383
+ const record2 = item;
9384
+ if (record2.type === "computer_call") return { ...record2 };
9385
+ if (record2.type === "computer_call_output" && record2.output && typeof record2.output === "object" && !Array.isArray(record2.output)) {
9386
+ return { ...record2, output: { ...record2.output } };
9347
9387
  }
9348
9388
  return item;
9349
9389
  });
@@ -9474,273 +9514,161 @@ function isModelCallFetch(input) {
9474
9514
  // src/replayable-json-body.ts
9475
9515
  import OpenAI6 from "openai";
9476
9516
  import { types as utilTypes } from "util";
9477
- var TARGET_CHUNK_CHARS = 64 * 1024;
9478
- var LARGE_STRING_SOURCE_CHARS = 32 * 1024;
9479
- var STRING_SLICE_CODE_UNITS = 10 * 1024;
9480
- var REPLAYABLE_REQUEST_BODY_FACTORY = Symbol.for(
9481
- "opengeni.replayable-request-body-factory"
9482
- );
9483
- var ReplayableJsonBody = class {
9484
- source;
9485
- constructor(source) {
9486
- this.source = source;
9487
- }
9488
- async *[Symbol.asyncIterator]() {
9489
- const encoder = new TextEncoder();
9490
- for (const chunk of jsonTextChunks(this.source)) {
9491
- yield encoder.encode(chunk);
9492
- }
9517
+
9518
+ // src/model-preparation-diagnostics.ts
9519
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
9520
+
9521
+ // src/model-request-capture.ts
9522
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
9523
+ var modelRequestCapture = new AsyncLocalStorage2();
9524
+ var captureIndices = /* @__PURE__ */ new WeakMap();
9525
+ var modelCallLifecycle = new AsyncLocalStorage2();
9526
+ function withModelCallLifecycle(lifecycle, fn) {
9527
+ return modelCallLifecycle.run(lifecycle, fn);
9528
+ }
9529
+ async function beforeModelRequest() {
9530
+ await modelCallLifecycle.getStore()?.beforeModelRequest?.();
9531
+ }
9532
+ function modelResponseSettlement(event) {
9533
+ if (event.type !== "response_done") return void 0;
9534
+ return modelCallLifecycle.getStore()?.onModelResponse?.(event);
9535
+ }
9536
+ function nextModelContextCaptureIndex(agent) {
9537
+ const index = (captureIndices.get(agent) ?? 0) + 1;
9538
+ captureIndices.set(agent, index);
9539
+ return index;
9540
+ }
9541
+ function withModelRequestCapture(capture, fn) {
9542
+ return capture ? modelRequestCapture.run(capture, fn) : fn();
9543
+ }
9544
+ function captureProviderRequestBody(provider, input, init) {
9545
+ const context = modelRequestCapture.getStore();
9546
+ const callback = context?.onProviderRequest;
9547
+ if (!callback) return { init, captured: Promise.resolve(), cancel: () => {
9548
+ } };
9549
+ const index = context.nextProviderRequestIndex?.();
9550
+ const observer = (providerId, body2, reason) => callback(providerId, body2, reason, index);
9551
+ let cancel = () => {
9552
+ };
9553
+ let body = init?.body;
9554
+ let nextInit = init;
9555
+ if (body instanceof ReadableStream) {
9556
+ const [sent, inspected] = body.tee();
9557
+ nextInit = { ...init, body: sent };
9558
+ body = inspected;
9559
+ } else if (body == null && input instanceof Request) {
9560
+ body = input.clone().body;
9493
9561
  }
9494
- createStream() {
9495
- const iterator = this[Symbol.asyncIterator]();
9496
- return new ReadableStream({
9497
- async pull(controller) {
9498
- try {
9499
- const next = await iterator.next();
9500
- if (next.done) controller.close();
9501
- else controller.enqueue(next.value);
9502
- } catch (error) {
9503
- controller.error(error);
9504
- }
9505
- },
9506
- async cancel(reason) {
9507
- await iterator.return?.(reason).catch(() => void 0);
9562
+ const captured = (async () => {
9563
+ const limit = 4 * 1024 * 1024;
9564
+ let text2;
9565
+ if (typeof body === "string") {
9566
+ if (Buffer.byteLength(body, "utf8") > limit) {
9567
+ await observer(provider, null, "Request exceeds the 4 MiB capture limit.");
9568
+ return;
9508
9569
  }
9509
- });
9510
- }
9511
- };
9512
- var ReplayableJsonOpenAI = class extends OpenAI6 {
9513
- modelRequestPolicy;
9514
- constructor(options, hooks = {}) {
9515
- super(options);
9516
- this.modelRequestPolicy = hooks.modelRequestPolicy;
9517
- }
9518
- post(path, opts) {
9519
- if (!isModelRequestPath(path) || opts === void 0) {
9520
- return super.post(path, opts);
9521
- }
9522
- const wrapped = Promise.resolve(opts).then((resolved) => {
9523
- const body = resolved.body;
9524
- let prepared = resolved;
9525
- if (this.modelRequestPolicy && isJsonRecordBody(body)) {
9526
- const policy = this.modelRequestPolicy({ path, body });
9527
- if (policy?.body || policy?.headers) {
9528
- prepared = {
9529
- ...resolved,
9530
- ...policy.body ? { body: policy.body } : {},
9531
- ...policy.headers ? { headers: mergePolicyHeaders(resolved.headers, policy.headers) } : {}
9532
- };
9570
+ text2 = body;
9571
+ } else if (body instanceof ReadableStream) {
9572
+ const reader = body.getReader();
9573
+ let cancelled = false;
9574
+ cancel = () => {
9575
+ cancelled = true;
9576
+ void reader.cancel().catch(() => void 0);
9577
+ };
9578
+ const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
9579
+ signal?.addEventListener("abort", cancel, { once: true });
9580
+ if (signal?.aborted) cancel();
9581
+ const decoder = new TextDecoder("utf-8", { fatal: true });
9582
+ const chunks = [];
9583
+ let bytes = 0;
9584
+ try {
9585
+ while (true) {
9586
+ const chunk = await reader.read();
9587
+ if (chunk.done) break;
9588
+ bytes += chunk.value.byteLength;
9589
+ if (bytes > limit) {
9590
+ void reader.cancel().catch(() => void 0);
9591
+ await observer(provider, null, "Request exceeds the 4 MiB capture limit.");
9592
+ return;
9593
+ }
9594
+ chunks.push(decoder.decode(chunk.value, { stream: true }));
9533
9595
  }
9596
+ if (cancelled) return;
9597
+ chunks.push(decoder.decode());
9598
+ text2 = chunks.join("");
9599
+ } catch {
9600
+ void reader.cancel().catch(() => void 0);
9601
+ if (!cancelled)
9602
+ await observer(provider, null, "The provider body could not be read as UTF-8.");
9603
+ return;
9604
+ } finally {
9605
+ signal?.removeEventListener("abort", cancel);
9606
+ reader.releaseLock();
9607
+ cancel = () => {
9608
+ };
9534
9609
  }
9535
- return wrapJsonRequestOptions(prepared);
9536
- });
9537
- return super.post(path, wrapped);
9538
- }
9539
- async buildRequest(inputOptions, context) {
9540
- const replayable = inputOptions.body instanceof ReplayableJsonBody ? inputOptions.body : void 0;
9541
- const priorStreamingMarker = inputOptions.__metadata?.hasStreamingBody;
9542
- const built = await super.buildRequest(inputOptions, context);
9543
- if (!replayable) return built;
9544
- if (priorStreamingMarker === void 0) {
9545
- if (inputOptions.__metadata) delete inputOptions.__metadata.hasStreamingBody;
9546
9610
  } else {
9547
- inputOptions.__metadata = {
9548
- ...inputOptions.__metadata,
9549
- hasStreamingBody: priorStreamingMarker
9550
- };
9611
+ await observer(provider, null, "This transport body cannot be inspected.");
9612
+ return;
9551
9613
  }
9552
- const request = built.req;
9553
- request[REPLAYABLE_REQUEST_BODY_FACTORY] = () => replayable.createStream();
9554
- return built;
9614
+ await observer(provider, text2);
9615
+ })().catch(() => void 0);
9616
+ return { init: nextInit, captured, cancel: () => cancel() };
9617
+ }
9618
+ async function notifyModelRequestCapture(request) {
9619
+ const capture = modelRequestCapture.getStore();
9620
+ if (!capture) return;
9621
+ try {
9622
+ await capture(snapshotModelRequestPrefix(request));
9623
+ } catch {
9555
9624
  }
9556
- };
9557
- function isModelRequestPath(path) {
9558
- const pathname = path.split("?", 1)[0] ?? path;
9559
- return pathname.endsWith("/responses") || pathname.endsWith("/chat/completions");
9560
9625
  }
9561
- function wrapJsonRequestOptions(options) {
9562
- const body = options.body;
9563
- if (!isJsonObjectBody(body) || body instanceof ReplayableJsonBody) return options;
9626
+ function snapshotModelRequestPrefix(request) {
9564
9627
  return {
9565
- ...options,
9566
- body: new ReplayableJsonBody(body),
9567
- headers: mergePolicyHeaders(options.headers, { "content-type": "application/json" })
9628
+ ...request,
9629
+ tools: structuredClone(request.tools)
9568
9630
  };
9569
9631
  }
9570
- function isJsonObjectBody(value) {
9571
- if (!value || typeof value !== "object") return false;
9572
- if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) return false;
9573
- if (value instanceof Blob || value instanceof FormData || value instanceof URLSearchParams) {
9574
- return false;
9632
+ var ModelRequestCaptureModel = class {
9633
+ constructor(inner) {
9634
+ this.inner = inner;
9575
9635
  }
9576
- if (value instanceof ReadableStream) return false;
9577
- return !(Symbol.asyncIterator in value) && !(Symbol.iterator in value);
9578
- }
9579
- function isJsonRecordBody(value) {
9580
- return isJsonObjectBody(value) && !Array.isArray(value);
9581
- }
9582
- function mergePolicyHeaders(headers, additions) {
9583
- const replacedNames = new Set(Object.keys(additions).map((name) => name.toLowerCase()));
9584
- if (headers instanceof Headers) {
9585
- const merged2 = new Headers(headers);
9586
- for (const [name, value] of Object.entries(additions)) merged2.set(name, value);
9587
- return merged2;
9636
+ async getResponse(request) {
9637
+ await beforeModelRequest();
9638
+ rememberPreparedModelRequest(request);
9639
+ void notifyModelRequestCapture(request);
9640
+ return this.inner.getResponse(request);
9588
9641
  }
9589
- if (headers && typeof headers === "object" && "values" in headers && "nulls" in headers && headers.values instanceof Headers && headers.nulls instanceof Set) {
9590
- const resolved = headers;
9591
- const rows = [
9592
- ...resolved.values.entries(),
9593
- ...[...resolved.nulls].map((name) => [name, null])
9594
- ];
9595
- return mergePolicyHeaders(rows, additions);
9642
+ async *getStreamedResponse(request) {
9643
+ await beforeModelRequest();
9644
+ rememberPreparedModelRequest(request);
9645
+ void notifyModelRequestCapture(request);
9646
+ for await (const event of this.inner.getStreamedResponse(request)) {
9647
+ const settlement = modelResponseSettlement(event);
9648
+ void settlement?.catch(() => void 0);
9649
+ yield event;
9650
+ }
9596
9651
  }
9597
- if (Array.isArray(headers)) {
9598
- return [
9599
- ...headers.filter(
9600
- (row) => !Array.isArray(row) || typeof row[0] !== "string" || !replacedNames.has(row[0].toLowerCase())
9601
- ),
9602
- ...Object.entries(additions)
9603
- ];
9652
+ getRetryAdvice(args) {
9653
+ return this.inner.getRetryAdvice?.(args);
9604
9654
  }
9605
- const merged = { ...headers ?? {} };
9606
- for (const name of Object.keys(merged)) {
9607
- if (replacedNames.has(name.toLowerCase())) delete merged[name];
9655
+ };
9656
+ var ModelRequestCaptureProvider = class {
9657
+ constructor(inner) {
9658
+ this.inner = inner;
9608
9659
  }
9609
- return { ...merged, ...additions };
9610
- }
9611
- function* jsonTextChunks(value) {
9612
- const fragments = jsonValueFragments(value, "", /* @__PURE__ */ new Set(), 0);
9613
- if (!fragments) throw new TypeError("Model request body is not JSON serializable");
9614
- let buffered = "";
9615
- for (const fragment of fragments) {
9616
- if (buffered.length > 0 && buffered.length + fragment.length > TARGET_CHUNK_CHARS) {
9617
- yield buffered;
9618
- buffered = "";
9619
- }
9620
- if (fragment.length >= TARGET_CHUNK_CHARS) yield fragment;
9621
- else buffered += fragment;
9622
- }
9623
- if (buffered.length > 0) yield buffered;
9624
- }
9625
- function jsonValueFragments(source, key, ancestors, depth) {
9626
- if (typeof source === "string" && source.length > LARGE_STRING_SOURCE_CHARS) {
9627
- return jsonStringFragments(source);
9628
- }
9629
- if (depth >= 2 || depth > 0 && !Array.isArray(source)) {
9630
- return nativeJsonPropertyFragments(source, key);
9631
- }
9632
- const value = prepareJsonValue(source, key);
9633
- if (value === void 0 || typeof value === "function" || typeof value === "symbol") {
9634
- return null;
9635
- }
9636
- if (typeof value === "bigint") {
9637
- throw new TypeError("Do not know how to serialize a BigInt");
9638
- }
9639
- if (typeof value === "string") {
9640
- return jsonStringFragments(value);
9641
- }
9642
- if (value === null || typeof value !== "object") {
9643
- return [JSON.stringify(value)];
9644
- }
9645
- const rawJson = JSON;
9646
- if (rawJson.isRawJSON?.(value)) return [JSON.stringify(value)];
9647
- if (ancestors.has(value)) throw new TypeError("cyclic object value");
9648
- return Array.isArray(value) ? jsonArrayFragments(value, ancestors, depth) : jsonObjectFragments(value, ancestors, depth);
9649
- }
9650
- function* jsonArrayFragments(value, ancestors, depth) {
9651
- ancestors.add(value);
9652
- try {
9653
- const length = value.length;
9654
- yield "[";
9655
- for (let index = 0; index < length; index += 1) {
9656
- if (index > 0) yield ",";
9657
- const child = jsonValueFragments(value[index], String(index), ancestors, depth + 1);
9658
- if (child) yield* child;
9659
- else yield "null";
9660
- }
9661
- yield "]";
9662
- } finally {
9663
- ancestors.delete(value);
9664
- }
9665
- }
9666
- function* jsonObjectFragments(value, ancestors, depth) {
9667
- ancestors.add(value);
9668
- try {
9669
- const keys = Object.keys(value);
9670
- let emitted = false;
9671
- yield "{";
9672
- for (const key of keys) {
9673
- const child = jsonValueFragments(value[key], key, ancestors, depth + 1);
9674
- if (!child) continue;
9675
- if (emitted) yield ",";
9676
- emitted = true;
9677
- yield* jsonStringFragments(key);
9678
- yield ":";
9679
- yield* child;
9680
- }
9681
- yield "}";
9682
- } finally {
9683
- ancestors.delete(value);
9684
- }
9685
- }
9686
- function nativeJsonPropertyFragments(source, key) {
9687
- const holder = /* @__PURE__ */ Object.create(null);
9688
- holder[key] = source;
9689
- const serialized = JSON.stringify(holder);
9690
- if (serialized === "{}") return null;
9691
- const prefix = `{${JSON.stringify(key)}:`;
9692
- if (!serialized.startsWith(prefix) || !serialized.endsWith("}")) {
9693
- throw new TypeError("Model request body is not JSON serializable");
9694
- }
9695
- return boundedNativeJsonFragments(serialized.slice(prefix.length, -1));
9696
- }
9697
- function* boundedNativeJsonFragments(serialized) {
9698
- for (let start = 0; start < serialized.length; ) {
9699
- let end = Math.min(serialized.length, start + TARGET_CHUNK_CHARS);
9700
- if (end < serialized.length && serialized.charCodeAt(end - 1) >= 55296 && serialized.charCodeAt(end - 1) <= 56319 && serialized.charCodeAt(end) >= 56320 && serialized.charCodeAt(end) <= 57343) {
9701
- end -= 1;
9702
- }
9703
- yield serialized.slice(start, end);
9704
- start = end;
9705
- }
9706
- }
9707
- function prepareJsonValue(source, key) {
9708
- let value = source;
9709
- const sourceType = typeof value;
9710
- if (value !== null && (sourceType === "object" || sourceType === "function" || sourceType === "bigint")) {
9711
- const toJSON = value.toJSON;
9712
- if (typeof toJSON === "function") value = toJSON.call(value, key);
9713
- }
9714
- if (value !== null && typeof value === "object") {
9715
- if (utilTypes.isNumberObject(value)) return Number.prototype.valueOf.call(value);
9716
- if (utilTypes.isStringObject(value)) return String.prototype.valueOf.call(value);
9717
- if (utilTypes.isBooleanObject(value)) return Boolean.prototype.valueOf.call(value);
9718
- if (utilTypes.isBigIntObject(value)) return BigInt.prototype.valueOf.call(value);
9719
- }
9720
- return value;
9721
- }
9722
- function* jsonStringFragments(value) {
9723
- if (value.length <= LARGE_STRING_SOURCE_CHARS) {
9724
- yield JSON.stringify(value);
9725
- return;
9726
- }
9727
- yield '"';
9728
- for (let start = 0; start < value.length; ) {
9729
- let end = Math.min(value.length, start + STRING_SLICE_CODE_UNITS);
9730
- if (end < value.length && value.charCodeAt(end - 1) >= 55296 && value.charCodeAt(end - 1) <= 56319 && value.charCodeAt(end) >= 56320 && value.charCodeAt(end) <= 57343) {
9731
- end -= 1;
9732
- }
9733
- const encoded = JSON.stringify(value.slice(start, end));
9734
- yield encoded.slice(1, -1);
9735
- start = end;
9660
+ async getModel(modelName) {
9661
+ const model = await this.inner.getModel(modelName);
9662
+ if (model instanceof ModelRequestCaptureModel) return model;
9663
+ return new ModelRequestCaptureModel(model);
9736
9664
  }
9737
- yield '"';
9738
- }
9665
+ };
9739
9666
 
9740
9667
  // src/model-preparation-diagnostics.ts
9741
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
9742
- var modelPreparationObserver = new AsyncLocalStorage2();
9743
- var modelTransportStartedObserver = new AsyncLocalStorage2();
9668
+ var modelPreparationObserver = new AsyncLocalStorage3();
9669
+ var modelTransportStartedObserver = new AsyncLocalStorage3();
9670
+ var modelTransportAdmission = new AsyncLocalStorage3();
9671
+ var modelTransportRefusals = /* @__PURE__ */ new WeakMap();
9744
9672
  var ModelPreparationTraceProcessor = class {
9745
9673
  async onTraceStart(_trace) {
9746
9674
  }
@@ -9781,7 +9709,38 @@ function withModelTransportStartedObserver(observer, callback) {
9781
9709
  return observer ? modelTransportStartedObserver.run(observer, callback) : callback();
9782
9710
  }
9783
9711
  async function recordModelTransportStarted() {
9784
- await modelTransportStartedObserver.getStore()?.();
9712
+ try {
9713
+ await beforeModelRequest();
9714
+ await modelTransportStartedObserver.getStore()?.();
9715
+ } catch (error) {
9716
+ const admission = modelTransportAdmission.getStore();
9717
+ if (admission) admission.refusal = { error };
9718
+ throw error;
9719
+ }
9720
+ }
9721
+ function sdkModelTransportAdmissionFetch(inner) {
9722
+ return async (input, init) => {
9723
+ const admission = {};
9724
+ return modelTransportAdmission.run(admission, async () => {
9725
+ try {
9726
+ return await inner(input, init);
9727
+ } catch (error) {
9728
+ if (!admission.refusal || admission.refusal.error !== error) throw error;
9729
+ const response = new Response(null, {
9730
+ status: 400,
9731
+ headers: { "x-should-retry": "false" }
9732
+ });
9733
+ modelTransportRefusals.set(response.headers, admission.refusal);
9734
+ return response;
9735
+ }
9736
+ });
9737
+ };
9738
+ }
9739
+ function rethrowModelTransportAdmissionRefusal(headers) {
9740
+ const refusal = modelTransportRefusals.get(headers);
9741
+ if (!refusal) return;
9742
+ modelTransportRefusals.delete(headers);
9743
+ throw refusal.error;
9785
9744
  }
9786
9745
  function markModelPreparationFirstSandboxOperation(durationSeconds) {
9787
9746
  try {
@@ -9970,134 +9929,276 @@ function recordModelPreparationManifestInventory(phase, manifest) {
9970
9929
  }
9971
9930
  }
9972
9931
 
9973
- // src/model-request-capture.ts
9974
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
9975
- var modelRequestCapture = new AsyncLocalStorage3();
9976
- var captureIndices = /* @__PURE__ */ new WeakMap();
9977
- function nextModelContextCaptureIndex(agent) {
9978
- const index = (captureIndices.get(agent) ?? 0) + 1;
9979
- captureIndices.set(agent, index);
9980
- return index;
9981
- }
9982
- function withModelRequestCapture(capture, fn) {
9983
- return capture ? modelRequestCapture.run(capture, fn) : fn();
9984
- }
9985
- function captureProviderRequestBody(provider, input, init) {
9986
- const context = modelRequestCapture.getStore();
9987
- const callback = context?.onProviderRequest;
9988
- if (!callback) return { init, captured: Promise.resolve(), cancel: () => {
9989
- } };
9990
- const index = context.nextProviderRequestIndex?.();
9991
- const observer = (providerId, body2, reason) => callback(providerId, body2, reason, index);
9992
- let cancel = () => {
9993
- };
9994
- let body = init?.body;
9995
- let nextInit = init;
9996
- if (body instanceof ReadableStream) {
9997
- const [sent, inspected] = body.tee();
9998
- nextInit = { ...init, body: sent };
9999
- body = inspected;
10000
- } else if (body == null && input instanceof Request) {
10001
- body = input.clone().body;
9932
+ // src/replayable-json-body.ts
9933
+ var TARGET_CHUNK_CHARS = 64 * 1024;
9934
+ var LARGE_STRING_SOURCE_CHARS = 32 * 1024;
9935
+ var STRING_SLICE_CODE_UNITS = 10 * 1024;
9936
+ var REPLAYABLE_REQUEST_BODY_FACTORY = Symbol.for(
9937
+ "opengeni.replayable-request-body-factory"
9938
+ );
9939
+ var ReplayableJsonBody = class {
9940
+ source;
9941
+ constructor(source) {
9942
+ this.source = source;
10002
9943
  }
10003
- const captured = (async () => {
10004
- const limit = 4 * 1024 * 1024;
10005
- let text2;
10006
- if (typeof body === "string") {
10007
- if (Buffer.byteLength(body, "utf8") > limit) {
10008
- await observer(provider, null, "Request exceeds the 4 MiB capture limit.");
10009
- return;
9944
+ async *[Symbol.asyncIterator]() {
9945
+ const encoder = new TextEncoder();
9946
+ for (const chunk of jsonTextChunks(this.source)) {
9947
+ yield encoder.encode(chunk);
9948
+ }
9949
+ }
9950
+ createStream() {
9951
+ const iterator = this[Symbol.asyncIterator]();
9952
+ return new ReadableStream({
9953
+ async pull(controller) {
9954
+ try {
9955
+ const next = await iterator.next();
9956
+ if (next.done) controller.close();
9957
+ else controller.enqueue(next.value);
9958
+ } catch (error) {
9959
+ controller.error(error);
9960
+ }
9961
+ },
9962
+ async cancel(reason) {
9963
+ await iterator.return?.(reason).catch(() => void 0);
10010
9964
  }
10011
- text2 = body;
10012
- } else if (body instanceof ReadableStream) {
10013
- const reader = body.getReader();
10014
- let cancelled = false;
10015
- cancel = () => {
10016
- cancelled = true;
10017
- void reader.cancel().catch(() => void 0);
10018
- };
10019
- const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
10020
- signal?.addEventListener("abort", cancel, { once: true });
10021
- if (signal?.aborted) cancel();
10022
- const decoder = new TextDecoder("utf-8", { fatal: true });
10023
- const chunks = [];
10024
- let bytes = 0;
10025
- try {
10026
- while (true) {
10027
- const chunk = await reader.read();
10028
- if (chunk.done) break;
10029
- bytes += chunk.value.byteLength;
10030
- if (bytes > limit) {
10031
- void reader.cancel().catch(() => void 0);
10032
- await observer(provider, null, "Request exceeds the 4 MiB capture limit.");
10033
- return;
10034
- }
10035
- chunks.push(decoder.decode(chunk.value, { stream: true }));
9965
+ });
9966
+ }
9967
+ };
9968
+ var ReplayableJsonOpenAI = class extends OpenAI6 {
9969
+ modelRequestPolicy;
9970
+ constructor(options, hooks = {}) {
9971
+ super({
9972
+ ...options,
9973
+ fetch: sdkModelTransportAdmissionFetch(options?.fetch ?? globalThis.fetch)
9974
+ });
9975
+ this.modelRequestPolicy = hooks.modelRequestPolicy;
9976
+ }
9977
+ makeStatusError(status, error, message, headers) {
9978
+ rethrowModelTransportAdmissionRefusal(headers);
9979
+ return super.makeStatusError(status, error, message, headers);
9980
+ }
9981
+ post(path, opts) {
9982
+ if (!isModelRequestPath(path) || opts === void 0) {
9983
+ return super.post(path, opts);
9984
+ }
9985
+ const wrapped = Promise.resolve(opts).then((resolved) => {
9986
+ const body = resolved.body;
9987
+ let prepared = resolved;
9988
+ if (this.modelRequestPolicy && isJsonRecordBody(body)) {
9989
+ const policy = this.modelRequestPolicy({ path, body });
9990
+ if (policy?.body || policy?.headers) {
9991
+ prepared = {
9992
+ ...resolved,
9993
+ ...policy.body ? { body: policy.body } : {},
9994
+ ...policy.headers ? { headers: mergePolicyHeaders(resolved.headers, policy.headers) } : {}
9995
+ };
10036
9996
  }
10037
- if (cancelled) return;
10038
- chunks.push(decoder.decode());
10039
- text2 = chunks.join("");
10040
- } catch {
10041
- void reader.cancel().catch(() => void 0);
10042
- if (!cancelled)
10043
- await observer(provider, null, "The provider body could not be read as UTF-8.");
10044
- return;
10045
- } finally {
10046
- signal?.removeEventListener("abort", cancel);
10047
- reader.releaseLock();
10048
- cancel = () => {
10049
- };
10050
9997
  }
9998
+ return wrapJsonRequestOptions(prepared);
9999
+ });
10000
+ return super.post(path, wrapped);
10001
+ }
10002
+ async buildRequest(inputOptions, context) {
10003
+ const replayable = inputOptions.body instanceof ReplayableJsonBody ? inputOptions.body : void 0;
10004
+ const priorStreamingMarker = inputOptions.__metadata?.hasStreamingBody;
10005
+ const built = await super.buildRequest(inputOptions, context);
10006
+ if (!replayable) return built;
10007
+ if (priorStreamingMarker === void 0) {
10008
+ if (inputOptions.__metadata) delete inputOptions.__metadata.hasStreamingBody;
10051
10009
  } else {
10052
- await observer(provider, null, "This transport body cannot be inspected.");
10053
- return;
10010
+ inputOptions.__metadata = {
10011
+ ...inputOptions.__metadata,
10012
+ hasStreamingBody: priorStreamingMarker
10013
+ };
10014
+ }
10015
+ const request = built.req;
10016
+ request[REPLAYABLE_REQUEST_BODY_FACTORY] = () => replayable.createStream();
10017
+ return built;
10018
+ }
10019
+ };
10020
+ function isModelRequestPath(path) {
10021
+ const pathname = path.split("?", 1)[0] ?? path;
10022
+ return pathname.endsWith("/responses") || pathname.endsWith("/chat/completions");
10023
+ }
10024
+ function wrapJsonRequestOptions(options) {
10025
+ const body = options.body;
10026
+ if (!isJsonObjectBody(body) || body instanceof ReplayableJsonBody) return options;
10027
+ return {
10028
+ ...options,
10029
+ body: new ReplayableJsonBody(body),
10030
+ headers: mergePolicyHeaders(options.headers, { "content-type": "application/json" })
10031
+ };
10032
+ }
10033
+ function isJsonObjectBody(value) {
10034
+ if (!value || typeof value !== "object") return false;
10035
+ if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) return false;
10036
+ if (value instanceof Blob || value instanceof FormData || value instanceof URLSearchParams) {
10037
+ return false;
10038
+ }
10039
+ if (value instanceof ReadableStream) return false;
10040
+ return !(Symbol.asyncIterator in value) && !(Symbol.iterator in value);
10041
+ }
10042
+ function isJsonRecordBody(value) {
10043
+ return isJsonObjectBody(value) && !Array.isArray(value);
10044
+ }
10045
+ function mergePolicyHeaders(headers, additions) {
10046
+ const replacedNames = new Set(Object.keys(additions).map((name) => name.toLowerCase()));
10047
+ if (headers instanceof Headers) {
10048
+ const merged2 = new Headers(headers);
10049
+ for (const [name, value] of Object.entries(additions)) merged2.set(name, value);
10050
+ return merged2;
10051
+ }
10052
+ if (headers && typeof headers === "object" && "values" in headers && "nulls" in headers && headers.values instanceof Headers && headers.nulls instanceof Set) {
10053
+ const resolved = headers;
10054
+ const rows = [
10055
+ ...resolved.values.entries(),
10056
+ ...[...resolved.nulls].map((name) => [name, null])
10057
+ ];
10058
+ return mergePolicyHeaders(rows, additions);
10059
+ }
10060
+ if (Array.isArray(headers)) {
10061
+ return [
10062
+ ...headers.filter(
10063
+ (row) => !Array.isArray(row) || typeof row[0] !== "string" || !replacedNames.has(row[0].toLowerCase())
10064
+ ),
10065
+ ...Object.entries(additions)
10066
+ ];
10067
+ }
10068
+ const merged = { ...headers ?? {} };
10069
+ for (const name of Object.keys(merged)) {
10070
+ if (replacedNames.has(name.toLowerCase())) delete merged[name];
10071
+ }
10072
+ return { ...merged, ...additions };
10073
+ }
10074
+ function* jsonTextChunks(value) {
10075
+ const fragments = jsonValueFragments(value, "", /* @__PURE__ */ new Set(), 0);
10076
+ if (!fragments) throw new TypeError("Model request body is not JSON serializable");
10077
+ let buffered = "";
10078
+ for (const fragment of fragments) {
10079
+ if (buffered.length > 0 && buffered.length + fragment.length > TARGET_CHUNK_CHARS) {
10080
+ yield buffered;
10081
+ buffered = "";
10054
10082
  }
10055
- await observer(provider, text2);
10056
- })().catch(() => void 0);
10057
- return { init: nextInit, captured, cancel: () => cancel() };
10083
+ if (fragment.length >= TARGET_CHUNK_CHARS) yield fragment;
10084
+ else buffered += fragment;
10085
+ }
10086
+ if (buffered.length > 0) yield buffered;
10058
10087
  }
10059
- async function notifyModelRequestCapture(request) {
10060
- const capture = modelRequestCapture.getStore();
10061
- if (!capture) return;
10088
+ function jsonValueFragments(source, key, ancestors, depth) {
10089
+ if (typeof source === "string" && source.length > LARGE_STRING_SOURCE_CHARS) {
10090
+ return jsonStringFragments(source);
10091
+ }
10092
+ if (depth >= 2 || depth > 0 && !Array.isArray(source)) {
10093
+ return nativeJsonPropertyFragments(source, key);
10094
+ }
10095
+ const value = prepareJsonValue(source, key);
10096
+ if (value === void 0 || typeof value === "function" || typeof value === "symbol") {
10097
+ return null;
10098
+ }
10099
+ if (typeof value === "bigint") {
10100
+ throw new TypeError("Do not know how to serialize a BigInt");
10101
+ }
10102
+ if (typeof value === "string") {
10103
+ return jsonStringFragments(value);
10104
+ }
10105
+ if (value === null || typeof value !== "object") {
10106
+ return [JSON.stringify(value)];
10107
+ }
10108
+ const rawJson = JSON;
10109
+ if (rawJson.isRawJSON?.(value)) return [JSON.stringify(value)];
10110
+ if (ancestors.has(value)) throw new TypeError("cyclic object value");
10111
+ return Array.isArray(value) ? jsonArrayFragments(value, ancestors, depth) : jsonObjectFragments(value, ancestors, depth);
10112
+ }
10113
+ function* jsonArrayFragments(value, ancestors, depth) {
10114
+ ancestors.add(value);
10062
10115
  try {
10063
- await capture(snapshotModelRequestPrefix(request));
10064
- } catch {
10116
+ const length = value.length;
10117
+ yield "[";
10118
+ for (let index = 0; index < length; index += 1) {
10119
+ if (index > 0) yield ",";
10120
+ const child = jsonValueFragments(value[index], String(index), ancestors, depth + 1);
10121
+ if (child) yield* child;
10122
+ else yield "null";
10123
+ }
10124
+ yield "]";
10125
+ } finally {
10126
+ ancestors.delete(value);
10065
10127
  }
10066
10128
  }
10067
- function snapshotModelRequestPrefix(request) {
10068
- return {
10069
- ...request,
10070
- tools: structuredClone(request.tools)
10071
- };
10129
+ function* jsonObjectFragments(value, ancestors, depth) {
10130
+ ancestors.add(value);
10131
+ try {
10132
+ const keys = Object.keys(value);
10133
+ let emitted = false;
10134
+ yield "{";
10135
+ for (const key of keys) {
10136
+ const child = jsonValueFragments(value[key], key, ancestors, depth + 1);
10137
+ if (!child) continue;
10138
+ if (emitted) yield ",";
10139
+ emitted = true;
10140
+ yield* jsonStringFragments(key);
10141
+ yield ":";
10142
+ yield* child;
10143
+ }
10144
+ yield "}";
10145
+ } finally {
10146
+ ancestors.delete(value);
10147
+ }
10072
10148
  }
10073
- var ModelRequestCaptureModel = class {
10074
- constructor(inner) {
10075
- this.inner = inner;
10149
+ function nativeJsonPropertyFragments(source, key) {
10150
+ const holder = /* @__PURE__ */ Object.create(null);
10151
+ holder[key] = source;
10152
+ const serialized = JSON.stringify(holder);
10153
+ if (serialized === "{}") return null;
10154
+ const prefix = `{${JSON.stringify(key)}:`;
10155
+ if (!serialized.startsWith(prefix) || !serialized.endsWith("}")) {
10156
+ throw new TypeError("Model request body is not JSON serializable");
10076
10157
  }
10077
- async getResponse(request) {
10078
- rememberPreparedModelRequest(request);
10079
- void notifyModelRequestCapture(request);
10080
- return this.inner.getResponse(request);
10158
+ return boundedNativeJsonFragments(serialized.slice(prefix.length, -1));
10159
+ }
10160
+ function* boundedNativeJsonFragments(serialized) {
10161
+ for (let start = 0; start < serialized.length; ) {
10162
+ let end = Math.min(serialized.length, start + TARGET_CHUNK_CHARS);
10163
+ if (end < serialized.length && serialized.charCodeAt(end - 1) >= 55296 && serialized.charCodeAt(end - 1) <= 56319 && serialized.charCodeAt(end) >= 56320 && serialized.charCodeAt(end) <= 57343) {
10164
+ end -= 1;
10165
+ }
10166
+ yield serialized.slice(start, end);
10167
+ start = end;
10081
10168
  }
10082
- async *getStreamedResponse(request) {
10083
- rememberPreparedModelRequest(request);
10084
- void notifyModelRequestCapture(request);
10085
- yield* this.inner.getStreamedResponse(request);
10169
+ }
10170
+ function prepareJsonValue(source, key) {
10171
+ let value = source;
10172
+ const sourceType = typeof value;
10173
+ if (value !== null && (sourceType === "object" || sourceType === "function" || sourceType === "bigint")) {
10174
+ const toJSON = value.toJSON;
10175
+ if (typeof toJSON === "function") value = toJSON.call(value, key);
10086
10176
  }
10087
- getRetryAdvice(args) {
10088
- return this.inner.getRetryAdvice?.(args);
10177
+ if (value !== null && typeof value === "object") {
10178
+ if (utilTypes.isNumberObject(value)) return Number.prototype.valueOf.call(value);
10179
+ if (utilTypes.isStringObject(value)) return String.prototype.valueOf.call(value);
10180
+ if (utilTypes.isBooleanObject(value)) return Boolean.prototype.valueOf.call(value);
10181
+ if (utilTypes.isBigIntObject(value)) return BigInt.prototype.valueOf.call(value);
10089
10182
  }
10090
- };
10091
- var ModelRequestCaptureProvider = class {
10092
- constructor(inner) {
10093
- this.inner = inner;
10183
+ return value;
10184
+ }
10185
+ function* jsonStringFragments(value) {
10186
+ if (value.length <= LARGE_STRING_SOURCE_CHARS) {
10187
+ yield JSON.stringify(value);
10188
+ return;
10094
10189
  }
10095
- async getModel(modelName) {
10096
- const model = await this.inner.getModel(modelName);
10097
- if (model instanceof ModelRequestCaptureModel) return model;
10098
- return new ModelRequestCaptureModel(model);
10190
+ yield '"';
10191
+ for (let start = 0; start < value.length; ) {
10192
+ let end = Math.min(value.length, start + STRING_SLICE_CODE_UNITS);
10193
+ if (end < value.length && value.charCodeAt(end - 1) >= 55296 && value.charCodeAt(end - 1) <= 56319 && value.charCodeAt(end) >= 56320 && value.charCodeAt(end) <= 57343) {
10194
+ end -= 1;
10195
+ }
10196
+ const encoded = JSON.stringify(value.slice(start, end));
10197
+ yield encoded.slice(1, -1);
10198
+ start = end;
10099
10199
  }
10100
- };
10200
+ yield '"';
10201
+ }
10101
10202
 
10102
10203
  // src/provider-quota.ts
10103
10204
  import { APIError } from "openai";
@@ -10251,12 +10352,12 @@ function errorTexts(value, out, seen) {
10251
10352
  }
10252
10353
  if (!value || typeof value !== "object" || seen.has(value)) return;
10253
10354
  seen.add(value);
10254
- const record = value;
10355
+ const record2 = value;
10255
10356
  for (const key of ["message", "code", "type", "name", "param"]) {
10256
- const field = record[key];
10357
+ const field = record2[key];
10257
10358
  if (typeof field === "string" && field.length > 0) out.push(field);
10258
10359
  }
10259
- for (const key of ["error", "cause", "response", "data"]) errorTexts(record[key], out, seen);
10360
+ for (const key of ["error", "cause", "response", "data"]) errorTexts(record2[key], out, seen);
10260
10361
  }
10261
10362
  function headerValue(headers, name) {
10262
10363
  if (!headers || typeof headers !== "object") return null;
@@ -10349,12 +10450,19 @@ function withoutQuotaExhaustedRetries(inner) {
10349
10450
  // src/claude-subscription-usage.ts
10350
10451
  import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
10351
10452
  var observers = new AsyncLocalStorage4();
10352
- function withClaudeUsageObserver(observer, run2) {
10353
- return observers.run(observer, run2);
10453
+ function withClaudeUsageObserver(observer, run2, prepare) {
10454
+ return observers.run({ observe: observer, ...prepare ? { prepare } : {} }, run2);
10455
+ }
10456
+ async function prepareClaudeSubscriptionRequest(providerId, input, init) {
10457
+ const prepare = observers.getStore()?.prepare;
10458
+ if (!prepare) return init;
10459
+ const headers = new Headers(input instanceof Request ? input.headers : void 0);
10460
+ new Headers(init?.headers).forEach((value, key) => headers.set(key, value));
10461
+ return { ...init, headers: await prepare(providerId, headers) };
10354
10462
  }
10355
10463
  function observeClaudeUsageResponse(providerId, response) {
10356
10464
  try {
10357
- observers.getStore()?.(providerId, response);
10465
+ observers.getStore()?.observe(providerId, response);
10358
10466
  } catch {
10359
10467
  }
10360
10468
  }
@@ -10627,6 +10735,7 @@ function instrumentedModelFetch(provider, inner) {
10627
10735
  if (!isModelCallFetch(input)) {
10628
10736
  return await inner(input, init);
10629
10737
  }
10738
+ init = await prepareClaudeSubscriptionRequest(provider, input, init);
10630
10739
  await recordModelTransportStarted();
10631
10740
  const capture = captureProviderRequestBody(provider, input, init);
10632
10741
  const started = performance.now();
@@ -10693,7 +10802,7 @@ var RunMcpCredentials = class {
10693
10802
  #closed = false;
10694
10803
  #onAbort = () => this.close();
10695
10804
  constructor(targets, options = {}) {
10696
- this.#targets = targets.map(({ id, url }) => ({ id, url }));
10805
+ this.#targets = targets.filter((target) => !target.connectionRef).map(({ id, url }) => ({ id, url }));
10697
10806
  this.#signal = options.signal;
10698
10807
  this.#now = options.now ?? Date.now;
10699
10808
  this.#signal?.addEventListener("abort", this.#onAbort, { once: true });
@@ -10770,11 +10879,11 @@ var RunMcpCredentials = class {
10770
10879
  replace(material) {
10771
10880
  this.prepare(material)();
10772
10881
  }
10773
- /** Refuse credentials for omitted, local, or rewritten server routes. */
10882
+ /** Refuse credentials for native, omitted, local, or rewritten server routes. */
10774
10883
  assertRemoteTargets(targets) {
10775
10884
  this.#remoteTargets = this.#targets.filter(
10776
10885
  (original) => targets.some(
10777
- (target) => target.id === original.id && normalizedUrl(target.url) !== null && normalizedUrl(target.url) === normalizedUrl(original.url)
10886
+ (target) => !target.connectionRef && target.id === original.id && normalizedUrl(target.url) !== null && normalizedUrl(target.url) === normalizedUrl(original.url)
10778
10887
  )
10779
10888
  );
10780
10889
  this.#dropExcluded();
@@ -10817,6 +10926,10 @@ var RunMcpCredentials = class {
10817
10926
  /** Called at the literal fetch boundary, including POST, SSE GET and DELETE. */
10818
10927
  requestInit(target, input, init) {
10819
10928
  this.#assertOpen();
10929
+ if (target.connectionRef) {
10930
+ this.excludeLocalTarget(target.id);
10931
+ return init;
10932
+ }
10820
10933
  this.assertAvailable(target.id);
10821
10934
  const entry = this.#entries.get(target.id);
10822
10935
  if (!entry) return init;
@@ -11175,7 +11288,7 @@ import {
11175
11288
  IntegrationInvocationError
11176
11289
  } from "@opengeni/capabilities";
11177
11290
  import {
11178
- AGENT_INSTRUCTIONS_CORE_PLACEHOLDER,
11291
+ AGENT_INSTRUCTIONS_CORE_PLACEHOLDER as AGENT_INSTRUCTIONS_CORE_PLACEHOLDER2,
11179
11292
  collectSandboxEnvironment,
11180
11293
  configuredProviders as configuredProviders2,
11181
11294
  McpOperationRecoverySchema,
@@ -11221,6 +11334,8 @@ import {
11221
11334
  GenerateVideoToolInput,
11222
11335
  GetVideoGenerationCapabilitiesToolInput,
11223
11336
  RequestHumanInputToolInput as RequestHumanInputToolInput2,
11337
+ resolveAgentToolFamilies,
11338
+ resolveAgentMediaToolSurface,
11224
11339
  AttemptToolResult as AttemptToolResult3,
11225
11340
  IN_PROCESS_INTEGRATION_TOOL_FAMILY_DOMAINS,
11226
11341
  firstPartyToolFamily,
@@ -11523,13 +11638,15 @@ function unavailableToolResult(input) {
11523
11638
  });
11524
11639
  }
11525
11640
  var LazyToolRuntime = class {
11526
- constructor(transport, mcpServerIds, toolPreparationReady, deferredMcpServerIds = mcpServerIds, preparationIndependentToolNames = /* @__PURE__ */ new Set(), modelMcpServerIds = () => /* @__PURE__ */ new Map()) {
11641
+ constructor(transport, mcpServerIds, toolPreparationReady, deferredMcpServerIds = mcpServerIds, preparationIndependentToolNames = /* @__PURE__ */ new Set(), modelMcpServerIds = () => /* @__PURE__ */ new Map(), conditionalRouter = false, routerInHistory = false) {
11527
11642
  this.transport = transport;
11528
11643
  this.mcpServerIds = mcpServerIds;
11529
11644
  this.toolPreparationReady = toolPreparationReady;
11530
11645
  this.deferredMcpServerIds = deferredMcpServerIds;
11531
11646
  this.preparationIndependentToolNames = preparationIndependentToolNames;
11532
11647
  this.modelMcpServerIds = modelMcpServerIds;
11648
+ this.conditionalRouter = conditionalRouter;
11649
+ this.routerWasExposed = routerInHistory;
11533
11650
  this.controlTools = transport !== "generic_dispatch" ? [this.buildNativeSearchTool(), this.buildListTool()] : [this.buildGenericSearchTool(), this.buildGenericInvokeTool(), this.buildListTool()];
11534
11651
  if (toolPreparationReady) {
11535
11652
  void toolPreparationReady.then(
@@ -11554,9 +11671,17 @@ var LazyToolRuntime = class {
11554
11671
  activeAgent = null;
11555
11672
  activeRunContext;
11556
11673
  controlTools;
11674
+ routerWasExposed;
11557
11675
  hasPendingPreparation() {
11558
11676
  return !this.preparationSettled;
11559
11677
  }
11678
+ async prepareConditionalRouter() {
11679
+ if (this.conditionalRouter) await this.ensurePrepared();
11680
+ }
11681
+ visibleControlTools() {
11682
+ this.routerWasExposed ||= !this.conditionalRouter || this.searchableToolNames.size > 0 || this.hasPendingPreparation() && this.deferredMcpServerIds.size > 0;
11683
+ return this.routerWasExposed ? this.controlTools : [];
11684
+ }
11560
11685
  async ensurePrepared() {
11561
11686
  await this.toolPreparationReady;
11562
11687
  this.preparationSettled = true;
@@ -11820,14 +11945,16 @@ var lazyToolRuntimeByAgent = /* @__PURE__ */ new WeakMap();
11820
11945
  function lazyToolRuntimeForAgent(agent) {
11821
11946
  return lazyToolRuntimeByAgent.get(agent);
11822
11947
  }
11823
- function installLazyToolRuntime(agent, transport, mcpServerIds, toolPreparationReady, deferredMcpServerIds = mcpServerIds, preparationIndependentToolNames = /* @__PURE__ */ new Set(), modelMcpServerIds) {
11948
+ function installLazyToolRuntime(agent, transport, mcpServerIds, toolPreparationReady, deferredMcpServerIds = mcpServerIds, preparationIndependentToolNames = /* @__PURE__ */ new Set(), modelMcpServerIds, conditionalRouter = false, routerInHistory = false) {
11824
11949
  const runtime = new LazyToolRuntime(
11825
11950
  transport,
11826
11951
  mcpServerIds,
11827
11952
  toolPreparationReady,
11828
11953
  deferredMcpServerIds,
11829
11954
  preparationIndependentToolNames,
11830
- modelMcpServerIds
11955
+ modelMcpServerIds,
11956
+ conditionalRouter,
11957
+ routerInHistory
11831
11958
  );
11832
11959
  installLazyToolRuntimeOnAgent(agent, runtime);
11833
11960
  return runtime;
@@ -11843,14 +11970,15 @@ function installLazyToolRuntimeOnAgent(agent, runtime) {
11843
11970
  runtime.registerOriginalToolLoader(agent, originalGetAllTools);
11844
11971
  agent.getAllTools = async (runContext) => {
11845
11972
  runtime.noteToolResolution(agent, runContext);
11973
+ await runtime.prepareConditionalRouter();
11846
11974
  if (runtime.hasPendingPreparation()) {
11847
11975
  const tools2 = await originalGetAllTools(runContext);
11848
11976
  runtime.refresh(tools2);
11849
- return [...tools2, ...runtime.controlTools];
11977
+ return [...tools2, ...runtime.visibleControlTools()];
11850
11978
  }
11851
11979
  const tools = await originalGetAllTools(runContext);
11852
11980
  runtime.refresh(tools);
11853
- return [...runtime.configuredExecutionTools(tools), ...runtime.controlTools];
11981
+ return [...runtime.configuredExecutionTools(tools), ...runtime.visibleControlTools()];
11854
11982
  };
11855
11983
  const originalClone = agent.clone?.bind(agent);
11856
11984
  if (originalClone) {
@@ -12016,6 +12144,7 @@ var LazyToolModel = class {
12016
12144
  this.runtime = runtime;
12017
12145
  }
12018
12146
  async getResponse(request) {
12147
+ await beforeModelRequest();
12019
12148
  const prepared = prepareLazyToolRequest(request, this.runtime);
12020
12149
  rememberPreparedModelRequest(prepared);
12021
12150
  void notifyModelRequestCapture(prepared);
@@ -12026,6 +12155,7 @@ var LazyToolModel = class {
12026
12155
  return this.runtime.transport === "generic_dispatch" ? transformGenericDispatchResponse(response, this.runtime) : response;
12027
12156
  }
12028
12157
  async *getStreamedResponse(request) {
12158
+ await beforeModelRequest();
12029
12159
  const prepared = prepareLazyToolRequest(request, this.runtime);
12030
12160
  rememberPreparedModelRequest(prepared);
12031
12161
  void notifyModelRequestCapture(prepared);
@@ -12035,19 +12165,18 @@ var LazyToolModel = class {
12035
12165
  await this.runtime.ensurePrepared();
12036
12166
  }
12037
12167
  }
12038
- if (this.runtime.transport === "generic_dispatch" && event.type === "response_done") {
12039
- yield {
12040
- ...event,
12041
- response: {
12042
- ...event.response,
12043
- output: event.response.output.flatMap(
12044
- (item) => transformGenericDispatchCall(item, this.runtime)
12045
- )
12046
- }
12047
- };
12048
- } else {
12049
- yield event;
12050
- }
12168
+ const delivered = this.runtime.transport === "generic_dispatch" && event.type === "response_done" ? {
12169
+ ...event,
12170
+ response: {
12171
+ ...event.response,
12172
+ output: event.response.output.flatMap(
12173
+ (item) => transformGenericDispatchCall(item, this.runtime)
12174
+ )
12175
+ }
12176
+ } : event;
12177
+ const settlement = modelResponseSettlement(delivered);
12178
+ void settlement?.catch(() => void 0);
12179
+ yield delivered;
12051
12180
  }
12052
12181
  }
12053
12182
  getRetryAdvice(args) {
@@ -12775,17 +12904,165 @@ Adapt accordingly based on the user\u2019s request type. When asked to:
12775
12904
 
12776
12905
  Do not infer authorization for a materially different action than the user requested. Act without asking when the action is read-only or affects only the systems, data, and people the user placed in scope, or when it is a normal implementation step within the requested workflow that causes no significant external state change (e.g. tool calls to external applications).
12777
12906
 
12778
- A terminal condition such as \u201Cfinish,\u201D \u201Cbabysit,\u201D or \u201Cdo not stop\u201D requires persistence toward the outcome, but does not broaden the set of authorized actions. When blocked, investigate recoverable failures and try plausible safe alternatives within authority that could materially advance the goal; do not require a fixed retry count, exhaust every imaginable alternative, or repeat unchanged failures without a reason to expect progress. A definitive missing permission or required human decision can justify an immediate goal pause with evidence and the change needed to resume. Work already in flight or a meaningful timed recheck calls for the available waiting mechanism, not a goal pause. Tool approvals remain human-only.
12907
+ A terminal condition such as \u201Cfinish,\u201D \u201Cbabysit,\u201D or \u201Cdo not stop\u201D requires persistence toward the outcome, but does not broaden the set of authorized actions. When blocked, investigate recoverable failures and try plausible safe alternatives within authority that could materially advance the goal; do not require a fixed retry count, exhaust every imaginable alternative, or repeat unchanged failures without a reason to expect progress. A definitive missing permission or required human decision can justify an immediate goal pause with evidence and the change needed to resume. Work already in flight or a meaningful timed recheck calls for the available waiting mechanism, not a goal pause. Tool approvals remain human-only.
12908
+
12909
+ Make informed assumptions that keep the work moving within the user's intent and scope. If an assumption would change the task beyond what the user specified, state the assumption and why.
12910
+
12911
+ When the user asks a clarifying question or objects, answer with concrete evidence and reasoning rather than unsubstantiated deference, so tradeoffs are easy to evaluate.
12912
+
12913
+ If completion requires new authority, external coordination, or a meaningful expansion beyond the user\u2019s implied intent and task scope (e.g. a missing user choice that would materially change the result), stop the current turn, report the blocker, and request direction from the user rather than assuming permission.
12914
+
12915
+ Decide the design before building it. First check whether OpenGeni already provides the capability natively (for example, a Site reaches the model and workspace tools through the host bridge and needs no server of its own). If a native path fits, use it. Follow the project's established architecture and choices the user has already authorized or delegated; the user need not name each host, provider, or credential. Ask before making a new external commitment or materially departing from the established architecture beyond the authorized scope: name the candidate designs, and do not start parallel work that assumes the unresolved choice. The absence of a native path alone does not require a question; continue with routine implementation choices within scope.
12916
+
12917
+ # Destructive Actions
12918
+
12919
+ Be cautious with commands or API calls that can delete, overwrite, or otherwise make data difficult to recover.
12920
+
12921
+ Before taking a destructive action:
12922
+
12923
+ - Make sure the action is clearly within the user's request.
12924
+ - Resolve the exact targets with read-only checks when necessary.
12925
+ - Do not use \`$HOME\`, \`~\`, \`/\`, a workspace root, or another broad directory as the target of a recursive or destructive command.
12926
+ - When creating temporary directories, prefer using \`mktemp -d\`, or \`New-Item\` in Powershell.
12927
+ - When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.
12928
+ - Prefer recoverable operations, such as moving files to trash, when practical.
12929
+ - If the target or scope is unclear, stop and ask the user.
12930
+
12931
+ Never run commands such as \`rm -rf $HOME\` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.
12932
+
12933
+ After deleting anything material, briefly tell the user what was removed and whether it can be recovered.
12934
+
12935
+ # Using skills
12936
+
12937
+ Skills are reusable instructions supplied dynamically for the current session. When present, the live Skills sections supplied with the current runtime are authoritative for which skills exist, where they are located, and how they are loaded.
12938
+
12939
+ - Use a skill when the user names it or the task clearly needs what it provides, not because of keyword matches or because it is available. Use the smallest set that covers the request.
12940
+ - Read a selected skill before acting, once: while its text is still in your context, do not read it again. Read its referenced files only when needed, resolve them relative to its own directory, and reuse its scripts, assets, and templates when provided.
12941
+ - Do not announce Skill reads. If a skill materially changes an action or pauses the work, name it and say why.
12942
+ - The user's instructions take precedence over skill guidance.
12943
+ - If a named skill is unavailable or cannot be read, say so briefly and continue with the best fallback.
12944
+
12945
+ # Integration setup
12946
+
12947
+ Use available integration tools directly. If access is missing, check \`variable_set_list\` (see Session coordination), then search \`capability_catalog_search\`. For a suitable match with \`setup.nextAction\`, call \`capability_authorization_request\` with its ID and a task-specific rationale. If no match exists and the task needs a remote MCP whose exact HTTPS URL the user supplied or reliable documentation establishes, call \`custom_mcp_setup_request\` with its name, URL, and rationale. Never invent URLs or request credentials in chat. Showing either card does not need integration-management permission and grants no access; the authenticated human must authorize setup. A card is for an integration required by the authorized design, including established or delegated choices. Resolve out-of-scope architecture choices before requesting setup. After setup, rediscover tools and verify access. If blocked or a setup tool is unavailable, explain the specific gap.
12948
+
12949
+ # Session coordination
12950
+
12951
+ 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.
12952
+
12953
+ 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.
12954
+
12955
+ Command completion alone resumes you only while you have an explicit \`wait_for_input\` registered. For ordinary background commands, register that session-level wait before ending your turn. Exception: pending Codemode calls need the current live attempt; keep observing them with \`command_wait\`/\`command_read\` instead of ending the turn. If you finish normally, command results remain retained and can accompany later input, but do not start another turn by themselves. No per-command dismissal is required.
12956
+
12957
+ 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.
12958
+
12959
+ Create a child worker only for a concrete, bounded subtask that can run independently and whose result has a clear integration point in the current request. Delegation has setup and coordination overhead: by default, answer directly when the work takes only a few steps, and send a related follow-up to a child you already spawned with \`session_send_message\` instead of spawning another. Explicit user requests and applicable Skill guidance for delegation, independent review, or fresh workers override that default within existing authority. Before spawning, decide what output you need and keep the parent's concurrent work disjoint. Do not duplicate a child's implementation; independent review or comparison may intentionally examine the same subject with a distinct deliverable. If no useful independent work remains and no such delegation is requested, continue in this session. A session cannot gain a Variable Set while it works, so when even a short step needs one from \`variable_set_list\` that this session lacks and the request calls for it, run that step in a child created with those \`variableSetIds\` instead of asking the user to attach it. Do not repurpose or direct an unrelated existing session unless the user explicitly asks. If no matching session tool is available on this turn, handle what you can in this session and report any required delegation that is unavailable instead of inventing an API.
12960
+
12961
+ When supervising work, an accepted message, queued status, or changing timestamp is not proof of execution. Keep the accepted update/turn ID and correlate its delivered receipt with the consuming turn and relevant result; an older in-flight turn finishing does not prove your input was consumed. Use the receipt correlation described by the sending tool. Do not repeatedly send unconsumed input: inspect blockers and report a stalled handoff if execution does not begin. Preserve explicit human pauses and approvals.
12962
+
12963
+ After spawning, keep each child id and event cursor. Before committing, publishing, completing a goal, or giving a final answer that depends on a child, consume and integrate that child's completed result. When a child needs minutes and nothing else can advance meanwhile, call \`wait_for_input\` right after spawning instead of alternating \`session_wait\` and \`session_get\`: the child's terminal result wakes you and carries its final answer in \`payload.finalAnswer\`. Use that answer directly; read the child's results with \`session_events\` only when \`finalAnswer\` is absent or truncated (\`finalAnswer.nextAction\` reads the complete answer) or when you need detail it lacks. To join a short child inside this turn, use \`session_wait\` with \`waitFor: "completion"\`; a later terminal result repeating an answer you already integrated needs no reread. A \`goal.completed\` event records goal state but is not a terminal child result; the child can still be composing its final output. Do not present delegated work as incorporated until you have consumed the completed result. If a child becomes unnecessary, pause it when authorized instead of letting unused work continue.
12964
+
12965
+ For a short wait on a child or peer session inside the current turn, call \`session_wait\` with its session id and your last seen sequence instead of sleeping and polling; use \`command_wait\` for one short provider-neutral wait on a background command. Both time out after at most 50 seconds. Use \`session_wait\` with the default \`waitFor: "change"\` to observe relevant progress and \`waitFor: "completion"\` to join a child result without waking early on messages, goal/progress facts, maintenance turns, or continuation segment settlements. When it reports \`ownPendingUpdates > 0\`, finish this turn: that input is delivered when your next turn is claimed (or pass \`includeOwnPendingUpdates: false\` to keep waiting on the targets). Do not immediately repeat a timed-out short wait without new evidence; an unchanged \`session_get\` snapshot between waits is not new evidence. Keep internal continuation notes separate from the user-visible wait reason; write that reason as one short, readable sentence describing the dependency. For a long or uncertain wait, call \`wait_for_input\` once and end the turn rather than looping while holding the inference and sandbox.
12966
+
12967
+ No short execution wait or preliminary status recheck is required before \`wait_for_input\`. Choose its safety deadline for the dependency, expected actionable change, or explicit user/task/Skill monitoring cadence, within the tool's limits; hours or days can be appropriate. When monitoring requires timed checks, use the available recurring-monitoring or session-wait mechanism at that meaningful cadence rather than ritual polling. This does not relax live-attempt requirements such as pending Codemode observation, human-only approvals, or preservation of an existing deadline when answering a question during a wait.
12968
+ `;
12969
+
12970
+ // src/agent-instructions/types.ts
12971
+ function hasSandbox(context) {
12972
+ return context.resources.managedSandbox || context.resources.connectedMachine;
12973
+ }
12974
+ function blocks(...parts) {
12975
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join("\n\n");
12976
+ }
12977
+ function sentences(...parts) {
12978
+ return parts.filter((part) => typeof part === "string" && part.length > 0).join(" ");
12979
+ }
12980
+ function bullets(...items) {
12981
+ return items.filter((item) => typeof item === "string" && item.length > 0).map((item) => `- ${item}`).join("\n");
12982
+ }
12983
+
12984
+ // src/agent-instructions/base-behavior.ts
12985
+ var INSTRUCTION_PRECEDENCE = "Product, workspace, and session instructions take precedence over the default behavior described here, such as tone, length, and format. They never override the runtime mechanics or the rules on authorization and destructive actions.";
12986
+ var PERSONALITY = `# Personality
12987
+
12988
+ Match the user's tone and understanding, and guide them through unfamiliar tasks without expecting them to know what to ask for. Keep your own judgment: disagree when you have reason, and reconsider when the evidence warrants it. Skip flattery and forced enthusiasm, and mention caveats only when they change what the user should do.
12989
+
12990
+ ## Writing style
12991
+
12992
+ Use the minimum formatting that keeps a response clear; avoid unnecessary bold, headers, and lists. When you use lists, follow CommonMark: put a blank line before every list and between a header and the content after it, or the response will not render correctly.
12993
+
12994
+ Lead with the outcome rather than the steps you took. Calibrate to the user's background: more compact for an expert, a bit more educational for someone newer. Prefer plain language over jargon, and mention technical details or tool names only when they help the user.`;
12995
+ function workingWithTheUser(context) {
12996
+ const reserve = context.capabilities.artifacts ? "Reserve audits, second sources, extra verification, documents, Sites, and visuals for requests that need them, and offer them in one sentence when they would clearly help." : "Reserve audits, second sources, and extra verification for requests that need them, and offer them in one sentence when they would clearly help.";
12997
+ return blocks(
12998
+ "# Working with the user",
12999
+ "Keep the user informed while work is underway, then end the turn with a self-contained final response or, where the rules below say so, `wait_for_input`.",
13000
+ "## Match effort to the request",
13001
+ sentences(
13002
+ "Scale the work to what the user asked.",
13003
+ "A simple question or lookup gets a direct answer from the fewest tool calls that establish it; do not verify beyond what the question needs.",
13004
+ reserve,
13005
+ "Waiting is the user's main cost.",
13006
+ "Larger or riskier work, and research or comparison questions, still get the full effort they need."
13007
+ ),
13008
+ 'When the user repeats an ask, such as "check again", "run it again", or the same question for a new time window, reuse the approach, query, script, or session from the earlier turn with the new inputs instead of rediscovering the environment.',
13009
+ `## Progress updates
13010
+
13011
+ A progress update is one short, plain sentence about what you found or what comes next; leave out tool, file, and query names unless the user needs them. Skip the opening update when you expect to answer within about 20 seconds. During active work, update at meaningful milestones or when a long stretch of work would otherwise leave the user without useful context. Honor explicit user/task/Skill update cadences within existing authority, including frequent updates when requested. Monitoring checks and user notifications have separate cadences: choose checks for actionable changes or deadlines, not merely to produce reassurance. Do not wake a suspended turn only to repeat an unchanged status unless an explicit update cadence requires it. Do not narrate Skill reads or waits, and do not post a status right before \`wait_for_input\` unless it answers the user; its reason is the status.
13012
+
13013
+ Do not use a progress update as the final response or as a blocking clarification. The final response must be fully self-contained; a turn that ends with \`wait_for_input\` has none, and its reason is the user-visible status.
13014
+
13015
+ Never praise your plan by contrasting it with an implied worse alternative, as in "I will do <X>, not <Y>".`,
13016
+ `## Final answer
13017
+
13018
+ Put the answer or outcome in the first sentence. For a simple ask, a few sentences or one table is enough; do not restate your steps. An answer built from web or published sources (research, evidence summaries, product or price comparisons) may be short but not partial: summarize what the sources establish, including the best-supported finding, not only the practical takeaway; give figures in the user's terms, such as a monthly total at their stated size rather than only a starting price or unit rate; and link the source next to each study or figure you cite. Use only as much formatting or structure as the content needs. Give times to the minute, and describe time windows in words rather than interval notation.
13019
+
13020
+ Answer questions directly and briefly; after making changes, say what changed, how you checked it, and anything still blocked.`,
13021
+ "### Formatting rules",
13022
+ "Your answer is rendered by an application for the user:",
13023
+ bullets(
13024
+ "You may format with GitHub-flavored Markdown.",
13025
+ "Answer in chat by default, including summaries and reports."
13026
+ )
13027
+ );
13028
+ }
13029
+ var RULES_FOR_WORK = `# Rules for getting work done
13030
+
13031
+ - Run independent tool calls in parallel to save round trips.
13032
+ - Do not introduce unsolicited warnings, disclaimers, approval flows, or safety/compliance checklists due to hypothetical risk.
13033
+ - Match verification to the full requested scope. Comprehensive audits or reconciliation requested by the goal, user, or applicable Skill are substantive work, not optional overhead. Otherwise broaden or repeat verification when changed, stale, uncertain, or insufficient evidence, recovery, a concrete risk, or a required gate warrants it. Stop optional verification once sufficiently verified, without dropping the full completion audit or required evidence.`;
13034
+ function autonomy(context) {
13035
+ const nativeCheck = context.capabilities.artifacts ? "First check whether OpenGeni already provides the capability natively (for example, a Site reaches the model and workspace tools through the host bridge and needs no server of its own)." : "First check whether an available tool already provides the capability natively.";
13036
+ return blocks(
13037
+ `## Autonomy and persistence
13038
+
13039
+ Adapt accordingly based on the user\u2019s request type. When asked to:
13040
+
13041
+ - Answer, explain, review, or report status: gather the evidence the answer needs, in proportion to the question, and answer directly. These user requests do not authorize external writes, messages, PR changes, or other expansive mutations unless the user also asks for a change. Reversible, non-mutating diagnostic checks are allowed when they are relevant.
13042
+ - Diagnose: determine the cause and explain it. Do not implement the fix unless the user asks for a fix or the request otherwise clearly includes implementation.
13043
+ - Change or build: implement the requested change, verify it in proportion to risk, and hand off the completed result while a safe, relevant next step remains.
13044
+ - Monitor or wait: use the recurring-monitoring or wait mechanism provided by the product. Unchanged external state is expected and is not by itself a blocker.
13045
+
13046
+ Do not infer authorization for a materially different action than the user requested. Act without asking when the action is read-only or affects only the systems, data, and people the user placed in scope, or when it is a normal implementation step within the requested workflow that causes no significant external state change (e.g. tool calls to external applications).
13047
+
13048
+ A terminal condition such as \u201Cfinish,\u201D \u201Cbabysit,\u201D or \u201Cdo not stop\u201D requires persistence toward the outcome, but does not broaden the set of authorized actions. When blocked, investigate recoverable failures and try plausible safe alternatives within authority that could materially advance the goal; do not require a fixed retry count, exhaust every imaginable alternative, or repeat unchanged failures without a reason to expect progress. Tool approvals remain human-only.
12779
13049
 
12780
13050
  Make informed assumptions that keep the work moving within the user's intent and scope. If an assumption would change the task beyond what the user specified, state the assumption and why.
12781
13051
 
12782
13052
  When the user asks a clarifying question or objects, answer with concrete evidence and reasoning rather than unsubstantiated deference, so tradeoffs are easy to evaluate.
12783
13053
 
12784
- If completion requires new authority, external coordination, or a meaningful expansion beyond the user\u2019s implied intent and task scope (e.g. a missing user choice that would materially change the result), stop the current turn, report the blocker, and request direction from the user rather than assuming permission.
12785
-
12786
- Decide the design before building it. First check whether OpenGeni already provides the capability natively (for example, a Site reaches the model and workspace tools through the host bridge and needs no server of its own). If a native path fits, use it. Follow the project's established architecture and choices the user has already authorized or delegated; the user need not name each host, provider, or credential. Ask before making a new external commitment or materially departing from the established architecture beyond the authorized scope: name the candidate designs, and do not start parallel work that assumes the unresolved choice. The absence of a native path alone does not require a question; continue with routine implementation choices within scope.
12787
-
12788
- # Destructive Actions
13054
+ If completion requires new authority, external coordination, or a meaningful expansion beyond the user\u2019s implied intent and task scope (e.g. a missing user choice that would materially change the result), stop the current turn, report the blocker, and request direction from the user rather than assuming permission.`,
13055
+ sentences(
13056
+ "Decide the design before building it.",
13057
+ nativeCheck,
13058
+ "If a native path fits, use it.",
13059
+ "Follow the project's established architecture and choices the user has already authorized or delegated; the user need not name each host, provider, or credential.",
13060
+ "Ask before making a new external commitment or materially departing from the established architecture beyond the authorized scope: name the candidate designs, and do not start parallel work that assumes the unresolved choice.",
13061
+ "The absence of a native path alone does not require a question; continue with routine implementation choices within scope."
13062
+ )
13063
+ );
13064
+ }
13065
+ var DESTRUCTIVE_ACTIONS = `# Destructive Actions
12789
13066
 
12790
13067
  Be cautious with commands or API calls that can delete, overwrite, or otherwise make data difficult to recover.
12791
13068
 
@@ -12793,50 +13070,444 @@ Before taking a destructive action:
12793
13070
 
12794
13071
  - Make sure the action is clearly within the user's request.
12795
13072
  - Resolve the exact targets with read-only checks when necessary.
12796
- - Do not use \`$HOME\`, \`~\`, \`/\`, a workspace root, or another broad directory as the target of a recursive or destructive command.
12797
- - When creating temporary directories, prefer using \`mktemp -d\`, or \`New-Item\` in Powershell.
12798
- - When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.
12799
13073
  - Prefer recoverable operations, such as moving files to trash, when practical.
12800
13074
  - If the target or scope is unclear, stop and ask the user.
12801
13075
 
12802
- Never run commands such as \`rm -rf $HOME\` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.
13076
+ After deleting anything material, briefly tell the user what was removed and whether it can be recovered.`;
13077
+ function renderBaseBehavior(context) {
13078
+ return blocks(
13079
+ INSTRUCTION_PRECEDENCE,
13080
+ PERSONALITY,
13081
+ workingWithTheUser(context),
13082
+ RULES_FOR_WORK,
13083
+ autonomy(context),
13084
+ DESTRUCTIVE_ACTIONS
13085
+ );
13086
+ }
12803
13087
 
12804
- After deleting anything material, briefly tell the user what was removed and whether it can be recovered.
13088
+ // src/agent-instructions/runtime-mechanics.ts
13089
+ function newMessages(context) {
13090
+ const { goals, subagents } = context.capabilities;
13091
+ const inFlightExamples = subagents ? "(a child, a command, or a timed recheck)" : "(a command or a timed recheck)";
13092
+ return sentences(
13093
+ "The user may send a new message while you are still working.",
13094
+ "Decide whether it replaces the active request or adds to it.",
13095
+ "If it replaces it, drop the previous work and focus on the new request.",
13096
+ "If it adds to unfinished work, handle both together.",
13097
+ "If it only asks a question or for status, answer it without starting or resuming other work in that turn unless the user asks.",
13098
+ `If work you already started is still in flight ${inFlightExamples}, give the answer, then call \`wait_for_input\` when available so its result resumes you${goals ? ", even when a goal is active" : ""}.`,
13099
+ "If you were already waiting, reuse that reason and keep its deadline by setting the timeout to the time left rather than a fresh full timeout.",
13100
+ goals ? "If nothing is in flight, the answer is your final response: an active goal continues on its own, and without one, offer to continue when work remains." : "If nothing is in flight, the answer is your final response; offer to continue when work remains.",
13101
+ "Keep a status answer to one or two sentences about progress in the user's terms, without session, credential, or tool mechanics; name a blocker only when the user must act on it, and say what they need to do.",
13102
+ 'Treat "thanks", "nice", and similar replies as acknowledgement, not approval of a next step.'
13103
+ );
13104
+ }
13105
+ var WAITING = `If an existing wait's remaining time is below the tool's minimum or its deadline has passed, do not send an invalid timeout or round up and silently extend it. A question-only human/API turn that has not consumed immediate machine input may finish without replacing the retained wait; its deadline machinery remains authoritative. Otherwise, do not assume the old wait remains armed: register a valid wait if still needed and make any unavoidable deadline adjustment explicit.
12805
13106
 
12806
- # Using skills
13107
+ Outside a question or status turn, do not end with only a status reply and leave an immediate continuation to rediscover the same wait: either keep advancing substantive work in this turn or, when further progress genuinely depends on work already in flight or a meaningful timed recheck, call \`wait_for_input\` when available before ending. Do not use \`wait_for_input\` for work you can still advance or for a blocker that requires a human decision. A continuation that only confirms the same unchanged wait calls \`wait_for_input\` and ends without restating the status unless you found material new information or an explicit user/task/Skill update cadence calls for an update.
12807
13108
 
12808
- Skills are reusable instructions supplied dynamically for the current session. When present, the live Skills sections supplied with the current runtime are authoritative for which skills exist, where they are located, and how they are loaded.
13109
+ Avoid holding execution open with long sleeps or repeated blocking waits when an out-of-turn wait is available. Respect each tool's actual execution-wait limits; those limits do not cap \`wait_for_input\`, which may span hours or days within its own limits.
12809
13110
 
12810
- - Use a skill when the user names it or the task clearly needs what it provides, not because of keyword matches or because it is available. Use the smallest set that covers the request.
12811
- - Read a selected skill before acting, once: while its text is still in your context, do not read it again. Read its referenced files only when needed, resolve them relative to its own directory, and reuse its scripts, assets, and templates when provided.
12812
- - Do not announce Skill reads. If a skill materially changes an action or pauses the work, name it and say why.
12813
- - The user's instructions take precedence over skill guidance.
12814
- - If a named skill is unavailable or cannot be read, say so briefly and continue with the best fallback.
13111
+ No short execution wait or preliminary status recheck is required before \`wait_for_input\`. Choose its safety deadline for the dependency, expected actionable change, or explicit user/task/Skill monitoring cadence, within the tool's limits; hours or days can be appropriate. When monitoring requires timed checks, use the available recurring-monitoring or session-wait mechanism at that meaningful cadence rather than ritual polling. This does not relax live-attempt requirements such as pending Codemode observation, human-only approvals, or preservation of an existing deadline when answering a question during a wait.`;
13112
+ var COMPACTION = `When earlier context is compacted, continue from the supplied summary and durable session history. Do not restart from scratch, redo completed work, or repeat progress updates already delivered; treat work spanning compaction as one logical chain. Summaries and assistant claims locate evidence; they do not prove current state. Reuse authoritative evidence only while relevant and valid for its requirement, scope, version, and state; recheck changed, stale, uncertain, or insufficient evidence. Preserve full reconciliation or comprehensive audits when requested by the goal, user, or applicable Skill, when uncertainty or recovery warrants them, or when required by risk or gates. Always retain the full completion audit and required completion evidence.`;
13113
+ var BACKGROUND_COMMANDS = `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.
12815
13114
 
12816
- # Integration setup
13115
+ Command completion alone resumes you only while you have an explicit \`wait_for_input\` registered. For ordinary background commands, register that session-level wait before ending your turn. Exception: pending Codemode calls need the current live attempt; keep observing them with \`command_wait\`/\`command_read\` instead of ending the turn. If you finish normally, command results remain retained and can accompany later input, but do not start another turn by themselves. No per-command dismissal is required.`;
13116
+ function renderRuntimeMechanics(context) {
13117
+ return blocks(
13118
+ "# Runtime mechanics",
13119
+ "## New messages while you work",
13120
+ newMessages(context),
13121
+ "## Waiting",
13122
+ WAITING,
13123
+ "## Compaction",
13124
+ COMPACTION,
13125
+ "## Background commands",
13126
+ BACKGROUND_COMMANDS
13127
+ );
13128
+ }
12817
13129
 
12818
- Use available integration tools directly. If access is missing, check \`variable_set_list\` (see Session coordination), then search \`capability_catalog_search\`. For a suitable match with \`setup.nextAction\`, call \`capability_authorization_request\` with its ID and a task-specific rationale. If no match exists and the task needs a remote MCP whose exact HTTPS URL the user supplied or reliable documentation establishes, call \`custom_mcp_setup_request\` with its name, URL, and rationale. Never invent URLs or request credentials in chat. Showing either card does not need integration-management permission and grants no access; the authenticated human must authorize setup. A card is for an integration required by the authorized design, including established or delegated choices. Resolve out-of-scope architecture choices before requesting setup. After setup, rediscover tools and verify access. If blocked or a setup tool is unavailable, explain the specific gap.
13130
+ // src/agent-instructions/modules/admin.ts
13131
+ var adminModule = {
13132
+ id: "admin",
13133
+ applies: (context) => context.capabilities.workspaceAdmin,
13134
+ render: (context) => blocks(
13135
+ "# Integration setup",
13136
+ sentences(
13137
+ "Use available integration tools directly.",
13138
+ context.capabilities.subagents ? "If access is missing, check `variable_set_list` (see Session coordination), then search `capability_catalog_search`." : "If access is missing, check `variable_set_list`, then search `capability_catalog_search`.",
13139
+ "For a suitable match with `setup.nextAction`, call `capability_authorization_request` with its ID and a task-specific rationale.",
13140
+ "If no match exists and the task needs a remote MCP whose exact HTTPS URL the user supplied or reliable documentation establishes, call `custom_mcp_setup_request` with its name, URL, and rationale.",
13141
+ "Never invent URLs or request credentials in chat.",
13142
+ "Showing either card does not need integration-management permission and grants no access; the authenticated human must authorize setup.",
13143
+ "A card is for an integration required by the authorized design, including established or delegated choices.",
13144
+ "Resolve out-of-scope architecture choices before requesting setup.",
13145
+ "After setup, rediscover tools and verify access.",
13146
+ "If blocked or a setup tool is unavailable, explain the specific gap."
13147
+ )
13148
+ )
13149
+ };
12819
13150
 
12820
- # Session coordination
13151
+ // src/agent-instructions/modules/artifacts.ts
13152
+ var artifactsModule = {
13153
+ id: "artifacts",
13154
+ applies: (context) => context.capabilities.artifacts,
13155
+ render: (context) => {
13156
+ const opengeni = context.renderer === "opengeni";
13157
+ return blocks(
13158
+ "# Documents, files, and visuals",
13159
+ bullets(
13160
+ "Create a document Artifact only when the user asks for a document or file, or when the deliverable is large (multi-page) or clearly meant to be kept or shared. Read the opengeni-documents Skill and create the native document artifact before authoring it; do not write a sandbox Markdown/DOCX report first or treat publishing a file as native document creation. Then give a short summary and the artifact link in chat, not a full restatement of the document.",
13161
+ context.capabilities.goals && "If the session has a goal, declare each document deliverable through the goal tools before authoring, including ones discovered after the goal was created. Inspect the relevant final artifact head after the last edit, supply its verified delivery evidence at goal completion, and give the user the artifact reference returned by the tools. A sandbox path, a raw file ID, or an assertion that a report exists is not completed report delivery.",
13162
+ "If artifact creation, inspection, access, or delivery tooling is unavailable or fails, report the concrete blocker and leave report delivery incomplete. Do not silently fall back to a sandbox link, invent an artifact reference, or claim success. Ordinary in-chat answers, brief progress updates, internal worker findings, source-code navigation, and explicitly requested local-file workflows do not become report deliverables merely because they contain Markdown or a file link."
13163
+ ),
13164
+ sentences(
13165
+ "Publish files you deliberately deliver so they are retained and discoverable in Artifacts; do not publish every temporary file.",
13166
+ "Reuse retained references for unchanged outputs.",
13167
+ opengeni && "Source-code navigation may still use workspace file links.",
13168
+ opengeni && "Inline HTML stays in chat unless explicitly saved as a Site.",
13169
+ "For building, publishing, or embedding a saved Site, read opengeni-sites when available.",
13170
+ "Sites and native documents keep their tool-returned canonical links.",
13171
+ "Never substitute a storage URL or a sandbox path for a published artifact reference."
13172
+ ),
13173
+ opengeni && blocks(
13174
+ "## Visuals in chat",
13175
+ "Use inline HTML when an interactive visualization materially helps the user; read the opengeni-visualize skill first. Use ordinary Markdown for simple explanations and tables.",
13176
+ "Display images with ![descriptive alt text](artifact:<artifactId>). Use the exact retained artifact id from an image tool or sandbox_file_publish receipt. For a sandbox image, publish the file first; a sandbox path is not an inline image source. Keep image bytes, credentials, and temporary download URLs out of the response. Ordinary public image URLs also work. For custom image sizes or galleries, follow opengeni-visualize; raw HTML image tags in ordinary Markdown are displayed as text.",
13177
+ "For published files, [Open file](artifact:<artifactId>) opens the retained file in Artifacts. ![Preview](artifact:<artifactId>) displays images, video, audio, or PDFs inline in the OpenGeni console, with an Artifact link for other formats. Replace <artifactId> with the exact artifact.artifactId from the publication receipt and use a descriptive label."
13178
+ )
13179
+ );
13180
+ }
13181
+ };
12821
13182
 
12822
- 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.
13183
+ // src/agent-instructions/modules/attachments.ts
13184
+ var attachmentsModule = {
13185
+ id: "attachments",
13186
+ applies: (context) => context.resources.attachments,
13187
+ render: () => blocks(
13188
+ "# Attached files",
13189
+ "File resources are mounted under .opengeni/files/<file-id>/ unless the session specifies another mount path. Attached files are mounted read-only; copy them before modifying."
13190
+ )
13191
+ };
12823
13192
 
12824
- 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.
13193
+ // src/agent-instructions/modules/environment.ts
13194
+ function rigInstructions(rig) {
13195
+ return [
13196
+ `This session uses sandbox environment "${rig.name}" (active version v${rig.version}) \u2014 a versioned definition of custom sandbox setup and health checks.`,
13197
+ "Your sandbox is an EPHEMERAL FORK of this environment. You may install tools here, but local changes do not update the environment definition or other sessions.",
13198
+ "To make a verified setup change available to future sessions using this environment, call rig_propose_change with the exact command that already worked here. Never assume an unverified change propagates.",
13199
+ "If tooling you expect is missing, consult rig_get to see the sandbox environment's current setup and checks before reinstalling."
13200
+ ];
13201
+ }
13202
+ function workspaceEnvironmentInstructions(environment) {
13203
+ const lines = [
13204
+ `A workspace environment named "${environment.name}" is attached to this session; its variables are exported in the sandbox shell environment.`
13205
+ ];
13206
+ const variableNames = (environment.variableNames ?? []).filter((name) => name.length > 0);
13207
+ if (variableNames.length > 0) {
13208
+ lines.push(`Exported environment variables: ${[...variableNames].sort().join(", ")}.`);
13209
+ }
13210
+ const description = environment.description?.trim();
13211
+ if (description) {
13212
+ lines.push(`Environment notes from the operator: ${description}`);
13213
+ }
13214
+ return lines;
13215
+ }
13216
+ var workspaceEnvironmentModule = {
13217
+ id: "workspace_environment",
13218
+ applies: (context) => context.resources.workspaceEnvironment !== void 0,
13219
+ render: (context) => blocks(
13220
+ "# Workspace environment",
13221
+ sentences(...workspaceEnvironmentInstructions(context.resources.workspaceEnvironment))
13222
+ )
13223
+ };
13224
+ var rigModule = {
13225
+ id: "rig",
13226
+ applies: (context) => context.resources.rig !== void 0,
13227
+ render: (context) => {
13228
+ const [identity2, fork, propose, consult] = rigInstructions(context.resources.rig);
13229
+ return blocks(
13230
+ "# Sandbox environment",
13231
+ sentences(
13232
+ identity2,
13233
+ fork,
13234
+ context.capabilities.workspaceAdmin && propose,
13235
+ context.capabilities.workspaceAdmin && consult
13236
+ )
13237
+ );
13238
+ }
13239
+ };
12825
13240
 
12826
- Command completion alone resumes you only while you have an explicit \`wait_for_input\` registered. For ordinary background commands, register that session-level wait before ending your turn. Exception: pending Codemode calls need the current live attempt; keep observing them with \`command_wait\`/\`command_read\` instead of ending the turn. If you finish normally, command results remain retained and can accompany later input, but do not start another turn by themselves. No per-command dismissal is required.
13241
+ // src/agent-instructions/modules/goals.ts
13242
+ var goalsModule = {
13243
+ id: "goals",
13244
+ applies: (context) => context.capabilities.goals,
13245
+ render: () => blocks(
13246
+ "# Goals",
13247
+ "If the session has a goal, you own it: keep working until you call opengeni__goal_complete with concrete evidence or opengeni__goal_pause with a rationale; revise it with opengeni__goal_update; create one with opengeni__goal_set when given a long-running objective. Resume a paused goal with opengeni__goal_resume when the user asks you to continue, regardless of who paused it, or when the blocker you paused for has cleared. A question alone is not such a request: answer it and leave the goal paused.",
13248
+ "Goal completion records short ledger proof, not the user-facing deliverable. After goal_complete succeeds, finish the same turn with the requested answer, or a concise summary and retained artifact link. Never use evidence as the final reply. A later child result after completion is context to integrate, not a reason to stay silent or restart the completed goal.",
13249
+ "Saying or verifying that the work is done does not complete the goal: call opengeni__goal_complete, and search for the goal tools first when they are not listed.",
13250
+ "A definitive missing permission or required human decision can justify an immediate goal pause with evidence and the change needed to resume. Work already in flight or a meaningful timed recheck calls for the available waiting mechanism, not a goal pause."
13251
+ )
13252
+ };
12827
13253
 
12828
- 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.
13254
+ // src/agent-instructions/modules/knowledge.ts
13255
+ var knowledgeModule = {
13256
+ id: "knowledge",
13257
+ applies: (context) => context.capabilities.knowledge,
13258
+ render: () => blocks(
13259
+ "# Knowledge and durable storage",
13260
+ 'Choose durable storage by purpose, including requests to "remember this" or keep something "for future sessions". Knowledge is retrieval-only information, not standing behavior. Use instruction_policy_get then instruction_policy_save for short always-on workspace rules, such as "Keep replies concise; expand when asked." Use Skills for reusable procedures and context-specific or personal behavioral preferences; make the Skill description state when it applies so the prompt index can guide skill_read. Do not save behavioral preferences as Knowledge by rephrasing them as facts like "the user prefers concise replies". Preserve the intended scope: do not turn a personal preference into a workspace-wide rule; use an authorized personal Skill when appropriate, or explain the unavailable scope. Split mixed requests into a short rule and detailed Skill steps without duplicating them in Knowledge.',
13261
+ "Before changing workspace instructions, read the current instruction and exact baseline, preserve unrelated rules, append new rules, and use only a localized exact anchored edit for updates or removals. Agents cannot replace the complete instruction; whole-policy rewrites belong in the manual workspace editor. Do not bypass a destination's Agent learning setting, review, scope, limits, or unavailable tools by saving to another destination. Report the actual destination and receipt: active, pending review, or not saved. Do not promise future behavior from a Knowledge save.",
13262
+ "Use knowledge_search and knowledge_get when retained information is relevant. For questions about what the workspace knows, ground the answer in authorized Knowledge and attached sources. Missing internal facts remain unknown; do not infer a person's role or cite unrelated public search results as evidence. Keep any relevant external research clearly separate from workspace records. Default retrieval returns published information. Before retaining or correcting anything, also search view=needs_review for existing pending entries and collections; read those with knowledge_get view=needs_review. Pending means unapproved: you may inspect and improve it, but do not present it as accepted knowledge or activate behavioral guidance from it. Reuse the existing entryId and current version instead of creating another proposal each run.",
13263
+ "Save durable facts, decisions, requirements, incidents, fixes and outcomes autonomously with knowledge_save only when they help a plausible future task. Do not retain routine approvals, acknowledgments, temporary task instructions, status chatter or raw screenshots merely because they occurred. Before saving, use knowledge_prepare_save when available to fetch the authorized collection map with descriptions and parent IDs plus related published and pending entries; otherwise search both views and browse collections. Skip unchanged duplicates, improve the existing entry when appropriate, and create a new entry only for distinct useful information. Read the current entry before correcting it and preserve uncertainty, conflicting evidence and existing relationships. When a user supplies or confirms a durable fact, use knowledge_retain_message to retain the actual message and cite its returned entryId/revisionId in the finding evidence. Preserve existing source evidence and relationships when correcting an entry; do not replace them with empty arrays merely because the user confirmed a new value. Explicit confirmation can supersede a conflicting pending proposal, but explain that outcome to the user. Preserve uncertainty and exact supporting evidence; the fact label is not a verification claim.",
13264
+ "Chat attachments retain their original files for the conversation without automatically publishing OCR or source text into Knowledge. Inspect an image visually in the current task; save only a useful supported observation, requirement or incident when warranted. Use knowledge_retain_file purpose=evidence only when a selected finding needs the original as supporting evidence, or purpose=reference when deliberately retaining a reusable source document. Supporting sources remain accessible through evidence links and explicit includeEvidence searches, but do not fill ordinary Knowledge discovery. An upload alone is not a reason to save Knowledge. A source entry contains retained original text; a finding states a useful conclusion and cites the exact source revision. Do not create both when they would simply repeat the same text.",
13265
+ "Reuse collections for customers, products, systems or subjects across sources, and link one entry to multiple collections instead of copying it. Technical incidents belong with the affected system and should include cause, fix and outcome when known. Reorganize references when useful; do not erase source evidence or revision history.",
13266
+ "Private tasks author personal Knowledge; shared tasks author workspace Knowledge. Automatic publishes immediately, Review first keeps a pending proposal without pausing your task, and Off prevents authoring while permitting retrieval. Never bypass review by making a new entry, switching tools, or asking for another approval. Reuse the same operationId and exact request after an uncertain save, including recovery. Use task_note_save for temporary coordination in this task tree. Conversation history is separate. Workspace instructions are concise standing rules; Skills are reusable procedures with their own Agent learning settings. Do not save the same content in multiple authorities."
13267
+ )
13268
+ };
12829
13269
 
12830
- Create a child worker only for a concrete, bounded subtask that can run independently and whose result has a clear integration point in the current request. Delegation has setup and coordination overhead: by default, answer directly when the work takes only a few steps, and send a related follow-up to a child you already spawned with \`session_send_message\` instead of spawning another. Explicit user requests and applicable Skill guidance for delegation, independent review, or fresh workers override that default within existing authority. Before spawning, decide what output you need and keep the parent's concurrent work disjoint. Do not duplicate a child's implementation; independent review or comparison may intentionally examine the same subject with a distinct deliverable. If no useful independent work remains and no such delegation is requested, continue in this session. A session cannot gain a Variable Set while it works, so when even a short step needs one from \`variable_set_list\` that this session lacks and the request calls for it, run that step in a child created with those \`variableSetIds\` instead of asking the user to attach it. Do not repurpose or direct an unrelated existing session unless the user explicitly asks. If no matching session tool is available on this turn, handle what you can in this session and report any required delegation that is unavailable instead of inventing an API.
13270
+ // src/agent-instructions/modules/machines.ts
13271
+ var connectedMachineModule = {
13272
+ id: "connected_machine",
13273
+ applies: (context) => context.resources.connectedMachine,
13274
+ render: (context) => blocks(
13275
+ "# Connected Machine",
13276
+ "This session runs on a Connected Machine, a computer its owner connected to this workspace. You work directly on its real filesystem, so treat existing files and processes as the owner's.",
13277
+ context.renderer === "opengeni" && bullets(
13278
+ "Connected Machine examples are [app.py](sandbox:/home/u/proj/app.py:12) on POSIX and [app.ts](<sandbox:C:/repo/app.ts:12>) on Windows.",
13279
+ "On a Connected Machine, absolute file links may point outside the working directory (including sibling worktrees and temporary files); use the real path on the selected machine."
13280
+ )
13281
+ )
13282
+ };
12831
13283
 
12832
- When supervising work, an accepted message, queued status, or changing timestamp is not proof of execution. Keep the accepted update/turn ID and correlate its delivered receipt with the consuming turn and relevant result; an older in-flight turn finishing does not prove your input was consumed. Use the receipt correlation described by the sending tool. Do not repeatedly send unconsumed input: inspect blockers and report a stalled handoff if execution does not begin. Preserve explicit human pauses and approvals.
13284
+ // src/agent-instructions/modules/renderer-markdown.ts
13285
+ var rendererMarkdownModule = {
13286
+ id: "renderer_markdown",
13287
+ applies: (context) => context.renderer === "markdown",
13288
+ render: (context) => blocks(
13289
+ "# Links and rendering",
13290
+ hasSandbox(context) ? "Your answer is shown as ordinary Markdown in a client that cannot open workspace file links or render inline HTML. Do not write `sandbox:` or `artifact:` links, inline HTML, or embedded images of workspace files. Mention a workspace file by its path in backticks, and link only to web URLs the user can open, such as a canonical link a tool returns." : "Your answer is shown as ordinary Markdown in a client that cannot render inline HTML. Do not write `sandbox:` or `artifact:` links or inline HTML, and link only to web URLs the user can open, such as a canonical link a tool returns."
13291
+ )
13292
+ };
12833
13293
 
12834
- After spawning, keep each child id and event cursor. Before committing, publishing, completing a goal, or giving a final answer that depends on a child, consume and integrate that child's completed result. When a child needs minutes and nothing else can advance meanwhile, call \`wait_for_input\` right after spawning instead of alternating \`session_wait\` and \`session_get\`: the child's terminal result wakes you and carries its final answer in \`payload.finalAnswer\`. Use that answer directly; read the child's results with \`session_events\` only when \`finalAnswer\` is absent or truncated (\`finalAnswer.nextAction\` reads the complete answer) or when you need detail it lacks. To join a short child inside this turn, use \`session_wait\` with \`waitFor: "completion"\`; a later terminal result repeating an answer you already integrated needs no reread. A \`goal.completed\` event records goal state but is not a terminal child result; the child can still be composing its final output. Do not present delegated work as incorporated until you have consumed the completed result. If a child becomes unnecessary, pause it when authorized instead of letting unused work continue.
13294
+ // src/agent-instructions/modules/repositories.ts
13295
+ var repositoriesModule = {
13296
+ id: "repositories",
13297
+ applies: (context) => context.resources.repositories || context.resources.gitCredentials || context.resources.connectedMachine,
13298
+ render: (context) => blocks(
13299
+ "# Repositories and Git",
13300
+ sentences(
13301
+ context.resources.repositories && "Repository resources are mounted under repos/<host>/<owner>/<repo> unless the session specifies another collision-free mount path.",
13302
+ context.resources.managedSandbox && "Provider CLIs such as gh, glab, and az may be pre-authenticated by the host through brokered git credentials or a sandbox preparation profile; try them before asking for credentials.",
13303
+ "When the Git repository you change has a remote and git provider credentials are available, work on a focused branch and open a pull request.",
13304
+ "Otherwise leave changes in the working tree and do not create or mention branches, commits, or pull requests unless the user asks; if the repository has a remote, say the changes are not pushed, and if the user asks for something you cannot make, say what blocks it."
13305
+ ),
13306
+ "You may find yourself working in a dirty worktree. Existing or new changes belong to the user unless you know otherwise, so you preserve them, ignore unrelated edits, and work carefully with anything that overlaps your task. If you cannot work around them you escalate to the user.",
13307
+ "Never use destructive commands like `git reset --hard` or `git checkout --` unless the user has clearly asked for that operation. If the request is ambiguous, ask for approval first. You prefer non-interactive git commands."
13308
+ )
13309
+ };
12835
13310
 
12836
- For a short wait on a child or peer session inside the current turn, call \`session_wait\` with its session id and your last seen sequence instead of sleeping and polling; use \`command_wait\` for one short provider-neutral wait on a background command. Both time out after at most 50 seconds. Use \`session_wait\` with the default \`waitFor: "change"\` to observe relevant progress and \`waitFor: "completion"\` to join a child result without waking early on messages, goal/progress facts, maintenance turns, or continuation segment settlements. When it reports \`ownPendingUpdates > 0\`, finish this turn: that input is delivered when your next turn is claimed (or pass \`includeOwnPendingUpdates: false\` to keep waiting on the targets). Do not immediately repeat a timed-out short wait without new evidence; an unchanged \`session_get\` snapshot between waits is not new evidence. Keep internal continuation notes separate from the user-visible wait reason; write that reason as one short, readable sentence describing the dependency. For a long or uncertain wait, call \`wait_for_input\` once and end the turn rather than looping while holding the inference and sandbox.
13311
+ // src/agent-instructions/modules/sandbox.ts
13312
+ function workspacePathRule(context) {
13313
+ const { managedSandbox, connectedMachine } = context.resources;
13314
+ if (managedSandbox && connectedMachine) {
13315
+ return "Use the active workspace path exactly as exposed to you. Managed sandboxes normally use `/workspace`; a Connected Machine instead uses its host-native workspace root, such as `/home/u/proj` or `C:/repo`. Both are valid inside a `sandbox:` link when they are the active workspace.";
13316
+ }
13317
+ return connectedMachine ? "Use the active workspace path exactly as exposed to you. A Connected Machine uses its host-native workspace root, such as `/home/u/proj` or `C:/repo`, and that root is valid inside a `sandbox:` link." : "Use the active workspace path exactly as exposed to you. Managed sandboxes normally use `/workspace`.";
13318
+ }
13319
+ function fileLinks(context) {
13320
+ if (context.renderer !== "opengeni") return null;
13321
+ return blocks(
13322
+ "## File links",
13323
+ "When referencing a real local source file or an explicitly requested local file, prefer a clickable markdown link.",
13324
+ bullets(
13325
+ "Clickable file links should look like [app.py](sandbox:/workspace/app.py:12): plain label, sandbox:/workspace/... target, with optional line number after the path.",
13326
+ "If a file path has spaces, wrap the target in angle brackets: [My Component.ts](<sandbox:/workspace/My Project/My Component.ts:3>).",
13327
+ workspacePathRule(context),
13328
+ context.resources.managedSandbox && "In managed sandboxes, never link directly to `/tmp` or any file outside the current workspace. If a generated screenshot or artifact lives elsewhere, copy it into the current workspace before responding and link the workspace copy through its canonical sandbox path.",
13329
+ "Do not wrap markdown links in backticks, or put backticks inside the label or target. This confuses the markdown renderer.",
13330
+ "Do not use URIs like file://, vscode://, or https:// for local file links, and do not invent or translate the active workspace root.",
13331
+ "Do not provide ranges of lines.",
13332
+ "Avoid repeating the same filename multiple times when one grouping is clearer."
13333
+ )
13334
+ );
13335
+ }
13336
+ var sandboxModule = {
13337
+ id: "sandbox",
13338
+ applies: hasSandbox,
13339
+ render: (context) => blocks(
13340
+ "# Working in the sandbox",
13341
+ "When a task needs files or commands, work inside the sandbox workspace with the filesystem and shell tools.",
13342
+ bullets(
13343
+ "Search text and files with `rg` or `rg --files` first; if `rg` is unavailable, use the next best tool.",
13344
+ "Do not chain shell commands with separators like `echo \"====\";` or `printf '---'`; they make the output noisy for the user.",
13345
+ "Exercise caution when escaping text for exec_command calls - backticks and `$()` passed to shell command input will still execute. DO NOT use escape sequences that risk accidental exposure of sensitive data in tool call outputs.",
13346
+ "When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME` or `$home`. Instead, use a task-specific variable name."
13347
+ ),
13348
+ "## File editing constraints",
13349
+ "Use `apply_patch` for local file edits. Do not create or edit files with `cat` or other shell write tricks. Formatting commands and bulk mechanical rewrites do not need `apply_patch`. Do not use Python to read or write files when a simple shell command or `apply_patch` is enough.",
13350
+ "## Destructive commands",
13351
+ bullets(
13352
+ "Do not use `$HOME`, `~`, `/`, a workspace root, or another broad directory as the target of a recursive or destructive command.",
13353
+ "When creating temporary directories, prefer using `mktemp -d`, or `New-Item` in Powershell.",
13354
+ "When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths."
13355
+ ),
13356
+ "Never run commands such as `rm -rf $HOME` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.",
13357
+ fileLinks(context)
13358
+ )
13359
+ };
12837
13360
 
12838
- No short execution wait or preliminary status recheck is required before \`wait_for_input\`. Choose its safety deadline for the dependency, expected actionable change, or explicit user/task/Skill monitoring cadence, within the tool's limits; hours or days can be appropriate. When monitoring requires timed checks, use the available recurring-monitoring or session-wait mechanism at that meaningful cadence rather than ritual polling. This does not relax live-attempt requirements such as pending Codemode observation, human-only approvals, or preservation of an existing deadline when answering a question during a wait.
12839
- `;
13361
+ // src/agent-instructions/modules/skills.ts
13362
+ var skillsModule = {
13363
+ id: "skills",
13364
+ applies: (context) => context.capabilities.skills !== false,
13365
+ render: () => blocks(
13366
+ "# Using skills",
13367
+ "Skills are reusable instructions supplied dynamically for the current session. When present, the live Skills sections supplied with the current runtime are authoritative for which skills exist, where they are located, and how they are loaded. Installed and selected Skills appear in the session Skill index; follow its reading instructions and any role-specific guidance. Follow the user's task and the applicable Skill instructions for the current role.",
13368
+ bullets(
13369
+ "Use a skill when the user names it or the task clearly needs what it provides, not because of keyword matches or because it is available. Use the smallest set that covers the request.",
13370
+ "Read a selected skill before acting, once: while its text is still in your context, do not read it again. Read its referenced files only when needed, resolve them relative to its own directory, and reuse its scripts, assets, and templates when provided.",
13371
+ "Do not announce Skill reads. If a skill materially changes an action or pauses the work, name it and say why.",
13372
+ "The user's instructions take precedence over skill guidance.",
13373
+ "If a named skill is unavailable or cannot be read, say so briefly and continue with the best fallback."
13374
+ )
13375
+ )
13376
+ };
13377
+
13378
+ // src/agent-instructions/modules/subagents.ts
13379
+ var subagentsModule = {
13380
+ id: "subagents",
13381
+ applies: (context) => context.capabilities.subagents,
13382
+ render: (context) => {
13383
+ const { goals, workspaceAdmin } = context.capabilities;
13384
+ return blocks(
13385
+ "# Session coordination",
13386
+ "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.",
13387
+ "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.",
13388
+ sentences(
13389
+ "Create a child worker only for a concrete, bounded subtask that can run independently and whose result has a clear integration point in the current request.",
13390
+ "Delegation has setup and coordination overhead: by default, answer directly when the work takes only a few steps, and send a related follow-up to a child you already spawned with `session_send_message` instead of spawning another.",
13391
+ "Explicit user requests and applicable Skill guidance for delegation, independent review, or fresh workers override that default within existing authority.",
13392
+ "Before spawning, decide what output you need and keep the parent's concurrent work disjoint.",
13393
+ "Do not duplicate a child's implementation; independent review or comparison may intentionally examine the same subject with a distinct deliverable.",
13394
+ "If no useful independent work remains and no such delegation is requested, continue in this session.",
13395
+ workspaceAdmin && "A session cannot gain a Variable Set while it works, so when even a short step needs one from `variable_set_list` that this session lacks and the request calls for it, run that step in a child created with those `variableSetIds` instead of asking the user to attach it.",
13396
+ "Do not repurpose or direct an unrelated existing session unless the user explicitly asks.",
13397
+ "If no matching session tool is available on this turn, handle what you can in this session and report any required delegation that is unavailable instead of inventing an API."
13398
+ ),
13399
+ "When supervising work, an accepted message, queued status, or changing timestamp is not proof of execution. Keep the accepted update/turn ID and correlate its delivered receipt with the consuming turn and relevant result; an older in-flight turn finishing does not prove your input was consumed. Use the receipt correlation described by the sending tool. Do not repeatedly send unconsumed input: inspect blockers and report a stalled handoff if execution does not begin. Preserve explicit human pauses and approvals.",
13400
+ sentences(
13401
+ "After spawning, keep each child id and event cursor.",
13402
+ goals ? "Before committing, publishing, completing a goal, or giving a final answer that depends on a child, consume and integrate that child's completed result." : "Before committing, publishing, or giving a final answer that depends on a child, consume and integrate that child's completed result.",
13403
+ "When a child needs minutes and nothing else can advance meanwhile, call `wait_for_input` right after spawning instead of alternating `session_wait` and `session_get`: the child's terminal result wakes you and carries its final answer in `payload.finalAnswer`.",
13404
+ "Use that answer directly; read the child's results with `session_events` only when `finalAnswer` is absent or truncated (`finalAnswer.nextAction` reads the complete answer) or when you need detail it lacks.",
13405
+ 'To join a short child inside this turn, use `session_wait` with `waitFor: "completion"`; a later terminal result repeating an answer you already integrated needs no reread.',
13406
+ goals && "A `goal.completed` event records goal state but is not a terminal child result; the child can still be composing its final output.",
13407
+ "Do not present delegated work as incorporated until you have consumed the completed result.",
13408
+ "If a child becomes unnecessary, pause it when authorized instead of letting unused work continue."
13409
+ ),
13410
+ 'For a short wait on a child or peer session inside the current turn, call `session_wait` with its session id and your last seen sequence instead of sleeping and polling; use `command_wait` for one short provider-neutral wait on a background command. Both time out after at most 50 seconds. Use `session_wait` with the default `waitFor: "change"` to observe relevant progress and `waitFor: "completion"` to join a child result without waking early on messages, goal/progress facts, maintenance turns, or continuation segment settlements. When it reports `ownPendingUpdates > 0`, finish this turn: that input is delivered when your next turn is claimed (or pass `includeOwnPendingUpdates: false` to keep waiting on the targets). Do not immediately repeat a timed-out short wait without new evidence; an unchanged `session_get` snapshot between waits is not new evidence. Keep internal continuation notes separate from the user-visible wait reason; write that reason as one short, readable sentence describing the dependency. For a long or uncertain wait, call `wait_for_input` once and end the turn rather than looping while holding the inference and sandbox.'
13411
+ );
13412
+ }
13413
+ };
13414
+
13415
+ // src/agent-instructions/compose.ts
13416
+ var AGENT_PROMPT_MODULES = [
13417
+ rendererMarkdownModule,
13418
+ sandboxModule,
13419
+ connectedMachineModule,
13420
+ repositoriesModule,
13421
+ workspaceEnvironmentModule,
13422
+ rigModule,
13423
+ artifactsModule,
13424
+ goalsModule,
13425
+ subagentsModule,
13426
+ knowledgeModule,
13427
+ skillsModule,
13428
+ adminModule,
13429
+ attachmentsModule
13430
+ ];
13431
+ var MODULAR_LAYER_SEPARATOR = "\n\n";
13432
+ var SESSION_INSTRUCTIONS_PREAMBLE = "# Session instructions\n\nThese instructions were set for this session. Follow them over the default behavior above, such as tone, length, and format.\n\n";
13433
+ function composeOperationalContract(context) {
13434
+ const sections = [
13435
+ { id: "base_behavior", text: renderBaseBehavior(context) },
13436
+ { id: "runtime_mechanics", text: renderRuntimeMechanics(context) }
13437
+ ];
13438
+ for (const module of AGENT_PROMPT_MODULES) {
13439
+ if (!module.applies(context)) continue;
13440
+ const text2 = module.render(context).trim();
13441
+ if (text2) sections.push({ id: module.id, text: text2 });
13442
+ }
13443
+ return {
13444
+ content: sections.map((section) => section.text).join(MODULAR_LAYER_SEPARATOR),
13445
+ modules: sections.map((section) => ({ id: section.id, chars: section.text.length }))
13446
+ };
13447
+ }
13448
+ function composeModularAgentInstructions(input) {
13449
+ const contract = composeOperationalContract({
13450
+ capabilities: input.capabilities,
13451
+ renderer: input.renderer,
13452
+ resources: input.resources
13453
+ });
13454
+ const layers = [
13455
+ { id: "identity", title: "Identity", content: input.identity.trim(), joinBefore: "" },
13456
+ {
13457
+ id: "operational_contract",
13458
+ title: "Operational contract",
13459
+ content: contract.content,
13460
+ modules: contract.modules,
13461
+ joinBefore: MODULAR_LAYER_SEPARATOR
13462
+ }
13463
+ ];
13464
+ const push = (id, title, content) => {
13465
+ const trimmed = content?.trim();
13466
+ if (!trimmed) return;
13467
+ layers.push({ id, title, content: trimmed, joinBefore: MODULAR_LAYER_SEPARATOR });
13468
+ };
13469
+ push("codemode", "Codemode", input.codemode);
13470
+ push("code_search", "Code search", input.codeSearch);
13471
+ push("git_bindings", "Git credential bindings", input.gitBindings);
13472
+ push("skill_catalog", "Skills", input.skillCatalog);
13473
+ push("workspace_governance", "Workspace governance", input.workspaceGovernance);
13474
+ push("workspace_memory", "Workspace memory", input.workspaceMemory);
13475
+ const session = input.sessionInstructions?.trim();
13476
+ if (session) {
13477
+ push(
13478
+ "session_instructions",
13479
+ "Session instructions",
13480
+ `${SESSION_INSTRUCTIONS_PREAMBLE}${session}`
13481
+ );
13482
+ }
13483
+ return {
13484
+ layers,
13485
+ composed: layers.map((layer) => `${layer.joinBefore}${layer.content}`).join("")
13486
+ };
13487
+ }
13488
+
13489
+ // src/agent-instructions/identity.ts
13490
+ import { AGENT_INSTRUCTIONS_CORE_PLACEHOLDER, DEFAULT_AGENT_INSTRUCTIONS } from "@opengeni/config";
13491
+ var DEFAULT_AGENT_IDENTITY = [
13492
+ "You are an OpenGeni workspace agent: a general assistant for questions, writing, research, analysis, and technical work.",
13493
+ "You and the user share one workspace, and your job is to collaborate with them until their goal is genuinely handled.",
13494
+ "You are a curious, thoughtful collaborator and a clear communicator."
13495
+ ].join(" ");
13496
+ function identityFromLegacyTemplate(template) {
13497
+ const identity2 = template?.split(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER).join("").trim();
13498
+ return identity2 ? identity2 : null;
13499
+ }
13500
+ function resolveAgentIdentity(input) {
13501
+ const session = input.sessionIdentity?.trim();
13502
+ if (session) return session;
13503
+ const workspace = identityFromLegacyTemplate(input.workspaceIdentity);
13504
+ if (workspace) return workspace;
13505
+ if (input.deploymentTemplate && input.deploymentTemplate !== DEFAULT_AGENT_INSTRUCTIONS) {
13506
+ const deployment = identityFromLegacyTemplate(input.deploymentTemplate);
13507
+ if (deployment) return deployment;
13508
+ }
13509
+ return DEFAULT_AGENT_IDENTITY;
13510
+ }
12840
13511
 
12841
13512
  // src/input-wait-yield.ts
12842
13513
  var InputWaitYield = class {
@@ -12940,6 +13611,12 @@ var InputWaitYield = class {
12940
13611
  this.closeAdmission();
12941
13612
  await this.drain(this.scope, signal);
12942
13613
  }
13614
+ /** A settled stream may need one final-reply handoff before attempt closure.
13615
+ * Drain already-admitted receipts without reopening that stream's admission.
13616
+ */
13617
+ async drainForHandoff(signal = this.scope.signal) {
13618
+ await this.drain(this.scope, signal);
13619
+ }
12943
13620
  endStream(scope) {
12944
13621
  scope.phase = "settled";
12945
13622
  scope.ended = true;
@@ -13098,6 +13775,7 @@ function withRetainableSessionImageOutputHook(tools, hook) {
13098
13775
 
13099
13776
  // src/model-provider-routing.ts
13100
13777
  import { configuredProviders, resolveModelProvider } from "@opengeni/config";
13778
+ import { APIError as APIError2 } from "openai";
13101
13779
  import { CODEX_MODEL_ID_PREFIX } from "@opengeni/codex";
13102
13780
  import { XAI_SUBSCRIPTION_MODEL_ID_PREFIX } from "@opengeni/xai-subscription";
13103
13781
 
@@ -13161,6 +13839,99 @@ var AppendOnlyOpenAIResponsesModel = class extends OpenAIResponsesModel {
13161
13839
  }
13162
13840
  };
13163
13841
 
13842
+ // src/responses-terminal-error.ts
13843
+ var DIAGNOSTIC_MAX_BYTES = 4 * 1024;
13844
+ var FIELD_MAX_BYTES = 256;
13845
+ var TRUNCATION_MARKER = "\u2026 [truncated]";
13846
+ function boundedField(value, maxBytes) {
13847
+ if (typeof value !== "string") return void 0;
13848
+ const bytes = new TextEncoder().encode(value);
13849
+ if (bytes.byteLength <= maxBytes) return value;
13850
+ let end = maxBytes - new TextEncoder().encode(TRUNCATION_MARKER).byteLength;
13851
+ while (end > 0 && (bytes[end] & 192) === 128) end -= 1;
13852
+ return `${new TextDecoder().decode(bytes.subarray(0, end))}${TRUNCATION_MARKER}`;
13853
+ }
13854
+ function record(value) {
13855
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
13856
+ }
13857
+ var SAFETY_CODES = /* @__PURE__ */ new Set([
13858
+ "content_policy_violation",
13859
+ "content_filter",
13860
+ "contentpolicyviolation",
13861
+ "contentfilter",
13862
+ "responsibleaipolicyviolation",
13863
+ "safety_violation",
13864
+ "bio_policy",
13865
+ "cyber_policy"
13866
+ ]);
13867
+ var REQUEST_CODES = /* @__PURE__ */ new Set([
13868
+ "invalid_request",
13869
+ "invalid_request_error",
13870
+ "invalidrequest",
13871
+ "invalid_prompt",
13872
+ "context_length_exceeded",
13873
+ "invalid_argument"
13874
+ ]);
13875
+ var RATE_CODES = /* @__PURE__ */ new Set([
13876
+ "rate_limit_exceeded",
13877
+ "rate_limit_error",
13878
+ "rate_limited",
13879
+ "ratelimitexceeded",
13880
+ "too_many_requests",
13881
+ "429"
13882
+ ]);
13883
+ var UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
13884
+ "server_error",
13885
+ "internal_server_error",
13886
+ "service_unavailable",
13887
+ "overloaded",
13888
+ "overloaded_error",
13889
+ "model_overloaded",
13890
+ "engine_overloaded",
13891
+ "server_overloaded"
13892
+ ]);
13893
+ var ResponsesStreamingTerminalError = class extends Error {
13894
+ constructor(eventType, source, headers) {
13895
+ super(`Responses request terminated unsuccessfully (${eventType}).`);
13896
+ this.eventType = eventType;
13897
+ this.name = "ResponsesStreamingTerminalError";
13898
+ const error = record(source);
13899
+ this.code = boundedField(error?.code, FIELD_MAX_BYTES);
13900
+ this.type = boundedField(error?.type, FIELD_MAX_BYTES);
13901
+ this.detail = boundedField(error?.message ?? source, DIAGNOSTIC_MAX_BYTES) ?? this.message;
13902
+ this.headers = new Headers();
13903
+ const retryAfter = boundedField(headers?.get("retry-after"), FIELD_MAX_BYTES);
13904
+ if (retryAfter !== void 0) this.headers.set("retry-after", retryAfter);
13905
+ const directSeconds = Number(error?.retry_after_seconds ?? error?.retryAfterSeconds);
13906
+ const header = this.headers.get("retry-after");
13907
+ const headerSeconds = header ? Number(header) : Number.NaN;
13908
+ const headerDate = header && !Number.isFinite(headerSeconds) ? Date.parse(header) : Number.NaN;
13909
+ const seconds = Number.isFinite(directSeconds) ? directSeconds : Number.isFinite(headerSeconds) ? headerSeconds : Number.isFinite(headerDate) ? Math.max(0, (headerDate - Date.now()) / 1e3) : Number.NaN;
13910
+ this.retryAfterSeconds = Number.isFinite(seconds) && seconds > 0 ? seconds : void 0;
13911
+ const codes = [this.code, this.type].map((value) => value?.toLowerCase());
13912
+ const matches = (allowed) => codes.some((value) => value !== void 0 && allowed.has(value));
13913
+ const recoveryCode = codes[0] || codes[1];
13914
+ this.category = matches(SAFETY_CODES) || /\bthis request was blocked by our safety systems\b/i.test(this.detail) ? "safety" : matches(REQUEST_CODES) ? "request" : recoveryCode !== void 0 && RATE_CODES.has(recoveryCode) ? "rate_limit" : recoveryCode !== void 0 && UNAVAILABLE_CODES.has(recoveryCode) ? "unavailable" : "unknown";
13915
+ }
13916
+ code;
13917
+ type;
13918
+ detail;
13919
+ headers;
13920
+ retryAfterSeconds;
13921
+ category;
13922
+ };
13923
+ function responsesStreamingTerminalError(event, headers) {
13924
+ const value = record(event);
13925
+ if (value?.type !== "response.failed" && value?.type !== "response.error" && value?.type !== "error") {
13926
+ return void 0;
13927
+ }
13928
+ return new ResponsesStreamingTerminalError(
13929
+ value.type,
13930
+ value.error ?? record(value.response)?.error ?? value,
13931
+ headers
13932
+ );
13933
+ }
13934
+
13164
13935
  // src/model-provider-routing.ts
13165
13936
  function isUnknownFinishReason(value) {
13166
13937
  return typeof value === "string" && value.trim().toLowerCase() === "unknown";
@@ -13203,6 +13974,58 @@ var OpenGeniResponsesModel = class extends AppendOnlyOpenAIResponsesModel {
13203
13974
  super(client, model);
13204
13975
  this.provider = provider;
13205
13976
  }
13977
+ async _fetchResponse(request, stream) {
13978
+ if (!stream || !this.ownsResponsesTerminalClassification()) {
13979
+ return await super._fetchResponse(request, stream);
13980
+ }
13981
+ const built = this._buildResponsesCreateRequest(request, true);
13982
+ const internal = request._internal;
13983
+ const pending = this._client.responses.create(
13984
+ built.requestData,
13985
+ {
13986
+ headers: built.sdkRequestHeaders,
13987
+ signal: built.signal,
13988
+ ...built.transportExtraQuery ? { query: built.transportExtraQuery } : {},
13989
+ ...internal?.runnerManagedRetry === true ? { maxRetries: 0 } : {}
13990
+ }
13991
+ );
13992
+ if (typeof pending.withResponse !== "function") {
13993
+ return this.classifiedResponseStream(await pending, new Headers(), null);
13994
+ }
13995
+ const receipt = await pending.withResponse();
13996
+ return this.classifiedResponseStream(
13997
+ receipt.data,
13998
+ receipt.response.headers,
13999
+ receipt.request_id
14000
+ );
14001
+ }
14002
+ async *classifiedResponseStream(stream, headers, requestId) {
14003
+ try {
14004
+ for await (const event of stream) {
14005
+ const failure = responsesStreamingTerminalError(event, headers);
14006
+ if (failure) throw failure;
14007
+ const eventType = event.type;
14008
+ if (requestId && (eventType === "response.completed" || eventType === "response.done") && "response" in event && event.response && !("_request_id" in event.response)) {
14009
+ try {
14010
+ Object.defineProperty(event.response, "_request_id", {
14011
+ value: requestId,
14012
+ enumerable: false
14013
+ });
14014
+ } catch {
14015
+ }
14016
+ }
14017
+ yield event;
14018
+ }
14019
+ } catch (error) {
14020
+ if (error instanceof APIError2 && error.status === void 0 && error.error) {
14021
+ throw new ResponsesStreamingTerminalError("response.error", error.error, headers);
14022
+ }
14023
+ throw error;
14024
+ }
14025
+ }
14026
+ ownsResponsesTerminalClassification() {
14027
+ return this.provider.kind !== "codex-subscription" && this.provider.kind !== "xai-subscription";
14028
+ }
13206
14029
  _buildResponsesCreateRequest(request, stream) {
13207
14030
  const startedAt = performance.now();
13208
14031
  let outcome = "completed";
@@ -13697,7 +14520,7 @@ import { existsSync, readdirSync } from "fs";
13697
14520
  // ../sdk/package.json
13698
14521
  var package_default = {
13699
14522
  name: "@opengeni/sdk",
13700
- version: "7.4.0",
14523
+ version: "7.5.0-canary.36927100590001",
13701
14524
  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.",
13702
14525
  license: "Apache-2.0",
13703
14526
  repository: {
@@ -13719,6 +14542,10 @@ var package_default = {
13719
14542
  module: "./src/index.ts",
13720
14543
  types: "./src/index.ts",
13721
14544
  exports: {
14545
+ "./allowance-refusal": {
14546
+ types: "./src/allowance-refusal.ts",
14547
+ default: "./src/allowance-refusal.ts"
14548
+ },
13722
14549
  ".": {
13723
14550
  types: "./src/index.ts",
13724
14551
  default: "./src/index.ts"
@@ -13747,10 +14574,18 @@ var package_default = {
13747
14574
  types: "./src/knowledge.ts",
13748
14575
  default: "./src/knowledge.ts"
13749
14576
  },
14577
+ "./usage-allowances": {
14578
+ types: "./src/usage-allowances.ts",
14579
+ default: "./src/usage-allowances.ts"
14580
+ },
13750
14581
  "./workspace-integrations": {
13751
14582
  types: "./src/workspace-integrations.ts",
13752
14583
  default: "./src/workspace-integrations.ts"
13753
14584
  },
14585
+ "./session-history-import": {
14586
+ types: "./src/session-history-import.ts",
14587
+ default: "./src/session-history-import.ts"
14588
+ },
13754
14589
  "./document-authority": {
13755
14590
  types: "./src/document-authority.ts",
13756
14591
  default: "./src/document-authority.ts"
@@ -13819,6 +14654,14 @@ var package_default = {
13819
14654
  types: "./src/chat/index.ts",
13820
14655
  default: "./src/chat/index.ts"
13821
14656
  },
14657
+ "./tenant-workspaces": {
14658
+ types: "./src/tenant-workspaces.ts",
14659
+ default: "./src/tenant-workspaces.ts"
14660
+ },
14661
+ "./session-proxy": {
14662
+ types: "./src/session-proxy.ts",
14663
+ default: "./src/session-proxy.ts"
14664
+ },
13822
14665
  "./next": {
13823
14666
  types: "./src/adapters/next.ts",
13824
14667
  default: "./src/adapters/next.ts"
@@ -13865,7 +14708,7 @@ var package_default = {
13865
14708
  // ../react/package.json
13866
14709
  var package_default2 = {
13867
14710
  name: "@opengeni/react",
13868
- version: "7.4.0",
14711
+ version: "7.5.0-canary.36927100590001",
13869
14712
  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.",
13870
14713
  license: "Apache-2.0",
13871
14714
  repository: {
@@ -13886,6 +14729,18 @@ var package_default2 = {
13886
14729
  module: "./src/index.ts",
13887
14730
  types: "./src/index.ts",
13888
14731
  exports: {
14732
+ "./terminal": {
14733
+ types: "./src/terminal.ts",
14734
+ default: "./src/terminal.ts"
14735
+ },
14736
+ "./editor": {
14737
+ types: "./src/editor.ts",
14738
+ default: "./src/editor.ts"
14739
+ },
14740
+ "./desktop": {
14741
+ types: "./src/desktop.ts",
14742
+ default: "./src/desktop.ts"
14743
+ },
13889
14744
  "./sites": {
13890
14745
  types: "./src/sites.ts",
13891
14746
  default: "./src/sites.ts"
@@ -13923,6 +14778,10 @@ var package_default2 = {
13923
14778
  types: "./src/accounts.tsx",
13924
14779
  default: "./src/accounts.tsx"
13925
14780
  },
14781
+ "./usage": {
14782
+ types: "./src/usage.ts",
14783
+ default: "./src/usage.ts"
14784
+ },
13926
14785
  "./machines": {
13927
14786
  types: "./src/machines.ts",
13928
14787
  default: "./src/machines.ts"
@@ -14122,7 +14981,7 @@ var package_default2 = {
14122
14981
  // ../codemode/package.json
14123
14982
  var package_default3 = {
14124
14983
  name: "@opengeni/codemode",
14125
- version: "0.6.5",
14984
+ version: "0.6.6-canary.36927100590001",
14126
14985
  description: "Attempt-frozen programmatic tool catalog and execution authority for OpenGeni.",
14127
14986
  license: "Apache-2.0",
14128
14987
  repository: {
@@ -14172,7 +15031,7 @@ var package_default3 = {
14172
15031
  // ../ogtool/package.json
14173
15032
  var package_default4 = {
14174
15033
  name: "@opengeni/ogtool",
14175
- version: "0.3.47",
15034
+ version: "0.3.48-canary.36927100590001",
14176
15035
  description: "Codemode CLI and typed client entrypoint for an OpenGeni execution attempt.",
14177
15036
  license: "Apache-2.0",
14178
15037
  repository: {
@@ -14556,13 +15415,13 @@ function contextTextEstimate(value) {
14556
15415
  const containsNonText = (part) => {
14557
15416
  if (Array.isArray(part)) return part.some(containsNonText);
14558
15417
  if (!part || typeof part !== "object") return false;
14559
- const record = part;
14560
- if (typeof record.encrypted_content === "string") return true;
15418
+ const record2 = part;
15419
+ if (typeof record2.encrypted_content === "string") return true;
14561
15420
  if (["input_image", "image_url", "input_audio", "input_file", "compaction"].includes(
14562
- String(record.type)
15421
+ String(record2.type)
14563
15422
  ))
14564
15423
  return true;
14565
- return Object.values(record).some(containsNonText);
15424
+ return Object.values(record2).some(containsNonText);
14566
15425
  };
14567
15426
  return containsNonText(value) ? null : estimateSerializedValueTokens(value);
14568
15427
  }
@@ -14587,15 +15446,23 @@ function buildProviderRequestSnapshot(input) {
14587
15446
  ...Array.isArray(value) ? { itemEstimatedTokens: value.map(contextTextEstimate) } : {}
14588
15447
  }));
14589
15448
  const instructionsTokens = parts.find((part) => part.key === "instructions")?.estimatedTokens ?? 0;
15449
+ const wireInstructions = typeof payload.instructions === "string" ? payload.instructions : null;
15450
+ const sectionLayers = wireInstructions && input.persistentLayers?.length ? splitCapturedInstructions({
15451
+ persistentLayers: input.persistentLayers,
15452
+ capturedInstructions: wireInstructions,
15453
+ genesisTitleDirective: input.genesisTitleDirective ?? ""
15454
+ }) : [];
15455
+ const layers = sectionLayers.some((layer) => layer.id !== "sent_system_instructions") ? sectionLayers : [];
14590
15456
  const toolsTokens = parts.find((part) => part.key === "tools")?.estimatedTokens ?? 0;
14591
15457
  return {
14592
15458
  version: MODEL_CONTEXT_SNAPSHOT_VERSION,
14593
15459
  source: "model_request",
14594
15460
  capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
14595
15461
  requestIndex: input.requestIndex,
14596
- // Wire body owns the contents. Legacy prefix fields are not reconstructed.
15462
+ // Wire body owns the contents. Legacy prefix fields are not reconstructed;
15463
+ // `layers` only names sections of the wire instructions.
14597
15464
  instructions: "",
14598
- layers: [],
15465
+ layers,
14599
15466
  tools: [],
14600
15467
  skills: [],
14601
15468
  tokens: {
@@ -14627,7 +15494,8 @@ var LAYER_TITLES = {
14627
15494
  sdk_capability_instructions: "SDK capability instructions",
14628
15495
  sandbox_preamble: "Sandbox runtime preamble",
14629
15496
  sandbox_filesystem: "Sandbox filesystem",
14630
- sent_system_instructions: "Sent system instructions"
15497
+ sent_system_instructions: "Sent system instructions",
15498
+ identity: "Identity"
14631
15499
  };
14632
15500
  function joinPersistentAgentInstructionLayers(layers) {
14633
15501
  if (layers.length === 0) return "";
@@ -14635,7 +15503,7 @@ function joinPersistentAgentInstructionLayers(layers) {
14635
15503
  for (let index = 1; index < layers.length; index += 1) {
14636
15504
  const previous = layers[index - 1];
14637
15505
  const current = layers[index];
14638
- const separator = previous.id === "operational_contract" && current.id === "persona_and_core" ? "\n\n" : " ";
15506
+ const separator = current.joinBefore ?? (previous.id === "operational_contract" && current.id === "persona_and_core" ? "\n\n" : " ");
14639
15507
  composed = `${composed}${separator}${current.content}`;
14640
15508
  }
14641
15509
  return composed;
@@ -14646,7 +15514,8 @@ function countedInstructionLayer(draft) {
14646
15514
  title: draft.title,
14647
15515
  content: draft.content,
14648
15516
  utf8Bytes: Buffer.byteLength(draft.content, "utf8"),
14649
- estimatedTokens: estimateTextTokens(draft.content)
15517
+ estimatedTokens: estimateTextTokens(draft.content),
15518
+ ...draft.modules ? { modules: draft.modules.map((module) => ({ ...module })) } : {}
14650
15519
  };
14651
15520
  }
14652
15521
  function splitCapturedInstructions(input) {
@@ -14840,14 +15709,14 @@ function countedTool(input) {
14840
15709
  };
14841
15710
  }
14842
15711
  function serializedToolToModelContextTool(tool2, visibility) {
14843
- const record = tool2;
14844
- const schema = record.parameters !== void 0 ? record.parameters : record.providerData !== void 0 ? record.providerData : void 0;
15712
+ const record2 = tool2;
15713
+ const schema = record2.parameters !== void 0 ? record2.parameters : record2.providerData !== void 0 ? record2.providerData : void 0;
14845
15714
  return countedTool({
14846
- name: typeof record.name === "string" && record.name.length > 0 ? record.name : tool2.type,
15715
+ name: typeof record2.name === "string" && record2.name.length > 0 ? record2.name : tool2.type,
14847
15716
  type: tool2.type,
14848
15717
  visibility,
14849
- ...typeof record.description === "string" ? { description: record.description } : {},
14850
- ...typeof record.namespace === "string" ? { namespace: record.namespace } : {},
15718
+ ...typeof record2.description === "string" ? { description: record2.description } : {},
15719
+ ...typeof record2.namespace === "string" ? { namespace: record2.namespace } : {},
14851
15720
  ...schema !== void 0 ? { schema } : {}
14852
15721
  });
14853
15722
  }
@@ -14898,15 +15767,15 @@ function skillsFromGovernanceLayer(content) {
14898
15767
  if (Array.isArray(parsed)) {
14899
15768
  for (const entry of parsed) {
14900
15769
  if (!entry || typeof entry !== "object") continue;
14901
- const record = entry;
14902
- const name = typeof record.title === "string" ? record.title : typeof record.stableKey === "string" ? record.stableKey : null;
14903
- const description = typeof record.description === "string" ? record.description : "";
15770
+ const record2 = entry;
15771
+ const name = typeof record2.title === "string" ? record2.title : typeof record2.stableKey === "string" ? record2.stableKey : null;
15772
+ const description = typeof record2.description === "string" ? record2.description : "";
14904
15773
  if (!name) continue;
14905
15774
  skills.push({
14906
15775
  kind: "preference_descriptor",
14907
15776
  name,
14908
15777
  description,
14909
- source: typeof record.scope === "string" ? record.scope : void 0
15778
+ source: typeof record2.scope === "string" ? record2.scope : void 0
14910
15779
  });
14911
15780
  }
14912
15781
  }
@@ -15497,14 +16366,14 @@ function modelInputItemType(value) {
15497
16366
  }
15498
16367
  function modelInputFileMediaType(value) {
15499
16368
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
15500
- const record = value;
16369
+ const record2 = value;
15501
16370
  for (const field of ["contentType", "content_type", "mediaType", "media_type", "mimeType"]) {
15502
- const candidate = record[field];
16371
+ const candidate = record2[field];
15503
16372
  if (typeof candidate === "string" && candidate.trim()) {
15504
16373
  return candidate.toLowerCase().split(";", 1)[0].trim();
15505
16374
  }
15506
16375
  }
15507
- const fileValue = record.file;
16376
+ const fileValue = record2.file;
15508
16377
  if (typeof fileValue === "string") {
15509
16378
  const match = /^data:([^;,]+)[;,]/i.exec(fileValue);
15510
16379
  if (match?.[1]) return match[1].toLowerCase();
@@ -15668,21 +16537,21 @@ var CLIENT_TOOL_CALL_ITEM_TYPES = /* @__PURE__ */ new Set([
15668
16537
  ]);
15669
16538
  function isClientToolWork(item) {
15670
16539
  if (!item || typeof item !== "object") return false;
15671
- const record = item;
15672
- if (record.type === "tool_search_call") {
15673
- return (record.execution ?? record.providerData?.execution) !== "server";
16540
+ const record2 = item;
16541
+ if (record2.type === "tool_search_call") {
16542
+ return (record2.execution ?? record2.providerData?.execution) !== "server";
15674
16543
  }
15675
- return CLIENT_TOOL_CALL_ITEM_TYPES.has(String(record.type));
16544
+ return CLIENT_TOOL_CALL_ITEM_TYPES.has(String(record2.type));
15676
16545
  }
15677
16546
  function isAssistantMessageItem(item) {
15678
16547
  if (!item || typeof item !== "object") return false;
15679
- const record = item;
15680
- return record.type === "message" && (record.role === void 0 || record.role === "assistant");
16548
+ const record2 = item;
16549
+ return record2.type === "message" && (record2.role === void 0 || record2.role === "assistant");
15681
16550
  }
15682
16551
  function declaredAssistantMessagePhase(item) {
15683
16552
  if (!item || typeof item !== "object") return void 0;
15684
- const record = item;
15685
- const phase = record.phase ?? record.providerData?.phase;
16553
+ const record2 = item;
16554
+ const phase = record2.phase ?? record2.providerData?.phase;
15686
16555
  return phase === "commentary" || phase === "final_answer" ? phase : void 0;
15687
16556
  }
15688
16557
  function providerMessageId(item) {
@@ -15830,38 +16699,38 @@ function imageDataByteLength(data) {
15830
16699
  return data.every((value) => typeof value === "number") ? data.length : null;
15831
16700
  }
15832
16701
  if (!data || typeof data !== "object") return null;
15833
- const record = data;
15834
- if (record.type === "Buffer" && Array.isArray(record.data)) {
15835
- return record.data.every((value) => typeof value === "number") ? record.data.length : null;
16702
+ const record2 = data;
16703
+ if (record2.type === "Buffer" && Array.isArray(record2.data)) {
16704
+ return record2.data.every((value) => typeof value === "number") ? record2.data.length : null;
15836
16705
  }
15837
- const keys = Object.keys(record);
15838
- return keys.length > 0 && keys.every((key) => /^\d+$/.test(key) && typeof record[key] === "number") ? keys.length : null;
16706
+ const keys = Object.keys(record2);
16707
+ return keys.length > 0 && keys.every((key) => /^\d+$/.test(key) && typeof record2[key] === "number") ? keys.length : null;
15839
16708
  }
15840
16709
  function toolOutputMediaPreview(value) {
15841
16710
  if (typeof value === "string") {
15842
16711
  return sessionEventMediaPreviewFromDataUrl(value);
15843
16712
  }
15844
16713
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
15845
- const record = value;
15846
- if (record.type === "input_image") {
15847
- const source = record.image ?? record.image_url ?? record.imageUrl;
16714
+ const record2 = value;
16715
+ if (record2.type === "input_image") {
16716
+ const source = record2.image ?? record2.image_url ?? record2.imageUrl;
15848
16717
  const url = typeof source === "string" ? source : source && typeof source === "object" ? source.url : null;
15849
16718
  if (typeof url !== "string" || url.length === 0) return null;
15850
16719
  return sessionEventMediaPreviewFromDataUrl(url) ?? sessionEventMediaPreview("image/*", null);
15851
16720
  }
15852
- if ((record.type === "image" || record.type === "audio") && typeof record.data === "string") {
15853
- const mediaType2 = typeof record.mimeType === "string" && record.mimeType.length > 0 ? record.mimeType : record.type === "audio" ? "audio/*" : "image/png";
15854
- return sessionEventMediaPreviewFromDataUrl(record.data) ?? sessionEventMediaPreview(mediaType2, base64DecodedByteLength(record.data));
16721
+ if ((record2.type === "image" || record2.type === "audio") && typeof record2.data === "string") {
16722
+ const mediaType2 = typeof record2.mimeType === "string" && record2.mimeType.length > 0 ? record2.mimeType : record2.type === "audio" ? "audio/*" : "image/png";
16723
+ return sessionEventMediaPreviewFromDataUrl(record2.data) ?? sessionEventMediaPreview(mediaType2, base64DecodedByteLength(record2.data));
15855
16724
  }
15856
- if (record.type === "resource" && record.resource && typeof record.resource === "object") {
15857
- const resource = record.resource;
16725
+ if (record2.type === "resource" && record2.resource && typeof record2.resource === "object") {
16726
+ const resource = record2.resource;
15858
16727
  if (typeof resource.blob === "string") {
15859
16728
  const mediaType2 = typeof resource.mimeType === "string" && resource.mimeType.length > 0 ? resource.mimeType : "application/octet-stream";
15860
16729
  return sessionEventMediaPreviewFromDataUrl(resource.blob) ?? sessionEventMediaPreview(mediaType2, base64DecodedByteLength(resource.blob));
15861
16730
  }
15862
16731
  }
15863
- if (record.type !== "image" || !record.image || typeof record.image !== "object") return null;
15864
- const image = record.image;
16732
+ if (record2.type !== "image" || !record2.image || typeof record2.image !== "object") return null;
16733
+ const image = record2.image;
15865
16734
  const mediaType = typeof image.mediaType === "string" && image.mediaType.length > 0 ? image.mediaType : "image/png";
15866
16735
  if (typeof image.url === "string" && image.url.length > 0) {
15867
16736
  return sessionEventMediaPreviewFromDataUrl(image.url) ?? sessionEventMediaPreview(mediaType, null);
@@ -15885,11 +16754,11 @@ function normalizeToolOutputForEvent(output) {
15885
16754
  return normalized;
15886
16755
  }
15887
16756
  if (output && typeof output === "object") {
15888
- const record = output;
15889
- if (Array.isArray(record.content)) {
16757
+ const record2 = output;
16758
+ if (Array.isArray(record2.content)) {
15890
16759
  return {
15891
- ...record,
15892
- content: record.content.map((el) => toolOutputMediaPreview(el) ?? el)
16760
+ ...record2,
16761
+ content: record2.content.map((el) => toolOutputMediaPreview(el) ?? el)
15893
16762
  };
15894
16763
  }
15895
16764
  }
@@ -16079,9 +16948,9 @@ function gatewayBillingFromResponse(response) {
16079
16948
  if (!response || typeof response !== "object" || Array.isArray(response)) {
16080
16949
  return null;
16081
16950
  }
16082
- const record = response;
16083
- const providerData = record.providerData && typeof record.providerData === "object" && !Array.isArray(record.providerData) ? record.providerData : null;
16084
- const metadataCandidate = record.provider_metadata ?? record.providerMetadata ?? providerData?.provider_metadata ?? providerData?.providerMetadata;
16951
+ const record2 = response;
16952
+ const providerData = record2.providerData && typeof record2.providerData === "object" && !Array.isArray(record2.providerData) ? record2.providerData : null;
16953
+ const metadataCandidate = record2.provider_metadata ?? record2.providerMetadata ?? providerData?.provider_metadata ?? providerData?.providerMetadata;
16085
16954
  if (!metadataCandidate || typeof metadataCandidate !== "object" || Array.isArray(metadataCandidate)) {
16086
16955
  return null;
16087
16956
  }
@@ -16124,12 +16993,12 @@ function modelResponseServiceTierFromResponse(response) {
16124
16993
  if (!response || typeof response !== "object") {
16125
16994
  return null;
16126
16995
  }
16127
- const record = response;
16128
- const direct = record.service_tier ?? record.serviceTier;
16996
+ const record2 = response;
16997
+ const direct = record2.service_tier ?? record2.serviceTier;
16129
16998
  if (typeof direct === "string" && direct.length > 0) {
16130
16999
  return direct;
16131
17000
  }
16132
- const providerData = record.providerData && typeof record.providerData === "object" ? record.providerData : null;
17001
+ const providerData = record2.providerData && typeof record2.providerData === "object" ? record2.providerData : null;
16133
17002
  const nested = providerData?.service_tier ?? providerData?.serviceTier;
16134
17003
  return typeof nested === "string" && nested.length > 0 ? nested : null;
16135
17004
  }
@@ -16153,10 +17022,10 @@ function usageFromResponse(response) {
16153
17022
  if (!raw || typeof raw !== "object") {
16154
17023
  return null;
16155
17024
  }
16156
- const record = raw;
17025
+ const record2 = raw;
16157
17026
  const usage = {
16158
17027
  ...numberProp(
16159
- record,
17028
+ record2,
16160
17029
  "inputTokens",
16161
17030
  "inputTokens",
16162
17031
  "input_tokens",
@@ -16164,17 +17033,17 @@ function usageFromResponse(response) {
16164
17033
  "prompt_tokens"
16165
17034
  ),
16166
17035
  ...numberProp(
16167
- record,
17036
+ record2,
16168
17037
  "outputTokens",
16169
17038
  "outputTokens",
16170
17039
  "output_tokens",
16171
17040
  "completionTokens",
16172
17041
  "completion_tokens"
16173
17042
  ),
16174
- ...numberProp(record, "totalTokens", "totalTokens", "total_tokens"),
16175
- ...inputTokenDetailsProp(record),
16176
- ...outputTokenDetailsProp(record),
16177
- ...requestUsageEntriesProp(record)
17043
+ ...numberProp(record2, "totalTokens", "totalTokens", "total_tokens"),
17044
+ ...inputTokenDetailsProp(record2),
17045
+ ...outputTokenDetailsProp(record2),
17046
+ ...requestUsageEntriesProp(record2)
16178
17047
  };
16179
17048
  return Object.keys(usage).length > 0 ? usage : null;
16180
17049
  }
@@ -17049,7 +17918,8 @@ function createInteractionAttemptToolDefinitions(input) {
17049
17918
  options.output,
17050
17919
  raw,
17051
17920
  context,
17052
- options.execute
17921
+ options.execute,
17922
+ options.readOnly
17053
17923
  )
17054
17924
  });
17055
17925
  };
@@ -17748,6 +18618,7 @@ function createFirstPartyInteractionAttemptToolDefinitions(input) {
17748
18618
  turnId: input.scope.turnId,
17749
18619
  attemptId: input.scope.attemptId,
17750
18620
  executionGeneration: input.scope.executionGeneration,
18621
+ ...input.credentialRestriction ? { credentialRestriction: input.credentialRestriction } : {},
17751
18622
  exp: Math.floor(Date.now() / 1e3) + 60 * 60
17752
18623
  });
17753
18624
  const headers = new Headers(init?.headers);
@@ -18006,7 +18877,7 @@ function readBrowserObservation(observation, input) {
18006
18877
  maxNodeBytes: BROWSER_AGENT_MAX_NODE_BYTES
18007
18878
  };
18008
18879
  }
18009
- async function safeInteractionExecution(inputSchema, outputSchema, raw, context, execute) {
18880
+ async function safeInteractionExecution(inputSchema, outputSchema, raw, context, execute, readOnly) {
18010
18881
  try {
18011
18882
  const value = inputSchema.parse(raw);
18012
18883
  const executed = await execute(value, context);
@@ -18025,11 +18896,12 @@ async function safeInteractionExecution(inputSchema, outputSchema, raw, context,
18025
18896
  if (error instanceof external_exports.ZodError) {
18026
18897
  return interactionErrorResult("invalid_arguments", "Interaction tool arguments are invalid.");
18027
18898
  }
18028
- if (error instanceof OpenGeniApiError && !error.outcomeUnknown && error.status < 500) {
18899
+ if (error instanceof OpenGeniApiError && !error.outcomeUnknown && (error.status < 500 || readOnly)) {
18029
18900
  return interactionErrorResult(
18030
18901
  error.code ?? `http_${error.status}`,
18031
18902
  boundedErrorMessage(error.message),
18032
- error.retryable
18903
+ error.retryable,
18904
+ error.correlationId
18033
18905
  );
18034
18906
  }
18035
18907
  throw error;
@@ -18045,8 +18917,8 @@ function browserToolImageContent(data, mimeType) {
18045
18917
  }
18046
18918
  return { type: "image", data: Buffer.from(data).toString("base64"), mimeType };
18047
18919
  }
18048
- function interactionErrorResult(code, message, retryable = false) {
18049
- const error = { code, message, retryable };
18920
+ function interactionErrorResult(code, message, retryable = false, requestId) {
18921
+ const error = { code, message, retryable, ...requestId ? { requestId } : {} };
18050
18922
  return {
18051
18923
  isError: true,
18052
18924
  content: [{ type: "text", text: JSON.stringify({ error }) }],
@@ -18114,21 +18986,21 @@ function extractOpenSuffixFromRunState(state) {
18114
18986
  if (!state || typeof state !== "object") {
18115
18987
  return [];
18116
18988
  }
18117
- const record = state;
18989
+ const record2 = state;
18118
18990
  const fromGenerated = extractOpenSuffixMembers(
18119
- protocolItemsFromGeneratedItems(record.generatedItems ?? record._generatedItems)
18991
+ protocolItemsFromGeneratedItems(record2.generatedItems ?? record2._generatedItems)
18120
18992
  );
18121
18993
  if (fromGenerated.length > 0) {
18122
18994
  return fromGenerated;
18123
18995
  }
18124
- if (Array.isArray(record.history)) {
18125
- const fromHistory = extractOpenSuffixMembers(record.history);
18996
+ if (Array.isArray(record2.history)) {
18997
+ const fromHistory = extractOpenSuffixMembers(record2.history);
18126
18998
  if (fromHistory.length > 0) {
18127
18999
  return fromHistory;
18128
19000
  }
18129
19001
  }
18130
- if (typeof record.toString === "function") {
18131
- const serialized = record.toString();
19002
+ if (typeof record2.toString === "function") {
19003
+ const serialized = record2.toString();
18132
19004
  if (serialized !== "[object Object]") {
18133
19005
  return extractOpenSuffixFromSerializedRunState(serialized);
18134
19006
  }
@@ -18274,6 +19146,13 @@ var CHAT_INCOMPATIBLE_ITEM_TYPES = /* @__PURE__ */ new Set([
18274
19146
  function isChatIncompatibleHostedToolCall(item) {
18275
19147
  return item.type === "hosted_tool_call" && item.name !== "file_search_call";
18276
19148
  }
19149
+ function chatSystemContent(content) {
19150
+ if (!Array.isArray(content) || !content.every(
19151
+ (part) => part !== null && typeof part === "object" && (part.type === "input_text" || part.type === "output_text" || part.type === "text") && typeof part.text === "string"
19152
+ ))
19153
+ return content;
19154
+ return content.map((part) => part.text).join("\n");
19155
+ }
18277
19156
  function projectHistoryForProvider(items, providerApi) {
18278
19157
  if (providerApi === "responses") {
18279
19158
  if (!items.some((item) => item.type === "message" && item.role === "developer")) return items;
@@ -18300,9 +19179,12 @@ function projectHistoryForProvider(items, providerApi) {
18300
19179
  }
18301
19180
  let changed = false;
18302
19181
  const projected = items.map((item) => {
18303
- if (item.type === "message" && item.role === "developer") {
18304
- changed = true;
18305
- return { ...item, role: "system" };
19182
+ if (item.type === "message" && (item.role === "developer" || item.role === "system")) {
19183
+ const content = chatSystemContent(item.content);
19184
+ if (item.role === "developer" || content !== item.content) {
19185
+ changed = true;
19186
+ return { ...item, role: "system", content };
19187
+ }
18306
19188
  }
18307
19189
  const resultId = item.type === "function_call_result" ? callId2(item) : null;
18308
19190
  if (CHAT_INCOMPATIBLE_ITEM_TYPES.has(String(item.type ?? "")) || isChatIncompatibleHostedToolCall(item) || isChatIncompatibleCall(item) || resultId !== null && incompatibleCallIds.has(resultId)) {
@@ -18561,10 +19443,10 @@ function totalCoversKnownComponents(total, inputTokens, outputTokens) {
18561
19443
  function rejectInconsistentRequestTotals(requestEntries, rejectedFields) {
18562
19444
  let inconsistent = false;
18563
19445
  for (const [index, entry] of requestEntries.entries()) {
18564
- const record = entry;
18565
- const selectedInput = firstPresentEntry(record, ["inputTokens", "input_tokens"]);
18566
- const selectedOutput = firstPresentEntry(record, ["outputTokens", "output_tokens"]);
18567
- const selectedTotal = firstPresentEntry(record, ["totalTokens", "total_tokens"]);
19446
+ const record2 = entry;
19447
+ const selectedInput = firstPresentEntry(record2, ["inputTokens", "input_tokens"]);
19448
+ const selectedOutput = firstPresentEntry(record2, ["outputTokens", "output_tokens"]);
19449
+ const selectedTotal = firstPresentEntry(record2, ["totalTokens", "total_tokens"]);
18568
19450
  if (!selectedInput || !selectedOutput || !selectedTotal) continue;
18569
19451
  const inputTokens = modelUsageTokenCountOrNull(selectedInput.value);
18570
19452
  const outputTokens = modelUsageTokenCountOrNull(selectedOutput.value);
@@ -18644,10 +19526,10 @@ function detailRecords(details, path, rejectedFields) {
18644
19526
  }
18645
19527
  return { records, complete };
18646
19528
  }
18647
- function firstPresentEntry(record, keys) {
19529
+ function firstPresentEntry(record2, keys) {
18648
19530
  for (const key of keys) {
18649
- if (Object.prototype.hasOwnProperty.call(record, key) && record[key] !== void 0) {
18650
- return { key, value: record[key] };
19531
+ if (Object.prototype.hasOwnProperty.call(record2, key) && record2[key] !== void 0) {
19532
+ return { key, value: record2[key] };
18651
19533
  }
18652
19534
  }
18653
19535
  return null;
@@ -18718,6 +19600,7 @@ function createFirstPartyAttemptClient(input) {
18718
19600
  principalKind: "agent_attempt",
18719
19601
  permissions: [...input.permissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2],
18720
19602
  firstPartyMcpTools: [...input.selectedTools],
19603
+ ...input.credentialRestriction ? { credentialRestriction: input.credentialRestriction } : {},
18721
19604
  exp: Math.floor(Date.now() / 1e3) + 60 * 60
18722
19605
  });
18723
19606
  const headers = new Headers(init?.headers);
@@ -19046,12 +19929,12 @@ function functionToolNamespaceFields(tool2) {
19046
19929
  namespaceDescription = value;
19047
19930
  }
19048
19931
  }
19049
- const record = tool2;
19050
- if (!namespace && typeof record.namespace === "string" && record.namespace.length > 0) {
19051
- namespace = record.namespace;
19932
+ const record2 = tool2;
19933
+ if (!namespace && typeof record2.namespace === "string" && record2.namespace.length > 0) {
19934
+ namespace = record2.namespace;
19052
19935
  }
19053
- if (!namespaceDescription && typeof record.namespaceDescription === "string" && record.namespaceDescription.length > 0) {
19054
- namespaceDescription = record.namespaceDescription;
19936
+ if (!namespaceDescription && typeof record2.namespaceDescription === "string" && record2.namespaceDescription.length > 0) {
19937
+ namespaceDescription = record2.namespaceDescription;
19055
19938
  }
19056
19939
  return {
19057
19940
  ...namespace ? { namespace } : {},
@@ -19062,19 +19945,19 @@ function serializeToolForRemoteCompaction(tool2) {
19062
19945
  if (!tool2 || typeof tool2 !== "object" || typeof tool2.type !== "string") {
19063
19946
  return null;
19064
19947
  }
19065
- const record = tool2;
19066
- const name = typeof record.name === "string" ? record.name : "";
19948
+ const record2 = tool2;
19949
+ const name = typeof record2.name === "string" ? record2.name : "";
19067
19950
  if (tool2.type === "function") {
19068
- const { namespace, namespaceDescription } = functionToolNamespaceFields(record);
19951
+ const { namespace, namespaceDescription } = functionToolNamespaceFields(record2);
19069
19952
  return {
19070
19953
  type: "function",
19071
19954
  name,
19072
- description: typeof record.description === "string" ? record.description : "",
19073
- parameters: record.parameters,
19955
+ description: typeof record2.description === "string" ? record2.description : "",
19956
+ parameters: record2.parameters,
19074
19957
  // Pass through like SDK serializeTool — do not coerce undefined → false
19075
19958
  // (Responses wire would gain an explicit `"strict": false` and bust cache).
19076
- strict: record.strict,
19077
- ...typeof record.deferLoading === "boolean" ? { deferLoading: record.deferLoading } : {},
19959
+ strict: record2.strict,
19960
+ ...typeof record2.deferLoading === "boolean" ? { deferLoading: record2.deferLoading } : {},
19078
19961
  ...namespace ? {
19079
19962
  namespace,
19080
19963
  ...namespaceDescription ? { namespaceDescription } : {}
@@ -19085,7 +19968,7 @@ function serializeToolForRemoteCompaction(tool2) {
19085
19968
  return {
19086
19969
  type: "hosted_tool",
19087
19970
  name,
19088
- providerData: record.providerData
19971
+ providerData: record2.providerData
19089
19972
  };
19090
19973
  }
19091
19974
  if (tool2.type === "apply_patch") {
@@ -19095,11 +19978,11 @@ function serializeToolForRemoteCompaction(tool2) {
19095
19978
  return {
19096
19979
  type: "shell",
19097
19980
  name,
19098
- environment: record.environment
19981
+ environment: record2.environment
19099
19982
  };
19100
19983
  }
19101
19984
  if (tool2.type === "computer") {
19102
- const computer = record.computer && typeof record.computer === "object" ? record.computer : null;
19985
+ const computer = record2.computer && typeof record2.computer === "object" ? record2.computer : null;
19103
19986
  if (computer && typeof computer.environment === "string" && Array.isArray(computer.dimensions) && computer.dimensions.length === 2 && computer.dimensions.every((value) => typeof value === "number")) {
19104
19987
  return {
19105
19988
  type: "computer",
@@ -19168,8 +20051,8 @@ async function requestRemoteCompactionV2(settings, input, options) {
19168
20051
  }
19169
20052
  function isFailedCompactionProviderResponse(response) {
19170
20053
  if (!response || typeof response !== "object") return false;
19171
- const record = response;
19172
- return record.status === "failed" || record.status === "incomplete" || record.error !== null && record.error !== void 0;
20054
+ const record2 = response;
20055
+ return record2.status === "failed" || record2.status === "incomplete" || record2.error !== null && record2.error !== void 0;
19173
20056
  }
19174
20057
  function compactionProviderFailureDiagnostics(error) {
19175
20058
  let current = error;
@@ -19189,44 +20072,44 @@ function compactionProviderFailureDiagnostics(error) {
19189
20072
  for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
19190
20073
  if (seen.has(current)) break;
19191
20074
  seen.add(current);
19192
- const record = current;
19193
- rejectionReason ??= compactionRejectionReason(record);
20075
+ const record2 = current;
20076
+ rejectionReason ??= compactionRejectionReason(record2);
19194
20077
  if (!errorName && current instanceof Error) {
19195
20078
  errorName = boundCompactionDiagnosticField(current.name);
19196
20079
  }
19197
- if (param === null && typeof record.param === "string" && record.param.length > 0) {
19198
- param = boundCompactionDiagnosticField(record.param);
20080
+ if (param === null && typeof record2.param === "string" && record2.param.length > 0) {
20081
+ param = boundCompactionDiagnosticField(record2.param);
19199
20082
  }
19200
- if (httpStatus === null && typeof record.status === "number" && Number.isFinite(record.status)) {
19201
- httpStatus = record.status;
20083
+ if (httpStatus === null && typeof record2.status === "number" && Number.isFinite(record2.status)) {
20084
+ httpStatus = record2.status;
19202
20085
  }
19203
- if (responseStatus === null && typeof record.status === "string") {
19204
- responseStatus = boundCompactionDiagnosticField(record.status);
20086
+ if (responseStatus === null && typeof record2.status === "string") {
20087
+ responseStatus = boundCompactionDiagnosticField(record2.status);
19205
20088
  }
19206
- const directResponseStatus = record.response_status ?? record.responseStatus;
20089
+ const directResponseStatus = record2.response_status ?? record2.responseStatus;
19207
20090
  if (responseStatus === null && typeof directResponseStatus === "string") {
19208
20091
  responseStatus = boundCompactionDiagnosticField(directResponseStatus);
19209
20092
  }
19210
- const directResponseId = record.response_id ?? record.responseId ?? record.id;
20093
+ const directResponseId = record2.response_id ?? record2.responseId ?? record2.id;
19211
20094
  if (responseId === null && typeof directResponseId === "string") {
19212
20095
  responseId = boundCompactionDiagnosticField(directResponseId);
19213
20096
  }
19214
- if (code === null && typeof record.code === "string") {
19215
- code = boundCompactionDiagnosticField(record.code);
20097
+ if (code === null && typeof record2.code === "string") {
20098
+ code = boundCompactionDiagnosticField(record2.code);
19216
20099
  }
19217
- if (type === null && typeof record.type === "string") {
19218
- type = boundCompactionDiagnosticField(record.type);
20100
+ if (type === null && typeof record2.type === "string") {
20101
+ type = boundCompactionDiagnosticField(record2.type);
19219
20102
  }
19220
- const directEventType = record.event_type ?? record.eventType;
20103
+ const directEventType = record2.event_type ?? record2.eventType;
19221
20104
  if (eventType === null && typeof directEventType === "string") {
19222
20105
  eventType = boundCompactionDiagnosticField(directEventType);
19223
20106
  }
19224
20107
  if (requestId === null) {
19225
- const directRequestId = record.request_id ?? record.requestId ?? record.requestID ?? record._request_id;
20108
+ const directRequestId = record2.request_id ?? record2.requestId ?? record2.requestID ?? record2._request_id;
19226
20109
  if (typeof directRequestId === "string") {
19227
20110
  requestId = boundCompactionDiagnosticField(directRequestId);
19228
20111
  }
19229
- const headers = record.headers;
20112
+ const headers = record2.headers;
19230
20113
  if (!requestId && headers && typeof headers === "object") {
19231
20114
  const get = headers.get;
19232
20115
  if (typeof get === "function") {
@@ -19237,7 +20120,7 @@ function compactionProviderFailureDiagnostics(error) {
19237
20120
  }
19238
20121
  }
19239
20122
  }
19240
- const nestedError = record.error;
20123
+ const nestedError = record2.error;
19241
20124
  if (nestedError && typeof nestedError === "object" && !seen.has(nestedError)) {
19242
20125
  const nested = nestedError;
19243
20126
  rejectionReason ??= compactionRejectionReason(nested);
@@ -19263,7 +20146,7 @@ function compactionProviderFailureDiagnostics(error) {
19263
20146
  eventType = boundCompactionDiagnosticField(nestedEventType);
19264
20147
  }
19265
20148
  }
19266
- current = record.cause;
20149
+ current = record2.cause;
19267
20150
  }
19268
20151
  return {
19269
20152
  errorName,
@@ -19278,9 +20161,9 @@ function compactionProviderFailureDiagnostics(error) {
19278
20161
  ...rejectionReason ? { rejectionReason } : {}
19279
20162
  };
19280
20163
  }
19281
- function compactionRejectionReason(record) {
19282
- return typeof record.message === "string" && record.message.length <= 1024 && /^Item '[A-Za-z0-9_-]+' of type '[a-z_]+' was provided without its required 'reasoning' item: '[A-Za-z0-9_-]+'\.$/.test(
19283
- record.message
20164
+ function compactionRejectionReason(record2) {
20165
+ return typeof record2.message === "string" && record2.message.length <= 1024 && /^Item '[A-Za-z0-9_-]+' of type '[a-z_]+' was provided without its required 'reasoning' item: '[A-Za-z0-9_-]+'\.$/.test(
20166
+ record2.message
19284
20167
  ) ? "missing_required_reasoning_item" : null;
19285
20168
  }
19286
20169
  var COMPACTION_DIAGNOSTIC_FIELD_MAX_BYTES = 256;
@@ -19303,8 +20186,8 @@ function compactionResponseDiagnostics(response, extractedText = extractResponse
19303
20186
  extractedTextLength: extractedText.length
19304
20187
  };
19305
20188
  }
19306
- const record = response;
19307
- const output = Array.isArray(record.output) ? record.output : [];
20189
+ const record2 = response;
20190
+ const output = Array.isArray(record2.output) ? record2.output : [];
19308
20191
  const outputItems = output.slice(0, 50).map((item) => {
19309
20192
  if (!item || typeof item !== "object") return { type: typeof item };
19310
20193
  const value = item;
@@ -19319,12 +20202,12 @@ function compactionResponseDiagnostics(response, extractedText = extractResponse
19319
20202
  contentPartCount: content.length
19320
20203
  };
19321
20204
  });
19322
- const choices = Array.isArray(record.choices) ? record.choices : [];
20205
+ const choices = Array.isArray(record2.choices) ? record2.choices : [];
19323
20206
  const usage = modelResponseUsageFromResponse(response)?.usage;
19324
- const incomplete = record.incomplete_details && typeof record.incomplete_details === "object" ? record.incomplete_details : null;
20207
+ const incomplete = record2.incomplete_details && typeof record2.incomplete_details === "object" ? record2.incomplete_details : null;
19325
20208
  return {
19326
- responseId: typeof record.id === "string" ? record.id : null,
19327
- status: typeof record.status === "string" ? record.status : null,
20209
+ responseId: typeof record2.id === "string" ? record2.id : null,
20210
+ status: typeof record2.status === "string" ? record2.status : null,
19328
20211
  outputItemCount: output.length,
19329
20212
  outputItems,
19330
20213
  choiceCount: choices.length,
@@ -19428,31 +20311,10 @@ var ConnectorActionExecutionError = class extends Error {
19428
20311
  var modelToolInvocation = new AsyncLocalStorage7();
19429
20312
  var modelMcpCallIdentity = new AsyncLocalStorage7();
19430
20313
  var agentInputWaitYields = /* @__PURE__ */ new WeakMap();
19431
- function rigInstructions(rig) {
19432
- return [
19433
- `This session uses sandbox environment "${rig.name}" (active version v${rig.version}) \u2014 a versioned definition of custom sandbox setup and health checks.`,
19434
- "Your sandbox is an EPHEMERAL FORK of this environment. You may install tools here, but local changes do not update the environment definition or other sessions.",
19435
- "To make a verified setup change available to future sessions using this environment, call rig_propose_change with the exact command that already worked here. Never assume an unverified change propagates.",
19436
- "If tooling you expect is missing, consult rig_get to see the sandbox environment's current setup and checks before reinstalling."
19437
- ];
19438
- }
19439
- function workspaceEnvironmentInstructions(environment) {
19440
- const lines = [
19441
- `A workspace environment named "${environment.name}" is attached to this session; its variables are exported in the sandbox shell environment.`
19442
- ];
19443
- const variableNames = (environment.variableNames ?? []).filter((name) => name.length > 0);
19444
- if (variableNames.length > 0) {
19445
- lines.push(`Exported environment variables: ${[...variableNames].sort().join(", ")}.`);
19446
- }
19447
- const description = environment.description?.trim();
19448
- if (description) {
19449
- lines.push(`Environment notes from the operator: ${description}`);
19450
- }
19451
- return lines;
19452
- }
19453
20314
  function coreInstructions(workspaceEnvironment, rig) {
19454
20315
  return [
19455
20316
  "If the session has a goal, you own it: keep working until you call opengeni__goal_complete with concrete evidence or opengeni__goal_pause with a rationale; revise it with opengeni__goal_update; create one with opengeni__goal_set when given a long-running objective. Resume a paused goal with opengeni__goal_resume when the user asks you to continue, regardless of who paused it, or when the blocker you paused for has cleared. A question alone is not such a request: answer it and leave the goal paused.",
20317
+ "Goal completion records short ledger proof, not the user-facing deliverable. After goal_complete succeeds, finish the same turn with the requested answer, or a concise summary and retained artifact link. Never use evidence as the final reply. A later child result after completion is context to integrate, not a reason to stay silent or restart the completed goal.",
19456
20318
  'Choose durable storage by purpose, including requests to "remember this" or keep something "for future sessions". Knowledge is retrieval-only information, not standing behavior. Use instruction_policy_get then instruction_policy_save for short always-on workspace rules, such as "Keep replies concise; expand when asked." Use Skills for reusable procedures and context-specific or personal behavioral preferences; make the Skill description state when it applies so the prompt index can guide skill_read. Do not save behavioral preferences as Knowledge by rephrasing them as facts like "the user prefers concise replies". Preserve the intended scope: do not turn a personal preference into a workspace-wide rule; use an authorized personal Skill when appropriate, or explain the unavailable scope. Split mixed requests into a short rule and detailed Skill steps without duplicating them in Knowledge.',
19457
20319
  "Before changing workspace instructions, read the current instruction and exact baseline, preserve unrelated rules, append new rules, and use only a localized exact anchored edit for updates or removals. Agents cannot replace the complete instruction; whole-policy rewrites belong in the manual workspace editor. Do not bypass a destination's Agent learning setting, review, scope, limits, or unavailable tools by saving to another destination. Report the actual destination and receipt: active, pending review, or not saved. Do not promise future behavior from a Knowledge save.",
19458
20320
  "Use knowledge_search and knowledge_get when retained information is relevant. For questions about what the workspace knows, ground the answer in authorized Knowledge and attached sources. Missing internal facts remain unknown; do not infer a person's role or cite unrelated public search results as evidence. Keep any relevant external research clearly separate from workspace records. Default retrieval returns published information. Before retaining or correcting anything, also search view=needs_review for existing pending entries and collections; read those with knowledge_get view=needs_review. Pending means unapproved: you may inspect and improve it, but do not present it as accepted knowledge or activate behavioral guidance from it. Reuse the existing entryId and current version instead of creating another proposal each run. Save durable facts, decisions, requirements, incidents, fixes and outcomes autonomously with knowledge_save only when they help a plausible future task. Do not retain routine approvals, acknowledgments, temporary task instructions, status chatter or raw screenshots merely because they occurred. Before saving, use knowledge_prepare_save when available to fetch the authorized collection map with descriptions and parent IDs plus related published and pending entries; otherwise search both views and browse collections. Skip unchanged duplicates, improve the existing entry when appropriate, and create a new entry only for distinct useful information. Read the current entry before correcting it and preserve uncertainty, conflicting evidence and existing relationships. When a user supplies or confirms a durable fact, use knowledge_retain_message to retain the actual message and cite its returned entryId/revisionId in the finding evidence. Preserve existing source evidence and relationships when correcting an entry; do not replace them with empty arrays merely because the user confirmed a new value. Explicit confirmation can supersede a conflicting pending proposal, but explain that outcome to the user. Preserve uncertainty and exact supporting evidence; the fact label is not a verification claim. Chat attachments retain their original files for the conversation without automatically publishing OCR or source text into Knowledge. Inspect an image visually in the current task; save only a useful supported observation, requirement or incident when warranted. Use knowledge_retain_file purpose=evidence only when a selected finding needs the original as supporting evidence, or purpose=reference when deliberately retaining a reusable source document. Supporting sources remain accessible through evidence links and explicit includeEvidence searches, but do not fill ordinary Knowledge discovery. An upload alone is not a reason to save Knowledge. A source entry contains retained original text; a finding states a useful conclusion and cites the exact source revision. Do not create both when they would simply repeat the same text. Reuse collections for customers, products, systems or subjects across sources, and link one entry to multiple collections instead of copying it. Technical incidents belong with the affected system and should include cause, fix and outcome when known. Reorganize references when useful; do not erase source evidence or revision history. Private tasks author personal Knowledge; shared tasks author workspace Knowledge. Automatic publishes immediately, Review first keeps a pending proposal without pausing your task, and Off prevents authoring while permitting retrieval. Never bypass review by making a new entry, switching tools, or asking for another approval. Reuse the same operationId and exact request after an uncertain save, including recovery. Use task_note_save for temporary coordination in this task tree. Conversation history is separate. Workspace instructions are concise standing rules; Skills are reusable procedures with their own Agent learning settings. Do not save the same content in multiple authorities.",
@@ -19464,8 +20326,8 @@ function coreInstructions(workspaceEnvironment, rig) {
19464
20326
  }
19465
20327
  function composeAgentInstructions(template, workspaceEnvironment, rig) {
19466
20328
  const core = coreInstructions(workspaceEnvironment, rig).join(" ");
19467
- if (template.includes(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER)) {
19468
- return template.split(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER).join(core);
20329
+ if (template.includes(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER2)) {
20330
+ return template.split(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER2).join(core);
19469
20331
  }
19470
20332
  return core ? `${template} ${core}` : template;
19471
20333
  }
@@ -19494,7 +20356,47 @@ function gitBindingDiscoveryApplies(bindings, activeSandboxBackend) {
19494
20356
  }
19495
20357
  return [...bindingsByProvider.values()].some((ids) => ids.size > 1);
19496
20358
  }
20359
+ function agentPromptResourcesFor(settings, resources, options) {
20360
+ const backend = options.activeSandboxBackend ?? settings.sandboxBackend;
20361
+ const connectedMachine = backend === "selfhosted";
20362
+ const managedSandbox = backend !== "none" && !connectedMachine;
20363
+ const gitTokenSeeds = Object.values(options.gitTokenSeeds ?? {}).filter(Boolean);
20364
+ return {
20365
+ managedSandbox,
20366
+ connectedMachine,
20367
+ // A Connected Machine never receives platform clones.
20368
+ repositories: managedSandbox && resources.some((resource) => resource.kind === "repository"),
20369
+ gitCredentials: managedSandbox && (Boolean(options.gitTokenSeed) || gitTokenSeeds.length > 0 || (options.gitCredentialBindings?.length ?? 0) > 0),
20370
+ attachments: (managedSandbox || connectedMachine) && (resources.some((resource) => resource.kind === "file") || (options.fileResourceDownloads?.length ?? 0) > 0),
20371
+ ...options.workspaceEnvironment ? { workspaceEnvironment: options.workspaceEnvironment } : {},
20372
+ ...options.rig ? { rig: options.rig } : {}
20373
+ };
20374
+ }
20375
+ function inspectModularAgentInstructions(settings, config, options) {
20376
+ const identity2 = resolveAgentIdentity({
20377
+ sessionIdentity: config.identity,
20378
+ workspaceIdentity: options.workspaceAgentIdentity ?? options.instructionsTemplate,
20379
+ deploymentTemplate: settings.agentInstructionsTemplate
20380
+ });
20381
+ const composed = composeModularAgentInstructions({
20382
+ capabilities: config.capabilities,
20383
+ renderer: config.renderer,
20384
+ identity: identity2,
20385
+ resources: options.agentPromptResources ?? agentPromptResourcesFor(settings, [], options),
20386
+ ...codemodeIsAvailable(options) ? { codemode: CODEMODE_PROGRAMMATIC_DIRECTIVE } : {},
20387
+ ...options.codeSearchAvailable ? { codeSearch: CODE_SEARCH_DIRECTIVE } : {},
20388
+ ...gitBindingDiscoveryApplies(options.gitCredentialBindings, options.activeSandboxBackend) ? { gitBindings: GIT_BINDING_DISCOVERY_DIRECTIVE } : {},
20389
+ ...options.skillCatalog && !options.skillCatalogInHistory ? { skillCatalog: formatSkillCatalog(options.skillCatalog) } : {},
20390
+ workspaceGovernance: options.workspaceGovernance,
20391
+ workspaceMemory: options.workspaceMemory,
20392
+ sessionInstructions: options.sessionInstructions
20393
+ });
20394
+ return { layers: composed.layers, composed: composed.composed };
20395
+ }
19497
20396
  function inspectPersistentAgentInstructions(settings, options) {
20397
+ if (options.agentConfig) {
20398
+ return inspectModularAgentInstructions(settings, options.agentConfig, options);
20399
+ }
19498
20400
  const personaAndCore = composeAgentInstructions(
19499
20401
  options.instructionsTemplate ?? settings.agentInstructionsTemplate,
19500
20402
  options.workspaceEnvironment,
@@ -19647,6 +20549,10 @@ var SkillReadToolInput = external_exports.object({
19647
20549
  paths: external_exports.array(external_exports.string().min(1).max(1024)).min(1).max(128).optional()
19648
20550
  });
19649
20551
  function buildOpenGeniAgent(settings, resources, options = {}) {
20552
+ if (resolveAgentToolFamilies(options.agentConfig).skills === false) {
20553
+ const { skillActivations: _disabledActivations, ...withoutSkills } = options;
20554
+ options = { ...withoutSkills, skillCatalog: [] };
20555
+ }
19650
20556
  if (Boolean(options.codemodeTokenSeed) !== Boolean(options.codemodeTokenSessionId)) {
19651
20557
  throw new Error("codemodeTokenSeed and codemodeTokenSessionId must be supplied together");
19652
20558
  }
@@ -19673,9 +20579,19 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19673
20579
  const skillCatalog = hostSuppliedSkillCatalog ? options.skillCatalog : skillComposition.index.length > 0 ? skillCatalogFromComposition(skillComposition) : void 0;
19674
20580
  const instructionOptions = {
19675
20581
  ...options,
19676
- ...skillCatalog !== void 0 ? { skillCatalog } : {}
20582
+ ...skillCatalog !== void 0 ? { skillCatalog } : {},
20583
+ ...options.agentConfig && !options.agentPromptResources ? { agentPromptResources: agentPromptResourcesFor(settings, resources, options) } : {}
19677
20584
  };
19678
- const hostedWebSearch = options.hostedWebSearch ?? settings.webSearchEnabled;
20585
+ const toolFamilies = resolveAgentToolFamilies(options.agentConfig, {
20586
+ hasSkills: (skillCatalog?.length ?? 0) > 0,
20587
+ webSearch: options.hostedWebSearch ?? settings.webSearchEnabled,
20588
+ humanInput: options.humanInputEnabled !== false
20589
+ });
20590
+ const hostedWebSearch = toolFamilies.webSearch;
20591
+ const mediaTools = resolveAgentMediaToolSurface(options.agentConfig, {
20592
+ image: options.imageGeneration?.kind ?? null,
20593
+ video: Boolean(options.videoGeneration)
20594
+ });
19679
20595
  const encryptedReasoning = options.encryptedReasoning ?? settings.openaiReasoningEncryptedContent;
19680
20596
  const serviceTier = options.serviceTier;
19681
20597
  const providerData = {
@@ -19684,10 +20600,10 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19684
20600
  ...serviceTier ? { service_tier: serviceTier } : {}
19685
20601
  };
19686
20602
  const hostedTools = hostedWebSearch ? [webSearchTool()] : [];
19687
- if (options.imageGeneration?.kind === "native_hosted") {
20603
+ if (mediaTools.hosted.includes("image_generation")) {
19688
20604
  hostedTools.push(imageGenerationTool({ model: "gpt-image-2" }));
19689
20605
  }
19690
- const providerImageGenerationTool = options.imageGeneration?.kind === "provider_adapter" ? tool({
20606
+ const providerImageGenerationTool = mediaTools.runtime.includes("generate_image") ? tool({
19691
20607
  name: "generate_image",
19692
20608
  description: "Generate or edit exactly one image. Optionally provide up to four ordered references using exact /workspace paths, workspace File IDs, or generated-image artifact IDs; every reference must be a PNG, JPEG, or WebP image, so convert SVG or other formats first. Describe each reference's role by position in the prompt. The result is a permanent image artifact and its exact sandbox path. Do not call repeatedly unless the user requested multiple distinct images.",
19693
20609
  parameters: GenerateImageToolInput,
@@ -19701,7 +20617,9 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19701
20617
  return await options.imageGeneration.execute(input, { toolCallId });
19702
20618
  }
19703
20619
  }) : null;
19704
- const videoGenerationCapabilityTool = options.videoGeneration ? tool({
20620
+ const videoGenerationCapabilityTool = mediaTools.runtime.includes(
20621
+ "get_video_generation_capabilities"
20622
+ ) ? tool({
19705
20623
  name: "get_video_generation_capabilities",
19706
20624
  description: "Return the video-generation models and exact source, duration, resolution, aspect-ratio, and audio capabilities currently enabled for this workspace. Call immediately before generate_video, then select a listed model and source mode; availability is runtime state and is never encoded in the generate_video schema.",
19707
20625
  parameters: GetVideoGenerationCapabilitiesToolInput,
@@ -19712,7 +20630,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19712
20630
  return await adapter.capabilities();
19713
20631
  }
19714
20632
  }) : null;
19715
- const videoGenerationTool = options.videoGeneration ? tool({
20633
+ const videoGenerationTool = mediaTools.runtime.includes("generate_video") ? tool({
19716
20634
  name: "generate_video",
19717
20635
  description: "Start one durable asynchronous video generation after get_video_generation_capabilities. Match the selected model's exact source mode: omit references for text-to-video, provide one exact /workspace image path for image-to-video, or provide one exact /workspace video path for video editing. Call once per intentionally distinct result. An accepted result means work continues independently and must never be retried automatically. A rejected result means no operation or provider request was created; correct the stated reference problem and call again only with corrected input.",
19718
20636
  parameters: GenerateVideoToolInput,
@@ -19725,7 +20643,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19725
20643
  return await adapter.execute(input, { toolCallId });
19726
20644
  }
19727
20645
  }) : null;
19728
- const humanInputTool = options.humanInputEnabled === false ? null : tool({
20646
+ const humanInputTool = !toolFamilies.humanInput ? null : tool({
19729
20647
  name: HUMAN_INPUT_TOOL_NAME,
19730
20648
  description: "Pause this turn and request structured human input. Use for decisions or missing information that only a person can provide. Supports free text, single-select, multi-select, multiple questions, explicit skip policy, and an optional expiry. Every single-select or multi-select question also gives the person an Other field for an exact free-text answer; interpret that answer normally and make a new request only if genuine clarification is still needed.",
19731
20649
  parameters: RequestHumanInputToolInput2,
@@ -19776,7 +20694,7 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19776
20694
  ...videoGenerationTool ? [videoGenerationTool] : [],
19777
20695
  ...humanInputTool ? [humanInputTool] : []
19778
20696
  ];
19779
- const embeddedSkillReadTool = !hostSuppliedSkillCatalog && skillComposition.artifacts.length > 0 ? tool({
20697
+ const embeddedSkillReadTool = toolFamilies.allowsFunctionTool("skill_read") && !hostSuppliedSkillCatalog && skillComposition.artifacts.length > 0 ? tool({
19780
20698
  name: "skill_read",
19781
20699
  description: "Read Skill text without starting a sandbox. Omit paths to read SKILL.md; provide relative paths to read exactly those files, never implicitly adding SKILL.md. Set listFiles:true without paths to list relative paths only, with no file bodies. Use an id or name from the Skill index.",
19782
20700
  parameters: SkillReadToolInput,
@@ -19986,10 +20904,10 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
19986
20904
  return agent;
19987
20905
  }
19988
20906
  function maybeInstallLazyToolTransport(agent, settings, options) {
19989
- const transport = options.lazyToolTransport;
20907
+ const transport = options.lazyToolTransport ?? (options.agentConfig && options.toolRouterInHistory ? "generic_dispatch" : void 0);
19990
20908
  if (!transport) return;
19991
20909
  const enabled = transport === "codex_native" ? settings.codexToolSearchEnabled : settings.lazyToolSearchEnabled;
19992
- if (!enabled) return;
20910
+ if (!enabled && !(options.agentConfig && options.toolRouterInHistory)) return;
19993
20911
  const mcpServers = options.mcpServers ?? [];
19994
20912
  const mcpServerIds = new Set(mcpServers.map((server) => mcpServerRegistryId(server)));
19995
20913
  const deferredMcpServerIds = new Set(
@@ -20013,7 +20931,9 @@ function maybeInstallLazyToolTransport(agent, settings, options) {
20013
20931
  }
20014
20932
  }
20015
20933
  return identities;
20016
- }
20934
+ },
20935
+ options.agentConfig != null,
20936
+ options.toolRouterInHistory === true
20017
20937
  );
20018
20938
  }
20019
20939
  function mcpServerRegistryId(server) {
@@ -20445,6 +21365,13 @@ function buildAgentCapabilitiesFromComposition(settings, skillComposition, optio
20445
21365
  // readiness proof, which reaches bounded same-turn recovery.
20446
21366
  execCommandErrorFunction: (_context, error) => {
20447
21367
  if (isModalTaskExecStartPreDispatchUnavailableError(error)) throw error;
21368
+ if (isRoutingMutationOutcomeUnknownError(error)) {
21369
+ if (toolCancellation) throw error;
21370
+ return renderRoutingMutationOutcomeUnknownToolResult(error);
21371
+ }
21372
+ if (isModalCommandStartOutcomeUnknownError(error)) {
21373
+ return "Managed sandbox command start outcome unknown. The command may have executed. Do not blindly retry it; inspect the existing sandbox state before taking further action.";
21374
+ }
20448
21375
  const details = error instanceof Error ? error.toString() : String(error);
20449
21376
  return `An error occurred while running the tool. Please try again. Error: ${details}`;
20450
21377
  },
@@ -20673,7 +21600,7 @@ async function prepareAgentTools(settings, tools, options = {}) {
20673
21600
  options = { ...options, sessionAttachedRemoteMcpTargets: identityTargets };
20674
21601
  options.runMcpCredentials?.assertRemoteTargets(
20675
21602
  settings.mcpServers.filter(
20676
- (config) => tools.some((tool2) => tool2.id === config.id) && !localRegistry.has(config.id) && !isFirstPartyMcpServer(settings, config) && !isCodexAppsMcpServer(config)
21603
+ (config) => tools.some((tool2) => tool2.id === config.id) && !config.connectionRef && !localRegistry.has(config.id) && !isFirstPartyMcpServer(settings, config) && !isCodexAppsMcpServer(config)
20677
21604
  )
20678
21605
  );
20679
21606
  const aggregateToolBudget = new McpAggregateToolListBudget();
@@ -21144,7 +22071,7 @@ function selectedSessionRemoteMcpTargets(settings, attachments, tools, localServ
21144
22071
  );
21145
22072
  if (configs.length !== 1) return [];
21146
22073
  const config = configs[0];
21147
- if (isFirstPartyMcpServer(settings, config) || isCodexAppsMcpServer(config) || BUILT_IN_MCP_BRIDGE_ADAPTERS.some(
22074
+ if (config.connectionRef || isFirstPartyMcpServer(settings, config) || isCodexAppsMcpServer(config) || BUILT_IN_MCP_BRIDGE_ADAPTERS.some(
21148
22075
  (adapter) => adapter.matches({
21149
22076
  url: config.url,
21150
22077
  ...config.connectionRef ? { connectionRef: config.connectionRef } : {}
@@ -22133,20 +23060,20 @@ function inspectMcpTransportError(error, seen = /* @__PURE__ */ new WeakSet()) {
22133
23060
  }
22134
23061
  seen.add(current.value);
22135
23062
  inspectedNodes += 1;
22136
- const record = current.value;
23063
+ const record2 = current.value;
22137
23064
  let httpStatusValues;
22138
23065
  let statusValues;
22139
23066
  let code;
22140
23067
  let failureKind;
22141
23068
  let message;
22142
23069
  try {
22143
- const status = record.status;
22144
- const statusCode = record.statusCode;
22145
- code = record.code;
23070
+ const status = record2.status;
23071
+ const statusCode = record2.statusCode;
23072
+ code = record2.code;
22146
23073
  httpStatusValues = [status, statusCode];
22147
23074
  statusValues = [...httpStatusValues, code];
22148
- failureKind = record.mcpTransportFailureKind;
22149
- message = record.message;
23075
+ failureKind = record2.mcpTransportFailureKind;
23076
+ message = record2.message;
22150
23077
  if (current.value instanceof Error && Object.getPrototypeOf(current.value) !== Error.prototype) {
22151
23078
  hasTypedError = true;
22152
23079
  }
@@ -22181,7 +23108,7 @@ function inspectMcpTransportError(error, seen = /* @__PURE__ */ new WeakSet()) {
22181
23108
  for (const key of MCP_TRANSPORT_ERROR_NESTED_KEYS) {
22182
23109
  let nested;
22183
23110
  try {
22184
- nested = record[key];
23111
+ nested = record2[key];
22185
23112
  } catch {
22186
23113
  complete = false;
22187
23114
  continue;
@@ -22273,27 +23200,7 @@ function exactMcpLifecycleError(error, options = {}) {
22273
23200
  return exactError;
22274
23201
  }
22275
23202
  function mcpTransportLogger(serverId) {
22276
- const logFailure = (_message, ...args) => {
22277
- let error;
22278
- for (let index = args.length - 1; index >= 0; index -= 1) {
22279
- if (args[index] instanceof Error) {
22280
- error = args[index];
22281
- break;
22282
- }
22283
- }
22284
- console.warn(
22285
- "[mcp] transport operation failed",
22286
- mcpErrorFields(error, "mcp_transport_failed", serverId)
22287
- );
22288
- };
22289
- return {
22290
- namespace: "opengeni:mcp-transport",
22291
- debug: () => void 0,
22292
- error: logFailure,
22293
- warn: logFailure,
22294
- dontLogModelData: true,
22295
- dontLogToolData: true
22296
- };
23203
+ return createMcpTransportLogger(serverId, mcpErrorFields);
22297
23204
  }
22298
23205
  async function mcpServerRequestInit(settings, config) {
22299
23206
  if (isCodexAppsMcpServer(config)) {
@@ -22351,6 +23258,7 @@ async function signFirstPartyDelegatedBearer(settings, options) {
22351
23258
  workspaceId: options.workspaceId,
22352
23259
  subjectId: options.subjectId ?? "worker:first-party-mcp",
22353
23260
  ...options.subjectLabel ? { subjectLabel: options.subjectLabel } : {},
23261
+ ...options.credentialRestriction ? { credentialRestriction: options.credentialRestriction } : {},
22354
23262
  permissions: options.firstPartyPermissions ?? [...DEFAULT_FIRST_PARTY_MCP_PERMISSIONS3],
22355
23263
  principalKind: hasExactAttemptClaims ? "agent_attempt" : "service",
22356
23264
  firstPartyMcpTools: options.firstPartyTools ?? [...DEFAULT_FIRST_PARTY_MCP_TOOLS2],
@@ -23311,7 +24219,9 @@ function bindModelVisibleContextCapture(agent, onCapture) {
23311
24219
  provider,
23312
24220
  body,
23313
24221
  ...unavailableReason ? { unavailableReason } : {},
23314
- requestIndex: index ?? nextModelContextCaptureIndex(agent)
24222
+ requestIndex: index ?? nextModelContextCaptureIndex(agent),
24223
+ persistentLayers: persistentAgentInstructionInspectionFor(agent).layers,
24224
+ genesisTitleDirective: GENESIS_TITLE_DIRECTIVE
23315
24225
  })
23316
24226
  );
23317
24227
  };
@@ -23332,9 +24242,15 @@ async function runAgentStream(agent, input, settings, overrides = {}) {
23332
24242
  const scope = gate?.beginStream(overrides.signal);
23333
24243
  try {
23334
24244
  if (scope) agent.toolUseBehavior = scope.toolUseBehavior;
23335
- const stream = await withPreparedCompactionRequest(
23336
- agent,
23337
- () => runAgentStreamInternal(agent, input, settings, overrides, scope)
24245
+ const stream = await withModelCallLifecycle(
24246
+ {
24247
+ ...overrides.beforeModelRequest ? { beforeModelRequest: overrides.beforeModelRequest } : {},
24248
+ ...overrides.onModelResponse ? { onModelResponse: overrides.onModelResponse } : {}
24249
+ },
24250
+ () => withPreparedCompactionRequest(
24251
+ agent,
24252
+ () => runAgentStreamInternal(agent, input, settings, overrides, scope)
24253
+ )
23338
24254
  );
23339
24255
  if (scope) {
23340
24256
  const finish = () => scope.endStream(stream.cancelled);
@@ -26277,6 +27193,7 @@ export {
26277
27193
  normalizeVercelGatewayRequestBody,
26278
27194
  modelRequestPolicyForProvider,
26279
27195
  vercelGatewayRoutingFetch,
27196
+ beforeModelRequest,
26280
27197
  markModelPreparationFirstSandboxOperation,
26281
27198
  recordModelPreparationMeasurement,
26282
27199
  PROVIDER_QUOTA_EXHAUSTED_CODE,
@@ -26315,8 +27232,19 @@ export {
26315
27232
  projectAttemptToolResultForCaller,
26316
27233
  wrapAttemptToolExecute,
26317
27234
  wrapAttemptToolDefinitions,
27235
+ INSTRUCTION_PRECEDENCE,
27236
+ rigInstructions,
27237
+ workspaceEnvironmentInstructions,
27238
+ AGENT_PROMPT_MODULES,
27239
+ SESSION_INSTRUCTIONS_PREAMBLE,
27240
+ composeOperationalContract,
27241
+ composeModularAgentInstructions,
27242
+ DEFAULT_AGENT_IDENTITY,
27243
+ identityFromLegacyTemplate,
27244
+ resolveAgentIdentity,
26318
27245
  InputWaitYield,
26319
27246
  withRetainableSessionImageOutputHook,
27247
+ ResponsesStreamingTerminalError,
26320
27248
  OpenGeniChatCompletionsModel,
26321
27249
  OpenGeniResponsesModel,
26322
27250
  buildModelInstance,
@@ -26404,14 +27332,13 @@ export {
26404
27332
  persistentAgentInstructionInspectionFor,
26405
27333
  ConnectorActionBindingRejectedError,
26406
27334
  ConnectorActionExecutionError,
26407
- rigInstructions,
26408
- workspaceEnvironmentInstructions,
26409
27335
  coreInstructions,
26410
27336
  composeAgentInstructions,
26411
27337
  appendSessionInstructions,
26412
27338
  appendSessionGoal,
26413
27339
  appendPersistentSessionSettings,
26414
27340
  appendWorkspaceMemory,
27341
+ agentPromptResourcesFor,
26415
27342
  inspectPersistentAgentInstructions,
26416
27343
  appendCodemodeInstructions,
26417
27344
  appendGitCredentialBindingInstructions,
@@ -26483,4 +27410,4 @@ export {
26483
27410
  runAzureCliLoginHook,
26484
27411
  renderSessionGoalContext2 as renderSessionGoalContext
26485
27412
  };
26486
- //# sourceMappingURL=chunk-22M75RJF.js.map
27413
+ //# sourceMappingURL=chunk-ZY655LYR.js.map