@opengeni/runtime 0.13.4 → 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-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 +248 -40
- package/dist/index.js.map +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 +198 -23
- 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/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,
|
|
@@ -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
|
}
|
|
@@ -9754,6 +9860,10 @@ async function prepareAgentTools(settings, tools, options = {}) {
|
|
|
9754
9860
|
url,
|
|
9755
9861
|
name: config.name ?? config.id,
|
|
9756
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),
|
|
9757
9867
|
// codex_apps returns connector tools with empty `outputSchema: {}` that the
|
|
9758
9868
|
// MCP SDK's strict Tool schema rejects (fails the turn during tools/list);
|
|
9759
9869
|
// sanitize the response on the wire before validation. The namespace Set
|
|
@@ -9813,7 +9923,7 @@ async function prepareAgentTools(settings, tools, options = {}) {
|
|
|
9813
9923
|
const error = connectedBestEffort.errors.get(failed);
|
|
9814
9924
|
console.warn(
|
|
9815
9925
|
`[mcp] optional server "${failed.name}" failed to connect/list tools; skipping it for this turn`,
|
|
9816
|
-
error
|
|
9926
|
+
safeMcpErrorFields(error)
|
|
9817
9927
|
);
|
|
9818
9928
|
}
|
|
9819
9929
|
}
|
|
@@ -10093,6 +10203,41 @@ function safeMcpErrorFields(error) {
|
|
|
10093
10203
|
}
|
|
10094
10204
|
return { errorClass, status };
|
|
10095
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
|
+
}
|
|
10096
10241
|
function mcpErrorReason(fields) {
|
|
10097
10242
|
return fields.status === void 0 ? fields.errorClass : `${fields.errorClass} ${fields.status}`;
|
|
10098
10243
|
}
|
|
@@ -10271,8 +10416,11 @@ var PrefixedMcpServer = class {
|
|
|
10271
10416
|
bestEffort;
|
|
10272
10417
|
loggedListToolsFailure = false;
|
|
10273
10418
|
listedToolSchemaTokens = 0;
|
|
10419
|
+
modelToolSchemaAccountingDeferred = false;
|
|
10274
10420
|
connect() {
|
|
10275
|
-
return this.inner.connect()
|
|
10421
|
+
return this.inner.connect().catch((error) => {
|
|
10422
|
+
throw safeMcpTransportError(error);
|
|
10423
|
+
});
|
|
10276
10424
|
}
|
|
10277
10425
|
close() {
|
|
10278
10426
|
this.releaseAggregateBudget();
|
|
@@ -10310,7 +10458,15 @@ var PrefixedMcpServer = class {
|
|
|
10310
10458
|
}
|
|
10311
10459
|
/** Latest exact tools/list projection used to build the model request. */
|
|
10312
10460
|
modelToolSchemaTokens() {
|
|
10313
|
-
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;
|
|
10314
10470
|
}
|
|
10315
10471
|
async callTool(toolName, args, meta) {
|
|
10316
10472
|
const unprefixed = this.unprefixToolName(toolName);
|
|
@@ -11641,6 +11797,7 @@ function sandboxFileDownloadCommand(download, targetPath) {
|
|
|
11641
11797
|
const targetDir = posixPath.dirname(targetPath);
|
|
11642
11798
|
const tmpPath = `${targetPath}.opengeni-download-$$`;
|
|
11643
11799
|
return [
|
|
11800
|
+
"set +x",
|
|
11644
11801
|
"set -eu",
|
|
11645
11802
|
`mkdir -p -- ${shellQuote(targetDir)}`,
|
|
11646
11803
|
`if [ ! -f ${shellQuote(targetPath)} ]; then`,
|
|
@@ -11896,10 +12053,51 @@ function runtimeGitBindingDescriptors(resources) {
|
|
|
11896
12053
|
protocol: url.protocol.replace(/:$/, "").toLowerCase(),
|
|
11897
12054
|
host: url.host.toLowerCase(),
|
|
11898
12055
|
path,
|
|
11899
|
-
uri: resource.uri
|
|
12056
|
+
uri: resource.uri,
|
|
12057
|
+
mountPath: `/workspace/${resourceMountPath(resource)}`
|
|
11900
12058
|
};
|
|
11901
12059
|
});
|
|
11902
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
|
+
}
|
|
11903
12101
|
function gitCredentialBindingKey(provider, credentialBindingId) {
|
|
11904
12102
|
return `${provider}\0${credentialBindingId}`;
|
|
11905
12103
|
}
|
|
@@ -12170,6 +12368,7 @@ function gitCredentialHelperCommandLines(resources = [], bindings = []) {
|
|
|
12170
12368
|
const brokerOnlyProviders = [...providerBindingKinds.entries()].filter(([, counts]) => counts.brokered > 0 && counts.direct === 0).map(([provider]) => provider);
|
|
12171
12369
|
return [
|
|
12172
12370
|
...gitCredentialTokenWriterCommandLines(bindings),
|
|
12371
|
+
...gitCredentialBindingInventoryCommandLines(resources, bindings),
|
|
12173
12372
|
// Provision git/provider-CLI helpers at SETUP (runtime) before any clone
|
|
12174
12373
|
// runs. Renewal updates only token files and deliberately leaves these
|
|
12175
12374
|
// repository-specific host mappings intact.
|
|
@@ -12332,7 +12531,7 @@ function gitCredentialHelperCommandLines(resources = [], bindings = []) {
|
|
|
12332
12531
|
` *" $provider "*) printf '%s\\n' "$tool provider API authentication is host-brokered for this session; use the configured provider MCP tools" >&2; exit 2 ;;`,
|
|
12333
12532
|
" esac",
|
|
12334
12533
|
' case " $multi_binding_providers " in',
|
|
12335
|
-
` *" $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 ;;`,
|
|
12336
12535
|
" esac",
|
|
12337
12536
|
' case "$provider" in',
|
|
12338
12537
|
' github) token_file="${OPENGENI_GIT_TOKEN_FILE:-$HOME/.opengeni/git-token}" ;;',
|
|
@@ -12377,6 +12576,7 @@ function gitProviderTokenRefreshCommand(seeds) {
|
|
|
12377
12576
|
return "";
|
|
12378
12577
|
}
|
|
12379
12578
|
return [
|
|
12579
|
+
"set +x",
|
|
12380
12580
|
seedPrefix,
|
|
12381
12581
|
"set -eu",
|
|
12382
12582
|
'export HOME="${HOME:-/workspace}"',
|
|
@@ -12387,6 +12587,7 @@ function gitCredentialBindingTokenRefreshCommand(bindings) {
|
|
|
12387
12587
|
const seedPrefix = gitCredentialBindingSeedExportPrefix(bindings);
|
|
12388
12588
|
if (!seedPrefix) return "";
|
|
12389
12589
|
return [
|
|
12590
|
+
"set +x",
|
|
12390
12591
|
seedPrefix,
|
|
12391
12592
|
"set -eu",
|
|
12392
12593
|
'export HOME="${HOME:-/workspace}"',
|
|
@@ -12428,6 +12629,7 @@ async function refreshGitCredentialBindingTokenFiles(session, bindings, options
|
|
|
12428
12629
|
function repositoryCloneCommand(resources, bindings = []) {
|
|
12429
12630
|
assertUniqueResourceMountPaths(resources);
|
|
12430
12631
|
const commands = [
|
|
12632
|
+
"set +x",
|
|
12431
12633
|
"set -eu",
|
|
12432
12634
|
'export HOME="${HOME:-/workspace}"',
|
|
12433
12635
|
'export GIT_TERMINAL_PROMPT="${GIT_TERMINAL_PROMPT:-0}"',
|
|
@@ -12534,6 +12736,7 @@ function repositoryCloneCommand(resources, bindings = []) {
|
|
|
12534
12736
|
}
|
|
12535
12737
|
function toolspaceTokenSeedCommand(options = {}) {
|
|
12536
12738
|
return [
|
|
12739
|
+
"set +x",
|
|
12537
12740
|
"set -eu",
|
|
12538
12741
|
'export HOME="${HOME:-/workspace}"',
|
|
12539
12742
|
'if [ -n "${OPENGENI_TOOLSPACE_TOKEN_SEED:-}" ]; then',
|
|
@@ -12555,7 +12758,8 @@ async function runToolspaceTokenSeedHook(session, context) {
|
|
|
12555
12758
|
if (!context.toolspaceTokenSeed) {
|
|
12556
12759
|
return;
|
|
12557
12760
|
}
|
|
12558
|
-
const command = `
|
|
12761
|
+
const command = `set +x
|
|
12762
|
+
export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(context.toolspaceTokenSeed)}
|
|
12559
12763
|
${toolspaceTokenSeedCommand(
|
|
12560
12764
|
{
|
|
12561
12765
|
...context.toolspaceTokenFile ? { tokenFile: context.toolspaceTokenFile } : {},
|
|
@@ -12576,7 +12780,8 @@ ${toolspaceTokenSeedCommand(
|
|
|
12576
12780
|
assertSandboxCommandSucceeded(result, "Toolspace token seed hook");
|
|
12577
12781
|
}
|
|
12578
12782
|
async function refreshToolspaceTokenFile(session, token, options = {}) {
|
|
12579
|
-
const command = `
|
|
12783
|
+
const command = `set +x
|
|
12784
|
+
export OPENGENI_TOOLSPACE_TOKEN_SEED=${shellQuote(token)}
|
|
12580
12785
|
${toolspaceTokenSeedCommand(
|
|
12581
12786
|
{
|
|
12582
12787
|
...options.tokenFile ? { tokenFile: options.tokenFile } : {},
|
|
@@ -12724,7 +12929,8 @@ async function runRepositoryCloneHook(session, resources, context = { environmen
|
|
|
12724
12929
|
gitCredentialBindingSeedExportPrefix(gitCredentialBindings)
|
|
12725
12930
|
].filter(Boolean).join("\n");
|
|
12726
12931
|
const cloneCommand = repositoryCloneCommand(resources, gitCredentialBindings);
|
|
12727
|
-
const command = seedPrefix ?
|
|
12932
|
+
const command = seedPrefix ? `set +x
|
|
12933
|
+
${seedPrefix}
|
|
12728
12934
|
${cloneCommand}` : cloneCommand;
|
|
12729
12935
|
const result = await runSandboxLifecycleCommand(
|
|
12730
12936
|
session,
|
|
@@ -12755,6 +12961,7 @@ ${cloneCommand}` : cloneCommand;
|
|
|
12755
12961
|
}
|
|
12756
12962
|
function azureCliLoginCommand() {
|
|
12757
12963
|
return [
|
|
12964
|
+
"set +x",
|
|
12758
12965
|
'export HOME="${HOME:-/workspace}"',
|
|
12759
12966
|
'mkdir -p "$HOME/.azure"',
|
|
12760
12967
|
'CLIENT_ID="${AZURE_CLIENT_ID:-${ARM_CLIENT_ID:-}}"',
|
|
@@ -13235,6 +13442,7 @@ export {
|
|
|
13235
13442
|
agentErrorToControlError,
|
|
13236
13443
|
agentsErrorRunState,
|
|
13237
13444
|
appendGenesisTitleDirective,
|
|
13445
|
+
appendGitCredentialBindingInstructions,
|
|
13238
13446
|
appendPersistentSessionSettings,
|
|
13239
13447
|
appendSessionInstructions,
|
|
13240
13448
|
appendToolspaceInstructions,
|