theclawbay 0.3.26 → 0.3.28
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 +10 -4
- package/dist/commands/logout.js +218 -1
- package/dist/commands/setup.js +547 -15
- package/dist/lib/config/paths.d.ts +2 -0
- package/dist/lib/config/paths.js +3 -1
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# theclawbay
|
|
2
2
|
|
|
3
|
-
CLI for connecting Codex, OpenClaw, OpenCode, Kilo, and experimental Trae to The Claw Bay.
|
|
3
|
+
CLI for connecting Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, and experimental Trae to The Claw Bay.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -16,9 +16,15 @@ Get your API key from `https://theclawbay.com/dashboard`.
|
|
|
16
16
|
theclawbay setup --api-key <apiKey>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
In an interactive terminal, setup shows one picker for Codex, OpenClaw, OpenCode, Kilo, and Windows Trae.
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
In an interactive terminal, setup shows one picker for Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, and Windows Trae.
|
|
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
|
+
|
|
22
|
+
History notes:
|
|
23
|
+
|
|
24
|
+
- Continue setup only updates `~/.continue/config.yaml` and leaves `~/.continue/sessions` untouched.
|
|
25
|
+
- Cline setup only updates `~/.cline/data/globalState.json` and `~/.cline/data/secrets.json`; task history stays in `~/.cline/state` and `~/.cline/tasks`.
|
|
26
|
+
- Roo Code setup uses a managed auto-import file plus editor settings and does not touch task history. Imported Roo profiles can persist inside Roo after first launch.
|
|
27
|
+
- Aider setup appends a managed block to `~/.aider.conf.yml` and enables `restore-chat-history: true` without touching `.aider.chat.history.md`.
|
|
22
28
|
|
|
23
29
|
## Optional
|
|
24
30
|
|
package/dist/commands/logout.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
7
7
|
const node_os_1 = __importDefault(require("node:os"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const yaml_1 = require("yaml");
|
|
9
10
|
const base_command_1 = require("../lib/base-command");
|
|
10
11
|
const codex_auth_seeding_1 = require("../lib/codex-auth-seeding");
|
|
11
12
|
const codex_history_migration_1 = require("../lib/codex-history-migration");
|
|
@@ -16,10 +17,19 @@ const DEFAULT_PROVIDER_ID = "theclawbay";
|
|
|
16
17
|
const WAN_PROVIDER_ID = "theclawbay-wan";
|
|
17
18
|
const MANAGED_START = "# theclawbay-managed:start";
|
|
18
19
|
const MANAGED_END = "# theclawbay-managed:end";
|
|
20
|
+
const AIDER_MANAGED_START = "# theclawbay-aider-managed:start";
|
|
21
|
+
const AIDER_MANAGED_END = "# theclawbay-aider-managed:end";
|
|
19
22
|
const SHELL_START = "# theclawbay-shell-managed:start";
|
|
20
23
|
const SHELL_END = "# theclawbay-shell-managed:end";
|
|
21
|
-
const ENV_FILE = node_path_1.default.join(
|
|
24
|
+
const ENV_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "env");
|
|
22
25
|
const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
|
|
26
|
+
const CONTINUE_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.yaml");
|
|
27
|
+
const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "globalState.json");
|
|
28
|
+
const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
|
|
29
|
+
const AIDER_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yml");
|
|
30
|
+
const CLINE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "cline.restore.json");
|
|
31
|
+
const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
|
|
32
|
+
const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
|
|
23
33
|
const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
|
|
24
34
|
const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set([
|
|
25
35
|
OPENAI_PROVIDER_ID,
|
|
@@ -27,6 +37,8 @@ const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set([
|
|
|
27
37
|
DEFAULT_PROVIDER_ID,
|
|
28
38
|
]);
|
|
29
39
|
const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = [DEFAULT_PROVIDER_ID, WAN_PROVIDER_ID];
|
|
40
|
+
const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
|
|
41
|
+
const CONTINUE_MODEL_NAME = "The Claw Bay";
|
|
30
42
|
const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
|
|
31
43
|
const TRAE_BUNDLE_BACKUP_SUFFIX = ".theclawbay-managed-backup";
|
|
32
44
|
function removeManagedBlock(source, start, end) {
|
|
@@ -125,6 +137,61 @@ function objectRecordOr(value, fallback) {
|
|
|
125
137
|
return { ...value };
|
|
126
138
|
return fallback;
|
|
127
139
|
}
|
|
140
|
+
function isTheClawBayOpenAiCompatibleBaseUrl(value) {
|
|
141
|
+
return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
|
|
142
|
+
}
|
|
143
|
+
async function readJsonObjectFile(filePath) {
|
|
144
|
+
const existingRaw = await readFileIfExists(filePath);
|
|
145
|
+
if (existingRaw === null || !existingRaw.trim())
|
|
146
|
+
return {};
|
|
147
|
+
try {
|
|
148
|
+
return objectRecordOr(JSON.parse(existingRaw), {});
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return {};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function writeJsonFile(filePath, value, mode) {
|
|
155
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(filePath), { recursive: true });
|
|
156
|
+
await promises_1.default.writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
157
|
+
if (mode !== undefined)
|
|
158
|
+
await promises_1.default.chmod(filePath, mode);
|
|
159
|
+
}
|
|
160
|
+
function roamingAppDataDir() {
|
|
161
|
+
if (process.env.APPDATA?.trim())
|
|
162
|
+
return process.env.APPDATA;
|
|
163
|
+
return node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Roaming");
|
|
164
|
+
}
|
|
165
|
+
function editorSettingsCandidates() {
|
|
166
|
+
const home = node_os_1.default.homedir();
|
|
167
|
+
if (node_os_1.default.platform() === "darwin") {
|
|
168
|
+
const appSupport = node_path_1.default.join(home, "Library", "Application Support");
|
|
169
|
+
return [
|
|
170
|
+
node_path_1.default.join(appSupport, "Code", "User", "settings.json"),
|
|
171
|
+
node_path_1.default.join(appSupport, "Code - Insiders", "User", "settings.json"),
|
|
172
|
+
node_path_1.default.join(appSupport, "Cursor", "User", "settings.json"),
|
|
173
|
+
node_path_1.default.join(appSupport, "Windsurf", "User", "settings.json"),
|
|
174
|
+
node_path_1.default.join(appSupport, "VSCodium", "User", "settings.json"),
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
if (node_os_1.default.platform() === "win32") {
|
|
178
|
+
const appData = roamingAppDataDir();
|
|
179
|
+
return [
|
|
180
|
+
node_path_1.default.join(appData, "Code", "User", "settings.json"),
|
|
181
|
+
node_path_1.default.join(appData, "Code - Insiders", "User", "settings.json"),
|
|
182
|
+
node_path_1.default.join(appData, "Cursor", "User", "settings.json"),
|
|
183
|
+
node_path_1.default.join(appData, "Windsurf", "User", "settings.json"),
|
|
184
|
+
node_path_1.default.join(appData, "VSCodium", "User", "settings.json"),
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
return [
|
|
188
|
+
node_path_1.default.join(home, ".config", "Code", "User", "settings.json"),
|
|
189
|
+
node_path_1.default.join(home, ".config", "Code - Insiders", "User", "settings.json"),
|
|
190
|
+
node_path_1.default.join(home, ".config", "Cursor", "User", "settings.json"),
|
|
191
|
+
node_path_1.default.join(home, ".config", "Windsurf", "User", "settings.json"),
|
|
192
|
+
node_path_1.default.join(home, ".config", "VSCodium", "User", "settings.json"),
|
|
193
|
+
];
|
|
194
|
+
}
|
|
128
195
|
async function cleanupCodexConfig() {
|
|
129
196
|
const configPath = node_path_1.default.join(paths_1.codexDir, "config.toml");
|
|
130
197
|
const existing = await readFileIfExists(configPath);
|
|
@@ -136,6 +203,148 @@ async function cleanupCodexConfig() {
|
|
|
136
203
|
next = removeTopLevelProviderSelection(next);
|
|
137
204
|
return writeIfChanged(configPath, next, existing);
|
|
138
205
|
}
|
|
206
|
+
async function cleanupContinueConfig() {
|
|
207
|
+
const existing = await readFileIfExists(CONTINUE_CONFIG_PATH);
|
|
208
|
+
if (existing === null || !existing.trim())
|
|
209
|
+
return false;
|
|
210
|
+
try {
|
|
211
|
+
const doc = (0, yaml_1.parseDocument)(existing);
|
|
212
|
+
const root = objectRecordOr(doc.toJS(), {});
|
|
213
|
+
const models = Array.isArray(root.models) ? root.models : [];
|
|
214
|
+
const filtered = models.filter((entry) => {
|
|
215
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry))
|
|
216
|
+
return true;
|
|
217
|
+
const candidate = entry;
|
|
218
|
+
return !(candidate.provider === "openai" &&
|
|
219
|
+
candidate.name === CONTINUE_MODEL_NAME &&
|
|
220
|
+
isTheClawBayOpenAiCompatibleBaseUrl(candidate.apiBase));
|
|
221
|
+
});
|
|
222
|
+
if (filtered.length === models.length)
|
|
223
|
+
return false;
|
|
224
|
+
doc.set("models", filtered);
|
|
225
|
+
await promises_1.default.writeFile(CONTINUE_CONFIG_PATH, doc.toString(), "utf8");
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function cleanupClineConfig() {
|
|
233
|
+
const globalState = await readJsonObjectFile(CLINE_GLOBAL_STATE_PATH);
|
|
234
|
+
const secrets = await readJsonObjectFile(CLINE_SECRETS_PATH);
|
|
235
|
+
const snapshotRaw = await readFileIfExists(CLINE_RESTORE_STATE_PATH);
|
|
236
|
+
let changed = false;
|
|
237
|
+
if (snapshotRaw?.trim()) {
|
|
238
|
+
try {
|
|
239
|
+
const snapshot = JSON.parse(snapshotRaw);
|
|
240
|
+
for (const [key, value] of Object.entries(snapshot.globalState ?? {})) {
|
|
241
|
+
if (value === null) {
|
|
242
|
+
if (key in globalState) {
|
|
243
|
+
delete globalState[key];
|
|
244
|
+
changed = true;
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (globalState[key] !== value) {
|
|
249
|
+
globalState[key] = value;
|
|
250
|
+
changed = true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
for (const [key, value] of Object.entries(snapshot.secrets ?? {})) {
|
|
254
|
+
if (value === null) {
|
|
255
|
+
if (key in secrets) {
|
|
256
|
+
delete secrets[key];
|
|
257
|
+
changed = true;
|
|
258
|
+
}
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (secrets[key] !== value) {
|
|
262
|
+
secrets[key] = value;
|
|
263
|
+
changed = true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// Fall through to best-effort cleanup below.
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
if (globalState.planModeApiProvider === OPENAI_PROVIDER_ID) {
|
|
273
|
+
delete globalState.planModeApiProvider;
|
|
274
|
+
changed = true;
|
|
275
|
+
}
|
|
276
|
+
if (globalState.actModeApiProvider === OPENAI_PROVIDER_ID) {
|
|
277
|
+
delete globalState.actModeApiProvider;
|
|
278
|
+
changed = true;
|
|
279
|
+
}
|
|
280
|
+
if (isTheClawBayOpenAiCompatibleBaseUrl(globalState.openAiBaseUrl)) {
|
|
281
|
+
delete globalState.openAiBaseUrl;
|
|
282
|
+
changed = true;
|
|
283
|
+
}
|
|
284
|
+
for (const key of ["planModeOpenAiModelId", "actModeOpenAiModelId"]) {
|
|
285
|
+
if (typeof globalState[key] === "string") {
|
|
286
|
+
delete globalState[key];
|
|
287
|
+
changed = true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (typeof secrets.openAiApiKey === "string") {
|
|
291
|
+
delete secrets.openAiApiKey;
|
|
292
|
+
changed = true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (changed) {
|
|
296
|
+
await writeJsonFile(CLINE_GLOBAL_STATE_PATH, globalState);
|
|
297
|
+
await writeJsonFile(CLINE_SECRETS_PATH, secrets, 0o600);
|
|
298
|
+
}
|
|
299
|
+
await removeFileIfExists(CLINE_RESTORE_STATE_PATH);
|
|
300
|
+
return changed;
|
|
301
|
+
}
|
|
302
|
+
async function cleanupRooConfig() {
|
|
303
|
+
const snapshotRaw = await readFileIfExists(ROO_SETTINGS_STATE_PATH);
|
|
304
|
+
let changed = false;
|
|
305
|
+
if (snapshotRaw?.trim()) {
|
|
306
|
+
try {
|
|
307
|
+
const entries = JSON.parse(snapshotRaw);
|
|
308
|
+
for (const entry of entries) {
|
|
309
|
+
const settings = await readJsonObjectFile(entry.settingsPath);
|
|
310
|
+
const currentValue = settings["roo-cline.autoImportSettingsPath"];
|
|
311
|
+
if (currentValue !== ROO_IMPORT_FILE)
|
|
312
|
+
continue;
|
|
313
|
+
if (entry.previousValue === null) {
|
|
314
|
+
delete settings["roo-cline.autoImportSettingsPath"];
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
settings["roo-cline.autoImportSettingsPath"] = entry.previousValue;
|
|
318
|
+
}
|
|
319
|
+
await writeJsonFile(entry.settingsPath, settings);
|
|
320
|
+
changed = true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
// Fall back to common editor settings paths below.
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (!changed) {
|
|
328
|
+
for (const settingsPath of editorSettingsCandidates()) {
|
|
329
|
+
const settings = await readJsonObjectFile(settingsPath);
|
|
330
|
+
if (settings["roo-cline.autoImportSettingsPath"] !== ROO_IMPORT_FILE)
|
|
331
|
+
continue;
|
|
332
|
+
delete settings["roo-cline.autoImportSettingsPath"];
|
|
333
|
+
await writeJsonFile(settingsPath, settings);
|
|
334
|
+
changed = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const removedImport = await removeFileIfExists(ROO_IMPORT_FILE);
|
|
338
|
+
await removeFileIfExists(ROO_SETTINGS_STATE_PATH);
|
|
339
|
+
return changed || removedImport;
|
|
340
|
+
}
|
|
341
|
+
async function cleanupAiderConfig() {
|
|
342
|
+
const existing = await readFileIfExists(AIDER_CONFIG_PATH);
|
|
343
|
+
if (existing === null)
|
|
344
|
+
return false;
|
|
345
|
+
const next = removeManagedBlock(existing, AIDER_MANAGED_START, AIDER_MANAGED_END);
|
|
346
|
+
return writeIfChanged(AIDER_CONFIG_PATH, next, existing);
|
|
347
|
+
}
|
|
139
348
|
async function cleanupShellFiles() {
|
|
140
349
|
const updated = [];
|
|
141
350
|
const shellRcPaths = [".bashrc", ".zshrc", ".profile"].map((name) => node_path_1.default.join(node_os_1.default.homedir(), name));
|
|
@@ -296,10 +505,14 @@ class LogoutCommand extends base_command_1.BaseCommand {
|
|
|
296
505
|
const updatedShellFiles = await cleanupShellFiles();
|
|
297
506
|
const updatedVsCodeHooks = await cleanupVsCodeHooks();
|
|
298
507
|
const updatedCodexConfig = await cleanupCodexConfig();
|
|
508
|
+
const updatedContinueConfig = await cleanupContinueConfig();
|
|
509
|
+
const updatedClineConfig = await cleanupClineConfig();
|
|
299
510
|
const updatedOpenClawConfig = await cleanupOpenClawConfig();
|
|
300
511
|
const updatedOpenCodeConfig = await cleanupOpenCodeConfig();
|
|
301
512
|
const updatedKiloConfig = await cleanupKiloConfig();
|
|
513
|
+
const updatedRooConfig = await cleanupRooConfig();
|
|
302
514
|
const updatedTraeBundle = await cleanupTraeBundle();
|
|
515
|
+
const updatedAiderConfig = await cleanupAiderConfig();
|
|
303
516
|
const sessionMigration = await (0, codex_history_migration_1.migrateSessionProviders)({
|
|
304
517
|
codexHome: paths_1.codexDir,
|
|
305
518
|
migrationStateFile: MIGRATION_STATE_FILE,
|
|
@@ -368,10 +581,14 @@ class LogoutCommand extends base_command_1.BaseCommand {
|
|
|
368
581
|
else {
|
|
369
582
|
this.log("- Codex model cache: no cleanup needed.");
|
|
370
583
|
}
|
|
584
|
+
this.log(`- Continue config cleaned: ${updatedContinueConfig ? "yes" : "no"}`);
|
|
585
|
+
this.log(`- Cline config cleaned: ${updatedClineConfig ? "yes" : "no"}`);
|
|
371
586
|
this.log(`- OpenClaw config cleaned: ${updatedOpenClawConfig ? "yes" : "no"}`);
|
|
372
587
|
this.log(`- OpenCode config cleaned: ${updatedOpenCodeConfig ? "yes" : "no"}`);
|
|
373
588
|
this.log(`- Kilo config cleaned: ${updatedKiloConfig ? "yes" : "no"}`);
|
|
589
|
+
this.log(`- Roo Code setup hook cleaned: ${updatedRooConfig ? "yes" : "no"}`);
|
|
374
590
|
this.log(`- Trae experimental patch cleaned: ${updatedTraeBundle ? "yes" : "no"}`);
|
|
591
|
+
this.log(`- Aider config cleaned: ${updatedAiderConfig ? "yes" : "no"}`);
|
|
375
592
|
this.log("Note: restart terminals/VS Code windows to clear already-loaded shell environment.");
|
|
376
593
|
});
|
|
377
594
|
}
|
package/dist/commands/setup.js
CHANGED
|
@@ -10,6 +10,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
10
10
|
const node_readline_1 = require("node:readline");
|
|
11
11
|
const node_child_process_1 = require("node:child_process");
|
|
12
12
|
const core_1 = require("@oclif/core");
|
|
13
|
+
const yaml_1 = require("yaml");
|
|
13
14
|
const base_command_1 = require("../lib/base-command");
|
|
14
15
|
const codex_auth_seeding_1 = require("../lib/codex-auth-seeding");
|
|
15
16
|
const codex_history_migration_1 = require("../lib/codex-history-migration");
|
|
@@ -25,22 +26,40 @@ const CLI_HTTP_USER_AGENT = "theclawbay-cli";
|
|
|
25
26
|
const SUPPORTED_MODEL_IDS = (0, supported_models_1.getSupportedModelIds)();
|
|
26
27
|
const MODEL_DISPLAY_NAMES = (0, supported_models_1.getSupportedModelDisplayNames)();
|
|
27
28
|
const DEFAULT_CODEX_MODEL = SUPPORTED_MODEL_IDS[0] ?? "gpt-5.4";
|
|
29
|
+
const DEFAULT_CONTINUE_MODEL = DEFAULT_CODEX_MODEL;
|
|
30
|
+
const DEFAULT_CLINE_MODEL = DEFAULT_CODEX_MODEL;
|
|
28
31
|
const DEFAULT_OPENCLAW_MODEL = DEFAULT_CODEX_MODEL;
|
|
29
32
|
const DEFAULT_KILO_MODEL = DEFAULT_CODEX_MODEL;
|
|
33
|
+
const DEFAULT_ROO_MODEL = DEFAULT_CODEX_MODEL;
|
|
30
34
|
const DEFAULT_TRAE_MODEL = DEFAULT_CODEX_MODEL;
|
|
35
|
+
const DEFAULT_AIDER_MODEL = DEFAULT_CODEX_MODEL;
|
|
31
36
|
const DEFAULT_MODELS = [...SUPPORTED_MODEL_IDS];
|
|
32
37
|
const PREFERRED_MODELS = [...SUPPORTED_MODEL_IDS];
|
|
33
38
|
const ENV_KEY_NAME = "THECLAWBAY_API_KEY";
|
|
34
|
-
const ENV_FILE = node_path_1.default.join(
|
|
39
|
+
const ENV_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "env");
|
|
40
|
+
const CONTINUE_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.yaml");
|
|
41
|
+
const CLINE_GLOBAL_STATE_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "globalState.json");
|
|
42
|
+
const CLINE_SECRETS_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".cline", "data", "secrets.json");
|
|
43
|
+
const AIDER_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yml");
|
|
44
|
+
const CLINE_RESTORE_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "cline.restore.json");
|
|
45
|
+
const ROO_SETTINGS_STATE_PATH = node_path_1.default.join(paths_1.theclawbayStateDir, "roo-settings.restore.json");
|
|
46
|
+
const ROO_IMPORT_FILE = node_path_1.default.join(paths_1.theclawbayConfigDir, "roo-code-settings.json");
|
|
35
47
|
const MIGRATION_STATE_FILE = node_path_1.default.join(paths_1.codexDir, "theclawbay.migration.json");
|
|
36
48
|
const MANAGED_START = "# theclawbay-managed:start";
|
|
37
49
|
const MANAGED_END = "# theclawbay-managed:end";
|
|
50
|
+
const AIDER_MANAGED_START = "# theclawbay-aider-managed:start";
|
|
51
|
+
const AIDER_MANAGED_END = "# theclawbay-aider-managed:end";
|
|
38
52
|
const SHELL_START = "# theclawbay-shell-managed:start";
|
|
39
53
|
const SHELL_END = "# theclawbay-shell-managed:end";
|
|
40
54
|
const OPENCLAW_PROVIDER_ID = DEFAULT_PROVIDER_ID;
|
|
41
55
|
const HISTORY_PROVIDER_NEUTRALIZE_SOURCES = new Set(["openai", "theclawbay-wan", DEFAULT_PROVIDER_ID]);
|
|
42
56
|
const HISTORY_PROVIDER_DB_MIGRATE_SOURCES = ["openai", "theclawbay-wan"];
|
|
43
|
-
const SETUP_CLIENT_IDS = ["codex", "openclaw", "opencode", "kilo", "trae"];
|
|
57
|
+
const SETUP_CLIENT_IDS = ["codex", "continue", "cline", "openclaw", "opencode", "kilo", "roo", "trae", "aider"];
|
|
58
|
+
const THECLAWBAY_OPENAI_PROXY_SUFFIX = "/api/codex-auth/v1/proxy/v1";
|
|
59
|
+
const CONTINUE_MODEL_NAME = "The Claw Bay";
|
|
60
|
+
const ROO_PROFILE_NAME = "The Claw Bay";
|
|
61
|
+
const ROO_PROFILE_ID = "theclawbay-openai-compatible";
|
|
62
|
+
const ROO_MODE_SLUGS = ["architect", "code", "ask", "debug", "orchestrator"];
|
|
44
63
|
const TRAE_PATCH_MARKER = "theclawbay-trae-patch";
|
|
45
64
|
const TRAE_BUNDLE_BACKUP_SUFFIX = ".theclawbay-managed-backup";
|
|
46
65
|
const TRAE_TARGET_FUNCTION_START = "async setOriginModelListMapAndCache(e,t=!0){";
|
|
@@ -62,6 +81,49 @@ function hasCommand(name) {
|
|
|
62
81
|
const result = (0, node_child_process_1.spawnSync)(lookupCommand, [name], { stdio: "ignore" });
|
|
63
82
|
return result.status === 0;
|
|
64
83
|
}
|
|
84
|
+
function supportsTerminalHyperlinks() {
|
|
85
|
+
if (!process.stdout.isTTY)
|
|
86
|
+
return false;
|
|
87
|
+
if (process.env.FORCE_HYPERLINK === "1")
|
|
88
|
+
return true;
|
|
89
|
+
if (process.env.NO_HYPERLINK === "1")
|
|
90
|
+
return false;
|
|
91
|
+
const term = (process.env.TERM ?? "").toLowerCase();
|
|
92
|
+
if (!term || term === "dumb")
|
|
93
|
+
return false;
|
|
94
|
+
const termProgram = (process.env.TERM_PROGRAM ?? "").toLowerCase();
|
|
95
|
+
if (termProgram === "iterm.app" || termProgram === "wezterm" || termProgram === "vscode") {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (process.env.WT_SESSION ||
|
|
99
|
+
process.env.KITTY_WINDOW_ID ||
|
|
100
|
+
process.env.KONSOLE_VERSION ||
|
|
101
|
+
process.env.VTE_VERSION ||
|
|
102
|
+
process.env.DOMTERM ||
|
|
103
|
+
process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm") {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return term.includes("xterm-kitty") || term.includes("foot") || term.includes("wezterm");
|
|
107
|
+
}
|
|
108
|
+
function formatTerminalHyperlink(label, url) {
|
|
109
|
+
return `\u001B]8;;${url}\u0007${label}\u001B]8;;\u0007`;
|
|
110
|
+
}
|
|
111
|
+
function formatDim(value) {
|
|
112
|
+
return `\u001B[2m${value}\u001B[0m`;
|
|
113
|
+
}
|
|
114
|
+
function officialSiteLabel(siteUrl) {
|
|
115
|
+
const parsed = new URL(siteUrl);
|
|
116
|
+
const hostname = parsed.hostname.replace(/^www\./, "");
|
|
117
|
+
const pathname = parsed.pathname.replace(/\/+$/g, "");
|
|
118
|
+
return pathname && pathname !== "/" ? `${hostname}${pathname}` : hostname;
|
|
119
|
+
}
|
|
120
|
+
function formatSetupClientLabel(client, hyperlinksEnabled) {
|
|
121
|
+
const iconAndLabel = `${client.icon} ${client.label}`;
|
|
122
|
+
if (hyperlinksEnabled) {
|
|
123
|
+
return `${formatTerminalHyperlink(iconAndLabel, client.siteUrl)} ${formatDim(`(${officialSiteLabel(client.siteUrl)})`)}`;
|
|
124
|
+
}
|
|
125
|
+
return `${iconAndLabel} - ${client.siteUrl}`;
|
|
126
|
+
}
|
|
65
127
|
function localAppDataDir() {
|
|
66
128
|
if (process.env.LOCALAPPDATA?.trim())
|
|
67
129
|
return process.env.LOCALAPPDATA;
|
|
@@ -175,6 +237,168 @@ function shellQuote(value) {
|
|
|
175
237
|
function modelDisplayName(modelId) {
|
|
176
238
|
return MODEL_DISPLAY_NAMES[modelId] ?? modelId;
|
|
177
239
|
}
|
|
240
|
+
function openAiCompatibleProxyUrl(backendUrl) {
|
|
241
|
+
return `${trimTrailingSlash(backendUrl)}${THECLAWBAY_OPENAI_PROXY_SUFFIX}`;
|
|
242
|
+
}
|
|
243
|
+
function isTheClawBayOpenAiCompatibleBaseUrl(value) {
|
|
244
|
+
return typeof value === "string" && value.trim().endsWith(THECLAWBAY_OPENAI_PROXY_SUFFIX);
|
|
245
|
+
}
|
|
246
|
+
function roamingAppDataDir() {
|
|
247
|
+
if (process.env.APPDATA?.trim())
|
|
248
|
+
return process.env.APPDATA;
|
|
249
|
+
return node_path_1.default.join(node_os_1.default.homedir(), "AppData", "Roaming");
|
|
250
|
+
}
|
|
251
|
+
async function readFileIfExists(filePath) {
|
|
252
|
+
try {
|
|
253
|
+
return await promises_1.default.readFile(filePath, "utf8");
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
const err = error;
|
|
257
|
+
if (err.code === "ENOENT")
|
|
258
|
+
return null;
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async function readJsonObjectFile(filePath) {
|
|
263
|
+
const existingRaw = await readFileIfExists(filePath);
|
|
264
|
+
if (existingRaw === null || !existingRaw.trim())
|
|
265
|
+
return {};
|
|
266
|
+
try {
|
|
267
|
+
return objectRecordOr(JSON.parse(existingRaw), {});
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
throw new Error(`invalid JSON in ${filePath}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function writeJsonObjectFile(filePath, doc, mode) {
|
|
274
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(filePath), { recursive: true });
|
|
275
|
+
await promises_1.default.writeFile(filePath, `${JSON.stringify(doc, null, 2)}\n`, "utf8");
|
|
276
|
+
if (mode !== undefined)
|
|
277
|
+
await promises_1.default.chmod(filePath, mode);
|
|
278
|
+
}
|
|
279
|
+
function editorHosts() {
|
|
280
|
+
const home = node_os_1.default.homedir();
|
|
281
|
+
if (node_os_1.default.platform() === "darwin") {
|
|
282
|
+
const appSupport = node_path_1.default.join(home, "Library", "Application Support");
|
|
283
|
+
return [
|
|
284
|
+
{
|
|
285
|
+
id: "vscode",
|
|
286
|
+
label: "VS Code",
|
|
287
|
+
extensionDir: node_path_1.default.join(home, ".vscode", "extensions"),
|
|
288
|
+
userSettingsPath: node_path_1.default.join(appSupport, "Code", "User", "settings.json"),
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
id: "vscode-insiders",
|
|
292
|
+
label: "VS Code Insiders",
|
|
293
|
+
extensionDir: node_path_1.default.join(home, ".vscode-insiders", "extensions"),
|
|
294
|
+
userSettingsPath: node_path_1.default.join(appSupport, "Code - Insiders", "User", "settings.json"),
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: "cursor",
|
|
298
|
+
label: "Cursor",
|
|
299
|
+
extensionDir: node_path_1.default.join(home, ".cursor", "extensions"),
|
|
300
|
+
userSettingsPath: node_path_1.default.join(appSupport, "Cursor", "User", "settings.json"),
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
id: "windsurf",
|
|
304
|
+
label: "Windsurf",
|
|
305
|
+
extensionDir: node_path_1.default.join(home, ".windsurf", "extensions"),
|
|
306
|
+
userSettingsPath: node_path_1.default.join(appSupport, "Windsurf", "User", "settings.json"),
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: "vscodium",
|
|
310
|
+
label: "VSCodium",
|
|
311
|
+
extensionDir: node_path_1.default.join(home, ".vscode-oss", "extensions"),
|
|
312
|
+
userSettingsPath: node_path_1.default.join(appSupport, "VSCodium", "User", "settings.json"),
|
|
313
|
+
},
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
if (node_os_1.default.platform() === "win32") {
|
|
317
|
+
const homeDir = process.env.USERPROFILE?.trim() || home;
|
|
318
|
+
const appData = roamingAppDataDir();
|
|
319
|
+
return [
|
|
320
|
+
{
|
|
321
|
+
id: "vscode",
|
|
322
|
+
label: "VS Code",
|
|
323
|
+
extensionDir: node_path_1.default.join(homeDir, ".vscode", "extensions"),
|
|
324
|
+
userSettingsPath: node_path_1.default.join(appData, "Code", "User", "settings.json"),
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
id: "vscode-insiders",
|
|
328
|
+
label: "VS Code Insiders",
|
|
329
|
+
extensionDir: node_path_1.default.join(homeDir, ".vscode-insiders", "extensions"),
|
|
330
|
+
userSettingsPath: node_path_1.default.join(appData, "Code - Insiders", "User", "settings.json"),
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: "cursor",
|
|
334
|
+
label: "Cursor",
|
|
335
|
+
extensionDir: node_path_1.default.join(homeDir, ".cursor", "extensions"),
|
|
336
|
+
userSettingsPath: node_path_1.default.join(appData, "Cursor", "User", "settings.json"),
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
id: "windsurf",
|
|
340
|
+
label: "Windsurf",
|
|
341
|
+
extensionDir: node_path_1.default.join(homeDir, ".windsurf", "extensions"),
|
|
342
|
+
userSettingsPath: node_path_1.default.join(appData, "Windsurf", "User", "settings.json"),
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
id: "vscodium",
|
|
346
|
+
label: "VSCodium",
|
|
347
|
+
extensionDir: node_path_1.default.join(homeDir, ".vscode-oss", "extensions"),
|
|
348
|
+
userSettingsPath: node_path_1.default.join(appData, "VSCodium", "User", "settings.json"),
|
|
349
|
+
},
|
|
350
|
+
];
|
|
351
|
+
}
|
|
352
|
+
return [
|
|
353
|
+
{
|
|
354
|
+
id: "vscode",
|
|
355
|
+
label: "VS Code",
|
|
356
|
+
extensionDir: node_path_1.default.join(home, ".vscode", "extensions"),
|
|
357
|
+
userSettingsPath: node_path_1.default.join(home, ".config", "Code", "User", "settings.json"),
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: "vscode-insiders",
|
|
361
|
+
label: "VS Code Insiders",
|
|
362
|
+
extensionDir: node_path_1.default.join(home, ".vscode-insiders", "extensions"),
|
|
363
|
+
userSettingsPath: node_path_1.default.join(home, ".config", "Code - Insiders", "User", "settings.json"),
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
id: "cursor",
|
|
367
|
+
label: "Cursor",
|
|
368
|
+
extensionDir: node_path_1.default.join(home, ".cursor", "extensions"),
|
|
369
|
+
userSettingsPath: node_path_1.default.join(home, ".config", "Cursor", "User", "settings.json"),
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
id: "windsurf",
|
|
373
|
+
label: "Windsurf",
|
|
374
|
+
extensionDir: node_path_1.default.join(home, ".windsurf", "extensions"),
|
|
375
|
+
userSettingsPath: node_path_1.default.join(home, ".config", "Windsurf", "User", "settings.json"),
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: "vscodium",
|
|
379
|
+
label: "VSCodium",
|
|
380
|
+
extensionDir: node_path_1.default.join(home, ".vscode-oss", "extensions"),
|
|
381
|
+
userSettingsPath: node_path_1.default.join(home, ".config", "VSCodium", "User", "settings.json"),
|
|
382
|
+
},
|
|
383
|
+
];
|
|
384
|
+
}
|
|
385
|
+
async function detectExtensionHosts(prefixes) {
|
|
386
|
+
const matches = [];
|
|
387
|
+
for (const host of editorHosts()) {
|
|
388
|
+
if (!(await pathExists(host.extensionDir)))
|
|
389
|
+
continue;
|
|
390
|
+
const entries = (0, node_fs_1.readdirSync)(host.extensionDir, { withFileTypes: true });
|
|
391
|
+
const found = entries.some((entry) => {
|
|
392
|
+
if (!entry.isDirectory())
|
|
393
|
+
return false;
|
|
394
|
+
const normalized = entry.name.toLowerCase();
|
|
395
|
+
return prefixes.some((prefix) => normalized.startsWith(prefix));
|
|
396
|
+
});
|
|
397
|
+
if (found)
|
|
398
|
+
matches.push(host);
|
|
399
|
+
}
|
|
400
|
+
return matches;
|
|
401
|
+
}
|
|
178
402
|
function parseSetupClientFlags(raw) {
|
|
179
403
|
if (!raw)
|
|
180
404
|
return null;
|
|
@@ -205,12 +429,13 @@ async function promptForSetupClients(clients) {
|
|
|
205
429
|
let cursor = 0;
|
|
206
430
|
let settled = false;
|
|
207
431
|
let hint = clients.some((client) => client.detected)
|
|
208
|
-
? "
|
|
209
|
-
: "No supported local clients are detected yet.
|
|
432
|
+
? "Choose the tools you want to configure."
|
|
433
|
+
: "No supported local clients are detected yet. Apply setup will just save your managed config and API key env.";
|
|
210
434
|
const stdin = process.stdin;
|
|
211
435
|
const stdout = process.stdout;
|
|
212
436
|
const wasRaw = stdin.isRaw;
|
|
213
|
-
const
|
|
437
|
+
const applyIndex = options.length;
|
|
438
|
+
const hyperlinksEnabled = supportsTerminalHyperlinks();
|
|
214
439
|
const clearScreen = () => {
|
|
215
440
|
stdout.write("\x1b[2J\x1b[H");
|
|
216
441
|
};
|
|
@@ -219,15 +444,16 @@ async function promptForSetupClients(clients) {
|
|
|
219
444
|
clearScreen();
|
|
220
445
|
stdout.write("Choose local clients to configure\n");
|
|
221
446
|
stdout.write(`Use ↑/↓ to move, Enter to toggle the highlighted integration, or press 1-${options.length} to toggle directly.\n`);
|
|
222
|
-
stdout.write("
|
|
447
|
+
stdout.write("Each tool name links to its official site when your terminal supports it.\n");
|
|
448
|
+
stdout.write("Move to Apply setup and press Enter when you're ready.\n\n");
|
|
223
449
|
for (const [index, option] of options.entries()) {
|
|
224
450
|
const pointer = index === cursor ? ">" : " ";
|
|
225
451
|
const mark = option.detected ? (option.checked ? "[x]" : "[ ]") : "[-]";
|
|
226
452
|
const badge = option.detected ? (option.recommended ? "recommended" : "optional") : "not detected";
|
|
227
|
-
stdout.write(`${pointer} ${index + 1}. ${mark} ${option
|
|
453
|
+
stdout.write(`${pointer} ${index + 1}. ${mark} ${formatSetupClientLabel(option, hyperlinksEnabled)} ${badge}\n`);
|
|
228
454
|
}
|
|
229
|
-
const
|
|
230
|
-
stdout.write(`${
|
|
455
|
+
const applyPointer = cursor === applyIndex ? ">" : " ";
|
|
456
|
+
stdout.write(`${applyPointer} Apply setup with ${selectedCount()} selected integration${selectedCount() === 1 ? "" : "s"}\n`);
|
|
231
457
|
stdout.write(`\n${hint}\n`);
|
|
232
458
|
};
|
|
233
459
|
const finish = () => {
|
|
@@ -273,7 +499,7 @@ async function promptForSetupClients(clients) {
|
|
|
273
499
|
return;
|
|
274
500
|
}
|
|
275
501
|
if (key.name === "space") {
|
|
276
|
-
if (cursor ===
|
|
502
|
+
if (cursor === applyIndex) {
|
|
277
503
|
finish();
|
|
278
504
|
return;
|
|
279
505
|
}
|
|
@@ -295,7 +521,7 @@ async function promptForSetupClients(clients) {
|
|
|
295
521
|
return;
|
|
296
522
|
}
|
|
297
523
|
if (key.name === "return" || key.name === "enter") {
|
|
298
|
-
if (cursor ===
|
|
524
|
+
if (cursor === applyIndex) {
|
|
299
525
|
finish();
|
|
300
526
|
return;
|
|
301
527
|
}
|
|
@@ -386,6 +612,35 @@ async function detectCodexClient() {
|
|
|
386
612
|
}
|
|
387
613
|
return false;
|
|
388
614
|
}
|
|
615
|
+
async function detectContinueClient() {
|
|
616
|
+
if (hasCommand("cn") || hasCommand("continue"))
|
|
617
|
+
return true;
|
|
618
|
+
const candidates = [
|
|
619
|
+
CONTINUE_CONFIG_PATH,
|
|
620
|
+
node_path_1.default.join(node_os_1.default.homedir(), ".continue", "config.json"),
|
|
621
|
+
node_path_1.default.join(node_os_1.default.homedir(), ".continue", "sessions"),
|
|
622
|
+
];
|
|
623
|
+
for (const candidate of candidates) {
|
|
624
|
+
if (await pathExists(candidate))
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
return (await detectExtensionHosts(["continue.continue-"])).length > 0;
|
|
628
|
+
}
|
|
629
|
+
async function detectClineClient() {
|
|
630
|
+
if (hasCommand("cline"))
|
|
631
|
+
return true;
|
|
632
|
+
const candidates = [
|
|
633
|
+
CLINE_GLOBAL_STATE_PATH,
|
|
634
|
+
CLINE_SECRETS_PATH,
|
|
635
|
+
node_path_1.default.join(node_os_1.default.homedir(), ".cline", "state", "taskHistory.json"),
|
|
636
|
+
node_path_1.default.join(node_os_1.default.homedir(), ".cline", "tasks"),
|
|
637
|
+
];
|
|
638
|
+
for (const candidate of candidates) {
|
|
639
|
+
if (await pathExists(candidate))
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
return (await detectExtensionHosts(["saoudrizwan.claude-dev-"])).length > 0;
|
|
643
|
+
}
|
|
389
644
|
async function detectKiloClient() {
|
|
390
645
|
if (hasCommand("kilo"))
|
|
391
646
|
return true;
|
|
@@ -395,12 +650,30 @@ async function detectKiloClient() {
|
|
|
395
650
|
}
|
|
396
651
|
return false;
|
|
397
652
|
}
|
|
653
|
+
async function detectRooClient() {
|
|
654
|
+
return (await detectExtensionHosts(["rooveterinaryinc.roo-cline-"])).length > 0;
|
|
655
|
+
}
|
|
398
656
|
async function detectTraeClient() {
|
|
399
657
|
const bundlePath = traeBundlePath();
|
|
400
658
|
if (!bundlePath)
|
|
401
659
|
return false;
|
|
402
660
|
return pathExists(bundlePath);
|
|
403
661
|
}
|
|
662
|
+
async function detectAiderClient() {
|
|
663
|
+
if (hasCommand("aider"))
|
|
664
|
+
return true;
|
|
665
|
+
const candidates = [
|
|
666
|
+
AIDER_CONFIG_PATH,
|
|
667
|
+
node_path_1.default.join(node_os_1.default.homedir(), ".aider.conf.yaml"),
|
|
668
|
+
node_path_1.default.join(process.cwd(), ".aider.conf.yml"),
|
|
669
|
+
node_path_1.default.join(process.cwd(), ".aider.chat.history.md"),
|
|
670
|
+
];
|
|
671
|
+
for (const candidate of candidates) {
|
|
672
|
+
if (await pathExists(candidate))
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
404
677
|
async function resolveModels(backendUrl, apiKey) {
|
|
405
678
|
const ids = await fetchBackendModelIds(backendUrl, apiKey);
|
|
406
679
|
const available = new Set(ids ?? []);
|
|
@@ -468,6 +741,146 @@ async function writeCodexConfig(params) {
|
|
|
468
741
|
await promises_1.default.writeFile(configPath, next, "utf8");
|
|
469
742
|
return configPath;
|
|
470
743
|
}
|
|
744
|
+
function isManagedContinueModel(model, proxyUrl) {
|
|
745
|
+
if (typeof model !== "object" || model === null || Array.isArray(model))
|
|
746
|
+
return false;
|
|
747
|
+
const candidate = model;
|
|
748
|
+
return (candidate.provider === "openai" &&
|
|
749
|
+
candidate.name === CONTINUE_MODEL_NAME &&
|
|
750
|
+
candidate.apiBase === proxyUrl);
|
|
751
|
+
}
|
|
752
|
+
async function writeContinueConfig(params) {
|
|
753
|
+
const configPath = CONTINUE_CONFIG_PATH;
|
|
754
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(configPath), { recursive: true });
|
|
755
|
+
const existingRaw = (await readFileIfExists(configPath)) ?? "";
|
|
756
|
+
const proxyUrl = openAiCompatibleProxyUrl(params.backendUrl);
|
|
757
|
+
const doc = (0, yaml_1.parseDocument)(existingRaw);
|
|
758
|
+
const docRoot = objectRecordOr(doc.toJS(), {});
|
|
759
|
+
const models = Array.isArray(docRoot.models)
|
|
760
|
+
? docRoot.models.filter((entry) => !isManagedContinueModel(entry, proxyUrl))
|
|
761
|
+
: [];
|
|
762
|
+
models.unshift({
|
|
763
|
+
name: CONTINUE_MODEL_NAME,
|
|
764
|
+
provider: "openai",
|
|
765
|
+
model: params.model.trim() || DEFAULT_CONTINUE_MODEL,
|
|
766
|
+
apiKey: params.apiKey,
|
|
767
|
+
apiBase: proxyUrl,
|
|
768
|
+
roles: ["chat", "edit", "apply"],
|
|
769
|
+
});
|
|
770
|
+
if (typeof docRoot.name !== "string" || !docRoot.name.trim()) {
|
|
771
|
+
doc.set("name", "Local Config");
|
|
772
|
+
}
|
|
773
|
+
if (typeof docRoot.version !== "string" || !docRoot.version.trim()) {
|
|
774
|
+
doc.set("version", "1.0.0");
|
|
775
|
+
}
|
|
776
|
+
doc.set("models", models);
|
|
777
|
+
await promises_1.default.writeFile(configPath, doc.toString(), "utf8");
|
|
778
|
+
return configPath;
|
|
779
|
+
}
|
|
780
|
+
function isManagedClineState(doc) {
|
|
781
|
+
return (doc.planModeApiProvider === "openai" &&
|
|
782
|
+
doc.actModeApiProvider === "openai" &&
|
|
783
|
+
isTheClawBayOpenAiCompatibleBaseUrl(doc.openAiBaseUrl));
|
|
784
|
+
}
|
|
785
|
+
async function writeClineConfig(params) {
|
|
786
|
+
const proxyUrl = openAiCompatibleProxyUrl(params.backendUrl);
|
|
787
|
+
const globalState = await readJsonObjectFile(CLINE_GLOBAL_STATE_PATH);
|
|
788
|
+
const secrets = await readJsonObjectFile(CLINE_SECRETS_PATH);
|
|
789
|
+
const alreadyManaged = isManagedClineState(globalState) && typeof secrets.openAiApiKey === "string";
|
|
790
|
+
if (!alreadyManaged) {
|
|
791
|
+
const snapshot = {
|
|
792
|
+
globalState: {
|
|
793
|
+
planModeApiProvider: "planModeApiProvider" in globalState ? globalState.planModeApiProvider : null,
|
|
794
|
+
actModeApiProvider: "actModeApiProvider" in globalState ? globalState.actModeApiProvider : null,
|
|
795
|
+
openAiBaseUrl: "openAiBaseUrl" in globalState ? globalState.openAiBaseUrl : null,
|
|
796
|
+
planModeOpenAiModelId: "planModeOpenAiModelId" in globalState ? globalState.planModeOpenAiModelId : null,
|
|
797
|
+
actModeOpenAiModelId: "actModeOpenAiModelId" in globalState ? globalState.actModeOpenAiModelId : null,
|
|
798
|
+
},
|
|
799
|
+
secrets: {
|
|
800
|
+
openAiApiKey: typeof secrets.openAiApiKey === "string" ? secrets.openAiApiKey : null,
|
|
801
|
+
},
|
|
802
|
+
};
|
|
803
|
+
await writeJsonObjectFile(CLINE_RESTORE_STATE_PATH, snapshot, 0o600);
|
|
804
|
+
}
|
|
805
|
+
globalState.planModeApiProvider = "openai";
|
|
806
|
+
globalState.actModeApiProvider = "openai";
|
|
807
|
+
globalState.openAiBaseUrl = proxyUrl;
|
|
808
|
+
globalState.planModeOpenAiModelId = params.model.trim() || DEFAULT_CLINE_MODEL;
|
|
809
|
+
globalState.actModeOpenAiModelId = params.model.trim() || DEFAULT_CLINE_MODEL;
|
|
810
|
+
secrets.openAiApiKey = params.apiKey;
|
|
811
|
+
await writeJsonObjectFile(CLINE_GLOBAL_STATE_PATH, globalState);
|
|
812
|
+
await writeJsonObjectFile(CLINE_SECRETS_PATH, secrets, 0o600);
|
|
813
|
+
return [CLINE_GLOBAL_STATE_PATH, CLINE_SECRETS_PATH];
|
|
814
|
+
}
|
|
815
|
+
async function writeRooConfig(params) {
|
|
816
|
+
const hosts = await detectExtensionHosts(["rooveterinaryinc.roo-cline-"]);
|
|
817
|
+
if (hosts.length === 0) {
|
|
818
|
+
throw new Error("Roo Code was not detected in a supported editor profile.");
|
|
819
|
+
}
|
|
820
|
+
const existingSnapshotRaw = await readFileIfExists(ROO_SETTINGS_STATE_PATH);
|
|
821
|
+
let existingSnapshot = [];
|
|
822
|
+
if (existingSnapshotRaw?.trim()) {
|
|
823
|
+
try {
|
|
824
|
+
existingSnapshot = JSON.parse(existingSnapshotRaw);
|
|
825
|
+
}
|
|
826
|
+
catch {
|
|
827
|
+
existingSnapshot = [];
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
const snapshotByPath = new Map(existingSnapshot.map((entry) => [entry.settingsPath, entry]));
|
|
831
|
+
const managedPaths = [];
|
|
832
|
+
for (const host of hosts) {
|
|
833
|
+
const existed = await pathExists(host.userSettingsPath);
|
|
834
|
+
const settings = await readJsonObjectFile(host.userSettingsPath);
|
|
835
|
+
const currentValue = typeof settings["roo-cline.autoImportSettingsPath"] === "string"
|
|
836
|
+
? settings["roo-cline.autoImportSettingsPath"]
|
|
837
|
+
: null;
|
|
838
|
+
if (currentValue !== ROO_IMPORT_FILE) {
|
|
839
|
+
snapshotByPath.set(host.userSettingsPath, {
|
|
840
|
+
settingsPath: host.userSettingsPath,
|
|
841
|
+
existed,
|
|
842
|
+
previousValue: currentValue,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
settings["roo-cline.autoImportSettingsPath"] = ROO_IMPORT_FILE;
|
|
846
|
+
await writeJsonObjectFile(host.userSettingsPath, settings);
|
|
847
|
+
managedPaths.push(host.userSettingsPath);
|
|
848
|
+
}
|
|
849
|
+
const providerConfigId = ROO_PROFILE_ID;
|
|
850
|
+
const rooImport = {
|
|
851
|
+
providerProfiles: {
|
|
852
|
+
currentApiConfigName: ROO_PROFILE_NAME,
|
|
853
|
+
apiConfigs: {
|
|
854
|
+
[ROO_PROFILE_NAME]: {
|
|
855
|
+
id: providerConfigId,
|
|
856
|
+
apiProvider: "openai",
|
|
857
|
+
openAiBaseUrl: openAiCompatibleProxyUrl(params.backendUrl),
|
|
858
|
+
openAiApiKey: params.apiKey,
|
|
859
|
+
openAiModelId: params.model.trim() || DEFAULT_ROO_MODEL,
|
|
860
|
+
},
|
|
861
|
+
},
|
|
862
|
+
modeApiConfigs: Object.fromEntries(ROO_MODE_SLUGS.map((slug) => [slug, providerConfigId])),
|
|
863
|
+
},
|
|
864
|
+
};
|
|
865
|
+
await writeJsonObjectFile(ROO_IMPORT_FILE, rooImport, 0o600);
|
|
866
|
+
await writeJsonObjectFile(ROO_SETTINGS_STATE_PATH, Array.from(snapshotByPath.values()), 0o600);
|
|
867
|
+
return [ROO_IMPORT_FILE, ...managedPaths];
|
|
868
|
+
}
|
|
869
|
+
async function writeAiderConfig(params) {
|
|
870
|
+
const existing = (await readFileIfExists(AIDER_CONFIG_PATH)) ?? "";
|
|
871
|
+
const cleaned = removeManagedBlock(existing, AIDER_MANAGED_START, AIDER_MANAGED_END);
|
|
872
|
+
const next = appendManagedBlock(cleaned, [
|
|
873
|
+
AIDER_MANAGED_START,
|
|
874
|
+
`model: ${JSON.stringify(`openai/${params.model.trim() || DEFAULT_AIDER_MODEL}`)}`,
|
|
875
|
+
`openai-api-key: ${JSON.stringify(params.apiKey)}`,
|
|
876
|
+
`openai-api-base: ${JSON.stringify(openAiCompatibleProxyUrl(params.backendUrl))}`,
|
|
877
|
+
"restore-chat-history: true",
|
|
878
|
+
AIDER_MANAGED_END,
|
|
879
|
+
]);
|
|
880
|
+
await promises_1.default.mkdir(node_path_1.default.dirname(AIDER_CONFIG_PATH), { recursive: true });
|
|
881
|
+
await promises_1.default.writeFile(AIDER_CONFIG_PATH, next, "utf8");
|
|
882
|
+
return AIDER_CONFIG_PATH;
|
|
883
|
+
}
|
|
471
884
|
async function persistApiKeyEnv(apiKey) {
|
|
472
885
|
const envDir = node_path_1.default.dirname(ENV_FILE);
|
|
473
886
|
await promises_1.default.mkdir(envDir, { recursive: true });
|
|
@@ -743,10 +1156,14 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
743
1156
|
throw new Error('API key is required. Run "theclawbay setup --api-key <key>".');
|
|
744
1157
|
const backendRaw = flags.backend ?? (0, api_key_1.tryInferBackendUrlFromApiKey)(apiKey) ?? managed?.backendUrl ?? DEFAULT_BACKEND_URL;
|
|
745
1158
|
const backendUrl = normalizeUrl(backendRaw, "--backend");
|
|
746
|
-
const [codexDetected, kiloDetected, traeDetected] = await Promise.all([
|
|
1159
|
+
const [codexDetected, continueDetected, clineDetected, kiloDetected, rooDetected, traeDetected, aiderDetected] = await Promise.all([
|
|
747
1160
|
detectCodexClient(),
|
|
1161
|
+
detectContinueClient(),
|
|
1162
|
+
detectClineClient(),
|
|
748
1163
|
detectKiloClient(),
|
|
1164
|
+
detectRooClient(),
|
|
749
1165
|
detectTraeClient(),
|
|
1166
|
+
detectAiderClient(),
|
|
750
1167
|
]);
|
|
751
1168
|
const setupClients = [
|
|
752
1169
|
{
|
|
@@ -754,30 +1171,72 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
754
1171
|
label: "Codex CLI, VS Code extension, and Codex app",
|
|
755
1172
|
detected: codexDetected,
|
|
756
1173
|
recommended: true,
|
|
1174
|
+
icon: "◎",
|
|
1175
|
+
siteUrl: "https://openai.com/codex",
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
id: "continue",
|
|
1179
|
+
label: "Continue",
|
|
1180
|
+
detected: continueDetected,
|
|
1181
|
+
recommended: true,
|
|
1182
|
+
icon: "▶",
|
|
1183
|
+
siteUrl: "https://continue.dev",
|
|
1184
|
+
},
|
|
1185
|
+
{
|
|
1186
|
+
id: "cline",
|
|
1187
|
+
label: "Cline",
|
|
1188
|
+
detected: clineDetected,
|
|
1189
|
+
recommended: true,
|
|
1190
|
+
icon: "◈",
|
|
1191
|
+
siteUrl: "https://cline.bot",
|
|
757
1192
|
},
|
|
758
1193
|
{
|
|
759
1194
|
id: "openclaw",
|
|
760
1195
|
label: "OpenClaw",
|
|
761
1196
|
detected: hasCommand("openclaw"),
|
|
762
1197
|
recommended: true,
|
|
1198
|
+
icon: "🦞",
|
|
1199
|
+
siteUrl: "https://openclaw.ai",
|
|
763
1200
|
},
|
|
764
1201
|
{
|
|
765
1202
|
id: "opencode",
|
|
766
1203
|
label: "OpenCode",
|
|
767
1204
|
detected: hasCommand("opencode"),
|
|
768
1205
|
recommended: true,
|
|
1206
|
+
icon: "⌘",
|
|
1207
|
+
siteUrl: "https://opencode.ai",
|
|
769
1208
|
},
|
|
770
1209
|
{
|
|
771
1210
|
id: "kilo",
|
|
772
1211
|
label: "Kilo Code",
|
|
773
1212
|
detected: kiloDetected,
|
|
774
1213
|
recommended: true,
|
|
1214
|
+
icon: "⚡",
|
|
1215
|
+
siteUrl: "https://kilo.ai",
|
|
1216
|
+
},
|
|
1217
|
+
{
|
|
1218
|
+
id: "roo",
|
|
1219
|
+
label: "Roo Code",
|
|
1220
|
+
detected: rooDetected,
|
|
1221
|
+
recommended: true,
|
|
1222
|
+
icon: "🦘",
|
|
1223
|
+
siteUrl: "https://roocode.com",
|
|
775
1224
|
},
|
|
776
1225
|
{
|
|
777
1226
|
id: "trae",
|
|
778
1227
|
label: "Trae (experimental)",
|
|
779
1228
|
detected: traeDetected,
|
|
780
1229
|
recommended: false,
|
|
1230
|
+
icon: "△",
|
|
1231
|
+
siteUrl: "https://www.trae.ai",
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
id: "aider",
|
|
1235
|
+
label: "Aider",
|
|
1236
|
+
detected: aiderDetected,
|
|
1237
|
+
recommended: true,
|
|
1238
|
+
icon: "✦",
|
|
1239
|
+
siteUrl: "https://aider.chat",
|
|
781
1240
|
},
|
|
782
1241
|
];
|
|
783
1242
|
const selectedSetupClients = await resolveSetupClientSelection({
|
|
@@ -797,11 +1256,15 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
797
1256
|
let authSeed = null;
|
|
798
1257
|
let stateDbMigration = null;
|
|
799
1258
|
let modelCacheMigration = null;
|
|
1259
|
+
let continueConfigPath = null;
|
|
1260
|
+
let clineConfigPaths = [];
|
|
800
1261
|
let openClawConfigPath = null;
|
|
801
1262
|
let openClawCliWarning = null;
|
|
802
1263
|
let openCodePath = null;
|
|
803
1264
|
let kiloConfigPath = null;
|
|
1265
|
+
let rooConfigPaths = [];
|
|
804
1266
|
let traeBundlePathPatched = null;
|
|
1267
|
+
let aiderConfigPath = null;
|
|
805
1268
|
if (selectedSetupClients.has("codex")) {
|
|
806
1269
|
codexConfigPath = await writeCodexConfig({ backendUrl, model: resolved?.model ?? DEFAULT_CODEX_MODEL, apiKey });
|
|
807
1270
|
updatedVsCodeEnvFiles = await persistVsCodeServerEnvSource();
|
|
@@ -823,6 +1286,20 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
823
1286
|
codexHome: paths_1.codexDir,
|
|
824
1287
|
});
|
|
825
1288
|
}
|
|
1289
|
+
if (selectedSetupClients.has("continue")) {
|
|
1290
|
+
continueConfigPath = await writeContinueConfig({
|
|
1291
|
+
backendUrl,
|
|
1292
|
+
model: resolved?.model ?? DEFAULT_CONTINUE_MODEL,
|
|
1293
|
+
apiKey,
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
if (selectedSetupClients.has("cline")) {
|
|
1297
|
+
clineConfigPaths = await writeClineConfig({
|
|
1298
|
+
backendUrl,
|
|
1299
|
+
model: resolved?.model ?? DEFAULT_CLINE_MODEL,
|
|
1300
|
+
apiKey,
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
826
1303
|
if (selectedSetupClients.has("openclaw")) {
|
|
827
1304
|
const openClawResult = await setupOpenClaw({
|
|
828
1305
|
backendUrl,
|
|
@@ -849,6 +1326,13 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
849
1326
|
apiKey,
|
|
850
1327
|
});
|
|
851
1328
|
}
|
|
1329
|
+
if (selectedSetupClients.has("roo")) {
|
|
1330
|
+
rooConfigPaths = await writeRooConfig({
|
|
1331
|
+
backendUrl,
|
|
1332
|
+
model: resolved?.model ?? DEFAULT_ROO_MODEL,
|
|
1333
|
+
apiKey,
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
852
1336
|
if (selectedSetupClients.has("trae")) {
|
|
853
1337
|
traeBundlePathPatched = await patchTraeBundle({
|
|
854
1338
|
backendUrl,
|
|
@@ -857,6 +1341,13 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
857
1341
|
models: resolved?.models ?? [{ id: DEFAULT_CODEX_MODEL, name: modelDisplayName(DEFAULT_CODEX_MODEL) }],
|
|
858
1342
|
});
|
|
859
1343
|
}
|
|
1344
|
+
if (selectedSetupClients.has("aider")) {
|
|
1345
|
+
aiderConfigPath = await writeAiderConfig({
|
|
1346
|
+
backendUrl,
|
|
1347
|
+
model: resolved?.model ?? DEFAULT_AIDER_MODEL,
|
|
1348
|
+
apiKey,
|
|
1349
|
+
});
|
|
1350
|
+
}
|
|
860
1351
|
this.log("Setup complete");
|
|
861
1352
|
this.log(`- Managed config: ${paths_1.managedConfigPath}`);
|
|
862
1353
|
this.log(`- Backend: ${backendUrl}`);
|
|
@@ -919,6 +1410,26 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
919
1410
|
else {
|
|
920
1411
|
this.log("- Codex: not detected (skipped)");
|
|
921
1412
|
}
|
|
1413
|
+
if (selectedSetupClients.has("continue")) {
|
|
1414
|
+
this.log(`- Continue: configured (${continueConfigPath})`);
|
|
1415
|
+
this.log("- Continue history: left ~/.continue/sessions untouched.");
|
|
1416
|
+
}
|
|
1417
|
+
else if (continueDetected) {
|
|
1418
|
+
this.log("- Continue: detected but skipped");
|
|
1419
|
+
}
|
|
1420
|
+
else {
|
|
1421
|
+
this.log("- Continue: not detected (skipped)");
|
|
1422
|
+
}
|
|
1423
|
+
if (selectedSetupClients.has("cline")) {
|
|
1424
|
+
this.log(`- Cline: configured (${clineConfigPaths.join(", ")})`);
|
|
1425
|
+
this.log("- Cline history: left ~/.cline/state and ~/.cline/tasks untouched.");
|
|
1426
|
+
}
|
|
1427
|
+
else if (clineDetected) {
|
|
1428
|
+
this.log("- Cline: detected but skipped");
|
|
1429
|
+
}
|
|
1430
|
+
else {
|
|
1431
|
+
this.log("- Cline: not detected (skipped)");
|
|
1432
|
+
}
|
|
922
1433
|
const openClawDetected = setupClients.find((client) => client.id === "openclaw")?.detected ?? false;
|
|
923
1434
|
if (selectedSetupClients.has("openclaw")) {
|
|
924
1435
|
this.log(`- OpenClaw: configured (${openClawConfigPath})`);
|
|
@@ -950,6 +1461,17 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
950
1461
|
else {
|
|
951
1462
|
this.log("- Kilo Code: not detected (skipped)");
|
|
952
1463
|
}
|
|
1464
|
+
if (selectedSetupClients.has("roo")) {
|
|
1465
|
+
this.log(`- Roo Code: configured (${rooConfigPaths.join(", ")})`);
|
|
1466
|
+
this.log("- Roo Code history: left existing task history untouched.");
|
|
1467
|
+
this.log("- Roo Code note: imported profiles can persist inside Roo after first launch even after logout.");
|
|
1468
|
+
}
|
|
1469
|
+
else if (rooDetected) {
|
|
1470
|
+
this.log("- Roo Code: detected but skipped");
|
|
1471
|
+
}
|
|
1472
|
+
else {
|
|
1473
|
+
this.log("- Roo Code: not detected (skipped)");
|
|
1474
|
+
}
|
|
953
1475
|
if (selectedSetupClients.has("trae")) {
|
|
954
1476
|
this.log(`- Trae: experimental bundle patch installed (${traeBundlePathPatched})`);
|
|
955
1477
|
this.log(`- Trae: replaced Builder and SoloCoder model lists with ${resolved?.models.length ?? 1} TheClawBay models.`);
|
|
@@ -961,6 +1483,16 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
961
1483
|
else {
|
|
962
1484
|
this.log("- Trae: not detected (skipped)");
|
|
963
1485
|
}
|
|
1486
|
+
if (selectedSetupClients.has("aider")) {
|
|
1487
|
+
this.log(`- Aider: configured (${aiderConfigPath})`);
|
|
1488
|
+
this.log("- Aider history: restore-chat-history enabled; existing .aider chat files were left untouched.");
|
|
1489
|
+
}
|
|
1490
|
+
else if (aiderDetected) {
|
|
1491
|
+
this.log("- Aider: detected but skipped");
|
|
1492
|
+
}
|
|
1493
|
+
else {
|
|
1494
|
+
this.log("- Aider: not detected (skipped)");
|
|
1495
|
+
}
|
|
964
1496
|
if (authSeed?.action === "seeded") {
|
|
965
1497
|
this.log("- Codex login state: seeded local API-key auth for Codex UI.");
|
|
966
1498
|
}
|
|
@@ -979,11 +1511,11 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
979
1511
|
else if (authSeed) {
|
|
980
1512
|
this.log("- Codex login state: no change.");
|
|
981
1513
|
}
|
|
982
|
-
this.log("Next: restart
|
|
1514
|
+
this.log("Next: restart Continue, Cline, Roo Code, or Trae only if they were already open during setup.");
|
|
983
1515
|
});
|
|
984
1516
|
}
|
|
985
1517
|
}
|
|
986
|
-
SetupCommand.description = "One-time setup: configure Codex
|
|
1518
|
+
SetupCommand.description = "One-time setup: configure Codex plus any detected Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Trae, or Aider installs to use The Claw Bay";
|
|
987
1519
|
SetupCommand.flags = {
|
|
988
1520
|
backend: core_1.Flags.string({
|
|
989
1521
|
required: false,
|
|
@@ -996,7 +1528,7 @@ SetupCommand.flags = {
|
|
|
996
1528
|
}),
|
|
997
1529
|
clients: core_1.Flags.string({
|
|
998
1530
|
required: false,
|
|
999
|
-
description: "Detected local clients to configure: codex, openclaw, opencode, kilo, trae",
|
|
1531
|
+
description: "Detected local clients to configure: codex, continue, cline, openclaw, opencode, kilo, roo, trae, aider",
|
|
1000
1532
|
}),
|
|
1001
1533
|
yes: core_1.Flags.boolean({
|
|
1002
1534
|
required: false,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare const codexDir: string;
|
|
2
|
+
export declare const theclawbayConfigDir: string;
|
|
3
|
+
export declare const theclawbayStateDir: string;
|
|
2
4
|
export declare const managedConfigPath: string;
|
|
3
5
|
export declare const updateCheckStatePath: string;
|
|
4
6
|
export declare const legacyManagedConfigPathClayBay: string;
|
package/dist/lib/config/paths.js
CHANGED
|
@@ -3,10 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.legacyManagedConfigPathCodexAuth = exports.legacyManagedConfigPathClayBay = exports.updateCheckStatePath = exports.managedConfigPath = exports.codexDir = void 0;
|
|
6
|
+
exports.legacyManagedConfigPathCodexAuth = exports.legacyManagedConfigPathClayBay = exports.updateCheckStatePath = exports.managedConfigPath = exports.theclawbayStateDir = exports.theclawbayConfigDir = exports.codexDir = void 0;
|
|
7
7
|
const node_os_1 = __importDefault(require("node:os"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
exports.codexDir = node_path_1.default.join(node_os_1.default.homedir(), ".codex");
|
|
10
|
+
exports.theclawbayConfigDir = node_path_1.default.join(node_os_1.default.homedir(), ".config", "theclawbay");
|
|
11
|
+
exports.theclawbayStateDir = node_path_1.default.join(exports.theclawbayConfigDir, "state");
|
|
10
12
|
exports.managedConfigPath = node_path_1.default.join(exports.codexDir, "theclawbay.managed.json");
|
|
11
13
|
exports.updateCheckStatePath = node_path_1.default.join(exports.codexDir, "theclawbay.update-check.json");
|
|
12
14
|
exports.legacyManagedConfigPathClayBay = node_path_1.default.join(exports.codexDir, "theclaybay.managed.json");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theclawbay",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "CLI for connecting Codex, OpenClaw, OpenCode, Kilo, and experimental Trae to The Claw Bay.",
|
|
3
|
+
"version": "0.3.28",
|
|
4
|
+
"description": "CLI for connecting Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, and experimental Trae to The Claw Bay.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
7
7
|
"theclawbay": "dist/index.js"
|
|
@@ -32,15 +32,20 @@
|
|
|
32
32
|
"cli",
|
|
33
33
|
"setup",
|
|
34
34
|
"api-key",
|
|
35
|
+
"continue",
|
|
36
|
+
"cline",
|
|
35
37
|
"openclaw",
|
|
36
38
|
"opencode",
|
|
37
39
|
"kilo",
|
|
40
|
+
"roo",
|
|
41
|
+
"aider",
|
|
38
42
|
"trae"
|
|
39
43
|
],
|
|
40
44
|
"preferGlobal": true,
|
|
41
45
|
"dependencies": {
|
|
42
46
|
"@oclif/core": "^4.8.0",
|
|
43
|
-
"tslib": "^2.8.1"
|
|
47
|
+
"tslib": "^2.8.1",
|
|
48
|
+
"yaml": "^2.8.2"
|
|
44
49
|
},
|
|
45
50
|
"devDependencies": {
|
|
46
51
|
"@types/node": "^20.17.0",
|