@magpie-community/opencode-qoder-auth 0.2.9 → 0.2.11
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/README.md +8 -3
- package/index.mjs +38 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -200,9 +200,14 @@ in-flight read and caching it in memory for an hour. The same identity
|
|
|
200
200
|
goes on the list, the claim and a device-token retry; it is not saved in
|
|
201
201
|
the account's credentials.
|
|
202
202
|
|
|
203
|
-
- Install Qoder desktop or
|
|
204
|
-
available. The plugin finds the desktop's
|
|
205
|
-
|
|
203
|
+
- Install Qoder desktop, or sign in to Qoder CLI once, to make its native
|
|
204
|
+
runtime available. The plugin finds the desktop's `resources/umid`
|
|
205
|
+
(`Qoder.app` on macOS, `%LOCALAPPDATA%\Programs\Qoder` on Windows,
|
|
206
|
+
`/opt/Qoder` on Linux) or the runtime the CLI caches in `~/.qoder/.bin`
|
|
207
|
+
(`runtime-info-<platform>-<arch>-*` on macOS and Linux,
|
|
208
|
+
`umid-win32-x64-*\runtime-info.exe` on Windows; `QODER_CONFIG_DIR`,
|
|
209
|
+
`QODER_CLI_HOME` and `QODER_CONFIG_DIR_NAME` move it as they move the
|
|
210
|
+
CLI's folder).
|
|
206
211
|
- For another installation location, set `QODER_RUNTIME_INFO` to the
|
|
207
212
|
absolute path of Qoder's installed `runtime-info` executable
|
|
208
213
|
(`runtime-info.exe` on Windows), with its accompanying SDK files.
|
package/index.mjs
CHANGED
|
@@ -1037,23 +1037,45 @@ const CAMPAIGN_MACHINE_TTL = 60 * 60 * 1000 // Qoder's desktop client renews its
|
|
|
1037
1037
|
// campaignRuntime uses Qoder's own native device identity helper, installed
|
|
1038
1038
|
// by its desktop client or cached by its CLI. A made-up token (including the
|
|
1039
1039
|
// chat envelope's machine id and type 5) doesn't reveal international claims.
|
|
1040
|
-
|
|
1040
|
+
//
|
|
1041
|
+
// Where each one keeps it (Qoder desktop 0.4.3's packages, qodercli 1.1.66):
|
|
1042
|
+
// - desktop: <install>/resources/umid/runtime-info(.exe): Qoder.app on
|
|
1043
|
+
// macOS, %LOCALAPPDATA%\Programs\Qoder (the user installer) on Windows,
|
|
1044
|
+
// /opt/Qoder (the .deb and the .rpm) on Linux;
|
|
1045
|
+
// - CLI: <config>/.bin, where <config> is QODER_CONFIG_DIR, else
|
|
1046
|
+
// QODER_CLI_HOME (or the home folder) joined with QODER_CONFIG_DIR_NAME
|
|
1047
|
+
// (or .qoder): a file runtime-info-<platform>-<arch>-<hash> on macOS and
|
|
1048
|
+
// Linux, a folder umid-win32-<arch>-<hash> holding runtime-info.exe on
|
|
1049
|
+
// Windows.
|
|
1050
|
+
async function campaignRuntime({ home = homedir(), platform = process.platform, arch = process.arch, env = process.env, opt = "/opt" } = {}) {
|
|
1041
1051
|
if (env.QODER_RUNTIME_INFO) return resolve(env.QODER_RUNTIME_INFO)
|
|
1042
1052
|
const name = platform === "win32" ? "runtime-info.exe" : "runtime-info"
|
|
1053
|
+
const isFile = async (path) => (await stat(path).catch(() => null))?.isFile() ?? false
|
|
1043
1054
|
const paths = []
|
|
1044
1055
|
if (platform === "win32") {
|
|
1045
1056
|
const local = env.LOCALAPPDATA || join(home, "AppData", "Local")
|
|
1046
1057
|
paths.push(join(local, "Programs", "Qoder", "resources", "umid", name))
|
|
1047
1058
|
} else if (platform === "darwin") {
|
|
1048
1059
|
for (const dir of ["/Applications", join(home, "Applications")]) paths.push(join(dir, "Qoder.app", "Contents", "Resources", "umid", name))
|
|
1060
|
+
} else if (platform === "linux") {
|
|
1061
|
+
paths.push(join(opt, "Qoder", "resources", "umid", name))
|
|
1062
|
+
}
|
|
1063
|
+
for (const path of paths) if (await isFile(path)) return path
|
|
1064
|
+
const config = env.QODER_CONFIG_DIR || join(env.QODER_CLI_HOME || env.GEMINI_CLI_HOME || home, env.QODER_CONFIG_DIR_NAME || ".qoder")
|
|
1065
|
+
const cache = join(config, ".bin")
|
|
1066
|
+
const entries = await readdir(cache, { withFileTypes: true }).catch(() => [])
|
|
1067
|
+
const found = []
|
|
1068
|
+
for (const d of entries) {
|
|
1069
|
+
let path
|
|
1070
|
+
if (platform === "win32") {
|
|
1071
|
+
if (d.isDirectory() && d.name.startsWith(`umid-win32-${arch}-`)) path = join(cache, d.name, name)
|
|
1072
|
+
} else if (d.isFile() && d.name.startsWith(`runtime-info-${platform}-${arch}-`) && !d.name.endsWith(".tmp")) {
|
|
1073
|
+
path = join(cache, d.name)
|
|
1074
|
+
}
|
|
1075
|
+
if (path && (await isFile(path))) found.push({ path, time: (await stat(path)).mtimeMs })
|
|
1049
1076
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
const dirs = (await readdir(cache, { withFileTypes: true }).catch(() => []))
|
|
1053
|
-
.filter((d) => d.isDirectory() && d.name.startsWith(`umid-${platform}-${arch}-`))
|
|
1054
|
-
const cached = await Promise.all(dirs.map(async (d) => ({ path: join(cache, d.name, name), time: (await stat(join(cache, d.name))).mtimeMs })))
|
|
1055
|
-
for (const { path } of cached.sort((a, b) => b.time - a.time)) if ((await stat(path).catch(() => null))?.isFile()) return path
|
|
1056
|
-
throw new Error("Qoder check-in: device identity runtime not found; install Qoder desktop or run Qoder CLI, or set QODER_RUNTIME_INFO to its runtime-info executable")
|
|
1077
|
+
if (found.length) return found.sort((a, b) => b.time - a.time)[0].path
|
|
1078
|
+
throw new Error("Qoder check-in: device identity runtime not found; install Qoder desktop or sign in to Qoder CLI once, or set QODER_RUNTIME_INFO to its runtime-info executable")
|
|
1057
1079
|
}
|
|
1058
1080
|
|
|
1059
1081
|
// Read the SDK identity as Qoder does: environment 3 is international; on
|
|
@@ -1292,6 +1314,9 @@ const makePlugin = (site) => async ({ client }) => {
|
|
|
1292
1314
|
}
|
|
1293
1315
|
// each account's listing, the model configs a request carries
|
|
1294
1316
|
const listings = new Map()
|
|
1317
|
+
// A public and a VPC account can name the same uid but have different
|
|
1318
|
+
// catalogs. Keep each deployment's listing apart.
|
|
1319
|
+
const listingKey = (cred) => `${cred.vpc ?? ""}\0${cred.uid}`
|
|
1295
1320
|
// the accounts fresh renewed: the built-in took the lapse mark off on a
|
|
1296
1321
|
// renewed job token (qoderPersist), whatever the request then met
|
|
1297
1322
|
const renewals = new WeakSet()
|
|
@@ -1300,7 +1325,7 @@ const makePlugin = (site) => async ({ client }) => {
|
|
|
1300
1325
|
// says "renewed" for it
|
|
1301
1326
|
const unsaid = new Set()
|
|
1302
1327
|
const renewed = (cred) => {
|
|
1303
|
-
const was = unsaid.delete(cred
|
|
1328
|
+
const was = unsaid.delete(listingKey(cred))
|
|
1304
1329
|
return renewals.has(cred) || was
|
|
1305
1330
|
}
|
|
1306
1331
|
|
|
@@ -1321,10 +1346,11 @@ const makePlugin = (site) => async ({ client }) => {
|
|
|
1321
1346
|
})
|
|
1322
1347
|
|
|
1323
1348
|
const models = async (cred, again = false) => {
|
|
1324
|
-
|
|
1349
|
+
const key = listingKey(cred)
|
|
1350
|
+
let l = listings.get(key)
|
|
1325
1351
|
if (!l || again) {
|
|
1326
1352
|
l = modelInfos(await fetchListing(siteOf(site, cred), cred))
|
|
1327
|
-
listings.set(
|
|
1353
|
+
listings.set(key, l)
|
|
1328
1354
|
}
|
|
1329
1355
|
return l
|
|
1330
1356
|
}
|
|
@@ -1537,7 +1563,7 @@ const makePlugin = (site) => async ({ client }) => {
|
|
|
1537
1563
|
if (e?.expired) throw Object.assign(new Error(e.message), { signIn: "expired" })
|
|
1538
1564
|
return provider.models
|
|
1539
1565
|
}
|
|
1540
|
-
if (renewals.has(cred)) unsaid.add(cred
|
|
1566
|
+
if (renewals.has(cred)) unsaid.add(listingKey(cred))
|
|
1541
1567
|
try {
|
|
1542
1568
|
const ms = await models(cred, true)
|
|
1543
1569
|
if (!ms.length) return provider.models
|
package/package.json
CHANGED