sync-omo-config 1.0.1 → 1.3.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.
Files changed (2) hide show
  1. package/dist/index.js +91 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,9 +4,53 @@ 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
+ `[System.Windows.Forms.MessageBox]::Show('${escps(message)}','${escps(title)}','OK','Error') | Out-Null`
36
+ ].join("; ");
37
+ const proc = Bun.spawn(["powershell", "-NoProfile", "-Command", script], {
38
+ stdout: "ignore",
39
+ stderr: "ignore"
40
+ });
41
+ proc.exited.catch(() => {
42
+ return;
43
+ });
44
+ return;
45
+ }
46
+ console.warn(`[sync-omo-config] Desktop notify not supported on ${platform}`);
47
+ }
7
48
  function getDataDir() {
8
49
  const home = homedir();
9
- const xdgData = process.env.XDG_DATA_HOME || path.join(home, ".local", "share");
50
+ const xdgData = process.env.XDG_DATA_HOME || (home ? path.join(home, ".local", "share") : undefined);
51
+ if (!xdgData) {
52
+ throw new Error("[sync-omo-config] Cannot determine data directory: HOME is not set");
53
+ }
10
54
  return path.join(xdgData, "opencode");
11
55
  }
12
56
  function getConfigDir() {
@@ -58,23 +102,24 @@ async function syncOmoConfig() {
58
102
  const authFile = Bun.file(authPath);
59
103
  if (!await authFile.exists()) {
60
104
  console.log(`${LOG_PREFIX} auth.json not found at ${authPath}, skipping sync`);
61
- return;
105
+ return [];
62
106
  }
63
107
  let auth;
64
108
  try {
65
109
  auth = await authFile.json();
66
110
  } catch (e) {
67
111
  console.error(`${LOG_PREFIX} Failed to parse auth.json:`, e);
68
- return;
112
+ return [];
69
113
  }
70
114
  const omoConfigs = [];
115
+ const expiredServers = [];
71
116
  for (const [serverUrl, authInfo] of Object.entries(auth)) {
72
117
  if (!isWellKnownAuth(authInfo)) {
73
118
  continue;
74
119
  }
75
120
  console.log(`${LOG_PREFIX} Fetching config from ${serverUrl}`);
76
121
  try {
77
- const wellKnownUrl = `${serverUrl}/.well-known/opencode`;
122
+ const wellKnownUrl = serverUrl.includes("/.well-known/opencode") ? serverUrl : `${serverUrl}/.well-known/opencode`;
78
123
  const response = await fetch(wellKnownUrl, {
79
124
  headers: {
80
125
  Accept: "application/json"
@@ -85,6 +130,15 @@ async function syncOmoConfig() {
85
130
  continue;
86
131
  }
87
132
  const data = await response.json();
133
+ if (data.auth_status === "invalid" || data.auth_status === "reauth_required") {
134
+ console.warn(`${LOG_PREFIX} Auth expired for ${serverUrl}, will notify via TUI toast`);
135
+ 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`);
136
+ expiredServers.push(serverUrl);
137
+ delete auth[serverUrl];
138
+ await Bun.write(authPath, JSON.stringify(auth, null, 2), { mode: 384 });
139
+ console.log(`${LOG_PREFIX} Removed expired credential for ${serverUrl} from auth.json`);
140
+ continue;
141
+ }
88
142
  if (data.omo && typeof data.omo === "object") {
89
143
  console.log(`${LOG_PREFIX} Found omo config from ${serverUrl}`);
90
144
  omoConfigs.push(data.omo);
@@ -96,7 +150,7 @@ async function syncOmoConfig() {
96
150
  }
97
151
  if (omoConfigs.length === 0) {
98
152
  console.log(`${LOG_PREFIX} No omo configs found, skipping write`);
99
- return;
153
+ return expiredServers;
100
154
  }
101
155
  console.log(`${LOG_PREFIX} Found ${omoConfigs.length} omo config(s)`);
102
156
  const configDir = getConfigDir();
@@ -119,12 +173,42 @@ async function syncOmoConfig() {
119
173
  }
120
174
  await Bun.write(omoPath, JSON.stringify(mergedConfig, null, 2));
121
175
  console.log(`${LOG_PREFIX} Successfully wrote oh-my-opencode.json to ${omoPath}`);
176
+ return expiredServers;
122
177
  } catch (error) {
123
178
  console.error(`${LOG_PREFIX} Unexpected error during sync:`, error);
179
+ return [];
124
180
  }
125
181
  }
126
- var SyncOmoConfigPlugin = async function SyncOmoConfigPlugin2() {
127
- await syncOmoConfig();
182
+ var SyncOmoConfigPlugin = async function SyncOmoConfigPlugin2(input) {
183
+ const expiredServers = await syncOmoConfig();
184
+ if (expiredServers.length === 0)
185
+ return {};
186
+ const pending = new Set(expiredServers);
187
+ const delays = [2000, 4000, 8000, 15000];
188
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
189
+ const notify = async () => {
190
+ for (const delay of delays) {
191
+ if (pending.size === 0)
192
+ return;
193
+ await sleep(delay);
194
+ for (const server of [...pending]) {
195
+ const ok = await input.client.tui.showToast({
196
+ body: {
197
+ title: "\u26A0 \u6388\u6743\u5DF2\u5931\u6548",
198
+ 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`,
199
+ variant: "error",
200
+ duration: 30000
201
+ }
202
+ }).then(() => true).catch((e) => {
203
+ console.error("[sync-omo-config] Failed to show toast:", e);
204
+ return false;
205
+ });
206
+ if (ok)
207
+ pending.delete(server);
208
+ }
209
+ }
210
+ };
211
+ notify();
128
212
  return {};
129
213
  };
130
214
  var src_default = SyncOmoConfigPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sync-omo-config",
3
- "version": "1.0.1",
3
+ "version": "1.3.0",
4
4
  "description": "OpenCode plugin to sync omo config from well-known endpoint to oh-my-opencode.json",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",