@runpod/mcp-server 4.10.1 → 4.11.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/CHANGELOG.md +11 -0
- package/dist/{chunk-FQJFKWUV.mjs → chunk-24UOECYY.mjs} +19 -1
- package/dist/chunk-24UOECYY.mjs.map +1 -0
- package/dist/{chunk-AKX5ZMCL.mjs → chunk-4M7QDHK4.mjs} +312 -28
- package/dist/chunk-4M7QDHK4.mjs.map +1 -0
- package/dist/hosted.cjs +326 -26
- package/dist/hosted.cjs.map +1 -1
- package/dist/hosted.mjs +2 -2
- package/dist/http.cjs +326 -26
- package/dist/http.cjs.map +1 -1
- package/dist/http.mjs +2 -2
- package/dist/specgen/profile.cjs +19 -0
- package/dist/specgen/profile.cjs.map +1 -1
- package/dist/specgen/profile.d.cts +6 -3
- package/dist/specgen/profile.d.ts +6 -3
- package/dist/specgen/profile.mjs +3 -1
- package/dist/stdio.cjs +324 -25
- package/dist/stdio.cjs.map +1 -1
- package/dist/stdio.mjs +324 -25
- package/dist/stdio.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-AKX5ZMCL.mjs.map +0 -1
- package/dist/chunk-FQJFKWUV.mjs.map +0 -1
package/dist/hosted.cjs
CHANGED
|
@@ -337,25 +337,16 @@ async function dispatchGeneratedTool(client, tool, args) {
|
|
|
337
337
|
const value = args[param.name];
|
|
338
338
|
query[param.name] = param.explode === false && Array.isArray(value) ? value.join(",") : value;
|
|
339
339
|
}
|
|
340
|
-
|
|
341
|
-
if (
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (tool.hasBody && requestBody !== void 0) {
|
|
355
|
-
const properties = tool.inputSchema.properties ?? {};
|
|
356
|
-
const defs = tool.inputSchema.$defs ?? {};
|
|
357
|
-
requestBody = coerceScalars(requestBody, properties.body, defs);
|
|
358
|
-
}
|
|
340
|
+
const sent = tool.hasBody ? bodyAsSent(tool, args.body) : { body: args.body };
|
|
341
|
+
if (!sent)
|
|
342
|
+
return {
|
|
343
|
+
ok: false,
|
|
344
|
+
status: 400,
|
|
345
|
+
payload: {
|
|
346
|
+
error: "The body argument arrived as a string that is not valid JSON. Send body as an object."
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const requestBody = sent.body;
|
|
359
350
|
const verbs = client;
|
|
360
351
|
const { data, error, response } = await verbs[tool.method](tool.path, {
|
|
361
352
|
params: { path: pathParams, query },
|
|
@@ -368,6 +359,32 @@ async function dispatchGeneratedTool(client, tool, args) {
|
|
|
368
359
|
payload: data ?? { status: response.status }
|
|
369
360
|
};
|
|
370
361
|
}
|
|
362
|
+
function bodyAsSent(tool, body) {
|
|
363
|
+
let parsed = body;
|
|
364
|
+
if (typeof parsed === "string") {
|
|
365
|
+
try {
|
|
366
|
+
parsed = JSON.parse(parsed);
|
|
367
|
+
} catch {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (parsed === void 0) return { body: parsed };
|
|
372
|
+
const properties = tool.inputSchema.properties ?? {};
|
|
373
|
+
const defs = tool.inputSchema.$defs ?? {};
|
|
374
|
+
return { body: coerceScalars(parsed, properties.body, defs) };
|
|
375
|
+
}
|
|
376
|
+
function argsAsSent(tool, args) {
|
|
377
|
+
if (!tool.hasBody || args.body === void 0) return args;
|
|
378
|
+
const sent = bodyAsSent(tool, args.body);
|
|
379
|
+
return sent ? { ...args, body: sent.body } : null;
|
|
380
|
+
}
|
|
381
|
+
function omittedEmptyQueryArg(tool) {
|
|
382
|
+
const required = new Set(tool.inputSchema.required ?? []);
|
|
383
|
+
const query = new Set(
|
|
384
|
+
tool.params.filter((p) => p.location === "query").map((p) => p.name)
|
|
385
|
+
);
|
|
386
|
+
return (name, value) => query.has(name) && !required.has(name) && isEmptyValue(value);
|
|
387
|
+
}
|
|
371
388
|
function isEmptyValue(value) {
|
|
372
389
|
return value === null || value === "" || Array.isArray(value) && !value.length;
|
|
373
390
|
}
|
|
@@ -2804,6 +2821,109 @@ var generatedTools = [
|
|
|
2804
2821
|
}
|
|
2805
2822
|
}
|
|
2806
2823
|
},
|
|
2824
|
+
{
|
|
2825
|
+
name: "exec-pod",
|
|
2826
|
+
title: "Run a command in a Pod",
|
|
2827
|
+
operationId: "execPod",
|
|
2828
|
+
description: `Run one command inside a running Pod's container and get stdout, stderr and the exit code back. No SSH key, public IP or exposed port is needed. command is an argv array run without a shell: pass ["sh", "-c", "..."] for pipes, redirects, globs or &&. One call waits at most timeoutSeconds (1-25, default 20). timedOut true means the call stopped waiting, NOT that the command stopped: it keeps running in the container. For anything longer (model downloads, pip installs, builds), start it in the background and log to a file, e.g. ["sh", "-c", "nohup wget -c -O /workspace/m.safetensors URL > /tmp/dl.log 2>&1 &"], then check progress with later calls (ls -la, du -h, tail /tmp/dl.log). stdout and stderr are each capped at 1 MiB (truncated true). Right after a create, the Pod can answer 404 "Pod not found" for about 10 seconds even with the right id, then 409 while its container starts: retry in about 10 seconds, a few times at most. A Pod that is not running answers 409. A host not yet updated for exec answers 503. Reaches only Pods owned by the API key's own account. Commands can change or delete data in the Pod: run write commands only for what the user asked.`,
|
|
2829
|
+
directoryDescription: "Run one command inside a running Pod's container and return stdout, stderr and the exit code. The command is an argv array run without a shell. One call waits at most timeoutSeconds (1-25, default 20); a command still running then keeps running in the container, and the result says timedOut. stdout and stderr are each capped at 1 MiB. A Pod that is not running answers 409, and a host not yet updated for exec answers 503. Reaches only Pods owned by the caller's own account. The command can change or delete data in the Pod.",
|
|
2830
|
+
method: "POST",
|
|
2831
|
+
path: "/v2/pods/{id}/exec",
|
|
2832
|
+
params: [
|
|
2833
|
+
{
|
|
2834
|
+
name: "id",
|
|
2835
|
+
location: "path"
|
|
2836
|
+
}
|
|
2837
|
+
],
|
|
2838
|
+
hasBody: true,
|
|
2839
|
+
annotations: {
|
|
2840
|
+
readOnlyHint: false,
|
|
2841
|
+
destructiveHint: true,
|
|
2842
|
+
idempotentHint: false,
|
|
2843
|
+
openWorldHint: true
|
|
2844
|
+
},
|
|
2845
|
+
inputSchema: {
|
|
2846
|
+
type: "object",
|
|
2847
|
+
properties: {
|
|
2848
|
+
id: {
|
|
2849
|
+
type: "string",
|
|
2850
|
+
description: "Pod identifier"
|
|
2851
|
+
},
|
|
2852
|
+
body: {
|
|
2853
|
+
$ref: "#/$defs/PodExecRequest",
|
|
2854
|
+
type: "object"
|
|
2855
|
+
}
|
|
2856
|
+
},
|
|
2857
|
+
required: ["id", "body"],
|
|
2858
|
+
$defs: {
|
|
2859
|
+
PodExecRequest: {
|
|
2860
|
+
type: "object",
|
|
2861
|
+
additionalProperties: false,
|
|
2862
|
+
required: ["command"],
|
|
2863
|
+
properties: {
|
|
2864
|
+
command: {
|
|
2865
|
+
type: "array",
|
|
2866
|
+
minItems: 1,
|
|
2867
|
+
maxItems: 256,
|
|
2868
|
+
prefixItems: [
|
|
2869
|
+
{
|
|
2870
|
+
type: "string",
|
|
2871
|
+
minLength: 1,
|
|
2872
|
+
maxLength: 4096,
|
|
2873
|
+
pattern: "^[^\\x00]*[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\\x00][^\\x00]*$"
|
|
2874
|
+
}
|
|
2875
|
+
],
|
|
2876
|
+
items: {
|
|
2877
|
+
type: "string",
|
|
2878
|
+
maxLength: 4096,
|
|
2879
|
+
pattern: "^[^\\x00]*$"
|
|
2880
|
+
},
|
|
2881
|
+
description: 'Command to run, as an argv array of 1-256 arguments of at most 4096 characters each. It is run directly, never through a shell; for pipes, redirects or globbing pass `["sh", "-c", "..."]`.',
|
|
2882
|
+
examples: [
|
|
2883
|
+
["nvidia-smi", "--query-gpu=name,memory.used", "--format=csv"]
|
|
2884
|
+
]
|
|
2885
|
+
},
|
|
2886
|
+
timeoutSeconds: {
|
|
2887
|
+
type: "integer",
|
|
2888
|
+
minimum: 1,
|
|
2889
|
+
maximum: 25,
|
|
2890
|
+
default: 20,
|
|
2891
|
+
description: "How long the call waits for the command to finish, in seconds. A command still running at this point returns with `timedOut: true`.",
|
|
2892
|
+
examples: [10]
|
|
2893
|
+
},
|
|
2894
|
+
cwd: {
|
|
2895
|
+
type: "string",
|
|
2896
|
+
pattern: "^/[^\\x00-\\x1f\\x7f]*$",
|
|
2897
|
+
maxLength: 1024,
|
|
2898
|
+
description: "Absolute working directory for the command, at most 1024 characters and without control characters. Defaults to the image's `WORKDIR`.",
|
|
2899
|
+
examples: ["/workspace"]
|
|
2900
|
+
},
|
|
2901
|
+
env: {
|
|
2902
|
+
type: "object",
|
|
2903
|
+
maxProperties: 64,
|
|
2904
|
+
propertyNames: {
|
|
2905
|
+
type: "string",
|
|
2906
|
+
minLength: 1,
|
|
2907
|
+
maxLength: 256,
|
|
2908
|
+
pattern: "^[^=\\x00]+$"
|
|
2909
|
+
},
|
|
2910
|
+
additionalProperties: {
|
|
2911
|
+
type: "string",
|
|
2912
|
+
maxLength: 16384,
|
|
2913
|
+
pattern: "^[^\\x00]*$"
|
|
2914
|
+
},
|
|
2915
|
+
description: "Up to 64 environment variables added to the container's environment for this command only. A name is 1-256 characters and must not contain `=` or a NUL character; a value is at most 16384 characters and must not contain a NUL character.",
|
|
2916
|
+
examples: [
|
|
2917
|
+
{
|
|
2918
|
+
HF_HOME: "/workspace/hf"
|
|
2919
|
+
}
|
|
2920
|
+
]
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
},
|
|
2807
2927
|
{
|
|
2808
2928
|
name: "get-cluster",
|
|
2809
2929
|
title: "Get cluster",
|
|
@@ -6866,6 +6986,122 @@ var generatedTools = [
|
|
|
6866
6986
|
}
|
|
6867
6987
|
];
|
|
6868
6988
|
|
|
6989
|
+
// src/specgen/validate.ts
|
|
6990
|
+
var import__ = require("ajv/dist/2020.js");
|
|
6991
|
+
function schemaValidationMode(value = process.env.MCP_SCHEMA_VALIDATION) {
|
|
6992
|
+
const mode = value?.trim().toLowerCase();
|
|
6993
|
+
return mode === "off" || mode === "enforce" ? mode : "shadow";
|
|
6994
|
+
}
|
|
6995
|
+
var ajv = new import__.Ajv2020({
|
|
6996
|
+
strict: false,
|
|
6997
|
+
allErrors: true,
|
|
6998
|
+
validateFormats: false
|
|
6999
|
+
});
|
|
7000
|
+
var compiled = /* @__PURE__ */ new WeakMap();
|
|
7001
|
+
function validatorFor(schema) {
|
|
7002
|
+
let validate = compiled.get(schema);
|
|
7003
|
+
if (!validate) {
|
|
7004
|
+
validate = ajv.compile(structuredClone(schema));
|
|
7005
|
+
compiled.set(schema, validate);
|
|
7006
|
+
}
|
|
7007
|
+
return validate;
|
|
7008
|
+
}
|
|
7009
|
+
var MAX_NULL_PASSES = 8;
|
|
7010
|
+
function isNullTypeError(error, data) {
|
|
7011
|
+
return error.keyword === "type" && error.instancePath !== "" && valueAt(data, error.instancePath) === null;
|
|
7012
|
+
}
|
|
7013
|
+
function pointerSegments(pointer) {
|
|
7014
|
+
return pointer.split("/").slice(1).map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
7015
|
+
}
|
|
7016
|
+
function valueAt(data, pointer) {
|
|
7017
|
+
let node = data;
|
|
7018
|
+
for (const key of pointerSegments(pointer)) {
|
|
7019
|
+
if (node === null || typeof node !== "object") return void 0;
|
|
7020
|
+
node = node[key];
|
|
7021
|
+
}
|
|
7022
|
+
return node;
|
|
7023
|
+
}
|
|
7024
|
+
function removeAt(data, pointer) {
|
|
7025
|
+
const segments = pointerSegments(pointer);
|
|
7026
|
+
const last = segments.pop();
|
|
7027
|
+
const parent = valueAt(data, segments.length ? `/${segments.join("/")}` : "");
|
|
7028
|
+
if (last === void 0 || parent === null || typeof parent !== "object")
|
|
7029
|
+
return false;
|
|
7030
|
+
if (Array.isArray(parent)) return false;
|
|
7031
|
+
delete parent[last];
|
|
7032
|
+
return true;
|
|
7033
|
+
}
|
|
7034
|
+
var WRAPPER_KEYWORDS = /* @__PURE__ */ new Set(["if"]);
|
|
7035
|
+
function toViolation(error) {
|
|
7036
|
+
const base = pointerSegments(error.instancePath);
|
|
7037
|
+
let path = base.join(".");
|
|
7038
|
+
let message = error.message ?? "is invalid";
|
|
7039
|
+
const params = error.params;
|
|
7040
|
+
if (error.keyword === "required" && typeof params.missingProperty === "string") {
|
|
7041
|
+
path = [...base, params.missingProperty].join(".");
|
|
7042
|
+
message = "is required";
|
|
7043
|
+
} else if (error.keyword === "additionalProperties" && typeof params.additionalProperty === "string") {
|
|
7044
|
+
path = [...base, params.additionalProperty].join(".");
|
|
7045
|
+
message = "is not an accepted argument here";
|
|
7046
|
+
} else if (error.keyword === "pattern") {
|
|
7047
|
+
message = "is not in an accepted format";
|
|
7048
|
+
}
|
|
7049
|
+
const allowed = error.keyword === "enum" ? params.allowedValues : error.keyword === "const" ? [params.allowedValue] : void 0;
|
|
7050
|
+
return {
|
|
7051
|
+
path,
|
|
7052
|
+
keyword: error.keyword,
|
|
7053
|
+
message,
|
|
7054
|
+
...allowed ? { allowed } : {},
|
|
7055
|
+
schemaPath: error.schemaPath
|
|
7056
|
+
};
|
|
7057
|
+
}
|
|
7058
|
+
function schemaViolations(schema, args, omitted = () => false) {
|
|
7059
|
+
const validate = validatorFor(schema);
|
|
7060
|
+
const data = structuredClone(
|
|
7061
|
+
Object.fromEntries(
|
|
7062
|
+
Object.entries(args).filter(([name, value]) => !omitted(name, value))
|
|
7063
|
+
)
|
|
7064
|
+
);
|
|
7065
|
+
for (let pass = 0; ; pass++) {
|
|
7066
|
+
if (validate(data)) return [];
|
|
7067
|
+
const errors = validate.errors ?? [];
|
|
7068
|
+
let removed = false;
|
|
7069
|
+
if (pass < MAX_NULL_PASSES) {
|
|
7070
|
+
for (const error of errors.filter((e) => isNullTypeError(e, data)))
|
|
7071
|
+
removed = removeAt(data, error.instancePath) || removed;
|
|
7072
|
+
}
|
|
7073
|
+
if (!removed) {
|
|
7074
|
+
return errors.filter((e) => !WRAPPER_KEYWORDS.has(e.keyword)).map(toViolation);
|
|
7075
|
+
}
|
|
7076
|
+
}
|
|
7077
|
+
}
|
|
7078
|
+
var INVALID_ARGUMENTS_HINT = "Fix the listed fields and call again.";
|
|
7079
|
+
function invalidArgumentsPayload(violations) {
|
|
7080
|
+
return {
|
|
7081
|
+
error: "Invalid arguments",
|
|
7082
|
+
code: "invalid_arguments",
|
|
7083
|
+
fields: violations.map(({ path, message, allowed }) => ({
|
|
7084
|
+
path,
|
|
7085
|
+
problem: message,
|
|
7086
|
+
...allowed ? { allowed } : {}
|
|
7087
|
+
})),
|
|
7088
|
+
hint: INVALID_ARGUMENTS_HINT
|
|
7089
|
+
};
|
|
7090
|
+
}
|
|
7091
|
+
function logSchemaViolations(tool, mode, violations) {
|
|
7092
|
+
console.error(
|
|
7093
|
+
"schema_violation",
|
|
7094
|
+
JSON.stringify({
|
|
7095
|
+
tool,
|
|
7096
|
+
mode,
|
|
7097
|
+
violations: violations.map(({ keyword, schemaPath }) => ({
|
|
7098
|
+
keyword,
|
|
7099
|
+
schemaPath
|
|
7100
|
+
}))
|
|
7101
|
+
})
|
|
7102
|
+
);
|
|
7103
|
+
}
|
|
7104
|
+
|
|
6869
7105
|
// src/specgen/tools/annotations.ts
|
|
6870
7106
|
var readOnly = {
|
|
6871
7107
|
readOnlyHint: true,
|
|
@@ -7080,6 +7316,8 @@ var DIRECTORY_TOOLS = {
|
|
|
7080
7316
|
"deploy-hub-repo": IN,
|
|
7081
7317
|
"detach-cost-center-resource": IN,
|
|
7082
7318
|
"endpoint-health": IN,
|
|
7319
|
+
// env can carry tokens (HF_TOKEN for a model download), so the directory omits it.
|
|
7320
|
+
"exec-pod": { include: true, omitInputs: ["body.env"] },
|
|
7083
7321
|
"get-capacity": IN,
|
|
7084
7322
|
"get-cluster": IN,
|
|
7085
7323
|
"get-cost-center": IN,
|
|
@@ -7199,6 +7437,21 @@ function directoryOmittedInputs(name) {
|
|
|
7199
7437
|
const decision = DIRECTORY_TOOLS[name];
|
|
7200
7438
|
return decision?.include ? decision.omitInputs ?? [] : [];
|
|
7201
7439
|
}
|
|
7440
|
+
function omittedInputsIn(omit, args) {
|
|
7441
|
+
return omit.filter((key) => {
|
|
7442
|
+
const [parent, child] = key.split(".");
|
|
7443
|
+
if (child === void 0) return parent in args;
|
|
7444
|
+
let value = args[parent];
|
|
7445
|
+
if (typeof value === "string") {
|
|
7446
|
+
try {
|
|
7447
|
+
value = JSON.parse(value);
|
|
7448
|
+
} catch {
|
|
7449
|
+
return false;
|
|
7450
|
+
}
|
|
7451
|
+
}
|
|
7452
|
+
return !!value && typeof value === "object" && child in value;
|
|
7453
|
+
});
|
|
7454
|
+
}
|
|
7202
7455
|
function profileForPath(pathname) {
|
|
7203
7456
|
return pathname.replace(/\/+$/, "") === DIRECTORY_PATH ? "directory" : "default";
|
|
7204
7457
|
}
|
|
@@ -10788,13 +11041,40 @@ function withoutCredentialExamples(schema) {
|
|
|
10788
11041
|
};
|
|
10789
11042
|
return strip(schema);
|
|
10790
11043
|
}
|
|
10791
|
-
function
|
|
10792
|
-
if (!omit.length) return schema;
|
|
11044
|
+
function withoutKeys(schema, omit) {
|
|
10793
11045
|
const properties = { ...schema.properties ?? {} };
|
|
10794
11046
|
for (const key of omit) delete properties[key];
|
|
10795
11047
|
const required = Array.isArray(schema.required) ? schema.required.filter((key) => !omit.includes(key)) : schema.required;
|
|
10796
11048
|
return { ...schema, properties, ...required ? { required } : {} };
|
|
10797
11049
|
}
|
|
11050
|
+
function withoutInputs(schema, omit) {
|
|
11051
|
+
if (!omit.length) return schema;
|
|
11052
|
+
let out = withoutKeys(
|
|
11053
|
+
schema,
|
|
11054
|
+
omit.filter((key) => !key.includes("."))
|
|
11055
|
+
);
|
|
11056
|
+
for (const key of omit.filter((k) => k.includes("."))) {
|
|
11057
|
+
const [parent, child] = key.split(".");
|
|
11058
|
+
const properties = out.properties ?? {};
|
|
11059
|
+
const node = properties[parent];
|
|
11060
|
+
if (!node) continue;
|
|
11061
|
+
const ref = typeof node.$ref === "string" ? node.$ref : void 0;
|
|
11062
|
+
const defName = ref?.startsWith("#/$defs/") ? ref.slice(8) : void 0;
|
|
11063
|
+
const defs = out.$defs ?? {};
|
|
11064
|
+
if (defName && defs[defName]) {
|
|
11065
|
+
out = {
|
|
11066
|
+
...out,
|
|
11067
|
+
$defs: { ...defs, [defName]: withoutKeys(defs[defName], [child]) }
|
|
11068
|
+
};
|
|
11069
|
+
} else {
|
|
11070
|
+
out = {
|
|
11071
|
+
...out,
|
|
11072
|
+
properties: { ...properties, [parent]: withoutKeys(node, [child]) }
|
|
11073
|
+
};
|
|
11074
|
+
}
|
|
11075
|
+
}
|
|
11076
|
+
return out;
|
|
11077
|
+
}
|
|
10798
11078
|
function callShape(schema) {
|
|
10799
11079
|
const defs = schema.$defs ?? {};
|
|
10800
11080
|
const resolve = (node) => {
|
|
@@ -10896,7 +11176,7 @@ function words2(name) {
|
|
|
10896
11176
|
|
|
10897
11177
|
// src/server.ts
|
|
10898
11178
|
var SERVER_NAME = "Runpod API Server";
|
|
10899
|
-
var SERVER_VERSION = true ? "4.
|
|
11179
|
+
var SERVER_VERSION = true ? "4.11.0" : "dev";
|
|
10900
11180
|
|
|
10901
11181
|
// src/specgen/analytics.ts
|
|
10902
11182
|
var import_node_crypto = require("crypto");
|
|
@@ -11607,6 +11887,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11607
11887
|
const caller = callerId(ctx.apiKey);
|
|
11608
11888
|
const profile = opts.profile ?? "default";
|
|
11609
11889
|
const directory = profile === "directory";
|
|
11890
|
+
const schemaMode = schemaValidationMode();
|
|
11610
11891
|
const alp = directory ? void 0 : opts.alp;
|
|
11611
11892
|
const servedGeneratedTools = directory ? generatedTools.filter((tool) => directoryIncludes(tool.name)) : generatedTools;
|
|
11612
11893
|
const servedCuratedTools = [
|
|
@@ -11713,7 +11994,7 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11713
11994
|
(tool) => tool.name === request.params.name
|
|
11714
11995
|
);
|
|
11715
11996
|
const curatedArgs = curated ? withoutNullOptionals(curated.inputSchema, args) : args;
|
|
11716
|
-
const omitted = directory ? directoryOmittedInputs(request.params.name)
|
|
11997
|
+
const omitted = directory ? omittedInputsIn(directoryOmittedInputs(request.params.name), args) : [];
|
|
11717
11998
|
const rejected = omitted.length ? {
|
|
11718
11999
|
ok: false,
|
|
11719
12000
|
status: 400,
|
|
@@ -11723,8 +12004,26 @@ function createSpecgenServer(ctx, version = "0.1.0", opts = {}) {
|
|
|
11723
12004
|
} : curated && !curated.lenientArguments ? validateArguments(
|
|
11724
12005
|
curated.inputSchema,
|
|
11725
12006
|
curatedArgs
|
|
11726
|
-
) : null;
|
|
11727
|
-
|
|
12007
|
+
) : generated ? validateArguments(generated.inputSchema, args) : null;
|
|
12008
|
+
let schemaRejected = null;
|
|
12009
|
+
if (!rejected && schemaMode !== "off") {
|
|
12010
|
+
const sent = generated ? argsAsSent(generated, args) : null;
|
|
12011
|
+
const violations = curated ? curated.lenientArguments ? [] : schemaViolations(curated.inputSchema, curatedArgs) : generated && sent ? schemaViolations(
|
|
12012
|
+
generated.inputSchema,
|
|
12013
|
+
sent,
|
|
12014
|
+
omittedEmptyQueryArg(generated)
|
|
12015
|
+
) : [];
|
|
12016
|
+
if (violations.length) {
|
|
12017
|
+
logSchemaViolations(request.params.name, schemaMode, violations);
|
|
12018
|
+
if (schemaMode === "enforce")
|
|
12019
|
+
schemaRejected = {
|
|
12020
|
+
ok: false,
|
|
12021
|
+
status: 400,
|
|
12022
|
+
payload: invalidArgumentsPayload(violations)
|
|
12023
|
+
};
|
|
12024
|
+
}
|
|
12025
|
+
}
|
|
12026
|
+
const result = rejected ?? schemaRejected ?? await runTool(
|
|
11728
12027
|
() => curated ? curated.handler(ctx, curatedArgs) : dispatchTool(generated, request.params.name, args)
|
|
11729
12028
|
);
|
|
11730
12029
|
logToolCall({
|
|
@@ -12063,6 +12362,7 @@ function createToolContext(options = {}) {
|
|
|
12063
12362
|
|
|
12064
12363
|
// src/specgen/not-found-limiter.ts
|
|
12065
12364
|
var SINK_TIMEOUT_MS2 = 3e3;
|
|
12365
|
+
var LOOP_LIMITED_TOOLS = /* @__PURE__ */ new Set(["get-pod"]);
|
|
12066
12366
|
var NOT_FOUND_LOOP = "not_found_loop";
|
|
12067
12367
|
var blocked = /* @__PURE__ */ new Map();
|
|
12068
12368
|
function notFoundSinkUrl(submitUrl) {
|
|
@@ -12087,7 +12387,7 @@ function createNotFoundLimiter(opts) {
|
|
|
12087
12387
|
};
|
|
12088
12388
|
},
|
|
12089
12389
|
onToolResult: (tool, status) => {
|
|
12090
|
-
if (status !== 404) return;
|
|
12390
|
+
if (status !== 404 || !LOOP_LIMITED_TOOLS.has(tool)) return;
|
|
12091
12391
|
const pair = `${opts.key}|${tool}`;
|
|
12092
12392
|
void fetchImpl(opts.sinkUrl, {
|
|
12093
12393
|
method: "POST",
|