opencode-telegram-link 1.0.0-rc.3 → 1.0.0-rc.5
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 +3 -3
- package/dist/broker/commands.d.ts.map +1 -1
- package/dist/broker/main.js +173 -53
- package/dist/broker/main.js.map +9 -8
- package/dist/opencode/config-helper.d.ts.map +1 -1
- package/dist/plugin.js +24 -28
- package/dist/plugin.js.map +4 -4
- package/dist/service.d.ts +19 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/uninstall.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
OpenCode Telegram Notifier is a privacy-first OpenCode plugin and multi-host management gateway for asynchronous notifications, interactive inline buttons, safe remote replies, and proactive remote task dispatching. It is designed for developers who run OpenCode across multiple projects and multiple computers (dev machine, laptop, VPS) while routing every Telegram and Web interaction to the exact originating host, process, and workspace window.
|
|
4
4
|
|
|
5
|
-
> Version: **v1.0.0-rc.
|
|
6
|
-
> Status: Release Candidate
|
|
5
|
+
> Version: **v1.0.0-rc.5** (OpenCode Commander Web Dashboard, Proactive Remote Dispatch, Multi-Engine Voice STT, Multi-Host Gateway & Node Agent Architecture).
|
|
6
|
+
> Status: Release Candidate 5. Install from a release tarball or source checkout until the first public npm package is published.
|
|
7
7
|
|
|
8
8
|
[繁體中文總覽 (Traditional Chinese)](docs/README.zh-TW.md)
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
## Features & Highlights (v1.0.0-rc.
|
|
12
|
+
## Features & Highlights (v1.0.0-rc.5)
|
|
13
13
|
|
|
14
14
|
- 🖥️ **OpenCode Commander (Web GUI Dashboard)**: Built-in modern Glassmorphism Web Console (`http://<gateway-ip>:42617/dashboard`) providing real-time visibility, live metrics, and centralized cluster management.
|
|
15
15
|
- 🌐 **Cluster Topology & 1-to-1 Window Mapping**: Live cards for all connected computers and OpenCode workspace windows with real-time session indicators and task counters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/broker/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,kBAAkB,EAExB,MAAM,UAAU,CAAC;AAElB,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,wBAAsB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/broker/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,kBAAkB,EAExB,MAAM,UAAU,CAAC;AAElB,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D,CAAC;AAEF,wBAAsB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsC9F;AA2DD,wBAAsB,cAAc,CAClC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,cAAc,EACvB,mBAAmB,GAAE,OAAO,KAAa,GACxC,OAAO,CAAC,MAAM,CAAC,CAejB"}
|
package/dist/broker/main.js
CHANGED
|
@@ -14518,9 +14518,9 @@ var DiagnosticSchema = exports_external.object({
|
|
|
14518
14518
|
|
|
14519
14519
|
// src/setup.ts
|
|
14520
14520
|
import { randomBytes as randomBytes2, randomUUID as randomUUID3 } from "crypto";
|
|
14521
|
-
import { existsSync, readFileSync } from "fs";
|
|
14522
|
-
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir3, open as open2, readFile as readFile5, rename as rename4, rm as rm2, writeFile as
|
|
14523
|
-
import { hostname as hostname3, platform as
|
|
14521
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
14522
|
+
import { chmod as chmod3, lstat as lstat5, mkdir as mkdir3, open as open2, readFile as readFile5, rename as rename4, rm as rm2, writeFile as writeFile4 } from "fs/promises";
|
|
14523
|
+
import { hostname as hostname3, platform as platform5 } from "os";
|
|
14524
14524
|
import { dirname as dirname2, join as join5, resolve as resolve2 } from "path";
|
|
14525
14525
|
|
|
14526
14526
|
// src/config.ts
|
|
@@ -15781,14 +15781,11 @@ async function injectOpenCodeConfig(targetPath, config2) {
|
|
|
15781
15781
|
chatId: config2.telegram.chatId
|
|
15782
15782
|
};
|
|
15783
15783
|
}
|
|
15784
|
+
delete existingJson["opencode-telegram-link"];
|
|
15785
|
+
delete existingJson["telegram-link"];
|
|
15784
15786
|
const isMatch = (entry) => {
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
}
|
|
15788
|
-
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
15789
|
-
return entry[0] === "opencode-telegram-link" || entry[0].endsWith("opencode-telegram-link");
|
|
15790
|
-
}
|
|
15791
|
-
return false;
|
|
15787
|
+
const name = typeof entry === "string" ? entry : Array.isArray(entry) && typeof entry[0] === "string" ? entry[0] : "";
|
|
15788
|
+
return name === "opencode-telegram-link" || name.startsWith("opencode-telegram-link") || name.includes("opencode-telegram-link") || name.includes("opencode_notification") || name.includes("telegram-link");
|
|
15792
15789
|
};
|
|
15793
15790
|
function mergePluginOptions(existing, updated) {
|
|
15794
15791
|
const existingObj = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
@@ -15811,19 +15808,15 @@ async function injectOpenCodeConfig(targetPath, config2) {
|
|
|
15811
15808
|
return merged;
|
|
15812
15809
|
}
|
|
15813
15810
|
if (Array.isArray(existingJson.plugin)) {
|
|
15814
|
-
const
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
|
|
15819
|
-
|
|
15820
|
-
} else {
|
|
15821
|
-
existingJson.plugin.push(["opencode-telegram-link", pluginConfig]);
|
|
15822
|
-
}
|
|
15811
|
+
const existingEntry = existingJson.plugin.find(isMatch);
|
|
15812
|
+
const existingOptions = Array.isArray(existingEntry) ? existingEntry[1] : undefined;
|
|
15813
|
+
const mergedOptions = mergePluginOptions(existingOptions, pluginConfig);
|
|
15814
|
+
const cleanedPlugins = existingJson.plugin.filter((p) => !isMatch(p));
|
|
15815
|
+
cleanedPlugins.push(["opencode-telegram-link", mergedOptions]);
|
|
15816
|
+
existingJson.plugin = cleanedPlugins;
|
|
15823
15817
|
} else if (Array.isArray(existingJson.plugins)) {
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
}
|
|
15818
|
+
const plugins = existingJson.plugins;
|
|
15819
|
+
existingJson.plugins = [...plugins.filter((p) => !isMatch(p)), "opencode-telegram-link"];
|
|
15827
15820
|
const existingPluginMap = existingJson.plugin && typeof existingJson.plugin === "object" ? existingJson.plugin : {};
|
|
15828
15821
|
existingPluginMap["opencode-telegram-link"] = mergePluginOptions(existingPluginMap["opencode-telegram-link"], pluginConfig);
|
|
15829
15822
|
existingJson.plugin = existingPluginMap;
|
|
@@ -15845,14 +15838,17 @@ async function removeOpenCodeConfig(targetPath) {
|
|
|
15845
15838
|
const existingJson = parseJsonc(existingContent);
|
|
15846
15839
|
let modified = false;
|
|
15847
15840
|
const isPluginMatch = (entry) => {
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
}
|
|
15851
|
-
if (Array.isArray(entry) && typeof entry[0] === "string") {
|
|
15852
|
-
return isPluginMatch(entry[0]);
|
|
15853
|
-
}
|
|
15854
|
-
return false;
|
|
15841
|
+
const name = typeof entry === "string" ? entry : Array.isArray(entry) && typeof entry[0] === "string" ? entry[0] : "";
|
|
15842
|
+
return name === "opencode-telegram-link" || name.startsWith("opencode-telegram-link") || name.includes("opencode-telegram-link") || name.includes("opencode_notification") || name.includes("telegram-link");
|
|
15855
15843
|
};
|
|
15844
|
+
if ("opencode-telegram-link" in existingJson) {
|
|
15845
|
+
delete existingJson["opencode-telegram-link"];
|
|
15846
|
+
modified = true;
|
|
15847
|
+
}
|
|
15848
|
+
if ("telegram-link" in existingJson) {
|
|
15849
|
+
delete existingJson["telegram-link"];
|
|
15850
|
+
modified = true;
|
|
15851
|
+
}
|
|
15856
15852
|
if (Array.isArray(existingJson.plugin)) {
|
|
15857
15853
|
const originalLength = existingJson.plugin.length;
|
|
15858
15854
|
const filtered = existingJson.plugin.filter((p) => !isPluginMatch(p));
|
|
@@ -15892,6 +15888,93 @@ async function removeOpenCodeConfig(targetPath) {
|
|
|
15892
15888
|
return { modified: false };
|
|
15893
15889
|
}
|
|
15894
15890
|
}
|
|
15891
|
+
// src/service.ts
|
|
15892
|
+
import { existsSync } from "fs";
|
|
15893
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
15894
|
+
import { homedir as homedir3, platform as platform4 } from "os";
|
|
15895
|
+
function isSystemdAvailable() {
|
|
15896
|
+
if (platform4() !== "linux")
|
|
15897
|
+
return false;
|
|
15898
|
+
try {
|
|
15899
|
+
const result = Bun.spawnSync(["systemctl", "--version"]);
|
|
15900
|
+
return result.exitCode === 0;
|
|
15901
|
+
} catch {
|
|
15902
|
+
return false;
|
|
15903
|
+
}
|
|
15904
|
+
}
|
|
15905
|
+
function generateSystemdService(options = {}) {
|
|
15906
|
+
const user = options.user || process.env.USER || "root";
|
|
15907
|
+
const home = options.home || process.env.HOME || homedir3();
|
|
15908
|
+
const envPath = options.envPath || process.env.PATH || "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
15909
|
+
const execPath = options.execPath || process.execPath;
|
|
15910
|
+
const binScript = options.binScript || process.argv[1] || "opencode-telegram-link";
|
|
15911
|
+
return `[Unit]
|
|
15912
|
+
Description=OpenCode Telegram Gateway & Commander
|
|
15913
|
+
After=network.target
|
|
15914
|
+
|
|
15915
|
+
[Service]
|
|
15916
|
+
Type=simple
|
|
15917
|
+
User=${user}
|
|
15918
|
+
WorkingDirectory=${home}
|
|
15919
|
+
Environment=HOME=${home}
|
|
15920
|
+
Environment="PATH=${envPath}"
|
|
15921
|
+
Environment="OPENCODE_TELEGRAM_BROKER_BIND_HOST=0.0.0.0"
|
|
15922
|
+
ExecStart=${execPath} ${binScript} start --bind-host 0.0.0.0
|
|
15923
|
+
Restart=always
|
|
15924
|
+
RestartSec=5
|
|
15925
|
+
|
|
15926
|
+
[Install]
|
|
15927
|
+
WantedBy=multi-user.target
|
|
15928
|
+
`;
|
|
15929
|
+
}
|
|
15930
|
+
async function installSystemdService(options = {}) {
|
|
15931
|
+
try {
|
|
15932
|
+
const serviceContent = generateSystemdService(options);
|
|
15933
|
+
const tmpServicePath = `/tmp/opencode-gateway.${process.pid}.service`;
|
|
15934
|
+
await writeFile2(tmpServicePath, serviceContent, "utf8");
|
|
15935
|
+
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
15936
|
+
const cpCmd = isRoot ? ["cp", tmpServicePath, "/etc/systemd/system/opencode-gateway.service"] : ["sudo", "cp", tmpServicePath, "/etc/systemd/system/opencode-gateway.service"];
|
|
15937
|
+
const cpResult = Bun.spawnSync(cpCmd);
|
|
15938
|
+
if (cpResult.exitCode !== 0) {
|
|
15939
|
+
const err = cpResult.stderr ? new TextDecoder().decode(cpResult.stderr) : "Failed to copy service file";
|
|
15940
|
+
return { success: false, error: err };
|
|
15941
|
+
}
|
|
15942
|
+
const reloadCmd = isRoot ? ["systemctl", "daemon-reload"] : ["sudo", "systemctl", "daemon-reload"];
|
|
15943
|
+
Bun.spawnSync(reloadCmd);
|
|
15944
|
+
const enableCmd = isRoot ? ["systemctl", "enable", "--now", "opencode-gateway"] : ["sudo", "systemctl", "enable", "--now", "opencode-gateway"];
|
|
15945
|
+
const enableResult = Bun.spawnSync(enableCmd);
|
|
15946
|
+
if (enableResult.exitCode !== 0) {
|
|
15947
|
+
const err = enableResult.stderr ? new TextDecoder().decode(enableResult.stderr) : "Failed to enable service";
|
|
15948
|
+
return { success: false, error: err };
|
|
15949
|
+
}
|
|
15950
|
+
return { success: true };
|
|
15951
|
+
} catch (err) {
|
|
15952
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
15953
|
+
}
|
|
15954
|
+
}
|
|
15955
|
+
async function uninstallSystemdService() {
|
|
15956
|
+
const serviceFile = "/etc/systemd/system/opencode-gateway.service";
|
|
15957
|
+
if (!existsSync(serviceFile)) {
|
|
15958
|
+
return { success: true, removed: false };
|
|
15959
|
+
}
|
|
15960
|
+
try {
|
|
15961
|
+
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
15962
|
+
const disableCmd = isRoot ? ["systemctl", "disable", "--now", "opencode-gateway"] : ["sudo", "systemctl", "disable", "--now", "opencode-gateway"];
|
|
15963
|
+
Bun.spawnSync(disableCmd);
|
|
15964
|
+
const rmCmd = isRoot ? ["rm", "-f", serviceFile] : ["sudo", "rm", "-f", serviceFile];
|
|
15965
|
+
Bun.spawnSync(rmCmd);
|
|
15966
|
+
const reloadCmd = isRoot ? ["systemctl", "daemon-reload"] : ["sudo", "systemctl", "daemon-reload"];
|
|
15967
|
+
Bun.spawnSync(reloadCmd);
|
|
15968
|
+
return { success: true, removed: true };
|
|
15969
|
+
} catch (err) {
|
|
15970
|
+
return {
|
|
15971
|
+
success: false,
|
|
15972
|
+
removed: false,
|
|
15973
|
+
error: err instanceof Error ? err.message : String(err)
|
|
15974
|
+
};
|
|
15975
|
+
}
|
|
15976
|
+
}
|
|
15977
|
+
|
|
15895
15978
|
// src/state/database.ts
|
|
15896
15979
|
import { Database } from "bun:sqlite";
|
|
15897
15980
|
import { chmod as chmod2, copyFile as copyFile2, lstat as lstat4, rename as rename2 } from "fs/promises";
|
|
@@ -16389,7 +16472,7 @@ var SCHEMA_VERSION_2 = `
|
|
|
16389
16472
|
`;
|
|
16390
16473
|
// src/state/discovery.ts
|
|
16391
16474
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
16392
|
-
import { readFile as readFile4, rename as rename3, rm, writeFile as
|
|
16475
|
+
import { readFile as readFile4, rename as rename3, rm, writeFile as writeFile3 } from "fs/promises";
|
|
16393
16476
|
import { join as join4 } from "path";
|
|
16394
16477
|
var DiscoveryRecordSchema = exports_external.object({
|
|
16395
16478
|
port: exports_external.number().int().min(1).max(65535),
|
|
@@ -16411,7 +16494,7 @@ async function writeDiscoveryRecord(stateDirectory, port) {
|
|
|
16411
16494
|
};
|
|
16412
16495
|
const destination = discoveryRecordPath(stateDirectory);
|
|
16413
16496
|
const temporary = `${destination}.${record2.nonce}.tmp`;
|
|
16414
|
-
await
|
|
16497
|
+
await writeFile3(temporary, `${JSON.stringify(record2)}
|
|
16415
16498
|
`, { encoding: "utf8", mode: 384 });
|
|
16416
16499
|
await rename3(temporary, destination);
|
|
16417
16500
|
return record2;
|
|
@@ -16658,7 +16741,7 @@ class TelegramApiError extends Error {
|
|
|
16658
16741
|
|
|
16659
16742
|
// src/setup.ts
|
|
16660
16743
|
function resolveDockerComposeContext(cwd = process.cwd(), explicitComposePath) {
|
|
16661
|
-
if (explicitComposePath &&
|
|
16744
|
+
if (explicitComposePath && existsSync2(explicitComposePath)) {
|
|
16662
16745
|
return {
|
|
16663
16746
|
composeFile: explicitComposePath,
|
|
16664
16747
|
projectDir: dirname2(explicitComposePath)
|
|
@@ -16671,7 +16754,7 @@ function resolveDockerComposeContext(cwd = process.cwd(), explicitComposePath) {
|
|
|
16671
16754
|
];
|
|
16672
16755
|
for (const file2 of packageCandidates) {
|
|
16673
16756
|
try {
|
|
16674
|
-
if (
|
|
16757
|
+
if (existsSync2(file2)) {
|
|
16675
16758
|
return {
|
|
16676
16759
|
composeFile: file2,
|
|
16677
16760
|
projectDir: dirname2(file2)
|
|
@@ -16681,7 +16764,7 @@ function resolveDockerComposeContext(cwd = process.cwd(), explicitComposePath) {
|
|
|
16681
16764
|
}
|
|
16682
16765
|
const cwdCompose = join5(cwd, "docker-compose.yml");
|
|
16683
16766
|
try {
|
|
16684
|
-
if (
|
|
16767
|
+
if (existsSync2(cwdCompose)) {
|
|
16685
16768
|
const content = readFileSync(cwdCompose, "utf8");
|
|
16686
16769
|
if (content.includes("opencode-telegram-broker") || content.includes("broker.Dockerfile")) {
|
|
16687
16770
|
return {
|
|
@@ -17015,7 +17098,7 @@ async function runInteractiveSetup(options = {}) {
|
|
|
17015
17098
|
const tokenFile = join5(stateDirectory, "telegram-bot-token");
|
|
17016
17099
|
await writePrivateTokenFile(stateDirectory, tokenFile, botToken);
|
|
17017
17100
|
const identityFile = join5(stateDirectory, "telegram-identity.json");
|
|
17018
|
-
await
|
|
17101
|
+
await writeFile4(identityFile, `${JSON.stringify({ userId: pairing.userId, chatId: pairing.chatId, tokenFile, locale }, null, 2)}
|
|
17019
17102
|
`, "utf8");
|
|
17020
17103
|
stdout.write(isZh ? `\u2502 \u2714 \u5B89\u5168 Token \u6A94\u6848\u5DF2\u5132\u5B58 (${tokenFile})
|
|
17021
17104
|
` : `\u2502 \u2714 Secure token file saved (${tokenFile})
|
|
@@ -17146,9 +17229,32 @@ ${generatePluginConfigSnippet(configData)}
|
|
|
17146
17229
|
} else {
|
|
17147
17230
|
stdout.write(`\u2502
|
|
17148
17231
|
`);
|
|
17149
|
-
|
|
17232
|
+
if (!isNode && isSystemdAvailable()) {
|
|
17233
|
+
const autoSystemd = await reader.ask(isZh ? "\u25C7 \u662F\u5426\u5C07 Gateway \u8A3B\u518A\u70BA Systemd \u7CFB\u7D71\u958B\u6A5F\u81EA\u52D5\u555F\u52D5\u670D\u52D9\uFF1F [Y/n]: " : "\u25C7 Register Gateway as a systemd background service (auto-start on boot)? [Y/n]: ", stdout, "Y");
|
|
17234
|
+
if (autoSystemd.toLowerCase() !== "n" && autoSystemd.toLowerCase() !== "no") {
|
|
17235
|
+
stdout.write(isZh ? `\u2502 \u280B \u6B63\u5728\u8A3B\u518A\u4E26\u555F\u7528 Systemd \u670D\u52D9 (opencode-gateway.service)...
|
|
17236
|
+
` : `\u2502 \u280B Registering and enabling systemd service (opencode-gateway.service)...
|
|
17237
|
+
`);
|
|
17238
|
+
const serviceResult = await installSystemdService();
|
|
17239
|
+
if (serviceResult.success) {
|
|
17240
|
+
stdout.write(isZh ? `\u2502 \u2714 Systemd \u670D\u52D9\u5DF2\u6210\u529F\u5EFA\u7ACB\u4E26\u555F\u52D5\uFF01\u91CD\u958B\u6A5F\u6642\u5C07\u81EA\u52D5\u5728\u80CC\u666F\u57F7\u884C\u3002
|
|
17241
|
+
` : `\u2502 \u2714 Systemd service created and enabled! Will auto-start on boot.
|
|
17242
|
+
`);
|
|
17243
|
+
} else {
|
|
17244
|
+
stdout.write(isZh ? `\u2502 \u2716 Systemd \u670D\u52D9\u8A3B\u518A\u5931\u6557: ${serviceResult.error}\uFF08\u60A8\u53EF\u65BC\u7A0D\u5F8C\u624B\u52D5\u555F\u52D5: npx opencode-telegram-link start\uFF09
|
|
17245
|
+
` : `\u2502 \u2716 Failed to register systemd service: ${serviceResult.error}
|
|
17246
|
+
`);
|
|
17247
|
+
}
|
|
17248
|
+
} else {
|
|
17249
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672C\u6A5F\u539F\u751F\u6A21\u5F0F\u5DF2\u8A2D\u5B9A\u5B8C\u6210\uFF01\u7576 OpenCode \u555F\u52D5\u6642\u5C07\u81EA\u52D5\u5728\u80CC\u666F\u63A5\u7BA1 Broker\u3002
|
|
17250
|
+
` : `\u2502 \u2714 Native mode configured! OpenCode will automatically manage Broker in background.
|
|
17251
|
+
`);
|
|
17252
|
+
}
|
|
17253
|
+
} else {
|
|
17254
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672C\u6A5F\u539F\u751F\u6A21\u5F0F\u5DF2\u8A2D\u5B9A\u5B8C\u6210\uFF01\u7576 OpenCode \u555F\u52D5\u6642\u5C07\u81EA\u52D5\u5728\u80CC\u666F\u63A5\u7BA1 Broker\u3002
|
|
17150
17255
|
` : `\u2502 \u2714 Native mode configured! OpenCode will automatically manage Broker in background.
|
|
17151
17256
|
`);
|
|
17257
|
+
}
|
|
17152
17258
|
}
|
|
17153
17259
|
if (!isNode && pairing && api2) {
|
|
17154
17260
|
stdout.write(`\u2502
|
|
@@ -17333,7 +17439,7 @@ async function assertPrivateFile(path) {
|
|
|
17333
17439
|
await assertPrivateMode(path, stats.mode, 384);
|
|
17334
17440
|
}
|
|
17335
17441
|
async function assertPrivateMode(path, mode, expectedMode) {
|
|
17336
|
-
if (
|
|
17442
|
+
if (platform5() === "win32")
|
|
17337
17443
|
return;
|
|
17338
17444
|
if ((mode & 63) !== 0) {
|
|
17339
17445
|
throw new SetupError("SETUP_PERMISSIONS_UNSAFE", "setup state must not allow group or other access");
|
|
@@ -17341,7 +17447,7 @@ async function assertPrivateMode(path, mode, expectedMode) {
|
|
|
17341
17447
|
await chmodPrivate(path, expectedMode);
|
|
17342
17448
|
}
|
|
17343
17449
|
async function chmodPrivate(path, mode) {
|
|
17344
|
-
if (
|
|
17450
|
+
if (platform5() !== "win32")
|
|
17345
17451
|
await chmod3(path, mode);
|
|
17346
17452
|
}
|
|
17347
17453
|
function parseSetupArgs(argv) {
|
|
@@ -17442,7 +17548,7 @@ function publicBot(bot) {
|
|
|
17442
17548
|
|
|
17443
17549
|
// src/uninstall.ts
|
|
17444
17550
|
import { rm as rm4 } from "fs/promises";
|
|
17445
|
-
import { homedir as
|
|
17551
|
+
import { homedir as homedir4, tmpdir } from "os";
|
|
17446
17552
|
import { join as join8 } from "path";
|
|
17447
17553
|
|
|
17448
17554
|
// src/broker/registry.ts
|
|
@@ -17751,7 +17857,7 @@ function sameSessionRoute(left, right) {
|
|
|
17751
17857
|
}
|
|
17752
17858
|
// src/broker/server.ts
|
|
17753
17859
|
import { createHash as createHash5, randomUUID as randomUUID6, timingSafeEqual } from "crypto";
|
|
17754
|
-
import { readFile as readFile6, writeFile as
|
|
17860
|
+
import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
17755
17861
|
import { join as join6 } from "path";
|
|
17756
17862
|
|
|
17757
17863
|
// src/i18n/catalogs.ts
|
|
@@ -17986,7 +18092,7 @@ function rejectionHash(updateId, reason) {
|
|
|
17986
18092
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17987
18093
|
|
|
17988
18094
|
// src/version.ts
|
|
17989
|
-
var PACKAGE_VERSION = "1.0.0-rc.
|
|
18095
|
+
var PACKAGE_VERSION = "1.0.0-rc.5";
|
|
17990
18096
|
|
|
17991
18097
|
// src/telegram/commands.ts
|
|
17992
18098
|
function isSlashCommand(text) {
|
|
@@ -20053,7 +20159,7 @@ async function loadDashboardSettings(stateDirectory) {
|
|
|
20053
20159
|
}
|
|
20054
20160
|
async function saveDashboardSettings(stateDirectory, settings) {
|
|
20055
20161
|
const filePath = join6(stateDirectory, "dashboard-settings.json");
|
|
20056
|
-
await
|
|
20162
|
+
await writeFile5(filePath, JSON.stringify(settings, null, 2), "utf-8");
|
|
20057
20163
|
}
|
|
20058
20164
|
async function readJsonBody(request) {
|
|
20059
20165
|
const text = await request.text();
|
|
@@ -21459,10 +21565,11 @@ async function runBrokerCli(options = {}) {
|
|
|
21459
21565
|
stdout: options.stdout ?? process.stdout,
|
|
21460
21566
|
stderr: options.stderr ?? process.stderr
|
|
21461
21567
|
};
|
|
21462
|
-
const
|
|
21463
|
-
const
|
|
21568
|
+
const normalizedArgv = argv[0] === "broker" ? argv.slice(1) : argv;
|
|
21569
|
+
const command = normalizedArgv[0];
|
|
21570
|
+
const flags = parseFlags(normalizedArgv.slice(1));
|
|
21464
21571
|
const brokerOptions = brokerOptionsFrom(flags, env);
|
|
21465
|
-
if (!command || command === "start") {
|
|
21572
|
+
if (!command || command === "start" || command === "run") {
|
|
21466
21573
|
return await runStartCommand(brokerOptions, streams, options.onStarted);
|
|
21467
21574
|
}
|
|
21468
21575
|
try {
|
|
@@ -21740,12 +21847,25 @@ async function runInteractiveUninstall(options = {}) {
|
|
|
21740
21847
|
stdout.write(isZh ? `\u25C7 [1/4] \u6B63\u5728\u6AA2\u67E5\u4E26\u505C\u6B62\u57F7\u884C\u4E2D\u7684 Broker (\u672C\u6A5F\u7A0B\u5E8F\u6216 Docker \u5BB9\u5668)...
|
|
21741
21848
|
` : `\u25C7 [1/4] Checking and stopping running Broker (native process or Docker container)...
|
|
21742
21849
|
`);
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
21746
|
-
|
|
21747
|
-
|
|
21850
|
+
const composeContext = resolveDockerComposeContext(cwd);
|
|
21851
|
+
if (composeContext) {
|
|
21852
|
+
try {
|
|
21853
|
+
const dockerCmd = process.platform === "win32" ? "docker.exe" : "docker";
|
|
21854
|
+
const dockerDown = Bun.spawnSync([dockerCmd, "compose", "down"], {
|
|
21855
|
+
cwd: composeContext.projectDir
|
|
21856
|
+
});
|
|
21857
|
+
if (dockerDown.exitCode === 0) {
|
|
21858
|
+
stdout.write(isZh ? `\u2502 \u2714 Docker Broker \u5BB9\u5668\u5DF2\u505C\u6B62\u4E26\u6E05\u7406\u3002
|
|
21748
21859
|
` : `\u2502 \u2714 Docker Broker container stopped and cleaned up.
|
|
21860
|
+
`);
|
|
21861
|
+
}
|
|
21862
|
+
} catch {}
|
|
21863
|
+
}
|
|
21864
|
+
try {
|
|
21865
|
+
const systemdResult = await uninstallSystemdService();
|
|
21866
|
+
if (systemdResult.removed) {
|
|
21867
|
+
stdout.write(isZh ? `\u2502 \u2714 Systemd \u670D\u52D9 (opencode-gateway.service) \u5DF2\u505C\u7528\u4E26\u79FB\u9664\u3002
|
|
21868
|
+
` : `\u2502 \u2714 Systemd service (opencode-gateway.service) stopped and removed.
|
|
21749
21869
|
`);
|
|
21750
21870
|
}
|
|
21751
21871
|
} catch {}
|
|
@@ -21792,8 +21912,8 @@ async function runInteractiveUninstall(options = {}) {
|
|
|
21792
21912
|
}
|
|
21793
21913
|
const symlinkLocations = [
|
|
21794
21914
|
join8(cwd, "node_modules", "opencode-telegram-link"),
|
|
21795
|
-
join8(
|
|
21796
|
-
join8(
|
|
21915
|
+
join8(homedir4(), ".config", "opencode", "node_modules", "opencode-telegram-link"),
|
|
21916
|
+
join8(homedir4(), ".opencode", "node_modules", "opencode-telegram-link")
|
|
21797
21917
|
];
|
|
21798
21918
|
for (const symlink of symlinkLocations) {
|
|
21799
21919
|
try {
|
|
@@ -21913,4 +22033,4 @@ export {
|
|
|
21913
22033
|
runBroker
|
|
21914
22034
|
};
|
|
21915
22035
|
|
|
21916
|
-
//# debugId=
|
|
22036
|
+
//# debugId=6769A77FD917233264756E2164756E21
|