@swarp/cli 0.1.2-rc.40 → 0.1.2-rc.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp-server.mjs +436 -90
- package/package.json +1 -1
- package/skills/swarp/SKILL.md +11 -0
- package/src/mcp-server/deploy-router.mjs +378 -0
- package/src/mcp-server/index.mjs +8 -1
- package/src/mcp-server/onboard.mjs +48 -16
package/dist/mcp-server.mjs
CHANGED
|
@@ -2989,7 +2989,7 @@ var require_compile = __commonJS({
|
|
|
2989
2989
|
const schOrFunc = root.refs[ref];
|
|
2990
2990
|
if (schOrFunc)
|
|
2991
2991
|
return schOrFunc;
|
|
2992
|
-
let _sch =
|
|
2992
|
+
let _sch = resolve6.call(this, root, ref);
|
|
2993
2993
|
if (_sch === void 0) {
|
|
2994
2994
|
const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2995
2995
|
const { schemaId } = this.opts;
|
|
@@ -3016,7 +3016,7 @@ var require_compile = __commonJS({
|
|
|
3016
3016
|
function sameSchemaEnv(s1, s2) {
|
|
3017
3017
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3018
3018
|
}
|
|
3019
|
-
function
|
|
3019
|
+
function resolve6(root, ref) {
|
|
3020
3020
|
let sch;
|
|
3021
3021
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3022
3022
|
ref = sch;
|
|
@@ -3591,7 +3591,7 @@ var require_fast_uri = __commonJS({
|
|
|
3591
3591
|
}
|
|
3592
3592
|
return uri;
|
|
3593
3593
|
}
|
|
3594
|
-
function
|
|
3594
|
+
function resolve6(baseURI, relativeURI, options) {
|
|
3595
3595
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3596
3596
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3597
3597
|
schemelessOptions.skipEscape = true;
|
|
@@ -3818,7 +3818,7 @@ var require_fast_uri = __commonJS({
|
|
|
3818
3818
|
var fastUri = {
|
|
3819
3819
|
SCHEMES,
|
|
3820
3820
|
normalize,
|
|
3821
|
-
resolve:
|
|
3821
|
+
resolve: resolve6,
|
|
3822
3822
|
resolveComponent,
|
|
3823
3823
|
equal,
|
|
3824
3824
|
serialize,
|
|
@@ -7349,7 +7349,7 @@ var require_call_credentials = __commonJS({
|
|
|
7349
7349
|
if (isCurrentOauth2Client(googleCredentials)) {
|
|
7350
7350
|
getHeaders = googleCredentials.getRequestHeaders(options.service_url);
|
|
7351
7351
|
} else {
|
|
7352
|
-
getHeaders = new Promise((
|
|
7352
|
+
getHeaders = new Promise((resolve6, reject) => {
|
|
7353
7353
|
googleCredentials.getRequestMetadata(options.service_url, (err, headers) => {
|
|
7354
7354
|
if (err) {
|
|
7355
7355
|
reject(err);
|
|
@@ -7359,7 +7359,7 @@ var require_call_credentials = __commonJS({
|
|
|
7359
7359
|
reject(new Error("Headers not set by metadata plugin"));
|
|
7360
7360
|
return;
|
|
7361
7361
|
}
|
|
7362
|
-
|
|
7362
|
+
resolve6(headers);
|
|
7363
7363
|
});
|
|
7364
7364
|
});
|
|
7365
7365
|
}
|
|
@@ -7412,10 +7412,10 @@ var require_call_credentials = __commonJS({
|
|
|
7412
7412
|
this.metadataGenerator = metadataGenerator;
|
|
7413
7413
|
}
|
|
7414
7414
|
generateMetadata(options) {
|
|
7415
|
-
return new Promise((
|
|
7415
|
+
return new Promise((resolve6, reject) => {
|
|
7416
7416
|
this.metadataGenerator(options, (err, metadata) => {
|
|
7417
7417
|
if (metadata !== void 0) {
|
|
7418
|
-
|
|
7418
|
+
resolve6(metadata);
|
|
7419
7419
|
} else {
|
|
7420
7420
|
reject(err);
|
|
7421
7421
|
}
|
|
@@ -7774,14 +7774,14 @@ var require_channel_credentials = __commonJS({
|
|
|
7774
7774
|
}
|
|
7775
7775
|
connect(socket) {
|
|
7776
7776
|
const tlsConnectOptions = Object.assign({ socket }, this.connectionOptions);
|
|
7777
|
-
return new Promise((
|
|
7777
|
+
return new Promise((resolve6, reject) => {
|
|
7778
7778
|
const tlsSocket = (0, tls_1.connect)(tlsConnectOptions, () => {
|
|
7779
7779
|
var _a;
|
|
7780
7780
|
if (((_a = this.connectionOptions.rejectUnauthorized) !== null && _a !== void 0 ? _a : true) && !tlsSocket.authorized) {
|
|
7781
7781
|
reject(tlsSocket.authorizationError);
|
|
7782
7782
|
return;
|
|
7783
7783
|
}
|
|
7784
|
-
|
|
7784
|
+
resolve6({
|
|
7785
7785
|
socket: tlsSocket,
|
|
7786
7786
|
secure: true
|
|
7787
7787
|
});
|
|
@@ -7900,8 +7900,8 @@ var require_channel_credentials = __commonJS({
|
|
|
7900
7900
|
if (this.hasReceivedUpdates()) {
|
|
7901
7901
|
return Promise.resolve(this.getLatestSecureContext());
|
|
7902
7902
|
} else {
|
|
7903
|
-
return new Promise((
|
|
7904
|
-
this.secureContextWatchers.push(
|
|
7903
|
+
return new Promise((resolve6) => {
|
|
7904
|
+
this.secureContextWatchers.push(resolve6);
|
|
7905
7905
|
});
|
|
7906
7906
|
}
|
|
7907
7907
|
}
|
|
@@ -7934,7 +7934,7 @@ var require_channel_credentials = __commonJS({
|
|
|
7934
7934
|
this.callCredentials = callCredentials;
|
|
7935
7935
|
}
|
|
7936
7936
|
connect(socket) {
|
|
7937
|
-
return new Promise((
|
|
7937
|
+
return new Promise((resolve6, reject) => {
|
|
7938
7938
|
const secureContext = this.parent.getLatestSecureContext();
|
|
7939
7939
|
if (!secureContext) {
|
|
7940
7940
|
reject(new Error("Failed to load credentials"));
|
|
@@ -7959,7 +7959,7 @@ var require_channel_credentials = __commonJS({
|
|
|
7959
7959
|
reject(tlsSocket.authorizationError);
|
|
7960
7960
|
return;
|
|
7961
7961
|
}
|
|
7962
|
-
|
|
7962
|
+
resolve6({
|
|
7963
7963
|
socket: tlsSocket,
|
|
7964
7964
|
secure: true
|
|
7965
7965
|
});
|
|
@@ -11535,7 +11535,7 @@ var require_aspromise = __commonJS({
|
|
|
11535
11535
|
var params = new Array(arguments.length - 1), offset = 0, index = 2, pending = true;
|
|
11536
11536
|
while (index < arguments.length)
|
|
11537
11537
|
params[offset++] = arguments[index++];
|
|
11538
|
-
return new Promise(function executor(
|
|
11538
|
+
return new Promise(function executor(resolve6, reject) {
|
|
11539
11539
|
params[offset] = function callback(err) {
|
|
11540
11540
|
if (pending) {
|
|
11541
11541
|
pending = false;
|
|
@@ -11545,7 +11545,7 @@ var require_aspromise = __commonJS({
|
|
|
11545
11545
|
var params2 = new Array(arguments.length - 1), offset2 = 0;
|
|
11546
11546
|
while (offset2 < params2.length)
|
|
11547
11547
|
params2[offset2++] = arguments[offset2];
|
|
11548
|
-
|
|
11548
|
+
resolve6.apply(null, params2);
|
|
11549
11549
|
}
|
|
11550
11550
|
}
|
|
11551
11551
|
};
|
|
@@ -13057,7 +13057,7 @@ var require_path = __commonJS({
|
|
|
13057
13057
|
return prefix + parts.join("/");
|
|
13058
13058
|
}
|
|
13059
13059
|
);
|
|
13060
|
-
path2.resolve = function
|
|
13060
|
+
path2.resolve = function resolve6(originPath, includePath, alreadyNormalized) {
|
|
13061
13061
|
if (!alreadyNormalized)
|
|
13062
13062
|
includePath = normalize(includePath);
|
|
13063
13063
|
if (isAbsolute(includePath))
|
|
@@ -13377,7 +13377,7 @@ var require_mapfield = __commonJS({
|
|
|
13377
13377
|
keepComments ? this.comment : void 0
|
|
13378
13378
|
]);
|
|
13379
13379
|
};
|
|
13380
|
-
MapField.prototype.resolve = function
|
|
13380
|
+
MapField.prototype.resolve = function resolve6() {
|
|
13381
13381
|
if (this.resolved)
|
|
13382
13382
|
return this;
|
|
13383
13383
|
if (types2.mapKey[this.keyType] === void 0)
|
|
@@ -13454,7 +13454,7 @@ var require_method = __commonJS({
|
|
|
13454
13454
|
this.parsedOptions
|
|
13455
13455
|
]);
|
|
13456
13456
|
};
|
|
13457
|
-
Method.prototype.resolve = function
|
|
13457
|
+
Method.prototype.resolve = function resolve6() {
|
|
13458
13458
|
if (this.resolved)
|
|
13459
13459
|
return this;
|
|
13460
13460
|
this.resolvedRequestType = this.parent.lookupType(this.requestType);
|
|
@@ -15017,7 +15017,7 @@ var require_field = __commonJS({
|
|
|
15017
15017
|
keepComments ? this.comment : void 0
|
|
15018
15018
|
]);
|
|
15019
15019
|
};
|
|
15020
|
-
Field.prototype.resolve = function
|
|
15020
|
+
Field.prototype.resolve = function resolve6() {
|
|
15021
15021
|
if (this.resolved)
|
|
15022
15022
|
return this;
|
|
15023
15023
|
if ((this.typeDefault = types2.defaults[this.type]) === void 0) {
|
|
@@ -15290,7 +15290,7 @@ var require_object = __commonJS({
|
|
|
15290
15290
|
this.parent = null;
|
|
15291
15291
|
this.resolved = false;
|
|
15292
15292
|
};
|
|
15293
|
-
ReflectionObject.prototype.resolve = function
|
|
15293
|
+
ReflectionObject.prototype.resolve = function resolve6() {
|
|
15294
15294
|
if (this.resolved)
|
|
15295
15295
|
return this;
|
|
15296
15296
|
if (this.root instanceof Root)
|
|
@@ -21191,18 +21191,18 @@ var require_compression_filter = __commonJS({
|
|
|
21191
21191
|
this.maxRecvMessageLength = maxRecvMessageLength;
|
|
21192
21192
|
}
|
|
21193
21193
|
compressMessage(message) {
|
|
21194
|
-
return new Promise((
|
|
21194
|
+
return new Promise((resolve6, reject) => {
|
|
21195
21195
|
zlib.deflate(message, (err, output) => {
|
|
21196
21196
|
if (err) {
|
|
21197
21197
|
reject(err);
|
|
21198
21198
|
} else {
|
|
21199
|
-
|
|
21199
|
+
resolve6(output);
|
|
21200
21200
|
}
|
|
21201
21201
|
});
|
|
21202
21202
|
});
|
|
21203
21203
|
}
|
|
21204
21204
|
decompressMessage(message) {
|
|
21205
|
-
return new Promise((
|
|
21205
|
+
return new Promise((resolve6, reject) => {
|
|
21206
21206
|
let totalLength = 0;
|
|
21207
21207
|
const messageParts = [];
|
|
21208
21208
|
const decompresser = zlib.createInflate();
|
|
@@ -21218,7 +21218,7 @@ var require_compression_filter = __commonJS({
|
|
|
21218
21218
|
}
|
|
21219
21219
|
});
|
|
21220
21220
|
decompresser.on("end", () => {
|
|
21221
|
-
|
|
21221
|
+
resolve6(Buffer.concat(messageParts));
|
|
21222
21222
|
});
|
|
21223
21223
|
decompresser.write(message);
|
|
21224
21224
|
decompresser.end();
|
|
@@ -21231,18 +21231,18 @@ var require_compression_filter = __commonJS({
|
|
|
21231
21231
|
this.maxRecvMessageLength = maxRecvMessageLength;
|
|
21232
21232
|
}
|
|
21233
21233
|
compressMessage(message) {
|
|
21234
|
-
return new Promise((
|
|
21234
|
+
return new Promise((resolve6, reject) => {
|
|
21235
21235
|
zlib.gzip(message, (err, output) => {
|
|
21236
21236
|
if (err) {
|
|
21237
21237
|
reject(err);
|
|
21238
21238
|
} else {
|
|
21239
|
-
|
|
21239
|
+
resolve6(output);
|
|
21240
21240
|
}
|
|
21241
21241
|
});
|
|
21242
21242
|
});
|
|
21243
21243
|
}
|
|
21244
21244
|
decompressMessage(message) {
|
|
21245
|
-
return new Promise((
|
|
21245
|
+
return new Promise((resolve6, reject) => {
|
|
21246
21246
|
let totalLength = 0;
|
|
21247
21247
|
const messageParts = [];
|
|
21248
21248
|
const decompresser = zlib.createGunzip();
|
|
@@ -21258,7 +21258,7 @@ var require_compression_filter = __commonJS({
|
|
|
21258
21258
|
}
|
|
21259
21259
|
});
|
|
21260
21260
|
decompresser.on("end", () => {
|
|
21261
|
-
|
|
21261
|
+
resolve6(Buffer.concat(messageParts));
|
|
21262
21262
|
});
|
|
21263
21263
|
decompresser.write(message);
|
|
21264
21264
|
decompresser.end();
|
|
@@ -22593,7 +22593,7 @@ var require_http_proxy = __commonJS({
|
|
|
22593
22593
|
options.headers = headers;
|
|
22594
22594
|
const proxyAddressString = (0, subchannel_address_1.subchannelAddressToString)(address);
|
|
22595
22595
|
trace("Using proxy " + proxyAddressString + " to connect to " + options.path);
|
|
22596
|
-
return new Promise((
|
|
22596
|
+
return new Promise((resolve6, reject) => {
|
|
22597
22597
|
const request = http.request(options);
|
|
22598
22598
|
request.once("connect", (res, socket, head) => {
|
|
22599
22599
|
request.removeAllListeners();
|
|
@@ -22604,7 +22604,7 @@ var require_http_proxy = __commonJS({
|
|
|
22604
22604
|
socket.unshift(head);
|
|
22605
22605
|
}
|
|
22606
22606
|
trace("Successfully established a plaintext connection to " + options.path + " through proxy " + proxyAddressString);
|
|
22607
|
-
|
|
22607
|
+
resolve6(socket);
|
|
22608
22608
|
} else {
|
|
22609
22609
|
(0, logging_1.log)(constants_1.LogVerbosity.ERROR, "Failed to connect to " + options.path + " through proxy " + proxyAddressString + " with status " + res.statusCode);
|
|
22610
22610
|
reject();
|
|
@@ -23504,7 +23504,7 @@ var require_transport = __commonJS({
|
|
|
23504
23504
|
if (secureConnectResult.socket.closed) {
|
|
23505
23505
|
return Promise.reject("Connection closed before starting HTTP/2 handshake");
|
|
23506
23506
|
}
|
|
23507
|
-
return new Promise((
|
|
23507
|
+
return new Promise((resolve6, reject) => {
|
|
23508
23508
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
23509
23509
|
let remoteName = null;
|
|
23510
23510
|
let realTarget = this.channelTarget;
|
|
@@ -23573,7 +23573,7 @@ var require_transport = __commonJS({
|
|
|
23573
23573
|
session.removeAllListeners();
|
|
23574
23574
|
secureConnectResult.socket.removeListener("close", closeHandler);
|
|
23575
23575
|
secureConnectResult.socket.removeListener("error", errorHandler);
|
|
23576
|
-
|
|
23576
|
+
resolve6(new Http2Transport(session, address, options, remoteName));
|
|
23577
23577
|
this.session = null;
|
|
23578
23578
|
});
|
|
23579
23579
|
session.once("close", closeHandler);
|
|
@@ -23587,7 +23587,7 @@ var require_transport = __commonJS({
|
|
|
23587
23587
|
if (proxiedSocket) {
|
|
23588
23588
|
return proxiedSocket;
|
|
23589
23589
|
} else {
|
|
23590
|
-
return new Promise((
|
|
23590
|
+
return new Promise((resolve6, reject) => {
|
|
23591
23591
|
const closeCallback = () => {
|
|
23592
23592
|
reject(new Error("Socket closed"));
|
|
23593
23593
|
};
|
|
@@ -23597,7 +23597,7 @@ var require_transport = __commonJS({
|
|
|
23597
23597
|
const socket = net.connect(address, () => {
|
|
23598
23598
|
socket.removeListener("close", closeCallback);
|
|
23599
23599
|
socket.removeListener("error", errorCallback);
|
|
23600
|
-
|
|
23600
|
+
resolve6(socket);
|
|
23601
23601
|
});
|
|
23602
23602
|
socket.once("close", closeCallback);
|
|
23603
23603
|
socket.once("error", errorCallback);
|
|
@@ -26901,7 +26901,7 @@ var require_server_interceptors = __commonJS({
|
|
|
26901
26901
|
} else {
|
|
26902
26902
|
decompresser = zlib.createGunzip();
|
|
26903
26903
|
}
|
|
26904
|
-
return new Promise((
|
|
26904
|
+
return new Promise((resolve6, reject) => {
|
|
26905
26905
|
let totalLength = 0;
|
|
26906
26906
|
const messageParts = [];
|
|
26907
26907
|
decompresser.on("data", (chunk) => {
|
|
@@ -26916,7 +26916,7 @@ var require_server_interceptors = __commonJS({
|
|
|
26916
26916
|
}
|
|
26917
26917
|
});
|
|
26918
26918
|
decompresser.on("end", () => {
|
|
26919
|
-
|
|
26919
|
+
resolve6(Buffer.concat(messageParts));
|
|
26920
26920
|
});
|
|
26921
26921
|
decompresser.write(messageContents);
|
|
26922
26922
|
decompresser.end();
|
|
@@ -27506,10 +27506,10 @@ var require_server = __commonJS({
|
|
|
27506
27506
|
bindOneAddress(address, boundPortObject) {
|
|
27507
27507
|
this.trace("Attempting to bind " + (0, subchannel_address_1.subchannelAddressToString)(address));
|
|
27508
27508
|
const http2Server = this.createHttp2Server(boundPortObject.credentials);
|
|
27509
|
-
return new Promise((
|
|
27509
|
+
return new Promise((resolve6, reject) => {
|
|
27510
27510
|
const onError = (err) => {
|
|
27511
27511
|
this.trace("Failed to bind " + (0, subchannel_address_1.subchannelAddressToString)(address) + " with error " + err.message);
|
|
27512
|
-
|
|
27512
|
+
resolve6({
|
|
27513
27513
|
port: "port" in address ? address.port : 1,
|
|
27514
27514
|
error: err.message
|
|
27515
27515
|
});
|
|
@@ -27537,7 +27537,7 @@ var require_server = __commonJS({
|
|
|
27537
27537
|
});
|
|
27538
27538
|
boundPortObject.listeningServers.add(http2Server);
|
|
27539
27539
|
this.trace("Successfully bound " + (0, subchannel_address_1.subchannelAddressToString)(boundSubchannelAddress));
|
|
27540
|
-
|
|
27540
|
+
resolve6({
|
|
27541
27541
|
port: "port" in boundSubchannelAddress ? boundSubchannelAddress.port : 1
|
|
27542
27542
|
});
|
|
27543
27543
|
http2Server.removeListener("error", onError);
|
|
@@ -27590,7 +27590,7 @@ var require_server = __commonJS({
|
|
|
27590
27590
|
}
|
|
27591
27591
|
}
|
|
27592
27592
|
resolvePort(port) {
|
|
27593
|
-
return new Promise((
|
|
27593
|
+
return new Promise((resolve6, reject) => {
|
|
27594
27594
|
let seenResolution = false;
|
|
27595
27595
|
const resolverListener = (endpointList, attributes, serviceConfig, resolutionNote) => {
|
|
27596
27596
|
if (seenResolution) {
|
|
@@ -27606,7 +27606,7 @@ var require_server = __commonJS({
|
|
|
27606
27606
|
reject(new Error(`No addresses resolved for port ${port}`));
|
|
27607
27607
|
return true;
|
|
27608
27608
|
}
|
|
27609
|
-
|
|
27609
|
+
resolve6(addressList);
|
|
27610
27610
|
return true;
|
|
27611
27611
|
};
|
|
27612
27612
|
const resolver = (0, resolver_1.createResolver)(port, resolverListener, this.options);
|
|
@@ -43662,7 +43662,7 @@ var Protocol = class {
|
|
|
43662
43662
|
return;
|
|
43663
43663
|
}
|
|
43664
43664
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
43665
|
-
await new Promise((
|
|
43665
|
+
await new Promise((resolve6) => setTimeout(resolve6, pollInterval));
|
|
43666
43666
|
options?.signal?.throwIfAborted();
|
|
43667
43667
|
}
|
|
43668
43668
|
} catch (error2) {
|
|
@@ -43679,7 +43679,7 @@ var Protocol = class {
|
|
|
43679
43679
|
*/
|
|
43680
43680
|
request(request, resultSchema, options) {
|
|
43681
43681
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
43682
|
-
return new Promise((
|
|
43682
|
+
return new Promise((resolve6, reject) => {
|
|
43683
43683
|
const earlyReject = (error2) => {
|
|
43684
43684
|
reject(error2);
|
|
43685
43685
|
};
|
|
@@ -43757,7 +43757,7 @@ var Protocol = class {
|
|
|
43757
43757
|
if (!parseResult.success) {
|
|
43758
43758
|
reject(parseResult.error);
|
|
43759
43759
|
} else {
|
|
43760
|
-
|
|
43760
|
+
resolve6(parseResult.data);
|
|
43761
43761
|
}
|
|
43762
43762
|
} catch (error2) {
|
|
43763
43763
|
reject(error2);
|
|
@@ -44018,12 +44018,12 @@ var Protocol = class {
|
|
|
44018
44018
|
}
|
|
44019
44019
|
} catch {
|
|
44020
44020
|
}
|
|
44021
|
-
return new Promise((
|
|
44021
|
+
return new Promise((resolve6, reject) => {
|
|
44022
44022
|
if (signal.aborted) {
|
|
44023
44023
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
44024
44024
|
return;
|
|
44025
44025
|
}
|
|
44026
|
-
const timeoutId = setTimeout(
|
|
44026
|
+
const timeoutId = setTimeout(resolve6, interval);
|
|
44027
44027
|
signal.addEventListener("abort", () => {
|
|
44028
44028
|
clearTimeout(timeoutId);
|
|
44029
44029
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -44893,12 +44893,12 @@ var StdioServerTransport = class {
|
|
|
44893
44893
|
this.onclose?.();
|
|
44894
44894
|
}
|
|
44895
44895
|
send(message) {
|
|
44896
|
-
return new Promise((
|
|
44896
|
+
return new Promise((resolve6) => {
|
|
44897
44897
|
const json2 = serializeMessage(message);
|
|
44898
44898
|
if (this._stdout.write(json2)) {
|
|
44899
|
-
|
|
44899
|
+
resolve6();
|
|
44900
44900
|
} else {
|
|
44901
|
-
this._stdout.once("drain",
|
|
44901
|
+
this._stdout.once("drain", resolve6);
|
|
44902
44902
|
}
|
|
44903
44903
|
});
|
|
44904
44904
|
}
|
|
@@ -44940,18 +44940,18 @@ var DispatchClient = class {
|
|
|
44940
44940
|
}
|
|
44941
44941
|
}
|
|
44942
44942
|
listAgents() {
|
|
44943
|
-
return new Promise((
|
|
44944
|
-
this.stub.ListAgents({}, (err, res) => err ? reject(err) :
|
|
44943
|
+
return new Promise((resolve6, reject) => {
|
|
44944
|
+
this.stub.ListAgents({}, (err, res) => err ? reject(err) : resolve6(res));
|
|
44945
44945
|
});
|
|
44946
44946
|
}
|
|
44947
44947
|
cancelTask(taskId) {
|
|
44948
|
-
return new Promise((
|
|
44949
|
-
this.stub.CancelTask({ task_id: taskId }, (err, res) => err ? reject(err) :
|
|
44948
|
+
return new Promise((resolve6, reject) => {
|
|
44949
|
+
this.stub.CancelTask({ task_id: taskId }, (err, res) => err ? reject(err) : resolve6(res));
|
|
44950
44950
|
});
|
|
44951
44951
|
}
|
|
44952
44952
|
getAgentStatus(agent) {
|
|
44953
|
-
return new Promise((
|
|
44954
|
-
this.stub.GetAgentStatus({ agent }, (err, res) => err ? reject(err) :
|
|
44953
|
+
return new Promise((resolve6, reject) => {
|
|
44954
|
+
this.stub.GetAgentStatus({ agent }, (err, res) => err ? reject(err) : resolve6(res));
|
|
44955
44955
|
});
|
|
44956
44956
|
}
|
|
44957
44957
|
close() {
|
|
@@ -44964,11 +44964,11 @@ function callToAsyncIterator(call) {
|
|
|
44964
44964
|
const queue = [];
|
|
44965
44965
|
let done = false;
|
|
44966
44966
|
let error2 = null;
|
|
44967
|
-
let
|
|
44967
|
+
let resolve6 = null;
|
|
44968
44968
|
call.on("data", (chunk) => {
|
|
44969
|
-
if (
|
|
44970
|
-
const r =
|
|
44971
|
-
|
|
44969
|
+
if (resolve6) {
|
|
44970
|
+
const r = resolve6;
|
|
44971
|
+
resolve6 = null;
|
|
44972
44972
|
r({ value: chunk, done: false });
|
|
44973
44973
|
} else {
|
|
44974
44974
|
queue.push(chunk);
|
|
@@ -44976,17 +44976,17 @@ function callToAsyncIterator(call) {
|
|
|
44976
44976
|
});
|
|
44977
44977
|
call.on("end", () => {
|
|
44978
44978
|
done = true;
|
|
44979
|
-
if (
|
|
44980
|
-
const r =
|
|
44981
|
-
|
|
44979
|
+
if (resolve6) {
|
|
44980
|
+
const r = resolve6;
|
|
44981
|
+
resolve6 = null;
|
|
44982
44982
|
r({ value: void 0, done: true });
|
|
44983
44983
|
}
|
|
44984
44984
|
});
|
|
44985
44985
|
call.on("error", (err) => {
|
|
44986
44986
|
error2 = err;
|
|
44987
|
-
if (
|
|
44988
|
-
const r =
|
|
44989
|
-
|
|
44987
|
+
if (resolve6) {
|
|
44988
|
+
const r = resolve6;
|
|
44989
|
+
resolve6 = null;
|
|
44990
44990
|
r(Promise.reject(err));
|
|
44991
44991
|
}
|
|
44992
44992
|
});
|
|
@@ -45000,7 +45000,7 @@ function callToAsyncIterator(call) {
|
|
|
45000
45000
|
return Promise.resolve({ value: void 0, done: true });
|
|
45001
45001
|
}
|
|
45002
45002
|
return new Promise((res) => {
|
|
45003
|
-
|
|
45003
|
+
resolve6 = res;
|
|
45004
45004
|
});
|
|
45005
45005
|
}
|
|
45006
45006
|
};
|
|
@@ -45335,13 +45335,19 @@ function nextPhase() {
|
|
|
45335
45335
|
return null;
|
|
45336
45336
|
}
|
|
45337
45337
|
function checkPrerequisites() {
|
|
45338
|
+
const versionFlags = { flyctl: "version", sprite: "--version", gh: "--version" };
|
|
45338
45339
|
const results = [];
|
|
45339
45340
|
for (const tool of ["flyctl", "sprite", "gh"]) {
|
|
45340
45341
|
try {
|
|
45341
45342
|
execFileSync("which", [tool], { stdio: "ignore" });
|
|
45342
|
-
|
|
45343
|
+
let version2 = "unknown";
|
|
45344
|
+
try {
|
|
45345
|
+
version2 = execFileSync(tool, [versionFlags[tool]], { encoding: "utf-8", timeout: 5e3 }).trim().split("\n")[0];
|
|
45346
|
+
} catch {
|
|
45347
|
+
}
|
|
45348
|
+
results.push({ tool, installed: true, version: version2 });
|
|
45343
45349
|
} catch {
|
|
45344
|
-
results.push({ tool, installed: false });
|
|
45350
|
+
results.push({ tool, installed: false, version: null });
|
|
45345
45351
|
}
|
|
45346
45352
|
}
|
|
45347
45353
|
return results;
|
|
@@ -45443,7 +45449,21 @@ async function handleOnboard(toolArgs) {
|
|
|
45443
45449
|
if (action === "check_prerequisites") {
|
|
45444
45450
|
const results = checkPrerequisites();
|
|
45445
45451
|
const allInstalled = results.every((r) => r.installed);
|
|
45446
|
-
const lines = results.map((r) => ` ${r.installed ? "\u2713" : "\u2717"} ${r.tool}`);
|
|
45452
|
+
const lines = results.map((r) => ` ${r.installed ? "\u2713" : "\u2717"} ${r.tool} \u2014 ${r.installed ? `installed (${r.version})` : "not installed"}`);
|
|
45453
|
+
const missing = results.filter((r) => !r.installed);
|
|
45454
|
+
const installInstructions = missing.map((r) => {
|
|
45455
|
+
switch (r.tool) {
|
|
45456
|
+
case "flyctl":
|
|
45457
|
+
return `Install flyctl by running: curl -L https://fly.io/install.sh | sh
|
|
45458
|
+
Then authenticate: fly auth login`;
|
|
45459
|
+
case "sprite":
|
|
45460
|
+
return `Install sprite by running: curl -fsSL https://sprites.dev/install.sh | sh`;
|
|
45461
|
+
case "gh":
|
|
45462
|
+
return `Install gh by running: (type -p wget >/dev/null || (apt-get update && apt-get install -y wget)) && mkdir -p /etc/apt/keyrings && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && apt-get update && apt-get install -y gh`;
|
|
45463
|
+
default:
|
|
45464
|
+
return `Install ${r.tool} manually.`;
|
|
45465
|
+
}
|
|
45466
|
+
});
|
|
45447
45467
|
return {
|
|
45448
45468
|
content: [{
|
|
45449
45469
|
type: "text",
|
|
@@ -45451,7 +45471,14 @@ async function handleOnboard(toolArgs) {
|
|
|
45451
45471
|
"Prerequisite check:",
|
|
45452
45472
|
...lines,
|
|
45453
45473
|
"",
|
|
45454
|
-
allInstalled ? 'All prerequisites met. Run swarp_onboard with action="complete_phase" phase="prerequisites" to advance.' :
|
|
45474
|
+
allInstalled ? 'All prerequisites met. Run swarp_onboard with action="complete_phase" phase="prerequisites" to advance.' : [
|
|
45475
|
+
`${missing.length} missing tool(s). Install them now:`,
|
|
45476
|
+
"",
|
|
45477
|
+
...installInstructions,
|
|
45478
|
+
"",
|
|
45479
|
+
"Run these install commands directly \u2014 Claude Code will ask for permission.",
|
|
45480
|
+
'After installing, run swarp_onboard with action="check_prerequisites" again to verify.'
|
|
45481
|
+
].join("\n")
|
|
45455
45482
|
].join("\n")
|
|
45456
45483
|
}]
|
|
45457
45484
|
};
|
|
@@ -45462,25 +45489,30 @@ function getPhaseInstructions(phase, state) {
|
|
|
45462
45489
|
switch (phase) {
|
|
45463
45490
|
case "prerequisites":
|
|
45464
45491
|
return [
|
|
45465
|
-
|
|
45466
|
-
" - flyctl (Fly.io CLI): https://fly.io/docs/getting-started/installing-flyctl/",
|
|
45467
|
-
" - sprite (Fly Sprites CLI): https://sprites.dev",
|
|
45468
|
-
" - gh (GitHub CLI): https://cli.github.com",
|
|
45492
|
+
'Check that required CLIs are installed by running swarp_onboard action="check_prerequisites".',
|
|
45469
45493
|
"",
|
|
45470
|
-
|
|
45494
|
+
"If any tools are missing, install them by running the provided install commands directly.",
|
|
45495
|
+
"Claude Code permissions will gate execution \u2014 just run the commands.",
|
|
45496
|
+
"After installing, re-run check_prerequisites to verify, then complete the phase."
|
|
45471
45497
|
].join("\n");
|
|
45472
45498
|
case "router":
|
|
45473
45499
|
return [
|
|
45474
45500
|
"Deploy the SWARP router to Fly.io.",
|
|
45475
45501
|
"",
|
|
45502
|
+
"Before calling swarp_deploy_router, make sure the user has:",
|
|
45503
|
+
" a. A swarp.dev CLI token in .env as SWARP_AUTH_TOKEN. If missing,",
|
|
45504
|
+
" guide them: sign in at https://swarp.dev, generate a token at",
|
|
45505
|
+
" https://swarp.dev/account, then add it to .env in this directory.",
|
|
45506
|
+
" b. flyctl installed and authenticated (fly auth login).",
|
|
45507
|
+
"",
|
|
45476
45508
|
"Steps:",
|
|
45477
|
-
|
|
45478
|
-
|
|
45479
|
-
"
|
|
45480
|
-
"
|
|
45481
|
-
|
|
45482
|
-
|
|
45483
|
-
|
|
45509
|
+
'1. Ask the user for their Fly.io org name (default: "personal")',
|
|
45510
|
+
'2. Call swarp_deploy_router with { "fly_org": "<org>" }',
|
|
45511
|
+
" The cost confirmation hook will show an estimate (~$2.09/mo)",
|
|
45512
|
+
" and ask for approval before anything is created.",
|
|
45513
|
+
" The tool is idempotent \u2014 safe to re-run if something fails.",
|
|
45514
|
+
"3. On success the tool saves router_url, fly_app, and fly_org",
|
|
45515
|
+
" to .swarp.json automatically \u2014 no additional save_config calls.",
|
|
45484
45516
|
'4. Complete: swarp_onboard action="complete_phase" phase="router"'
|
|
45485
45517
|
].join("\n");
|
|
45486
45518
|
case "secrets":
|
|
@@ -45538,6 +45570,318 @@ var onboardToolDef = {
|
|
|
45538
45570
|
}
|
|
45539
45571
|
};
|
|
45540
45572
|
|
|
45573
|
+
// src/mcp-server/deploy-router.mjs
|
|
45574
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
45575
|
+
import { mkdtempSync, writeFileSync as writeFileSync3, readFileSync as readFileSync5, existsSync as existsSync5 } from "node:fs";
|
|
45576
|
+
import { tmpdir } from "node:os";
|
|
45577
|
+
import { join as join3, resolve as resolve5 } from "node:path";
|
|
45578
|
+
var DEFAULT_SWARP_API_BASE = "https://xzcysgjzygqhfdrriibs.supabase.co";
|
|
45579
|
+
var DEFAULT_REGION = "dfw";
|
|
45580
|
+
var DEFAULT_APP_NAME_PREFIX = "swarp-router";
|
|
45581
|
+
var DEFAULT_ROUTER_IMAGE = "ghcr.io/dl3consulting/swarp-router:latest";
|
|
45582
|
+
function loadDotEnv(cwd) {
|
|
45583
|
+
const envPath = resolve5(cwd, ".env");
|
|
45584
|
+
if (!existsSync5(envPath)) return {};
|
|
45585
|
+
const content = readFileSync5(envPath, "utf-8");
|
|
45586
|
+
const out = {};
|
|
45587
|
+
for (const rawLine of content.split("\n")) {
|
|
45588
|
+
const line = rawLine.trim();
|
|
45589
|
+
if (!line || line.startsWith("#")) continue;
|
|
45590
|
+
const eqIdx = line.indexOf("=");
|
|
45591
|
+
if (eqIdx === -1) continue;
|
|
45592
|
+
const key = line.slice(0, eqIdx).trim();
|
|
45593
|
+
let value = line.slice(eqIdx + 1).trim();
|
|
45594
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
45595
|
+
value = value.slice(1, -1);
|
|
45596
|
+
}
|
|
45597
|
+
out[key] = value;
|
|
45598
|
+
}
|
|
45599
|
+
return out;
|
|
45600
|
+
}
|
|
45601
|
+
function resolveVar(name, dotEnv) {
|
|
45602
|
+
return process.env[name] ?? dotEnv[name];
|
|
45603
|
+
}
|
|
45604
|
+
var FLY_TOML_TEMPLATE = (image, appName) => `
|
|
45605
|
+
app = "${appName}"
|
|
45606
|
+
primary_region = "${DEFAULT_REGION}"
|
|
45607
|
+
|
|
45608
|
+
[build]
|
|
45609
|
+
image = "${image}"
|
|
45610
|
+
|
|
45611
|
+
[processes]
|
|
45612
|
+
router = "/usr/local/bin/swarp-router"
|
|
45613
|
+
|
|
45614
|
+
[[mounts]]
|
|
45615
|
+
source = "swarp_data"
|
|
45616
|
+
destination = "/data"
|
|
45617
|
+
processes = ["router"]
|
|
45618
|
+
|
|
45619
|
+
# gRPC router: Fly HTTP proxy terminates TLS, forwards h2c to :50051.
|
|
45620
|
+
# h2_backend is required for gRPC \u2014 tells Fly to speak HTTP/2 to the backend.
|
|
45621
|
+
[http_service]
|
|
45622
|
+
internal_port = 50051
|
|
45623
|
+
processes = ["router"]
|
|
45624
|
+
force_https = true
|
|
45625
|
+
[http_service.http_options]
|
|
45626
|
+
h2_backend = true
|
|
45627
|
+
`.trim() + "\n";
|
|
45628
|
+
function flyctl(args, opts = {}) {
|
|
45629
|
+
try {
|
|
45630
|
+
return execFileSync2("flyctl", args, {
|
|
45631
|
+
encoding: "utf-8",
|
|
45632
|
+
timeout: opts.timeout ?? 6e4,
|
|
45633
|
+
stdio: opts.stdio ?? ["ignore", "pipe", "pipe"],
|
|
45634
|
+
...opts
|
|
45635
|
+
});
|
|
45636
|
+
} catch (err) {
|
|
45637
|
+
const stderr = err.stderr?.toString() ?? "";
|
|
45638
|
+
const stdout = err.stdout?.toString() ?? "";
|
|
45639
|
+
const message = stderr || stdout || err.message;
|
|
45640
|
+
throw new Error(`flyctl ${args[0]} failed: ${message.trim()}`);
|
|
45641
|
+
}
|
|
45642
|
+
}
|
|
45643
|
+
async function provisionInstallSecret({ authToken, apiBase, flyOrg, flyApp }) {
|
|
45644
|
+
const url = `${apiBase}/functions/v1/swarp-install-provision`;
|
|
45645
|
+
const res = await fetch(url, {
|
|
45646
|
+
method: "POST",
|
|
45647
|
+
headers: {
|
|
45648
|
+
Authorization: `Bearer ${authToken}`,
|
|
45649
|
+
"Content-Type": "application/json"
|
|
45650
|
+
},
|
|
45651
|
+
body: JSON.stringify({ fly_org: flyOrg, fly_app: flyApp })
|
|
45652
|
+
});
|
|
45653
|
+
if (!res.ok) {
|
|
45654
|
+
const body = await res.text();
|
|
45655
|
+
throw new Error(`swarp.dev provision failed: ${res.status} ${body}`);
|
|
45656
|
+
}
|
|
45657
|
+
return res.json();
|
|
45658
|
+
}
|
|
45659
|
+
function appExists(appName) {
|
|
45660
|
+
try {
|
|
45661
|
+
const output = flyctl(["apps", "list", "--json"]);
|
|
45662
|
+
const apps = JSON.parse(output);
|
|
45663
|
+
return apps.some((a) => (a.Name ?? a.name) === appName);
|
|
45664
|
+
} catch {
|
|
45665
|
+
return false;
|
|
45666
|
+
}
|
|
45667
|
+
}
|
|
45668
|
+
function volumeExists(appName) {
|
|
45669
|
+
try {
|
|
45670
|
+
const output = flyctl(["volumes", "list", "--app", appName, "--json"]);
|
|
45671
|
+
const volumes = JSON.parse(output);
|
|
45672
|
+
return volumes.some((v) => v.name === "swarp_data" || v.Name === "swarp_data");
|
|
45673
|
+
} catch {
|
|
45674
|
+
return false;
|
|
45675
|
+
}
|
|
45676
|
+
}
|
|
45677
|
+
function createApp(appName, flyOrg) {
|
|
45678
|
+
flyctl(["apps", "create", appName, "--org", flyOrg], { timeout: 3e4 });
|
|
45679
|
+
}
|
|
45680
|
+
function createVolume(appName, region) {
|
|
45681
|
+
flyctl([
|
|
45682
|
+
"volumes",
|
|
45683
|
+
"create",
|
|
45684
|
+
"swarp_data",
|
|
45685
|
+
"--app",
|
|
45686
|
+
appName,
|
|
45687
|
+
"--region",
|
|
45688
|
+
region,
|
|
45689
|
+
"--size",
|
|
45690
|
+
"1",
|
|
45691
|
+
"--yes"
|
|
45692
|
+
], { timeout: 6e4 });
|
|
45693
|
+
}
|
|
45694
|
+
function setSecret(appName, key, value) {
|
|
45695
|
+
execFileSync2(
|
|
45696
|
+
"flyctl",
|
|
45697
|
+
["secrets", "set", "--app", appName, "--stage", `${key}=${value}`],
|
|
45698
|
+
{ stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 }
|
|
45699
|
+
);
|
|
45700
|
+
}
|
|
45701
|
+
function deploy(configPath, appName) {
|
|
45702
|
+
flyctl([
|
|
45703
|
+
"deploy",
|
|
45704
|
+
"--config",
|
|
45705
|
+
configPath,
|
|
45706
|
+
"--app",
|
|
45707
|
+
appName,
|
|
45708
|
+
"--now",
|
|
45709
|
+
"--ha=false"
|
|
45710
|
+
], { timeout: 6e5 });
|
|
45711
|
+
}
|
|
45712
|
+
function getAppUrl(appName) {
|
|
45713
|
+
try {
|
|
45714
|
+
const output = flyctl(["status", "--app", appName, "--json"]);
|
|
45715
|
+
const status = JSON.parse(output);
|
|
45716
|
+
return status.Hostname ?? status.hostname ?? `${appName}.fly.dev`;
|
|
45717
|
+
} catch {
|
|
45718
|
+
return `${appName}.fly.dev`;
|
|
45719
|
+
}
|
|
45720
|
+
}
|
|
45721
|
+
function writeSwarpConfig(configPath, updates) {
|
|
45722
|
+
const existing = existsSync5(configPath) ? JSON.parse(readFileSync5(configPath, "utf-8")) : {};
|
|
45723
|
+
const merged = { ...existing, ...updates };
|
|
45724
|
+
writeFileSync3(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
45725
|
+
return merged;
|
|
45726
|
+
}
|
|
45727
|
+
async function handleDeployRouter(toolArgs) {
|
|
45728
|
+
const { fly_org: flyOrg, app_name: appNameInput, region = DEFAULT_REGION } = toolArgs ?? {};
|
|
45729
|
+
if (!flyOrg) {
|
|
45730
|
+
return {
|
|
45731
|
+
content: [{ type: "text", text: 'Error: fly_org is required. Example: { "fly_org": "personal" }' }],
|
|
45732
|
+
isError: true
|
|
45733
|
+
};
|
|
45734
|
+
}
|
|
45735
|
+
const dotEnv = loadDotEnv(process.cwd());
|
|
45736
|
+
const authToken = resolveVar("SWARP_AUTH_TOKEN", dotEnv);
|
|
45737
|
+
if (!authToken) {
|
|
45738
|
+
return {
|
|
45739
|
+
content: [{
|
|
45740
|
+
type: "text",
|
|
45741
|
+
text: [
|
|
45742
|
+
"Error: SWARP_AUTH_TOKEN is not set.",
|
|
45743
|
+
"",
|
|
45744
|
+
"The plugin needs your swarp.dev session token to fetch a unique",
|
|
45745
|
+
"HMAC signing key for your router. To generate it:",
|
|
45746
|
+
"",
|
|
45747
|
+
" 1. Sign in at https://swarp.dev with your Google account",
|
|
45748
|
+
' 2. Go to https://swarp.dev/account and click "Generate CLI token"',
|
|
45749
|
+
" 3. Copy the token and add it to a .env file in this directory:",
|
|
45750
|
+
"",
|
|
45751
|
+
` echo 'SWARP_AUTH_TOKEN="<paste-token-here>"' >> .env`,
|
|
45752
|
+
"",
|
|
45753
|
+
" 4. Re-run swarp_deploy_router",
|
|
45754
|
+
"",
|
|
45755
|
+
"The token grants the plugin permission to provision and retrieve",
|
|
45756
|
+
"install secrets on your behalf. Treat it like a password \u2014 never",
|
|
45757
|
+
"commit .env to git (it should be in .gitignore already)."
|
|
45758
|
+
].join("\n")
|
|
45759
|
+
}],
|
|
45760
|
+
isError: true
|
|
45761
|
+
};
|
|
45762
|
+
}
|
|
45763
|
+
const routerImage = resolveVar("SWARP_ROUTER_IMAGE", dotEnv) ?? DEFAULT_ROUTER_IMAGE;
|
|
45764
|
+
try {
|
|
45765
|
+
flyctl(["auth", "whoami"], { timeout: 1e4 });
|
|
45766
|
+
} catch {
|
|
45767
|
+
return {
|
|
45768
|
+
content: [{
|
|
45769
|
+
type: "text",
|
|
45770
|
+
text: "Error: flyctl is not authenticated. Run: fly auth login"
|
|
45771
|
+
}],
|
|
45772
|
+
isError: true
|
|
45773
|
+
};
|
|
45774
|
+
}
|
|
45775
|
+
const apiBase = resolveVar("SWARP_API_BASE", dotEnv) ?? DEFAULT_SWARP_API_BASE;
|
|
45776
|
+
const appName = appNameInput ?? DEFAULT_APP_NAME_PREFIX;
|
|
45777
|
+
const configPath = resolve5(".swarp.json");
|
|
45778
|
+
const steps = [];
|
|
45779
|
+
try {
|
|
45780
|
+
steps.push("\u2192 Fetching install secret from swarp.dev...");
|
|
45781
|
+
const install = await provisionInstallSecret({
|
|
45782
|
+
authToken,
|
|
45783
|
+
apiBase,
|
|
45784
|
+
flyOrg,
|
|
45785
|
+
flyApp: appName
|
|
45786
|
+
});
|
|
45787
|
+
steps.push(` ${install.existed ? "\u21BB Reusing existing install secret" : "\u2713 New install secret provisioned"}`);
|
|
45788
|
+
const exists = appExists(appName);
|
|
45789
|
+
if (exists) {
|
|
45790
|
+
steps.push(` \u21BB Fly app "${appName}" already exists \u2014 skipping create`);
|
|
45791
|
+
} else {
|
|
45792
|
+
steps.push(`\u2192 Creating Fly app "${appName}" in org "${flyOrg}"...`);
|
|
45793
|
+
createApp(appName, flyOrg);
|
|
45794
|
+
steps.push(" \u2713 App created");
|
|
45795
|
+
}
|
|
45796
|
+
if (!volumeExists(appName)) {
|
|
45797
|
+
steps.push('\u2192 Creating 1GB volume "swarp_data"...');
|
|
45798
|
+
createVolume(appName, region);
|
|
45799
|
+
steps.push(" \u2713 Volume created");
|
|
45800
|
+
} else {
|
|
45801
|
+
steps.push(' \u21BB Volume "swarp_data" already exists');
|
|
45802
|
+
}
|
|
45803
|
+
steps.push("\u2192 Setting SUPABASE_JWT_SECRET (staged)...");
|
|
45804
|
+
setSecret(appName, "SUPABASE_JWT_SECRET", install.jwt_secret);
|
|
45805
|
+
steps.push(" \u2713 Secret staged");
|
|
45806
|
+
const tmpDir = mkdtempSync(join3(tmpdir(), "swarp-deploy-"));
|
|
45807
|
+
const tomlPath = join3(tmpDir, "fly.toml");
|
|
45808
|
+
writeFileSync3(tomlPath, FLY_TOML_TEMPLATE(routerImage, appName), "utf-8");
|
|
45809
|
+
steps.push(`\u2192 Deploying router image ${routerImage}...`);
|
|
45810
|
+
deploy(tomlPath, appName);
|
|
45811
|
+
steps.push(" \u2713 Deploy complete");
|
|
45812
|
+
const hostname2 = getAppUrl(appName);
|
|
45813
|
+
const routerUrl = `${hostname2}:443`;
|
|
45814
|
+
writeSwarpConfig(configPath, {
|
|
45815
|
+
router_url: routerUrl,
|
|
45816
|
+
fly_app: appName,
|
|
45817
|
+
fly_org: flyOrg
|
|
45818
|
+
});
|
|
45819
|
+
try {
|
|
45820
|
+
await provisionInstallSecret({
|
|
45821
|
+
authToken,
|
|
45822
|
+
apiBase,
|
|
45823
|
+
flyOrg,
|
|
45824
|
+
flyApp: appName
|
|
45825
|
+
});
|
|
45826
|
+
} catch (err) {
|
|
45827
|
+
steps.push(` \u26A0 Could not update swarp.dev with final URL: ${err.message}`);
|
|
45828
|
+
}
|
|
45829
|
+
return {
|
|
45830
|
+
content: [{
|
|
45831
|
+
type: "text",
|
|
45832
|
+
text: [
|
|
45833
|
+
...steps,
|
|
45834
|
+
"",
|
|
45835
|
+
`Router deployed: https://${hostname2}`,
|
|
45836
|
+
`gRPC endpoint: ${routerUrl}`,
|
|
45837
|
+
"",
|
|
45838
|
+
"Config saved to .swarp.json.",
|
|
45839
|
+
'Run swarp_onboard action="complete_phase" phase="router" to advance.'
|
|
45840
|
+
].join("\n")
|
|
45841
|
+
}]
|
|
45842
|
+
};
|
|
45843
|
+
} catch (err) {
|
|
45844
|
+
return {
|
|
45845
|
+
content: [{
|
|
45846
|
+
type: "text",
|
|
45847
|
+
text: [
|
|
45848
|
+
...steps,
|
|
45849
|
+
"",
|
|
45850
|
+
`Error: ${err.message}`,
|
|
45851
|
+
"",
|
|
45852
|
+
"You can re-run this tool \u2014 it is idempotent (existing apps and volumes are skipped)."
|
|
45853
|
+
].join("\n")
|
|
45854
|
+
}],
|
|
45855
|
+
isError: true
|
|
45856
|
+
};
|
|
45857
|
+
}
|
|
45858
|
+
}
|
|
45859
|
+
var deployRouterToolDef = {
|
|
45860
|
+
name: "swarp_deploy_router",
|
|
45861
|
+
description: "Deploy the SWARP gRPC router to Fly.io. Creates the app, volume, and machine, sets the per-user install secret, and saves router_url to .swarp.json. Idempotent. Requires flyctl installed and authenticated, and SWARP_AUTH_TOKEN set in a .env file in the project directory (generate the token at https://swarp.dev/account).",
|
|
45862
|
+
inputSchema: {
|
|
45863
|
+
type: "object",
|
|
45864
|
+
properties: {
|
|
45865
|
+
fly_org: {
|
|
45866
|
+
type: "string",
|
|
45867
|
+
description: 'Fly.io organization slug to deploy into (e.g. "personal")'
|
|
45868
|
+
},
|
|
45869
|
+
app_name: {
|
|
45870
|
+
type: "string",
|
|
45871
|
+
description: 'Fly app name (default: "swarp-router")'
|
|
45872
|
+
},
|
|
45873
|
+
region: {
|
|
45874
|
+
type: "string",
|
|
45875
|
+
description: 'Fly region code (default: "dfw")'
|
|
45876
|
+
}
|
|
45877
|
+
},
|
|
45878
|
+
required: ["fly_org"]
|
|
45879
|
+
},
|
|
45880
|
+
annotations: {
|
|
45881
|
+
destructiveHint: true
|
|
45882
|
+
}
|
|
45883
|
+
};
|
|
45884
|
+
|
|
45541
45885
|
// src/mcp-server/index.mjs
|
|
45542
45886
|
async function startMcpServer() {
|
|
45543
45887
|
let config2 = {};
|
|
@@ -45566,8 +45910,9 @@ async function startMcpServer() {
|
|
|
45566
45910
|
}
|
|
45567
45911
|
}
|
|
45568
45912
|
const localTools = client ? buildLocalTools(config2) : [];
|
|
45913
|
+
const onboardingTools = [onboardToolDef, deployRouterToolDef];
|
|
45569
45914
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
45570
|
-
return { tools: [
|
|
45915
|
+
return { tools: [...onboardingTools, ...agentTools, ...localTools] };
|
|
45571
45916
|
});
|
|
45572
45917
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
45573
45918
|
const { name, arguments: toolArgs } = req.params;
|
|
@@ -45576,6 +45921,7 @@ async function startMcpServer() {
|
|
|
45576
45921
|
return handleAgentDispatch(client, agent.name, toolArgs);
|
|
45577
45922
|
}
|
|
45578
45923
|
if (name === "swarp_onboard") return handleOnboard(toolArgs);
|
|
45924
|
+
if (name === "swarp_deploy_router") return handleDeployRouter(toolArgs);
|
|
45579
45925
|
if (name === "swarm_audit") return handleAudit(config2, toolArgs);
|
|
45580
45926
|
if (name === "swarm_generate") return handleGenerate(config2, toolArgs);
|
|
45581
45927
|
if (name === "swarm_status") return handleStatus(client, toolArgs);
|
|
@@ -45753,19 +46099,19 @@ async function handleDeploy(config2, toolArgs) {
|
|
|
45753
46099
|
};
|
|
45754
46100
|
}
|
|
45755
46101
|
try {
|
|
45756
|
-
const { readFileSync:
|
|
45757
|
-
const { resolve:
|
|
46102
|
+
const { readFileSync: readFileSync6, existsSync: existsSync6 } = await import("node:fs");
|
|
46103
|
+
const { resolve: resolve6, join: join4 } = await import("node:path");
|
|
45758
46104
|
const yaml = (await Promise.resolve().then(() => (init_js_yaml(), js_yaml_exports))).default;
|
|
45759
46105
|
const { FlySpriteAdapter: FlySpriteAdapter2 } = await Promise.resolve().then(() => (init_fly_sprites(), fly_sprites_exports));
|
|
45760
|
-
const agentsDir =
|
|
45761
|
-
const yamlPath =
|
|
45762
|
-
if (!
|
|
46106
|
+
const agentsDir = resolve6(config2.agents_dir ?? "agents");
|
|
46107
|
+
const yamlPath = join4(agentsDir, agentName, "agent.yaml");
|
|
46108
|
+
if (!existsSync6(yamlPath)) {
|
|
45763
46109
|
return {
|
|
45764
46110
|
content: [{ type: "text", text: `Error: agent.yaml not found at ${yamlPath}` }],
|
|
45765
46111
|
isError: true
|
|
45766
46112
|
};
|
|
45767
46113
|
}
|
|
45768
|
-
const agentConfig = yaml.load(
|
|
46114
|
+
const agentConfig = yaml.load(readFileSync6(yamlPath, "utf-8"));
|
|
45769
46115
|
const adapter = new FlySpriteAdapter2(token);
|
|
45770
46116
|
await adapter.createAgent(agentName, agentConfig);
|
|
45771
46117
|
return { content: [{ type: "text", text: `Deployed ${agentName}` }] };
|