specrails-desktop 2.63.2 → 2.64.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/dist/assets/{ActivityFeedPage-B1bpTy7O.js → ActivityFeedPage-Dtp7EyHc.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-BussBbN3.js → AgentBrowserCapture-CLqlEFw8.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-BiT1n3BU.js → AgentModeAnalyticsPane-B8_hM3Tw.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-CUjNfeKa.js → AgentModeCodePane-CNF8ZNjE.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-RVEwyS59.js → AgentModeJobsPane-CJpJbO9m.js} +1 -1
- package/client/dist/assets/AgentsPage-BC8XSR79.js +120 -0
- package/client/dist/assets/{AnalyticsPage-Bser2Ly3.js → AnalyticsPage-Cdv4jLtW.js} +1 -1
- package/client/dist/assets/{CodePage-BK0grm6e.js → CodePage-DI1kegAr.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-DEBidZbs.js → DesktopAnalyticsPage-Bdp8E8U6.js} +1 -1
- package/client/dist/assets/{DocsDialog-Dhyo57n9.js → DocsDialog-Bm4RS7FX.js} +1 -1
- package/client/dist/assets/{DocsPage-BcEkPXd6.js → DocsPage-DihYcU8r.js} +1 -1
- package/client/dist/assets/{ExportDropdown-mRmqdkjr.js → ExportDropdown-Bb1lHx3r.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-BlCe3vrU.js → InteractiveJobComposer-BO6ASN-2.js} +1 -1
- package/client/dist/assets/{JobDetailModal-CkAejD1F.js → JobDetailModal-CuPYq7tP.js} +1 -1
- package/client/dist/assets/{JobDetailPage-P-FS_lKz.js → JobDetailPage-BusMjJi9.js} +1 -1
- package/client/dist/assets/{JobsPage-CoUXgYse.js → JobsPage-C0QbsF2d.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-iFylNk68.js → LoopBuilderPage-B7TlU4iS.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-4obS_Ptg.js → LoopPreviewModal-BRWtXOD2.js} +1 -1
- package/client/dist/assets/{LoopWindowSurface-CLr5OPqj.js → LoopWindowSurface-DE0v2K1p.js} +1 -1
- package/client/dist/assets/{LoopsPage-eKpWFtCp.js → LoopsPage-C4q1DmCE.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-BHIUPVmC.js → MinimizedChatsContext-DHfigjHS.js} +1 -1
- package/client/dist/assets/{PluginsPage-BgTC2CQx.js → PluginsPage-Z1JHSMdR.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-B4chTfU8.js → ProjectSettingsDialog-BUNj0tvN.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-DAIxIYsl.js → RepositoryDeliveries-B4ybHOyB.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-DeCoUsRN.js → RepositoryScopeSelector-2eSqR9WK.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-Cktv0-9b.js → ReviewPacketPage-hwfPNjyy.js} +1 -1
- package/client/dist/assets/{TemplatePreviewModal-BZTV1TM1.js → TemplatePreviewModal-V7FpMWuw.js} +1 -1
- package/client/dist/assets/{TicketDetailModalContext-DiPngt2g.js → TicketDetailModalContext-Dkwo2cDs.js} +1 -1
- package/client/dist/assets/{Trans-ZiXIfj50.js → Trans-BbFxRFtR.js} +1 -1
- package/client/dist/assets/{formatDistanceToNow-CdN5lTyD.js → formatDistanceToNow-NjPHBLfB.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-62h40I4t.js → getTimezoneOffsetInMilliseconds-vJ7qUoqN.js} +1 -1
- package/client/dist/assets/{index-CECj3joE.js → index-Ce4yZtKf.js} +36 -36
- package/client/dist/assets/{jira-api-C_D_RDhl.js → jira-api-Cabj-H0J.js} +1 -1
- package/client/dist/assets/{project-repositories-Be0CWklo.js → project-repositories-Cnnuj9Ia.js} +1 -1
- package/client/dist/assets/{settings-Hw7av-B1.js → settings-B1NV8Ow9.js} +1 -1
- package/client/dist/assets/settings-BQ8XFZeE.js +1 -0
- package/client/dist/assets/settings-BRkxfBbO.js +1 -0
- package/client/dist/assets/settings-C_CcU1dP.js +1 -0
- package/client/dist/assets/settings-Cto9n0eL.js +1 -0
- package/client/dist/assets/{settings-nryN6wuS.js → settings-Pyw8uYtL.js} +1 -1
- package/client/dist/assets/settings-b3HVCNNd.js +1 -0
- package/client/dist/assets/settings-hdive4u6.js +1 -0
- package/client/dist/assets/{spending-eWiZGhC_.js → spending-CQnrWiR3.js} +1 -1
- package/client/dist/assets/{useDesktop-C0mRIlHT.js → useDesktop-BjLT0_EE.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-B1a6GChu.js → useRuntimeRuns-C97qEqMg.js} +1 -1
- package/client/dist/assets/{useSharedWebSocket-CcsE5986.js → useSharedWebSocket-Bj4LMp7b.js} +2 -2
- package/client/dist/index.html +15 -15
- package/docs/internals/api-reference.md +26 -0
- package/docs/internals/core-runtime-updates.md +3 -3
- package/docs/internals/source-map.md +9 -2
- package/local-runner/dist/specrails-local-runner.js +487 -148
- package/mcp-bridge/dist/specrails-mcp.js +330 -42
- package/package.json +6 -3
- package/server/dist/index.js +14 -1
- package/server/dist/mobile/mobile-admin-router.js +16 -0
- package/server/dist/mobile/mobile-gateway.js +18 -0
- package/server/dist/mobile/mobile-missions.js +6 -4
- package/server/dist/mobile/mobile-preview-channel.js +179 -0
- package/server/dist/mobile/mobile-preview.js +366 -0
- package/server/dist/mobile/mobile-router.js +9 -1
- package/server/dist/mobile/mobile-webrtc-peer.js +54 -4
- package/server/dist/mobile/mobile-ws.js +4 -2
- package/server/dist/modules/browser/domain/preview-origins.js +117 -0
- package/server/dist/modules/browser/runtime/browser-capture-manager.js +141 -18
- package/server/dist/modules/browser/runtime/browser-capture-types.js +10 -1
- package/server/dist/modules/browser/runtime/browser-playwright.js +19 -0
- package/server/dist/modules/browser/runtime/preview-targets.js +80 -0
- package/server/dist/modules/terminals/runtime/background-process-service.js +24 -1
- package/server/dist/project-registry.js +10 -0
- package/client/dist/assets/AgentsPage-DKE-eMC5.js +0 -118
- package/client/dist/assets/settings-BO2N-oPf.js +0 -1
- package/client/dist/assets/settings-BQChAs_w.js +0 -1
- package/client/dist/assets/settings-BzmYlcQB.js +0 -1
- package/client/dist/assets/settings-CGjXb6TX.js +0 -1
- package/client/dist/assets/settings-CMxEWY46.js +0 -1
- package/client/dist/assets/settings-C_dRSgI2.js +0 -1
|
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
try {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw mod = 0, e;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
9
16
|
var __export = (target, all) => {
|
|
10
17
|
for (var name in all)
|
|
11
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +34,110 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
34
|
mod
|
|
28
35
|
));
|
|
29
36
|
|
|
37
|
+
// node_modules/content-type/index.js
|
|
38
|
+
var require_content_type = __commonJS({
|
|
39
|
+
"node_modules/content-type/index.js"(exports2) {
|
|
40
|
+
"use strict";
|
|
41
|
+
var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
|
|
42
|
+
var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/;
|
|
43
|
+
var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
44
|
+
var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g;
|
|
45
|
+
var QUOTE_REGEXP = /([\\"])/g;
|
|
46
|
+
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
47
|
+
exports2.format = format;
|
|
48
|
+
exports2.parse = parse2;
|
|
49
|
+
function format(obj) {
|
|
50
|
+
if (!obj || typeof obj !== "object") {
|
|
51
|
+
throw new TypeError("argument obj is required");
|
|
52
|
+
}
|
|
53
|
+
var parameters = obj.parameters;
|
|
54
|
+
var type = obj.type;
|
|
55
|
+
if (!type || !TYPE_REGEXP.test(type)) {
|
|
56
|
+
throw new TypeError("invalid type");
|
|
57
|
+
}
|
|
58
|
+
var string4 = type;
|
|
59
|
+
if (parameters && typeof parameters === "object") {
|
|
60
|
+
var param;
|
|
61
|
+
var params = Object.keys(parameters).sort();
|
|
62
|
+
for (var i = 0; i < params.length; i++) {
|
|
63
|
+
param = params[i];
|
|
64
|
+
if (!TOKEN_REGEXP.test(param)) {
|
|
65
|
+
throw new TypeError("invalid parameter name");
|
|
66
|
+
}
|
|
67
|
+
string4 += "; " + param + "=" + qstring(parameters[param]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return string4;
|
|
71
|
+
}
|
|
72
|
+
function parse2(string4) {
|
|
73
|
+
if (!string4) {
|
|
74
|
+
throw new TypeError("argument string is required");
|
|
75
|
+
}
|
|
76
|
+
var header = typeof string4 === "object" ? getcontenttype(string4) : string4;
|
|
77
|
+
if (typeof header !== "string") {
|
|
78
|
+
throw new TypeError("argument string is required to be a string");
|
|
79
|
+
}
|
|
80
|
+
var index = header.indexOf(";");
|
|
81
|
+
var type = index !== -1 ? header.slice(0, index).trim() : header.trim();
|
|
82
|
+
if (!TYPE_REGEXP.test(type)) {
|
|
83
|
+
throw new TypeError("invalid media type");
|
|
84
|
+
}
|
|
85
|
+
var obj = new ContentType(type.toLowerCase());
|
|
86
|
+
if (index !== -1) {
|
|
87
|
+
var key;
|
|
88
|
+
var match;
|
|
89
|
+
var value;
|
|
90
|
+
PARAM_REGEXP.lastIndex = index;
|
|
91
|
+
while (match = PARAM_REGEXP.exec(header)) {
|
|
92
|
+
if (match.index !== index) {
|
|
93
|
+
throw new TypeError("invalid parameter format");
|
|
94
|
+
}
|
|
95
|
+
index += match[0].length;
|
|
96
|
+
key = match[1].toLowerCase();
|
|
97
|
+
value = match[2];
|
|
98
|
+
if (value.charCodeAt(0) === 34) {
|
|
99
|
+
value = value.slice(1, -1);
|
|
100
|
+
if (value.indexOf("\\") !== -1) {
|
|
101
|
+
value = value.replace(QESC_REGEXP, "$1");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
obj.parameters[key] = value;
|
|
105
|
+
}
|
|
106
|
+
if (index !== header.length) {
|
|
107
|
+
throw new TypeError("invalid parameter format");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return obj;
|
|
111
|
+
}
|
|
112
|
+
function getcontenttype(obj) {
|
|
113
|
+
var header;
|
|
114
|
+
if (typeof obj.getHeader === "function") {
|
|
115
|
+
header = obj.getHeader("content-type");
|
|
116
|
+
} else if (typeof obj.headers === "object") {
|
|
117
|
+
header = obj.headers && obj.headers["content-type"];
|
|
118
|
+
}
|
|
119
|
+
if (typeof header !== "string") {
|
|
120
|
+
throw new TypeError("content-type header is missing from object");
|
|
121
|
+
}
|
|
122
|
+
return header;
|
|
123
|
+
}
|
|
124
|
+
function qstring(val) {
|
|
125
|
+
var str = String(val);
|
|
126
|
+
if (TOKEN_REGEXP.test(str)) {
|
|
127
|
+
return str;
|
|
128
|
+
}
|
|
129
|
+
if (str.length > 0 && !TEXT_REGEXP.test(str)) {
|
|
130
|
+
throw new TypeError("invalid parameter value");
|
|
131
|
+
}
|
|
132
|
+
return '"' + str.replace(QUOTE_REGEXP, "\\$1") + '"';
|
|
133
|
+
}
|
|
134
|
+
function ContentType(type) {
|
|
135
|
+
this.parameters = /* @__PURE__ */ Object.create(null);
|
|
136
|
+
this.type = type;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
30
141
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
31
142
|
var import_node_process = __toESM(require("node:process"), 1);
|
|
32
143
|
|
|
@@ -5416,8 +5527,17 @@ var ServerResultSchema = union([
|
|
|
5416
5527
|
]);
|
|
5417
5528
|
|
|
5418
5529
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
5530
|
+
var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
5419
5531
|
var ReadBuffer = class {
|
|
5532
|
+
constructor(options) {
|
|
5533
|
+
this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
|
|
5534
|
+
}
|
|
5420
5535
|
append(chunk) {
|
|
5536
|
+
const newSize = (this._buffer?.length ?? 0) + chunk.length;
|
|
5537
|
+
if (newSize > this._maxBufferSize) {
|
|
5538
|
+
this.clear();
|
|
5539
|
+
throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
|
|
5540
|
+
}
|
|
5421
5541
|
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
5422
5542
|
}
|
|
5423
5543
|
readMessage() {
|
|
@@ -5445,18 +5565,24 @@ function serializeMessage(message) {
|
|
|
5445
5565
|
|
|
5446
5566
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
5447
5567
|
var StdioServerTransport = class {
|
|
5448
|
-
constructor(_stdin = import_node_process.default.stdin, _stdout = import_node_process.default.stdout) {
|
|
5568
|
+
constructor(_stdin = import_node_process.default.stdin, _stdout = import_node_process.default.stdout, options) {
|
|
5449
5569
|
this._stdin = _stdin;
|
|
5450
5570
|
this._stdout = _stdout;
|
|
5451
|
-
this._readBuffer = new ReadBuffer();
|
|
5452
5571
|
this._started = false;
|
|
5453
5572
|
this._ondata = (chunk) => {
|
|
5454
|
-
|
|
5455
|
-
|
|
5573
|
+
try {
|
|
5574
|
+
this._readBuffer.append(chunk);
|
|
5575
|
+
this.processReadBuffer();
|
|
5576
|
+
} catch (error2) {
|
|
5577
|
+
this.onerror?.(error2);
|
|
5578
|
+
this.close().catch(() => {
|
|
5579
|
+
});
|
|
5580
|
+
}
|
|
5456
5581
|
};
|
|
5457
5582
|
this._onerror = (error2) => {
|
|
5458
5583
|
this.onerror?.(error2);
|
|
5459
5584
|
};
|
|
5585
|
+
this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
|
|
5460
5586
|
}
|
|
5461
5587
|
/**
|
|
5462
5588
|
* Starts listening for messages on stdin.
|
|
@@ -5504,6 +5630,23 @@ var StdioServerTransport = class {
|
|
|
5504
5630
|
}
|
|
5505
5631
|
};
|
|
5506
5632
|
|
|
5633
|
+
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/mediaType.js
|
|
5634
|
+
var import_content_type = __toESM(require_content_type(), 1);
|
|
5635
|
+
function mediaTypeEssence(header) {
|
|
5636
|
+
if (!header) {
|
|
5637
|
+
return void 0;
|
|
5638
|
+
}
|
|
5639
|
+
try {
|
|
5640
|
+
return import_content_type.default.parse(header).type;
|
|
5641
|
+
} catch {
|
|
5642
|
+
const essence = (header.split(";", 1)[0] ?? "").trim().toLowerCase();
|
|
5643
|
+
if (essence === "" || header.slice(essence.length).includes(",")) {
|
|
5644
|
+
return void 0;
|
|
5645
|
+
}
|
|
5646
|
+
return essence;
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
|
|
5507
5650
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/shared/transport.js
|
|
5508
5651
|
function normalizeHeaders(headers) {
|
|
5509
5652
|
if (!headers)
|
|
@@ -5530,6 +5673,68 @@ function createFetchWithInit(baseFetch = fetch, baseInit) {
|
|
|
5530
5673
|
return baseFetch(url2, mergedInit);
|
|
5531
5674
|
};
|
|
5532
5675
|
}
|
|
5676
|
+
var MAX_REDIRECTS = 5;
|
|
5677
|
+
var REDIRECT_STATUSES = [301, 302, 303, 307, 308];
|
|
5678
|
+
function isWithinOrigin(from, to) {
|
|
5679
|
+
if (from.protocol === to.protocol && from.hostname === to.hostname && from.port === to.port) {
|
|
5680
|
+
return true;
|
|
5681
|
+
}
|
|
5682
|
+
return from.hostname === to.hostname && from.protocol === "http:" && from.port === "" && to.protocol === "https:" && to.port === "";
|
|
5683
|
+
}
|
|
5684
|
+
function redirectTarget(response, requestUrl) {
|
|
5685
|
+
const location = REDIRECT_STATUSES.includes(response.status) ? response.headers.get("location") : null;
|
|
5686
|
+
try {
|
|
5687
|
+
return location ? new URL(location, requestUrl) : void 0;
|
|
5688
|
+
} catch {
|
|
5689
|
+
return void 0;
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5692
|
+
function followWithinOrigin(baseFetch, url2, init, response, followed = 0) {
|
|
5693
|
+
const target = redirectTarget(response, url2);
|
|
5694
|
+
const keepsMethod = response.status === 307 || response.status === 308 || (init?.method ?? "GET").toUpperCase() === "GET";
|
|
5695
|
+
if (!target || followed === MAX_REDIRECTS || !keepsMethod) {
|
|
5696
|
+
return void 0;
|
|
5697
|
+
}
|
|
5698
|
+
const from = new URL(url2);
|
|
5699
|
+
const addsUserinfo = (target.username || target.password) && (target.username !== from.username || target.password !== from.password);
|
|
5700
|
+
if (addsUserinfo || !isWithinOrigin(from, target)) {
|
|
5701
|
+
return void 0;
|
|
5702
|
+
}
|
|
5703
|
+
return Promise.resolve(response.body?.cancel()).then(() => baseFetch(target, { ...init, redirect: "manual" })).then((next) => followWithinOrigin(baseFetch, target, init, next, followed + 1) ?? next);
|
|
5704
|
+
}
|
|
5705
|
+
var followingFetches = /* @__PURE__ */ new WeakSet();
|
|
5706
|
+
function fetchLeavingRedirects(baseFetch) {
|
|
5707
|
+
const following = (url2, init) => (baseFetch ?? fetch)(url2, init);
|
|
5708
|
+
followingFetches.add(following);
|
|
5709
|
+
return following;
|
|
5710
|
+
}
|
|
5711
|
+
function fetchWithinOrigin(baseFetch = fetch) {
|
|
5712
|
+
if (followingFetches.has(baseFetch)) {
|
|
5713
|
+
return baseFetch;
|
|
5714
|
+
}
|
|
5715
|
+
return (url2, init) => {
|
|
5716
|
+
if (init?.redirect === "error" || init?.redirect === "manual") {
|
|
5717
|
+
return baseFetch(url2, init);
|
|
5718
|
+
}
|
|
5719
|
+
return Promise.resolve(baseFetch(url2, { ...init, redirect: "manual" })).then((response) => followWithinOrigin(baseFetch, url2, init, response) ?? response);
|
|
5720
|
+
};
|
|
5721
|
+
}
|
|
5722
|
+
function unfollowedRedirect(response, requestUrl) {
|
|
5723
|
+
if (response.type === "opaqueredirect") {
|
|
5724
|
+
return "Redirect not followed: this runtime does not expose the redirect target";
|
|
5725
|
+
}
|
|
5726
|
+
const from = response.url || requestUrl;
|
|
5727
|
+
const target = redirectTarget(response, from);
|
|
5728
|
+
if (!target) {
|
|
5729
|
+
return void 0;
|
|
5730
|
+
}
|
|
5731
|
+
target.username = target.password = target.search = target.hash = "";
|
|
5732
|
+
if (target.protocol === "http:" && new URL(from).protocol === "https:") {
|
|
5733
|
+
target.protocol = "https:";
|
|
5734
|
+
return `Redirect to plain http not followed; try ${target.href} instead`;
|
|
5735
|
+
}
|
|
5736
|
+
return `Redirect to ${target.href} not followed`;
|
|
5737
|
+
}
|
|
5533
5738
|
|
|
5534
5739
|
// node_modules/pkce-challenge/dist/index.node.js
|
|
5535
5740
|
var crypto;
|
|
@@ -5676,7 +5881,12 @@ var OAuthTokensSchema = object({
|
|
|
5676
5881
|
token_type: string2(),
|
|
5677
5882
|
expires_in: coerce_exports.number().optional(),
|
|
5678
5883
|
scope: string2().optional(),
|
|
5679
|
-
refresh_token: string2().optional()
|
|
5884
|
+
refresh_token: string2().optional(),
|
|
5885
|
+
/**
|
|
5886
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
5887
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
5888
|
+
*/
|
|
5889
|
+
issuer: string2().optional().catch(void 0)
|
|
5680
5890
|
}).strip();
|
|
5681
5891
|
var OAuthErrorResponseSchema = object({
|
|
5682
5892
|
error: string2(),
|
|
@@ -5706,7 +5916,12 @@ var OAuthClientInformationSchema = object({
|
|
|
5706
5916
|
client_id: string2(),
|
|
5707
5917
|
client_secret: string2().optional(),
|
|
5708
5918
|
client_id_issued_at: number2().optional(),
|
|
5709
|
-
client_secret_expires_at: number2().optional()
|
|
5919
|
+
client_secret_expires_at: number2().optional(),
|
|
5920
|
+
/**
|
|
5921
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
5922
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
5923
|
+
*/
|
|
5924
|
+
issuer: string2().optional().catch(void 0)
|
|
5710
5925
|
}).strip();
|
|
5711
5926
|
var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
|
|
5712
5927
|
var OAuthClientRegistrationErrorSchema = object({
|
|
@@ -5904,10 +6119,31 @@ async function parseErrorResponse(input) {
|
|
|
5904
6119
|
const errorClass = OAUTH_ERRORS[error2] || ServerError;
|
|
5905
6120
|
return new errorClass(error_description || "", error_uri);
|
|
5906
6121
|
} catch (error2) {
|
|
5907
|
-
const
|
|
6122
|
+
const redirect = input instanceof Response ? unfollowedRedirect(input, input.url) : void 0;
|
|
6123
|
+
const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}${redirect ?? `Invalid OAuth error response: ${error2}. Raw body: ${body}`}`;
|
|
5908
6124
|
return new ServerError(errorMessage);
|
|
5909
6125
|
}
|
|
5910
6126
|
}
|
|
6127
|
+
function issuersMatch(a, b) {
|
|
6128
|
+
let [x, y] = [a, b];
|
|
6129
|
+
try {
|
|
6130
|
+
[x, y] = [new URL(a).href, new URL(b).href];
|
|
6131
|
+
} catch {
|
|
6132
|
+
}
|
|
6133
|
+
return x === y || x.endsWith("/") && x.slice(0, -1) === y || y.endsWith("/") && y.slice(0, -1) === x;
|
|
6134
|
+
}
|
|
6135
|
+
function discardIfIssuerMismatch(stored, issuer) {
|
|
6136
|
+
if (!stored)
|
|
6137
|
+
return void 0;
|
|
6138
|
+
if (typeof stored.issuer !== "string")
|
|
6139
|
+
return stored.issuer == null ? stored : { ...stored, issuer: void 0 };
|
|
6140
|
+
return issuersMatch(stored.issuer, issuer) ? stored : void 0;
|
|
6141
|
+
}
|
|
6142
|
+
var TokenResponseSchema = OAuthTokensSchema.omit({ issuer: true });
|
|
6143
|
+
var RegistrationResponseSchema = OAuthClientInformationFullSchema.omit({ issuer: true });
|
|
6144
|
+
function boundElsewhereError(stored, issuer) {
|
|
6145
|
+
return new Error(`OAuth client information is bound to authorization server ${stored.issuer} and is not presented to ${issuer}. Clear the stored client information, or correct \`expectedIssuer\`, if the authorization server has moved.`);
|
|
6146
|
+
}
|
|
5911
6147
|
async function auth(provider, options) {
|
|
5912
6148
|
try {
|
|
5913
6149
|
return await authInternal(provider, options);
|
|
@@ -5961,9 +6197,24 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
5961
6197
|
authorizationServerMetadata: metadata
|
|
5962
6198
|
});
|
|
5963
6199
|
}
|
|
5964
|
-
const
|
|
6200
|
+
const issuer = String(authorizationServerUrl);
|
|
6201
|
+
const selectedResource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
6202
|
+
const resource = selectedResource && resourceMetadata && !provider.validateResourceURL ? resourceMetadata.resource : selectedResource;
|
|
5965
6203
|
const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
|
|
5966
|
-
|
|
6204
|
+
const storedClientInformation = await Promise.resolve(provider.clientInformation());
|
|
6205
|
+
let clientInformation = discardIfIssuerMismatch(storedClientInformation, issuer);
|
|
6206
|
+
const canRegisterAgain = provider.saveClientInformation !== void 0 && !!provider.redirectUrl;
|
|
6207
|
+
if (storedClientInformation && !clientInformation && !canRegisterAgain) {
|
|
6208
|
+
throw boundElsewhereError(storedClientInformation, issuer);
|
|
6209
|
+
}
|
|
6210
|
+
const unstampedClientInformation = clientInformation?.issuer == null ? clientInformation : void 0;
|
|
6211
|
+
const bindClientInformation = async () => {
|
|
6212
|
+
try {
|
|
6213
|
+
if (unstampedClientInformation)
|
|
6214
|
+
await provider.saveClientInformation?.({ ...unstampedClientInformation, issuer });
|
|
6215
|
+
} catch {
|
|
6216
|
+
}
|
|
6217
|
+
};
|
|
5967
6218
|
if (!clientInformation) {
|
|
5968
6219
|
if (authorizationCode !== void 0) {
|
|
5969
6220
|
throw new Error("Existing OAuth client information is required when exchanging an authorization code");
|
|
@@ -5975,9 +6226,7 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
5975
6226
|
}
|
|
5976
6227
|
const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
|
|
5977
6228
|
if (shouldUseUrlBasedClientId) {
|
|
5978
|
-
clientInformation = {
|
|
5979
|
-
client_id: clientMetadataUrl
|
|
5980
|
-
};
|
|
6229
|
+
clientInformation = { client_id: clientMetadataUrl, issuer };
|
|
5981
6230
|
await provider.saveClientInformation?.(clientInformation);
|
|
5982
6231
|
} else {
|
|
5983
6232
|
if (!provider.saveClientInformation) {
|
|
@@ -5989,8 +6238,8 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
5989
6238
|
scope: resolvedScope,
|
|
5990
6239
|
fetchFn
|
|
5991
6240
|
});
|
|
5992
|
-
|
|
5993
|
-
clientInformation
|
|
6241
|
+
clientInformation = { ...fullInformation, issuer };
|
|
6242
|
+
await provider.saveClientInformation(clientInformation);
|
|
5994
6243
|
}
|
|
5995
6244
|
}
|
|
5996
6245
|
const nonInteractiveFlow = !provider.redirectUrl;
|
|
@@ -6001,10 +6250,14 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
6001
6250
|
authorizationCode,
|
|
6002
6251
|
fetchFn
|
|
6003
6252
|
});
|
|
6004
|
-
await
|
|
6253
|
+
await bindClientInformation();
|
|
6254
|
+
await provider.saveTokens({ ...tokens2, issuer });
|
|
6005
6255
|
return "AUTHORIZED";
|
|
6006
6256
|
}
|
|
6007
|
-
const tokens = await provider.tokens();
|
|
6257
|
+
const tokens = discardIfIssuerMismatch(await provider.tokens(), issuer);
|
|
6258
|
+
if (tokens?.refresh_token && tokens.issuer == null) {
|
|
6259
|
+
console.warn("[mcp-sdk] stored OAuth tokens have no 'issuer' property (saved by an earlier version, or by a provider that does not keep it) and are used as-is; make sure your OAuthClientProvider stores what saveTokens() and saveClientInformation() receive unchanged.");
|
|
6260
|
+
}
|
|
6008
6261
|
if (tokens?.refresh_token) {
|
|
6009
6262
|
try {
|
|
6010
6263
|
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
@@ -6015,7 +6268,8 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
6015
6268
|
addClientAuthentication: provider.addClientAuthentication,
|
|
6016
6269
|
fetchFn
|
|
6017
6270
|
});
|
|
6018
|
-
await
|
|
6271
|
+
await bindClientInformation();
|
|
6272
|
+
await provider.saveTokens({ ...newTokens, issuer });
|
|
6019
6273
|
return "AUTHORIZED";
|
|
6020
6274
|
} catch (error2) {
|
|
6021
6275
|
if (!(error2 instanceof OAuthError) || error2 instanceof ServerError) {
|
|
@@ -6114,7 +6368,7 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
|
|
|
6114
6368
|
}
|
|
6115
6369
|
async function fetchWithCorsRetry(url2, headers, fetchFn = fetch) {
|
|
6116
6370
|
try {
|
|
6117
|
-
return await fetchFn(url2, { headers });
|
|
6371
|
+
return await fetchWithinOrigin(fetchFn)(url2, { headers });
|
|
6118
6372
|
} catch (error2) {
|
|
6119
6373
|
if (error2 instanceof TypeError) {
|
|
6120
6374
|
if (headers) {
|
|
@@ -6139,7 +6393,7 @@ async function tryMetadataDiscovery(url2, protocolVersion, fetchFn = fetch) {
|
|
|
6139
6393
|
return await fetchWithCorsRetry(url2, headers, fetchFn);
|
|
6140
6394
|
}
|
|
6141
6395
|
function shouldAttemptFallback(response, pathname) {
|
|
6142
|
-
return !response || response.
|
|
6396
|
+
return !response || !response.ok && response.status < 500 && pathname !== "/";
|
|
6143
6397
|
}
|
|
6144
6398
|
async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
|
|
6145
6399
|
const issuer = new URL(serverUrl);
|
|
@@ -6205,7 +6459,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
|
|
|
6205
6459
|
}
|
|
6206
6460
|
if (!response.ok) {
|
|
6207
6461
|
await response.body?.cancel();
|
|
6208
|
-
if (response.status
|
|
6462
|
+
if (response.status < 500) {
|
|
6209
6463
|
continue;
|
|
6210
6464
|
}
|
|
6211
6465
|
throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
|
|
@@ -6238,6 +6492,9 @@ async function discoverOAuthServerInfo(serverUrl, opts) {
|
|
|
6238
6492
|
resourceMetadata
|
|
6239
6493
|
};
|
|
6240
6494
|
}
|
|
6495
|
+
function resourceIndicatorToString(resource) {
|
|
6496
|
+
return typeof resource === "string" ? resource : resource.href;
|
|
6497
|
+
}
|
|
6241
6498
|
async function startAuthorization(authorizationServerUrl, { metadata, clientInformation, redirectUrl, scope, state, resource }) {
|
|
6242
6499
|
let authorizationUrl;
|
|
6243
6500
|
if (metadata) {
|
|
@@ -6269,7 +6526,7 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
|
|
|
6269
6526
|
authorizationUrl.searchParams.append("prompt", "consent");
|
|
6270
6527
|
}
|
|
6271
6528
|
if (resource) {
|
|
6272
|
-
authorizationUrl.searchParams.set("resource", resource
|
|
6529
|
+
authorizationUrl.searchParams.set("resource", resourceIndicatorToString(resource));
|
|
6273
6530
|
}
|
|
6274
6531
|
return { authorizationUrl, codeVerifier };
|
|
6275
6532
|
}
|
|
@@ -6288,7 +6545,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
6288
6545
|
Accept: "application/json"
|
|
6289
6546
|
});
|
|
6290
6547
|
if (resource) {
|
|
6291
|
-
tokenRequestParams.set("resource", resource
|
|
6548
|
+
tokenRequestParams.set("resource", resourceIndicatorToString(resource));
|
|
6292
6549
|
}
|
|
6293
6550
|
if (addClientAuthentication) {
|
|
6294
6551
|
await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
|
|
@@ -6297,7 +6554,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
6297
6554
|
const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
|
|
6298
6555
|
applyClientAuthentication(authMethod, clientInformation, headers, tokenRequestParams);
|
|
6299
6556
|
}
|
|
6300
|
-
const response = await (fetchFn ?? fetch)(tokenUrl, {
|
|
6557
|
+
const response = await fetchWithinOrigin(fetchFn ?? fetch)(tokenUrl, {
|
|
6301
6558
|
method: "POST",
|
|
6302
6559
|
headers,
|
|
6303
6560
|
body: tokenRequestParams
|
|
@@ -6305,7 +6562,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
6305
6562
|
if (!response.ok) {
|
|
6306
6563
|
throw await parseErrorResponse(response);
|
|
6307
6564
|
}
|
|
6308
|
-
return
|
|
6565
|
+
return TokenResponseSchema.parse(await response.json());
|
|
6309
6566
|
}
|
|
6310
6567
|
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
|
|
6311
6568
|
const tokenRequestParams = new URLSearchParams({
|
|
@@ -6323,6 +6580,15 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
|
|
|
6323
6580
|
return { refresh_token: refreshToken, ...tokens };
|
|
6324
6581
|
}
|
|
6325
6582
|
async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
|
|
6583
|
+
const readClientInformation = async () => {
|
|
6584
|
+
const storedClientInformation = await provider.clientInformation();
|
|
6585
|
+
const checked = discardIfIssuerMismatch(storedClientInformation, String(authorizationServerUrl));
|
|
6586
|
+
if (storedClientInformation && !checked) {
|
|
6587
|
+
throw boundElsewhereError(storedClientInformation, String(authorizationServerUrl));
|
|
6588
|
+
}
|
|
6589
|
+
return checked;
|
|
6590
|
+
};
|
|
6591
|
+
let clientInformation = await readClientInformation();
|
|
6326
6592
|
const scope = provider.clientMetadata.scope;
|
|
6327
6593
|
let tokenRequestParams;
|
|
6328
6594
|
if (provider.prepareTokenRequest) {
|
|
@@ -6338,11 +6604,11 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
6338
6604
|
const codeVerifier = await provider.codeVerifier();
|
|
6339
6605
|
tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
|
|
6340
6606
|
}
|
|
6341
|
-
|
|
6607
|
+
clientInformation ?? (clientInformation = await readClientInformation());
|
|
6342
6608
|
return executeTokenRequest(authorizationServerUrl, {
|
|
6343
6609
|
metadata,
|
|
6344
6610
|
tokenRequestParams,
|
|
6345
|
-
clientInformation
|
|
6611
|
+
clientInformation,
|
|
6346
6612
|
addClientAuthentication: provider.addClientAuthentication,
|
|
6347
6613
|
resource,
|
|
6348
6614
|
fetchFn
|
|
@@ -6358,7 +6624,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
6358
6624
|
} else {
|
|
6359
6625
|
registrationUrl = new URL("/register", authorizationServerUrl);
|
|
6360
6626
|
}
|
|
6361
|
-
const response = await (fetchFn ?? fetch)(registrationUrl, {
|
|
6627
|
+
const response = await fetchWithinOrigin(fetchFn ?? fetch)(registrationUrl, {
|
|
6362
6628
|
method: "POST",
|
|
6363
6629
|
headers: {
|
|
6364
6630
|
"Content-Type": "application/json"
|
|
@@ -6371,7 +6637,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
6371
6637
|
if (!response.ok) {
|
|
6372
6638
|
throw await parseErrorResponse(response);
|
|
6373
6639
|
}
|
|
6374
|
-
return
|
|
6640
|
+
return RegistrationResponseSchema.parse(await response.json());
|
|
6375
6641
|
}
|
|
6376
6642
|
|
|
6377
6643
|
// node_modules/eventsource-parser/dist/index.js
|
|
@@ -6598,9 +6864,19 @@ var StreamableHTTPClientTransport = class {
|
|
|
6598
6864
|
this._authProvider = opts?.authProvider;
|
|
6599
6865
|
this._fetch = opts?.fetch;
|
|
6600
6866
|
this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
|
|
6867
|
+
this._followRedirects = opts?.redirectPolicy === "follow";
|
|
6868
|
+
if (this._followRedirects) {
|
|
6869
|
+
this._fetch = fetchLeavingRedirects(this._fetch);
|
|
6870
|
+
this._fetchWithInit = fetchLeavingRedirects(this._fetchWithInit);
|
|
6871
|
+
}
|
|
6601
6872
|
this._sessionId = opts?.sessionId;
|
|
6602
6873
|
this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
|
6603
6874
|
}
|
|
6875
|
+
/** Error text for a redirect `response` that was not followed, or `undefined` for any other response. */
|
|
6876
|
+
_unfollowedRedirect(response, url2) {
|
|
6877
|
+
const text = unfollowedRedirect(response, url2);
|
|
6878
|
+
return text && !this._followRedirects ? `${text} (redirectPolicy: 'same-origin')` : text;
|
|
6879
|
+
}
|
|
6604
6880
|
async _authThenStart() {
|
|
6605
6881
|
if (!this._authProvider) {
|
|
6606
6882
|
throw new UnauthorizedError("No auth provider");
|
|
@@ -6650,11 +6926,13 @@ var StreamableHTTPClientTransport = class {
|
|
|
6650
6926
|
if (resumptionToken) {
|
|
6651
6927
|
headers.set("last-event-id", resumptionToken);
|
|
6652
6928
|
}
|
|
6653
|
-
const
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6929
|
+
const fetchFn = this._fetch ?? fetch;
|
|
6930
|
+
const init = { method: "GET", headers, signal: this._abortController?.signal };
|
|
6931
|
+
let response = await fetchFn(this._url, this._followRedirects ? init : { ...init, redirect: "manual" });
|
|
6932
|
+
const followed = this._followRedirects ? void 0 : followWithinOrigin(fetchFn, this._url, init, response);
|
|
6933
|
+
if (followed) {
|
|
6934
|
+
response = await followed;
|
|
6935
|
+
}
|
|
6658
6936
|
if (!response.ok) {
|
|
6659
6937
|
await response.body?.cancel();
|
|
6660
6938
|
if (response.status === 401 && this._authProvider) {
|
|
@@ -6663,7 +6941,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
6663
6941
|
if (response.status === 405) {
|
|
6664
6942
|
return;
|
|
6665
6943
|
}
|
|
6666
|
-
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
|
|
6944
|
+
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${this._unfollowedRedirect(response, this._url) ?? response.statusText}`);
|
|
6667
6945
|
}
|
|
6668
6946
|
this._handleSseStream(response.body, options, true);
|
|
6669
6947
|
} catch (error2) {
|
|
@@ -6826,7 +7104,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
6826
7104
|
body: JSON.stringify(message),
|
|
6827
7105
|
signal: this._abortController?.signal
|
|
6828
7106
|
};
|
|
6829
|
-
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
7107
|
+
const response = await fetchWithinOrigin(this._fetch ?? fetch)(this._url, init);
|
|
6830
7108
|
const sessionId = response.headers.get("mcp-session-id");
|
|
6831
7109
|
if (sessionId) {
|
|
6832
7110
|
this._sessionId = sessionId;
|
|
@@ -6878,7 +7156,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
6878
7156
|
return this.send(message);
|
|
6879
7157
|
}
|
|
6880
7158
|
}
|
|
6881
|
-
throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
|
|
7159
|
+
throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${this._unfollowedRedirect(response, this._url) ?? text}`);
|
|
6882
7160
|
}
|
|
6883
7161
|
this._hasCompletedAuthFlow = false;
|
|
6884
7162
|
this._lastUpscopingHeader = void 0;
|
|
@@ -6891,11 +7169,12 @@ var StreamableHTTPClientTransport = class {
|
|
|
6891
7169
|
}
|
|
6892
7170
|
const messages = Array.isArray(message) ? message : [message];
|
|
6893
7171
|
const hasRequests = messages.filter((msg) => "method" in msg && "id" in msg && msg.id !== void 0).length > 0;
|
|
6894
|
-
const
|
|
7172
|
+
const contentType2 = response.headers.get("content-type");
|
|
7173
|
+
const responseMediaType = mediaTypeEssence(contentType2);
|
|
6895
7174
|
if (hasRequests) {
|
|
6896
|
-
if (
|
|
7175
|
+
if (responseMediaType === "text/event-stream") {
|
|
6897
7176
|
this._handleSseStream(response.body, { onresumptiontoken }, false);
|
|
6898
|
-
} else if (
|
|
7177
|
+
} else if (responseMediaType === "application/json") {
|
|
6899
7178
|
const data = await response.json();
|
|
6900
7179
|
const responseMessages = Array.isArray(data) ? data.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data)];
|
|
6901
7180
|
for (const msg of responseMessages) {
|
|
@@ -6903,7 +7182,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
6903
7182
|
}
|
|
6904
7183
|
} else {
|
|
6905
7184
|
await response.body?.cancel();
|
|
6906
|
-
throw new StreamableHTTPError(-1, `Unexpected content type: ${
|
|
7185
|
+
throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType2}`);
|
|
6907
7186
|
}
|
|
6908
7187
|
} else {
|
|
6909
7188
|
await response.body?.cancel();
|
|
@@ -6939,10 +7218,10 @@ var StreamableHTTPClientTransport = class {
|
|
|
6939
7218
|
headers,
|
|
6940
7219
|
signal: this._abortController?.signal
|
|
6941
7220
|
};
|
|
6942
|
-
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
7221
|
+
const response = await fetchWithinOrigin(this._fetch ?? fetch)(this._url, init);
|
|
6943
7222
|
await response.body?.cancel();
|
|
6944
7223
|
if (!response.ok && response.status !== 405) {
|
|
6945
|
-
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
|
|
7224
|
+
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${this._unfollowedRedirect(response, this._url) ?? response.statusText}`);
|
|
6946
7225
|
}
|
|
6947
7226
|
this._sessionId = void 0;
|
|
6948
7227
|
} catch (error2) {
|
|
@@ -7251,3 +7530,12 @@ main().catch((err) => {
|
|
|
7251
7530
|
`);
|
|
7252
7531
|
process.exit(1);
|
|
7253
7532
|
});
|
|
7533
|
+
/*! Bundled license information:
|
|
7534
|
+
|
|
7535
|
+
content-type/index.js:
|
|
7536
|
+
(*!
|
|
7537
|
+
* content-type
|
|
7538
|
+
* Copyright(c) 2015 Douglas Christopher Wilson
|
|
7539
|
+
* MIT Licensed
|
|
7540
|
+
*)
|
|
7541
|
+
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specrails-desktop",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.64.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"cross-spawn": "^7.0.6",
|
|
63
63
|
"diff": "^9.0.0",
|
|
64
64
|
"express": "^5.2.1",
|
|
65
|
-
"js-yaml": "4.
|
|
65
|
+
"js-yaml": "4.3.2",
|
|
66
66
|
"multer": "^2.2.0",
|
|
67
67
|
"node-pty": "^1.0.0",
|
|
68
68
|
"pdf-parse": "^2.4.5",
|
|
@@ -96,6 +96,9 @@
|
|
|
96
96
|
},
|
|
97
97
|
"overrides": {
|
|
98
98
|
"ip": "npm:@eggjs/ip@2.1.0",
|
|
99
|
-
"shell-quote": "1.
|
|
99
|
+
"shell-quote": "1.12.0",
|
|
100
|
+
"@tailwindcss/typography": {
|
|
101
|
+
"postcss-selector-parser": "7.1.6"
|
|
102
|
+
}
|
|
100
103
|
}
|
|
101
104
|
}
|
package/server/dist/index.js
CHANGED
|
@@ -623,7 +623,20 @@ function applyPtyWsRateLimiting(ws) {
|
|
|
623
623
|
// Second HTTPS+WSS listener in THIS process; the main server stays loopback.
|
|
624
624
|
// The control plane is desktop-only: loopback + (via /api below) requireAuth.
|
|
625
625
|
// Mounted before the /api desktop router so its sub-path is unambiguous.
|
|
626
|
-
const mobileGateway = new mobile_1.MobileGateway({
|
|
626
|
+
const mobileGateway = new mobile_1.MobileGateway({
|
|
627
|
+
desktopDb: registry.desktopDb,
|
|
628
|
+
desktopPort: port,
|
|
629
|
+
broadcast,
|
|
630
|
+
// Companion app preview: each project's browser + the process-log targets.
|
|
631
|
+
preview: {
|
|
632
|
+
enabled: () => BROWSER_CAPTURE_ENABLED,
|
|
633
|
+
browserFor: (projectId) => registry.getContext(projectId)?.browserCaptureManager ?? null,
|
|
634
|
+
allBrowsers: () => registry.listProjects()
|
|
635
|
+
.map((project) => registry.getContext(project.id)?.browserCaptureManager)
|
|
636
|
+
.filter((manager) => manager != null),
|
|
637
|
+
targets: registry.previewTargets,
|
|
638
|
+
},
|
|
639
|
+
});
|
|
627
640
|
_mobileGateway = mobileGateway;
|
|
628
641
|
app.use('/api/mobile', auth_1.requireLoopback, (0, mobile_1.createMobileAdminRouter)({
|
|
629
642
|
gateway: mobileGateway,
|