scai
Version:
> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with ❤️.
62 lines (61 loc) • 2.11 kB
JavaScript
// File: lib/generate.ts
import { Spinner } from './spinner.js';
import { Config, readConfig } from '../config.js';
import { startModelProcess } from '../utils/checkModel.js';
/**
* The generate module uses the local model API to produce output
* based on the `content` of the input. It returns the response
* on the `data` property of ModuleIO.
*/
export async function generate(input) {
const model = Config.getModel();
const { contextLength } = readConfig();
// Safely build prompt
const queryPart = input.query ? `User query:\n${input.query}\n\n` : "";
const contentPart = input.content
? (typeof input.content === "string"
? input.content
: JSON.stringify(input.content, null, 2))
: "";
const prompt = `${queryPart}${contentPart}`.trim();
const spinner = new Spinner();
spinner.start();
try {
const data = await doGenerate(prompt, model, contextLength, spinner, false);
return { query: input.query, data };
}
catch {
spinner.fail('Model request failed. Attempting restart...');
await startModelProcess();
const data = await doGenerate(prompt, model, contextLength, spinner, true);
return { query: input.query, data };
}
}
async function doGenerate(prompt, model, contextLength, spinner, retrying) {
const res = await fetch('http://localhost:11434/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model,
prompt,
stream: false,
options: {
num_ctx: contextLength,
},
}),
});
if (!res.ok) {
throw new Error(`Model request failed with status ${res.status}`);
}
const data = await res.json();
if (retrying) {
spinner.succeed('Model response received after restart.');
}
else {
spinner.succeed();
}
process.stdout.write('\n');
return data.response?.trim() ?? '';
process.stdout.write('\n');
return data.response?.trim() ?? '';
}