[content] /fast/home/franz.srambical/crowd-pilot-extension/out/extension.js (javascript)
        '{ kind: "showTextDocument" }',
        '{ kind: "setSelections", selections: Array<{ start: [number, number], end: [number, number] }> }',
        '{ kind: "editInsert", position: [number, number], text: string }',
        '{ kind: "editDelete", range: { start: [number, number], end: [number, number] } }',
        '{ kind: "editReplace", range: { start: [number, number], end: [number, number] }, text: string }',
        '{ kind: "terminalShow" }',
        '{ kind: "terminalSendText", text: string }',
        'Guidelines:',
        '- If you you insert text, insert until the logical end of the current statement or block.',
        '- When inserting text, make sure to not repeat existing text (except when replacing existing text).',
        '- Use double-quoted JSON strings.'
    ].join('
');
    const doc = editor.document;
    const cursor = editor.selection.active;
    const fullText = doc.getText();
    const numberedContext = fullText.split(/
?
/).map((line, i) => `${i}: ${line}`).join('
');
    const tabbingPrompt = [
        'Your role: Propose the single next action according to the schema to help the developer progress.',
        '',
        'Available context:',
        `- File: ${doc.fileName}`,
        `- Language: ${doc.languageId}`,
        `- Cursor: (${cursor.line}, ${cursor.character})`,
        '',
        'Full file content (zero-based line numbers):',
        '```',
        numberedContext,
        '```',
        '',
        'Respond with ONLY a JSON object containing exactly one action.'
    ].join('
');
    const requestBody = {
        model: 'qwen/qwen2.5-0.5b-instruct',
        messages: [
            { role: 'system', content: schemaDescription },
            { role: 'user', content: tabbingPrompt }
        ]
    };
    const postData = JSON.stringify(requestBody);
    const options = {
        hostname: HOSTNAME,
        port: PORT,
        path: '/v1/chat/completions',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': buffer_1.Buffer.byteLength(postData)
        }
    };
    const json = await new Promise((resolve, reject) => {
        const req = http.request(options, (res) => {
            let data = '';
            res.on('data', (chunk) => { data += chunk.toString(); });
            res.on('end', () => {
                try {
                    resolve(JSON.parse(data));
                }
                catch (err) {
                    reject(new Error(`Failed to parse response: ${err instanceof Error ? err.message : String(err)}`));
                }
            });
        });
        req.on('error', (err) => reject(err));
        req.write(postData);
        req.end();
    });
    const content = extractChatContent(json);
    if (typeof content !== 'string' || content.trim().length === 0) {
        throw new Error('Empty model content');
    }
    const action = parsePlannedAction(content);
    if (!action) {
        throw new Error('No valid action parsed from model output');
    }
    return action;
}
function extractChatContent(json) {
    try {
        if (json && Array.isArray(json.choices) && json.choices[0]) {
            const choice = json.choices[0];
            if (choice.message && typeof choice.message.content === 'string') {
                return choice.message.content;
            }
            if (typeof choice.text === 'string') {
                return choice.text;
            }
        }
        return undefined;
    }
    catch {
        return undefined;
    }
}
function parsePlannedAction(raw) {
    let text = raw.trim();
    text = text.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
    // Strip any hidden reasoning traces enclosed in <think>...</think>
    text = text.replace(/<think>[\s\S]*?<\/think>/gi, '').trim();