opencode-telegram-link 1.0.0-rc.2 → 1.0.0-rc.3
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/main.js +380 -364
- package/dist/broker/main.js.map +6 -6
- package/dist/plugin.js +2 -2
- package/dist/plugin.js.map +2 -2
- package/dist/setup.d.ts +2 -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/dist/broker/main.js
CHANGED
|
@@ -16704,11 +16704,18 @@ class SetupError extends Error {
|
|
|
16704
16704
|
}
|
|
16705
16705
|
|
|
16706
16706
|
class AsyncPromptReader {
|
|
16707
|
+
input;
|
|
16707
16708
|
iterator;
|
|
16708
16709
|
buffer = "";
|
|
16709
16710
|
constructor(input) {
|
|
16711
|
+
this.input = input;
|
|
16710
16712
|
this.iterator = input[Symbol.asyncIterator]();
|
|
16711
16713
|
}
|
|
16714
|
+
close() {
|
|
16715
|
+
if (this.input && "pause" in this.input && typeof this.input.pause === "function") {
|
|
16716
|
+
this.input.pause();
|
|
16717
|
+
}
|
|
16718
|
+
}
|
|
16712
16719
|
async readLine() {
|
|
16713
16720
|
while (true) {
|
|
16714
16721
|
const newlineIndex = this.buffer.indexOf(`
|
|
@@ -16796,360 +16803,361 @@ async function runInteractiveSetup(options = {}) {
|
|
|
16796
16803
|
const stderr = options.stderr ?? process.stderr;
|
|
16797
16804
|
const fetchImpl = options.fetch ?? fetch;
|
|
16798
16805
|
const reader = new AsyncPromptReader(options.stdin ?? process.stdin);
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16806
|
+
try {
|
|
16807
|
+
const now = options.now ?? Date.now;
|
|
16808
|
+
const stateDirectory = options.stateDirectory ?? defaultStateDirectory();
|
|
16809
|
+
const cwd = options.cwd ?? process.cwd();
|
|
16810
|
+
stdout.write(`
|
|
16803
16811
|
\u250C OpenCode Telegram Notifier \u2014 Setup Wizard
|
|
16804
16812
|
\u2502
|
|
16805
16813
|
`);
|
|
16806
|
-
|
|
16814
|
+
stdout.write(`\u25C7 Language / \u8A9E\u8A00:
|
|
16807
16815
|
`);
|
|
16808
|
-
|
|
16816
|
+
stdout.write(`\u2502 1) \u7E41\u9AD4\u4E2D\u6587 (zh-TW) [\u9810\u8A2D/Default]
|
|
16809
16817
|
`);
|
|
16810
|
-
|
|
16818
|
+
stdout.write(`\u2502 2) English (en)
|
|
16811
16819
|
`);
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
|
|
16820
|
+
const langChoice = await reader.ask("\u2502 \u8ACB\u9078\u64C7 / Select [1]: ", stdout, "1");
|
|
16821
|
+
const locale = langChoice === "2" || langChoice.toLowerCase() === "en" ? "en" : "zh-TW";
|
|
16822
|
+
const isZh = locale === "zh-TW";
|
|
16823
|
+
stdout.write(`\u2502
|
|
16816
16824
|
`);
|
|
16817
|
-
|
|
16825
|
+
stdout.write(isZh ? `\u25C7 \u8ACB\u9078\u64C7\u6B64\u6A5F\u5668\u7684\u89D2\u8272 (Role):
|
|
16818
16826
|
\u2502 1) \u7368\u7ACB Gateway \u6A21\u5F0F (Gateway Mode) [\u9810\u8A2D/Default] \u2014 \u64C1\u6709\u5C08\u5C6C Telegram Bot\uFF0C\u53EF\u4F9B\u672C\u6A5F\u8207\u5176\u4ED6\u7BC0\u9EDE\u9023\u7DDA
|
|
16819
16827
|
\u2502 2) \u7BC0\u9EDE Agent \u6A21\u5F0F (Node Agent Mode) \u2014 \u9023\u7DDA\u81F3\u73FE\u6709\u7684 Gateway\uFF0C\u5171\u7528 Telegram Bot
|
|
16820
16828
|
` : `\u25C7 Select machine role:
|
|
16821
16829
|
\u2502 1) Standalone Gateway Mode [Default] \u2014 Owns a Telegram Bot, serves local and remote nodes
|
|
16822
16830
|
\u2502 2) Node Agent Mode \u2014 Connects to an existing Gateway, shares Telegram Bot
|
|
16823
16831
|
`);
|
|
16824
|
-
|
|
16825
|
-
|
|
16826
|
-
|
|
16827
|
-
|
|
16832
|
+
const roleChoice = await reader.ask(isZh ? "\u2502 \u8ACB\u9078\u64C7 / Select [1]: " : "\u2502 Select [1]: ", stdout, "1");
|
|
16833
|
+
const isNode = roleChoice === "2" || roleChoice.toLowerCase().includes("node");
|
|
16834
|
+
const defaultHost = hostname3() || "host";
|
|
16835
|
+
stdout.write(`\u2502
|
|
16828
16836
|
`);
|
|
16829
|
-
|
|
16837
|
+
stdout.write(isZh ? `\u25C7 \u4E3B\u6A5F\u8B58\u5225\u6A19\u7C64 (Host Label) [\u9810\u8A2D: ${defaultHost}]:
|
|
16830
16838
|
\u2502 (\u6B64\u6A19\u7C64\u5C07\u986F\u793A\u65BC Telegram \u901A\u77E5\u9802\u90E8\uFF0C\u4FBF\u65BC\u8B58\u5225\u4F86\u6E90\u4E3B\u6A5F)
|
|
16831
16839
|
` : `\u25C7 Host Label [Default: ${defaultHost}]:
|
|
16832
16840
|
\u2502 (Shown in notification header to identify this machine)
|
|
16833
16841
|
`);
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
+
const hostLabel = await reader.ask(isZh ? `\u2502 \u6A19\u7C64\u540D\u7A31 [${defaultHost}]: ` : `\u2502 Label [${defaultHost}]: `, stdout, defaultHost);
|
|
16843
|
+
let configData;
|
|
16844
|
+
let isDocker = false;
|
|
16845
|
+
let pairing;
|
|
16846
|
+
let api2;
|
|
16847
|
+
let botInfo;
|
|
16848
|
+
if (isNode) {
|
|
16849
|
+
stdout.write(`\u2502
|
|
16842
16850
|
`);
|
|
16843
|
-
|
|
16851
|
+
stdout.write(isZh ? `\u25C7 \u8ACB\u8F38\u5165 Central Gateway \u7684 WebSocket \u4F4D\u5740:
|
|
16844
16852
|
\u2502 (\u7BC4\u4F8B: ws://192.168.1.100:42617 \u6216 wss://gateway.example.com)
|
|
16845
16853
|
` : `\u25C7 Enter Central Gateway WebSocket URL:
|
|
16846
16854
|
\u2502 (Example: ws://192.168.1.100:42617 or wss://gateway.example.com)
|
|
16847
16855
|
`);
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16856
|
+
const gatewayUrl = await reader.ask("\u2502 Gateway URL: ", stdout);
|
|
16857
|
+
if (!gatewayUrl) {
|
|
16858
|
+
stderr.write(isZh ? `\u2716 Gateway URL \u4E0D\u80FD\u70BA\u7A7A\u3002
|
|
16851
16859
|
` : `\u2716 Gateway URL cannot be empty.
|
|
16852
16860
|
`);
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16861
|
+
return 1;
|
|
16862
|
+
}
|
|
16863
|
+
stdout.write(`\u2502
|
|
16856
16864
|
`);
|
|
16857
|
-
|
|
16865
|
+
stdout.write(isZh ? `\u25C7 \u8ACB\u8F38\u5165 Gateway \u9023\u7DDA\u91D1\u9470 (Secret Token):
|
|
16858
16866
|
\u2502 (\u82E5 Gateway \u7121\u9700\u91D1\u9470\u53EF\u76F4\u63A5\u6309 Enter)
|
|
16859
16867
|
` : `\u25C7 Enter Gateway Secret Token:
|
|
16860
16868
|
\u2502 (Press Enter if no secret required)
|
|
16861
16869
|
`);
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16871
|
-
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
|
|
16877
|
-
|
|
16878
|
-
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16870
|
+
const gatewaySecret = await reader.ask("\u2502 Secret: ", stdout, "");
|
|
16871
|
+
configData = {
|
|
16872
|
+
mode: "local",
|
|
16873
|
+
role: "node",
|
|
16874
|
+
hostLabel,
|
|
16875
|
+
locale,
|
|
16876
|
+
gateway: {
|
|
16877
|
+
url: gatewayUrl,
|
|
16878
|
+
secret: gatewaySecret || "default-secret"
|
|
16879
|
+
},
|
|
16880
|
+
notifications: {
|
|
16881
|
+
completion: true,
|
|
16882
|
+
error: true,
|
|
16883
|
+
question: true,
|
|
16884
|
+
permission: true,
|
|
16885
|
+
includeChildLifecycle: false,
|
|
16886
|
+
completionDebounceMs: 1500,
|
|
16887
|
+
pluginBufferSize: 100
|
|
16888
|
+
},
|
|
16889
|
+
broker: {
|
|
16890
|
+
host: "127.0.0.1",
|
|
16891
|
+
port: 42617
|
|
16892
|
+
},
|
|
16893
|
+
interaction: {
|
|
16894
|
+
sessionPromptTtlMinutes: 1440,
|
|
16895
|
+
questionTtlMinutes: 30
|
|
16896
|
+
}
|
|
16897
|
+
};
|
|
16898
|
+
} else {
|
|
16899
|
+
stdout.write(`\u2502
|
|
16892
16900
|
`);
|
|
16893
|
-
|
|
16901
|
+
stdout.write(isZh ? `\u25C7 \u90E8\u7F72\u6A21\u5F0F\u9078\u64C7 / Deployment Mode:
|
|
16894
16902
|
\u2502 1) \u672C\u6A5F\u539F\u751F\u6A21\u5F0F (Native Mode) [\u9810\u8A2D/Default] \u2014 Broker \u4F5C\u70BA\u672C\u6A5F\u5E38\u99D0\u7A0B\u5E8F\uFF0COpenCode \u81EA\u52D5\u5728\u80CC\u666F\u62C9\u8D77
|
|
16895
16903
|
\u2502 2) Docker \u5BB9\u5668\u6A21\u5F0F (Docker Container) \u2014 Broker \u9694\u96E2\u65BC Docker \u5BB9\u5668\u4E2D\u57F7\u884C
|
|
16896
16904
|
` : `\u25C7 Deployment Mode:
|
|
16897
16905
|
\u2502 1) Native Mode [Default] \u2014 Broker runs as a local background process, auto-spawned by OpenCode
|
|
16898
16906
|
\u2502 2) Docker Container Mode \u2014 Broker runs isolated inside a Docker container
|
|
16899
16907
|
`);
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
|
|
16908
|
+
const modeChoice = await reader.ask(isZh ? "\u2502 \u8ACB\u9078\u64C7 / Select [1]: " : "\u2502 Select [1]: ", stdout, "1");
|
|
16909
|
+
isDocker = modeChoice === "2" || modeChoice.toLowerCase().includes("docker");
|
|
16910
|
+
let botToken = "";
|
|
16911
|
+
let attempts = 0;
|
|
16912
|
+
while (!botInfo) {
|
|
16913
|
+
attempts += 1;
|
|
16914
|
+
if (attempts > 5) {
|
|
16915
|
+
stderr.write(isZh ? `\u2716 \u8D85\u904E\u91CD\u8A66\u6B21\u6578\uFF0C\u8A2D\u5B9A\u7D42\u6B62\u3002
|
|
16908
16916
|
` : `\u2716 Too many attempts. Aborted.
|
|
16909
16917
|
`);
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16918
|
+
return 1;
|
|
16919
|
+
}
|
|
16920
|
+
stdout.write(`\u2502
|
|
16913
16921
|
`);
|
|
16914
|
-
|
|
16915
|
-
|
|
16922
|
+
if (isZh) {
|
|
16923
|
+
stdout.write(`\u25C7 \u8ACB\u8F38\u5165\u5411 @BotFather \u7533\u8ACB\u7684 Telegram Bot Token:
|
|
16916
16924
|
`);
|
|
16917
|
-
|
|
16925
|
+
stdout.write(`\u2502 (\u7BC4\u4F8B: 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ)
|
|
16918
16926
|
`);
|
|
16919
|
-
|
|
16920
|
-
|
|
16927
|
+
} else {
|
|
16928
|
+
stdout.write(`\u25C7 Enter your Telegram Bot Token from @BotFather:
|
|
16921
16929
|
`);
|
|
16922
|
-
|
|
16930
|
+
stdout.write(`\u2502 (Example: 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ)
|
|
16923
16931
|
`);
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
|
|
16927
|
-
|
|
16932
|
+
}
|
|
16933
|
+
botToken = await reader.ask("\u2502 Token: ", stdout);
|
|
16934
|
+
if (!botToken) {
|
|
16935
|
+
stdout.write(isZh ? `\u2502 \u2716 Token \u4E0D\u80FD\u70BA\u7A7A\uFF0C\u8ACB\u91CD\u65B0\u8F38\u5165\u3002
|
|
16928
16936
|
` : `\u2502 \u2716 Token cannot be empty.
|
|
16929
16937
|
`);
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16938
|
+
continue;
|
|
16939
|
+
}
|
|
16940
|
+
if (!/^\d+:[A-Za-z0-9_-]{20,}$/.test(botToken)) {
|
|
16941
|
+
stdout.write(isZh ? `\u2502 \u2716 Token \u683C\u5F0F\u4E0D\u7B26\u5408 Telegram \u898F\u7BC4\uFF0C\u8ACB\u91CD\u65B0\u8F38\u5165\u3002
|
|
16934
16942
|
` : `\u2502 \u2716 Invalid token format.
|
|
16935
16943
|
`);
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16944
|
+
continue;
|
|
16945
|
+
}
|
|
16946
|
+
stdout.write(isZh ? `\u2502 \u280B \u6B63\u5728\u5411 Telegram \u9A57\u8B49 Bot Token...
|
|
16939
16947
|
` : `\u2502 \u280B Verifying Bot Token with Telegram...
|
|
16940
16948
|
`);
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16949
|
+
api2 = new TelegramBotApi({ token: botToken, fetch: fetchImpl });
|
|
16950
|
+
try {
|
|
16951
|
+
botInfo = await api2.getMe();
|
|
16952
|
+
const botName2 = botInfo.username ? `@${botInfo.username}` : `bot ${botInfo.id}`;
|
|
16953
|
+
stdout.write(isZh ? `\u2502 \u2714 \u9023\u7DDA\u6210\u529F\uFF01\u5DF2\u8FA8\u8B58 Bot: ${botName2} (ID: ${botInfo.id})
|
|
16946
16954
|
` : `\u2502 \u2714 Connected! Identified Bot: ${botName2} (ID: ${botInfo.id})
|
|
16947
16955
|
`);
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16956
|
+
} catch (err) {
|
|
16957
|
+
const errMsg = err instanceof Error ? err.message : "connection failed";
|
|
16958
|
+
stdout.write(isZh ? `\u2502 \u2716 Token \u9A57\u8B49\u5931\u6557 (${errMsg})\uFF0C\u8ACB\u78BA\u8A8D\u5F8C\u91CD\u8A66\u3002
|
|
16951
16959
|
` : `\u2502 \u2716 Verification failed (${errMsg}). Please retry.
|
|
16952
16960
|
`);
|
|
16961
|
+
}
|
|
16953
16962
|
}
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
stdout.write(`\u2502
|
|
16963
|
+
api2 = new TelegramBotApi({ token: botToken, fetch: fetchImpl });
|
|
16964
|
+
const nonce = createPairingNonce();
|
|
16965
|
+
const botName = botInfo.username ? `@${botInfo.username}` : `Bot (ID: ${botInfo.id})`;
|
|
16966
|
+
stdout.write(`\u2502
|
|
16959
16967
|
`);
|
|
16960
|
-
|
|
16961
|
-
|
|
16968
|
+
if (isZh) {
|
|
16969
|
+
stdout.write(`\u25C7 [\u8EAB\u5206\u9A57\u8B49\u914D\u5C0D]
|
|
16962
16970
|
`);
|
|
16963
|
-
|
|
16971
|
+
stdout.write(`\u2502 \u8ACB\u5728 Telegram \u6253\u958B\u8207 ${botName} \u7684\u79C1\u804A\u8996\u7A97\uFF0C\u4E26\u767C\u9001\u6B64\u9A57\u8B49\u78BC\uFF1A
|
|
16964
16972
|
`);
|
|
16965
|
-
|
|
16973
|
+
stdout.write(`\u2502
|
|
16966
16974
|
\u2502 \uD83D\uDC49 ${nonce}
|
|
16967
16975
|
\u2502
|
|
16968
16976
|
`);
|
|
16969
|
-
|
|
16977
|
+
stdout.write(`\u2502 \u280B \u7B49\u5F85 Telegram \u79C1\u8A0A\u4E2D...
|
|
16970
16978
|
`);
|
|
16971
|
-
|
|
16972
|
-
|
|
16979
|
+
} else {
|
|
16980
|
+
stdout.write(`\u25C7 [Identity Pairing]
|
|
16973
16981
|
`);
|
|
16974
|
-
|
|
16982
|
+
stdout.write(`\u2502 Open a private chat with ${botName} on Telegram and send this code:
|
|
16975
16983
|
`);
|
|
16976
|
-
|
|
16984
|
+
stdout.write(`\u2502
|
|
16977
16985
|
\u2502 \uD83D\uDC49 ${nonce}
|
|
16978
16986
|
\u2502
|
|
16979
16987
|
`);
|
|
16980
|
-
|
|
16988
|
+
stdout.write(`\u2502 \u280B Waiting for Telegram private message...
|
|
16981
16989
|
`);
|
|
16982
|
-
|
|
16983
|
-
|
|
16984
|
-
|
|
16985
|
-
|
|
16986
|
-
|
|
16987
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
|
|
16990
|
+
}
|
|
16991
|
+
const expiresAt = now() + 120000;
|
|
16992
|
+
try {
|
|
16993
|
+
pairing = await waitForPairingMessage(api2, {
|
|
16994
|
+
nonce,
|
|
16995
|
+
expiresAt,
|
|
16996
|
+
now,
|
|
16997
|
+
pollTimeoutSeconds: 5
|
|
16998
|
+
});
|
|
16999
|
+
} catch {
|
|
17000
|
+
stdout.write(isZh ? `\u2502 \u2716 \u914D\u5C0D\u8D85\u6642\u6216\u672A\u6536\u5230\u6709\u6548\u8A0A\u606F\uFF0C\u8A2D\u5B9A\u4E2D\u6B62\u3002
|
|
16993
17001
|
` : `\u2502 \u2716 Pairing timed out or no valid message received. Aborted.
|
|
16994
17002
|
`);
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
17003
|
+
return 1;
|
|
17004
|
+
}
|
|
17005
|
+
stdout.write(isZh ? `\u2502 \u2714 \u6536\u5230\u9A57\u8B49\u8A0A\u606F\uFF01\u4F86\u81EA Telegram \u7528\u6236 (ID: ${pairing.userId}, Chat: ${pairing.chatId})
|
|
16998
17006
|
` : `\u2502 \u2714 Received pairing message! Telegram User (ID: ${pairing.userId}, Chat: ${pairing.chatId})
|
|
16999
17007
|
`);
|
|
17000
|
-
|
|
17001
|
-
|
|
17002
|
-
|
|
17008
|
+
const confirmBind = await reader.ask(isZh ? "\u2502 \u662F\u5426\u5C07\u6B64 Telegram \u5E33\u865F\u7D81\u5B9A\u70BA OpenCode \u7BA1\u7406\u54E1\uFF1F [Y/n]: " : "\u2502 Authorize this Telegram user for OpenCode notifications & replies? [Y/n]: ", stdout, "Y");
|
|
17009
|
+
if (confirmBind.toLowerCase() === "n" || confirmBind.toLowerCase() === "no") {
|
|
17010
|
+
stdout.write(isZh ? `\u2502 \u2716 \u5DF2\u53D6\u6D88\u7D81\u5B9A\u3002
|
|
17003
17011
|
` : `\u2502 \u2716 Pairing cancelled.
|
|
17004
17012
|
`);
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17013
|
+
return 1;
|
|
17014
|
+
}
|
|
17015
|
+
const tokenFile = join5(stateDirectory, "telegram-bot-token");
|
|
17016
|
+
await writePrivateTokenFile(stateDirectory, tokenFile, botToken);
|
|
17017
|
+
const identityFile = join5(stateDirectory, "telegram-identity.json");
|
|
17018
|
+
await writeFile3(identityFile, `${JSON.stringify({ userId: pairing.userId, chatId: pairing.chatId, tokenFile, locale }, null, 2)}
|
|
17011
17019
|
`, "utf8");
|
|
17012
|
-
|
|
17020
|
+
stdout.write(isZh ? `\u2502 \u2714 \u5B89\u5168 Token \u6A94\u6848\u5DF2\u5132\u5B58 (${tokenFile})
|
|
17013
17021
|
` : `\u2502 \u2714 Secure token file saved (${tokenFile})
|
|
17014
17022
|
`);
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17023
|
+
configData = {
|
|
17024
|
+
mode: "local",
|
|
17025
|
+
role: "gateway",
|
|
17026
|
+
hostLabel,
|
|
17027
|
+
locale,
|
|
17028
|
+
telegram: {
|
|
17029
|
+
tokenFile,
|
|
17030
|
+
userId: pairing.userId,
|
|
17031
|
+
chatId: pairing.chatId
|
|
17032
|
+
},
|
|
17033
|
+
notifications: {
|
|
17034
|
+
completion: true,
|
|
17035
|
+
error: true,
|
|
17036
|
+
question: true,
|
|
17037
|
+
permission: true,
|
|
17038
|
+
includeChildLifecycle: false,
|
|
17039
|
+
completionDebounceMs: 1500,
|
|
17040
|
+
pluginBufferSize: 100
|
|
17041
|
+
},
|
|
17042
|
+
broker: {
|
|
17043
|
+
host: "127.0.0.1",
|
|
17044
|
+
port: 42617
|
|
17045
|
+
},
|
|
17046
|
+
interaction: {
|
|
17047
|
+
sessionPromptTtlMinutes: 1440,
|
|
17048
|
+
questionTtlMinutes: 30
|
|
17049
|
+
}
|
|
17050
|
+
};
|
|
17051
|
+
}
|
|
17052
|
+
stdout.write(`\u2502
|
|
17045
17053
|
`);
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17054
|
+
const discovered = await discoverOpenCodeConfigFiles(cwd);
|
|
17055
|
+
const existingConfigs = discovered.filter((d) => d.exists);
|
|
17056
|
+
const fallback = discovered.find((d) => !d.isWorkspace) ?? discovered[0];
|
|
17057
|
+
const targets = existingConfigs.length > 0 ? existingConfigs : fallback ? [fallback] : [];
|
|
17058
|
+
if (targets.length > 0) {
|
|
17059
|
+
const descList = targets.map((t) => `${t.path} [${t.exists ? isZh ? "\u5DF2\u5B58\u5728" : "existing" : isZh ? "\u5C07\u81EA\u52D5\u5EFA\u7ACB" : "will create"}]`).join(", ");
|
|
17060
|
+
stdout.write(isZh ? `\u25C7 \u5075\u6E2C\u5230 OpenCode \u8A2D\u5B9A\u6A94 (${descList})
|
|
17053
17061
|
` : `\u25C7 Discovered OpenCode config file(s) (${descList})
|
|
17054
17062
|
`);
|
|
17055
|
-
|
|
17056
|
-
|
|
17057
|
-
|
|
17058
|
-
|
|
17059
|
-
|
|
17060
|
-
|
|
17063
|
+
const autoWrite = await reader.ask(isZh ? "\u2502 \u662F\u5426\u81EA\u52D5\u5BEB\u5165\u5916\u639B\u8A2D\u5B9A\uFF1F [Y/n]: " : "\u2502 Automatically update OpenCode config file(s)? [Y/n]: ", stdout, "Y");
|
|
17064
|
+
if (autoWrite.toLowerCase() !== "n" && autoWrite.toLowerCase() !== "no") {
|
|
17065
|
+
for (const target of targets) {
|
|
17066
|
+
try {
|
|
17067
|
+
const { backupPath } = await injectOpenCodeConfig(target.path, configData);
|
|
17068
|
+
stdout.write(isZh ? `\u2502 \u2714 OpenCode \u8A2D\u5B9A\u6A94\u5DF2\u66F4\u65B0: ${target.path}${backupPath ? ` (\u5099\u4EFD\u65BC ${backupPath})` : ""}
|
|
17061
17069
|
` : `\u2502 \u2714 OpenCode config updated: ${target.path}${backupPath ? ` (backup at ${backupPath})` : ""}
|
|
17062
17070
|
`);
|
|
17063
|
-
|
|
17064
|
-
|
|
17065
|
-
|
|
17071
|
+
} catch (err) {
|
|
17072
|
+
const errMsg = err instanceof Error ? err.message : "failed to write config";
|
|
17073
|
+
stdout.write(isZh ? `\u2502 \u2716 \u8A2D\u5B9A\u6A94\u5BEB\u5165\u5931\u6557 (${target.path}): ${errMsg}
|
|
17066
17074
|
` : `\u2502 \u2716 Failed to write config (${target.path}): ${errMsg}
|
|
17067
17075
|
`);
|
|
17076
|
+
}
|
|
17068
17077
|
}
|
|
17069
|
-
}
|
|
17070
|
-
|
|
17071
|
-
stdout.write(isZh ? `\u2502 \u8ACB\u624B\u52D5\u5C07\u4E0B\u5217\u8A2D\u5B9A\u52A0\u5165\u60A8\u7684 opencode.json:
|
|
17078
|
+
} else {
|
|
17079
|
+
stdout.write(isZh ? `\u2502 \u8ACB\u624B\u52D5\u5C07\u4E0B\u5217\u8A2D\u5B9A\u52A0\u5165\u60A8\u7684 opencode.json:
|
|
17072
17080
|
` : `\u2502 Please add the following configuration to your opencode.json:
|
|
17073
17081
|
`);
|
|
17074
|
-
|
|
17082
|
+
stdout.write(`\u2502
|
|
17075
17083
|
${generatePluginConfigSnippet(configData)}
|
|
17076
17084
|
\u2502
|
|
17077
17085
|
`);
|
|
17086
|
+
}
|
|
17078
17087
|
}
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
stdout.write(`\u2502
|
|
17088
|
+
let dockerFailed = false;
|
|
17089
|
+
if (isDocker) {
|
|
17090
|
+
stdout.write(`\u2502
|
|
17083
17091
|
`);
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17092
|
+
const autoStartDocker = await reader.ask(isZh ? "\u25C7 \u662F\u5426\u7ACB\u5373\u5728\u80CC\u666F\u81EA\u52D5\u5EFA\u7F6E\u4E26\u555F\u52D5 Docker Broker \u5BB9\u5668\uFF1F [Y/n]: " : "\u25C7 Build and start Docker Broker container in background now? [Y/n]: ", stdout, "Y");
|
|
17093
|
+
if (autoStartDocker.toLowerCase() !== "n" && autoStartDocker.toLowerCase() !== "no") {
|
|
17094
|
+
stdout.write(isZh ? `\u2502 \u280B \u6B63\u5728\u5EFA\u7F6E\u4E26\u555F\u52D5 Docker \u5BB9\u5668 (docker compose up -d --build)...
|
|
17087
17095
|
` : `\u2502 \u280B Building and starting Docker container (docker compose up -d --build)...
|
|
17088
17096
|
`);
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
17094
|
-
}
|
|
17095
|
-
const result = Bun.spawnSync([
|
|
17096
|
-
dockerCmd,
|
|
17097
|
-
"compose",
|
|
17098
|
-
"-f",
|
|
17099
|
-
composeCtx.composeFile,
|
|
17100
|
-
"--project-directory",
|
|
17101
|
-
composeCtx.projectDir,
|
|
17102
|
-
"up",
|
|
17103
|
-
"-d",
|
|
17104
|
-
"--build"
|
|
17105
|
-
], {
|
|
17106
|
-
cwd: composeCtx.projectDir,
|
|
17107
|
-
env: {
|
|
17108
|
-
...process.env,
|
|
17109
|
-
HOME: process.env.HOME || process.env.USERPROFILE || ""
|
|
17097
|
+
try {
|
|
17098
|
+
const dockerCmd = process.platform === "win32" ? "docker.exe" : "docker";
|
|
17099
|
+
const composeCtx = resolveDockerComposeContext(cwd);
|
|
17100
|
+
if (!composeCtx) {
|
|
17101
|
+
throw new Error("Could not find docker-compose.yml in project or package directory");
|
|
17110
17102
|
}
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17103
|
+
const result = Bun.spawnSync([
|
|
17104
|
+
dockerCmd,
|
|
17105
|
+
"compose",
|
|
17106
|
+
"-f",
|
|
17107
|
+
composeCtx.composeFile,
|
|
17108
|
+
"--project-directory",
|
|
17109
|
+
composeCtx.projectDir,
|
|
17110
|
+
"up",
|
|
17111
|
+
"-d",
|
|
17112
|
+
"--build"
|
|
17113
|
+
], {
|
|
17114
|
+
cwd: composeCtx.projectDir,
|
|
17115
|
+
env: {
|
|
17116
|
+
...process.env,
|
|
17117
|
+
HOME: process.env.HOME || process.env.USERPROFILE || ""
|
|
17118
|
+
}
|
|
17119
|
+
});
|
|
17120
|
+
if (result.exitCode === 0) {
|
|
17121
|
+
stdout.write(isZh ? `\u2502 \u2714 Docker Broker \u5BB9\u5668\u5DF2\u6210\u529F\u5728\u80CC\u666F\u555F\u52D5\uFF01
|
|
17114
17122
|
` : `\u2502 \u2714 Docker Broker container started in background!
|
|
17115
17123
|
`);
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17124
|
+
} else {
|
|
17125
|
+
dockerFailed = true;
|
|
17126
|
+
const stderr2 = result.stderr ? new TextDecoder().decode(result.stderr).trim() : "";
|
|
17127
|
+
stdout.write(isZh ? `\u2502 \u2716 Docker \u81EA\u52D5\u555F\u52D5\u672A\u6210\u529F${stderr2 ? ` (${stderr2})` : ""}\uFF08\u8ACB\u78BA\u8A8D Docker Desktop \u662F\u5426\u904B\u884C\u4E2D\uFF09\u3002
|
|
17120
17128
|
` : `\u2502 \u2716 Docker start failed${stderr2 ? ` (${stderr2})` : ""} (please check if Docker is running).
|
|
17121
17129
|
`);
|
|
17122
|
-
|
|
17130
|
+
stdout.write(isZh ? `\u2502 \u60A8\u53EF\u65BC\u7A0D\u5F8C\u624B\u52D5\u57F7\u884C: docker compose -f "${composeCtx.composeFile}" up -d
|
|
17123
17131
|
` : `\u2502 You can manually run later: docker compose -f "${composeCtx.composeFile}" up -d
|
|
17124
17132
|
`);
|
|
17125
|
-
|
|
17126
|
-
|
|
17127
|
-
|
|
17128
|
-
|
|
17129
|
-
|
|
17133
|
+
}
|
|
17134
|
+
} catch (err) {
|
|
17135
|
+
dockerFailed = true;
|
|
17136
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
17137
|
+
stdout.write(isZh ? `\u2502 \u2716 Docker \u555F\u52D5\u5931\u6557: ${msg}\uFF0C\u60A8\u53EF\u65BC\u5B89\u88DD/\u555F\u52D5 Docker \u5F8C\u624B\u52D5\u57F7\u884C docker compose up -d
|
|
17130
17138
|
` : `\u2502 \u2716 Docker startup failed: ${msg}. You can run 'docker compose up -d' after installing/starting Docker.
|
|
17131
17139
|
`);
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17140
|
+
}
|
|
17141
|
+
} else {
|
|
17142
|
+
stdout.write(isZh ? `\u2502 \u60A8\u53EF\u65BC\u7A0D\u5F8C\u624B\u52D5\u555F\u52D5\u5BB9\u5668: docker compose up -d
|
|
17135
17143
|
` : `\u2502 You can manually start the container later: docker compose up -d
|
|
17136
17144
|
`);
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17145
|
+
}
|
|
17146
|
+
} else {
|
|
17147
|
+
stdout.write(`\u2502
|
|
17140
17148
|
`);
|
|
17141
|
-
|
|
17149
|
+
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
|
|
17142
17150
|
` : `\u2502 \u2714 Native mode configured! OpenCode will automatically manage Broker in background.
|
|
17143
17151
|
`);
|
|
17144
|
-
|
|
17145
|
-
|
|
17146
|
-
|
|
17152
|
+
}
|
|
17153
|
+
if (!isNode && pairing && api2) {
|
|
17154
|
+
stdout.write(`\u2502
|
|
17147
17155
|
`);
|
|
17148
|
-
|
|
17149
|
-
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17156
|
+
const sendTest = await reader.ask(isZh ? "\u25C7 \u662F\u5426\u767C\u9001\u6E2C\u8A66\u901A\u77E5\u5230\u60A8\u7684 Telegram\uFF1F [Y/n]: " : "\u25C7 Send a welcome test notification to your Telegram now? [Y/n]: ", stdout, "Y");
|
|
17157
|
+
if (sendTest.toLowerCase() !== "n" && sendTest.toLowerCase() !== "no") {
|
|
17158
|
+
try {
|
|
17159
|
+
const botDisplayName = botInfo?.username ? `@${botInfo.username}` : `Bot (ID: ${botInfo?.id})`;
|
|
17160
|
+
const welcomeText = isZh ? `\uD83C\uDF89 <b>OpenCode Telegram Notifier \u8A2D\u5B9A\u6210\u529F\uFF01</b>
|
|
17153
17161
|
|
|
17154
17162
|
\u5DF2\u6210\u529F\u7D81\u5B9A\u4E3B\u6A5F [${hostLabel}] \u8207 Telegram\u3002
|
|
17155
17163
|
\u7576 OpenCode \u4EFB\u52D9\u5B8C\u6210\u3001\u767C\u751F\u7570\u5E38\u6216\u9700\u8981\u56DE\u8986\u6642\uFF0C\u60A8\u5C07\u5728\u6B64\u6536\u5230\u5373\u6642\u901A\u77E5\u3002
|
|
@@ -17162,38 +17170,41 @@ You will receive notifications here when sessions finish or require input.
|
|
|
17162
17170
|
|
|
17163
17171
|
\u2022 Bot: ${botDisplayName}
|
|
17164
17172
|
\u2022 Authorized User ID: <code>${pairing.userId}</code>`;
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17173
|
+
await api2.sendMessage({
|
|
17174
|
+
chatId: pairing.chatId,
|
|
17175
|
+
text: welcomeText,
|
|
17176
|
+
parseMode: "HTML"
|
|
17177
|
+
});
|
|
17178
|
+
stdout.write(isZh ? `\u2502 \u2714 \u5DF2\u6210\u529F\u767C\u9001\u6E2C\u8A66\u901A\u77E5\u5230\u60A8\u7684 Telegram\uFF01\u8ACB\u6AA2\u67E5\u624B\u6A5F\u8A0A\u606F\u3002
|
|
17171
17179
|
` : `\u2502 \u2714 Test notification sent to your Telegram! Please check your messages.
|
|
17172
17180
|
`);
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17181
|
+
} catch (err) {
|
|
17182
|
+
const errMsg = err instanceof Error ? err.message : "send failed";
|
|
17183
|
+
stdout.write(isZh ? `\u2502 \u2716 \u6E2C\u8A66\u901A\u77E5\u767C\u9001\u5931\u6557: ${errMsg}
|
|
17176
17184
|
` : `\u2502 \u2716 Failed to send test notification: ${errMsg}
|
|
17177
17185
|
`);
|
|
17186
|
+
}
|
|
17178
17187
|
}
|
|
17179
17188
|
}
|
|
17180
|
-
|
|
17181
|
-
stdout.write(`\u2502
|
|
17189
|
+
stdout.write(`\u2502
|
|
17182
17190
|
`);
|
|
17183
|
-
|
|
17184
|
-
|
|
17191
|
+
if (dockerFailed) {
|
|
17192
|
+
stdout.write(isZh ? `\u2514 \u26A0 \u8A2D\u5B9A\u6A94\u5DF2\u5BEB\u5165\uFF0C\u4F46 Docker \u5BB9\u5668\u555F\u52D5\u5931\u6557\u3002\u8ACB\u78BA\u8A8D Docker \u670D\u52D9\u904B\u884C\u5F8C\u624B\u52D5\u555F\u52D5\u5BB9\u5668\u3002
|
|
17185
17193
|
|
|
17186
17194
|
` : `\u2514 \u26A0 Configuration written, but Docker container failed to start. Please ensure Docker is running and start the container manually.
|
|
17187
17195
|
|
|
17188
17196
|
`);
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17197
|
+
return 1;
|
|
17198
|
+
}
|
|
17199
|
+
stdout.write(isZh ? `\u2514 \uD83C\uDF89 \u5B89\u88DD\u8A2D\u5B9A\u5B8C\u6210\uFF01\u60A8\u73FE\u5728\u53EF\u4EE5\u56DE\u5230 OpenCode \u958B\u59CB\u5DE5\u4F5C\u3002
|
|
17192
17200
|
|
|
17193
17201
|
` : `\u2514 \uD83C\uDF89 Setup completed! You can now return to OpenCode and start working.
|
|
17194
17202
|
|
|
17195
17203
|
`);
|
|
17196
|
-
|
|
17204
|
+
return 0;
|
|
17205
|
+
} finally {
|
|
17206
|
+
reader.close();
|
|
17207
|
+
}
|
|
17197
17208
|
}
|
|
17198
17209
|
async function runSetupCli(options = {}) {
|
|
17199
17210
|
const argv = options.argv ?? process.argv.slice(2);
|
|
@@ -17975,7 +17986,7 @@ function rejectionHash(updateId, reason) {
|
|
|
17975
17986
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17976
17987
|
|
|
17977
17988
|
// src/version.ts
|
|
17978
|
-
var PACKAGE_VERSION = "1.0.0-rc.
|
|
17989
|
+
var PACKAGE_VERSION = "1.0.0-rc.3";
|
|
17979
17990
|
|
|
17980
17991
|
// src/telegram/commands.ts
|
|
17981
17992
|
function isSlashCommand(text) {
|
|
@@ -21694,161 +21705,165 @@ async function runInteractiveUninstall(options = {}) {
|
|
|
21694
21705
|
const stdout = options.stdout ?? process.stdout;
|
|
21695
21706
|
const stderr = options.stderr ?? process.stderr;
|
|
21696
21707
|
const reader = new AsyncPromptReader(options.stdin ?? process.stdin);
|
|
21697
|
-
|
|
21698
|
-
|
|
21699
|
-
|
|
21700
|
-
|
|
21708
|
+
try {
|
|
21709
|
+
const stateDirectory = options.stateDirectory ?? defaultStateDirectory();
|
|
21710
|
+
const cwd = options.cwd ?? process.cwd();
|
|
21711
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
21712
|
+
stdout.write(`
|
|
21701
21713
|
\u250C OpenCode Telegram Notifier \u2014 Uninstaller / \u79FB\u9664\u7CBE\u9748
|
|
21702
21714
|
\u2502
|
|
21703
21715
|
`);
|
|
21704
|
-
|
|
21716
|
+
stdout.write(`\u25C7 Language / \u8A9E\u8A00:
|
|
21705
21717
|
`);
|
|
21706
|
-
|
|
21718
|
+
stdout.write(`\u2502 1) \u7E41\u9AD4\u4E2D\u6587 (zh-TW) [\u9810\u8A2D/Default]
|
|
21707
21719
|
`);
|
|
21708
|
-
|
|
21720
|
+
stdout.write(`\u2502 2) English (en)
|
|
21709
21721
|
`);
|
|
21710
|
-
|
|
21711
|
-
|
|
21712
|
-
|
|
21713
|
-
|
|
21722
|
+
const langChoice = await reader.ask("\u2502 \u8ACB\u9078\u64C7 / Select [1]: ", stdout, "1");
|
|
21723
|
+
const locale = langChoice === "2" || langChoice.toLowerCase() === "en" ? "en" : "zh-TW";
|
|
21724
|
+
const isZh = locale === "zh-TW";
|
|
21725
|
+
stdout.write(`\u2502
|
|
21714
21726
|
`);
|
|
21715
|
-
|
|
21716
|
-
|
|
21717
|
-
|
|
21727
|
+
const confirm = await reader.ask(isZh ? "\u25C7 \u662F\u5426\u78BA\u8A8D\u8981\u89E3\u9664\u5B89\u88DD OpenCode Telegram Notifier\uFF1F [y/N]: " : "\u25C7 Are you sure you want to uninstall OpenCode Telegram Notifier? [y/N]: ", stdout, "N");
|
|
21728
|
+
if (confirm.toLowerCase() !== "y" && confirm.toLowerCase() !== "yes") {
|
|
21729
|
+
stdout.write(isZh ? `\u2502 \u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002
|
|
21718
21730
|
\u2514 \uD83D\uDC4B \u7D50\u675F\u3002
|
|
21719
21731
|
|
|
21720
21732
|
` : `\u2502 Aborted.
|
|
21721
21733
|
\u2514 \uD83D\uDC4B Done.
|
|
21722
21734
|
|
|
21723
21735
|
`);
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21736
|
+
return 0;
|
|
21737
|
+
}
|
|
21738
|
+
stdout.write(`\u2502
|
|
21727
21739
|
`);
|
|
21728
|
-
|
|
21740
|
+
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)...
|
|
21729
21741
|
` : `\u25C7 [1/4] Checking and stopping running Broker (native process or Docker container)...
|
|
21730
21742
|
`);
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
|
|
21743
|
+
try {
|
|
21744
|
+
const dockerCmd = process.platform === "win32" ? "docker.exe" : "docker";
|
|
21745
|
+
const dockerDown = Bun.spawnSync([dockerCmd, "compose", "down"], { cwd });
|
|
21746
|
+
if (dockerDown.exitCode === 0) {
|
|
21747
|
+
stdout.write(isZh ? `\u2502 \u2714 Docker Broker \u5BB9\u5668\u5DF2\u505C\u6B62\u4E26\u6E05\u7406\u3002
|
|
21736
21748
|
` : `\u2502 \u2714 Docker Broker container stopped and cleaned up.
|
|
21737
21749
|
`);
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
21750
|
+
}
|
|
21751
|
+
} catch {}
|
|
21752
|
+
try {
|
|
21753
|
+
const identity = await loadOrCreateStateIdentity(stateDirectory);
|
|
21754
|
+
const isRunning = await probeBroker(42617, identity.brokerSecret);
|
|
21755
|
+
if (isRunning) {
|
|
21756
|
+
await runStopCommand({ stateDirectory, port: 42617 }, { stdout, stderr }, fetchImpl);
|
|
21757
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672C\u6A5F Broker \u5DF2\u6210\u529F\u505C\u6B62\u3002
|
|
21746
21758
|
` : `\u2502 \u2714 Local broker stopped.
|
|
21747
21759
|
`);
|
|
21748
|
-
|
|
21749
|
-
|
|
21760
|
+
} else {
|
|
21761
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672C\u6A5F Broker \u672A\u5728\u57F7\u884C\u4E2D\u3002
|
|
21750
21762
|
` : `\u2502 \u2714 Local broker is not running.
|
|
21751
21763
|
`);
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21764
|
+
}
|
|
21765
|
+
} catch {
|
|
21766
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672A\u627E\u5230\u57F7\u884C\u4E2D\u7684\u672C\u6A5F Broker \u6216\u5DF2\u505C\u6B62\u3002
|
|
21755
21767
|
` : `\u2502 \u2714 No active local broker found or already stopped.
|
|
21756
21768
|
`);
|
|
21757
|
-
|
|
21758
|
-
|
|
21769
|
+
}
|
|
21770
|
+
stdout.write(`\u2502
|
|
21759
21771
|
`);
|
|
21760
|
-
|
|
21772
|
+
stdout.write(isZh ? `\u25C7 [2/4] \u6B63\u5728\u641C\u5C0B OpenCode \u8A2D\u5B9A\u6A94...
|
|
21761
21773
|
` : `\u25C7 [2/4] Searching for OpenCode configuration files...
|
|
21762
21774
|
`);
|
|
21763
|
-
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21775
|
+
const discoveredConfigs = await discoverOpenCodeConfigFiles(cwd);
|
|
21776
|
+
const existingConfigs = discoveredConfigs.filter((c) => c.exists);
|
|
21777
|
+
if (existingConfigs.length > 0) {
|
|
21778
|
+
const cleanConfig = await reader.ask(isZh ? `\u2502 \u627E\u5230 ${existingConfigs.length} \u500B\u8A2D\u5B9A\u6A94\uFF0C\u662F\u5426\u5F9E\u4E2D\u79FB\u9664\u5916\u639B\u8A2D\u5B9A\uFF1F [Y/n]: ` : `\u2502 Found ${existingConfigs.length} config file(s). Remove plugin configuration? [Y/n]: `, stdout, "Y");
|
|
21779
|
+
if (cleanConfig.toLowerCase() !== "n" && cleanConfig.toLowerCase() !== "no") {
|
|
21780
|
+
for (const config2 of existingConfigs) {
|
|
21781
|
+
const { modified, backupPath } = await removeOpenCodeConfig(config2.path);
|
|
21782
|
+
if (modified) {
|
|
21783
|
+
stdout.write(isZh ? `\u2502 \u2714 \u5DF2\u5F9E ${config2.path} \u79FB\u9664\u5916\u639B\u8A2D\u5B9A${backupPath ? ` (\u5099\u4EFD\u65BC ${backupPath})` : ""}
|
|
21772
21784
|
` : `\u2502 \u2714 Removed plugin config from ${config2.path}${backupPath ? ` (backup at ${backupPath})` : ""}
|
|
21773
21785
|
`);
|
|
21774
|
-
|
|
21775
|
-
|
|
21786
|
+
} else {
|
|
21787
|
+
stdout.write(isZh ? `\u2502 - ${config2.path} \u672A\u5305\u542B\u672C\u5916\u639B\u8A2D\u5B9A\u3002
|
|
21776
21788
|
` : `\u2502 - No plugin config in ${config2.path}.
|
|
21777
21789
|
`);
|
|
21790
|
+
}
|
|
21778
21791
|
}
|
|
21779
21792
|
}
|
|
21780
|
-
|
|
21781
|
-
|
|
21782
|
-
|
|
21783
|
-
|
|
21784
|
-
|
|
21785
|
-
|
|
21786
|
-
|
|
21787
|
-
|
|
21788
|
-
|
|
21789
|
-
}
|
|
21790
|
-
}
|
|
21791
|
-
|
|
21792
|
-
stdout.write(isZh ? `\u2502 \u2714 \u672A\u627E\u5230\u4EFB\u4F55 opencode.json \u8A2D\u5B9A\u6A94\u3002
|
|
21793
|
+
const symlinkLocations = [
|
|
21794
|
+
join8(cwd, "node_modules", "opencode-telegram-link"),
|
|
21795
|
+
join8(homedir3(), ".config", "opencode", "node_modules", "opencode-telegram-link"),
|
|
21796
|
+
join8(homedir3(), ".opencode", "node_modules", "opencode-telegram-link")
|
|
21797
|
+
];
|
|
21798
|
+
for (const symlink of symlinkLocations) {
|
|
21799
|
+
try {
|
|
21800
|
+
await rm4(symlink, { recursive: true, force: true });
|
|
21801
|
+
} catch {}
|
|
21802
|
+
}
|
|
21803
|
+
} else {
|
|
21804
|
+
stdout.write(isZh ? `\u2502 \u2714 \u672A\u627E\u5230\u4EFB\u4F55 opencode.json \u8A2D\u5B9A\u6A94\u3002
|
|
21793
21805
|
` : `\u2502 \u2714 No opencode.json configuration files found.
|
|
21794
21806
|
`);
|
|
21795
|
-
|
|
21796
|
-
|
|
21807
|
+
}
|
|
21808
|
+
stdout.write(`\u2502
|
|
21797
21809
|
`);
|
|
21798
|
-
|
|
21799
|
-
|
|
21800
|
-
try {
|
|
21801
|
-
const dbPath = join8(stateDirectory, "state.sqlite");
|
|
21802
|
-
await rm4(dbPath, { force: true });
|
|
21803
|
-
await rm4(`${dbPath}-wal`, { force: true });
|
|
21804
|
-
await rm4(`${dbPath}-shm`, { force: true });
|
|
21805
|
-
await rm4(discoveryRecordPath(stateDirectory), { force: true });
|
|
21806
|
-
await rm4(join8(stateDirectory, "dashboard-settings.json"), { force: true });
|
|
21810
|
+
const cleanState = await reader.ask(isZh ? "\u25C7 [3/4] \u662F\u5426\u6E05\u9664\u904B\u4F5C\u66AB\u5B58\u8CC7\u6599\u5EAB\u8207\u8A0A\u606F\u8DEF\u7531\u72C0\u614B (SQLite)\uFF1F [Y/n]: " : "\u25C7 [3/4] Remove operational database & message routing state (SQLite)? [Y/n]: ", stdout, "Y");
|
|
21811
|
+
if (cleanState.toLowerCase() !== "n" && cleanState.toLowerCase() !== "no") {
|
|
21807
21812
|
try {
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21813
|
+
const dbPath = join8(stateDirectory, "state.sqlite");
|
|
21814
|
+
await rm4(dbPath, { force: true });
|
|
21815
|
+
await rm4(`${dbPath}-wal`, { force: true });
|
|
21816
|
+
await rm4(`${dbPath}-shm`, { force: true });
|
|
21817
|
+
await rm4(discoveryRecordPath(stateDirectory), { force: true });
|
|
21818
|
+
await rm4(join8(stateDirectory, "dashboard-settings.json"), { force: true });
|
|
21819
|
+
try {
|
|
21820
|
+
await rm4(join8(tmpdir(), "opencode_telegram_plugin.log"), { force: true });
|
|
21821
|
+
} catch {}
|
|
21822
|
+
stdout.write(isZh ? `\u2502 \u2714 \u904B\u4F5C\u66AB\u5B58\u8CC7\u6599\u5EAB\u8207\u63A7\u5236\u53F0\u8A2D\u5B9A\u6A94 (dashboard-settings.json) \u5DF2\u6E05\u9664\u3002
|
|
21811
21823
|
` : `\u2502 \u2714 Operational state database & dashboard settings cleared.
|
|
21812
21824
|
`);
|
|
21813
|
-
|
|
21814
|
-
|
|
21825
|
+
} catch {
|
|
21826
|
+
stdout.write(isZh ? `\u2502 - \u66AB\u5B58\u8CC7\u6599\u5EAB\u4E0D\u5B58\u5728\u6216\u5DF2\u6E05\u7406\u3002
|
|
21815
21827
|
` : `\u2502 - State database not found or already clean.
|
|
21816
21828
|
`);
|
|
21829
|
+
}
|
|
21817
21830
|
}
|
|
21818
|
-
|
|
21819
|
-
stdout.write(`\u2502
|
|
21831
|
+
stdout.write(`\u2502
|
|
21820
21832
|
`);
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21833
|
+
const cleanToken = await reader.ask(isZh ? "\u25C7 [4/4] \u662F\u5426\u522A\u9664\u5132\u5B58\u7684 Telegram Bot Token \u6A94\u6848\uFF1F [y/N]: " : "\u25C7 [4/4] Delete saved Telegram Bot Token file? [y/N]: ", stdout, "N");
|
|
21834
|
+
if (cleanToken.toLowerCase() === "y" || cleanToken.toLowerCase() === "yes") {
|
|
21835
|
+
try {
|
|
21836
|
+
const tokenPath = join8(stateDirectory, "telegram-bot-token");
|
|
21837
|
+
await rm4(tokenPath, { force: true });
|
|
21838
|
+
stdout.write(isZh ? `\u2502 \u2714 Token \u6A94\u6848\u5DF2\u5B89\u5168\u522A\u9664\u3002
|
|
21827
21839
|
` : `\u2502 \u2714 Token file securely removed.
|
|
21828
21840
|
`);
|
|
21829
|
-
|
|
21830
|
-
|
|
21841
|
+
} catch {
|
|
21842
|
+
stdout.write(isZh ? `\u2502 - Token \u6A94\u6848\u4E0D\u5B58\u5728\u3002
|
|
21831
21843
|
` : `\u2502 - Token file does not exist.
|
|
21832
21844
|
`);
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
|
|
21845
|
+
}
|
|
21846
|
+
const cleanAll = await reader.ask(isZh ? `\u2502 \u662F\u5426\u9023\u540C\u91D1\u9470\u76EE\u9304 ${stateDirectory} \u4E00\u4F75\u5B8C\u5168\u522A\u9664\uFF1F [y/N]: ` : `\u2502 Delete entire state directory (${stateDirectory})? [y/N]: `, stdout, "N");
|
|
21847
|
+
if (cleanAll.toLowerCase() === "y" || cleanAll.toLowerCase() === "yes") {
|
|
21848
|
+
try {
|
|
21849
|
+
await rm4(stateDirectory, { recursive: true, force: true });
|
|
21850
|
+
stdout.write(isZh ? `\u2502 \u2714 \u91D1\u9470\u8207\u72C0\u614B\u76EE\u9304\u5DF2\u5B8C\u5168\u79FB\u9664\u3002
|
|
21839
21851
|
` : `\u2502 \u2714 State directory completely removed.
|
|
21840
21852
|
`);
|
|
21841
|
-
|
|
21853
|
+
} catch {}
|
|
21854
|
+
}
|
|
21842
21855
|
}
|
|
21843
|
-
|
|
21844
|
-
stdout.write(`\u2502
|
|
21856
|
+
stdout.write(`\u2502
|
|
21845
21857
|
`);
|
|
21846
|
-
|
|
21858
|
+
stdout.write(isZh ? `\u2514 \uD83C\uDF89 OpenCode Telegram Notifier \u5DF2\u6210\u529F\u79FB\u9664\uFF01
|
|
21847
21859
|
|
|
21848
21860
|
` : `\u2514 \uD83C\uDF89 OpenCode Telegram Notifier successfully uninstalled!
|
|
21849
21861
|
|
|
21850
21862
|
`);
|
|
21851
|
-
|
|
21863
|
+
return 0;
|
|
21864
|
+
} finally {
|
|
21865
|
+
reader.close();
|
|
21866
|
+
}
|
|
21852
21867
|
}
|
|
21853
21868
|
async function runUninstallCli(options = {}) {
|
|
21854
21869
|
const argv = options.argv ?? process.argv.slice(2);
|
|
@@ -21892,9 +21907,10 @@ async function runBroker() {
|
|
|
21892
21907
|
}
|
|
21893
21908
|
if (import.meta.main) {
|
|
21894
21909
|
await runBroker();
|
|
21910
|
+
process.exit(process.exitCode ?? 0);
|
|
21895
21911
|
}
|
|
21896
21912
|
export {
|
|
21897
21913
|
runBroker
|
|
21898
21914
|
};
|
|
21899
21915
|
|
|
21900
|
-
//# debugId=
|
|
21916
|
+
//# debugId=4DA37A84D8B98D2764756E2164756E21
|