opencode-usage-plugin 0.0.2-dev3 → 0.0.2-dev5
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 +1245 -750
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,671 +1,991 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var maskSecret = (secret) => {
|
|
6
|
-
if (!secret || typeof secret !== "string" || secret.length <= 8) {
|
|
7
|
-
return "***";
|
|
8
|
-
}
|
|
9
|
-
return `${secret.slice(0, 4)}...${secret.slice(-4)}`;
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
5
|
};
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
info: async () => {
|
|
15
|
-
},
|
|
16
|
-
warn: async () => {
|
|
17
|
-
},
|
|
18
|
-
error: async () => {
|
|
19
|
-
}
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
9
|
};
|
|
21
|
-
var createLogger = (client) => {
|
|
22
|
-
const service = "opencode-usage";
|
|
23
|
-
return {
|
|
24
|
-
debug: async (message, extra) => {
|
|
25
|
-
await client.app.log({
|
|
26
|
-
service,
|
|
27
|
-
level: "debug",
|
|
28
|
-
message,
|
|
29
|
-
...extra ?? {}
|
|
30
|
-
});
|
|
31
|
-
},
|
|
32
|
-
info: async (message, extra) => {
|
|
33
|
-
await client.app.log({
|
|
34
|
-
service,
|
|
35
|
-
level: "info",
|
|
36
|
-
message,
|
|
37
|
-
...extra ?? {}
|
|
38
|
-
});
|
|
39
|
-
},
|
|
40
|
-
warn: async (message, extra) => {
|
|
41
|
-
await client.app.log({
|
|
42
|
-
service,
|
|
43
|
-
level: "warn",
|
|
44
|
-
message,
|
|
45
|
-
...extra ?? {}
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
error: async (message, extra) => {
|
|
49
|
-
await client.app.log({
|
|
50
|
-
service,
|
|
51
|
-
level: "error",
|
|
52
|
-
message,
|
|
53
|
-
...extra ?? {}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
var noopLogger = noOpLogger;
|
|
59
10
|
|
|
60
|
-
// src/providers/common/
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
11
|
+
// src/providers/common/logger.ts
|
|
12
|
+
var logger_exports = {};
|
|
13
|
+
__export(logger_exports, {
|
|
14
|
+
createLogger: () => createLogger,
|
|
15
|
+
maskSecret: () => maskSecret,
|
|
16
|
+
noopLogger: () => noopLogger
|
|
17
|
+
});
|
|
18
|
+
var maskSecret, noOpLogger, createLogger, noopLogger;
|
|
19
|
+
var init_logger = __esm({
|
|
20
|
+
"src/providers/common/logger.ts"() {
|
|
21
|
+
"use strict";
|
|
22
|
+
maskSecret = (secret) => {
|
|
23
|
+
if (!secret || typeof secret !== "string" || secret.length <= 8) {
|
|
24
|
+
return "***";
|
|
25
|
+
}
|
|
26
|
+
return `${secret.slice(0, 4)}...${secret.slice(-4)}`;
|
|
27
|
+
};
|
|
28
|
+
noOpLogger = {
|
|
29
|
+
debug: async () => {
|
|
30
|
+
},
|
|
31
|
+
info: async () => {
|
|
32
|
+
},
|
|
33
|
+
warn: async () => {
|
|
34
|
+
},
|
|
35
|
+
error: async () => {
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
createLogger = (client) => {
|
|
39
|
+
const service = "opencode-usage";
|
|
40
|
+
return {
|
|
41
|
+
debug: async (message, extra) => {
|
|
42
|
+
await client.app.log({
|
|
43
|
+
service,
|
|
44
|
+
level: "debug",
|
|
45
|
+
message,
|
|
46
|
+
...extra ?? {}
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
info: async (message, extra) => {
|
|
50
|
+
await client.app.log({
|
|
51
|
+
service,
|
|
52
|
+
level: "info",
|
|
53
|
+
message,
|
|
54
|
+
...extra ?? {}
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
warn: async (message, extra) => {
|
|
58
|
+
await client.app.log({
|
|
59
|
+
service,
|
|
60
|
+
level: "warn",
|
|
61
|
+
message,
|
|
62
|
+
...extra ?? {}
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
error: async (message, extra) => {
|
|
66
|
+
await client.app.log({
|
|
67
|
+
service,
|
|
68
|
+
level: "error",
|
|
69
|
+
message,
|
|
70
|
+
...extra ?? {}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
noopLogger = noOpLogger;
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
};
|
|
71
|
-
var formatDuration = (seconds) => {
|
|
72
|
-
if (seconds <= 0) {
|
|
73
|
-
return "0s";
|
|
74
|
-
}
|
|
75
|
-
const weeks = Math.floor(seconds / 604800);
|
|
76
|
-
const days = Math.floor(seconds % 604800 / 86400);
|
|
77
|
-
const hours = Math.floor(seconds % 86400 / 3600);
|
|
78
|
-
const minutes = Math.floor(seconds % 3600 / 60);
|
|
79
|
-
const secs = seconds % 60;
|
|
80
|
-
const parts = [];
|
|
81
|
-
if (weeks > 0) parts.push(`${weeks}w`);
|
|
82
|
-
if (days > 0) parts.push(`${days}d`);
|
|
83
|
-
if (hours > 0) parts.push(`${hours}h`);
|
|
84
|
-
if (minutes > 0) parts.push(`${minutes}m`);
|
|
85
|
-
if (secs > 0 || parts.length === 0) parts.push(`${secs}s`);
|
|
86
|
-
return parts.join(" ");
|
|
87
|
-
};
|
|
88
|
-
var formatResetAt = (resetAtMs) => {
|
|
89
|
-
return new Date(resetAtMs).toLocaleString(void 0, {
|
|
90
|
-
weekday: "long",
|
|
91
|
-
year: "numeric",
|
|
92
|
-
month: "long",
|
|
93
|
-
day: "numeric",
|
|
94
|
-
hour: "numeric",
|
|
95
|
-
minute: "numeric",
|
|
96
|
-
second: "numeric",
|
|
97
|
-
timeZoneName: "short"
|
|
98
|
-
});
|
|
99
|
-
};
|
|
77
|
+
});
|
|
100
78
|
|
|
101
79
|
// src/providers/common/files.ts
|
|
102
80
|
import { readFile } from "node:fs/promises";
|
|
103
81
|
import { homedir } from "node:os";
|
|
104
82
|
import { join } from "node:path";
|
|
105
|
-
var xdgDataHome
|
|
106
|
-
var
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
83
|
+
var xdgDataHome, xdgConfigHome, xdgCacheHome, AUTH_PATHS, readJson, loadOpenCodeAuth;
|
|
84
|
+
var init_files = __esm({
|
|
85
|
+
"src/providers/common/files.ts"() {
|
|
86
|
+
"use strict";
|
|
87
|
+
xdgDataHome = () => process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share");
|
|
88
|
+
xdgConfigHome = () => process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
|
|
89
|
+
xdgCacheHome = () => process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
|
|
90
|
+
AUTH_PATHS = {
|
|
91
|
+
opencode: () => join(xdgDataHome(), "opencode", "auth.json"),
|
|
92
|
+
openaiPlugin: () => join(homedir(), ".opencode", "auth", "openai.json"),
|
|
93
|
+
antigravityConfig: () => join(xdgConfigHome(), "opencode", "antigravity-accounts.json"),
|
|
94
|
+
antigravityData: () => join(xdgDataHome(), "opencode", "antigravity-accounts.json")
|
|
95
|
+
};
|
|
96
|
+
readJson = async (filePath, logger) => {
|
|
97
|
+
try {
|
|
98
|
+
const content = await readFile(filePath, "utf-8");
|
|
99
|
+
return JSON.parse(content);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
if (logger) {
|
|
102
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
103
|
+
await logger.debug(`Auth file not found or invalid: ${filePath}`, { error: message });
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
loadOpenCodeAuth = async (logger) => {
|
|
109
|
+
return readJson(AUTH_PATHS.opencode(), logger);
|
|
110
|
+
};
|
|
123
111
|
}
|
|
124
|
-
};
|
|
125
|
-
var loadOpenCodeAuth = async (logger) => {
|
|
126
|
-
return readJson(AUTH_PATHS.opencode(), logger);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// src/providers/common/registry.ts
|
|
130
|
-
var PROVIDER_ALIASES = {
|
|
131
|
-
openai: ["openai", "codex", "chatgpt"],
|
|
132
|
-
google: ["google", "antigravity"],
|
|
133
|
-
"zai-coding-plan": ["zai-coding-plan", "zai", "z.ai"]
|
|
134
|
-
};
|
|
135
|
-
var getProviderAliases = (provider) => {
|
|
136
|
-
return PROVIDER_ALIASES[provider];
|
|
137
|
-
};
|
|
112
|
+
});
|
|
138
113
|
|
|
139
|
-
// src/
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return null;
|
|
114
|
+
// src/cache/file.ts
|
|
115
|
+
import { mkdir, readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
|
|
116
|
+
var CACHE_DIR, CACHE_PATH, TMP_PATH, ensureCacheDir, readCache, writeCache;
|
|
117
|
+
var init_file = __esm({
|
|
118
|
+
"src/cache/file.ts"() {
|
|
119
|
+
"use strict";
|
|
120
|
+
init_files();
|
|
121
|
+
CACHE_DIR = () => `${xdgCacheHome()}/opencode/opencode-usage-plugin`;
|
|
122
|
+
CACHE_PATH = () => `${CACHE_DIR()}/usage.json`;
|
|
123
|
+
TMP_PATH = () => `${CACHE_PATH()}.tmp`;
|
|
124
|
+
ensureCacheDir = async () => {
|
|
125
|
+
try {
|
|
126
|
+
await mkdir(CACHE_DIR(), { recursive: true });
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
readCache = async (logger) => {
|
|
134
|
+
try {
|
|
135
|
+
const content = await readFile2(CACHE_PATH(), "utf-8");
|
|
136
|
+
const parsed = JSON.parse(content);
|
|
137
|
+
if (typeof parsed === "object" && parsed !== null && "schema_version" in parsed && "updated_at" in parsed && "refresh_interval_seconds" in parsed && "providers" in parsed) {
|
|
138
|
+
return parsed;
|
|
139
|
+
}
|
|
140
|
+
await logger?.warn("Invalid cache schema, returning null");
|
|
141
|
+
return null;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (logger) {
|
|
144
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
+
await logger.debug("Cache file not found or invalid", { error: message });
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
writeCache = async (cache, logger) => {
|
|
151
|
+
try {
|
|
152
|
+
await ensureCacheDir();
|
|
153
|
+
const content = JSON.stringify(cache, null, 2);
|
|
154
|
+
await writeFile(TMP_PATH(), content, "utf-8");
|
|
155
|
+
await rename(TMP_PATH(), CACHE_PATH());
|
|
156
|
+
await logger?.debug("Cache written successfully", { path: CACHE_PATH() });
|
|
157
|
+
} catch (error) {
|
|
158
|
+
await logger?.error("Failed to write cache", {
|
|
159
|
+
error: error instanceof Error ? error.message : String(error)
|
|
160
|
+
});
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
190
164
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
var
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// src/cache/types.ts
|
|
168
|
+
var SCHEMA_VERSION, REFRESH_INTERVAL_SECONDS, STALE_THRESHOLD_MULTIPLIER;
|
|
169
|
+
var init_types = __esm({
|
|
170
|
+
"src/cache/types.ts"() {
|
|
171
|
+
"use strict";
|
|
172
|
+
SCHEMA_VERSION = 1;
|
|
173
|
+
REFRESH_INTERVAL_SECONDS = 300;
|
|
174
|
+
STALE_THRESHOLD_MULTIPLIER = 2;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// src/cache/reader.ts
|
|
179
|
+
var reader_exports = {};
|
|
180
|
+
__export(reader_exports, {
|
|
181
|
+
loadCacheForDisplay: () => loadCacheForDisplay
|
|
182
|
+
});
|
|
183
|
+
var loadCacheForDisplay;
|
|
184
|
+
var init_reader = __esm({
|
|
185
|
+
"src/cache/reader.ts"() {
|
|
186
|
+
"use strict";
|
|
187
|
+
init_file();
|
|
188
|
+
init_types();
|
|
189
|
+
loadCacheForDisplay = async (logger) => {
|
|
190
|
+
const cache = await readCache(logger);
|
|
191
|
+
if (!cache) {
|
|
192
|
+
await logger.warn("No cache available");
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const updatedAt = new Date(cache.updated_at);
|
|
196
|
+
const now = /* @__PURE__ */ new Date();
|
|
197
|
+
const staleThresholdMs = REFRESH_INTERVAL_SECONDS * 1e3 * STALE_THRESHOLD_MULTIPLIER;
|
|
198
|
+
const isStale = now.getTime() - updatedAt.getTime() > staleThresholdMs;
|
|
199
|
+
if (isStale) {
|
|
200
|
+
await logger.debug("Cache is stale", {
|
|
201
|
+
updatedAt: cache.updated_at,
|
|
202
|
+
staleThresholdSeconds: REFRESH_INTERVAL_SECONDS * STALE_THRESHOLD_MULTIPLIER
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const configuredProviders = {};
|
|
206
|
+
for (const [providerId, entry] of Object.entries(cache.providers)) {
|
|
207
|
+
if (entry.configured) {
|
|
208
|
+
configuredProviders[providerId] = entry;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
providers: configuredProviders,
|
|
213
|
+
updatedAt: cache.updated_at,
|
|
214
|
+
isStale
|
|
215
|
+
};
|
|
206
216
|
};
|
|
207
217
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// src/providers/common/time.ts
|
|
221
|
+
var calculateResetAfterSeconds, formatDuration, formatResetAt;
|
|
222
|
+
var init_time = __esm({
|
|
223
|
+
"src/providers/common/time.ts"() {
|
|
224
|
+
"use strict";
|
|
225
|
+
calculateResetAfterSeconds = (resetAt, now = Date.now()) => {
|
|
226
|
+
if (!resetAt) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
const diffMs = resetAt - now;
|
|
230
|
+
if (diffMs <= 0) {
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
return Math.floor(diffMs / 1e3);
|
|
234
|
+
};
|
|
235
|
+
formatDuration = (seconds) => {
|
|
236
|
+
if (seconds <= 0) {
|
|
237
|
+
return "0s";
|
|
238
|
+
}
|
|
239
|
+
const weeks = Math.floor(seconds / 604800);
|
|
240
|
+
const days = Math.floor(seconds % 604800 / 86400);
|
|
241
|
+
const hours = Math.floor(seconds % 86400 / 3600);
|
|
242
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
243
|
+
const secs = seconds % 60;
|
|
244
|
+
const parts = [];
|
|
245
|
+
if (weeks > 0) parts.push(`${weeks}w`);
|
|
246
|
+
if (days > 0) parts.push(`${days}d`);
|
|
247
|
+
if (hours > 0) parts.push(`${hours}h`);
|
|
248
|
+
if (minutes > 0) parts.push(`${minutes}m`);
|
|
249
|
+
if (secs > 0 || parts.length === 0) parts.push(`${secs}s`);
|
|
250
|
+
return parts.join(" ");
|
|
251
|
+
};
|
|
252
|
+
formatResetAt = (resetAtMs) => {
|
|
253
|
+
return new Date(resetAtMs).toLocaleString(void 0, {
|
|
254
|
+
weekday: "long",
|
|
255
|
+
year: "numeric",
|
|
256
|
+
month: "long",
|
|
257
|
+
day: "numeric",
|
|
258
|
+
hour: "numeric",
|
|
259
|
+
minute: "numeric",
|
|
260
|
+
second: "numeric",
|
|
261
|
+
timeZoneName: "short"
|
|
262
|
+
});
|
|
263
|
+
};
|
|
215
264
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// src/providers/common/registry.ts
|
|
268
|
+
var PROVIDER_ALIASES, getProviderAliases;
|
|
269
|
+
var init_registry = __esm({
|
|
270
|
+
"src/providers/common/registry.ts"() {
|
|
271
|
+
"use strict";
|
|
272
|
+
PROVIDER_ALIASES = {
|
|
273
|
+
openai: ["openai", "codex", "chatgpt"],
|
|
274
|
+
google: ["google", "antigravity"],
|
|
275
|
+
"zai-coding-plan": ["zai-coding-plan", "zai", "z.ai"]
|
|
276
|
+
};
|
|
277
|
+
getProviderAliases = (provider) => {
|
|
278
|
+
return PROVIDER_ALIASES[provider];
|
|
279
|
+
};
|
|
227
280
|
}
|
|
228
|
-
|
|
229
|
-
};
|
|
281
|
+
});
|
|
230
282
|
|
|
231
|
-
// src/providers/google/
|
|
232
|
-
var
|
|
233
|
-
var
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const response = await fetch("https://oauth2.googleapis.com/token", {
|
|
249
|
-
method: "POST",
|
|
250
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
251
|
-
body: new URLSearchParams({
|
|
252
|
-
client_id: GOOGLE_CLIENT_ID,
|
|
253
|
-
client_secret: GOOGLE_CLIENT_SECRET,
|
|
254
|
-
refresh_token: refreshToken,
|
|
255
|
-
grant_type: "refresh_token"
|
|
256
|
-
})
|
|
257
|
-
});
|
|
258
|
-
if (!response.ok) {
|
|
259
|
-
await logger.warn("Failed to refresh OAuth token for google", {
|
|
260
|
-
status: response.status,
|
|
261
|
-
token: maskSecret(refreshToken)
|
|
262
|
-
});
|
|
283
|
+
// src/providers/google/auth.ts
|
|
284
|
+
var toAuthData, loadOpenCodeAuthEntry, toAuthContext, selectAccount, loadAuthFromAccounts, getGoogleAuth;
|
|
285
|
+
var init_auth = __esm({
|
|
286
|
+
"src/providers/google/auth.ts"() {
|
|
287
|
+
"use strict";
|
|
288
|
+
init_files();
|
|
289
|
+
init_registry();
|
|
290
|
+
toAuthData = (entry) => {
|
|
291
|
+
if (!entry) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
if (typeof entry === "string") {
|
|
295
|
+
return { token: entry };
|
|
296
|
+
}
|
|
297
|
+
if (typeof entry === "object") {
|
|
298
|
+
return entry;
|
|
299
|
+
}
|
|
263
300
|
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
301
|
+
};
|
|
302
|
+
loadOpenCodeAuthEntry = async (logger) => {
|
|
303
|
+
const auth = await loadOpenCodeAuth(logger);
|
|
304
|
+
if (!auth) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
for (const alias of getProviderAliases("google")) {
|
|
308
|
+
const entry = toAuthData(auth[alias]);
|
|
309
|
+
if (entry) {
|
|
310
|
+
return entry;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
};
|
|
315
|
+
toAuthContext = (entry) => {
|
|
316
|
+
if (!entry) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
const accessToken = entry.access ?? entry.token;
|
|
320
|
+
let refreshToken = entry.refresh;
|
|
321
|
+
let projectId = void 0;
|
|
322
|
+
if (refreshToken && refreshToken.includes("|")) {
|
|
323
|
+
const parts = refreshToken.split("|");
|
|
324
|
+
refreshToken = parts[0];
|
|
325
|
+
projectId = parts[1];
|
|
326
|
+
}
|
|
327
|
+
if (!accessToken && !refreshToken) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
accessToken,
|
|
332
|
+
refreshToken,
|
|
333
|
+
expires: entry.expires,
|
|
334
|
+
projectId
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
selectAccount = (accounts) => {
|
|
338
|
+
if (!accounts?.accounts?.length) {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
const candidateIndex = accounts.activeIndex ?? 0;
|
|
342
|
+
const account = accounts.accounts[candidateIndex] ?? accounts.accounts[0];
|
|
343
|
+
return account ?? null;
|
|
344
|
+
};
|
|
345
|
+
loadAuthFromAccounts = async (logger) => {
|
|
346
|
+
const configAccounts = await readJson(
|
|
347
|
+
AUTH_PATHS.antigravityConfig(),
|
|
348
|
+
logger
|
|
349
|
+
);
|
|
350
|
+
const account = selectAccount(configAccounts);
|
|
351
|
+
if (account) {
|
|
352
|
+
return {
|
|
353
|
+
refreshToken: account.refreshToken,
|
|
354
|
+
projectId: account.projectId ?? account.managedProjectId,
|
|
355
|
+
email: account.email
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
const dataAccounts = await readJson(
|
|
359
|
+
AUTH_PATHS.antigravityData(),
|
|
360
|
+
logger
|
|
361
|
+
);
|
|
362
|
+
const fallbackAccount = selectAccount(dataAccounts);
|
|
363
|
+
if (!fallbackAccount) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
refreshToken: fallbackAccount.refreshToken,
|
|
368
|
+
projectId: fallbackAccount.projectId ?? fallbackAccount.managedProjectId,
|
|
369
|
+
email: fallbackAccount.email
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
getGoogleAuth = async (logger) => {
|
|
373
|
+
const openCodeAuth = await loadOpenCodeAuthEntry(logger);
|
|
374
|
+
const authContext = toAuthContext(openCodeAuth);
|
|
375
|
+
if (authContext) {
|
|
376
|
+
return authContext;
|
|
377
|
+
}
|
|
378
|
+
return loadAuthFromAccounts(logger);
|
|
379
|
+
};
|
|
270
380
|
}
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// src/providers/google/fetch.ts
|
|
384
|
+
var GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, DEFAULT_PROJECT_ID, WINDOW_SECONDS, ENDPOINTS, HEADERS, refreshAccessToken, fetchModels, toWindow, buildUsage, resolveAccessToken, fetchGoogleUsage;
|
|
385
|
+
var init_fetch = __esm({
|
|
386
|
+
"src/providers/google/fetch.ts"() {
|
|
387
|
+
"use strict";
|
|
388
|
+
init_logger();
|
|
389
|
+
init_time();
|
|
390
|
+
init_auth();
|
|
391
|
+
GOOGLE_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
|
|
392
|
+
GOOGLE_CLIENT_SECRET = "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";
|
|
393
|
+
DEFAULT_PROJECT_ID = "rising-fact-p41fc";
|
|
394
|
+
WINDOW_SECONDS = 5 * 60 * 60;
|
|
395
|
+
ENDPOINTS = [
|
|
396
|
+
"https://daily-cloudcode-pa.sandbox.googleapis.com",
|
|
397
|
+
"https://autopush-cloudcode-pa.sandbox.googleapis.com",
|
|
398
|
+
"https://cloudcode-pa.googleapis.com"
|
|
399
|
+
];
|
|
400
|
+
HEADERS = {
|
|
401
|
+
"User-Agent": "antigravity/1.11.5 windows/amd64",
|
|
402
|
+
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
403
|
+
"Client-Metadata": '{"ideType":"IDE_UNSPECIFIED","platform":"PLATFORM_UNSPECIFIED","pluginType":"GEMINI"}'
|
|
404
|
+
};
|
|
405
|
+
refreshAccessToken = async (refreshToken, logger) => {
|
|
406
|
+
try {
|
|
407
|
+
const response = await fetch("https://oauth2.googleapis.com/token", {
|
|
408
|
+
method: "POST",
|
|
409
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
410
|
+
body: new URLSearchParams({
|
|
411
|
+
client_id: GOOGLE_CLIENT_ID,
|
|
412
|
+
client_secret: GOOGLE_CLIENT_SECRET,
|
|
413
|
+
refresh_token: refreshToken,
|
|
414
|
+
grant_type: "refresh_token"
|
|
415
|
+
})
|
|
416
|
+
});
|
|
417
|
+
if (!response.ok) {
|
|
418
|
+
await logger.warn("Failed to refresh OAuth token for google", {
|
|
419
|
+
status: response.status,
|
|
420
|
+
token: maskSecret(refreshToken)
|
|
421
|
+
});
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
288
424
|
return await response.json();
|
|
425
|
+
} catch (error) {
|
|
426
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
427
|
+
await logger.warn(`Token refresh failed for google: ${message}`);
|
|
428
|
+
return null;
|
|
289
429
|
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
430
|
+
};
|
|
431
|
+
fetchModels = async (accessToken, projectId, logger) => {
|
|
432
|
+
const body = projectId ? { project: projectId } : {};
|
|
433
|
+
for (const endpoint of ENDPOINTS) {
|
|
434
|
+
try {
|
|
435
|
+
const response = await fetch(`${endpoint}/v1internal:fetchAvailableModels`, {
|
|
436
|
+
method: "POST",
|
|
437
|
+
headers: {
|
|
438
|
+
Authorization: `Bearer ${accessToken}`,
|
|
439
|
+
"Content-Type": "application/json",
|
|
440
|
+
...HEADERS
|
|
441
|
+
},
|
|
442
|
+
body: JSON.stringify(body),
|
|
443
|
+
signal: AbortSignal.timeout(15e3)
|
|
444
|
+
});
|
|
445
|
+
if (response.ok) {
|
|
446
|
+
await logger.debug(`Fetched models from ${endpoint}`, { projectId });
|
|
447
|
+
return await response.json();
|
|
448
|
+
}
|
|
449
|
+
} catch {
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
await logger.error("Failed to fetch models from all google endpoints", { projectId });
|
|
454
|
+
return null;
|
|
455
|
+
};
|
|
456
|
+
toWindow = (remainingFraction, resetTime) => {
|
|
457
|
+
const remainingPercent = remainingFraction !== void 0 ? Math.round(remainingFraction * 100) : null;
|
|
458
|
+
const usedPercent = remainingPercent !== null ? Math.max(0, 100 - remainingPercent) : null;
|
|
459
|
+
const resetAt = resetTime ? new Date(resetTime).getTime() : null;
|
|
460
|
+
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
|
|
461
|
+
return {
|
|
462
|
+
usedPercent,
|
|
463
|
+
remainingPercent,
|
|
464
|
+
windowSeconds: WINDOW_SECONDS,
|
|
465
|
+
resetAfterSeconds,
|
|
466
|
+
resetAt,
|
|
467
|
+
resetAtFormatted: resetAt ? formatResetAt(resetAt) : null,
|
|
468
|
+
resetAfterFormatted: resetAfterSeconds !== null ? formatDuration(resetAfterSeconds) : null
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
buildUsage = (data) => {
|
|
472
|
+
const models = {};
|
|
473
|
+
for (const [modelName, modelData] of Object.entries(data.models ?? {})) {
|
|
474
|
+
const window = toWindow(modelData.quotaInfo?.remainingFraction, modelData.quotaInfo?.resetTime);
|
|
475
|
+
models[modelName] = {
|
|
476
|
+
windows: {
|
|
477
|
+
"5h": window
|
|
478
|
+
}
|
|
479
|
+
};
|
|
319
480
|
}
|
|
481
|
+
return {
|
|
482
|
+
windows: {},
|
|
483
|
+
models: Object.keys(models).length ? models : void 0
|
|
484
|
+
};
|
|
320
485
|
};
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
if (!refreshToken) {
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
const refreshed = await refreshAccessToken(refreshToken, logger);
|
|
336
|
-
return refreshed?.access_token ?? null;
|
|
337
|
-
};
|
|
338
|
-
var fetchGoogleUsage = async (logger = noopLogger) => {
|
|
339
|
-
const auth = await getGoogleAuth(logger);
|
|
340
|
-
if (!auth) {
|
|
341
|
-
await logger.warn("No auth configured for google");
|
|
342
|
-
return {
|
|
343
|
-
provider: "google",
|
|
344
|
-
ok: false,
|
|
345
|
-
configured: false,
|
|
346
|
-
error: "Not configured - no accounts found",
|
|
347
|
-
usage: null
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
const accessToken = await resolveAccessToken(
|
|
351
|
-
auth.refreshToken,
|
|
352
|
-
auth.accessToken,
|
|
353
|
-
auth.expires,
|
|
354
|
-
logger
|
|
355
|
-
);
|
|
356
|
-
if (!accessToken) {
|
|
357
|
-
await logger.warn("Failed to refresh OAuth token for google", { email: auth.email });
|
|
358
|
-
return {
|
|
359
|
-
provider: "google",
|
|
360
|
-
ok: false,
|
|
361
|
-
configured: true,
|
|
362
|
-
error: "Failed to refresh OAuth token",
|
|
363
|
-
usage: null
|
|
486
|
+
resolveAccessToken = async (refreshToken, accessToken, expires, logger) => {
|
|
487
|
+
const now = Date.now();
|
|
488
|
+
if (accessToken && (!expires || expires > now)) {
|
|
489
|
+
return accessToken;
|
|
490
|
+
}
|
|
491
|
+
if (!refreshToken) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const refreshed = await refreshAccessToken(refreshToken, logger);
|
|
495
|
+
return refreshed?.access_token ?? null;
|
|
364
496
|
};
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
497
|
+
fetchGoogleUsage = async (logger = noopLogger) => {
|
|
498
|
+
const auth = await getGoogleAuth(logger);
|
|
499
|
+
if (!auth) {
|
|
500
|
+
await logger.warn("No auth configured for google");
|
|
501
|
+
return {
|
|
502
|
+
provider: "google",
|
|
503
|
+
ok: false,
|
|
504
|
+
configured: false,
|
|
505
|
+
error: "Not configured - no accounts found",
|
|
506
|
+
usage: null
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
const accessToken = await resolveAccessToken(
|
|
510
|
+
auth.refreshToken,
|
|
511
|
+
auth.accessToken,
|
|
512
|
+
auth.expires,
|
|
513
|
+
logger
|
|
514
|
+
);
|
|
515
|
+
if (!accessToken) {
|
|
516
|
+
await logger.warn("Failed to refresh OAuth token for google", { email: auth.email });
|
|
517
|
+
return {
|
|
518
|
+
provider: "google",
|
|
519
|
+
ok: false,
|
|
520
|
+
configured: true,
|
|
521
|
+
error: "Failed to refresh OAuth token",
|
|
522
|
+
usage: null
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
const projectId = auth.projectId ?? DEFAULT_PROJECT_ID;
|
|
526
|
+
const modelsData = await fetchModels(accessToken, projectId, logger);
|
|
527
|
+
if (!modelsData) {
|
|
528
|
+
await logger.error("Failed to fetch models from google API", { projectId });
|
|
529
|
+
return {
|
|
530
|
+
provider: "google",
|
|
531
|
+
ok: false,
|
|
532
|
+
configured: true,
|
|
533
|
+
error: "Failed to fetch models from API",
|
|
534
|
+
usage: null
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
await logger.info("google usage fetched successfully");
|
|
538
|
+
return {
|
|
539
|
+
provider: "google",
|
|
540
|
+
ok: true,
|
|
541
|
+
configured: true,
|
|
542
|
+
usage: buildUsage(modelsData)
|
|
543
|
+
};
|
|
376
544
|
};
|
|
377
545
|
}
|
|
378
|
-
|
|
379
|
-
return {
|
|
380
|
-
provider: "google",
|
|
381
|
-
ok: true,
|
|
382
|
-
configured: true,
|
|
383
|
-
usage: buildUsage(modelsData)
|
|
384
|
-
};
|
|
385
|
-
};
|
|
546
|
+
});
|
|
386
547
|
|
|
387
548
|
// src/providers/openai/auth.ts
|
|
388
|
-
var toAuthData2
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
549
|
+
var toAuthData2, hasAccessToken, loadOpenCodeAuthEntry2, getOpenaiAuth;
|
|
550
|
+
var init_auth2 = __esm({
|
|
551
|
+
"src/providers/openai/auth.ts"() {
|
|
552
|
+
"use strict";
|
|
553
|
+
init_files();
|
|
554
|
+
init_registry();
|
|
555
|
+
toAuthData2 = (entry) => {
|
|
556
|
+
if (!entry) {
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
if (typeof entry === "string") {
|
|
560
|
+
return { token: entry };
|
|
561
|
+
}
|
|
562
|
+
if (typeof entry === "object") {
|
|
563
|
+
return entry;
|
|
564
|
+
}
|
|
565
|
+
return null;
|
|
566
|
+
};
|
|
567
|
+
hasAccessToken = (auth) => {
|
|
568
|
+
return Boolean(auth?.access || auth?.token);
|
|
569
|
+
};
|
|
570
|
+
loadOpenCodeAuthEntry2 = async (logger) => {
|
|
571
|
+
const auth = await loadOpenCodeAuth(logger);
|
|
572
|
+
if (!auth) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
for (const alias of getProviderAliases("openai")) {
|
|
576
|
+
const entry = toAuthData2(auth[alias]);
|
|
577
|
+
if (entry && hasAccessToken(entry)) {
|
|
578
|
+
return entry;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return null;
|
|
582
|
+
};
|
|
583
|
+
getOpenaiAuth = async (logger) => {
|
|
584
|
+
const openCodeAuth = await loadOpenCodeAuthEntry2(logger);
|
|
585
|
+
if (openCodeAuth && hasAccessToken(openCodeAuth)) {
|
|
586
|
+
return openCodeAuth;
|
|
587
|
+
}
|
|
588
|
+
const pluginAuth = await readJson(AUTH_PATHS.openaiPlugin(), logger);
|
|
589
|
+
if (pluginAuth && hasAccessToken(pluginAuth)) {
|
|
590
|
+
return pluginAuth;
|
|
591
|
+
}
|
|
592
|
+
return null;
|
|
593
|
+
};
|
|
424
594
|
}
|
|
425
|
-
|
|
426
|
-
};
|
|
595
|
+
});
|
|
427
596
|
|
|
428
597
|
// src/providers/openai/fetch.ts
|
|
429
|
-
var toWindow2
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
resetAfterFormatted: resetAfterSeconds !== null ? formatDuration(resetAfterSeconds) : null
|
|
444
|
-
};
|
|
445
|
-
};
|
|
446
|
-
var fetchOpenaiUsage = async (logger = noopLogger) => {
|
|
447
|
-
const auth = await getOpenaiAuth(logger);
|
|
448
|
-
if (!auth) {
|
|
449
|
-
await logger.warn("No auth configured for openai");
|
|
450
|
-
return {
|
|
451
|
-
provider: "openai",
|
|
452
|
-
ok: false,
|
|
453
|
-
configured: false,
|
|
454
|
-
error: "Not configured - no OAuth token found",
|
|
455
|
-
usage: null
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
const accessToken = auth.access ?? auth.token;
|
|
459
|
-
if (!accessToken) {
|
|
460
|
-
await logger.warn("Auth configured but access token missing for openai");
|
|
461
|
-
return {
|
|
462
|
-
provider: "openai",
|
|
463
|
-
ok: false,
|
|
464
|
-
configured: false,
|
|
465
|
-
error: "Not configured - access token missing",
|
|
466
|
-
usage: null
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
try {
|
|
470
|
-
const response = await fetch("https://chatgpt.com/backend-api/wham/usage", {
|
|
471
|
-
method: "GET",
|
|
472
|
-
headers: {
|
|
473
|
-
Authorization: `Bearer ${accessToken}`,
|
|
474
|
-
"Content-Type": "application/json"
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
if (!response.ok) {
|
|
478
|
-
await logger.error(`API error ${response.status} for openai`, {
|
|
479
|
-
token: maskSecret(accessToken)
|
|
480
|
-
});
|
|
598
|
+
var toWindow2, fetchOpenaiUsage;
|
|
599
|
+
var init_fetch2 = __esm({
|
|
600
|
+
"src/providers/openai/fetch.ts"() {
|
|
601
|
+
"use strict";
|
|
602
|
+
init_logger();
|
|
603
|
+
init_time();
|
|
604
|
+
init_auth2();
|
|
605
|
+
toWindow2 = (window) => {
|
|
606
|
+
if (!window) {
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
const usedPercent = window.used_percent;
|
|
610
|
+
const resetAt = window.reset_at ? window.reset_at * 1e3 : null;
|
|
611
|
+
const resetAfterSeconds = window.reset_after_seconds ?? calculateResetAfterSeconds(resetAt);
|
|
481
612
|
return {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
613
|
+
usedPercent,
|
|
614
|
+
remainingPercent: Math.max(0, 100 - usedPercent),
|
|
615
|
+
windowSeconds: window.limit_window_seconds ?? null,
|
|
616
|
+
resetAfterSeconds,
|
|
617
|
+
resetAt,
|
|
618
|
+
resetAtFormatted: resetAt ? formatResetAt(resetAt) : null,
|
|
619
|
+
resetAfterFormatted: resetAfterSeconds !== null ? formatDuration(resetAfterSeconds) : null
|
|
487
620
|
};
|
|
488
|
-
}
|
|
489
|
-
const payload = await response.json();
|
|
490
|
-
const primary = toWindow2(payload.rate_limit.primary_window);
|
|
491
|
-
const secondary = toWindow2(payload.rate_limit.secondary_window);
|
|
492
|
-
const windows = {};
|
|
493
|
-
if (primary) {
|
|
494
|
-
windows["5h"] = primary;
|
|
495
|
-
}
|
|
496
|
-
if (secondary) {
|
|
497
|
-
windows["weekly"] = secondary;
|
|
498
|
-
}
|
|
499
|
-
const usage = {
|
|
500
|
-
windows
|
|
501
621
|
};
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
622
|
+
fetchOpenaiUsage = async (logger = noopLogger) => {
|
|
623
|
+
const auth = await getOpenaiAuth(logger);
|
|
624
|
+
if (!auth) {
|
|
625
|
+
await logger.warn("No auth configured for openai");
|
|
626
|
+
return {
|
|
627
|
+
provider: "openai",
|
|
628
|
+
ok: false,
|
|
629
|
+
configured: false,
|
|
630
|
+
error: "Not configured - no OAuth token found",
|
|
631
|
+
usage: null
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
const accessToken = auth.access ?? auth.token;
|
|
635
|
+
if (!accessToken) {
|
|
636
|
+
await logger.warn("Auth configured but access token missing for openai");
|
|
637
|
+
return {
|
|
638
|
+
provider: "openai",
|
|
639
|
+
ok: false,
|
|
640
|
+
configured: false,
|
|
641
|
+
error: "Not configured - access token missing",
|
|
642
|
+
usage: null
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
try {
|
|
646
|
+
const response = await fetch("https://chatgpt.com/backend-api/wham/usage", {
|
|
647
|
+
method: "GET",
|
|
648
|
+
headers: {
|
|
649
|
+
Authorization: `Bearer ${accessToken}`,
|
|
650
|
+
"Content-Type": "application/json"
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
if (!response.ok) {
|
|
654
|
+
await logger.error(`API error ${response.status} for openai`, {
|
|
655
|
+
token: maskSecret(accessToken)
|
|
656
|
+
});
|
|
657
|
+
return {
|
|
658
|
+
provider: "openai",
|
|
659
|
+
ok: false,
|
|
660
|
+
configured: true,
|
|
661
|
+
error: `API error: ${response.status}`,
|
|
662
|
+
usage: null
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
const payload = await response.json();
|
|
666
|
+
const primary = toWindow2(payload.rate_limit.primary_window);
|
|
667
|
+
const secondary = toWindow2(payload.rate_limit.secondary_window);
|
|
668
|
+
const windows = {};
|
|
669
|
+
if (primary) {
|
|
670
|
+
windows["5h"] = primary;
|
|
671
|
+
}
|
|
672
|
+
if (secondary) {
|
|
673
|
+
windows["weekly"] = secondary;
|
|
674
|
+
}
|
|
675
|
+
const usage = {
|
|
676
|
+
windows
|
|
677
|
+
};
|
|
678
|
+
await logger.info("openai usage fetched successfully");
|
|
679
|
+
return {
|
|
680
|
+
provider: "openai",
|
|
681
|
+
ok: true,
|
|
682
|
+
configured: true,
|
|
683
|
+
usage
|
|
684
|
+
};
|
|
685
|
+
} catch (error) {
|
|
686
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
687
|
+
await logger.error(`Request failed for openai: ${message}`);
|
|
688
|
+
return {
|
|
689
|
+
provider: "openai",
|
|
690
|
+
ok: false,
|
|
691
|
+
configured: true,
|
|
692
|
+
error: `Request failed: ${message}`,
|
|
693
|
+
usage: null
|
|
694
|
+
};
|
|
695
|
+
}
|
|
518
696
|
};
|
|
519
697
|
}
|
|
520
|
-
};
|
|
698
|
+
});
|
|
521
699
|
|
|
522
700
|
// src/providers/zai-coding-plan/auth.ts
|
|
523
|
-
var resolveAuthValue
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
701
|
+
var resolveAuthValue, getZaiApiKey;
|
|
702
|
+
var init_auth3 = __esm({
|
|
703
|
+
"src/providers/zai-coding-plan/auth.ts"() {
|
|
704
|
+
"use strict";
|
|
705
|
+
init_files();
|
|
706
|
+
init_registry();
|
|
707
|
+
resolveAuthValue = (entry) => {
|
|
708
|
+
if (!entry) {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
if (typeof entry === "string") {
|
|
712
|
+
return entry;
|
|
713
|
+
}
|
|
714
|
+
if (typeof entry === "object") {
|
|
715
|
+
return entry.api_key ?? entry.token ?? entry.key ?? null;
|
|
716
|
+
}
|
|
717
|
+
return null;
|
|
718
|
+
};
|
|
719
|
+
getZaiApiKey = async (logger) => {
|
|
720
|
+
if (process.env.ZAI_API_KEY) {
|
|
721
|
+
return process.env.ZAI_API_KEY;
|
|
722
|
+
}
|
|
723
|
+
const auth = await loadOpenCodeAuth(logger);
|
|
724
|
+
if (!auth) {
|
|
725
|
+
return null;
|
|
726
|
+
}
|
|
727
|
+
for (const alias of getProviderAliases("zai-coding-plan")) {
|
|
728
|
+
const value = resolveAuthValue(auth[alias]);
|
|
729
|
+
if (value) {
|
|
730
|
+
return value;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return null;
|
|
734
|
+
};
|
|
548
735
|
}
|
|
549
|
-
|
|
550
|
-
};
|
|
736
|
+
});
|
|
551
737
|
|
|
552
738
|
// src/providers/zai-coding-plan/fetch.ts
|
|
553
|
-
var normalizeTimestamp
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
739
|
+
var normalizeTimestamp, TOKEN_WINDOW_SECONDS, resolveWindowSeconds, resolveWindowLabel, toWindow3, fetchZaiUsage;
|
|
740
|
+
var init_fetch3 = __esm({
|
|
741
|
+
"src/providers/zai-coding-plan/fetch.ts"() {
|
|
742
|
+
"use strict";
|
|
743
|
+
init_logger();
|
|
744
|
+
init_time();
|
|
745
|
+
init_auth3();
|
|
746
|
+
normalizeTimestamp = (value) => {
|
|
747
|
+
return value < 1e12 ? value * 1e3 : value;
|
|
748
|
+
};
|
|
749
|
+
TOKEN_WINDOW_SECONDS = {
|
|
750
|
+
3: 3600
|
|
751
|
+
};
|
|
752
|
+
resolveWindowSeconds = (limit) => {
|
|
753
|
+
if (!limit) {
|
|
754
|
+
return null;
|
|
755
|
+
}
|
|
756
|
+
if (!limit.number) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
const unitSeconds = TOKEN_WINDOW_SECONDS[limit.unit];
|
|
760
|
+
if (!unitSeconds) {
|
|
761
|
+
return null;
|
|
762
|
+
}
|
|
763
|
+
return unitSeconds * limit.number;
|
|
764
|
+
};
|
|
765
|
+
resolveWindowLabel = (windowSeconds) => {
|
|
766
|
+
if (!windowSeconds) {
|
|
767
|
+
return "tokens";
|
|
768
|
+
}
|
|
769
|
+
if (windowSeconds % 86400 === 0) {
|
|
770
|
+
const days = windowSeconds / 86400;
|
|
771
|
+
return days === 7 ? "weekly" : `${days}d`;
|
|
772
|
+
}
|
|
773
|
+
if (windowSeconds % 3600 === 0) {
|
|
774
|
+
return `${windowSeconds / 3600}h`;
|
|
775
|
+
}
|
|
776
|
+
return `${windowSeconds}s`;
|
|
777
|
+
};
|
|
778
|
+
toWindow3 = (limit) => {
|
|
779
|
+
if (!limit) {
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
const usedPercent = limit.percentage ?? null;
|
|
783
|
+
const remainingPercent = usedPercent !== null ? Math.max(0, 100 - usedPercent) : null;
|
|
784
|
+
const resetAt = limit.nextResetTime ? normalizeTimestamp(limit.nextResetTime) : null;
|
|
785
|
+
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
|
|
786
|
+
return {
|
|
787
|
+
usedPercent,
|
|
788
|
+
remainingPercent,
|
|
789
|
+
windowSeconds: resolveWindowSeconds(limit),
|
|
790
|
+
resetAfterSeconds,
|
|
791
|
+
resetAt,
|
|
792
|
+
resetAtFormatted: resetAt ? formatResetAt(resetAt) : null,
|
|
793
|
+
resetAfterFormatted: resetAfterSeconds !== null ? formatDuration(resetAfterSeconds) : null
|
|
794
|
+
};
|
|
795
|
+
};
|
|
796
|
+
fetchZaiUsage = async (logger = noopLogger) => {
|
|
797
|
+
const apiKey = await getZaiApiKey(logger);
|
|
798
|
+
if (!apiKey) {
|
|
799
|
+
await logger.warn("No auth configured for zai-coding-plan");
|
|
800
|
+
return {
|
|
801
|
+
provider: "zai-coding-plan",
|
|
802
|
+
ok: false,
|
|
803
|
+
configured: false,
|
|
804
|
+
error: "Not configured - no API key found",
|
|
805
|
+
usage: null
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
try {
|
|
809
|
+
const response = await fetch("https://api.z.ai/api/monitor/usage/quota/limit", {
|
|
810
|
+
method: "GET",
|
|
811
|
+
headers: {
|
|
812
|
+
Authorization: `Bearer ${apiKey}`,
|
|
813
|
+
"Content-Type": "application/json"
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
if (!response.ok) {
|
|
817
|
+
await logger.error(`API error ${response.status} for zai-coding-plan`, {
|
|
818
|
+
token: maskSecret(apiKey)
|
|
819
|
+
});
|
|
820
|
+
return {
|
|
821
|
+
provider: "zai-coding-plan",
|
|
822
|
+
ok: false,
|
|
823
|
+
configured: true,
|
|
824
|
+
error: `API error: ${response.status}`,
|
|
825
|
+
usage: null
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
const payload = await response.json();
|
|
829
|
+
const limits = payload.data?.limits ?? [];
|
|
830
|
+
const tokensLimit = limits.find((limit) => limit.type === "TOKENS_LIMIT");
|
|
831
|
+
const windows = {};
|
|
832
|
+
const window = toWindow3(tokensLimit);
|
|
833
|
+
if (window) {
|
|
834
|
+
const label = resolveWindowLabel(window.windowSeconds);
|
|
835
|
+
windows[label] = window;
|
|
836
|
+
}
|
|
837
|
+
const usage = {
|
|
838
|
+
windows
|
|
839
|
+
};
|
|
840
|
+
await logger.info("zai-coding-plan usage fetched successfully");
|
|
841
|
+
return {
|
|
842
|
+
provider: "zai-coding-plan",
|
|
843
|
+
ok: true,
|
|
844
|
+
configured: true,
|
|
845
|
+
usage
|
|
846
|
+
};
|
|
847
|
+
} catch (error) {
|
|
848
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
849
|
+
await logger.error(`Request failed for zai-coding-plan: ${message}`);
|
|
850
|
+
return {
|
|
851
|
+
provider: "zai-coding-plan",
|
|
852
|
+
ok: false,
|
|
853
|
+
configured: true,
|
|
854
|
+
error: `Request failed: ${message}`,
|
|
855
|
+
usage: null
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
};
|
|
569
859
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
// src/types/provider.ts
|
|
863
|
+
var PROVIDERS;
|
|
864
|
+
var init_provider = __esm({
|
|
865
|
+
"src/types/provider.ts"() {
|
|
866
|
+
"use strict";
|
|
867
|
+
PROVIDERS = ["openai", "google", "zai-coding-plan"];
|
|
575
868
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
869
|
+
});
|
|
870
|
+
|
|
871
|
+
// src/types/dashboard.ts
|
|
872
|
+
var init_dashboard = __esm({
|
|
873
|
+
"src/types/dashboard.ts"() {
|
|
874
|
+
"use strict";
|
|
579
875
|
}
|
|
580
|
-
|
|
581
|
-
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
// src/types/index.ts
|
|
879
|
+
var init_types2 = __esm({
|
|
880
|
+
"src/types/index.ts"() {
|
|
881
|
+
"use strict";
|
|
882
|
+
init_provider();
|
|
883
|
+
init_dashboard();
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
// src/cache/fetcher.ts
|
|
888
|
+
var fetchUsage, fetchAllProviders;
|
|
889
|
+
var init_fetcher = __esm({
|
|
890
|
+
"src/cache/fetcher.ts"() {
|
|
891
|
+
"use strict";
|
|
892
|
+
init_fetch();
|
|
893
|
+
init_fetch2();
|
|
894
|
+
init_fetch3();
|
|
895
|
+
init_types2();
|
|
896
|
+
init_file();
|
|
897
|
+
init_types();
|
|
898
|
+
fetchUsage = async (provider, logger) => {
|
|
899
|
+
switch (provider) {
|
|
900
|
+
case "openai":
|
|
901
|
+
return fetchOpenaiUsage(logger);
|
|
902
|
+
case "google":
|
|
903
|
+
return fetchGoogleUsage(logger);
|
|
904
|
+
case "zai-coding-plan":
|
|
905
|
+
return fetchZaiUsage(logger);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
fetchAllProviders = async (logger) => {
|
|
909
|
+
await logger.info("Fetching usage for all providers");
|
|
910
|
+
const existingCache = await readCache(logger);
|
|
911
|
+
const results = await Promise.all(PROVIDERS.map((provider) => fetchUsage(provider, logger)));
|
|
912
|
+
const providers = {};
|
|
913
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
914
|
+
for (const result of results) {
|
|
915
|
+
const providerId = result.provider;
|
|
916
|
+
const wasConfigured = existingCache?.providers[providerId]?.configured ?? false;
|
|
917
|
+
providers[providerId] = {
|
|
918
|
+
supported: true,
|
|
919
|
+
configured: result.configured,
|
|
920
|
+
last_attempt_at: now,
|
|
921
|
+
last_success_at: result.ok ? now : null,
|
|
922
|
+
data: result.ok ? result.usage : null,
|
|
923
|
+
error: result.ok ? null : result.error ?? null
|
|
924
|
+
};
|
|
925
|
+
if (!result.configured && wasConfigured) {
|
|
926
|
+
providers[providerId].data = null;
|
|
927
|
+
await logger.debug(`Wiped data for ${providerId} (no longer configured)`);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
const cache = {
|
|
931
|
+
schema_version: SCHEMA_VERSION,
|
|
932
|
+
updated_at: now,
|
|
933
|
+
refresh_interval_seconds: REFRESH_INTERVAL_SECONDS,
|
|
934
|
+
providers
|
|
935
|
+
};
|
|
936
|
+
await writeCache(cache, logger);
|
|
937
|
+
return cache;
|
|
938
|
+
};
|
|
582
939
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
usage: null
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
|
-
try {
|
|
616
|
-
const response = await fetch("https://api.z.ai/api/monitor/usage/quota/limit", {
|
|
617
|
-
method: "GET",
|
|
618
|
-
headers: {
|
|
619
|
-
Authorization: `Bearer ${apiKey}`,
|
|
620
|
-
"Content-Type": "application/json"
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
if (!response.ok) {
|
|
624
|
-
await logger.error(`API error ${response.status} for zai-coding-plan`, {
|
|
625
|
-
token: maskSecret(apiKey)
|
|
626
|
-
});
|
|
627
|
-
return {
|
|
628
|
-
provider: "zai-coding-plan",
|
|
629
|
-
ok: false,
|
|
630
|
-
configured: true,
|
|
631
|
-
error: `API error: ${response.status}`,
|
|
632
|
-
usage: null
|
|
940
|
+
});
|
|
941
|
+
|
|
942
|
+
// src/cache/worker.ts
|
|
943
|
+
var worker_exports = {};
|
|
944
|
+
__export(worker_exports, {
|
|
945
|
+
isWorkerRunning: () => isWorkerRunning,
|
|
946
|
+
startWorker: () => startWorker,
|
|
947
|
+
stopWorker: () => stopWorker
|
|
948
|
+
});
|
|
949
|
+
var intervalId, startWorker, stopWorker, isWorkerRunning;
|
|
950
|
+
var init_worker = __esm({
|
|
951
|
+
"src/cache/worker.ts"() {
|
|
952
|
+
"use strict";
|
|
953
|
+
init_fetcher();
|
|
954
|
+
init_types();
|
|
955
|
+
intervalId = null;
|
|
956
|
+
startWorker = (logger) => {
|
|
957
|
+
if (intervalId !== null) {
|
|
958
|
+
logger.warn("Worker already started");
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
const refreshLoop = async () => {
|
|
962
|
+
try {
|
|
963
|
+
await fetchAllProviders(logger);
|
|
964
|
+
} catch (error) {
|
|
965
|
+
await logger.error("Worker refresh failed", {
|
|
966
|
+
error: error instanceof Error ? error.message : String(error)
|
|
967
|
+
});
|
|
968
|
+
}
|
|
633
969
|
};
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const tokensLimit = limits.find((limit) => limit.type === "TOKENS_LIMIT");
|
|
638
|
-
const windows = {};
|
|
639
|
-
const window = toWindow3(tokensLimit);
|
|
640
|
-
if (window) {
|
|
641
|
-
const label = resolveWindowLabel(window.windowSeconds);
|
|
642
|
-
windows[label] = window;
|
|
643
|
-
}
|
|
644
|
-
const usage = {
|
|
645
|
-
windows
|
|
970
|
+
void refreshLoop();
|
|
971
|
+
intervalId = globalThis.setInterval(refreshLoop, REFRESH_INTERVAL_SECONDS * 1e3);
|
|
972
|
+
void logger.info(`Worker started, refreshing every ${REFRESH_INTERVAL_SECONDS}s`);
|
|
646
973
|
};
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
} catch (error) {
|
|
655
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
656
|
-
await logger.error(`Request failed for zai-coding-plan: ${message}`);
|
|
657
|
-
return {
|
|
658
|
-
provider: "zai-coding-plan",
|
|
659
|
-
ok: false,
|
|
660
|
-
configured: true,
|
|
661
|
-
error: `Request failed: ${message}`,
|
|
662
|
-
usage: null
|
|
974
|
+
stopWorker = (logger) => {
|
|
975
|
+
if (intervalId === null) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
globalThis.clearInterval(intervalId);
|
|
979
|
+
intervalId = null;
|
|
980
|
+
void logger.info("Worker stopped");
|
|
663
981
|
};
|
|
982
|
+
isWorkerRunning = () => intervalId !== null;
|
|
664
983
|
}
|
|
665
|
-
};
|
|
984
|
+
});
|
|
666
985
|
|
|
667
|
-
// src/
|
|
668
|
-
|
|
986
|
+
// src/index.ts
|
|
987
|
+
init_logger();
|
|
988
|
+
import { tool } from "@opencode-ai/plugin";
|
|
669
989
|
|
|
670
990
|
// src/toast/filter.ts
|
|
671
991
|
var FLAGSHIP_PATTERNS = [
|
|
@@ -689,7 +1009,7 @@ var filterFlagshipModels = (models) => {
|
|
|
689
1009
|
return filtered;
|
|
690
1010
|
};
|
|
691
1011
|
|
|
692
|
-
// src/
|
|
1012
|
+
// src/dashboard/format.ts
|
|
693
1013
|
var getStatus = (remainingPercent) => {
|
|
694
1014
|
if (remainingPercent === null) {
|
|
695
1015
|
return { emoji: "\u26AA", text: "N/A" };
|
|
@@ -702,186 +1022,335 @@ var getStatus = (remainingPercent) => {
|
|
|
702
1022
|
}
|
|
703
1023
|
return { emoji: "\u{1F7E2}", text: "OK" };
|
|
704
1024
|
};
|
|
705
|
-
var
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const modelWindowEntries = Object.values(modelWindows.windows);
|
|
714
|
-
if (modelWindowEntries.length > 0) {
|
|
715
|
-
window = modelWindowEntries[0];
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
if (!window) {
|
|
720
|
-
return null;
|
|
1025
|
+
var formatWindowLabel = (key) => {
|
|
1026
|
+
switch (key) {
|
|
1027
|
+
case "5h":
|
|
1028
|
+
return "5h Window";
|
|
1029
|
+
case "weekly":
|
|
1030
|
+
return "Weekly Window";
|
|
1031
|
+
default:
|
|
1032
|
+
return `${key} Window`;
|
|
721
1033
|
}
|
|
722
|
-
|
|
1034
|
+
};
|
|
1035
|
+
var renderBar = (percent, width = 20) => {
|
|
1036
|
+
if (percent === null) {
|
|
1037
|
+
return `[${"\u2591".repeat(width)}]`;
|
|
1038
|
+
}
|
|
1039
|
+
const validPercent = Math.max(0, Math.min(100, percent));
|
|
1040
|
+
const filledLength = Math.round(validPercent / 100 * width);
|
|
1041
|
+
const emptyLength = width - filledLength;
|
|
1042
|
+
return `[${"\u2588".repeat(filledLength)}${"\u2591".repeat(emptyLength)}]`;
|
|
1043
|
+
};
|
|
1044
|
+
var formatWindow = (key, window) => {
|
|
723
1045
|
const remainingPercent = window.remainingPercent ?? null;
|
|
724
|
-
const resetsIn = window.resetAfterFormatted ?? "N/A";
|
|
725
1046
|
const { emoji, text } = getStatus(remainingPercent);
|
|
726
1047
|
return {
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
usedPercent,
|
|
1048
|
+
label: formatWindowLabel(key),
|
|
1049
|
+
usedPercent: window.usedPercent ?? null,
|
|
730
1050
|
remainingPercent,
|
|
731
1051
|
status: emoji,
|
|
732
1052
|
statusText: text,
|
|
733
|
-
resetsIn
|
|
1053
|
+
resetsIn: window.resetAfterFormatted ?? "N/A"
|
|
734
1054
|
};
|
|
735
1055
|
};
|
|
736
|
-
var
|
|
737
|
-
if (
|
|
738
|
-
return [];
|
|
1056
|
+
var formatDashboardData = (input) => {
|
|
1057
|
+
if (input === null) {
|
|
1058
|
+
return { providers: [] };
|
|
739
1059
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
usage = {
|
|
743
|
-
...usage,
|
|
744
|
-
models: filterFlagshipModels(usage.models)
|
|
745
|
-
};
|
|
1060
|
+
if (!("providers" in input)) {
|
|
1061
|
+
return formatDashboardDataFromResults(input);
|
|
746
1062
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1063
|
+
return formatDashboardDataFromCache(input);
|
|
1064
|
+
};
|
|
1065
|
+
var formatDashboardDataFromResults = (results) => {
|
|
1066
|
+
const providers = [];
|
|
1067
|
+
for (const result of results) {
|
|
1068
|
+
if (!result.usage) {
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
const sections = [];
|
|
1072
|
+
let usage = result.usage;
|
|
1073
|
+
if (result.provider === "google" && usage.models) {
|
|
1074
|
+
usage = {
|
|
1075
|
+
...usage,
|
|
1076
|
+
models: filterFlagshipModels(usage.models)
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
const globalWindows = Object.entries(usage.windows);
|
|
1080
|
+
if (globalWindows.length > 0) {
|
|
1081
|
+
sections.push({
|
|
1082
|
+
title: "Overall Usage",
|
|
1083
|
+
windows: globalWindows.map(([key, win]) => formatWindow(key, win))
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
if (usage.models) {
|
|
1087
|
+
const modelSections = [];
|
|
1088
|
+
for (const [modelName, modelUsage] of Object.entries(usage.models)) {
|
|
1089
|
+
const modelWindowEntries = Object.entries(modelUsage.windows);
|
|
1090
|
+
if (modelWindowEntries.length > 0) {
|
|
1091
|
+
modelSections.push({
|
|
1092
|
+
title: modelName,
|
|
1093
|
+
windows: modelWindowEntries.map(([key, win]) => formatWindow(key, win))
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
760
1096
|
}
|
|
1097
|
+
if (modelSections.length > 0) {
|
|
1098
|
+
sections.push({
|
|
1099
|
+
title: "Model Usage",
|
|
1100
|
+
windows: [],
|
|
1101
|
+
sections: modelSections
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
if (sections.length > 0) {
|
|
1106
|
+
providers.push({
|
|
1107
|
+
name: result.provider.toUpperCase().replace(/-/g, " "),
|
|
1108
|
+
sections
|
|
1109
|
+
});
|
|
761
1110
|
}
|
|
762
|
-
return rows;
|
|
763
1111
|
}
|
|
764
|
-
return
|
|
1112
|
+
return { providers };
|
|
765
1113
|
};
|
|
766
|
-
var
|
|
767
|
-
const
|
|
768
|
-
|
|
769
|
-
|
|
1114
|
+
var formatDashboardDataFromCache = (displayCache) => {
|
|
1115
|
+
const providers = [];
|
|
1116
|
+
for (const [providerId, entry] of Object.entries(displayCache.providers)) {
|
|
1117
|
+
if (!entry.data) {
|
|
1118
|
+
continue;
|
|
1119
|
+
}
|
|
1120
|
+
const sections = [];
|
|
1121
|
+
let usage = entry.data;
|
|
1122
|
+
if (providerId === "google" && usage.models) {
|
|
1123
|
+
usage = {
|
|
1124
|
+
...usage,
|
|
1125
|
+
models: filterFlagshipModels(usage.models)
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
const globalWindows = Object.entries(usage.windows);
|
|
1129
|
+
if (globalWindows.length > 0) {
|
|
1130
|
+
sections.push({
|
|
1131
|
+
title: "Overall Usage",
|
|
1132
|
+
windows: globalWindows.map(([key, win]) => formatWindow(key, win))
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
if (usage.models) {
|
|
1136
|
+
const modelSections = [];
|
|
1137
|
+
for (const [modelName, modelUsage] of Object.entries(usage.models)) {
|
|
1138
|
+
const modelWindowEntries = Object.entries(modelUsage.windows);
|
|
1139
|
+
if (modelWindowEntries.length > 0) {
|
|
1140
|
+
modelSections.push({
|
|
1141
|
+
title: modelName,
|
|
1142
|
+
windows: modelWindowEntries.map(([key, win]) => formatWindow(key, win))
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
if (modelSections.length > 0) {
|
|
1147
|
+
sections.push({
|
|
1148
|
+
title: "Model Usage",
|
|
1149
|
+
windows: [],
|
|
1150
|
+
sections: modelSections
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
if (sections.length > 0) {
|
|
1155
|
+
providers.push({
|
|
1156
|
+
name: providerId.toUpperCase().replace(/-/g, " "),
|
|
1157
|
+
sections
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
770
1160
|
}
|
|
771
|
-
return
|
|
1161
|
+
return { providers };
|
|
772
1162
|
};
|
|
773
|
-
var
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1163
|
+
var formatDashboardString = (data, updatedAt, isStale) => {
|
|
1164
|
+
if (data.providers.length === 0) {
|
|
1165
|
+
let result2 = "No usage data available";
|
|
1166
|
+
if (updatedAt) {
|
|
1167
|
+
result2 += `
|
|
1168
|
+
|
|
1169
|
+
Updated at: ${updatedAt}`;
|
|
1170
|
+
}
|
|
1171
|
+
return result2;
|
|
778
1172
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
1173
|
+
const lines = [];
|
|
1174
|
+
const HEADER_WIDTH = 65;
|
|
1175
|
+
for (const provider of data.providers) {
|
|
1176
|
+
const providerName = provider.name;
|
|
1177
|
+
const dashCount = Math.max(0, HEADER_WIDTH - providerName.length - 1);
|
|
1178
|
+
lines.push(`${providerName} ${"\u2500".repeat(dashCount)}`);
|
|
1179
|
+
for (let i = 0; i < provider.sections.length; i++) {
|
|
1180
|
+
const section = provider.sections[i];
|
|
1181
|
+
lines.push(section.title);
|
|
1182
|
+
for (let j = 0; j < section.windows.length; j++) {
|
|
1183
|
+
const window = section.windows[j];
|
|
1184
|
+
const isLastWindow = j === section.windows.length - 1;
|
|
1185
|
+
const branch = isLastWindow ? "\u2514\u2500" : "\u251C\u2500";
|
|
1186
|
+
const pipe = isLastWindow ? " " : "\u2502 ";
|
|
1187
|
+
lines.push(` ${branch} ${window.label}`);
|
|
1188
|
+
const percentStr = window.usedPercent !== null ? `${Math.round(window.usedPercent)}%` : "N/A";
|
|
1189
|
+
lines.push(
|
|
1190
|
+
` ${pipe} ${renderBar(window.usedPercent)} ${percentStr} \u2022 Resets in ${window.resetsIn}`
|
|
1191
|
+
);
|
|
1192
|
+
if (!isLastWindow) {
|
|
1193
|
+
lines.push(` ${pipe}`);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
if (section.sections) {
|
|
1197
|
+
for (let k = 0; k < section.sections.length; k++) {
|
|
1198
|
+
const subsection = section.sections[k];
|
|
1199
|
+
const isLastSubsection = k === section.sections.length - 1;
|
|
1200
|
+
const branch = isLastSubsection ? "\u2514\u2500" : "\u251C\u2500";
|
|
1201
|
+
const pipe = isLastSubsection ? " " : "\u2502 ";
|
|
1202
|
+
lines.push(` ${branch} ${subsection.title}`);
|
|
1203
|
+
for (let m = 0; m < subsection.windows.length; m++) {
|
|
1204
|
+
const window = subsection.windows[m];
|
|
1205
|
+
const isLastWindow = m === subsection.windows.length - 1;
|
|
1206
|
+
const subBranch = isLastWindow ? "\u2514\u2500" : "\u251C\u2500";
|
|
1207
|
+
lines.push(` ${pipe} ${subBranch} ${window.label}`);
|
|
1208
|
+
const percentStr = window.usedPercent !== null ? `${Math.round(window.usedPercent)}%` : "N/A";
|
|
1209
|
+
const subPipe = isLastWindow ? " " : "\u2502 ";
|
|
1210
|
+
lines.push(
|
|
1211
|
+
` ${pipe} ${subPipe} ${renderBar(window.usedPercent)} ${percentStr} \u2022 Resets in ${window.resetsIn}`
|
|
1212
|
+
);
|
|
1213
|
+
if (!isLastWindow) {
|
|
1214
|
+
lines.push(` ${pipe} ${subPipe}`);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
if (!isLastSubsection) {
|
|
1218
|
+
lines.push(` ${pipe}`);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
lines.push("");
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
let result = lines.join("\n").trim();
|
|
1226
|
+
if (updatedAt) {
|
|
1227
|
+
result += `
|
|
1228
|
+
|
|
1229
|
+
Updated at: ${updatedAt}`;
|
|
1230
|
+
}
|
|
1231
|
+
if (isStale) {
|
|
1232
|
+
result += " (STALE)";
|
|
1233
|
+
}
|
|
1234
|
+
return result;
|
|
799
1235
|
};
|
|
800
1236
|
|
|
801
1237
|
// src/toast/format.ts
|
|
802
|
-
var
|
|
1238
|
+
var getStatus2 = (remainingPercent) => {
|
|
1239
|
+
if (remainingPercent === null) return "\u26AA";
|
|
1240
|
+
if (remainingPercent < 10) return "\u{1F534}";
|
|
1241
|
+
if (remainingPercent < 30) return "\u{1F7E1}";
|
|
1242
|
+
return "\u{1F7E2}";
|
|
1243
|
+
};
|
|
1244
|
+
var formatWindowLine = (name, window, isModel = false) => {
|
|
1245
|
+
const used = window.usedPercent !== null ? Math.round(window.usedPercent) : 0;
|
|
1246
|
+
const reset = window.resetAfterFormatted ?? "N/A";
|
|
1247
|
+
const remaining = window.remainingPercent ?? null;
|
|
1248
|
+
const emoji = isModel ? "" : `${getStatus2(remaining)} `;
|
|
1249
|
+
const indent = isModel ? " " : "";
|
|
1250
|
+
return `${indent}${emoji}${name.padEnd(isModel ? 13 : 10)} ${used}% \u2022 ${reset}`;
|
|
1251
|
+
};
|
|
1252
|
+
var formatProviderSection = (provider, usage) => {
|
|
803
1253
|
if (!usage) {
|
|
804
|
-
return
|
|
1254
|
+
return [`\u26AA ${provider}: Not configured`];
|
|
805
1255
|
}
|
|
1256
|
+
const lines = [];
|
|
806
1257
|
const globalWindows = Object.values(usage.windows);
|
|
807
1258
|
if (globalWindows.length > 0) {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
return `${provider}: ${used}% used \u2022 resets in ${reset}`;
|
|
1259
|
+
lines.push(formatWindowLine(provider, globalWindows[0]));
|
|
1260
|
+
} else {
|
|
1261
|
+
lines.push(`\u26AA ${provider}: No usage data`);
|
|
812
1262
|
}
|
|
813
1263
|
if (usage.models) {
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
const used = window.usedPercent ?? 0;
|
|
819
|
-
const reset = window.resetAfterFormatted ?? "N/A";
|
|
820
|
-
return `${provider}: ${modelName} ${used}% \u2022 resets in ${reset}`;
|
|
821
|
-
}
|
|
822
|
-
if (models.length > 1) {
|
|
823
|
-
const parts = [];
|
|
824
|
-
for (const [modelName, modelData] of models) {
|
|
825
|
-
const window = Object.values(modelData.windows)[0];
|
|
826
|
-
const used = window.usedPercent ?? 0;
|
|
827
|
-
parts.push(`${modelName} ${used}%`);
|
|
1264
|
+
for (const [modelName, modelData] of Object.entries(usage.models)) {
|
|
1265
|
+
const modelWindow = Object.values(modelData.windows)[0];
|
|
1266
|
+
if (modelWindow) {
|
|
1267
|
+
lines.push(formatWindowLine(modelName, modelWindow, true));
|
|
828
1268
|
}
|
|
829
|
-
return `${provider}: ${parts.join(", ")}`;
|
|
830
1269
|
}
|
|
831
1270
|
}
|
|
832
|
-
return
|
|
1271
|
+
return lines;
|
|
833
1272
|
};
|
|
834
|
-
var formatUsageToast = async (
|
|
1273
|
+
var formatUsageToast = async (input, logger) => {
|
|
1274
|
+
if (!input) {
|
|
1275
|
+
return {
|
|
1276
|
+
title: "\u{1F4CA} Usage",
|
|
1277
|
+
message: "No providers configured",
|
|
1278
|
+
variant: "info"
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
const displayCache = "providers" in input ? input : null;
|
|
1282
|
+
const results = "providers" in input ? null : input;
|
|
835
1283
|
const lines = [];
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1284
|
+
const contentLines = [];
|
|
1285
|
+
const DIVIDER = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
|
|
1286
|
+
let updatedAt = "";
|
|
1287
|
+
let isStale = false;
|
|
1288
|
+
if (displayCache) {
|
|
1289
|
+
updatedAt = displayCache.updatedAt;
|
|
1290
|
+
isStale = displayCache.isStale;
|
|
1291
|
+
for (const [providerId, entry] of Object.entries(displayCache.providers)) {
|
|
1292
|
+
if (!entry.data) continue;
|
|
1293
|
+
let usage = entry.data;
|
|
1294
|
+
if (providerId === "google" && usage?.models) {
|
|
1295
|
+
usage = {
|
|
1296
|
+
...usage,
|
|
1297
|
+
models: filterFlagshipModels(usage.models)
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
contentLines.push(...formatProviderSection(providerId, usage));
|
|
840
1301
|
}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1302
|
+
if (Object.values(displayCache.providers).some((e) => e.error !== null)) {
|
|
1303
|
+
contentLines.push("\u26A0\uFE0F Some providers failed");
|
|
1304
|
+
}
|
|
1305
|
+
} else if (results) {
|
|
1306
|
+
const now = /* @__PURE__ */ new Date();
|
|
1307
|
+
updatedAt = `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}`;
|
|
1308
|
+
for (const result of results) {
|
|
1309
|
+
if (!result.usage) {
|
|
1310
|
+
await logger?.debug(`Provider ${result.provider} not configured, skipping`);
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1313
|
+
let usage = result.usage;
|
|
1314
|
+
if (result.provider === "google" && usage?.models) {
|
|
1315
|
+
usage = {
|
|
1316
|
+
...usage,
|
|
1317
|
+
models: filterFlagshipModels(usage.models)
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
contentLines.push(...formatProviderSection(result.provider, usage));
|
|
847
1321
|
}
|
|
848
|
-
const line = formatProviderLine(result.provider, usage);
|
|
849
|
-
lines.push(line);
|
|
850
1322
|
}
|
|
851
|
-
if (
|
|
1323
|
+
if (contentLines.length === 0) {
|
|
852
1324
|
return {
|
|
853
|
-
title: "Usage",
|
|
1325
|
+
title: "\u{1F4CA} Usage",
|
|
854
1326
|
message: "No providers configured",
|
|
855
1327
|
variant: "info"
|
|
856
1328
|
};
|
|
857
1329
|
}
|
|
1330
|
+
lines.push(DIVIDER);
|
|
1331
|
+
lines.push(...contentLines);
|
|
1332
|
+
lines.push(DIVIDER);
|
|
1333
|
+
let footer = `Updated: ${updatedAt}`;
|
|
1334
|
+
if (isStale) footer += " (stale)";
|
|
1335
|
+
lines.push(footer);
|
|
858
1336
|
return {
|
|
859
|
-
title: "Usage",
|
|
1337
|
+
title: "\u{1F4CA} Usage",
|
|
860
1338
|
message: lines.join("\n"),
|
|
861
1339
|
variant: "info"
|
|
862
1340
|
};
|
|
863
1341
|
};
|
|
864
1342
|
|
|
865
1343
|
// src/index.ts
|
|
866
|
-
var fetchUsage = async (provider, logger) => {
|
|
867
|
-
switch (provider) {
|
|
868
|
-
case "openai":
|
|
869
|
-
return fetchOpenaiUsage(logger);
|
|
870
|
-
case "google":
|
|
871
|
-
return fetchGoogleUsage(logger);
|
|
872
|
-
case "zai-coding-plan":
|
|
873
|
-
return fetchZaiUsage(logger);
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
1344
|
var UsagePlugin = async ({ client }) => {
|
|
877
1345
|
const logger = createLogger(client);
|
|
878
1346
|
const usageToastTool = tool({
|
|
879
1347
|
description: "Show subscription usage as toast for OpenAI, Google, and z.ai providers",
|
|
880
1348
|
args: {},
|
|
881
1349
|
async execute() {
|
|
882
|
-
await
|
|
883
|
-
|
|
884
|
-
const
|
|
1350
|
+
const { loadCacheForDisplay: loadCacheForDisplay2 } = await Promise.resolve().then(() => (init_reader(), reader_exports));
|
|
1351
|
+
await logger.info("Loading usage from cache");
|
|
1352
|
+
const displayCache = await loadCacheForDisplay2(logger);
|
|
1353
|
+
const toast = await formatUsageToast(displayCache, logger);
|
|
885
1354
|
await client.tui.showToast({
|
|
886
1355
|
body: {
|
|
887
1356
|
title: toast.title,
|
|
@@ -896,10 +1365,14 @@ var UsagePlugin = async ({ client }) => {
|
|
|
896
1365
|
description: "Get subscription usage data for OpenAI, Google, and z.ai providers as a formatted table",
|
|
897
1366
|
args: {},
|
|
898
1367
|
async execute() {
|
|
899
|
-
await
|
|
900
|
-
|
|
901
|
-
const
|
|
902
|
-
|
|
1368
|
+
const { loadCacheForDisplay: loadCacheForDisplay2 } = await Promise.resolve().then(() => (init_reader(), reader_exports));
|
|
1369
|
+
await logger.info("Loading usage from cache");
|
|
1370
|
+
const displayCache = await loadCacheForDisplay2(logger);
|
|
1371
|
+
if (!displayCache) {
|
|
1372
|
+
return "No cache available";
|
|
1373
|
+
}
|
|
1374
|
+
const dashboardData = formatDashboardData(displayCache);
|
|
1375
|
+
return formatDashboardString(dashboardData, displayCache.updatedAt, displayCache.isStale);
|
|
903
1376
|
}
|
|
904
1377
|
});
|
|
905
1378
|
return {
|
|
@@ -907,6 +1380,12 @@ var UsagePlugin = async ({ client }) => {
|
|
|
907
1380
|
usage_toast: usageToastTool,
|
|
908
1381
|
usage_table: usageTableTool
|
|
909
1382
|
},
|
|
1383
|
+
async event({ event }) {
|
|
1384
|
+
if (event.type === "server.connected") {
|
|
1385
|
+
const { startWorker: startWorker2 } = await Promise.resolve().then(() => (init_worker(), worker_exports));
|
|
1386
|
+
startWorker2(logger);
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
910
1389
|
async config(config) {
|
|
911
1390
|
config.command = config.command ?? {};
|
|
912
1391
|
config.command["usage-toast"] = {
|
|
@@ -920,6 +1399,22 @@ var UsagePlugin = async ({ client }) => {
|
|
|
920
1399
|
}
|
|
921
1400
|
};
|
|
922
1401
|
};
|
|
1402
|
+
var setupShutdownHandlers = async () => {
|
|
1403
|
+
const { isWorkerRunning: isWorkerRunning2, stopWorker: stopWorker2 } = await Promise.resolve().then(() => (init_worker(), worker_exports));
|
|
1404
|
+
const { createLogger: createLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
1405
|
+
const logger = createLogger2({
|
|
1406
|
+
app: { log: () => Promise.resolve(true) }
|
|
1407
|
+
});
|
|
1408
|
+
const onShutdown = async () => {
|
|
1409
|
+
if (await isWorkerRunning2()) {
|
|
1410
|
+
stopWorker2(logger);
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
process.on("SIGINT", onShutdown);
|
|
1414
|
+
process.on("SIGTERM", onShutdown);
|
|
1415
|
+
process.on("exit", onShutdown);
|
|
1416
|
+
};
|
|
1417
|
+
void setupShutdownHandlers();
|
|
923
1418
|
var index_default = UsagePlugin;
|
|
924
1419
|
export {
|
|
925
1420
|
UsagePlugin,
|