@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/{chunk-SSB7VOLE.js → chunk-QYXOVIUK.js} +15 -4
- package/dist/chunk-QYXOVIUK.js.map +1 -0
- package/dist/{chunk-JGUQSAG5.js → chunk-RHB7ETON.js} +3078 -3030
- package/dist/chunk-RHB7ETON.js.map +1 -0
- package/dist/{index-DU-KXVlx.d.ts → index-Ciehex_q.d.ts} +13 -2
- package/dist/index.d.ts +11 -3
- package/dist/index.js +255 -43
- package/dist/index.js.map +1 -1
- package/dist/mcp-network.d.ts +1 -0
- package/dist/mcp-network.js +1 -1
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +1 -1
- package/package.json +3 -3
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/troubleshooting.md +1 -1
- package/src/codex-tool-search.ts +161 -36
- package/src/index.ts +209 -25
- package/src/mcp-network.ts +15 -3
- package/src/sandbox/index.ts +1 -0
- package/src/sandbox/routing/routing-session.ts +49 -4
- package/src/sandbox/run-credentials.ts +2 -2
- package/src/sandbox/turn-tool-cancellation.ts +29 -0
- package/src/sandbox/workspace-archive.ts +4 -1
- package/src/sandbox-computer.ts +5 -2
- package/dist/chunk-JGUQSAG5.js.map +0 -1
- package/dist/chunk-SSB7VOLE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -175,7 +175,7 @@ import {
|
|
|
175
175
|
withToolspaceTokenEnvironment,
|
|
176
176
|
withToolspaceTokenSession,
|
|
177
177
|
wrapCapabilityToolsForTurnCancellation
|
|
178
|
-
} from "./chunk-
|
|
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-
|
|
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
|
-
|
|
6996
|
-
You have access to tools from the following sources
|
|
6997
|
-
|
|
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(
|
|
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 (
|
|
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(
|
|
7072
|
-
|
|
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(
|
|
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 =
|
|
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. +
|
|
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
|
-
//
|
|
9496
|
+
// 5. + the per-session persona instructions (session-specific, so it
|
|
9401
9497
|
// refines both the workspace persona and the substrate note),
|
|
9402
|
-
//
|
|
9403
|
-
//
|
|
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
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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 = `
|
|
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 = `
|
|
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 ?
|
|
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,
|