scalemax 0.1.51 → 0.1.52

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.
@@ -2,10 +2,10 @@ import path from 'node:path';
2
2
  import fs from 'fs-extra';
3
3
  import JSON5 from 'json5';
4
4
  import { atomicWrite, backupFile, captureFileSnapshots, restoreFileSnapshots, snapshotRollback } from '../utils/fs.js';
5
- import { clientConfigPath } from './paths.js';
6
5
  import { anthropicModelIds, deepSeekChatModelIds, isDeepSeekChatModelId, modelIdKey, modelName, modelSupportsTools, openAiBaseUrl, openAiResponsesModelIds, preferredAnthropicModel, preferredChatCompletionsModel, preferredOpenAiResponsesModel } from './models.js';
7
6
  import { isAnthropicModel } from '../utils/api.js';
8
7
  import { rooRipgrepRepairNote } from '../repair/roo-ripgrep.js';
8
+ import { rooSettingsTargets } from '../detect/roo-code.js';
9
9
  const id = 'roo-code';
10
10
  const name = 'Roo Code (VS Code)';
11
11
  const importSetting = 'roo-cline.autoImportSettingsPath';
@@ -167,23 +167,30 @@ export async function configure(ctx) {
167
167
  return note ? { ...result, note } : result;
168
168
  }
169
169
  async function configureHandoff(ctx) {
170
- const settingsFile = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
170
+ const targets = await rooSettingsTargets(ctx.home, ctx.platform, ctx.env);
171
171
  const profileFile = importPath(ctx.home);
172
- const snapshots = await captureFileSnapshots([settingsFile, profileFile]);
173
- const originalSettings = await fs.readFile(settingsFile, 'utf8').catch(() => '');
172
+ const snapshots = await captureFileSnapshots([...targets.map(target => target.settingsFile), profileFile]);
174
173
  const originalProfile = await fs.readFile(profileFile, 'utf8').catch(() => '');
175
- const settings = parseSettings(originalSettings, settingsFile);
176
- const nextSettings = JSON.stringify({ ...settings, [importSetting]: importSettingValue }, null, 2) + '\n';
174
+ const writes = [];
175
+ for (const target of targets) {
176
+ const original = await fs.readFile(target.settingsFile, 'utf8').catch(() => '');
177
+ const next = JSON.stringify({ ...parseSettings(original, target.settingsFile), [importSetting]: importSettingValue }, null, 2) + '\n';
178
+ if (original !== next)
179
+ writes.push({ file: target.settingsFile, text: next });
180
+ }
177
181
  const nextProfile = handoff(ctx);
178
- if (originalSettings === nextSettings && originalProfile === nextProfile) {
182
+ const editors = targets.map(target => target.editor).join(', ');
183
+ if (!writes.length && originalProfile === nextProfile) {
179
184
  await fs.chmod(profileFile, 0o600).catch(() => undefined);
180
- return { id, name, changed: false, path: profileFile, message: 'supported Roo Code auto-import handoff is already current; reload VS Code to consume it', tip: ROO_CODE_MODE_TIP };
185
+ return { id, name, changed: false, path: profileFile, message: `supported Roo Code auto-import handoff is already current (${editors}); reload the editor to consume it`, tip: ROO_CODE_MODE_TIP };
181
186
  }
182
- await backupFile(settingsFile, ctx.home);
187
+ for (const write of writes)
188
+ await backupFile(write.file, ctx.home);
183
189
  await backupFile(profileFile, ctx.home);
184
190
  try {
185
191
  await atomicWrite(profileFile, nextProfile, 0o600, ctx.platform);
186
- await atomicWrite(settingsFile, nextSettings, 0o600, ctx.platform);
192
+ for (const write of writes)
193
+ await atomicWrite(write.file, write.text, 0o600, ctx.platform);
187
194
  }
188
195
  catch (error) {
189
196
  try {
@@ -199,19 +206,23 @@ async function configureHandoff(ctx) {
199
206
  name,
200
207
  changed: true,
201
208
  path: profileFile,
202
- message: 'created a private, supported auto-import handoff; reload VS Code so Roo Code imports the profile into SecretStorage',
209
+ message: `created a private, supported auto-import handoff for ${editors}; reload the editor so Roo Code imports the profile into SecretStorage`,
203
210
  tip: ROO_CODE_MODE_TIP,
204
211
  rollback: snapshotRollback(snapshots, ctx.platform),
205
212
  };
206
213
  }
207
214
  export async function verify(ctx) {
208
- const settingsFile = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
209
215
  const profileFile = importPath(ctx.home);
210
- const settings = parseSettings(await fs.readFile(settingsFile, 'utf8'), settingsFile);
216
+ let handoffSet = true;
217
+ for (const target of await rooSettingsTargets(ctx.home, ctx.platform, ctx.env)) {
218
+ const settings = parseSettings(await fs.readFile(target.settingsFile, 'utf8'), target.settingsFile);
219
+ if (settings[importSetting] !== importSettingValue)
220
+ handoffSet = false;
221
+ }
211
222
  const profile = await fs.readJson(profileFile).catch(() => undefined);
212
223
  const expectedProfiles = profilesFor(ctx);
213
224
  const current = currentProfileFor(ctx, expectedProfiles);
214
- if (settings[importSetting] !== importSettingValue || profile?.providerProfiles?.currentApiConfigName !== current.name) {
225
+ if (!handoffSet || profile?.providerProfiles?.currentApiConfigName !== current.name) {
215
226
  throw new Error('Roo Code auto-import handoff is incomplete.');
216
227
  }
217
228
  if (profile?.globalSettings?.maxWorkspaceFiles !== 0) {
@@ -232,10 +243,11 @@ export async function verify(ctx) {
232
243
  return { id, name, changed: false, path: profileFile, message: 'verified supported auto-import handoff (runtime activation requires a VS Code reload)' };
233
244
  }
234
245
  export async function remove(ctx) {
235
- const settingsFile = clientConfigPath(id, ctx.home, ctx.platform, ctx.env);
236
246
  const profileFile = importPath(ctx.home);
237
247
  let changed = false;
238
- if (await fs.pathExists(settingsFile)) {
248
+ for (const { settingsFile } of await rooSettingsTargets(ctx.home, ctx.platform, ctx.env)) {
249
+ if (!(await fs.pathExists(settingsFile)))
250
+ continue;
239
251
  const text = await fs.readFile(settingsFile, 'utf8');
240
252
  const settings = parseSettings(text, settingsFile);
241
253
  if (settings[importSetting] === importSettingValue) {
@@ -5,6 +5,13 @@ export interface EditorExtensionRoot {
5
5
  editor: string;
6
6
  /** Path segments below the home folder. */
7
7
  segments: readonly string[];
8
+ /**
9
+ * The editor's user-data folder name under the platform config root
10
+ * (%APPDATA% / ~/Library/Application Support / ~/.config), whose
11
+ * `User/settings.json` Roo Code reads. Absent for remote servers, which have
12
+ * no local settings file of their own.
13
+ */
14
+ userDir?: string;
8
15
  }
9
16
  /**
10
17
  * VS Code's own per-user extension folders. Detection stays limited to these
@@ -17,6 +24,18 @@ export declare const VSCODE_EXTENSION_ROOTS: readonly EditorExtensionRoot[];
17
24
  * installed extension itself rather than writing editor settings.
18
25
  */
19
26
  export declare const ALL_EDITOR_EXTENSION_ROOTS: readonly EditorExtensionRoot[];
27
+ export interface RooSettingsTarget {
28
+ editor: string;
29
+ /** That editor's user settings.json, which holds roo-cline.autoImportSettingsPath. */
30
+ settingsFile: string;
31
+ }
32
+ /**
33
+ * Every settings.json Roo Code reads its auto-import path from: VS Code's
34
+ * (always, as before) plus each VS Code-family editor that has Roo Code
35
+ * installed. A fork reads only its own settings.json, so writing VS Code's
36
+ * alone left Roo in Antigravity, Cursor or Windsurf unconfigured.
37
+ */
38
+ export declare function rooSettingsTargets(home: string, platform: NodeJS.Platform, env?: NodeJS.ProcessEnv): Promise<RooSettingsTarget[]>;
20
39
  export interface RooExtensionDir {
21
40
  editor: string;
22
41
  /** Absolute extension folder, e.g. ~/.vscode/extensions/rooveterinaryinc.roo-cline-3.54.0 */
@@ -3,14 +3,15 @@ import fs from 'fs-extra';
3
3
  import JSON5 from 'json5';
4
4
  import { commandExists } from '../utils/exec.js';
5
5
  import { clientConfigPath } from '../configure/paths.js';
6
+ import { configRoot } from '../utils/paths.js';
6
7
  export const ROO_EXTENSION_PATTERN = /^rooveterinaryinc\.roo-cline-/i;
7
8
  /**
8
9
  * VS Code's own per-user extension folders. Detection stays limited to these
9
10
  * because configure writes VS Code's settings.json, which forks do not read.
10
11
  */
11
12
  export const VSCODE_EXTENSION_ROOTS = [
12
- { editor: 'VS Code', segments: ['.vscode', 'extensions'] },
13
- { editor: 'VS Code Insiders', segments: ['.vscode-insiders', 'extensions'] },
13
+ { editor: 'VS Code', segments: ['.vscode', 'extensions'], userDir: 'Code' },
14
+ { editor: 'VS Code Insiders', segments: ['.vscode-insiders', 'extensions'], userDir: 'Code - Insiders' },
14
15
  ];
15
16
  /**
16
17
  * Every per-user extension folder Roo Code can be installed into: VS Code,
@@ -19,14 +20,36 @@ export const VSCODE_EXTENSION_ROOTS = [
19
20
  */
20
21
  export const ALL_EDITOR_EXTENSION_ROOTS = [
21
22
  ...VSCODE_EXTENSION_ROOTS,
22
- { editor: 'Cursor', segments: ['.cursor', 'extensions'] },
23
- { editor: 'Windsurf', segments: ['.windsurf', 'extensions'] },
24
- { editor: 'VSCodium', segments: ['.vscode-oss', 'extensions'] },
23
+ { editor: 'Cursor', segments: ['.cursor', 'extensions'], userDir: 'Cursor' },
24
+ { editor: 'Windsurf', segments: ['.windsurf', 'extensions'], userDir: 'Windsurf' },
25
+ { editor: 'VSCodium', segments: ['.vscode-oss', 'extensions'], userDir: 'VSCodium' },
25
26
  { editor: 'VS Code Server', segments: ['.vscode-server', 'extensions'] },
26
27
  { editor: 'Cursor Server', segments: ['.cursor-server', 'extensions'] },
27
- { editor: 'Trae', segments: ['.trae', 'extensions'] },
28
- { editor: 'Kiro', segments: ['.kiro', 'extensions'] },
28
+ { editor: 'Trae', segments: ['.trae', 'extensions'], userDir: 'Trae' },
29
+ { editor: 'Kiro', segments: ['.kiro', 'extensions'], userDir: 'Kiro' },
30
+ // Google Antigravity (VS Code fork, Open VSX). Product.json on Windows,
31
+ // 2.5.5: dataFolderName ".antigravity-ide", user data "%APPDATA%\Antigravity IDE".
32
+ { editor: 'Antigravity IDE', segments: ['.antigravity-ide', 'extensions'], userDir: 'Antigravity IDE' },
33
+ { editor: 'Antigravity', segments: ['.antigravity', 'extensions'], userDir: 'Antigravity' },
29
34
  ];
35
+ /**
36
+ * Every settings.json Roo Code reads its auto-import path from: VS Code's
37
+ * (always, as before) plus each VS Code-family editor that has Roo Code
38
+ * installed. A fork reads only its own settings.json, so writing VS Code's
39
+ * alone left Roo in Antigravity, Cursor or Windsurf unconfigured.
40
+ */
41
+ export async function rooSettingsTargets(home, platform, env = process.env) {
42
+ const targets = [{ editor: 'VS Code', settingsFile: clientConfigPath('roo-code', home, platform, env) }];
43
+ const root = configRoot(home, platform, env);
44
+ const forks = ALL_EDITOR_EXTENSION_ROOTS.filter(entry => entry.userDir && entry.editor !== 'VS Code');
45
+ for (const hit of await findRooExtensionDirs(home, forks)) {
46
+ const fork = forks.find(entry => entry.editor === hit.editor);
47
+ const settingsFile = path.join(root, fork.userDir, 'User', 'settings.json');
48
+ if (!targets.some(target => target.settingsFile === settingsFile))
49
+ targets.push({ editor: hit.editor, settingsFile });
50
+ }
51
+ return targets;
52
+ }
30
53
  /** Roo Code extension folders under the given roots; missing roots are skipped. */
31
54
  export async function findRooExtensionDirs(home, roots = VSCODE_EXTENSION_ROOTS) {
32
55
  const hits = [];
@@ -42,7 +65,7 @@ export async function findRooExtensionDirs(home, roots = VSCODE_EXTENSION_ROOTS)
42
65
  return hits;
43
66
  }
44
67
  export async function detect(ctx) {
45
- const paths = (await findRooExtensionDirs(ctx.home)).map(hit => hit.dir);
68
+ const paths = (await findRooExtensionDirs(ctx.home, ALL_EDITOR_EXTENSION_ROOTS.filter(entry => entry.userDir))).map(hit => hit.dir);
46
69
  const executable = await commandExists('code', ctx.env);
47
70
  if (executable)
48
71
  paths.unshift('command:code');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scalemax",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "description": "Universal ScaleMax installer for AI coding clients",
5
5
  "type": "module",
6
6
  "bin": {