@machina.ai/cell-cli 1.49.0-rc4 → 1.49.0-rc6

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.
Files changed (47) hide show
  1. package/dist/package.json +3 -3
  2. package/dist/src/acp/acpSession.test.js +5 -1
  3. package/dist/src/acp/acpSession.test.js.map +1 -1
  4. package/dist/src/config/config.js +16 -3
  5. package/dist/src/config/config.js.map +1 -1
  6. package/dist/src/config/config.test.js +2 -2
  7. package/dist/src/config/config.test.js.map +1 -1
  8. package/dist/src/config/sandboxConfig.js +7 -7
  9. package/dist/src/config/sandboxConfig.js.map +1 -1
  10. package/dist/src/config/sandboxConfig.test.js +27 -27
  11. package/dist/src/config/sandboxConfig.test.js.map +1 -1
  12. package/dist/src/config/settings.d.ts +4 -0
  13. package/dist/src/config/settings.js +73 -1
  14. package/dist/src/config/settings.js.map +1 -1
  15. package/dist/src/config/settings.test.js +161 -16
  16. package/dist/src/config/settings.test.js.map +1 -1
  17. package/dist/src/gemini.test.js +1 -1
  18. package/dist/src/gemini.test.js.map +1 -1
  19. package/dist/src/generated/git-commit.d.ts +2 -2
  20. package/dist/src/generated/git-commit.js +2 -2
  21. package/dist/src/ui/commands/aboutCommand.test.js +2 -2
  22. package/dist/src/ui/commands/aboutCommand.test.js.map +1 -1
  23. package/dist/src/ui/commands/docsCommand.test.js +1 -1
  24. package/dist/src/ui/commands/docsCommand.test.js.map +1 -1
  25. package/dist/src/ui/commands/extensionsCommand.test.js +1 -1
  26. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  27. package/dist/src/ui/commands/marketplaceCommand.js +6 -0
  28. package/dist/src/ui/commands/marketplaceCommand.js.map +1 -1
  29. package/dist/src/ui/commands/marketplaceCommand.test.d.ts +6 -0
  30. package/dist/src/ui/commands/marketplaceCommand.test.js +59 -0
  31. package/dist/src/ui/commands/marketplaceCommand.test.js.map +1 -0
  32. package/dist/src/ui/components/AsciiArt.d.ts +6 -6
  33. package/dist/src/ui/components/AsciiArt.js +6 -6
  34. package/dist/src/utils/handleAutoUpdate.test.js +3 -3
  35. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -1
  36. package/dist/src/utils/sandbox-macos-permissive-proxied.sb +1 -1
  37. package/dist/src/utils/sandbox-macos-restrictive-proxied.sb +1 -1
  38. package/dist/src/utils/sandbox-macos-strict-proxied.sb +1 -1
  39. package/dist/src/utils/sandbox.js +8 -8
  40. package/dist/src/utils/sandbox.js.map +1 -1
  41. package/dist/src/utils/sandbox.test.js +23 -23
  42. package/dist/src/utils/sandbox.test.js.map +1 -1
  43. package/dist/src/utils/sandboxUtils.d.ts +3 -3
  44. package/dist/src/utils/sandboxUtils.js +3 -3
  45. package/dist/src/utils/sandboxUtils.js.map +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/package.json +3 -3
@@ -45,7 +45,7 @@ import stripJsonComments from 'strip-json-comments'; // Will be mocked separatel
45
45
  import { isWorkspaceTrusted } from './trustedFolders.js';
46
46
  // These imports will get the versions from the vi.mock('./settings.js', ...) factory.
47
47
  import { loadSettings, USER_SETTINGS_PATH, // This IS the mocked path.
48
- getSystemSettingsPath, getSystemDefaultsPath, saveSettings, getDefaultsFromSchema, loadEnvironment, migrateDeprecatedSettings, SettingScope, LoadedSettings, sanitizeEnvVar, createTestMergedSettings, resetSettingsCacheForTesting, } from './settings.js';
48
+ getSystemSettingsPath, getSystemDefaultsPath, saveSettings, getDefaultsFromSchema, loadEnvironment, migrateDeprecatedSettings, enforceAgentsMdSetting, SettingScope, LoadedSettings, sanitizeEnvVar, createTestMergedSettings, resetSettingsCacheForTesting, } from './settings.js';
49
49
  import { FatalConfigError, CELL_DIR, AuthType, Storage, } from '@google/gemini-cli-core';
50
50
  import { updateSettingsFilePreservingFormat } from '../utils/commentJson.js';
51
51
  import { getSettingsSchema, MergeStrategy, } from './settingsSchema.js';
@@ -204,13 +204,41 @@ describe('Settings Loading and Merging', () => {
204
204
  },
205
205
  },
206
206
  };
207
- if (scope === 'user') {
208
- expect(settings.user.settings).toEqual(expectedWithAuth);
207
+ const expectedWithMerged = structuredClone(expectedWithAuth);
208
+ if (expectedWithMerged.context?.fileName) {
209
+ const fn = expectedWithMerged.context.fileName;
210
+ expectedWithMerged.context.fileName = Array.isArray(fn)
211
+ ? fn.includes('AGENTS.md')
212
+ ? fn
213
+ : ['AGENTS.md', ...fn]
214
+ : fn === 'AGENTS.md'
215
+ ? fn
216
+ : ['AGENTS.md', fn];
209
217
  }
210
218
  else {
211
- expect(settings[scope].settings).toEqual(content);
219
+ if (!expectedWithMerged.context) {
220
+ expectedWithMerged.context = {};
221
+ }
222
+ expectedWithMerged.context.fileName = ['AGENTS.md', 'GEMINI.md'];
223
+ }
224
+ const expectedScopeSettings = structuredClone(scope === 'user' ? expectedWithAuth : content);
225
+ if (scope === 'user' || scope === 'workspace') {
226
+ if (!expectedScopeSettings.context) {
227
+ expectedScopeSettings.context = {};
228
+ }
229
+ const fn = expectedScopeSettings.context.fileName;
230
+ expectedScopeSettings.context.fileName = fn
231
+ ? Array.isArray(fn)
232
+ ? fn.includes('AGENTS.md')
233
+ ? fn
234
+ : ['AGENTS.md', ...fn]
235
+ : fn === 'AGENTS.md'
236
+ ? fn
237
+ : ['AGENTS.md', fn]
238
+ : ['AGENTS.md', 'GEMINI.md'];
212
239
  }
213
- expect(settings.merged).toMatchObject(expectedWithAuth);
240
+ expect(settings[scope].settings).toEqual(expectedScopeSettings);
241
+ expect(settings.merged).toMatchObject(expectedWithMerged);
214
242
  });
215
243
  it('should merge system, user and workspace settings, with system taking precedence over workspace, and workspace over user', () => {
216
244
  mockFsExistsSync.mockImplementation((p) => {
@@ -268,13 +296,22 @@ describe('Settings Loading and Merging', () => {
268
296
  expect(settings.system.settings).toEqual(systemSettingsContent);
269
297
  expect(settings.user.settings).toEqual({
270
298
  ...userSettingsContent,
299
+ context: {
300
+ fileName: ['AGENTS.md', 'USER_CONTEXT.md'],
301
+ },
271
302
  security: {
272
303
  auth: {
273
304
  selectedType: AuthType.KEYCLOAK,
274
305
  },
275
306
  },
276
307
  });
277
- expect(settings.workspace.settings).toEqual(workspaceSettingsContent);
308
+ expect(settings.workspace.settings).toEqual({
309
+ ...workspaceSettingsContent,
310
+ context: {
311
+ ...workspaceSettingsContent.context,
312
+ fileName: ['AGENTS.md', 'WORKSPACE_CONTEXT.md'],
313
+ },
314
+ });
278
315
  expect(settings.merged).toMatchObject({
279
316
  ui: {
280
317
  theme: 'system-theme',
@@ -285,7 +322,7 @@ describe('Settings Loading and Merging', () => {
285
322
  },
286
323
  telemetry: { enabled: false },
287
324
  context: {
288
- fileName: 'WORKSPACE_CONTEXT.md',
325
+ fileName: ['AGENTS.md', 'WORKSPACE_CONTEXT.md'],
289
326
  },
290
327
  mcp: {
291
328
  allowed: ['server1', 'server2'],
@@ -407,13 +444,23 @@ describe('Settings Loading and Merging', () => {
407
444
  expect(settings.system.settings).toEqual(systemSettingsContent);
408
445
  expect(settings.user.settings).toEqual({
409
446
  ...userSettingsContent,
447
+ context: {
448
+ ...userSettingsContent.context,
449
+ fileName: ['AGENTS.md', 'USER_CONTEXT.md'],
450
+ },
410
451
  security: {
411
452
  auth: {
412
453
  selectedType: AuthType.KEYCLOAK,
413
454
  },
414
455
  },
415
456
  });
416
- expect(settings.workspace.settings).toEqual(workspaceSettingsContent);
457
+ expect(settings.workspace.settings).toEqual({
458
+ ...workspaceSettingsContent,
459
+ context: {
460
+ ...workspaceSettingsContent.context,
461
+ fileName: ['AGENTS.md', 'WORKSPACE_CONTEXT.md'],
462
+ },
463
+ });
417
464
  expect(settings.merged).toEqual({
418
465
  context: {
419
466
  discoveryMaxDirs: 200,
@@ -424,7 +471,7 @@ describe('Settings Loading and Merging', () => {
424
471
  '/workspace/dir',
425
472
  '/system/dir',
426
473
  ],
427
- fileName: 'WORKSPACE_CONTEXT.md',
474
+ fileName: ['AGENTS.md', 'WORKSPACE_CONTEXT.md'],
428
475
  },
429
476
  mcpServers: {},
430
477
  ui: { theme: 'system-theme' },
@@ -619,13 +666,19 @@ describe('Settings Loading and Merging', () => {
619
666
  description: 'contextFileName in user settings',
620
667
  path: USER_SETTINGS_PATH,
621
668
  content: { context: { fileName: 'CUSTOM.md' } },
622
- expected: { key: 'context.fileName', value: 'CUSTOM.md' },
669
+ expected: {
670
+ key: 'context.fileName',
671
+ value: ['AGENTS.md', 'CUSTOM.md'],
672
+ },
623
673
  },
624
674
  {
625
675
  description: 'contextFileName in workspace settings',
626
676
  path: MOCK_WORKSPACE_SETTINGS_PATH,
627
677
  content: { context: { fileName: 'PROJECT_SPECIFIC.md' } },
628
- expected: { key: 'context.fileName', value: 'PROJECT_SPECIFIC.md' },
678
+ expected: {
679
+ key: 'context.fileName',
680
+ value: ['AGENTS.md', 'PROJECT_SPECIFIC.md'],
681
+ },
629
682
  },
630
683
  {
631
684
  description: 'excludedProjectEnvVars in user settings',
@@ -701,7 +754,7 @@ describe('Settings Loading and Merging', () => {
701
754
  'WORKSPACE_VAR',
702
755
  ]);
703
756
  });
704
- it('should default contextFileName to undefined if not in any settings file', () => {
757
+ it('should default contextFileName to include AGENTS.md and GEMINI.md if not in any settings file', () => {
705
758
  mockFsExistsSync.mockImplementation((p) => normalizePath(p) === normalizePath(USER_SETTINGS_PATH) ||
706
759
  normalizePath(p) === normalizePath(MOCK_WORKSPACE_SETTINGS_PATH));
707
760
  const userSettingsContent = { ui: { theme: 'dark' } };
@@ -714,7 +767,10 @@ describe('Settings Loading and Merging', () => {
714
767
  return '';
715
768
  });
716
769
  const settings = loadSettings(MOCK_WORKSPACE_DIR);
717
- expect(settings.merged.context?.fileName).toBeUndefined();
770
+ expect(settings.merged.context?.fileName).toEqual([
771
+ 'AGENTS.md',
772
+ 'GEMINI.md',
773
+ ]);
718
774
  });
719
775
  it.each([
720
776
  {
@@ -1631,7 +1687,10 @@ describe('Settings Loading and Merging', () => {
1631
1687
  });
1632
1688
  const settings = loadSettings(MOCK_WORKSPACE_DIR);
1633
1689
  expect(settings.merged.tools?.sandbox).toBe(true);
1634
- expect(settings.merged.context?.fileName).toBe('WORKSPACE.md');
1690
+ expect(settings.merged.context?.fileName).toEqual([
1691
+ 'AGENTS.md',
1692
+ 'WORKSPACE.md',
1693
+ ]);
1635
1694
  expect(settings.merged.ui?.theme).toBe('dark');
1636
1695
  });
1637
1696
  it('should NOT merge workspace settings when workspace is not trusted', () => {
@@ -1658,7 +1717,10 @@ describe('Settings Loading and Merging', () => {
1658
1717
  });
1659
1718
  const settings = loadSettings(MOCK_WORKSPACE_DIR);
1660
1719
  expect(settings.merged.tools?.sandbox).toBe(false); // User setting
1661
- expect(settings.merged.context?.fileName).toBe('USER.md'); // User setting
1720
+ expect(settings.merged.context?.fileName).toEqual([
1721
+ 'AGENTS.md',
1722
+ 'USER.md',
1723
+ ]); // User setting
1662
1724
  expect(settings.merged.ui?.theme).toBe('dark'); // User setting
1663
1725
  });
1664
1726
  it('should NOT merge workspace settings when workspace trust is undefined', () => {
@@ -1685,7 +1747,10 @@ describe('Settings Loading and Merging', () => {
1685
1747
  });
1686
1748
  const settings = loadSettings(MOCK_WORKSPACE_DIR);
1687
1749
  expect(settings.merged.tools?.sandbox).toBe(false); // User setting
1688
- expect(settings.merged.context?.fileName).toBe('USER.md'); // User setting
1750
+ expect(settings.merged.context?.fileName).toEqual([
1751
+ 'AGENTS.md',
1752
+ 'USER.md',
1753
+ ]); // User setting
1689
1754
  });
1690
1755
  });
1691
1756
  describe('loadEnvironment', () => {
@@ -2144,6 +2209,86 @@ describe('Settings Loading and Merging', () => {
2144
2209
  });
2145
2210
  });
2146
2211
  });
2212
+ describe('enforceAgentsMdSetting', () => {
2213
+ let mockFsExistsSync;
2214
+ beforeEach(() => {
2215
+ vi.resetAllMocks();
2216
+ mockFsExistsSync = vi.mocked(fs.existsSync);
2217
+ vi.spyOn(trustedFolders, 'isWorkspaceTrusted').mockReturnValue({
2218
+ isTrusted: true,
2219
+ source: undefined,
2220
+ });
2221
+ });
2222
+ afterEach(() => {
2223
+ vi.restoreAllMocks();
2224
+ });
2225
+ it('should do nothing if context or context.fileName is missing from existing file', () => {
2226
+ const userSettingsContent = { ui: { theme: 'dark' } };
2227
+ mockFsExistsSync.mockReturnValue(true);
2228
+ const loadedSettings = createMockSettings(userSettingsContent);
2229
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2230
+ loadedSettings.user.readOnly = false;
2231
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2232
+ enforceAgentsMdSetting(loadedSettings);
2233
+ expect(setValueSpy).not.toHaveBeenCalled();
2234
+ });
2235
+ it('should migrate context.fileName from custom string to array starting with AGENTS.md', () => {
2236
+ const userSettingsContent = { context: { fileName: 'CUSTOM.md' } };
2237
+ mockFsExistsSync.mockReturnValue(true);
2238
+ const loadedSettings = createMockSettings(userSettingsContent);
2239
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2240
+ loadedSettings.user.readOnly = false;
2241
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2242
+ enforceAgentsMdSetting(loadedSettings);
2243
+ expect(setValueSpy).toHaveBeenCalledWith(SettingScope.User, 'context', expect.objectContaining({ fileName: ['AGENTS.md', 'CUSTOM.md'] }));
2244
+ });
2245
+ it('should prepend AGENTS.md if context.fileName is an array not containing agents.md', () => {
2246
+ const userSettingsContent = {
2247
+ context: { fileName: ['PROJECT.md', 'OTHER.md'] },
2248
+ };
2249
+ mockFsExistsSync.mockReturnValue(true);
2250
+ const loadedSettings = createMockSettings(userSettingsContent);
2251
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2252
+ loadedSettings.user.readOnly = false;
2253
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2254
+ enforceAgentsMdSetting(loadedSettings);
2255
+ expect(setValueSpy).toHaveBeenCalledWith(SettingScope.User, 'context', expect.objectContaining({
2256
+ fileName: ['AGENTS.md', 'PROJECT.md', 'OTHER.md'],
2257
+ }));
2258
+ });
2259
+ it('should not do anything if AGENTS.md is already in context.fileName array', () => {
2260
+ const userSettingsContent = {
2261
+ context: { fileName: ['AGENTS.md', 'GEMINI.md'] },
2262
+ };
2263
+ mockFsExistsSync.mockReturnValue(true);
2264
+ const loadedSettings = createMockSettings(userSettingsContent);
2265
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2266
+ loadedSettings.user.readOnly = false;
2267
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2268
+ enforceAgentsMdSetting(loadedSettings);
2269
+ expect(setValueSpy).not.toHaveBeenCalled();
2270
+ });
2271
+ it('should not mutate files if settingsFile is read-only', () => {
2272
+ const userSettingsContent = { context: { fileName: 'CUSTOM.md' } };
2273
+ mockFsExistsSync.mockReturnValue(true);
2274
+ const loadedSettings = createMockSettings(userSettingsContent);
2275
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2276
+ loadedSettings.user.readOnly = true;
2277
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2278
+ enforceAgentsMdSetting(loadedSettings);
2279
+ expect(setValueSpy).not.toHaveBeenCalled();
2280
+ });
2281
+ it('should not do anything if settings file does not physically exist', () => {
2282
+ const userSettingsContent = { context: { fileName: 'CUSTOM.md' } };
2283
+ mockFsExistsSync.mockReturnValue(false); // File does not exist on disk
2284
+ const loadedSettings = createMockSettings(userSettingsContent);
2285
+ loadedSettings.user.path = USER_SETTINGS_PATH;
2286
+ loadedSettings.user.readOnly = false;
2287
+ const setValueSpy = vi.spyOn(loadedSettings, 'setValue');
2288
+ enforceAgentsMdSetting(loadedSettings);
2289
+ expect(setValueSpy).not.toHaveBeenCalled();
2290
+ });
2291
+ });
2147
2292
  describe('saveSettings', () => {
2148
2293
  it('should save settings using updateSettingsFilePreservingFormat', () => {
2149
2294
  const mockUpdateSettings = vi.mocked(updateSettingsFilePreservingFormat);