#!/usr/bin/env node

// src/providers/path-resolver.ts
import { accessSync, constants, statSync } from "fs";
import { delimiter, join } from "path";
function isExecutableFile(path) {
  try {
    const stat = statSync(path);
    if (!stat.isFile()) return false;
    accessSync(path, constants.X_OK);
    return true;
  } catch {
    return false;
  }
}
function unique(paths) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const path of paths) {
    if (!path || seen.has(path)) continue;
    seen.add(path);
    result.push(path);
  }
  return result;
}
function findExecutableCandidates(name, env) {
  const pathEntries = (env.PATH ?? "").split(delimiter).filter(Boolean);
  return unique(pathEntries.map((entry) => join(entry, name))).filter(isExecutableFile);
}
function resolveExecutable(name, env, envVarName, errorMessage2) {
  const custom = env[envVarName]?.trim();
  if (custom) {
    if (custom.includes("/") && !isExecutableFile(custom)) {
      throw new Error(`${envVarName} is not an executable file: ${custom}`);
    }
    return custom;
  }
  const [first] = findExecutableCandidates(name, env);
  if (first) return first;
  throw new Error(errorMessage2);
}

// src/providers/claude.ts
function filterClaudeEnvVars(env) {
  const filtered = {};
  for (const [key, value] of Object.entries(env)) {
    if (!key.startsWith("CLAUDECODE")) {
      filtered[key] = value;
    }
  }
  return filtered;
}
function buildClaudeArgs(options) {
  const args = [];
  if (options.outputFormat) args.push("--output-format", options.outputFormat);
  if (options.inputFormat) args.push("--input-format", options.inputFormat);
  args.push("--permission-prompt-tool", options.permissionPromptTool ?? "stdio");
  args.push("--permission-mode", options.permissionMode ?? "default");
  if (options.verbose) args.push("--verbose");
  if (options.resumeSessionId) args.push("--resume", options.resumeSessionId);
  if (options.forkSession !== false) args.push("--fork-session");
  if (options.includePartialMessages) args.push("--include-partial-messages");
  return args;
}
function resolveClaudePtyCommand(env) {
  return resolveExecutable(
    "claude",
    env,
    "CLAUDE_BIN",
    "claude not found in PATH. Set CLAUDE_BIN or install Claude Code: https://claude.ai/download"
  );
}
function resolveClaudeJsonCommand(env) {
  return env.CLAUDE_BIN || "claude";
}
var CLAUDE_HOOK_EVENTS = [
  "PreToolUse",
  "PostToolUse",
  "PostToolUseFailure",
  "Stop",
  "PermissionRequest",
  "UserPromptSubmit",
  "SessionStart"
];
var PERMISSION_HOOK_TIMEOUT_SECONDS = 365 * 24 * 60 * 60;
var HOOK_FORWARDER_SCRIPT = `
let body = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => { body += chunk; });
process.stdin.on("end", async () => {
  let payload = {};
  try { payload = body ? JSON.parse(body) : {}; } catch { payload = { raw: body }; }
  const request = {
    sessionId: process.env.DEV_ANYWHERE_SESSION_ID,
    provider: process.env.DEV_ANYWHERE_PROVIDER,
    marker: process.env.DEV_ANYWHERE_HOOK_MARKER,
    event: process.env.DEV_ANYWHERE_HOOK_EVENT || payload.hook_event_name || payload.event_name || "unknown",
    requestId: payload.request_id || payload.requestId,
    payload,
  };
  try {
    const response = await fetch(process.env.DEV_ANYWHERE_HOOK_URL, {
      method: "POST",
      headers: {
        "content-type": "application/json",
        authorization: "Bearer " + process.env.DEV_ANYWHERE_HOOK_TOKEN,
      },
      body: JSON.stringify(request),
    });
    process.stdout.write(await response.text());
  } catch {
    process.exit(0);
  }
});
`.trim();
function shellQuote(value) {
  return `'${value.replace(/'/g, "'\\''")}'`;
}
function buildHookForwardCommand(event) {
  return `DEV_ANYWHERE_HOOK_EVENT=${shellQuote(event)} node -e ${shellQuote(HOOK_FORWARDER_SCRIPT)}`;
}
function buildClaudeHookSettings(options) {
  const includePermissionRequest = options?.includePermissionRequest ?? true;
  const hooks = {};
  for (const event of CLAUDE_HOOK_EVENTS) {
    if (event === "PermissionRequest" && !includePermissionRequest) continue;
    hooks[event] = [
      {
        matcher: "",
        hooks: [
          {
            type: "command",
            command: buildHookForwardCommand(event),
            timeout: event === "PermissionRequest" ? PERMISSION_HOOK_TIMEOUT_SECONDS : 5
          }
        ]
      }
    ];
  }
  return { hooks };
}
function withClaudeHookArgs(args, context) {
  if (!context) return args;
  return [...args, "--settings", JSON.stringify(buildClaudeHookSettings())];
}
function withClaudeTerminalHookArgs(args, context) {
  if (!context) return args;
  return [
    ...args,
    "--settings",
    JSON.stringify(buildClaudeHookSettings({ includePermissionRequest: false }))
  ];
}
function withClaudeTerminalPermissionArgs(args, permissionMode) {
  if (!permissionMode) return args;
  return ["--permission-mode", permissionMode, ...args];
}
function withClaudeHookEnv(env, context) {
  if (!context) return env;
  return {
    ...env,
    DEV_ANYWHERE_PROVIDER: context.provider,
    DEV_ANYWHERE_SESSION_ID: context.sessionId,
    DEV_ANYWHERE_HOOK_URL: context.hookUrl,
    DEV_ANYWHERE_HOOK_MARKER: context.marker,
    DEV_ANYWHERE_HOOK_TOKEN: context.token
  };
}
var CLAUDE_PROVIDER = {
  id: "claude",
  displayName: "Claude Code",
  capabilities: {
    supportsHooks: true,
    supportsSessionScopedConfig: true,
    supportsProjectScopedConfig: true,
    supportsGlobalSetup: true
  },
  buildJsonCommand(options, env) {
    const baseArgs = buildClaudeArgs({
      outputFormat: "stream-json",
      inputFormat: "stream-json",
      permissionPromptTool: "stdio",
      permissionMode: options.permissionMode,
      verbose: true,
      forkSession: true,
      resumeSessionId: options.resumeSessionId,
      includePartialMessages: options.includePartialMessages
    });
    return {
      command: resolveClaudeJsonCommand(env),
      args: [...withClaudeHookArgs(baseArgs, options.hook), ...options.extraArgs ?? []],
      env: withClaudeHookEnv(filterClaudeEnvVars(env), options.hook)
    };
  },
  buildTerminalCommand(options, env) {
    const args = withClaudeTerminalPermissionArgs(options.args, options.permissionMode);
    return {
      command: resolveClaudePtyCommand(env),
      args: withClaudeTerminalHookArgs(args, options.hook),
      env: withClaudeHookEnv(env, options.hook)
    };
  }
};

// src/providers/codex.ts
function codexApprovalArgs(permissionMode) {
  switch (permissionMode) {
    case void 0:
      return [];
    case "default":
      return ["--ask-for-approval", "untrusted"];
    case "auto":
      return ["--ask-for-approval", "on-request"];
    case "bypassPermissions":
      return ["--dangerously-bypass-approvals-and-sandbox"];
    default:
      return ["--ask-for-approval", "untrusted"];
  }
}
function withCodexTerminalPermissionArgs(args, permissionMode) {
  return [...codexApprovalArgs(permissionMode), ...args];
}
function resolveCodexCommand(env) {
  return resolveExecutable(
    "codex",
    env,
    "CODEX_BIN",
    "codex not found in PATH. Set CODEX_BIN or install Codex CLI."
  );
}
var CODEX_PROVIDER = {
  id: "codex",
  displayName: "Codex CLI",
  capabilities: {
    supportsHooks: true,
    supportsSessionScopedConfig: true,
    supportsProjectScopedConfig: true,
    supportsGlobalSetup: true
  },
  buildJsonCommand(_options, env) {
    return {
      command: resolveCodexCommand(env),
      args: ["app-server", "--listen", "stdio://"],
      env
    };
  },
  buildTerminalCommand(options, env) {
    const args = withCodexTerminalPermissionArgs(options.args, options.permissionMode);
    return {
      command: resolveCodexCommand(env),
      args,
      env
    };
  }
};

// src/providers/availability.ts
var PROVIDER_BIN_NAME = {
  claude: "claude",
  codex: "codex"
};
var PROVIDER_ENV_NAME = {
  claude: "CLAUDE_BIN",
  codex: "CODEX_BIN"
};
function errorMessage(err) {
  return err instanceof Error ? err.message : String(err);
}
function uniqueSuggestions(paths) {
  const seen = /* @__PURE__ */ new Set();
  const result = [];
  for (const path of paths) {
    const normalized = path?.trim();
    if (!normalized || seen.has(normalized)) continue;
    seen.add(normalized);
    result.push(normalized);
  }
  return result;
}
function discoverProviderCandidates(provider, env) {
  const envPath = env[PROVIDER_ENV_NAME[provider]];
  return uniqueSuggestions([
    envPath,
    ...findExecutableCandidates(PROVIDER_BIN_NAME[provider], env)
  ]);
}
function attachSuggestions(availability, suggestions) {
  return suggestions.length > 0 ? { ...availability, suggestions } : availability;
}
function detect(resolve, suggestions = []) {
  try {
    const command = resolve();
    return attachSuggestions(
      { available: true, command },
      uniqueSuggestions([command, ...suggestions])
    );
  } catch (err) {
    return attachSuggestions(
      { available: false, error: errorMessage(err) },
      uniqueSuggestions(suggestions)
    );
  }
}
function detectAgentCliStatus(env = process.env, options = {}) {
  return {
    claude: detect(
      () => resolveClaudePtyCommand(env),
      [...discoverProviderCandidates("claude", env), ...options.suggestions?.claude ?? []]
    ),
    codex: detect(
      () => resolveCodexCommand(env),
      [...discoverProviderCandidates("codex", env), ...options.suggestions?.codex ?? []]
    )
  };
}

export {
  CLAUDE_PROVIDER,
  CODEX_PROVIDER,
  detectAgentCliStatus
};
//# sourceMappingURL=chunk-SYPXSTOM.js.map