import path from "node:path";
import fs from "node:fs/promises";
import fsSync from "node:fs";
import { createHash } from "node:crypto";
import { getAppPaths } from "@kenkaiiii/gg-core";
export const APP_NAME = "ggcoder";
export const VERSION = "0.0.1";
// getAppPaths + AppPaths now live in @kenkaiiii/gg-core. Re-exported here so the
// many `./config.js` importers keep resolving them unchanged.
export { getAppPaths };
export async function ensureAppDirs() {
    const paths = getAppPaths();
    await fs.mkdir(paths.agentDir, { recursive: true, mode: 0o700 });
    await fs.mkdir(paths.sessionsDir, { recursive: true, mode: 0o700 });
    await fs.mkdir(paths.skillsDir, { recursive: true, mode: 0o700 });
    await fs.mkdir(paths.extensionsDir, { recursive: true, mode: 0o700 });
    await fs.mkdir(paths.agentsDir, { recursive: true, mode: 0o700 });
    await seedDefaultAgents(paths.agentsDir);
    await seedDefaultSkills(paths.skillsDir);
    return paths;
}
const VALID_PROVIDERS = new Set([
    "anthropic",
    "xiaomi",
    "openai",
    "gemini",
    "glm",
    "moonshot",
    "minimax",
    "deepseek",
    "openrouter",
    "sakana",
    "xai",
]);
function isValidProvider(value) {
    return typeof value === "string" && VALID_PROVIDERS.has(value);
}
/** Load saved settings from the settings file. Returns defaults on missing/invalid file. */
export function loadSavedSettings(settingsFilePath) {
    const filePath = settingsFilePath ?? getAppPaths().settingsFile;
    const result = {
        thinkingEnabled: false,
        theme: "auto",
        idealReviewEnabled: true,
        lspDiagnostics: true,
        allowOutsideWorkspaceWrites: false,
        sessionRetentionDays: 30,
    };
    try {
        const raw = JSON.parse(fsSync.readFileSync(filePath, "utf-8"));
        // Only accept providers the current build actually supports. A stale
        // provider name (e.g. a previously-supported provider that's since been
        // removed) would otherwise poison startup with "Not logged in" errors.
        if (isValidProvider(raw.defaultProvider)) {
            result.provider = raw.defaultProvider;
            // Only honor the saved model when the provider was also accepted —
            // otherwise a model from the removed provider would leak through.
            if (typeof raw.defaultModel === "string")
                result.model = raw.defaultModel;
        }
        if (raw.thinkingEnabled === true)
            result.thinkingEnabled = true;
        if (isValidThinkingLevel(raw.thinkingLevel))
            result.thinkingLevel = raw.thinkingLevel;
        if (typeof raw.theme === "string" && isValidThemeSetting(raw.theme))
            result.theme = raw.theme;
        if (raw.idealReviewEnabled === false)
            result.idealReviewEnabled = false;
        if (raw.lspDiagnostics === false)
            result.lspDiagnostics = false;
        if (raw.allowOutsideWorkspaceWrites === true)
            result.allowOutsideWorkspaceWrites = true;
        if (typeof raw.subagentMaxPerModel === "number" &&
            Number.isInteger(raw.subagentMaxPerModel) &&
            raw.subagentMaxPerModel >= 1 &&
            raw.subagentMaxPerModel <= 4) {
            result.subagentMaxPerModel = raw.subagentMaxPerModel;
        }
        if (typeof raw.sessionRetentionDays === "number" &&
            Number.isInteger(raw.sessionRetentionDays) &&
            raw.sessionRetentionDays >= 0) {
            result.sessionRetentionDays = raw.sessionRetentionDays;
        }
        if (raw.speedProfile === "optimized" || raw.speedProfile === "baseline") {
            result.speedProfile = raw.speedProfile;
        }
    }
    catch {
        // No settings file or invalid JSON — use defaults
    }
    return result;
}
const VALID_THINKING_LEVELS = new Set(["low", "medium", "high", "xhigh", "max"]);
function isValidThinkingLevel(value) {
    return typeof value === "string" && VALID_THINKING_LEVELS.has(value);
}
const VALID_THEME_SETTINGS = new Set([
    "auto",
    "dark",
    "light",
    "dark-ansi",
    "light-ansi",
    "dark-daltonized",
    "light-daltonized",
]);
function isValidThemeSetting(value) {
    return VALID_THEME_SETTINGS.has(value);
}
/**
 * SHA-256 of the exact `auditor.md` / `skeptic.md` bodies seeded by v5.22.6.
 * Used to delete only our own mistakenly-seeded copies — never a user's file.
 */
export const SHADOWING_SEEDED_AGENT_HASHES = {
    "auditor.md": "7c8c6c1ff892a7ebf45164b0367e340f099cf2cd611bfec23eb39ecc24592502",
    "skeptic.md": "7def72d81da78919efb4934f396d8da47912786a49176badf996eac4d57a285d",
};
/**
 * Seed built-in agent definitions on first run (won't overwrite user edits).
 *
 * Exported for tests: `getAppPaths()` resolves `os.homedir()` inside gg-core's
 * prebuilt dist, which vitest does not transform, so a homedir spy would not
 * apply and the test would operate on the developer's real `~/.gg`. Tests must
 * call this with an explicit temp directory instead of going via ensureAppDirs.
 */
export async function seedDefaultAgents(agentsDir) {
    const defaults = {
        "owl.md": `---
name: owl
description: "In-repo code explorer \u2014 traces symbols, call chains, and structure (no web)"
tools: read, grep, find, ls, source_path
---

You are Owl, a sharp-eyed codebase explorer.
You map how THIS repository fits together \u2014 structure, symbols, call chains, patterns. You work only from local code and never research the web (that's \`researcher\`).

When given a task:
1. Fix the scope \u2014 the exact symbol, pattern, or question to resolve
2. \`find\`/\`ls\` to map the relevant directories
3. \`grep\` to locate symbols, imports, and call sites
4. \`read\` the key files to confirm details
5. Trace connections \u2014 exports, imports, callers, data flow

Return findings tightly:
- **Answer**: the direct answer, first
- **Files**: each relevant path + one line on what it holds
- **Connections**: who calls/imports what
- **Flags**: anything surprising, risky, or ambiguous

Explore widely, report tightly. Miss nothing, waste no words.
`,
        "bee.md": `---
name: bee
description: "Task worker \u2014 writes code, runs commands, fixes bugs, does anything"
tools: read, write, edit, bash, find, grep, ls, source_path
---

You are Bee, an industrious task worker.
You complete an assigned task end-to-end \u2014 writing code, running commands, fixing bugs, refactoring \u2014 and deliver a working result, not a description of one.

When given a task:
1. Understand what's asked and explore the relevant code for context
2. Implement directly, in minimal focused changes
3. Verify: run the narrowest check that proves the change (typecheck or the nearest test), and fix what breaks
4. Report concisely

## Stop when
- The task is done and your verification passes \u2014 OR
- You're blocked (ambiguous requirement, missing dependency, a failure you can't resolve without guessing). Stop and report the blocker; don't thrash or expand scope to force it.

## Report (end with this)
- **Done**: what you changed, file by file, one line each
- **Verified**: the exact command you ran and its result \u2014 never claim a check you didn't run
- **Blocked/Notes**: anything unfinished, assumed, or left for follow-up

Do the work, don't just describe it. Don't over-engineer.
`,
    };
    for (const [filename, content] of Object.entries(defaults)) {
        const filePath = path.join(agentsDir, filename);
        try {
            await fs.access(filePath);
            // File exists — don't overwrite user edits
        }
        catch {
            await fs.writeFile(filePath, content, "utf-8");
        }
    }
    await removeShadowingSeededAgents(agentsDir);
}
/**
 * v5.22.6 briefly seeded `auditor.md` / `skeptic.md` into the user agents dir.
 * Those names are already shipped as BUNDLED_AGENTS with richer prompts, and
 * user-dir agents take precedence — so the seeded copies silently shadowed the
 * bundled ones (a weaker /bullet-proof). Delete them, but ONLY when the file is
 * byte-identical to what 5.22.6 wrote, so a user who edited or authored their
 * own agent of that name keeps it.
 */
async function removeShadowingSeededAgents(agentsDir) {
    for (const [filename, seededHash] of Object.entries(SHADOWING_SEEDED_AGENT_HASHES)) {
        const filePath = path.join(agentsDir, filename);
        try {
            const content = await fs.readFile(filePath, "utf-8");
            const hash = createHash("sha256").update(content, "utf-8").digest("hex");
            if (hash === seededHash)
                await fs.rm(filePath, { force: true });
        }
        catch {
            // Missing or unreadable — nothing to clean up.
        }
    }
}
/** Seed built-in skill definitions on first run (won't overwrite user edits). */
async function seedDefaultSkills(skillsDir) {
    const defaults = {
        "find-skills.md": FIND_SKILLS_MD,
    };
    for (const [filename, content] of Object.entries(defaults)) {
        const filePath = path.join(skillsDir, filename);
        try {
            await fs.access(filePath);
            // File exists — don't overwrite user edits
        }
        catch {
            await fs.writeFile(filePath, content, "utf-8");
        }
    }
}
const FIND_SKILLS_MD = `---
name: find-skills
description: Discover and install agent skills from the open ecosystem into .gg/skills/. Use when the user asks "how do I do X", "find a skill for X", "is there a skill that can…", or wants to extend the agent with capabilities that already exist elsewhere.
---

# Find Skills

Help the user discover and install reusable agent skills from the open ecosystem.

## When to use

Activate this skill when the user:

- Asks "how do I do X" for a specialized, recurring task
- Says "find a skill for…", "add a skill that…", "is there something that handles…"
- Wants to extend the agent with capabilities that likely already exist

## Install location — read this carefully

- **Default: project-local** → \`./.gg/skills/\`. Project-specific skills (React testing, Convex patterns, Next.js conventions, etc.) must live with the project they belong to. A React skill installed globally pollutes every other project.
- **Global** → \`~/.gg/skills/\`. Only install here if the user **explicitly** asks ("install globally", "across all projects") and the skill is genuinely cross-cutting (e.g. a release-notes generator, a git-hygiene helper).

When in doubt, install to the project. It is trivial to promote a project skill to global later; harder to unpollute a global namespace.

## Where to look

- **Catalog**: https://skills.sh — browsable leaderboard
- **Vercel Labs**: https://github.com/vercel-labs/agent-skills
- **Anthropic**: https://github.com/anthropics/skills
- Any trusted GitHub repo containing a \`SKILL.md\`

Prefer publishers with track record (vercel-labs, anthropics) and repos with stars + recent commits.

## Process

1. **Clarify the need** in one question if it's not obvious from context — what domain, what task?
2. **Search** using the \`web_search\` and \`web_fetch\` tools. Use precise terms ("react testing skill" beats "testing").
3. **Shortlist 2–3 candidates.** Present each with: name, one-line description, source repo URL, why it fits. Don't just install the first hit.
4. **Confirm scope** with the user: project (default) or global.
5. **Install** using the \`bash\` tool (see below).
6. **Verify** the file landed and tell the user to start a new gg-coder session so the loader picks it up.

## How to install

Skills come in two shapes. gg-coder's loader handles both.

### Shape A — single file

A single \`SKILL.md\` (or \`<name>.md\`). Install as one flat file:

\`\`\`bash
mkdir -p .gg/skills
curl -fsSL <raw-githubusercontent-url> -o .gg/skills/<skill-name>.md
\`\`\`

### Shape B — directory with supporting files

A directory containing \`SKILL.md\` plus scripts, reference docs, or assets. Preserve the directory:

\`\`\`bash
mkdir -p .gg/skills
# Simplest: tarball the repo, extract only the skill path
curl -fsSL https://github.com/<owner>/<repo>/archive/refs/heads/main.tar.gz \\
  | tar -xz --strip-components=2 -C .gg/skills <repo>-main/skills/<skill-name>
\`\`\`

If that layout doesn't match the source repo, inspect with \`gh api repos/<owner>/<repo>/contents/<path>\` and fetch individual files via their \`download_url\`.

For global installs, swap \`.gg/skills\` for \`~/.gg/skills\` — but remember the default is project.

## If nothing fits

- Say so honestly — don't fabricate a match.
- Offer to either (a) complete the task directly this once, or (b) scaffold a new \`./.gg/skills/<name>.md\` based on what the user describes. A minimal skill is just frontmatter plus instructions:

\`\`\`markdown
---
name: my-skill
description: One-line description of when this skill should be used
---

Instructions the agent should follow when invoked…
\`\`\`
`;
//# sourceMappingURL=config.js.map