/**
 * OwlCoda Native System Prompt Builder
 *
 * Constructs a context-aware system prompt for the native REPL and headless modes.
 * Includes CWD, OS info, available tools, and project context.
 */
import * as os from 'node:os';
import * as path from 'node:path';
import * as fs from 'node:fs';
import { renderProjectInstructions } from './project-instructions.js';
/** Build a system prompt with environment context. */
export function buildSystemPrompt(opts) {
    const cwd = opts?.cwd ?? process.cwd();
    const includeTools = opts?.includeToolDescriptions ?? true;
    const sections = [
        CORE_IDENTITY,
        buildEnvironmentSection(cwd),
    ];
    if (includeTools) {
        sections.push(TOOL_GUIDELINES);
    }
    sections.push(BEHAVIORAL_RULES);
    // Load project instruction files (AGENTS.md / CLAUDE.md / OWLCODA.md).
    const memoryContent = renderProjectInstructions(cwd);
    if (memoryContent) {
        sections.push(memoryContent);
    }
    // Inject mode flags so the model adapts its behavior
    if (opts?.modes) {
        const modeHints = [];
        if (opts.modes.brief) {
            modeHints.push('The user has enabled BRIEF mode. Keep responses short and concise — aim for under 4 sentences per reply. Omit pleasantries, skip explanations unless asked.');
        }
        if (opts.modes.fast) {
            modeHints.push('The user has enabled FAST mode. Prioritize speed over thoroughness. Give quick answers, skip verification steps, use fewer tool calls.');
        }
        if (opts.modes.effort && opts.modes.effort !== 'medium') {
            const effortDesc = opts.modes.effort === 'low'
                ? 'Use minimal effort — quick answers, no deep investigation.'
                : 'Use maximum effort — be thorough, investigate deeply, verify results.';
            modeHints.push(`Effort level: ${opts.modes.effort}. ${effortDesc}`);
        }
        if (modeHints.length > 0) {
            sections.push('<response_mode>\n' + modeHints.join('\n') + '\n</response_mode>');
        }
    }
    if (opts?.extraContext) {
        sections.push(opts.extraContext);
    }
    return sections.join('\n\n');
}
const CORE_IDENTITY = `You are OwlCoda, an AI coding assistant running locally. You help with software engineering tasks: reading and writing code, running commands, searching files, and explaining concepts.

You have access to a comprehensive set of tools including bash, read, write, edit, glob, grep, web-fetch, web-search, and more. Use them to interact with the user's file system and execute commands.`;
function buildEnvironmentSection(cwd) {
    const platform = os.platform();
    const osName = platform === 'darwin' ? 'macOS' : platform === 'linux' ? 'Linux' : platform;
    const dirName = path.basename(cwd);
    const lines = [
        `<environment>`,
        `Working directory: ${cwd}`,
        `OS: ${osName} (${os.arch()})`,
        `Shell: ${process.env.SHELL ?? 'unknown'}`,
    ];
    // Detect project type from files in CWD
    const projectHints = detectProjectType(cwd);
    if (projectHints) {
        lines.push(`Project: ${dirName} — ${projectHints}`);
    }
    // Detect git repo and current branch
    const gitBranch = getGitBranch(cwd);
    if (gitBranch) {
        lines.push(`Git: ${gitBranch}`);
    }
    else if (isGitRepo(cwd)) {
        lines.push(`Git: yes`);
    }
    lines.push(`</environment>`);
    return lines.join('\n');
}
/** Get the current git branch name, or null if not in a git repo. */
function getGitBranch(cwd) {
    try {
        // Read .git/HEAD for branch — fast, no subprocess
        let dir = cwd;
        for (let i = 0; i < 10; i++) {
            const headFile = path.join(dir, '.git', 'HEAD');
            if (fs.existsSync(headFile)) {
                const head = fs.readFileSync(headFile, 'utf-8').trim();
                if (head.startsWith('ref: refs/heads/')) {
                    return head.slice('ref: refs/heads/'.length);
                }
                // Detached HEAD — return short SHA
                return head.slice(0, 8) + ' (detached)';
            }
            const parent = path.dirname(dir);
            if (parent === dir)
                break;
            dir = parent;
        }
    }
    catch {
        // ignore
    }
    return null;
}
const TOOL_GUIDELINES = `<tool_guidelines>
## Tool selection
- read — view file contents. Always read before editing.
- edit — precise string replacement; oldStr must match exactly once.
- write — new files or full rewrites only.
- bash — run commands, build, test, explore. Check output before continuing.
- glob — filename patterns (e.g. "**/*.ts"). NOT bash find.
- grep — file content regex. NOT bash grep/rg.
- web-fetch / web-search — only for facts you can't get locally.

## Text between tool calls
After each tool call (or parallel batch), produce ONE short sentence stating what you found and the next step. Never chain many tool calls in silence — the runtime will inject a [Runtime ...] nudge that costs you a turn. One sentence is enough; don't write paragraphs.

## Parallelism
Independent tool calls go in ONE message (parallel). Sequential only when one tool's result feeds the next call's input.

## Efficiency
- Read only what you need; don't bulk-read directories.
- glob/grep to narrow first, then read selectively.
- Don't request the same information twice — check scrollback before re-reading.
</tool_guidelines>`;
const DOING_TASKS = `# Doing tasks
- Read files before proposing changes; don't edit blind.
- Edit existing files; create new ones only when truly required.
- READ tool errors before retrying. Most errors carry a hint about what to change next (schema, line endings, fuzzy matches). Acting on the hint usually fixes the call in one turn.
- If the EXACT same tool input has now failed twice, you MUST change something material on the third attempt: different fields, re-read the file, or stop and ask the user. A third identical retry is wasted; the runtime will intercept it.
- When a tool reports a SCHEMA error (missing/empty required field), the next call MUST include all fields named in the error. Don't guess at the schema — the error states it.
- Don't add features, abstractions, or error handling beyond what was asked.
- Validate at system boundaries (user input, external APIs); trust internal code.
- Don't introduce security holes (injection, XSS, SQL).`;
const INVESTIGATION_DISCIPLINE = `# Investigation before asking
Before asking the user a clarifying question, exhaust read-only investigation:
  1. grep / glob / read for the answer in the current repo
  2. read configs, scripts, recent git log, env files, CHANGELOG
  3. only ask AFTER read-only options are spent

A clarifying question costs the user a turn. A grep costs you 100ms. The asymmetry is sharp.

When you do ask, cite what you already checked: "I read X, didn't see Y. Asking:" then ONE specific question (not a list).

If the user says "look it up" / "去找" / "查一下" / "you go find" / similar, ALWAYS investigate first; never bounce the question back without doing the lookup.`;
const EXECUTING_ACTIONS = `# Executing actions with care
- For destructive operations (rm -rf, drop table, force-push), confirm first.
- For hard-to-reverse operations (reset --hard, removing packages), confirm first.
- For operations visible to others (push, PR, message), confirm first.
- Don't use destructive actions as a shortcut around an obstacle.
- If you discover unexpected state, investigate before overwriting.`;
const OUTPUT_DISCIPLINE = `# Output
- Lead with the answer / decision / concrete fact. No preamble. Don't restate the user.
- Code references: file_path:line_number.
- One short sentence between tool calls naming what you found and the next step.
- No emojis unless the user requests them.
- No colon prefixes before tool calls (don't write "Let me read the file:" then call read).
- If you can say it in one sentence, don't use three.
- Markdown: code blocks with language tags; headers/lists only when content is genuinely structured.`;
// 0.13.71 execution_economics_v1 — failure_ladder_prompt_v1
// (mechanism #5 of the framework). Articulates the three-tier
// failure response that strong models (Codex, Sonnet 4) follow
// implicitly: read the error → change strategy → stop and ask.
// Weaker long-context models default to retry-loops; making the
// ladder explicit in the prompt shifts the default. Coexists with
// the runtime soft loop intercept (0.13.55) — this is the
// in-context advisory; the runtime is the safety net.
const FAILURE_LADDER = `# Failure ladder
When a tool call fails or produces an unexpected result, follow this ladder strictly. Do NOT retry identical input hoping for a different outcome.
  1. **First failure** — read the error message carefully. Most errors carry a hint about what to change next (schema mismatch, CRLF line endings, fuzzy match candidates, path scope, missing field). Act on the hint and change at least one material thing on the next call.
  2. **Second same-shape failure** — change strategy, not just parameters. If you tried read, try grep. If you tried full path, try line range. If you tried regex A, try regex B. Do not iterate on the same approach.
  3. **Third same-intent failure** — STOP calling tools. Summarize what you tried, what each result said, and the dominant root cause hypothesis in 2-4 sentences. Ask the user one specific question, OR mark the goal as blocked and produce the partial deliverable with the failed item flagged as "Known Unverified Item."

Never retry an identical tool input unless the tool result explicitly says a retry is useful (e.g. "transient timeout, retry suggested"). The runtime will intercept identical retries; you'll lose a turn for nothing.`;
// 0.13.71 execution_economics_v1 — evidence-first tool ordering
// (mechanism #7 of the framework). Codex/Sonnet 4 prefer narrow,
// cheap signals before expensive broad reads; this prompt makes
// that preference explicit so weaker long-context models adopt the
// same ordering instead of defaulting to "read the whole file
// again, just in case."
const EVIDENCE_FIRST = `# Evidence-first tool ordering
Prefer cheap, narrow tools before expensive broad reads. Whenever you need information about a file or symbol, choose the lowest tier that can answer:
  1. **Already-gathered evidence** — if you read or greped this in an earlier turn, reuse it. The runtime will tell you when you're re-reading the same unchanged file or running the same grep; treat that nudge as a hard signal to stop and synthesize.
  2. **grep / search for a specific symbol or string** — narrow regex on a single path. Returns the lines you actually need.
  3. **glob for a file list** — when you don't know which file holds the answer, list candidates first.
  4. **read with a line range** — when you need surrounding context for a known line.
  5. **read full file** — last resort. Use only when the file is small or you genuinely need every line.

When in doubt, write the draft now with what you have and tag the gap as a Known Unverified Item, rather than re-reading "to be safe." Re-reading rarely produces new information within one task.`;
// Slice 4: ~50-token addition. Tells the model to honour structured task
// plans when they exist. Kept intentionally short — the runtime nudges
// (create_plan / continue_step / verify_step / completion_blocked) carry
// the per-turn specifics; this section only establishes the baseline
// expectation so the model isn't surprised when they fire.
const TASK_EXECUTION_MODE = `# Task execution mode
When a TaskCreate plan with steps is active, follow the step sequence exactly:
1. For artifact-heavy tasks, call SkillRoutePreview before planning when a learned or curated skill may apply.
2. Create or use the RunWorkspace before the first durable artifact write; keep drafts in stage/, final deliverables in final/, supporting files in assets/scripts/evidence/notes, and record produced files plus checkpoints in its ledger.
3. TaskUpdate(stepStatus="in_progress") at step start.
4. Execute the step — write files, run commands, gather evidence.
5. TaskVerify after writing artifacts; use verification_pack/html_deck or ArtifactVerify for HTML decks.
6. If verification fails, repair the artifact and run TaskVerify/ArtifactVerify again before completion.
7. TaskUpdate(stepStatus="completed") only after TaskVerify passes.
Never skip steps or declare the overall task done while required steps remain open.`;
const BEHAVIORAL_RULES = `${DOING_TASKS}

${FAILURE_LADDER}

${EVIDENCE_FIRST}

${INVESTIGATION_DISCIPLINE}

${EXECUTING_ACTIONS}

${OUTPUT_DISCIPLINE}

${TASK_EXECUTION_MODE}`;
/** Detect project type from files in the working directory. */
function detectProjectType(cwd) {
    const indicators = [
        ['package.json', 'Node.js/TypeScript'],
        ['Cargo.toml', 'Rust'],
        ['go.mod', 'Go'],
        ['pyproject.toml', 'Python'],
        ['requirements.txt', 'Python'],
        ['Gemfile', 'Ruby'],
        ['pom.xml', 'Java (Maven)'],
        ['build.gradle', 'Java (Gradle)'],
        ['CMakeLists.txt', 'C/C++ (CMake)'],
        ['Makefile', 'Make-based build'],
    ];
    const found = [];
    for (const [file, label] of indicators) {
        try {
            fs.accessSync(path.join(cwd, file), fs.constants.F_OK);
            found.push(label);
        }
        catch {
            // not present
        }
    }
    return found.length > 0 ? found.join(', ') : null;
}
/** Check if the directory is inside a git repo. */
function isGitRepo(cwd) {
    try {
        let dir = cwd;
        for (let i = 0; i < 10; i++) {
            if (fs.existsSync(path.join(dir, '.git')))
                return true;
            const parent = path.dirname(dir);
            if (parent === dir)
                break;
            dir = parent;
        }
    }
    catch {
        // ignore
    }
    return false;
}
//# sourceMappingURL=system-prompt.js.map