gogcli-mcp 4.0.0 → 4.1.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/SKILL.md +1 -1
- package/dist/index.js +886 -228
- package/dist/lib.js +203 -201
- package/manifest.json +2 -2
- package/mint.yaml +4 -4
- package/package.json +2 -2
- package/server.json +2 -2
- package/skills/gogcli/SKILL.md +1 -1
- package/src/runner.ts +4 -1
- package/tests/runner.test.ts +45 -1
package/dist/index.js
CHANGED
|
@@ -20845,6 +20845,7 @@ function missingClientCapabilities(required2, declared) {
|
|
|
20845
20845
|
return Object.keys(missing).length > 0 ? missing : void 0;
|
|
20846
20846
|
}
|
|
20847
20847
|
var FIRST_MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
20848
|
+
var SUPPORTED_MODERN_PROTOCOL_VERSIONS = [FIRST_MODERN_PROTOCOL_VERSION];
|
|
20848
20849
|
function isModernProtocolVersion(version2) {
|
|
20849
20850
|
return version2 >= FIRST_MODERN_PROTOCOL_VERSION;
|
|
20850
20851
|
}
|
|
@@ -23403,6 +23404,25 @@ function isSpecNotificationMethod(method) {
|
|
|
23403
23404
|
return ALL_CODECS.some((codec2) => codec2.hasNotificationMethod(method));
|
|
23404
23405
|
}
|
|
23405
23406
|
var ALL_CODECS = [rev2025Codec, rev2026Codec];
|
|
23407
|
+
function isPlainObject$3(value) {
|
|
23408
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
23409
|
+
}
|
|
23410
|
+
function requestMetaOf(params) {
|
|
23411
|
+
if (!isPlainObject$3(params)) return void 0;
|
|
23412
|
+
const meta3 = params["_meta"];
|
|
23413
|
+
return isPlainObject$3(meta3) ? meta3 : void 0;
|
|
23414
|
+
}
|
|
23415
|
+
function hasEnvelopeClaim(params) {
|
|
23416
|
+
const meta3 = requestMetaOf(params);
|
|
23417
|
+
return meta3 !== void 0 && PROTOCOL_VERSION_META_KEY in meta3;
|
|
23418
|
+
}
|
|
23419
|
+
function envelopeClaimVersion(params) {
|
|
23420
|
+
const value = requestMetaOf(params)?.[PROTOCOL_VERSION_META_KEY];
|
|
23421
|
+
return typeof value === "string" ? value : void 0;
|
|
23422
|
+
}
|
|
23423
|
+
function validateEnvelopeMeta(meta3) {
|
|
23424
|
+
return codecForVersion(MODERN_WIRE_REVISION).validateEnvelopeMeta(meta3);
|
|
23425
|
+
}
|
|
23406
23426
|
var schemas_exports3 = /* @__PURE__ */ __exportAll({
|
|
23407
23427
|
AnnotationsSchema: () => AnnotationsSchema,
|
|
23408
23428
|
AudioContentSchema: () => AudioContentSchema,
|
|
@@ -23753,6 +23773,45 @@ var LADDER_ERROR_HTTP_STATUS = {
|
|
|
23753
23773
|
[ProtocolErrorCode.MissingRequiredClientCapability]: 400,
|
|
23754
23774
|
[HEADER_MISMATCH_ERROR_CODE]: 400
|
|
23755
23775
|
};
|
|
23776
|
+
function rejection(rung, cell, httpStatus, error62, settled) {
|
|
23777
|
+
return {
|
|
23778
|
+
kind: "reject",
|
|
23779
|
+
rung,
|
|
23780
|
+
cell,
|
|
23781
|
+
httpStatus,
|
|
23782
|
+
code: error62.code,
|
|
23783
|
+
message: error62.message,
|
|
23784
|
+
...error62.data !== void 0 && { data: error62.data },
|
|
23785
|
+
settled
|
|
23786
|
+
};
|
|
23787
|
+
}
|
|
23788
|
+
function carriesValidModernEnvelopeClaim(params) {
|
|
23789
|
+
if (!hasEnvelopeClaim(params)) return false;
|
|
23790
|
+
const claimedVersion = envelopeClaimVersion(params);
|
|
23791
|
+
if (claimedVersion === void 0 || !isModernProtocolVersion(claimedVersion)) return false;
|
|
23792
|
+
const meta3 = requestMetaOf(params);
|
|
23793
|
+
return meta3 !== void 0 && validateEnvelopeMeta(meta3).length === 0;
|
|
23794
|
+
}
|
|
23795
|
+
function modernOnlyStrictRejection(route, supportedVersions) {
|
|
23796
|
+
switch (route.reason) {
|
|
23797
|
+
case "http-method":
|
|
23798
|
+
return rejection("http-method", "modern-only-method-not-allowed", 405, new ProtocolError(-32e3, "Method not allowed."), true);
|
|
23799
|
+
case "batch":
|
|
23800
|
+
return rejection("jsonrpc-shape", "modern-only-batch-not-supported", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC batches are not supported by this endpoint"), true);
|
|
23801
|
+
case "response":
|
|
23802
|
+
return rejection("jsonrpc-shape", "modern-only-response-post", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC responses cannot be posted to this endpoint"), true);
|
|
23803
|
+
case "notification":
|
|
23804
|
+
return;
|
|
23805
|
+
case "initialize":
|
|
23806
|
+
case "no-claim": {
|
|
23807
|
+
const requested = route.requestedVersion;
|
|
23808
|
+
return rejection("era-classification", "modern-only-missing-envelope", 400, requested === void 0 ? new ProtocolError(ProtocolErrorCode.UnsupportedProtocolVersion, "Unsupported protocol version: the request did not name a protocol version", { supported: [...supportedVersions] }) : new UnsupportedProtocolVersionError({
|
|
23809
|
+
supported: [...supportedVersions],
|
|
23810
|
+
requested
|
|
23811
|
+
}), true);
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23814
|
+
}
|
|
23756
23815
|
function parseSchema(schema, data) {
|
|
23757
23816
|
return safeParse2(schema, data);
|
|
23758
23817
|
}
|
|
@@ -24345,6 +24404,9 @@ function withRequestStateValue(ctx, value) {
|
|
|
24345
24404
|
};
|
|
24346
24405
|
}
|
|
24347
24406
|
var writeNegotiatedProtocolVersion;
|
|
24407
|
+
function setNegotiatedProtocolVersion(instance, version2) {
|
|
24408
|
+
writeNegotiatedProtocolVersion(instance, version2);
|
|
24409
|
+
}
|
|
24348
24410
|
var Protocol = class {
|
|
24349
24411
|
_transport;
|
|
24350
24412
|
_requestMessageId = 0;
|
|
@@ -32288,6 +32350,190 @@ function getCompleter(schema) {
|
|
|
32288
32350
|
return schema[COMPLETABLE_SYMBOL]?.complete;
|
|
32289
32351
|
}
|
|
32290
32352
|
var MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
32353
|
+
function listenFilterAccepts(filter, event) {
|
|
32354
|
+
switch (event.kind) {
|
|
32355
|
+
case "tools_list_changed":
|
|
32356
|
+
return filter.toolsListChanged === true;
|
|
32357
|
+
case "prompts_list_changed":
|
|
32358
|
+
return filter.promptsListChanged === true;
|
|
32359
|
+
case "resources_list_changed":
|
|
32360
|
+
return filter.resourcesListChanged === true;
|
|
32361
|
+
case "resource_updated":
|
|
32362
|
+
return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
32363
|
+
}
|
|
32364
|
+
}
|
|
32365
|
+
function honoredSubset(requested, capabilities) {
|
|
32366
|
+
const honored = {};
|
|
32367
|
+
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
32368
|
+
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
32369
|
+
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
32370
|
+
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
32371
|
+
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
32372
|
+
return honored;
|
|
32373
|
+
}
|
|
32374
|
+
var DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
32375
|
+
function stampSubscriptionId(notification, subscriptionId) {
|
|
32376
|
+
return {
|
|
32377
|
+
method: notification.method,
|
|
32378
|
+
params: {
|
|
32379
|
+
...notification.params,
|
|
32380
|
+
_meta: {
|
|
32381
|
+
...notification.params?._meta,
|
|
32382
|
+
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
32383
|
+
}
|
|
32384
|
+
}
|
|
32385
|
+
};
|
|
32386
|
+
}
|
|
32387
|
+
function parseListenFilter(message) {
|
|
32388
|
+
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
32389
|
+
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
32390
|
+
}
|
|
32391
|
+
var CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
32392
|
+
"notifications/tools/list_changed",
|
|
32393
|
+
"notifications/prompts/list_changed",
|
|
32394
|
+
"notifications/resources/list_changed",
|
|
32395
|
+
"notifications/resources/updated"
|
|
32396
|
+
]);
|
|
32397
|
+
var StdioListenRouter = class {
|
|
32398
|
+
/** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
|
|
32399
|
+
_subs = /* @__PURE__ */ new Map();
|
|
32400
|
+
/**
|
|
32401
|
+
* The serving instance's declared capabilities. Filled in by the entry
|
|
32402
|
+
* once the modern instance is constructed (the router is created before
|
|
32403
|
+
* the instance exists), so the acknowledged filter is narrowed against
|
|
32404
|
+
* what the server can actually deliver.
|
|
32405
|
+
*/
|
|
32406
|
+
_serverCapabilities;
|
|
32407
|
+
/**
|
|
32408
|
+
* The serving instance's identity, stamped onto the graceful-close
|
|
32409
|
+
* results' `_meta` (the spec's `SubscriptionsListenResultMeta` extends
|
|
32410
|
+
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
32411
|
+
*/
|
|
32412
|
+
_serverInfo;
|
|
32413
|
+
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
32414
|
+
this._maxSubscriptions = _maxSubscriptions;
|
|
32415
|
+
this._serverCapabilities = serverCapabilities;
|
|
32416
|
+
this._serverInfo = serverInfo;
|
|
32417
|
+
}
|
|
32418
|
+
/**
|
|
32419
|
+
* Record the serving instance's declared capabilities and identity once
|
|
32420
|
+
* it has been constructed. Called by `serveStdio`'s connect path;
|
|
32421
|
+
* subsequent `serve()` calls narrow the honored filter against the
|
|
32422
|
+
* capabilities, and `teardownAll()` stamps the identity.
|
|
32423
|
+
*/
|
|
32424
|
+
setServerCapabilities(capabilities, serverInfo) {
|
|
32425
|
+
this._serverCapabilities = capabilities;
|
|
32426
|
+
if (serverInfo !== void 0) this._serverInfo = serverInfo;
|
|
32427
|
+
}
|
|
32428
|
+
/** Whether `id` is an active listen subscription on this connection. */
|
|
32429
|
+
has(id) {
|
|
32430
|
+
return this._subs.has(id);
|
|
32431
|
+
}
|
|
32432
|
+
/**
|
|
32433
|
+
* Serve one inbound `subscriptions/listen` request: registers the
|
|
32434
|
+
* subscription and returns the stamped acknowledged notification (or, on
|
|
32435
|
+
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
32436
|
+
*
|
|
32437
|
+
* @throws when called before {@linkcode setServerCapabilities} (or the
|
|
32438
|
+
* constructor) has supplied the serving instance's capabilities. Honoring a
|
|
32439
|
+
* filter without knowing the server's advertised capabilities would fail
|
|
32440
|
+
* open (deliver unadvertised types); the entry guarantees capabilities are
|
|
32441
|
+
* set before any listen request is routed here.
|
|
32442
|
+
*/
|
|
32443
|
+
serve(message) {
|
|
32444
|
+
if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
|
|
32445
|
+
if (this._subs.size >= this._maxSubscriptions) return {
|
|
32446
|
+
jsonrpc: "2.0",
|
|
32447
|
+
id: message.id,
|
|
32448
|
+
error: {
|
|
32449
|
+
code: -32603,
|
|
32450
|
+
message: "Subscription limit reached"
|
|
32451
|
+
}
|
|
32452
|
+
};
|
|
32453
|
+
const filter = parseListenFilter(message);
|
|
32454
|
+
if (filter === void 0) return {
|
|
32455
|
+
jsonrpc: "2.0",
|
|
32456
|
+
id: message.id,
|
|
32457
|
+
error: {
|
|
32458
|
+
code: -32602,
|
|
32459
|
+
message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
|
|
32460
|
+
}
|
|
32461
|
+
};
|
|
32462
|
+
const honored = honoredSubset(filter, this._serverCapabilities);
|
|
32463
|
+
this._subs.set(message.id, honored);
|
|
32464
|
+
return stampSubscriptionId({
|
|
32465
|
+
method: "notifications/subscriptions/acknowledged",
|
|
32466
|
+
params: { notifications: honored }
|
|
32467
|
+
}, message.id);
|
|
32468
|
+
}
|
|
32469
|
+
/**
|
|
32470
|
+
* Tear down one subscription (inbound `notifications/cancelled`). Returns
|
|
32471
|
+
* `true` when a subscription was removed. After this call NOTHING further
|
|
32472
|
+
* is delivered for that subscription id (the post-cancel hardening).
|
|
32473
|
+
*/
|
|
32474
|
+
cancel(id) {
|
|
32475
|
+
return this._subs.delete(id);
|
|
32476
|
+
}
|
|
32477
|
+
/**
|
|
32478
|
+
* Route an outbound notification through the active subscriptions.
|
|
32479
|
+
*
|
|
32480
|
+
* - For a subscription-gated change notification, returns one stamped copy
|
|
32481
|
+
* per subscription that opted in to it (an empty array means it is
|
|
32482
|
+
* dropped — the modern era never delivers an un-requested change type).
|
|
32483
|
+
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
32484
|
+
* forwards it as-is).
|
|
32485
|
+
*/
|
|
32486
|
+
routeOutbound(message) {
|
|
32487
|
+
if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
|
|
32488
|
+
const uriParam = message.params?.["uri"];
|
|
32489
|
+
const uri = typeof uriParam === "string" ? uriParam : void 0;
|
|
32490
|
+
const event = notificationToServerEvent(message.method, uri);
|
|
32491
|
+
const out = [];
|
|
32492
|
+
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
32493
|
+
method: message.method,
|
|
32494
|
+
params: message.params ?? {}
|
|
32495
|
+
}, subscriptionId));
|
|
32496
|
+
return out;
|
|
32497
|
+
}
|
|
32498
|
+
/**
|
|
32499
|
+
* Server-side graceful teardown of every active subscription: returns the
|
|
32500
|
+
* empty `subscriptions/listen` JSON-RPC result for each subscription id —
|
|
32501
|
+
* the spec's graceful-close signal, `_meta` carrying the subscription id
|
|
32502
|
+
* and the serving instance's identity — for the entry to emit before
|
|
32503
|
+
* closing the wire. Clears the set so nothing further is delivered.
|
|
32504
|
+
*/
|
|
32505
|
+
teardownAll() {
|
|
32506
|
+
const out = [];
|
|
32507
|
+
for (const id of this._subs.keys()) out.push({
|
|
32508
|
+
jsonrpc: "2.0",
|
|
32509
|
+
id,
|
|
32510
|
+
result: {
|
|
32511
|
+
resultType: "complete",
|
|
32512
|
+
_meta: {
|
|
32513
|
+
[SUBSCRIPTION_ID_META_KEY]: id,
|
|
32514
|
+
...this._serverInfo !== void 0 && { [SERVER_INFO_META_KEY]: this._serverInfo }
|
|
32515
|
+
}
|
|
32516
|
+
}
|
|
32517
|
+
});
|
|
32518
|
+
this._subs.clear();
|
|
32519
|
+
return out;
|
|
32520
|
+
}
|
|
32521
|
+
};
|
|
32522
|
+
function notificationToServerEvent(method, uri) {
|
|
32523
|
+
switch (method) {
|
|
32524
|
+
case "notifications/tools/list_changed":
|
|
32525
|
+
return { kind: "tools_list_changed" };
|
|
32526
|
+
case "notifications/prompts/list_changed":
|
|
32527
|
+
return { kind: "prompts_list_changed" };
|
|
32528
|
+
case "notifications/resources/list_changed":
|
|
32529
|
+
return { kind: "resources_list_changed" };
|
|
32530
|
+
default:
|
|
32531
|
+
return {
|
|
32532
|
+
kind: "resource_updated",
|
|
32533
|
+
uri: uri ?? ""
|
|
32534
|
+
};
|
|
32535
|
+
}
|
|
32536
|
+
}
|
|
32291
32537
|
var DEFAULT_LEGACY_SHIM_MAX_ROUNDS = 8;
|
|
32292
32538
|
var DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS = 6e5;
|
|
32293
32539
|
function resolveLegacyShimOptions(options) {
|
|
@@ -32425,6 +32671,12 @@ var INPUT_REQUIRED_CAPABLE_METHODS = /* @__PURE__ */ new Set([
|
|
|
32425
32671
|
var writeClientIdentity;
|
|
32426
32672
|
var installDiscoverHandler;
|
|
32427
32673
|
var readServerIdentity;
|
|
32674
|
+
function installModernOnlyHandlers(server, servedModernVersions) {
|
|
32675
|
+
installDiscoverHandler(server, servedModernVersions);
|
|
32676
|
+
}
|
|
32677
|
+
function serverIdentityOf(server) {
|
|
32678
|
+
return readServerIdentity(server);
|
|
32679
|
+
}
|
|
32428
32680
|
var Server = class extends Protocol {
|
|
32429
32681
|
_clientCapabilities;
|
|
32430
32682
|
_clientVersion;
|
|
@@ -33699,6 +33951,400 @@ var StdioServerTransport = class {
|
|
|
33699
33951
|
});
|
|
33700
33952
|
}
|
|
33701
33953
|
};
|
|
33954
|
+
var DISCARD_ANSWER_TIMEOUT_MS = 3e3;
|
|
33955
|
+
var StdioConnectionChannel = class {
|
|
33956
|
+
onclose;
|
|
33957
|
+
onerror;
|
|
33958
|
+
onmessage;
|
|
33959
|
+
_closed = false;
|
|
33960
|
+
/** Request ids the entry delivered to the instance that the instance has not yet answered. */
|
|
33961
|
+
_pendingRequests = /* @__PURE__ */ new Set();
|
|
33962
|
+
_drainWaiters = [];
|
|
33963
|
+
constructor(_wire, _onInstanceClose, _outboundIntercept) {
|
|
33964
|
+
this._wire = _wire;
|
|
33965
|
+
this._onInstanceClose = _onInstanceClose;
|
|
33966
|
+
this._outboundIntercept = _outboundIntercept;
|
|
33967
|
+
}
|
|
33968
|
+
async start() {
|
|
33969
|
+
}
|
|
33970
|
+
async send(message, options) {
|
|
33971
|
+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
|
|
33972
|
+
const { id } = message;
|
|
33973
|
+
if (id !== void 0) this._settle(id);
|
|
33974
|
+
}
|
|
33975
|
+
if (this._closed) return;
|
|
33976
|
+
if (this._outboundIntercept?.(message) === "handled") return;
|
|
33977
|
+
return this._wire.send(message, options);
|
|
33978
|
+
}
|
|
33979
|
+
setProtocolVersion = (version2) => {
|
|
33980
|
+
this._wire.setProtocolVersion?.(version2);
|
|
33981
|
+
};
|
|
33982
|
+
/** Forwards one inbound message to the connected instance. */
|
|
33983
|
+
deliver(message, extra) {
|
|
33984
|
+
if (this._closed) return;
|
|
33985
|
+
if (isJSONRPCRequest(message)) this._pendingRequests.add(message.id);
|
|
33986
|
+
else if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
|
|
33987
|
+
const cancelledId = message.params?.requestId;
|
|
33988
|
+
if (cancelledId !== void 0) this._settle(cancelledId);
|
|
33989
|
+
}
|
|
33990
|
+
this.onmessage?.(message, extra);
|
|
33991
|
+
}
|
|
33992
|
+
/**
|
|
33993
|
+
* Resolves once every request delivered to the instance has been answered
|
|
33994
|
+
* through {@linkcode send}, settled by a delivered cancellation, or the
|
|
33995
|
+
* channel has been closed and nothing further can be answered. The wait is
|
|
33996
|
+
* bounded by `timeoutMs` as a backstop so no edge can hold the caller
|
|
33997
|
+
* indefinitely; resolves `false` only when the bound elapsed with requests
|
|
33998
|
+
* still unanswered. Used by the probe-discard path so a probe request the
|
|
33999
|
+
* entry accepted is never silently dropped.
|
|
34000
|
+
*/
|
|
34001
|
+
async whenRequestsAnswered(timeoutMs) {
|
|
34002
|
+
if (this._closed || this._pendingRequests.size === 0) return true;
|
|
34003
|
+
return await new Promise((resolve) => {
|
|
34004
|
+
const waiter = () => {
|
|
34005
|
+
clearTimeout(timer);
|
|
34006
|
+
resolve(true);
|
|
34007
|
+
};
|
|
34008
|
+
const timer = setTimeout(() => {
|
|
34009
|
+
this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
|
|
34010
|
+
resolve(false);
|
|
34011
|
+
}, timeoutMs);
|
|
34012
|
+
this._drainWaiters.push(waiter);
|
|
34013
|
+
});
|
|
34014
|
+
}
|
|
34015
|
+
async close() {
|
|
34016
|
+
if (this._closed) return;
|
|
34017
|
+
this._closed = true;
|
|
34018
|
+
this._pendingRequests.clear();
|
|
34019
|
+
this._releaseDrainWaiters();
|
|
34020
|
+
try {
|
|
34021
|
+
this._onInstanceClose();
|
|
34022
|
+
} finally {
|
|
34023
|
+
this.onclose?.();
|
|
34024
|
+
}
|
|
34025
|
+
}
|
|
34026
|
+
_settle(id) {
|
|
34027
|
+
this._pendingRequests.delete(id);
|
|
34028
|
+
if (this._pendingRequests.size === 0) this._releaseDrainWaiters();
|
|
34029
|
+
}
|
|
34030
|
+
_releaseDrainWaiters() {
|
|
34031
|
+
const waiters = this._drainWaiters;
|
|
34032
|
+
this._drainWaiters = [];
|
|
34033
|
+
for (const waiter of waiters) waiter();
|
|
34034
|
+
}
|
|
34035
|
+
};
|
|
34036
|
+
function classifyOpeningMessage(message) {
|
|
34037
|
+
const params = message.params;
|
|
34038
|
+
if (message.method === "initialize" && !carriesValidModernEnvelopeClaim(params)) {
|
|
34039
|
+
const requestedVersion = params !== null && typeof params === "object" && typeof params.protocolVersion === "string" ? params.protocolVersion : void 0;
|
|
34040
|
+
return {
|
|
34041
|
+
kind: "legacy",
|
|
34042
|
+
reason: "initialize",
|
|
34043
|
+
...requestedVersion !== void 0 && { requestedVersion }
|
|
34044
|
+
};
|
|
34045
|
+
}
|
|
34046
|
+
if (!hasEnvelopeClaim(params)) return {
|
|
34047
|
+
kind: "legacy",
|
|
34048
|
+
reason: "no-claim"
|
|
34049
|
+
};
|
|
34050
|
+
const meta3 = requestMetaOf(params);
|
|
34051
|
+
const firstIssue = (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0];
|
|
34052
|
+
if (firstIssue !== void 0) return {
|
|
34053
|
+
kind: "invalid-envelope",
|
|
34054
|
+
issue: firstIssue
|
|
34055
|
+
};
|
|
34056
|
+
const claimedVersion = envelopeClaimVersion(params);
|
|
34057
|
+
if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) return {
|
|
34058
|
+
kind: "unsupported-revision",
|
|
34059
|
+
requested: claimedVersion ?? "unknown"
|
|
34060
|
+
};
|
|
34061
|
+
return {
|
|
34062
|
+
kind: "modern",
|
|
34063
|
+
revision: claimedVersion,
|
|
34064
|
+
classification: {
|
|
34065
|
+
era: "modern",
|
|
34066
|
+
revision: claimedVersion
|
|
34067
|
+
}
|
|
34068
|
+
};
|
|
34069
|
+
}
|
|
34070
|
+
function serveStdio(factory, options = {}) {
|
|
34071
|
+
const legacyMode = options.legacy ?? "serve";
|
|
34072
|
+
const wire = options.transport ?? new StdioServerTransport();
|
|
34073
|
+
let state = { phase: "opening" };
|
|
34074
|
+
let discarding;
|
|
34075
|
+
let closing = false;
|
|
34076
|
+
const isTornDown = () => closing || state.phase === "closed";
|
|
34077
|
+
const reportError = (error62) => {
|
|
34078
|
+
try {
|
|
34079
|
+
options.onerror?.(error62);
|
|
34080
|
+
} catch {
|
|
34081
|
+
}
|
|
34082
|
+
};
|
|
34083
|
+
const writeErrorResponse = (id, code, message, data) => wire.send({
|
|
34084
|
+
jsonrpc: "2.0",
|
|
34085
|
+
id,
|
|
34086
|
+
error: {
|
|
34087
|
+
code,
|
|
34088
|
+
message,
|
|
34089
|
+
...data !== void 0 && { data }
|
|
34090
|
+
}
|
|
34091
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
34092
|
+
const listenRouter = new StdioListenRouter(options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS);
|
|
34093
|
+
const modernOutboundIntercept = (message) => {
|
|
34094
|
+
if (!isJSONRPCNotification(message)) return void 0;
|
|
34095
|
+
const routed = listenRouter.routeOutbound(message);
|
|
34096
|
+
if (routed === "passthrough") return void 0;
|
|
34097
|
+
for (const stamped of routed) wire.send({
|
|
34098
|
+
jsonrpc: "2.0",
|
|
34099
|
+
...stamped
|
|
34100
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
34101
|
+
return "handled";
|
|
34102
|
+
};
|
|
34103
|
+
const tryServeListen = async (message) => {
|
|
34104
|
+
if (isJSONRPCRequest(message) && message.method === "subscriptions/listen") {
|
|
34105
|
+
const meta3 = requestMetaOf(message.params);
|
|
34106
|
+
const issue2 = hasEnvelopeClaim(message.params) ? (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0] : {
|
|
34107
|
+
key: "_meta",
|
|
34108
|
+
problem: "the per-request envelope is required on protocol revision 2026-07-28"
|
|
34109
|
+
};
|
|
34110
|
+
const claimedVersion = envelopeClaimVersion(message.params);
|
|
34111
|
+
let reply;
|
|
34112
|
+
if (issue2 !== void 0) reply = {
|
|
34113
|
+
jsonrpc: "2.0",
|
|
34114
|
+
id: message.id,
|
|
34115
|
+
error: {
|
|
34116
|
+
code: -32602,
|
|
34117
|
+
message: `Invalid _meta envelope: ${issue2.key}: ${issue2.problem}`
|
|
34118
|
+
}
|
|
34119
|
+
};
|
|
34120
|
+
else if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) {
|
|
34121
|
+
const error62 = new UnsupportedProtocolVersionError({
|
|
34122
|
+
supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
|
|
34123
|
+
requested: claimedVersion ?? "unknown"
|
|
34124
|
+
});
|
|
34125
|
+
reply = {
|
|
34126
|
+
jsonrpc: "2.0",
|
|
34127
|
+
id: message.id,
|
|
34128
|
+
error: {
|
|
34129
|
+
code: error62.code,
|
|
34130
|
+
message: error62.message,
|
|
34131
|
+
data: error62.data
|
|
34132
|
+
}
|
|
34133
|
+
};
|
|
34134
|
+
} else reply = listenRouter.serve(message);
|
|
34135
|
+
await wire.send("error" in reply ? reply : {
|
|
34136
|
+
jsonrpc: "2.0",
|
|
34137
|
+
method: reply.method,
|
|
34138
|
+
params: reply.params
|
|
34139
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
34140
|
+
return true;
|
|
34141
|
+
}
|
|
34142
|
+
if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
|
|
34143
|
+
const cancelledId = message.params?.requestId;
|
|
34144
|
+
if (cancelledId !== void 0 && listenRouter.cancel(cancelledId)) return true;
|
|
34145
|
+
}
|
|
34146
|
+
return false;
|
|
34147
|
+
};
|
|
34148
|
+
const answerLegacyRejection = (request, reason, requestedVersion) => {
|
|
34149
|
+
const rejection2 = modernOnlyStrictRejection({
|
|
34150
|
+
kind: "legacy",
|
|
34151
|
+
reason,
|
|
34152
|
+
...requestedVersion !== void 0 && { requestedVersion }
|
|
34153
|
+
}, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
34154
|
+
if (rejection2 === void 0) return Promise.resolve();
|
|
34155
|
+
reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection2.cell}): ${rejection2.message}`));
|
|
34156
|
+
return writeErrorResponse(request.id, rejection2.code, rejection2.message, rejection2.data);
|
|
34157
|
+
};
|
|
34158
|
+
const onInstanceClosed = (channel) => {
|
|
34159
|
+
if (closing || channel === discarding) return;
|
|
34160
|
+
closeAll();
|
|
34161
|
+
};
|
|
34162
|
+
const connectInstance = async (era, revision) => {
|
|
34163
|
+
const product = await factory({ era });
|
|
34164
|
+
const server = product instanceof McpServer ? product.server : product;
|
|
34165
|
+
if (era === "modern") {
|
|
34166
|
+
setNegotiatedProtocolVersion(server, revision);
|
|
34167
|
+
installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
34168
|
+
listenRouter.setServerCapabilities(server.getCapabilities(), serverIdentityOf(server));
|
|
34169
|
+
}
|
|
34170
|
+
const channel = new StdioConnectionChannel(wire, () => onInstanceClosed(channel), era === "modern" ? modernOutboundIntercept : void 0);
|
|
34171
|
+
await product.connect(channel);
|
|
34172
|
+
return {
|
|
34173
|
+
product,
|
|
34174
|
+
channel
|
|
34175
|
+
};
|
|
34176
|
+
};
|
|
34177
|
+
const disposeLateInstance = (instance) => instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
34178
|
+
const discardProbeInstance = async (instance) => {
|
|
34179
|
+
discarding = instance.channel;
|
|
34180
|
+
try {
|
|
34181
|
+
if (!await instance.channel.whenRequestsAnswered(DISCARD_ANSWER_TIMEOUT_MS)) reportError(/* @__PURE__ */ new Error(`Discarded the probe instance with requests still unanswered after ${DISCARD_ANSWER_TIMEOUT_MS}ms; continuing with the fallback`));
|
|
34182
|
+
await instance.product.close();
|
|
34183
|
+
} catch (error62) {
|
|
34184
|
+
reportError(toError(error62));
|
|
34185
|
+
} finally {
|
|
34186
|
+
discarding = void 0;
|
|
34187
|
+
}
|
|
34188
|
+
};
|
|
34189
|
+
const processMessage = async (message) => {
|
|
34190
|
+
if (state.phase === "closed") return;
|
|
34191
|
+
if (state.phase === "pinned") {
|
|
34192
|
+
if (state.era === "modern" && isJSONRPCRequest(message) && message.method === "initialize" && !carriesValidModernEnvelopeClaim(message.params)) {
|
|
34193
|
+
await answerLegacyRejection(message, "initialize", message.params !== null && typeof message.params === "object" && typeof message.params.protocolVersion === "string" ? message.params.protocolVersion : void 0);
|
|
34194
|
+
return;
|
|
34195
|
+
}
|
|
34196
|
+
if (state.era === "modern" && await tryServeListen(message)) return;
|
|
34197
|
+
state.instance.channel.deliver(message);
|
|
34198
|
+
return;
|
|
34199
|
+
}
|
|
34200
|
+
if (!isJSONRPCRequest(message) && !isJSONRPCNotification(message)) {
|
|
34201
|
+
reportError(/* @__PURE__ */ new Error("Discarded a JSON-RPC response received before the connection negotiated an era"));
|
|
34202
|
+
return;
|
|
34203
|
+
}
|
|
34204
|
+
const opening = classifyOpeningMessage(message);
|
|
34205
|
+
switch (opening.kind) {
|
|
34206
|
+
case "invalid-envelope": {
|
|
34207
|
+
const detail = `Invalid _meta envelope for protocol revision 2026-07-28: ${opening.issue.key}: ${opening.issue.problem}`;
|
|
34208
|
+
if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InvalidParams, detail, { envelope: opening.issue });
|
|
34209
|
+
else reportError(/* @__PURE__ */ new Error(`Discarded a notification with a malformed envelope: ${detail}`));
|
|
34210
|
+
return;
|
|
34211
|
+
}
|
|
34212
|
+
case "unsupported-revision":
|
|
34213
|
+
if (isJSONRPCRequest(message)) {
|
|
34214
|
+
const error62 = new UnsupportedProtocolVersionError({
|
|
34215
|
+
supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
|
|
34216
|
+
requested: opening.requested
|
|
34217
|
+
});
|
|
34218
|
+
reportError(error62);
|
|
34219
|
+
await writeErrorResponse(message.id, error62.code, error62.message, error62.data);
|
|
34220
|
+
} else reportError(/* @__PURE__ */ new Error(`Discarded a notification claiming unsupported protocol revision ${opening.requested}`));
|
|
34221
|
+
return;
|
|
34222
|
+
case "modern":
|
|
34223
|
+
if (isJSONRPCRequest(message) && message.method === "server/discover") {
|
|
34224
|
+
if (state.phase === "probe") {
|
|
34225
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
34226
|
+
return;
|
|
34227
|
+
}
|
|
34228
|
+
const instance = await connectInstance("modern", opening.revision);
|
|
34229
|
+
if (isTornDown()) {
|
|
34230
|
+
await disposeLateInstance(instance);
|
|
34231
|
+
return;
|
|
34232
|
+
}
|
|
34233
|
+
state = {
|
|
34234
|
+
phase: "probe",
|
|
34235
|
+
instance
|
|
34236
|
+
};
|
|
34237
|
+
instance.channel.deliver(message, { classification: opening.classification });
|
|
34238
|
+
return;
|
|
34239
|
+
}
|
|
34240
|
+
if (state.phase === "probe") {
|
|
34241
|
+
if (isJSONRPCNotification(message)) {
|
|
34242
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
34243
|
+
return;
|
|
34244
|
+
}
|
|
34245
|
+
state = {
|
|
34246
|
+
phase: "pinned",
|
|
34247
|
+
era: "modern",
|
|
34248
|
+
instance: state.instance
|
|
34249
|
+
};
|
|
34250
|
+
} else {
|
|
34251
|
+
const instance = await connectInstance("modern", opening.revision);
|
|
34252
|
+
if (isTornDown()) {
|
|
34253
|
+
await disposeLateInstance(instance);
|
|
34254
|
+
return;
|
|
34255
|
+
}
|
|
34256
|
+
state = {
|
|
34257
|
+
phase: "pinned",
|
|
34258
|
+
era: "modern",
|
|
34259
|
+
instance
|
|
34260
|
+
};
|
|
34261
|
+
}
|
|
34262
|
+
if (await tryServeListen(message)) return;
|
|
34263
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
34264
|
+
return;
|
|
34265
|
+
case "legacy": {
|
|
34266
|
+
if (legacyMode === "reject") {
|
|
34267
|
+
if (isJSONRPCRequest(message)) await answerLegacyRejection(message, opening.reason, opening.requestedVersion);
|
|
34268
|
+
return;
|
|
34269
|
+
}
|
|
34270
|
+
if (state.phase === "probe") {
|
|
34271
|
+
await discardProbeInstance(state.instance);
|
|
34272
|
+
if (isTornDown()) return;
|
|
34273
|
+
state = { phase: "opening" };
|
|
34274
|
+
}
|
|
34275
|
+
const instance = await connectInstance("legacy");
|
|
34276
|
+
if (isTornDown()) {
|
|
34277
|
+
await disposeLateInstance(instance);
|
|
34278
|
+
return;
|
|
34279
|
+
}
|
|
34280
|
+
state = {
|
|
34281
|
+
phase: "pinned",
|
|
34282
|
+
era: "legacy",
|
|
34283
|
+
instance
|
|
34284
|
+
};
|
|
34285
|
+
state.instance.channel.deliver(message);
|
|
34286
|
+
return;
|
|
34287
|
+
}
|
|
34288
|
+
}
|
|
34289
|
+
};
|
|
34290
|
+
const queue = [];
|
|
34291
|
+
let pumping = false;
|
|
34292
|
+
const pump = async () => {
|
|
34293
|
+
if (pumping) return;
|
|
34294
|
+
pumping = true;
|
|
34295
|
+
try {
|
|
34296
|
+
while (queue.length > 0) {
|
|
34297
|
+
const message = queue.shift();
|
|
34298
|
+
try {
|
|
34299
|
+
await processMessage(message);
|
|
34300
|
+
} catch (error62) {
|
|
34301
|
+
if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InternalError, "Internal server error");
|
|
34302
|
+
reportError(toError(error62));
|
|
34303
|
+
}
|
|
34304
|
+
}
|
|
34305
|
+
} finally {
|
|
34306
|
+
pumping = false;
|
|
34307
|
+
}
|
|
34308
|
+
};
|
|
34309
|
+
const closeAll = async () => {
|
|
34310
|
+
if (closing || state.phase === "closed") return;
|
|
34311
|
+
closing = true;
|
|
34312
|
+
const current = state;
|
|
34313
|
+
state = { phase: "closed" };
|
|
34314
|
+
for (const result of listenRouter.teardownAll()) await wire.send(result).catch((error62) => reportError(toError(error62)));
|
|
34315
|
+
if (current.phase === "probe" || current.phase === "pinned") await current.instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
34316
|
+
await wire.close().catch((error62) => reportError(toError(error62)));
|
|
34317
|
+
};
|
|
34318
|
+
wire.onmessage = (message) => {
|
|
34319
|
+
queue.push(message);
|
|
34320
|
+
pump();
|
|
34321
|
+
};
|
|
34322
|
+
wire.onerror = (error62) => {
|
|
34323
|
+
reportError(error62);
|
|
34324
|
+
if (state.phase === "probe" || state.phase === "pinned") state.instance.channel.onerror?.(error62);
|
|
34325
|
+
};
|
|
34326
|
+
wire.onclose = () => {
|
|
34327
|
+
if (closing || state.phase === "closed") return;
|
|
34328
|
+
closing = true;
|
|
34329
|
+
const current = state;
|
|
34330
|
+
state = { phase: "closed" };
|
|
34331
|
+
if (current.phase === "probe" || current.phase === "pinned") current.instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
34332
|
+
};
|
|
34333
|
+
const started = wire.start().catch((error62) => {
|
|
34334
|
+
reportError(toError(error62));
|
|
34335
|
+
throw error62;
|
|
34336
|
+
});
|
|
34337
|
+
started.catch(() => {
|
|
34338
|
+
});
|
|
34339
|
+
return { close: async () => {
|
|
34340
|
+
await started.catch(() => {
|
|
34341
|
+
});
|
|
34342
|
+
await closeAll();
|
|
34343
|
+
} };
|
|
34344
|
+
}
|
|
34345
|
+
function toError(value) {
|
|
34346
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
34347
|
+
}
|
|
33702
34348
|
|
|
33703
34349
|
// ../../node_modules/@chrischall/mcp-utils/dist/errors/index.js
|
|
33704
34350
|
var McpToolError = class extends Error {
|
|
@@ -33905,7 +34551,7 @@ async function createMcpServer(opts) {
|
|
|
33905
34551
|
}
|
|
33906
34552
|
return server;
|
|
33907
34553
|
}
|
|
33908
|
-
function withGracefulShutdown(
|
|
34554
|
+
function withGracefulShutdown(target, opts = {}) {
|
|
33909
34555
|
const shouldExit = opts.exit ?? true;
|
|
33910
34556
|
let shuttingDown = false;
|
|
33911
34557
|
const handler = (signal) => {
|
|
@@ -33916,7 +34562,7 @@ function withGracefulShutdown(server, opts = {}) {
|
|
|
33916
34562
|
try {
|
|
33917
34563
|
if (opts.onSignal)
|
|
33918
34564
|
await opts.onSignal(signal);
|
|
33919
|
-
await
|
|
34565
|
+
await target.close();
|
|
33920
34566
|
} catch (err) {
|
|
33921
34567
|
console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
|
|
33922
34568
|
} finally {
|
|
@@ -33928,16 +34574,26 @@ function withGracefulShutdown(server, opts = {}) {
|
|
|
33928
34574
|
process.on("SIGINT", () => handler("SIGINT"));
|
|
33929
34575
|
process.on("SIGTERM", () => handler("SIGTERM"));
|
|
33930
34576
|
}
|
|
33931
|
-
|
|
33932
|
-
|
|
34577
|
+
function runMcp(opts) {
|
|
34578
|
+
if (opts.banner !== void 0) {
|
|
34579
|
+
console.error(opts.banner);
|
|
34580
|
+
}
|
|
34581
|
+
const spec = opts.transport ?? "stdio";
|
|
34582
|
+
const handle = serveStdio(() => createMcpServer({ ...opts, banner: void 0 }), {
|
|
34583
|
+
legacy: opts.legacy ?? "serve",
|
|
34584
|
+
onerror: opts.onerror ?? ((error62) => {
|
|
34585
|
+
console.error(`[mcp-utils] stdio server error: ${redactSecrets(error62.message)}`);
|
|
34586
|
+
}),
|
|
34587
|
+
// `'stdio'` means "let the entry make its own StdioServerTransport over
|
|
34588
|
+
// this process"; anything else is the caller's transport, which the entry
|
|
34589
|
+
// then owns (it starts it, pumps it, and closes it with the handle).
|
|
34590
|
+
...spec === "stdio" ? {} : { transport: spec }
|
|
34591
|
+
});
|
|
33933
34592
|
const shutdown = opts.shutdown ?? true;
|
|
33934
34593
|
if (shutdown !== false) {
|
|
33935
|
-
withGracefulShutdown(
|
|
34594
|
+
withGracefulShutdown(handle, shutdown === true ? {} : shutdown);
|
|
33936
34595
|
}
|
|
33937
|
-
|
|
33938
|
-
const transport = spec === "stdio" ? new StdioServerTransport() : spec;
|
|
33939
|
-
await server.connect(transport);
|
|
33940
|
-
return server;
|
|
34596
|
+
return handle;
|
|
33941
34597
|
}
|
|
33942
34598
|
|
|
33943
34599
|
// ../../node_modules/@chrischall/mcp-utils/dist/config/index.js
|
|
@@ -33989,227 +34645,26 @@ var pageSchema = {
|
|
|
33989
34645
|
|
|
33990
34646
|
// src/runner.ts
|
|
33991
34647
|
import { delimiter, join } from "node:path";
|
|
33992
|
-
|
|
33993
|
-
|
|
33994
|
-
|
|
33995
|
-
|
|
33996
|
-
|
|
33997
|
-
|
|
33998
|
-
|
|
33999
|
-
|
|
34000
|
-
|
|
34001
|
-
for (const [key, value] of Object.entries(process.env)) {
|
|
34002
|
-
if (key === "GOG_ACCESS_TOKEN") continue;
|
|
34003
|
-
if (key === "GOOGLE_APPLICATION_CREDENTIALS") continue;
|
|
34004
|
-
if (/(_TOKEN|_SECRET|_KEY|_CREDENTIALS)$/.test(key)) continue;
|
|
34005
|
-
result[key] = value;
|
|
34648
|
+
|
|
34649
|
+
// src/timestamps.ts
|
|
34650
|
+
var DEFAULT_DISPLAY_TZ = "America/New_York";
|
|
34651
|
+
function isValidTimeZone(tz) {
|
|
34652
|
+
try {
|
|
34653
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
34654
|
+
return true;
|
|
34655
|
+
} catch {
|
|
34656
|
+
return false;
|
|
34006
34657
|
}
|
|
34007
|
-
return result;
|
|
34008
34658
|
}
|
|
34009
|
-
|
|
34010
|
-
|
|
34011
|
-
|
|
34012
|
-
|
|
34013
|
-
new RegExp(`${TOKEN_LEFT_BOUNDARY}1//[A-Za-z0-9._\\-]+`, "g")
|
|
34014
|
-
// OAuth2 refresh tokens
|
|
34015
|
-
];
|
|
34016
|
-
function redactGoogleTokens(text) {
|
|
34017
|
-
let redacted = text;
|
|
34018
|
-
for (const re of GOOGLE_TOKEN_PATTERNS) {
|
|
34019
|
-
redacted = redacted.replace(re, "[REDACTED]");
|
|
34020
|
-
}
|
|
34021
|
-
return redacted;
|
|
34659
|
+
function displayTimeZone() {
|
|
34660
|
+
const configured = readEnvVar("DISPLAY_TZ");
|
|
34661
|
+
if (configured && isValidTimeZone(configured)) return configured;
|
|
34662
|
+
return DEFAULT_DISPLAY_TZ;
|
|
34022
34663
|
}
|
|
34023
|
-
function
|
|
34024
|
-
|
|
34025
|
-
|
|
34026
|
-
|
|
34027
|
-
var opaquePlaceholder = (i) => `\0gogOpaque${i}\0`;
|
|
34028
|
-
function redactPreservingOpaqueFields(text, fields, redact) {
|
|
34029
|
-
const lifted = [];
|
|
34030
|
-
let staged = text;
|
|
34031
|
-
for (const field of fields) {
|
|
34032
|
-
const escaped = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34033
|
-
const re = new RegExp(`("${escaped}"\\s*:\\s*")(${OPAQUE_FIELD_VALUE})(")`, "g");
|
|
34034
|
-
staged = staged.replace(re, (_m, open2, value, close) => {
|
|
34035
|
-
lifted.push(value);
|
|
34036
|
-
return `${open2}${opaquePlaceholder(lifted.length - 1)}${close}`;
|
|
34037
|
-
});
|
|
34038
|
-
}
|
|
34039
|
-
if (lifted.length === 0) return redact(text);
|
|
34040
|
-
let redacted = redact(staged);
|
|
34041
|
-
lifted.forEach((value, i) => {
|
|
34042
|
-
redacted = redacted.split(opaquePlaceholder(i)).join(value);
|
|
34043
|
-
});
|
|
34044
|
-
return redacted;
|
|
34045
|
-
}
|
|
34046
|
-
function augmentedPath() {
|
|
34047
|
-
const home = process.env.HOME;
|
|
34048
|
-
const candidates = [
|
|
34049
|
-
process.env.PATH ?? "",
|
|
34050
|
-
"/opt/homebrew/bin",
|
|
34051
|
-
"/usr/local/bin",
|
|
34052
|
-
home ? `${home}/.local/bin` : "",
|
|
34053
|
-
home ? `${home}/go/bin` : ""
|
|
34054
|
-
];
|
|
34055
|
-
const seen = /* @__PURE__ */ new Set();
|
|
34056
|
-
const parts = [];
|
|
34057
|
-
for (const c of candidates) {
|
|
34058
|
-
if (!c) continue;
|
|
34059
|
-
for (const dir of c.split(delimiter)) {
|
|
34060
|
-
if (!dir || seen.has(dir)) continue;
|
|
34061
|
-
seen.add(dir);
|
|
34062
|
-
parts.push(dir);
|
|
34063
|
-
}
|
|
34064
|
-
}
|
|
34065
|
-
return parts.join(delimiter);
|
|
34066
|
-
}
|
|
34067
|
-
function formatTimeout(ms) {
|
|
34068
|
-
const seconds = Math.round(ms / 1e3);
|
|
34069
|
-
if (seconds >= 60) {
|
|
34070
|
-
const minutes = Math.round(seconds / 60);
|
|
34071
|
-
return `${ms}ms (${minutes} minute${minutes !== 1 ? "s" : ""})`;
|
|
34072
|
-
}
|
|
34073
|
-
return `${ms}ms`;
|
|
34074
|
-
}
|
|
34075
|
-
async function spawnWithTempFiles(args, opts) {
|
|
34076
|
-
const { mkdtemp, mkdir, writeFile, rm } = await import("node:fs/promises");
|
|
34077
|
-
const { tmpdir } = await import("node:os");
|
|
34078
|
-
const dir = await mkdtemp(join(tmpdir(), "gogcli-mcp-"));
|
|
34079
|
-
try {
|
|
34080
|
-
const argv = [];
|
|
34081
|
-
let seq = 0;
|
|
34082
|
-
for (const arg of args) {
|
|
34083
|
-
if (!isGogFileArg(arg)) {
|
|
34084
|
-
argv.push(arg);
|
|
34085
|
-
continue;
|
|
34086
|
-
}
|
|
34087
|
-
const sub = join(dir, String(seq));
|
|
34088
|
-
seq += 1;
|
|
34089
|
-
await mkdir(sub, { recursive: true, mode: 448 });
|
|
34090
|
-
const path = join(sub, arg.filename ?? `${arg.flag}.${arg.ext ?? "txt"}`);
|
|
34091
|
-
const data = arg.encoding === "base64" ? Buffer.from(arg.contents, "base64") : Buffer.from(arg.contents, "utf8");
|
|
34092
|
-
await writeFile(path, data, { mode: 384 });
|
|
34093
|
-
argv.push(arg.positional ? path : `--${arg.flag}=${path}`);
|
|
34094
|
-
}
|
|
34095
|
-
return await spawnGog(argv, opts);
|
|
34096
|
-
} finally {
|
|
34097
|
-
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
34098
|
-
});
|
|
34099
|
-
}
|
|
34100
|
-
}
|
|
34101
|
-
function spawnExecutor(args, opts) {
|
|
34102
|
-
if (args.some(isGogFileArg)) {
|
|
34103
|
-
return spawnWithTempFiles(args, opts);
|
|
34104
|
-
}
|
|
34105
|
-
return spawnGog(args, opts);
|
|
34106
|
-
}
|
|
34107
|
-
async function spawnGog(fullArgs, opts) {
|
|
34108
|
-
const { timeout, interactive = false, spawner, binary = false } = opts;
|
|
34109
|
-
const spawn = spawner ?? (await import("node:child_process")).spawn;
|
|
34110
|
-
const effectiveTimeout = timeout ?? TIMEOUT_MS;
|
|
34111
|
-
return new Promise((resolve, reject) => {
|
|
34112
|
-
const childEnv = { ...sanitizedEnv(), PATH: augmentedPath() };
|
|
34113
|
-
const child = spawn(readEnvVar("GOG_PATH") ?? "gog", fullArgs, { env: childEnv });
|
|
34114
|
-
const stdoutChunks = [];
|
|
34115
|
-
const stderrChunks = [];
|
|
34116
|
-
let settled = false;
|
|
34117
|
-
const timer = setTimeout(() => {
|
|
34118
|
-
settled = true;
|
|
34119
|
-
child.kill();
|
|
34120
|
-
reject(new Error(`gog timed out after ${formatTimeout(effectiveTimeout)}`));
|
|
34121
|
-
}, effectiveTimeout);
|
|
34122
|
-
child.stdout.on("data", (chunk) => {
|
|
34123
|
-
stdoutChunks.push(chunk);
|
|
34124
|
-
});
|
|
34125
|
-
child.stderr.on("data", (chunk) => {
|
|
34126
|
-
stderrChunks.push(chunk);
|
|
34127
|
-
});
|
|
34128
|
-
child.on("close", (code) => {
|
|
34129
|
-
clearTimeout(timer);
|
|
34130
|
-
if (settled) return;
|
|
34131
|
-
settled = true;
|
|
34132
|
-
const stderr = Buffer.concat(stderrChunks).toString().trim();
|
|
34133
|
-
if (code === 0) {
|
|
34134
|
-
if (binary) {
|
|
34135
|
-
resolve(Buffer.concat(stdoutChunks).toString("base64"));
|
|
34136
|
-
return;
|
|
34137
|
-
}
|
|
34138
|
-
const stdout = Buffer.concat(stdoutChunks).toString();
|
|
34139
|
-
if (interactive && stderr) {
|
|
34140
|
-
resolve(stdout + "\n" + stderr);
|
|
34141
|
-
} else {
|
|
34142
|
-
resolve(stdout);
|
|
34143
|
-
}
|
|
34144
|
-
} else {
|
|
34145
|
-
reject(new Error(stderr || `gog exited with code ${code}`));
|
|
34146
|
-
}
|
|
34147
|
-
});
|
|
34148
|
-
child.on("error", (err) => {
|
|
34149
|
-
clearTimeout(timer);
|
|
34150
|
-
if (settled) return;
|
|
34151
|
-
settled = true;
|
|
34152
|
-
if (err.code === "ENOENT") {
|
|
34153
|
-
reject(new Error(
|
|
34154
|
-
"gog executable not found. Install gogcli (https://github.com/openclaw/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
|
|
34155
|
-
));
|
|
34156
|
-
return;
|
|
34157
|
-
}
|
|
34158
|
-
reject(err);
|
|
34159
|
-
});
|
|
34160
|
-
});
|
|
34161
|
-
}
|
|
34162
|
-
function assembleArgs(args, opts) {
|
|
34163
|
-
const effectiveAccount = opts.account ?? readEnvVar("GOG_ACCOUNT");
|
|
34164
|
-
const fullArgs = ["--json", "--color=never"];
|
|
34165
|
-
if (!opts.interactive) {
|
|
34166
|
-
fullArgs.push("--no-input");
|
|
34167
|
-
}
|
|
34168
|
-
if (opts.readonly || readonlyEnvEnabled()) {
|
|
34169
|
-
fullArgs.push("--readonly");
|
|
34170
|
-
}
|
|
34171
|
-
if (effectiveAccount) {
|
|
34172
|
-
fullArgs.push("--account", effectiveAccount);
|
|
34173
|
-
}
|
|
34174
|
-
fullArgs.push(...args);
|
|
34175
|
-
return fullArgs;
|
|
34176
|
-
}
|
|
34177
|
-
async function run(args, options = {}) {
|
|
34178
|
-
const { account, spawner, interactive = false, timeout, readonly: readonly2 = false, redactMode = "full", opaqueFields } = options;
|
|
34179
|
-
const base = redactMode === "tokens" ? redactGoogleTokens : redactSecrets2;
|
|
34180
|
-
const redact = opaqueFields?.length ? (text) => redactPreservingOpaqueFields(text, opaqueFields, base) : base;
|
|
34181
|
-
const fullArgs = assembleArgs(args, { account, interactive, readonly: readonly2 });
|
|
34182
|
-
try {
|
|
34183
|
-
return redact(await spawnExecutor(fullArgs, { timeout, interactive, spawner }));
|
|
34184
|
-
} catch (err) {
|
|
34185
|
-
throw new Error(base(err instanceof Error ? err.message : String(err)));
|
|
34186
|
-
}
|
|
34187
|
-
}
|
|
34188
|
-
async function runBinary(args, options = {}) {
|
|
34189
|
-
const { account, spawner, timeout, readonly: readonly2 = false } = options;
|
|
34190
|
-
const fullArgs = assembleArgs(args, { account, interactive: false, readonly: readonly2 });
|
|
34191
|
-
return spawnExecutor(fullArgs, { timeout, interactive: false, spawner, binary: true });
|
|
34192
|
-
}
|
|
34193
|
-
|
|
34194
|
-
// src/timestamps.ts
|
|
34195
|
-
var DEFAULT_DISPLAY_TZ = "America/New_York";
|
|
34196
|
-
function isValidTimeZone(tz) {
|
|
34197
|
-
try {
|
|
34198
|
-
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
34199
|
-
return true;
|
|
34200
|
-
} catch {
|
|
34201
|
-
return false;
|
|
34202
|
-
}
|
|
34203
|
-
}
|
|
34204
|
-
function displayTimeZone() {
|
|
34205
|
-
const configured = readEnvVar("DISPLAY_TZ");
|
|
34206
|
-
if (configured && isValidTimeZone(configured)) return configured;
|
|
34207
|
-
return DEFAULT_DISPLAY_TZ;
|
|
34208
|
-
}
|
|
34209
|
-
function naiveSourceTimeZone() {
|
|
34210
|
-
const configured = readEnvVar("GOG_TIMEZONE");
|
|
34211
|
-
if (configured && isValidTimeZone(configured)) return configured;
|
|
34212
|
-
return displayTimeZone();
|
|
34664
|
+
function naiveSourceTimeZone() {
|
|
34665
|
+
const configured = readEnvVar("GOG_TIMEZONE");
|
|
34666
|
+
if (configured && isValidTimeZone(configured)) return configured;
|
|
34667
|
+
return displayTimeZone();
|
|
34213
34668
|
}
|
|
34214
34669
|
function offsetAt(instant, tz) {
|
|
34215
34670
|
const w = wallPartsIn(instant, tz);
|
|
@@ -34390,6 +34845,209 @@ function normalizeTimestamps(text, tz = displayTimeZone(), naiveTz = naiveSource
|
|
|
34390
34845
|
return JSON.stringify(parsed, null, detectIndent(text));
|
|
34391
34846
|
}
|
|
34392
34847
|
|
|
34848
|
+
// src/runner.ts
|
|
34849
|
+
function isGogFileArg(arg) {
|
|
34850
|
+
return typeof arg !== "string";
|
|
34851
|
+
}
|
|
34852
|
+
var TIMEOUT_MS = 3e4;
|
|
34853
|
+
function readonlyEnvEnabled() {
|
|
34854
|
+
return readEnvVar("GOG_READONLY") !== void 0 && parseBoolEnv("GOG_READONLY", { default: true });
|
|
34855
|
+
}
|
|
34856
|
+
function sanitizedEnv() {
|
|
34857
|
+
const result = {};
|
|
34858
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
34859
|
+
if (key === "GOG_ACCESS_TOKEN") continue;
|
|
34860
|
+
if (key === "GOOGLE_APPLICATION_CREDENTIALS") continue;
|
|
34861
|
+
if (/(_TOKEN|_SECRET|_KEY|_CREDENTIALS)$/.test(key)) continue;
|
|
34862
|
+
result[key] = value;
|
|
34863
|
+
}
|
|
34864
|
+
return result;
|
|
34865
|
+
}
|
|
34866
|
+
var TOKEN_LEFT_BOUNDARY = "(?<![A-Za-z0-9+/])";
|
|
34867
|
+
var GOOGLE_TOKEN_PATTERNS = [
|
|
34868
|
+
new RegExp(`${TOKEN_LEFT_BOUNDARY}ya29\\.[A-Za-z0-9._\\-]+`, "g"),
|
|
34869
|
+
// OAuth2 access tokens
|
|
34870
|
+
new RegExp(`${TOKEN_LEFT_BOUNDARY}1//[A-Za-z0-9._\\-]+`, "g")
|
|
34871
|
+
// OAuth2 refresh tokens
|
|
34872
|
+
];
|
|
34873
|
+
function redactGoogleTokens(text) {
|
|
34874
|
+
let redacted = text;
|
|
34875
|
+
for (const re of GOOGLE_TOKEN_PATTERNS) {
|
|
34876
|
+
redacted = redacted.replace(re, "[REDACTED]");
|
|
34877
|
+
}
|
|
34878
|
+
return redacted;
|
|
34879
|
+
}
|
|
34880
|
+
function redactSecrets2(text) {
|
|
34881
|
+
return redactGoogleTokens(redactSecrets(text));
|
|
34882
|
+
}
|
|
34883
|
+
var OPAQUE_FIELD_VALUE = "[A-Za-z0-9+/_-]{16,}={0,2}";
|
|
34884
|
+
var opaquePlaceholder = (i) => `\0gogOpaque${i}\0`;
|
|
34885
|
+
function redactPreservingOpaqueFields(text, fields, redact) {
|
|
34886
|
+
const lifted = [];
|
|
34887
|
+
let staged = text;
|
|
34888
|
+
for (const field of fields) {
|
|
34889
|
+
const escaped = field.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
34890
|
+
const re = new RegExp(`("${escaped}"\\s*:\\s*")(${OPAQUE_FIELD_VALUE})(")`, "g");
|
|
34891
|
+
staged = staged.replace(re, (_m, open2, value, close) => {
|
|
34892
|
+
lifted.push(value);
|
|
34893
|
+
return `${open2}${opaquePlaceholder(lifted.length - 1)}${close}`;
|
|
34894
|
+
});
|
|
34895
|
+
}
|
|
34896
|
+
if (lifted.length === 0) return redact(text);
|
|
34897
|
+
let redacted = redact(staged);
|
|
34898
|
+
lifted.forEach((value, i) => {
|
|
34899
|
+
redacted = redacted.split(opaquePlaceholder(i)).join(value);
|
|
34900
|
+
});
|
|
34901
|
+
return redacted;
|
|
34902
|
+
}
|
|
34903
|
+
function augmentedPath() {
|
|
34904
|
+
const home = process.env.HOME;
|
|
34905
|
+
const candidates = [
|
|
34906
|
+
process.env.PATH ?? "",
|
|
34907
|
+
"/opt/homebrew/bin",
|
|
34908
|
+
"/usr/local/bin",
|
|
34909
|
+
home ? `${home}/.local/bin` : "",
|
|
34910
|
+
home ? `${home}/go/bin` : ""
|
|
34911
|
+
];
|
|
34912
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34913
|
+
const parts = [];
|
|
34914
|
+
for (const c of candidates) {
|
|
34915
|
+
if (!c) continue;
|
|
34916
|
+
for (const dir of c.split(delimiter)) {
|
|
34917
|
+
if (!dir || seen.has(dir)) continue;
|
|
34918
|
+
seen.add(dir);
|
|
34919
|
+
parts.push(dir);
|
|
34920
|
+
}
|
|
34921
|
+
}
|
|
34922
|
+
return parts.join(delimiter);
|
|
34923
|
+
}
|
|
34924
|
+
function formatTimeout(ms) {
|
|
34925
|
+
const seconds = Math.round(ms / 1e3);
|
|
34926
|
+
if (seconds >= 60) {
|
|
34927
|
+
const minutes = Math.round(seconds / 60);
|
|
34928
|
+
return `${ms}ms (${minutes} minute${minutes !== 1 ? "s" : ""})`;
|
|
34929
|
+
}
|
|
34930
|
+
return `${ms}ms`;
|
|
34931
|
+
}
|
|
34932
|
+
async function spawnWithTempFiles(args, opts) {
|
|
34933
|
+
const { mkdtemp, mkdir, writeFile, rm } = await import("node:fs/promises");
|
|
34934
|
+
const { tmpdir } = await import("node:os");
|
|
34935
|
+
const dir = await mkdtemp(join(tmpdir(), "gogcli-mcp-"));
|
|
34936
|
+
try {
|
|
34937
|
+
const argv = [];
|
|
34938
|
+
let seq = 0;
|
|
34939
|
+
for (const arg of args) {
|
|
34940
|
+
if (!isGogFileArg(arg)) {
|
|
34941
|
+
argv.push(arg);
|
|
34942
|
+
continue;
|
|
34943
|
+
}
|
|
34944
|
+
const sub = join(dir, String(seq));
|
|
34945
|
+
seq += 1;
|
|
34946
|
+
await mkdir(sub, { recursive: true, mode: 448 });
|
|
34947
|
+
const path = join(sub, arg.filename ?? `${arg.flag}.${arg.ext ?? "txt"}`);
|
|
34948
|
+
const data = arg.encoding === "base64" ? Buffer.from(arg.contents, "base64") : Buffer.from(arg.contents, "utf8");
|
|
34949
|
+
await writeFile(path, data, { mode: 384 });
|
|
34950
|
+
argv.push(arg.positional ? path : `--${arg.flag}=${path}`);
|
|
34951
|
+
}
|
|
34952
|
+
return await spawnGog(argv, opts);
|
|
34953
|
+
} finally {
|
|
34954
|
+
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
34955
|
+
});
|
|
34956
|
+
}
|
|
34957
|
+
}
|
|
34958
|
+
function spawnExecutor(args, opts) {
|
|
34959
|
+
if (args.some(isGogFileArg)) {
|
|
34960
|
+
return spawnWithTempFiles(args, opts);
|
|
34961
|
+
}
|
|
34962
|
+
return spawnGog(args, opts);
|
|
34963
|
+
}
|
|
34964
|
+
async function spawnGog(fullArgs, opts) {
|
|
34965
|
+
const { timeout, interactive = false, spawner, binary = false } = opts;
|
|
34966
|
+
const spawn = spawner ?? (await import("node:child_process")).spawn;
|
|
34967
|
+
const effectiveTimeout = timeout ?? TIMEOUT_MS;
|
|
34968
|
+
return new Promise((resolve, reject) => {
|
|
34969
|
+
const childEnv = { ...sanitizedEnv(), GOG_TIMEZONE: naiveSourceTimeZone(), PATH: augmentedPath() };
|
|
34970
|
+
const child = spawn(readEnvVar("GOG_PATH") ?? "gog", fullArgs, { env: childEnv });
|
|
34971
|
+
const stdoutChunks = [];
|
|
34972
|
+
const stderrChunks = [];
|
|
34973
|
+
let settled = false;
|
|
34974
|
+
const timer = setTimeout(() => {
|
|
34975
|
+
settled = true;
|
|
34976
|
+
child.kill();
|
|
34977
|
+
reject(new Error(`gog timed out after ${formatTimeout(effectiveTimeout)}`));
|
|
34978
|
+
}, effectiveTimeout);
|
|
34979
|
+
child.stdout.on("data", (chunk) => {
|
|
34980
|
+
stdoutChunks.push(chunk);
|
|
34981
|
+
});
|
|
34982
|
+
child.stderr.on("data", (chunk) => {
|
|
34983
|
+
stderrChunks.push(chunk);
|
|
34984
|
+
});
|
|
34985
|
+
child.on("close", (code) => {
|
|
34986
|
+
clearTimeout(timer);
|
|
34987
|
+
if (settled) return;
|
|
34988
|
+
settled = true;
|
|
34989
|
+
const stderr = Buffer.concat(stderrChunks).toString().trim();
|
|
34990
|
+
if (code === 0) {
|
|
34991
|
+
if (binary) {
|
|
34992
|
+
resolve(Buffer.concat(stdoutChunks).toString("base64"));
|
|
34993
|
+
return;
|
|
34994
|
+
}
|
|
34995
|
+
const stdout = Buffer.concat(stdoutChunks).toString();
|
|
34996
|
+
if (interactive && stderr) {
|
|
34997
|
+
resolve(stdout + "\n" + stderr);
|
|
34998
|
+
} else {
|
|
34999
|
+
resolve(stdout);
|
|
35000
|
+
}
|
|
35001
|
+
} else {
|
|
35002
|
+
reject(new Error(stderr || `gog exited with code ${code}`));
|
|
35003
|
+
}
|
|
35004
|
+
});
|
|
35005
|
+
child.on("error", (err) => {
|
|
35006
|
+
clearTimeout(timer);
|
|
35007
|
+
if (settled) return;
|
|
35008
|
+
settled = true;
|
|
35009
|
+
if (err.code === "ENOENT") {
|
|
35010
|
+
reject(new Error(
|
|
35011
|
+
"gog executable not found. Install gogcli (https://github.com/openclaw/gogcli) or set GOG_PATH in your MCP client config to the absolute binary path (run `which gog` in a terminal to find it)."
|
|
35012
|
+
));
|
|
35013
|
+
return;
|
|
35014
|
+
}
|
|
35015
|
+
reject(err);
|
|
35016
|
+
});
|
|
35017
|
+
});
|
|
35018
|
+
}
|
|
35019
|
+
function assembleArgs(args, opts) {
|
|
35020
|
+
const effectiveAccount = opts.account ?? readEnvVar("GOG_ACCOUNT");
|
|
35021
|
+
const fullArgs = ["--json", "--color=never"];
|
|
35022
|
+
if (!opts.interactive) {
|
|
35023
|
+
fullArgs.push("--no-input");
|
|
35024
|
+
}
|
|
35025
|
+
if (opts.readonly || readonlyEnvEnabled()) {
|
|
35026
|
+
fullArgs.push("--readonly");
|
|
35027
|
+
}
|
|
35028
|
+
if (effectiveAccount) {
|
|
35029
|
+
fullArgs.push("--account", effectiveAccount);
|
|
35030
|
+
}
|
|
35031
|
+
fullArgs.push(...args);
|
|
35032
|
+
return fullArgs;
|
|
35033
|
+
}
|
|
35034
|
+
async function run(args, options = {}) {
|
|
35035
|
+
const { account, spawner, interactive = false, timeout, readonly: readonly2 = false, redactMode = "full", opaqueFields } = options;
|
|
35036
|
+
const base = redactMode === "tokens" ? redactGoogleTokens : redactSecrets2;
|
|
35037
|
+
const redact = opaqueFields?.length ? (text) => redactPreservingOpaqueFields(text, opaqueFields, base) : base;
|
|
35038
|
+
const fullArgs = assembleArgs(args, { account, interactive, readonly: readonly2 });
|
|
35039
|
+
try {
|
|
35040
|
+
return redact(await spawnExecutor(fullArgs, { timeout, interactive, spawner }));
|
|
35041
|
+
} catch (err) {
|
|
35042
|
+
throw new Error(base(err instanceof Error ? err.message : String(err)));
|
|
35043
|
+
}
|
|
35044
|
+
}
|
|
35045
|
+
async function runBinary(args, options = {}) {
|
|
35046
|
+
const { account, spawner, timeout, readonly: readonly2 = false } = options;
|
|
35047
|
+
const fullArgs = assembleArgs(args, { account, interactive: false, readonly: readonly2 });
|
|
35048
|
+
return spawnExecutor(fullArgs, { timeout, interactive: false, spawner, binary: true });
|
|
35049
|
+
}
|
|
35050
|
+
|
|
34393
35051
|
// src/pagination.ts
|
|
34394
35052
|
function detectIndent2(text) {
|
|
34395
35053
|
const match = /\n(\s+)\S/.exec(text);
|
|
@@ -36863,7 +37521,7 @@ function registerTasksTools(server) {
|
|
|
36863
37521
|
}
|
|
36864
37522
|
|
|
36865
37523
|
// src/server.ts
|
|
36866
|
-
var VERSION = true ? "4.
|
|
37524
|
+
var VERSION = true ? "4.1.0" : "0.0.0";
|
|
36867
37525
|
var BASE_TOOL_REGISTRARS = [
|
|
36868
37526
|
registerApiTools,
|
|
36869
37527
|
registerAppScriptTools,
|