opencode-plugin-auto-update 0.3.0 → 0.3.1
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 +92 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { appendFile, readFile as
|
|
2
|
+
import { appendFile, readFile as readFile4 } from "fs/promises";
|
|
3
3
|
import { join as join3 } from "path";
|
|
4
4
|
import { homedir as homedir3 } from "os";
|
|
5
5
|
|
|
@@ -126,6 +126,22 @@ async function getHostname() {
|
|
|
126
126
|
|
|
127
127
|
// src/update.ts
|
|
128
128
|
var DEFAULT_CONFIG_DIR2 = join2(homedir2(), ".config", "opencode");
|
|
129
|
+
function normalizePluginConfig(config) {
|
|
130
|
+
const existingPlugin = Array.isArray(config.plugin) ? [...config.plugin] : [];
|
|
131
|
+
const existingPlugins = Array.isArray(config.plugins) ? [...config.plugins] : [];
|
|
132
|
+
if (existingPlugins.length === 0) {
|
|
133
|
+
return { config, changed: false };
|
|
134
|
+
}
|
|
135
|
+
const merged = [];
|
|
136
|
+
for (const entry of [...existingPlugin, ...existingPlugins]) {
|
|
137
|
+
if (!merged.includes(entry)) {
|
|
138
|
+
merged.push(entry);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
config.plugin = merged;
|
|
142
|
+
delete config.plugins;
|
|
143
|
+
return { config, changed: true };
|
|
144
|
+
}
|
|
129
145
|
async function runAutoUpdate(options = {}) {
|
|
130
146
|
const disabled = options.disabled ?? envFlag("OPENCODE_AUTO_UPDATE_DISABLED");
|
|
131
147
|
if (disabled) {
|
|
@@ -133,7 +149,7 @@ async function runAutoUpdate(options = {}) {
|
|
|
133
149
|
}
|
|
134
150
|
const debug = options.debug ?? envFlag("OPENCODE_AUTO_UPDATE_DEBUG");
|
|
135
151
|
const ignoreThrottle = options.ignoreThrottle ?? envFlag("OPENCODE_AUTO_UPDATE_BYPASS_THROTTLE");
|
|
136
|
-
const intervalHours = options.intervalHours ?? envNumber("OPENCODE_AUTO_UPDATE_INTERVAL_HOURS",
|
|
152
|
+
const intervalHours = options.intervalHours ?? envNumber("OPENCODE_AUTO_UPDATE_INTERVAL_HOURS", 0);
|
|
137
153
|
const preservePinned = options.preservePinned ?? envFlag("OPENCODE_AUTO_UPDATE_PINNED");
|
|
138
154
|
const configDir = options.configDir ?? DEFAULT_CONFIG_DIR2;
|
|
139
155
|
const configPath = join2(configDir, "opencode.json");
|
|
@@ -159,15 +175,24 @@ async function runAutoUpdate(options = {}) {
|
|
|
159
175
|
try {
|
|
160
176
|
const state = await readThrottleState({ configDir });
|
|
161
177
|
const now = Date.now();
|
|
162
|
-
const intervalMs =
|
|
178
|
+
const intervalMs = intervalHours * 60 * 60 * 1e3;
|
|
163
179
|
if (!ignoreThrottle && state.lastRun && now - state.lastRun < intervalMs) {
|
|
164
180
|
log("[auto-update] Throttled, skipping update.");
|
|
165
181
|
return;
|
|
166
182
|
}
|
|
167
183
|
await writeThrottleState({ ...state, lastRun: now }, { debug, configDir });
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
184
|
+
const rawConfig = await readConfig(configPath);
|
|
185
|
+
if (!rawConfig) {
|
|
186
|
+
log("[auto-update] No config found, skipping.");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const normalized = normalizePluginConfig(rawConfig);
|
|
190
|
+
if (normalized.changed) {
|
|
191
|
+
await writeConfig(configPath, normalized.config);
|
|
192
|
+
log("[auto-update] Migrated config.plugins -> config.plugin");
|
|
193
|
+
}
|
|
194
|
+
const { plugins } = getPluginList(normalized.config);
|
|
195
|
+
if (!plugins || plugins.length === 0) {
|
|
171
196
|
log("[auto-update] No plugins found to update.");
|
|
172
197
|
return;
|
|
173
198
|
}
|
|
@@ -187,7 +212,11 @@ async function runAutoUpdate(options = {}) {
|
|
|
187
212
|
error
|
|
188
213
|
});
|
|
189
214
|
if (updateResult.changed) {
|
|
190
|
-
const updatedConfig = {
|
|
215
|
+
const updatedConfig = {
|
|
216
|
+
...normalized.config,
|
|
217
|
+
plugin: updateResult.plugins
|
|
218
|
+
};
|
|
219
|
+
delete updatedConfig.plugins;
|
|
191
220
|
await writeConfig(configPath, updatedConfig);
|
|
192
221
|
}
|
|
193
222
|
const hasOcx = await commandExists("ocx");
|
|
@@ -231,16 +260,10 @@ async function writeConfig(configPath, config) {
|
|
|
231
260
|
`, "utf-8");
|
|
232
261
|
}
|
|
233
262
|
function getPluginList(config) {
|
|
234
|
-
if (!config) {
|
|
235
|
-
return { plugins: null, key: null };
|
|
236
|
-
}
|
|
237
263
|
if (Array.isArray(config.plugin)) {
|
|
238
|
-
return { plugins: config.plugin
|
|
239
|
-
}
|
|
240
|
-
if (Array.isArray(config.plugins)) {
|
|
241
|
-
return { plugins: config.plugins, key: "plugins" };
|
|
264
|
+
return { plugins: config.plugin };
|
|
242
265
|
}
|
|
243
|
-
return { plugins: null
|
|
266
|
+
return { plugins: null };
|
|
244
267
|
}
|
|
245
268
|
async function updatePlugins(options) {
|
|
246
269
|
const { plugins, configDir, preservePinned, useBun, log, error } = options;
|
|
@@ -407,8 +430,47 @@ function formatLogMessage(args) {
|
|
|
407
430
|
}).join(" ");
|
|
408
431
|
}
|
|
409
432
|
|
|
433
|
+
// src/utils/circular-log.ts
|
|
434
|
+
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
435
|
+
var MAX_ENTRIES = 5;
|
|
436
|
+
async function readCircularLog(logPath) {
|
|
437
|
+
try {
|
|
438
|
+
const contents = await readFile3(logPath, "utf-8");
|
|
439
|
+
return JSON.parse(contents);
|
|
440
|
+
} catch {
|
|
441
|
+
return { entries: [] };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async function appendCircularLog(logPath, entry) {
|
|
445
|
+
const log = await readCircularLog(logPath);
|
|
446
|
+
log.entries.push(entry);
|
|
447
|
+
if (log.entries.length > MAX_ENTRIES) {
|
|
448
|
+
log.entries = log.entries.slice(-MAX_ENTRIES);
|
|
449
|
+
}
|
|
450
|
+
await writeFile3(logPath, JSON.stringify(log, null, 2) + "\n", "utf-8");
|
|
451
|
+
}
|
|
452
|
+
function formatLogEntry(plugins, errors, duration, success) {
|
|
453
|
+
return {
|
|
454
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
455
|
+
pluginsUpdated: plugins,
|
|
456
|
+
errors: errors.slice(0, 10),
|
|
457
|
+
duration,
|
|
458
|
+
success
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
410
462
|
// src/index.ts
|
|
411
463
|
var CONFIG_PATH = join3(homedir3(), ".config", "opencode", "opencode-plugin-auto-update.json");
|
|
464
|
+
function extractUpdatedPlugins(logEntries) {
|
|
465
|
+
const plugins = [];
|
|
466
|
+
for (const entry of logEntries) {
|
|
467
|
+
const match = entry.match(/Updated\s+(.+?)\s+from\s+v[\d.]+\s+to\s+v[\d.]+/i);
|
|
468
|
+
if (match && match[1]) {
|
|
469
|
+
plugins.push(match[1]);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return plugins;
|
|
473
|
+
}
|
|
412
474
|
var DEBUG_FILE = "/tmp/opencode-auto-update-debug.log";
|
|
413
475
|
var DEBUG_ENABLED = false;
|
|
414
476
|
async function src_default(ctx) {
|
|
@@ -440,6 +502,7 @@ async function src_default(ctx) {
|
|
|
440
502
|
await writeDebug("toast shown");
|
|
441
503
|
}
|
|
442
504
|
};
|
|
505
|
+
const CIRCULAR_LOG_PATH = join3(ctx.directory, "..", ".auto-update-history.json");
|
|
443
506
|
const startUpdate = () => {
|
|
444
507
|
if (updateStarted) {
|
|
445
508
|
return;
|
|
@@ -448,18 +511,31 @@ async function src_default(ctx) {
|
|
|
448
511
|
void writeDebug(`startUpdate invoked (ignoreThrottle=${shouldIgnoreThrottle()})`);
|
|
449
512
|
const logEntries = [];
|
|
450
513
|
const errorEntries = [];
|
|
514
|
+
const startTime = Date.now();
|
|
451
515
|
runAutoUpdate({
|
|
452
516
|
debug: configDebug,
|
|
453
517
|
ignoreThrottle: shouldIgnoreThrottle(),
|
|
454
518
|
onLog: (message) => logEntries.push(message),
|
|
455
519
|
onError: (message) => errorEntries.push(message)
|
|
456
520
|
}).then(() => {
|
|
521
|
+
const duration = Date.now() - startTime;
|
|
522
|
+
const success = errorEntries.length === 0;
|
|
523
|
+
const pluginsUpdated = extractUpdatedPlugins(logEntries);
|
|
524
|
+
void appendCircularLog(
|
|
525
|
+
CIRCULAR_LOG_PATH,
|
|
526
|
+
formatLogEntry(pluginsUpdated, errorEntries, duration, success)
|
|
527
|
+
);
|
|
457
528
|
updateMessage = formatUpdateMessage(logEntries, errorEntries);
|
|
458
529
|
void writeDebug(`update finished (logs=${logEntries.length}, errors=${errorEntries.length})`);
|
|
459
530
|
notifyUser(updateMessage).catch((error) => {
|
|
460
531
|
void writeDebug(`notifyUser error: ${String(error)}`);
|
|
461
532
|
});
|
|
462
533
|
}).catch((error) => {
|
|
534
|
+
const duration = Date.now() - startTime;
|
|
535
|
+
void appendCircularLog(
|
|
536
|
+
CIRCULAR_LOG_PATH,
|
|
537
|
+
formatLogEntry([], [String(error)], duration, false)
|
|
538
|
+
);
|
|
463
539
|
void writeDebug(`runAutoUpdate error: ${String(error)}`);
|
|
464
540
|
});
|
|
465
541
|
};
|
|
@@ -506,7 +582,7 @@ async function writeDebug(message) {
|
|
|
506
582
|
}
|
|
507
583
|
async function readLocalConfig() {
|
|
508
584
|
try {
|
|
509
|
-
const raw = await
|
|
585
|
+
const raw = await readFile4(CONFIG_PATH, "utf-8");
|
|
510
586
|
const parsed = JSON.parse(raw);
|
|
511
587
|
return parsed ?? {};
|
|
512
588
|
} catch {
|