mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
Merge pull request #282 from casiusss/feat/sandbox-mode-setting
feat: add configurable sandbox mode setting
This commit is contained in:
@@ -190,12 +190,31 @@ server.on('upgrade', (request, socket, head) => {
|
||||
|
||||
// Events WebSocket connection handler
|
||||
wss.on('connection', (ws: WebSocket) => {
|
||||
console.log('[WebSocket] Client connected');
|
||||
console.log('[WebSocket] Client connected, ready state:', ws.readyState);
|
||||
|
||||
// Subscribe to all events and forward to this client
|
||||
const unsubscribe = events.subscribe((type, payload) => {
|
||||
console.log('[WebSocket] Event received:', {
|
||||
type,
|
||||
hasPayload: !!payload,
|
||||
payloadKeys: payload ? Object.keys(payload) : [],
|
||||
wsReadyState: ws.readyState,
|
||||
wsOpen: ws.readyState === WebSocket.OPEN,
|
||||
});
|
||||
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type, payload }));
|
||||
const message = JSON.stringify({ type, payload });
|
||||
console.log('[WebSocket] Sending event to client:', {
|
||||
type,
|
||||
messageLength: message.length,
|
||||
sessionId: (payload as any)?.sessionId,
|
||||
});
|
||||
ws.send(message);
|
||||
} else {
|
||||
console.log(
|
||||
'[WebSocket] WARNING: Cannot send event, WebSocket not open. ReadyState:',
|
||||
ws.readyState
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -205,7 +224,7 @@ wss.on('connection', (ws: WebSocket) => {
|
||||
});
|
||||
|
||||
ws.on('error', (error) => {
|
||||
console.error('[WebSocket] Error:', error);
|
||||
console.error('[WebSocket] ERROR:', error);
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -216,6 +216,9 @@ export interface CreateSdkOptionsConfig {
|
||||
|
||||
/** Enable auto-loading of CLAUDE.md files via SDK's settingSources */
|
||||
autoLoadClaudeMd?: boolean;
|
||||
|
||||
/** Enable sandbox mode for bash command isolation */
|
||||
enableSandboxMode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,7 +317,7 @@ export function createSuggestionsOptions(config: CreateSdkOptionsConfig): Option
|
||||
* - Full tool access for code modification
|
||||
* - Standard turns for interactive sessions
|
||||
* - Model priority: explicit model > session model > chat default
|
||||
* - Sandbox enabled for bash safety
|
||||
* - Sandbox mode controlled by enableSandboxMode setting
|
||||
* - When autoLoadClaudeMd is true, uses preset mode and settingSources for CLAUDE.md loading
|
||||
*/
|
||||
export function createChatOptions(config: CreateSdkOptionsConfig): Options {
|
||||
@@ -333,10 +336,12 @@ export function createChatOptions(config: CreateSdkOptionsConfig): Options {
|
||||
maxTurns: MAX_TURNS.standard,
|
||||
cwd: config.cwd,
|
||||
allowedTools: [...TOOL_PRESETS.chat],
|
||||
...(config.enableSandboxMode && {
|
||||
sandbox: {
|
||||
enabled: true,
|
||||
autoAllowBashIfSandboxed: true,
|
||||
},
|
||||
}),
|
||||
...claudeMdOptions,
|
||||
...(config.abortController && { abortController: config.abortController }),
|
||||
};
|
||||
@@ -349,7 +354,7 @@ export function createChatOptions(config: CreateSdkOptionsConfig): Options {
|
||||
* - Full tool access for code modification and implementation
|
||||
* - Extended turns for thorough feature implementation
|
||||
* - Uses default model (can be overridden)
|
||||
* - Sandbox enabled for bash safety
|
||||
* - Sandbox mode controlled by enableSandboxMode setting
|
||||
* - When autoLoadClaudeMd is true, uses preset mode and settingSources for CLAUDE.md loading
|
||||
*/
|
||||
export function createAutoModeOptions(config: CreateSdkOptionsConfig): Options {
|
||||
@@ -365,10 +370,12 @@ export function createAutoModeOptions(config: CreateSdkOptionsConfig): Options {
|
||||
maxTurns: MAX_TURNS.maximum,
|
||||
cwd: config.cwd,
|
||||
allowedTools: [...TOOL_PRESETS.fullAccess],
|
||||
...(config.enableSandboxMode && {
|
||||
sandbox: {
|
||||
enabled: true,
|
||||
autoAllowBashIfSandboxed: true,
|
||||
},
|
||||
}),
|
||||
...claudeMdOptions,
|
||||
...(config.abortController && { abortController: config.abortController }),
|
||||
};
|
||||
|
||||
@@ -45,6 +45,34 @@ export async function getAutoLoadClaudeMdSetting(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the enableSandboxMode setting from global settings.
|
||||
* Returns false if settings service is not available.
|
||||
*
|
||||
* @param settingsService - Optional settings service instance
|
||||
* @param logPrefix - Prefix for log messages (e.g., '[AgentService]')
|
||||
* @returns Promise resolving to the enableSandboxMode setting value
|
||||
*/
|
||||
export async function getEnableSandboxModeSetting(
|
||||
settingsService?: SettingsService | null,
|
||||
logPrefix = '[SettingsHelper]'
|
||||
): Promise<boolean> {
|
||||
if (!settingsService) {
|
||||
console.log(`${logPrefix} SettingsService not available, sandbox mode disabled`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const globalSettings = await settingsService.getGlobalSettings();
|
||||
const result = globalSettings.enableSandboxMode ?? true;
|
||||
console.log(`${logPrefix} enableSandboxMode from global settings: ${result}`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`${logPrefix} Failed to load enableSandboxMode setting:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out CLAUDE.md from context files when autoLoadClaudeMd is enabled
|
||||
* and rebuilds the formatted prompt without it.
|
||||
|
||||
@@ -45,11 +45,7 @@ export class ClaudeProvider extends BaseProvider {
|
||||
maxTurns,
|
||||
cwd,
|
||||
allowedTools: toolsToUse,
|
||||
permissionMode: 'acceptEdits',
|
||||
sandbox: {
|
||||
enabled: true,
|
||||
autoAllowBashIfSandboxed: true,
|
||||
},
|
||||
permissionMode: 'default',
|
||||
abortController,
|
||||
// Resume existing SDK session if we have a session ID
|
||||
...(sdkSessionId && conversationHistory && conversationHistory.length > 0
|
||||
@@ -57,6 +53,8 @@ export class ClaudeProvider extends BaseProvider {
|
||||
: {}),
|
||||
// Forward settingSources for CLAUDE.md file loading
|
||||
...(options.settingSources && { settingSources: options.settingSources }),
|
||||
// Forward sandbox configuration
|
||||
...(options.sandbox && { sandbox: options.sandbox }),
|
||||
};
|
||||
|
||||
// Build prompt payload
|
||||
@@ -90,7 +88,8 @@ export class ClaudeProvider extends BaseProvider {
|
||||
yield msg as ProviderMessage;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[ClaudeProvider] executeQuery() error during execution:', error);
|
||||
console.error('[ClaudeProvider] ERROR: executeQuery() error during execution:', error);
|
||||
console.error('[ClaudeProvider] ERROR stack:', (error as Error).stack);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface ExecuteOptions {
|
||||
conversationHistory?: ConversationMessage[]; // Previous messages for context
|
||||
sdkSessionId?: string; // Claude SDK session ID for resuming conversations
|
||||
settingSources?: Array<'user' | 'project' | 'local'>; // Claude filesystem settings to load
|
||||
sandbox?: { enabled: boolean; autoAllowBashIfSandboxed?: boolean }; // Sandbox configuration
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,16 @@ export function createSendHandler(agentService: AgentService) {
|
||||
model?: string;
|
||||
};
|
||||
|
||||
console.log('[Send Handler] Received request:', {
|
||||
sessionId,
|
||||
messageLength: message?.length,
|
||||
workingDirectory,
|
||||
imageCount: imagePaths?.length || 0,
|
||||
model,
|
||||
});
|
||||
|
||||
if (!sessionId || !message) {
|
||||
console.log('[Send Handler] ERROR: Validation failed - missing sessionId or message');
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'sessionId and message are required',
|
||||
@@ -27,6 +36,8 @@ export function createSendHandler(agentService: AgentService) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[Send Handler] Validation passed, calling agentService.sendMessage()');
|
||||
|
||||
// Start the message processing (don't await - it streams via WebSocket)
|
||||
agentService
|
||||
.sendMessage({
|
||||
@@ -37,12 +48,16 @@ export function createSendHandler(agentService: AgentService) {
|
||||
model,
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[Send Handler] ERROR: Background error in sendMessage():', error);
|
||||
logError(error, 'Send message failed (background)');
|
||||
});
|
||||
|
||||
console.log('[Send Handler] Returning immediate response to client');
|
||||
|
||||
// Return immediately - responses come via WebSocket
|
||||
res.json({ success: true, message: 'Message sent' });
|
||||
} catch (error) {
|
||||
console.error('[Send Handler] ERROR: Synchronous error:', error);
|
||||
logError(error, 'Send message failed');
|
||||
res.status(500).json({ success: false, error: getErrorMessage(error) });
|
||||
}
|
||||
|
||||
@@ -17,7 +17,11 @@ import { ProviderFactory } from '../providers/provider-factory.js';
|
||||
import { createChatOptions, validateWorkingDirectory } from '../lib/sdk-options.js';
|
||||
import { PathNotAllowedError } from '@automaker/platform';
|
||||
import type { SettingsService } from './settings-service.js';
|
||||
import { getAutoLoadClaudeMdSetting, filterClaudeMdFromContext } from '../lib/settings-helpers.js';
|
||||
import {
|
||||
getAutoLoadClaudeMdSetting,
|
||||
getEnableSandboxModeSetting,
|
||||
filterClaudeMdFromContext,
|
||||
} from '../lib/settings-helpers.js';
|
||||
|
||||
interface Message {
|
||||
id: string;
|
||||
@@ -142,10 +146,12 @@ export class AgentService {
|
||||
}) {
|
||||
const session = this.sessions.get(sessionId);
|
||||
if (!session) {
|
||||
console.error('[AgentService] ERROR: Session not found:', sessionId);
|
||||
throw new Error(`Session ${sessionId} not found`);
|
||||
}
|
||||
|
||||
if (session.isRunning) {
|
||||
console.error('[AgentService] ERROR: Agent already running for session:', sessionId);
|
||||
throw new Error('Agent is already processing a message');
|
||||
}
|
||||
|
||||
@@ -215,6 +221,12 @@ export class AgentService {
|
||||
'[AgentService]'
|
||||
);
|
||||
|
||||
// Load enableSandboxMode setting (global setting only)
|
||||
const enableSandboxMode = await getEnableSandboxModeSetting(
|
||||
this.settingsService,
|
||||
'[AgentService]'
|
||||
);
|
||||
|
||||
// Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.)
|
||||
const contextResult = await loadContextFiles({
|
||||
projectPath: effectiveWorkDir,
|
||||
@@ -239,6 +251,7 @@ export class AgentService {
|
||||
systemPrompt: combinedSystemPrompt,
|
||||
abortController: session.abortController!,
|
||||
autoLoadClaudeMd,
|
||||
enableSandboxMode,
|
||||
});
|
||||
|
||||
// Extract model, maxTurns, and allowedTools from SDK options
|
||||
@@ -249,10 +262,6 @@ export class AgentService {
|
||||
// Get provider for this model
|
||||
const provider = ProviderFactory.getProviderForModel(effectiveModel);
|
||||
|
||||
console.log(
|
||||
`[AgentService] Using provider "${provider.getName()}" for model "${effectiveModel}"`
|
||||
);
|
||||
|
||||
// Build options for provider
|
||||
const options: ExecuteOptions = {
|
||||
prompt: '', // Will be set below based on images
|
||||
@@ -264,6 +273,7 @@ export class AgentService {
|
||||
abortController: session.abortController!,
|
||||
conversationHistory: conversationHistory.length > 0 ? conversationHistory : undefined,
|
||||
settingSources: sdkOptions.settingSources,
|
||||
sandbox: sdkOptions.sandbox, // Pass sandbox configuration
|
||||
sdkSessionId: session.sdkSessionId, // Pass SDK session ID for resuming
|
||||
};
|
||||
|
||||
@@ -289,7 +299,6 @@ export class AgentService {
|
||||
// Capture SDK session ID from any message and persist it
|
||||
if (msg.session_id && !session.sdkSessionId) {
|
||||
session.sdkSessionId = msg.session_id;
|
||||
console.log(`[AgentService] Captured SDK session ID: ${msg.session_id}`);
|
||||
// Persist the SDK session ID to ensure conversation continuity across server restarts
|
||||
await this.updateSession(sessionId, { sdkSessionId: msg.session_id });
|
||||
}
|
||||
@@ -737,8 +746,6 @@ export class AgentService {
|
||||
queue: session.promptQueue,
|
||||
});
|
||||
|
||||
console.log(`[AgentService] Processing next queued prompt for session ${sessionId}`);
|
||||
|
||||
try {
|
||||
await this.sendMessage({
|
||||
sessionId,
|
||||
|
||||
@@ -32,7 +32,11 @@ import {
|
||||
} from '../lib/sdk-options.js';
|
||||
import { FeatureLoader } from './feature-loader.js';
|
||||
import type { SettingsService } from './settings-service.js';
|
||||
import { getAutoLoadClaudeMdSetting, filterClaudeMdFromContext } from '../lib/settings-helpers.js';
|
||||
import {
|
||||
getAutoLoadClaudeMdSetting,
|
||||
getEnableSandboxModeSetting,
|
||||
filterClaudeMdFromContext,
|
||||
} from '../lib/settings-helpers.js';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
@@ -1149,6 +1153,7 @@ Format your response as a structured markdown document.`;
|
||||
allowedTools: sdkOptions.allowedTools as string[],
|
||||
abortController,
|
||||
settingSources: sdkOptions.settingSources,
|
||||
sandbox: sdkOptions.sandbox, // Pass sandbox configuration
|
||||
};
|
||||
|
||||
const stream = provider.executeQuery(options);
|
||||
@@ -1833,12 +1838,16 @@ This mock response was generated because AUTOMAKER_MOCK_AGENT=true was set.
|
||||
? options.autoLoadClaudeMd
|
||||
: await getAutoLoadClaudeMdSetting(finalProjectPath, this.settingsService, '[AutoMode]');
|
||||
|
||||
// Load enableSandboxMode setting (global setting only)
|
||||
const enableSandboxMode = await getEnableSandboxModeSetting(this.settingsService, '[AutoMode]');
|
||||
|
||||
// Build SDK options using centralized configuration for feature implementation
|
||||
const sdkOptions = createAutoModeOptions({
|
||||
cwd: workDir,
|
||||
model: model,
|
||||
abortController,
|
||||
autoLoadClaudeMd,
|
||||
enableSandboxMode,
|
||||
});
|
||||
|
||||
// Extract model, maxTurns, and allowedTools from SDK options
|
||||
@@ -1879,6 +1888,7 @@ This mock response was generated because AUTOMAKER_MOCK_AGENT=true was set.
|
||||
abortController,
|
||||
systemPrompt: sdkOptions.systemPrompt,
|
||||
settingSources: sdkOptions.settingSources,
|
||||
sandbox: sdkOptions.sandbox, // Pass sandbox configuration
|
||||
};
|
||||
|
||||
// Execute via provider
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('sdk-options.ts', () => {
|
||||
it('should create options with chat settings', async () => {
|
||||
const { createChatOptions, TOOL_PRESETS, MAX_TURNS } = await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createChatOptions({ cwd: '/test/path' });
|
||||
const options = createChatOptions({ cwd: '/test/path', enableSandboxMode: true });
|
||||
|
||||
expect(options.cwd).toBe('/test/path');
|
||||
expect(options.maxTurns).toBe(MAX_TURNS.standard);
|
||||
@@ -212,6 +212,27 @@ describe('sdk-options.ts', () => {
|
||||
|
||||
expect(options.model).toBe('claude-sonnet-4-20250514');
|
||||
});
|
||||
|
||||
it('should not set sandbox when enableSandboxMode is false', async () => {
|
||||
const { createChatOptions } = await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createChatOptions({
|
||||
cwd: '/test/path',
|
||||
enableSandboxMode: false,
|
||||
});
|
||||
|
||||
expect(options.sandbox).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not set sandbox when enableSandboxMode is not provided', async () => {
|
||||
const { createChatOptions } = await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createChatOptions({
|
||||
cwd: '/test/path',
|
||||
});
|
||||
|
||||
expect(options.sandbox).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createAutoModeOptions', () => {
|
||||
@@ -219,7 +240,7 @@ describe('sdk-options.ts', () => {
|
||||
const { createAutoModeOptions, TOOL_PRESETS, MAX_TURNS } =
|
||||
await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createAutoModeOptions({ cwd: '/test/path' });
|
||||
const options = createAutoModeOptions({ cwd: '/test/path', enableSandboxMode: true });
|
||||
|
||||
expect(options.cwd).toBe('/test/path');
|
||||
expect(options.maxTurns).toBe(MAX_TURNS.maximum);
|
||||
@@ -252,6 +273,27 @@ describe('sdk-options.ts', () => {
|
||||
|
||||
expect(options.abortController).toBe(abortController);
|
||||
});
|
||||
|
||||
it('should not set sandbox when enableSandboxMode is false', async () => {
|
||||
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createAutoModeOptions({
|
||||
cwd: '/test/path',
|
||||
enableSandboxMode: false,
|
||||
});
|
||||
|
||||
expect(options.sandbox).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not set sandbox when enableSandboxMode is not provided', async () => {
|
||||
const { createAutoModeOptions } = await import('@/lib/sdk-options.js');
|
||||
|
||||
const options = createAutoModeOptions({
|
||||
cwd: '/test/path',
|
||||
});
|
||||
|
||||
expect(options.sandbox).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCustomOptions', () => {
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('claude-provider.ts', () => {
|
||||
maxTurns: 10,
|
||||
cwd: '/test/dir',
|
||||
allowedTools: ['Read', 'Write'],
|
||||
permissionMode: 'acceptEdits',
|
||||
permissionMode: 'default',
|
||||
}),
|
||||
});
|
||||
});
|
||||
@@ -100,7 +100,7 @@ describe('claude-provider.ts', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should enable sandbox by default', async () => {
|
||||
it('should pass sandbox configuration when provided', async () => {
|
||||
vi.mocked(sdk.query).mockReturnValue(
|
||||
(async function* () {
|
||||
yield { type: 'text', text: 'test' };
|
||||
@@ -110,6 +110,10 @@ describe('claude-provider.ts', () => {
|
||||
const generator = provider.executeQuery({
|
||||
prompt: 'Test',
|
||||
cwd: '/test',
|
||||
sandbox: {
|
||||
enabled: true,
|
||||
autoAllowBashIfSandboxed: true,
|
||||
},
|
||||
});
|
||||
|
||||
await collectAsyncGenerator(generator);
|
||||
@@ -242,11 +246,21 @@ describe('claude-provider.ts', () => {
|
||||
});
|
||||
|
||||
await expect(collectAsyncGenerator(generator)).rejects.toThrow('SDK execution failed');
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'[ClaudeProvider] executeQuery() error during execution:',
|
||||
|
||||
// Should log error message
|
||||
expect(consoleErrorSpy).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'[ClaudeProvider] ERROR: executeQuery() error during execution:',
|
||||
testError
|
||||
);
|
||||
|
||||
// Should log stack trace
|
||||
expect(consoleErrorSpy).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'[ClaudeProvider] ERROR stack:',
|
||||
testError.stack
|
||||
);
|
||||
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,6 +50,8 @@ export function SettingsView() {
|
||||
setValidationModel,
|
||||
autoLoadClaudeMd,
|
||||
setAutoLoadClaudeMd,
|
||||
enableSandboxMode,
|
||||
setEnableSandboxMode,
|
||||
} = useAppStore();
|
||||
|
||||
// Hide usage tracking when using API key (only show for Claude Code CLI users)
|
||||
@@ -108,6 +110,8 @@ export function SettingsView() {
|
||||
<ClaudeMdSettings
|
||||
autoLoadClaudeMd={autoLoadClaudeMd}
|
||||
onAutoLoadClaudeMdChange={setAutoLoadClaudeMd}
|
||||
enableSandboxMode={enableSandboxMode}
|
||||
onEnableSandboxModeChange={setEnableSandboxMode}
|
||||
/>
|
||||
{showUsageTracking && <ClaudeUsageSection />}
|
||||
</div>
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { FileCode } from 'lucide-react';
|
||||
import { FileCode, Shield } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface ClaudeMdSettingsProps {
|
||||
autoLoadClaudeMd: boolean;
|
||||
onAutoLoadClaudeMdChange: (enabled: boolean) => void;
|
||||
enableSandboxMode: boolean;
|
||||
onEnableSandboxModeChange: (enabled: boolean) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* ClaudeMdSettings Component
|
||||
*
|
||||
* UI control for the autoLoadClaudeMd setting which enables automatic loading
|
||||
* of project instructions from .claude/CLAUDE.md files via the Claude Agent SDK.
|
||||
* UI controls for Claude Agent SDK settings including:
|
||||
* - Auto-loading of project instructions from .claude/CLAUDE.md files
|
||||
* - Sandbox mode for isolated bash command execution
|
||||
*
|
||||
* Usage:
|
||||
* ```tsx
|
||||
* <ClaudeMdSettings
|
||||
* autoLoadClaudeMd={autoLoadClaudeMd}
|
||||
* onAutoLoadClaudeMdChange={setAutoLoadClaudeMd}
|
||||
* enableSandboxMode={enableSandboxMode}
|
||||
* onEnableSandboxModeChange={setEnableSandboxMode}
|
||||
* />
|
||||
* ```
|
||||
*/
|
||||
export function ClaudeMdSettings({
|
||||
autoLoadClaudeMd,
|
||||
onAutoLoadClaudeMdChange,
|
||||
enableSandboxMode,
|
||||
onEnableSandboxModeChange,
|
||||
}: ClaudeMdSettingsProps) {
|
||||
return (
|
||||
<div
|
||||
@@ -76,6 +83,32 @@ export function ClaudeMdSettings({
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="group flex items-start space-x-3 p-3 rounded-xl hover:bg-accent/30 transition-colors duration-200 -mx-3 mt-2">
|
||||
<Checkbox
|
||||
id="enable-sandbox-mode"
|
||||
checked={enableSandboxMode}
|
||||
onCheckedChange={(checked) => onEnableSandboxModeChange(checked === true)}
|
||||
className="mt-1"
|
||||
data-testid="enable-sandbox-mode-checkbox"
|
||||
/>
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
htmlFor="enable-sandbox-mode"
|
||||
className="text-foreground cursor-pointer font-medium flex items-center gap-2"
|
||||
>
|
||||
<Shield className="w-4 h-4 text-brand-500" />
|
||||
Enable Sandbox Mode
|
||||
</Label>
|
||||
<p className="text-xs text-muted-foreground/80 leading-relaxed">
|
||||
Run bash commands in an isolated sandbox environment for additional security.
|
||||
<span className="block mt-1 text-warning/80">
|
||||
Note: On some systems, enabling sandbox mode may cause the agent to hang without
|
||||
responding. If you experience issues, try disabling this option.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -224,6 +224,7 @@ export async function syncSettingsToServer(): Promise<boolean> {
|
||||
enhancementModel: state.enhancementModel,
|
||||
validationModel: state.validationModel,
|
||||
autoLoadClaudeMd: state.autoLoadClaudeMd,
|
||||
enableSandboxMode: state.enableSandboxMode,
|
||||
keyboardShortcuts: state.keyboardShortcuts,
|
||||
aiProfiles: state.aiProfiles,
|
||||
projects: state.projects,
|
||||
|
||||
@@ -480,6 +480,7 @@ export interface AppState {
|
||||
|
||||
// Claude Agent SDK Settings
|
||||
autoLoadClaudeMd: boolean; // Auto-load CLAUDE.md files using SDK's settingSources option
|
||||
enableSandboxMode: boolean; // Enable sandbox mode for bash commands (may cause issues on some systems)
|
||||
|
||||
// Project Analysis
|
||||
projectAnalysis: ProjectAnalysis | null;
|
||||
@@ -756,6 +757,7 @@ export interface AppActions {
|
||||
|
||||
// Claude Agent SDK Settings actions
|
||||
setAutoLoadClaudeMd: (enabled: boolean) => Promise<void>;
|
||||
setEnableSandboxMode: (enabled: boolean) => Promise<void>;
|
||||
|
||||
// AI Profile actions
|
||||
addAIProfile: (profile: Omit<AIProfile, 'id'>) => void;
|
||||
@@ -929,6 +931,7 @@ const initialState: AppState = {
|
||||
enhancementModel: 'sonnet', // Default to sonnet for feature enhancement
|
||||
validationModel: 'opus', // Default to opus for GitHub issue validation
|
||||
autoLoadClaudeMd: false, // Default to disabled (user must opt-in)
|
||||
enableSandboxMode: true, // Default to enabled for security (can be disabled if issues occur)
|
||||
aiProfiles: DEFAULT_AI_PROFILES,
|
||||
projectAnalysis: null,
|
||||
isAnalyzing: false,
|
||||
@@ -1561,6 +1564,12 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
setEnableSandboxMode: async (enabled) => {
|
||||
set({ enableSandboxMode: enabled });
|
||||
// Sync to server settings file
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
|
||||
// AI Profile actions
|
||||
addAIProfile: (profile) => {
|
||||
@@ -2706,6 +2715,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
enhancementModel: state.enhancementModel,
|
||||
validationModel: state.validationModel,
|
||||
autoLoadClaudeMd: state.autoLoadClaudeMd,
|
||||
enableSandboxMode: state.enableSandboxMode,
|
||||
// Profiles and sessions
|
||||
aiProfiles: state.aiProfiles,
|
||||
chatSessions: state.chatSessions,
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface ExecuteOptions {
|
||||
conversationHistory?: ConversationMessage[]; // Previous messages for context
|
||||
sdkSessionId?: string; // Claude SDK session ID for resuming conversations
|
||||
settingSources?: Array<'user' | 'project' | 'local'>; // Sources for CLAUDE.md loading
|
||||
sandbox?: { enabled: boolean; autoAllowBashIfSandboxed?: boolean }; // Sandbox configuration
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -301,6 +301,8 @@ export interface GlobalSettings {
|
||||
// Claude Agent SDK Settings
|
||||
/** Auto-load CLAUDE.md files using SDK's settingSources option */
|
||||
autoLoadClaudeMd?: boolean;
|
||||
/** Enable sandbox mode for bash commands (default: true, disable if issues occur) */
|
||||
enableSandboxMode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,6 +461,7 @@ export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
|
||||
worktreePanelCollapsed: false,
|
||||
lastSelectedSessionByProject: {},
|
||||
autoLoadClaudeMd: false,
|
||||
enableSandboxMode: true,
|
||||
};
|
||||
|
||||
/** Default credentials (empty strings - user must provide API keys) */
|
||||
|
||||
88
package-lock.json
generated
88
package-lock.json
generated
@@ -451,6 +451,7 @@
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -1034,6 +1035,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.4.tgz",
|
||||
"integrity": "sha512-xMF6OfEAUVY5Waega4juo1QGACfNkNF+aJLqpd8oUJz96ms2zbfQ9Gh35/tI3y8akEV31FruKfj7hBnIU/nkqA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"crelt": "^1.0.6",
|
||||
@@ -1076,6 +1078,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
||||
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@dnd-kit/accessibility": "^3.1.1",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
@@ -1896,7 +1899,6 @@
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cross-dirname": "^0.1.0",
|
||||
"debug": "^4.3.4",
|
||||
@@ -1918,7 +1920,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
@@ -1935,7 +1936,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
@@ -1950,7 +1950,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
@@ -2706,7 +2705,6 @@
|
||||
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -2831,7 +2829,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -2848,7 +2845,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -2865,7 +2861,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -2974,7 +2969,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -2997,7 +2991,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -3020,7 +3013,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -3106,7 +3098,6 @@
|
||||
],
|
||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@emnapi/runtime": "^1.7.0"
|
||||
},
|
||||
@@ -3129,7 +3120,6 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -3149,7 +3139,6 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -3488,8 +3477,7 @@
|
||||
"version": "16.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.10.tgz",
|
||||
"integrity": "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "16.0.10",
|
||||
@@ -3503,7 +3491,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3520,7 +3507,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3537,7 +3523,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3554,7 +3539,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3571,7 +3555,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3588,7 +3571,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3605,7 +3587,6 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3622,7 +3603,6 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
@@ -3713,6 +3693,7 @@
|
||||
"integrity": "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.57.0"
|
||||
},
|
||||
@@ -5153,7 +5134,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
@@ -5487,6 +5467,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.141.6.tgz",
|
||||
"integrity": "sha512-qWFxi2D6eGc1L03RzUuhyEOplZ7Q6q62YOl7Of9Y0q4YjwQwxRm4zxwDVtvUIoy4RLVCpqp5UoE+Nxv2PY9trg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@tanstack/history": "1.141.0",
|
||||
"@tanstack/react-store": "^0.8.0",
|
||||
@@ -6038,6 +6019,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
||||
"integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
}
|
||||
@@ -6048,6 +6030,7 @@
|
||||
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
@@ -6153,6 +6136,7 @@
|
||||
"integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.50.0",
|
||||
"@typescript-eslint/types": "8.50.0",
|
||||
@@ -6646,7 +6630,8 @@
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
|
||||
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@xyflow/react": {
|
||||
"version": "12.10.0",
|
||||
@@ -6744,6 +6729,7 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -6804,6 +6790,7 @@
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
@@ -7363,6 +7350,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.9.0",
|
||||
"caniuse-lite": "^1.0.30001759",
|
||||
@@ -7894,8 +7882,7 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
@@ -8181,8 +8168,7 @@
|
||||
"integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "10.1.0",
|
||||
@@ -8279,6 +8265,7 @@
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -8580,6 +8567,7 @@
|
||||
"integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"app-builder-lib": "26.0.12",
|
||||
"builder-util": "26.0.11",
|
||||
@@ -8906,7 +8894,6 @@
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@electron/asar": "^3.2.1",
|
||||
"debug": "^4.1.1",
|
||||
@@ -8927,7 +8914,6 @@
|
||||
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"jsonfile": "^4.0.0",
|
||||
@@ -9178,6 +9164,7 @@
|
||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -11083,7 +11070,6 @@
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
@@ -11145,7 +11131,6 @@
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
@@ -13564,7 +13549,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.6",
|
||||
"picocolors": "^1.0.0",
|
||||
@@ -13581,7 +13565,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"commander": "^9.4.0"
|
||||
},
|
||||
@@ -13599,7 +13582,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
@@ -13788,6 +13770,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
|
||||
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -13797,6 +13780,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
||||
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
@@ -14146,7 +14130,6 @@
|
||||
"deprecated": "Rimraf versions prior to v4 are no longer supported",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
@@ -14335,6 +14318,7 @@
|
||||
"resolved": "https://registry.npmjs.org/seroval/-/seroval-1.4.0.tgz",
|
||||
"integrity": "sha512-BdrNXdzlofomLTiRnwJTSEAaGKyHHZkbMXIywOh7zlzp4uZnXErEwl9XZ+N1hJSNpeTtNxWvVwN0wUzAIQ4Hpg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
@@ -14383,7 +14367,6 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@img/colour": "^1.0.0",
|
||||
"detect-libc": "^2.1.2",
|
||||
@@ -14434,7 +14417,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14457,7 +14439,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14480,7 +14461,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14497,7 +14477,6 @@
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14514,7 +14493,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14531,7 +14509,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14548,7 +14525,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14565,7 +14541,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14582,7 +14557,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/libvips"
|
||||
}
|
||||
@@ -14599,7 +14573,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14622,7 +14595,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14645,7 +14617,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14668,7 +14639,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14691,7 +14661,6 @@
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -14714,7 +14683,6 @@
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||
},
|
||||
@@ -15183,7 +15151,6 @@
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
|
||||
"integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"client-only": "0.0.1"
|
||||
},
|
||||
@@ -15353,7 +15320,6 @@
|
||||
"integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "~2.6.2"
|
||||
@@ -15417,7 +15383,6 @@
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
@@ -15515,6 +15480,7 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -15719,6 +15685,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -16090,6 +16057,7 @@
|
||||
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.27.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -16179,7 +16147,8 @@
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-electron-renderer/-/vite-plugin-electron-renderer-0.14.6.tgz",
|
||||
"integrity": "sha512-oqkWFa7kQIkvHXG7+Mnl1RTroA4sP0yesKatmAy0gjZC4VwUqlvF9IvOpHd1fpLWsqYX/eZlVxlhULNtaQ78Jw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/vite/node_modules/fdir": {
|
||||
"version": "6.5.0",
|
||||
@@ -16205,6 +16174,7 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -16247,6 +16217,7 @@
|
||||
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.0.16",
|
||||
"@vitest/mocker": "4.0.16",
|
||||
@@ -16504,6 +16475,7 @@
|
||||
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user