@opengeni/codemode 0.4.25-canary.0 → 0.4.27-canary.0
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/README.md +44 -4
- package/dist/declarations.d.ts +2 -2
- package/dist/index.d.ts +29 -41
- package/dist/index.js +283 -474
- package/dist/index.js.map +1 -1
- package/dist/site.d.ts +9 -0
- package/package.json +3 -3
- package/src/declarations.ts +13 -326
- package/src/index.ts +288 -317
- package/src/site.ts +131 -0
package/dist/index.js
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import {
|
|
3
|
-
import Ajv from "ajv";
|
|
4
|
-
import Ajv2019 from "ajv/dist/2019.js";
|
|
5
|
-
import Ajv2020 from "ajv/dist/2020.js";
|
|
2
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
6
3
|
import {
|
|
7
4
|
ATTEMPT_TOOL_CATALOG_VERSION,
|
|
8
5
|
ATTEMPT_TOOL_CATALOG_MAX_BYTES,
|
|
9
6
|
AttemptToolCall,
|
|
10
7
|
AttemptToolCatalog,
|
|
11
|
-
AttemptToolCatalogEntry,
|
|
12
8
|
AttemptToolResult,
|
|
13
9
|
CodemodeCallSubmission,
|
|
14
10
|
CodemodeOperation,
|
|
15
11
|
CodemodeDispatchAck,
|
|
16
12
|
CodemodeDispatchRequest,
|
|
17
|
-
|
|
18
|
-
OPENGENI_API_CONTRACT_REVISION,
|
|
19
|
-
isToolResultSpilledReceipt
|
|
13
|
+
AttemptToolCaller
|
|
20
14
|
} from "@opengeni/contracts";
|
|
15
|
+
import {
|
|
16
|
+
ToolGatewayApprovalRequiredError as AttemptToolApprovalRequiredError,
|
|
17
|
+
ToolGatewayCatalogIntegrityError as AttemptToolCatalogIntegrityError,
|
|
18
|
+
ToolGatewayCatalogStaleError as AttemptToolCatalogStaleError,
|
|
19
|
+
ToolGatewayCatalogTooLargeError as AttemptToolCatalogTooLargeError,
|
|
20
|
+
ToolGatewayInputValidationError as AttemptToolInputValidationError,
|
|
21
|
+
ToolGatewayOutputValidationError as AttemptToolOutputValidationError,
|
|
22
|
+
ToolGatewayPathCollisionError as AttemptToolPathCollisionError,
|
|
23
|
+
ToolGatewayToolNotFoundError as AttemptToolNotFoundError,
|
|
24
|
+
digestCanonicalJson,
|
|
25
|
+
prepareToolGatewayDefinitions
|
|
26
|
+
} from "@opengeni/tool-gateway";
|
|
21
27
|
|
|
22
28
|
// src/environment.ts
|
|
23
29
|
import { readFile } from "fs/promises";
|
|
@@ -1067,314 +1073,138 @@ function createOpenGeniCodemode(client = () => environmentCodemodeClient()) {
|
|
|
1067
1073
|
var openGeni = createOpenGeniCodemode();
|
|
1068
1074
|
|
|
1069
1075
|
// src/declarations.ts
|
|
1076
|
+
import { generateToolDeclarations, jsonSchemaToTypeScript } from "@opengeni/tool-gateway";
|
|
1070
1077
|
function generateCodemodeDeclarations(catalog, options = {}) {
|
|
1071
1078
|
const verified = parseVerifiedAttemptToolCatalog(catalog);
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
" interface CodemodeGeneratedTools {",
|
|
1082
|
-
...renderChildren(root, 4),
|
|
1083
|
-
" }",
|
|
1084
|
-
"}",
|
|
1085
|
-
"",
|
|
1086
|
-
"export {};",
|
|
1087
|
-
""
|
|
1088
|
-
].join("\n");
|
|
1089
|
-
}
|
|
1090
|
-
function jsonSchemaToTypeScript(schema) {
|
|
1091
|
-
return schemaType(schema, schema, /* @__PURE__ */ new Set(), 0);
|
|
1092
|
-
}
|
|
1093
|
-
function namespaceNode() {
|
|
1094
|
-
return { children: /* @__PURE__ */ new Map(), entry: null };
|
|
1095
|
-
}
|
|
1096
|
-
function insertEntry(root, entry) {
|
|
1097
|
-
let node = root;
|
|
1098
|
-
for (const [index, segment] of entry.codemodePath.entries()) {
|
|
1099
|
-
if (node.entry) {
|
|
1100
|
-
throw new Error(
|
|
1101
|
-
`Codemode declaration path ${entry.codemodePath.join(".")} extends a tool leaf`
|
|
1102
|
-
);
|
|
1103
|
-
}
|
|
1104
|
-
let child = node.children.get(segment);
|
|
1105
|
-
if (!child) {
|
|
1106
|
-
child = namespaceNode();
|
|
1107
|
-
node.children.set(segment, child);
|
|
1108
|
-
}
|
|
1109
|
-
node = child;
|
|
1110
|
-
if (index === entry.codemodePath.length - 1) {
|
|
1111
|
-
if (node.entry || node.children.size > 0) {
|
|
1112
|
-
throw new Error(`Codemode declaration path ${entry.codemodePath.join(".")} collides`);
|
|
1113
|
-
}
|
|
1114
|
-
node.entry = entry;
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
function renderChildren(node, indent) {
|
|
1119
|
-
const lines = [];
|
|
1120
|
-
for (const [name, child] of [...node.children].sort(
|
|
1121
|
-
([left], [right]) => left.localeCompare(right)
|
|
1122
|
-
)) {
|
|
1123
|
-
if (child.entry) {
|
|
1124
|
-
lines.push(...renderTool(name, child.entry, indent));
|
|
1125
|
-
continue;
|
|
1079
|
+
return generateToolDeclarations(
|
|
1080
|
+
{ digest: verified.digest, entries: verified.entries },
|
|
1081
|
+
{
|
|
1082
|
+
moduleSpecifier: options.moduleSpecifier ?? "@opengeni/codemode",
|
|
1083
|
+
interfaceName: "CodemodeGeneratedTools",
|
|
1084
|
+
callOptionsType: "CodemodeCallOptions",
|
|
1085
|
+
fallbackResultType: "CodemodeToolResult",
|
|
1086
|
+
generatedBy: "@opengeni/codemode via @opengeni/tool-gateway",
|
|
1087
|
+
catalogDigestLabel: "Attempt catalog digest"
|
|
1126
1088
|
}
|
|
1127
|
-
lines.push(`${spaces(indent)}readonly ${name}: {`);
|
|
1128
|
-
lines.push(...renderChildren(child, indent + 2));
|
|
1129
|
-
lines.push(`${spaces(indent)}};`);
|
|
1130
|
-
}
|
|
1131
|
-
return lines;
|
|
1132
|
-
}
|
|
1133
|
-
function renderTool(name, entry, indent) {
|
|
1134
|
-
const input = schemaType(entry.inputSchema, entry.inputSchema, /* @__PURE__ */ new Set(), 0);
|
|
1135
|
-
const output = entry.outputSchema ? schemaType(entry.outputSchema, entry.outputSchema, /* @__PURE__ */ new Set(), 0) : "CodemodeToolResult";
|
|
1136
|
-
const optionalArguments = rootObjectArgumentsAreOptional(entry.inputSchema);
|
|
1137
|
-
const description = boundedDoc(entry.description ?? entry.title);
|
|
1138
|
-
return [
|
|
1139
|
-
...description ? renderDoc(description, indent) : [],
|
|
1140
|
-
`${spaces(indent)}readonly ${name}: (`,
|
|
1141
|
-
`${spaces(indent + 2)}argumentsValue${optionalArguments ? "?" : ""}: ${input},`,
|
|
1142
|
-
`${spaces(indent + 2)}options?: CodemodeCallOptions,`,
|
|
1143
|
-
`${spaces(indent)}) => Promise<${output}>;`
|
|
1144
|
-
];
|
|
1145
|
-
}
|
|
1146
|
-
function rootObjectArgumentsAreOptional(schema) {
|
|
1147
|
-
if (!isSchemaObject(schema)) return false;
|
|
1148
|
-
const required = Array.isArray(schema.required) ? schema.required.filter((value) => typeof value === "string") : [];
|
|
1149
|
-
return required.length === 0 && (schema.type === "object" || isSchemaObject(schema.properties));
|
|
1150
|
-
}
|
|
1151
|
-
function schemaType(schema, rootSchema, resolvingRefs, depth) {
|
|
1152
|
-
if (depth > 48 || schema === true) return "unknown";
|
|
1153
|
-
if (schema === false) return "never";
|
|
1154
|
-
if (!isSchemaObject(schema)) return "unknown";
|
|
1155
|
-
if (typeof schema.$ref === "string") {
|
|
1156
|
-
const reference = schema.$ref;
|
|
1157
|
-
if (!reference.startsWith("#/") || resolvingRefs.has(reference)) return "unknown";
|
|
1158
|
-
const resolved = resolveLocalReference(rootSchema, reference);
|
|
1159
|
-
if (resolved === void 0) return "unknown";
|
|
1160
|
-
const next = new Set(resolvingRefs);
|
|
1161
|
-
next.add(reference);
|
|
1162
|
-
return schemaType(resolved, rootSchema, next, depth + 1);
|
|
1163
|
-
}
|
|
1164
|
-
if (Object.hasOwn(schema, "const")) return literalType(schema.const);
|
|
1165
|
-
if (Array.isArray(schema.enum)) {
|
|
1166
|
-
return union(schema.enum.map(literalType));
|
|
1167
|
-
}
|
|
1168
|
-
const composites = [];
|
|
1169
|
-
if (Array.isArray(schema.oneOf)) {
|
|
1170
|
-
composites.push(
|
|
1171
|
-
union(schema.oneOf.map((part) => schemaType(part, rootSchema, resolvingRefs, depth + 1)))
|
|
1172
|
-
);
|
|
1173
|
-
}
|
|
1174
|
-
if (Array.isArray(schema.anyOf)) {
|
|
1175
|
-
composites.push(
|
|
1176
|
-
union(schema.anyOf.map((part) => schemaType(part, rootSchema, resolvingRefs, depth + 1)))
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
if (Array.isArray(schema.allOf)) {
|
|
1180
|
-
composites.push(
|
|
1181
|
-
intersection(
|
|
1182
|
-
schema.allOf.map((part) => schemaType(part, rootSchema, resolvingRefs, depth + 1))
|
|
1183
|
-
)
|
|
1184
|
-
);
|
|
1185
|
-
}
|
|
1186
|
-
if (composites.length > 0) {
|
|
1187
|
-
const composed = intersection(composites);
|
|
1188
|
-
return schema.nullable === true ? union([composed, "null"]) : composed;
|
|
1189
|
-
}
|
|
1190
|
-
const declaredTypes = Array.isArray(schema.type) ? schema.type.filter((value) => typeof value === "string") : typeof schema.type === "string" ? [schema.type] : inferredSchemaTypes(schema);
|
|
1191
|
-
const rendered = declaredTypes.map(
|
|
1192
|
-
(type) => typeType(type, schema, rootSchema, resolvingRefs, depth + 1)
|
|
1193
1089
|
);
|
|
1194
|
-
if (schema.nullable === true) rendered.push("null");
|
|
1195
|
-
return union(rendered.length > 0 ? rendered : ["unknown"]);
|
|
1196
|
-
}
|
|
1197
|
-
function inferredSchemaTypes(schema) {
|
|
1198
|
-
if (isSchemaObject(schema.properties) || Object.hasOwn(schema, "additionalProperties")) {
|
|
1199
|
-
return ["object"];
|
|
1200
|
-
}
|
|
1201
|
-
if (Object.hasOwn(schema, "items") || Array.isArray(schema.prefixItems)) return ["array"];
|
|
1202
|
-
return [];
|
|
1203
|
-
}
|
|
1204
|
-
function typeType(type, schema, rootSchema, resolvingRefs, depth) {
|
|
1205
|
-
switch (type) {
|
|
1206
|
-
case "null":
|
|
1207
|
-
return "null";
|
|
1208
|
-
case "boolean":
|
|
1209
|
-
return "boolean";
|
|
1210
|
-
case "integer":
|
|
1211
|
-
case "number":
|
|
1212
|
-
return "number";
|
|
1213
|
-
case "string":
|
|
1214
|
-
return "string";
|
|
1215
|
-
case "array":
|
|
1216
|
-
return arrayType(schema, rootSchema, resolvingRefs, depth);
|
|
1217
|
-
case "object":
|
|
1218
|
-
return objectType(schema, rootSchema, resolvingRefs, depth);
|
|
1219
|
-
default:
|
|
1220
|
-
return "unknown";
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
function arrayType(schema, rootSchema, resolvingRefs, depth) {
|
|
1224
|
-
if (Array.isArray(schema.prefixItems)) {
|
|
1225
|
-
const tuple = schema.prefixItems.map(
|
|
1226
|
-
(item2) => schemaType(item2, rootSchema, resolvingRefs, depth + 1)
|
|
1227
|
-
);
|
|
1228
|
-
if (schema.items === false) return `readonly [${tuple.join(", ")}]`;
|
|
1229
|
-
const rest = schema.items === void 0 || schema.items === true ? "unknown" : schemaType(schema.items, rootSchema, resolvingRefs, depth + 1);
|
|
1230
|
-
return `readonly [${tuple.join(", ")}${tuple.length > 0 ? ", " : ""}...${rest}[]]`;
|
|
1231
|
-
}
|
|
1232
|
-
const item = schema.items === void 0 || schema.items === true ? "unknown" : schemaType(schema.items, rootSchema, resolvingRefs, depth + 1);
|
|
1233
|
-
return `readonly (${item})[]`;
|
|
1234
1090
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1091
|
+
|
|
1092
|
+
// src/site.ts
|
|
1093
|
+
import { randomUUID } from "crypto";
|
|
1094
|
+
import { generateToolDeclarations as generateToolDeclarations2 } from "@opengeni/tool-gateway";
|
|
1095
|
+
var CODEMODE_SITE_LOCAL_PATH = "/__opengeni/site-tools";
|
|
1096
|
+
function createCodemodeSiteRequestHandler(client = () => environmentCodemodeClient()) {
|
|
1097
|
+
const provide = typeof client === "function" ? client : () => client;
|
|
1098
|
+
return async (request) => {
|
|
1099
|
+
try {
|
|
1100
|
+
const active = await provide();
|
|
1101
|
+
const pathname = new URL(request.url).pathname;
|
|
1102
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/catalog`) {
|
|
1103
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1104
|
+
return Response.json(projectSiteCatalog(catalog));
|
|
1105
|
+
}
|
|
1106
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/declarations`) {
|
|
1107
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1108
|
+
return Response.json({
|
|
1109
|
+
catalogDigest: catalog.digest,
|
|
1110
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
1111
|
+
source: generateToolDeclarations2(
|
|
1112
|
+
{ digest: catalog.digest, entries: catalog.entries },
|
|
1113
|
+
{
|
|
1114
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
1115
|
+
interfaceName: "OpenGeniGeneratedTools",
|
|
1116
|
+
callOptionsType: "OpenGeniToolCallOptions",
|
|
1117
|
+
fallbackResultType: "ToolGatewayResult",
|
|
1118
|
+
generatedBy: "@opengeni/codemode local Site preview",
|
|
1119
|
+
catalogDigestLabel: "Attempt catalog digest"
|
|
1120
|
+
}
|
|
1121
|
+
)
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
if (request.method === "POST" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/calls`) {
|
|
1125
|
+
const body = await request.json();
|
|
1126
|
+
if (!isSiteCall(body)) return siteError(400, "invalid_request", "Invalid Site tool call");
|
|
1127
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1128
|
+
if (body.catalogDigest !== catalog.digest) {
|
|
1129
|
+
return siteError(409, "catalog_stale", "The local Site tool catalog changed", true);
|
|
1130
|
+
}
|
|
1131
|
+
const operationId = body.operationId ?? randomUUID();
|
|
1132
|
+
const result = await active.call(body.identity, body.arguments, {
|
|
1133
|
+
operationId,
|
|
1134
|
+
signal: request.signal
|
|
1135
|
+
});
|
|
1136
|
+
return Response.json({
|
|
1137
|
+
operationId,
|
|
1138
|
+
catalogDigest: catalog.digest,
|
|
1139
|
+
result
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
return siteError(404, "not_found", "Local Site tool endpoint not found");
|
|
1143
|
+
} catch (error) {
|
|
1144
|
+
if (error instanceof CodemodeTransportError) {
|
|
1145
|
+
return siteError(
|
|
1146
|
+
error.status && error.status >= 400 && error.status <= 599 ? error.status : 502,
|
|
1147
|
+
error.remoteCode ?? error.code,
|
|
1148
|
+
error.message,
|
|
1149
|
+
error.retryable === true,
|
|
1150
|
+
error.outcomeUnknown === true
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
return siteError(
|
|
1154
|
+
500,
|
|
1155
|
+
"local_codemode_error",
|
|
1156
|
+
error instanceof Error ? error.message : "Local Site tool request failed"
|
|
1157
|
+
);
|
|
1263
1158
|
}
|
|
1264
|
-
|
|
1265
|
-
}
|
|
1266
|
-
return fields.length === 0 ? "Record<string, never>" : `{ ${fields.join("; ")} }`;
|
|
1267
|
-
}
|
|
1268
|
-
function resolveLocalReference(rootSchema, reference) {
|
|
1269
|
-
let current = rootSchema;
|
|
1270
|
-
for (const encoded of reference.slice(2).split("/")) {
|
|
1271
|
-
if (!isSchemaObject(current)) return void 0;
|
|
1272
|
-
const segment = encoded.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
1273
|
-
if (!Object.hasOwn(current, segment)) return void 0;
|
|
1274
|
-
current = current[segment];
|
|
1275
|
-
}
|
|
1276
|
-
return current;
|
|
1277
|
-
}
|
|
1278
|
-
function literalType(value) {
|
|
1279
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1280
|
-
return JSON.stringify(value);
|
|
1281
|
-
}
|
|
1282
|
-
if (Array.isArray(value)) return `readonly [${value.map(literalType).join(", ")}]`;
|
|
1283
|
-
if (isSchemaObject(value)) {
|
|
1284
|
-
return `{ ${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => `readonly ${identifierOrQuoted(key)}: ${literalType(child)}`).join("; ")} }`;
|
|
1285
|
-
}
|
|
1286
|
-
return "unknown";
|
|
1287
|
-
}
|
|
1288
|
-
function union(types) {
|
|
1289
|
-
const unique = [...new Set(types)];
|
|
1290
|
-
if (unique.includes("unknown")) return "unknown";
|
|
1291
|
-
if (unique.length === 0) return "never";
|
|
1292
|
-
return unique.length === 1 ? unique[0] : unique.map(parenthesizeComposite).join(" | ");
|
|
1293
|
-
}
|
|
1294
|
-
function intersection(types) {
|
|
1295
|
-
const unique = [...new Set(types.filter((type) => type !== "unknown"))];
|
|
1296
|
-
if (unique.length === 0) return "unknown";
|
|
1297
|
-
return unique.length === 1 ? unique[0] : unique.map(parenthesizeComposite).join(" & ");
|
|
1298
|
-
}
|
|
1299
|
-
function parenthesizeComposite(type) {
|
|
1300
|
-
return /[|&]/u.test(type) ? `(${type})` : type;
|
|
1301
|
-
}
|
|
1302
|
-
function identifierOrQuoted(value) {
|
|
1303
|
-
return /^[A-Za-z_$][A-Za-z0-9_$]*$/u.test(value) ? value : JSON.stringify(value);
|
|
1159
|
+
};
|
|
1304
1160
|
}
|
|
1305
|
-
function
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1161
|
+
function projectSiteCatalog(catalog) {
|
|
1162
|
+
return {
|
|
1163
|
+
version: catalog.version,
|
|
1164
|
+
generation: catalog.generation,
|
|
1165
|
+
digest: catalog.digest,
|
|
1166
|
+
createdAt: catalog.createdAt,
|
|
1167
|
+
entries: catalog.entries
|
|
1168
|
+
};
|
|
1310
1169
|
}
|
|
1311
|
-
function
|
|
1312
|
-
|
|
1170
|
+
function isSiteCall(value) {
|
|
1171
|
+
if (!isRecord(value) || typeof value.catalogDigest !== "string") return false;
|
|
1172
|
+
if (value.operationId !== void 0 && typeof value.operationId !== "string") return false;
|
|
1173
|
+
return isRecord(value.identity) && typeof value.identity.serverId === "string" && typeof value.identity.toolName === "string" && isRecord(value.arguments);
|
|
1313
1174
|
}
|
|
1314
|
-
function
|
|
1315
|
-
return
|
|
1175
|
+
function siteError(status, code, message, retryable = false, outcomeUnknown = false) {
|
|
1176
|
+
return Response.json(
|
|
1177
|
+
{
|
|
1178
|
+
error: {
|
|
1179
|
+
code,
|
|
1180
|
+
message,
|
|
1181
|
+
retryable,
|
|
1182
|
+
...outcomeUnknown ? { outcomeUnknown: true } : {}
|
|
1183
|
+
}
|
|
1184
|
+
},
|
|
1185
|
+
{ status }
|
|
1186
|
+
);
|
|
1316
1187
|
}
|
|
1317
|
-
function
|
|
1318
|
-
return
|
|
1188
|
+
function isRecord(value) {
|
|
1189
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1319
1190
|
}
|
|
1320
1191
|
|
|
1321
1192
|
// src/index.ts
|
|
1322
|
-
var AttemptToolCatalogStaleError = class extends Error {
|
|
1323
|
-
code = "catalog_stale";
|
|
1324
|
-
constructor() {
|
|
1325
|
-
super("Codemode catalog is stale for the active execution attempt");
|
|
1326
|
-
this.name = "AttemptToolCatalogStaleError";
|
|
1327
|
-
}
|
|
1328
|
-
};
|
|
1329
|
-
var AttemptToolNotFoundError = class extends Error {
|
|
1330
|
-
code = "tool_not_found";
|
|
1331
|
-
constructor() {
|
|
1332
|
-
super("Tool is not present in the active execution attempt catalog");
|
|
1333
|
-
this.name = "AttemptToolNotFoundError";
|
|
1334
|
-
}
|
|
1335
|
-
};
|
|
1336
|
-
var AttemptToolApprovalRequiredError = class extends Error {
|
|
1337
|
-
code = "approval_required";
|
|
1338
|
-
constructor() {
|
|
1339
|
-
super("Tool requires human approval and must be invoked through the agent");
|
|
1340
|
-
this.name = "AttemptToolApprovalRequiredError";
|
|
1341
|
-
}
|
|
1342
|
-
};
|
|
1343
|
-
var AttemptToolCatalogIntegrityError = class extends Error {
|
|
1344
|
-
code = "catalog_integrity_failed";
|
|
1345
|
-
constructor() {
|
|
1346
|
-
super("Attempt tool catalog digest does not match its authoritative content");
|
|
1347
|
-
this.name = "AttemptToolCatalogIntegrityError";
|
|
1348
|
-
}
|
|
1349
|
-
};
|
|
1350
|
-
var AttemptToolCatalogTooLargeError = class extends Error {
|
|
1351
|
-
code = "catalog_too_large";
|
|
1352
|
-
constructor() {
|
|
1353
|
-
super("Attempt tool catalog exceeds the maximum serialized size");
|
|
1354
|
-
this.name = "AttemptToolCatalogTooLargeError";
|
|
1355
|
-
}
|
|
1356
|
-
};
|
|
1357
|
-
var AttemptToolInputValidationError = class extends Error {
|
|
1358
|
-
code = "invalid_tool_arguments";
|
|
1359
|
-
constructor() {
|
|
1360
|
-
super("Tool arguments do not match the attempt catalog input schema");
|
|
1361
|
-
this.name = "AttemptToolInputValidationError";
|
|
1362
|
-
}
|
|
1363
|
-
};
|
|
1364
|
-
var AttemptToolOutputValidationError = class extends Error {
|
|
1365
|
-
code = "invalid_tool_result";
|
|
1366
|
-
constructor() {
|
|
1367
|
-
super("Tool result does not match the attempt catalog output schema");
|
|
1368
|
-
this.name = "AttemptToolOutputValidationError";
|
|
1369
|
-
}
|
|
1370
|
-
};
|
|
1371
1193
|
var CodemodeTransportError = class extends Error {
|
|
1372
|
-
constructor(message, status = null) {
|
|
1194
|
+
constructor(message, status = null, options = {}) {
|
|
1373
1195
|
super(message);
|
|
1374
1196
|
this.status = status;
|
|
1375
1197
|
this.name = "CodemodeTransportError";
|
|
1198
|
+
this.remoteCode = options.code ?? null;
|
|
1199
|
+
this.retryable = options.retryable ?? null;
|
|
1200
|
+
this.outcomeUnknown = options.outcomeUnknown ?? null;
|
|
1201
|
+
this.details = options.details ?? null;
|
|
1376
1202
|
}
|
|
1377
1203
|
code = "codemode_transport_error";
|
|
1204
|
+
remoteCode;
|
|
1205
|
+
retryable;
|
|
1206
|
+
outcomeUnknown;
|
|
1207
|
+
details;
|
|
1378
1208
|
};
|
|
1379
1209
|
var CodemodeOperationError = class extends Error {
|
|
1380
1210
|
constructor(operation, code) {
|
|
@@ -1433,15 +1263,22 @@ var CodemodeClient = class {
|
|
|
1433
1263
|
return compileCodemodeTools(await this.catalog(options), this);
|
|
1434
1264
|
}
|
|
1435
1265
|
async call(identity, argumentsValue = {}, options = {}) {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1266
|
+
return (await this.callResolved(
|
|
1267
|
+
(catalog) => catalog.entries.find(
|
|
1268
|
+
(entry) => entry.identity.serverId === identity.serverId && entry.identity.toolName === identity.toolName
|
|
1269
|
+
) ?? null,
|
|
1270
|
+
argumentsValue,
|
|
1271
|
+
options
|
|
1272
|
+
)).result;
|
|
1273
|
+
}
|
|
1274
|
+
async callResolved(resolveEntry, argumentsValue, options) {
|
|
1275
|
+
let catalog = await this.catalog(options.signal ? { signal: options.signal } : {});
|
|
1276
|
+
let entry = resolveEntry(catalog);
|
|
1277
|
+
if (!entry) throw new AttemptToolNotFoundError();
|
|
1278
|
+
const operationId = options.operationId ?? randomUUID2();
|
|
1443
1279
|
const deadline = Date.now() + boundedPositiveInteger(options.timeoutMs ?? this.timeoutMs, 1e3, 60 * 6e4);
|
|
1444
1280
|
let submitted = false;
|
|
1281
|
+
let staleRefreshAttempted = false;
|
|
1445
1282
|
let operation = null;
|
|
1446
1283
|
let nextNotifyAt = 0;
|
|
1447
1284
|
while (true) {
|
|
@@ -1451,7 +1288,7 @@ var CodemodeClient = class {
|
|
|
1451
1288
|
`Codemode operation ${operationId} did not settle before the client deadline`
|
|
1452
1289
|
);
|
|
1453
1290
|
}
|
|
1454
|
-
const shouldNotify = !submitted || operation?.state === "queued" && Date.now() >= nextNotifyAt;
|
|
1291
|
+
const shouldNotify = !submitted || (operation?.state === "queued" || operation?.state === "running") && Date.now() >= nextNotifyAt;
|
|
1455
1292
|
if (shouldNotify) {
|
|
1456
1293
|
submitted = true;
|
|
1457
1294
|
nextNotifyAt = Date.now() + 2e3;
|
|
@@ -1459,21 +1296,55 @@ var CodemodeClient = class {
|
|
|
1459
1296
|
operation = await this.submit(
|
|
1460
1297
|
operationId,
|
|
1461
1298
|
catalog.digest,
|
|
1462
|
-
identity,
|
|
1299
|
+
entry.identity,
|
|
1463
1300
|
argumentsValue,
|
|
1464
1301
|
options.signal
|
|
1465
1302
|
);
|
|
1466
1303
|
} catch (error) {
|
|
1304
|
+
if (operation === null && !staleRefreshAttempted && error instanceof CodemodeTransportError && error.remoteCode === "codemode_catalog_stale") {
|
|
1305
|
+
staleRefreshAttempted = true;
|
|
1306
|
+
catalog = await this.catalog({
|
|
1307
|
+
refresh: true,
|
|
1308
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1309
|
+
});
|
|
1310
|
+
entry = resolveEntry(catalog);
|
|
1311
|
+
if (!entry) throw new AttemptToolNotFoundError();
|
|
1312
|
+
submitted = false;
|
|
1313
|
+
nextNotifyAt = 0;
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
if (options.signal?.aborted) throw error;
|
|
1317
|
+
if (operation === null && !canReconcileCodemodeSubmission(error)) throw error;
|
|
1318
|
+
let recovered;
|
|
1467
1319
|
try {
|
|
1468
|
-
|
|
1469
|
-
} catch {
|
|
1470
|
-
throw
|
|
1320
|
+
recovered = await this.read(operationId, options.signal);
|
|
1321
|
+
} catch (recoveryError) {
|
|
1322
|
+
if (options.signal?.aborted) throw recoveryError;
|
|
1323
|
+
throw new CodemodeTransportError(
|
|
1324
|
+
`Codemode operation ${operationId} could not be reconciled after its submission response failed`,
|
|
1325
|
+
null,
|
|
1326
|
+
{
|
|
1327
|
+
code: "codemode_operation_recovery_unavailable",
|
|
1328
|
+
retryable: true,
|
|
1329
|
+
outcomeUnknown: true,
|
|
1330
|
+
details: { operationId }
|
|
1331
|
+
}
|
|
1332
|
+
);
|
|
1471
1333
|
}
|
|
1334
|
+
assertRecoveredCodemodeOperation(recovered, {
|
|
1335
|
+
operationId,
|
|
1336
|
+
catalog,
|
|
1337
|
+
identity: entry.identity,
|
|
1338
|
+
arguments: argumentsValue
|
|
1339
|
+
});
|
|
1340
|
+
operation = recovered;
|
|
1472
1341
|
}
|
|
1473
1342
|
} else {
|
|
1474
1343
|
operation = await this.read(operationId, options.signal);
|
|
1475
1344
|
}
|
|
1476
|
-
if (operation.state === "completed")
|
|
1345
|
+
if (operation.state === "completed") {
|
|
1346
|
+
return { result: AttemptToolResult.parse(operation.result), entry };
|
|
1347
|
+
}
|
|
1477
1348
|
if (["failed", "outcome_unknown", "cancelled"].includes(operation.state)) {
|
|
1478
1349
|
throw new CodemodeOperationError(
|
|
1479
1350
|
operation,
|
|
@@ -1488,25 +1359,22 @@ var CodemodeClient = class {
|
|
|
1488
1359
|
if (path.length < 2 || path.some((segment) => segment.length === 0)) {
|
|
1489
1360
|
throw new AttemptToolNotFoundError();
|
|
1490
1361
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
return await this.call(matches[0].identity, argumentsValue, options);
|
|
1362
|
+
return (await this.callResolved(
|
|
1363
|
+
(catalog) => catalogEntryForPath(catalog, path),
|
|
1364
|
+
argumentsValue,
|
|
1365
|
+
options
|
|
1366
|
+
)).result;
|
|
1497
1367
|
}
|
|
1498
1368
|
/** Return structured content when the catalog declares it; otherwise retain the full MCP result. */
|
|
1499
1369
|
async callPathValue(path, argumentsValue = {}, options = {}) {
|
|
1500
1370
|
if (path.length < 2 || path.some((segment) => segment.length === 0)) {
|
|
1501
1371
|
throw new AttemptToolNotFoundError();
|
|
1502
1372
|
}
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1373
|
+
const { result, entry } = await this.callResolved(
|
|
1374
|
+
(catalog) => catalogEntryForPath(catalog, path),
|
|
1375
|
+
argumentsValue,
|
|
1376
|
+
options
|
|
1506
1377
|
);
|
|
1507
|
-
if (matches.length !== 1) throw new AttemptToolNotFoundError();
|
|
1508
|
-
const entry = matches[0];
|
|
1509
|
-
const result = await this.call(entry.identity, argumentsValue, options);
|
|
1510
1378
|
if (!entry.outputSchema) return result;
|
|
1511
1379
|
if (result.isError) throw new CodemodeToolCallError(result);
|
|
1512
1380
|
if (!result.structuredContent) {
|
|
@@ -1543,22 +1411,46 @@ var CodemodeClient = class {
|
|
|
1543
1411
|
...init,
|
|
1544
1412
|
headers: {
|
|
1545
1413
|
...Object.fromEntries(new Headers(init.headers).entries()),
|
|
1546
|
-
[OPENGENI_API_CONTRACT_HEADER]: OPENGENI_API_CONTRACT_REVISION,
|
|
1547
1414
|
authorization: `Bearer ${token}`
|
|
1548
1415
|
}
|
|
1549
1416
|
});
|
|
1550
1417
|
if (!response.ok) {
|
|
1551
1418
|
let message = `Codemode request failed with HTTP ${response.status}`;
|
|
1419
|
+
let errorOptions = {};
|
|
1552
1420
|
try {
|
|
1553
|
-
const
|
|
1554
|
-
if (
|
|
1421
|
+
const error = parseCodemodeApiError(await response.json());
|
|
1422
|
+
if (error?.message) message = error.message;
|
|
1423
|
+
if (error) {
|
|
1424
|
+
errorOptions = {
|
|
1425
|
+
...error.code ? { code: error.code } : {},
|
|
1426
|
+
...error.retryable === void 0 ? {} : { retryable: error.retryable },
|
|
1427
|
+
...error.outcomeUnknown === void 0 ? {} : { outcomeUnknown: error.outcomeUnknown },
|
|
1428
|
+
...error.details ? { details: error.details } : {}
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1555
1431
|
} catch {
|
|
1556
1432
|
}
|
|
1557
|
-
throw new CodemodeTransportError(message, response.status);
|
|
1433
|
+
throw new CodemodeTransportError(message, response.status, errorOptions);
|
|
1558
1434
|
}
|
|
1559
1435
|
return response;
|
|
1560
1436
|
}
|
|
1561
1437
|
};
|
|
1438
|
+
function canReconcileCodemodeSubmission(error) {
|
|
1439
|
+
return !(error instanceof CodemodeTransportError) || error.outcomeUnknown === true;
|
|
1440
|
+
}
|
|
1441
|
+
function assertRecoveredCodemodeOperation(operation, expected) {
|
|
1442
|
+
const matches = operation.operationId === expected.operationId && operation.accountId === expected.catalog.accountId && operation.workspaceId === expected.catalog.workspaceId && operation.sessionId === expected.catalog.sessionId && operation.turnId === expected.catalog.turnId && operation.attemptId === expected.catalog.attemptId && operation.executionGeneration === expected.catalog.executionGeneration && operation.catalogDigest === expected.catalog.digest && operation.identity.serverId === expected.identity.serverId && operation.identity.toolName === expected.identity.toolName && digestCanonicalJson(operation.arguments) === digestCanonicalJson(expected.arguments);
|
|
1443
|
+
if (matches) return;
|
|
1444
|
+
throw new CodemodeTransportError(
|
|
1445
|
+
"Codemode operation id is already bound to a different request",
|
|
1446
|
+
409,
|
|
1447
|
+
{
|
|
1448
|
+
code: "codemode_operation_conflict",
|
|
1449
|
+
retryable: false,
|
|
1450
|
+
outcomeUnknown: false
|
|
1451
|
+
}
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1562
1454
|
function compileCodemodeTools(catalog, client) {
|
|
1563
1455
|
const verified = parseVerifiedAttemptToolCatalog(catalog);
|
|
1564
1456
|
const root = /* @__PURE__ */ Object.create(null);
|
|
@@ -1581,97 +1473,65 @@ function compileCodemodeTools(catalog, client) {
|
|
|
1581
1473
|
return root;
|
|
1582
1474
|
}
|
|
1583
1475
|
var AttemptToolEnvironment = class {
|
|
1584
|
-
constructor(catalog,
|
|
1585
|
-
this.authorize = authorize;
|
|
1476
|
+
constructor(catalog, gateway) {
|
|
1586
1477
|
this.catalog = catalog;
|
|
1587
|
-
|
|
1588
|
-
this.byIdentity.set(identityKey(definition.entry.identity), definition);
|
|
1589
|
-
this.byModelName.set(definition.entry.modelName, definition);
|
|
1590
|
-
}
|
|
1478
|
+
this.gateway = gateway;
|
|
1591
1479
|
}
|
|
1592
|
-
catalog;
|
|
1593
|
-
byIdentity = /* @__PURE__ */ new Map();
|
|
1594
|
-
byModelName = /* @__PURE__ */ new Map();
|
|
1595
1480
|
async call(input, context = {}) {
|
|
1481
|
+
return await (await this.prepareCall(input, context)).execute();
|
|
1482
|
+
}
|
|
1483
|
+
async prepareCall(input, context = {}) {
|
|
1596
1484
|
const call = AttemptToolCall.parse(input);
|
|
1597
|
-
|
|
1598
|
-
throw new AttemptToolCatalogStaleError();
|
|
1599
|
-
}
|
|
1600
|
-
const definition = this.byIdentity.get(identityKey(call.identity));
|
|
1601
|
-
if (!definition) {
|
|
1602
|
-
throw new AttemptToolNotFoundError();
|
|
1603
|
-
}
|
|
1604
|
-
if (call.caller.kind === "codemode" && definition.entry.approval === "human") {
|
|
1605
|
-
throw new AttemptToolApprovalRequiredError();
|
|
1606
|
-
}
|
|
1607
|
-
if (!definition.validateInput(call.arguments)) {
|
|
1608
|
-
throw new AttemptToolInputValidationError();
|
|
1609
|
-
}
|
|
1610
|
-
await this.authorize?.({ call, entry: definition.entry });
|
|
1611
|
-
const result = AttemptToolResult.parse(
|
|
1612
|
-
await definition.execute(call.arguments, {
|
|
1613
|
-
operationId: call.operationId,
|
|
1614
|
-
caller: call.caller,
|
|
1615
|
-
...context.transportMeta === void 0 ? {} : { transportMeta: context.transportMeta },
|
|
1616
|
-
...context.signal === void 0 ? {} : { signal: context.signal }
|
|
1617
|
-
})
|
|
1618
|
-
);
|
|
1619
|
-
if (!result.isError && definition.validateOutput) {
|
|
1620
|
-
const outputMatchesSchema = result.structuredContent !== void 0 && definition.validateOutput(result.structuredContent);
|
|
1621
|
-
if (!outputMatchesSchema && !isToolResultSpilledReceipt(result.structuredContent)) {
|
|
1622
|
-
throw new AttemptToolOutputValidationError();
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
return result;
|
|
1485
|
+
return await this.gateway.prepareCall(call, context);
|
|
1626
1486
|
}
|
|
1627
1487
|
async callModel(input) {
|
|
1628
|
-
|
|
1629
|
-
if (!definition) {
|
|
1630
|
-
throw new AttemptToolNotFoundError();
|
|
1631
|
-
}
|
|
1632
|
-
const call = AttemptToolCall.parse({
|
|
1633
|
-
operationId: input.operationId ?? randomUUID(),
|
|
1634
|
-
catalogDigest: this.catalog.digest,
|
|
1635
|
-
identity: definition.entry.identity,
|
|
1636
|
-
arguments: input.arguments,
|
|
1637
|
-
caller: { kind: "model", subjectId: input.subjectId }
|
|
1638
|
-
});
|
|
1639
|
-
return await this.call(call, {
|
|
1640
|
-
...input.transportMeta === void 0 ? {} : { transportMeta: input.transportMeta },
|
|
1641
|
-
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
1642
|
-
});
|
|
1488
|
+
return await this.gateway.callModel(input);
|
|
1643
1489
|
}
|
|
1644
1490
|
};
|
|
1645
1491
|
function createAttemptToolEnvironment(input) {
|
|
1646
1492
|
const createdAt = (input.createdAt ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1647
|
-
const
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
validateInput: compileCatalogSchema(schemaValidators, entry.inputSchema),
|
|
1659
|
-
validateOutput: entry.outputSchema ? compileCatalogSchema(schemaValidators, entry.outputSchema) : null
|
|
1660
|
-
};
|
|
1661
|
-
});
|
|
1493
|
+
const prepared = prepareToolGatewayDefinitions(
|
|
1494
|
+
input.definitions.map(
|
|
1495
|
+
(definition) => ({
|
|
1496
|
+
...definition,
|
|
1497
|
+
execute: async (argumentsValue, context) => await definition.execute(argumentsValue, {
|
|
1498
|
+
...context,
|
|
1499
|
+
caller: AttemptToolCaller.parse(context.caller)
|
|
1500
|
+
})
|
|
1501
|
+
})
|
|
1502
|
+
)
|
|
1503
|
+
);
|
|
1662
1504
|
const unsigned = {
|
|
1663
1505
|
version: ATTEMPT_TOOL_CATALOG_VERSION,
|
|
1664
1506
|
...input.scope,
|
|
1665
1507
|
generation: input.generation,
|
|
1666
1508
|
createdAt,
|
|
1667
|
-
entries:
|
|
1509
|
+
entries: [...prepared.entries]
|
|
1668
1510
|
};
|
|
1669
1511
|
const catalog = AttemptToolCatalog.parse({
|
|
1670
1512
|
...unsigned,
|
|
1671
1513
|
digest: digestAttemptToolCatalog(unsigned)
|
|
1672
1514
|
});
|
|
1673
1515
|
assertCatalogSize(catalog);
|
|
1674
|
-
return new AttemptToolEnvironment(
|
|
1516
|
+
return new AttemptToolEnvironment(
|
|
1517
|
+
catalog,
|
|
1518
|
+
prepared.create({
|
|
1519
|
+
catalogDigest: catalog.digest,
|
|
1520
|
+
requireApproval: (entry, caller) => caller.kind === "codemode" && entry.approval === "human",
|
|
1521
|
+
...input.confirmModelApproval ? {
|
|
1522
|
+
confirmModelApproval: ({ entry, subjectId }) => input.confirmModelApproval({
|
|
1523
|
+
modelName: entry.modelName,
|
|
1524
|
+
subjectId
|
|
1525
|
+
})
|
|
1526
|
+
} : {},
|
|
1527
|
+
...input.authorize ? {
|
|
1528
|
+
authorize: async ({ call, entry }) => await input.authorize({
|
|
1529
|
+
call: AttemptToolCall.parse(call),
|
|
1530
|
+
entry
|
|
1531
|
+
})
|
|
1532
|
+
} : {}
|
|
1533
|
+
})
|
|
1534
|
+
);
|
|
1675
1535
|
}
|
|
1676
1536
|
function digestAttemptToolCatalog(catalog) {
|
|
1677
1537
|
const { createdAt: _createdAt, ...authoritative } = catalog;
|
|
@@ -1712,84 +1572,6 @@ function assertCatalogSize(catalog) {
|
|
|
1712
1572
|
throw new AttemptToolCatalogTooLargeError();
|
|
1713
1573
|
}
|
|
1714
1574
|
}
|
|
1715
|
-
var COMPILED_CATALOG_SCHEMA_CACHE_MAX_ENTRIES = 512;
|
|
1716
|
-
var compiledCatalogSchemaCache = /* @__PURE__ */ new Map();
|
|
1717
|
-
function createSchemaValidators() {
|
|
1718
|
-
const options = {
|
|
1719
|
-
allErrors: false,
|
|
1720
|
-
coerceTypes: false,
|
|
1721
|
-
strict: false,
|
|
1722
|
-
useDefaults: false,
|
|
1723
|
-
validateFormats: false
|
|
1724
|
-
};
|
|
1725
|
-
return {
|
|
1726
|
-
draft7: new Ajv(options),
|
|
1727
|
-
draft2019: new Ajv2019(options),
|
|
1728
|
-
draft2020: new Ajv2020(options)
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
function compileCatalogSchema(validators, schema) {
|
|
1732
|
-
const dialect = typeof schema.$schema === "string" ? schema.$schema : "";
|
|
1733
|
-
const family = dialect.includes("2020-12") ? "2020-12" : dialect.includes("2019-09") ? "2019-09" : "draft7";
|
|
1734
|
-
const cacheKey = `${family}:${digestCanonicalJson(schema)}`;
|
|
1735
|
-
const cached = compiledCatalogSchemaCache.get(cacheKey);
|
|
1736
|
-
if (cached) {
|
|
1737
|
-
compiledCatalogSchemaCache.delete(cacheKey);
|
|
1738
|
-
compiledCatalogSchemaCache.set(cacheKey, cached);
|
|
1739
|
-
return cached;
|
|
1740
|
-
}
|
|
1741
|
-
const compiled = family === "2020-12" ? validators.draft2020.compile(schema) : family === "2019-09" ? validators.draft2019.compile(schema) : validators.draft7.compile(schema);
|
|
1742
|
-
while (compiledCatalogSchemaCache.size >= COMPILED_CATALOG_SCHEMA_CACHE_MAX_ENTRIES) {
|
|
1743
|
-
const oldest = compiledCatalogSchemaCache.keys().next().value;
|
|
1744
|
-
if (oldest === void 0) break;
|
|
1745
|
-
compiledCatalogSchemaCache.delete(oldest);
|
|
1746
|
-
}
|
|
1747
|
-
compiledCatalogSchemaCache.set(cacheKey, compiled);
|
|
1748
|
-
return compiled;
|
|
1749
|
-
}
|
|
1750
|
-
function allocateCodemodePaths(definitions) {
|
|
1751
|
-
const bases = definitions.map(
|
|
1752
|
-
(definition) => (definition.codemodePath?.length ? definition.codemodePath : [definition.identity.serverId, definition.identity.toolName]).map(safeNamespaceSegment)
|
|
1753
|
-
);
|
|
1754
|
-
const counts = /* @__PURE__ */ new Map();
|
|
1755
|
-
for (const path of bases) {
|
|
1756
|
-
const key = path.join("\0");
|
|
1757
|
-
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1758
|
-
}
|
|
1759
|
-
return bases.map((base, index) => {
|
|
1760
|
-
const key = base.join("\0");
|
|
1761
|
-
if (counts.get(key) === 1) return base;
|
|
1762
|
-
const suffix = `_${shortIdentityDigest(definitions[index].identity)}`;
|
|
1763
|
-
const last = base.at(-1);
|
|
1764
|
-
return [...base.slice(0, -1), `${last.slice(0, 128 - suffix.length)}${suffix}`];
|
|
1765
|
-
});
|
|
1766
|
-
}
|
|
1767
|
-
function safeNamespaceSegment(value) {
|
|
1768
|
-
let normalized = value.replace(/[^A-Za-z0-9_$]/gu, "_");
|
|
1769
|
-
if (!/^[A-Za-z_$]/u.test(normalized)) normalized = `_${normalized}`;
|
|
1770
|
-
if (["__proto__", "prototype", "constructor"].includes(normalized)) {
|
|
1771
|
-
normalized = `_${normalized}`;
|
|
1772
|
-
}
|
|
1773
|
-
return normalized.slice(0, 128) || "_";
|
|
1774
|
-
}
|
|
1775
|
-
function shortIdentityDigest(identity) {
|
|
1776
|
-
return createHash("sha256").update(identityKey(identity), "utf8").digest("hex").slice(0, 10);
|
|
1777
|
-
}
|
|
1778
|
-
function identityKey(identity) {
|
|
1779
|
-
return `${identity.serverId}\0${identity.toolName}`;
|
|
1780
|
-
}
|
|
1781
|
-
function digestCanonicalJson(value) {
|
|
1782
|
-
return createHash("sha256").update(JSON.stringify(canonicalJsonValue(value)), "utf8").digest("hex");
|
|
1783
|
-
}
|
|
1784
|
-
function canonicalJsonValue(value) {
|
|
1785
|
-
if (Array.isArray(value)) return value.map(canonicalJsonValue);
|
|
1786
|
-
if (value !== null && typeof value === "object") {
|
|
1787
|
-
return Object.fromEntries(
|
|
1788
|
-
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, canonicalJsonValue(entry)])
|
|
1789
|
-
);
|
|
1790
|
-
}
|
|
1791
|
-
return value;
|
|
1792
|
-
}
|
|
1793
1575
|
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
1794
1576
|
function boundedPositiveInteger(value, minimum, maximum) {
|
|
1795
1577
|
if (!Number.isFinite(value)) return minimum;
|
|
@@ -1807,6 +1589,30 @@ function structuredToolError(result) {
|
|
|
1807
1589
|
retryable: error?.retryable === true
|
|
1808
1590
|
};
|
|
1809
1591
|
}
|
|
1592
|
+
function catalogEntryForPath(catalog, path) {
|
|
1593
|
+
const matches = catalog.entries.filter(
|
|
1594
|
+
(entry) => entry.codemodePath.length === path.length && entry.codemodePath.every((segment, index) => segment === path[index])
|
|
1595
|
+
);
|
|
1596
|
+
return matches.length === 1 ? matches[0] : null;
|
|
1597
|
+
}
|
|
1598
|
+
function parseCodemodeApiError(input) {
|
|
1599
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
1600
|
+
const root = input;
|
|
1601
|
+
const nested = root.error && typeof root.error === "object" && !Array.isArray(root.error) ? root.error : root;
|
|
1602
|
+
const details = nested.details && typeof nested.details === "object" && !Array.isArray(nested.details) ? nested.details : void 0;
|
|
1603
|
+
const detailCode = details?.code;
|
|
1604
|
+
const code = typeof detailCode === "string" && /^[a-z0-9_]{1,128}$/u.test(detailCode) ? detailCode : void 0;
|
|
1605
|
+
const message = typeof nested.message === "string" ? nested.message : void 0;
|
|
1606
|
+
const retryable = typeof nested.retryable === "boolean" ? nested.retryable : void 0;
|
|
1607
|
+
const outcomeUnknown = typeof nested.outcomeUnknown === "boolean" ? nested.outcomeUnknown : void 0;
|
|
1608
|
+
return message || code || retryable !== void 0 || outcomeUnknown !== void 0 || details ? {
|
|
1609
|
+
...message ? { message } : {},
|
|
1610
|
+
...code ? { code } : {},
|
|
1611
|
+
...retryable === void 0 ? {} : { retryable },
|
|
1612
|
+
...outcomeUnknown === void 0 ? {} : { outcomeUnknown },
|
|
1613
|
+
...details ? { details } : {}
|
|
1614
|
+
} : null;
|
|
1615
|
+
}
|
|
1810
1616
|
async function abortableDelay(delayMs, signal) {
|
|
1811
1617
|
if (!signal) {
|
|
1812
1618
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -1834,7 +1640,9 @@ export {
|
|
|
1834
1640
|
AttemptToolInputValidationError,
|
|
1835
1641
|
AttemptToolNotFoundError,
|
|
1836
1642
|
AttemptToolOutputValidationError,
|
|
1643
|
+
AttemptToolPathCollisionError,
|
|
1837
1644
|
CODEMODE_ENVIRONMENT,
|
|
1645
|
+
CODEMODE_SITE_LOCAL_PATH,
|
|
1838
1646
|
CodemodeArtifact,
|
|
1839
1647
|
CodemodeArtifactCollection,
|
|
1840
1648
|
CodemodeArtifactExport,
|
|
@@ -1867,6 +1675,7 @@ export {
|
|
|
1867
1675
|
codemodeDispatchSubject,
|
|
1868
1676
|
compileCodemodeTools,
|
|
1869
1677
|
createAttemptToolEnvironment,
|
|
1678
|
+
createCodemodeSiteRequestHandler,
|
|
1870
1679
|
createCodemodeTools,
|
|
1871
1680
|
createOpenGeniCodemode,
|
|
1872
1681
|
decodeCodemodeDispatchAck,
|