* Initialize sandbox with log monitoring enabled by default
( sandboxAskCallback?: SandboxAskCallback, )
| 728 | * Initialize sandbox with log monitoring enabled by default |
| 729 | */ |
| 730 | async function initialize( |
| 731 | sandboxAskCallback?: SandboxAskCallback, |
| 732 | ): Promise<void> { |
| 733 | // If already initializing or initialized, return the promise |
| 734 | if (initializationPromise) { |
| 735 | return initializationPromise |
| 736 | } |
| 737 | |
| 738 | // Check if sandboxing is enabled in settings |
| 739 | if (!isSandboxingEnabled()) { |
| 740 | return |
| 741 | } |
| 742 | |
| 743 | // Wrap the callback to enforce allowManagedDomainsOnly policy. |
| 744 | // This ensures all code paths (REPL, print/SDK) are covered. |
| 745 | const wrappedCallback: SandboxAskCallback | undefined = sandboxAskCallback |
| 746 | ? async (hostPattern: NetworkHostPattern) => { |
| 747 | if (shouldAllowManagedSandboxDomainsOnly()) { |
| 748 | logForDebugging( |
| 749 | `[sandbox] Blocked network request to ${hostPattern.host} (allowManagedDomainsOnly)`, |
| 750 | ) |
| 751 | return false |
| 752 | } |
| 753 | return sandboxAskCallback(hostPattern) |
| 754 | } |
| 755 | : undefined |
| 756 | |
| 757 | // Create the initialization promise synchronously (before any await) to prevent |
| 758 | // race conditions where wrapWithSandbox() is called before the promise is assigned. |
| 759 | initializationPromise = (async () => { |
| 760 | try { |
| 761 | // Resolve worktree main repo path once before building config. |
| 762 | // Worktree status doesn't change mid-session, so this is cached for all |
| 763 | // subsequent refreshConfig() calls (which must be synchronous to avoid |
| 764 | // race conditions where pending requests slip through with stale config). |
| 765 | if (worktreeMainRepoPath === undefined) { |
| 766 | worktreeMainRepoPath = await detectWorktreeMainRepoPath(getCwdState()) |
| 767 | } |
| 768 | |
| 769 | const settings = getSettings_DEPRECATED() |
| 770 | const runtimeConfig = convertToSandboxRuntimeConfig(settings) |
| 771 | |
| 772 | // Log monitor is automatically enabled for macOS |
| 773 | await BaseSandboxManager.initialize(runtimeConfig, wrappedCallback) |
| 774 | |
| 775 | // Subscribe to settings changes to update sandbox config dynamically |
| 776 | settingsSubscriptionCleanup = settingsChangeDetector.subscribe(() => { |
| 777 | const settings = getSettings_DEPRECATED() |
| 778 | const newConfig = convertToSandboxRuntimeConfig(settings) |
| 779 | BaseSandboxManager.updateConfig(newConfig) |
| 780 | logForDebugging('Sandbox configuration updated from settings change') |
| 781 | }) |
| 782 | } catch (error) { |
| 783 | // Clear the promise on error so initialization can be retried |
| 784 | initializationPromise = undefined |
| 785 | |
| 786 | // Log error but don't throw - let sandboxing fail gracefully |
| 787 | logForDebugging(`Failed to initialize sandbox: ${errorMessage(error)}`) |
nothing calls this directly
no test coverage detected