@skylandnpm/octopus-proxy 0.1.29 → 0.1.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-XHNRMXZT.js → chunk-PYZSSOSD.js} +9 -44
- package/dist/cli.js +1 -1
- package/dist/main.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ octopus-proxy onboard
|
|
|
15
15
|
|
|
16
16
|
向导默认使用 `https://octopus.wuyehao.com` 作为 Hub 地址;按需可输入其他地址,或用 `--hub-url` 指定。再次运行向导时会读取现有配置,直接回车即可保留各项设置;机器人 Secret 只提示已配置,不在终端显示原值。macOS 上选择编码工具时,向导优先显示已配置或探测到的命令路径,否则给出该工具的 macOS 路径示例;回车后会检查文件可执行性并运行版本命令,失败时要求重新输入。无交互环境可使用 `octopus-proxy onboard --non-interactive`,未提供 `--hub-url` 时也使用该默认地址;完整选项见 `octopus-proxy help`。安装服务后可运行 `octopus-proxy status` 和 `octopus-proxy doctor` 检查状态。
|
|
17
17
|
|
|
18
|
-
Proxy 始终使用独立的控制与文件 WebSocket;文件读取和上传不会回退到控制通道。两个通道会同时连接并各自重连,Hub 只会把文件命令发送到同一 Proxy
|
|
18
|
+
Proxy 始终使用独立的控制与文件 WebSocket;文件读取和上传不会回退到控制通道。两个通道会同时连接并各自重连,Hub 只会把文件命令发送到同一 Proxy 实例的已就绪文件通道。控制与文件连接在 `X-Octopus-Proxy-Instance-Id` 中分别使用 `:control`、`:files` 后缀;Hub 去除后缀再配对实例,因此即使反向代理把 `/ws/proxy-files` 重写为上游 `/ws/proxy`,也能正确识别文件通道。反向代理需转发 WebSocket Upgrade、Authorization、`X-Octopus-Bot-Id` 与 `X-Octopus-Proxy-Instance-Id`。同一套 bot ID 和 Secret 被另一台 Proxy 主机连接后,Hub 会让新实例接管,旧实例会同时关闭两个通道并停止自动重连;若要让旧实例重新接管,必须显式重启其服务。
|
|
19
19
|
|
|
20
20
|
添加授权项目时,填写项目 ID 后会询问是否继续添加;直接回车即可结束添加并继续保存配置。
|
|
21
21
|
|
|
@@ -16630,29 +16630,6 @@ function createAdapter(runtime, workspace, uploads, emit) {
|
|
|
16630
16630
|
return new OpenCodeAdapter(runtime, workspace, uploads, forward);
|
|
16631
16631
|
}
|
|
16632
16632
|
|
|
16633
|
-
// src/hub-channel-compatibility.ts
|
|
16634
|
-
var HubChannelCompatibility = class {
|
|
16635
|
-
enabled = false;
|
|
16636
|
-
filesAttemptedAt = 0;
|
|
16637
|
-
filesFailures = 0;
|
|
16638
|
-
filesAttempt(now = Date.now()) {
|
|
16639
|
-
this.filesAttemptedAt = now;
|
|
16640
|
-
}
|
|
16641
|
-
filesWelcome() {
|
|
16642
|
-
this.filesFailures = 0;
|
|
16643
|
-
}
|
|
16644
|
-
controlClosed(filesPending, now = Date.now()) {
|
|
16645
|
-
if (this.enabled || !filesPending || now - this.filesAttemptedAt >= 5e3) return false;
|
|
16646
|
-
this.enabled = true;
|
|
16647
|
-
return true;
|
|
16648
|
-
}
|
|
16649
|
-
filesClosedBeforeWelcome(stopping) {
|
|
16650
|
-
if (this.enabled || stopping || ++this.filesFailures < 3) return false;
|
|
16651
|
-
this.enabled = true;
|
|
16652
|
-
return true;
|
|
16653
|
-
}
|
|
16654
|
-
};
|
|
16655
|
-
|
|
16656
16633
|
// src/proxy-binding.ts
|
|
16657
16634
|
var PROXY_REPLACED_CLOSE_CODE = 4009;
|
|
16658
16635
|
var ProxyBinding = class {
|
|
@@ -16802,7 +16779,6 @@ async function runDaemon(configPath) {
|
|
|
16802
16779
|
const workspace = new Workspace(config.projects), runtime = createRuntime(config), uploads = new Uploads(workspace, join10(config.stateDirectory, "uploads")), journal = new Journal(join10(config.stateDirectory, "journal"));
|
|
16803
16780
|
const epoch = randomUUID12();
|
|
16804
16781
|
let stopping = false, botId = "";
|
|
16805
|
-
const hubChannels = new HubChannelCompatibility();
|
|
16806
16782
|
const binding = new ProxyBinding();
|
|
16807
16783
|
const sockets = /* @__PURE__ */ new Set();
|
|
16808
16784
|
let controlSocket, filesSocket;
|
|
@@ -16871,29 +16847,27 @@ async function runDaemon(configPath) {
|
|
|
16871
16847
|
return adapter.dispatch(c);
|
|
16872
16848
|
}
|
|
16873
16849
|
function activateChannels() {
|
|
16874
|
-
if (channelsActivated || !controlWelcome || !filesWelcomed
|
|
16850
|
+
if (channelsActivated || !controlWelcome || !filesWelcomed || controlWelcome.socket.readyState !== WebSocket2.OPEN) return;
|
|
16875
16851
|
channelsActivated = true;
|
|
16876
16852
|
events.bind(controlWelcome.socket, controlWelcome.resume);
|
|
16877
16853
|
for (const p of config.projects) emit(p.id, "octopus.resync", {});
|
|
16878
16854
|
}
|
|
16879
16855
|
function connect(files, attempt = 0) {
|
|
16880
|
-
if (stopping || !binding.active
|
|
16856
|
+
if (stopping || !binding.active) return;
|
|
16857
|
+
const current = files ? filesSocket : controlSocket;
|
|
16858
|
+
if (current && current.readyState !== WebSocket2.CLOSED) return;
|
|
16881
16859
|
const url = new URL(files ? "/ws/proxy-files" : "/ws/proxy", config.hubUrl);
|
|
16882
16860
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
16883
16861
|
const headers = {
|
|
16884
16862
|
Authorization: `SecretKey ${config.secretKey}`,
|
|
16885
16863
|
"X-Octopus-Bot-Id": config.botId,
|
|
16886
|
-
"X-Octopus-Proxy-Instance-Id": epoch
|
|
16887
|
-
// Preserve the logical channel when a reverse proxy rewrites
|
|
16888
|
-
// /ws/proxy-files to the generic /ws/proxy upstream endpoint.
|
|
16889
|
-
"X-Octopus-Proxy-Channel": files ? "files" : "control"
|
|
16864
|
+
"X-Octopus-Proxy-Instance-Id": `${epoch}:${files ? "files" : "control"}`
|
|
16890
16865
|
};
|
|
16891
16866
|
const socket = new WebSocket2(url, { headers, maxPayload: 3 * 1024 * 1024 });
|
|
16892
16867
|
sockets.add(socket);
|
|
16893
16868
|
if (files) {
|
|
16894
16869
|
filesSocket = socket;
|
|
16895
16870
|
filesWelcomed = false;
|
|
16896
|
-
hubChannels.filesAttempt();
|
|
16897
16871
|
} else controlSocket = socket;
|
|
16898
16872
|
let lastPong = Date.now();
|
|
16899
16873
|
const heartbeat = setInterval(() => {
|
|
@@ -16918,10 +16892,8 @@ async function runDaemon(configPath) {
|
|
|
16918
16892
|
if (value.type === "welcome") {
|
|
16919
16893
|
botId = value.botId;
|
|
16920
16894
|
uploads.limits = value.limits;
|
|
16921
|
-
if (files)
|
|
16922
|
-
|
|
16923
|
-
hubChannels.filesWelcome();
|
|
16924
|
-
} else controlWelcome = { socket, resume: value.resume };
|
|
16895
|
+
if (files) filesWelcomed = true;
|
|
16896
|
+
else controlWelcome = { socket, resume: value.resume };
|
|
16925
16897
|
activateChannels();
|
|
16926
16898
|
return;
|
|
16927
16899
|
}
|
|
@@ -16956,17 +16928,10 @@ async function runDaemon(configPath) {
|
|
|
16956
16928
|
console.error("This bot was claimed by another Proxy instance; automatic reconnection is disabled until this service is restarted");
|
|
16957
16929
|
for (const peer of sockets) peer.close();
|
|
16958
16930
|
}
|
|
16959
|
-
|
|
16960
|
-
const rejectedFilesChannel = binding.active && files && !filesWelcomed && hubChannels.filesClosedBeforeWelcome(stopping);
|
|
16961
|
-
if (collision || rejectedFilesChannel) {
|
|
16962
|
-
console.warn("Hub does not preserve the Proxy files channel; keeping the control channel online until Hub routing is upgraded");
|
|
16963
|
-
filesSocket?.close();
|
|
16964
|
-
filesSocket = void 0;
|
|
16965
|
-
activateChannels();
|
|
16966
|
-
} else if (!stopping && binding.active && code !== 1e3) {
|
|
16931
|
+
if (!stopping && binding.active && code !== 1e3) {
|
|
16967
16932
|
console.warn(`Hub ${files ? "files" : "control"} connection closed: ${code}${reason.length ? ` ${reason.toString()}` : ""}`);
|
|
16968
16933
|
}
|
|
16969
|
-
if (!stopping && binding.active
|
|
16934
|
+
if (!stopping && binding.active) setTimeout(() => connect(files, attempt + 1), Math.min(3e4, 1e3 * 2 ** Math.min(attempt, 5)) + Math.random() * 500);
|
|
16970
16935
|
});
|
|
16971
16936
|
}
|
|
16972
16937
|
await runtime.init().catch((error) => console.error(`${runtime.kind} startup:`, error.message));
|
package/dist/cli.js
CHANGED
package/dist/main.js
CHANGED