sync-omo-config 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +99 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,9 +4,61 @@ import { homedir } from "os";
|
|
|
4
4
|
import { existsSync } from "fs";
|
|
5
5
|
import { mkdir } from "fs/promises";
|
|
6
6
|
import path from "path";
|
|
7
|
+
function notifyDesktop(title, message) {
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
const esc = (value) => value.replaceAll(`
|
|
10
|
+
`, " ").replaceAll('"', "\\\"");
|
|
11
|
+
const escps = (value) => value.replaceAll(`
|
|
12
|
+
`, " ").replaceAll("'", "''");
|
|
13
|
+
if (platform === "darwin") {
|
|
14
|
+
const script = [
|
|
15
|
+
`display notification "${esc(message)}" with title "${esc(title)}"`,
|
|
16
|
+
`display alert "${esc(title)}" message "${esc(message)}" giving up after 10`
|
|
17
|
+
].join(`
|
|
18
|
+
`);
|
|
19
|
+
const proc = Bun.spawn(["/usr/bin/osascript", "-e", script], { stdout: "ignore", stderr: "ignore" });
|
|
20
|
+
proc.exited.catch(() => {
|
|
21
|
+
return;
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (platform === "linux") {
|
|
26
|
+
const proc = Bun.spawn(["/usr/bin/env", "notify-send", "--urgency=critical", title, message], { stdout: "ignore", stderr: "ignore" });
|
|
27
|
+
proc.exited.catch(() => {
|
|
28
|
+
return;
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (platform === "win32") {
|
|
33
|
+
const script = [
|
|
34
|
+
"Add-Type -AssemblyName System.Windows.Forms",
|
|
35
|
+
"$n = New-Object System.Windows.Forms.NotifyIcon",
|
|
36
|
+
"$n.Icon = [System.Drawing.SystemIcons]::Warning",
|
|
37
|
+
`$n.BalloonTipTitle = '${escps(title)}'`,
|
|
38
|
+
`$n.BalloonTipText = '${escps(message)}'`,
|
|
39
|
+
"$n.BalloonTipIcon = 'Error'",
|
|
40
|
+
"$n.Visible = $true",
|
|
41
|
+
"$n.ShowBalloonTip(15000)",
|
|
42
|
+
"Start-Sleep -Seconds 16",
|
|
43
|
+
"$n.Dispose()"
|
|
44
|
+
].join("; ");
|
|
45
|
+
const proc = Bun.spawn(["powershell", "-NoProfile", "-Command", script], {
|
|
46
|
+
stdout: "ignore",
|
|
47
|
+
stderr: "ignore"
|
|
48
|
+
});
|
|
49
|
+
proc.exited.catch(() => {
|
|
50
|
+
return;
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
console.warn(`[sync-omo-config] Desktop notify not supported on ${platform}`);
|
|
55
|
+
}
|
|
7
56
|
function getDataDir() {
|
|
8
57
|
const home = homedir();
|
|
9
|
-
const xdgData = process.env.XDG_DATA_HOME || path.join(home, ".local", "share");
|
|
58
|
+
const xdgData = process.env.XDG_DATA_HOME || (home ? path.join(home, ".local", "share") : undefined);
|
|
59
|
+
if (!xdgData) {
|
|
60
|
+
throw new Error("[sync-omo-config] Cannot determine data directory: HOME is not set");
|
|
61
|
+
}
|
|
10
62
|
return path.join(xdgData, "opencode");
|
|
11
63
|
}
|
|
12
64
|
function getConfigDir() {
|
|
@@ -58,23 +110,24 @@ async function syncOmoConfig() {
|
|
|
58
110
|
const authFile = Bun.file(authPath);
|
|
59
111
|
if (!await authFile.exists()) {
|
|
60
112
|
console.log(`${LOG_PREFIX} auth.json not found at ${authPath}, skipping sync`);
|
|
61
|
-
return;
|
|
113
|
+
return [];
|
|
62
114
|
}
|
|
63
115
|
let auth;
|
|
64
116
|
try {
|
|
65
117
|
auth = await authFile.json();
|
|
66
118
|
} catch (e) {
|
|
67
119
|
console.error(`${LOG_PREFIX} Failed to parse auth.json:`, e);
|
|
68
|
-
return;
|
|
120
|
+
return [];
|
|
69
121
|
}
|
|
70
122
|
const omoConfigs = [];
|
|
123
|
+
const expiredServers = [];
|
|
71
124
|
for (const [serverUrl, authInfo] of Object.entries(auth)) {
|
|
72
125
|
if (!isWellKnownAuth(authInfo)) {
|
|
73
126
|
continue;
|
|
74
127
|
}
|
|
75
128
|
console.log(`${LOG_PREFIX} Fetching config from ${serverUrl}`);
|
|
76
129
|
try {
|
|
77
|
-
const wellKnownUrl = `${serverUrl}/.well-known/opencode`;
|
|
130
|
+
const wellKnownUrl = serverUrl.includes("/.well-known/opencode") ? serverUrl : `${serverUrl}/.well-known/opencode`;
|
|
78
131
|
const response = await fetch(wellKnownUrl, {
|
|
79
132
|
headers: {
|
|
80
133
|
Accept: "application/json"
|
|
@@ -85,6 +138,15 @@ async function syncOmoConfig() {
|
|
|
85
138
|
continue;
|
|
86
139
|
}
|
|
87
140
|
const data = await response.json();
|
|
141
|
+
if (data.auth_status === "invalid" || data.auth_status === "reauth_required") {
|
|
142
|
+
console.warn(`${LOG_PREFIX} Auth expired for ${serverUrl}, will notify via TUI toast`);
|
|
143
|
+
notifyDesktop("OpenCode: \u6388\u6743\u5DF2\u5931\u6548", `\u670D\u52A1\u5668 ${serverUrl} \u7684\u6388\u6743\u5DF2\u8FC7\u671F\uFF0C\u5DF2\u81EA\u52A8\u6E05\u9664\u51ED\u8BC1\u3002\u8BF7\u91CD\u65B0\u767B\u5F55\u8BA4\u8BC1\u3002`);
|
|
144
|
+
expiredServers.push(serverUrl);
|
|
145
|
+
delete auth[serverUrl];
|
|
146
|
+
await Bun.write(authPath, JSON.stringify(auth, null, 2), { mode: 384 });
|
|
147
|
+
console.log(`${LOG_PREFIX} Removed expired credential for ${serverUrl} from auth.json`);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
88
150
|
if (data.omo && typeof data.omo === "object") {
|
|
89
151
|
console.log(`${LOG_PREFIX} Found omo config from ${serverUrl}`);
|
|
90
152
|
omoConfigs.push(data.omo);
|
|
@@ -96,7 +158,7 @@ async function syncOmoConfig() {
|
|
|
96
158
|
}
|
|
97
159
|
if (omoConfigs.length === 0) {
|
|
98
160
|
console.log(`${LOG_PREFIX} No omo configs found, skipping write`);
|
|
99
|
-
return;
|
|
161
|
+
return expiredServers;
|
|
100
162
|
}
|
|
101
163
|
console.log(`${LOG_PREFIX} Found ${omoConfigs.length} omo config(s)`);
|
|
102
164
|
const configDir = getConfigDir();
|
|
@@ -119,12 +181,42 @@ async function syncOmoConfig() {
|
|
|
119
181
|
}
|
|
120
182
|
await Bun.write(omoPath, JSON.stringify(mergedConfig, null, 2));
|
|
121
183
|
console.log(`${LOG_PREFIX} Successfully wrote oh-my-opencode.json to ${omoPath}`);
|
|
184
|
+
return expiredServers;
|
|
122
185
|
} catch (error) {
|
|
123
186
|
console.error(`${LOG_PREFIX} Unexpected error during sync:`, error);
|
|
187
|
+
return [];
|
|
124
188
|
}
|
|
125
189
|
}
|
|
126
|
-
var SyncOmoConfigPlugin = async function SyncOmoConfigPlugin2() {
|
|
127
|
-
await syncOmoConfig();
|
|
190
|
+
var SyncOmoConfigPlugin = async function SyncOmoConfigPlugin2(input) {
|
|
191
|
+
const expiredServers = await syncOmoConfig();
|
|
192
|
+
if (expiredServers.length === 0)
|
|
193
|
+
return {};
|
|
194
|
+
const pending = new Set(expiredServers);
|
|
195
|
+
const delays = [2000, 4000, 8000, 15000];
|
|
196
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
197
|
+
const notify = async () => {
|
|
198
|
+
for (const delay of delays) {
|
|
199
|
+
if (pending.size === 0)
|
|
200
|
+
return;
|
|
201
|
+
await sleep(delay);
|
|
202
|
+
for (const server of [...pending]) {
|
|
203
|
+
const ok = await input.client.tui.showToast({
|
|
204
|
+
body: {
|
|
205
|
+
title: "\u26A0 \u6388\u6743\u5DF2\u5931\u6548",
|
|
206
|
+
message: `\u670D\u52A1\u5668 ${server} \u7684\u6388\u6743\u5DF2\u8FC7\u671F\uFF0C\u5DF2\u81EA\u52A8\u6E05\u9664\u51ED\u8BC1\u3002\u8BF7\u91CD\u65B0\u767B\u5F55\u8BA4\u8BC1\u3002`,
|
|
207
|
+
variant: "error",
|
|
208
|
+
duration: 30000
|
|
209
|
+
}
|
|
210
|
+
}).then(() => true).catch((e) => {
|
|
211
|
+
console.error("[sync-omo-config] Failed to show toast:", e);
|
|
212
|
+
return false;
|
|
213
|
+
});
|
|
214
|
+
if (ok)
|
|
215
|
+
pending.delete(server);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
notify();
|
|
128
220
|
return {};
|
|
129
221
|
};
|
|
130
222
|
var src_default = SyncOmoConfigPlugin;
|