theclawbay 0.3.37 → 0.3.38
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 +236 -47
- package/dist/commands/setup.js +351 -70
- 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, Windows Trae, and Zo.
|
|
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 `1-9` and `0`.
|
|
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
|
@@ -12,6 +12,7 @@ const base_command_1 = require("../lib/base-command");
|
|
|
12
12
|
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
|
+
const supported_models_1 = require("../lib/supported-models");
|
|
15
16
|
const paths_1 = require("../lib/config/paths");
|
|
16
17
|
const OPENAI_PROVIDER_ID = "openai";
|
|
17
18
|
const DEFAULT_PROVIDER_ID = "theclawbay";
|
|
@@ -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";
|
|
@@ -162,6 +166,57 @@ function objectRecordOr(value, fallback) {
|
|
|
162
166
|
function isTheClawBayOpenAiCompatibleBaseUrl(value) {
|
|
163
167
|
return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
|
|
164
168
|
}
|
|
169
|
+
function uniqueStrings(values) {
|
|
170
|
+
const output = [];
|
|
171
|
+
const seen = new Set();
|
|
172
|
+
for (const value of values) {
|
|
173
|
+
const normalized = value.trim();
|
|
174
|
+
if (!normalized || seen.has(normalized))
|
|
175
|
+
continue;
|
|
176
|
+
seen.add(normalized);
|
|
177
|
+
output.push(normalized);
|
|
178
|
+
}
|
|
179
|
+
return output;
|
|
180
|
+
}
|
|
181
|
+
function xdgConfigHomeDir() {
|
|
182
|
+
const raw = process.env.XDG_CONFIG_HOME?.trim();
|
|
183
|
+
if (raw)
|
|
184
|
+
return raw;
|
|
185
|
+
return node_path_1.default.join(node_os_1.default.homedir(), ".config");
|
|
186
|
+
}
|
|
187
|
+
function configDirCandidates(appName) {
|
|
188
|
+
const home = node_os_1.default.homedir();
|
|
189
|
+
const dirs = [node_path_1.default.join(xdgConfigHomeDir(), appName)];
|
|
190
|
+
if (node_os_1.default.platform() === "darwin") {
|
|
191
|
+
dirs.push(node_path_1.default.join(home, "Library", "Application Support", appName));
|
|
192
|
+
}
|
|
193
|
+
else if (node_os_1.default.platform() === "win32") {
|
|
194
|
+
dirs.push(node_path_1.default.join(roamingAppDataDir(), appName));
|
|
195
|
+
}
|
|
196
|
+
return uniqueStrings(dirs);
|
|
197
|
+
}
|
|
198
|
+
function openCodeConfigCleanupTargets() {
|
|
199
|
+
const home = node_os_1.default.homedir();
|
|
200
|
+
const dirs = configDirCandidates("opencode");
|
|
201
|
+
const candidates = [];
|
|
202
|
+
for (const dir of dirs) {
|
|
203
|
+
candidates.push(node_path_1.default.join(dir, "opencode.json"));
|
|
204
|
+
candidates.push(node_path_1.default.join(dir, ".opencode.json"));
|
|
205
|
+
candidates.push(node_path_1.default.join(dir, "config.json"));
|
|
206
|
+
}
|
|
207
|
+
candidates.push(node_path_1.default.join(home, ".opencode.json"));
|
|
208
|
+
return uniqueStrings(candidates);
|
|
209
|
+
}
|
|
210
|
+
function kiloConfigCleanupTargets() {
|
|
211
|
+
const home = node_os_1.default.homedir();
|
|
212
|
+
const dirs = uniqueStrings([...configDirCandidates("kilo"), node_path_1.default.join(home, ".kilo")]);
|
|
213
|
+
const candidates = [];
|
|
214
|
+
for (const dir of dirs) {
|
|
215
|
+
candidates.push(node_path_1.default.join(dir, "opencode.json"));
|
|
216
|
+
candidates.push(node_path_1.default.join(dir, "config.json"));
|
|
217
|
+
}
|
|
218
|
+
return uniqueStrings(candidates);
|
|
219
|
+
}
|
|
165
220
|
async function readJsonObjectFile(filePath) {
|
|
166
221
|
const existingRaw = await readFileIfExists(filePath);
|
|
167
222
|
if (existingRaw === null || !existingRaw.trim())
|
|
@@ -179,6 +234,18 @@ async function writeJsonFile(filePath, value, mode) {
|
|
|
179
234
|
if (mode !== undefined)
|
|
180
235
|
await promises_1.default.chmod(filePath, mode);
|
|
181
236
|
}
|
|
237
|
+
function isManagedOpenCodeModel(value) {
|
|
238
|
+
if (typeof value !== "string")
|
|
239
|
+
return false;
|
|
240
|
+
if (!value.startsWith(`${OPENAI_PROVIDER_ID}/`))
|
|
241
|
+
return false;
|
|
242
|
+
return SUPPORTED_MODEL_IDS.has(value.slice(`${OPENAI_PROVIDER_ID}/`.length));
|
|
243
|
+
}
|
|
244
|
+
function isManagedOpenCodeProvider(value) {
|
|
245
|
+
const provider = objectRecordOr(value, {});
|
|
246
|
+
const options = objectRecordOr(provider.options, {});
|
|
247
|
+
return isTheClawBayOpenAiCompatibleBaseUrl(options.baseURL);
|
|
248
|
+
}
|
|
182
249
|
function roamingAppDataDir() {
|
|
183
250
|
if (process.env.APPDATA?.trim())
|
|
184
251
|
return process.env.APPDATA;
|
|
@@ -433,67 +500,189 @@ async function cleanupOpenClawConfig() {
|
|
|
433
500
|
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
434
501
|
return true;
|
|
435
502
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
503
|
+
function normalizeOpenCodeRestoreSnapshot(snapshot, fallbackConfigPath) {
|
|
504
|
+
if (typeof snapshot !== "object" || snapshot === null || Array.isArray(snapshot))
|
|
505
|
+
return null;
|
|
506
|
+
const obj = snapshot;
|
|
507
|
+
if (obj.version === 2 && Array.isArray(obj.targets)) {
|
|
508
|
+
const targets = [];
|
|
509
|
+
for (const entry of obj.targets) {
|
|
510
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
511
|
+
continue;
|
|
512
|
+
const candidate = entry;
|
|
513
|
+
const configPath = typeof candidate.configPath === "string" ? candidate.configPath.trim() : "";
|
|
514
|
+
if (!configPath)
|
|
515
|
+
continue;
|
|
516
|
+
targets.push({
|
|
517
|
+
configPath,
|
|
518
|
+
existed: candidate.existed === true,
|
|
519
|
+
openAiProvider: typeof candidate.openAiProvider === "object" &&
|
|
520
|
+
candidate.openAiProvider !== null &&
|
|
521
|
+
!Array.isArray(candidate.openAiProvider)
|
|
522
|
+
? candidate.openAiProvider
|
|
523
|
+
: null,
|
|
524
|
+
model: typeof candidate.model === "string" ? candidate.model : null,
|
|
525
|
+
schema: typeof candidate.schema === "string" ? candidate.schema : null,
|
|
526
|
+
plugin: "plugin" in candidate
|
|
527
|
+
? Array.isArray(candidate.plugin)
|
|
528
|
+
? candidate.plugin
|
|
529
|
+
: null
|
|
530
|
+
: undefined,
|
|
531
|
+
});
|
|
454
532
|
}
|
|
533
|
+
return { version: 2, targets };
|
|
455
534
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
535
|
+
const looksLikeV1 = "openAiProvider" in obj || "model" in obj || "schema" in obj;
|
|
536
|
+
if (!looksLikeV1)
|
|
537
|
+
return null;
|
|
538
|
+
return {
|
|
539
|
+
version: 2,
|
|
540
|
+
targets: [
|
|
541
|
+
{
|
|
542
|
+
configPath: fallbackConfigPath,
|
|
543
|
+
existed: true,
|
|
544
|
+
openAiProvider: typeof obj.openAiProvider === "object" && obj.openAiProvider !== null && !Array.isArray(obj.openAiProvider)
|
|
545
|
+
? obj.openAiProvider
|
|
546
|
+
: null,
|
|
547
|
+
model: typeof obj.model === "string" ? obj.model : null,
|
|
548
|
+
schema: typeof obj.schema === "string" ? obj.schema : null,
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
};
|
|
466
552
|
}
|
|
467
|
-
async function
|
|
468
|
-
const
|
|
469
|
-
const existingRaw = await readFileIfExists(configPath);
|
|
553
|
+
async function readOpenCodeRestoreSnapshot(restoreStatePath, fallbackConfigPath) {
|
|
554
|
+
const existingRaw = await readFileIfExists(restoreStatePath);
|
|
470
555
|
if (existingRaw === null || !existingRaw.trim())
|
|
471
|
-
return
|
|
472
|
-
let doc;
|
|
556
|
+
return null;
|
|
473
557
|
try {
|
|
474
|
-
|
|
558
|
+
return normalizeOpenCodeRestoreSnapshot(JSON.parse(existingRaw), fallbackConfigPath);
|
|
475
559
|
}
|
|
476
560
|
catch {
|
|
477
|
-
return
|
|
561
|
+
return null;
|
|
478
562
|
}
|
|
563
|
+
}
|
|
564
|
+
async function cleanupOpenCodeFamilyConfigs(params) {
|
|
565
|
+
const configPaths = uniqueStrings(params.configPaths);
|
|
566
|
+
const fallbackConfigPath = configPaths[0] ?? node_path_1.default.join(xdgConfigHomeDir(), "opencode", "opencode.json");
|
|
567
|
+
const snapshot = await readOpenCodeRestoreSnapshot(params.restoreStatePath, fallbackConfigPath);
|
|
568
|
+
const snapshotTargets = snapshot?.targets ?? [];
|
|
479
569
|
let changed = false;
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
570
|
+
const restoreConfig = async (target) => {
|
|
571
|
+
if (!target.existed) {
|
|
572
|
+
changed = (await removeFileIfExists(target.configPath)) || changed;
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const existingRaw = await readFileIfExists(target.configPath);
|
|
576
|
+
if (existingRaw === null || !existingRaw.trim()) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
let doc;
|
|
580
|
+
try {
|
|
581
|
+
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
582
|
+
}
|
|
583
|
+
catch {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const providerRoot = objectRecordOr(doc.provider, {});
|
|
587
|
+
if (DEFAULT_PROVIDER_ID in providerRoot) {
|
|
588
|
+
delete providerRoot[DEFAULT_PROVIDER_ID];
|
|
589
|
+
changed = true;
|
|
590
|
+
}
|
|
591
|
+
if (Object.prototype.hasOwnProperty.call(target, "plugin")) {
|
|
592
|
+
if (target.plugin === null) {
|
|
593
|
+
if ("plugin" in doc) {
|
|
594
|
+
delete doc.plugin;
|
|
595
|
+
changed = true;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
doc.plugin = target.plugin;
|
|
600
|
+
changed = true;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (target.openAiProvider) {
|
|
604
|
+
providerRoot[OPENAI_PROVIDER_ID] = target.openAiProvider;
|
|
605
|
+
}
|
|
606
|
+
else if (OPENAI_PROVIDER_ID in providerRoot) {
|
|
607
|
+
delete providerRoot[OPENAI_PROVIDER_ID];
|
|
608
|
+
}
|
|
609
|
+
doc.provider = providerRoot;
|
|
610
|
+
if (target.model === null) {
|
|
611
|
+
if (isManagedOpenCodeModel(doc.model) || (typeof doc.model === "string" && doc.model.startsWith(`${DEFAULT_PROVIDER_ID}/`))) {
|
|
612
|
+
delete doc.model;
|
|
613
|
+
changed = true;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
doc.model = target.model;
|
|
484
618
|
changed = true;
|
|
485
619
|
}
|
|
620
|
+
if (target.schema === null) {
|
|
621
|
+
if (typeof doc.$schema === "string") {
|
|
622
|
+
delete doc.$schema;
|
|
623
|
+
changed = true;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
doc.$schema = target.schema;
|
|
628
|
+
changed = true;
|
|
629
|
+
}
|
|
630
|
+
await promises_1.default.writeFile(target.configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
631
|
+
};
|
|
632
|
+
if (snapshotTargets.length > 0) {
|
|
633
|
+
for (const target of snapshotTargets) {
|
|
634
|
+
await restoreConfig(target);
|
|
635
|
+
}
|
|
636
|
+
await removeFileIfExists(params.restoreStatePath);
|
|
637
|
+
return changed;
|
|
486
638
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
639
|
+
for (const configPath of configPaths) {
|
|
640
|
+
const existingRaw = await readFileIfExists(configPath);
|
|
641
|
+
if (existingRaw === null || !existingRaw.trim())
|
|
642
|
+
continue;
|
|
643
|
+
let doc;
|
|
644
|
+
try {
|
|
645
|
+
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
646
|
+
}
|
|
647
|
+
catch {
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
let fileChanged = false;
|
|
651
|
+
const providerRoot = objectRecordOr(doc.provider, {});
|
|
652
|
+
if (DEFAULT_PROVIDER_ID in providerRoot) {
|
|
653
|
+
delete providerRoot[DEFAULT_PROVIDER_ID];
|
|
654
|
+
fileChanged = true;
|
|
655
|
+
}
|
|
656
|
+
const model = doc.model;
|
|
657
|
+
if (typeof model === "string" &&
|
|
658
|
+
(model.startsWith(`${DEFAULT_PROVIDER_ID}/`) || isManagedOpenCodeModel(model))) {
|
|
659
|
+
delete doc.model;
|
|
660
|
+
fileChanged = true;
|
|
661
|
+
}
|
|
662
|
+
if (isManagedOpenCodeProvider(providerRoot[OPENAI_PROVIDER_ID])) {
|
|
663
|
+
delete providerRoot[OPENAI_PROVIDER_ID];
|
|
664
|
+
fileChanged = true;
|
|
665
|
+
}
|
|
666
|
+
if (!fileChanged)
|
|
667
|
+
continue;
|
|
491
668
|
changed = true;
|
|
669
|
+
doc.provider = providerRoot;
|
|
670
|
+
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
492
671
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
672
|
+
await removeFileIfExists(params.restoreStatePath);
|
|
673
|
+
return changed;
|
|
674
|
+
}
|
|
675
|
+
async function cleanupOpenCodeConfig() {
|
|
676
|
+
return cleanupOpenCodeFamilyConfigs({
|
|
677
|
+
configPaths: openCodeConfigCleanupTargets(),
|
|
678
|
+
restoreStatePath: OPENCODE_RESTORE_STATE_PATH,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
async function cleanupKiloConfig() {
|
|
682
|
+
return cleanupOpenCodeFamilyConfigs({
|
|
683
|
+
configPaths: kiloConfigCleanupTargets(),
|
|
684
|
+
restoreStatePath: KILO_RESTORE_STATE_PATH,
|
|
685
|
+
});
|
|
497
686
|
}
|
|
498
687
|
async function cleanupTraeBundle() {
|
|
499
688
|
const bundlePath = traeBundlePath();
|
package/dist/commands/setup.js
CHANGED
|
@@ -43,6 +43,8 @@ const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homed
|
|
|
43
43
|
const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
|
|
44
44
|
const AIDER_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yml");
|
|
45
45
|
const CLINE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "cline.restore.json");
|
|
46
|
+
const OPENCODE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "opencode.restore.json");
|
|
47
|
+
const KILO_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "kilo.restore.json");
|
|
46
48
|
const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
|
|
47
49
|
const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
|
|
48
50
|
const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
|
|
@@ -65,6 +67,9 @@ const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
|
|
|
65
67
|
const TRAE_BUNDLE_BACKUP_SUFFIX = ".theclawbay-managed-backup";
|
|
66
68
|
const TRAE_TARGET_FUNCTION_START = "async setOriginModelListMapAndCache(e,t=!0){";
|
|
67
69
|
const TRAE_TARGET_FUNCTION_END = "}async refreshModelListConfig";
|
|
70
|
+
const OPENAI_PROVIDER_ID = "openai";
|
|
71
|
+
const OPENCODE_CONFIG_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
72
|
+
const KILO_CONFIG_SCHEMA_URL = "https://kilo.ai/config.json";
|
|
68
73
|
const ZO_CONFIG_NAME_PREFIX = "The Claw Bay";
|
|
69
74
|
const ZO_COOKIE_HOST = ".zo.computer";
|
|
70
75
|
const ZO_ACCESS_TOKEN_COOKIE = "access_token";
|
|
@@ -437,6 +442,56 @@ function openAiCompatibleProxyUrl(backendUrl) {
|
|
|
437
442
|
function isTheClawBayOpenAiCompatibleBaseUrl(value) {
|
|
438
443
|
return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
|
|
439
444
|
}
|
|
445
|
+
function uniqueStrings(values) {
|
|
446
|
+
const output = [];
|
|
447
|
+
const seen = new Set();
|
|
448
|
+
for (const value of values) {
|
|
449
|
+
const normalized = value.trim();
|
|
450
|
+
if (!normalized || seen.has(normalized))
|
|
451
|
+
continue;
|
|
452
|
+
seen.add(normalized);
|
|
453
|
+
output.push(normalized);
|
|
454
|
+
}
|
|
455
|
+
return output;
|
|
456
|
+
}
|
|
457
|
+
function xdgConfigHomeDir() {
|
|
458
|
+
const raw = process.env.XDG_CONFIG_HOME?.trim();
|
|
459
|
+
if (raw)
|
|
460
|
+
return raw;
|
|
461
|
+
return node_path_1.default.join(node_os_1.default.homedir(), ".config");
|
|
462
|
+
}
|
|
463
|
+
function configFileCandidatesForDir(dir, basenames) {
|
|
464
|
+
return basenames.map((basename) => node_path_1.default.join(dir, basename));
|
|
465
|
+
}
|
|
466
|
+
function findProjectConfigFile(params) {
|
|
467
|
+
let current = node_path_1.default.resolve(params.startDir);
|
|
468
|
+
const root = node_path_1.default.parse(current).root;
|
|
469
|
+
while (true) {
|
|
470
|
+
for (const candidate of configFileCandidatesForDir(current, params.basenames)) {
|
|
471
|
+
if ((0, node_fs_1.existsSync)(candidate))
|
|
472
|
+
return candidate;
|
|
473
|
+
}
|
|
474
|
+
if ((0, node_fs_1.existsSync)(node_path_1.default.join(current, ".git")))
|
|
475
|
+
return null;
|
|
476
|
+
if (current === root)
|
|
477
|
+
return null;
|
|
478
|
+
const parent = node_path_1.default.dirname(current);
|
|
479
|
+
if (parent === current)
|
|
480
|
+
return null;
|
|
481
|
+
current = parent;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function configDirCandidates(appName) {
|
|
485
|
+
const home = node_os_1.default.homedir();
|
|
486
|
+
const dirs = [node_path_1.default.join(xdgConfigHomeDir(), appName)];
|
|
487
|
+
if (node_os_1.default.platform() === "darwin") {
|
|
488
|
+
dirs.push(node_path_1.default.join(home, "Library", "Application Support", appName));
|
|
489
|
+
}
|
|
490
|
+
else if (node_os_1.default.platform() === "win32") {
|
|
491
|
+
dirs.push(node_path_1.default.join(roamingAppDataDir(), appName));
|
|
492
|
+
}
|
|
493
|
+
return uniqueStrings(dirs);
|
|
494
|
+
}
|
|
440
495
|
async function readFileIfExists(filePath) {
|
|
441
496
|
try {
|
|
442
497
|
return await promises_1.default.readFile(filePath, "utf8");
|
|
@@ -1203,7 +1258,7 @@ async function patchOpenClawConfigFile(params) {
|
|
|
1203
1258
|
baseUrl: `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`,
|
|
1204
1259
|
apiKey: params.apiKey,
|
|
1205
1260
|
api: "openai-responses",
|
|
1206
|
-
models: params.models,
|
|
1261
|
+
models: buildOpenClawModels(params.models),
|
|
1207
1262
|
};
|
|
1208
1263
|
const configPath = node_path_1.default.join(node_os_1.default.homedir(), ".openclaw", "openclaw.json");
|
|
1209
1264
|
await promises_1.default.mkdir(node_path_1.default.dirname(configPath), { recursive: true });
|
|
@@ -1235,6 +1290,9 @@ async function patchOpenClawConfigFile(params) {
|
|
|
1235
1290
|
const defaultsRoot = objectRecordOr(agentsRoot.defaults, {});
|
|
1236
1291
|
const modelRoot = objectRecordOr(defaultsRoot.model, {});
|
|
1237
1292
|
modelRoot.primary = resolveOpenClawPrimaryModel(params);
|
|
1293
|
+
if (typeof defaultsRoot.thinkingDefault !== "string") {
|
|
1294
|
+
defaultsRoot.thinkingDefault = "medium";
|
|
1295
|
+
}
|
|
1238
1296
|
defaultsRoot.model = modelRoot;
|
|
1239
1297
|
agentsRoot.defaults = defaultsRoot;
|
|
1240
1298
|
doc.agents = agentsRoot;
|
|
@@ -1251,87 +1309,302 @@ function objectRecordOr(value, fallback) {
|
|
|
1251
1309
|
}
|
|
1252
1310
|
return fallback;
|
|
1253
1311
|
}
|
|
1254
|
-
function
|
|
1312
|
+
function modelContextLimit(modelId) {
|
|
1313
|
+
if (modelId === "gpt-5.4")
|
|
1314
|
+
return 1050000;
|
|
1315
|
+
return 272000;
|
|
1316
|
+
}
|
|
1317
|
+
function modelOutputLimit(modelId) {
|
|
1318
|
+
if (modelId === "gpt-5.4")
|
|
1319
|
+
return 128000;
|
|
1320
|
+
return 65536;
|
|
1321
|
+
}
|
|
1322
|
+
function buildOpenClawModels(models) {
|
|
1323
|
+
const supportedModelMap = new Map((0, supported_models_1.getSupportedModels)().map((model) => [model.id, model]));
|
|
1324
|
+
return models
|
|
1325
|
+
.filter((model) => Boolean(model.id))
|
|
1326
|
+
.map((model) => {
|
|
1327
|
+
const pricing = supportedModelMap.get(model.id);
|
|
1328
|
+
return {
|
|
1329
|
+
id: model.id,
|
|
1330
|
+
name: model.name || model.id,
|
|
1331
|
+
api: "openai-responses",
|
|
1332
|
+
reasoning: true,
|
|
1333
|
+
input: ["text", "image"],
|
|
1334
|
+
cost: {
|
|
1335
|
+
input: pricing?.inputPer1M ?? 0,
|
|
1336
|
+
output: pricing?.outputPer1M ?? 0,
|
|
1337
|
+
cacheRead: pricing?.cachedInputPer1M ?? 0,
|
|
1338
|
+
cacheWrite: pricing?.inputPer1M ?? 0,
|
|
1339
|
+
},
|
|
1340
|
+
contextWindow: modelContextLimit(model.id),
|
|
1341
|
+
maxTokens: modelOutputLimit(model.id),
|
|
1342
|
+
};
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
function buildOpenCodeModelConfig(model) {
|
|
1346
|
+
return {
|
|
1347
|
+
name: model.name || model.id,
|
|
1348
|
+
reasoning: true,
|
|
1349
|
+
tool_call: true,
|
|
1350
|
+
attachment: true,
|
|
1351
|
+
modalities: {
|
|
1352
|
+
input: ["text", "image"],
|
|
1353
|
+
output: ["text"],
|
|
1354
|
+
},
|
|
1355
|
+
limit: {
|
|
1356
|
+
context: modelContextLimit(model.id),
|
|
1357
|
+
output: modelOutputLimit(model.id),
|
|
1358
|
+
},
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function buildOpenCodeModelsObject(models) {
|
|
1255
1362
|
const result = {};
|
|
1256
1363
|
for (const model of models) {
|
|
1257
1364
|
if (!model.id)
|
|
1258
1365
|
continue;
|
|
1259
|
-
result[model.id] =
|
|
1366
|
+
result[model.id] = buildOpenCodeModelConfig(model);
|
|
1260
1367
|
}
|
|
1261
1368
|
return result;
|
|
1262
1369
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1370
|
+
function normalizeOpenCodeRestoreSnapshot(snapshot, fallbackConfigPath) {
|
|
1371
|
+
if (typeof snapshot !== "object" || snapshot === null || Array.isArray(snapshot))
|
|
1372
|
+
return null;
|
|
1373
|
+
const obj = snapshot;
|
|
1374
|
+
if (obj.version === 2 && Array.isArray(obj.targets)) {
|
|
1375
|
+
const targets = [];
|
|
1376
|
+
for (const entry of obj.targets) {
|
|
1377
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
1378
|
+
continue;
|
|
1379
|
+
const candidate = entry;
|
|
1380
|
+
const configPath = typeof candidate.configPath === "string" ? candidate.configPath.trim() : "";
|
|
1381
|
+
if (!configPath)
|
|
1382
|
+
continue;
|
|
1383
|
+
targets.push({
|
|
1384
|
+
configPath,
|
|
1385
|
+
existed: candidate.existed === true,
|
|
1386
|
+
openAiProvider: typeof candidate.openAiProvider === "object" &&
|
|
1387
|
+
candidate.openAiProvider !== null &&
|
|
1388
|
+
!Array.isArray(candidate.openAiProvider)
|
|
1389
|
+
? candidate.openAiProvider
|
|
1390
|
+
: null,
|
|
1391
|
+
model: typeof candidate.model === "string" ? candidate.model : null,
|
|
1392
|
+
schema: typeof candidate.schema === "string" ? candidate.schema : null,
|
|
1393
|
+
plugin: "plugin" in candidate
|
|
1394
|
+
? Array.isArray(candidate.plugin)
|
|
1395
|
+
? candidate.plugin
|
|
1396
|
+
: null
|
|
1397
|
+
: undefined,
|
|
1398
|
+
});
|
|
1282
1399
|
}
|
|
1400
|
+
return { version: 2, targets };
|
|
1283
1401
|
}
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1402
|
+
const looksLikeV1 = "openAiProvider" in obj || "model" in obj || "schema" in obj;
|
|
1403
|
+
if (!looksLikeV1)
|
|
1404
|
+
return null;
|
|
1405
|
+
return {
|
|
1406
|
+
version: 2,
|
|
1407
|
+
targets: [
|
|
1408
|
+
{
|
|
1409
|
+
configPath: fallbackConfigPath,
|
|
1410
|
+
existed: true,
|
|
1411
|
+
openAiProvider: typeof obj.openAiProvider === "object" && obj.openAiProvider !== null && !Array.isArray(obj.openAiProvider)
|
|
1412
|
+
? obj.openAiProvider
|
|
1413
|
+
: null,
|
|
1414
|
+
model: typeof obj.model === "string" ? obj.model : null,
|
|
1415
|
+
schema: typeof obj.schema === "string" ? obj.schema : null,
|
|
1416
|
+
},
|
|
1417
|
+
],
|
|
1293
1418
|
};
|
|
1294
|
-
doc.provider = providerRoot;
|
|
1295
|
-
doc.model = `${DEFAULT_PROVIDER_ID}/${params.model}`;
|
|
1296
|
-
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
1297
|
-
return configPath;
|
|
1298
1419
|
}
|
|
1299
|
-
async function
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1420
|
+
async function readOpenCodeRestoreSnapshot(restoreStatePath, fallbackConfigPath) {
|
|
1421
|
+
const existingRaw = await readFileIfExists(restoreStatePath);
|
|
1422
|
+
if (existingRaw === null || !existingRaw.trim())
|
|
1423
|
+
return null;
|
|
1303
1424
|
try {
|
|
1304
|
-
|
|
1425
|
+
return normalizeOpenCodeRestoreSnapshot(JSON.parse(existingRaw), fallbackConfigPath);
|
|
1305
1426
|
}
|
|
1306
|
-
catch
|
|
1307
|
-
|
|
1308
|
-
if (err.code !== "ENOENT")
|
|
1309
|
-
throw error;
|
|
1427
|
+
catch {
|
|
1428
|
+
return null;
|
|
1310
1429
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1430
|
+
}
|
|
1431
|
+
function openCodeConfigFileCandidates() {
|
|
1432
|
+
const home = node_os_1.default.homedir();
|
|
1433
|
+
const dirs = configDirCandidates("opencode");
|
|
1434
|
+
const candidates = [];
|
|
1435
|
+
for (const dir of dirs) {
|
|
1436
|
+
candidates.push(node_path_1.default.join(dir, "opencode.json"));
|
|
1437
|
+
candidates.push(node_path_1.default.join(dir, ".opencode.json"));
|
|
1438
|
+
candidates.push(node_path_1.default.join(dir, "config.json"));
|
|
1439
|
+
}
|
|
1440
|
+
candidates.push(node_path_1.default.join(home, ".opencode.json"));
|
|
1441
|
+
return uniqueStrings(candidates);
|
|
1442
|
+
}
|
|
1443
|
+
function findOpenCodeProjectConfigFile() {
|
|
1444
|
+
return findProjectConfigFile({
|
|
1445
|
+
startDir: process.cwd(),
|
|
1446
|
+
basenames: ["opencode.json", "opencode.jsonc", ".opencode.json", ".opencode.jsonc"],
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
function isOpenCodeAuthPlugin(value) {
|
|
1450
|
+
if (typeof value !== "string")
|
|
1451
|
+
return false;
|
|
1452
|
+
const normalized = value.trim();
|
|
1453
|
+
if (!normalized)
|
|
1454
|
+
return false;
|
|
1455
|
+
return normalized.startsWith("opencode-openai-codex-auth");
|
|
1456
|
+
}
|
|
1457
|
+
function filteredOpenCodePlugins(value) {
|
|
1458
|
+
if (!Array.isArray(value))
|
|
1459
|
+
return { next: value, changed: false };
|
|
1460
|
+
const filtered = value.filter((entry) => !isOpenCodeAuthPlugin(entry));
|
|
1461
|
+
if (filtered.length === value.length)
|
|
1462
|
+
return { next: value, changed: false };
|
|
1463
|
+
return { next: filtered, changed: true };
|
|
1464
|
+
}
|
|
1465
|
+
function kiloConfigFileCandidates() {
|
|
1466
|
+
const home = node_os_1.default.homedir();
|
|
1467
|
+
const dirs = uniqueStrings([...configDirCandidates("kilo"), node_path_1.default.join(home, ".kilo")]);
|
|
1468
|
+
const candidates = [];
|
|
1469
|
+
for (const dir of dirs) {
|
|
1470
|
+
candidates.push(node_path_1.default.join(dir, "opencode.json"));
|
|
1471
|
+
candidates.push(node_path_1.default.join(dir, "config.json"));
|
|
1472
|
+
}
|
|
1473
|
+
return uniqueStrings(candidates);
|
|
1474
|
+
}
|
|
1475
|
+
function resolveOpenCodeConfigTargets() {
|
|
1476
|
+
const candidates = openCodeConfigFileCandidates();
|
|
1477
|
+
const existing = candidates.filter((candidate) => (0, node_fs_1.existsSync)(candidate));
|
|
1478
|
+
if (existing.length)
|
|
1479
|
+
return existing;
|
|
1480
|
+
const primaryDir = configDirCandidates("opencode")[0] ?? node_path_1.default.join(xdgConfigHomeDir(), "opencode");
|
|
1481
|
+
return uniqueStrings([node_path_1.default.join(primaryDir, "opencode.json"), node_path_1.default.join(primaryDir, ".opencode.json")]);
|
|
1482
|
+
}
|
|
1483
|
+
function resolveKiloConfigTargets() {
|
|
1484
|
+
const candidates = kiloConfigFileCandidates();
|
|
1485
|
+
const existing = candidates.filter((candidate) => (0, node_fs_1.existsSync)(candidate));
|
|
1486
|
+
if (existing.length)
|
|
1487
|
+
return existing;
|
|
1488
|
+
const home = node_os_1.default.homedir();
|
|
1489
|
+
const primaryDir = uniqueStrings([...configDirCandidates("kilo"), node_path_1.default.join(home, ".kilo")])[0] ??
|
|
1490
|
+
node_path_1.default.join(xdgConfigHomeDir(), "kilo");
|
|
1491
|
+
return uniqueStrings([node_path_1.default.join(primaryDir, "opencode.json")]);
|
|
1492
|
+
}
|
|
1493
|
+
function isManagedOpenCodeProvider(provider) {
|
|
1494
|
+
const options = objectRecordOr(provider.options, {});
|
|
1495
|
+
return isTheClawBayOpenAiCompatibleBaseUrl(options.baseURL);
|
|
1496
|
+
}
|
|
1497
|
+
function isManagedOpenCodeModel(value, supportedModelIds) {
|
|
1498
|
+
if (typeof value !== "string")
|
|
1499
|
+
return false;
|
|
1500
|
+
if (!value.startsWith(`${OPENAI_PROVIDER_ID}/`))
|
|
1501
|
+
return false;
|
|
1502
|
+
return supportedModelIds.has(value.slice(`${OPENAI_PROVIDER_ID}/`.length));
|
|
1503
|
+
}
|
|
1504
|
+
async function writeOpenCodeFamilyConfig(params) {
|
|
1505
|
+
const normalizedConfigPaths = uniqueStrings(params.configPaths);
|
|
1506
|
+
const fallbackConfigPath = normalizedConfigPaths[0] ?? node_path_1.default.join(xdgConfigHomeDir(), "opencode", "opencode.json");
|
|
1507
|
+
const restoreState = (await readOpenCodeRestoreSnapshot(params.restoreStatePath, fallbackConfigPath)) ??
|
|
1508
|
+
{
|
|
1509
|
+
version: 2,
|
|
1510
|
+
targets: [],
|
|
1511
|
+
};
|
|
1512
|
+
const supportedModelIds = new Set(params.models.map((entry) => entry.id).filter(Boolean));
|
|
1513
|
+
const restoreHasTarget = (configPath) => restoreState.targets.some((entry) => entry.configPath === configPath);
|
|
1514
|
+
let restoreStateChanged = false;
|
|
1515
|
+
const ensureRestorePluginSnapshot = (configPath, plugin) => {
|
|
1516
|
+
const target = restoreState.targets.find((entry) => entry.configPath === configPath);
|
|
1517
|
+
if (!target)
|
|
1518
|
+
return;
|
|
1519
|
+
if (Object.prototype.hasOwnProperty.call(target, "plugin"))
|
|
1520
|
+
return;
|
|
1521
|
+
target.plugin = Array.isArray(plugin) ? plugin : null;
|
|
1522
|
+
restoreStateChanged = true;
|
|
1523
|
+
};
|
|
1524
|
+
for (const configPath of normalizedConfigPaths) {
|
|
1525
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(configPath), { recursive: true });
|
|
1526
|
+
let existed = true;
|
|
1527
|
+
let existingRaw = "";
|
|
1313
1528
|
try {
|
|
1314
|
-
|
|
1529
|
+
existingRaw = await promises_1.default.readFile(configPath, "utf8");
|
|
1315
1530
|
}
|
|
1316
|
-
catch {
|
|
1317
|
-
|
|
1531
|
+
catch (error) {
|
|
1532
|
+
const err = error;
|
|
1533
|
+
if (err.code !== "ENOENT")
|
|
1534
|
+
throw error;
|
|
1535
|
+
existed = false;
|
|
1536
|
+
}
|
|
1537
|
+
let doc = {};
|
|
1538
|
+
if (existingRaw.trim()) {
|
|
1539
|
+
try {
|
|
1540
|
+
doc = objectRecordOr(JSON.parse(existingRaw), {});
|
|
1541
|
+
}
|
|
1542
|
+
catch {
|
|
1543
|
+
throw new Error(`invalid JSON in config: ${configPath}`);
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
const providerRoot = objectRecordOr(doc.provider, {});
|
|
1547
|
+
const openAiProvider = objectRecordOr(providerRoot[OPENAI_PROVIDER_ID], {});
|
|
1548
|
+
const alreadyManaged = isManagedOpenCodeProvider(openAiProvider) && isManagedOpenCodeModel(doc.model, supportedModelIds);
|
|
1549
|
+
if (!alreadyManaged && !restoreHasTarget(configPath)) {
|
|
1550
|
+
restoreState.targets.push({
|
|
1551
|
+
configPath,
|
|
1552
|
+
existed,
|
|
1553
|
+
openAiProvider: Object.keys(openAiProvider).length > 0 ? openAiProvider : null,
|
|
1554
|
+
model: typeof doc.model === "string" && !doc.model.startsWith(`${DEFAULT_PROVIDER_ID}/`)
|
|
1555
|
+
? doc.model
|
|
1556
|
+
: null,
|
|
1557
|
+
schema: typeof doc.$schema === "string" ? doc.$schema : null,
|
|
1558
|
+
plugin: Array.isArray(doc.plugin) ? doc.plugin : null,
|
|
1559
|
+
});
|
|
1560
|
+
restoreStateChanged = true;
|
|
1561
|
+
}
|
|
1562
|
+
else if (!alreadyManaged) {
|
|
1563
|
+
ensureRestorePluginSnapshot(configPath, doc.plugin);
|
|
1564
|
+
}
|
|
1565
|
+
const pluginFilter = filteredOpenCodePlugins(doc.plugin);
|
|
1566
|
+
if (pluginFilter.changed) {
|
|
1567
|
+
doc.plugin = pluginFilter.next;
|
|
1568
|
+
}
|
|
1569
|
+
const managedOpenAiProvider = objectRecordOr(providerRoot[OPENAI_PROVIDER_ID], {});
|
|
1570
|
+
const optionsRoot = objectRecordOr(managedOpenAiProvider.options, {});
|
|
1571
|
+
optionsRoot.baseURL = `${trimTrailingSlash(params.backendUrl)}/api/codex-auth/v1/proxy/v1`;
|
|
1572
|
+
optionsRoot.apiKey = params.apiKey;
|
|
1573
|
+
managedOpenAiProvider.options = optionsRoot;
|
|
1574
|
+
managedOpenAiProvider.models = buildOpenCodeModelsObject(params.models);
|
|
1575
|
+
managedOpenAiProvider.whitelist = params.models.map((entry) => entry.id).filter(Boolean);
|
|
1576
|
+
if ("blacklist" in managedOpenAiProvider) {
|
|
1577
|
+
delete managedOpenAiProvider.blacklist;
|
|
1578
|
+
}
|
|
1579
|
+
providerRoot[OPENAI_PROVIDER_ID] = managedOpenAiProvider;
|
|
1580
|
+
if (DEFAULT_PROVIDER_ID in providerRoot) {
|
|
1581
|
+
delete providerRoot[DEFAULT_PROVIDER_ID];
|
|
1318
1582
|
}
|
|
1583
|
+
doc.$schema = params.schemaUrl;
|
|
1584
|
+
doc.provider = providerRoot;
|
|
1585
|
+
doc.model = `${OPENAI_PROVIDER_ID}/${params.model}`;
|
|
1586
|
+
await promises_1.default.writeFile(configPath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
1319
1587
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
return
|
|
1588
|
+
if (restoreState.targets.length > 0 && restoreStateChanged) {
|
|
1589
|
+
await writeJsonObjectFile(params.restoreStatePath, restoreState, 0o600);
|
|
1590
|
+
}
|
|
1591
|
+
return normalizedConfigPaths;
|
|
1592
|
+
}
|
|
1593
|
+
async function writeOpenCodeConfig(params) {
|
|
1594
|
+
return writeOpenCodeFamilyConfig({
|
|
1595
|
+
configPaths: resolveOpenCodeConfigTargets(),
|
|
1596
|
+
restoreStatePath: OPENCODE_RESTORE_STATE_PATH,
|
|
1597
|
+
schemaUrl: OPENCODE_CONFIG_SCHEMA_URL,
|
|
1598
|
+
...params,
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
async function writeKiloConfig(params) {
|
|
1602
|
+
return writeOpenCodeFamilyConfig({
|
|
1603
|
+
configPaths: resolveKiloConfigTargets(),
|
|
1604
|
+
restoreStatePath: KILO_RESTORE_STATE_PATH,
|
|
1605
|
+
schemaUrl: KILO_CONFIG_SCHEMA_URL,
|
|
1606
|
+
...params,
|
|
1607
|
+
});
|
|
1335
1608
|
}
|
|
1336
1609
|
function traePatchSnippet(params) {
|
|
1337
1610
|
const patchedModels = params.models.length
|
|
@@ -1512,8 +1785,8 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
1512
1785
|
let clineConfigPaths = [];
|
|
1513
1786
|
let openClawConfigPath = null;
|
|
1514
1787
|
let openClawCliWarning = null;
|
|
1515
|
-
let
|
|
1516
|
-
let
|
|
1788
|
+
let openCodeConfigPaths = [];
|
|
1789
|
+
let kiloConfigPaths = [];
|
|
1517
1790
|
let rooConfigPaths = [];
|
|
1518
1791
|
let traeBundlePathPatched = null;
|
|
1519
1792
|
let aiderConfigPath = null;
|
|
@@ -1577,7 +1850,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
1577
1850
|
}
|
|
1578
1851
|
if (selectedSetupClients.has("opencode")) {
|
|
1579
1852
|
progress.update("Configuring OpenCode");
|
|
1580
|
-
|
|
1853
|
+
openCodeConfigPaths = await writeOpenCodeConfig({
|
|
1581
1854
|
backendUrl,
|
|
1582
1855
|
model: resolved?.model ?? DEFAULT_CODEX_MODEL,
|
|
1583
1856
|
models: resolved?.models ?? [{ id: DEFAULT_CODEX_MODEL, name: modelDisplayName(DEFAULT_CODEX_MODEL) }],
|
|
@@ -1586,7 +1859,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
1586
1859
|
}
|
|
1587
1860
|
if (selectedSetupClients.has("kilo")) {
|
|
1588
1861
|
progress.update("Configuring Kilo Code");
|
|
1589
|
-
|
|
1862
|
+
kiloConfigPaths = await writeKiloConfig({
|
|
1590
1863
|
backendUrl,
|
|
1591
1864
|
model: resolved?.model ?? DEFAULT_CODEX_MODEL,
|
|
1592
1865
|
models: resolved?.models ?? [{ id: DEFAULT_CODEX_MODEL, name: modelDisplayName(DEFAULT_CODEX_MODEL) }],
|
|
@@ -1761,7 +2034,15 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
1761
2034
|
}
|
|
1762
2035
|
const openCodeDetected = setupClients.find((client) => client.id === "opencode")?.detected ?? false;
|
|
1763
2036
|
if (selectedSetupClients.has("opencode")) {
|
|
1764
|
-
this.log(`- OpenCode: configured (${
|
|
2037
|
+
this.log(`- OpenCode: configured (${openCodeConfigPaths.join(", ")})`);
|
|
2038
|
+
const openCodeProjectConfig = findOpenCodeProjectConfigFile();
|
|
2039
|
+
const openCodeConfigEnv = process.env.OPENCODE_CONFIG?.trim() || "";
|
|
2040
|
+
if (openCodeConfigEnv) {
|
|
2041
|
+
this.log(`- OpenCode note: OPENCODE_CONFIG is set (${openCodeConfigEnv}). OpenCode may load that file and override your global config.`);
|
|
2042
|
+
}
|
|
2043
|
+
if (openCodeProjectConfig) {
|
|
2044
|
+
this.log(`- OpenCode note: found project-level ${node_path_1.default.basename(openCodeProjectConfig)} at ${openCodeProjectConfig} which overrides global config.`);
|
|
2045
|
+
}
|
|
1765
2046
|
}
|
|
1766
2047
|
else if (openCodeDetected) {
|
|
1767
2048
|
this.log("- OpenCode: detected but skipped");
|
|
@@ -1770,7 +2051,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
1770
2051
|
this.log("- OpenCode: not detected (skipped)");
|
|
1771
2052
|
}
|
|
1772
2053
|
if (selectedSetupClients.has("kilo")) {
|
|
1773
|
-
this.log(`- Kilo Code: configured (${
|
|
2054
|
+
this.log(`- Kilo Code: configured (${kiloConfigPaths.join(", ")})`);
|
|
1774
2055
|
}
|
|
1775
2056
|
else if (kiloDetected) {
|
|
1776
2057
|
this.log("- Kilo Code: detected but skipped");
|
package/package.json
CHANGED