@telepat/ideon 0.1.5 → 0.1.6
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/ideon.js +107 -15
- package/package.json +1 -1
package/dist/ideon.js
CHANGED
|
@@ -56,6 +56,7 @@ var appSettingsSchema = z.object({
|
|
|
56
56
|
var envSettingsSchema = z.object({
|
|
57
57
|
openRouterApiKey: z.string().optional(),
|
|
58
58
|
replicateApiToken: z.string().optional(),
|
|
59
|
+
disableKeytar: z.boolean().optional(),
|
|
59
60
|
model: z.string().optional(),
|
|
60
61
|
temperature: z.number().min(0).max(2).optional(),
|
|
61
62
|
maxTokens: z.number().int().positive().optional(),
|
|
@@ -100,6 +101,7 @@ function readEnvSettings(env = process.env) {
|
|
|
100
101
|
return envSettingsSchema.parse({
|
|
101
102
|
openRouterApiKey: env.IDEON_OPENROUTER_API_KEY,
|
|
102
103
|
replicateApiToken: env.IDEON_REPLICATE_API_TOKEN,
|
|
104
|
+
disableKeytar: parseBoolean(env.IDEON_DISABLE_KEYTAR),
|
|
103
105
|
model: env.IDEON_MODEL,
|
|
104
106
|
temperature: parseNumber(env.IDEON_TEMPERATURE),
|
|
105
107
|
maxTokens: parseNumber(env.IDEON_MAX_TOKENS),
|
|
@@ -1200,17 +1202,80 @@ import keytar from "keytar";
|
|
|
1200
1202
|
var SERVICE_NAME = "ideon";
|
|
1201
1203
|
var OPENROUTER_ACCOUNT = "openrouter-api-key";
|
|
1202
1204
|
var REPLICATE_ACCOUNT = "replicate-api-token";
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1205
|
+
var KEYTAR_UNAVAILABLE_ERROR_NAME = "KeytarUnavailableError";
|
|
1206
|
+
var hasWarnedAboutUnavailableKeytar = false;
|
|
1207
|
+
var KeytarUnavailableError = class extends Error {
|
|
1208
|
+
constructor(message) {
|
|
1209
|
+
super(message);
|
|
1210
|
+
this.name = KEYTAR_UNAVAILABLE_ERROR_NAME;
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
function nullSecrets() {
|
|
1208
1214
|
return {
|
|
1209
|
-
openRouterApiKey,
|
|
1210
|
-
replicateApiToken
|
|
1215
|
+
openRouterApiKey: null,
|
|
1216
|
+
replicateApiToken: null
|
|
1211
1217
|
};
|
|
1212
1218
|
}
|
|
1213
|
-
|
|
1219
|
+
function shouldDisableKeytar(options) {
|
|
1220
|
+
return options.disableKeytar === true;
|
|
1221
|
+
}
|
|
1222
|
+
function isKeytarAvailabilityError(error) {
|
|
1223
|
+
if (!(error instanceof Error)) {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
const lowered = error.message.toLowerCase();
|
|
1227
|
+
return [
|
|
1228
|
+
"dbus",
|
|
1229
|
+
"d-bus",
|
|
1230
|
+
"org.freedesktop.secrets",
|
|
1231
|
+
"secret service",
|
|
1232
|
+
"secret-service",
|
|
1233
|
+
"keychain",
|
|
1234
|
+
"keyring",
|
|
1235
|
+
"credential store",
|
|
1236
|
+
"credentials were unavailable",
|
|
1237
|
+
"cannot autolaunch",
|
|
1238
|
+
"no such interface",
|
|
1239
|
+
"not supported in this environment"
|
|
1240
|
+
].some((fragment) => lowered.includes(fragment));
|
|
1241
|
+
}
|
|
1242
|
+
function warnKeytarUnavailable(details) {
|
|
1243
|
+
if (hasWarnedAboutUnavailableKeytar) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
hasWarnedAboutUnavailableKeytar = true;
|
|
1247
|
+
console.warn(
|
|
1248
|
+
`System keychain unavailable (${details}). Falling back to environment variables for secrets. Set IDEON_DISABLE_KEYTAR=true to skip keychain access in this environment.`
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
async function loadSecrets(options = {}) {
|
|
1252
|
+
if (shouldDisableKeytar(options)) {
|
|
1253
|
+
return nullSecrets();
|
|
1254
|
+
}
|
|
1255
|
+
try {
|
|
1256
|
+
const [openRouterApiKey, replicateApiToken] = await Promise.all([
|
|
1257
|
+
keytar.getPassword(SERVICE_NAME, OPENROUTER_ACCOUNT),
|
|
1258
|
+
keytar.getPassword(SERVICE_NAME, REPLICATE_ACCOUNT)
|
|
1259
|
+
]);
|
|
1260
|
+
return {
|
|
1261
|
+
openRouterApiKey,
|
|
1262
|
+
replicateApiToken
|
|
1263
|
+
};
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
if (isKeytarAvailabilityError(error)) {
|
|
1266
|
+
const message = error instanceof Error ? error.message : "unknown error";
|
|
1267
|
+
warnKeytarUnavailable(message);
|
|
1268
|
+
return nullSecrets();
|
|
1269
|
+
}
|
|
1270
|
+
throw error;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
async function saveSecrets(secrets, options = {}) {
|
|
1274
|
+
if (shouldDisableKeytar(options)) {
|
|
1275
|
+
throw new KeytarUnavailableError(
|
|
1276
|
+
"System keychain access is disabled by IDEON_DISABLE_KEYTAR=true. Use IDEON_OPENROUTER_API_KEY and IDEON_REPLICATE_API_TOKEN instead."
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1214
1279
|
const tasks = [];
|
|
1215
1280
|
if (secrets.openRouterApiKey !== void 0) {
|
|
1216
1281
|
tasks.push(saveSecretValue(OPENROUTER_ACCOUNT, secrets.openRouterApiKey));
|
|
@@ -1221,17 +1286,31 @@ async function saveSecrets(secrets) {
|
|
|
1221
1286
|
await Promise.all(tasks);
|
|
1222
1287
|
}
|
|
1223
1288
|
async function saveSecretValue(account, value2) {
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1289
|
+
try {
|
|
1290
|
+
if (!value2) {
|
|
1291
|
+
await keytar.deletePassword(SERVICE_NAME, account);
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
await keytar.setPassword(SERVICE_NAME, account, value2);
|
|
1295
|
+
} catch (error) {
|
|
1296
|
+
if (isKeytarAvailabilityError(error)) {
|
|
1297
|
+
const message = error instanceof Error ? error.message : "unknown error";
|
|
1298
|
+
throw new KeytarUnavailableError(
|
|
1299
|
+
`System keychain unavailable while saving credentials (${message}). Use IDEON_OPENROUTER_API_KEY and IDEON_REPLICATE_API_TOKEN instead.`
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
throw error;
|
|
1227
1303
|
}
|
|
1228
|
-
await keytar.setPassword(SERVICE_NAME, account, value2);
|
|
1229
1304
|
}
|
|
1230
1305
|
|
|
1231
1306
|
// src/cli/commands/settings.tsx
|
|
1232
1307
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1233
1308
|
async function openSettings() {
|
|
1234
|
-
const
|
|
1309
|
+
const envSettings = readEnvSettings();
|
|
1310
|
+
const [settings, secrets] = await Promise.all([
|
|
1311
|
+
loadSavedSettings(),
|
|
1312
|
+
loadSecrets({ disableKeytar: envSettings.disableKeytar })
|
|
1313
|
+
]);
|
|
1235
1314
|
let result = null;
|
|
1236
1315
|
const app = render(
|
|
1237
1316
|
/* @__PURE__ */ jsx2(
|
|
@@ -1252,7 +1331,17 @@ async function openSettings() {
|
|
|
1252
1331
|
return;
|
|
1253
1332
|
}
|
|
1254
1333
|
const savedResult = finalResult;
|
|
1255
|
-
await
|
|
1334
|
+
await saveSettings(savedResult.settings);
|
|
1335
|
+
try {
|
|
1336
|
+
await saveSecrets(savedResult.secrets, { disableKeytar: envSettings.disableKeytar });
|
|
1337
|
+
} catch (error) {
|
|
1338
|
+
if (error instanceof KeytarUnavailableError) {
|
|
1339
|
+
console.log("Settings saved, but secrets were not stored in the system keychain.");
|
|
1340
|
+
console.log("Use IDEON_OPENROUTER_API_KEY and IDEON_REPLICATE_API_TOKEN in this environment.");
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
throw error;
|
|
1344
|
+
}
|
|
1256
1345
|
console.log(`Settings saved to ${getSettingsFilePath()}.`);
|
|
1257
1346
|
}
|
|
1258
1347
|
|
|
@@ -3526,8 +3615,11 @@ import { createInterface } from "readline/promises";
|
|
|
3526
3615
|
// src/config/resolver.ts
|
|
3527
3616
|
import { readFile as readFile4 } from "fs/promises";
|
|
3528
3617
|
async function resolveRunInput(input) {
|
|
3529
|
-
const [savedSettings, secrets] = await Promise.all([loadSavedSettings(), loadSecrets()]);
|
|
3530
3618
|
const envSettings = readEnvSettings();
|
|
3619
|
+
const [savedSettings, secrets] = await Promise.all([
|
|
3620
|
+
loadSavedSettings(),
|
|
3621
|
+
loadSecrets({ disableKeytar: envSettings.disableKeytar })
|
|
3622
|
+
]);
|
|
3531
3623
|
const job = input.jobPath ? await loadJobInput(input.jobPath) : null;
|
|
3532
3624
|
assertNoLegacyXMode(savedSettings.contentTargets, "saved settings contentTargets");
|
|
3533
3625
|
assertNoLegacyXMode(job?.settings?.contentTargets, "job settings contentTargets");
|