opencode-aicodewith-auth 0.1.3 → 0.1.4
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 +447 -14
- package/dist/lib/hooks/auto-update/cache.d.ts +1 -0
- package/dist/lib/hooks/auto-update/checker.d.ts +10 -0
- package/dist/lib/hooks/auto-update/constants.d.ts +15 -0
- package/dist/lib/hooks/auto-update/index.d.ts +12 -0
- package/dist/lib/hooks/auto-update/types.d.ts +29 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -60,8 +60,8 @@ var aicodewith = createAicodewith();
|
|
|
60
60
|
|
|
61
61
|
// index.ts
|
|
62
62
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
63
|
-
import
|
|
64
|
-
import
|
|
63
|
+
import path4 from "path";
|
|
64
|
+
import os3 from "os";
|
|
65
65
|
|
|
66
66
|
// lib/constants.ts
|
|
67
67
|
var PLUGIN_NAME = "opencode-aicodewith-auth";
|
|
@@ -993,9 +993,440 @@ async function handleSuccessResponse(response, isStreaming) {
|
|
|
993
993
|
});
|
|
994
994
|
}
|
|
995
995
|
|
|
996
|
+
// lib/hooks/auto-update/index.ts
|
|
997
|
+
import { spawn } from "child_process";
|
|
998
|
+
|
|
999
|
+
// lib/hooks/auto-update/checker.ts
|
|
1000
|
+
import * as fs2 from "fs";
|
|
1001
|
+
import * as path2 from "path";
|
|
1002
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1003
|
+
|
|
1004
|
+
// lib/hooks/auto-update/constants.ts
|
|
1005
|
+
import * as path from "path";
|
|
1006
|
+
import * as os from "os";
|
|
1007
|
+
import * as fs from "fs";
|
|
1008
|
+
var PACKAGE_NAME = "opencode-aicodewith-auth";
|
|
1009
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
|
|
1010
|
+
var NPM_FETCH_TIMEOUT = 5000;
|
|
1011
|
+
function getCacheDir() {
|
|
1012
|
+
if (process.platform === "win32") {
|
|
1013
|
+
return path.join(process.env.LOCALAPPDATA ?? os.homedir(), "opencode");
|
|
1014
|
+
}
|
|
1015
|
+
return path.join(os.homedir(), ".cache", "opencode");
|
|
1016
|
+
}
|
|
1017
|
+
var CACHE_DIR3 = getCacheDir();
|
|
1018
|
+
var INSTALLED_PACKAGE_JSON = path.join(CACHE_DIR3, "node_modules", PACKAGE_NAME, "package.json");
|
|
1019
|
+
function getUserConfigDir() {
|
|
1020
|
+
if (process.platform === "win32") {
|
|
1021
|
+
const crossPlatformDir = path.join(os.homedir(), ".config");
|
|
1022
|
+
const appdataDir = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
|
1023
|
+
const crossPlatformConfig = path.join(crossPlatformDir, "opencode", "opencode.json");
|
|
1024
|
+
const crossPlatformConfigJsonc = path.join(crossPlatformDir, "opencode", "opencode.jsonc");
|
|
1025
|
+
if (fs.existsSync(crossPlatformConfig) || fs.existsSync(crossPlatformConfigJsonc)) {
|
|
1026
|
+
return crossPlatformDir;
|
|
1027
|
+
}
|
|
1028
|
+
return appdataDir;
|
|
1029
|
+
}
|
|
1030
|
+
return process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config");
|
|
1031
|
+
}
|
|
1032
|
+
function getWindowsAppdataDir() {
|
|
1033
|
+
if (process.platform !== "win32")
|
|
1034
|
+
return null;
|
|
1035
|
+
return process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
|
1036
|
+
}
|
|
1037
|
+
var USER_CONFIG_DIR = getUserConfigDir();
|
|
1038
|
+
var USER_OPENCODE_CONFIG = path.join(USER_CONFIG_DIR, "opencode", "opencode.json");
|
|
1039
|
+
var USER_OPENCODE_CONFIG_JSONC = path.join(USER_CONFIG_DIR, "opencode", "opencode.jsonc");
|
|
1040
|
+
|
|
1041
|
+
// lib/hooks/auto-update/checker.ts
|
|
1042
|
+
import * as os2 from "os";
|
|
1043
|
+
var LOG_PREFIX = `[${PACKAGE_NAME}:auto-update]`;
|
|
1044
|
+
function log(...args) {
|
|
1045
|
+
if (process.env.DEBUG?.includes(PACKAGE_NAME) || process.env.DEBUG?.includes("auto-update")) {
|
|
1046
|
+
console.log(LOG_PREFIX, ...args);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
function stripJsonComments(json) {
|
|
1050
|
+
return json.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m).replace(/,(\s*[}\]])/g, "$1");
|
|
1051
|
+
}
|
|
1052
|
+
function getConfigPaths(directory) {
|
|
1053
|
+
const paths = [
|
|
1054
|
+
path2.join(directory, ".opencode", "opencode.json"),
|
|
1055
|
+
path2.join(directory, ".opencode", "opencode.jsonc"),
|
|
1056
|
+
USER_OPENCODE_CONFIG,
|
|
1057
|
+
USER_OPENCODE_CONFIG_JSONC
|
|
1058
|
+
];
|
|
1059
|
+
if (process.platform === "win32") {
|
|
1060
|
+
const crossPlatformDir = path2.join(os2.homedir(), ".config");
|
|
1061
|
+
const appdataDir = getWindowsAppdataDir();
|
|
1062
|
+
if (appdataDir) {
|
|
1063
|
+
const alternateDir = USER_CONFIG_DIR === crossPlatformDir ? appdataDir : crossPlatformDir;
|
|
1064
|
+
const alternateConfig = path2.join(alternateDir, "opencode", "opencode.json");
|
|
1065
|
+
const alternateConfigJsonc = path2.join(alternateDir, "opencode", "opencode.jsonc");
|
|
1066
|
+
if (!paths.includes(alternateConfig)) {
|
|
1067
|
+
paths.push(alternateConfig);
|
|
1068
|
+
}
|
|
1069
|
+
if (!paths.includes(alternateConfigJsonc)) {
|
|
1070
|
+
paths.push(alternateConfigJsonc);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
return paths;
|
|
1075
|
+
}
|
|
1076
|
+
function getLocalDevPath(directory) {
|
|
1077
|
+
for (const configPath of getConfigPaths(directory)) {
|
|
1078
|
+
try {
|
|
1079
|
+
if (!fs2.existsSync(configPath))
|
|
1080
|
+
continue;
|
|
1081
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
1082
|
+
const config = JSON.parse(stripJsonComments(content));
|
|
1083
|
+
const plugins = config.plugin ?? [];
|
|
1084
|
+
for (const entry of plugins) {
|
|
1085
|
+
if (entry.startsWith("file://") && entry.includes(PACKAGE_NAME)) {
|
|
1086
|
+
try {
|
|
1087
|
+
return fileURLToPath2(entry);
|
|
1088
|
+
} catch {
|
|
1089
|
+
return entry.replace("file://", "");
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
} catch {
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
return null;
|
|
1098
|
+
}
|
|
1099
|
+
function findPackageJsonUp(startPath) {
|
|
1100
|
+
try {
|
|
1101
|
+
const stat = fs2.statSync(startPath);
|
|
1102
|
+
let dir = stat.isDirectory() ? startPath : path2.dirname(startPath);
|
|
1103
|
+
for (let i = 0;i < 10; i++) {
|
|
1104
|
+
const pkgPath = path2.join(dir, "package.json");
|
|
1105
|
+
if (fs2.existsSync(pkgPath)) {
|
|
1106
|
+
try {
|
|
1107
|
+
const content = fs2.readFileSync(pkgPath, "utf-8");
|
|
1108
|
+
const pkg = JSON.parse(content);
|
|
1109
|
+
if (pkg.name === PACKAGE_NAME)
|
|
1110
|
+
return pkgPath;
|
|
1111
|
+
} catch {}
|
|
1112
|
+
}
|
|
1113
|
+
const parent = path2.dirname(dir);
|
|
1114
|
+
if (parent === dir)
|
|
1115
|
+
break;
|
|
1116
|
+
dir = parent;
|
|
1117
|
+
}
|
|
1118
|
+
} catch {}
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
function getLocalDevVersion(directory) {
|
|
1122
|
+
const localPath = getLocalDevPath(directory);
|
|
1123
|
+
if (!localPath)
|
|
1124
|
+
return null;
|
|
1125
|
+
try {
|
|
1126
|
+
const pkgPath = findPackageJsonUp(localPath);
|
|
1127
|
+
if (!pkgPath)
|
|
1128
|
+
return null;
|
|
1129
|
+
const content = fs2.readFileSync(pkgPath, "utf-8");
|
|
1130
|
+
const pkg = JSON.parse(content);
|
|
1131
|
+
return pkg.version ?? null;
|
|
1132
|
+
} catch {
|
|
1133
|
+
return null;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
function findPluginEntry(directory) {
|
|
1137
|
+
for (const configPath of getConfigPaths(directory)) {
|
|
1138
|
+
try {
|
|
1139
|
+
if (!fs2.existsSync(configPath))
|
|
1140
|
+
continue;
|
|
1141
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
1142
|
+
const config = JSON.parse(stripJsonComments(content));
|
|
1143
|
+
const plugins = config.plugin ?? [];
|
|
1144
|
+
for (const entry of plugins) {
|
|
1145
|
+
if (entry === PACKAGE_NAME) {
|
|
1146
|
+
return { entry, isPinned: false, pinnedVersion: null, configPath };
|
|
1147
|
+
}
|
|
1148
|
+
if (entry.startsWith(`${PACKAGE_NAME}@`)) {
|
|
1149
|
+
const pinnedVersion = entry.slice(PACKAGE_NAME.length + 1);
|
|
1150
|
+
const isPinned = pinnedVersion !== "latest";
|
|
1151
|
+
return { entry, isPinned, pinnedVersion: isPinned ? pinnedVersion : null, configPath };
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
} catch {
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
return null;
|
|
1159
|
+
}
|
|
1160
|
+
function getCachedVersion() {
|
|
1161
|
+
try {
|
|
1162
|
+
if (fs2.existsSync(INSTALLED_PACKAGE_JSON)) {
|
|
1163
|
+
const content = fs2.readFileSync(INSTALLED_PACKAGE_JSON, "utf-8");
|
|
1164
|
+
const pkg = JSON.parse(content);
|
|
1165
|
+
if (pkg.version)
|
|
1166
|
+
return pkg.version;
|
|
1167
|
+
}
|
|
1168
|
+
} catch {}
|
|
1169
|
+
try {
|
|
1170
|
+
const currentDir = path2.dirname(fileURLToPath2(import.meta.url));
|
|
1171
|
+
const pkgPath = findPackageJsonUp(currentDir);
|
|
1172
|
+
if (pkgPath) {
|
|
1173
|
+
const content = fs2.readFileSync(pkgPath, "utf-8");
|
|
1174
|
+
const pkg = JSON.parse(content);
|
|
1175
|
+
if (pkg.version)
|
|
1176
|
+
return pkg.version;
|
|
1177
|
+
}
|
|
1178
|
+
} catch (err) {
|
|
1179
|
+
log("Failed to resolve version from current directory:", err);
|
|
1180
|
+
}
|
|
1181
|
+
return null;
|
|
1182
|
+
}
|
|
1183
|
+
function updatePinnedVersion(configPath, oldEntry, newVersion) {
|
|
1184
|
+
try {
|
|
1185
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
1186
|
+
const newEntry = `${PACKAGE_NAME}@${newVersion}`;
|
|
1187
|
+
const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
|
|
1188
|
+
if (!pluginMatch || pluginMatch.index === undefined) {
|
|
1189
|
+
log(`No "plugin" array found in ${configPath}`);
|
|
1190
|
+
return false;
|
|
1191
|
+
}
|
|
1192
|
+
const startIdx = pluginMatch.index + pluginMatch[0].length;
|
|
1193
|
+
let bracketCount = 1;
|
|
1194
|
+
let endIdx = startIdx;
|
|
1195
|
+
for (let i = startIdx;i < content.length && bracketCount > 0; i++) {
|
|
1196
|
+
if (content[i] === "[")
|
|
1197
|
+
bracketCount++;
|
|
1198
|
+
else if (content[i] === "]")
|
|
1199
|
+
bracketCount--;
|
|
1200
|
+
endIdx = i;
|
|
1201
|
+
}
|
|
1202
|
+
const before = content.slice(0, startIdx);
|
|
1203
|
+
const pluginArrayContent = content.slice(startIdx, endIdx);
|
|
1204
|
+
const after = content.slice(endIdx);
|
|
1205
|
+
const escapedOldEntry = oldEntry.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1206
|
+
const regex = new RegExp(`["']${escapedOldEntry}["']`);
|
|
1207
|
+
if (!regex.test(pluginArrayContent)) {
|
|
1208
|
+
log(`Entry "${oldEntry}" not found in plugin array of ${configPath}`);
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
const updatedPluginArray = pluginArrayContent.replace(regex, `"${newEntry}"`);
|
|
1212
|
+
const updatedContent = before + updatedPluginArray + after;
|
|
1213
|
+
if (updatedContent === content) {
|
|
1214
|
+
log(`No changes made to ${configPath}`);
|
|
1215
|
+
return false;
|
|
1216
|
+
}
|
|
1217
|
+
fs2.writeFileSync(configPath, updatedContent, "utf-8");
|
|
1218
|
+
log(`Updated ${configPath}: ${oldEntry} \u2192 ${newEntry}`);
|
|
1219
|
+
return true;
|
|
1220
|
+
} catch (err) {
|
|
1221
|
+
log(`Failed to update config file ${configPath}:`, err);
|
|
1222
|
+
return false;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
async function getLatestVersion() {
|
|
1226
|
+
const controller = new AbortController;
|
|
1227
|
+
const timeoutId = setTimeout(() => controller.abort(), NPM_FETCH_TIMEOUT);
|
|
1228
|
+
try {
|
|
1229
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
1230
|
+
signal: controller.signal,
|
|
1231
|
+
headers: { Accept: "application/json" }
|
|
1232
|
+
});
|
|
1233
|
+
if (!response.ok)
|
|
1234
|
+
return null;
|
|
1235
|
+
const data = await response.json();
|
|
1236
|
+
return data.latest ?? null;
|
|
1237
|
+
} catch {
|
|
1238
|
+
return null;
|
|
1239
|
+
} finally {
|
|
1240
|
+
clearTimeout(timeoutId);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// lib/hooks/auto-update/cache.ts
|
|
1245
|
+
import * as fs3 from "fs";
|
|
1246
|
+
import * as path3 from "path";
|
|
1247
|
+
function stripTrailingCommas(json) {
|
|
1248
|
+
return json.replace(/,(\s*[}\]])/g, "$1");
|
|
1249
|
+
}
|
|
1250
|
+
function removeFromBunLock(packageName) {
|
|
1251
|
+
const lockPath = path3.join(CACHE_DIR3, "bun.lock");
|
|
1252
|
+
if (!fs3.existsSync(lockPath))
|
|
1253
|
+
return false;
|
|
1254
|
+
try {
|
|
1255
|
+
const content = fs3.readFileSync(lockPath, "utf-8");
|
|
1256
|
+
const lock = JSON.parse(stripTrailingCommas(content));
|
|
1257
|
+
let modified = false;
|
|
1258
|
+
if (lock.workspaces?.[""]?.dependencies?.[packageName]) {
|
|
1259
|
+
delete lock.workspaces[""].dependencies[packageName];
|
|
1260
|
+
modified = true;
|
|
1261
|
+
}
|
|
1262
|
+
if (lock.packages?.[packageName]) {
|
|
1263
|
+
delete lock.packages[packageName];
|
|
1264
|
+
modified = true;
|
|
1265
|
+
}
|
|
1266
|
+
if (modified) {
|
|
1267
|
+
fs3.writeFileSync(lockPath, JSON.stringify(lock, null, 2));
|
|
1268
|
+
log(`Removed from bun.lock: ${packageName}`);
|
|
1269
|
+
}
|
|
1270
|
+
return modified;
|
|
1271
|
+
} catch {
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
function invalidatePackage(packageName = PACKAGE_NAME) {
|
|
1276
|
+
try {
|
|
1277
|
+
const pkgDir = path3.join(CACHE_DIR3, "node_modules", packageName);
|
|
1278
|
+
const pkgJsonPath = path3.join(CACHE_DIR3, "package.json");
|
|
1279
|
+
let packageRemoved = false;
|
|
1280
|
+
let dependencyRemoved = false;
|
|
1281
|
+
let lockRemoved = false;
|
|
1282
|
+
if (fs3.existsSync(pkgDir)) {
|
|
1283
|
+
fs3.rmSync(pkgDir, { recursive: true, force: true });
|
|
1284
|
+
log(`Package removed: ${pkgDir}`);
|
|
1285
|
+
packageRemoved = true;
|
|
1286
|
+
}
|
|
1287
|
+
if (fs3.existsSync(pkgJsonPath)) {
|
|
1288
|
+
const content = fs3.readFileSync(pkgJsonPath, "utf-8");
|
|
1289
|
+
const pkgJson = JSON.parse(content);
|
|
1290
|
+
if (pkgJson.dependencies?.[packageName]) {
|
|
1291
|
+
delete pkgJson.dependencies[packageName];
|
|
1292
|
+
fs3.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
|
|
1293
|
+
log(`Dependency removed from package.json: ${packageName}`);
|
|
1294
|
+
dependencyRemoved = true;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
lockRemoved = removeFromBunLock(packageName);
|
|
1298
|
+
if (!packageRemoved && !dependencyRemoved && !lockRemoved) {
|
|
1299
|
+
log(`Package not found, nothing to invalidate: ${packageName}`);
|
|
1300
|
+
return false;
|
|
1301
|
+
}
|
|
1302
|
+
return true;
|
|
1303
|
+
} catch (err) {
|
|
1304
|
+
log("Failed to invalidate package:", err);
|
|
1305
|
+
return false;
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// lib/hooks/auto-update/index.ts
|
|
1310
|
+
function createAutoUpdateHook(ctx, options = {}) {
|
|
1311
|
+
const { autoUpdate = true } = options;
|
|
1312
|
+
let hasChecked = false;
|
|
1313
|
+
return {
|
|
1314
|
+
event: async ({ event }) => {
|
|
1315
|
+
if (event.type !== "session.created")
|
|
1316
|
+
return;
|
|
1317
|
+
if (hasChecked)
|
|
1318
|
+
return;
|
|
1319
|
+
const props = event.properties;
|
|
1320
|
+
if (props?.info?.parentID)
|
|
1321
|
+
return;
|
|
1322
|
+
hasChecked = true;
|
|
1323
|
+
const localDevVersion = getLocalDevVersion(ctx.directory);
|
|
1324
|
+
if (localDevVersion) {
|
|
1325
|
+
log("Local development mode, skipping update check");
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
runBackgroundUpdateCheck(ctx, autoUpdate).catch((err) => {
|
|
1329
|
+
log("Background update check failed:", err);
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
async function runBackgroundUpdateCheck(ctx, autoUpdate) {
|
|
1335
|
+
const pluginInfo = findPluginEntry(ctx.directory);
|
|
1336
|
+
if (!pluginInfo) {
|
|
1337
|
+
log("Plugin not found in config");
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
const cachedVersion = getCachedVersion();
|
|
1341
|
+
const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
|
|
1342
|
+
if (!currentVersion) {
|
|
1343
|
+
log("No version found (cached or pinned)");
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
const latestVersion = await getLatestVersion();
|
|
1347
|
+
if (!latestVersion) {
|
|
1348
|
+
log("Failed to fetch latest version");
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (currentVersion === latestVersion) {
|
|
1352
|
+
log("Already on latest version");
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
log(`Update available: ${currentVersion} \u2192 ${latestVersion}`);
|
|
1356
|
+
if (!autoUpdate) {
|
|
1357
|
+
await showUpdateAvailableToast(ctx, currentVersion, latestVersion);
|
|
1358
|
+
log("Auto-update disabled, notification only");
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
if (pluginInfo.isPinned) {
|
|
1362
|
+
const updated = updatePinnedVersion(pluginInfo.configPath, pluginInfo.entry, latestVersion);
|
|
1363
|
+
if (!updated) {
|
|
1364
|
+
await showUpdateAvailableToast(ctx, currentVersion, latestVersion);
|
|
1365
|
+
log("Failed to update pinned version in config");
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
log(`Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME}@${latestVersion}`);
|
|
1369
|
+
}
|
|
1370
|
+
invalidatePackage(PACKAGE_NAME);
|
|
1371
|
+
const installSuccess = await runBunInstallSafe();
|
|
1372
|
+
if (installSuccess) {
|
|
1373
|
+
await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
|
|
1374
|
+
log(`Update installed: ${currentVersion} \u2192 ${latestVersion}`);
|
|
1375
|
+
} else {
|
|
1376
|
+
await showUpdateAvailableToast(ctx, currentVersion, latestVersion);
|
|
1377
|
+
log("bun install failed; update not installed (falling back to notification-only)");
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
async function runBunInstallSafe() {
|
|
1381
|
+
return new Promise((resolve) => {
|
|
1382
|
+
try {
|
|
1383
|
+
const child = spawn("bun", ["install"], {
|
|
1384
|
+
cwd: CACHE_DIR3,
|
|
1385
|
+
stdio: "ignore",
|
|
1386
|
+
detached: true
|
|
1387
|
+
});
|
|
1388
|
+
child.unref();
|
|
1389
|
+
child.on("close", (code) => {
|
|
1390
|
+
resolve(code === 0);
|
|
1391
|
+
});
|
|
1392
|
+
child.on("error", () => {
|
|
1393
|
+
resolve(false);
|
|
1394
|
+
});
|
|
1395
|
+
setTimeout(() => resolve(false), 30000);
|
|
1396
|
+
} catch (err) {
|
|
1397
|
+
log("bun install error:", err);
|
|
1398
|
+
resolve(false);
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
async function showUpdateAvailableToast(ctx, currentVersion, latestVersion) {
|
|
1403
|
+
await ctx.client.tui.showToast({
|
|
1404
|
+
body: {
|
|
1405
|
+
title: `${PACKAGE_NAME} Update Available`,
|
|
1406
|
+
message: `v${currentVersion} \u2192 v${latestVersion}
|
|
1407
|
+
Restart OpenCode to apply.`,
|
|
1408
|
+
variant: "info",
|
|
1409
|
+
duration: 8000
|
|
1410
|
+
}
|
|
1411
|
+
}).catch(() => {});
|
|
1412
|
+
log(`Update available toast shown: v${latestVersion}`);
|
|
1413
|
+
}
|
|
1414
|
+
async function showAutoUpdatedToast(ctx, oldVersion, newVersion) {
|
|
1415
|
+
await ctx.client.tui.showToast({
|
|
1416
|
+
body: {
|
|
1417
|
+
title: `${PACKAGE_NAME} Updated!`,
|
|
1418
|
+
message: `v${oldVersion} \u2192 v${newVersion}
|
|
1419
|
+
Restart OpenCode to apply.`,
|
|
1420
|
+
variant: "success",
|
|
1421
|
+
duration: 8000
|
|
1422
|
+
}
|
|
1423
|
+
}).catch(() => {});
|
|
1424
|
+
log(`Auto-updated toast shown: v${oldVersion} \u2192 v${newVersion}`);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
996
1427
|
// index.ts
|
|
997
1428
|
var CODEX_MODEL_PREFIXES = ["gpt-", "codex"];
|
|
998
|
-
var
|
|
1429
|
+
var PACKAGE_NAME2 = "opencode-aicodewith-auth";
|
|
999
1430
|
var PROVIDER_NAME = "AICodewith";
|
|
1000
1431
|
var PLUGIN_ENTRY = import.meta.url;
|
|
1001
1432
|
var PROVIDER_EXT = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
|
|
@@ -1013,10 +1444,10 @@ var MODEL_CONFIGS = {
|
|
|
1013
1444
|
};
|
|
1014
1445
|
var ALLOWED_MODEL_IDS = Object.keys(MODEL_CONFIGS);
|
|
1015
1446
|
var ALLOWED_MODEL_SET = new Set(ALLOWED_MODEL_IDS);
|
|
1016
|
-
var homeDir = process.env.OPENCODE_TEST_HOME ||
|
|
1017
|
-
var configRoot = process.env.XDG_CONFIG_HOME ||
|
|
1018
|
-
var configDir =
|
|
1019
|
-
var configPath =
|
|
1447
|
+
var homeDir = process.env.OPENCODE_TEST_HOME || os3.homedir();
|
|
1448
|
+
var configRoot = process.env.XDG_CONFIG_HOME || path4.join(homeDir, ".config");
|
|
1449
|
+
var configDir = path4.join(configRoot, "opencode");
|
|
1450
|
+
var configPath = path4.join(configDir, "opencode.json");
|
|
1020
1451
|
var ensureConfigPromise;
|
|
1021
1452
|
var toModelMap = (ids, existing = {}) => ids.reduce((acc, id) => {
|
|
1022
1453
|
const existingConfig = Object.prototype.hasOwnProperty.call(existing, id) ? existing[id] : {};
|
|
@@ -1032,7 +1463,7 @@ var readJson = async (filePath) => {
|
|
|
1032
1463
|
return;
|
|
1033
1464
|
}
|
|
1034
1465
|
};
|
|
1035
|
-
var isPackageEntry = (value) => value ===
|
|
1466
|
+
var isPackageEntry = (value) => value === PACKAGE_NAME2 || value.startsWith(`${PACKAGE_NAME2}@`);
|
|
1036
1467
|
var ensurePluginEntry = (list) => {
|
|
1037
1468
|
if (!Array.isArray(list))
|
|
1038
1469
|
return [PLUGIN_ENTRY];
|
|
@@ -1146,14 +1577,14 @@ var ensureGeminiSseParam = (url) => {
|
|
|
1146
1577
|
};
|
|
1147
1578
|
var buildGeminiUrl = (originalUrl, streaming) => {
|
|
1148
1579
|
const original = new URL(originalUrl);
|
|
1149
|
-
let
|
|
1150
|
-
if (!
|
|
1151
|
-
|
|
1580
|
+
let path5 = original.pathname;
|
|
1581
|
+
if (!path5.includes("/v1beta/") && !path5.includes("/v1/")) {
|
|
1582
|
+
path5 = `/v1beta${path5.startsWith("/") ? "" : "/"}${path5}`;
|
|
1152
1583
|
}
|
|
1153
1584
|
const base = new URL(AICODEWITH_GEMINI_BASE_URL);
|
|
1154
1585
|
const basePath = base.pathname.replace(/\/$/, "");
|
|
1155
1586
|
const target = new URL(base.origin);
|
|
1156
|
-
target.pathname = `${basePath}${
|
|
1587
|
+
target.pathname = `${basePath}${path5}`;
|
|
1157
1588
|
target.search = original.search;
|
|
1158
1589
|
const url = target.toString();
|
|
1159
1590
|
return streaming ? ensureGeminiSseParam(url) : url;
|
|
@@ -1188,10 +1619,11 @@ var getOutputTokenLimit = (input, output) => {
|
|
|
1188
1619
|
}
|
|
1189
1620
|
return DEFAULT_OUTPUT_TOKEN_MAX;
|
|
1190
1621
|
};
|
|
1191
|
-
var AicodewithCodexAuthPlugin = async (
|
|
1622
|
+
var AicodewithCodexAuthPlugin = async (ctx) => {
|
|
1192
1623
|
await ensureConfigFile().catch((error) => {
|
|
1193
|
-
console.warn(`[${
|
|
1624
|
+
console.warn(`[${PACKAGE_NAME2}] Failed to update opencode config: ${error instanceof Error ? error.message : error}`);
|
|
1194
1625
|
});
|
|
1626
|
+
const autoUpdateHook = createAutoUpdateHook(ctx, { autoUpdate: true });
|
|
1195
1627
|
const authHook = {
|
|
1196
1628
|
provider: PROVIDER_ID,
|
|
1197
1629
|
loader: async (getAuth, _provider) => {
|
|
@@ -1267,6 +1699,7 @@ var AicodewithCodexAuthPlugin = async (_ctx) => {
|
|
|
1267
1699
|
config: async (config) => {
|
|
1268
1700
|
applyProviderConfig(config);
|
|
1269
1701
|
},
|
|
1702
|
+
event: autoUpdateHook.event,
|
|
1270
1703
|
"chat.params": async (input, output) => {
|
|
1271
1704
|
if (input.model.providerID !== PROVIDER_ID)
|
|
1272
1705
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function invalidatePackage(packageName?: string): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PluginEntryInfo } from "./types";
|
|
2
|
+
declare function log(...args: unknown[]): void;
|
|
3
|
+
export declare function isLocalDevMode(directory: string): boolean;
|
|
4
|
+
export declare function getLocalDevPath(directory: string): string | null;
|
|
5
|
+
export declare function getLocalDevVersion(directory: string): string | null;
|
|
6
|
+
export declare function findPluginEntry(directory: string): PluginEntryInfo | null;
|
|
7
|
+
export declare function getCachedVersion(): string | null;
|
|
8
|
+
export declare function updatePinnedVersion(configPath: string, oldEntry: string, newVersion: string): boolean;
|
|
9
|
+
export declare function getLatestVersion(): Promise<string | null>;
|
|
10
|
+
export { log };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file constants.ts
|
|
3
|
+
* @input None
|
|
4
|
+
* @output Auto-update configuration constants
|
|
5
|
+
* @pos Constants for package paths, npm registry, cache directories
|
|
6
|
+
*/
|
|
7
|
+
export declare const PACKAGE_NAME = "opencode-aicodewith-auth";
|
|
8
|
+
export declare const NPM_REGISTRY_URL = "https://registry.npmjs.org/-/package/opencode-aicodewith-auth/dist-tags";
|
|
9
|
+
export declare const NPM_FETCH_TIMEOUT = 5000;
|
|
10
|
+
export declare const CACHE_DIR: string;
|
|
11
|
+
export declare const INSTALLED_PACKAGE_JSON: string;
|
|
12
|
+
export declare function getWindowsAppdataDir(): string | null;
|
|
13
|
+
export declare const USER_CONFIG_DIR: string;
|
|
14
|
+
export declare const USER_OPENCODE_CONFIG: string;
|
|
15
|
+
export declare const USER_OPENCODE_CONFIG_JSONC: string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PluginInput } from "@opencode-ai/plugin";
|
|
2
|
+
import type { AutoUpdateOptions } from "./types";
|
|
3
|
+
export declare function createAutoUpdateHook(ctx: PluginInput, options?: AutoUpdateOptions): {
|
|
4
|
+
event: ({ event }: {
|
|
5
|
+
event: {
|
|
6
|
+
type: string;
|
|
7
|
+
properties?: unknown;
|
|
8
|
+
};
|
|
9
|
+
}) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
export type { AutoUpdateOptions } from "./types";
|
|
12
|
+
export { invalidatePackage } from "./cache";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface NpmDistTags {
|
|
2
|
+
latest: string;
|
|
3
|
+
[key: string]: string;
|
|
4
|
+
}
|
|
5
|
+
export interface OpencodeConfig {
|
|
6
|
+
plugin?: string[];
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface PackageJson {
|
|
10
|
+
version: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface UpdateCheckResult {
|
|
15
|
+
needsUpdate: boolean;
|
|
16
|
+
currentVersion: string | null;
|
|
17
|
+
latestVersion: string | null;
|
|
18
|
+
isLocalDev: boolean;
|
|
19
|
+
isPinned: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface AutoUpdateOptions {
|
|
22
|
+
autoUpdate?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface PluginEntryInfo {
|
|
25
|
+
entry: string;
|
|
26
|
+
isPinned: boolean;
|
|
27
|
+
pinnedVersion: string | null;
|
|
28
|
+
configPath: string;
|
|
29
|
+
}
|
package/package.json
CHANGED