theclawbay 0.3.32 → 0.3.33
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 +1 -0
- package/dist/commands/logout.js +75 -39
- package/dist/commands/setup.js +120 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,7 @@ theclawbay setup --api-key <apiKey>
|
|
|
18
18
|
|
|
19
19
|
In an interactive terminal, setup shows one picker for Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, and Windows Trae.
|
|
20
20
|
Each row includes a terminal-friendly icon plus the tool's official site, and you can toggle items with arrow keys plus `Enter` or by pressing their number.
|
|
21
|
+
Re-running setup also migrates legacy OpenCode and Kilo patches to the current reasoning-capable provider path and refreshes OpenClaw model metadata.
|
|
21
22
|
|
|
22
23
|
## Optional
|
|
23
24
|
|
package/dist/commands/logout.js
CHANGED
|
@@ -13,6 +13,7 @@ const codex_auth_seeding_1 = require("../lib/codex-auth-seeding");
|
|
|
13
13
|
const codex_history_migration_1 = require("../lib/codex-history-migration");
|
|
14
14
|
const codex_model_cache_migration_1 = require("../lib/codex-model-cache-migration");
|
|
15
15
|
const paths_1 = require("../lib/config/paths");
|
|
16
|
+
const supported_models_1 = require("../lib/supported-models");
|
|
16
17
|
const OPENAI_PROVIDER_ID = "openai";
|
|
17
18
|
const DEFAULT_PROVIDER_ID = "theclawbay";
|
|
18
19
|
const WAN_PROVIDER_ID = "theclawbay-wan";
|
|
@@ -29,6 +30,8 @@ const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homed
|
|
|
29
30
|
const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
|
|
30
31
|
const AIDER_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yml");
|
|
31
32
|
const CLINE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "cline.restore.json");
|
|
33
|
+
const OPENCODE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "opencode.restore.json");
|
|
34
|
+
const KILO_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "kilo.restore.json");
|
|
32
35
|
const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
|
|
33
36
|
const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
|
|
34
37
|
const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
|
|
@@ -39,6 +42,7 @@ const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set([
|
|
|
39
42
|
]);
|
|
40
43
|
const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = [DEFAULT_PROVIDER_ID, WAN_PROVIDER_ID];
|
|
41
44
|
const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
|
|
45
|
+
const SUPPORTED_MODEL_IDS = new Set((0, supported_models_1.getSupportedModelIds)());
|
|
42
46
|
const CONTINUE_MODEL_NAME = "The Claw Bay";
|
|
43
47
|
const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
|
|
44
48
|
const TRAE_BUNDLE_BACKUP_SUFFIX = ".theclawbay-managed-backup";
|
|
@@ -179,6 +183,18 @@ async function writeJsonFile(filePath, value, mode) {
|
|
|
179
183
|
if (mode !== undefined)
|
|
180
184
|
await promises_1.default.chmod(filePath, mode);
|
|
181
185
|
}
|
|
186
|
+
function isManagedOpenCodeModel(value) {
|
|
187
|
+
if (typeof value !== "string")
|
|
188
|
+
return false;
|
|
189
|
+
if (!value.startsWith(`${OPENAI_PROVIDER_ID}/`))
|
|
190
|
+
return false;
|
|
191
|
+
return SUPPORTED_MODEL_IDS.has(value.slice(`${OPENAI_PROVIDER_ID}/`.length));
|
|
192
|
+
}
|
|
193
|
+
function isManagedOpenCodeProvider(value) {
|
|
194
|
+
const provider = objectRecordOr(value, {});
|
|
195
|
+
const options = objectRecordOr(provider.options, {});
|
|
196
|
+
return isTheClawBayOpenAiCompatibleBaseUrl(options.baseURL);
|
|
197
|
+
}
|
|
182
198
|
function roamingAppDataDir() {
|
|
183
199
|
if (process.env.APPDATA?.trim())
|
|
184
200
|
return process.env.APPDATA;
|
|
@@ -433,11 +449,11 @@ async function cleanupOpenClawConfig() {
|
|
|
433
449
|
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
434
450
|
return true;
|
|
435
451
|
}
|
|
436
|
-
async function
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
452
|
+
async function cleanupOpenCodeFamilyConfig(params) {
|
|
453
|
+
const existingRaw = await readFileIfExists(params.configPath);
|
|
454
|
+
if (existingRaw === null || !existingRaw.trim()) {
|
|
455
|
+
return removeFileIfExists(params.restoreStatePath);
|
|
456
|
+
}
|
|
441
457
|
let doc;
|
|
442
458
|
try {
|
|
443
459
|
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
@@ -445,56 +461,76 @@ async function cleanupOpenCodeConfig() {
|
|
|
445
461
|
catch {
|
|
446
462
|
return false;
|
|
447
463
|
}
|
|
464
|
+
const snapshotRaw = await readFileIfExists(params.restoreStatePath);
|
|
448
465
|
let changed = false;
|
|
449
466
|
const providerRoot = objectRecordOr(doc.provider, {});
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
delete providerRoot[id];
|
|
453
|
-
changed = true;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
doc.provider = providerRoot;
|
|
457
|
-
const model = doc.model;
|
|
458
|
-
if (typeof model === "string" && model.startsWith(`${DEFAULT_PROVIDER_ID}/`)) {
|
|
459
|
-
delete doc.model;
|
|
467
|
+
if (DEFAULT_PROVIDER_ID in providerRoot) {
|
|
468
|
+
delete providerRoot[DEFAULT_PROVIDER_ID];
|
|
460
469
|
changed = true;
|
|
461
470
|
}
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
471
|
+
if (snapshotRaw?.trim()) {
|
|
472
|
+
try {
|
|
473
|
+
const snapshot = JSON.parse(snapshotRaw);
|
|
474
|
+
if (snapshot.openAiProvider) {
|
|
475
|
+
providerRoot[OPENAI_PROVIDER_ID] = snapshot.openAiProvider;
|
|
476
|
+
}
|
|
477
|
+
else if (OPENAI_PROVIDER_ID in providerRoot) {
|
|
478
|
+
delete providerRoot[OPENAI_PROVIDER_ID];
|
|
479
|
+
}
|
|
480
|
+
doc.provider = providerRoot;
|
|
481
|
+
if (snapshot.model === null) {
|
|
482
|
+
if (isManagedOpenCodeModel(doc.model) || typeof doc.model === "string" && doc.model.startsWith(`${DEFAULT_PROVIDER_ID}/`)) {
|
|
483
|
+
delete doc.model;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
doc.model = snapshot.model;
|
|
488
|
+
}
|
|
489
|
+
if (snapshot.schema === null) {
|
|
490
|
+
if (typeof doc.$schema === "string")
|
|
491
|
+
delete doc.$schema;
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
doc.$schema = snapshot.schema;
|
|
495
|
+
}
|
|
484
496
|
changed = true;
|
|
497
|
+
await promises_1.default.writeFile(params.configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
498
|
+
await removeFileIfExists(params.restoreStatePath);
|
|
499
|
+
return changed;
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
// Fall through to best-effort cleanup below.
|
|
485
503
|
}
|
|
486
504
|
}
|
|
487
505
|
doc.provider = providerRoot;
|
|
488
506
|
const model = doc.model;
|
|
489
|
-
if (typeof model === "string" && model.startsWith(`${DEFAULT_PROVIDER_ID}/`)) {
|
|
507
|
+
if (typeof model === "string" && (model.startsWith(`${DEFAULT_PROVIDER_ID}/`) || isManagedOpenCodeModel(model))) {
|
|
490
508
|
delete doc.model;
|
|
491
509
|
changed = true;
|
|
492
510
|
}
|
|
511
|
+
if (isManagedOpenCodeProvider(providerRoot[OPENAI_PROVIDER_ID])) {
|
|
512
|
+
delete providerRoot[OPENAI_PROVIDER_ID];
|
|
513
|
+
doc.provider = providerRoot;
|
|
514
|
+
changed = true;
|
|
515
|
+
}
|
|
493
516
|
if (!changed)
|
|
494
517
|
return false;
|
|
495
|
-
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
518
|
+
await promises_1.default.writeFile(params.configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
519
|
+
await removeFileIfExists(params.restoreStatePath);
|
|
496
520
|
return true;
|
|
497
521
|
}
|
|
522
|
+
async function cleanupOpenCodeConfig() {
|
|
523
|
+
return cleanupOpenCodeFamilyConfig({
|
|
524
|
+
configPath: node_path_1.default.join(node_os_1.default.homedir(), ".config", "opencode", "opencode.json"),
|
|
525
|
+
restoreStatePath: OPENCODE_RESTORE_STATE_PATH,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
async function cleanupKiloConfig() {
|
|
529
|
+
return cleanupOpenCodeFamilyConfig({
|
|
530
|
+
configPath: node_path_1.default.join(node_os_1.default.homedir(), ".config", "kilo", "opencode.json"),
|
|
531
|
+
restoreStatePath: KILO_RESTORE_STATE_PATH,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
498
534
|
async function cleanupTraeBundle() {
|
|
499
535
|
const bundlePath = traeBundlePath();
|
|
500
536
|
if (!bundlePath)
|
package/dist/commands/setup.js
CHANGED
|
@@ -42,6 +42,8 @@ const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homed
|
|
|
42
42
|
const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
|
|
43
43
|
const AIDER_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yml");
|
|
44
44
|
const CLINE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "cline.restore.json");
|
|
45
|
+
const OPENCODE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "opencode.restore.json");
|
|
46
|
+
const KILO_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "kilo.restore.json");
|
|
45
47
|
const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
|
|
46
48
|
const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
|
|
47
49
|
const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
|
|
@@ -56,6 +58,9 @@ const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set(["openai", "theclawbay-wan",
|
|
|
56
58
|
const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = ["openai", "theclawbay-wan"];
|
|
57
59
|
const SETUP_CLIENT_IDS = ["codex", "continue", "cline", "openclaw", "opencode", "kilo", "roo", "trae", "aider"];
|
|
58
60
|
const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
|
|
61
|
+
const OPENAI_PROVIDER_ID = "openai";
|
|
62
|
+
const OPENCODE_CONFIG_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
63
|
+
const KILO_CONFIG_SCHEMA_URL = "https://kilo.ai/config.json";
|
|
59
64
|
const CONTINUE_MODEL_NAME = "The Claw Bay";
|
|
60
65
|
const ROO_PROFILE_NAME = "The Claw Bay";
|
|
61
66
|
const ROO_PROFILE_ID = "theclawbay-openai-compatible";
|
|
@@ -1018,7 +1023,7 @@ async function patchOpenClawConfigFile(params) {
|
|
|
1018
1023
|
baseUrl: `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`,
|
|
1019
1024
|
apiKey: params.apiKey,
|
|
1020
1025
|
api: "openai-responses",
|
|
1021
|
-
models: params.models,
|
|
1026
|
+
models: buildOpenClawModels(params.models),
|
|
1022
1027
|
};
|
|
1023
1028
|
const configPath = node_path_1.default.join(node_os_1.default.homedir(), ".openclaw", "openclaw.json");
|
|
1024
1029
|
await promises_1.default.mkdir(node_path_1.default.dirname(configPath), { recursive: true });
|
|
@@ -1050,6 +1055,9 @@ async function patchOpenClawConfigFile(params) {
|
|
|
1050
1055
|
const defaultsRoot = objectRecordOr(agentsRoot.defaults, {});
|
|
1051
1056
|
const modelRoot = objectRecordOr(defaultsRoot.model, {});
|
|
1052
1057
|
modelRoot.primary = resolveOpenClawPrimaryModel(params);
|
|
1058
|
+
if (typeof defaultsRoot.thinkingDefault !== "string") {
|
|
1059
|
+
defaultsRoot.thinkingDefault = "medium";
|
|
1060
|
+
}
|
|
1053
1061
|
defaultsRoot.model = modelRoot;
|
|
1054
1062
|
agentsRoot.defaults = defaultsRoot;
|
|
1055
1063
|
doc.agents = agentsRoot;
|
|
@@ -1066,21 +1074,57 @@ function objectRecordOr(value, fallback) {
|
|
|
1066
1074
|
}
|
|
1067
1075
|
return fallback;
|
|
1068
1076
|
}
|
|
1069
|
-
function
|
|
1077
|
+
function modelContextLimit(modelId) {
|
|
1078
|
+
if (modelId === "gpt-5.4")
|
|
1079
|
+
return 1050000;
|
|
1080
|
+
return 272000;
|
|
1081
|
+
}
|
|
1082
|
+
function modelOutputLimit(modelId) {
|
|
1083
|
+
if (modelId === "gpt-5.4")
|
|
1084
|
+
return 128000;
|
|
1085
|
+
return 65536;
|
|
1086
|
+
}
|
|
1087
|
+
function buildOpenCodeModelConfig(model) {
|
|
1088
|
+
return {
|
|
1089
|
+
name: model.name || model.id,
|
|
1090
|
+
reasoning: true,
|
|
1091
|
+
tool_call: true,
|
|
1092
|
+
attachment: true,
|
|
1093
|
+
modalities: {
|
|
1094
|
+
input: ["text", "image"],
|
|
1095
|
+
output: ["text"],
|
|
1096
|
+
},
|
|
1097
|
+
limit: {
|
|
1098
|
+
context: modelContextLimit(model.id),
|
|
1099
|
+
output: modelOutputLimit(model.id),
|
|
1100
|
+
},
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function buildOpenCodeModelsObject(models) {
|
|
1070
1104
|
const result = {};
|
|
1071
1105
|
for (const model of models) {
|
|
1072
1106
|
if (!model.id)
|
|
1073
1107
|
continue;
|
|
1074
|
-
result[model.id] =
|
|
1108
|
+
result[model.id] = buildOpenCodeModelConfig(model);
|
|
1075
1109
|
}
|
|
1076
1110
|
return result;
|
|
1077
1111
|
}
|
|
1078
|
-
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1112
|
+
function isManagedOpenCodeProvider(provider) {
|
|
1113
|
+
const options = objectRecordOr(provider.options, {});
|
|
1114
|
+
return isTheClawBayOpenAiCompatibleBaseUrl(options.baseURL);
|
|
1115
|
+
}
|
|
1116
|
+
function isManagedOpenCodeModel(value, supportedModelIds) {
|
|
1117
|
+
if (typeof value !== "string")
|
|
1118
|
+
return false;
|
|
1119
|
+
if (!value.startsWith(`${OPENAI_PROVIDER_ID}/`))
|
|
1120
|
+
return false;
|
|
1121
|
+
return supportedModelIds.has(value.slice(`${OPENAI_PROVIDER_ID}/`.length));
|
|
1122
|
+
}
|
|
1123
|
+
async function writeOpenCodeFamilyConfig(params) {
|
|
1124
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(params.configPath), { recursive: true });
|
|
1081
1125
|
let existingRaw = "";
|
|
1082
1126
|
try {
|
|
1083
|
-
existingRaw = await promises_1.default.readFile(configPath, "utf8");
|
|
1127
|
+
existingRaw = await promises_1.default.readFile(params.configPath, "utf8");
|
|
1084
1128
|
}
|
|
1085
1129
|
catch (error) {
|
|
1086
1130
|
const err = error;
|
|
@@ -1093,60 +1137,81 @@ async function writeOpenCodeConfig(params) {
|
|
|
1093
1137
|
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
1094
1138
|
}
|
|
1095
1139
|
catch {
|
|
1096
|
-
throw new Error(`invalid JSON in
|
|
1140
|
+
throw new Error(`invalid JSON in config: ${params.configPath}`);
|
|
1097
1141
|
}
|
|
1098
1142
|
}
|
|
1099
1143
|
const providerRoot = objectRecordOr(doc.provider, {});
|
|
1100
|
-
providerRoot[
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1144
|
+
const openAiProvider = objectRecordOr(providerRoot[OPENAI_PROVIDER_ID], {});
|
|
1145
|
+
const supportedModelIds = new Set(params.models.map((entry) => entry.id).filter(Boolean));
|
|
1146
|
+
const alreadyManaged = isManagedOpenCodeProvider(openAiProvider) && isManagedOpenCodeModel(doc.model, supportedModelIds);
|
|
1147
|
+
if (!alreadyManaged) {
|
|
1148
|
+
const snapshot = {
|
|
1149
|
+
openAiProvider: Object.keys(openAiProvider).length > 0 ? openAiProvider : null,
|
|
1150
|
+
model: typeof doc.model === "string" && !doc.model.startsWith(`${DEFAULT_PROVIDER_ID}/`)
|
|
1151
|
+
? doc.model
|
|
1152
|
+
: null,
|
|
1153
|
+
schema: typeof doc.$schema === "string" ? doc.$schema : null,
|
|
1154
|
+
};
|
|
1155
|
+
await writeJsonObjectFile(params.restoreStatePath, snapshot, 0o600);
|
|
1156
|
+
}
|
|
1157
|
+
const managedOpenAiProvider = objectRecordOr(providerRoot[OPENAI_PROVIDER_ID], {});
|
|
1158
|
+
const optionsRoot = objectRecordOr(managedOpenAiProvider.options, {});
|
|
1159
|
+
optionsRoot.baseURL = `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`;
|
|
1160
|
+
optionsRoot.apiKey = params.apiKey;
|
|
1161
|
+
managedOpenAiProvider.options = optionsRoot;
|
|
1162
|
+
managedOpenAiProvider.models = buildOpenCodeModelsObject(params.models);
|
|
1163
|
+
managedOpenAiProvider.whitelist = params.models.map((entry) => entry.id).filter(Boolean);
|
|
1164
|
+
if ("blacklist" in managedOpenAiProvider) {
|
|
1165
|
+
delete managedOpenAiProvider.blacklist;
|
|
1166
|
+
}
|
|
1167
|
+
providerRoot[OPENAI_PROVIDER_ID] = managedOpenAiProvider;
|
|
1168
|
+
if (DEFAULT_PROVIDER_ID in providerRoot) {
|
|
1169
|
+
delete providerRoot[DEFAULT_PROVIDER_ID];
|
|
1170
|
+
}
|
|
1171
|
+
doc.$schema = params.schemaUrl;
|
|
1109
1172
|
doc.provider = providerRoot;
|
|
1110
|
-
doc.model = `${
|
|
1111
|
-
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
1112
|
-
return configPath;
|
|
1173
|
+
doc.model = `${OPENAI_PROVIDER_ID}/${params.model}`;
|
|
1174
|
+
await promises_1.default.writeFile(params.configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
1175
|
+
return params.configPath;
|
|
1176
|
+
}
|
|
1177
|
+
function buildOpenClawModels(models) {
|
|
1178
|
+
const supportedModelMap = new Map((0, supported_models_1.getSupportedModels)().map((model) => [model.id, model]));
|
|
1179
|
+
return models
|
|
1180
|
+
.filter((model) => Boolean(model.id))
|
|
1181
|
+
.map((model) => {
|
|
1182
|
+
const pricing = supportedModelMap.get(model.id);
|
|
1183
|
+
return {
|
|
1184
|
+
id: model.id,
|
|
1185
|
+
name: model.name || model.id,
|
|
1186
|
+
api: "openai-responses",
|
|
1187
|
+
reasoning: true,
|
|
1188
|
+
input: ["text", "image"],
|
|
1189
|
+
cost: {
|
|
1190
|
+
input: pricing?.inputPer1M ?? 0,
|
|
1191
|
+
output: pricing?.outputPer1M ?? 0,
|
|
1192
|
+
cacheRead: pricing?.cachedInputPer1M ?? 0,
|
|
1193
|
+
cacheWrite: pricing?.inputPer1M ?? 0,
|
|
1194
|
+
},
|
|
1195
|
+
contextWindow: modelContextLimit(model.id),
|
|
1196
|
+
maxTokens: modelOutputLimit(model.id),
|
|
1197
|
+
};
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
async function writeOpenCodeConfig(params) {
|
|
1201
|
+
return writeOpenCodeFamilyConfig({
|
|
1202
|
+
configPath: node_path_1.default.join(node_os_1.default.homedir(), ".config", "opencode", "opencode.json"),
|
|
1203
|
+
restoreStatePath: OPENCODE_RESTORE_STATE_PATH,
|
|
1204
|
+
schemaUrl: OPENCODE_CONFIG_SCHEMA_URL,
|
|
1205
|
+
...params,
|
|
1206
|
+
});
|
|
1113
1207
|
}
|
|
1114
1208
|
async function writeKiloConfig(params) {
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
}
|
|
1121
|
-
catch (error) {
|
|
1122
|
-
const err = error;
|
|
1123
|
-
if (err.code !== "ENOENT")
|
|
1124
|
-
throw error;
|
|
1125
|
-
}
|
|
1126
|
-
let doc = {};
|
|
1127
|
-
if (existingRaw.trim()) {
|
|
1128
|
-
try {
|
|
1129
|
-
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
1130
|
-
}
|
|
1131
|
-
catch {
|
|
1132
|
-
throw new Error(`invalid JSON in Kilo config: ${configPath}`);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
const providerRoot = objectRecordOr(doc.provider, {});
|
|
1136
|
-
providerRoot[DEFAULT_PROVIDER_ID] = {
|
|
1137
|
-
npm: "@ai-sdk/openai-compatible",
|
|
1138
|
-
name: DEFAULT_PROVIDER_ID,
|
|
1139
|
-
options: {
|
|
1140
|
-
baseURL: `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`,
|
|
1141
|
-
apiKey: params.apiKey,
|
|
1142
|
-
},
|
|
1143
|
-
models: openCodeModelsObject(params.models),
|
|
1144
|
-
};
|
|
1145
|
-
doc.$schema = "https://kilo.ai/config.json";
|
|
1146
|
-
doc.provider = providerRoot;
|
|
1147
|
-
doc.model = `${DEFAULT_PROVIDER_ID}/${params.model || DEFAULT_KILO_MODEL}`;
|
|
1148
|
-
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
1149
|
-
return configPath;
|
|
1209
|
+
return writeOpenCodeFamilyConfig({
|
|
1210
|
+
configPath: node_path_1.default.join(node_os_1.default.homedir(), ".config", "kilo", "opencode.json"),
|
|
1211
|
+
restoreStatePath: KILO_RESTORE_STATE_PATH,
|
|
1212
|
+
schemaUrl: KILO_CONFIG_SCHEMA_URL,
|
|
1213
|
+
...params,
|
|
1214
|
+
});
|
|
1150
1215
|
}
|
|
1151
1216
|
function traePatchSnippet(params) {
|
|
1152
1217
|
const patchedModels = params.models.length
|
package/package.json
CHANGED