@vybestack/llxprt-code 0.7.0 → 0.8.0-nightly.251231.feb9158c8

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 (169) hide show
  1. package/dist/package.json +4 -3
  2. package/dist/src/auth/BucketFailoverHandlerImpl.spec.js +1 -1
  3. package/dist/src/auth/BucketFailoverHandlerImpl.spec.js.map +1 -1
  4. package/dist/src/auth/__tests__/oauthManager.safety.test.js +2 -2
  5. package/dist/src/auth/__tests__/oauthManager.safety.test.js.map +1 -1
  6. package/dist/src/auth/anthropic-oauth-provider.d.ts +3 -1
  7. package/dist/src/auth/anthropic-oauth-provider.js +40 -29
  8. package/dist/src/auth/anthropic-oauth-provider.js.map +1 -1
  9. package/dist/src/auth/codex-oauth-provider.d.ts +3 -2
  10. package/dist/src/auth/codex-oauth-provider.js +41 -2
  11. package/dist/src/auth/codex-oauth-provider.js.map +1 -1
  12. package/dist/src/auth/gemini-oauth-provider.d.ts +2 -1
  13. package/dist/src/auth/gemini-oauth-provider.js +5 -1
  14. package/dist/src/auth/gemini-oauth-provider.js.map +1 -1
  15. package/dist/src/auth/oauth-manager.bucketFailover.spec.js +1 -1
  16. package/dist/src/auth/oauth-manager.bucketFailover.spec.js.map +1 -1
  17. package/dist/src/auth/oauth-manager.bucketRefresh.spec.d.ts +6 -0
  18. package/dist/src/auth/oauth-manager.bucketRefresh.spec.js +56 -0
  19. package/dist/src/auth/oauth-manager.bucketRefresh.spec.js.map +1 -0
  20. package/dist/src/auth/oauth-manager.concurrency.spec.js +1 -1
  21. package/dist/src/auth/oauth-manager.concurrency.spec.js.map +1 -1
  22. package/dist/src/auth/oauth-manager.d.ts +19 -2
  23. package/dist/src/auth/oauth-manager.js +262 -10
  24. package/dist/src/auth/oauth-manager.js.map +1 -1
  25. package/dist/src/auth/oauth-manager.logout.spec.js +3 -3
  26. package/dist/src/auth/oauth-manager.logout.spec.js.map +1 -1
  27. package/dist/src/auth/oauth-manager.spec.js +2 -1
  28. package/dist/src/auth/oauth-manager.spec.js.map +1 -1
  29. package/dist/src/auth/qwen-oauth-provider.d.ts +3 -1
  30. package/dist/src/auth/qwen-oauth-provider.js +87 -21
  31. package/dist/src/auth/qwen-oauth-provider.js.map +1 -1
  32. package/dist/src/commands/extensions/install.js +2 -2
  33. package/dist/src/commands/extensions/install.js.map +1 -1
  34. package/dist/src/commands/extensions/install.test.js +28 -28
  35. package/dist/src/commands/extensions/install.test.js.map +1 -1
  36. package/dist/src/commands/extensions/link.js +2 -2
  37. package/dist/src/commands/extensions/link.js.map +1 -1
  38. package/dist/src/commands/extensions/uninstall.js +1 -1
  39. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  40. package/dist/src/commands/mcp/list.js +2 -2
  41. package/dist/src/commands/mcp/list.js.map +1 -1
  42. package/dist/src/config/__tests__/sandboxConfig.test.d.ts +6 -0
  43. package/dist/src/config/__tests__/sandboxConfig.test.js +81 -0
  44. package/dist/src/config/__tests__/sandboxConfig.test.js.map +1 -0
  45. package/dist/src/config/config.d.ts +6 -4
  46. package/dist/src/config/config.js +50 -13
  47. package/dist/src/config/config.js.map +1 -1
  48. package/dist/src/config/config.loadMemory.test.js +4 -1
  49. package/dist/src/config/config.loadMemory.test.js.map +1 -1
  50. package/dist/src/config/extension.d.ts +19 -18
  51. package/dist/src/config/extension.js +68 -55
  52. package/dist/src/config/extension.js.map +1 -1
  53. package/dist/src/config/extensions/extensionEnablement.d.ts +2 -2
  54. package/dist/src/config/extensions/extensionEnablement.js +1 -1
  55. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  56. package/dist/src/config/extensions/extensionEnablement.test.js +4 -4
  57. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  58. package/dist/src/config/extensions/github.js +1 -1
  59. package/dist/src/config/extensions/github.js.map +1 -1
  60. package/dist/src/config/extensions/github.test.js +5 -0
  61. package/dist/src/config/extensions/github.test.js.map +1 -1
  62. package/dist/src/config/extensions/update.js +3 -4
  63. package/dist/src/config/extensions/update.js.map +1 -1
  64. package/dist/src/config/sandboxConfig.d.ts +2 -0
  65. package/dist/src/config/sandboxConfig.js +309 -9
  66. package/dist/src/config/sandboxConfig.js.map +1 -1
  67. package/dist/src/config/sandboxProfiles.d.ts +32 -0
  68. package/dist/src/config/sandboxProfiles.js +81 -0
  69. package/dist/src/config/sandboxProfiles.js.map +1 -0
  70. package/dist/src/config/settings.js +56 -1
  71. package/dist/src/config/settings.js.map +1 -1
  72. package/dist/src/config/settingsSchema.d.ts +31 -9
  73. package/dist/src/config/settingsSchema.js +31 -9
  74. package/dist/src/config/settingsSchema.js.map +1 -1
  75. package/dist/src/extensions/extensionAutoUpdater.d.ts +1 -2
  76. package/dist/src/extensions/extensionAutoUpdater.js +14 -13
  77. package/dist/src/extensions/extensionAutoUpdater.js.map +1 -1
  78. package/dist/src/extensions/extensionAutoUpdater.test.js +5 -6
  79. package/dist/src/extensions/extensionAutoUpdater.test.js.map +1 -1
  80. package/dist/src/gemini.js +69 -19
  81. package/dist/src/gemini.js.map +1 -1
  82. package/dist/src/gemini.renderOptions.test.js +1 -1
  83. package/dist/src/gemini.renderOptions.test.js.map +1 -1
  84. package/dist/src/gemini.test.js +20 -8
  85. package/dist/src/gemini.test.js.map +1 -1
  86. package/dist/src/generated/git-commit.d.ts +1 -1
  87. package/dist/src/generated/git-commit.js +1 -1
  88. package/dist/src/integration-tests/__tests__/oauth-buckets.integration.spec.js +2 -2
  89. package/dist/src/integration-tests/__tests__/oauth-buckets.integration.spec.js.map +1 -1
  90. package/dist/src/integration-tests/todo-continuation.integration.test.js +3 -3
  91. package/dist/src/integration-tests/todo-continuation.integration.test.js.map +1 -1
  92. package/dist/src/nonInteractiveCli.js +47 -11
  93. package/dist/src/nonInteractiveCli.js.map +1 -1
  94. package/dist/src/providers/aliases/mistral.config +8 -0
  95. package/dist/src/runtime/runtimeSettings.js +8 -0
  96. package/dist/src/runtime/runtimeSettings.js.map +1 -1
  97. package/dist/src/services/FileCommandLoader.d.ts +1 -1
  98. package/dist/src/services/FileCommandLoader.js +4 -4
  99. package/dist/src/services/FileCommandLoader.js.map +1 -1
  100. package/dist/src/ui/AppContainer.js +66 -9
  101. package/dist/src/ui/AppContainer.js.map +1 -1
  102. package/dist/src/ui/commands/memoryCommand.d.ts +1 -1
  103. package/dist/src/ui/commands/memoryCommand.js +8 -5
  104. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  105. package/dist/src/ui/commands/restoreCommand.js +1 -1
  106. package/dist/src/ui/commands/restoreCommand.js.map +1 -1
  107. package/dist/src/ui/components/Composer.js +1 -1
  108. package/dist/src/ui/components/Composer.js.map +1 -1
  109. package/dist/src/ui/components/DialogManager.js +3 -3
  110. package/dist/src/ui/components/DialogManager.js.map +1 -1
  111. package/dist/src/ui/components/FolderTrustDialog.js +10 -4
  112. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
  113. package/dist/src/ui/components/FolderTrustDialog.test.js +6 -10
  114. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  115. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +2 -2
  116. package/dist/src/ui/components/WorkspaceMigrationDialog.js +2 -2
  117. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +1 -1
  118. package/dist/src/ui/components/messages/CompressionMessage.js +28 -4
  119. package/dist/src/ui/components/messages/CompressionMessage.js.map +1 -1
  120. package/dist/src/ui/contexts/KeypressContext.js +7 -0
  121. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  122. package/dist/src/ui/contexts/KeypressContext.test.js +1 -1
  123. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  124. package/dist/src/ui/contexts/UIStateContext.d.ts +4 -5
  125. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +1 -1
  126. package/dist/src/ui/hooks/slashCommandProcessor.js +25 -9
  127. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  128. package/dist/src/ui/hooks/useExtensionUpdates.test.js +3 -0
  129. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  130. package/dist/src/ui/hooks/useFolderTrust.d.ts +4 -1
  131. package/dist/src/ui/hooks/useFolderTrust.js +18 -3
  132. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  133. package/dist/src/ui/hooks/useGeminiStream.js +55 -5
  134. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  135. package/dist/src/ui/hooks/useHistoryManager.d.ts +1 -1
  136. package/dist/src/ui/hooks/useHistoryManager.js +2 -2
  137. package/dist/src/ui/hooks/useHistoryManager.js.map +1 -1
  138. package/dist/src/ui/hooks/useReactToolScheduler.js +6 -2
  139. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  140. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +2 -2
  141. package/dist/src/ui/hooks/useWorkspaceMigration.js +13 -8
  142. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +1 -1
  143. package/dist/src/ui/oauth-submission.test.js +2 -2
  144. package/dist/src/ui/oauth-submission.test.js.map +1 -1
  145. package/dist/src/ui/utils/ui-sizing.d.ts +7 -0
  146. package/dist/src/ui/utils/ui-sizing.js +22 -0
  147. package/dist/src/ui/utils/ui-sizing.js.map +1 -0
  148. package/dist/src/utils/commentJson.d.ts +9 -0
  149. package/dist/src/utils/commentJson.js +130 -0
  150. package/dist/src/utils/commentJson.js.map +1 -0
  151. package/dist/src/utils/commentJson.test.d.ts +6 -0
  152. package/dist/src/utils/commentJson.test.js +307 -0
  153. package/dist/src/utils/commentJson.test.js.map +1 -0
  154. package/dist/src/utils/errors.d.ts +25 -0
  155. package/dist/src/utils/errors.js +78 -0
  156. package/dist/src/utils/errors.js.map +1 -1
  157. package/dist/src/utils/errors.test.d.ts +6 -0
  158. package/dist/src/utils/errors.test.js +178 -0
  159. package/dist/src/utils/errors.test.js.map +1 -0
  160. package/dist/src/utils/math.d.ts +13 -0
  161. package/dist/src/utils/math.js +14 -0
  162. package/dist/src/utils/math.js.map +1 -0
  163. package/dist/src/utils/sandbox.d.ts +1 -1
  164. package/dist/src/utils/sandbox.js +186 -13
  165. package/dist/src/utils/sandbox.js.map +1 -1
  166. package/dist/src/validateNonInterActiveAuth.js +58 -3
  167. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  168. package/dist/tsconfig.build.tsbuildinfo +1 -1
  169. package/package.json +4 -3
@@ -7,14 +7,158 @@ import { FatalSandboxError } from '@vybestack/llxprt-code-core';
7
7
  import commandExists from 'command-exists';
8
8
  import * as os from 'node:os';
9
9
  import { getPackageJson } from '../utils/package.js';
10
+ import { resolvePath } from '../utils/resolvePath.js';
11
+ import { ensureDefaultSandboxProfiles, loadSandboxProfile, } from './sandboxProfiles.js';
10
12
  const VALID_SANDBOX_COMMANDS = [
11
13
  'docker',
12
14
  'podman',
13
15
  'sandbox-exec',
14
16
  ];
17
+ const VALID_ENGINE_CHOICES = [
18
+ 'auto',
19
+ 'docker',
20
+ 'podman',
21
+ 'sandbox-exec',
22
+ 'none',
23
+ ];
24
+ const VALID_NETWORK_CHOICES = ['on', 'off', 'proxied'];
25
+ const VALID_SSH_AGENT_CHOICES = ['auto', 'on', 'off'];
15
26
  function isSandboxCommand(value) {
16
27
  return VALID_SANDBOX_COMMANDS.includes(value);
17
28
  }
29
+ function isEngineChoice(value) {
30
+ return VALID_ENGINE_CHOICES.includes(value);
31
+ }
32
+ function normalizeEngineInput(value) {
33
+ if (!value) {
34
+ return undefined;
35
+ }
36
+ const trimmed = value.trim().toLowerCase();
37
+ if (trimmed.length === 0) {
38
+ return undefined;
39
+ }
40
+ if (!isEngineChoice(trimmed)) {
41
+ throw new FatalSandboxError(`Invalid sandbox engine '${value}'. Must be one of ${VALID_ENGINE_CHOICES.join(', ')}`);
42
+ }
43
+ return trimmed;
44
+ }
45
+ function parseMemoryLimit(memory) {
46
+ const trimmed = memory.trim();
47
+ if (trimmed.length === 0) {
48
+ throw new FatalSandboxError('Sandbox memory value cannot be empty');
49
+ }
50
+ const match = trimmed.match(/^(\d+)([kKmMgG])?$/);
51
+ if (!match) {
52
+ throw new FatalSandboxError(`Invalid sandbox memory value '${memory}'. Expected values like 512m or 2g.`);
53
+ }
54
+ const value = Number(match[1]);
55
+ if (!Number.isFinite(value) || value <= 0) {
56
+ throw new FatalSandboxError(`Sandbox memory value must be positive, got '${memory}'.`);
57
+ }
58
+ const unit = match[2]?.toLowerCase() ?? 'm';
59
+ return `${value}${unit}`;
60
+ }
61
+ function parseCpuLimit(value) {
62
+ const cpuValue = typeof value === 'string' ? Number(value) : value;
63
+ if (!Number.isFinite(cpuValue) || cpuValue <= 0) {
64
+ throw new FatalSandboxError(`Sandbox CPU value must be greater than zero, got '${value}'.`);
65
+ }
66
+ return cpuValue;
67
+ }
68
+ function parsePidsLimit(value) {
69
+ const pidsValue = typeof value === 'string' ? Number(value) : value;
70
+ if (!Number.isFinite(pidsValue) || pidsValue <= 0) {
71
+ throw new FatalSandboxError(`Sandbox pids value must be greater than zero, got '${value}'.`);
72
+ }
73
+ if (!Number.isInteger(pidsValue)) {
74
+ throw new FatalSandboxError(`Sandbox pids value must be an integer, got '${value}'.`);
75
+ }
76
+ return pidsValue;
77
+ }
78
+ function resolveMountPath(input) {
79
+ const resolved = resolvePath(input);
80
+ if (!resolved) {
81
+ throw new FatalSandboxError(`Mount path cannot be empty.`);
82
+ }
83
+ return resolved;
84
+ }
85
+ function normalizeEnvEntries(env) {
86
+ if (!env) {
87
+ return undefined;
88
+ }
89
+ const entries = {};
90
+ for (const [key, value] of Object.entries(env)) {
91
+ if (typeof value !== 'string') {
92
+ throw new FatalSandboxError(`Sandbox env value for '${key}' must be a string.`);
93
+ }
94
+ const trimmedValue = value.trim();
95
+ if (trimmedValue.startsWith('~') ||
96
+ trimmedValue.toLowerCase().startsWith('%userprofile%')) {
97
+ entries[key] = resolvePath(trimmedValue);
98
+ }
99
+ else {
100
+ entries[key] = value;
101
+ }
102
+ }
103
+ return entries;
104
+ }
105
+ function normalizeMounts(mounts) {
106
+ if (!mounts) {
107
+ return undefined;
108
+ }
109
+ return mounts.map((mount) => {
110
+ if (!mount.from || mount.from.trim().length === 0) {
111
+ throw new FatalSandboxError('Sandbox mount requires a "from" path.');
112
+ }
113
+ const from = resolveMountPath(mount.from);
114
+ const to = mount.to ? resolveMountPath(mount.to) : undefined;
115
+ const mode = mount.mode ?? 'ro';
116
+ if (mode !== 'ro' && mode !== 'rw') {
117
+ throw new FatalSandboxError(`Sandbox mount mode must be 'ro' or 'rw', got '${mode}'.`);
118
+ }
119
+ return { from, to, mode };
120
+ });
121
+ }
122
+ function normalizeSandboxProfile(profile) {
123
+ const normalized = { ...profile };
124
+ if (profile.engine) {
125
+ const engine = normalizeEngineInput(profile.engine);
126
+ normalized.engine = engine;
127
+ }
128
+ if (profile.network) {
129
+ const normalizedNetwork = profile.network.trim().toLowerCase();
130
+ if (!VALID_NETWORK_CHOICES.includes(normalizedNetwork)) {
131
+ throw new FatalSandboxError(`Invalid sandbox network '${profile.network}'. Must be one of ${VALID_NETWORK_CHOICES.join(', ')}`);
132
+ }
133
+ normalized.network =
134
+ normalizedNetwork;
135
+ }
136
+ if (profile.sshAgent) {
137
+ const normalizedSsh = profile.sshAgent.trim().toLowerCase();
138
+ if (!VALID_SSH_AGENT_CHOICES.includes(normalizedSsh)) {
139
+ throw new FatalSandboxError(`Invalid sandbox sshAgent '${profile.sshAgent}'. Must be one of ${VALID_SSH_AGENT_CHOICES.join(', ')}`);
140
+ }
141
+ normalized.sshAgent =
142
+ normalizedSsh;
143
+ }
144
+ if (profile.resources) {
145
+ normalized.resources = {
146
+ ...profile.resources,
147
+ cpus: profile.resources.cpus !== undefined
148
+ ? parseCpuLimit(profile.resources.cpus)
149
+ : undefined,
150
+ memory: profile.resources.memory !== undefined
151
+ ? parseMemoryLimit(profile.resources.memory)
152
+ : undefined,
153
+ pids: profile.resources.pids !== undefined
154
+ ? parsePidsLimit(profile.resources.pids)
155
+ : undefined,
156
+ };
157
+ }
158
+ normalized.mounts = normalizeMounts(profile.mounts);
159
+ normalized.env = normalizeEnvEntries(profile.env);
160
+ return normalized;
161
+ }
18
162
  function getSandboxCommand(sandbox) {
19
163
  // If the SANDBOX env var is set, we're already inside the sandbox.
20
164
  if (process.env.SANDBOX) {
@@ -43,9 +187,10 @@ function getSandboxCommand(sandbox) {
43
187
  }
44
188
  throw new FatalSandboxError(`Missing sandbox command '${sandbox}' (from LLXPRT_SANDBOX)`);
45
189
  }
46
- // look for seatbelt, docker, or podman, in that order
47
- // for container-based sandboxing, require sandbox to be enabled explicitly
48
- if (os.platform() === 'darwin' && commandExists.sync('sandbox-exec')) {
190
+ // All sandbox types require explicit opt-in (sandbox === true)
191
+ if (sandbox === true &&
192
+ os.platform() === 'darwin' &&
193
+ commandExists.sync('sandbox-exec')) {
49
194
  return 'sandbox-exec';
50
195
  }
51
196
  else if (commandExists.sync('docker') && sandbox === true) {
@@ -61,13 +206,168 @@ function getSandboxCommand(sandbox) {
61
206
  }
62
207
  return '';
63
208
  }
209
+ function resolveSandboxEngine(engine, baseCommand) {
210
+ if (engine === 'none') {
211
+ return '';
212
+ }
213
+ const pickFallback = () => {
214
+ if (commandExists.sync('docker')) {
215
+ return 'docker';
216
+ }
217
+ if (commandExists.sync('podman')) {
218
+ return 'podman';
219
+ }
220
+ if (os.platform() === 'darwin' && commandExists.sync('sandbox-exec')) {
221
+ return 'sandbox-exec';
222
+ }
223
+ return '';
224
+ };
225
+ if (engine && engine !== 'auto') {
226
+ if (engine === 'sandbox-exec') {
227
+ if (os.platform() === 'darwin' && commandExists.sync('sandbox-exec')) {
228
+ return 'sandbox-exec';
229
+ }
230
+ return pickFallback();
231
+ }
232
+ if (engine === 'docker' || engine === 'podman') {
233
+ if (commandExists.sync(engine)) {
234
+ return engine;
235
+ }
236
+ return pickFallback();
237
+ }
238
+ }
239
+ if (baseCommand) {
240
+ return baseCommand;
241
+ }
242
+ // Don't auto-enable sandbox - require explicit opt-in
243
+ return '';
244
+ }
245
+ function applyProfileEnvironment(profile) {
246
+ const env = {};
247
+ if (profile.env) {
248
+ for (const [key, value] of Object.entries(profile.env)) {
249
+ env[key] = value;
250
+ }
251
+ }
252
+ if (profile.network) {
253
+ env.LLXPRT_SANDBOX_NETWORK = profile.network;
254
+ }
255
+ if (profile.sshAgent) {
256
+ env.LLXPRT_SANDBOX_SSH_AGENT = profile.sshAgent;
257
+ }
258
+ if (profile.resources?.cpus !== undefined) {
259
+ env.LLXPRT_SANDBOX_CPUS = String(profile.resources.cpus);
260
+ }
261
+ if (profile.resources?.memory !== undefined) {
262
+ env.LLXPRT_SANDBOX_MEMORY = profile.resources.memory;
263
+ }
264
+ if (profile.resources?.pids !== undefined) {
265
+ env.LLXPRT_SANDBOX_PIDS = String(profile.resources.pids);
266
+ }
267
+ if (profile.mounts && profile.mounts.length > 0) {
268
+ const mountsValue = profile.mounts
269
+ .map((mount) => {
270
+ const target = mount.to ?? mount.from;
271
+ const mode = mount.mode ?? 'ro';
272
+ return `${mount.from}:${target}:${mode}`;
273
+ })
274
+ .join(',');
275
+ env.SANDBOX_MOUNTS = mountsValue;
276
+ env.LLXPRT_SANDBOX_MOUNTS = mountsValue;
277
+ }
278
+ return env;
279
+ }
280
+ function applySandboxProfileEnv(profile) {
281
+ if (!profile) {
282
+ return;
283
+ }
284
+ const env = applyProfileEnvironment(profile);
285
+ for (const [key, value] of Object.entries(env)) {
286
+ process.env[key] = value;
287
+ }
288
+ // Preserve backward-compatible env vars used by the sandbox launcher while
289
+ // ensuring the profile's explicit choices win over ambient env.
290
+ if (profile.network) {
291
+ process.env.SANDBOX_NETWORK = profile.network;
292
+ }
293
+ if (profile.sshAgent) {
294
+ process.env.SANDBOX_SSH_AGENT = profile.sshAgent;
295
+ }
296
+ if (profile.resources?.cpus !== undefined) {
297
+ process.env.SANDBOX_CPUS = String(profile.resources.cpus);
298
+ }
299
+ if (profile.resources?.memory !== undefined) {
300
+ process.env.SANDBOX_MEMORY = profile.resources.memory;
301
+ }
302
+ if (profile.resources?.pids !== undefined) {
303
+ process.env.SANDBOX_PIDS = String(profile.resources.pids);
304
+ }
305
+ }
306
+ function resolveSandboxImage(packageImage, profile, argvImage) {
307
+ return (argvImage ??
308
+ profile?.image ??
309
+ process.env.LLXPRT_SANDBOX_IMAGE ??
310
+ packageImage);
311
+ }
312
+ function resolveSandboxProfileName(value) {
313
+ if (!value) {
314
+ return undefined;
315
+ }
316
+ const trimmed = value.trim();
317
+ return trimmed.length > 0 ? trimmed : undefined;
318
+ }
319
+ function normalizeProfileName(profileName) {
320
+ return profileName.replace(/\.json$/i, '');
321
+ }
64
322
  export async function loadSandboxConfig(settings, argv) {
65
- const sandboxOption = argv.sandbox ?? settings.sandbox;
66
- const command = getSandboxCommand(sandboxOption);
323
+ const cliEngine = normalizeEngineInput(argv.sandboxEngine);
324
+ if (cliEngine === 'none') {
325
+ return undefined;
326
+ }
67
327
  const packageJson = await getPackageJson();
68
- const image = argv.sandboxImage ??
69
- process.env.LLXPRT_SANDBOX_IMAGE ??
70
- packageJson?.config?.sandboxImageUri;
71
- return command && image ? { command, image } : undefined;
328
+ const packageImage = packageJson?.config?.sandboxImageUri;
329
+ let sandboxProfile;
330
+ const profileName = resolveSandboxProfileName(argv.sandboxProfileLoad);
331
+ if (profileName) {
332
+ await ensureDefaultSandboxProfiles(packageImage);
333
+ try {
334
+ sandboxProfile = normalizeSandboxProfile(await loadSandboxProfile(normalizeProfileName(profileName)));
335
+ }
336
+ catch (error) {
337
+ throw new FatalSandboxError(`Failed to load sandbox profile '${profileName}': ${error instanceof Error ? error.message : String(error)}`);
338
+ }
339
+ }
340
+ const sandboxOption = argv.sandbox ?? settings.sandbox;
341
+ let baseCommand = '';
342
+ try {
343
+ baseCommand = getSandboxCommand(sandboxOption);
344
+ }
345
+ catch (error) {
346
+ // If the user is driving sandbox selection via --sandbox-engine or a profile engine,
347
+ // allow sandboxOption parsing to fail without aborting.
348
+ if (!cliEngine && !sandboxProfile?.engine) {
349
+ throw error;
350
+ }
351
+ }
352
+ // Loading a sandbox profile implies sandboxing intent, even if --sandbox isn't set.
353
+ if (!baseCommand && sandboxProfile) {
354
+ baseCommand = commandExists.sync('docker')
355
+ ? 'docker'
356
+ : commandExists.sync('podman')
357
+ ? 'podman'
358
+ : os.platform() === 'darwin' && commandExists.sync('sandbox-exec')
359
+ ? 'sandbox-exec'
360
+ : '';
361
+ }
362
+ const command = resolveSandboxEngine(cliEngine ?? sandboxProfile?.engine, baseCommand);
363
+ if (!command) {
364
+ return undefined;
365
+ }
366
+ const image = resolveSandboxImage(packageImage, sandboxProfile, argv.sandboxImage);
367
+ if (!image) {
368
+ return undefined;
369
+ }
370
+ applySandboxProfileEnv(sandboxProfile);
371
+ return { command, image };
72
372
  }
73
373
  //# sourceMappingURL=sandboxConfig.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandboxConfig.js","sourceRoot":"","sources":["../../../src/config/sandboxConfig.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAUrD,MAAM,sBAAsB,GAA4C;IACtE,QAAQ;IACR,QAAQ;IACR,cAAc;CACf,CAAC;AAEF,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAQ,sBAA4C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,iBAAiB,CACxB,OAA0B;IAE1B,mEAAmE;IACnE,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,2FAA2F;IAC3F,MAAM,4BAA4B,GAChC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACzD,OAAO;QACL,4BAA4B,EAAE,MAAM,GAAG,CAAC;YACtC,CAAC,CAAC,4BAA4B;YAC9B,CAAC,CAAC,OAAO,CAAC;IACd,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,GAAG,IAAI,CAAC;SACrD,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,GAAG,KAAK,CAAC;IAE7E,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,iBAAiB,CACzB,4BAA4B,OAAO,qBAAqB,sBAAsB,CAAC,IAAI,CACjF,IAAI,CACL,EAAE,CACJ,CAAC;QACJ,CAAC;QACD,wCAAwC;QACxC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,iBAAiB,CACzB,4BAA4B,OAAO,yBAAyB,CAC7D,CAAC;IACJ,CAAC;IAED,sDAAsD;IACtD,2EAA2E;IAC3E,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACrE,OAAO,cAAc,CAAC;IACxB,CAAC;SAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC5D,OAAO,QAAQ,CAAC;IAClB,CAAC;SAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC5D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oEAAoE;IACpE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,iBAAiB,CACzB,sEAAsE;YACpE,+DAA+D,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAkB,EAClB,IAAoB;IAEpB,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC;IACvD,MAAM,OAAO,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAEjD,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,MAAM,KAAK,GACT,IAAI,CAAC,YAAY;QACjB,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAChC,WAAW,EAAE,MAAM,EAAE,eAAe,CAAC;IAEvC,OAAO,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"sandboxConfig.js","sourceRoot":"","sources":["../../../src/config/sandboxConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export type SandboxProfileEngine = 'auto' | 'docker' | 'podman' | 'sandbox-exec' | 'none';
7
+ export type SandboxProfileNetwork = 'on' | 'off' | 'proxied';
8
+ export type SandboxProfileSshAgent = 'auto' | 'on' | 'off';
9
+ export interface SandboxProfileResources {
10
+ cpus?: number;
11
+ memory?: string;
12
+ pids?: number;
13
+ }
14
+ export interface SandboxProfileMount {
15
+ from: string;
16
+ to?: string;
17
+ mode?: 'ro' | 'rw';
18
+ }
19
+ export interface SandboxProfile {
20
+ engine?: SandboxProfileEngine;
21
+ image?: string;
22
+ resources?: SandboxProfileResources;
23
+ network?: SandboxProfileNetwork;
24
+ sshAgent?: SandboxProfileSshAgent;
25
+ mounts?: SandboxProfileMount[];
26
+ env?: Record<string, string>;
27
+ }
28
+ export declare const SANDBOX_PROFILES_DIR_NAME = "sandboxes";
29
+ export declare function getSandboxProfilesDir(): string;
30
+ export declare function getDefaultSandboxProfiles(image: string | undefined): Record<string, SandboxProfile>;
31
+ export declare function ensureDefaultSandboxProfiles(image: string | undefined): Promise<void>;
32
+ export declare function loadSandboxProfile(profileName: string): Promise<SandboxProfile>;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import fs from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { Storage } from '@vybestack/llxprt-code-core';
9
+ export const SANDBOX_PROFILES_DIR_NAME = 'sandboxes';
10
+ export function getSandboxProfilesDir() {
11
+ return path.join(Storage.getGlobalLlxprtDir(), SANDBOX_PROFILES_DIR_NAME);
12
+ }
13
+ export function getDefaultSandboxProfiles(image) {
14
+ // Only include image field if a valid image is provided
15
+ const imageField = image ? { image } : {};
16
+ return {
17
+ dev: {
18
+ engine: 'auto',
19
+ ...imageField,
20
+ resources: { cpus: 2, memory: '4g', pids: 256 },
21
+ network: 'on',
22
+ sshAgent: 'auto',
23
+ mounts: [],
24
+ env: {},
25
+ },
26
+ safe: {
27
+ engine: 'auto',
28
+ ...imageField,
29
+ resources: { cpus: 2, memory: '4g', pids: 128 },
30
+ network: 'off',
31
+ sshAgent: 'off',
32
+ mounts: [],
33
+ env: {},
34
+ },
35
+ tight: {
36
+ engine: 'auto',
37
+ ...imageField,
38
+ resources: { cpus: 1, memory: '2g', pids: 64 },
39
+ network: 'off',
40
+ sshAgent: 'off',
41
+ mounts: [],
42
+ env: {},
43
+ },
44
+ offline: {
45
+ engine: 'auto',
46
+ ...imageField,
47
+ resources: { cpus: 2, memory: '4g', pids: 128 },
48
+ network: 'off',
49
+ sshAgent: 'off',
50
+ mounts: [],
51
+ env: {},
52
+ },
53
+ };
54
+ }
55
+ export async function ensureDefaultSandboxProfiles(image) {
56
+ const profilesDir = getSandboxProfilesDir();
57
+ await fs.mkdir(profilesDir, { recursive: true, mode: 0o755 });
58
+ const defaults = getDefaultSandboxProfiles(image);
59
+ await Promise.all(Object.entries(defaults).map(async ([name, profile]) => {
60
+ const profilePath = path.join(profilesDir, `${name}.json`);
61
+ const payload = JSON.stringify(profile, null, 2);
62
+ try {
63
+ await fs.writeFile(profilePath, `${payload}\n`, {
64
+ mode: 0o644,
65
+ flag: 'wx',
66
+ });
67
+ }
68
+ catch (error) {
69
+ if (error.code !== 'EEXIST') {
70
+ throw error;
71
+ }
72
+ }
73
+ }));
74
+ }
75
+ export async function loadSandboxProfile(profileName) {
76
+ const profilesDir = getSandboxProfilesDir();
77
+ const profilePath = path.join(profilesDir, `${profileName}.json`);
78
+ const raw = await fs.readFile(profilePath, 'utf8');
79
+ return JSON.parse(raw);
80
+ }
81
+ //# sourceMappingURL=sandboxProfiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandboxProfiles.js","sourceRoot":"","sources":["../../../src/config/sandboxProfiles.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import * as dotenv from 'dotenv';
10
10
  import process from 'node:process';
11
11
  import { LLXPRT_CONFIG_DIR as LLXPRT_DIR, FatalConfigError, getErrorMessage, Storage, } from '@vybestack/llxprt-code-core';
12
12
  import stripJsonComments from 'strip-json-comments';
13
+ import * as commentJson from 'comment-json';
13
14
  import { DefaultLight } from '../ui/themes/default-light.js';
14
15
  import { DefaultDark } from '../ui/themes/default.js';
15
16
  import { isWorkspaceTrusted, isFolderTrustEnabled } from './trustedFolders.js';
@@ -563,6 +564,40 @@ export function loadSettings(workspaceDir = process.cwd()) {
563
564
  settings: workspaceSettings,
564
565
  }, isTrusted);
565
566
  }
567
+ function deepMergeWithComments(target, source) {
568
+ if (typeof target !== 'object' ||
569
+ target === null ||
570
+ typeof source !== 'object' ||
571
+ source === null) {
572
+ return source;
573
+ }
574
+ if (Array.isArray(source)) {
575
+ return source;
576
+ }
577
+ const result = target;
578
+ const sourceObj = source;
579
+ // Add or update keys from source
580
+ Object.keys(sourceObj).forEach((key) => {
581
+ if (typeof result[key] === 'object' &&
582
+ result[key] !== null &&
583
+ !Array.isArray(result[key]) &&
584
+ typeof sourceObj[key] === 'object' &&
585
+ sourceObj[key] !== null &&
586
+ !Array.isArray(sourceObj[key])) {
587
+ result[key] = deepMergeWithComments(result[key], sourceObj[key]);
588
+ }
589
+ else {
590
+ result[key] = sourceObj[key];
591
+ }
592
+ });
593
+ // Remove keys that are not in source
594
+ Object.keys(result).forEach((key) => {
595
+ if (!(key in sourceObj)) {
596
+ delete result[key];
597
+ }
598
+ });
599
+ return result;
600
+ }
566
601
  export function saveSettings(settingsFile) {
567
602
  try {
568
603
  // Ensure the directory exists
@@ -570,7 +605,27 @@ export function saveSettings(settingsFile) {
570
605
  if (!fs.existsSync(dirPath)) {
571
606
  fs.mkdirSync(dirPath, { recursive: true });
572
607
  }
573
- fs.writeFileSync(settingsFile.path, JSON.stringify(settingsFile.settings, null, 2), 'utf-8');
608
+ // Read the original file to preserve comments
609
+ let outputContent;
610
+ if (fs.existsSync(settingsFile.path)) {
611
+ const originalContent = fs.readFileSync(settingsFile.path, 'utf-8');
612
+ try {
613
+ // Parse with comments preserved
614
+ const parsedWithComments = commentJson.parse(originalContent);
615
+ // Deep merge to preserve comments at all levels
616
+ const merged = deepMergeWithComments(parsedWithComments, settingsFile.settings);
617
+ outputContent = commentJson.stringify(merged, null, 2);
618
+ }
619
+ catch {
620
+ // If parsing with comments fails, fall back to regular JSON
621
+ outputContent = JSON.stringify(settingsFile.settings, null, 2);
622
+ }
623
+ }
624
+ else {
625
+ // New file, no comments to preserve
626
+ outputContent = JSON.stringify(settingsFile.settings, null, 2);
627
+ }
628
+ fs.writeFileSync(settingsFile.path, outputContent, 'utf-8');
574
629
  }
575
630
  catch (error) {
576
631
  console.error('Error saving user settings file:', error);