opencode-aicodewith-auth 0.1.4 → 0.1.8
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 +121 -54
- package/dist/lib/hooks/auto-update/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -59,7 +59,7 @@ function createAicodewith(options = {}) {
|
|
|
59
59
|
var aicodewith = createAicodewith();
|
|
60
60
|
|
|
61
61
|
// index.ts
|
|
62
|
-
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
62
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, access } from "fs/promises";
|
|
63
63
|
import path4 from "path";
|
|
64
64
|
import os3 from "os";
|
|
65
65
|
|
|
@@ -1307,8 +1307,10 @@ function invalidatePackage(packageName = PACKAGE_NAME) {
|
|
|
1307
1307
|
}
|
|
1308
1308
|
|
|
1309
1309
|
// lib/hooks/auto-update/index.ts
|
|
1310
|
+
var DISPLAY_NAME = "AICodewith";
|
|
1311
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1310
1312
|
function createAutoUpdateHook(ctx, options = {}) {
|
|
1311
|
-
const { autoUpdate = true } = options;
|
|
1313
|
+
const { autoUpdate = true, showStartupToast = true } = options;
|
|
1312
1314
|
let hasChecked = false;
|
|
1313
1315
|
return {
|
|
1314
1316
|
event: async ({ event }) => {
|
|
@@ -1320,17 +1322,43 @@ function createAutoUpdateHook(ctx, options = {}) {
|
|
|
1320
1322
|
if (props?.info?.parentID)
|
|
1321
1323
|
return;
|
|
1322
1324
|
hasChecked = true;
|
|
1325
|
+
const cachedVersion = getCachedVersion();
|
|
1323
1326
|
const localDevVersion = getLocalDevVersion(ctx.directory);
|
|
1327
|
+
const displayVersion = localDevVersion ?? cachedVersion ?? "unknown";
|
|
1324
1328
|
if (localDevVersion) {
|
|
1329
|
+
if (showStartupToast) {
|
|
1330
|
+
showStartupToastWithSpinner(ctx, `${displayVersion} (dev)`, "Local development mode").catch(() => {});
|
|
1331
|
+
}
|
|
1325
1332
|
log("Local development mode, skipping update check");
|
|
1326
1333
|
return;
|
|
1327
1334
|
}
|
|
1335
|
+
if (showStartupToast) {
|
|
1336
|
+
showStartupToastWithSpinner(ctx, displayVersion, "GPT-5.2 \xB7 Claude \xB7 Gemini").catch(() => {});
|
|
1337
|
+
}
|
|
1328
1338
|
runBackgroundUpdateCheck(ctx, autoUpdate).catch((err) => {
|
|
1329
1339
|
log("Background update check failed:", err);
|
|
1330
1340
|
});
|
|
1331
1341
|
}
|
|
1332
1342
|
};
|
|
1333
1343
|
}
|
|
1344
|
+
async function showStartupToastWithSpinner(ctx, version, message) {
|
|
1345
|
+
const totalDuration = 3000;
|
|
1346
|
+
const frameInterval = 100;
|
|
1347
|
+
const totalFrames = Math.floor(totalDuration / frameInterval);
|
|
1348
|
+
for (let i = 0;i < totalFrames; i++) {
|
|
1349
|
+
const spinner = SPINNER_FRAMES[i % SPINNER_FRAMES.length];
|
|
1350
|
+
await ctx.client.tui.showToast({
|
|
1351
|
+
body: {
|
|
1352
|
+
title: `${spinner} ${DISPLAY_NAME} v${version}`,
|
|
1353
|
+
message,
|
|
1354
|
+
variant: "info",
|
|
1355
|
+
duration: frameInterval + 50
|
|
1356
|
+
}
|
|
1357
|
+
}).catch(() => {});
|
|
1358
|
+
await new Promise((resolve) => setTimeout(resolve, frameInterval));
|
|
1359
|
+
}
|
|
1360
|
+
log(`Startup toast shown: v${version}`);
|
|
1361
|
+
}
|
|
1334
1362
|
async function runBackgroundUpdateCheck(ctx, autoUpdate) {
|
|
1335
1363
|
const pluginInfo = findPluginEntry(ctx.directory);
|
|
1336
1364
|
if (!pluginInfo) {
|
|
@@ -1402,7 +1430,7 @@ async function runBunInstallSafe() {
|
|
|
1402
1430
|
async function showUpdateAvailableToast(ctx, currentVersion, latestVersion) {
|
|
1403
1431
|
await ctx.client.tui.showToast({
|
|
1404
1432
|
body: {
|
|
1405
|
-
title: `${
|
|
1433
|
+
title: `${DISPLAY_NAME} Update Available`,
|
|
1406
1434
|
message: `v${currentVersion} \u2192 v${latestVersion}
|
|
1407
1435
|
Restart OpenCode to apply.`,
|
|
1408
1436
|
variant: "info",
|
|
@@ -1414,7 +1442,7 @@ Restart OpenCode to apply.`,
|
|
|
1414
1442
|
async function showAutoUpdatedToast(ctx, oldVersion, newVersion) {
|
|
1415
1443
|
await ctx.client.tui.showToast({
|
|
1416
1444
|
body: {
|
|
1417
|
-
title: `${
|
|
1445
|
+
title: `${DISPLAY_NAME} Updated!`,
|
|
1418
1446
|
message: `v${oldVersion} \u2192 v${newVersion}
|
|
1419
1447
|
Restart OpenCode to apply.`,
|
|
1420
1448
|
variant: "success",
|
|
@@ -1423,46 +1451,91 @@ Restart OpenCode to apply.`,
|
|
|
1423
1451
|
}).catch(() => {});
|
|
1424
1452
|
log(`Auto-updated toast shown: v${oldVersion} \u2192 v${newVersion}`);
|
|
1425
1453
|
}
|
|
1454
|
+
// lib/provider-config.json
|
|
1455
|
+
var provider_config_default = {
|
|
1456
|
+
name: "AICodewith",
|
|
1457
|
+
env: ["AICODEWITH_API_KEY"],
|
|
1458
|
+
api: "https://api.openai.com/v1",
|
|
1459
|
+
models: {
|
|
1460
|
+
"gpt-5.2-codex": {
|
|
1461
|
+
name: "GPT-5.2 Codex",
|
|
1462
|
+
modalities: { input: ["text", "image"], output: ["text"] }
|
|
1463
|
+
},
|
|
1464
|
+
"gpt-5.2": {
|
|
1465
|
+
name: "GPT-5.2",
|
|
1466
|
+
modalities: { input: ["text", "image"], output: ["text"] }
|
|
1467
|
+
},
|
|
1468
|
+
"claude-sonnet-4-5-20250929": {
|
|
1469
|
+
name: "Claude Sonnet 4.5",
|
|
1470
|
+
modalities: { input: ["text", "image"], output: ["text"] }
|
|
1471
|
+
},
|
|
1472
|
+
"claude-opus-4-5-20251101": {
|
|
1473
|
+
name: "Claude Opus 4.5",
|
|
1474
|
+
modalities: { input: ["text", "image"], output: ["text"] }
|
|
1475
|
+
},
|
|
1476
|
+
"gemini-3-pro-high": {
|
|
1477
|
+
name: "Gemini 3 Pro",
|
|
1478
|
+
modalities: { input: ["text", "image"], output: ["text"] }
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1426
1482
|
|
|
1427
1483
|
// index.ts
|
|
1428
1484
|
var CODEX_MODEL_PREFIXES = ["gpt-", "codex"];
|
|
1429
1485
|
var PACKAGE_NAME2 = "opencode-aicodewith-auth";
|
|
1430
|
-
var PROVIDER_NAME = "AICodewith";
|
|
1431
1486
|
var PLUGIN_ENTRY = import.meta.url;
|
|
1432
1487
|
var PROVIDER_EXT = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
|
|
1433
1488
|
var PROVIDER_NPM = new URL(`./provider${PROVIDER_EXT}`, import.meta.url).href;
|
|
1434
|
-
var DEFAULT_API = "https://api.openai.com/v1";
|
|
1435
|
-
var DEFAULT_ENV = ["AICODEWITH_API_KEY"];
|
|
1436
1489
|
var DEFAULT_OUTPUT_TOKEN_MAX = 32000;
|
|
1437
|
-
var IMAGE_MODALITIES = { input: ["text", "image"], output: ["text"] };
|
|
1438
|
-
var MODEL_CONFIGS = {
|
|
1439
|
-
"gpt-5.2-codex": { name: "GPT-5.2 Codex", modalities: IMAGE_MODALITIES },
|
|
1440
|
-
"gpt-5.2": { name: "GPT-5.2", modalities: IMAGE_MODALITIES },
|
|
1441
|
-
"claude-sonnet-4-5-20250929": { name: "Claude Sonnet 4.5", modalities: IMAGE_MODALITIES },
|
|
1442
|
-
"claude-opus-4-5-20251101": { name: "Claude Opus 4.5", modalities: IMAGE_MODALITIES },
|
|
1443
|
-
"gemini-3-pro-high": { name: "Gemini 3 Pro", modalities: IMAGE_MODALITIES }
|
|
1444
|
-
};
|
|
1445
|
-
var ALLOWED_MODEL_IDS = Object.keys(MODEL_CONFIGS);
|
|
1446
|
-
var ALLOWED_MODEL_SET = new Set(ALLOWED_MODEL_IDS);
|
|
1447
1490
|
var homeDir = process.env.OPENCODE_TEST_HOME || os3.homedir();
|
|
1448
1491
|
var configRoot = process.env.XDG_CONFIG_HOME || path4.join(homeDir, ".config");
|
|
1449
1492
|
var configDir = path4.join(configRoot, "opencode");
|
|
1450
|
-
var
|
|
1493
|
+
var configPathJson = path4.join(configDir, "opencode.json");
|
|
1494
|
+
var configPathJsonc = path4.join(configDir, "opencode.jsonc");
|
|
1451
1495
|
var ensureConfigPromise;
|
|
1452
|
-
var
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1496
|
+
var fileExists = async (filePath) => {
|
|
1497
|
+
try {
|
|
1498
|
+
await access(filePath);
|
|
1499
|
+
return true;
|
|
1500
|
+
} catch {
|
|
1501
|
+
return false;
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
var stripJsonComments2 = (content) => {
|
|
1505
|
+
return content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m).replace(/,(\s*[}\]])/g, "$1");
|
|
1506
|
+
};
|
|
1507
|
+
var readJsonOrJsonc = async (filePath) => {
|
|
1459
1508
|
try {
|
|
1460
1509
|
const text = await readFile2(filePath, "utf-8");
|
|
1461
|
-
|
|
1510
|
+
const stripped = filePath.endsWith(".jsonc") ? stripJsonComments2(text) : text;
|
|
1511
|
+
return JSON.parse(stripped);
|
|
1462
1512
|
} catch {
|
|
1463
1513
|
return;
|
|
1464
1514
|
}
|
|
1465
1515
|
};
|
|
1516
|
+
var deepEqual = (a, b) => {
|
|
1517
|
+
if (a === b)
|
|
1518
|
+
return true;
|
|
1519
|
+
if (typeof a !== typeof b)
|
|
1520
|
+
return false;
|
|
1521
|
+
if (a === null || b === null)
|
|
1522
|
+
return a === b;
|
|
1523
|
+
if (typeof a !== "object")
|
|
1524
|
+
return false;
|
|
1525
|
+
const aObj = a;
|
|
1526
|
+
const bObj = b;
|
|
1527
|
+
const aKeys = Object.keys(aObj);
|
|
1528
|
+
const bKeys = Object.keys(bObj);
|
|
1529
|
+
if (aKeys.length !== bKeys.length)
|
|
1530
|
+
return false;
|
|
1531
|
+
for (const key of aKeys) {
|
|
1532
|
+
if (!Object.prototype.hasOwnProperty.call(bObj, key))
|
|
1533
|
+
return false;
|
|
1534
|
+
if (!deepEqual(aObj[key], bObj[key]))
|
|
1535
|
+
return false;
|
|
1536
|
+
}
|
|
1537
|
+
return true;
|
|
1538
|
+
};
|
|
1466
1539
|
var isPackageEntry = (value) => value === PACKAGE_NAME2 || value.startsWith(`${PACKAGE_NAME2}@`);
|
|
1467
1540
|
var ensurePluginEntry = (list) => {
|
|
1468
1541
|
if (!Array.isArray(list))
|
|
@@ -1470,36 +1543,17 @@ var ensurePluginEntry = (list) => {
|
|
|
1470
1543
|
const hasPlugin = list.some((entry) => typeof entry === "string" && (entry === PLUGIN_ENTRY || isPackageEntry(entry)));
|
|
1471
1544
|
return hasPlugin ? list : [...list, PLUGIN_ENTRY];
|
|
1472
1545
|
};
|
|
1546
|
+
var buildStandardProviderConfig = () => ({
|
|
1547
|
+
...provider_config_default,
|
|
1548
|
+
npm: PROVIDER_NPM
|
|
1549
|
+
});
|
|
1473
1550
|
var applyProviderConfig = (config) => {
|
|
1474
1551
|
let changed = false;
|
|
1475
1552
|
const providerMap = config.provider && typeof config.provider === "object" ? config.provider : {};
|
|
1476
|
-
const
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
next.name = PROVIDER_NAME;
|
|
1481
|
-
changed = true;
|
|
1482
|
-
}
|
|
1483
|
-
if (!Array.isArray(next.env)) {
|
|
1484
|
-
next.env = DEFAULT_ENV;
|
|
1485
|
-
changed = true;
|
|
1486
|
-
}
|
|
1487
|
-
if (!next.npm || typeof next.npm === "string" && isPackageEntry(next.npm)) {
|
|
1488
|
-
next.npm = PROVIDER_NPM;
|
|
1489
|
-
changed = true;
|
|
1490
|
-
}
|
|
1491
|
-
if (!next.api) {
|
|
1492
|
-
next.api = DEFAULT_API;
|
|
1493
|
-
changed = true;
|
|
1494
|
-
}
|
|
1495
|
-
const hasExtraModels = Object.keys(existingModels).some((id) => !ALLOWED_MODEL_SET.has(id));
|
|
1496
|
-
const hasMissingModels = ALLOWED_MODEL_IDS.some((id) => !Object.prototype.hasOwnProperty.call(existingModels, id));
|
|
1497
|
-
if (!next.models || hasExtraModels || hasMissingModels) {
|
|
1498
|
-
next.models = toModelMap(ALLOWED_MODEL_IDS, existingModels);
|
|
1499
|
-
changed = true;
|
|
1500
|
-
}
|
|
1501
|
-
providerMap[PROVIDER_ID] = next;
|
|
1502
|
-
if (config.provider !== providerMap) {
|
|
1553
|
+
const existingProvider = providerMap[PROVIDER_ID];
|
|
1554
|
+
const standardProvider = buildStandardProviderConfig();
|
|
1555
|
+
if (!deepEqual(existingProvider, standardProvider)) {
|
|
1556
|
+
providerMap[PROVIDER_ID] = standardProvider;
|
|
1503
1557
|
config.provider = providerMap;
|
|
1504
1558
|
changed = true;
|
|
1505
1559
|
}
|
|
@@ -1514,7 +1568,20 @@ var ensureConfigFile = async () => {
|
|
|
1514
1568
|
if (ensureConfigPromise)
|
|
1515
1569
|
return ensureConfigPromise;
|
|
1516
1570
|
ensureConfigPromise = (async () => {
|
|
1517
|
-
const
|
|
1571
|
+
const jsoncExists = await fileExists(configPathJsonc);
|
|
1572
|
+
const jsonExists = await fileExists(configPathJson);
|
|
1573
|
+
let configPath;
|
|
1574
|
+
let config;
|
|
1575
|
+
if (jsoncExists) {
|
|
1576
|
+
configPath = configPathJsonc;
|
|
1577
|
+
config = await readJsonOrJsonc(configPath) ?? {};
|
|
1578
|
+
} else if (jsonExists) {
|
|
1579
|
+
configPath = configPathJson;
|
|
1580
|
+
config = await readJsonOrJsonc(configPath) ?? {};
|
|
1581
|
+
} else {
|
|
1582
|
+
configPath = configPathJson;
|
|
1583
|
+
config = { $schema: "https://opencode.ai/config.json" };
|
|
1584
|
+
}
|
|
1518
1585
|
if (!config || typeof config !== "object")
|
|
1519
1586
|
return;
|
|
1520
1587
|
const changed = applyProviderConfig(config);
|
package/package.json
CHANGED