mono/packages/kbot/dist-in/commands/run.js
2025-06-03 21:46:06 +02:00

356 lines
32 KiB
JavaScript

import * as path from 'node:path';
import { hasMagic } from 'glob';
import { sync as dir } from '@polymech/fs/dir';
import { sync as exists } from '@polymech/fs/exists';
import { sync as write } from '@polymech/fs/write';
import { sync as read } from '@polymech/fs/read';
import { forward_slash, resolve, isFile, pathInfoEx } from '@polymech/commons';
import { isArray, isString } from '@polymech/core/primitives';
import { Logger } from 'tslog';
import { createClient } from '../client.js';
import { OptionsSchema } from '../zod_schema.js';
import { get, isWebUrl } from '../source.js';
import { flatten } from '../utils/array.js';
import { collector } from '../collector.js';
import { load as loadProfile } from '../profile.js';
import { load as loadTools } from '../tools.js';
import { preferences, prompt } from '../prompt.js';
import { variables } from '../variables.js';
import { E_Mode } from '../zod_schema.js';
import { runCompletion } from './run-completion.js';
import { runTools } from './run-tools.js';
import { runAssistant } from './run-assistant.js';
import { all } from '../models/index.js';
import { getLogger } from '../index.js';
import { lookup } from 'mime-types';
import { cwd as processCwd } from 'node:process';
export const default_sort = (files) => {
const getSortableParts = (filename) => {
const baseName = path.parse(filename).name;
const match = baseName.match(/^(\d+)_?(.*)$/); // Match leading numbers
const numPart = match ? parseInt(match[1], 10) : NaN;
const textPart = match ? match[2] : baseName; // Extract text part
return { numPart, textPart };
};
return files.sort((a, b) => {
const { numPart: aNum, textPart: aText } = getSortableParts(a);
const { numPart: bNum, textPart: bText } = getSortableParts(b);
if (!isNaN(aNum) && !isNaN(bNum)) {
return aNum - bNum || aText.localeCompare(bText, undefined, { numeric: true, sensitivity: 'base' });
}
return aText.localeCompare(bText, undefined, { numeric: true, sensitivity: 'base' });
});
};
/**
* Complete options by setting up defaults, validating inputs, and initializing required components
*
* @param opts - The initial task options
* @returns - The fully configured options object or null if validation fails
*/
export const complete_options = async (opts) => {
opts.logger = getLogger(opts);
const target = path.resolve(opts.output || opts.path || '.');
if (!exists(target)) {
dir(target);
}
opts.disable = flatten(opts.disable);
opts.disableTools = flatten(opts.disableTools);
opts.include = flatten(opts.include);
opts.exclude = flatten(opts.exclude || []);
opts.variables = opts.profile ? await loadProfile(opts) : {};
try {
const parsed = OptionsSchema().parse(opts);
const options = parsed;
const client = createClient(options);
if (!client) {
opts.logger.error('Failed to create client');
return null;
}
options.client = client;
options.variables = { ...options.variables, ...variables(options) };
options.collector = collector(options, client);
options.onRun = options.onRun || (async (options) => options);
return options;
}
catch (error) {
opts.logger.error('Failed to parse options:', error.message, error.issues);
return null;
}
};
/**
* Gather all messages from various sources for the task
*
* @param opts - The task options
* @param options - The completed options
* @returns - Array of messages and source files
*/
export const complete_messages = async (opts, options) => {
let messages = [];
const promptMessage = await prompt(opts);
if (!promptMessage?.content) {
return { messages: [], files: [] };
}
messages.push(promptMessage);
messages.push((await preferences(opts)));
// Get content from files and web URLs
let files = await get(path.resolve(options.path || '.'), options.include, options) || [];
files = files.map(f => {
if (f.path && f.content && typeof f.content === 'string') {
const mimeType = lookup(f.path);
// Check if the mime type is not binary (heuristic: starts with 'text/' or is a common non-binary type)
if (mimeType && (mimeType.startsWith('text/') || ['application/json', 'application/xml', 'application/javascript', 'application/typescript'].includes(mimeType))) {
if (options.wrap === 'meta') {
const absolutePath = path.resolve(options.path || '.', f.path);
const relativePath = f.path; // f.path is already relative from the get() function
const currentWorkingDirectory = processCwd();
const metaHeader = `IMPORTANT: The following information is file metadata. Please remove this entire block (from METADATA_START to METADATA_END) before processing the file content.
METADATA_START
File: ${relativePath}
Absolute Path: ${absolutePath}
CWD: ${currentWorkingDirectory}
METADATA_END
Original Content:
`;
return { ...f, content: metaHeader + f.content, role: 'user' };
}
else {
return { ...f, role: 'user' };
}
}
}
return { ...f, role: 'user' };
});
messages = [...messages, ...files];
return { messages, files };
};
/**
* Create and configure the parameters for the request
*
* @param options - The completed options
* @param messages - The gathered messages
* @returns - The configured parameters for the API request
*/
export const complete_params = async (options, messages) => {
const params = {
model: options.model,
messages,
tools: []
};
if (options.mode === E_Mode.TOOLS || options.mode === E_Mode.ASSISTANT) {
params.tools = await loadTools(options);
params.tool_choice = 'auto';
//params.parallel_tool_calls = false
}
return params;
};
/**
* Execute the request based on the mode and return the result
*
* @param options - The completed options
* @param client - The API client
* @param params - The request parameters
* @returns - The result of the execution
*/
export const execute_request = async (options, client, params) => {
let ret = null;
try {
switch (options.mode) {
case E_Mode.COMPLETION:
ret = await runCompletion(client, params, options);
break;
case E_Mode.TOOLS:
ret = await runTools(client, params, options);
break;
case E_Mode.ASSISTANT:
ret = await runAssistant(client, params, options);
break;
default:
throw new Error(`Unsupported mode: ${options.mode}`);
}
}
catch (e) {
options.logger?.error(`Error running ${options.mode} mode: ${e.message}`);
}
return ret;
};
/**
* Process a task with the configured options and return the result
*
* @param opts - The task options
* @returns - The result of the task execution
*/
export const processRun = async (opts) => {
let options = await complete_options(opts);
if (!options) {
return null;
}
const client = options.client;
const { messages, files } = await complete_messages(opts, options);
if (messages.length === 0) {
return "";
}
const params = await complete_params(options, messages);
const logDir = path.resolve(resolve(opts.logs || './logs'));
const paramsPath = path.join(logDir, 'params.json');
write(paramsPath, JSON.stringify({ ...params }, null, 2));
if (opts.mode === E_Mode.TOOLS) {
options.logger.debug(`kbot run ${options.mode} : ${options.model} @ ${options.router} : ${files.length} files from project ${path.resolve(options.path || '.')} with ${options.include}`, files.map(f => f.path), params.tools.map(t => `${t.function.name} : ${t.function.description}`));
}
else {
options.logger.debug(`kbot run ${options.mode} : ${options.model} @ ${options.router} : ${files.length} files from project ${path.resolve(options.path || '.')} with ${options.include}`, files.map(f => f.path));
}
options = await options.onRun(options) || options;
const ret = await execute_request(options, client, params);
return ret;
};
/**
* Extract file paths (Windows or POSIX style) from a single string,
* preserving any spaces within the paths. Needed for Salamand File Manager selections (eg: kbot "summarize, as json" -i "$(ListOfSelectedFullNames)")
* - For Windows, it looks for patterns like "C:\" (any drive letter).
* - For POSIX, it looks for a leading slash "/".
* - For web URLs, it looks for patterns like "http://" or "https://".
*
* Returns an array of path strings. If no matches are found, returns [].
*
*/
function extractPaths(input) {
// If it's a web URL, return it
if (isWebUrl(input)) {
return [input];
}
// If it's a direct path that exists, return it
if (exists(path.resolve(resolve(input)))) {
return [input];
}
// If it's a glob pattern, return it as is
if (hasMagic(input)) {
return [input];
}
// Matches either a Windows drive pattern like "C:\", a forward slash "/", or http/https URLs
const pathStartRegex = /([A-Za-z]:\\)|\/|(https?:\/\/)/g;
const matchIndices = [];
let match;
// Collect the start index of each path
while ((match = pathStartRegex.exec(input)) !== null) {
matchIndices.push(match.index);
}
// If none found, return empty
if (!matchIndices.length) {
return [];
}
// Slice from each index to just before the next
const paths = [];
for (let i = 0; i < matchIndices.length; i++) {
const start = matchIndices[i];
const end = i < matchIndices.length - 1 ? matchIndices[i + 1] : input.length;
const path = input.substring(start, end).trim();
if (path) {
paths.push(path);
}
}
return paths;
}
function flattenArrays(arrays) {
return arrays.reduce((accumulator, current) => {
return accumulator.concat(current);
}, []);
}
export const run = async (opts) => {
const ret = [];
const logger = new Logger({ minLevel: opts.logLevel || 2 });
opts.logger = logger;
if (opts.include) {
if (isString(opts.include)) {
opts.include = [opts.include];
}
if (isArray(opts.include)) {
// First check for glob patterns and web URLs
const specialPatterns = opts.include.filter((path) => hasMagic(path) || isWebUrl(path));
// Then process normal paths
const normalPaths = opts.include.filter((path) => !hasMagic(path) && !isWebUrl(path));
const processedPaths = flattenArrays(normalPaths.map(extractPaths));
// Combine special patterns and processed paths
opts.include = [...specialPatterns, ...processedPaths];
}
}
else {
opts.include = [];
}
// Process opts.exclude similarly to opts.include
if (opts.exclude) {
if (isString(opts.exclude)) {
opts.exclude = [opts.exclude];
}
if (isArray(opts.exclude)) {
const specialPatterns = opts.exclude.filter((path) => hasMagic(path) || isWebUrl(path));
const normalPaths = opts.exclude.filter((path) => !hasMagic(path) && !isWebUrl(path));
const processedPaths = flattenArrays(normalPaths.map(extractPaths));
opts.exclude = [...specialPatterns, ...processedPaths];
}
}
else {
opts.exclude = [];
}
if (opts.each) {
let items = [];
if (isArray(opts.each)) {
items = opts.each;
}
else if (exists(opts.each) && isFile(opts.each) && path.parse(opts.each).ext === '.json') {
items = read(opts.each, 'json') || [];
}
else if (hasMagic(opts.each)) {
const info = pathInfoEx(forward_slash(path.resolve(resolve(opts.each))), false, {
absolute: true,
});
items = default_sort(info.FILES);
}
else if (isFile(opts.each) && exists(opts.each)) {
items = [opts.each];
}
else if (isString(opts.each)) {
items = opts.each.split(',');
}
if (items.length === 0) {
opts.logger.warn(`No files matching pattern ${opts.each} found in ${opts.path}`);
return ret;
}
opts.logger.info(`Processing ${items.length} items matching pattern ${opts.each}...`);
const _models = all();
for (const item of items) {
const itemOpts = {
...opts,
ITEM: item,
variables: { ITEM: item }
};
//override model if item is a model id
const model = _models.find(m => m.id === item);
if (model) {
itemOpts.model = item;
}
let currentItemSpecificIncludes = [forward_slash(item)];
const itemPathInfo = path.parse(item);
// Only add corresponding .cpp if --glob-extension=match-cpp is set
if (opts.globExtension === 'match-cpp' && itemPathInfo.ext === '.h') {
const cppFilePath = path.join(itemPathInfo.dir, `${itemPathInfo.name}.cpp`);
if (exists(cppFilePath) && isFile(cppFilePath)) {
currentItemSpecificIncludes.push(forward_slash(cppFilePath));
}
}
itemOpts.include = [...opts.include, ...currentItemSpecificIncludes];
const result = await processRun(itemOpts);
if (result !== undefined) {
ret.push(result);
}
}
}
else {
const result = await processRun(opts);
if (result !== undefined) {
ret.push(result);
}
}
return ret;
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3J1bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUNqQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBQy9CLE9BQU8sRUFBRSxJQUFJLElBQUksR0FBRyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDOUMsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsSUFBSSxJQUFJLEtBQUssRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ2xELE9BQU8sRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDaEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQzlFLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFLN0QsT0FBTyxFQUFFLE1BQU0sRUFBVyxNQUFNLE9BQU8sQ0FBQTtBQUN2QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBO0FBQzNDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzNDLE9BQU8sRUFBRSxJQUFJLElBQUksV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ25ELE9BQU8sRUFBRSxJQUFJLElBQUksU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQy9DLE9BQU8sRUFB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QUE7SUFDbkQsS0FBSyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUN6RCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQy9CLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksT0FBTyxDQUFDLElBQUksTUFBTSxPQUFPLENBQUMsS0FBSyxNQUFNLE9BQU8sQ0FBQyxNQUFNLE9BQU8sS0FBSyxDQUFDLE1BQU0sdUJBQXVCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsU0FBUyxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDN1IsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxZQUFZLE9BQU8sQ0FBQyxJQUFJLE1BQU0sT0FBTyxDQUFDLEtBQUssTUFBTSxPQUFPLENBQUMsTUFBTSxPQUFPLEtBQUssQ0FBQyxNQUFNLHVCQUF1QixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksR0FBRyxDQUFDLFNBQVMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUNwTixDQUFDO0lBQ0QsT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLEtBQUssQ0FB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