@opengeni/runtime 0.13.3 → 0.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -175,7 +175,7 @@ import {
175
175
  withToolspaceTokenEnvironment,
176
176
  withToolspaceTokenSession,
177
177
  wrapCapabilityToolsForTurnCancellation
178
- } from "./chunk-JGUQSAG5.js";
178
+ } from "./chunk-RHB7ETON.js";
179
179
  import {
180
180
  getSkillLibraryEntry,
181
181
  isSkillLibraryEntryId,
@@ -186,7 +186,10 @@ import {
186
186
  MCP_MAX_CONCURRENT_SERVER_OPERATIONS,
187
187
  MCP_MAX_TOOL_DEFINITION_BYTES,
188
188
  MCP_MAX_TOOL_RESULT_BYTES,
189
+ MCP_MAX_TOOL_SEARCH_DESCRIPTION_BYTES,
189
190
  MCP_MAX_TOOL_SEARCH_DISCLOSURE_BYTES,
191
+ MCP_MAX_TOOL_SEARCH_SOURCES,
192
+ MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH,
190
193
  McpAggregateToolListBudget,
191
194
  assertMcpPayloadWithinBytes,
192
195
  assertMcpServerSelectionWithinBounds,
@@ -197,7 +200,7 @@ import {
197
200
  mcpOuterConnectTimeoutMs,
198
201
  mcpSerializedSizeBytes,
199
202
  undiciFetch
200
- } from "./chunk-SSB7VOLE.js";
203
+ } from "./chunk-QYXOVIUK.js";
201
204
  import {
202
205
  MemorySession,
203
206
  connectMcpServers
@@ -272,6 +275,7 @@ import {
272
275
  normalizeResourceMountPath,
273
276
  prefixedMcpToolName as sharedPrefixedMcpToolName,
274
277
  resourceMountPath,
278
+ redactSensitiveText as redactSensitiveText2,
275
279
  sessionEventMediaPreview,
276
280
  sessionEventMediaPreviewFromDataUrl,
277
281
  signDelegatedAccessToken,
@@ -6883,6 +6887,58 @@ var MAX_SEARCH_LIMIT = 20;
6883
6887
  function isCodexAppsFunctionTool(tool2) {
6884
6888
  return !!tool2 && typeof tool2 === "object" && tool2.type === "function" && typeof tool2.name === "string" && tool2.name.startsWith(CODEX_APPS_TOOL_PREFIX);
6885
6889
  }
6890
+ var MCP_TOOL_NAME_SEPARATOR = "__";
6891
+ var MANDATORY_FIRST_PARTY_MCP_SERVER_ID = "opengeni";
6892
+ var NO_MCP_SERVER_IDS = /* @__PURE__ */ new Set();
6893
+ function mcpServerIdForTool(tool2, mcpServerIds) {
6894
+ if (!tool2 || typeof tool2 !== "object") return null;
6895
+ if (tool2.type !== "function") return null;
6896
+ const name = tool2.name;
6897
+ if (typeof name !== "string") return null;
6898
+ let match = null;
6899
+ for (const serverId of mcpServerIds) {
6900
+ if (typeof serverId !== "string" || serverId.length === 0 || !name.startsWith(`${serverId}${MCP_TOOL_NAME_SEPARATOR}`)) {
6901
+ continue;
6902
+ }
6903
+ if (match === null || serverId.length > match.length) {
6904
+ match = serverId;
6905
+ }
6906
+ }
6907
+ return match;
6908
+ }
6909
+ function isSearchableMcpFunctionTool(tool2, mcpServerIds = NO_MCP_SERVER_IDS) {
6910
+ const serverId = mcpServerIdForTool(tool2, mcpServerIds);
6911
+ return serverId !== null && serverId !== MANDATORY_FIRST_PARTY_MCP_SERVER_ID;
6912
+ }
6913
+ function truncateUtf8(value, maxBytes) {
6914
+ if (Buffer.byteLength(value) <= maxBytes) return value;
6915
+ let output = "";
6916
+ for (const character of value) {
6917
+ const candidate = output + character;
6918
+ if (Buffer.byteLength(candidate) > maxBytes) break;
6919
+ output = candidate;
6920
+ }
6921
+ return output;
6922
+ }
6923
+ function searchSourceForTool(tool2, mcpServerIds) {
6924
+ const serverId = mcpServerIdForTool(tool2, mcpServerIds);
6925
+ return serverId && serverId !== MANDATORY_FIRST_PARTY_MCP_SERVER_ID ? truncateUtf8(serverId, MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH) : null;
6926
+ }
6927
+ function searchSourcesForTools(connectorNamespaces, tools, mcpServerIds) {
6928
+ const sources = /* @__PURE__ */ new Set();
6929
+ for (const source of connectorNamespaces) {
6930
+ if (typeof source !== "string" || source.length === 0) continue;
6931
+ if (sources.size >= MCP_MAX_TOOL_SEARCH_SOURCES) break;
6932
+ sources.add(truncateUtf8(source, MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH));
6933
+ }
6934
+ for (const tool2 of tools) {
6935
+ const source = isSearchableMcpFunctionTool(tool2, mcpServerIds) && !isCodexAppsFunctionTool(tool2) ? searchSourceForTool(tool2, mcpServerIds) : null;
6936
+ if (!source || sources.has(source)) continue;
6937
+ if (sources.size >= MCP_MAX_TOOL_SEARCH_SOURCES) break;
6938
+ sources.add(source);
6939
+ }
6940
+ return sources;
6941
+ }
6886
6942
  var STOPWORDS = /* @__PURE__ */ new Set([
6887
6943
  "a",
6888
6944
  "an",
@@ -6987,14 +7043,23 @@ function parseSearchArgs(raw) {
6987
7043
  }
6988
7044
  function renderSearchToolDescription(connectorNamespaces) {
6989
7045
  const base = `Search the user's connected app tools by capability. Describe in plain language WHAT you need to do (for example: "send an email", "create a calendar event") rather than guessing exact tool names. Returns the matching connector tools, which then become callable.`;
6990
- const sources = Array.from(connectorNamespaces).filter((n) => typeof n === "string" && n.length > 0).sort();
7046
+ const sources = Array.from(connectorNamespaces).filter((n) => typeof n === "string" && n.length > 0).slice(0, MCP_MAX_TOOL_SEARCH_SOURCES).map((source) => truncateUtf8(source, MCP_MAX_TOOL_SEARCH_SOURCE_LABEL_LENGTH)).filter(Boolean).sort();
6991
7047
  if (sources.length === 0) {
6992
7048
  return `${base}
6993
7049
  Connected sources: none currently available.`;
6994
7050
  }
6995
- return `${base}
6996
- You have access to tools from the following sources:
6997
- ${sources.map((s) => `- ${s}`).join("\n")}`;
7051
+ const header = `${base}
7052
+ You have access to tools from the following sources:`;
7053
+ const lines = [];
7054
+ for (const source of sources) {
7055
+ const candidate = `${header}${[...lines, `- ${source}`].map((line) => `
7056
+ ${line}`).join("")}`;
7057
+ if (Buffer.byteLength(candidate) > MCP_MAX_TOOL_SEARCH_DESCRIPTION_BYTES) break;
7058
+ lines.push(`- ${source}`);
7059
+ }
7060
+ return lines.length > 0 ? `${header}
7061
+ ${lines.join("\n")}` : `${base}
7062
+ Connected sources: none currently available.`;
6998
7063
  }
6999
7064
  var SEARCH_TOOL_PARAMETERS = {
7000
7065
  type: "object",
@@ -7008,8 +7073,10 @@ var SEARCH_TOOL_PARAMETERS = {
7008
7073
  required: ["query"],
7009
7074
  additionalProperties: false
7010
7075
  };
7011
- function codexToolSearchExecutor(args) {
7012
- const deferred = (args.availableTools ?? []).filter(isCodexAppsFunctionTool);
7076
+ function codexToolSearchExecutor(args, mcpServerIds) {
7077
+ const deferred = (args.availableTools ?? []).filter(
7078
+ (tool2) => isSearchableMcpFunctionTool(tool2, mcpServerIds)
7079
+ );
7013
7080
  if (deferred.length === 0) return [];
7014
7081
  const { query, limit } = parseSearchArgs(args.toolCall?.arguments);
7015
7082
  const ranked = bm25RankTools(deferred, query, limit);
@@ -7047,45 +7114,54 @@ function resolveSearchToolDescription(connectorNamespaces, freeze) {
7047
7114
  }
7048
7115
  return rendered;
7049
7116
  }
7050
- function buildCodexToolSearchToolFromDescription(description) {
7117
+ function buildCodexToolSearchToolFromDescription(description, mcpServerIds) {
7051
7118
  return toolSearchTool({
7052
7119
  execution: "client",
7053
7120
  description,
7054
7121
  parameters: SEARCH_TOOL_PARAMETERS,
7055
- execute: codexToolSearchExecutor
7122
+ execute: (args) => codexToolSearchExecutor(args, mcpServerIds)
7056
7123
  });
7057
7124
  }
7058
7125
  function isToolSearchTool(tool2) {
7059
7126
  const t = tool2;
7060
7127
  return !!t && (t.name === "tool_search" || t.providerData?.type === "tool_search");
7061
7128
  }
7062
- function applyCodexToolSearch(tools, connectorNamespaces = NO_NAMESPACES, descriptionFreeze) {
7129
+ function applyCodexToolSearch(tools, connectorNamespaces = NO_NAMESPACES, descriptionFreeze, mcpServerIds = NO_MCP_SERVER_IDS) {
7063
7130
  for (const tool2 of tools) {
7064
- if (isCodexAppsFunctionTool(tool2) && tool2.deferLoading !== true) {
7131
+ if (isSearchableMcpFunctionTool(tool2, mcpServerIds) && tool2.deferLoading !== true) {
7065
7132
  tool2.deferLoading = true;
7066
7133
  }
7067
7134
  }
7068
7135
  if (tools.some(isToolSearchTool)) {
7069
7136
  return tools;
7070
7137
  }
7071
- const description = resolveSearchToolDescription(connectorNamespaces, descriptionFreeze);
7072
- return [...tools, buildCodexToolSearchToolFromDescription(description)];
7138
+ const description = resolveSearchToolDescription(
7139
+ searchSourcesForTools(connectorNamespaces, tools, mcpServerIds),
7140
+ descriptionFreeze
7141
+ );
7142
+ return [...tools, buildCodexToolSearchToolFromDescription(description, mcpServerIds)];
7073
7143
  }
7074
- function installCodexToolSearch(agent, connectorNamespaces = NO_NAMESPACES) {
7075
- installCodexToolSearchWithFreeze(agent, connectorNamespaces, { value: null });
7144
+ function installCodexToolSearch(agent, connectorNamespaces = NO_NAMESPACES, mcpServerIds = NO_MCP_SERVER_IDS) {
7145
+ installCodexToolSearchWithFreeze(agent, connectorNamespaces, mcpServerIds, { value: null });
7076
7146
  }
7077
- function installCodexToolSearchWithFreeze(agent, connectorNamespaces, descriptionFreeze) {
7147
+ function installCodexToolSearchWithFreeze(agent, connectorNamespaces, mcpServerIds, descriptionFreeze) {
7078
7148
  const originalGetAllTools = agent.getAllTools.bind(agent);
7079
7149
  agent.getAllTools = async (runContext) => applyCodexToolSearch(
7080
7150
  await originalGetAllTools(runContext),
7081
7151
  connectorNamespaces,
7082
- descriptionFreeze
7152
+ descriptionFreeze,
7153
+ mcpServerIds
7083
7154
  );
7084
7155
  const originalClone = agent.clone?.bind(agent);
7085
7156
  if (originalClone) {
7086
7157
  const cloneWithToolSearch = (config) => {
7087
7158
  const cloned = originalClone(config);
7088
- installCodexToolSearchWithFreeze(cloned, connectorNamespaces, descriptionFreeze);
7159
+ installCodexToolSearchWithFreeze(
7160
+ cloned,
7161
+ connectorNamespaces,
7162
+ mcpServerIds,
7163
+ descriptionFreeze
7164
+ );
7089
7165
  return cloned;
7090
7166
  };
7091
7167
  agent.clone = cloneWithToolSearch;
@@ -7630,6 +7706,7 @@ import {
7630
7706
  PointerAction,
7631
7707
  PointerButton
7632
7708
  } from "@opengeni/agent-proto";
7709
+ import { redactSensitiveText } from "@opengeni/contracts";
7633
7710
  function requireBoundSession(capabilityType, session) {
7634
7711
  if (!session) {
7635
7712
  throw new ComputerUnavailableError(`capability "${capabilityType}" used before bind(session)`);
@@ -7783,7 +7860,7 @@ var SandboxComputer = class {
7783
7860
  const output = sandboxCommandOutput(result);
7784
7861
  if (sandboxCommandStillRunning(result)) {
7785
7862
  console.warn(
7786
- `[SandboxComputer] action command did not finish before the ${ACTION_YIELD_MS}ms yield window \u2014 proceeding to screenshot: ${cmd}`
7863
+ `[SandboxComputer] action command did not finish before the ${ACTION_YIELD_MS}ms yield window \u2014 proceeding to screenshot: ${redactSensitiveText(cmd)}`
7787
7864
  );
7788
7865
  return output;
7789
7866
  }
@@ -8040,7 +8117,9 @@ var NativeDesktopComputer = class {
8040
8117
  break;
8041
8118
  }
8042
8119
  }
8043
- const reason = lastError instanceof Error ? lastError.message : String(lastError);
8120
+ const reason = redactSensitiveText(
8121
+ lastError instanceof Error ? lastError.message : String(lastError)
8122
+ );
8044
8123
  console.warn(
8045
8124
  `[NativeDesktopComputer] screenshot failed after ${attempt} attempt(s): ${reason}`
8046
8125
  );
@@ -8750,6 +8829,8 @@ function rejectField(rejectedFields, field) {
8750
8829
  }
8751
8830
 
8752
8831
  // src/index.ts
8832
+ process.env.OPENAI_AGENTS_DONT_LOG_MODEL_DATA = "1";
8833
+ process.env.OPENAI_AGENTS_DONT_LOG_TOOL_DATA = "1";
8753
8834
  setSelfhostedApplyDiff(
8754
8835
  applyDiff
8755
8836
  );
@@ -9319,6 +9400,19 @@ function appendWorkspaceMemory(composed, workspaceMemory) {
9319
9400
  function appendToolspaceInstructions(composed, toolspaceAvailable) {
9320
9401
  return toolspaceAvailable ? `${composed} ${TOOLSPACE_PROGRAMMATIC_DIRECTIVE}` : composed;
9321
9402
  }
9403
+ var GIT_BINDING_DISCOVERY_DIRECTIVE = "This managed sandbox has multiple credential bindings for at least one Git provider. Native Git selects credentials from the repository remote. For gh, glab, or az, run inside the intended attached repository so its origin selects the binding; when running elsewhere, inspect $HOME/.opengeni/git-bindings.json and set OPENGENI_GIT_BINDING to the listed credentialBindingId. The inventory contains identifiers and repository routes, never credential values. A binding marked git_http_broker is Git-only, so use the configured provider MCP tools for provider API operations on it.";
9404
+ function appendGitCredentialBindingInstructions(composed, bindings, activeSandboxBackend) {
9405
+ if (activeSandboxBackend === "selfhosted" || !bindings?.length) {
9406
+ return composed;
9407
+ }
9408
+ const bindingsByProvider = /* @__PURE__ */ new Map();
9409
+ for (const binding of bindings) {
9410
+ const ids = bindingsByProvider.get(binding.provider) ?? /* @__PURE__ */ new Set();
9411
+ ids.add(binding.credentialBindingId);
9412
+ bindingsByProvider.set(binding.provider, ids);
9413
+ }
9414
+ return [...bindingsByProvider.values()].some((ids) => ids.size > 1) ? `${composed} ${GIT_BINDING_DISCOVERY_DIRECTIVE}` : composed;
9415
+ }
9322
9416
  function appendGenesisTitleDirective(instructions, genesisTitleHint) {
9323
9417
  return genesisTitleHint ? `${instructions} ${GENESIS_TITLE_DIRECTIVE}` : instructions;
9324
9418
  }
@@ -9333,7 +9427,7 @@ var agentActiveSandboxBackend = /* @__PURE__ */ new WeakMap();
9333
9427
  var agentRigSetup = /* @__PURE__ */ new WeakMap();
9334
9428
  var agentRigCredentialHooks = /* @__PURE__ */ new WeakMap();
9335
9429
  function mcpToolErrorOutput(error) {
9336
- const details = error instanceof Error ? error.message : String(error);
9430
+ const details = redactSensitiveText2(error instanceof Error ? error.message : String(error));
9337
9431
  return {
9338
9432
  isError: true,
9339
9433
  content: [
@@ -9395,12 +9489,14 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
9395
9489
  // when a toolspace token was minted for this turn (feature enabled + a
9396
9490
  // per-turn seed — the mint gate, which includes selfhosted turns since
9397
9491
  // they now receive the token too) — appendToolspaceInstructions,
9398
- // 3. + workspace memory working set, ONLY when the workspace setting is on
9492
+ // 3. + managed-sandbox Git binding discovery, ONLY when one provider has
9493
+ // multiple credential bindings,
9494
+ // 4. + workspace memory working set, ONLY when the workspace setting is on
9399
9495
  // and the worker resolved a nonblank block — appendWorkspaceMemory,
9400
- // 4. + the per-session persona instructions (session-specific, so it
9496
+ // 5. + the per-session persona instructions (session-specific, so it
9401
9497
  // refines both the workspace persona and the substrate note),
9402
- // 5. + host context for this exact turn, when supplied,
9403
- // 6. + durable session-setting state (title present + child notification
9498
+ // 6. + host context for this exact turn, when supplied,
9499
+ // 7. + durable session-setting state (title present + child notification
9404
9500
  // mode), when supplied by the worker,
9405
9501
  // The genesis title directive is deliberately NOT part of this persistent
9406
9502
  // string. runAgentStream injects it into the first model call only.
@@ -9408,13 +9504,17 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
9408
9504
  appendTurnInstructions(
9409
9505
  appendSessionInstructions(
9410
9506
  appendWorkspaceMemory(
9411
- appendToolspaceInstructions(
9412
- composeAgentInstructions(
9413
- options.instructionsTemplate ?? settings.agentInstructionsTemplate,
9414
- options.workspaceEnvironment,
9415
- options.rig
9507
+ appendGitCredentialBindingInstructions(
9508
+ appendToolspaceInstructions(
9509
+ composeAgentInstructions(
9510
+ options.instructionsTemplate ?? settings.agentInstructionsTemplate,
9511
+ options.workspaceEnvironment,
9512
+ options.rig
9513
+ ),
9514
+ settings.toolspaceEnabled && Boolean(options.toolspaceTokenSeed)
9416
9515
  ),
9417
- settings.toolspaceEnabled && Boolean(options.toolspaceTokenSeed)
9516
+ options.gitCredentialBindings,
9517
+ options.activeSandboxBackend
9418
9518
  ),
9419
9519
  options.workspaceMemory
9420
9520
  ),
@@ -9533,9 +9633,15 @@ function buildOpenGeniAgent(settings, resources, options = {}) {
9533
9633
  }
9534
9634
  function maybeInstallCodexToolSearch(agent, settings, options) {
9535
9635
  if (settings.codexToolSearchEnabled && options.structuredToolTransport === false) {
9636
+ const mcpServers = options.mcpServers ?? [];
9637
+ for (const server of mcpServers) {
9638
+ if (server.name === "opengeni") continue;
9639
+ server.deferModelToolSchemaAccounting?.();
9640
+ }
9536
9641
  installCodexToolSearch(
9537
9642
  agent,
9538
- options.codexConnectorNamespaces ?? /* @__PURE__ */ new Set()
9643
+ options.codexConnectorNamespaces ?? /* @__PURE__ */ new Set(),
9644
+ new Set(mcpServers.map((server) => server.name))
9539
9645
  );
9540
9646
  }
9541
9647
  }
@@ -9725,7 +9831,8 @@ async function prepareAgentTools(settings, tools, options = {}) {
9725
9831
  }
9726
9832
  const registry = new Map(settings.mcpServers.map((server) => [server.id, server]));
9727
9833
  const aggregateToolBudget = new McpAggregateToolListBudget();
9728
- const mcpFetchImpl = options.mcpFetchImpl ?? undiciFetch;
9834
+ const useBunNativeFetch = options.mcpFetchImpl === void 0 && !!process.versions.bun;
9835
+ const mcpFetchImpl = options.mcpFetchImpl ?? (useBunNativeFetch ? globalThis.fetch.bind(globalThis) : undiciFetch);
9729
9836
  const servers = await boundedParallelMap(
9730
9837
  tools,
9731
9838
  MCP_MAX_CONCURRENT_SERVER_OPERATIONS,
@@ -9740,7 +9847,10 @@ async function prepareAgentTools(settings, tools, options = {}) {
9740
9847
  const guardedFetch = guardedMcpFetch(
9741
9848
  firstParty ? { ...settings, integrationsAllowPrivateNetworkTargets: true } : settings,
9742
9849
  baseFetch,
9743
- firstParty ? { requireHttpsOutsideLocalTest: false } : {}
9850
+ {
9851
+ ...firstParty ? { requireHttpsOutsideLocalTest: false } : {},
9852
+ ...useBunNativeFetch ? { pinResolvedDestination: false } : {}
9853
+ }
9744
9854
  );
9745
9855
  const fetchImpl = config.connectionRef ? connectionBrokerFetch(guardedFetch, config, options) : firstParty ? firstPartyAuthFetch(guardedFetch, settings, options) : guardedFetch;
9746
9856
  const optional = tool2.optional === true;
@@ -9750,6 +9860,10 @@ async function prepareAgentTools(settings, tools, options = {}) {
9750
9860
  url,
9751
9861
  name: config.name ?? config.id,
9752
9862
  cacheToolsList: config.cacheToolsList,
9863
+ // The upstream transport logger receives raw thrown errors, whose
9864
+ // messages may contain response bodies, URLs, headers, or echoed
9865
+ // credentials. Keep its diagnostic surface structural only.
9866
+ logger: safeMcpTransportLogger(config.id),
9753
9867
  // codex_apps returns connector tools with empty `outputSchema: {}` that the
9754
9868
  // MCP SDK's strict Tool schema rejects (fails the turn during tools/list);
9755
9869
  // sanitize the response on the wire before validation. The namespace Set
@@ -9809,7 +9923,7 @@ async function prepareAgentTools(settings, tools, options = {}) {
9809
9923
  const error = connectedBestEffort.errors.get(failed);
9810
9924
  console.warn(
9811
9925
  `[mcp] optional server "${failed.name}" failed to connect/list tools; skipping it for this turn`,
9812
- error instanceof Error ? error.message : error
9926
+ safeMcpErrorFields(error)
9813
9927
  );
9814
9928
  }
9815
9929
  }
@@ -10089,6 +10203,41 @@ function safeMcpErrorFields(error) {
10089
10203
  }
10090
10204
  return { errorClass, status };
10091
10205
  }
10206
+ function safeMcpTransportError(error) {
10207
+ const fields = safeMcpErrorFields(error);
10208
+ const safeError = new Error(
10209
+ `MCP transport operation failed (${mcpErrorReason(fields)})`
10210
+ );
10211
+ safeError.name = "McpTransportError";
10212
+ if (fields.status !== void 0) {
10213
+ safeError.status = fields.status;
10214
+ safeError.code = fields.status;
10215
+ }
10216
+ return safeError;
10217
+ }
10218
+ function safeMcpTransportLogger(serverId) {
10219
+ const logFailure = (_message, ...args) => {
10220
+ let error;
10221
+ for (let index = args.length - 1; index >= 0; index -= 1) {
10222
+ if (args[index] instanceof Error) {
10223
+ error = args[index];
10224
+ break;
10225
+ }
10226
+ }
10227
+ console.warn("[mcp] transport operation failed", {
10228
+ serverId,
10229
+ ...safeMcpErrorFields(error)
10230
+ });
10231
+ };
10232
+ return {
10233
+ namespace: "opengeni:mcp-transport",
10234
+ debug: () => void 0,
10235
+ error: logFailure,
10236
+ warn: logFailure,
10237
+ dontLogModelData: true,
10238
+ dontLogToolData: true
10239
+ };
10240
+ }
10092
10241
  function mcpErrorReason(fields) {
10093
10242
  return fields.status === void 0 ? fields.errorClass : `${fields.errorClass} ${fields.status}`;
10094
10243
  }
@@ -10267,8 +10416,11 @@ var PrefixedMcpServer = class {
10267
10416
  bestEffort;
10268
10417
  loggedListToolsFailure = false;
10269
10418
  listedToolSchemaTokens = 0;
10419
+ modelToolSchemaAccountingDeferred = false;
10270
10420
  connect() {
10271
- return this.inner.connect();
10421
+ return this.inner.connect().catch((error) => {
10422
+ throw safeMcpTransportError(error);
10423
+ });
10272
10424
  }
10273
10425
  close() {
10274
10426
  this.releaseAggregateBudget();
@@ -10306,7 +10458,15 @@ var PrefixedMcpServer = class {
10306
10458
  }
10307
10459
  /** Latest exact tools/list projection used to build the model request. */
10308
10460
  modelToolSchemaTokens() {
10309
- return this.listedToolSchemaTokens;
10461
+ return this.modelToolSchemaAccountingDeferred ? 0 : this.listedToolSchemaTokens;
10462
+ }
10463
+ /**
10464
+ * Keep model-input accounting aligned with Codex `defer_loading`: the full
10465
+ * schema is not provider context until a tool_search_output discloses it.
10466
+ * Instances are turn-local, so this cannot leak into a non-Codex turn.
10467
+ */
10468
+ deferModelToolSchemaAccounting() {
10469
+ this.modelToolSchemaAccountingDeferred = true;
10310
10470
  }
10311
10471
  async callTool(toolName, args, meta) {
10312
10472
  const unprefixed = this.unprefixToolName(toolName);
@@ -11637,6 +11797,7 @@ function sandboxFileDownloadCommand(download, targetPath) {
11637
11797
  const targetDir = posixPath.dirname(targetPath);
11638
11798
  const tmpPath = `${targetPath}.opengeni-download-$$`;
11639
11799
  return [
11800
+ "set +x",
11640
11801
  "set -eu",
11641
11802
  `mkdir -p -- ${shellQuote(targetDir)}`,
11642
11803
  `if [ ! -f ${shellQuote(targetPath)} ]; then`,
@@ -11892,10 +12053,51 @@ function runtimeGitBindingDescriptors(resources) {
11892
12053
  protocol: url.protocol.replace(/:$/, "").toLowerCase(),
11893
12054
  host: url.host.toLowerCase(),
11894
12055
  path,
11895
- uri: resource.uri
12056
+ uri: resource.uri,
12057
+ mountPath: `/workspace/${resourceMountPath(resource)}`
11896
12058
  };
11897
12059
  });
11898
12060
  }
12061
+ function gitCredentialBindingInventoryCommandLines(resources, bindings) {
12062
+ const bindingTransports = new Map(
12063
+ bindings.map((binding) => [
12064
+ gitCredentialBindingKey(binding.provider, binding.credentialBindingId),
12065
+ binding.transport?.kind === "http_broker" ? "git_http_broker" : "direct_token"
12066
+ ])
12067
+ );
12068
+ const entries = /* @__PURE__ */ new Map();
12069
+ for (const descriptor of runtimeGitBindingDescriptors(resources)) {
12070
+ const key = gitCredentialBindingKey(descriptor.provider, descriptor.credentialBindingId);
12071
+ const transport = bindingTransports.get(key);
12072
+ if (!transport) continue;
12073
+ const entry = entries.get(key) ?? {
12074
+ credentialBindingId: descriptor.credentialBindingId,
12075
+ provider: descriptor.provider,
12076
+ transport,
12077
+ repositories: []
12078
+ };
12079
+ entry.repositories.push({ uri: descriptor.uri, mountPath: descriptor.mountPath });
12080
+ entries.set(key, entry);
12081
+ }
12082
+ const inventory = `${JSON.stringify(
12083
+ {
12084
+ version: 1,
12085
+ bindings: [...entries.values()]
12086
+ },
12087
+ null,
12088
+ 2
12089
+ )}
12090
+ `;
12091
+ return [
12092
+ 'git_binding_inventory="${OPENGENI_GIT_BINDINGS_FILE:-$HOME/.opengeni/git-bindings.json}"',
12093
+ 'mkdir -p "$(dirname "$git_binding_inventory")"',
12094
+ 'inventory_umask="$(umask)"',
12095
+ "umask 077",
12096
+ `printf '%s' ${shellQuote(inventory)} > "$git_binding_inventory.tmp.$$"`,
12097
+ 'mv -f "$git_binding_inventory.tmp.$$" "$git_binding_inventory"',
12098
+ 'umask "$inventory_umask"'
12099
+ ];
12100
+ }
11899
12101
  function gitCredentialBindingKey(provider, credentialBindingId) {
11900
12102
  return `${provider}\0${credentialBindingId}`;
11901
12103
  }
@@ -12166,6 +12368,7 @@ function gitCredentialHelperCommandLines(resources = [], bindings = []) {
12166
12368
  const brokerOnlyProviders = [...providerBindingKinds.entries()].filter(([, counts]) => counts.brokered > 0 && counts.direct === 0).map(([provider]) => provider);
12167
12369
  return [
12168
12370
  ...gitCredentialTokenWriterCommandLines(bindings),
12371
+ ...gitCredentialBindingInventoryCommandLines(resources, bindings),
12169
12372
  // Provision git/provider-CLI helpers at SETUP (runtime) before any clone
12170
12373
  // runs. Renewal updates only token files and deliberately leaves these
12171
12374
  // repository-specific host mappings intact.
@@ -12328,7 +12531,7 @@ function gitCredentialHelperCommandLines(resources = [], bindings = []) {
12328
12531
  ` *" $provider "*) printf '%s\\n' "$tool provider API authentication is host-brokered for this session; use the configured provider MCP tools" >&2; exit 2 ;;`,
12329
12532
  " esac",
12330
12533
  ' case " $multi_binding_providers " in',
12331
- ` *" $provider "*) printf '%s\\n' "Unable to select one of multiple $provider credentials; run inside an attached repository or set OPENGENI_GIT_BINDING" >&2; exit 2 ;;`,
12534
+ ` *" $provider "*) printf '%s\\n' "Unable to select one of multiple $provider credentials; run inside an attached repository, or inspect \${OPENGENI_GIT_BINDINGS_FILE:-$HOME/.opengeni/git-bindings.json} and set OPENGENI_GIT_BINDING" >&2; exit 2 ;;`,
12332
12535
  " esac",
12333
12536
  ' case "$provider" in',
12334
12537
  ' github) token_file="${OPENGENI_GIT_TOKEN_FILE:-$HOME/.opengeni/git-token}" ;;',
@@ -12373,6 +12576,7 @@ function gitProviderTokenRefreshCommand(seeds) {
12373
12576
  return "";
12374
12577
  }
12375
12578
  return [
12579
+ "set +x",
12376
12580
  seedPrefix,
12377
12581
  "set -eu",
12378
12582
  'export HOME="${HOME:-/workspace}"',
@@ -12383,6 +12587,7 @@ function gitCredentialBindingTokenRefreshCommand(bindings) {
12383
12587
  const seedPrefix = gitCredentialBindingSeedExportPrefix(bindings);
12384
12588
  if (!seedPrefix) return "";
12385
12589
  return [
12590
+ "set +x",
12386
12591
  seedPrefix,
12387
12592
  "set -eu",
12388
12593
  'export HOME="${HOME:-/workspace}"',
@@ -12424,6 +12629,7 @@ async function refreshGitCredentialBindingTokenFiles(session, bindings, options
12424
12629
  function repositoryCloneCommand(resources, bindings = []) {
12425
12630
  assertUniqueResourceMountPaths(resources);
12426
12631
  const commands = [
12632
+ "set +x",
12427
12633
  "set -eu",
12428
12634
  'export HOME="${HOME:-/workspace}"',
12429
12635
  'export GIT_TERMINAL_PROMPT="${GIT_TERMINAL_PROMPT:-0}"',
@@ -12530,6 +12736,7 @@ function repositoryCloneCommand(resources, bindings = []) {
12530
12736
  }
12531
12737
  function toolspaceTokenSeedCommand(options = {}) {
12532
12738
  return [
12739
+ "set +x",
12533
12740
  "set -eu",
12534
12741
  'export HOME="${HOME:-/workspace}"',
12535
12742
  'if [ -n "${OPENGENI_TOOLSPACE_TOKEN_SEED:-}" ]; then',
@@ -12551,7 +12758,8 @@ async function runToolspaceTokenSeedHook(session, context) {
12551
12758
  if (!context.toolspaceTokenSeed) {
12552
12759
  return;
12553
12760
  }
12554
- const command = `export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(context.toolspaceTokenSeed)}
12761
+ const command = `set +x
12762
+ export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(context.toolspaceTokenSeed)}
12555
12763
  ${toolspaceTokenSeedCommand(
12556
12764
  {
12557
12765
  ...context.toolspaceTokenFile ? { tokenFile: context.toolspaceTokenFile } : {},
@@ -12572,7 +12780,8 @@ ${toolspaceTokenSeedCommand(
12572
12780
  assertSandboxCommandSucceeded(result, "Toolspace token seed hook");
12573
12781
  }
12574
12782
  async function refreshToolspaceTokenFile(session, token, options = {}) {
12575
- const command = `export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(token)}
12783
+ const command = `set +x
12784
+ export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(token)}
12576
12785
  ${toolspaceTokenSeedCommand(
12577
12786
  {
12578
12787
  ...options.tokenFile ? { tokenFile: options.tokenFile } : {},
@@ -12720,7 +12929,8 @@ async function runRepositoryCloneHook(session, resources, context = { environmen
12720
12929
  gitCredentialBindingSeedExportPrefix(gitCredentialBindings)
12721
12930
  ].filter(Boolean).join("\n");
12722
12931
  const cloneCommand = repositoryCloneCommand(resources, gitCredentialBindings);
12723
- const command = seedPrefix ? `${seedPrefix}
12932
+ const command = seedPrefix ? `set +x
12933
+ ${seedPrefix}
12724
12934
  ${cloneCommand}` : cloneCommand;
12725
12935
  const result = await runSandboxLifecycleCommand(
12726
12936
  session,
@@ -12751,6 +12961,7 @@ ${cloneCommand}` : cloneCommand;
12751
12961
  }
12752
12962
  function azureCliLoginCommand() {
12753
12963
  return [
12964
+ "set +x",
12754
12965
  'export HOME="${HOME:-/workspace}"',
12755
12966
  'mkdir -p "$HOME/.azure"',
12756
12967
  'CLIENT_ID="${AZURE_CLIENT_ID:-${ARM_CLIENT_ID:-}}"',
@@ -13231,6 +13442,7 @@ export {
13231
13442
  agentErrorToControlError,
13232
13443
  agentsErrorRunState,
13233
13444
  appendGenesisTitleDirective,
13445
+ appendGitCredentialBindingInstructions,
13234
13446
  appendPersistentSessionSettings,
13235
13447
  appendSessionInstructions,
13236
13448
  appendToolspaceInstructions,