api-documentation-mcp 0.1.1 → 0.2.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 +61 -17
- package/dist/index.js +2091 -922
- package/package.json +19 -5
package/dist/index.js
CHANGED
|
@@ -86,23 +86,23 @@ var require_code = __commonJS({
|
|
|
86
86
|
};
|
|
87
87
|
exports._Code = _Code;
|
|
88
88
|
exports.nil = new _Code("");
|
|
89
|
-
function _(strs, ...
|
|
89
|
+
function _(strs, ...args2) {
|
|
90
90
|
const code = [strs[0]];
|
|
91
91
|
let i = 0;
|
|
92
|
-
while (i <
|
|
93
|
-
addCodeArg(code,
|
|
92
|
+
while (i < args2.length) {
|
|
93
|
+
addCodeArg(code, args2[i]);
|
|
94
94
|
code.push(strs[++i]);
|
|
95
95
|
}
|
|
96
96
|
return new _Code(code);
|
|
97
97
|
}
|
|
98
98
|
exports._ = _;
|
|
99
99
|
var plus = new _Code("+");
|
|
100
|
-
function str(strs, ...
|
|
100
|
+
function str(strs, ...args2) {
|
|
101
101
|
const expr = [safeStringify(strs[0])];
|
|
102
102
|
let i = 0;
|
|
103
|
-
while (i <
|
|
103
|
+
while (i < args2.length) {
|
|
104
104
|
expr.push(plus);
|
|
105
|
-
addCodeArg(expr,
|
|
105
|
+
addCodeArg(expr, args2[i]);
|
|
106
106
|
expr.push(plus, safeStringify(strs[++i]));
|
|
107
107
|
}
|
|
108
108
|
optimize(expr);
|
|
@@ -657,10 +657,10 @@ var require_codegen = __commonJS({
|
|
|
657
657
|
}
|
|
658
658
|
};
|
|
659
659
|
var Func = class extends BlockNode {
|
|
660
|
-
constructor(name,
|
|
660
|
+
constructor(name, args2, async) {
|
|
661
661
|
super();
|
|
662
662
|
this.name = name;
|
|
663
|
-
this.args =
|
|
663
|
+
this.args = args2;
|
|
664
664
|
this.async = async;
|
|
665
665
|
}
|
|
666
666
|
render(opts) {
|
|
@@ -935,8 +935,8 @@ var require_codegen = __commonJS({
|
|
|
935
935
|
return this;
|
|
936
936
|
}
|
|
937
937
|
// `function` heading (or definition if funcBody is passed)
|
|
938
|
-
func(name,
|
|
939
|
-
this._blockNode(new Func(name,
|
|
938
|
+
func(name, args2 = code_1.nil, async, funcBody) {
|
|
939
|
+
this._blockNode(new Func(name, args2, async));
|
|
940
940
|
if (funcBody)
|
|
941
941
|
this.code(funcBody).endFunc();
|
|
942
942
|
return this;
|
|
@@ -1030,13 +1030,13 @@ var require_codegen = __commonJS({
|
|
|
1030
1030
|
}
|
|
1031
1031
|
exports.not = not;
|
|
1032
1032
|
var andCode = mappend(exports.operators.AND);
|
|
1033
|
-
function and(...
|
|
1034
|
-
return
|
|
1033
|
+
function and(...args2) {
|
|
1034
|
+
return args2.reduce(andCode);
|
|
1035
1035
|
}
|
|
1036
1036
|
exports.and = and;
|
|
1037
1037
|
var orCode = mappend(exports.operators.OR);
|
|
1038
|
-
function or(...
|
|
1039
|
-
return
|
|
1038
|
+
function or(...args2) {
|
|
1039
|
+
return args2.reduce(orCode);
|
|
1040
1040
|
}
|
|
1041
1041
|
exports.or = or;
|
|
1042
1042
|
function mappend(op) {
|
|
@@ -1769,8 +1769,8 @@ var require_code2 = __commonJS({
|
|
|
1769
1769
|
];
|
|
1770
1770
|
if (it.opts.dynamicRef)
|
|
1771
1771
|
valCxt.push([names_1.default.dynamicAnchors, names_1.default.dynamicAnchors]);
|
|
1772
|
-
const
|
|
1773
|
-
return context !== codegen_1.nil ? (0, codegen_1._)`${func}.call(${context}, ${
|
|
1772
|
+
const args2 = (0, codegen_1._)`${dataAndSchema}, ${gen.object(...valCxt)}`;
|
|
1773
|
+
return context !== codegen_1.nil ? (0, codegen_1._)`${func}.call(${context}, ${args2})` : (0, codegen_1._)`${func}(${args2})`;
|
|
1774
1774
|
}
|
|
1775
1775
|
exports.callValidateCode = callValidateCode;
|
|
1776
1776
|
var newRegExp = (0, codegen_1._)`new RegExp`;
|
|
@@ -3333,6 +3333,37 @@ var require_utils = __commonJS({
|
|
|
3333
3333
|
}
|
|
3334
3334
|
return output.join("");
|
|
3335
3335
|
}
|
|
3336
|
+
function removeDotSegmentsRelative(path) {
|
|
3337
|
+
if (path === "" || path[0] === "/") {
|
|
3338
|
+
return removeDotSegments(path);
|
|
3339
|
+
}
|
|
3340
|
+
const segments = path.split("/");
|
|
3341
|
+
const last = segments.length - 1;
|
|
3342
|
+
const output = [];
|
|
3343
|
+
let trailingDirectory = false;
|
|
3344
|
+
for (let i = 0; i <= last; i++) {
|
|
3345
|
+
const segment = segments[i];
|
|
3346
|
+
if (segment === "." || segment === "..") {
|
|
3347
|
+
if (segment === "..") {
|
|
3348
|
+
if (output.length !== 0 && output[output.length - 1] !== "..") {
|
|
3349
|
+
output.pop();
|
|
3350
|
+
} else {
|
|
3351
|
+
output.push("..");
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
trailingDirectory = i === last;
|
|
3355
|
+
} else {
|
|
3356
|
+
output.push(segment);
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
if (trailingDirectory && output[output.length - 1] !== "..") {
|
|
3360
|
+
output.push("");
|
|
3361
|
+
}
|
|
3362
|
+
if (output.length === 0 || output[0] === "" || output[0].includes(":")) {
|
|
3363
|
+
output.unshift(".");
|
|
3364
|
+
}
|
|
3365
|
+
return output.join("/");
|
|
3366
|
+
}
|
|
3336
3367
|
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
3337
3368
|
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
3338
3369
|
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
@@ -3593,6 +3624,7 @@ var require_utils = __commonJS({
|
|
|
3593
3624
|
encodeFragment,
|
|
3594
3625
|
escapePreservingEscapes,
|
|
3595
3626
|
removeDotSegments,
|
|
3627
|
+
removeDotSegmentsRelative,
|
|
3596
3628
|
isIPv4,
|
|
3597
3629
|
isUUID,
|
|
3598
3630
|
normalizeIPv6,
|
|
@@ -3816,16 +3848,18 @@ var require_schemes = __commonJS({
|
|
|
3816
3848
|
var require_fast_uri = __commonJS({
|
|
3817
3849
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
3818
3850
|
"use strict";
|
|
3819
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3851
|
+
var { normalizeIPv6, removeDotSegments, removeDotSegmentsRelative, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3820
3852
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3821
3853
|
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3822
3854
|
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3855
|
+
var MALFORMED_HOST_ERROR = "URI host is malformed.";
|
|
3856
|
+
var FORBIDDEN_DOMAIN_HOST_CHARACTER = /[\0-\x20"#/:<>?@[\\\]^`{|}\x7F]/u;
|
|
3857
|
+
function validateScheme(scheme) {
|
|
3858
|
+
const stringScheme = String(scheme);
|
|
3859
|
+
if (!VALID_SCHEME.test(stringScheme)) {
|
|
3826
3860
|
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3827
3861
|
}
|
|
3828
|
-
return
|
|
3862
|
+
return stringScheme;
|
|
3829
3863
|
}
|
|
3830
3864
|
function normalize(uri, options) {
|
|
3831
3865
|
if (typeof uri === "string") {
|
|
@@ -3862,6 +3896,9 @@ var require_fast_uri = __commonJS({
|
|
|
3862
3896
|
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3863
3897
|
const resolvedHost = resolved.host;
|
|
3864
3898
|
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3899
|
+
if (hasForbiddenDomainHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP)) {
|
|
3900
|
+
throw new Error(MALFORMED_HOST_ERROR);
|
|
3901
|
+
}
|
|
3865
3902
|
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3866
3903
|
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
|
|
3867
3904
|
if (resolved.error && !encodedASCIIHost) {
|
|
@@ -3903,14 +3940,15 @@ var require_fast_uri = __commonJS({
|
|
|
3903
3940
|
if (relative.path[0] === "/") {
|
|
3904
3941
|
target.path = removeDotSegments(relative.path);
|
|
3905
3942
|
} else {
|
|
3906
|
-
|
|
3943
|
+
const baseHasAuthority = base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0;
|
|
3944
|
+
if (baseHasAuthority && !base.path) {
|
|
3907
3945
|
target.path = "/" + relative.path;
|
|
3908
3946
|
} else if (!base.path) {
|
|
3909
3947
|
target.path = relative.path;
|
|
3910
3948
|
} else {
|
|
3911
3949
|
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
|
|
3912
3950
|
}
|
|
3913
|
-
target.path = removeDotSegments(target.path);
|
|
3951
|
+
target.path = base.scheme === void 0 && !baseHasAuthority && target.path[0] !== "/" ? removeDotSegmentsRelative(target.path) : removeDotSegments(target.path);
|
|
3914
3952
|
}
|
|
3915
3953
|
target.query = relative.query;
|
|
3916
3954
|
}
|
|
@@ -3948,12 +3986,13 @@ var require_fast_uri = __commonJS({
|
|
|
3948
3986
|
const options = Object.assign({}, opts);
|
|
3949
3987
|
const uriTokens = [];
|
|
3950
3988
|
if (component.scheme) {
|
|
3951
|
-
component.scheme =
|
|
3989
|
+
component.scheme = validateScheme(component.scheme);
|
|
3952
3990
|
}
|
|
3953
3991
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3954
3992
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3955
3993
|
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
3956
|
-
const
|
|
3994
|
+
const schemelessReference = (component.scheme === void 0 || options.reference === "suffix") && !hasAuthority;
|
|
3995
|
+
const pathNoScheme = !options.skipEscape && schemelessReference;
|
|
3957
3996
|
if (component.path !== void 0) {
|
|
3958
3997
|
if (!options.skipEscape) {
|
|
3959
3998
|
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
@@ -3962,7 +4001,7 @@ var require_fast_uri = __commonJS({
|
|
|
3962
4001
|
}
|
|
3963
4002
|
}
|
|
3964
4003
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3965
|
-
component.scheme =
|
|
4004
|
+
component.scheme = validateScheme(component.scheme);
|
|
3966
4005
|
uriTokens.push(component.scheme, ":");
|
|
3967
4006
|
}
|
|
3968
4007
|
const authority = recomposeAuthority(component);
|
|
@@ -3978,9 +4017,9 @@ var require_fast_uri = __commonJS({
|
|
|
3978
4017
|
if (component.path !== void 0) {
|
|
3979
4018
|
let s = component.path;
|
|
3980
4019
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3981
|
-
s = removeDotSegments(s);
|
|
4020
|
+
s = schemelessReference && s[0] !== "/" ? removeDotSegmentsRelative(s) : removeDotSegments(s);
|
|
3982
4021
|
}
|
|
3983
|
-
if (
|
|
4022
|
+
if (schemelessReference) {
|
|
3984
4023
|
s = serializePathEncoding(s, true);
|
|
3985
4024
|
}
|
|
3986
4025
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") {
|
|
@@ -4027,16 +4066,34 @@ var require_fast_uri = __commonJS({
|
|
|
4027
4066
|
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4028
4067
|
}
|
|
4029
4068
|
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
4069
|
+
if (hasForbiddenDomainHost(parsed, options, schemeHandler, isIP)) {
|
|
4070
|
+
parsed.error = parsed.error || MALFORMED_HOST_ERROR;
|
|
4071
|
+
return true;
|
|
4072
|
+
}
|
|
4030
4073
|
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
4074
|
+
let url;
|
|
4031
4075
|
try {
|
|
4032
|
-
|
|
4076
|
+
url = new URL("http://" + parsed.host);
|
|
4033
4077
|
} catch (e) {
|
|
4034
4078
|
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
4035
4079
|
return true;
|
|
4036
4080
|
}
|
|
4081
|
+
if (!isHostOnlyURL(url)) {
|
|
4082
|
+
parsed.error = parsed.error || MALFORMED_HOST_ERROR;
|
|
4083
|
+
return true;
|
|
4084
|
+
}
|
|
4085
|
+
parsed.host = url.hostname;
|
|
4037
4086
|
}
|
|
4038
4087
|
return false;
|
|
4039
4088
|
}
|
|
4089
|
+
function hasForbiddenDomainHost(parsed, options, schemeHandler, isIP) {
|
|
4090
|
+
return Boolean(
|
|
4091
|
+
parsed.host && isIP === false && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && FORBIDDEN_DOMAIN_HOST_CHARACTER.test(parsed.host)
|
|
4092
|
+
);
|
|
4093
|
+
}
|
|
4094
|
+
function isHostOnlyURL(url) {
|
|
4095
|
+
return url.username === "" && url.password === "" && url.port === "" && url.pathname === "/" && url.search === "" && url.hash === "" && url.hostname !== "";
|
|
4096
|
+
}
|
|
4040
4097
|
function parseWithStatus(uri, opts) {
|
|
4041
4098
|
const options = Object.assign({}, opts);
|
|
4042
4099
|
const parsed = {
|
|
@@ -4091,9 +4148,8 @@ var require_fast_uri = __commonJS({
|
|
|
4091
4148
|
parsed.query = matches[7];
|
|
4092
4149
|
parsed.fragment = matches[8];
|
|
4093
4150
|
if (parsed.scheme !== void 0) {
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
parsed.scheme = decodedScheme.toLowerCase();
|
|
4151
|
+
if (VALID_SCHEME.test(parsed.scheme)) {
|
|
4152
|
+
parsed.scheme = parsed.scheme.toLowerCase();
|
|
4097
4153
|
} else {
|
|
4098
4154
|
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4099
4155
|
malformedScheme = true;
|
|
@@ -4121,7 +4177,7 @@ var require_fast_uri = __commonJS({
|
|
|
4121
4177
|
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4122
4178
|
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4123
4179
|
if (malformedIPLiteral) {
|
|
4124
|
-
parsed.error = parsed.error ||
|
|
4180
|
+
parsed.error = parsed.error || MALFORMED_HOST_ERROR;
|
|
4125
4181
|
malformedAuthorityOrPort = true;
|
|
4126
4182
|
}
|
|
4127
4183
|
} else {
|
|
@@ -4149,7 +4205,7 @@ var require_fast_uri = __commonJS({
|
|
|
4149
4205
|
if (!isIP) {
|
|
4150
4206
|
host = normalizePercentEncoding(host.toLowerCase());
|
|
4151
4207
|
}
|
|
4152
|
-
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
4208
|
+
parsed.host = isIP || options.scheme !== "null" ? reescapeHostDelimiters(host, isIP) : host;
|
|
4153
4209
|
}
|
|
4154
4210
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
4155
4211
|
if (parsed.path) {
|
|
@@ -7195,12 +7251,65 @@ var require_dist = __commonJS({
|
|
|
7195
7251
|
}
|
|
7196
7252
|
});
|
|
7197
7253
|
|
|
7198
|
-
// src/
|
|
7199
|
-
import {
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7254
|
+
// src/cli.ts
|
|
7255
|
+
import { readFileSync } from "node:fs";
|
|
7256
|
+
|
|
7257
|
+
// src/registry.ts
|
|
7258
|
+
function parseInput(schema, rawInput) {
|
|
7259
|
+
const result = schema.safeParse(rawInput ?? {});
|
|
7260
|
+
if (result.success) return result.data;
|
|
7261
|
+
const lines = result.error.issues.map((issue2) => `${issue2.path.join(".") || "params"}: ${issue2.message}`);
|
|
7262
|
+
throw new Error(`Invalid parameters: ${lines.join("; ")}`);
|
|
7263
|
+
}
|
|
7264
|
+
function defineCommand(definition) {
|
|
7265
|
+
return {
|
|
7266
|
+
id: definition.id,
|
|
7267
|
+
group: definition.group,
|
|
7268
|
+
title: definition.title,
|
|
7269
|
+
description: definition.description,
|
|
7270
|
+
params: definition.params,
|
|
7271
|
+
readOnly: definition.readOnly,
|
|
7272
|
+
destructive: definition.destructive === true,
|
|
7273
|
+
run: (rawInput) => definition.run(parseInput(definition.params, rawInput))
|
|
7274
|
+
};
|
|
7275
|
+
}
|
|
7276
|
+
function unwrap(schema) {
|
|
7277
|
+
let current = schema;
|
|
7278
|
+
for (let depth = 0; depth < 10; depth += 1) {
|
|
7279
|
+
const def = current._def;
|
|
7280
|
+
if (def.innerType) current = def.innerType;
|
|
7281
|
+
else if (def.schema) current = def.schema;
|
|
7282
|
+
else break;
|
|
7283
|
+
}
|
|
7284
|
+
return current;
|
|
7285
|
+
}
|
|
7286
|
+
function typeName(schema) {
|
|
7287
|
+
const inner = unwrap(schema);
|
|
7288
|
+
const kind = inner._def.typeName ?? "unknown";
|
|
7289
|
+
return kind.replace(/^Zod/, "").toLowerCase();
|
|
7290
|
+
}
|
|
7291
|
+
function describeParams(schema) {
|
|
7292
|
+
return Object.entries(schema.shape).map(([name, field]) => {
|
|
7293
|
+
const field_ = field;
|
|
7294
|
+
return {
|
|
7295
|
+
name,
|
|
7296
|
+
type: typeName(field_),
|
|
7297
|
+
required: !field_.isOptional(),
|
|
7298
|
+
...field_.description ? { description: field_.description } : {}
|
|
7299
|
+
};
|
|
7300
|
+
});
|
|
7301
|
+
}
|
|
7302
|
+
function describeCommand(command) {
|
|
7303
|
+
return {
|
|
7304
|
+
id: command.id,
|
|
7305
|
+
group: command.group,
|
|
7306
|
+
title: command.title,
|
|
7307
|
+
description: command.description,
|
|
7308
|
+
readOnly: command.readOnly,
|
|
7309
|
+
destructive: command.destructive,
|
|
7310
|
+
params: describeParams(command.params)
|
|
7311
|
+
};
|
|
7312
|
+
}
|
|
7204
7313
|
|
|
7205
7314
|
// node_modules/zod/v3/external.js
|
|
7206
7315
|
var external_exports = {};
|
|
@@ -8158,24 +8267,24 @@ var base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=)
|
|
|
8158
8267
|
var base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
|
|
8159
8268
|
var dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
|
|
8160
8269
|
var dateRegex = new RegExp(`^${dateRegexSource}$`);
|
|
8161
|
-
function timeRegexSource(
|
|
8270
|
+
function timeRegexSource(args2) {
|
|
8162
8271
|
let secondsRegexSource = `[0-5]\\d`;
|
|
8163
|
-
if (
|
|
8164
|
-
secondsRegexSource = `${secondsRegexSource}\\.\\d{${
|
|
8165
|
-
} else if (
|
|
8272
|
+
if (args2.precision) {
|
|
8273
|
+
secondsRegexSource = `${secondsRegexSource}\\.\\d{${args2.precision}}`;
|
|
8274
|
+
} else if (args2.precision == null) {
|
|
8166
8275
|
secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`;
|
|
8167
8276
|
}
|
|
8168
|
-
const secondsQuantifier =
|
|
8277
|
+
const secondsQuantifier = args2.precision ? "+" : "?";
|
|
8169
8278
|
return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`;
|
|
8170
8279
|
}
|
|
8171
|
-
function timeRegex(
|
|
8172
|
-
return new RegExp(`^${timeRegexSource(
|
|
8280
|
+
function timeRegex(args2) {
|
|
8281
|
+
return new RegExp(`^${timeRegexSource(args2)}$`);
|
|
8173
8282
|
}
|
|
8174
|
-
function datetimeRegex(
|
|
8175
|
-
let regex = `${dateRegexSource}T${timeRegexSource(
|
|
8283
|
+
function datetimeRegex(args2) {
|
|
8284
|
+
let regex = `${dateRegexSource}T${timeRegexSource(args2)}`;
|
|
8176
8285
|
const opts = [];
|
|
8177
|
-
opts.push(
|
|
8178
|
-
if (
|
|
8286
|
+
opts.push(args2.local ? `Z?` : `Z`);
|
|
8287
|
+
if (args2.offset)
|
|
8179
8288
|
opts.push(`([+-]\\d{2}:?\\d{2})`);
|
|
8180
8289
|
regex = `${regex}(${opts.join("|")})`;
|
|
8181
8290
|
return new RegExp(`^${regex}$`);
|
|
@@ -10483,9 +10592,9 @@ var ZodFunction = class _ZodFunction extends ZodType {
|
|
|
10483
10592
|
});
|
|
10484
10593
|
return INVALID;
|
|
10485
10594
|
}
|
|
10486
|
-
function makeArgsIssue(
|
|
10595
|
+
function makeArgsIssue(args2, error2) {
|
|
10487
10596
|
return makeIssue({
|
|
10488
|
-
data:
|
|
10597
|
+
data: args2,
|
|
10489
10598
|
path: ctx.path,
|
|
10490
10599
|
errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), en_default].filter((x) => !!x),
|
|
10491
10600
|
issueData: {
|
|
@@ -10509,10 +10618,10 @@ var ZodFunction = class _ZodFunction extends ZodType {
|
|
|
10509
10618
|
const fn = ctx.data;
|
|
10510
10619
|
if (this._def.returns instanceof ZodPromise) {
|
|
10511
10620
|
const me = this;
|
|
10512
|
-
return OK(async function(...
|
|
10621
|
+
return OK(async function(...args2) {
|
|
10513
10622
|
const error2 = new ZodError([]);
|
|
10514
|
-
const parsedArgs = await me._def.args.parseAsync(
|
|
10515
|
-
error2.addIssue(makeArgsIssue(
|
|
10623
|
+
const parsedArgs = await me._def.args.parseAsync(args2, params).catch((e) => {
|
|
10624
|
+
error2.addIssue(makeArgsIssue(args2, e));
|
|
10516
10625
|
throw error2;
|
|
10517
10626
|
});
|
|
10518
10627
|
const result = await Reflect.apply(fn, this, parsedArgs);
|
|
@@ -10524,10 +10633,10 @@ var ZodFunction = class _ZodFunction extends ZodType {
|
|
|
10524
10633
|
});
|
|
10525
10634
|
} else {
|
|
10526
10635
|
const me = this;
|
|
10527
|
-
return OK(function(...
|
|
10528
|
-
const parsedArgs = me._def.args.safeParse(
|
|
10636
|
+
return OK(function(...args2) {
|
|
10637
|
+
const parsedArgs = me._def.args.safeParse(args2, params);
|
|
10529
10638
|
if (!parsedArgs.success) {
|
|
10530
|
-
throw new ZodError([makeArgsIssue(
|
|
10639
|
+
throw new ZodError([makeArgsIssue(args2, parsedArgs.error)]);
|
|
10531
10640
|
}
|
|
10532
10641
|
const result = Reflect.apply(fn, this, parsedArgs.data);
|
|
10533
10642
|
const parsedReturns = me._def.returns.safeParse(result, params);
|
|
@@ -10564,9 +10673,9 @@ var ZodFunction = class _ZodFunction extends ZodType {
|
|
|
10564
10673
|
const validatedFunc = this.parse(func);
|
|
10565
10674
|
return validatedFunc;
|
|
10566
10675
|
}
|
|
10567
|
-
static create(
|
|
10676
|
+
static create(args2, returns, params) {
|
|
10568
10677
|
return new _ZodFunction({
|
|
10569
|
-
args:
|
|
10678
|
+
args: args2 ? args2 : ZodTuple.create([]).rest(ZodUnknown.create()),
|
|
10570
10679
|
returns: returns || ZodUnknown.create(),
|
|
10571
10680
|
typeName: ZodFirstPartyTypeKind.ZodFunction,
|
|
10572
10681
|
...processCreateParams(params)
|
|
@@ -11243,163 +11352,1460 @@ var coerce = {
|
|
|
11243
11352
|
};
|
|
11244
11353
|
var NEVER = INVALID;
|
|
11245
11354
|
|
|
11246
|
-
//
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
if (
|
|
11263
|
-
Object.defineProperty(inst, k, { value: _.prototype[k].bind(inst) });
|
|
11355
|
+
// src/commands/changes.ts
|
|
11356
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
11357
|
+
|
|
11358
|
+
// src/operations.ts
|
|
11359
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11360
|
+
|
|
11361
|
+
// src/tree.ts
|
|
11362
|
+
import { randomUUID } from "node:crypto";
|
|
11363
|
+
function isFolder(node) {
|
|
11364
|
+
return node.kind === "folder";
|
|
11365
|
+
}
|
|
11366
|
+
function findNode(nodes, id) {
|
|
11367
|
+
for (const node of nodes) {
|
|
11368
|
+
if (node.id === id) return node;
|
|
11369
|
+
if (isFolder(node)) {
|
|
11370
|
+
const nested = findNode(node.children, id);
|
|
11371
|
+
if (nested) return nested;
|
|
11264
11372
|
}
|
|
11265
|
-
inst._zod.constr = _;
|
|
11266
|
-
inst._zod.def = def;
|
|
11267
|
-
}
|
|
11268
|
-
const Parent = params?.Parent ?? Object;
|
|
11269
|
-
class Definition extends Parent {
|
|
11270
11373
|
}
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11374
|
+
return void 0;
|
|
11375
|
+
}
|
|
11376
|
+
function findRequest(nodes, id) {
|
|
11377
|
+
const node = findNode(nodes, id);
|
|
11378
|
+
if (!node || isFolder(node)) throw new Error(`Request "${id}" was not found.`);
|
|
11379
|
+
return node;
|
|
11380
|
+
}
|
|
11381
|
+
function findParentId(nodes, id, parentId3 = null) {
|
|
11382
|
+
for (const node of nodes) {
|
|
11383
|
+
if (node.id === id) return parentId3;
|
|
11384
|
+
if (isFolder(node)) {
|
|
11385
|
+
const nested = findParentId(node.children, id, node.id);
|
|
11386
|
+
if (nested !== void 0) return nested;
|
|
11279
11387
|
}
|
|
11280
|
-
return inst;
|
|
11281
11388
|
}
|
|
11282
|
-
|
|
11283
|
-
Object.defineProperty(_, Symbol.hasInstance, {
|
|
11284
|
-
value: (inst) => {
|
|
11285
|
-
if (params?.Parent && inst instanceof params.Parent)
|
|
11286
|
-
return true;
|
|
11287
|
-
return inst?._zod?.traits?.has(name);
|
|
11288
|
-
}
|
|
11289
|
-
});
|
|
11290
|
-
Object.defineProperty(_, "name", { value: name });
|
|
11291
|
-
return _;
|
|
11389
|
+
return void 0;
|
|
11292
11390
|
}
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11391
|
+
function insertNode(nodes, parentId3, node, index) {
|
|
11392
|
+
if (parentId3 === null) {
|
|
11393
|
+
const next = [...nodes];
|
|
11394
|
+
next.splice(index === void 0 ? next.length : Math.min(index, next.length), 0, node);
|
|
11395
|
+
return next;
|
|
11297
11396
|
}
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
captureStackTrace: () => captureStackTrace,
|
|
11322
|
-
cleanEnum: () => cleanEnum,
|
|
11323
|
-
cleanRegex: () => cleanRegex,
|
|
11324
|
-
clone: () => clone,
|
|
11325
|
-
createTransparentProxy: () => createTransparentProxy,
|
|
11326
|
-
defineLazy: () => defineLazy,
|
|
11327
|
-
esc: () => esc,
|
|
11328
|
-
escapeRegex: () => escapeRegex,
|
|
11329
|
-
extend: () => extend,
|
|
11330
|
-
finalizeIssue: () => finalizeIssue,
|
|
11331
|
-
floatSafeRemainder: () => floatSafeRemainder2,
|
|
11332
|
-
getElementAtPath: () => getElementAtPath,
|
|
11333
|
-
getEnumValues: () => getEnumValues,
|
|
11334
|
-
getLengthableOrigin: () => getLengthableOrigin,
|
|
11335
|
-
getParsedType: () => getParsedType2,
|
|
11336
|
-
getSizableOrigin: () => getSizableOrigin,
|
|
11337
|
-
isObject: () => isObject,
|
|
11338
|
-
isPlainObject: () => isPlainObject,
|
|
11339
|
-
issue: () => issue,
|
|
11340
|
-
joinValues: () => joinValues,
|
|
11341
|
-
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
11342
|
-
merge: () => merge,
|
|
11343
|
-
normalizeParams: () => normalizeParams,
|
|
11344
|
-
nullish: () => nullish,
|
|
11345
|
-
numKeys: () => numKeys,
|
|
11346
|
-
omit: () => omit,
|
|
11347
|
-
optionalKeys: () => optionalKeys,
|
|
11348
|
-
partial: () => partial,
|
|
11349
|
-
pick: () => pick,
|
|
11350
|
-
prefixIssues: () => prefixIssues,
|
|
11351
|
-
primitiveTypes: () => primitiveTypes,
|
|
11352
|
-
promiseAllObject: () => promiseAllObject,
|
|
11353
|
-
propertyKeyTypes: () => propertyKeyTypes,
|
|
11354
|
-
randomString: () => randomString,
|
|
11355
|
-
required: () => required,
|
|
11356
|
-
stringifyPrimitive: () => stringifyPrimitive,
|
|
11357
|
-
unwrapMessage: () => unwrapMessage
|
|
11358
|
-
});
|
|
11359
|
-
function assertEqual(val) {
|
|
11360
|
-
return val;
|
|
11361
|
-
}
|
|
11362
|
-
function assertNotEqual(val) {
|
|
11363
|
-
return val;
|
|
11364
|
-
}
|
|
11365
|
-
function assertIs(_arg) {
|
|
11366
|
-
}
|
|
11367
|
-
function assertNever(_x) {
|
|
11368
|
-
throw new Error();
|
|
11369
|
-
}
|
|
11370
|
-
function assert(_) {
|
|
11397
|
+
const insertInto = (siblings) => {
|
|
11398
|
+
for (let position = 0; position < siblings.length; position += 1) {
|
|
11399
|
+
const child = siblings[position];
|
|
11400
|
+
if (!isFolder(child)) continue;
|
|
11401
|
+
if (child.id === parentId3) {
|
|
11402
|
+
const children = [...child.children];
|
|
11403
|
+
children.splice(index === void 0 ? children.length : Math.min(index, children.length), 0, node);
|
|
11404
|
+
const next = [...siblings];
|
|
11405
|
+
next[position] = { ...child, children };
|
|
11406
|
+
return { nodes: next, found: true };
|
|
11407
|
+
}
|
|
11408
|
+
const nested = insertInto(child.children);
|
|
11409
|
+
if (nested.found) {
|
|
11410
|
+
const next = [...siblings];
|
|
11411
|
+
next[position] = { ...child, children: nested.nodes };
|
|
11412
|
+
return { nodes: next, found: true };
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11415
|
+
return { nodes: siblings, found: false };
|
|
11416
|
+
};
|
|
11417
|
+
const result = insertInto(nodes);
|
|
11418
|
+
if (!result.found) throw new Error(`Parent folder "${parentId3}" was not found.`);
|
|
11419
|
+
return result.nodes;
|
|
11371
11420
|
}
|
|
11372
|
-
function
|
|
11373
|
-
const
|
|
11374
|
-
|
|
11375
|
-
|
|
11421
|
+
function removeNode(nodes, id) {
|
|
11422
|
+
const directIndex = nodes.findIndex((node) => node.id === id);
|
|
11423
|
+
if (directIndex >= 0) {
|
|
11424
|
+
const next = [...nodes];
|
|
11425
|
+
const [removed] = next.splice(directIndex, 1);
|
|
11426
|
+
return { tree: next, removed };
|
|
11427
|
+
}
|
|
11428
|
+
for (let index = 0; index < nodes.length; index += 1) {
|
|
11429
|
+
const node = nodes[index];
|
|
11430
|
+
if (!isFolder(node)) continue;
|
|
11431
|
+
const result = removeNode(node.children, id);
|
|
11432
|
+
if (!result.removed) continue;
|
|
11433
|
+
const next = [...nodes];
|
|
11434
|
+
next[index] = { ...node, children: result.tree };
|
|
11435
|
+
return { tree: next, removed: result.removed };
|
|
11436
|
+
}
|
|
11437
|
+
return { tree: nodes };
|
|
11376
11438
|
}
|
|
11377
|
-
function
|
|
11378
|
-
|
|
11439
|
+
function updateNode(nodes, id, update) {
|
|
11440
|
+
let found = false;
|
|
11441
|
+
const tree = nodes.map((node) => {
|
|
11442
|
+
if (node.id === id) {
|
|
11443
|
+
found = true;
|
|
11444
|
+
return update(node);
|
|
11445
|
+
}
|
|
11446
|
+
if (!isFolder(node)) return node;
|
|
11447
|
+
const nested = updateNode(node.children, id, update);
|
|
11448
|
+
if (!nested.found) return node;
|
|
11449
|
+
found = true;
|
|
11450
|
+
return { ...node, children: nested.tree };
|
|
11451
|
+
});
|
|
11452
|
+
return { tree, found };
|
|
11379
11453
|
}
|
|
11380
|
-
function
|
|
11381
|
-
|
|
11382
|
-
return value.toString();
|
|
11383
|
-
return value;
|
|
11454
|
+
function requestList(nodes) {
|
|
11455
|
+
return nodes.flatMap((node) => isFolder(node) ? requestList(node.children) : [node]);
|
|
11384
11456
|
}
|
|
11385
|
-
function
|
|
11386
|
-
|
|
11457
|
+
function cloneWithNewIds(node) {
|
|
11458
|
+
if (isFolder(node)) return { ...node, id: randomUUID(), children: node.children.map(cloneWithNewIds) };
|
|
11387
11459
|
return {
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11394
|
-
throw new Error("cached value already set");
|
|
11395
|
-
}
|
|
11460
|
+
...node,
|
|
11461
|
+
id: randomUUID(),
|
|
11462
|
+
headers: node.headers?.map((item) => ({ ...item, id: randomUUID() })),
|
|
11463
|
+
params: node.params?.map((item) => ({ ...item, id: randomUUID() })),
|
|
11464
|
+
pathParams: node.pathParams?.map((item) => ({ ...item, id: randomUUID() })),
|
|
11465
|
+
bodyFields: node.bodyFields?.map((item) => ({ ...item, id: randomUUID() }))
|
|
11396
11466
|
};
|
|
11397
11467
|
}
|
|
11398
|
-
function
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
const
|
|
11468
|
+
function normalizeRequest(input, existing) {
|
|
11469
|
+
const headers = input.headers ?? existing?.headers ?? [];
|
|
11470
|
+
const params = input.params ?? existing?.params ?? [];
|
|
11471
|
+
const pathParams = input.pathParams ?? existing?.pathParams ?? [];
|
|
11472
|
+
const bodyFields = input.bodyFields ?? existing?.bodyFields ?? [];
|
|
11473
|
+
const responses = input.responses ?? existing?.responses ?? [];
|
|
11474
|
+
return {
|
|
11475
|
+
...existing,
|
|
11476
|
+
...input,
|
|
11477
|
+
id: existing?.id ?? input.id ?? randomUUID(),
|
|
11478
|
+
kind: "request",
|
|
11479
|
+
name: input.name,
|
|
11480
|
+
method: input.method.toUpperCase(),
|
|
11481
|
+
url: input.url,
|
|
11482
|
+
body: input.body ?? existing?.body ?? "",
|
|
11483
|
+
headers: headers.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
11484
|
+
params: params.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
11485
|
+
pathParams: pathParams.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
11486
|
+
bodyFields: bodyFields.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
11487
|
+
responses: responses.map((response) => ({
|
|
11488
|
+
...response,
|
|
11489
|
+
id: response.id || randomUUID(),
|
|
11490
|
+
content: response.content.map((content) => ({ ...content, id: content.id || randomUUID() }))
|
|
11491
|
+
}))
|
|
11492
|
+
};
|
|
11493
|
+
}
|
|
11494
|
+
|
|
11495
|
+
// src/redact.ts
|
|
11496
|
+
var referencePattern = /^\s*\{\{[^{}]+\}\}\s*$/;
|
|
11497
|
+
function maskSecret(value) {
|
|
11498
|
+
return referencePattern.test(value) ? value : "<redacted>";
|
|
11499
|
+
}
|
|
11500
|
+
function sanitizeUrl(value) {
|
|
11501
|
+
try {
|
|
11502
|
+
const url = new URL(value);
|
|
11503
|
+
if (url.username) url.username = "<redacted>";
|
|
11504
|
+
if (url.password) url.password = "<redacted>";
|
|
11505
|
+
for (const key of [...url.searchParams.keys()]) {
|
|
11506
|
+
if (isSensitiveName(key)) url.searchParams.set(key, maskSecret(url.searchParams.get(key) ?? ""));
|
|
11507
|
+
}
|
|
11508
|
+
return url.toString();
|
|
11509
|
+
} catch {
|
|
11510
|
+
return value;
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11513
|
+
function isSensitiveName(value) {
|
|
11514
|
+
return /authorization|cookie|token|secret|password|\bkey\b|api[-_]?key|client[-_]?secret/i.test(value);
|
|
11515
|
+
}
|
|
11516
|
+
function redactBody(value) {
|
|
11517
|
+
try {
|
|
11518
|
+
const parsed = JSON.parse(value);
|
|
11519
|
+
const redact = (item) => {
|
|
11520
|
+
if (Array.isArray(item)) return item.map(redact);
|
|
11521
|
+
if (!item || typeof item !== "object") return item;
|
|
11522
|
+
return Object.fromEntries(Object.entries(item).map(([key, entry]) => [key, isSensitiveName(key) ? "<redacted>" : redact(entry)]));
|
|
11523
|
+
};
|
|
11524
|
+
return JSON.stringify(redact(parsed), null, 2);
|
|
11525
|
+
} catch {
|
|
11526
|
+
return value.replace(
|
|
11527
|
+
/\b(authorization|cookie|token|secret|password|api[-_]?key|client[-_]?secret|key)\b\s*[:=]\s*(?:Bearer\s+)?(?:"[^"]*"|'[^']*'|[^,\r\n;}]+)/gi,
|
|
11528
|
+
"$1: <redacted>"
|
|
11529
|
+
);
|
|
11530
|
+
}
|
|
11531
|
+
}
|
|
11532
|
+
function safeRequest(request) {
|
|
11533
|
+
return {
|
|
11534
|
+
...request,
|
|
11535
|
+
url: sanitizeUrl(request.url),
|
|
11536
|
+
body: redactBody(request.body),
|
|
11537
|
+
...request.documentation ? { documentation: redactBody(request.documentation) } : {},
|
|
11538
|
+
...request.responses ? {
|
|
11539
|
+
responses: request.responses.map((response) => ({
|
|
11540
|
+
...response,
|
|
11541
|
+
content: response.content.map((content) => ({ ...content, example: redactBody(content.example) }))
|
|
11542
|
+
}))
|
|
11543
|
+
} : {},
|
|
11544
|
+
...request.openApiSchemas ? { openApiSchemas: JSON.parse(redactBody(JSON.stringify(request.openApiSchemas))) } : {},
|
|
11545
|
+
...request.headers ? { headers: request.headers.map((header) => ({ ...header, value: isSensitiveName(header.name) ? maskSecret(header.value) : header.value })) } : {},
|
|
11546
|
+
...request.params ? { params: request.params.map((param) => ({ ...param, value: isSensitiveName(param.name) ? maskSecret(param.value) : param.value })) } : {},
|
|
11547
|
+
...request.pathParams ? { pathParams: request.pathParams.map((param) => ({ ...param, value: isSensitiveName(param.name) ? maskSecret(param.value) : param.value })) } : {},
|
|
11548
|
+
...request.bodyFields ? { bodyFields: request.bodyFields.map((field) => ({ ...field, value: isSensitiveName(field.name) ? maskSecret(field.value) : field.value, filePath: void 0 })) } : {},
|
|
11549
|
+
...request.auth?.type === "bearer" ? { auth: { type: "bearer", token: maskSecret(request.auth.token) } } : {},
|
|
11550
|
+
...request.auth?.type === "basic" ? { auth: { type: "basic", username: maskSecret(request.auth.username), password: maskSecret(request.auth.password) } } : {},
|
|
11551
|
+
...request.auth?.type === "api-key" ? { auth: { ...request.auth, value: maskSecret(request.auth.value) } } : {},
|
|
11552
|
+
bodyPath: void 0
|
|
11553
|
+
};
|
|
11554
|
+
}
|
|
11555
|
+
function safeTree(nodes) {
|
|
11556
|
+
return nodes.map(
|
|
11557
|
+
(node) => isFolder(node) ? { id: node.id, kind: node.kind, name: node.name, children: safeTree(node.children) } : { id: node.id, kind: node.kind, name: node.name, method: node.method, url: sanitizeUrl(node.url), deprecated: node.deprecated === true }
|
|
11558
|
+
);
|
|
11559
|
+
}
|
|
11560
|
+
function summarize(node) {
|
|
11561
|
+
if (!node) return void 0;
|
|
11562
|
+
return isFolder(node) ? { id: node.id, kind: node.kind, name: node.name, childCount: node.children.length } : safeRequest(node);
|
|
11563
|
+
}
|
|
11564
|
+
|
|
11565
|
+
// src/operations.ts
|
|
11566
|
+
function applyOperation(tree, operation) {
|
|
11567
|
+
if (operation.action === "create_folder") {
|
|
11568
|
+
const parent = operation.parentId ? findNode(tree, operation.parentId) : void 0;
|
|
11569
|
+
if (operation.parentId && (!parent || !isFolder(parent))) throw new Error(`Parent folder "${operation.parentId}" was not found.`);
|
|
11570
|
+
const folder = { id: randomUUID2(), kind: "folder", name: operation.name.trim(), children: [] };
|
|
11571
|
+
return { tree: insertNode(tree, operation.parentId, folder), summary: { action: operation.action, target: folder.name, after: summarize(folder) } };
|
|
11572
|
+
}
|
|
11573
|
+
if (operation.action === "create_request") {
|
|
11574
|
+
const parent = operation.parentId ? findNode(tree, operation.parentId) : void 0;
|
|
11575
|
+
if (operation.parentId && (!parent || !isFolder(parent))) throw new Error(`Parent folder "${operation.parentId}" was not found.`);
|
|
11576
|
+
const request = normalizeRequest(operation.request);
|
|
11577
|
+
return { tree: insertNode(tree, operation.parentId, request), summary: { action: operation.action, target: request.name, after: summarize(request) } };
|
|
11578
|
+
}
|
|
11579
|
+
if (operation.action === "update_request") {
|
|
11580
|
+
const before2 = findNode(tree, operation.requestId);
|
|
11581
|
+
if (!before2 || isFolder(before2)) throw new Error(`Request "${operation.requestId}" was not found.`);
|
|
11582
|
+
const updated = normalizeRequest(
|
|
11583
|
+
{ ...before2, ...operation.patch, name: operation.patch.name ?? before2.name, method: operation.patch.method ?? before2.method, url: operation.patch.url ?? before2.url },
|
|
11584
|
+
before2
|
|
11585
|
+
);
|
|
11586
|
+
const result = updateNode(tree, operation.requestId, () => updated);
|
|
11587
|
+
return { tree: result.tree, summary: { action: operation.action, target: updated.name, before: summarize(before2), after: summarize(updated) } };
|
|
11588
|
+
}
|
|
11589
|
+
if (operation.action === "rename_folder") {
|
|
11590
|
+
const before2 = findNode(tree, operation.folderId);
|
|
11591
|
+
if (!before2 || !isFolder(before2)) throw new Error(`Folder "${operation.folderId}" was not found.`);
|
|
11592
|
+
const result = updateNode(tree, operation.folderId, (node) => isFolder(node) ? { ...node, name: operation.name.trim() } : node);
|
|
11593
|
+
return {
|
|
11594
|
+
tree: result.tree,
|
|
11595
|
+
summary: { action: operation.action, target: operation.name.trim(), before: summarize(before2), after: { ...summarize(before2), name: operation.name.trim() } }
|
|
11596
|
+
};
|
|
11597
|
+
}
|
|
11598
|
+
if (operation.action === "move_node") {
|
|
11599
|
+
const before2 = findNode(tree, operation.nodeId);
|
|
11600
|
+
if (!before2) throw new Error(`Collection item "${operation.nodeId}" was not found.`);
|
|
11601
|
+
const parent = operation.parentId ? findNode(tree, operation.parentId) : void 0;
|
|
11602
|
+
if (operation.parentId && (!parent || !isFolder(parent))) throw new Error(`Parent folder "${operation.parentId}" was not found.`);
|
|
11603
|
+
if (isFolder(before2) && (before2.id === operation.parentId || findNode(before2.children, operation.parentId ?? "")?.kind === "folder"))
|
|
11604
|
+
throw new Error("A folder cannot be moved inside itself or one of its descendants.");
|
|
11605
|
+
const oldParentId = findParentId(tree, before2.id);
|
|
11606
|
+
const removed2 = removeNode(tree, before2.id);
|
|
11607
|
+
if (!removed2.removed) throw new Error(`Collection item "${operation.nodeId}" could not be moved.`);
|
|
11608
|
+
const next = insertNode(removed2.tree, operation.parentId, removed2.removed, operation.index);
|
|
11609
|
+
return { tree: next, summary: { action: operation.action, target: before2.name, before: { parentId: oldParentId }, after: { parentId: operation.parentId, index: operation.index } } };
|
|
11610
|
+
}
|
|
11611
|
+
if (operation.action === "deprecate_request") {
|
|
11612
|
+
const before2 = findNode(tree, operation.requestId);
|
|
11613
|
+
if (!before2 || isFolder(before2)) throw new Error(`Request "${operation.requestId}" was not found.`);
|
|
11614
|
+
const updated = {
|
|
11615
|
+
...before2,
|
|
11616
|
+
deprecated: operation.deprecated,
|
|
11617
|
+
...operation.deprecated && operation.reason?.trim() ? { deprecationReason: operation.reason.trim() } : {},
|
|
11618
|
+
...!operation.deprecated ? { deprecationReason: void 0 } : {}
|
|
11619
|
+
};
|
|
11620
|
+
const result = updateNode(tree, operation.requestId, () => updated);
|
|
11621
|
+
return {
|
|
11622
|
+
tree: result.tree,
|
|
11623
|
+
summary: {
|
|
11624
|
+
action: operation.action,
|
|
11625
|
+
target: updated.name,
|
|
11626
|
+
before: { deprecated: before2.deprecated === true, deprecationReason: before2.deprecationReason },
|
|
11627
|
+
after: { deprecated: updated.deprecated, deprecationReason: updated.deprecationReason }
|
|
11628
|
+
}
|
|
11629
|
+
};
|
|
11630
|
+
}
|
|
11631
|
+
const before = findNode(tree, operation.nodeId);
|
|
11632
|
+
if (!before) throw new Error(`Collection item "${operation.nodeId}" was not found.`);
|
|
11633
|
+
const removed = removeNode(tree, operation.nodeId);
|
|
11634
|
+
return { tree: removed.tree, summary: { action: operation.action, target: before.name, before: summarize(before) } };
|
|
11635
|
+
}
|
|
11636
|
+
function applyOperations(tree, operations) {
|
|
11637
|
+
let next = tree;
|
|
11638
|
+
const summary = [];
|
|
11639
|
+
for (const operation of operations) {
|
|
11640
|
+
const result = applyOperation(next, operation);
|
|
11641
|
+
next = result.tree;
|
|
11642
|
+
summary.push(result.summary);
|
|
11643
|
+
}
|
|
11644
|
+
return { tree: next, summary };
|
|
11645
|
+
}
|
|
11646
|
+
|
|
11647
|
+
// src/store.ts
|
|
11648
|
+
import { createHash, randomUUID as randomUUID3 } from "node:crypto";
|
|
11649
|
+
import { existsSync } from "node:fs";
|
|
11650
|
+
import { homedir } from "node:os";
|
|
11651
|
+
import { join } from "node:path";
|
|
11652
|
+
import { DatabaseSync } from "node:sqlite";
|
|
11653
|
+
function dataDirectory() {
|
|
11654
|
+
const appName = "api-documentation-bit";
|
|
11655
|
+
if (process.env.API_DOCS_USER_DATA_DIR) return process.env.API_DOCS_USER_DATA_DIR;
|
|
11656
|
+
const base = process.platform === "win32" ? process.env.APPDATA || join(homedir(), "AppData", "Roaming") : process.platform === "darwin" ? join(homedir(), "Library", "Application Support") : process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
11657
|
+
return join(base, appName);
|
|
11658
|
+
}
|
|
11659
|
+
var localDatabase;
|
|
11660
|
+
var openedPath;
|
|
11661
|
+
function database() {
|
|
11662
|
+
const path = join(dataDirectory(), "workspace.sqlite");
|
|
11663
|
+
if (!existsSync(path)) {
|
|
11664
|
+
throw new Error(`Workspace database was not found at ${path}. Open API Documentation once to create the local workspace.`);
|
|
11665
|
+
}
|
|
11666
|
+
if (!localDatabase || openedPath !== path) {
|
|
11667
|
+
localDatabase?.close();
|
|
11668
|
+
localDatabase = new DatabaseSync(path);
|
|
11669
|
+
localDatabase.exec("PRAGMA busy_timeout = 5000;");
|
|
11670
|
+
openedPath = path;
|
|
11671
|
+
}
|
|
11672
|
+
return localDatabase;
|
|
11673
|
+
}
|
|
11674
|
+
function hashRaw(raw) {
|
|
11675
|
+
return createHash("sha256").update(raw).digest("hex");
|
|
11676
|
+
}
|
|
11677
|
+
function secretFingerprint(workspaceId5, variableId) {
|
|
11678
|
+
try {
|
|
11679
|
+
const row = database().prepare("SELECT value FROM secrets WHERE key = ?").get(`workspace-variable:${workspaceId5}:${variableId}`);
|
|
11680
|
+
return row ? createHash("sha256").update(row.value).digest("hex") : "";
|
|
11681
|
+
} catch (error2) {
|
|
11682
|
+
if (error2 instanceof Error && /no such table/.test(error2.message)) return "";
|
|
11683
|
+
throw error2;
|
|
11684
|
+
}
|
|
11685
|
+
}
|
|
11686
|
+
var activeAccountKey = "active-account";
|
|
11687
|
+
function activeAccountId() {
|
|
11688
|
+
try {
|
|
11689
|
+
const row = database().prepare("SELECT value FROM app_settings WHERE key = ?").get(activeAccountKey);
|
|
11690
|
+
return row?.value ?? null;
|
|
11691
|
+
} catch (error2) {
|
|
11692
|
+
if (error2 instanceof Error && /no such table/.test(error2.message)) return null;
|
|
11693
|
+
throw error2;
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
function visibleTo(workspace, accountId) {
|
|
11697
|
+
if (!workspace.cloudId || !accountId) return true;
|
|
11698
|
+
return !workspace.accountId || workspace.accountId === accountId;
|
|
11699
|
+
}
|
|
11700
|
+
function listWorkspaces() {
|
|
11701
|
+
const accountId = activeAccountId();
|
|
11702
|
+
const rows = database().prepare("SELECT data FROM workspaces ORDER BY rowid").all();
|
|
11703
|
+
return rows.map(({ data }) => JSON.parse(data)).filter((workspace) => visibleTo(workspace, accountId)).map((workspace) => ({ id: workspace.id, name: workspace.name, cloudId: workspace.cloudId ?? null, role: workspace.role ?? null }));
|
|
11704
|
+
}
|
|
11705
|
+
function readWorkspace(workspaceId5) {
|
|
11706
|
+
const row = database().prepare("SELECT data FROM workspaces WHERE id = ?").get(workspaceId5);
|
|
11707
|
+
if (!row) throw new Error(`Workspace "${workspaceId5}" was not found.`);
|
|
11708
|
+
const workspace = JSON.parse(row.data);
|
|
11709
|
+
if (!visibleTo(workspace, activeAccountId())) throw new Error(`Workspace "${workspaceId5}" was not found.`);
|
|
11710
|
+
if (!Array.isArray(workspace.tree)) throw new Error("Workspace collection data is invalid.");
|
|
11711
|
+
return { raw: row.data, workspace };
|
|
11712
|
+
}
|
|
11713
|
+
function assertCanEdit(workspace) {
|
|
11714
|
+
if (workspace.role === "viewer") throw new Error("This workspace is read-only for the current account.");
|
|
11715
|
+
}
|
|
11716
|
+
function updateWorkspace(workspaceId5, change) {
|
|
11717
|
+
const db = database();
|
|
11718
|
+
db.exec("BEGIN IMMEDIATE;");
|
|
11719
|
+
try {
|
|
11720
|
+
const { raw, workspace } = readWorkspace(workspaceId5);
|
|
11721
|
+
assertCanEdit(workspace);
|
|
11722
|
+
const next = change(workspace, raw);
|
|
11723
|
+
db.prepare("UPDATE workspaces SET data = ? WHERE id = ?").run(JSON.stringify(next), workspaceId5);
|
|
11724
|
+
db.exec("COMMIT;");
|
|
11725
|
+
return next;
|
|
11726
|
+
} catch (error2) {
|
|
11727
|
+
db.exec("ROLLBACK;");
|
|
11728
|
+
throw error2;
|
|
11729
|
+
}
|
|
11730
|
+
}
|
|
11731
|
+
function insertWorkspace(workspace) {
|
|
11732
|
+
database().prepare("INSERT INTO workspaces (id, data) VALUES (?, ?)").run(workspace.id, JSON.stringify(workspace));
|
|
11733
|
+
}
|
|
11734
|
+
function deleteWorkspace(workspaceId5) {
|
|
11735
|
+
const db = database();
|
|
11736
|
+
db.exec("BEGIN IMMEDIATE;");
|
|
11737
|
+
try {
|
|
11738
|
+
const { workspace } = readWorkspace(workspaceId5);
|
|
11739
|
+
if (workspace.cloudId) throw new Error("Cloud workspaces are managed in the desktop app, not from the CLI.");
|
|
11740
|
+
db.prepare("DELETE FROM commits WHERE workspace_id = ?").run(workspaceId5);
|
|
11741
|
+
db.prepare("DELETE FROM workspaces WHERE id = ?").run(workspaceId5);
|
|
11742
|
+
db.exec("COMMIT;");
|
|
11743
|
+
} catch (error2) {
|
|
11744
|
+
db.exec("ROLLBACK;");
|
|
11745
|
+
throw error2;
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11748
|
+
|
|
11749
|
+
// src/schemas.ts
|
|
11750
|
+
var bodyModes = ["form-data", "urlencoded", "graphql", "json", "xml", "yaml", "edn", "text", "other", "file", "none"];
|
|
11751
|
+
var authSchema = external_exports.discriminatedUnion("type", [
|
|
11752
|
+
external_exports.object({ type: external_exports.literal("none") }),
|
|
11753
|
+
external_exports.object({ type: external_exports.literal("bearer"), token: external_exports.string().max(65536) }),
|
|
11754
|
+
external_exports.object({ type: external_exports.literal("basic"), username: external_exports.string().max(8192), password: external_exports.string().max(65536) }),
|
|
11755
|
+
external_exports.object({ type: external_exports.literal("api-key"), name: external_exports.string().max(8192), value: external_exports.string().max(65536), location: external_exports.enum(["header", "query"]) })
|
|
11756
|
+
]);
|
|
11757
|
+
var fieldSchema = external_exports.object({
|
|
11758
|
+
id: external_exports.string().optional(),
|
|
11759
|
+
name: external_exports.string().max(8192),
|
|
11760
|
+
value: external_exports.string().max(65536),
|
|
11761
|
+
enabled: external_exports.boolean().default(true),
|
|
11762
|
+
description: external_exports.string().max(4096).optional()
|
|
11763
|
+
});
|
|
11764
|
+
var bodyFieldSchema = external_exports.object({
|
|
11765
|
+
id: external_exports.string().optional(),
|
|
11766
|
+
name: external_exports.string().max(8192),
|
|
11767
|
+
value: external_exports.string().max(65536),
|
|
11768
|
+
enabled: external_exports.boolean().default(true),
|
|
11769
|
+
type: external_exports.enum(["text", "file"]).default("text"),
|
|
11770
|
+
fileName: external_exports.string().max(1024).optional()
|
|
11771
|
+
});
|
|
11772
|
+
var responseContentSchema = external_exports.object({
|
|
11773
|
+
id: external_exports.string().optional(),
|
|
11774
|
+
mediaType: external_exports.string().max(160),
|
|
11775
|
+
schema: external_exports.string().max(1e6),
|
|
11776
|
+
example: external_exports.string().max(1e6)
|
|
11777
|
+
});
|
|
11778
|
+
var responseDefinitionSchema = external_exports.object({
|
|
11779
|
+
id: external_exports.string().optional(),
|
|
11780
|
+
statusCode: external_exports.string().trim().min(1).max(12),
|
|
11781
|
+
description: external_exports.string().max(500),
|
|
11782
|
+
content: external_exports.array(responseContentSchema).max(20)
|
|
11783
|
+
});
|
|
11784
|
+
var method = external_exports.string().trim().min(1).max(32).transform((value) => value.toUpperCase());
|
|
11785
|
+
var requestFields = {
|
|
11786
|
+
name: external_exports.string().trim().min(1).max(160),
|
|
11787
|
+
method,
|
|
11788
|
+
url: external_exports.string().max(8192),
|
|
11789
|
+
body: external_exports.string().max(1e6).optional(),
|
|
11790
|
+
bodyMode: external_exports.enum(bodyModes).optional(),
|
|
11791
|
+
bodyFields: external_exports.array(bodyFieldSchema).max(100).optional(),
|
|
11792
|
+
bodyVariables: external_exports.string().max(1e6).optional(),
|
|
11793
|
+
bodyMimeType: external_exports.string().max(1024).optional(),
|
|
11794
|
+
bodyFileName: external_exports.string().max(1024).optional(),
|
|
11795
|
+
headers: external_exports.array(fieldSchema).max(100).optional(),
|
|
11796
|
+
params: external_exports.array(fieldSchema).max(100).optional(),
|
|
11797
|
+
pathParams: external_exports.array(fieldSchema).max(100).optional(),
|
|
11798
|
+
auth: authSchema.optional(),
|
|
11799
|
+
documentation: external_exports.string().max(1e5).optional(),
|
|
11800
|
+
responses: external_exports.array(responseDefinitionSchema).max(100).optional(),
|
|
11801
|
+
deprecated: external_exports.boolean().optional(),
|
|
11802
|
+
deprecationReason: external_exports.string().max(4096).optional()
|
|
11803
|
+
};
|
|
11804
|
+
var requestSchema = external_exports.object(requestFields);
|
|
11805
|
+
var requestPatchSchema = external_exports.object(requestFields).partial();
|
|
11806
|
+
var operationSchema = external_exports.discriminatedUnion("action", [
|
|
11807
|
+
external_exports.object({ action: external_exports.literal("create_folder"), parentId: external_exports.string().nullable().default(null), name: external_exports.string().trim().min(1).max(160) }),
|
|
11808
|
+
external_exports.object({ action: external_exports.literal("create_request"), parentId: external_exports.string().nullable().default(null), request: requestSchema }),
|
|
11809
|
+
external_exports.object({ action: external_exports.literal("update_request"), requestId: external_exports.string().min(1), patch: requestPatchSchema }),
|
|
11810
|
+
external_exports.object({ action: external_exports.literal("rename_folder"), folderId: external_exports.string().min(1), name: external_exports.string().trim().min(1).max(160) }),
|
|
11811
|
+
external_exports.object({ action: external_exports.literal("move_node"), nodeId: external_exports.string().min(1), parentId: external_exports.string().nullable().default(null), index: external_exports.number().int().min(0).optional() }),
|
|
11812
|
+
external_exports.object({ action: external_exports.literal("deprecate_request"), requestId: external_exports.string().min(1), deprecated: external_exports.boolean().default(true), reason: external_exports.string().max(4096).optional() }),
|
|
11813
|
+
external_exports.object({ action: external_exports.literal("delete_node"), nodeId: external_exports.string().min(1) })
|
|
11814
|
+
]);
|
|
11815
|
+
var variableNameSchema = external_exports.string().trim().min(1).max(160);
|
|
11816
|
+
var variableValueSchema = external_exports.string().max(65536);
|
|
11817
|
+
|
|
11818
|
+
// src/commands/changes.ts
|
|
11819
|
+
var plans = /* @__PURE__ */ new Map();
|
|
11820
|
+
var planLifetimeMs = 10 * 60 * 1e3;
|
|
11821
|
+
var changeCommands = [
|
|
11822
|
+
defineCommand({
|
|
11823
|
+
id: "changes.preview",
|
|
11824
|
+
group: "changes",
|
|
11825
|
+
title: "Preview collection changes",
|
|
11826
|
+
description: "Validate a batch of collection operations and return sanitized before/after data without changing anything. Show the preview to the user, then call changes.apply only after they approve it.",
|
|
11827
|
+
params: external_exports.object({ workspaceId: external_exports.string().min(1), operations: external_exports.array(operationSchema).min(1).max(100) }),
|
|
11828
|
+
readOnly: true,
|
|
11829
|
+
run: ({ workspaceId: id, operations }) => {
|
|
11830
|
+
const { raw, workspace } = readWorkspace(id);
|
|
11831
|
+
if (workspace.role === "viewer") throw new Error("This workspace is read-only for the current account.");
|
|
11832
|
+
const result = applyOperations(structuredClone(workspace.tree), operations);
|
|
11833
|
+
const previewId = randomUUID4();
|
|
11834
|
+
const plan = {
|
|
11835
|
+
id: previewId,
|
|
11836
|
+
workspaceId: id,
|
|
11837
|
+
sourceHash: hashRaw(raw),
|
|
11838
|
+
operations,
|
|
11839
|
+
nextTree: result.tree,
|
|
11840
|
+
summary: result.summary,
|
|
11841
|
+
includesDelete: operations.some((operation) => operation.action === "delete_node"),
|
|
11842
|
+
expiresAt: Date.now() + planLifetimeMs
|
|
11843
|
+
};
|
|
11844
|
+
plans.set(previewId, plan);
|
|
11845
|
+
return {
|
|
11846
|
+
previewId,
|
|
11847
|
+
workspaceId: id,
|
|
11848
|
+
workspaceName: workspace.name,
|
|
11849
|
+
changes: result.summary,
|
|
11850
|
+
deletesItems: plan.includesDelete,
|
|
11851
|
+
expiresInSeconds: planLifetimeMs / 1e3
|
|
11852
|
+
};
|
|
11853
|
+
}
|
|
11854
|
+
}),
|
|
11855
|
+
defineCommand({
|
|
11856
|
+
id: "changes.apply",
|
|
11857
|
+
group: "changes",
|
|
11858
|
+
title: "Apply previewed changes",
|
|
11859
|
+
description: "Apply a batch returned by changes.preview. Only call after the user approved that exact preview. Requires confirmDelete=true when the batch deletes anything.",
|
|
11860
|
+
params: external_exports.object({ previewId: external_exports.string().min(1), confirmDelete: external_exports.boolean().default(false) }),
|
|
11861
|
+
readOnly: false,
|
|
11862
|
+
destructive: true,
|
|
11863
|
+
run: ({ previewId, confirmDelete }) => {
|
|
11864
|
+
const plan = plans.get(previewId);
|
|
11865
|
+
if (!plan || plan.expiresAt < Date.now()) {
|
|
11866
|
+
plans.delete(previewId);
|
|
11867
|
+
throw new Error("This preview expired or was not found. Run changes.preview again.");
|
|
11868
|
+
}
|
|
11869
|
+
if (plan.includesDelete && !confirmDelete) {
|
|
11870
|
+
throw new Error("This batch includes deletion. Ask the user to confirm the listed deletions, then retry with confirmDelete=true.");
|
|
11871
|
+
}
|
|
11872
|
+
const updated = updateWorkspace(plan.workspaceId, (workspace, raw) => {
|
|
11873
|
+
if (hashRaw(raw) !== plan.sourceHash) {
|
|
11874
|
+
throw new Error("The workspace changed after this preview. Run changes.preview again to avoid overwriting newer edits.");
|
|
11875
|
+
}
|
|
11876
|
+
return { ...workspace, tree: structuredClone(plan.nextTree) };
|
|
11877
|
+
});
|
|
11878
|
+
plans.delete(previewId);
|
|
11879
|
+
return { applied: true, workspaceId: plan.workspaceId, workspaceName: updated.name, changes: plan.summary };
|
|
11880
|
+
}
|
|
11881
|
+
})
|
|
11882
|
+
];
|
|
11883
|
+
|
|
11884
|
+
// src/commands/collection.ts
|
|
11885
|
+
var workspaceId = external_exports.string().min(1).describe("Workspace id from workspace.list");
|
|
11886
|
+
var folderId = external_exports.string().min(1).describe("Folder id from tree.get");
|
|
11887
|
+
var nodeId = external_exports.string().min(1).describe("Folder or request id from tree.get");
|
|
11888
|
+
var parentId = external_exports.string().nullable().default(null).describe("Parent folder id, or null for the root");
|
|
11889
|
+
var confirm = external_exports.literal(true).describe("Must be true; ask the user first");
|
|
11890
|
+
var collectionCommands = [
|
|
11891
|
+
defineCommand({
|
|
11892
|
+
id: "folder.create",
|
|
11893
|
+
group: "collection",
|
|
11894
|
+
title: "Create folder",
|
|
11895
|
+
description: "Create a folder under a parent folder, or at the root when parentId is null.",
|
|
11896
|
+
params: external_exports.object({ workspaceId, parentId, name: external_exports.string().trim().min(1).max(160) }),
|
|
11897
|
+
readOnly: false,
|
|
11898
|
+
run: ({ workspaceId: id, parentId: parent, name }) => {
|
|
11899
|
+
let created;
|
|
11900
|
+
updateWorkspace(id, (workspace) => {
|
|
11901
|
+
const result = applyOperation(workspace.tree, { action: "create_folder", parentId: parent, name });
|
|
11902
|
+
created = result.summary.after;
|
|
11903
|
+
return { ...workspace, tree: result.tree };
|
|
11904
|
+
});
|
|
11905
|
+
return created;
|
|
11906
|
+
}
|
|
11907
|
+
}),
|
|
11908
|
+
defineCommand({
|
|
11909
|
+
id: "folder.rename",
|
|
11910
|
+
group: "collection",
|
|
11911
|
+
title: "Rename folder",
|
|
11912
|
+
description: "Rename a folder.",
|
|
11913
|
+
params: external_exports.object({ workspaceId, folderId, name: external_exports.string().trim().min(1).max(160) }),
|
|
11914
|
+
readOnly: false,
|
|
11915
|
+
run: ({ workspaceId: id, folderId: folder, name }) => {
|
|
11916
|
+
updateWorkspace(id, (workspace) => ({ ...workspace, tree: applyOperation(workspace.tree, { action: "rename_folder", folderId: folder, name }).tree }));
|
|
11917
|
+
return { renamed: true, folderId: folder, name };
|
|
11918
|
+
}
|
|
11919
|
+
}),
|
|
11920
|
+
defineCommand({
|
|
11921
|
+
id: "folder.delete",
|
|
11922
|
+
group: "collection",
|
|
11923
|
+
title: "Delete folder",
|
|
11924
|
+
description: "Delete a folder and everything in it. Requires confirm=true after the user confirms the listed deletions.",
|
|
11925
|
+
params: external_exports.object({ workspaceId, folderId, confirm }),
|
|
11926
|
+
readOnly: false,
|
|
11927
|
+
destructive: true,
|
|
11928
|
+
run: ({ workspaceId: id, folderId: folder }) => {
|
|
11929
|
+
updateWorkspace(id, (workspace) => ({ ...workspace, tree: applyOperation(workspace.tree, { action: "delete_node", nodeId: folder }).tree }));
|
|
11930
|
+
return { deleted: true, folderId: folder };
|
|
11931
|
+
}
|
|
11932
|
+
}),
|
|
11933
|
+
defineCommand({
|
|
11934
|
+
id: "node.move",
|
|
11935
|
+
group: "collection",
|
|
11936
|
+
title: "Move folder or request",
|
|
11937
|
+
description: "Move a folder or request under another folder (or the root), optionally at a position.",
|
|
11938
|
+
params: external_exports.object({ workspaceId, nodeId, parentId, index: external_exports.number().int().min(0).optional() }),
|
|
11939
|
+
readOnly: false,
|
|
11940
|
+
run: ({ workspaceId: id, nodeId: node, parentId: parent, index }) => {
|
|
11941
|
+
updateWorkspace(id, (workspace) => ({
|
|
11942
|
+
...workspace,
|
|
11943
|
+
tree: applyOperation(workspace.tree, { action: "move_node", nodeId: node, parentId: parent, index }).tree
|
|
11944
|
+
}));
|
|
11945
|
+
return { moved: true, nodeId: node, parentId: parent, index: index ?? null };
|
|
11946
|
+
}
|
|
11947
|
+
})
|
|
11948
|
+
];
|
|
11949
|
+
|
|
11950
|
+
// src/commands/environments.ts
|
|
11951
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
11952
|
+
var workspaceId2 = external_exports.string().min(1).describe("Workspace id from workspace.list");
|
|
11953
|
+
var environmentId = external_exports.string().min(1).describe("Environment id from environment.list");
|
|
11954
|
+
var confirm2 = external_exports.literal(true).describe("Must be true; ask the user first");
|
|
11955
|
+
var maxEnvironments = 100;
|
|
11956
|
+
function variablesOf(workspace) {
|
|
11957
|
+
return workspace.variables ?? { globals: [], environments: [] };
|
|
11958
|
+
}
|
|
11959
|
+
function withVariables(workspace, variables) {
|
|
11960
|
+
return { ...workspace, variables };
|
|
11961
|
+
}
|
|
11962
|
+
function masked(row) {
|
|
11963
|
+
return { id: row.id, name: row.name, secret: row.secret, value: row.secret ? "<secret>" : row.value };
|
|
11964
|
+
}
|
|
11965
|
+
function findEnvironment(variables, id) {
|
|
11966
|
+
const environment = variables.environments.find((item) => item.id === id);
|
|
11967
|
+
if (!environment) throw new Error(`Environment "${id}" was not found.`);
|
|
11968
|
+
return environment;
|
|
11969
|
+
}
|
|
11970
|
+
var scopeSchema = external_exports.enum(["global", "environment"]).describe("global for workspace-wide values, environment for one environment");
|
|
11971
|
+
function rowsFor(variables, scope, env) {
|
|
11972
|
+
if (scope === "global") return variables.globals;
|
|
11973
|
+
if (!env) throw new Error("environmentId is required for an environment variable.");
|
|
11974
|
+
return findEnvironment(variables, env).variables;
|
|
11975
|
+
}
|
|
11976
|
+
function variableRevision(workspaceId5, row) {
|
|
11977
|
+
if (!row) return null;
|
|
11978
|
+
const sealed = row.secret ? secretFingerprint(workspaceId5, row.id) : "";
|
|
11979
|
+
return hashRaw(JSON.stringify({ id: row.id, name: row.name, secret: row.secret, value: row.secret ? "" : row.value, sealed }));
|
|
11980
|
+
}
|
|
11981
|
+
function changedSinceRead(name) {
|
|
11982
|
+
return new Error(`"${name}" changed since you read it. Read it again with variable.get and review the change before writing.`);
|
|
11983
|
+
}
|
|
11984
|
+
var environmentCommands = [
|
|
11985
|
+
defineCommand({
|
|
11986
|
+
id: "environment.list",
|
|
11987
|
+
group: "environment",
|
|
11988
|
+
title: "List environments and variables",
|
|
11989
|
+
description: "List globals and environments with their variables. Secret values are shown as <secret>.",
|
|
11990
|
+
params: external_exports.object({ workspaceId: workspaceId2 }),
|
|
11991
|
+
readOnly: true,
|
|
11992
|
+
run: ({ workspaceId: id }) => {
|
|
11993
|
+
const { workspace } = readWorkspace(id);
|
|
11994
|
+
const variables = variablesOf(workspace);
|
|
11995
|
+
return {
|
|
11996
|
+
activeEnvironmentId: workspace.activeEnvironmentId ?? null,
|
|
11997
|
+
globals: variables.globals.map(masked),
|
|
11998
|
+
environments: variables.environments.map((environment) => ({
|
|
11999
|
+
id: environment.id,
|
|
12000
|
+
name: environment.name,
|
|
12001
|
+
variables: environment.variables.map(masked)
|
|
12002
|
+
}))
|
|
12003
|
+
};
|
|
12004
|
+
}
|
|
12005
|
+
}),
|
|
12006
|
+
defineCommand({
|
|
12007
|
+
id: "environment.create",
|
|
12008
|
+
group: "environment",
|
|
12009
|
+
title: "Create environment",
|
|
12010
|
+
description: "Create an empty environment. It is not activated until environment.activate.",
|
|
12011
|
+
params: external_exports.object({ workspaceId: workspaceId2, name: external_exports.string().trim().min(1).max(160) }),
|
|
12012
|
+
readOnly: false,
|
|
12013
|
+
run: ({ workspaceId: id, name }) => {
|
|
12014
|
+
let created;
|
|
12015
|
+
updateWorkspace(id, (workspace) => {
|
|
12016
|
+
const variables = variablesOf(workspace);
|
|
12017
|
+
if (variables.environments.length >= maxEnvironments) throw new Error(`A workspace can have at most ${maxEnvironments} environments.`);
|
|
12018
|
+
created = { id: randomUUID5(), name, variables: [] };
|
|
12019
|
+
return withVariables(workspace, { ...variables, environments: [...variables.environments, created] });
|
|
12020
|
+
});
|
|
12021
|
+
return { id: created?.id, name };
|
|
12022
|
+
}
|
|
12023
|
+
}),
|
|
12024
|
+
defineCommand({
|
|
12025
|
+
id: "environment.rename",
|
|
12026
|
+
group: "environment",
|
|
12027
|
+
title: "Rename environment",
|
|
12028
|
+
description: "Rename an environment.",
|
|
12029
|
+
params: external_exports.object({ workspaceId: workspaceId2, environmentId, name: external_exports.string().trim().min(1).max(160) }),
|
|
12030
|
+
readOnly: false,
|
|
12031
|
+
run: ({ workspaceId: id, environmentId: env, name }) => {
|
|
12032
|
+
updateWorkspace(id, (workspace) => {
|
|
12033
|
+
const variables = variablesOf(workspace);
|
|
12034
|
+
findEnvironment(variables, env);
|
|
12035
|
+
return withVariables(workspace, {
|
|
12036
|
+
...variables,
|
|
12037
|
+
environments: variables.environments.map((item) => item.id === env ? { ...item, name } : item)
|
|
12038
|
+
});
|
|
12039
|
+
});
|
|
12040
|
+
return { id: env, name };
|
|
12041
|
+
}
|
|
12042
|
+
}),
|
|
12043
|
+
defineCommand({
|
|
12044
|
+
id: "environment.duplicate",
|
|
12045
|
+
group: "environment",
|
|
12046
|
+
title: "Duplicate environment",
|
|
12047
|
+
description: 'Copy an environment as "<name>_copy" with new variable ids. Secret values are copied as empty and must be set in the app.',
|
|
12048
|
+
params: external_exports.object({ workspaceId: workspaceId2, environmentId }),
|
|
12049
|
+
readOnly: false,
|
|
12050
|
+
run: ({ workspaceId: id, environmentId: env }) => {
|
|
12051
|
+
let copy;
|
|
12052
|
+
updateWorkspace(id, (workspace) => {
|
|
12053
|
+
const variables = variablesOf(workspace);
|
|
12054
|
+
const source = findEnvironment(variables, env);
|
|
12055
|
+
if (variables.environments.length >= maxEnvironments) throw new Error(`A workspace can have at most ${maxEnvironments} environments.`);
|
|
12056
|
+
copy = {
|
|
12057
|
+
id: randomUUID5(),
|
|
12058
|
+
name: `${source.name}_copy`,
|
|
12059
|
+
variables: source.variables.map((row) => ({ ...row, id: randomUUID5(), value: row.secret ? "" : row.value }))
|
|
12060
|
+
};
|
|
12061
|
+
return withVariables(workspace, { ...variables, environments: [...variables.environments, copy] });
|
|
12062
|
+
});
|
|
12063
|
+
return { id: copy?.id, name: copy?.name };
|
|
12064
|
+
}
|
|
12065
|
+
}),
|
|
12066
|
+
defineCommand({
|
|
12067
|
+
id: "environment.delete",
|
|
12068
|
+
group: "environment",
|
|
12069
|
+
title: "Delete environment",
|
|
12070
|
+
description: "Delete an environment and its variables. Requires confirm=true after the user confirms.",
|
|
12071
|
+
params: external_exports.object({ workspaceId: workspaceId2, environmentId, confirm: confirm2 }),
|
|
12072
|
+
readOnly: false,
|
|
12073
|
+
destructive: true,
|
|
12074
|
+
run: ({ workspaceId: id, environmentId: env }) => {
|
|
12075
|
+
updateWorkspace(id, (workspace) => {
|
|
12076
|
+
const variables = variablesOf(workspace);
|
|
12077
|
+
findEnvironment(variables, env);
|
|
12078
|
+
return {
|
|
12079
|
+
...withVariables(workspace, { ...variables, environments: variables.environments.filter((item) => item.id !== env) }),
|
|
12080
|
+
activeEnvironmentId: workspace.activeEnvironmentId === env ? null : workspace.activeEnvironmentId
|
|
12081
|
+
};
|
|
12082
|
+
});
|
|
12083
|
+
return { deleted: true, environmentId: env };
|
|
12084
|
+
}
|
|
12085
|
+
}),
|
|
12086
|
+
defineCommand({
|
|
12087
|
+
id: "environment.activate",
|
|
12088
|
+
group: "environment",
|
|
12089
|
+
title: "Set active environment",
|
|
12090
|
+
description: "Make an environment the active one that requests use, or pass null to use none.",
|
|
12091
|
+
params: external_exports.object({ workspaceId: workspaceId2, environmentId: external_exports.string().min(1).nullable() }),
|
|
12092
|
+
readOnly: false,
|
|
12093
|
+
run: ({ workspaceId: id, environmentId: env }) => {
|
|
12094
|
+
updateWorkspace(id, (workspace) => {
|
|
12095
|
+
if (env !== null) findEnvironment(variablesOf(workspace), env);
|
|
12096
|
+
return { ...workspace, activeEnvironmentId: env };
|
|
12097
|
+
});
|
|
12098
|
+
return { activeEnvironmentId: env };
|
|
12099
|
+
}
|
|
12100
|
+
}),
|
|
12101
|
+
defineCommand({
|
|
12102
|
+
id: "variable.get",
|
|
12103
|
+
group: "environment",
|
|
12104
|
+
title: "Get variable",
|
|
12105
|
+
description: "Read one variable and its revision. Secret values are never returned. Pass the revision to variable.set or variable.delete, so a change made since this read is refused.",
|
|
12106
|
+
params: external_exports.object({
|
|
12107
|
+
workspaceId: workspaceId2,
|
|
12108
|
+
scope: scopeSchema,
|
|
12109
|
+
environmentId: external_exports.string().min(1).optional().describe("Required when scope is environment"),
|
|
12110
|
+
name: variableNameSchema
|
|
12111
|
+
}),
|
|
12112
|
+
readOnly: true,
|
|
12113
|
+
run: ({ workspaceId: id, scope, environmentId: env, name }) => {
|
|
12114
|
+
const { workspace } = readWorkspace(id);
|
|
12115
|
+
const existing = rowsFor(variablesOf(workspace), scope, env).find((row) => row.name === name);
|
|
12116
|
+
if (!existing) return { exists: false, name, scope, environmentId: env ?? null, revision: null };
|
|
12117
|
+
return { exists: true, ...masked(existing), scope, environmentId: env ?? null, revision: variableRevision(id, existing) };
|
|
12118
|
+
}
|
|
12119
|
+
}),
|
|
12120
|
+
defineCommand({
|
|
12121
|
+
id: "variable.set",
|
|
12122
|
+
group: "environment",
|
|
12123
|
+
title: "Set variable",
|
|
12124
|
+
description: "Create or update a variable in globals or one environment. Read the variable with variable.get first and pass its revision as expectedRevision (null when it does not exist yet). A secret variable is created with an empty value; its value must be entered in the desktop app, and an existing secret cannot be changed here.",
|
|
12125
|
+
params: external_exports.object({
|
|
12126
|
+
workspaceId: workspaceId2,
|
|
12127
|
+
scope: scopeSchema,
|
|
12128
|
+
environmentId: external_exports.string().min(1).optional().describe("Required when scope is environment"),
|
|
12129
|
+
name: variableNameSchema,
|
|
12130
|
+
value: variableValueSchema.optional(),
|
|
12131
|
+
secret: external_exports.boolean().optional().describe("Secret variables keep their value in the app only"),
|
|
12132
|
+
expectedRevision: external_exports.string().min(1).nullable().optional().describe("Revision from variable.get; null when the variable does not exist yet")
|
|
12133
|
+
}),
|
|
12134
|
+
readOnly: false,
|
|
12135
|
+
run: ({ workspaceId: id, scope, environmentId: env, name, value, secret, expectedRevision }) => {
|
|
12136
|
+
const updated = updateWorkspace(id, (workspace) => {
|
|
12137
|
+
const variables = variablesOf(workspace);
|
|
12138
|
+
if (scope === "environment" && !env) throw new Error("environmentId is required for an environment variable.");
|
|
12139
|
+
const rows = rowsFor(variables, scope, env);
|
|
12140
|
+
const existing = rows.find((row2) => row2.name === name);
|
|
12141
|
+
if (expectedRevision !== void 0) {
|
|
12142
|
+
if (existing && expectedRevision === null) throw new Error(`"${name}" already exists. Read it with variable.get and pass its revision.`);
|
|
12143
|
+
if (variableRevision(id, existing) !== expectedRevision) throw changedSinceRead(name);
|
|
12144
|
+
}
|
|
12145
|
+
if (existing?.secret && value !== void 0 && value !== "") {
|
|
12146
|
+
throw new Error(`"${name}" is a secret. Change its value in the desktop app.`);
|
|
12147
|
+
}
|
|
12148
|
+
if (secret === true && value) throw new Error(`"${name}" is a secret. Enter its value in the desktop app.`);
|
|
12149
|
+
const row = {
|
|
12150
|
+
id: existing?.id ?? randomUUID5(),
|
|
12151
|
+
name,
|
|
12152
|
+
value: secret ? "" : value ?? existing?.value ?? "",
|
|
12153
|
+
secret: secret ?? existing?.secret ?? false
|
|
12154
|
+
};
|
|
12155
|
+
const nextRows = existing ? rows.map((item) => item.id === existing.id ? row : item) : [...rows, row];
|
|
12156
|
+
if (scope === "global") return withVariables(workspace, { ...variables, globals: nextRows });
|
|
12157
|
+
return withVariables(workspace, {
|
|
12158
|
+
...variables,
|
|
12159
|
+
environments: variables.environments.map((item) => item.id === env ? { ...item, variables: nextRows } : item)
|
|
12160
|
+
});
|
|
12161
|
+
});
|
|
12162
|
+
const written = rowsFor(variablesOf(updated), scope, env).find((row) => row.name === name);
|
|
12163
|
+
return { name, scope, environmentId: env ?? null, secret: secret ?? null, revision: variableRevision(id, written) };
|
|
12164
|
+
}
|
|
12165
|
+
}),
|
|
12166
|
+
defineCommand({
|
|
12167
|
+
id: "variable.delete",
|
|
12168
|
+
group: "environment",
|
|
12169
|
+
title: "Delete variable",
|
|
12170
|
+
description: "Delete a variable from globals or one environment. Read it with variable.get first and pass its revision as expectedRevision. Requires confirm=true after the user confirms.",
|
|
12171
|
+
params: external_exports.object({
|
|
12172
|
+
workspaceId: workspaceId2,
|
|
12173
|
+
scope: scopeSchema,
|
|
12174
|
+
environmentId: external_exports.string().min(1).optional(),
|
|
12175
|
+
name: variableNameSchema,
|
|
12176
|
+
expectedRevision: external_exports.string().min(1).nullable().optional().describe("Revision from variable.get"),
|
|
12177
|
+
confirm: confirm2
|
|
12178
|
+
}),
|
|
12179
|
+
readOnly: false,
|
|
12180
|
+
destructive: true,
|
|
12181
|
+
run: ({ workspaceId: id, scope, environmentId: env, name, expectedRevision }) => {
|
|
12182
|
+
updateWorkspace(id, (workspace) => {
|
|
12183
|
+
const variables = variablesOf(workspace);
|
|
12184
|
+
if (expectedRevision !== void 0) {
|
|
12185
|
+
const existing = rowsFor(variables, scope, env).find((row) => row.name === name);
|
|
12186
|
+
if (variableRevision(id, existing) !== expectedRevision) throw changedSinceRead(name);
|
|
12187
|
+
}
|
|
12188
|
+
if (scope === "global") {
|
|
12189
|
+
return withVariables(workspace, { ...variables, globals: variables.globals.filter((row) => row.name !== name) });
|
|
12190
|
+
}
|
|
12191
|
+
if (!env) throw new Error("environmentId is required for an environment variable.");
|
|
12192
|
+
return withVariables(workspace, {
|
|
12193
|
+
...variables,
|
|
12194
|
+
environments: variables.environments.map(
|
|
12195
|
+
(item) => item.id === env ? { ...item, variables: item.variables.filter((row) => row.name !== name) } : item
|
|
12196
|
+
)
|
|
12197
|
+
});
|
|
12198
|
+
});
|
|
12199
|
+
return { deleted: true, name, scope };
|
|
12200
|
+
}
|
|
12201
|
+
})
|
|
12202
|
+
];
|
|
12203
|
+
|
|
12204
|
+
// src/send.ts
|
|
12205
|
+
import { readFile } from "node:fs/promises";
|
|
12206
|
+
import { basename } from "node:path";
|
|
12207
|
+
var timeoutMs = 3e4;
|
|
12208
|
+
var maxBodyChars = 1e6;
|
|
12209
|
+
var variablePattern = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
12210
|
+
function resolveVariables(workspace, environmentId2) {
|
|
12211
|
+
const variables = workspace.variables ?? { globals: [], environments: [] };
|
|
12212
|
+
const environment = variables.environments.find((item) => item.id === (environmentId2 ?? workspace.activeEnvironmentId ?? ""));
|
|
12213
|
+
const rows = [...variables.globals, ...environment?.variables ?? []];
|
|
12214
|
+
const values = /* @__PURE__ */ new Map();
|
|
12215
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
12216
|
+
for (const row of rows) {
|
|
12217
|
+
if (row.secret || row.value === "") {
|
|
12218
|
+
blocked.add(row.name);
|
|
12219
|
+
values.delete(row.name);
|
|
12220
|
+
} else {
|
|
12221
|
+
values.set(row.name, row.value);
|
|
12222
|
+
blocked.delete(row.name);
|
|
12223
|
+
}
|
|
12224
|
+
}
|
|
12225
|
+
return { values, blocked };
|
|
12226
|
+
}
|
|
12227
|
+
function fill(text, values, missing) {
|
|
12228
|
+
return text.replace(variablePattern, (match, name) => {
|
|
12229
|
+
const value = values.get(name);
|
|
12230
|
+
if (value === void 0) {
|
|
12231
|
+
missing.add(name);
|
|
12232
|
+
return match;
|
|
12233
|
+
}
|
|
12234
|
+
return value;
|
|
12235
|
+
});
|
|
12236
|
+
}
|
|
12237
|
+
var defaultMime = {
|
|
12238
|
+
json: "application/json",
|
|
12239
|
+
graphql: "application/json",
|
|
12240
|
+
xml: "application/xml",
|
|
12241
|
+
yaml: "application/yaml",
|
|
12242
|
+
edn: "application/edn",
|
|
12243
|
+
text: "text/plain",
|
|
12244
|
+
other: "text/plain"
|
|
12245
|
+
};
|
|
12246
|
+
async function sendRequest(request, workspace, environmentId2, options = {}) {
|
|
12247
|
+
const { values, blocked } = resolveVariables(workspace, environmentId2);
|
|
12248
|
+
const missing = /* @__PURE__ */ new Set();
|
|
12249
|
+
const f = (text2) => fill(text2, values, missing);
|
|
12250
|
+
const headers = new Headers({ Accept: "*/*", "User-Agent": "API-Documentation-CLI/0.2.0" });
|
|
12251
|
+
for (const header of request.headers ?? []) {
|
|
12252
|
+
if (header.enabled && header.name.trim()) headers.set(f(header.name.trim()), f(header.value));
|
|
12253
|
+
}
|
|
12254
|
+
const url = new URL(f(request.url));
|
|
12255
|
+
url.pathname = url.pathname.split("/").map((segment) => {
|
|
12256
|
+
if (!segment.startsWith(":")) return segment;
|
|
12257
|
+
const name = segment.slice(1);
|
|
12258
|
+
const param = (request.pathParams ?? []).find((item) => item.enabled && item.name.trim() === name);
|
|
12259
|
+
if (!param) {
|
|
12260
|
+
missing.add(name);
|
|
12261
|
+
return segment;
|
|
12262
|
+
}
|
|
12263
|
+
return encodeURIComponent(f(param.value));
|
|
12264
|
+
}).join("/");
|
|
12265
|
+
for (const param of request.params ?? []) {
|
|
12266
|
+
if (param.enabled && param.name.trim()) url.searchParams.append(f(param.name.trim()), f(param.value));
|
|
12267
|
+
}
|
|
12268
|
+
const auth = request.auth ?? { type: "none" };
|
|
12269
|
+
if (auth.type === "bearer") headers.set("Authorization", `Bearer ${f(auth.token)}`);
|
|
12270
|
+
if (auth.type === "basic") headers.set("Authorization", `Basic ${Buffer.from(`${f(auth.username)}:${f(auth.password)}`).toString("base64")}`);
|
|
12271
|
+
if (auth.type === "api-key") {
|
|
12272
|
+
if (auth.location === "query") url.searchParams.set(f(auth.name), f(auth.value));
|
|
12273
|
+
else headers.set(f(auth.name), f(auth.value));
|
|
12274
|
+
}
|
|
12275
|
+
let body;
|
|
12276
|
+
const mode = request.bodyMode ?? "none";
|
|
12277
|
+
if (mode === "urlencoded") {
|
|
12278
|
+
const form = new URLSearchParams();
|
|
12279
|
+
for (const field of request.bodyFields ?? []) if (field.enabled && field.type === "text") form.append(f(field.name), f(field.value));
|
|
12280
|
+
body = form.toString();
|
|
12281
|
+
headers.set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
|
|
12282
|
+
} else if (mode === "form-data") {
|
|
12283
|
+
const form = new FormData();
|
|
12284
|
+
for (const field of request.bodyFields ?? []) {
|
|
12285
|
+
if (!field.enabled) continue;
|
|
12286
|
+
if (field.type === "text") form.append(f(field.name), f(field.value));
|
|
12287
|
+
else if (field.filePath) form.append(f(field.name), new Blob([await readFile(field.filePath)]), field.fileName || basename(field.filePath));
|
|
12288
|
+
}
|
|
12289
|
+
body = form;
|
|
12290
|
+
} else if (mode === "file") {
|
|
12291
|
+
if (!request.bodyPath) throw new Error("This request has no file to send as its body.");
|
|
12292
|
+
body = new Blob([await readFile(request.bodyPath)]);
|
|
12293
|
+
if (!headers.has("Content-Type")) headers.set("Content-Type", request.bodyMimeType || "application/octet-stream");
|
|
12294
|
+
} else if (mode !== "none" && request.body) {
|
|
12295
|
+
body = f(request.body);
|
|
12296
|
+
if (!headers.has("Content-Type")) headers.set("Content-Type", request.bodyMimeType || defaultMime[mode] || "text/plain");
|
|
12297
|
+
}
|
|
12298
|
+
if (missing.size) {
|
|
12299
|
+
const names = [...missing];
|
|
12300
|
+
const secretNames = names.filter((name) => blocked.has(name));
|
|
12301
|
+
const hint = secretNames.length ? ` Enter the secret values (${secretNames.join(", ")}) in the desktop app.` : "";
|
|
12302
|
+
throw new Error(`Variables need a value before sending: ${names.join(", ")}.${hint} Set other values with variable.set.`);
|
|
12303
|
+
}
|
|
12304
|
+
const method2 = request.method.toUpperCase();
|
|
12305
|
+
const target = sanitizeUrl(url.toString());
|
|
12306
|
+
if (options.dryRun) return { dryRun: true, method: method2, url: target };
|
|
12307
|
+
if (options.confirmUrl !== void 0 && options.confirmUrl !== target) {
|
|
12308
|
+
throw new Error(`The target changed. This request now goes to ${target}. Confirm that URL with a dry run before sending.`);
|
|
12309
|
+
}
|
|
12310
|
+
const started = Date.now();
|
|
12311
|
+
const response = await fetch(url, {
|
|
12312
|
+
method: method2,
|
|
12313
|
+
headers,
|
|
12314
|
+
body: method2 === "GET" || method2 === "HEAD" ? void 0 : body,
|
|
12315
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
12316
|
+
});
|
|
12317
|
+
const text = await response.text();
|
|
12318
|
+
return {
|
|
12319
|
+
status: response.status,
|
|
12320
|
+
statusText: response.statusText,
|
|
12321
|
+
url: sanitizeUrl(response.url || url.toString()),
|
|
12322
|
+
durationMs: Date.now() - started,
|
|
12323
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
12324
|
+
body: text.length > maxBodyChars ? text.slice(0, maxBodyChars) : text,
|
|
12325
|
+
bodyTruncated: text.length > maxBodyChars
|
|
12326
|
+
};
|
|
12327
|
+
}
|
|
12328
|
+
|
|
12329
|
+
// src/commands/requests.ts
|
|
12330
|
+
var workspaceId3 = external_exports.string().min(1).describe("Workspace id from workspace.list");
|
|
12331
|
+
var requestId = external_exports.string().min(1).describe("Request id from tree.get or request.search");
|
|
12332
|
+
var parentId2 = external_exports.string().nullable().default(null).describe("Folder id, or null for the root");
|
|
12333
|
+
var confirm3 = external_exports.literal(true).describe("Must be true; ask the user first");
|
|
12334
|
+
var requestCommands = [
|
|
12335
|
+
defineCommand({
|
|
12336
|
+
id: "request.search",
|
|
12337
|
+
group: "request",
|
|
12338
|
+
title: "Search requests",
|
|
12339
|
+
description: "Search request names, methods, URLs, documentation, and response descriptions. Sensitive URL values are masked.",
|
|
12340
|
+
params: external_exports.object({ workspaceId: workspaceId3, query: external_exports.string().trim().min(1).max(200) }),
|
|
12341
|
+
readOnly: true,
|
|
12342
|
+
run: ({ workspaceId: id, query }) => {
|
|
12343
|
+
const { workspace } = readWorkspace(id);
|
|
12344
|
+
const needle = query.toLocaleLowerCase();
|
|
12345
|
+
return requestList(workspace.tree).filter((request) => {
|
|
12346
|
+
const haystack = [request.name, request.method, request.url, request.documentation ?? "", ...(request.responses ?? []).map((item) => item.description)];
|
|
12347
|
+
return haystack.join("\n").toLocaleLowerCase().includes(needle);
|
|
12348
|
+
}).map((request) => safeRequest(request));
|
|
12349
|
+
}
|
|
12350
|
+
}),
|
|
12351
|
+
defineCommand({
|
|
12352
|
+
id: "request.get",
|
|
12353
|
+
group: "request",
|
|
12354
|
+
title: "Read request",
|
|
12355
|
+
description: "Read one request definition: params, body, auth, headers, documented responses, and documentation. Literal secrets are redacted; {{variable}} references are shown as written.",
|
|
12356
|
+
params: external_exports.object({ workspaceId: workspaceId3, requestId }),
|
|
12357
|
+
readOnly: true,
|
|
12358
|
+
run: ({ workspaceId: id, requestId: request }) => safeRequest(findRequest(readWorkspace(id).workspace.tree, request))
|
|
12359
|
+
}),
|
|
12360
|
+
defineCommand({
|
|
12361
|
+
id: "request.create",
|
|
12362
|
+
group: "request",
|
|
12363
|
+
title: "Create request",
|
|
12364
|
+
description: "Create a request under a folder, or at the root when parentId is null. Use {{variableName}} for environment-specific values.",
|
|
12365
|
+
params: external_exports.object({ workspaceId: workspaceId3, parentId: parentId2, request: external_exports.object(requestFields) }),
|
|
12366
|
+
readOnly: false,
|
|
12367
|
+
run: ({ workspaceId: id, parentId: parent, request }) => {
|
|
12368
|
+
let created;
|
|
12369
|
+
updateWorkspace(id, (workspace) => {
|
|
12370
|
+
const result = applyOperation(workspace.tree, { action: "create_request", parentId: parent, request });
|
|
12371
|
+
created = result.summary.after;
|
|
12372
|
+
return { ...workspace, tree: result.tree };
|
|
12373
|
+
});
|
|
12374
|
+
return created;
|
|
12375
|
+
}
|
|
12376
|
+
}),
|
|
12377
|
+
defineCommand({
|
|
12378
|
+
id: "request.update",
|
|
12379
|
+
group: "request",
|
|
12380
|
+
title: "Update request",
|
|
12381
|
+
description: "Change fields of a request. Only the fields you send are changed; existing auth is kept unless you send auth.",
|
|
12382
|
+
params: external_exports.object({ workspaceId: workspaceId3, requestId, patch: external_exports.object(requestFields).partial() }),
|
|
12383
|
+
readOnly: false,
|
|
12384
|
+
run: ({ workspaceId: id, requestId: request, patch }) => {
|
|
12385
|
+
updateWorkspace(id, (workspace) => ({
|
|
12386
|
+
...workspace,
|
|
12387
|
+
tree: applyOperation(workspace.tree, { action: "update_request", requestId: request, patch }).tree
|
|
12388
|
+
}));
|
|
12389
|
+
return { updated: true, requestId: request };
|
|
12390
|
+
}
|
|
12391
|
+
}),
|
|
12392
|
+
defineCommand({
|
|
12393
|
+
id: "request.duplicate",
|
|
12394
|
+
group: "request",
|
|
12395
|
+
title: "Duplicate request",
|
|
12396
|
+
description: 'Copy a request into the same folder as "<name>_copy", with new ids, and return the copy.',
|
|
12397
|
+
params: external_exports.object({ workspaceId: workspaceId3, requestId }),
|
|
12398
|
+
readOnly: false,
|
|
12399
|
+
run: ({ workspaceId: id, requestId: request }) => {
|
|
12400
|
+
let copyResult;
|
|
12401
|
+
updateWorkspace(id, (workspace) => {
|
|
12402
|
+
const original = findRequest(workspace.tree, request);
|
|
12403
|
+
const parent = findParentId(workspace.tree, original.id) ?? null;
|
|
12404
|
+
const copy = { ...cloneWithNewIds(original), name: `${original.name}_copy` };
|
|
12405
|
+
copyResult = safeRequest(copy);
|
|
12406
|
+
return { ...workspace, tree: insertNode(workspace.tree, parent, copy) };
|
|
12407
|
+
});
|
|
12408
|
+
return copyResult;
|
|
12409
|
+
}
|
|
12410
|
+
}),
|
|
12411
|
+
defineCommand({
|
|
12412
|
+
id: "request.deprecate",
|
|
12413
|
+
group: "request",
|
|
12414
|
+
title: "Mark request deprecated",
|
|
12415
|
+
description: "Mark a request as deprecated (or clear it) with an optional reason.",
|
|
12416
|
+
params: external_exports.object({ workspaceId: workspaceId3, requestId, deprecated: external_exports.boolean(), reason: external_exports.string().max(4096).optional() }),
|
|
12417
|
+
readOnly: false,
|
|
12418
|
+
run: ({ workspaceId: id, requestId: request, deprecated, reason }) => {
|
|
12419
|
+
updateWorkspace(id, (workspace) => ({
|
|
12420
|
+
...workspace,
|
|
12421
|
+
tree: applyOperation(workspace.tree, { action: "deprecate_request", requestId: request, deprecated, reason }).tree
|
|
12422
|
+
}));
|
|
12423
|
+
return { requestId: request, deprecated };
|
|
12424
|
+
}
|
|
12425
|
+
}),
|
|
12426
|
+
defineCommand({
|
|
12427
|
+
id: "request.delete",
|
|
12428
|
+
group: "request",
|
|
12429
|
+
title: "Delete request",
|
|
12430
|
+
description: "Delete a request. Requires confirm=true after the user confirms.",
|
|
12431
|
+
params: external_exports.object({ workspaceId: workspaceId3, requestId, confirm: confirm3 }),
|
|
12432
|
+
readOnly: false,
|
|
12433
|
+
destructive: true,
|
|
12434
|
+
run: ({ workspaceId: id, requestId: request }) => {
|
|
12435
|
+
updateWorkspace(id, (workspace) => ({ ...workspace, tree: applyOperation(workspace.tree, { action: "delete_node", nodeId: request }).tree }));
|
|
12436
|
+
return { deleted: true, requestId: request };
|
|
12437
|
+
}
|
|
12438
|
+
}),
|
|
12439
|
+
defineCommand({
|
|
12440
|
+
id: "request.send",
|
|
12441
|
+
group: "request",
|
|
12442
|
+
title: "Send request",
|
|
12443
|
+
description: "Send a request over HTTP and return status, headers, and body. {{variables}} are filled from the active or given environment and globals. Secret variables must be set in the desktop app first.",
|
|
12444
|
+
params: external_exports.object({
|
|
12445
|
+
workspaceId: workspaceId3,
|
|
12446
|
+
requestId,
|
|
12447
|
+
environmentId: external_exports.string().min(1).nullable().optional().describe("Environment id; defaults to the active one, or null for none"),
|
|
12448
|
+
dryRun: external_exports.boolean().optional().describe("Return the URL the request would call, without sending it"),
|
|
12449
|
+
confirmUrl: external_exports.string().min(1).optional().describe("Send only if the request still goes to this URL, as shown by a dry run")
|
|
12450
|
+
}),
|
|
12451
|
+
readOnly: false,
|
|
12452
|
+
run: async ({ workspaceId: id, requestId: request, environmentId: environmentId2, dryRun, confirmUrl }) => {
|
|
12453
|
+
const { workspace } = readWorkspace(id);
|
|
12454
|
+
return sendRequest(findRequest(workspace.tree, request), workspace, environmentId2 ?? null, { dryRun, confirmUrl });
|
|
12455
|
+
}
|
|
12456
|
+
})
|
|
12457
|
+
];
|
|
12458
|
+
|
|
12459
|
+
// src/commands/workspace.ts
|
|
12460
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
12461
|
+
var workspaceId4 = external_exports.string().min(1).describe("Workspace id from workspace.list");
|
|
12462
|
+
var emptyVariables = () => ({ globals: [], environments: [] });
|
|
12463
|
+
var workspaceCommands = [
|
|
12464
|
+
defineCommand({
|
|
12465
|
+
id: "workspace.list",
|
|
12466
|
+
group: "workspace",
|
|
12467
|
+
title: "List workspaces",
|
|
12468
|
+
description: "List the workspaces in the desktop app. Use the returned id for every other command.",
|
|
12469
|
+
params: external_exports.object({}),
|
|
12470
|
+
readOnly: true,
|
|
12471
|
+
run: () => listWorkspaces()
|
|
12472
|
+
}),
|
|
12473
|
+
defineCommand({
|
|
12474
|
+
id: "workspace.create",
|
|
12475
|
+
group: "workspace",
|
|
12476
|
+
title: "Create local workspace",
|
|
12477
|
+
description: "Create an empty local workspace. Cloud workspaces are created in the desktop app.",
|
|
12478
|
+
params: external_exports.object({ name: external_exports.string().trim().min(1).max(160).describe("Workspace name") }),
|
|
12479
|
+
readOnly: false,
|
|
12480
|
+
run: ({ name }) => {
|
|
12481
|
+
const workspace = {
|
|
12482
|
+
id: randomUUID6(),
|
|
12483
|
+
cloudId: null,
|
|
12484
|
+
name,
|
|
12485
|
+
tree: [],
|
|
12486
|
+
baseTree: [],
|
|
12487
|
+
variables: emptyVariables(),
|
|
12488
|
+
baseVariables: emptyVariables(),
|
|
12489
|
+
activeEnvironmentId: null,
|
|
12490
|
+
baseCommitId: null,
|
|
12491
|
+
localHeadId: null
|
|
12492
|
+
};
|
|
12493
|
+
insertWorkspace(workspace);
|
|
12494
|
+
return { id: workspace.id, name: workspace.name };
|
|
12495
|
+
}
|
|
12496
|
+
}),
|
|
12497
|
+
defineCommand({
|
|
12498
|
+
id: "workspace.rename",
|
|
12499
|
+
group: "workspace",
|
|
12500
|
+
title: "Rename workspace",
|
|
12501
|
+
description: "Change the name of a local workspace.",
|
|
12502
|
+
params: external_exports.object({ workspaceId: workspaceId4, name: external_exports.string().trim().min(1).max(160) }),
|
|
12503
|
+
readOnly: false,
|
|
12504
|
+
run: ({ workspaceId: id, name }) => {
|
|
12505
|
+
const workspace = updateWorkspace(id, (current) => ({ ...current, name }));
|
|
12506
|
+
return { id, name: workspace.name };
|
|
12507
|
+
}
|
|
12508
|
+
}),
|
|
12509
|
+
defineCommand({
|
|
12510
|
+
id: "workspace.delete",
|
|
12511
|
+
group: "workspace",
|
|
12512
|
+
title: "Delete local workspace",
|
|
12513
|
+
description: "Delete a local workspace and its commit history. Requires confirm=true after the user confirms. Cloud workspaces are refused.",
|
|
12514
|
+
params: external_exports.object({ workspaceId: workspaceId4, confirm: external_exports.literal(true).describe("Must be true; ask the user first") }),
|
|
12515
|
+
readOnly: false,
|
|
12516
|
+
destructive: true,
|
|
12517
|
+
run: ({ workspaceId: id }) => {
|
|
12518
|
+
const { workspace } = readWorkspace(id);
|
|
12519
|
+
deleteWorkspace(id);
|
|
12520
|
+
return { deleted: true, id, name: workspace.name };
|
|
12521
|
+
}
|
|
12522
|
+
}),
|
|
12523
|
+
defineCommand({
|
|
12524
|
+
id: "tree.get",
|
|
12525
|
+
group: "workspace",
|
|
12526
|
+
title: "Read collection tree",
|
|
12527
|
+
description: "Read the folder hierarchy and request summaries of a workspace. Credentials and secret-like values are redacted.",
|
|
12528
|
+
params: external_exports.object({ workspaceId: workspaceId4 }),
|
|
12529
|
+
readOnly: true,
|
|
12530
|
+
run: ({ workspaceId: id }) => {
|
|
12531
|
+
const { workspace } = readWorkspace(id);
|
|
12532
|
+
return { workspaceId: id, workspaceName: workspace.name, tree: safeTree(workspace.tree) };
|
|
12533
|
+
}
|
|
12534
|
+
})
|
|
12535
|
+
];
|
|
12536
|
+
|
|
12537
|
+
// src/commands/index.ts
|
|
12538
|
+
var listCommand = defineCommand({
|
|
12539
|
+
id: "commands.list",
|
|
12540
|
+
group: "meta",
|
|
12541
|
+
title: "List commands",
|
|
12542
|
+
description: "List every command with its parameters, so an agent can discover what the desktop app can do. Filter with a text query.",
|
|
12543
|
+
params: external_exports.object({ filter: external_exports.string().trim().max(200).optional().describe("Text to match in id, title, or description") }),
|
|
12544
|
+
readOnly: true,
|
|
12545
|
+
run: ({ filter }) => {
|
|
12546
|
+
const needle = filter?.toLocaleLowerCase();
|
|
12547
|
+
return allCommands.filter((command) => !needle || `${command.id} ${command.title} ${command.description}`.toLocaleLowerCase().includes(needle)).map(describeCommand);
|
|
12548
|
+
}
|
|
12549
|
+
});
|
|
12550
|
+
var allCommands = [
|
|
12551
|
+
listCommand,
|
|
12552
|
+
...workspaceCommands,
|
|
12553
|
+
...collectionCommands,
|
|
12554
|
+
...requestCommands,
|
|
12555
|
+
...environmentCommands,
|
|
12556
|
+
...changeCommands
|
|
12557
|
+
];
|
|
12558
|
+
function findCommand(id) {
|
|
12559
|
+
const command = allCommands.find((item) => item.id === id);
|
|
12560
|
+
if (!command) throw new Error(`Unknown command "${id}". Run "api-documentation-mcp commands" to list them.`);
|
|
12561
|
+
return command;
|
|
12562
|
+
}
|
|
12563
|
+
async function executeCommand(id, params) {
|
|
12564
|
+
return findCommand(id).run(params);
|
|
12565
|
+
}
|
|
12566
|
+
|
|
12567
|
+
// src/cli.ts
|
|
12568
|
+
var usage = `api-documentation-mcp: drive the API Documentation desktop app from the command line or an AI agent
|
|
12569
|
+
|
|
12570
|
+
USAGE:
|
|
12571
|
+
api-documentation-mcp commands [--json] [--filter TEXT] list every command and its parameters
|
|
12572
|
+
api-documentation-mcp call <command> [json-params] run one command, print its JSON result
|
|
12573
|
+
api-documentation-mcp run <script.json|-> [--json] run a JSON array or JSON lines of {"command", "params"}
|
|
12574
|
+
api-documentation-mcp mcp start the MCP server (stdio); also the default with no arguments
|
|
12575
|
+
api-documentation-mcp help
|
|
12576
|
+
|
|
12577
|
+
Commands read and write the app's local workspace database. Keep the desktop app open to see changes live.
|
|
12578
|
+
Destructive commands need "confirm": true, and collection writes that go through changes.preview need changes.apply.`;
|
|
12579
|
+
function printJson(value) {
|
|
12580
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
12581
|
+
`);
|
|
12582
|
+
}
|
|
12583
|
+
function parseParams(text) {
|
|
12584
|
+
if (!text) return {};
|
|
12585
|
+
try {
|
|
12586
|
+
return JSON.parse(text);
|
|
12587
|
+
} catch {
|
|
12588
|
+
throw new Error(`Parameters must be JSON, for example '{"workspaceId":"..."}'.`);
|
|
12589
|
+
}
|
|
12590
|
+
}
|
|
12591
|
+
function listCommands(args2) {
|
|
12592
|
+
const filterAt = args2.indexOf("--filter");
|
|
12593
|
+
const filter = filterAt >= 0 ? args2[filterAt + 1]?.toLocaleLowerCase() : void 0;
|
|
12594
|
+
const commands = allCommands.map(describeCommand).filter((command) => !filter || `${command.id} ${command.title} ${command.description}`.toLocaleLowerCase().includes(filter));
|
|
12595
|
+
if (args2.includes("--json")) return printJson(commands);
|
|
12596
|
+
for (const command of commands) {
|
|
12597
|
+
const flags = [command.readOnly ? "read-only" : "write", command.destructive ? "destructive" : null].filter(Boolean).join(", ");
|
|
12598
|
+
const params = command.params.map((param) => `${param.name}${param.required ? "" : "?"}`).join(" ");
|
|
12599
|
+
process.stdout.write(`${command.id.padEnd(24)} ${command.title} [${flags}]
|
|
12600
|
+
${params}
|
|
12601
|
+
`);
|
|
12602
|
+
}
|
|
12603
|
+
}
|
|
12604
|
+
function readScript(path) {
|
|
12605
|
+
const text = path === "-" ? readFileSync(0, "utf8") : readFileSync(path, "utf8");
|
|
12606
|
+
const trimmed = text.trim();
|
|
12607
|
+
if (!trimmed) return [];
|
|
12608
|
+
if (trimmed.startsWith("[")) return JSON.parse(trimmed);
|
|
12609
|
+
return trimmed.split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
|
|
12610
|
+
}
|
|
12611
|
+
async function runScript(path) {
|
|
12612
|
+
if (!path) throw new Error("run needs a script path, or - for stdin.");
|
|
12613
|
+
const steps = readScript(path);
|
|
12614
|
+
let failures = 0;
|
|
12615
|
+
for (const [index, step] of steps.entries()) {
|
|
12616
|
+
const { command, params } = step ?? {};
|
|
12617
|
+
if (typeof command !== "string") {
|
|
12618
|
+
failures += 1;
|
|
12619
|
+
process.stdout.write(`${JSON.stringify({ step: index + 1, ok: false, error: 'Each step needs a "command" string.' })}
|
|
12620
|
+
`);
|
|
12621
|
+
continue;
|
|
12622
|
+
}
|
|
12623
|
+
try {
|
|
12624
|
+
const result = await executeCommand(command, params ?? {});
|
|
12625
|
+
process.stdout.write(`${JSON.stringify({ step: index + 1, command, ok: true, result })}
|
|
12626
|
+
`);
|
|
12627
|
+
} catch (error2) {
|
|
12628
|
+
failures += 1;
|
|
12629
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
12630
|
+
process.stdout.write(`${JSON.stringify({ step: index + 1, command, ok: false, error: message })}
|
|
12631
|
+
`);
|
|
12632
|
+
}
|
|
12633
|
+
}
|
|
12634
|
+
if (failures) process.exitCode = 1;
|
|
12635
|
+
}
|
|
12636
|
+
async function runCli(args2) {
|
|
12637
|
+
const [name, ...rest] = args2;
|
|
12638
|
+
if (name === "help" || name === "--help" || name === "-h") return void process.stdout.write(`${usage}
|
|
12639
|
+
`);
|
|
12640
|
+
if (name === "commands") return listCommands(rest);
|
|
12641
|
+
if (name === "call") {
|
|
12642
|
+
const [command, params] = rest;
|
|
12643
|
+
if (!command) throw new Error('call needs a command id. Run "api-documentation-mcp commands" to list them.');
|
|
12644
|
+
return printJson(await executeCommand(command, parseParams(params)));
|
|
12645
|
+
}
|
|
12646
|
+
if (name === "run") return runScript(rest.find((item) => !item.startsWith("--")));
|
|
12647
|
+
throw new Error(`Unknown subcommand "${name}".
|
|
12648
|
+
|
|
12649
|
+
${usage}`);
|
|
12650
|
+
}
|
|
12651
|
+
|
|
12652
|
+
// node_modules/zod/v4/core/core.js
|
|
12653
|
+
var NEVER2 = Object.freeze({
|
|
12654
|
+
status: "aborted"
|
|
12655
|
+
});
|
|
12656
|
+
// @__NO_SIDE_EFFECTS__
|
|
12657
|
+
function $constructor(name, initializer3, params) {
|
|
12658
|
+
function init(inst, def) {
|
|
12659
|
+
var _a;
|
|
12660
|
+
Object.defineProperty(inst, "_zod", {
|
|
12661
|
+
value: inst._zod ?? {},
|
|
12662
|
+
enumerable: false
|
|
12663
|
+
});
|
|
12664
|
+
(_a = inst._zod).traits ?? (_a.traits = /* @__PURE__ */ new Set());
|
|
12665
|
+
inst._zod.traits.add(name);
|
|
12666
|
+
initializer3(inst, def);
|
|
12667
|
+
for (const k in _.prototype) {
|
|
12668
|
+
if (!(k in inst))
|
|
12669
|
+
Object.defineProperty(inst, k, { value: _.prototype[k].bind(inst) });
|
|
12670
|
+
}
|
|
12671
|
+
inst._zod.constr = _;
|
|
12672
|
+
inst._zod.def = def;
|
|
12673
|
+
}
|
|
12674
|
+
const Parent = params?.Parent ?? Object;
|
|
12675
|
+
class Definition extends Parent {
|
|
12676
|
+
}
|
|
12677
|
+
Object.defineProperty(Definition, "name", { value: name });
|
|
12678
|
+
function _(def) {
|
|
12679
|
+
var _a;
|
|
12680
|
+
const inst = params?.Parent ? new Definition() : this;
|
|
12681
|
+
init(inst, def);
|
|
12682
|
+
(_a = inst._zod).deferred ?? (_a.deferred = []);
|
|
12683
|
+
for (const fn of inst._zod.deferred) {
|
|
12684
|
+
fn();
|
|
12685
|
+
}
|
|
12686
|
+
return inst;
|
|
12687
|
+
}
|
|
12688
|
+
Object.defineProperty(_, "init", { value: init });
|
|
12689
|
+
Object.defineProperty(_, Symbol.hasInstance, {
|
|
12690
|
+
value: (inst) => {
|
|
12691
|
+
if (params?.Parent && inst instanceof params.Parent)
|
|
12692
|
+
return true;
|
|
12693
|
+
return inst?._zod?.traits?.has(name);
|
|
12694
|
+
}
|
|
12695
|
+
});
|
|
12696
|
+
Object.defineProperty(_, "name", { value: name });
|
|
12697
|
+
return _;
|
|
12698
|
+
}
|
|
12699
|
+
var $brand = Symbol("zod_brand");
|
|
12700
|
+
var $ZodAsyncError = class extends Error {
|
|
12701
|
+
constructor() {
|
|
12702
|
+
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
12703
|
+
}
|
|
12704
|
+
};
|
|
12705
|
+
var globalConfig = {};
|
|
12706
|
+
function config(newConfig) {
|
|
12707
|
+
if (newConfig)
|
|
12708
|
+
Object.assign(globalConfig, newConfig);
|
|
12709
|
+
return globalConfig;
|
|
12710
|
+
}
|
|
12711
|
+
|
|
12712
|
+
// node_modules/zod/v4/core/util.js
|
|
12713
|
+
var util_exports = {};
|
|
12714
|
+
__export(util_exports, {
|
|
12715
|
+
BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
|
|
12716
|
+
Class: () => Class,
|
|
12717
|
+
NUMBER_FORMAT_RANGES: () => NUMBER_FORMAT_RANGES,
|
|
12718
|
+
aborted: () => aborted,
|
|
12719
|
+
allowsEval: () => allowsEval,
|
|
12720
|
+
assert: () => assert,
|
|
12721
|
+
assertEqual: () => assertEqual,
|
|
12722
|
+
assertIs: () => assertIs,
|
|
12723
|
+
assertNever: () => assertNever,
|
|
12724
|
+
assertNotEqual: () => assertNotEqual,
|
|
12725
|
+
assignProp: () => assignProp,
|
|
12726
|
+
cached: () => cached,
|
|
12727
|
+
captureStackTrace: () => captureStackTrace,
|
|
12728
|
+
cleanEnum: () => cleanEnum,
|
|
12729
|
+
cleanRegex: () => cleanRegex,
|
|
12730
|
+
clone: () => clone,
|
|
12731
|
+
createTransparentProxy: () => createTransparentProxy,
|
|
12732
|
+
defineLazy: () => defineLazy,
|
|
12733
|
+
esc: () => esc,
|
|
12734
|
+
escapeRegex: () => escapeRegex,
|
|
12735
|
+
extend: () => extend,
|
|
12736
|
+
finalizeIssue: () => finalizeIssue,
|
|
12737
|
+
floatSafeRemainder: () => floatSafeRemainder2,
|
|
12738
|
+
getElementAtPath: () => getElementAtPath,
|
|
12739
|
+
getEnumValues: () => getEnumValues,
|
|
12740
|
+
getLengthableOrigin: () => getLengthableOrigin,
|
|
12741
|
+
getParsedType: () => getParsedType2,
|
|
12742
|
+
getSizableOrigin: () => getSizableOrigin,
|
|
12743
|
+
isObject: () => isObject,
|
|
12744
|
+
isPlainObject: () => isPlainObject,
|
|
12745
|
+
issue: () => issue,
|
|
12746
|
+
joinValues: () => joinValues,
|
|
12747
|
+
jsonStringifyReplacer: () => jsonStringifyReplacer,
|
|
12748
|
+
merge: () => merge,
|
|
12749
|
+
normalizeParams: () => normalizeParams,
|
|
12750
|
+
nullish: () => nullish,
|
|
12751
|
+
numKeys: () => numKeys,
|
|
12752
|
+
omit: () => omit,
|
|
12753
|
+
optionalKeys: () => optionalKeys,
|
|
12754
|
+
partial: () => partial,
|
|
12755
|
+
pick: () => pick,
|
|
12756
|
+
prefixIssues: () => prefixIssues,
|
|
12757
|
+
primitiveTypes: () => primitiveTypes,
|
|
12758
|
+
promiseAllObject: () => promiseAllObject,
|
|
12759
|
+
propertyKeyTypes: () => propertyKeyTypes,
|
|
12760
|
+
randomString: () => randomString,
|
|
12761
|
+
required: () => required,
|
|
12762
|
+
stringifyPrimitive: () => stringifyPrimitive,
|
|
12763
|
+
unwrapMessage: () => unwrapMessage
|
|
12764
|
+
});
|
|
12765
|
+
function assertEqual(val) {
|
|
12766
|
+
return val;
|
|
12767
|
+
}
|
|
12768
|
+
function assertNotEqual(val) {
|
|
12769
|
+
return val;
|
|
12770
|
+
}
|
|
12771
|
+
function assertIs(_arg) {
|
|
12772
|
+
}
|
|
12773
|
+
function assertNever(_x) {
|
|
12774
|
+
throw new Error();
|
|
12775
|
+
}
|
|
12776
|
+
function assert(_) {
|
|
12777
|
+
}
|
|
12778
|
+
function getEnumValues(entries) {
|
|
12779
|
+
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
12780
|
+
const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
|
|
12781
|
+
return values;
|
|
12782
|
+
}
|
|
12783
|
+
function joinValues(array2, separator = "|") {
|
|
12784
|
+
return array2.map((val) => stringifyPrimitive(val)).join(separator);
|
|
12785
|
+
}
|
|
12786
|
+
function jsonStringifyReplacer(_, value) {
|
|
12787
|
+
if (typeof value === "bigint")
|
|
12788
|
+
return value.toString();
|
|
12789
|
+
return value;
|
|
12790
|
+
}
|
|
12791
|
+
function cached(getter) {
|
|
12792
|
+
const set = false;
|
|
12793
|
+
return {
|
|
12794
|
+
get value() {
|
|
12795
|
+
if (!set) {
|
|
12796
|
+
const value = getter();
|
|
12797
|
+
Object.defineProperty(this, "value", { value });
|
|
12798
|
+
return value;
|
|
12799
|
+
}
|
|
12800
|
+
throw new Error("cached value already set");
|
|
12801
|
+
}
|
|
12802
|
+
};
|
|
12803
|
+
}
|
|
12804
|
+
function nullish(input) {
|
|
12805
|
+
return input === null || input === void 0;
|
|
12806
|
+
}
|
|
12807
|
+
function cleanRegex(source) {
|
|
12808
|
+
const start = source.startsWith("^") ? 1 : 0;
|
|
11403
12809
|
const end = source.endsWith("$") ? source.length - 1 : source.length;
|
|
11404
12810
|
return source.slice(start, end);
|
|
11405
12811
|
}
|
|
@@ -11802,8 +13208,8 @@ function getLengthableOrigin(input) {
|
|
|
11802
13208
|
return "string";
|
|
11803
13209
|
return "unknown";
|
|
11804
13210
|
}
|
|
11805
|
-
function issue(...
|
|
11806
|
-
const [iss, input, inst] =
|
|
13211
|
+
function issue(...args2) {
|
|
13212
|
+
const [iss, input, inst] = args2;
|
|
11807
13213
|
if (typeof iss === "string") {
|
|
11808
13214
|
return {
|
|
11809
13215
|
message: iss,
|
|
@@ -11980,20 +13386,20 @@ var hostname = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
|
|
|
11980
13386
|
var e164 = /^\+(?:[0-9]){6,14}[0-9]$/;
|
|
11981
13387
|
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
|
11982
13388
|
var date = /* @__PURE__ */ new RegExp(`^${dateSource}$`);
|
|
11983
|
-
function timeSource(
|
|
13389
|
+
function timeSource(args2) {
|
|
11984
13390
|
const hhmm = `(?:[01]\\d|2[0-3]):[0-5]\\d`;
|
|
11985
|
-
const regex = typeof
|
|
13391
|
+
const regex = typeof args2.precision === "number" ? args2.precision === -1 ? `${hhmm}` : args2.precision === 0 ? `${hhmm}:[0-5]\\d` : `${hhmm}:[0-5]\\d\\.\\d{${args2.precision}}` : `${hhmm}(?::[0-5]\\d(?:\\.\\d+)?)?`;
|
|
11986
13392
|
return regex;
|
|
11987
13393
|
}
|
|
11988
|
-
function time(
|
|
11989
|
-
return new RegExp(`^${timeSource(
|
|
13394
|
+
function time(args2) {
|
|
13395
|
+
return new RegExp(`^${timeSource(args2)}$`);
|
|
11990
13396
|
}
|
|
11991
|
-
function datetime(
|
|
11992
|
-
const time3 = timeSource({ precision:
|
|
13397
|
+
function datetime(args2) {
|
|
13398
|
+
const time3 = timeSource({ precision: args2.precision });
|
|
11993
13399
|
const opts = ["Z"];
|
|
11994
|
-
if (
|
|
13400
|
+
if (args2.local)
|
|
11995
13401
|
opts.push("");
|
|
11996
|
-
if (
|
|
13402
|
+
if (args2.offset)
|
|
11997
13403
|
opts.push(`([+-]\\d{2}:\\d{2})`);
|
|
11998
13404
|
const timeRegex2 = `${time3}(?:${opts.join("|")})`;
|
|
11999
13405
|
return new RegExp(`^${dateSource}T(?:${timeRegex2})$`);
|
|
@@ -12396,11 +13802,11 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
|
|
|
12396
13802
|
|
|
12397
13803
|
// node_modules/zod/v4/core/doc.js
|
|
12398
13804
|
var Doc = class {
|
|
12399
|
-
constructor(
|
|
13805
|
+
constructor(args2 = []) {
|
|
12400
13806
|
this.content = [];
|
|
12401
13807
|
this.indent = 0;
|
|
12402
13808
|
if (this)
|
|
12403
|
-
this.args =
|
|
13809
|
+
this.args = args2;
|
|
12404
13810
|
}
|
|
12405
13811
|
indented(fn) {
|
|
12406
13812
|
this.indent += 1;
|
|
@@ -12423,10 +13829,10 @@ var Doc = class {
|
|
|
12423
13829
|
}
|
|
12424
13830
|
compile() {
|
|
12425
13831
|
const F = Function;
|
|
12426
|
-
const
|
|
13832
|
+
const args2 = this?.args;
|
|
12427
13833
|
const content = this?.content ?? [``];
|
|
12428
13834
|
const lines = [...content.map((x) => ` ${x}`)];
|
|
12429
|
-
return new F(...
|
|
13835
|
+
return new F(...args2, lines.join("\n"));
|
|
12430
13836
|
}
|
|
12431
13837
|
};
|
|
12432
13838
|
|
|
@@ -15391,12 +16797,12 @@ var ZodType2 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
15391
16797
|
},
|
|
15392
16798
|
configurable: true
|
|
15393
16799
|
});
|
|
15394
|
-
inst.meta = (...
|
|
15395
|
-
if (
|
|
16800
|
+
inst.meta = (...args2) => {
|
|
16801
|
+
if (args2.length === 0) {
|
|
15396
16802
|
return globalRegistry.get(inst);
|
|
15397
16803
|
}
|
|
15398
16804
|
const cl = inst.clone();
|
|
15399
|
-
globalRegistry.add(cl,
|
|
16805
|
+
globalRegistry.add(cl, args2[0]);
|
|
15400
16806
|
return cl;
|
|
15401
16807
|
};
|
|
15402
16808
|
inst.isOptional = () => inst.safeParse(void 0).success;
|
|
@@ -15410,18 +16816,18 @@ var _ZodString = /* @__PURE__ */ $constructor("_ZodString", (inst, def) => {
|
|
|
15410
16816
|
inst.format = bag.format ?? null;
|
|
15411
16817
|
inst.minLength = bag.minimum ?? null;
|
|
15412
16818
|
inst.maxLength = bag.maximum ?? null;
|
|
15413
|
-
inst.regex = (...
|
|
15414
|
-
inst.includes = (...
|
|
15415
|
-
inst.startsWith = (...
|
|
15416
|
-
inst.endsWith = (...
|
|
15417
|
-
inst.min = (...
|
|
15418
|
-
inst.max = (...
|
|
15419
|
-
inst.length = (...
|
|
15420
|
-
inst.nonempty = (...
|
|
16819
|
+
inst.regex = (...args2) => inst.check(_regex(...args2));
|
|
16820
|
+
inst.includes = (...args2) => inst.check(_includes(...args2));
|
|
16821
|
+
inst.startsWith = (...args2) => inst.check(_startsWith(...args2));
|
|
16822
|
+
inst.endsWith = (...args2) => inst.check(_endsWith(...args2));
|
|
16823
|
+
inst.min = (...args2) => inst.check(_minLength(...args2));
|
|
16824
|
+
inst.max = (...args2) => inst.check(_maxLength(...args2));
|
|
16825
|
+
inst.length = (...args2) => inst.check(_length(...args2));
|
|
16826
|
+
inst.nonempty = (...args2) => inst.check(_minLength(1, ...args2));
|
|
15421
16827
|
inst.lowercase = (params) => inst.check(_lowercase(params));
|
|
15422
16828
|
inst.uppercase = (params) => inst.check(_uppercase(params));
|
|
15423
16829
|
inst.trim = () => inst.check(_trim());
|
|
15424
|
-
inst.normalize = (...
|
|
16830
|
+
inst.normalize = (...args2) => inst.check(_normalize(...args2));
|
|
15425
16831
|
inst.toLowerCase = () => inst.check(_toLowerCase());
|
|
15426
16832
|
inst.toUpperCase = () => inst.check(_toUpperCase());
|
|
15427
16833
|
});
|
|
@@ -15631,8 +17037,8 @@ var ZodObject2 = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
|
|
|
15631
17037
|
inst.merge = (other) => util_exports.merge(inst, other);
|
|
15632
17038
|
inst.pick = (mask) => util_exports.pick(inst, mask);
|
|
15633
17039
|
inst.omit = (mask) => util_exports.omit(inst, mask);
|
|
15634
|
-
inst.partial = (...
|
|
15635
|
-
inst.required = (...
|
|
17040
|
+
inst.partial = (...args2) => util_exports.partial(ZodOptional2, inst, args2[0]);
|
|
17041
|
+
inst.required = (...args2) => util_exports.required(ZodNonOptional, inst, args2[0]);
|
|
15636
17042
|
});
|
|
15637
17043
|
function object2(shape, params) {
|
|
15638
17044
|
const def = {
|
|
@@ -18577,8 +19983,8 @@ var parseReadonlyDef = (def, refs) => {
|
|
|
18577
19983
|
};
|
|
18578
19984
|
|
|
18579
19985
|
// node_modules/zod-to-json-schema/dist/esm/selectParser.js
|
|
18580
|
-
var selectParser = (def,
|
|
18581
|
-
switch (
|
|
19986
|
+
var selectParser = (def, typeName2, refs) => {
|
|
19987
|
+
switch (typeName2) {
|
|
18582
19988
|
case ZodFirstPartyTypeKind.ZodString:
|
|
18583
19989
|
return parseStringDef(def, refs);
|
|
18584
19990
|
case ZodFirstPartyTypeKind.ZodNumber:
|
|
@@ -18648,7 +20054,7 @@ var selectParser = (def, typeName, refs) => {
|
|
|
18648
20054
|
case ZodFirstPartyTypeKind.ZodSymbol:
|
|
18649
20055
|
return void 0;
|
|
18650
20056
|
default:
|
|
18651
|
-
return /* @__PURE__ */ ((_) => void 0)(
|
|
20057
|
+
return /* @__PURE__ */ ((_) => void 0)(typeName2);
|
|
18652
20058
|
}
|
|
18653
20059
|
};
|
|
18654
20060
|
|
|
@@ -18861,10 +20267,10 @@ var Protocol = class {
|
|
|
18861
20267
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
18862
20268
|
if (queuedMessage.type === "response" || queuedMessage.type === "error") {
|
|
18863
20269
|
const message = queuedMessage.message;
|
|
18864
|
-
const
|
|
18865
|
-
const resolver = this._requestResolvers.get(
|
|
20270
|
+
const requestId2 = message.id;
|
|
20271
|
+
const resolver = this._requestResolvers.get(requestId2);
|
|
18866
20272
|
if (resolver) {
|
|
18867
|
-
this._requestResolvers.delete(
|
|
20273
|
+
this._requestResolvers.delete(requestId2);
|
|
18868
20274
|
if (queuedMessage.type === "response") {
|
|
18869
20275
|
resolver(message);
|
|
18870
20276
|
} else {
|
|
@@ -18874,7 +20280,7 @@ var Protocol = class {
|
|
|
18874
20280
|
}
|
|
18875
20281
|
} else {
|
|
18876
20282
|
const messageType = queuedMessage.type === "response" ? "Response" : "Error";
|
|
18877
|
-
this._onerror(new Error(`${messageType} handler missing for request ${
|
|
20283
|
+
this._onerror(new Error(`${messageType} handler missing for request ${requestId2}`));
|
|
18878
20284
|
}
|
|
18879
20285
|
continue;
|
|
18880
20286
|
}
|
|
@@ -19583,26 +20989,26 @@ var Protocol = class {
|
|
|
19583
20989
|
*
|
|
19584
20990
|
* Note that this will replace any previous request handler for the same method.
|
|
19585
20991
|
*/
|
|
19586
|
-
setRequestHandler(
|
|
19587
|
-
const
|
|
19588
|
-
this.assertRequestHandlerCapability(
|
|
19589
|
-
this._requestHandlers.set(
|
|
19590
|
-
const parsed = parseWithCompat(
|
|
20992
|
+
setRequestHandler(requestSchema2, handler) {
|
|
20993
|
+
const method2 = getMethodLiteral(requestSchema2);
|
|
20994
|
+
this.assertRequestHandlerCapability(method2);
|
|
20995
|
+
this._requestHandlers.set(method2, (request, extra) => {
|
|
20996
|
+
const parsed = parseWithCompat(requestSchema2, request);
|
|
19591
20997
|
return Promise.resolve(handler(parsed, extra));
|
|
19592
20998
|
});
|
|
19593
20999
|
}
|
|
19594
21000
|
/**
|
|
19595
21001
|
* Removes the request handler for the given method.
|
|
19596
21002
|
*/
|
|
19597
|
-
removeRequestHandler(
|
|
19598
|
-
this._requestHandlers.delete(
|
|
21003
|
+
removeRequestHandler(method2) {
|
|
21004
|
+
this._requestHandlers.delete(method2);
|
|
19599
21005
|
}
|
|
19600
21006
|
/**
|
|
19601
21007
|
* Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
|
|
19602
21008
|
*/
|
|
19603
|
-
assertCanSetRequestHandler(
|
|
19604
|
-
if (this._requestHandlers.has(
|
|
19605
|
-
throw new Error(`A request handler for ${
|
|
21009
|
+
assertCanSetRequestHandler(method2) {
|
|
21010
|
+
if (this._requestHandlers.has(method2)) {
|
|
21011
|
+
throw new Error(`A request handler for ${method2} already exists, which would be overridden`);
|
|
19606
21012
|
}
|
|
19607
21013
|
}
|
|
19608
21014
|
/**
|
|
@@ -19611,8 +21017,8 @@ var Protocol = class {
|
|
|
19611
21017
|
* Note that this will replace any previous notification handler for the same method.
|
|
19612
21018
|
*/
|
|
19613
21019
|
setNotificationHandler(notificationSchema, handler) {
|
|
19614
|
-
const
|
|
19615
|
-
this._notificationHandlers.set(
|
|
21020
|
+
const method2 = getMethodLiteral(notificationSchema);
|
|
21021
|
+
this._notificationHandlers.set(method2, (notification) => {
|
|
19616
21022
|
const parsed = parseWithCompat(notificationSchema, notification);
|
|
19617
21023
|
return Promise.resolve(handler(parsed));
|
|
19618
21024
|
});
|
|
@@ -19620,8 +21026,8 @@ var Protocol = class {
|
|
|
19620
21026
|
/**
|
|
19621
21027
|
* Removes the notification handler for the given method.
|
|
19622
21028
|
*/
|
|
19623
|
-
removeNotificationHandler(
|
|
19624
|
-
this._notificationHandlers.delete(
|
|
21029
|
+
removeNotificationHandler(method2) {
|
|
21030
|
+
this._notificationHandlers.delete(method2);
|
|
19625
21031
|
}
|
|
19626
21032
|
/**
|
|
19627
21033
|
* Cleans up the progress handler associated with a task.
|
|
@@ -19662,13 +21068,13 @@ var Protocol = class {
|
|
|
19662
21068
|
const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId);
|
|
19663
21069
|
for (const message of messages) {
|
|
19664
21070
|
if (message.type === "request" && isJSONRPCRequest(message.message)) {
|
|
19665
|
-
const
|
|
19666
|
-
const resolver = this._requestResolvers.get(
|
|
21071
|
+
const requestId2 = message.message.id;
|
|
21072
|
+
const resolver = this._requestResolvers.get(requestId2);
|
|
19667
21073
|
if (resolver) {
|
|
19668
21074
|
resolver(new McpError(ErrorCode.InternalError, "Task cancelled or completed"));
|
|
19669
|
-
this._requestResolvers.delete(
|
|
21075
|
+
this._requestResolvers.delete(requestId2);
|
|
19670
21076
|
} else {
|
|
19671
|
-
this._onerror(new Error(`Resolver missing for request ${
|
|
21077
|
+
this._onerror(new Error(`Resolver missing for request ${requestId2} during task ${taskId} cleanup`));
|
|
19672
21078
|
}
|
|
19673
21079
|
}
|
|
19674
21080
|
}
|
|
@@ -20071,33 +21477,33 @@ var ExperimentalServerTasks = class {
|
|
|
20071
21477
|
};
|
|
20072
21478
|
|
|
20073
21479
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
20074
|
-
function assertToolsCallTaskCapability(requests,
|
|
21480
|
+
function assertToolsCallTaskCapability(requests, method2, entityName) {
|
|
20075
21481
|
if (!requests) {
|
|
20076
|
-
throw new Error(`${entityName} does not support task creation (required for ${
|
|
21482
|
+
throw new Error(`${entityName} does not support task creation (required for ${method2})`);
|
|
20077
21483
|
}
|
|
20078
|
-
switch (
|
|
21484
|
+
switch (method2) {
|
|
20079
21485
|
case "tools/call":
|
|
20080
21486
|
if (!requests.tools?.call) {
|
|
20081
|
-
throw new Error(`${entityName} does not support task creation for tools/call (required for ${
|
|
21487
|
+
throw new Error(`${entityName} does not support task creation for tools/call (required for ${method2})`);
|
|
20082
21488
|
}
|
|
20083
21489
|
break;
|
|
20084
21490
|
default:
|
|
20085
21491
|
break;
|
|
20086
21492
|
}
|
|
20087
21493
|
}
|
|
20088
|
-
function assertClientRequestTaskCapability(requests,
|
|
21494
|
+
function assertClientRequestTaskCapability(requests, method2, entityName) {
|
|
20089
21495
|
if (!requests) {
|
|
20090
|
-
throw new Error(`${entityName} does not support task creation (required for ${
|
|
21496
|
+
throw new Error(`${entityName} does not support task creation (required for ${method2})`);
|
|
20091
21497
|
}
|
|
20092
|
-
switch (
|
|
21498
|
+
switch (method2) {
|
|
20093
21499
|
case "sampling/createMessage":
|
|
20094
21500
|
if (!requests.sampling?.createMessage) {
|
|
20095
|
-
throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${
|
|
21501
|
+
throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method2})`);
|
|
20096
21502
|
}
|
|
20097
21503
|
break;
|
|
20098
21504
|
case "elicitation/create":
|
|
20099
21505
|
if (!requests.elicitation?.create) {
|
|
20100
|
-
throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${
|
|
21506
|
+
throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method2})`);
|
|
20101
21507
|
}
|
|
20102
21508
|
break;
|
|
20103
21509
|
default:
|
|
@@ -20165,8 +21571,8 @@ var Server = class extends Protocol {
|
|
|
20165
21571
|
/**
|
|
20166
21572
|
* Override request handler registration to enforce server-side validation for tools/call.
|
|
20167
21573
|
*/
|
|
20168
|
-
setRequestHandler(
|
|
20169
|
-
const shape = getObjectShape(
|
|
21574
|
+
setRequestHandler(requestSchema2, handler) {
|
|
21575
|
+
const shape = getObjectShape(requestSchema2);
|
|
20170
21576
|
const methodSchema = shape?.method;
|
|
20171
21577
|
if (!methodSchema) {
|
|
20172
21578
|
throw new Error("Schema is missing a method literal");
|
|
@@ -20175,8 +21581,8 @@ var Server = class extends Protocol {
|
|
|
20175
21581
|
if (typeof methodValue !== "string") {
|
|
20176
21582
|
throw new Error("Schema method literal must be a string");
|
|
20177
21583
|
}
|
|
20178
|
-
const
|
|
20179
|
-
if (
|
|
21584
|
+
const method2 = methodValue;
|
|
21585
|
+
if (method2 === "tools/call") {
|
|
20180
21586
|
const wrappedHandler = async (request, extra) => {
|
|
20181
21587
|
const validatedRequest = safeParse2(CallToolRequestSchema, request);
|
|
20182
21588
|
if (!validatedRequest.success) {
|
|
@@ -20200,57 +21606,57 @@ var Server = class extends Protocol {
|
|
|
20200
21606
|
}
|
|
20201
21607
|
return validationResult.data;
|
|
20202
21608
|
};
|
|
20203
|
-
return super.setRequestHandler(
|
|
21609
|
+
return super.setRequestHandler(requestSchema2, wrappedHandler);
|
|
20204
21610
|
}
|
|
20205
|
-
return super.setRequestHandler(
|
|
21611
|
+
return super.setRequestHandler(requestSchema2, handler);
|
|
20206
21612
|
}
|
|
20207
|
-
assertCapabilityForMethod(
|
|
20208
|
-
switch (
|
|
21613
|
+
assertCapabilityForMethod(method2) {
|
|
21614
|
+
switch (method2) {
|
|
20209
21615
|
case "sampling/createMessage":
|
|
20210
21616
|
if (!this._clientCapabilities?.sampling) {
|
|
20211
|
-
throw new Error(`Client does not support sampling (required for ${
|
|
21617
|
+
throw new Error(`Client does not support sampling (required for ${method2})`);
|
|
20212
21618
|
}
|
|
20213
21619
|
break;
|
|
20214
21620
|
case "elicitation/create":
|
|
20215
21621
|
if (!this._clientCapabilities?.elicitation) {
|
|
20216
|
-
throw new Error(`Client does not support elicitation (required for ${
|
|
21622
|
+
throw new Error(`Client does not support elicitation (required for ${method2})`);
|
|
20217
21623
|
}
|
|
20218
21624
|
break;
|
|
20219
21625
|
case "roots/list":
|
|
20220
21626
|
if (!this._clientCapabilities?.roots) {
|
|
20221
|
-
throw new Error(`Client does not support listing roots (required for ${
|
|
21627
|
+
throw new Error(`Client does not support listing roots (required for ${method2})`);
|
|
20222
21628
|
}
|
|
20223
21629
|
break;
|
|
20224
21630
|
case "ping":
|
|
20225
21631
|
break;
|
|
20226
21632
|
}
|
|
20227
21633
|
}
|
|
20228
|
-
assertNotificationCapability(
|
|
20229
|
-
switch (
|
|
21634
|
+
assertNotificationCapability(method2) {
|
|
21635
|
+
switch (method2) {
|
|
20230
21636
|
case "notifications/message":
|
|
20231
21637
|
if (!this._capabilities.logging) {
|
|
20232
|
-
throw new Error(`Server does not support logging (required for ${
|
|
21638
|
+
throw new Error(`Server does not support logging (required for ${method2})`);
|
|
20233
21639
|
}
|
|
20234
21640
|
break;
|
|
20235
21641
|
case "notifications/resources/updated":
|
|
20236
21642
|
case "notifications/resources/list_changed":
|
|
20237
21643
|
if (!this._capabilities.resources) {
|
|
20238
|
-
throw new Error(`Server does not support notifying about resources (required for ${
|
|
21644
|
+
throw new Error(`Server does not support notifying about resources (required for ${method2})`);
|
|
20239
21645
|
}
|
|
20240
21646
|
break;
|
|
20241
21647
|
case "notifications/tools/list_changed":
|
|
20242
21648
|
if (!this._capabilities.tools) {
|
|
20243
|
-
throw new Error(`Server does not support notifying of tool list changes (required for ${
|
|
21649
|
+
throw new Error(`Server does not support notifying of tool list changes (required for ${method2})`);
|
|
20244
21650
|
}
|
|
20245
21651
|
break;
|
|
20246
21652
|
case "notifications/prompts/list_changed":
|
|
20247
21653
|
if (!this._capabilities.prompts) {
|
|
20248
|
-
throw new Error(`Server does not support notifying of prompt list changes (required for ${
|
|
21654
|
+
throw new Error(`Server does not support notifying of prompt list changes (required for ${method2})`);
|
|
20249
21655
|
}
|
|
20250
21656
|
break;
|
|
20251
21657
|
case "notifications/elicitation/complete":
|
|
20252
21658
|
if (!this._clientCapabilities?.elicitation?.url) {
|
|
20253
|
-
throw new Error(`Client does not support URL elicitation (required for ${
|
|
21659
|
+
throw new Error(`Client does not support URL elicitation (required for ${method2})`);
|
|
20254
21660
|
}
|
|
20255
21661
|
break;
|
|
20256
21662
|
case "notifications/cancelled":
|
|
@@ -20259,38 +21665,38 @@ var Server = class extends Protocol {
|
|
|
20259
21665
|
break;
|
|
20260
21666
|
}
|
|
20261
21667
|
}
|
|
20262
|
-
assertRequestHandlerCapability(
|
|
21668
|
+
assertRequestHandlerCapability(method2) {
|
|
20263
21669
|
if (!this._capabilities) {
|
|
20264
21670
|
return;
|
|
20265
21671
|
}
|
|
20266
|
-
switch (
|
|
21672
|
+
switch (method2) {
|
|
20267
21673
|
case "completion/complete":
|
|
20268
21674
|
if (!this._capabilities.completions) {
|
|
20269
|
-
throw new Error(`Server does not support completions (required for ${
|
|
21675
|
+
throw new Error(`Server does not support completions (required for ${method2})`);
|
|
20270
21676
|
}
|
|
20271
21677
|
break;
|
|
20272
21678
|
case "logging/setLevel":
|
|
20273
21679
|
if (!this._capabilities.logging) {
|
|
20274
|
-
throw new Error(`Server does not support logging (required for ${
|
|
21680
|
+
throw new Error(`Server does not support logging (required for ${method2})`);
|
|
20275
21681
|
}
|
|
20276
21682
|
break;
|
|
20277
21683
|
case "prompts/get":
|
|
20278
21684
|
case "prompts/list":
|
|
20279
21685
|
if (!this._capabilities.prompts) {
|
|
20280
|
-
throw new Error(`Server does not support prompts (required for ${
|
|
21686
|
+
throw new Error(`Server does not support prompts (required for ${method2})`);
|
|
20281
21687
|
}
|
|
20282
21688
|
break;
|
|
20283
21689
|
case "resources/list":
|
|
20284
21690
|
case "resources/templates/list":
|
|
20285
21691
|
case "resources/read":
|
|
20286
21692
|
if (!this._capabilities.resources) {
|
|
20287
|
-
throw new Error(`Server does not support resources (required for ${
|
|
21693
|
+
throw new Error(`Server does not support resources (required for ${method2})`);
|
|
20288
21694
|
}
|
|
20289
21695
|
break;
|
|
20290
21696
|
case "tools/call":
|
|
20291
21697
|
case "tools/list":
|
|
20292
21698
|
if (!this._capabilities.tools) {
|
|
20293
|
-
throw new Error(`Server does not support tools (required for ${
|
|
21699
|
+
throw new Error(`Server does not support tools (required for ${method2})`);
|
|
20294
21700
|
}
|
|
20295
21701
|
break;
|
|
20296
21702
|
case "tasks/get":
|
|
@@ -20298,7 +21704,7 @@ var Server = class extends Protocol {
|
|
|
20298
21704
|
case "tasks/result":
|
|
20299
21705
|
case "tasks/cancel":
|
|
20300
21706
|
if (!this._capabilities.tasks) {
|
|
20301
|
-
throw new Error(`Server does not support tasks capability (required for ${
|
|
21707
|
+
throw new Error(`Server does not support tasks capability (required for ${method2})`);
|
|
20302
21708
|
}
|
|
20303
21709
|
break;
|
|
20304
21710
|
case "ping":
|
|
@@ -20306,14 +21712,14 @@ var Server = class extends Protocol {
|
|
|
20306
21712
|
break;
|
|
20307
21713
|
}
|
|
20308
21714
|
}
|
|
20309
|
-
assertTaskCapability(
|
|
20310
|
-
assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests,
|
|
21715
|
+
assertTaskCapability(method2) {
|
|
21716
|
+
assertClientRequestTaskCapability(this._clientCapabilities?.tasks?.requests, method2, "Client");
|
|
20311
21717
|
}
|
|
20312
|
-
assertTaskHandlerCapability(
|
|
21718
|
+
assertTaskHandlerCapability(method2) {
|
|
20313
21719
|
if (!this._capabilities) {
|
|
20314
21720
|
return;
|
|
20315
21721
|
}
|
|
20316
|
-
assertToolsCallTaskCapability(this._capabilities.tasks?.requests,
|
|
21722
|
+
assertToolsCallTaskCapability(this._capabilities.tasks?.requests, method2, "Server");
|
|
20317
21723
|
}
|
|
20318
21724
|
async _oninitialize(request) {
|
|
20319
21725
|
const requestedVersion = request.params.protocolVersion;
|
|
@@ -20612,6 +22018,15 @@ var McpServer = class {
|
|
|
20612
22018
|
this._promptHandlersInitialized = false;
|
|
20613
22019
|
this.server = new Server(serverInfo, options);
|
|
20614
22020
|
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
22021
|
+
if (options?.capabilities?.tools) {
|
|
22022
|
+
this.setToolRequestHandlers();
|
|
22023
|
+
}
|
|
22024
|
+
if (options?.capabilities?.resources) {
|
|
22025
|
+
this.setResourceRequestHandlers();
|
|
22026
|
+
}
|
|
22027
|
+
if (options?.capabilities?.prompts) {
|
|
22028
|
+
this.setPromptRequestHandlers();
|
|
22029
|
+
}
|
|
20615
22030
|
}
|
|
20616
22031
|
/**
|
|
20617
22032
|
* Access experimental features.
|
|
@@ -20703,8 +22118,8 @@ var McpServer = class {
|
|
|
20703
22118
|
if (taskSupport === "optional" && !isTaskRequest && isTaskHandler) {
|
|
20704
22119
|
return await this.handleAutomaticTaskPolling(tool, request, extra);
|
|
20705
22120
|
}
|
|
20706
|
-
const
|
|
20707
|
-
const result = await this.executeToolHandler(tool,
|
|
22121
|
+
const args2 = await this.validateToolInput(tool, request.params.arguments, request.params.name);
|
|
22122
|
+
const result = await this.executeToolHandler(tool, args2, extra);
|
|
20708
22123
|
if (isTaskRequest) {
|
|
20709
22124
|
return result;
|
|
20710
22125
|
}
|
|
@@ -20741,27 +22156,27 @@ var McpServer = class {
|
|
|
20741
22156
|
/**
|
|
20742
22157
|
* Validates tool input arguments against the tool's input schema.
|
|
20743
22158
|
*/
|
|
20744
|
-
async validateToolInput(tool,
|
|
20745
|
-
if (this._maxToolInputElements !== void 0 && toolInputElementCount(
|
|
20746
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${
|
|
22159
|
+
async validateToolInput(tool, args2, toolName2) {
|
|
22160
|
+
if (this._maxToolInputElements !== void 0 && toolInputElementCount(args2, this._maxToolInputElements) > this._maxToolInputElements) {
|
|
22161
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName2}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
20747
22162
|
}
|
|
20748
22163
|
if (!tool.inputSchema) {
|
|
20749
22164
|
return void 0;
|
|
20750
22165
|
}
|
|
20751
22166
|
const inputObj = normalizeObjectSchema(tool.inputSchema);
|
|
20752
22167
|
const schemaToParse = inputObj ?? tool.inputSchema;
|
|
20753
|
-
const parseResult = await safeParseAsync2(schemaToParse,
|
|
22168
|
+
const parseResult = await safeParseAsync2(schemaToParse, args2 ?? {});
|
|
20754
22169
|
if (!parseResult.success) {
|
|
20755
22170
|
const error2 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
20756
22171
|
const errorMessage = getParseErrorMessage(error2);
|
|
20757
|
-
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${
|
|
22172
|
+
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName2}: ${errorMessage}`);
|
|
20758
22173
|
}
|
|
20759
22174
|
return parseResult.data;
|
|
20760
22175
|
}
|
|
20761
22176
|
/**
|
|
20762
22177
|
* Validates tool output against the tool's output schema.
|
|
20763
22178
|
*/
|
|
20764
|
-
async validateToolOutput(tool, result,
|
|
22179
|
+
async validateToolOutput(tool, result, toolName2) {
|
|
20765
22180
|
if (!tool.outputSchema) {
|
|
20766
22181
|
return;
|
|
20767
22182
|
}
|
|
@@ -20772,20 +22187,20 @@ var McpServer = class {
|
|
|
20772
22187
|
return;
|
|
20773
22188
|
}
|
|
20774
22189
|
if (!result.structuredContent) {
|
|
20775
|
-
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Tool ${
|
|
22190
|
+
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Tool ${toolName2} has an output schema but no structured content was provided`);
|
|
20776
22191
|
}
|
|
20777
22192
|
const outputObj = normalizeObjectSchema(tool.outputSchema);
|
|
20778
22193
|
const parseResult = await safeParseAsync2(outputObj, result.structuredContent);
|
|
20779
22194
|
if (!parseResult.success) {
|
|
20780
22195
|
const error2 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
20781
22196
|
const errorMessage = getParseErrorMessage(error2);
|
|
20782
|
-
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${
|
|
22197
|
+
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName2}: ${errorMessage}`);
|
|
20783
22198
|
}
|
|
20784
22199
|
}
|
|
20785
22200
|
/**
|
|
20786
22201
|
* Executes a tool handler (either regular or task-based).
|
|
20787
22202
|
*/
|
|
20788
|
-
async executeToolHandler(tool,
|
|
22203
|
+
async executeToolHandler(tool, args2, extra) {
|
|
20789
22204
|
const handler = tool.handler;
|
|
20790
22205
|
const isTaskHandler = "createTask" in handler;
|
|
20791
22206
|
if (isTaskHandler) {
|
|
@@ -20795,7 +22210,7 @@ var McpServer = class {
|
|
|
20795
22210
|
const taskExtra = { ...extra, taskStore: extra.taskStore };
|
|
20796
22211
|
if (tool.inputSchema) {
|
|
20797
22212
|
const typedHandler = handler;
|
|
20798
|
-
return await Promise.resolve(typedHandler.createTask(
|
|
22213
|
+
return await Promise.resolve(typedHandler.createTask(args2, taskExtra));
|
|
20799
22214
|
} else {
|
|
20800
22215
|
const typedHandler = handler;
|
|
20801
22216
|
return await Promise.resolve(typedHandler.createTask(taskExtra));
|
|
@@ -20803,7 +22218,7 @@ var McpServer = class {
|
|
|
20803
22218
|
}
|
|
20804
22219
|
if (tool.inputSchema) {
|
|
20805
22220
|
const typedHandler = handler;
|
|
20806
|
-
return await Promise.resolve(typedHandler(
|
|
22221
|
+
return await Promise.resolve(typedHandler(args2, extra));
|
|
20807
22222
|
} else {
|
|
20808
22223
|
const typedHandler = handler;
|
|
20809
22224
|
return await Promise.resolve(typedHandler(extra));
|
|
@@ -20816,10 +22231,10 @@ var McpServer = class {
|
|
|
20816
22231
|
if (!extra.taskStore) {
|
|
20817
22232
|
throw new Error("No task store provided for task-capable tool.");
|
|
20818
22233
|
}
|
|
20819
|
-
const
|
|
22234
|
+
const args2 = await this.validateToolInput(tool, request.params.arguments, request.params.name);
|
|
20820
22235
|
const handler = tool.handler;
|
|
20821
22236
|
const taskExtra = { ...extra, taskStore: extra.taskStore };
|
|
20822
|
-
const createTaskResult =
|
|
22237
|
+
const createTaskResult = args2 ? await Promise.resolve(handler.createTask(args2, taskExtra)) : (
|
|
20823
22238
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20824
22239
|
await Promise.resolve(handler.createTask(taskExtra))
|
|
20825
22240
|
);
|
|
@@ -20994,9 +22409,9 @@ var McpServer = class {
|
|
|
20994
22409
|
const errorMessage = getParseErrorMessage(error2);
|
|
20995
22410
|
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request.params.name}: ${errorMessage}`);
|
|
20996
22411
|
}
|
|
20997
|
-
const
|
|
22412
|
+
const args2 = parseResult.data;
|
|
20998
22413
|
const cb = prompt.callback;
|
|
20999
|
-
return await Promise.resolve(cb(
|
|
22414
|
+
return await Promise.resolve(cb(args2, extra));
|
|
21000
22415
|
} else {
|
|
21001
22416
|
const cb = prompt.callback;
|
|
21002
22417
|
return await Promise.resolve(cb(extra));
|
|
@@ -21286,654 +22701,408 @@ var McpServer = class {
|
|
|
21286
22701
|
}
|
|
21287
22702
|
/**
|
|
21288
22703
|
* Sends a logging message to the client, if connected.
|
|
21289
|
-
* Note: You only need to send the parameters object, not the entire JSON RPC message
|
|
21290
|
-
* @see LoggingMessageNotification
|
|
21291
|
-
* @param params
|
|
21292
|
-
* @param sessionId optional for stateless and backward compatibility
|
|
21293
|
-
*/
|
|
21294
|
-
async sendLoggingMessage(params, sessionId) {
|
|
21295
|
-
return this.server.sendLoggingMessage(params, sessionId);
|
|
21296
|
-
}
|
|
21297
|
-
/**
|
|
21298
|
-
* Sends a resource list changed event to the client, if connected.
|
|
21299
|
-
*/
|
|
21300
|
-
sendResourceListChanged() {
|
|
21301
|
-
if (this.isConnected()) {
|
|
21302
|
-
this.server.sendResourceListChanged();
|
|
21303
|
-
}
|
|
21304
|
-
}
|
|
21305
|
-
/**
|
|
21306
|
-
* Sends a tool list changed event to the client, if connected.
|
|
21307
|
-
*/
|
|
21308
|
-
sendToolListChanged() {
|
|
21309
|
-
if (this.isConnected()) {
|
|
21310
|
-
this.server.sendToolListChanged();
|
|
21311
|
-
}
|
|
21312
|
-
}
|
|
21313
|
-
/**
|
|
21314
|
-
* Sends a prompt list changed event to the client, if connected.
|
|
21315
|
-
*/
|
|
21316
|
-
sendPromptListChanged() {
|
|
21317
|
-
if (this.isConnected()) {
|
|
21318
|
-
this.server.sendPromptListChanged();
|
|
21319
|
-
}
|
|
21320
|
-
}
|
|
21321
|
-
};
|
|
21322
|
-
var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
21323
|
-
type: "object",
|
|
21324
|
-
properties: {}
|
|
21325
|
-
};
|
|
21326
|
-
function isZodTypeLike(value) {
|
|
21327
|
-
return value !== null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "safeParse" in value && typeof value.safeParse === "function";
|
|
21328
|
-
}
|
|
21329
|
-
function isZodSchemaInstance(obj) {
|
|
21330
|
-
return "_def" in obj || "_zod" in obj || isZodTypeLike(obj);
|
|
21331
|
-
}
|
|
21332
|
-
function isZodRawShapeCompat(obj) {
|
|
21333
|
-
if (typeof obj !== "object" || obj === null) {
|
|
21334
|
-
return false;
|
|
21335
|
-
}
|
|
21336
|
-
if (isZodSchemaInstance(obj)) {
|
|
21337
|
-
return false;
|
|
21338
|
-
}
|
|
21339
|
-
if (Object.keys(obj).length === 0) {
|
|
21340
|
-
return true;
|
|
21341
|
-
}
|
|
21342
|
-
return Object.values(obj).some(isZodTypeLike);
|
|
21343
|
-
}
|
|
21344
|
-
function getZodSchemaObject(schema) {
|
|
21345
|
-
if (!schema) {
|
|
21346
|
-
return void 0;
|
|
21347
|
-
}
|
|
21348
|
-
if (isZodRawShapeCompat(schema)) {
|
|
21349
|
-
return objectFromShape(schema);
|
|
21350
|
-
}
|
|
21351
|
-
if (!isZodSchemaInstance(schema)) {
|
|
21352
|
-
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
21353
|
-
}
|
|
21354
|
-
return schema;
|
|
21355
|
-
}
|
|
21356
|
-
function promptArgumentsFromSchema(schema) {
|
|
21357
|
-
const shape = getObjectShape(schema);
|
|
21358
|
-
if (!shape)
|
|
21359
|
-
return [];
|
|
21360
|
-
return Object.entries(shape).map(([name, field]) => {
|
|
21361
|
-
const description = getSchemaDescription(field);
|
|
21362
|
-
const isOptional = isSchemaOptional(field);
|
|
21363
|
-
return {
|
|
21364
|
-
name,
|
|
21365
|
-
description,
|
|
21366
|
-
required: !isOptional
|
|
21367
|
-
};
|
|
21368
|
-
});
|
|
21369
|
-
}
|
|
21370
|
-
function getMethodValue(schema) {
|
|
21371
|
-
const shape = getObjectShape(schema);
|
|
21372
|
-
const methodSchema = shape?.method;
|
|
21373
|
-
if (!methodSchema) {
|
|
21374
|
-
throw new Error("Schema is missing a method literal");
|
|
21375
|
-
}
|
|
21376
|
-
const value = getLiteralValue(methodSchema);
|
|
21377
|
-
if (typeof value === "string") {
|
|
21378
|
-
return value;
|
|
21379
|
-
}
|
|
21380
|
-
throw new Error("Schema method literal must be a string");
|
|
21381
|
-
}
|
|
21382
|
-
function createCompletionResult(suggestions) {
|
|
21383
|
-
return {
|
|
21384
|
-
completion: {
|
|
21385
|
-
values: suggestions.slice(0, 100),
|
|
21386
|
-
total: suggestions.length,
|
|
21387
|
-
hasMore: suggestions.length > 100
|
|
21388
|
-
}
|
|
21389
|
-
};
|
|
21390
|
-
}
|
|
21391
|
-
var EMPTY_COMPLETION_RESULT = {
|
|
21392
|
-
completion: {
|
|
21393
|
-
values: [],
|
|
21394
|
-
hasMore: false
|
|
21395
|
-
}
|
|
21396
|
-
};
|
|
21397
|
-
|
|
21398
|
-
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
21399
|
-
import process2 from "node:process";
|
|
21400
|
-
|
|
21401
|
-
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
21402
|
-
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
21403
|
-
var ReadBuffer = class {
|
|
21404
|
-
constructor(options) {
|
|
21405
|
-
this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
|
|
21406
|
-
}
|
|
21407
|
-
append(chunk) {
|
|
21408
|
-
const newSize = (this._buffer?.length ?? 0) + chunk.length;
|
|
21409
|
-
if (newSize > this._maxBufferSize) {
|
|
21410
|
-
this.clear();
|
|
21411
|
-
throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
|
|
21412
|
-
}
|
|
21413
|
-
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
21414
|
-
}
|
|
21415
|
-
readMessage() {
|
|
21416
|
-
if (!this._buffer) {
|
|
21417
|
-
return null;
|
|
21418
|
-
}
|
|
21419
|
-
const index = this._buffer.indexOf("\n");
|
|
21420
|
-
if (index === -1) {
|
|
21421
|
-
return null;
|
|
21422
|
-
}
|
|
21423
|
-
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
21424
|
-
this._buffer = this._buffer.subarray(index + 1);
|
|
21425
|
-
return deserializeMessage(line);
|
|
21426
|
-
}
|
|
21427
|
-
clear() {
|
|
21428
|
-
this._buffer = void 0;
|
|
21429
|
-
}
|
|
21430
|
-
};
|
|
21431
|
-
function deserializeMessage(line) {
|
|
21432
|
-
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
21433
|
-
}
|
|
21434
|
-
function serializeMessage(message) {
|
|
21435
|
-
return JSON.stringify(message) + "\n";
|
|
21436
|
-
}
|
|
21437
|
-
|
|
21438
|
-
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
21439
|
-
var StdioServerTransport = class {
|
|
21440
|
-
constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
|
|
21441
|
-
this._stdin = _stdin;
|
|
21442
|
-
this._stdout = _stdout;
|
|
21443
|
-
this._started = false;
|
|
21444
|
-
this._ondata = (chunk) => {
|
|
21445
|
-
try {
|
|
21446
|
-
this._readBuffer.append(chunk);
|
|
21447
|
-
this.processReadBuffer();
|
|
21448
|
-
} catch (error2) {
|
|
21449
|
-
this.onerror?.(error2);
|
|
21450
|
-
this.close().catch(() => {
|
|
21451
|
-
});
|
|
21452
|
-
}
|
|
21453
|
-
};
|
|
21454
|
-
this._onerror = (error2) => {
|
|
21455
|
-
this.onerror?.(error2);
|
|
21456
|
-
};
|
|
21457
|
-
this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
|
|
22704
|
+
* Note: You only need to send the parameters object, not the entire JSON RPC message
|
|
22705
|
+
* @see LoggingMessageNotification
|
|
22706
|
+
* @param params
|
|
22707
|
+
* @param sessionId optional for stateless and backward compatibility
|
|
22708
|
+
*/
|
|
22709
|
+
async sendLoggingMessage(params, sessionId) {
|
|
22710
|
+
return this.server.sendLoggingMessage(params, sessionId);
|
|
21458
22711
|
}
|
|
21459
22712
|
/**
|
|
21460
|
-
*
|
|
22713
|
+
* Sends a resource list changed event to the client, if connected.
|
|
21461
22714
|
*/
|
|
21462
|
-
|
|
21463
|
-
if (this.
|
|
21464
|
-
|
|
22715
|
+
sendResourceListChanged() {
|
|
22716
|
+
if (this.isConnected()) {
|
|
22717
|
+
this.server.sendResourceListChanged();
|
|
21465
22718
|
}
|
|
21466
|
-
this._started = true;
|
|
21467
|
-
this._stdin.on("data", this._ondata);
|
|
21468
|
-
this._stdin.on("error", this._onerror);
|
|
21469
22719
|
}
|
|
21470
|
-
|
|
21471
|
-
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
}
|
|
21477
|
-
this.onmessage?.(message);
|
|
21478
|
-
} catch (error2) {
|
|
21479
|
-
this.onerror?.(error2);
|
|
21480
|
-
}
|
|
22720
|
+
/**
|
|
22721
|
+
* Sends a tool list changed event to the client, if connected.
|
|
22722
|
+
*/
|
|
22723
|
+
sendToolListChanged() {
|
|
22724
|
+
if (this.isConnected()) {
|
|
22725
|
+
this.server.sendToolListChanged();
|
|
21481
22726
|
}
|
|
21482
22727
|
}
|
|
21483
|
-
|
|
21484
|
-
|
|
21485
|
-
|
|
21486
|
-
|
|
21487
|
-
if (
|
|
21488
|
-
this.
|
|
22728
|
+
/**
|
|
22729
|
+
* Sends a prompt list changed event to the client, if connected.
|
|
22730
|
+
*/
|
|
22731
|
+
sendPromptListChanged() {
|
|
22732
|
+
if (this.isConnected()) {
|
|
22733
|
+
this.server.sendPromptListChanged();
|
|
21489
22734
|
}
|
|
21490
|
-
this._readBuffer.clear();
|
|
21491
|
-
this.onclose?.();
|
|
21492
|
-
}
|
|
21493
|
-
send(message) {
|
|
21494
|
-
return new Promise((resolve) => {
|
|
21495
|
-
const json = serializeMessage(message);
|
|
21496
|
-
if (this._stdout.write(json)) {
|
|
21497
|
-
resolve();
|
|
21498
|
-
} else {
|
|
21499
|
-
this._stdout.once("drain", resolve);
|
|
21500
|
-
}
|
|
21501
|
-
});
|
|
21502
22735
|
}
|
|
21503
22736
|
};
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
|
|
21507
|
-
var defaultAppData = process.platform === "win32" ? process.env.APPDATA || join(homedir(), "AppData", "Roaming") : process.platform === "darwin" ? join(homedir(), "Library", "Application Support") : process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
21508
|
-
var dataDirectory = process.env.API_DOCS_USER_DATA_DIR || join(defaultAppData, appName);
|
|
21509
|
-
var databasePath = join(dataDirectory, "workspace.sqlite");
|
|
21510
|
-
var plans = /* @__PURE__ */ new Map();
|
|
21511
|
-
var localDatabase;
|
|
21512
|
-
var bodyModes = ["form-data", "urlencoded", "graphql", "json", "xml", "yaml", "edn", "text", "other", "file", "none"];
|
|
21513
|
-
var authSchema = external_exports.discriminatedUnion("type", [
|
|
21514
|
-
external_exports.object({ type: external_exports.literal("none") }),
|
|
21515
|
-
external_exports.object({ type: external_exports.literal("bearer"), token: external_exports.string().max(65536) }),
|
|
21516
|
-
external_exports.object({ type: external_exports.literal("basic"), username: external_exports.string().max(8192), password: external_exports.string().max(65536) }),
|
|
21517
|
-
external_exports.object({ type: external_exports.literal("api-key"), name: external_exports.string().max(8192), value: external_exports.string().max(65536), location: external_exports.enum(["header", "query"]) })
|
|
21518
|
-
]);
|
|
21519
|
-
var fieldSchema = external_exports.object({
|
|
21520
|
-
id: external_exports.string().optional(),
|
|
21521
|
-
name: external_exports.string().max(8192),
|
|
21522
|
-
value: external_exports.string().max(65536),
|
|
21523
|
-
enabled: external_exports.boolean().default(true),
|
|
21524
|
-
description: external_exports.string().max(4096).optional()
|
|
21525
|
-
});
|
|
21526
|
-
var bodyFieldSchema = external_exports.object({
|
|
21527
|
-
id: external_exports.string().optional(),
|
|
21528
|
-
name: external_exports.string().max(8192),
|
|
21529
|
-
value: external_exports.string().max(65536),
|
|
21530
|
-
enabled: external_exports.boolean().default(true),
|
|
21531
|
-
type: external_exports.enum(["text", "file"]).default("text"),
|
|
21532
|
-
fileName: external_exports.string().max(1024).optional()
|
|
21533
|
-
});
|
|
21534
|
-
var responseContentSchema = external_exports.object({
|
|
21535
|
-
id: external_exports.string().optional(),
|
|
21536
|
-
mediaType: external_exports.string().max(160),
|
|
21537
|
-
schema: external_exports.string().max(1e6),
|
|
21538
|
-
example: external_exports.string().max(1e6)
|
|
21539
|
-
});
|
|
21540
|
-
var responseDefinitionSchema = external_exports.object({
|
|
21541
|
-
id: external_exports.string().optional(),
|
|
21542
|
-
statusCode: external_exports.string().trim().min(1).max(12),
|
|
21543
|
-
description: external_exports.string().max(500),
|
|
21544
|
-
content: external_exports.array(responseContentSchema).max(20)
|
|
21545
|
-
});
|
|
21546
|
-
var requestShape = {
|
|
21547
|
-
name: external_exports.string().trim().min(1).max(160),
|
|
21548
|
-
method: external_exports.string().trim().min(1).max(32),
|
|
21549
|
-
url: external_exports.string().max(8192),
|
|
21550
|
-
body: external_exports.string().max(1e6).optional(),
|
|
21551
|
-
bodyMode: external_exports.enum(bodyModes).optional(),
|
|
21552
|
-
bodyFields: external_exports.array(bodyFieldSchema).max(100).optional(),
|
|
21553
|
-
bodyVariables: external_exports.string().max(1e6).optional(),
|
|
21554
|
-
bodyMimeType: external_exports.string().max(1024).optional(),
|
|
21555
|
-
bodyFileName: external_exports.string().max(1024).optional(),
|
|
21556
|
-
headers: external_exports.array(fieldSchema).max(100).optional(),
|
|
21557
|
-
params: external_exports.array(fieldSchema).max(100).optional(),
|
|
21558
|
-
pathParams: external_exports.array(fieldSchema).max(100).optional(),
|
|
21559
|
-
auth: authSchema.optional(),
|
|
21560
|
-
documentation: external_exports.string().max(1e5).optional(),
|
|
21561
|
-
responses: external_exports.array(responseDefinitionSchema).max(100).optional(),
|
|
21562
|
-
deprecated: external_exports.boolean().optional(),
|
|
21563
|
-
deprecationReason: external_exports.string().max(4096).optional()
|
|
22737
|
+
var EMPTY_OBJECT_JSON_SCHEMA = {
|
|
22738
|
+
type: "object",
|
|
22739
|
+
properties: {}
|
|
21564
22740
|
};
|
|
21565
|
-
|
|
21566
|
-
|
|
21567
|
-
external_exports.object({ action: external_exports.literal("create_request"), parentId: external_exports.string().nullable().default(null), request: external_exports.object(requestShape).extend({ method: requestShape.method.transform((method) => method.toUpperCase()) }) }),
|
|
21568
|
-
external_exports.object({ action: external_exports.literal("update_request"), requestId: external_exports.string().min(1), patch: external_exports.object({
|
|
21569
|
-
...requestShape,
|
|
21570
|
-
name: requestShape.name.optional(),
|
|
21571
|
-
method: requestShape.method.transform((method) => method.toUpperCase()).optional(),
|
|
21572
|
-
url: requestShape.url.optional()
|
|
21573
|
-
}).partial() }),
|
|
21574
|
-
external_exports.object({ action: external_exports.literal("rename_folder"), folderId: external_exports.string().min(1), name: external_exports.string().trim().min(1).max(160) }),
|
|
21575
|
-
external_exports.object({ action: external_exports.literal("move_node"), nodeId: external_exports.string().min(1), parentId: external_exports.string().nullable().default(null), index: external_exports.number().int().min(0).optional() }),
|
|
21576
|
-
external_exports.object({ action: external_exports.literal("deprecate_request"), requestId: external_exports.string().min(1), deprecated: external_exports.boolean().default(true), reason: external_exports.string().max(4096).optional() }),
|
|
21577
|
-
external_exports.object({ action: external_exports.literal("delete_node"), nodeId: external_exports.string().min(1) })
|
|
21578
|
-
]);
|
|
21579
|
-
function database() {
|
|
21580
|
-
if (!existsSync(databasePath)) {
|
|
21581
|
-
throw new Error(`Workspace database was not found at ${databasePath}. Open API Documentation once to create the local workspace.`);
|
|
21582
|
-
}
|
|
21583
|
-
if (!localDatabase) {
|
|
21584
|
-
localDatabase = new DatabaseSync(databasePath);
|
|
21585
|
-
localDatabase.exec("PRAGMA busy_timeout = 5000;");
|
|
21586
|
-
}
|
|
21587
|
-
return localDatabase;
|
|
21588
|
-
}
|
|
21589
|
-
function jsonResult(value) {
|
|
21590
|
-
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
|
|
21591
|
-
}
|
|
21592
|
-
function loadRawWorkspace(workspaceId) {
|
|
21593
|
-
const row = database().prepare("SELECT data FROM workspaces WHERE id = ?").get(workspaceId);
|
|
21594
|
-
if (!row) throw new Error(`Workspace "${workspaceId}" was not found.`);
|
|
21595
|
-
const workspace = JSON.parse(row.data);
|
|
21596
|
-
if (!Array.isArray(workspace.tree)) throw new Error("Workspace collection data is invalid.");
|
|
21597
|
-
return { raw: row.data, workspace };
|
|
21598
|
-
}
|
|
21599
|
-
function assertCanEdit(workspace) {
|
|
21600
|
-
if (workspace.role === "viewer") throw new Error("This workspace is read-only for the current account.");
|
|
22741
|
+
function isZodTypeLike(value) {
|
|
22742
|
+
return value !== null && typeof value === "object" && "parse" in value && typeof value.parse === "function" && "safeParse" in value && typeof value.safeParse === "function";
|
|
21601
22743
|
}
|
|
21602
|
-
function
|
|
21603
|
-
return
|
|
22744
|
+
function isZodSchemaInstance(obj) {
|
|
22745
|
+
return "_def" in obj || "_zod" in obj || isZodTypeLike(obj);
|
|
21604
22746
|
}
|
|
21605
|
-
function
|
|
21606
|
-
|
|
21607
|
-
|
|
21608
|
-
if (isFolder(node)) {
|
|
21609
|
-
const nested = findNode(node.children, id);
|
|
21610
|
-
if (nested) return nested;
|
|
21611
|
-
}
|
|
22747
|
+
function isZodRawShapeCompat(obj) {
|
|
22748
|
+
if (typeof obj !== "object" || obj === null) {
|
|
22749
|
+
return false;
|
|
21612
22750
|
}
|
|
21613
|
-
|
|
21614
|
-
|
|
21615
|
-
function findParentId(nodes, id, parentId = null) {
|
|
21616
|
-
for (const node of nodes) {
|
|
21617
|
-
if (node.id === id) return parentId;
|
|
21618
|
-
if (isFolder(node)) {
|
|
21619
|
-
const nested = findParentId(node.children, id, node.id);
|
|
21620
|
-
if (nested !== void 0) return nested;
|
|
21621
|
-
}
|
|
22751
|
+
if (isZodSchemaInstance(obj)) {
|
|
22752
|
+
return false;
|
|
21622
22753
|
}
|
|
21623
|
-
|
|
21624
|
-
|
|
21625
|
-
function insertNode(nodes, parentId, node, index) {
|
|
21626
|
-
if (parentId === null) {
|
|
21627
|
-
const next = [...nodes];
|
|
21628
|
-
next.splice(index === void 0 ? next.length : Math.min(index, next.length), 0, node);
|
|
21629
|
-
return next;
|
|
22754
|
+
if (Object.keys(obj).length === 0) {
|
|
22755
|
+
return true;
|
|
21630
22756
|
}
|
|
21631
|
-
|
|
21632
|
-
for (let position = 0; position < siblings.length; position += 1) {
|
|
21633
|
-
const child = siblings[position];
|
|
21634
|
-
if (!isFolder(child)) continue;
|
|
21635
|
-
if (child.id === parentId) {
|
|
21636
|
-
const children = [...child.children];
|
|
21637
|
-
children.splice(index === void 0 ? children.length : Math.min(index, children.length), 0, node);
|
|
21638
|
-
const next = [...siblings];
|
|
21639
|
-
next[position] = { ...child, children };
|
|
21640
|
-
return { nodes: next, found: true };
|
|
21641
|
-
}
|
|
21642
|
-
const nested = insertInto(child.children);
|
|
21643
|
-
if (nested.found) {
|
|
21644
|
-
const next = [...siblings];
|
|
21645
|
-
next[position] = { ...child, children: nested.nodes };
|
|
21646
|
-
return { nodes: next, found: true };
|
|
21647
|
-
}
|
|
21648
|
-
}
|
|
21649
|
-
return { nodes: siblings, found: false };
|
|
21650
|
-
};
|
|
21651
|
-
const result = insertInto(nodes);
|
|
21652
|
-
if (!result.found) throw new Error(`Parent folder "${parentId}" was not found.`);
|
|
21653
|
-
return result.nodes;
|
|
22757
|
+
return Object.values(obj).some(isZodTypeLike);
|
|
21654
22758
|
}
|
|
21655
|
-
function
|
|
21656
|
-
|
|
21657
|
-
|
|
21658
|
-
const next = [...nodes];
|
|
21659
|
-
const [removed] = next.splice(directIndex, 1);
|
|
21660
|
-
return { tree: next, removed };
|
|
22759
|
+
function getZodSchemaObject(schema) {
|
|
22760
|
+
if (!schema) {
|
|
22761
|
+
return void 0;
|
|
21661
22762
|
}
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
if (!isFolder(node)) continue;
|
|
21665
|
-
const result = removeNode(node.children, id);
|
|
21666
|
-
if (!result.removed) continue;
|
|
21667
|
-
const next = [...nodes];
|
|
21668
|
-
next[index] = { ...node, children: result.tree };
|
|
21669
|
-
return { tree: next, removed: result.removed };
|
|
22763
|
+
if (isZodRawShapeCompat(schema)) {
|
|
22764
|
+
return objectFromShape(schema);
|
|
21670
22765
|
}
|
|
21671
|
-
|
|
21672
|
-
|
|
21673
|
-
function updateNode(nodes, id, update) {
|
|
21674
|
-
let found = false;
|
|
21675
|
-
const tree = nodes.map((node) => {
|
|
21676
|
-
if (node.id === id) {
|
|
21677
|
-
found = true;
|
|
21678
|
-
return update(node);
|
|
21679
|
-
}
|
|
21680
|
-
if (!isFolder(node)) return node;
|
|
21681
|
-
const nested = updateNode(node.children, id, update);
|
|
21682
|
-
if (!nested.found) return node;
|
|
21683
|
-
found = true;
|
|
21684
|
-
return { ...node, children: nested.tree };
|
|
21685
|
-
});
|
|
21686
|
-
return { tree, found };
|
|
21687
|
-
}
|
|
21688
|
-
function sanitizeUrl(value) {
|
|
21689
|
-
try {
|
|
21690
|
-
const url = new URL(value);
|
|
21691
|
-
if (url.username) url.username = "<redacted>";
|
|
21692
|
-
if (url.password) url.password = "<redacted>";
|
|
21693
|
-
for (const key of [...url.searchParams.keys()]) {
|
|
21694
|
-
if (isSensitiveName(key)) url.searchParams.set(key, "<redacted>");
|
|
21695
|
-
}
|
|
21696
|
-
return url.toString();
|
|
21697
|
-
} catch {
|
|
21698
|
-
return value;
|
|
22766
|
+
if (!isZodSchemaInstance(schema)) {
|
|
22767
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
21699
22768
|
}
|
|
22769
|
+
return schema;
|
|
21700
22770
|
}
|
|
21701
|
-
function
|
|
21702
|
-
|
|
21703
|
-
|
|
21704
|
-
|
|
21705
|
-
|
|
21706
|
-
const
|
|
21707
|
-
const
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
22771
|
+
function promptArgumentsFromSchema(schema) {
|
|
22772
|
+
const shape = getObjectShape(schema);
|
|
22773
|
+
if (!shape)
|
|
22774
|
+
return [];
|
|
22775
|
+
return Object.entries(shape).map(([name, field]) => {
|
|
22776
|
+
const description = getSchemaDescription(field);
|
|
22777
|
+
const isOptional = isSchemaOptional(field);
|
|
22778
|
+
return {
|
|
22779
|
+
name,
|
|
22780
|
+
description,
|
|
22781
|
+
required: !isOptional
|
|
21711
22782
|
};
|
|
21712
|
-
|
|
21713
|
-
|
|
21714
|
-
|
|
22783
|
+
});
|
|
22784
|
+
}
|
|
22785
|
+
function getMethodValue(schema) {
|
|
22786
|
+
const shape = getObjectShape(schema);
|
|
22787
|
+
const methodSchema = shape?.method;
|
|
22788
|
+
if (!methodSchema) {
|
|
22789
|
+
throw new Error("Schema is missing a method literal");
|
|
22790
|
+
}
|
|
22791
|
+
const value = getLiteralValue(methodSchema);
|
|
22792
|
+
if (typeof value === "string") {
|
|
22793
|
+
return value;
|
|
21715
22794
|
}
|
|
22795
|
+
throw new Error("Schema method literal must be a string");
|
|
21716
22796
|
}
|
|
21717
|
-
function
|
|
22797
|
+
function createCompletionResult(suggestions) {
|
|
21718
22798
|
return {
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
...request.openApiSchemas ? { openApiSchemas: JSON.parse(redactBody(JSON.stringify(request.openApiSchemas))) } : {},
|
|
21725
|
-
...request.headers ? { headers: request.headers.map((header) => ({ ...header, value: isSensitiveName(header.name) ? "<redacted>" : header.value })) } : {},
|
|
21726
|
-
...request.params ? { params: request.params.map((param) => ({ ...param, value: isSensitiveName(param.name) ? "<redacted>" : param.value })) } : {},
|
|
21727
|
-
...request.pathParams ? { pathParams: request.pathParams.map((param) => ({ ...param, value: isSensitiveName(param.name) ? "<redacted>" : param.value })) } : {},
|
|
21728
|
-
...request.bodyFields ? { bodyFields: request.bodyFields.map((field) => ({ ...field, value: isSensitiveName(field.name) ? "<redacted>" : field.value, filePath: void 0 })) } : {},
|
|
21729
|
-
...request.auth?.type === "bearer" ? { auth: { type: "bearer", token: "<redacted>" } } : {},
|
|
21730
|
-
...request.auth?.type === "basic" ? { auth: { type: "basic", username: "<redacted>", password: "<redacted>" } } : {},
|
|
21731
|
-
...request.auth?.type === "api-key" ? { auth: { ...request.auth, value: "<redacted>" } } : {},
|
|
21732
|
-
bodyPath: void 0
|
|
22799
|
+
completion: {
|
|
22800
|
+
values: suggestions.slice(0, 100),
|
|
22801
|
+
total: suggestions.length,
|
|
22802
|
+
hasMore: suggestions.length > 100
|
|
22803
|
+
}
|
|
21733
22804
|
};
|
|
21734
22805
|
}
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
22806
|
+
var EMPTY_COMPLETION_RESULT = {
|
|
22807
|
+
completion: {
|
|
22808
|
+
values: [],
|
|
22809
|
+
hasMore: false
|
|
22810
|
+
}
|
|
22811
|
+
};
|
|
22812
|
+
|
|
22813
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
22814
|
+
import process2 from "node:process";
|
|
22815
|
+
|
|
22816
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
22817
|
+
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
22818
|
+
var ReadBuffer = class {
|
|
22819
|
+
constructor(options) {
|
|
22820
|
+
this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
|
|
22821
|
+
}
|
|
22822
|
+
append(chunk) {
|
|
22823
|
+
const newSize = (this._buffer?.length ?? 0) + chunk.length;
|
|
22824
|
+
if (newSize > this._maxBufferSize) {
|
|
22825
|
+
this.clear();
|
|
22826
|
+
throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
|
|
22827
|
+
}
|
|
22828
|
+
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
22829
|
+
}
|
|
22830
|
+
readMessage() {
|
|
22831
|
+
if (!this._buffer) {
|
|
22832
|
+
return null;
|
|
22833
|
+
}
|
|
22834
|
+
const index = this._buffer.indexOf("\n");
|
|
22835
|
+
if (index === -1) {
|
|
22836
|
+
return null;
|
|
22837
|
+
}
|
|
22838
|
+
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
22839
|
+
this._buffer = this._buffer.subarray(index + 1);
|
|
22840
|
+
return deserializeMessage(line);
|
|
22841
|
+
}
|
|
22842
|
+
clear() {
|
|
22843
|
+
this._buffer = void 0;
|
|
22844
|
+
}
|
|
22845
|
+
};
|
|
22846
|
+
function deserializeMessage(line) {
|
|
22847
|
+
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
21741
22848
|
}
|
|
21742
|
-
function
|
|
21743
|
-
|
|
21744
|
-
const params = input.params ?? existing?.params ?? [];
|
|
21745
|
-
const pathParams = input.pathParams ?? existing?.pathParams ?? [];
|
|
21746
|
-
const bodyFields = input.bodyFields ?? existing?.bodyFields ?? [];
|
|
21747
|
-
const responses = input.responses ?? existing?.responses ?? [];
|
|
21748
|
-
return {
|
|
21749
|
-
...existing,
|
|
21750
|
-
...input,
|
|
21751
|
-
id: existing?.id ?? input.id ?? randomUUID(),
|
|
21752
|
-
kind: "request",
|
|
21753
|
-
name: input.name,
|
|
21754
|
-
method: input.method.toUpperCase(),
|
|
21755
|
-
url: input.url,
|
|
21756
|
-
body: input.body ?? existing?.body ?? "",
|
|
21757
|
-
headers: headers.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
21758
|
-
params: params.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
21759
|
-
pathParams: pathParams.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
21760
|
-
bodyFields: bodyFields.map((item) => ({ ...item, id: item.id || randomUUID() })),
|
|
21761
|
-
responses: responses.map((response) => ({ ...response, id: response.id || randomUUID(), content: response.content.map((content) => ({ ...content, id: content.id || randomUUID() })) }))
|
|
21762
|
-
};
|
|
22849
|
+
function serializeMessage(message) {
|
|
22850
|
+
return JSON.stringify(message) + "\n";
|
|
21763
22851
|
}
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
21773
|
-
|
|
21774
|
-
|
|
21775
|
-
|
|
22852
|
+
|
|
22853
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
22854
|
+
var StdioServerTransport = class {
|
|
22855
|
+
constructor(_stdin = process2.stdin, _stdout = process2.stdout, options) {
|
|
22856
|
+
this._stdin = _stdin;
|
|
22857
|
+
this._stdout = _stdout;
|
|
22858
|
+
this._started = false;
|
|
22859
|
+
this._ondata = (chunk) => {
|
|
22860
|
+
try {
|
|
22861
|
+
this._readBuffer.append(chunk);
|
|
22862
|
+
this.processReadBuffer();
|
|
22863
|
+
} catch (error2) {
|
|
22864
|
+
this.onerror?.(error2);
|
|
22865
|
+
this.close().catch(() => {
|
|
22866
|
+
});
|
|
22867
|
+
}
|
|
22868
|
+
};
|
|
22869
|
+
this._onerror = (error2) => {
|
|
22870
|
+
this.onerror?.(error2);
|
|
22871
|
+
};
|
|
22872
|
+
this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
|
|
21776
22873
|
}
|
|
21777
|
-
|
|
21778
|
-
|
|
21779
|
-
|
|
21780
|
-
|
|
21781
|
-
|
|
21782
|
-
|
|
22874
|
+
/**
|
|
22875
|
+
* Starts listening for messages on stdin.
|
|
22876
|
+
*/
|
|
22877
|
+
async start() {
|
|
22878
|
+
if (this._started) {
|
|
22879
|
+
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
|
|
22880
|
+
}
|
|
22881
|
+
this._started = true;
|
|
22882
|
+
this._stdin.on("data", this._ondata);
|
|
22883
|
+
this._stdin.on("error", this._onerror);
|
|
21783
22884
|
}
|
|
21784
|
-
|
|
21785
|
-
|
|
21786
|
-
|
|
21787
|
-
|
|
21788
|
-
|
|
22885
|
+
processReadBuffer() {
|
|
22886
|
+
while (true) {
|
|
22887
|
+
try {
|
|
22888
|
+
const message = this._readBuffer.readMessage();
|
|
22889
|
+
if (message === null) {
|
|
22890
|
+
break;
|
|
22891
|
+
}
|
|
22892
|
+
this.onmessage?.(message);
|
|
22893
|
+
} catch (error2) {
|
|
22894
|
+
this.onerror?.(error2);
|
|
22895
|
+
}
|
|
22896
|
+
}
|
|
21789
22897
|
}
|
|
21790
|
-
|
|
21791
|
-
|
|
21792
|
-
|
|
21793
|
-
const
|
|
21794
|
-
if (
|
|
21795
|
-
|
|
21796
|
-
|
|
21797
|
-
|
|
21798
|
-
|
|
21799
|
-
const next = insertNode(removed2.tree, operation.parentId, removed2.removed, operation.index);
|
|
21800
|
-
return { tree: next, summary: { action: operation.action, target: before2.name, before: { parentId: oldParentId }, after: { parentId: operation.parentId, index: operation.index } } };
|
|
22898
|
+
async close() {
|
|
22899
|
+
this._stdin.off("data", this._ondata);
|
|
22900
|
+
this._stdin.off("error", this._onerror);
|
|
22901
|
+
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
22902
|
+
if (remainingDataListeners === 0) {
|
|
22903
|
+
this._stdin.pause();
|
|
22904
|
+
}
|
|
22905
|
+
this._readBuffer.clear();
|
|
22906
|
+
this.onclose?.();
|
|
21801
22907
|
}
|
|
21802
|
-
|
|
21803
|
-
|
|
21804
|
-
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
22908
|
+
send(message) {
|
|
22909
|
+
return new Promise((resolve) => {
|
|
22910
|
+
const json = serializeMessage(message);
|
|
22911
|
+
if (this._stdout.write(json)) {
|
|
22912
|
+
resolve();
|
|
22913
|
+
} else {
|
|
22914
|
+
this._stdout.once("drain", resolve);
|
|
22915
|
+
}
|
|
22916
|
+
});
|
|
21808
22917
|
}
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
22918
|
+
};
|
|
22919
|
+
|
|
22920
|
+
// src/mcp-surface.ts
|
|
22921
|
+
var directCollectionWrites = /* @__PURE__ */ new Set([
|
|
22922
|
+
"folder.create",
|
|
22923
|
+
"folder.rename",
|
|
22924
|
+
"folder.delete",
|
|
22925
|
+
"node.move",
|
|
22926
|
+
"request.create",
|
|
22927
|
+
"request.update",
|
|
22928
|
+
"request.duplicate",
|
|
22929
|
+
"request.deprecate",
|
|
22930
|
+
"request.delete"
|
|
22931
|
+
]);
|
|
22932
|
+
function mcpCommands() {
|
|
22933
|
+
return allCommands.filter((command) => !directCollectionWrites.has(command.id));
|
|
21813
22934
|
}
|
|
21814
|
-
function
|
|
21815
|
-
|
|
22935
|
+
function missingVariableRevision(commandId, params) {
|
|
22936
|
+
if (commandId !== "variable.set" && commandId !== "variable.delete") return null;
|
|
22937
|
+
if (params.expectedRevision !== void 0) return null;
|
|
22938
|
+
return "Read the variable with variable.get first, then pass its revision as expectedRevision. Pass null when the variable does not exist yet.";
|
|
21816
22939
|
}
|
|
21817
|
-
function
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
return { id: workspace.id, name: workspace.name, cloudId: workspace.cloudId, role: workspace.role ?? null };
|
|
21822
|
-
});
|
|
22940
|
+
function missingTargetConfirmation(commandId, params) {
|
|
22941
|
+
if (commandId !== "request.send") return null;
|
|
22942
|
+
if (params.dryRun === true || typeof params.confirmUrl === "string") return null;
|
|
22943
|
+
return "Run request.send with dryRun set to true first, show the URL to the user, then send with confirmUrl set to that URL.";
|
|
21823
22944
|
}
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21829
|
-
|
|
21830
|
-
|
|
21831
|
-
|
|
21832
|
-
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
|
|
21839
|
-
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
|
|
21843
|
-
|
|
21844
|
-
|
|
21845
|
-
|
|
21846
|
-
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
|
|
21857
|
-
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
|
|
21861
|
-
|
|
21862
|
-
|
|
21863
|
-
|
|
21864
|
-
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
21871
|
-
|
|
21872
|
-
|
|
21873
|
-
|
|
21874
|
-
|
|
21875
|
-
|
|
21876
|
-
|
|
21877
|
-
|
|
21878
|
-
|
|
21879
|
-
|
|
21880
|
-
|
|
21881
|
-
|
|
21882
|
-
|
|
21883
|
-
|
|
21884
|
-
|
|
21885
|
-
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
|
|
21889
|
-
|
|
21890
|
-
|
|
21891
|
-
|
|
21892
|
-
|
|
21893
|
-
|
|
21894
|
-
|
|
21895
|
-
|
|
21896
|
-
|
|
21897
|
-
|
|
21898
|
-
|
|
21899
|
-
|
|
21900
|
-
|
|
21901
|
-
|
|
21902
|
-
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
|
|
21909
|
-
|
|
21910
|
-
|
|
21911
|
-
|
|
21912
|
-
const currentHash = createHash("sha256").update(raw).digest("hex");
|
|
21913
|
-
if (currentHash !== plan.sourceHash) throw new Error("The workspace changed after this preview. Run preview_changes again to avoid overwriting newer edits.");
|
|
21914
|
-
updated = { ...workspace, tree: structuredClone(plan.nextTree) };
|
|
21915
|
-
db.prepare("UPDATE workspaces SET data = ? WHERE id = ?").run(JSON.stringify(updated), plan.workspaceId);
|
|
21916
|
-
db.exec("COMMIT;");
|
|
21917
|
-
} catch (error2) {
|
|
21918
|
-
db.exec("ROLLBACK;");
|
|
21919
|
-
throw error2;
|
|
22945
|
+
|
|
22946
|
+
// src/guide.ts
|
|
22947
|
+
var guideText = `# API Documentation: how to build and change the workspace
|
|
22948
|
+
|
|
22949
|
+
Read this before any change. It sets how requests, variables, folders, and docs are made, so the result matches the API's real flows.
|
|
22950
|
+
|
|
22951
|
+
## 0. Start every task the same way
|
|
22952
|
+
1. Call list_commands for the parameters and whether a command is read-only or destructive.
|
|
22953
|
+
2. Read what exists first: workspace_list, tree_get, request_search, and request_get. Never create something that already exists under another name.
|
|
22954
|
+
3. Read the variables that are already there with variable_get before you add one. Reuse a name that exists.
|
|
22955
|
+
4. If the API contract is unknown, say what is unknown and ask. Do not guess a route, a field, or a status code.
|
|
22956
|
+
|
|
22957
|
+
## 1. Folders: one top-level folder per service
|
|
22958
|
+
- Top level: one folder per service or segment of the API, named in Title Case: Auth, Users, Billing, Orders. Create it with folder_create and parentId null.
|
|
22959
|
+
- Second level: one folder per business flow (for example "Checkout") or per resource (for example "Invoices"). Use a flow folder when several requests happen in order. Use a resource folder for standalone CRUD.
|
|
22960
|
+
- Put requests that every service needs (health check, token refresh) in a "Shared" folder at the top level.
|
|
22961
|
+
- Keep the tree at most three levels deep. Deeper nesting is hard to scan.
|
|
22962
|
+
- Move an existing item with node_move. Rename a folder with folder_rename. Do not delete and recreate a folder to move it, because its requests lose their place.
|
|
22963
|
+
|
|
22964
|
+
## 2. Requests: name and order
|
|
22965
|
+
- Name a request "METHOD resource action", for example "POST /invoices create". Keep the method visible in the name.
|
|
22966
|
+
- In a flow folder, prefix each request with its step: "1 Create cart", "2 Add item", "3 Checkout". The order must match the real order of calls.
|
|
22967
|
+
|
|
22968
|
+
## 3. Auth: set it for every request that needs it
|
|
22969
|
+
- Look at the endpoint's contract before you create the request.
|
|
22970
|
+
- JWT or any Authorization header: auth type bearer, token {{accessToken}}. Never a literal token.
|
|
22971
|
+
- API key: auth type api-key, with name, location (header or query), and value {{apiKey}}.
|
|
22972
|
+
- Username and password: auth type basic, with {{username}} and {{password}}.
|
|
22973
|
+
- Public endpoint: auth type none, and only when the contract says it is public.
|
|
22974
|
+
- request_update keeps the existing auth unless you send auth again. When you change how a request is called, send auth again so it is set on purpose.
|
|
22975
|
+
- Never write a real token, password, or key into a request. The variable holds it, and the value is entered in the app.
|
|
22976
|
+
|
|
22977
|
+
## 4. Variables: when a value becomes one
|
|
22978
|
+
Make a variable when a value does at least one of these:
|
|
22979
|
+
- It differs between environments, such as baseUrl, host, or tenantId. Use scope environment.
|
|
22980
|
+
- It is the same in every request, such as apiVersion or a tenant header name. Use scope global.
|
|
22981
|
+
- It is a credential, such as accessToken, apiKey, or password. Use secret true, with no value. The value is entered in the app.
|
|
22982
|
+
|
|
22983
|
+
Keep a literal value in the request when it is used once, does not change between environments, and is not a credential.
|
|
22984
|
+
|
|
22985
|
+
Naming: lowerCamelCase, specific, and the same name everywhere. Do not create baseUrl and base_url for the same thing.
|
|
22986
|
+
|
|
22987
|
+
Where a variable works: {{name}} resolves in the URL, params, headers, body, and auth when a request is sent. Globals apply everywhere. An active environment overrides a global of the same name. Set the active environment with environment_activate, and tell the user which one it is.
|
|
22988
|
+
|
|
22989
|
+
Writes: variable_set and variable_delete take the revision from variable_get as expectedRevision. Use null for a variable that does not exist yet. A stale revision is refused, so read again and retry.
|
|
22990
|
+
|
|
22991
|
+
## 5. Documentation: complete, and per business flow
|
|
22992
|
+
Every request gets:
|
|
22993
|
+
- Purpose: what the endpoint does, in one or two sentences.
|
|
22994
|
+
- Place in the flow: "Step 2 of Checkout. Before: Create cart. After: Confirm order." Name the requests.
|
|
22995
|
+
- Preconditions: what must be true first, and which variables must be set.
|
|
22996
|
+
- Auth: which variable provides it.
|
|
22997
|
+
- Request: each param, header, and body field, with its type, whether it is required, what it means, and a realistic example. Use {{variables}} in examples, never a real value.
|
|
22998
|
+
- Responses: one entry per status code the contract lists, with an example body. Include the error responses: which code, which error body, and when it happens.
|
|
22999
|
+
- Side effects: what changes on the server or in other requests.
|
|
23000
|
+
|
|
23001
|
+
Write it in the request's documentation field and its responses. Put the flow overview in the flow folder's first request. If a part is unknown, write "Unknown: ..." and ask the user. Do not fill it with a guess.
|
|
23002
|
+
|
|
23003
|
+
## 6. Changing collections: preview, ask, then apply
|
|
23004
|
+
- Every change to folders, requests, or moves goes through changes_preview. Apply it with changes_apply only after the user approves that exact preview.
|
|
23005
|
+
- Show the preview in chat: the workspace, the full path of each item, the before and after of each changed field, and what a deletion removes.
|
|
23006
|
+
- Ask the user to approve it, then stop. Do not call changes_apply in the same turn as the preview.
|
|
23007
|
+
- changes_apply refuses a preview when the workspace changed after it. Preview again.
|
|
23008
|
+
- Direct write commands (request_create, request_update, folder_create, node_move) are for the user's explicit request, and still need the approval above.
|
|
23009
|
+
|
|
23010
|
+
## 7. Deleting and deprecating
|
|
23011
|
+
- Prefer request_deprecate with a reason over deleting a request that other people may use.
|
|
23012
|
+
- Delete only when the user asks, and set confirm=true only after the user has confirmed that exact deletion.
|
|
23013
|
+
|
|
23014
|
+
## 8. Sending requests
|
|
23015
|
+
- Send only when the user asks. Say which environment is active first.
|
|
23016
|
+
- A variable with no value stops the send, and the error names it. Fill it in the app, or ask.
|
|
23017
|
+
- Do not send a request that changes data on a production server without asking.
|
|
23018
|
+
|
|
23019
|
+
## 9. Limits
|
|
23020
|
+
- Cloud workspaces are read-only over MCP. Changes to a cloud copy are made in the desktop app.
|
|
23021
|
+
- Viewer workspaces refuse writes.
|
|
23022
|
+
- Secret values are never returned. environment_list shows them as <secret>.
|
|
23023
|
+
`;
|
|
23024
|
+
function createGuideGate() {
|
|
23025
|
+
let read = false;
|
|
23026
|
+
return {
|
|
23027
|
+
markRead() {
|
|
23028
|
+
read = true;
|
|
23029
|
+
},
|
|
23030
|
+
refusal(command) {
|
|
23031
|
+
if (command.readOnly || read) return null;
|
|
23032
|
+
return "Read the guide first: call the guide tool, then retry this command.";
|
|
21920
23033
|
}
|
|
21921
|
-
|
|
21922
|
-
process.stderr.write(`Applied MCP changes to workspace ${plan.workspaceId}.
|
|
21923
|
-
`);
|
|
21924
|
-
return jsonResult({ applied: true, workspaceId: plan.workspaceId, workspaceName: updated.name, changes: plan.summary });
|
|
21925
|
-
});
|
|
23034
|
+
};
|
|
21926
23035
|
}
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
21932
|
-
|
|
21933
|
-
|
|
23036
|
+
|
|
23037
|
+
// src/mcp.ts
|
|
23038
|
+
var toolName = (commandId) => commandId.replace(/\./g, "_");
|
|
23039
|
+
var legacyTools = {
|
|
23040
|
+
list_workspaces: "workspace.list",
|
|
23041
|
+
get_collection_tree: "tree.get",
|
|
23042
|
+
search_requests: "request.search",
|
|
23043
|
+
get_request: "request.get",
|
|
23044
|
+
preview_changes: "changes.preview",
|
|
23045
|
+
apply_changes: "changes.apply"
|
|
23046
|
+
};
|
|
23047
|
+
var instructions = "Drive the API Documentation desktop app: list workspaces, read and change collections, requests, environments, and variables, and send requests. Call list_commands first to see every command and its parameters. Search and read requests before changing them. Record known route, parameters, headers, body, auth, and response contracts, and do not invent missing details. Use {{baseUrl}} or other descriptive {{variableName}} references for environment-specific values, and {{accessToken}} for credentials. Never write a real secret: secret variables are created empty, and their values are entered in the desktop app. Changes to collections go through changes.preview; render the diff in chat (workspace, full collection paths, before and after for each field, nested deletion impact), ask the user to approve that exact preview, and stop. Never call changes.apply in the same turn as the preview. Destructive commands require confirm=true, which is only set after the user explicitly confirms. Call guide before the first change: write commands are refused until it has been read in this session.";
|
|
23048
|
+
async function startMcpServer() {
|
|
23049
|
+
const server = new McpServer({ name: "api-documentation-local", version: "0.2.0" }, { instructions });
|
|
23050
|
+
const guide = createGuideGate();
|
|
23051
|
+
const register = (name, commandId, title, description) => {
|
|
23052
|
+
const command = allCommands.find((item) => item.id === commandId);
|
|
23053
|
+
if (!command) throw new Error(`Command ${commandId} is not registered.`);
|
|
23054
|
+
server.registerTool(
|
|
23055
|
+
name,
|
|
23056
|
+
{
|
|
23057
|
+
title,
|
|
23058
|
+
description,
|
|
23059
|
+
inputSchema: command.params.shape,
|
|
23060
|
+
annotations: { readOnlyHint: command.readOnly, destructiveHint: command.destructive, openWorldHint: command.id === "request.send" }
|
|
23061
|
+
},
|
|
23062
|
+
async (params) => {
|
|
23063
|
+
const input = params ?? {};
|
|
23064
|
+
const refusal = guide.refusal(command) ?? missingTargetConfirmation(commandId, input) ?? missingVariableRevision(commandId, input);
|
|
23065
|
+
if (refusal) throw new Error(refusal);
|
|
23066
|
+
return { content: [{ type: "text", text: JSON.stringify(await executeCommand(commandId, params), null, 2) }] };
|
|
23067
|
+
}
|
|
23068
|
+
);
|
|
23069
|
+
};
|
|
23070
|
+
for (const command of mcpCommands()) {
|
|
23071
|
+
register(toolName(command.id), command.id, command.title, command.description);
|
|
23072
|
+
}
|
|
23073
|
+
for (const [name, commandId] of Object.entries(legacyTools)) {
|
|
23074
|
+
const command = allCommands.find((item) => item.id === commandId);
|
|
23075
|
+
if (command) register(name, commandId, command.title, `${command.description} (Same as ${toolName(commandId)}.)`);
|
|
23076
|
+
}
|
|
23077
|
+
server.registerTool(
|
|
23078
|
+
"guide",
|
|
23079
|
+
{
|
|
23080
|
+
title: "Guide",
|
|
23081
|
+
description: "The rules for changing the app safely: read first, preview before apply, confirm deletes, and never write a secret. Read it before any write.",
|
|
23082
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
23083
|
+
},
|
|
23084
|
+
async () => {
|
|
23085
|
+
guide.markRead();
|
|
23086
|
+
return { content: [{ type: "text", text: guideText }] };
|
|
23087
|
+
}
|
|
23088
|
+
);
|
|
23089
|
+
server.registerTool(
|
|
23090
|
+
"list_commands",
|
|
23091
|
+
{
|
|
23092
|
+
title: "List commands",
|
|
23093
|
+
description: "List every desktop app command with its parameters and whether it is read-only or destructive.",
|
|
23094
|
+
annotations: { readOnlyHint: true, openWorldHint: false }
|
|
23095
|
+
},
|
|
23096
|
+
async () => ({ content: [{ type: "text", text: JSON.stringify(mcpCommands().map(describeCommand), null, 2) }] })
|
|
23097
|
+
);
|
|
23098
|
+
await server.connect(new StdioServerTransport());
|
|
21934
23099
|
}
|
|
21935
|
-
|
|
21936
|
-
|
|
23100
|
+
|
|
23101
|
+
// src/index.ts
|
|
23102
|
+
var args = process.argv.slice(2);
|
|
23103
|
+
var main = args.length === 0 || args[0] === "mcp" ? startMcpServer() : runCli(args);
|
|
23104
|
+
main.catch((error2) => {
|
|
23105
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
21937
23106
|
process.stderr.write(`${message}
|
|
21938
23107
|
`);
|
|
21939
23108
|
process.exitCode = 1;
|