@cnwenf/occ 2.1.344 → 2.1.346

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.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- globalThis.MACRO={"VERSION":"2.1.344","BINARY_NAME":"occ","BUILD_TIME":"2026-09-19T22:11:10.563Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
2
+ globalThis.MACRO={"VERSION":"2.1.346","BINARY_NAME":"occ","BUILD_TIME":"2026-09-21T18:17:57.821Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
3
3
  // @bun
4
4
  var __create = Object.create;
5
5
  var __getProtoOf = Object.getPrototypeOf;
@@ -57751,496 +57751,246 @@ var init_managedPath = __esm(() => {
57751
57751
  });
57752
57752
  });
57753
57753
 
57754
- // src/utils/lazySchema.ts
57755
- function lazySchema(factory2) {
57756
- let cached2;
57757
- return () => cached2 ??= factory2();
57758
- }
57759
-
57760
- // src/entrypoints/sandboxTypes.ts
57761
- var SandboxNetworkConfigSchema, SandboxFilesystemConfigSchema, SandboxSettingsSchema;
57762
- var init_sandboxTypes = __esm(() => {
57763
- init_v4();
57764
- SandboxNetworkConfigSchema = lazySchema(() => exports_external.object({
57765
- allowedDomains: exports_external.array(exports_external.string()).optional(),
57766
- deniedDomains: exports_external.array(exports_external.string()).optional().describe("Domains to block even when a broader allowedDomains wildcard would otherwise permit them."),
57767
- allowManagedDomainsOnly: exports_external.boolean().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. " + "User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),
57768
- strictAllowlist: exports_external.boolean().optional().describe("When true, the sandbox runtime deterministically denies hosts not in allowedDomains instead of prompting. " + "Enforced for sandboxed commands only \u2014 in-process tools such as WebFetch are not gated by this setting. " + "Only honored from user, managed/policy, or CLI (--settings) settings \u2014 " + "project settings (.claude/settings.json and .claude/settings.local.json) are ignored."),
57769
- allowUnixSockets: exports_external.array(exports_external.string()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),
57770
- allowAllUnixSockets: exports_external.boolean().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),
57771
- allowLocalBinding: exports_external.boolean().optional(),
57772
- httpProxyPort: exports_external.number().optional(),
57773
- socksProxyPort: exports_external.number().optional()
57774
- }).optional());
57775
- SandboxFilesystemConfigSchema = lazySchema(() => exports_external.object({
57776
- disabled: exports_external.boolean().optional().describe("macOS and Linux/WSL only: skip filesystem isolation entirely while " + "keeping network and seccomp isolation. Ignored on native Windows, " + "where the sandboxed process runs as a separate user with no " + "inherent rights, so skipping the filesystem rules would withhold " + "every access grant rather than loosen them \u2014 filesystem isolation " + "stays on there."),
57777
- allowWrite: exports_external.array(exports_external.string()).optional().describe("Additional paths to allow writing within the sandbox. " + "Merged with paths from Edit(...) allow permission rules."),
57778
- denyWrite: exports_external.array(exports_external.string()).optional().describe("Additional paths to deny writing within the sandbox. " + "Merged with paths from Edit(...) deny permission rules."),
57779
- denyRead: exports_external.array(exports_external.string()).optional().describe("Additional paths to deny reading within the sandbox. " + "Merged with paths from Read(...) deny permission rules."),
57780
- allowRead: exports_external.array(exports_external.string()).optional().describe("Paths to re-allow reading within denyRead regions. " + "Takes precedence over denyRead for matching paths."),
57781
- allowManagedReadPathsOnly: exports_external.boolean().optional().describe("When true (set in managed settings), only allowRead paths from policySettings are used.")
57782
- }).optional());
57783
- SandboxSettingsSchema = lazySchema(() => exports_external.object({
57784
- enabled: exports_external.boolean().optional(),
57785
- failIfUnavailable: exports_external.boolean().optional().describe("Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start " + "(missing dependencies, unsupported platform, or platform not in enabledPlatforms). " + "When false (default), a warning is shown and commands run unsandboxed. " + "Intended for managed-settings deployments that require sandboxing as a hard gate."),
57786
- autoAllowBashIfSandboxed: exports_external.boolean().optional(),
57787
- allowUnsandboxedCommands: exports_external.boolean().optional().describe("Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. " + "When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. " + "Default: true."),
57788
- network: SandboxNetworkConfigSchema(),
57789
- filesystem: SandboxFilesystemConfigSchema(),
57790
- ignoreViolations: exports_external.record(exports_external.string(), exports_external.array(exports_external.string())).optional(),
57791
- enableWeakerNestedSandbox: exports_external.boolean().optional(),
57792
- enableWeakerNetworkIsolation: exports_external.boolean().optional().describe("macOS only: Allow access to com.apple.trustd.agent in the sandbox. " + "Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates " + "when using httpProxyPort with a MITM proxy and custom CA. " + "**Reduces security** \u2014 opens a potential data exfiltration vector through the trustd service. Default: false"),
57793
- allowAppleEvents: exports_external.boolean().optional().describe("macOS only: Allow sandboxed commands to send Apple Events to other " + "applications via the Apple Event service. Default: false"),
57794
- excludedCommands: exports_external.array(exports_external.string()).optional(),
57795
- credentials: exports_external.object({
57796
- enabled: exports_external.boolean().optional().describe("When true, block sandboxed commands from reading credential files and secret env vars.")
57797
- }).optional(),
57798
- ripgrep: exports_external.object({
57799
- command: exports_external.string(),
57800
- args: exports_external.array(exports_external.string()).optional()
57801
- }).optional().describe("Custom ripgrep configuration for bundled ripgrep support")
57802
- }).passthrough());
57803
- });
57804
-
57805
- // src/utils/bundledMode.ts
57806
- function isRunningWithBun() {
57807
- return process.versions.bun !== undefined;
57808
- }
57809
- function isInBundledMode() {
57810
- return typeof Bun !== "undefined" && Array.isArray(Bun.embeddedFiles) && Bun.embeddedFiles.length > 0;
57811
- }
57812
-
57813
- // src/utils/findExecutable.ts
57814
- function findExecutable2(exe, args) {
57815
- const resolved = whichSync(exe);
57816
- return { cmd: resolved ?? exe, args };
57754
+ // src/utils/plugins/marketplacePolicyValidation.ts
57755
+ function stripTrailingDots(host) {
57756
+ let end = host.length;
57757
+ while (end > 0 && host[end - 1] === ".")
57758
+ end--;
57759
+ return host.slice(0, end);
57817
57760
  }
57818
- var init_findExecutable = __esm(() => {
57819
- init_which();
57820
- });
57821
-
57822
- // src/utils/env.ts
57823
- import { homedir as homedir8 } from "os";
57824
- import { join as join17 } from "path";
57825
- async function isCommandAvailable(command) {
57761
+ function normalizeHostname(raw) {
57762
+ const host = stripTrailingDots(raw.replace(/[\t\n\r]/g, "").toLowerCase());
57763
+ if (host === "" || INVALID_HOST_CHARS.test(host))
57764
+ return host;
57826
57765
  try {
57827
- return !!await which(command);
57766
+ const parsed = new URL(`https://${host}`);
57767
+ if (parsed.username !== "" || parsed.password !== "" || parsed.port !== "" || parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "")
57768
+ return host;
57769
+ return stripTrailingDots(parsed.hostname);
57828
57770
  } catch {
57829
- return false;
57771
+ return host;
57830
57772
  }
57831
57773
  }
57832
- function isConductor() {
57833
- return process.env.__CFBundleIdentifier === "com.conductor.app";
57834
- }
57835
- function detectTerminal() {
57836
- if (process.env.CURSOR_TRACE_ID)
57837
- return "cursor";
57838
- if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("cursor")) {
57839
- return "cursor";
57840
- }
57841
- if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("windsurf")) {
57842
- return "windsurf";
57774
+ function normalizeHostForComparison(raw) {
57775
+ const cached2 = hostNormalizeCache.get(raw);
57776
+ if (cached2 !== undefined)
57777
+ return cached2;
57778
+ let host = normalizeHostname(raw);
57779
+ while (host.startsWith("www."))
57780
+ host = host.slice(4);
57781
+ if (hostNormalizeCache.size >= HOST_NORMALIZE_CACHE_LIMIT) {
57782
+ hostNormalizeCache.clear();
57843
57783
  }
57844
- if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("antigravity")) {
57845
- return "antigravity";
57784
+ hostNormalizeCache.set(raw, host);
57785
+ return host;
57786
+ }
57787
+ function hostMatches(raw, expected) {
57788
+ return normalizeHostForComparison(raw) === expected;
57789
+ }
57790
+ function isGitHubHost(raw) {
57791
+ return hostMatches(raw, GITHUB_HOST);
57792
+ }
57793
+ function isGitHubOrSshGitHubHost(raw) {
57794
+ return isGitHubHost(raw) || normalizeHostname(raw) === GITHUB_SSH_HOST;
57795
+ }
57796
+ function hasSuspiciousHostChars(value) {
57797
+ return /[%\x00-\x1f\x7f-\u{10FFFF}]/u.test(value);
57798
+ }
57799
+ function hasBackslashSmuggling(raw) {
57800
+ const url3 = raw.replace(/^[\x00-\x20]+/, "");
57801
+ const schemeEnd = url3.indexOf("://");
57802
+ if (schemeEnd === -1)
57803
+ return false;
57804
+ let rest = url3.slice(schemeEnd + 3);
57805
+ const scheme = url3.slice(0, schemeEnd).toLowerCase();
57806
+ if (URL_LIKE_PROTOCOLS.has(scheme)) {
57807
+ const slashes = rest.match(/^[/\\]+/)?.[0] ?? "";
57808
+ if (slashes.includes("\\"))
57809
+ return true;
57810
+ rest = rest.slice(slashes.length);
57846
57811
  }
57847
- const bundleId = process.env.__CFBundleIdentifier?.toLowerCase();
57848
- if (bundleId?.includes("vscodium"))
57849
- return "codium";
57850
- if (bundleId?.includes("windsurf"))
57851
- return "windsurf";
57852
- if (bundleId?.includes("com.google.android.studio"))
57853
- return "androidstudio";
57854
- if (bundleId) {
57855
- for (const ide of JETBRAINS_IDES) {
57856
- if (bundleId.includes(ide))
57857
- return ide;
57812
+ const pathStart = rest.search(/[/?#]/);
57813
+ return (pathStart === -1 ? rest : rest.slice(0, pathStart)).includes("\\");
57814
+ }
57815
+ function isSuspiciousGitUrl(url3) {
57816
+ if (url3.includes("://")) {
57817
+ if (hasBackslashSmuggling(url3))
57818
+ return true;
57819
+ try {
57820
+ const parsed = new URL(url3);
57821
+ if (parsed.protocol === "http:" || parsed.protocol === "https:")
57822
+ return false;
57823
+ return hasSuspiciousHostChars(parsed.hostname);
57824
+ } catch {
57825
+ return true;
57858
57826
  }
57859
57827
  }
57860
- if (process.env.VisualStudioVersion) {
57861
- return "visualstudio";
57862
- }
57863
- if (process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm") {
57864
- if (process.platform === "darwin")
57865
- return "pycharm";
57866
- return "pycharm";
57867
- }
57868
- if (process.env.TERM === "xterm-ghostty") {
57869
- return "ghostty";
57870
- }
57871
- if (process.env.TERM?.includes("kitty")) {
57872
- return "kitty";
57873
- }
57874
- if (process.env.TERM_PROGRAM) {
57875
- return process.env.TERM_PROGRAM;
57876
- }
57877
- if (process.env.TMUX)
57878
- return "tmux";
57879
- if (process.env.STY)
57880
- return "screen";
57881
- if (process.env.KONSOLE_VERSION)
57882
- return "konsole";
57883
- if (process.env.GNOME_TERMINAL_SERVICE)
57884
- return "gnome-terminal";
57885
- if (process.env.XTERM_VERSION)
57886
- return "xterm";
57887
- if (process.env.VTE_VERSION)
57888
- return "vte-based";
57889
- if (process.env.TERMINATOR_UUID)
57890
- return "terminator";
57891
- if (process.env.KITTY_WINDOW_ID) {
57892
- return "kitty";
57893
- }
57894
- if (process.env.ALACRITTY_LOG)
57895
- return "alacritty";
57896
- if (process.env.TILIX_ID)
57897
- return "tilix";
57898
- if (process.env.WT_SESSION)
57899
- return "windows-terminal";
57900
- if (process.env.SESSIONNAME && process.env.TERM === "cygwin")
57901
- return "cygwin";
57902
- if (process.env.MSYSTEM)
57903
- return process.env.MSYSTEM.toLowerCase();
57904
- if (process.env.ConEmuANSI || process.env.ConEmuPID || process.env.ConEmuTask) {
57905
- return "conemu";
57906
- }
57907
- if (process.env.WSL_DISTRO_NAME)
57908
- return `wsl-${process.env.WSL_DISTRO_NAME}`;
57909
- if (isSSHSession()) {
57910
- return "ssh-session";
57911
- }
57912
- if (process.env.TERM) {
57913
- const term = process.env.TERM;
57914
- if (term.includes("alacritty"))
57915
- return "alacritty";
57916
- if (term.includes("rxvt"))
57917
- return "rxvt";
57918
- if (term.includes("termite"))
57919
- return "termite";
57920
- return process.env.TERM;
57921
- }
57922
- if (!process.stdout.isTTY)
57923
- return "non-interactive";
57924
- return null;
57828
+ const colonIndex = url3.indexOf(":");
57829
+ const atIndex = url3.indexOf("@");
57830
+ if (colonIndex >= 0 && atIndex > colonIndex)
57831
+ return true;
57832
+ const host = url3.match(/^(?:[^@]+@)?([^:]+):/)?.[1];
57833
+ return host ? hasSuspiciousHostChars(host) : false;
57925
57834
  }
57926
- function isSSHSession() {
57927
- return !!(process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY);
57835
+ function normalizeGithubAwareHost(raw) {
57836
+ const host = normalizeHostname(raw);
57837
+ return isGitHubHost(host) ? GITHUB_HOST : host;
57928
57838
  }
57929
- function getHostPlatformForAnalytics() {
57930
- const override = process.env.CLAUDE_CODE_HOST_PLATFORM;
57931
- if (override === "win32" || override === "darwin" || override === "linux") {
57932
- return override;
57933
- }
57934
- return env4.platform;
57839
+ function normalizeGithubHostForUrl(raw) {
57840
+ const host = normalizeGithubAwareHost(raw);
57841
+ return host === GITHUB_SSH_HOST ? GITHUB_HOST : host;
57935
57842
  }
57936
- var getGlobalClaudeFile, hasInternetAccess, detectPackageManagers, detectRuntimes, isWslEnvironment, isNpmFromWindowsPath, JETBRAINS_IDES, detectDeploymentEnvironment, env4;
57937
- var init_env = __esm(() => {
57938
- init_memoize();
57939
- init_oauth();
57940
- init_envUtils();
57941
- init_findExecutable();
57942
- init_fsOperations();
57943
- init_which();
57944
- getGlobalClaudeFile = memoize_default(() => {
57945
- if (getFsImplementation().existsSync(join17(getClaudeConfigHomeDir(), ".config.json"))) {
57946
- return join17(getClaudeConfigHomeDir(), ".config.json");
57843
+ function normalizePathSegments(path9) {
57844
+ const segments = [];
57845
+ for (const segment of path9.split("/")) {
57846
+ if (segment === ".")
57847
+ continue;
57848
+ if (segment === "..") {
57849
+ segments.pop();
57850
+ continue;
57947
57851
  }
57948
- const filename = `.claude${fileSuffixForOauthConfig()}.json`;
57949
- const p = join17(process.env.CLAUDE_CONFIG_DIR || homedir8(), filename);
57950
- return p;
57951
- });
57952
- hasInternetAccess = memoize_default(async () => {
57852
+ segments.push(segment);
57853
+ }
57854
+ return segments.filter((segment) => segment !== "").join("/");
57855
+ }
57856
+ function stripDotGitSuffix(path9) {
57857
+ let length = path9.length;
57858
+ for (;; ) {
57859
+ let end = length;
57860
+ while (end > 0 && path9.charCodeAt(end - 1) === 47)
57861
+ end--;
57862
+ if (end >= 4 && path9.startsWith(".git", end - 4))
57863
+ end -= 4;
57864
+ if (end === length)
57865
+ return length === path9.length ? path9 : path9.slice(0, length);
57866
+ length = end;
57867
+ }
57868
+ }
57869
+ function normalizeUrlForComparison(raw, options) {
57870
+ if (raw.includes("://")) {
57953
57871
  try {
57954
- const { default: axiosClient } = await Promise.resolve().then(() => (init_axios2(), exports_axios));
57955
- await axiosClient.head("http://1.1.1.1", {
57956
- signal: AbortSignal.timeout(1000)
57957
- });
57958
- return true;
57872
+ const parsed = new URL(raw);
57873
+ parsed.hostname = normalizeGithubHostForUrl(parsed.hostname);
57874
+ parsed.username = "";
57875
+ parsed.password = "";
57876
+ parsed.search = "";
57877
+ parsed.hash = "";
57878
+ try {
57879
+ parsed.pathname = decodeURIComponent(parsed.pathname);
57880
+ } catch {}
57881
+ const normalized = normalizePathSegments(parsed.pathname);
57882
+ parsed.pathname = options?.stripDotGit ? stripDotGitSuffix(normalized) : normalized;
57883
+ return parsed.toString();
57959
57884
  } catch {
57960
- return false;
57885
+ return raw;
57961
57886
  }
57962
- });
57963
- detectPackageManagers = memoize_default(async () => {
57964
- const packageManagers = [];
57965
- if (await isCommandAvailable("npm"))
57966
- packageManagers.push("npm");
57967
- if (await isCommandAvailable("yarn"))
57968
- packageManagers.push("yarn");
57969
- if (await isCommandAvailable("pnpm"))
57970
- packageManagers.push("pnpm");
57971
- return packageManagers;
57972
- });
57973
- detectRuntimes = memoize_default(async () => {
57974
- const runtimes = [];
57975
- if (await isCommandAvailable("bun"))
57976
- runtimes.push("bun");
57977
- if (await isCommandAvailable("deno"))
57978
- runtimes.push("deno");
57979
- if (await isCommandAvailable("node"))
57980
- runtimes.push("node");
57981
- return runtimes;
57982
- });
57983
- isWslEnvironment = memoize_default(() => {
57887
+ }
57888
+ const scpLike = raw.match(/^[^@]+@([^:]+)(:.*)$/s);
57889
+ return scpLike ? `${normalizeGithubHostForUrl(scpLike[1] ?? "")}${scpLike[2]}` : raw;
57890
+ }
57891
+ function parseScpLikeGitUrl(raw) {
57892
+ const match = SCP_LIKE_GIT_URL_PATTERN.exec(raw);
57893
+ return match ? { user: match[1], host: match[2], path: match[3] } : null;
57894
+ }
57895
+ function normalizeGitUrl(raw) {
57896
+ if (isSuspiciousGitUrl(raw))
57897
+ return raw;
57898
+ if (raw.includes("://")) {
57984
57899
  try {
57985
- return getFsImplementation().existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
57986
- } catch (_error) {
57987
- return false;
57900
+ const parsed = new URL(raw);
57901
+ parsed.hostname = normalizeGithubAwareHost(parsed.hostname);
57902
+ if (CREDENTIAL_STRIP_PROTOCOLS.has(parsed.protocol) || isGitHubHost(parsed.hostname)) {
57903
+ parsed.username = "";
57904
+ parsed.password = "";
57905
+ }
57906
+ return parsed.toString();
57907
+ } catch {
57908
+ return raw;
57988
57909
  }
57989
- });
57990
- isNpmFromWindowsPath = memoize_default(() => {
57910
+ }
57911
+ const scpLike = parseScpLikeGitUrl(raw);
57912
+ if (!scpLike)
57913
+ return raw;
57914
+ const host = scpLike.host.toLowerCase().replace(/\.+$/, "");
57915
+ return isGitHubHost(host) ? `${GITHUB_HOST}:${scpLike.path}` : `${scpLike.user}@${host}:${scpLike.path}`;
57916
+ }
57917
+ function gitUrlHasWildcard(url3) {
57918
+ if (url3.includes("://")) {
57919
+ if (hasBackslashSmuggling(url3))
57920
+ return false;
57921
+ let hostname3;
57991
57922
  try {
57992
- if (!isWslEnvironment()) {
57993
- return false;
57994
- }
57995
- const { cmd } = findExecutable2("npm", []);
57996
- return cmd.startsWith("/mnt/c/");
57997
- } catch (_error) {
57923
+ hostname3 = new URL(url3).hostname;
57924
+ } catch {
57998
57925
  return false;
57999
57926
  }
58000
- });
58001
- JETBRAINS_IDES = [
58002
- "pycharm",
58003
- "intellij",
58004
- "webstorm",
58005
- "phpstorm",
58006
- "rubymine",
58007
- "clion",
58008
- "goland",
58009
- "rider",
58010
- "datagrip",
58011
- "appcode",
58012
- "dataspell",
58013
- "aqua",
58014
- "gateway",
58015
- "fleet",
58016
- "jetbrains",
58017
- "androidstudio"
58018
- ];
58019
- detectDeploymentEnvironment = memoize_default(() => {
58020
- if (isEnvTruthy(process.env.CODESPACES))
58021
- return "codespaces";
58022
- if (process.env.GITPOD_WORKSPACE_ID)
58023
- return "gitpod";
58024
- if (process.env.REPL_ID || process.env.REPL_SLUG)
58025
- return "replit";
58026
- if (process.env.PROJECT_DOMAIN)
58027
- return "glitch";
58028
- if (isEnvTruthy(process.env.VERCEL))
58029
- return "vercel";
58030
- if (process.env.RAILWAY_ENVIRONMENT_NAME || process.env.RAILWAY_SERVICE_NAME) {
58031
- return "railway";
58032
- }
58033
- if (isEnvTruthy(process.env.RENDER))
58034
- return "render";
58035
- if (isEnvTruthy(process.env.NETLIFY))
58036
- return "netlify";
58037
- if (process.env.DYNO)
58038
- return "heroku";
58039
- if (process.env.FLY_APP_NAME || process.env.FLY_MACHINE_ID)
58040
- return "fly.io";
58041
- if (isEnvTruthy(process.env.CF_PAGES))
58042
- return "cloudflare-pages";
58043
- if (process.env.DENO_DEPLOYMENT_ID)
58044
- return "deno-deploy";
58045
- if (process.env.AWS_LAMBDA_FUNCTION_NAME)
58046
- return "aws-lambda";
58047
- if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_FARGATE")
58048
- return "aws-fargate";
58049
- if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_EC2")
58050
- return "aws-ecs";
57927
+ if (!isGitHubOrSshGitHubHost(hostname3))
57928
+ return false;
57929
+ if (normalizeUrlForComparison(url3, { stripDotGit: true }).includes("*"))
57930
+ return true;
57931
+ const normalized = normalizeGitUrl(url3);
58051
57932
  try {
58052
- const uuid3 = getFsImplementation().readFileSync("/sys/hypervisor/uuid", { encoding: "utf8" }).trim().toLowerCase();
58053
- if (uuid3.startsWith("ec2"))
58054
- return "aws-ec2";
58055
- } catch {}
58056
- if (process.env.K_SERVICE)
58057
- return "gcp-cloud-run";
58058
- if (process.env.GOOGLE_CLOUD_PROJECT)
58059
- return "gcp";
58060
- if (process.env.WEBSITE_SITE_NAME || process.env.WEBSITE_SKU)
58061
- return "azure-app-service";
58062
- if (process.env.AZURE_FUNCTIONS_ENVIRONMENT)
58063
- return "azure-functions";
58064
- if (process.env.APP_URL?.includes("ondigitalocean.app")) {
58065
- return "digitalocean-app-platform";
57933
+ const parsed = new URL(normalized);
57934
+ return parsed.hostname.includes("*") || parsed.pathname.includes("*");
57935
+ } catch {
57936
+ return normalized.includes("*");
58066
57937
  }
58067
- if (process.env.SPACE_CREATOR_USER_ID)
58068
- return "huggingface-spaces";
58069
- if (isEnvTruthy(process.env.GITHUB_ACTIONS))
58070
- return "github-actions";
58071
- if (isEnvTruthy(process.env.GITLAB_CI))
58072
- return "gitlab-ci";
58073
- if (process.env.CIRCLECI)
58074
- return "circleci";
58075
- if (process.env.BUILDKITE)
58076
- return "buildkite";
58077
- if (isEnvTruthy(process.env.CI))
58078
- return "ci";
58079
- if (process.env.KUBERNETES_SERVICE_HOST)
58080
- return "kubernetes";
58081
- try {
58082
- if (getFsImplementation().existsSync("/.dockerenv"))
58083
- return "docker";
58084
- } catch {}
58085
- if (env4.platform === "darwin")
58086
- return "unknown-darwin";
58087
- if (env4.platform === "linux")
58088
- return "unknown-linux";
58089
- if (env4.platform === "win32")
58090
- return "unknown-win32";
58091
- return "unknown";
58092
- });
58093
- env4 = {
58094
- hasInternetAccess,
58095
- isCI: isEnvTruthy(process.env.CI),
58096
- platform: ["win32", "darwin"].includes(process.platform) ? process.platform : "linux",
58097
- arch: process.arch,
58098
- nodeVersion: process.version,
58099
- terminal: detectTerminal(),
58100
- isSSH: isSSHSession,
58101
- getPackageManagers: detectPackageManagers,
58102
- getRuntimes: detectRuntimes,
58103
- isRunningWithBun: memoize_default(isRunningWithBun),
58104
- isWslEnvironment,
58105
- isNpmFromWindowsPath,
58106
- isConductor,
58107
- detectDeploymentEnvironment
58108
- };
58109
- });
58110
-
58111
- // src/constants/figures.ts
58112
- var BLACK_CIRCLE, BULLET_OPERATOR = "\u2219", TEARDROP_ASTERISK = "\u273B", UP_ARROW = "\u2191", DOWN_ARROW = "\u2193", LIGHTNING_BOLT = "\u21AF", EFFORT_LOW = "\u25CB", EFFORT_MEDIUM = "\u25D0", EFFORT_HIGH = "\u25CF", EFFORT_XHIGH = "\u25C9", EFFORT_MAX = "\u25C8", PAUSE_ICON = "\u23F8", REFRESH_ARROW = "\u21BB", CHANNEL_ARROW = "\u2190", DIAMOND_OPEN = "\u25C7", DIAMOND_FILLED = "\u25C6", REFERENCE_MARK = "\u203B", BLOCKQUOTE_BAR = "\u258E", BRIDGE_SPINNER_FRAMES, BRIDGE_READY_INDICATOR = "\xB7\u2714\uFE0E\xB7", BRIDGE_FAILED_INDICATOR = "\xD7";
58113
- var init_figures2 = __esm(() => {
58114
- init_env();
58115
- BLACK_CIRCLE = env4.platform === "darwin" ? "\u23FA" : "\u25CF";
58116
- BRIDGE_SPINNER_FRAMES = [
58117
- "\xB7|\xB7",
58118
- "\xB7/\xB7",
58119
- "\xB7\u2014\xB7",
58120
- "\xB7\\\xB7"
58121
- ];
58122
- });
58123
-
58124
- // src/types/permissions.ts
58125
- var exports_permissions = {};
58126
- __export(exports_permissions, {
58127
- PERMISSION_MODES_CLI_CHOICES: () => PERMISSION_MODES_CLI_CHOICES,
58128
- PERMISSION_MODES: () => PERMISSION_MODES,
58129
- INTERNAL_PERMISSION_MODES: () => INTERNAL_PERMISSION_MODES,
58130
- EXTERNAL_PERMISSION_MODES: () => EXTERNAL_PERMISSION_MODES
58131
- });
58132
- var EXTERNAL_PERMISSION_MODES, INTERNAL_PERMISSION_MODES, PERMISSION_MODES, PERMISSION_MODES_CLI_CHOICES;
58133
- var init_permissions = __esm(() => {
58134
- EXTERNAL_PERMISSION_MODES = [
58135
- "acceptEdits",
58136
- "auto",
58137
- "bypassPermissions",
58138
- "default",
58139
- "dontAsk",
58140
- "plan"
58141
- ];
58142
- INTERNAL_PERMISSION_MODES = [
58143
- ...EXTERNAL_PERMISSION_MODES
58144
- ];
58145
- PERMISSION_MODES = INTERNAL_PERMISSION_MODES;
58146
- PERMISSION_MODES_CLI_CHOICES = PERMISSION_MODES.map((mode) => mode === "default" ? "manual" : mode);
58147
- });
58148
-
58149
- // src/utils/permissions/PermissionMode.ts
58150
- function isExternalPermissionMode(mode) {
58151
- if (process.env.USER_TYPE !== "ant") {
58152
- return true;
58153
57938
  }
58154
- return mode !== "auto" && mode !== "bubble";
58155
- }
58156
- function getModeConfig(mode) {
58157
- return PERMISSION_MODE_CONFIG[mode] ?? PERMISSION_MODE_CONFIG.default;
58158
- }
58159
- function toExternalPermissionMode(mode) {
58160
- return getModeConfig(mode).external;
58161
- }
58162
- function normalizePermissionModeInput(str) {
58163
- return str === PERMISSION_MODE_MANUAL_ALIAS ? "default" : str;
58164
- }
58165
- function permissionModeFromString(str) {
58166
- const normalized = normalizePermissionModeInput(str);
58167
- return PERMISSION_MODES.includes(normalized) ? normalized : "default";
58168
- }
58169
- function permissionModeTitle(mode) {
58170
- return getModeConfig(mode).title;
57939
+ const match = url3.match(SCP_LIKE_HOST_PATTERN);
57940
+ const host = match?.[1];
57941
+ const path9 = match?.[2];
57942
+ if (!host || path9 === undefined || !isGitHubOrSshGitHubHost(host))
57943
+ return false;
57944
+ let decoded = path9;
57945
+ try {
57946
+ decoded = decodeURIComponent(path9);
57947
+ } catch {}
57948
+ return decoded.includes("*");
58171
57949
  }
58172
- function isDefaultMode(mode) {
58173
- return mode === "default" || mode === undefined;
57950
+ function regexCompiles(pattern) {
57951
+ try {
57952
+ new RegExp(pattern);
57953
+ return true;
57954
+ } catch {
57955
+ return false;
57956
+ }
58174
57957
  }
58175
- function permissionModeSymbol(mode) {
58176
- return getModeConfig(mode).symbol;
57958
+ function isValidWildcardOwner(owner) {
57959
+ return OWNER_CHARS_PATTERN.test(owner) && !owner.startsWith("-") && owner !== "." && owner !== "..";
58177
57960
  }
58178
- function permissionModeIndicator(mode) {
58179
- return getModeConfig(mode).indicator;
57961
+ function parseGitHubOwnerWildcard(repo) {
57962
+ if (!repo.endsWith("/*"))
57963
+ return null;
57964
+ const owner = repo.slice(0, -2);
57965
+ return isValidWildcardOwner(owner) ? owner : null;
58180
57966
  }
58181
- function getModeColor(mode) {
58182
- return getModeConfig(mode).color;
57967
+ function checkMarketplaceEntryEnforceability(entry) {
57968
+ const pattern = entry.source === "hostPattern" ? entry.hostPattern : entry.source === "pathPattern" ? entry.pathPattern : null;
57969
+ if (pattern !== null && !regexCompiles(pattern))
57970
+ return `${entry.source}: regex does not compile; the entry cannot be enforced`;
57971
+ if (entry.source === "github" && entry.repo.includes("*") && parseGitHubOwnerWildcard(entry.repo) === null)
57972
+ return 'github: an owner wildcard must be exactly "<owner>/*"; the entry cannot be enforced';
57973
+ if (entry.source === "git" && gitUrlHasWildcard(entry.url))
57974
+ return 'git: wildcards are only supported in github-form entries, as "<owner>/*"; the entry cannot be enforced';
57975
+ if ((entry.source === "github" || entry.source === "git") && entry.ref !== undefined && entry.ref.includes("*"))
57976
+ return `${entry.source}: ref contains "*", which git does not allow in ref names; the entry cannot be enforced`;
57977
+ return null;
58183
57978
  }
58184
- var permissionModeSchema, externalPermissionModeSchema, PERMISSION_MODE_MANUAL_ALIAS = "manual", PERMISSION_MODE_CONFIG;
58185
- var init_PermissionMode = __esm(() => {
58186
- init_featureFlags();
58187
- init_v4();
58188
- init_figures2();
58189
- init_permissions();
58190
- permissionModeSchema = lazySchema(() => v4_default.enum(PERMISSION_MODES));
58191
- externalPermissionModeSchema = lazySchema(() => v4_default.enum(EXTERNAL_PERMISSION_MODES));
58192
- PERMISSION_MODE_CONFIG = {
58193
- default: {
58194
- title: "Manual",
58195
- shortTitle: "Manual",
58196
- symbol: PAUSE_ICON,
58197
- color: "text",
58198
- external: "default",
58199
- indicator: "manual mode"
58200
- },
58201
- plan: {
58202
- title: "Plan Mode",
58203
- shortTitle: "Plan",
58204
- symbol: PAUSE_ICON,
58205
- color: "planMode",
58206
- external: "plan",
58207
- indicator: "plan mode"
58208
- },
58209
- acceptEdits: {
58210
- title: "Accept edits",
58211
- shortTitle: "Accept",
58212
- symbol: "\u23F5\u23F5",
58213
- color: "autoAccept",
58214
- external: "acceptEdits",
58215
- indicator: "accept edits"
58216
- },
58217
- bypassPermissions: {
58218
- title: "Bypass Permissions",
58219
- shortTitle: "Bypass",
58220
- symbol: "\u23F5\u23F5",
58221
- color: "error",
58222
- external: "bypassPermissions",
58223
- indicator: "bypass permissions"
58224
- },
58225
- dontAsk: {
58226
- title: "Don't Ask",
58227
- shortTitle: "DontAsk",
58228
- symbol: "\u23F5\u23F5",
58229
- color: "error",
58230
- external: "dontAsk",
58231
- indicator: "don't ask"
58232
- },
58233
- ...feature("TRANSCRIPT_CLASSIFIER") ? {
58234
- auto: {
58235
- title: "Auto mode",
58236
- shortTitle: "Auto",
58237
- symbol: "\u23F5\u23F5",
58238
- color: "warning",
58239
- external: "default",
58240
- indicator: "auto mode"
58241
- }
58242
- } : {}
58243
- };
57979
+ var GITHUB_HOST = "github.com", GITHUB_SSH_HOST = "ssh.github.com", INVALID_HOST_CHARS, URL_LIKE_PROTOCOLS, CREDENTIAL_STRIP_PROTOCOLS, OWNER_CHARS_PATTERN, SCP_LIKE_GIT_URL_PATTERN, SCP_LIKE_HOST_PATTERN, HOST_NORMALIZE_CACHE_LIMIT = 50, hostNormalizeCache;
57980
+ var init_marketplacePolicyValidation = __esm(() => {
57981
+ INVALID_HOST_CHARS = /[:/\\?#@\s]/;
57982
+ URL_LIKE_PROTOCOLS = new Set(["http", "https", "ws", "wss", "ftp"]);
57983
+ CREDENTIAL_STRIP_PROTOCOLS = new Set([
57984
+ "http:",
57985
+ "https:",
57986
+ "git:",
57987
+ "git+http:",
57988
+ "git+https:"
57989
+ ]);
57990
+ OWNER_CHARS_PATTERN = /^[A-Za-z0-9._-]+$/;
57991
+ SCP_LIKE_GIT_URL_PATTERN = /^([^@:/[\]]+)@([^@:/[\]]+):(.*)$/s;
57992
+ SCP_LIKE_HOST_PATTERN = /^(?:[^@]+@)?([^@:/]+):(.*)$/s;
57993
+ hostNormalizeCache = new Map;
58244
57994
  });
58245
57995
 
58246
57996
  // src/entrypoints/agentSdkTypes.js
@@ -58282,6 +58032,12 @@ var init_agentSdkTypes = __esm(() => {
58282
58032
  ];
58283
58033
  });
58284
58034
 
58035
+ // src/utils/lazySchema.ts
58036
+ function lazySchema(factory2) {
58037
+ let cached2;
58038
+ return () => cached2 ??= factory2();
58039
+ }
58040
+
58285
58041
  // src/utils/shell/shellProvider.ts
58286
58042
  var SHELL_TYPES, DEFAULT_HOOK_SHELL = "bash";
58287
58043
  var init_shellProvider = __esm(() => {
@@ -58906,6 +58662,317 @@ var init_schemas3 = __esm(() => {
58906
58662
  KnownMarketplacesFileSchema = lazySchema(() => exports_external.record(exports_external.string(), KnownMarketplaceSchema()));
58907
58663
  });
58908
58664
 
58665
+ // src/utils/settings/sanitizeWarningText.ts
58666
+ function sanitizeForWarningText(text) {
58667
+ return text.replace(C0_CONTROL_CHARS_RE, "");
58668
+ }
58669
+ var C0_CONTROL_CHARS_RE;
58670
+ var init_sanitizeWarningText = __esm(() => {
58671
+ C0_CONTROL_CHARS_RE = /[\u0000-\u001f]/g;
58672
+ });
58673
+
58674
+ // src/utils/settings/marketplacePolicySanitizer.ts
58675
+ function firstIssueDetail(issues) {
58676
+ for (const issue2 of issues) {
58677
+ const prefix = issue2.path.length > 0 ? `${issue2.path.map(String).join(".")}: ` : "";
58678
+ if (issue2.code === "invalid_union") {
58679
+ for (const branch of issue2.errors) {
58680
+ const detail = firstIssueDetail(branch);
58681
+ if (detail !== null)
58682
+ return `${prefix}${detail}`;
58683
+ }
58684
+ const noted = issue2;
58685
+ if (typeof noted.note === "string" && noted.note !== "")
58686
+ return `${prefix}${noted.note}`;
58687
+ }
58688
+ if (issue2.message !== "")
58689
+ return `${prefix}${issue2.message}`;
58690
+ }
58691
+ return null;
58692
+ }
58693
+ function sanitizeMarketplacePolicy(data, filePath) {
58694
+ if (!data || typeof data !== "object")
58695
+ return [];
58696
+ const obj = data;
58697
+ const warnings = [];
58698
+ for (const key of POLICY_KEYS) {
58699
+ if (!(key in obj))
58700
+ continue;
58701
+ const raw = obj[key];
58702
+ if (raw === null) {
58703
+ delete obj[key];
58704
+ continue;
58705
+ }
58706
+ if (!Array.isArray(raw)) {
58707
+ if (key === "strictKnownMarketplaces") {
58708
+ obj[key] = [];
58709
+ } else {
58710
+ delete obj[key];
58711
+ }
58712
+ warnings.push({
58713
+ file: filePath,
58714
+ path: key,
58715
+ message: key === "strictKnownMarketplaces" ? STRICT_PRESENT_INVALID_MESSAGE : BLOCKED_PRESENT_INVALID_MESSAGE,
58716
+ invalidValue: raw
58717
+ });
58718
+ continue;
58719
+ }
58720
+ const kept = [];
58721
+ for (const [index2, entry] of raw.entries()) {
58722
+ const parsed = MarketplaceSourceSchema().safeParse(entry);
58723
+ if (!parsed.success) {
58724
+ warnings.push({
58725
+ file: filePath,
58726
+ path: `${key}[${index2}]`,
58727
+ message: `Invalid entry was ignored: ${sanitizeForWarningText(firstIssueDetail(parsed.error.issues) ?? "failed validation")}`,
58728
+ invalidValue: entry
58729
+ });
58730
+ continue;
58731
+ }
58732
+ const problem = checkMarketplaceEntryEnforceability(parsed.data);
58733
+ if (problem === null) {
58734
+ kept.push(parsed.data);
58735
+ continue;
58736
+ }
58737
+ if (key === "blockedMarketplaces") {
58738
+ kept.push(parsed.data);
58739
+ warnings.push({
58740
+ file: filePath,
58741
+ path: `${key}[${index2}]`,
58742
+ message: `Unenforceable entry was kept: ${sanitizeForWarningText(problem)}; it can never match a marketplace source, but marketplace restrictions stay active`,
58743
+ invalidValue: entry
58744
+ });
58745
+ } else {
58746
+ warnings.push({
58747
+ file: filePath,
58748
+ path: `${key}[${index2}]`,
58749
+ message: `Invalid entry was ignored: ${sanitizeForWarningText(problem)}`,
58750
+ invalidValue: entry
58751
+ });
58752
+ }
58753
+ }
58754
+ obj[key] = kept;
58755
+ }
58756
+ return warnings;
58757
+ }
58758
+ var POLICY_KEYS, STRICT_PRESENT_INVALID_MESSAGE = '"strictKnownMarketplaces" was present but invalid; enforcing an empty allowlist (no marketplaces admitted) until it is fixed.', BLOCKED_PRESENT_INVALID_MESSAGE = '"blockedMarketplaces" was present but invalid and was dropped; its entries cannot be enforced until it is fixed.';
58759
+ var init_marketplacePolicySanitizer = __esm(() => {
58760
+ init_marketplacePolicyValidation();
58761
+ init_schemas3();
58762
+ init_sanitizeWarningText();
58763
+ POLICY_KEYS = ["strictKnownMarketplaces", "blockedMarketplaces"];
58764
+ });
58765
+
58766
+ // src/utils/settings/sanitizeAllowlists.ts
58767
+ function issueDetail(error49) {
58768
+ const issue2 = error49.issues[0];
58769
+ if (issue2 === undefined)
58770
+ return "failed validation";
58771
+ return issue2.path.length > 0 ? `${issue2.path.join(".")}: ${issue2.message}` : issue2.message;
58772
+ }
58773
+ function validateAllowlistEntry(key, entry) {
58774
+ if (key === "allowedChannelPlugins") {
58775
+ if (typeof entry === "string") {
58776
+ const at = entry.indexOf("@");
58777
+ const plugin = entry.slice(0, at);
58778
+ const marketplace = entry.slice(at + 1);
58779
+ if (at > 0 && marketplace.length > 0) {
58780
+ return {
58781
+ ok: true,
58782
+ value: { marketplace, plugin },
58783
+ notice: `"allowedChannelPlugins" entry "${sanitizeForWarningText(entry)}" was accepted; prefer the documented object form {"plugin": "${sanitizeForWarningText(plugin)}", "marketplace": "${sanitizeForWarningText(marketplace)}"}.`
58784
+ };
58785
+ }
58786
+ }
58787
+ const parsed2 = CHANNEL_PLUGIN_ENTRY.safeParse(entry);
58788
+ return parsed2.success ? { ok: true, value: parsed2.data } : { ok: false, detail: issueDetail(parsed2.error) };
58789
+ }
58790
+ const parsed = STRING_ENTRY.safeParse(entry);
58791
+ return parsed.success ? { ok: true, value: parsed.data } : { ok: false, detail: issueDetail(parsed.error) };
58792
+ }
58793
+ function sanitizeSecurityAllowlists(data, filePath) {
58794
+ if (!data || typeof data !== "object")
58795
+ return [];
58796
+ const obj = data;
58797
+ const warnings = [];
58798
+ for (const { key, emptyReason } of ALLOWLIST_SPECS) {
58799
+ if (!(key in obj))
58800
+ continue;
58801
+ const raw = obj[key];
58802
+ if (!Array.isArray(raw)) {
58803
+ obj[key] = [];
58804
+ warnings.push({
58805
+ file: filePath,
58806
+ path: key,
58807
+ message: `"${key}" was present but invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`,
58808
+ invalidValue: raw
58809
+ });
58810
+ continue;
58811
+ }
58812
+ const valid = [];
58813
+ for (const [index2, entry] of raw.entries()) {
58814
+ const result = validateAllowlistEntry(key, entry);
58815
+ if (result.ok) {
58816
+ valid.push(result.value);
58817
+ if (result.notice !== undefined) {
58818
+ warnings.push({
58819
+ file: filePath,
58820
+ path: `${key}[${index2}]`,
58821
+ message: result.notice
58822
+ });
58823
+ }
58824
+ } else {
58825
+ warnings.push({
58826
+ file: filePath,
58827
+ path: `${key}[${index2}]`,
58828
+ message: `Invalid entry was ignored: ${sanitizeForWarningText(result.detail)}`,
58829
+ invalidValue: entry
58830
+ });
58831
+ }
58832
+ }
58833
+ if (raw.length > 0 && valid.length === 0) {
58834
+ warnings.push({
58835
+ file: filePath,
58836
+ path: key,
58837
+ message: `Every entry of "${key}" was invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`
58838
+ });
58839
+ }
58840
+ obj[key] = valid;
58841
+ }
58842
+ return warnings;
58843
+ }
58844
+ var STRING_ENTRY, CHANNEL_PLUGIN_ENTRY, ALLOWLIST_SPECS;
58845
+ var init_sanitizeAllowlists = __esm(() => {
58846
+ init_v4();
58847
+ init_sanitizeWarningText();
58848
+ STRING_ENTRY = exports_external.string();
58849
+ CHANNEL_PLUGIN_ENTRY = exports_external.object({
58850
+ marketplace: exports_external.string(),
58851
+ plugin: exports_external.string()
58852
+ });
58853
+ ALLOWLIST_SPECS = [
58854
+ { key: "allowedHttpHookUrls", emptyReason: "no HTTP hooks may run" },
58855
+ {
58856
+ key: "httpHookAllowedEnvVars",
58857
+ emptyReason: "no environment variables may be interpolated into HTTP hook headers"
58858
+ },
58859
+ { key: "allowedChannelPlugins", emptyReason: "no channel plugins admitted" }
58860
+ ];
58861
+ });
58862
+
58863
+ // src/utils/stringUtils.ts
58864
+ function escapeRegExp(str) {
58865
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
58866
+ }
58867
+ function capitalize(str) {
58868
+ return str.charAt(0).toUpperCase() + str.slice(1);
58869
+ }
58870
+ function plural(n2, word, pluralWord = word + "s") {
58871
+ return n2 === 1 ? word : pluralWord;
58872
+ }
58873
+ function firstLineOf(s) {
58874
+ const nl = s.indexOf(`
58875
+ `);
58876
+ return nl === -1 ? s : s.slice(0, nl);
58877
+ }
58878
+ function countCharInString(str, char, start = 0) {
58879
+ let count3 = 0;
58880
+ let i2 = str.indexOf(char, start);
58881
+ while (i2 !== -1) {
58882
+ count3++;
58883
+ i2 = str.indexOf(char, i2 + 1);
58884
+ }
58885
+ return count3;
58886
+ }
58887
+ function normalizeFullWidthDigits(input) {
58888
+ return input.replace(/[\uFF10-\uFF19]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 65248));
58889
+ }
58890
+ function normalizeFullWidthSpace(input) {
58891
+ return input.replace(/\u3000/g, " ");
58892
+ }
58893
+ function safeJoinLines(lines, delimiter = ",", maxSize = MAX_STRING_LENGTH) {
58894
+ const truncationMarker = "...[truncated]";
58895
+ let result = "";
58896
+ for (const line of lines) {
58897
+ const delimiterToAdd = result ? delimiter : "";
58898
+ const fullAddition = delimiterToAdd + line;
58899
+ if (result.length + fullAddition.length <= maxSize) {
58900
+ result += fullAddition;
58901
+ } else {
58902
+ const remainingSpace = maxSize - result.length - delimiterToAdd.length - truncationMarker.length;
58903
+ if (remainingSpace > 0) {
58904
+ result += delimiterToAdd + line.slice(0, remainingSpace) + truncationMarker;
58905
+ } else {
58906
+ result += truncationMarker;
58907
+ }
58908
+ return result;
58909
+ }
58910
+ }
58911
+ return result;
58912
+ }
58913
+
58914
+ class EndTruncatingAccumulator {
58915
+ maxSize;
58916
+ content = "";
58917
+ isTruncated = false;
58918
+ totalBytesReceived = 0;
58919
+ constructor(maxSize = MAX_STRING_LENGTH) {
58920
+ this.maxSize = maxSize;
58921
+ }
58922
+ append(data) {
58923
+ const str = typeof data === "string" ? data : data.toString();
58924
+ this.totalBytesReceived += str.length;
58925
+ if (this.isTruncated && this.content.length >= this.maxSize) {
58926
+ return;
58927
+ }
58928
+ if (this.content.length + str.length > this.maxSize) {
58929
+ const remainingSpace = this.maxSize - this.content.length;
58930
+ if (remainingSpace > 0) {
58931
+ this.content += str.slice(0, remainingSpace);
58932
+ }
58933
+ this.isTruncated = true;
58934
+ } else {
58935
+ this.content += str;
58936
+ }
58937
+ }
58938
+ toString() {
58939
+ if (!this.isTruncated) {
58940
+ return this.content;
58941
+ }
58942
+ const truncatedBytes = this.totalBytesReceived - this.maxSize;
58943
+ const truncatedKB = Math.round(truncatedBytes / 1024);
58944
+ return this.content + `
58945
+ ... [output truncated - ${truncatedKB}KB removed]`;
58946
+ }
58947
+ clear() {
58948
+ this.content = "";
58949
+ this.isTruncated = false;
58950
+ this.totalBytesReceived = 0;
58951
+ }
58952
+ get length() {
58953
+ return this.content.length;
58954
+ }
58955
+ get truncated() {
58956
+ return this.isTruncated;
58957
+ }
58958
+ get totalBytes() {
58959
+ return this.totalBytesReceived;
58960
+ }
58961
+ }
58962
+ function truncateToLines(text, maxLines) {
58963
+ const lines = text.split(`
58964
+ `);
58965
+ if (lines.length <= maxLines) {
58966
+ return text;
58967
+ }
58968
+ return lines.slice(0, maxLines).join(`
58969
+ `) + "\u2026";
58970
+ }
58971
+ var MAX_STRING_LENGTH;
58972
+ var init_stringUtils = __esm(() => {
58973
+ MAX_STRING_LENGTH = 2 ** 25;
58974
+ });
58975
+
58909
58976
  // src/services/mcp/normalization.ts
58910
58977
  function normalizeNameForMCP(name) {
58911
58978
  let normalized = name.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -59129,119 +59196,6 @@ var init_permissionRuleParser = __esm(() => {
59129
59196
  };
59130
59197
  });
59131
59198
 
59132
- // src/utils/stringUtils.ts
59133
- function escapeRegExp(str) {
59134
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
59135
- }
59136
- function capitalize(str) {
59137
- return str.charAt(0).toUpperCase() + str.slice(1);
59138
- }
59139
- function plural(n2, word, pluralWord = word + "s") {
59140
- return n2 === 1 ? word : pluralWord;
59141
- }
59142
- function firstLineOf(s) {
59143
- const nl = s.indexOf(`
59144
- `);
59145
- return nl === -1 ? s : s.slice(0, nl);
59146
- }
59147
- function countCharInString(str, char, start = 0) {
59148
- let count3 = 0;
59149
- let i2 = str.indexOf(char, start);
59150
- while (i2 !== -1) {
59151
- count3++;
59152
- i2 = str.indexOf(char, i2 + 1);
59153
- }
59154
- return count3;
59155
- }
59156
- function normalizeFullWidthDigits(input) {
59157
- return input.replace(/[\uFF10-\uFF19]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 65248));
59158
- }
59159
- function normalizeFullWidthSpace(input) {
59160
- return input.replace(/\u3000/g, " ");
59161
- }
59162
- function safeJoinLines(lines, delimiter = ",", maxSize = MAX_STRING_LENGTH) {
59163
- const truncationMarker = "...[truncated]";
59164
- let result = "";
59165
- for (const line of lines) {
59166
- const delimiterToAdd = result ? delimiter : "";
59167
- const fullAddition = delimiterToAdd + line;
59168
- if (result.length + fullAddition.length <= maxSize) {
59169
- result += fullAddition;
59170
- } else {
59171
- const remainingSpace = maxSize - result.length - delimiterToAdd.length - truncationMarker.length;
59172
- if (remainingSpace > 0) {
59173
- result += delimiterToAdd + line.slice(0, remainingSpace) + truncationMarker;
59174
- } else {
59175
- result += truncationMarker;
59176
- }
59177
- return result;
59178
- }
59179
- }
59180
- return result;
59181
- }
59182
-
59183
- class EndTruncatingAccumulator {
59184
- maxSize;
59185
- content = "";
59186
- isTruncated = false;
59187
- totalBytesReceived = 0;
59188
- constructor(maxSize = MAX_STRING_LENGTH) {
59189
- this.maxSize = maxSize;
59190
- }
59191
- append(data) {
59192
- const str = typeof data === "string" ? data : data.toString();
59193
- this.totalBytesReceived += str.length;
59194
- if (this.isTruncated && this.content.length >= this.maxSize) {
59195
- return;
59196
- }
59197
- if (this.content.length + str.length > this.maxSize) {
59198
- const remainingSpace = this.maxSize - this.content.length;
59199
- if (remainingSpace > 0) {
59200
- this.content += str.slice(0, remainingSpace);
59201
- }
59202
- this.isTruncated = true;
59203
- } else {
59204
- this.content += str;
59205
- }
59206
- }
59207
- toString() {
59208
- if (!this.isTruncated) {
59209
- return this.content;
59210
- }
59211
- const truncatedBytes = this.totalBytesReceived - this.maxSize;
59212
- const truncatedKB = Math.round(truncatedBytes / 1024);
59213
- return this.content + `
59214
- ... [output truncated - ${truncatedKB}KB removed]`;
59215
- }
59216
- clear() {
59217
- this.content = "";
59218
- this.isTruncated = false;
59219
- this.totalBytesReceived = 0;
59220
- }
59221
- get length() {
59222
- return this.content.length;
59223
- }
59224
- get truncated() {
59225
- return this.isTruncated;
59226
- }
59227
- get totalBytes() {
59228
- return this.totalBytesReceived;
59229
- }
59230
- }
59231
- function truncateToLines(text, maxLines) {
59232
- const lines = text.split(`
59233
- `);
59234
- if (lines.length <= maxLines) {
59235
- return text;
59236
- }
59237
- return lines.slice(0, maxLines).join(`
59238
- `) + "\u2026";
59239
- }
59240
- var MAX_STRING_LENGTH;
59241
- var init_stringUtils = __esm(() => {
59242
- MAX_STRING_LENGTH = 2 ** 25;
59243
- });
59244
-
59245
59199
  // src/utils/settings/toolValidationConfig.ts
59246
59200
  function isFilePatternTool(toolName) {
59247
59201
  return TOOL_VALIDATION_CONFIG.filePatternTools.includes(toolName);
@@ -59528,6 +59482,492 @@ var init_permissionValidation = __esm(() => {
59528
59482
  }));
59529
59483
  });
59530
59484
 
59485
+ // src/entrypoints/sandboxTypes.ts
59486
+ var SandboxNetworkConfigSchema, SandboxFilesystemConfigSchema, SandboxSettingsSchema;
59487
+ var init_sandboxTypes = __esm(() => {
59488
+ init_v4();
59489
+ SandboxNetworkConfigSchema = lazySchema(() => exports_external.object({
59490
+ allowedDomains: exports_external.array(exports_external.string()).optional(),
59491
+ deniedDomains: exports_external.array(exports_external.string()).optional().describe("Domains to block even when a broader allowedDomains wildcard would otherwise permit them."),
59492
+ allowManagedDomainsOnly: exports_external.boolean().optional().describe("When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. " + "User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources."),
59493
+ strictAllowlist: exports_external.boolean().optional().describe("When true, the sandbox runtime deterministically denies hosts not in allowedDomains instead of prompting. " + "Enforced for sandboxed commands only \u2014 in-process tools such as WebFetch are not gated by this setting. " + "Only honored from user, managed/policy, or CLI (--settings) settings \u2014 " + "project settings (.claude/settings.json and .claude/settings.local.json) are ignored."),
59494
+ allowUnixSockets: exports_external.array(exports_external.string()).optional().describe("macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path)."),
59495
+ allowAllUnixSockets: exports_external.boolean().optional().describe("If true, allow all Unix sockets (disables blocking on both platforms)."),
59496
+ allowLocalBinding: exports_external.boolean().optional(),
59497
+ httpProxyPort: exports_external.number().optional(),
59498
+ socksProxyPort: exports_external.number().optional()
59499
+ }).optional());
59500
+ SandboxFilesystemConfigSchema = lazySchema(() => exports_external.object({
59501
+ disabled: exports_external.boolean().optional().describe("macOS and Linux/WSL only: skip filesystem isolation entirely while " + "keeping network and seccomp isolation. Ignored on native Windows, " + "where the sandboxed process runs as a separate user with no " + "inherent rights, so skipping the filesystem rules would withhold " + "every access grant rather than loosen them \u2014 filesystem isolation " + "stays on there."),
59502
+ allowWrite: exports_external.array(exports_external.string()).optional().describe("Additional paths to allow writing within the sandbox. " + "Merged with paths from Edit(...) allow permission rules."),
59503
+ denyWrite: exports_external.array(exports_external.string()).optional().describe("Additional paths to deny writing within the sandbox. " + "Merged with paths from Edit(...) deny permission rules."),
59504
+ denyRead: exports_external.array(exports_external.string()).optional().describe("Additional paths to deny reading within the sandbox. " + "Merged with paths from Read(...) deny permission rules."),
59505
+ allowRead: exports_external.array(exports_external.string()).optional().describe("Paths to re-allow reading within denyRead regions. " + "Takes precedence over denyRead for matching paths."),
59506
+ allowManagedReadPathsOnly: exports_external.boolean().optional().describe("When true (set in managed settings), only allowRead paths from policySettings are used.")
59507
+ }).optional());
59508
+ SandboxSettingsSchema = lazySchema(() => exports_external.object({
59509
+ enabled: exports_external.boolean().optional(),
59510
+ failIfUnavailable: exports_external.boolean().optional().describe("Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start " + "(missing dependencies, unsupported platform, or platform not in enabledPlatforms). " + "When false (default), a warning is shown and commands run unsandboxed. " + "Intended for managed-settings deployments that require sandboxing as a hard gate."),
59511
+ autoAllowBashIfSandboxed: exports_external.boolean().optional(),
59512
+ allowUnsandboxedCommands: exports_external.boolean().optional().describe("Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. " + "When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. " + "Default: true."),
59513
+ network: SandboxNetworkConfigSchema(),
59514
+ filesystem: SandboxFilesystemConfigSchema(),
59515
+ ignoreViolations: exports_external.record(exports_external.string(), exports_external.array(exports_external.string())).optional(),
59516
+ enableWeakerNestedSandbox: exports_external.boolean().optional(),
59517
+ enableWeakerNetworkIsolation: exports_external.boolean().optional().describe("macOS only: Allow access to com.apple.trustd.agent in the sandbox. " + "Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates " + "when using httpProxyPort with a MITM proxy and custom CA. " + "**Reduces security** \u2014 opens a potential data exfiltration vector through the trustd service. Default: false"),
59518
+ allowAppleEvents: exports_external.boolean().optional().describe("macOS only: Allow sandboxed commands to send Apple Events to other " + "applications via the Apple Event service. Default: false"),
59519
+ excludedCommands: exports_external.array(exports_external.string()).optional(),
59520
+ credentials: exports_external.object({
59521
+ enabled: exports_external.boolean().optional().describe("When true, block sandboxed commands from reading credential files and secret env vars.")
59522
+ }).optional(),
59523
+ ripgrep: exports_external.object({
59524
+ command: exports_external.string(),
59525
+ args: exports_external.array(exports_external.string()).optional()
59526
+ }).optional().describe("Custom ripgrep configuration for bundled ripgrep support")
59527
+ }).passthrough());
59528
+ });
59529
+
59530
+ // src/utils/bundledMode.ts
59531
+ function isRunningWithBun() {
59532
+ return process.versions.bun !== undefined;
59533
+ }
59534
+ function isInBundledMode() {
59535
+ return typeof Bun !== "undefined" && Array.isArray(Bun.embeddedFiles) && Bun.embeddedFiles.length > 0;
59536
+ }
59537
+
59538
+ // src/utils/findExecutable.ts
59539
+ function findExecutable2(exe, args) {
59540
+ const resolved = whichSync(exe);
59541
+ return { cmd: resolved ?? exe, args };
59542
+ }
59543
+ var init_findExecutable = __esm(() => {
59544
+ init_which();
59545
+ });
59546
+
59547
+ // src/utils/env.ts
59548
+ import { homedir as homedir8 } from "os";
59549
+ import { join as join17 } from "path";
59550
+ async function isCommandAvailable(command) {
59551
+ try {
59552
+ return !!await which(command);
59553
+ } catch {
59554
+ return false;
59555
+ }
59556
+ }
59557
+ function isConductor() {
59558
+ return process.env.__CFBundleIdentifier === "com.conductor.app";
59559
+ }
59560
+ function detectTerminal() {
59561
+ if (process.env.CURSOR_TRACE_ID)
59562
+ return "cursor";
59563
+ if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("cursor")) {
59564
+ return "cursor";
59565
+ }
59566
+ if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("windsurf")) {
59567
+ return "windsurf";
59568
+ }
59569
+ if (process.env.VSCODE_GIT_ASKPASS_MAIN?.includes("antigravity")) {
59570
+ return "antigravity";
59571
+ }
59572
+ const bundleId = process.env.__CFBundleIdentifier?.toLowerCase();
59573
+ if (bundleId?.includes("vscodium"))
59574
+ return "codium";
59575
+ if (bundleId?.includes("windsurf"))
59576
+ return "windsurf";
59577
+ if (bundleId?.includes("com.google.android.studio"))
59578
+ return "androidstudio";
59579
+ if (bundleId) {
59580
+ for (const ide of JETBRAINS_IDES) {
59581
+ if (bundleId.includes(ide))
59582
+ return ide;
59583
+ }
59584
+ }
59585
+ if (process.env.VisualStudioVersion) {
59586
+ return "visualstudio";
59587
+ }
59588
+ if (process.env.TERMINAL_EMULATOR === "JetBrains-JediTerm") {
59589
+ if (process.platform === "darwin")
59590
+ return "pycharm";
59591
+ return "pycharm";
59592
+ }
59593
+ if (process.env.TERM === "xterm-ghostty") {
59594
+ return "ghostty";
59595
+ }
59596
+ if (process.env.TERM?.includes("kitty")) {
59597
+ return "kitty";
59598
+ }
59599
+ if (process.env.TERM_PROGRAM) {
59600
+ return process.env.TERM_PROGRAM;
59601
+ }
59602
+ if (process.env.TMUX)
59603
+ return "tmux";
59604
+ if (process.env.STY)
59605
+ return "screen";
59606
+ if (process.env.KONSOLE_VERSION)
59607
+ return "konsole";
59608
+ if (process.env.GNOME_TERMINAL_SERVICE)
59609
+ return "gnome-terminal";
59610
+ if (process.env.XTERM_VERSION)
59611
+ return "xterm";
59612
+ if (process.env.VTE_VERSION)
59613
+ return "vte-based";
59614
+ if (process.env.TERMINATOR_UUID)
59615
+ return "terminator";
59616
+ if (process.env.KITTY_WINDOW_ID) {
59617
+ return "kitty";
59618
+ }
59619
+ if (process.env.ALACRITTY_LOG)
59620
+ return "alacritty";
59621
+ if (process.env.TILIX_ID)
59622
+ return "tilix";
59623
+ if (process.env.WT_SESSION)
59624
+ return "windows-terminal";
59625
+ if (process.env.SESSIONNAME && process.env.TERM === "cygwin")
59626
+ return "cygwin";
59627
+ if (process.env.MSYSTEM)
59628
+ return process.env.MSYSTEM.toLowerCase();
59629
+ if (process.env.ConEmuANSI || process.env.ConEmuPID || process.env.ConEmuTask) {
59630
+ return "conemu";
59631
+ }
59632
+ if (process.env.WSL_DISTRO_NAME)
59633
+ return `wsl-${process.env.WSL_DISTRO_NAME}`;
59634
+ if (isSSHSession()) {
59635
+ return "ssh-session";
59636
+ }
59637
+ if (process.env.TERM) {
59638
+ const term = process.env.TERM;
59639
+ if (term.includes("alacritty"))
59640
+ return "alacritty";
59641
+ if (term.includes("rxvt"))
59642
+ return "rxvt";
59643
+ if (term.includes("termite"))
59644
+ return "termite";
59645
+ return process.env.TERM;
59646
+ }
59647
+ if (!process.stdout.isTTY)
59648
+ return "non-interactive";
59649
+ return null;
59650
+ }
59651
+ function isSSHSession() {
59652
+ return !!(process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY);
59653
+ }
59654
+ function getHostPlatformForAnalytics() {
59655
+ const override = process.env.CLAUDE_CODE_HOST_PLATFORM;
59656
+ if (override === "win32" || override === "darwin" || override === "linux") {
59657
+ return override;
59658
+ }
59659
+ return env4.platform;
59660
+ }
59661
+ var getGlobalClaudeFile, hasInternetAccess, detectPackageManagers, detectRuntimes, isWslEnvironment, isNpmFromWindowsPath, JETBRAINS_IDES, detectDeploymentEnvironment, env4;
59662
+ var init_env = __esm(() => {
59663
+ init_memoize();
59664
+ init_oauth();
59665
+ init_envUtils();
59666
+ init_findExecutable();
59667
+ init_fsOperations();
59668
+ init_which();
59669
+ getGlobalClaudeFile = memoize_default(() => {
59670
+ if (getFsImplementation().existsSync(join17(getClaudeConfigHomeDir(), ".config.json"))) {
59671
+ return join17(getClaudeConfigHomeDir(), ".config.json");
59672
+ }
59673
+ const filename = `.claude${fileSuffixForOauthConfig()}.json`;
59674
+ const p = join17(process.env.CLAUDE_CONFIG_DIR || homedir8(), filename);
59675
+ return p;
59676
+ });
59677
+ hasInternetAccess = memoize_default(async () => {
59678
+ try {
59679
+ const { default: axiosClient } = await Promise.resolve().then(() => (init_axios2(), exports_axios));
59680
+ await axiosClient.head("http://1.1.1.1", {
59681
+ signal: AbortSignal.timeout(1000)
59682
+ });
59683
+ return true;
59684
+ } catch {
59685
+ return false;
59686
+ }
59687
+ });
59688
+ detectPackageManagers = memoize_default(async () => {
59689
+ const packageManagers = [];
59690
+ if (await isCommandAvailable("npm"))
59691
+ packageManagers.push("npm");
59692
+ if (await isCommandAvailable("yarn"))
59693
+ packageManagers.push("yarn");
59694
+ if (await isCommandAvailable("pnpm"))
59695
+ packageManagers.push("pnpm");
59696
+ return packageManagers;
59697
+ });
59698
+ detectRuntimes = memoize_default(async () => {
59699
+ const runtimes = [];
59700
+ if (await isCommandAvailable("bun"))
59701
+ runtimes.push("bun");
59702
+ if (await isCommandAvailable("deno"))
59703
+ runtimes.push("deno");
59704
+ if (await isCommandAvailable("node"))
59705
+ runtimes.push("node");
59706
+ return runtimes;
59707
+ });
59708
+ isWslEnvironment = memoize_default(() => {
59709
+ try {
59710
+ return getFsImplementation().existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
59711
+ } catch (_error) {
59712
+ return false;
59713
+ }
59714
+ });
59715
+ isNpmFromWindowsPath = memoize_default(() => {
59716
+ try {
59717
+ if (!isWslEnvironment()) {
59718
+ return false;
59719
+ }
59720
+ const { cmd } = findExecutable2("npm", []);
59721
+ return cmd.startsWith("/mnt/c/");
59722
+ } catch (_error) {
59723
+ return false;
59724
+ }
59725
+ });
59726
+ JETBRAINS_IDES = [
59727
+ "pycharm",
59728
+ "intellij",
59729
+ "webstorm",
59730
+ "phpstorm",
59731
+ "rubymine",
59732
+ "clion",
59733
+ "goland",
59734
+ "rider",
59735
+ "datagrip",
59736
+ "appcode",
59737
+ "dataspell",
59738
+ "aqua",
59739
+ "gateway",
59740
+ "fleet",
59741
+ "jetbrains",
59742
+ "androidstudio"
59743
+ ];
59744
+ detectDeploymentEnvironment = memoize_default(() => {
59745
+ if (isEnvTruthy(process.env.CODESPACES))
59746
+ return "codespaces";
59747
+ if (process.env.GITPOD_WORKSPACE_ID)
59748
+ return "gitpod";
59749
+ if (process.env.REPL_ID || process.env.REPL_SLUG)
59750
+ return "replit";
59751
+ if (process.env.PROJECT_DOMAIN)
59752
+ return "glitch";
59753
+ if (isEnvTruthy(process.env.VERCEL))
59754
+ return "vercel";
59755
+ if (process.env.RAILWAY_ENVIRONMENT_NAME || process.env.RAILWAY_SERVICE_NAME) {
59756
+ return "railway";
59757
+ }
59758
+ if (isEnvTruthy(process.env.RENDER))
59759
+ return "render";
59760
+ if (isEnvTruthy(process.env.NETLIFY))
59761
+ return "netlify";
59762
+ if (process.env.DYNO)
59763
+ return "heroku";
59764
+ if (process.env.FLY_APP_NAME || process.env.FLY_MACHINE_ID)
59765
+ return "fly.io";
59766
+ if (isEnvTruthy(process.env.CF_PAGES))
59767
+ return "cloudflare-pages";
59768
+ if (process.env.DENO_DEPLOYMENT_ID)
59769
+ return "deno-deploy";
59770
+ if (process.env.AWS_LAMBDA_FUNCTION_NAME)
59771
+ return "aws-lambda";
59772
+ if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_FARGATE")
59773
+ return "aws-fargate";
59774
+ if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_EC2")
59775
+ return "aws-ecs";
59776
+ try {
59777
+ const uuid3 = getFsImplementation().readFileSync("/sys/hypervisor/uuid", { encoding: "utf8" }).trim().toLowerCase();
59778
+ if (uuid3.startsWith("ec2"))
59779
+ return "aws-ec2";
59780
+ } catch {}
59781
+ if (process.env.K_SERVICE)
59782
+ return "gcp-cloud-run";
59783
+ if (process.env.GOOGLE_CLOUD_PROJECT)
59784
+ return "gcp";
59785
+ if (process.env.WEBSITE_SITE_NAME || process.env.WEBSITE_SKU)
59786
+ return "azure-app-service";
59787
+ if (process.env.AZURE_FUNCTIONS_ENVIRONMENT)
59788
+ return "azure-functions";
59789
+ if (process.env.APP_URL?.includes("ondigitalocean.app")) {
59790
+ return "digitalocean-app-platform";
59791
+ }
59792
+ if (process.env.SPACE_CREATOR_USER_ID)
59793
+ return "huggingface-spaces";
59794
+ if (isEnvTruthy(process.env.GITHUB_ACTIONS))
59795
+ return "github-actions";
59796
+ if (isEnvTruthy(process.env.GITLAB_CI))
59797
+ return "gitlab-ci";
59798
+ if (process.env.CIRCLECI)
59799
+ return "circleci";
59800
+ if (process.env.BUILDKITE)
59801
+ return "buildkite";
59802
+ if (isEnvTruthy(process.env.CI))
59803
+ return "ci";
59804
+ if (process.env.KUBERNETES_SERVICE_HOST)
59805
+ return "kubernetes";
59806
+ try {
59807
+ if (getFsImplementation().existsSync("/.dockerenv"))
59808
+ return "docker";
59809
+ } catch {}
59810
+ if (env4.platform === "darwin")
59811
+ return "unknown-darwin";
59812
+ if (env4.platform === "linux")
59813
+ return "unknown-linux";
59814
+ if (env4.platform === "win32")
59815
+ return "unknown-win32";
59816
+ return "unknown";
59817
+ });
59818
+ env4 = {
59819
+ hasInternetAccess,
59820
+ isCI: isEnvTruthy(process.env.CI),
59821
+ platform: ["win32", "darwin"].includes(process.platform) ? process.platform : "linux",
59822
+ arch: process.arch,
59823
+ nodeVersion: process.version,
59824
+ terminal: detectTerminal(),
59825
+ isSSH: isSSHSession,
59826
+ getPackageManagers: detectPackageManagers,
59827
+ getRuntimes: detectRuntimes,
59828
+ isRunningWithBun: memoize_default(isRunningWithBun),
59829
+ isWslEnvironment,
59830
+ isNpmFromWindowsPath,
59831
+ isConductor,
59832
+ detectDeploymentEnvironment
59833
+ };
59834
+ });
59835
+
59836
+ // src/constants/figures.ts
59837
+ var BLACK_CIRCLE, BULLET_OPERATOR = "\u2219", TEARDROP_ASTERISK = "\u273B", UP_ARROW = "\u2191", DOWN_ARROW = "\u2193", LIGHTNING_BOLT = "\u21AF", EFFORT_LOW = "\u25CB", EFFORT_MEDIUM = "\u25D0", EFFORT_HIGH = "\u25CF", EFFORT_XHIGH = "\u25C9", EFFORT_MAX = "\u25C8", PAUSE_ICON = "\u23F8", REFRESH_ARROW = "\u21BB", CHANNEL_ARROW = "\u2190", DIAMOND_OPEN = "\u25C7", DIAMOND_FILLED = "\u25C6", REFERENCE_MARK = "\u203B", BLOCKQUOTE_BAR = "\u258E", BRIDGE_SPINNER_FRAMES, BRIDGE_READY_INDICATOR = "\xB7\u2714\uFE0E\xB7", BRIDGE_FAILED_INDICATOR = "\xD7";
59838
+ var init_figures2 = __esm(() => {
59839
+ init_env();
59840
+ BLACK_CIRCLE = env4.platform === "darwin" ? "\u23FA" : "\u25CF";
59841
+ BRIDGE_SPINNER_FRAMES = [
59842
+ "\xB7|\xB7",
59843
+ "\xB7/\xB7",
59844
+ "\xB7\u2014\xB7",
59845
+ "\xB7\\\xB7"
59846
+ ];
59847
+ });
59848
+
59849
+ // src/types/permissions.ts
59850
+ var exports_permissions = {};
59851
+ __export(exports_permissions, {
59852
+ PERMISSION_MODES_CLI_CHOICES: () => PERMISSION_MODES_CLI_CHOICES,
59853
+ PERMISSION_MODES: () => PERMISSION_MODES,
59854
+ INTERNAL_PERMISSION_MODES: () => INTERNAL_PERMISSION_MODES,
59855
+ EXTERNAL_PERMISSION_MODES: () => EXTERNAL_PERMISSION_MODES
59856
+ });
59857
+ var EXTERNAL_PERMISSION_MODES, INTERNAL_PERMISSION_MODES, PERMISSION_MODES, PERMISSION_MODES_CLI_CHOICES;
59858
+ var init_permissions = __esm(() => {
59859
+ EXTERNAL_PERMISSION_MODES = [
59860
+ "acceptEdits",
59861
+ "auto",
59862
+ "bypassPermissions",
59863
+ "default",
59864
+ "dontAsk",
59865
+ "plan"
59866
+ ];
59867
+ INTERNAL_PERMISSION_MODES = [
59868
+ ...EXTERNAL_PERMISSION_MODES
59869
+ ];
59870
+ PERMISSION_MODES = INTERNAL_PERMISSION_MODES;
59871
+ PERMISSION_MODES_CLI_CHOICES = PERMISSION_MODES.map((mode) => mode === "default" ? "manual" : mode);
59872
+ });
59873
+
59874
+ // src/utils/permissions/PermissionMode.ts
59875
+ function isExternalPermissionMode(mode) {
59876
+ if (process.env.USER_TYPE !== "ant") {
59877
+ return true;
59878
+ }
59879
+ return mode !== "auto" && mode !== "bubble";
59880
+ }
59881
+ function getModeConfig(mode) {
59882
+ return PERMISSION_MODE_CONFIG[mode] ?? PERMISSION_MODE_CONFIG.default;
59883
+ }
59884
+ function toExternalPermissionMode(mode) {
59885
+ return getModeConfig(mode).external;
59886
+ }
59887
+ function normalizePermissionModeInput(str) {
59888
+ return str === PERMISSION_MODE_MANUAL_ALIAS ? "default" : str;
59889
+ }
59890
+ function permissionModeFromString(str) {
59891
+ const normalized = normalizePermissionModeInput(str);
59892
+ return PERMISSION_MODES.includes(normalized) ? normalized : "default";
59893
+ }
59894
+ function permissionModeTitle(mode) {
59895
+ return getModeConfig(mode).title;
59896
+ }
59897
+ function isDefaultMode(mode) {
59898
+ return mode === "default" || mode === undefined;
59899
+ }
59900
+ function permissionModeSymbol(mode) {
59901
+ return getModeConfig(mode).symbol;
59902
+ }
59903
+ function permissionModeIndicator(mode) {
59904
+ return getModeConfig(mode).indicator;
59905
+ }
59906
+ function getModeColor(mode) {
59907
+ return getModeConfig(mode).color;
59908
+ }
59909
+ var permissionModeSchema, externalPermissionModeSchema, PERMISSION_MODE_MANUAL_ALIAS = "manual", PERMISSION_MODE_CONFIG;
59910
+ var init_PermissionMode = __esm(() => {
59911
+ init_featureFlags();
59912
+ init_v4();
59913
+ init_figures2();
59914
+ init_permissions();
59915
+ permissionModeSchema = lazySchema(() => v4_default.enum(PERMISSION_MODES));
59916
+ externalPermissionModeSchema = lazySchema(() => v4_default.enum(EXTERNAL_PERMISSION_MODES));
59917
+ PERMISSION_MODE_CONFIG = {
59918
+ default: {
59919
+ title: "Manual",
59920
+ shortTitle: "Manual",
59921
+ symbol: PAUSE_ICON,
59922
+ color: "text",
59923
+ external: "default",
59924
+ indicator: "manual mode"
59925
+ },
59926
+ plan: {
59927
+ title: "Plan Mode",
59928
+ shortTitle: "Plan",
59929
+ symbol: PAUSE_ICON,
59930
+ color: "planMode",
59931
+ external: "plan",
59932
+ indicator: "plan mode"
59933
+ },
59934
+ acceptEdits: {
59935
+ title: "Accept edits",
59936
+ shortTitle: "Accept",
59937
+ symbol: "\u23F5\u23F5",
59938
+ color: "autoAccept",
59939
+ external: "acceptEdits",
59940
+ indicator: "accept edits"
59941
+ },
59942
+ bypassPermissions: {
59943
+ title: "Bypass Permissions",
59944
+ shortTitle: "Bypass",
59945
+ symbol: "\u23F5\u23F5",
59946
+ color: "error",
59947
+ external: "bypassPermissions",
59948
+ indicator: "bypass permissions"
59949
+ },
59950
+ dontAsk: {
59951
+ title: "Don't Ask",
59952
+ shortTitle: "DontAsk",
59953
+ symbol: "\u23F5\u23F5",
59954
+ color: "error",
59955
+ external: "dontAsk",
59956
+ indicator: "don't ask"
59957
+ },
59958
+ ...feature("TRANSCRIPT_CLASSIFIER") ? {
59959
+ auto: {
59960
+ title: "Auto mode",
59961
+ shortTitle: "Auto",
59962
+ symbol: "\u23F5\u23F5",
59963
+ color: "warning",
59964
+ external: "default",
59965
+ indicator: "auto mode"
59966
+ }
59967
+ } : {}
59968
+ };
59969
+ });
59970
+
59531
59971
  // src/utils/settings/types.ts
59532
59972
  function isMcpServerNameEntry(entry) {
59533
59973
  return "serverName" in entry && entry.serverName !== undefined;
@@ -60084,11 +60524,11 @@ function filterInvalidPermissionRules(data, filePath) {
60084
60524
  }
60085
60525
  const result = validatePermissionRule(rule);
60086
60526
  if (!result.valid) {
60087
- let message = `Invalid permission rule "${rule}" was skipped`;
60527
+ let message = `Invalid permission rule "${sanitizeForWarningText(rule)}" was skipped`;
60088
60528
  if (result.error)
60089
- message += `: ${result.error}`;
60529
+ message += `: ${sanitizeForWarningText(result.error)}`;
60090
60530
  if (result.suggestion)
60091
- message += `. ${result.suggestion}`;
60531
+ message += `. ${sanitizeForWarningText(result.suggestion)}`;
60092
60532
  warnings.push({
60093
60533
  file: filePath,
60094
60534
  path: `permissions.${key}`,
@@ -60106,11 +60546,26 @@ var init_validation2 = __esm(() => {
60106
60546
  init_slowOperations();
60107
60547
  init_stringUtils();
60108
60548
  init_permissionValidation();
60549
+ init_sanitizeWarningText();
60109
60550
  init_schemaOutput();
60110
60551
  init_types2();
60111
60552
  init_validationTips();
60112
60553
  });
60113
60554
 
60555
+ // src/utils/settings/policySourceSanitizer.ts
60556
+ function sanitizePolicySourceData(data, sourcePath) {
60557
+ return [
60558
+ ...filterInvalidPermissionRules(data, sourcePath),
60559
+ ...sanitizeSecurityAllowlists(data, sourcePath),
60560
+ ...sanitizeMarketplacePolicy(data, sourcePath)
60561
+ ];
60562
+ }
60563
+ var init_policySourceSanitizer = __esm(() => {
60564
+ init_marketplacePolicySanitizer();
60565
+ init_sanitizeAllowlists();
60566
+ init_validation2();
60567
+ });
60568
+
60114
60569
  // src/utils/settings/mdm/constants.ts
60115
60570
  import { homedir as homedir9, userInfo } from "os";
60116
60571
  import { join as join18 } from "path";
@@ -60259,17 +60714,18 @@ async function refreshMdmSettings() {
60259
60714
  return consumeRawReadResult(raw);
60260
60715
  }
60261
60716
  function parseCommandOutputAsSettings(stdout, sourcePath) {
60262
- const data = safeParseJSON(stdout, false);
60263
- if (!data || typeof data !== "object") {
60717
+ const parsed = safeParseJSON(stdout, false);
60718
+ if (!parsed || typeof parsed !== "object") {
60264
60719
  return { settings: {}, errors: [] };
60265
60720
  }
60266
- const ruleWarnings = filterInvalidPermissionRules(data, sourcePath);
60721
+ const data = clone(parsed);
60722
+ const sanitizeWarnings = sanitizePolicySourceData(data, sourcePath);
60267
60723
  const parseResult = SettingsSchema().safeParse(data);
60268
60724
  if (!parseResult.success) {
60269
60725
  const errors3 = formatZodError(parseResult.error, sourcePath);
60270
- return { settings: {}, errors: [...ruleWarnings, ...errors3] };
60726
+ return { settings: {}, errors: [...sanitizeWarnings, ...errors3] };
60271
60727
  }
60272
- return { settings: parseResult.data, errors: ruleWarnings };
60728
+ return { settings: parseResult.data, errors: sanitizeWarnings };
60273
60729
  }
60274
60730
  function parseRegQueryStdout(stdout, valueName = "Settings") {
60275
60731
  const lines = stdout.split(/\r?\n/);
@@ -60346,8 +60802,10 @@ var init_settings = __esm(() => {
60346
60802
  init_fileRead();
60347
60803
  init_fsOperations();
60348
60804
  init_json();
60805
+ init_slowOperations();
60349
60806
  init_startupProfiler();
60350
60807
  init_managedPath();
60808
+ init_policySourceSanitizer();
60351
60809
  init_types2();
60352
60810
  init_validation2();
60353
60811
  init_constants4();
@@ -60355,435 +60813,6 @@ var init_settings = __esm(() => {
60355
60813
  EMPTY_RESULT = Object.freeze({ settings: {}, errors: [] });
60356
60814
  });
60357
60815
 
60358
- // src/utils/plugins/marketplacePolicyValidation.ts
60359
- function stripTrailingDots(host) {
60360
- let end = host.length;
60361
- while (end > 0 && host[end - 1] === ".")
60362
- end--;
60363
- return host.slice(0, end);
60364
- }
60365
- function normalizeHostname(raw) {
60366
- const host = stripTrailingDots(raw.replace(/[\t\n\r]/g, "").toLowerCase());
60367
- if (host === "" || INVALID_HOST_CHARS.test(host))
60368
- return host;
60369
- try {
60370
- const parsed = new URL(`https://${host}`);
60371
- if (parsed.username !== "" || parsed.password !== "" || parsed.port !== "" || parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "")
60372
- return host;
60373
- return stripTrailingDots(parsed.hostname);
60374
- } catch {
60375
- return host;
60376
- }
60377
- }
60378
- function normalizeHostForComparison(raw) {
60379
- const cached2 = hostNormalizeCache.get(raw);
60380
- if (cached2 !== undefined)
60381
- return cached2;
60382
- let host = normalizeHostname(raw);
60383
- while (host.startsWith("www."))
60384
- host = host.slice(4);
60385
- if (hostNormalizeCache.size >= HOST_NORMALIZE_CACHE_LIMIT) {
60386
- hostNormalizeCache.clear();
60387
- }
60388
- hostNormalizeCache.set(raw, host);
60389
- return host;
60390
- }
60391
- function hostMatches(raw, expected) {
60392
- return normalizeHostForComparison(raw) === expected;
60393
- }
60394
- function isGitHubHost(raw) {
60395
- return hostMatches(raw, GITHUB_HOST);
60396
- }
60397
- function isGitHubOrSshGitHubHost(raw) {
60398
- return isGitHubHost(raw) || normalizeHostname(raw) === GITHUB_SSH_HOST;
60399
- }
60400
- function hasSuspiciousHostChars(value) {
60401
- return /[%\x00-\x1f\x7f-\u{10FFFF}]/u.test(value);
60402
- }
60403
- function hasBackslashSmuggling(raw) {
60404
- const url3 = raw.replace(/^[\x00-\x20]+/, "");
60405
- const schemeEnd = url3.indexOf("://");
60406
- if (schemeEnd === -1)
60407
- return false;
60408
- let rest = url3.slice(schemeEnd + 3);
60409
- const scheme = url3.slice(0, schemeEnd).toLowerCase();
60410
- if (URL_LIKE_PROTOCOLS.has(scheme)) {
60411
- const slashes = rest.match(/^[/\\]+/)?.[0] ?? "";
60412
- if (slashes.includes("\\"))
60413
- return true;
60414
- rest = rest.slice(slashes.length);
60415
- }
60416
- const pathStart = rest.search(/[/?#]/);
60417
- return (pathStart === -1 ? rest : rest.slice(0, pathStart)).includes("\\");
60418
- }
60419
- function isSuspiciousGitUrl(url3) {
60420
- if (url3.includes("://")) {
60421
- if (hasBackslashSmuggling(url3))
60422
- return true;
60423
- try {
60424
- const parsed = new URL(url3);
60425
- if (parsed.protocol === "http:" || parsed.protocol === "https:")
60426
- return false;
60427
- return hasSuspiciousHostChars(parsed.hostname);
60428
- } catch {
60429
- return true;
60430
- }
60431
- }
60432
- const colonIndex = url3.indexOf(":");
60433
- const atIndex = url3.indexOf("@");
60434
- if (colonIndex >= 0 && atIndex > colonIndex)
60435
- return true;
60436
- const host = url3.match(/^(?:[^@]+@)?([^:]+):/)?.[1];
60437
- return host ? hasSuspiciousHostChars(host) : false;
60438
- }
60439
- function normalizeGithubAwareHost(raw) {
60440
- const host = normalizeHostname(raw);
60441
- return isGitHubHost(host) ? GITHUB_HOST : host;
60442
- }
60443
- function normalizeGithubHostForUrl(raw) {
60444
- const host = normalizeGithubAwareHost(raw);
60445
- return host === GITHUB_SSH_HOST ? GITHUB_HOST : host;
60446
- }
60447
- function normalizePathSegments(path9) {
60448
- const segments = [];
60449
- for (const segment of path9.split("/")) {
60450
- if (segment === ".")
60451
- continue;
60452
- if (segment === "..") {
60453
- segments.pop();
60454
- continue;
60455
- }
60456
- segments.push(segment);
60457
- }
60458
- return segments.filter((segment) => segment !== "").join("/");
60459
- }
60460
- function stripDotGitSuffix(path9) {
60461
- let length = path9.length;
60462
- for (;; ) {
60463
- let end = length;
60464
- while (end > 0 && path9.charCodeAt(end - 1) === 47)
60465
- end--;
60466
- if (end >= 4 && path9.startsWith(".git", end - 4))
60467
- end -= 4;
60468
- if (end === length)
60469
- return length === path9.length ? path9 : path9.slice(0, length);
60470
- length = end;
60471
- }
60472
- }
60473
- function normalizeUrlForComparison(raw, options) {
60474
- if (raw.includes("://")) {
60475
- try {
60476
- const parsed = new URL(raw);
60477
- parsed.hostname = normalizeGithubHostForUrl(parsed.hostname);
60478
- parsed.username = "";
60479
- parsed.password = "";
60480
- parsed.search = "";
60481
- parsed.hash = "";
60482
- try {
60483
- parsed.pathname = decodeURIComponent(parsed.pathname);
60484
- } catch {}
60485
- const normalized = normalizePathSegments(parsed.pathname);
60486
- parsed.pathname = options?.stripDotGit ? stripDotGitSuffix(normalized) : normalized;
60487
- return parsed.toString();
60488
- } catch {
60489
- return raw;
60490
- }
60491
- }
60492
- const scpLike = raw.match(/^[^@]+@([^:]+)(:.*)$/s);
60493
- return scpLike ? `${normalizeGithubHostForUrl(scpLike[1] ?? "")}${scpLike[2]}` : raw;
60494
- }
60495
- function parseScpLikeGitUrl(raw) {
60496
- const match = SCP_LIKE_GIT_URL_PATTERN.exec(raw);
60497
- return match ? { user: match[1], host: match[2], path: match[3] } : null;
60498
- }
60499
- function normalizeGitUrl(raw) {
60500
- if (isSuspiciousGitUrl(raw))
60501
- return raw;
60502
- if (raw.includes("://")) {
60503
- try {
60504
- const parsed = new URL(raw);
60505
- parsed.hostname = normalizeGithubAwareHost(parsed.hostname);
60506
- if (CREDENTIAL_STRIP_PROTOCOLS.has(parsed.protocol) || isGitHubHost(parsed.hostname)) {
60507
- parsed.username = "";
60508
- parsed.password = "";
60509
- }
60510
- return parsed.toString();
60511
- } catch {
60512
- return raw;
60513
- }
60514
- }
60515
- const scpLike = parseScpLikeGitUrl(raw);
60516
- if (!scpLike)
60517
- return raw;
60518
- const host = scpLike.host.toLowerCase().replace(/\.+$/, "");
60519
- return isGitHubHost(host) ? `${GITHUB_HOST}:${scpLike.path}` : `${scpLike.user}@${host}:${scpLike.path}`;
60520
- }
60521
- function gitUrlHasWildcard(url3) {
60522
- if (url3.includes("://")) {
60523
- if (hasBackslashSmuggling(url3))
60524
- return false;
60525
- let hostname3;
60526
- try {
60527
- hostname3 = new URL(url3).hostname;
60528
- } catch {
60529
- return false;
60530
- }
60531
- if (!isGitHubOrSshGitHubHost(hostname3))
60532
- return false;
60533
- if (normalizeUrlForComparison(url3, { stripDotGit: true }).includes("*"))
60534
- return true;
60535
- const normalized = normalizeGitUrl(url3);
60536
- try {
60537
- const parsed = new URL(normalized);
60538
- return parsed.hostname.includes("*") || parsed.pathname.includes("*");
60539
- } catch {
60540
- return normalized.includes("*");
60541
- }
60542
- }
60543
- const match = url3.match(SCP_LIKE_HOST_PATTERN);
60544
- const host = match?.[1];
60545
- const path9 = match?.[2];
60546
- if (!host || path9 === undefined || !isGitHubOrSshGitHubHost(host))
60547
- return false;
60548
- let decoded = path9;
60549
- try {
60550
- decoded = decodeURIComponent(path9);
60551
- } catch {}
60552
- return decoded.includes("*");
60553
- }
60554
- function regexCompiles(pattern) {
60555
- try {
60556
- new RegExp(pattern);
60557
- return true;
60558
- } catch {
60559
- return false;
60560
- }
60561
- }
60562
- function isValidWildcardOwner(owner) {
60563
- return OWNER_CHARS_PATTERN.test(owner) && !owner.startsWith("-") && owner !== "." && owner !== "..";
60564
- }
60565
- function parseGitHubOwnerWildcard(repo) {
60566
- if (!repo.endsWith("/*"))
60567
- return null;
60568
- const owner = repo.slice(0, -2);
60569
- return isValidWildcardOwner(owner) ? owner : null;
60570
- }
60571
- function checkMarketplaceEntryEnforceability(entry) {
60572
- const pattern = entry.source === "hostPattern" ? entry.hostPattern : entry.source === "pathPattern" ? entry.pathPattern : null;
60573
- if (pattern !== null && !regexCompiles(pattern))
60574
- return `${entry.source}: regex does not compile; the entry cannot be enforced`;
60575
- if (entry.source === "github" && entry.repo.includes("*") && parseGitHubOwnerWildcard(entry.repo) === null)
60576
- return 'github: an owner wildcard must be exactly "<owner>/*"; the entry cannot be enforced';
60577
- if (entry.source === "git" && gitUrlHasWildcard(entry.url))
60578
- return 'git: wildcards are only supported in github-form entries, as "<owner>/*"; the entry cannot be enforced';
60579
- if ((entry.source === "github" || entry.source === "git") && entry.ref !== undefined && entry.ref.includes("*"))
60580
- return `${entry.source}: ref contains "*", which git does not allow in ref names; the entry cannot be enforced`;
60581
- return null;
60582
- }
60583
- var GITHUB_HOST = "github.com", GITHUB_SSH_HOST = "ssh.github.com", INVALID_HOST_CHARS, URL_LIKE_PROTOCOLS, CREDENTIAL_STRIP_PROTOCOLS, OWNER_CHARS_PATTERN, SCP_LIKE_GIT_URL_PATTERN, SCP_LIKE_HOST_PATTERN, HOST_NORMALIZE_CACHE_LIMIT = 50, hostNormalizeCache;
60584
- var init_marketplacePolicyValidation = __esm(() => {
60585
- INVALID_HOST_CHARS = /[:/\\?#@\s]/;
60586
- URL_LIKE_PROTOCOLS = new Set(["http", "https", "ws", "wss", "ftp"]);
60587
- CREDENTIAL_STRIP_PROTOCOLS = new Set([
60588
- "http:",
60589
- "https:",
60590
- "git:",
60591
- "git+http:",
60592
- "git+https:"
60593
- ]);
60594
- OWNER_CHARS_PATTERN = /^[A-Za-z0-9._-]+$/;
60595
- SCP_LIKE_GIT_URL_PATTERN = /^([^@:/[\]]+)@([^@:/[\]]+):(.*)$/s;
60596
- SCP_LIKE_HOST_PATTERN = /^(?:[^@]+@)?([^@:/]+):(.*)$/s;
60597
- hostNormalizeCache = new Map;
60598
- });
60599
-
60600
- // src/utils/settings/marketplacePolicySanitizer.ts
60601
- function firstIssueDetail(issues) {
60602
- for (const issue2 of issues) {
60603
- const prefix = issue2.path.length > 0 ? `${issue2.path.map(String).join(".")}: ` : "";
60604
- if (issue2.code === "invalid_union") {
60605
- for (const branch of issue2.errors) {
60606
- const detail = firstIssueDetail(branch);
60607
- if (detail !== null)
60608
- return `${prefix}${detail}`;
60609
- }
60610
- const noted = issue2;
60611
- if (typeof noted.note === "string" && noted.note !== "")
60612
- return `${prefix}${noted.note}`;
60613
- }
60614
- if (issue2.message !== "")
60615
- return `${prefix}${issue2.message}`;
60616
- }
60617
- return null;
60618
- }
60619
- function sanitizeMarketplacePolicy(data, filePath) {
60620
- if (!data || typeof data !== "object")
60621
- return [];
60622
- const obj = data;
60623
- const warnings = [];
60624
- for (const key of POLICY_KEYS) {
60625
- if (!(key in obj))
60626
- continue;
60627
- const raw = obj[key];
60628
- if (raw === null) {
60629
- delete obj[key];
60630
- continue;
60631
- }
60632
- if (!Array.isArray(raw)) {
60633
- if (key === "strictKnownMarketplaces") {
60634
- obj[key] = [];
60635
- } else {
60636
- delete obj[key];
60637
- }
60638
- warnings.push({
60639
- file: filePath,
60640
- path: key,
60641
- message: key === "strictKnownMarketplaces" ? STRICT_PRESENT_INVALID_MESSAGE : BLOCKED_PRESENT_INVALID_MESSAGE,
60642
- invalidValue: raw
60643
- });
60644
- continue;
60645
- }
60646
- const kept = [];
60647
- for (const [index2, entry] of raw.entries()) {
60648
- const parsed = MarketplaceSourceSchema().safeParse(entry);
60649
- if (!parsed.success) {
60650
- warnings.push({
60651
- file: filePath,
60652
- path: `${key}[${index2}]`,
60653
- message: `Invalid entry was ignored: ${firstIssueDetail(parsed.error.issues) ?? "failed validation"}`,
60654
- invalidValue: entry
60655
- });
60656
- continue;
60657
- }
60658
- const problem = checkMarketplaceEntryEnforceability(parsed.data);
60659
- if (problem === null) {
60660
- kept.push(parsed.data);
60661
- continue;
60662
- }
60663
- if (key === "blockedMarketplaces") {
60664
- kept.push(parsed.data);
60665
- warnings.push({
60666
- file: filePath,
60667
- path: `${key}[${index2}]`,
60668
- message: `Unenforceable entry was kept: ${problem}; it can never match a marketplace source, but marketplace restrictions stay active`,
60669
- invalidValue: entry
60670
- });
60671
- } else {
60672
- warnings.push({
60673
- file: filePath,
60674
- path: `${key}[${index2}]`,
60675
- message: `Invalid entry was ignored: ${problem}`,
60676
- invalidValue: entry
60677
- });
60678
- }
60679
- }
60680
- obj[key] = kept;
60681
- }
60682
- return warnings;
60683
- }
60684
- var POLICY_KEYS, STRICT_PRESENT_INVALID_MESSAGE = '"strictKnownMarketplaces" was present but invalid; enforcing an empty allowlist (no marketplaces admitted) until it is fixed.', BLOCKED_PRESENT_INVALID_MESSAGE = '"blockedMarketplaces" was present but invalid and was dropped; its entries cannot be enforced until it is fixed.';
60685
- var init_marketplacePolicySanitizer = __esm(() => {
60686
- init_marketplacePolicyValidation();
60687
- init_schemas3();
60688
- POLICY_KEYS = ["strictKnownMarketplaces", "blockedMarketplaces"];
60689
- });
60690
-
60691
- // src/utils/settings/sanitizeAllowlists.ts
60692
- function issueDetail(error49) {
60693
- const issue2 = error49.issues[0];
60694
- if (issue2 === undefined)
60695
- return "failed validation";
60696
- return issue2.path.length > 0 ? `${issue2.path.join(".")}: ${issue2.message}` : issue2.message;
60697
- }
60698
- function validateAllowlistEntry(key, entry) {
60699
- if (key === "allowedChannelPlugins") {
60700
- if (typeof entry === "string") {
60701
- const at = entry.indexOf("@");
60702
- const plugin = entry.slice(0, at);
60703
- const marketplace = entry.slice(at + 1);
60704
- if (at > 0 && marketplace.length > 0) {
60705
- return {
60706
- ok: true,
60707
- value: { marketplace, plugin },
60708
- notice: `"allowedChannelPlugins" entry "${entry}" was accepted; prefer the documented object form {"plugin": "${plugin}", "marketplace": "${marketplace}"}.`
60709
- };
60710
- }
60711
- }
60712
- const parsed2 = CHANNEL_PLUGIN_ENTRY.safeParse(entry);
60713
- return parsed2.success ? { ok: true, value: parsed2.data } : { ok: false, detail: issueDetail(parsed2.error) };
60714
- }
60715
- const parsed = STRING_ENTRY.safeParse(entry);
60716
- return parsed.success ? { ok: true, value: parsed.data } : { ok: false, detail: issueDetail(parsed.error) };
60717
- }
60718
- function sanitizeSecurityAllowlists(data, filePath) {
60719
- if (!data || typeof data !== "object")
60720
- return [];
60721
- const obj = data;
60722
- const warnings = [];
60723
- for (const { key, emptyReason } of ALLOWLIST_SPECS) {
60724
- if (!(key in obj))
60725
- continue;
60726
- const raw = obj[key];
60727
- if (!Array.isArray(raw)) {
60728
- obj[key] = [];
60729
- warnings.push({
60730
- file: filePath,
60731
- path: key,
60732
- message: `"${key}" was present but invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`,
60733
- invalidValue: raw
60734
- });
60735
- continue;
60736
- }
60737
- const valid = [];
60738
- for (const [index2, entry] of raw.entries()) {
60739
- const result = validateAllowlistEntry(key, entry);
60740
- if (result.ok) {
60741
- valid.push(result.value);
60742
- if (result.notice !== undefined) {
60743
- warnings.push({
60744
- file: filePath,
60745
- path: `${key}[${index2}]`,
60746
- message: result.notice
60747
- });
60748
- }
60749
- } else {
60750
- warnings.push({
60751
- file: filePath,
60752
- path: `${key}[${index2}]`,
60753
- message: `Invalid entry was ignored: ${result.detail}`,
60754
- invalidValue: entry
60755
- });
60756
- }
60757
- }
60758
- if (raw.length > 0 && valid.length === 0) {
60759
- warnings.push({
60760
- file: filePath,
60761
- path: key,
60762
- message: `Every entry of "${key}" was invalid; enforcing an empty allowlist (${emptyReason}) until it is fixed.`
60763
- });
60764
- }
60765
- obj[key] = valid;
60766
- }
60767
- return warnings;
60768
- }
60769
- var STRING_ENTRY, CHANNEL_PLUGIN_ENTRY, ALLOWLIST_SPECS;
60770
- var init_sanitizeAllowlists = __esm(() => {
60771
- init_v4();
60772
- STRING_ENTRY = exports_external.string();
60773
- CHANNEL_PLUGIN_ENTRY = exports_external.object({
60774
- marketplace: exports_external.string(),
60775
- plugin: exports_external.string()
60776
- });
60777
- ALLOWLIST_SPECS = [
60778
- { key: "allowedHttpHookUrls", emptyReason: "no HTTP hooks may run" },
60779
- {
60780
- key: "httpHookAllowedEnvVars",
60781
- emptyReason: "no environment variables may be interpolated into HTTP hook headers"
60782
- },
60783
- { key: "allowedChannelPlugins", emptyReason: "no channel plugins admitted" }
60784
- ];
60785
- });
60786
-
60787
60816
  // src/utils/settings/settings.ts
60788
60817
  var exports_settings = {};
60789
60818
  __export(exports_settings, {
@@ -60918,30 +60947,20 @@ function parseSettingsFileUncached(path9) {
60918
60947
  if (content.trim() === "") {
60919
60948
  return { settings: {}, errors: [] };
60920
60949
  }
60921
- const data = safeParseJSON(content, false);
60922
- const ruleWarnings = filterInvalidPermissionRules(data, path9);
60923
- const allowlistWarnings = sanitizeSecurityAllowlists(data, path9);
60924
- const marketplacePolicyWarnings = sanitizeMarketplacePolicy(data, path9);
60950
+ const parsed = safeParseJSON(content, false);
60951
+ const data = parsed && typeof parsed === "object" ? clone(parsed) : parsed;
60952
+ const sanitizeWarnings = sanitizePolicySourceData(data, path9);
60925
60953
  const result = SettingsSchema().safeParse(data);
60926
60954
  if (!result.success) {
60927
60955
  const errors3 = formatZodError(result.error, path9);
60928
60956
  return {
60929
60957
  settings: null,
60930
- errors: [
60931
- ...ruleWarnings,
60932
- ...allowlistWarnings,
60933
- ...marketplacePolicyWarnings,
60934
- ...errors3
60935
- ]
60958
+ errors: [...sanitizeWarnings, ...errors3]
60936
60959
  };
60937
60960
  }
60938
60961
  return {
60939
60962
  settings: result.data,
60940
- errors: [
60941
- ...ruleWarnings,
60942
- ...allowlistWarnings,
60943
- ...marketplacePolicyWarnings
60944
- ]
60963
+ errors: sanitizeWarnings
60945
60964
  };
60946
60965
  } catch (error49) {
60947
60966
  handleFileSystemError(error49, path9);
@@ -61004,8 +61023,13 @@ function getSettingsForSource(source) {
61004
61023
  }
61005
61024
  function getSettingsForSourceUncached(source) {
61006
61025
  if (source === "policySettings") {
61007
- const remoteSettings = getRemoteManagedSettingsSyncFromCache();
61008
- if (remoteSettings && Object.keys(remoteSettings).length > 0) {
61026
+ const cachedRemote = getRemoteManagedSettingsSyncFromCache();
61027
+ if (cachedRemote && Object.keys(cachedRemote).length > 0) {
61028
+ const remoteSettings = clone(cachedRemote);
61029
+ const remoteWarnings = sanitizePolicySourceData(remoteSettings, "remote managed settings");
61030
+ for (const warning of remoteWarnings) {
61031
+ logForDebugging(`[settings] ${warning.file}: ${warning.path}: ${warning.message}`);
61032
+ }
61009
61033
  return remoteSettings;
61010
61034
  }
61011
61035
  const mdmResult = getMdmSettings();
@@ -61202,13 +61226,16 @@ function loadSettingsFromDisk() {
61202
61226
  if (source === "policySettings") {
61203
61227
  let policySettings = null;
61204
61228
  const policyErrors = [];
61205
- const remoteSettings = getRemoteManagedSettingsSyncFromCache();
61206
- if (remoteSettings && Object.keys(remoteSettings).length > 0) {
61229
+ const cachedRemote = getRemoteManagedSettingsSyncFromCache();
61230
+ if (cachedRemote && Object.keys(cachedRemote).length > 0) {
61231
+ const remoteSettings = clone(cachedRemote);
61232
+ const remoteWarnings = sanitizePolicySourceData(remoteSettings, "remote managed settings");
61207
61233
  const result = SettingsSchema().safeParse(remoteSettings);
61208
61234
  if (result.success) {
61209
61235
  policySettings = result.data;
61236
+ policyErrors.push(...remoteWarnings);
61210
61237
  } else {
61211
- policyErrors.push(...formatZodError(result.error, "remote managed settings"));
61238
+ policyErrors.push(...remoteWarnings, ...formatZodError(result.error, "remote managed settings"));
61212
61239
  }
61213
61240
  }
61214
61241
  if (!policySettings) {
@@ -61568,8 +61595,7 @@ var init_settings2 = __esm(() => {
61568
61595
  init_managedPath();
61569
61596
  init_settings();
61570
61597
  init_settingsCache();
61571
- init_marketplacePolicySanitizer();
61572
- init_sanitizeAllowlists();
61598
+ init_policySourceSanitizer();
61573
61599
  init_types2();
61574
61600
  init_validation2();
61575
61601
  MAX_SETTINGS_FILE_BYTES = 2 * 1024 * 1024;
@@ -193323,6 +193349,8 @@ function resetGetMemoryFilesCache(reason = "session_start") {
193323
193349
  hasLoggedAgentsMdMode = false;
193324
193350
  hasLoggedAgentsMdLoad = false;
193325
193351
  agentsMdNoticeRoot = undefined;
193352
+ lastAgentsMdNotice = undefined;
193353
+ lastAgentsMdDeprecation = undefined;
193326
193354
  clearMemoryFileCaches();
193327
193355
  }
193328
193356
  function getLargeMemoryFiles(files, threshold = MIN_MEMORY_CHARACTER_COUNT) {
@@ -195005,6 +195033,23 @@ function getProjectDirsUpToHome(subdir, cwd2) {
195005
195033
  }
195006
195034
  return dirs;
195007
195035
  }
195036
+ function addWorktreeMainRepoFallback(projectDirs, subdir, cwd2) {
195037
+ const gitRoot = findGitRoot(cwd2);
195038
+ const canonicalRoot = findCanonicalGitRoot(cwd2);
195039
+ if (!gitRoot || !canonicalRoot || canonicalRoot === gitRoot) {
195040
+ return projectDirs;
195041
+ }
195042
+ const worktreeSubdir = normalizePathForComparison(join34(gitRoot, ".claude", subdir));
195043
+ const worktreeHasSubdir = projectDirs.some((dir) => normalizePathForComparison(dir) === worktreeSubdir);
195044
+ if (worktreeHasSubdir) {
195045
+ return projectDirs;
195046
+ }
195047
+ const mainClaudeSubdir = join34(canonicalRoot, ".claude", subdir);
195048
+ if (projectDirs.includes(mainClaudeSubdir)) {
195049
+ return projectDirs;
195050
+ }
195051
+ return [...projectDirs, mainClaudeSubdir];
195052
+ }
195008
195053
  async function findMarkdownFilesNative(dir, signal) {
195009
195054
  const files = [];
195010
195055
  const visitedDirs = new Set;
@@ -195122,19 +195167,7 @@ var init_markdownConfigLoader = __esm(() => {
195122
195167
  const searchStartTime = Date.now();
195123
195168
  const userDir = join34(getClaudeConfigHomeDir(), subdir);
195124
195169
  const managedDir = join34(getManagedFilePath(), ".claude", subdir);
195125
- const projectDirs = getProjectDirsUpToHome(subdir, cwd2);
195126
- const gitRoot = findGitRoot(cwd2);
195127
- const canonicalRoot = findCanonicalGitRoot(cwd2);
195128
- if (gitRoot && canonicalRoot && canonicalRoot !== gitRoot) {
195129
- const worktreeSubdir = normalizePathForComparison(join34(gitRoot, ".claude", subdir));
195130
- const worktreeHasSubdir = projectDirs.some((dir) => normalizePathForComparison(dir) === worktreeSubdir);
195131
- if (!worktreeHasSubdir) {
195132
- const mainClaudeSubdir = join34(canonicalRoot, ".claude", subdir);
195133
- if (!projectDirs.includes(mainClaudeSubdir)) {
195134
- projectDirs.push(mainClaudeSubdir);
195135
- }
195136
- }
195137
- }
195170
+ const projectDirs = addWorktreeMainRepoFallback(getProjectDirsUpToHome(subdir, cwd2), subdir, cwd2);
195138
195171
  const [managedFiles, userFiles, projectFilesNested] = await Promise.all([
195139
195172
  loadMarkdownFiles(managedDir).then((_2) => _2.map((file2) => ({
195140
195173
  ...file2,
@@ -612907,7 +612940,7 @@ var init_loadSkillsDir = __esm(() => {
612907
612940
  getSkillDirCommands = memoize_default(async (cwd2) => {
612908
612941
  const userSkillsDir = join117(getClaudeConfigHomeDir(), "skills");
612909
612942
  const managedSkillsDir = join117(getManagedFilePath(), ".claude", "skills");
612910
- const projectSkillsDirs = getProjectDirsUpToHome("skills", cwd2);
612943
+ const projectSkillsDirs = addWorktreeMainRepoFallback(getProjectDirsUpToHome("skills", cwd2), "skills", cwd2);
612911
612944
  logForDebugging(`Loading skills from: managed=${managedSkillsDir}, user=${userSkillsDir}, project=[${projectSkillsDirs.join(", ")}]`);
612912
612945
  const additionalDirs = getAdditionalDirectoriesForClaudeMd();
612913
612946
  const skillsLocked = isRestrictedToPluginOnly("skills");
@@ -738754,7 +738787,6 @@ __export(exports_worktree, {
738754
738787
  createTmuxSessionForWorktree: () => createTmuxSessionForWorktree,
738755
738788
  createAgentWorktree: () => createAgentWorktree,
738756
738789
  copyWorktreeIncludeFiles: () => copyWorktreeIncludeFiles,
738757
- copyUntrackedProjectSkills: () => copyUntrackedProjectSkills,
738758
738790
  cleanupWorktree: () => cleanupWorktree,
738759
738791
  cleanupStaleAgentWorktrees: () => cleanupStaleAgentWorktrees
738760
738792
  });
@@ -739001,33 +739033,6 @@ async function copyWorktreeIncludeFiles(repoRoot, worktreePath) {
739001
739033
  }
739002
739034
  return copied;
739003
739035
  }
739004
- async function copyUntrackedProjectSkills(repoRoot, worktreePath) {
739005
- const skillsPathspec = ".claude/skills";
739006
- const listed = await execFileNoThrowWithCwd(gitExe(), ["ls-files", "--others", "--exclude-standard", "--", skillsPathspec], { cwd: repoRoot });
739007
- if (listed.code !== 0 || !listed.stdout.trim()) {
739008
- return [];
739009
- }
739010
- const copied = [];
739011
- for (const relativePath2 of listed.stdout.trim().split(`
739012
- `).filter(Boolean)) {
739013
- if (containsPathTraversal(relativePath2)) {
739014
- continue;
739015
- }
739016
- const srcPath = join167(repoRoot, relativePath2);
739017
- const destPath = join167(worktreePath, relativePath2);
739018
- try {
739019
- await mkdirRecursive(dirname74(destPath));
739020
- await copyFile11(srcPath, destPath);
739021
- copied.push(relativePath2);
739022
- } catch (e4) {
739023
- logForDebugging(`Failed to copy untracked skill ${relativePath2} to worktree: ${errorMessage(e4)}`, { level: "warn" });
739024
- }
739025
- }
739026
- if (copied.length > 0) {
739027
- logForDebugging(`Copied ${copied.length} untracked project skill file(s) into worktree: ${copied.join(", ")}`);
739028
- }
739029
- return copied;
739030
- }
739031
739036
  async function performPostCreationSetup(repoRoot, worktreePath) {
739032
739037
  const localSettingsRelativePath = getRelativeSettingsFilePathForSource("localSettings");
739033
739038
  const sourceSettingsLocal = join167(repoRoot, localSettingsRelativePath);
@@ -739075,7 +739080,6 @@ async function performPostCreationSetup(repoRoot, worktreePath) {
739075
739080
  await symlinkDirectories(repoRoot, worktreePath, dirsToSymlink);
739076
739081
  }
739077
739082
  await copyWorktreeIncludeFiles(repoRoot, worktreePath);
739078
- await copyUntrackedProjectSkills(repoRoot, worktreePath);
739079
739083
  if (feature("COMMIT_ATTRIBUTION")) {
739080
739084
  const worktreeHooksDir = hooksPath === huskyPath ? join167(worktreePath, ".husky") : undefined;
739081
739085
  Promise.resolve().then(() => (init_postCommitAttribution(), exports_postCommitAttribution)).then((m5) => m5.installPrepareCommitMsgHook(worktreePath, worktreeHooksDir).catch((error52) => {
@@ -826546,13 +826550,13 @@ function canBatchWith(head, next2) {
826546
826550
  return next2 !== undefined && next2.mode === "prompt" && next2.workload === head.workload && next2.isMeta === head.isMeta;
826547
826551
  }
826548
826552
  async function runHeadless(inputPrompt, getAppState, setAppState, commands7, tools, sdkMcpConfigs, agents2, options) {
826553
+ registerHeadlessCostSaveOnExit();
826549
826554
  if (process.env.USER_TYPE === "ant" && isEnvTruthy(process.env.CLAUDE_CODE_EXIT_AFTER_FIRST_RENDER)) {
826550
826555
  process.stderr.write(`
826551
826556
  Startup time: ${Math.round(process.uptime() * 1000)}ms
826552
826557
  `);
826553
826558
  process.exit(0);
826554
826559
  }
826555
- registerHeadlessCostSaveOnExit();
826556
826560
  if (typeof inputPrompt === "string" && shouldTriggerUltracodeFromPrompt(inputPrompt)) {
826557
826561
  enableUltracodeForSession();
826558
826562
  logEvent2("tengu_ultracode_keyword_triggered", {
@@ -836920,7 +836924,7 @@ var _FEATURE_ALLOWLIST = new Set([
836920
836924
  var feature2 = (name3) => _FEATURE_ALLOWLIST.has(name3);
836921
836925
  if (typeof globalThis.MACRO === "undefined") {
836922
836926
  globalThis.MACRO = {
836923
- VERSION: "2.1.276",
836927
+ VERSION: "2.1.278",
836924
836928
  BINARY_NAME: "occ",
836925
836929
  BUILD_TIME: new Date().toISOString(),
836926
836930
  FEEDBACK_CHANNEL: "",