import { open } from 'node:fs/promises';
import { requestJSON } from './http-client.mjs';
try {
const { API_MODEL, API_HISTORY_FILE } = process.env;
const keep = Number(process.env.API_CONTEXT_KEEP_TURNS || '4');
const budget = Number(process.env.API_CONTEXT_MAX_BYTES || '4096');
if (!API_MODEL?.trim() || !API_HISTORY_FILE || !Number.isInteger(keep) || keep < 0 || keep > 20
|| !Number.isInteger(budget) || budget < 128 || budget > 65_536) throw new Error('Invalid configuration.');
const file = await open(API_HISTORY_FILE, 'r');
let input;
try {
if (!(await file.stat()).isFile()) throw new Error('Expected a regular file.');
const buffer = Buffer.alloc(131_073);
let bytesRead = 0;
while (bytesRead < buffer.length) {
const part = await file.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);
if (!part.bytesRead) break;
bytesRead += part.bytesRead;
}
if (bytesRead > 131_072) throw new Error('History exceeds example file limit.');
input = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(buffer.subarray(0, bytesRead)));
} finally { await file.close(); }
if (!input || Object.keys(input).sort().join(',') !== 'question,system,turns'
|| typeof input.system !== 'string' || !input.system.trim()
|| typeof input.question !== 'string' || !input.question.trim() || !Array.isArray(input.turns)
|| input.turns.some((turn) => !turn || Object.keys(turn).sort().join(',') !== 'assistant,user'
|| typeof turn.user !== 'string' || !turn.user.trim()
|| typeof turn.assistant !== 'string' || !turn.assistant.trim())) {
throw new Error('Expected text-only complete turns.');
}
const turns = keep === 0 ? [] : input.turns.slice(-keep);
let messages;
while (true) {
messages = [{ role: 'system', content: input.system },
...turns.flatMap((turn) => [{ role: 'user', content: turn.user }, { role: 'assistant', content: turn.assistant }]),
{ role: 'user', content: input.question }];
if (Buffer.byteLength(JSON.stringify(messages), 'utf8') <= budget) break;
if (!turns.length) throw new Error('Required instructions and question exceed local byte budget.');
turns.shift();
}
const result = await requestJSON('/v1/chat/completions', { model: API_MODEL, messages });
const choice = result.choices?.[0];
const message = choice?.message;
if (!Array.isArray(result.choices) || result.choices.length !== 1 || choice?.index !== 0
|| choice.finish_reason !== 'stop' || message?.role !== 'assistant'
|| message.refusal != null || message.tool_calls != null || message.function_call != null
|| typeof message.content !== 'string' || !message.content.trim()) throw new Error('Incomplete text response.');
console.log(JSON.stringify({ answer: message.content, retained_turns: turns.length,
omitted_turns: input.turns.length - turns.length, messages_bytes: Buffer.byteLength(JSON.stringify(messages), 'utf8') }));
} catch {
console.error('Context example failed. Check the text-only history, local budget, and request logs. Original file is unchanged.');
process.exitCode = 1;
}