@opengeni/codemode 0.4.25-canary.0 → 0.4.27-canary.1
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 +31 -41
- package/dist/index.js +314 -476
- 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 +298 -319
- package/src/site.ts +158 -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,160 @@ 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
1090
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
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 (pathname.startsWith(`${CODEMODE_SITE_LOCAL_PATH}/sdk/`)) {
|
|
1103
|
+
const path = pathname.slice(`${CODEMODE_SITE_LOCAL_PATH}/sdk`.length) + new URL(request.url).search;
|
|
1104
|
+
const response = await active.sessionRequest(path, {
|
|
1105
|
+
method: request.method,
|
|
1106
|
+
signal: request.signal,
|
|
1107
|
+
headers: {
|
|
1108
|
+
"content-type": request.headers.get("content-type") ?? "application/json",
|
|
1109
|
+
accept: request.headers.get("accept") ?? "application/json",
|
|
1110
|
+
...request.headers.has("last-event-id") ? { "last-event-id": request.headers.get("last-event-id") } : {}
|
|
1111
|
+
},
|
|
1112
|
+
...request.body ? { body: await request.text() } : {}
|
|
1113
|
+
});
|
|
1114
|
+
const headers = new Headers(response.headers);
|
|
1115
|
+
headers.delete("content-encoding");
|
|
1116
|
+
headers.delete("content-length");
|
|
1117
|
+
headers.delete("transfer-encoding");
|
|
1118
|
+
return new Response(response.body, {
|
|
1119
|
+
status: response.status,
|
|
1120
|
+
statusText: response.statusText,
|
|
1121
|
+
headers
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/catalog`) {
|
|
1125
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1126
|
+
return Response.json(projectSiteCatalog(catalog));
|
|
1127
|
+
}
|
|
1128
|
+
if (request.method === "GET" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/declarations`) {
|
|
1129
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1130
|
+
return Response.json({
|
|
1131
|
+
catalogDigest: catalog.digest,
|
|
1132
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
1133
|
+
source: generateToolDeclarations2(
|
|
1134
|
+
{ digest: catalog.digest, entries: catalog.entries },
|
|
1135
|
+
{
|
|
1136
|
+
moduleSpecifier: "@opengeni/sdk",
|
|
1137
|
+
interfaceName: "OpenGeniGeneratedTools",
|
|
1138
|
+
callOptionsType: "OpenGeniToolCallOptions",
|
|
1139
|
+
fallbackResultType: "ToolGatewayResult",
|
|
1140
|
+
generatedBy: "@opengeni/codemode local Site preview",
|
|
1141
|
+
catalogDigestLabel: "Attempt catalog digest"
|
|
1142
|
+
}
|
|
1143
|
+
)
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
if (request.method === "POST" && pathname === `${CODEMODE_SITE_LOCAL_PATH}/calls`) {
|
|
1147
|
+
const body = await request.json();
|
|
1148
|
+
if (!isSiteCall(body)) return siteError(400, "invalid_request", "Invalid Site tool call");
|
|
1149
|
+
const catalog = await active.catalog({ signal: request.signal });
|
|
1150
|
+
if (body.catalogDigest !== catalog.digest) {
|
|
1151
|
+
return siteError(409, "catalog_stale", "The local Site tool catalog changed", true);
|
|
1152
|
+
}
|
|
1153
|
+
const operationId = body.operationId ?? randomUUID();
|
|
1154
|
+
const result = await active.call(body.identity, body.arguments, {
|
|
1155
|
+
operationId,
|
|
1156
|
+
signal: request.signal
|
|
1157
|
+
});
|
|
1158
|
+
return Response.json({
|
|
1159
|
+
operationId,
|
|
1160
|
+
catalogDigest: catalog.digest,
|
|
1161
|
+
result
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
return siteError(404, "not_found", "Local Site tool endpoint not found");
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
if (error instanceof CodemodeTransportError) {
|
|
1167
|
+
return siteError(
|
|
1168
|
+
error.status && error.status >= 400 && error.status <= 599 ? error.status : 502,
|
|
1169
|
+
error.remoteCode ?? error.code,
|
|
1170
|
+
error.message,
|
|
1171
|
+
error.retryable === true,
|
|
1172
|
+
error.outcomeUnknown === true
|
|
1173
|
+
);
|
|
1174
|
+
}
|
|
1175
|
+
return siteError(
|
|
1176
|
+
500,
|
|
1177
|
+
"local_codemode_error",
|
|
1178
|
+
error instanceof Error ? error.message : "Local Site tool request failed"
|
|
1179
|
+
);
|
|
1263
1180
|
}
|
|
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);
|
|
1181
|
+
};
|
|
1304
1182
|
}
|
|
1305
|
-
function
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1183
|
+
function projectSiteCatalog(catalog) {
|
|
1184
|
+
return {
|
|
1185
|
+
version: catalog.version,
|
|
1186
|
+
generation: catalog.generation,
|
|
1187
|
+
digest: catalog.digest,
|
|
1188
|
+
createdAt: catalog.createdAt,
|
|
1189
|
+
entries: catalog.entries
|
|
1190
|
+
};
|
|
1310
1191
|
}
|
|
1311
|
-
function
|
|
1312
|
-
|
|
1192
|
+
function isSiteCall(value) {
|
|
1193
|
+
if (!isRecord(value) || typeof value.catalogDigest !== "string") return false;
|
|
1194
|
+
if (value.operationId !== void 0 && typeof value.operationId !== "string") return false;
|
|
1195
|
+
return isRecord(value.identity) && typeof value.identity.serverId === "string" && typeof value.identity.toolName === "string" && isRecord(value.arguments);
|
|
1313
1196
|
}
|
|
1314
|
-
function
|
|
1315
|
-
return
|
|
1197
|
+
function siteError(status, code, message, retryable = false, outcomeUnknown = false) {
|
|
1198
|
+
return Response.json(
|
|
1199
|
+
{
|
|
1200
|
+
error: {
|
|
1201
|
+
code,
|
|
1202
|
+
message,
|
|
1203
|
+
retryable,
|
|
1204
|
+
...outcomeUnknown ? { outcomeUnknown: true } : {}
|
|
1205
|
+
}
|
|
1206
|
+
},
|
|
1207
|
+
{ status }
|
|
1208
|
+
);
|
|
1316
1209
|
}
|
|
1317
|
-
function
|
|
1318
|
-
return
|
|
1210
|
+
function isRecord(value) {
|
|
1211
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1319
1212
|
}
|
|
1320
1213
|
|
|
1321
1214
|
// 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
1215
|
var CodemodeTransportError = class extends Error {
|
|
1372
|
-
constructor(message, status = null) {
|
|
1216
|
+
constructor(message, status = null, options = {}) {
|
|
1373
1217
|
super(message);
|
|
1374
1218
|
this.status = status;
|
|
1375
1219
|
this.name = "CodemodeTransportError";
|
|
1220
|
+
this.remoteCode = options.code ?? null;
|
|
1221
|
+
this.retryable = options.retryable ?? null;
|
|
1222
|
+
this.outcomeUnknown = options.outcomeUnknown ?? null;
|
|
1223
|
+
this.details = options.details ?? null;
|
|
1376
1224
|
}
|
|
1377
1225
|
code = "codemode_transport_error";
|
|
1226
|
+
remoteCode;
|
|
1227
|
+
retryable;
|
|
1228
|
+
outcomeUnknown;
|
|
1229
|
+
details;
|
|
1378
1230
|
};
|
|
1379
1231
|
var CodemodeOperationError = class extends Error {
|
|
1380
1232
|
constructor(operation, code) {
|
|
@@ -1433,15 +1285,22 @@ var CodemodeClient = class {
|
|
|
1433
1285
|
return compileCodemodeTools(await this.catalog(options), this);
|
|
1434
1286
|
}
|
|
1435
1287
|
async call(identity, argumentsValue = {}, options = {}) {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1288
|
+
return (await this.callResolved(
|
|
1289
|
+
(catalog) => catalog.entries.find(
|
|
1290
|
+
(entry) => entry.identity.serverId === identity.serverId && entry.identity.toolName === identity.toolName
|
|
1291
|
+
) ?? null,
|
|
1292
|
+
argumentsValue,
|
|
1293
|
+
options
|
|
1294
|
+
)).result;
|
|
1295
|
+
}
|
|
1296
|
+
async callResolved(resolveEntry, argumentsValue, options) {
|
|
1297
|
+
let catalog = await this.catalog(options.signal ? { signal: options.signal } : {});
|
|
1298
|
+
let entry = resolveEntry(catalog);
|
|
1299
|
+
if (!entry) throw new AttemptToolNotFoundError();
|
|
1300
|
+
const operationId = options.operationId ?? randomUUID2();
|
|
1443
1301
|
const deadline = Date.now() + boundedPositiveInteger(options.timeoutMs ?? this.timeoutMs, 1e3, 60 * 6e4);
|
|
1444
1302
|
let submitted = false;
|
|
1303
|
+
let staleRefreshAttempted = false;
|
|
1445
1304
|
let operation = null;
|
|
1446
1305
|
let nextNotifyAt = 0;
|
|
1447
1306
|
while (true) {
|
|
@@ -1451,7 +1310,7 @@ var CodemodeClient = class {
|
|
|
1451
1310
|
`Codemode operation ${operationId} did not settle before the client deadline`
|
|
1452
1311
|
);
|
|
1453
1312
|
}
|
|
1454
|
-
const shouldNotify = !submitted || operation?.state === "queued" && Date.now() >= nextNotifyAt;
|
|
1313
|
+
const shouldNotify = !submitted || (operation?.state === "queued" || operation?.state === "running") && Date.now() >= nextNotifyAt;
|
|
1455
1314
|
if (shouldNotify) {
|
|
1456
1315
|
submitted = true;
|
|
1457
1316
|
nextNotifyAt = Date.now() + 2e3;
|
|
@@ -1459,21 +1318,55 @@ var CodemodeClient = class {
|
|
|
1459
1318
|
operation = await this.submit(
|
|
1460
1319
|
operationId,
|
|
1461
1320
|
catalog.digest,
|
|
1462
|
-
identity,
|
|
1321
|
+
entry.identity,
|
|
1463
1322
|
argumentsValue,
|
|
1464
1323
|
options.signal
|
|
1465
1324
|
);
|
|
1466
1325
|
} catch (error) {
|
|
1326
|
+
if (operation === null && !staleRefreshAttempted && error instanceof CodemodeTransportError && error.remoteCode === "codemode_catalog_stale") {
|
|
1327
|
+
staleRefreshAttempted = true;
|
|
1328
|
+
catalog = await this.catalog({
|
|
1329
|
+
refresh: true,
|
|
1330
|
+
...options.signal ? { signal: options.signal } : {}
|
|
1331
|
+
});
|
|
1332
|
+
entry = resolveEntry(catalog);
|
|
1333
|
+
if (!entry) throw new AttemptToolNotFoundError();
|
|
1334
|
+
submitted = false;
|
|
1335
|
+
nextNotifyAt = 0;
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
1338
|
+
if (options.signal?.aborted) throw error;
|
|
1339
|
+
if (operation === null && !canReconcileCodemodeSubmission(error)) throw error;
|
|
1340
|
+
let recovered;
|
|
1467
1341
|
try {
|
|
1468
|
-
|
|
1469
|
-
} catch {
|
|
1470
|
-
throw
|
|
1342
|
+
recovered = await this.read(operationId, options.signal);
|
|
1343
|
+
} catch (recoveryError) {
|
|
1344
|
+
if (options.signal?.aborted) throw recoveryError;
|
|
1345
|
+
throw new CodemodeTransportError(
|
|
1346
|
+
`Codemode operation ${operationId} could not be reconciled after its submission response failed`,
|
|
1347
|
+
null,
|
|
1348
|
+
{
|
|
1349
|
+
code: "codemode_operation_recovery_unavailable",
|
|
1350
|
+
retryable: true,
|
|
1351
|
+
outcomeUnknown: true,
|
|
1352
|
+
details: { operationId }
|
|
1353
|
+
}
|
|
1354
|
+
);
|
|
1471
1355
|
}
|
|
1356
|
+
assertRecoveredCodemodeOperation(recovered, {
|
|
1357
|
+
operationId,
|
|
1358
|
+
catalog,
|
|
1359
|
+
identity: entry.identity,
|
|
1360
|
+
arguments: argumentsValue
|
|
1361
|
+
});
|
|
1362
|
+
operation = recovered;
|
|
1472
1363
|
}
|
|
1473
1364
|
} else {
|
|
1474
1365
|
operation = await this.read(operationId, options.signal);
|
|
1475
1366
|
}
|
|
1476
|
-
if (operation.state === "completed")
|
|
1367
|
+
if (operation.state === "completed") {
|
|
1368
|
+
return { result: AttemptToolResult.parse(operation.result), entry };
|
|
1369
|
+
}
|
|
1477
1370
|
if (["failed", "outcome_unknown", "cancelled"].includes(operation.state)) {
|
|
1478
1371
|
throw new CodemodeOperationError(
|
|
1479
1372
|
operation,
|
|
@@ -1488,25 +1381,22 @@ var CodemodeClient = class {
|
|
|
1488
1381
|
if (path.length < 2 || path.some((segment) => segment.length === 0)) {
|
|
1489
1382
|
throw new AttemptToolNotFoundError();
|
|
1490
1383
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
return await this.call(matches[0].identity, argumentsValue, options);
|
|
1384
|
+
return (await this.callResolved(
|
|
1385
|
+
(catalog) => catalogEntryForPath(catalog, path),
|
|
1386
|
+
argumentsValue,
|
|
1387
|
+
options
|
|
1388
|
+
)).result;
|
|
1497
1389
|
}
|
|
1498
1390
|
/** Return structured content when the catalog declares it; otherwise retain the full MCP result. */
|
|
1499
1391
|
async callPathValue(path, argumentsValue = {}, options = {}) {
|
|
1500
1392
|
if (path.length < 2 || path.some((segment) => segment.length === 0)) {
|
|
1501
1393
|
throw new AttemptToolNotFoundError();
|
|
1502
1394
|
}
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1395
|
+
const { result, entry } = await this.callResolved(
|
|
1396
|
+
(catalog) => catalogEntryForPath(catalog, path),
|
|
1397
|
+
argumentsValue,
|
|
1398
|
+
options
|
|
1506
1399
|
);
|
|
1507
|
-
if (matches.length !== 1) throw new AttemptToolNotFoundError();
|
|
1508
|
-
const entry = matches[0];
|
|
1509
|
-
const result = await this.call(entry.identity, argumentsValue, options);
|
|
1510
1400
|
if (!entry.outputSchema) return result;
|
|
1511
1401
|
if (result.isError) throw new CodemodeToolCallError(result);
|
|
1512
1402
|
if (!result.structuredContent) {
|
|
@@ -1537,28 +1427,59 @@ var CodemodeClient = class {
|
|
|
1537
1427
|
});
|
|
1538
1428
|
return CodemodeOperation.parse(await response.json());
|
|
1539
1429
|
}
|
|
1540
|
-
|
|
1430
|
+
/** Server-side Site preview forwarding. The attempt bearer never enters the page. */
|
|
1431
|
+
async sessionRequest(path, init) {
|
|
1432
|
+
if (!path.startsWith("/v1/")) {
|
|
1433
|
+
throw new Error("Unsupported Site session API path");
|
|
1434
|
+
}
|
|
1435
|
+
return this.request(`/sdk${path}`, init, false);
|
|
1436
|
+
}
|
|
1437
|
+
async request(path, init, throwOnError = true) {
|
|
1541
1438
|
const token = typeof this.options.token === "function" ? await this.options.token() : this.options.token;
|
|
1542
1439
|
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
1543
1440
|
...init,
|
|
1544
1441
|
headers: {
|
|
1545
1442
|
...Object.fromEntries(new Headers(init.headers).entries()),
|
|
1546
|
-
[OPENGENI_API_CONTRACT_HEADER]: OPENGENI_API_CONTRACT_REVISION,
|
|
1547
1443
|
authorization: `Bearer ${token}`
|
|
1548
1444
|
}
|
|
1549
1445
|
});
|
|
1550
|
-
if (!response.ok) {
|
|
1446
|
+
if (!response.ok && throwOnError) {
|
|
1551
1447
|
let message = `Codemode request failed with HTTP ${response.status}`;
|
|
1448
|
+
let errorOptions = {};
|
|
1552
1449
|
try {
|
|
1553
|
-
const
|
|
1554
|
-
if (
|
|
1450
|
+
const error = parseCodemodeApiError(await response.json());
|
|
1451
|
+
if (error?.message) message = error.message;
|
|
1452
|
+
if (error) {
|
|
1453
|
+
errorOptions = {
|
|
1454
|
+
...error.code ? { code: error.code } : {},
|
|
1455
|
+
...error.retryable === void 0 ? {} : { retryable: error.retryable },
|
|
1456
|
+
...error.outcomeUnknown === void 0 ? {} : { outcomeUnknown: error.outcomeUnknown },
|
|
1457
|
+
...error.details ? { details: error.details } : {}
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1555
1460
|
} catch {
|
|
1556
1461
|
}
|
|
1557
|
-
throw new CodemodeTransportError(message, response.status);
|
|
1462
|
+
throw new CodemodeTransportError(message, response.status, errorOptions);
|
|
1558
1463
|
}
|
|
1559
1464
|
return response;
|
|
1560
1465
|
}
|
|
1561
1466
|
};
|
|
1467
|
+
function canReconcileCodemodeSubmission(error) {
|
|
1468
|
+
return !(error instanceof CodemodeTransportError) || error.outcomeUnknown === true;
|
|
1469
|
+
}
|
|
1470
|
+
function assertRecoveredCodemodeOperation(operation, expected) {
|
|
1471
|
+
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);
|
|
1472
|
+
if (matches) return;
|
|
1473
|
+
throw new CodemodeTransportError(
|
|
1474
|
+
"Codemode operation id is already bound to a different request",
|
|
1475
|
+
409,
|
|
1476
|
+
{
|
|
1477
|
+
code: "codemode_operation_conflict",
|
|
1478
|
+
retryable: false,
|
|
1479
|
+
outcomeUnknown: false
|
|
1480
|
+
}
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1562
1483
|
function compileCodemodeTools(catalog, client) {
|
|
1563
1484
|
const verified = parseVerifiedAttemptToolCatalog(catalog);
|
|
1564
1485
|
const root = /* @__PURE__ */ Object.create(null);
|
|
@@ -1581,97 +1502,65 @@ function compileCodemodeTools(catalog, client) {
|
|
|
1581
1502
|
return root;
|
|
1582
1503
|
}
|
|
1583
1504
|
var AttemptToolEnvironment = class {
|
|
1584
|
-
constructor(catalog,
|
|
1585
|
-
this.authorize = authorize;
|
|
1505
|
+
constructor(catalog, gateway) {
|
|
1586
1506
|
this.catalog = catalog;
|
|
1587
|
-
|
|
1588
|
-
this.byIdentity.set(identityKey(definition.entry.identity), definition);
|
|
1589
|
-
this.byModelName.set(definition.entry.modelName, definition);
|
|
1590
|
-
}
|
|
1507
|
+
this.gateway = gateway;
|
|
1591
1508
|
}
|
|
1592
|
-
catalog;
|
|
1593
|
-
byIdentity = /* @__PURE__ */ new Map();
|
|
1594
|
-
byModelName = /* @__PURE__ */ new Map();
|
|
1595
1509
|
async call(input, context = {}) {
|
|
1510
|
+
return await (await this.prepareCall(input, context)).execute();
|
|
1511
|
+
}
|
|
1512
|
+
async prepareCall(input, context = {}) {
|
|
1596
1513
|
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;
|
|
1514
|
+
return await this.gateway.prepareCall(call, context);
|
|
1626
1515
|
}
|
|
1627
1516
|
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
|
-
});
|
|
1517
|
+
return await this.gateway.callModel(input);
|
|
1643
1518
|
}
|
|
1644
1519
|
};
|
|
1645
1520
|
function createAttemptToolEnvironment(input) {
|
|
1646
1521
|
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
|
-
});
|
|
1522
|
+
const prepared = prepareToolGatewayDefinitions(
|
|
1523
|
+
input.definitions.map(
|
|
1524
|
+
(definition) => ({
|
|
1525
|
+
...definition,
|
|
1526
|
+
execute: async (argumentsValue, context) => await definition.execute(argumentsValue, {
|
|
1527
|
+
...context,
|
|
1528
|
+
caller: AttemptToolCaller.parse(context.caller)
|
|
1529
|
+
})
|
|
1530
|
+
})
|
|
1531
|
+
)
|
|
1532
|
+
);
|
|
1662
1533
|
const unsigned = {
|
|
1663
1534
|
version: ATTEMPT_TOOL_CATALOG_VERSION,
|
|
1664
1535
|
...input.scope,
|
|
1665
1536
|
generation: input.generation,
|
|
1666
1537
|
createdAt,
|
|
1667
|
-
entries:
|
|
1538
|
+
entries: [...prepared.entries]
|
|
1668
1539
|
};
|
|
1669
1540
|
const catalog = AttemptToolCatalog.parse({
|
|
1670
1541
|
...unsigned,
|
|
1671
1542
|
digest: digestAttemptToolCatalog(unsigned)
|
|
1672
1543
|
});
|
|
1673
1544
|
assertCatalogSize(catalog);
|
|
1674
|
-
return new AttemptToolEnvironment(
|
|
1545
|
+
return new AttemptToolEnvironment(
|
|
1546
|
+
catalog,
|
|
1547
|
+
prepared.create({
|
|
1548
|
+
catalogDigest: catalog.digest,
|
|
1549
|
+
requireApproval: (entry, caller) => caller.kind === "codemode" && entry.approval === "human",
|
|
1550
|
+
...input.confirmModelApproval ? {
|
|
1551
|
+
confirmModelApproval: ({ entry, subjectId }) => input.confirmModelApproval({
|
|
1552
|
+
modelName: entry.modelName,
|
|
1553
|
+
subjectId
|
|
1554
|
+
})
|
|
1555
|
+
} : {},
|
|
1556
|
+
...input.authorize ? {
|
|
1557
|
+
authorize: async ({ call, entry }) => await input.authorize({
|
|
1558
|
+
call: AttemptToolCall.parse(call),
|
|
1559
|
+
entry
|
|
1560
|
+
})
|
|
1561
|
+
} : {}
|
|
1562
|
+
})
|
|
1563
|
+
);
|
|
1675
1564
|
}
|
|
1676
1565
|
function digestAttemptToolCatalog(catalog) {
|
|
1677
1566
|
const { createdAt: _createdAt, ...authoritative } = catalog;
|
|
@@ -1712,84 +1601,6 @@ function assertCatalogSize(catalog) {
|
|
|
1712
1601
|
throw new AttemptToolCatalogTooLargeError();
|
|
1713
1602
|
}
|
|
1714
1603
|
}
|
|
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
1604
|
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
1605
|
function boundedPositiveInteger(value, minimum, maximum) {
|
|
1795
1606
|
if (!Number.isFinite(value)) return minimum;
|
|
@@ -1807,6 +1618,30 @@ function structuredToolError(result) {
|
|
|
1807
1618
|
retryable: error?.retryable === true
|
|
1808
1619
|
};
|
|
1809
1620
|
}
|
|
1621
|
+
function catalogEntryForPath(catalog, path) {
|
|
1622
|
+
const matches = catalog.entries.filter(
|
|
1623
|
+
(entry) => entry.codemodePath.length === path.length && entry.codemodePath.every((segment, index) => segment === path[index])
|
|
1624
|
+
);
|
|
1625
|
+
return matches.length === 1 ? matches[0] : null;
|
|
1626
|
+
}
|
|
1627
|
+
function parseCodemodeApiError(input) {
|
|
1628
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return null;
|
|
1629
|
+
const root = input;
|
|
1630
|
+
const nested = root.error && typeof root.error === "object" && !Array.isArray(root.error) ? root.error : root;
|
|
1631
|
+
const details = nested.details && typeof nested.details === "object" && !Array.isArray(nested.details) ? nested.details : void 0;
|
|
1632
|
+
const detailCode = details?.code;
|
|
1633
|
+
const code = typeof detailCode === "string" && /^[a-z0-9_]{1,128}$/u.test(detailCode) ? detailCode : void 0;
|
|
1634
|
+
const message = typeof nested.message === "string" ? nested.message : void 0;
|
|
1635
|
+
const retryable = typeof nested.retryable === "boolean" ? nested.retryable : void 0;
|
|
1636
|
+
const outcomeUnknown = typeof nested.outcomeUnknown === "boolean" ? nested.outcomeUnknown : void 0;
|
|
1637
|
+
return message || code || retryable !== void 0 || outcomeUnknown !== void 0 || details ? {
|
|
1638
|
+
...message ? { message } : {},
|
|
1639
|
+
...code ? { code } : {},
|
|
1640
|
+
...retryable === void 0 ? {} : { retryable },
|
|
1641
|
+
...outcomeUnknown === void 0 ? {} : { outcomeUnknown },
|
|
1642
|
+
...details ? { details } : {}
|
|
1643
|
+
} : null;
|
|
1644
|
+
}
|
|
1810
1645
|
async function abortableDelay(delayMs, signal) {
|
|
1811
1646
|
if (!signal) {
|
|
1812
1647
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -1834,7 +1669,9 @@ export {
|
|
|
1834
1669
|
AttemptToolInputValidationError,
|
|
1835
1670
|
AttemptToolNotFoundError,
|
|
1836
1671
|
AttemptToolOutputValidationError,
|
|
1672
|
+
AttemptToolPathCollisionError,
|
|
1837
1673
|
CODEMODE_ENVIRONMENT,
|
|
1674
|
+
CODEMODE_SITE_LOCAL_PATH,
|
|
1838
1675
|
CodemodeArtifact,
|
|
1839
1676
|
CodemodeArtifactCollection,
|
|
1840
1677
|
CodemodeArtifactExport,
|
|
@@ -1867,6 +1704,7 @@ export {
|
|
|
1867
1704
|
codemodeDispatchSubject,
|
|
1868
1705
|
compileCodemodeTools,
|
|
1869
1706
|
createAttemptToolEnvironment,
|
|
1707
|
+
createCodemodeSiteRequestHandler,
|
|
1870
1708
|
createCodemodeTools,
|
|
1871
1709
|
createOpenGeniCodemode,
|
|
1872
1710
|
decodeCodemodeDispatchAck,
|