kbot esm 2/3

This commit is contained in:
lovebird 2025-02-20 18:49:41 +01:00
parent b6c6ad1306
commit 3b187760e8
59 changed files with 8396 additions and 829 deletions

View File

@ -0,0 +1 @@
export declare const build: () => Promise<void>;

View File

@ -0,0 +1,36 @@
import path from 'path';
import { sync as read } from '@polymech/fs/read';
import { sync as write } from '@polymech/fs/write';
import { sync as exists } from '@polymech/fs/exists';
import { logger } from '../';
import { fetchOpenAIModels } from '../models/openai';
import { fetchOpenRouterModels } from '../models/openrouter';
import { CONFIG_DEFAULT } from '@polymech/osr-commons';
export const build = async () => {
const examplesSrc = path.resolve(__dirname, '../docs_/examples.md');
if (exists(examplesSrc)) {
const examples = read(examplesSrc, 'string') || '';
const examplesPath = path.resolve(__dirname, '../src/docs-internal/examples.ts');
write(examplesPath, `export const examples = ${JSON.stringify(examples)}`);
logger.info(`Examples file generated " ${examplesPath}`);
}
else {
logger.error(`Examples file not found ${examplesSrc}`);
}
const config = CONFIG_DEFAULT();
const modelsOpenAI = await fetchOpenAIModels(config.openai.key);
const modelsOpenRouter = (await fetchOpenRouterModels()).map((model) => {
return {
id: model.id,
name: model.name,
pricing: model.pricing,
context: model.context,
created: model.created
};
});
const modelsOpenAIPath = path.resolve(__dirname, '../src/models/cache/openai.ts');
write(modelsOpenAIPath, `export const models = ${JSON.stringify(modelsOpenAI)}`);
const modelsOpenRouterPath = path.resolve(__dirname, '../src/models/cache/openrouter.ts');
write(modelsOpenRouterPath, `export const models = ${JSON.stringify(modelsOpenRouter)}`);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvYnVpbGQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRXZCLE9BQU8sRUFBRSxJQUFJLElBQUksSUFBSSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDaEQsT0FBTyxFQUFFLElBQUksSUFBSSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNsRCxPQUFPLEVBQUUsSUFBSSxJQUFJLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxLQUFLLENBQUE7QUFDNUIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDcEQsT0FBTyxFQUFFLHFCQUFxQixFQUFtQixNQUFNLHNCQUFzQixDQUFBO0FBQzdFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUd0RCxNQUFNLENBQUMsTUFBTSxLQUFLLEdBQUcsS0FBSyxJQUFJLEVBQUU7SUFDOUIsTUFBTSxXQUFXLEdBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsc0JBQXNCLENBQUMsQ0FBQTtJQUNwRSxJQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ2pELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLGtDQUFrQyxDQUFDLENBQUE7UUFDaEYsS0FBSyxDQUFDLFlBQVksRUFBQywyQkFBMkIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDekUsTUFBTSxDQUFDLElBQUksQ0FBQyw2QkFBNkIsWUFBWSxFQUFFLENBQUMsQ0FBQTtJQUMxRCxDQUFDO1NBQUksQ0FBQztRQUNKLE1BQU0sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLFdBQVcsRUFBRSxDQUFDLENBQUE7SUFDeEQsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLGNBQWMsRUFBUyxDQUFBO0lBRXRDLE1BQU0sWUFBWSxHQUFJLE1BQU0saUJBQWlCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNoRSxNQUFNLGdCQUFnQixHQUFHLENBQUMsTUFBTSxxQkFBcUIsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDckUsT0FBTztZQUNMLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUNaLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtZQUNoQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztTQUN2QixDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDRixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLCtCQUErQixDQUFDLENBQUE7SUFDakYsS0FBSyxDQUFDLGdCQUFnQixFQUFDLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUUvRSxNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLG1DQUFtQyxDQUFDLENBQUE7SUFDekYsS0FBSyxDQUFDLG9CQUFvQixFQUFDLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxDQUFBO0FBQ3pGLENBQUMsQ0FBQSJ9

View File

@ -0,0 +1 @@
export declare const examples: () => void;

View File

@ -0,0 +1,10 @@
import { marked } from 'marked';
import { markedTerminal } from 'marked-terminal';
import { examples as content } from '../docs-internal/examples';
export const examples = () => {
marked.use(markedTerminal({
emoji: false,
}));
process.stdout.write(marked(content));
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhhbXBsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvZXhhbXBsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUMvQixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDaEQsT0FBTyxFQUFFLFFBQVEsSUFBSSxPQUFPLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQTtBQUUvRCxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFO0lBQzNCLE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUN2QjtRQUNFLEtBQUssRUFBRSxLQUFLO0tBQ2IsQ0FDRixDQUFDLENBQUE7SUFDRixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFXLENBQUMsQ0FBQTtBQUNqRCxDQUFDLENBQUEifQ==

View File

@ -0,0 +1 @@
export declare const fetch: () => Promise<void>;

View File

@ -0,0 +1,33 @@
import path from 'path';
import { sync as write } from '@polymech/fs/write';
import { logger, module_root } from '..';
import { fetchOpenAIModels } from '../models/openai';
import { fetchOpenRouterModels } from '../models/openrouter';
import { CONFIG_DEFAULT } from '@polymech/osr-commons';
export const fetch = async () => {
const config = CONFIG_DEFAULT();
if (config.openai && config.openai.key) {
const modelsOpenAI = await fetchOpenAIModels(config.openai.key);
if (modelsOpenAI) {
const modelsOpenAIPath = path.resolve(module_root(), 'openai.json');
write(modelsOpenAIPath, modelsOpenAI);
logger.info(`Fetched ${modelsOpenAI.length} OpenAI models, to ${modelsOpenAIPath}`);
}
else {
logger.error(`Failed to fetch OpenAI models`);
}
}
const modelsOpenRouter = (await fetchOpenRouterModels()).map((model) => {
return {
id: model.id,
name: model.name,
pricing: model.pricing,
context: model.context,
created: model.created
};
});
const modelsOpenRouterPath = path.resolve(module_root(), 'openrouter.json');
write(modelsOpenRouterPath, modelsOpenRouter);
logger.info(`Fetched ${modelsOpenRouter.length} OpenRouter models, to ${modelsOpenRouterPath}`);
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvZmV0Y2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBQ3ZCLE9BQU8sRUFBRSxJQUFJLElBQUksS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxJQUFJLENBQUE7QUFDeEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDcEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sc0JBQXNCLENBQUE7QUFDNUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFBO0FBRXRELE1BQU0sQ0FBQyxNQUFNLEtBQUssR0FBRyxLQUFLLElBQUksRUFBRTtJQUU5QixNQUFNLE1BQU0sR0FBRyxjQUFjLEVBQVMsQ0FBQTtJQUN0QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN2QyxNQUFNLFlBQVksR0FBRyxNQUFNLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDL0QsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsYUFBYSxDQUFDLENBQUE7WUFDbkUsS0FBSyxDQUFDLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxDQUFBO1lBQ3JDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxZQUFZLENBQUMsTUFBTSxzQkFBc0IsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFBO1FBQ3JGLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFBO1FBQy9DLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLE1BQU0scUJBQXFCLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQ3JFLE9BQU87WUFDTCxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDWixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7WUFDaEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztZQUN0QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87U0FDdkIsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFBO0lBQ0YsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLGlCQUFpQixDQUFDLENBQUE7SUFDM0UsS0FBSyxDQUFDLG9CQUFvQixFQUFFLGdCQUFnQixDQUFDLENBQUE7SUFDN0MsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLGdCQUFnQixDQUFDLE1BQU0sMEJBQTBCLG9CQUFvQixFQUFFLENBQUMsQ0FBQTtBQUNqRyxDQUFDLENBQUEifQ==

View File

@ -0,0 +1,3 @@
export declare const help: () => string;
declare const _default: (argv: any) => Promise<string>;
export default _default;

View File

@ -0,0 +1,48 @@
import { marked } from 'marked';
import { markedTerminal } from 'marked-terminal';
import { OptionsSchema } from '../zod_schema';
import { getDefaultValue, getDescription } from '@polymech/osr-commons';
import { z } from 'zod';
export const help = () => {
const schema = OptionsSchema();
const desc = schema._def.description;
const shape = schema.shape;
const md = [
'# KBot Command Line Interface',
'',
'```bash',
'kplus modify [prompt] [options]',
'```',
'',
'## Description',
'',
desc || 'KBot CLI Tool',
'',
'## Options',
''
];
// Process each parameter
for (const [key, def] of Object.entries(shape)) {
const isOptional = def instanceof z.ZodOptional;
const defaultValue = getDefaultValue(def);
const description = getDescription(def);
md.push(`--${key}`);
md.push('');
md.push(`Description: ${description}`);
if (defaultValue !== undefined) {
md.push(`Default: \`${JSON.stringify(defaultValue)}\``);
}
md.push(`Required: ${(!isOptional).toString()}`);
md.push('');
}
marked.use(markedTerminal({
emoji: false
}));
const content = marked(md.join('\n'));
process.stdout.write(content);
return content;
};
export default async (argv) => {
return help();
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9oZWxwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDL0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBRWhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQTtBQUN2RSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFBO0FBRXZCLE1BQU0sQ0FBQyxNQUFNLElBQUksR0FBRyxHQUFHLEVBQUU7SUFDdkIsTUFBTSxNQUFNLEdBQUcsYUFBYSxFQUFFLENBQUE7SUFDOUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUE7SUFDcEMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQTtJQUUxQixNQUFNLEVBQUUsR0FBRztRQUNULCtCQUErQjtRQUMvQixFQUFFO1FBQ0YsU0FBUztRQUNULGlDQUFpQztRQUNqQyxLQUFLO1FBQ0wsRUFBRTtRQUNGLGdCQUFnQjtRQUNoQixFQUFFO1FBQ0YsSUFBSSxJQUFJLGVBQWU7UUFDdkIsRUFBRTtRQUNGLFlBQVk7UUFDWixFQUFFO0tBQ0gsQ0FBQTtJQUVELHlCQUF5QjtJQUN6QixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sVUFBVSxHQUFHLEdBQUcsWUFBWSxDQUFDLENBQUMsV0FBVyxDQUFBO1FBRS9DLE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUN6QyxNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUE7UUFFdkMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLENBQUE7UUFDbkIsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUNYLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLFdBQVcsRUFBRSxDQUFDLENBQUE7UUFDdEMsSUFBSSxZQUFZLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDL0IsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3pELENBQUM7UUFDRCxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQTtRQUNoRCxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ2IsQ0FBQztJQUVELE1BQU0sQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1FBQ3hCLEtBQUssRUFBRSxLQUFLO0tBQ2IsQ0FBQyxDQUFDLENBQUE7SUFDSCxNQUFNLE9BQU8sR0FBVyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBVyxDQUFDO0lBQ3hELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQzdCLE9BQU8sT0FBTyxDQUFBO0FBQ2hCLENBQUMsQ0FBQTtBQUVELGVBQWUsS0FBSyxFQUFFLElBQVMsRUFBRSxFQUFFO0lBQ2pDLE9BQU8sSUFBSSxFQUFFLENBQUE7QUFDZixDQUFDLENBQUEifQ==

View File

@ -0,0 +1,2 @@
import { IKBotTask } from '../types';
export declare const init: (argv: IKBotTask) => Promise<number>;

View File

@ -0,0 +1,105 @@
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 * as path from 'path';
import { Logger } from 'tslog';
import { MODULE_NAME } from '../constants';
const PREFERENCES_TEMPLATE = `# Personal Preferences
This file stores personal information and preferences to help the AI assistant provide more personalized and contextual responses.
## My Preferences
Gender :
Location :
Language :
Occupation :
Age :
## Contacts
My email address :
My wife's email address :
My second wife's email address :
## Content
When creating content
- always Markdown
- always add links to sources
- when searching for news, always add links to videos
`;
const CONFIG_TEMPLATE = {
"deepl": {
"auth_key": "YOUR_DEEPL_AUTH_KEY",
"free_api": false
},
"scaleserp": {
"key": "YOUR_SCALE_SERP_KEY"
},
"geocoder": {
"key": "YOUR_GEOCODER_KEY"
},
"serpapi": {
"key": "YOUR_SERPAPI_KEY"
},
"openai": {
"key": "YOUR_OPENAI_KEY"
},
"bigdata": {
"key": "YOUR_BIGDATA_KEY"
},
"novita": {
"key": "YOUR_NOVITA_KEY"
},
"perplexity": {
"key": "YOUR_PERPLEXITY_KEY"
},
"gemini": {
"key": "YOUR_GEMINI_KEY"
},
"openrouter": {
"key": "YOUR_OPENROUTER_KEY"
},
"deepseek": {
"key": "YOUR_DEEPSEEK_KEY"
},
"google": {
"cse": "YOUR_GOOGLE_CSE",
"api_key": "YOUR_GOOGLE_API_KEY"
}
};
export const init = async (argv) => {
const logger = new Logger({
hideLogPositionForProduction: true,
maskPlaceholder: '***',
name: MODULE_NAME,
prettyLogTemplate: "{{logLevelName}}\t[{{filePathWithLine}}{{name}}]\t",
});
const kbotDir = path.resolve(path.join(process.cwd(), `.${MODULE_NAME}`));
if (!exists(kbotDir)) {
dir(kbotDir);
}
// Create preferences file if it doesn't exist
const preferencesPath = path.resolve(kbotDir, 'preferences.md');
if (!exists(preferencesPath)) {
write(preferencesPath, PREFERENCES_TEMPLATE);
logger.info(`📋 Created preferences file: ${preferencesPath}`);
}
else {
logger.info(`📋 Preferences file already exists: ${preferencesPath}`);
}
// Create config file if it doesn't exist
const configPath = path.resolve(kbotDir, 'config.json');
if (!exists(configPath)) {
write(configPath, CONFIG_TEMPLATE);
logger.info(`📋 Created configuration file: ${configPath}`);
}
else {
logger.info(`📋 Configuration file already exists: ${configPath}`);
}
logger.info('📋 Initialization complete!');
return 0;
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9pbml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLElBQUksR0FBRyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDOUMsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsSUFBSSxJQUFJLEtBQUssRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ2xELE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBRTVCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTyxPQUFPLENBQUE7QUFDL0IsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUUxQyxNQUFNLG9CQUFvQixHQUFHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBeUI1QixDQUFBO0FBRUQsTUFBTSxlQUFlLEdBQUc7SUFDdEIsT0FBTyxFQUFFO1FBQ1AsVUFBVSxFQUFFLHFCQUFxQjtRQUNqQyxVQUFVLEVBQUUsS0FBSztLQUNsQjtJQUNELFdBQVcsRUFBRTtRQUNYLEtBQUssRUFBRSxxQkFBcUI7S0FDN0I7SUFDRCxVQUFVLEVBQUU7UUFDVixLQUFLLEVBQUUsbUJBQW1CO0tBQzNCO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsS0FBSyxFQUFFLGtCQUFrQjtLQUMxQjtJQUNELFFBQVEsRUFBRTtRQUNSLEtBQUssRUFBRSxpQkFBaUI7S0FDekI7SUFDRCxTQUFTLEVBQUU7UUFDVCxLQUFLLEVBQUUsa0JBQWtCO0tBQzFCO0lBQ0QsUUFBUSxFQUFFO1FBQ1IsS0FBSyxFQUFFLGlCQUFpQjtLQUN6QjtJQUNELFlBQVksRUFBRTtRQUNaLEtBQUssRUFBRSxxQkFBcUI7S0FDN0I7SUFDRCxRQUFRLEVBQUU7UUFDUixLQUFLLEVBQUUsaUJBQWlCO0tBQ3pCO0lBQ0QsWUFBWSxFQUFFO1FBQ1osS0FBSyxFQUFFLHFCQUFxQjtLQUM3QjtJQUNELFVBQVUsRUFBRTtRQUNWLEtBQUssRUFBRSxtQkFBbUI7S0FDM0I7SUFDRCxRQUFRLEVBQUU7UUFDUixLQUFLLEVBQUUsaUJBQWlCO1FBQ3hCLFNBQVMsRUFBRSxxQkFBcUI7S0FDakM7Q0FDRixDQUFBO0FBRUQsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxJQUFlLEVBQUUsRUFBRTtJQUM1QyxNQUFNLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBVTtRQUNqQyw0QkFBNEIsRUFBRSxJQUFJO1FBQ2xDLGVBQWUsRUFBRSxLQUFLO1FBQ3RCLElBQUksRUFBRSxXQUFXO1FBQ2pCLGlCQUFpQixFQUFFLG9EQUFvRDtLQUN4RSxDQUFDLENBQUE7SUFDRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3pFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNyQixHQUFHLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDZCxDQUFDO0lBQ0QsOENBQThDO0lBQzlDLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLGdCQUFnQixDQUFDLENBQUE7SUFDL0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzdCLEtBQUssQ0FBQyxlQUFlLEVBQUUsb0JBQW9CLENBQUMsQ0FBQTtRQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxlQUFlLEVBQUUsQ0FBQyxDQUFBO0lBQ2hFLENBQUM7U0FBSSxDQUFDO1FBQ0osTUFBTSxDQUFDLElBQUksQ0FBQyx1Q0FBdUMsZUFBZSxFQUFFLENBQUMsQ0FBQTtJQUN2RSxDQUFDO0lBRUQseUNBQXlDO0lBQ3pDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFBO0lBQ3ZELElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUN4QixLQUFLLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLFVBQVUsRUFBRSxDQUFDLENBQUE7SUFDN0QsQ0FBQztTQUFJLENBQUM7UUFDSixNQUFNLENBQUMsSUFBSSxDQUFDLHlDQUF5QyxVQUFVLEVBQUUsQ0FBQyxDQUFBO0lBQ3BFLENBQUM7SUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUE7SUFDMUMsT0FBTyxDQUFDLENBQUE7QUFDVixDQUFDLENBQUEifQ==

View File

@ -0,0 +1,3 @@
import { IKBotTask } from '@polymech/osr-ai-tools/types';
export declare const processRun: (opts: IKBotTask) => Promise<any>;
export declare const run: (opts: IKBotTask) => Promise<any[]>;

File diff suppressed because one or more lines are too long

5
packages/kbot/dist-in/index.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Logger } from 'tslog';
export declare const logger: Logger<unknown>;
export { run } from './commands/run';
export declare const module_root: () => string;
export declare const assistant_supported: Record<string, string>;

View File

@ -0,0 +1,32 @@
import path from 'path';
import { createLogger } from '@polymech/osr-log';
import { get_var } from '@polymech/osr-commons';
import { MODULE_NAME } from './constants';
export const logger = createLogger('llm-tools');
export { run } from './commands/run';
const isWindows = process.platform === 'win32';
export const module_root = () => path.resolve(path.join(get_var(isWindows ? 'HOMEPATH' : 'HOME'), `.${MODULE_NAME}`));
export const assistant_supported = {
".c": "text/x-c",
".cpp": "text/x-c++",
".cs": "text/x-csharp",
".css": "text/css",
".doc": "application/msword",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".go": "text/x-golang",
".html": "text/html",
".java": "text/x-java",
".js": "text/javascript",
".json": "application/json",
".md": "text/markdown",
".pdf": "application/pdf",
".php": "text/x-php",
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".py": "text/x-python", // sometimes text/x-script.python
".rb": "text/x-ruby",
".sh": "application/x-sh",
".tex": "text/x-tex",
".ts": "application/typescript",
".txt": "text/plain"
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFBO0FBR3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUNoRCxPQUFPLEVBQWtCLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFBO0FBQy9ELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDekMsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFvQixZQUFZLENBQUMsV0FBVyxDQUFDLENBQUE7QUFDaEUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQ3BDLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxDQUFBO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUV0SCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBMkI7SUFDdkQsSUFBSSxFQUFFLFVBQVU7SUFDaEIsTUFBTSxFQUFFLFlBQVk7SUFDcEIsS0FBSyxFQUFFLGVBQWU7SUFDdEIsTUFBTSxFQUFFLFVBQVU7SUFDbEIsTUFBTSxFQUFFLG9CQUFvQjtJQUM1QixPQUFPLEVBQUUseUVBQXlFO0lBQ2xGLEtBQUssRUFBRSxlQUFlO0lBQ3RCLE9BQU8sRUFBRSxXQUFXO0lBQ3BCLE9BQU8sRUFBRSxhQUFhO0lBQ3RCLEtBQUssRUFBRSxpQkFBaUI7SUFDeEIsT0FBTyxFQUFFLGtCQUFrQjtJQUMzQixLQUFLLEVBQUUsZUFBZTtJQUN0QixNQUFNLEVBQUUsaUJBQWlCO0lBQ3pCLE1BQU0sRUFBRSxZQUFZO0lBQ3BCLE9BQU8sRUFBRSwyRUFBMkU7SUFDcEYsS0FBSyxFQUFFLGVBQWUsRUFBVSxpQ0FBaUM7SUFDakUsS0FBSyxFQUFFLGFBQWE7SUFDcEIsS0FBSyxFQUFFLGtCQUFrQjtJQUN6QixNQUFNLEVBQUUsWUFBWTtJQUNwQixLQUFLLEVBQUUsd0JBQXdCO0lBQy9CLE1BQU0sRUFBRSxZQUFZO0NBQ3JCLENBQUMifQ==

2
packages/kbot/dist-in/main.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env node
export declare const logger: any;

View File

@ -0,0 +1,41 @@
#!/usr/bin/env node
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { run } from './commands/run.js';
import { createLogger } from '@polymech/log';
import { OptionsSchema, types } from './zod_schema.js';
import { toYargs } from '@polymech/commons';
import helpCommand from './commands/help.js';
import { examples } from './commands/examples.js';
import { init } from './commands/init.js';
import { build } from './commands/build.js';
import { fetch } from './commands/fetch.js';
export const logger = createLogger('llm-tools');
const modify = async (argv) => await run(argv);
const yargOptions = {
onKey: ((_yargs, key, options) => {
switch (key) {
case 'prompt':
{
return _yargs.positional(key, options);
}
case 'include':
{
return _yargs.option(key, { ...options, alias: key[0].toLowerCase() });
}
}
})
};
yargs(hideBin(process.argv))
.command('init', 'Initialize KBot configuration', (yargs) => toYargs(yargs, OptionsSchema(), yargOptions), init)
.command('modify [prompt]', 'Modify an existing project', (yargs) => toYargs(yargs, OptionsSchema(), yargOptions), modify)
.command('types', 'Generate types', (yargs) => { }, (argv) => types())
.command('build', 'Build kbot essentials', (yargs) => { }, (argv) => build())
.command('fetch', "Fetch models, to $HOME/.kbot/", (yargs) => { }, (argv) => fetch())
.command('help-md', 'Generate markdown help', (yargs) => { }, helpCommand)
.command('examples', 'Show examples', (yargs) => { }, examples)
.command(['modify [prompt]', '$0'], 'Default command modify', (yargs) => toYargs(yargs, OptionsSchema(), yargOptions), modify)
.help()
.wrap(yargs.terminalWidth() - 20)
.parse();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUE7QUFDekIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBRXRELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUMzQyxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDakQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFFM0MsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFRLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUNwRCxNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsSUFBZSxFQUFFLEVBQUUsQ0FBRSxNQUFNLEdBQUcsQ0FBQyxJQUFpQixDQUFDLENBQUE7QUFFdkUsTUFBTSxXQUFXLEdBQVE7SUFDdkIsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQy9CLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDWixLQUFLLFFBQVE7Z0JBQ1gsQ0FBQztvQkFDQyxPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFBO2dCQUN4QyxDQUFDO1lBQ0gsS0FBSyxTQUFTO2dCQUNaLENBQUM7b0JBQ0MsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxFQUFDLEdBQUcsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUMsQ0FBQyxDQUFBO2dCQUN0RSxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQztDQUNILENBQUE7QUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUN6QixPQUFPLENBQ04sTUFBTSxFQUNOLCtCQUErQixFQUMvQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsRUFBRSxXQUFXLENBQUMsRUFDdkQsSUFBSSxDQUNMO0tBQ0EsT0FBTyxDQUNOLGlCQUFpQixFQUNqQiw0QkFBNEIsRUFDNUIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLEVBQUUsV0FBVyxDQUFDLEVBQ3ZELE1BQU0sQ0FDUDtLQUNBLE9BQU8sQ0FDTixPQUFPLEVBQ1AsZ0JBQWdCLEVBQ2hCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ2QsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUNsQjtLQUNBLE9BQU8sQ0FDTixPQUFPLEVBQ1AsdUJBQXVCLEVBQ3ZCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ2QsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUNsQjtLQUNBLE9BQU8sQ0FDTixPQUFPLEVBQ1AsK0JBQStCLEVBQy9CLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ2QsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUNsQjtLQUNBLE9BQU8sQ0FDTixTQUFTLEVBQ1Qsd0JBQXdCLEVBQ3hCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ2QsV0FBVyxDQUNaO0tBQ0EsT0FBTyxDQUNOLFVBQVUsRUFDVixlQUFlLEVBQ2YsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFDZCxRQUFRLENBQ1Q7S0FDQSxPQUFPLENBQUMsQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsRUFBRSx3QkFBd0IsRUFDMUQsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLEVBQUUsV0FBVyxDQUFDLEVBQUUsTUFBTSxDQUFDO0tBQ2pFLElBQUksRUFBRTtLQUNOLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDO0tBQ2hDLEtBQUssRUFBRSxDQUFBIn0=

10
packages/kbot/dist-in/types.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
export * from './zod_types';
export type onToolCall = (category: string, name: string, args: any, result?: any) => Promise<void>;
export type onMessage = (category: string, name: string, args: any, result?: any) => Promise<void>;
import { IKBotOptions } from './zod_types';
import OpenAI from 'openai';
import { ICollector } from '@polymech/osr-ai-tools/types';
export interface IKBotTask extends IKBotOptions {
client: OpenAI;
collector: ICollector;
}

View File

@ -0,0 +1,2 @@
export * from './zod_types';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxhQUFhLENBQUEifQ==

21
packages/kbot/dist-in/zod_schema.d.ts vendored Normal file
View File

@ -0,0 +1,21 @@
import { z } from 'zod';
export declare const get_var: (key?: string) => string;
export declare const HOME: (sub?: string) => string;
export declare const PREFERENCES_DEFAULT: (key?: string) => string;
export declare const E_Filters: z.ZodEnum<z.Writeable<any>>;
export declare const RouterTypeSchema: z.ZodEnum<["openrouter", "openai", "deepseek", "huggingface", "ollama", "fireworks", "gemini", "xai"]>;
export type RouterType = z.infer<typeof RouterTypeSchema>;
export declare const EMode: {
readonly COMPLETION: "completion";
readonly TOOLS: "tools";
readonly ASSISTANT: "assistant";
readonly CUSTOM: "custom";
};
export declare const EType: z.ZodEnum<["completion", "tools", "assistant", "custom"]>;
export declare const SplitType: z.ZodEnum<["none", "langchain/CharacterTextSplitter", "langchain/LatexTextSplitter", "langchain/MarkdownTextSplitter", "langchain/RecursiveCharacterTextSplitter", "langchain/TokenTextSplitter"]>;
export type OptionsSchemaMeta = Record<string, unknown>;
export declare const OptionsSchema: (opts?: any) => any;
export { fetchOpenRouterModels, listModelsAsStrings as listOpenRouterModelsAsStrings } from './models/openrouter';
export { fetchOpenAIModels, listModelsAsStrings as listOpenAIModelsAsStrings } from './models/openai';
export declare const types: () => void;
export declare const schemas: () => void;

File diff suppressed because one or more lines are too long

7527
packages/kbot/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
"dependencies": {
"@gradio/client": "1.12.0",
"@polymech/ai-tools": "file:../ai-tools",
"@polymech/commons": "file:../commons",
"@polymech/core": "file:../core",
"@polymech/fs": "file:../fs",
"@polymech/log": "file:../log",

View File

@ -5,7 +5,7 @@ import { createClient } from '../client'
import * as fs from 'fs'
vi.mock('fs')
vi.mock('@polymech/osr-commons', () => ({
vi.mock('@polymech/commons', () => ({
CONFIG_DEFAULT: () => ({
openrouter: { key: 'default-openrouter-key' },
openai: { key: 'default-openai-key' }

View File

@ -9,7 +9,7 @@ import { logger } from '../'
vi.mock('@polymech/fs/exists')
vi.mock('@polymech/fs/read')
vi.mock('@polymech/commons/_glob')
vi.mock('@polymech/osr-commons', () => ({
vi.mock('@polymech/commons', () => ({
resolve: vi.fn((path) => path),
substitute: vi.fn((x, y) => y)
}))

View File

@ -1,14 +1,15 @@
import path from 'path'
import OpenAI from 'openai'
//import { ChatCompletion, ChatCompletionMessage, ChatCompletionMessageParam } from 'openai/resources'
//import { } from 'openai/resources'
import { ICollector } from '@polymech/osr-ai-tools/types'
import { winstonLogger, } from '@polymech/osr-log'
import { resolve } from '@polymech/osr-commons'
import { ICollector } from '@polymech/ai-tools'
import { resolve } from '@polymech/commons'
import { RunnableFunctionWithParse } from 'openai/lib/RunnableFunction'
import { IKBotOptions } from './zod_types'
import { logger as loggerIntern } from './'
import { winstonLogger, } from '@polymech/ai-tools'
import { IKBotOptions } from './zod_types.js'
import { logger as loggerIntern } from './index.js'
import { ChatCompletion, ChatCompletionMessage, ChatCompletionMessageParam } from 'openai/resources/index.mjs'
export const collector = (options: IKBotOptions, client: OpenAI): ICollector => {

View File

@ -1,13 +1,13 @@
import path from 'path'
import { CONFIG_DEFAULT } from '@polymech/commons'
import { sync as read } from '@polymech/fs/read'
import { sync as write } from '@polymech/fs/write'
import { sync as exists } from '@polymech/fs/exists'
import { logger } from '../'
import { fetchOpenAIModels } from '../models/openai'
import { fetchOpenRouterModels, OpenRouterModel } from '../models/openrouter'
import { CONFIG_DEFAULT } from '@polymech/osr-commons'
import { arch } from 'os'
import { logger } from '../index.js'
import { fetchOpenAIModels } from '../models/openai.js'
import { fetchOpenRouterModels } from '../models/openrouter.js'
export const build = async () => {
const examplesSrc = path.resolve(__dirname, '../docs_/examples.md')

View File

@ -1,6 +1,6 @@
import { marked } from 'marked'
import { markedTerminal } from 'marked-terminal'
import { examples as content } from '../docs-internal/examples'
import { examples as content } from '../docs-internal/examples.js'
export const examples = () => {
marked.use(markedTerminal(

View File

@ -1,9 +1,9 @@
import path from 'path'
import { sync as write } from '@polymech/fs/write'
import { logger, module_root } from '..'
import { fetchOpenAIModels } from '../models/openai'
import { fetchOpenRouterModels } from '../models/openrouter'
import { CONFIG_DEFAULT } from '@polymech/osr-commons'
import { logger, module_root } from '../index.js'
import { fetchOpenAIModels } from '../models/openai.js'
import { fetchOpenRouterModels } from '../models/openrouter.js'
import { CONFIG_DEFAULT } from '@polymech/commons'
export const fetch = async () => {

View File

@ -1,9 +1,9 @@
import { z } from 'zod'
import { marked } from 'marked'
import { markedTerminal } from 'marked-terminal'
import { getDefaultValue, getDescription } from '@polymech/commons'
import { OptionsSchema } from '../zod_schema'
import { getDefaultValue, getDescription } from '@polymech/osr-commons'
import { z } from 'zod'
import { OptionsSchema } from '../zod_schema.js'
export const help = () => {
const schema = OptionsSchema()

View File

@ -1,10 +1,10 @@
import * as path from 'path'
import { Logger } from 'tslog'
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 * as path from 'path'
import { IKBotTask } from '../types'
import { Logger } from 'tslog'
import { MODULE_NAME } from '../constants'
import { IKBotTask } from '../types.js'
import { MODULE_NAME } from '../constants.js'
const PREFERENCES_TEMPLATE = `# Personal Preferences

View File

@ -1,7 +1,7 @@
// src/markdown-blessed.ts
import * as blessed from 'blessed';
import { marked, Tokens } from 'marked';
import * as blessed from 'blessed'
import { marked, Tokens } from 'marked'
/**
* Define a custom renderer where the `image` method
* uses Marked's new signature: image({ href, title, text }: Tokens.Image).
@ -56,20 +56,3 @@ export function displayMarkdown(markdownContent: string): void {
screen.render();
}
// Example usage:
const markdownSample = `
# Hello Blessed & Marked (TypeScript)
Here is some **bold text**, _italic text_, and \`inline code\`.
Below is an image placeholder:
![Example Alt Text](https://example.com/image.png)
---
> A blockquote here to show Markdown support.
Enjoy!
`;

View File

@ -1,12 +1,13 @@
import * as path from 'path'
import * as fs from 'fs'
import OpenAI from 'openai'
import { IKBotTask } from '../types'
import { logger } from '../'
import { onCompletion } from './run-completion'
import { glob } from '../source'
import { prompt } from '../prompt'
import { error } from 'console'
import { IKBotTask } from '../types.js'
import { logger } from '../index.js'
import { onCompletion } from './run-completion.js'
import { glob } from '../source.js'
import { prompt } from '../prompt.js'
const supported: Record<string, string> = {
".c": "text/x-c",

View File

@ -4,11 +4,12 @@ import { marked } from 'marked'
import { markedTerminal } from 'marked-terminal'
import * as path from 'path'
import { sync as write } from '@polymech/fs/write'
import { resolve } from '@polymech/osr-commons'
import { logger } from '../'
import { dumpAsScript } from '../utils/script'
import { applyFilters, Filter } from '../filters'
import { variables } from '../variables'
import { resolve } from '@polymech/commons'
import { logger } from '../index.js'
import { dumpAsScript } from '../utils/script.js'
import { applyFilters, Filter } from '../filters.js'
import { variables } from '../variables.js'
export const onCompletion = async (result: any = "", options: IKBotTask) => {

View File

@ -1,8 +1,8 @@
import { globSync } from 'glob'
import * as path from 'path'
import { forward_slash } from '@polymech/osr-commons'
import { forward_slash } from '@polymech/commons'
import { logger } from '../'
import { IKBotTask } from '@polymech/osr-ai-tools/types'
import { IKBotTask } from '@polymech/ai-tools'
export const runEach = async (opts: IKBotTask, processRun: (args: IKBotTask) => Promise<any>) => {
const ret = []

View File

@ -2,9 +2,10 @@ import { IKBotTask } from '../types'
import OpenAI from 'openai'
import { ChatCompletionMessage, ChatCompletionMessageParam } from 'openai/resources/index.mjs'
import { ChatCompletionToolRunnerParams } from 'openai/lib/ChatCompletionRunner'
import { content } from '../utils/content'
import { logger } from '../'
import { onCompletion } from './run-completion'
import { content } from '../utils/content.js'
import { logger } from '../index.js'
import { onCompletion } from './run-completion.js'
export const runTools = async (client: OpenAI, params: any, options: IKBotTask) => {
const sessionId = Date.now().toString()

View File

@ -4,27 +4,29 @@ 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, isFolder, pathInfoEx } from '@polymech/osr-commons'
import { forward_slash, resolve, isFile, isFolder, pathInfoEx } from '@polymech/commons'
import { isArray, isString } from '@polymech/core/primitives'
import { ChatCompletionToolRunnerParams } from 'openai/lib/ChatCompletionRunner'
import { ChatCompletionMessageParam } from 'openai/resources/index.mjs'
import { logger } from '../'
import { createClient } from '../client'
import { OptionsSchema } from '../zod_schema'
import { get } from '../source'
import { flatten } from '../utils/array'
import { collector } from '../collector'
import { load as loadProfile } from '../profile'
import { load as loadTools } from '../tools'
import { preferences, prompt } from '../prompt'
import { variables } from '../variables'
import { EMode } from '../zod_schema'
import { runCompletion } from './run-completion'
import { runTools } from './run-tools'
import { runAssistant } from './run-assistant'
import { IKBotTask } from '@polymech/osr-ai-tools/types'
import { all } from '../models'
import { IKBotTask } from '@polymech/ai-tools'
import { logger } from '../index.js'
import { createClient } from '../client.js'
import { OptionsSchema } from '../zod_schema.js'
import { get } 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 { EMode } 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'
export const processRun = async (opts: IKBotTask) => {

View File

@ -1,11 +1,13 @@
import * as fs from 'fs'
import * as path from 'path'
import { CONFIG_DEFAULT, resolve } from '@polymech/osr-commons'
import { logger } from './index'
import { CONFIG_DEFAULT, resolve } from '@polymech/commons'
import { sync as exists } from '@polymech/fs/exists'
import { sync as read } from '@polymech/fs/read'
import { IKBotOptions } from './zod_types'
import { env_vars } from './utils/env'
import { IKBotOptions } from './zod_types.js'
import { logger } from './index'
import { env_vars } from './utils/env.js'
export const loadConfig = (options: IKBotOptions) => {
if (options.config) {
try {

View File

@ -1,5 +1,5 @@
import { isString } from '@polymech/core/primitives'
import { logger } from './'
import { logger } from './index.js'
export type Filter = (json: string) => any

View File

@ -1,11 +1,13 @@
import path from 'path'
import { Logger } from 'tslog'
import { createLogger } from '@polymech/osr-log'
import { CONFIG_DEFAULT, get_var } from '@polymech/osr-commons'
import { MODULE_NAME } from './constants'
export const logger: Logger<unknown> = createLogger('llm-tools')
export { run } from './commands/run'
import { createLogger } from '@polymech/log'
import { get_var } from '@polymech/commons'
import { MODULE_NAME } from './constants.js'
export const logger: any = createLogger('llm-tools')
export { run } from './commands/run.js'
const isWindows = process.platform === 'win32'
export const module_root = () => path.resolve(path.join(get_var( isWindows ? 'HOMEPATH' : 'HOME'), `.${MODULE_NAME}`))

View File

@ -1,19 +1,21 @@
#!/usr/bin/env node
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'
import { run } from './commands/run'
import { Logger } from 'tslog'
import { createLogger } from '@polymech/osr-log'
import { OptionsSchema, types } from './zod_schema'
import { IKBotTask } from './types'
import { toYargs } from '@polymech/osr-commons'
import helpCommand from './commands/help'
import { examples } from './commands/examples'
import { init } from './commands/init'
import { build } from './commands/build'
import { fetch } from './commands/fetch'
export const logger: Logger<unknown> = createLogger('llm-tools')
import { toYargs } from '@polymech/commons'
import { createLogger } from '@polymech/log'
import { OptionsSchema, types } from './zod_schema.js'
import { IKBotTask } from './types.js'
import helpCommand from './commands/help.js'
import { examples } from './commands/examples.js'
import { init } from './commands/init.js'
import { build } from './commands/build.js'
import { fetch } from './commands/fetch.js'
import { run } from './commands/run.js'
export const logger: any = createLogger('llm-tools')
const modify = async (argv: IKBotTask) => await run(argv as IKBotTask)

View File

@ -1,6 +1,8 @@
import { isString } from '@polymech/core/primitives'
import { sync as read } from '@polymech/fs/read'
import { logger } from '..'
import { logger } from '../index.js'
import { deepmerge as merge } from 'deepmerge-ts'
export const deepMerge = async (target: string, source: any) => {
if (!isString(target) || !source) {

View File

@ -1,8 +1,9 @@
import * as path from 'path'
import { base64 } from './source'
import { sync as read } from '@polymech/fs/read'
import { ChatCompletionUserMessageParam } from 'openai/resources/index.mjs'
import { base64 } from './source.js'
export type IHandlerResult = ChatCompletionUserMessageParam &
{
path?: string

View File

@ -1,15 +1,14 @@
import { z } from 'zod'
import chalk from 'chalk'
import * as path from 'path'
import { resolve } from '@polymech/osr-commons'
import { sync as read } from '@polymech/fs/read'
import { sync as exists } from '@polymech/fs/exists'
import { logger, module_root } from '../index'
import { CACHE_PATH as OPENROUTER_CACHE_PATH, CachedModels as OpenRouterCachedModels, fetchOpenRouterModels, listModelsAsStrings as listOpenRouterModelsAsStrings } from './openrouter'
import { CACHE_PATH as OPENAI_CACHE_PATH, CachedModels as OpenAICachedModels, listModelsAsStrings as listOpenAIModelsAsStrings } from './openai'
import { fetchOpenAIModels } from '../models/openai'
import { CONFIG_DEFAULT } from '@polymech/osr-commons'
import { logger, module_root } from '../index.js'
import { CACHE_PATH as OPENROUTER_CACHE_PATH, CachedModels as OpenRouterCachedModels, fetchOpenRouterModels, listModelsAsStrings as listOpenRouterModelsAsStrings } from './openrouter.js'
import { CACHE_PATH as OPENAI_CACHE_PATH, CachedModels as OpenAICachedModels, listModelsAsStrings as listOpenAIModelsAsStrings } from './openai.js'
import { fetchOpenAIModels } from '../models/openai.js'
import { CONFIG_DEFAULT } from '@polymech/commons'
import { models as OpenAIModels } from './cache/openai'
import { models as OpenRouterModels } from './cache/openrouter'

View File

@ -1,12 +1,11 @@
import { OpenAI } from 'openai'
import * as fs from 'fs'
import * as path from 'path'
import { logger } from '../index'
import { sync as dir } from '@polymech/fs/dir'
import { sync as exists } from '@polymech/fs/exists'
import { sync as read } from '@polymech/fs/read'
import { sync as write } from '@polymech/fs/write'
import { logger } from '../index.js'
interface OpenAIModel {
id: string;
created: number;

View File

@ -1,11 +1,12 @@
import axios from 'axios'
import * as path from 'path';
import { logger } from '../index'
import { sync as dir } from '@polymech/fs/dir'
import { sync as exists } from '@polymech/fs/exists'
import { sync as read } from '@polymech/fs/read'
import { sync as write } from '@polymech/fs/write'
import { logger } from '../index.js'
interface ModelPricing {
prompt: number;
completion: number;

View File

@ -1,9 +1,11 @@
import { IKBotTask } from "./types"
import { isFile, resolve } from '@polymech/osr-commons'
import { isFile, resolve } from '@polymech/commons'
import { sync as exists } from '@polymech/fs/exists'
import * as path from 'node:path'
import { IProfile, parseProfile } from '@polymech/commons/profile'
import { env_vars } from './utils/env'
import { env_vars } from './utils/env.js'
const testPath = (profilePath: string) => {
if(!profilePath){

View File

@ -1,12 +1,15 @@
import { IKBotTask } from '@polymech/osr-ai-tools/types'
import { resolveQuery } from './utils/input'
import { IKBotTask } from '@polymech/ai-tools'
import { ChatCompletionMessageParam } from 'openai/resources/index.mjs'
import { sync as read } from '@polymech/fs/read'
import { sync as exists } from '@polymech/fs/exists'
import { resolve } from '@polymech/osr-commons'
import { resolve } from '@polymech/commons'
import * as path from 'path'
import { env_vars } from './utils/env'
import { PREFERENCES_FILE_NAME } from './constants'
import { resolveQuery } from './utils/input.js'
import { env_vars } from './utils/env.js'
import { PREFERENCES_FILE_NAME } from './constants.js'
export const prompt = async (opts: IKBotTask): Promise<ChatCompletionMessageParam | undefined> => {
const input = await resolveQuery(opts)
return {
@ -14,6 +17,7 @@ export const prompt = async (opts: IKBotTask): Promise<ChatCompletionMessagePara
content: input || ''
}
}
export const preferences = async (opts: IKBotTask): Promise<ChatCompletionMessageParam | undefined> => {
let preferencesPath = path.resolve(resolve(opts.preferences, false, env_vars()))
if(!exists(preferencesPath)) {

View File

@ -2,18 +2,16 @@ import * as path from 'path'
import * as fs from 'fs'
import { sync as read } from '@polymech/fs/read'
import { sync as dir } from '@polymech/fs/dir'
import { createItem as toNode } from '@polymech/fs/inspect'
import { INode } from '@polymech/fs/interfaces'
import { sync as exists } from '@polymech/fs/exists'
import { isFile, forward_slash } from '@polymech/osr-commons'
import { isFile, forward_slash } from '@polymech/commons'
import { logger } from './index'
import { lookup } from 'mime-types'
import { globSync } from 'glob'
import { EXCLUDE_GLOB, MAX_FILE_SIZE } from './constants'
import { defaultMimeRegistry, IHandlerResult } from './mime-handlers'
import { ChatCompletionContentPartImage } from 'openai/resources/index.mjs'
export const default_filters = {
isFile,
exists,

View File

@ -1,16 +1,16 @@
import { ChatCompletionMessageParam } from "openai/resources/chat/completions"
import { resolve } from '@polymech/osr-commons'
import { resolve } from '@polymech/commons'
import { } from '@polymech/commons/config'
import { sync as exists } from '@polymech/fs/exists'
import * as path from 'node:path'
import { tools as defaultTools } from "@polymech/osr-ai-tools/lib/tools/tools"
import { logger } from './index'
import { IKBotOptions } from './zod_types'
import { tools as defaultTools } from "@polymech/ai-tools/tools"
import { logger } from './index.js'
import { IKBotOptions } from './zod_types.js'
import { RunnableToolFunctionWithParse } from "openai/lib/RunnableFunction"
import { after, before } from './utils/aspects_simple'
import { IKBotTask } from "./types"
import { after, before } from './utils/aspects_simple.js'
import { IKBotTask } from "./types.js"
export type TMessageParam = ChatCompletionMessageParam & { type?: string }

View File

@ -1,13 +1,11 @@
export * from './zod_types'
import { IKBotOptions } from './zod_types.js'
import OpenAI from 'openai'
import { ICollector } from '@polymech/ai-tools'
export * from './zod_types.js'
export type onToolCall = (category: string, name: string, args: any, result?: any) => Promise<void>
export type onMessage = (category: string, name: string, args: any, result?: any) => Promise<void>
import { IKBotOptions } from './zod_types'
import OpenAI from 'openai'
import { ICollector } from '@polymech/osr-ai-tools/types'
export interface IKBotTask extends IKBotOptions
{
client: OpenAI

View File

@ -1,5 +1,3 @@
import { isString } from '@polymech/core/primitives'
export const flatten = (value: string | string[] | undefined): string[] => {
let initialArray: string[]
if (typeof value === "string") {

View File

@ -1,348 +0,0 @@
/* -------------------------------------------------------------------------
* aspects.ts
*
* A robust aspect system supporting:
* - before: optionally modifies arguments (sync or async)
* - after: optionally modifies return value (sync or async)
* - around: complete control over function invocation
* - error: intercept errors (sync or async)
*
* Works as both:
* 1) Decorators for class methods (e.g. @before(...))
* 2) Direct function wrappers (e.g. fn = before(fn, ...)).
* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------
* 1) SIGNALS Enum (string-based to avoid symbol issues)
* ------------------------------------------------------------------------ */
export enum SIGNALS {
BEFORE = 'BEFORE',
AFTER = 'AFTER',
AROUND = 'AROUND',
ERROR = 'ERROR',
}
/* -------------------------------------------------------------------------
* 2) Basic Types
* ------------------------------------------------------------------------ */
type AnyFunction = (...args: any[]) => any;
/**
* If a function returns a Promise<T>, then its awaited type is T.
* Otherwise, it's just ReturnType<T>.
*/
type AwaitedReturn<T extends AnyFunction> =
T extends (...args: any[]) => Promise<infer U> ? U : ReturnType<T>;
/* -------------------------------------------------------------------------
* 3) Advice Signatures
* ------------------------------------------------------------------------ */
/**
* BEFORE advice:
* - Receives `context` (the `this` of the function)
* - Receives the original `args`
* - Can return either nothing (`void`) or new arguments (`Parameters<T>`)
* - Can be async, returning a Promise that resolves to new args or `void`
*/
export type BeforeAdvice<T extends AnyFunction> = (
context: ThisParameterType<T>,
args: Parameters<T>
) => void | Parameters<T> | Promise<void | Parameters<T>>;
/**
* AFTER advice:
* - Receives `context`, the original functions final (awaited) result,
* and the original arguments
* - Can return a new result (sync or async)
*/
export type AfterAdvice<T extends AnyFunction> = (
context: ThisParameterType<T>,
result: AwaitedReturn<T>,
args: Parameters<T>
) => AwaitedReturn<T> | Promise<AwaitedReturn<T>>;
/**
* AROUND advice:
* - Provides a `proceed(...args)` function that calls the original method
* - You can call `proceed` any number of times, or skip it
* - Supports both sync and async usage
*/
export type AroundAdvice<T extends AnyFunction> = (
proceed: (...args: Parameters<T>) => ReturnType<T>,
context: ThisParameterType<T>,
args: Parameters<T>
) => ReturnType<T>;
/**
* ERROR advice:
* - Intercepts errors thrown by the original method (sync or async)
* - Can return a fallback result or rethrow
*/
export type ErrorAdvice<T extends AnyFunction> = (
error: unknown,
context: ThisParameterType<T>,
args: Parameters<T>
) => ReturnType<T> | void;
/* -------------------------------------------------------------------------
* 4) ISignalMap: Each signal has a distinct function wrapper signature
* ------------------------------------------------------------------------ */
interface ISignalMap {
[SIGNALS.BEFORE]: <T extends AnyFunction>(original: T, advice: BeforeAdvice<T>) => T;
[SIGNALS.AFTER]: <T extends AnyFunction>(original: T, advice: AfterAdvice<T>) => T;
[SIGNALS.AROUND]: <T extends AnyFunction>(original: T, advice: AroundAdvice<T>) => T;
[SIGNALS.ERROR]: <T extends AnyFunction>(original: T, advice: ErrorAdvice<T>) => T;
}
/* -------------------------------------------------------------------------
* 5) The SignalMap Implementation
* - This is where the actual "wrapping" logic lives.
* ------------------------------------------------------------------------ */
const SignalMap: ISignalMap = {
/**
* BEFORE:
* - Possibly modifies arguments
* - If returns a Promise, we await it before calling original
* - If returns an array, we use that as new arguments
*/
[SIGNALS.BEFORE]<T extends AnyFunction>(original: T, advice: BeforeAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const maybeNewArgs = advice(this, args);
if (maybeNewArgs instanceof Promise) {
return maybeNewArgs.then((resolvedArgs) => {
const finalArgs = resolvedArgs || args;
const result = original.apply(this, finalArgs);
return (result instanceof Promise) ? result : Promise.resolve(result);
}) as ReturnType<T>;
} else {
const finalArgs = Array.isArray(maybeNewArgs) ? maybeNewArgs : args;
return original.apply(this, finalArgs);
}
} as T;
},
/**
* AFTER:
* - Possibly modifies the return value
* - If original is async, we chain on its promise
* - Advice can be sync or async
*/
[SIGNALS.AFTER]<T extends AnyFunction>(original: T, advice: AfterAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const result = original.apply(this, args);
if (result instanceof Promise) {
return result.then((unwrapped) => {
const maybeNewResult = advice(this, unwrapped, args);
return (maybeNewResult instanceof Promise) ? maybeNewResult : maybeNewResult;
}) as ReturnType<T>;
} else {
const maybeNewResult = advice(this, result as AwaitedReturn<T>, args);
if (maybeNewResult instanceof Promise) {
return maybeNewResult.then(r => r) as ReturnType<T>;
}
return maybeNewResult as ReturnType<T>;
}
} as T;
},
/**
* AROUND:
* - Full control over invocation
* - Typically you do: proceed(...args)
* - If you want to skip or call multiple times, you can
*/
[SIGNALS.AROUND]<T extends AnyFunction>(original: T, advice: AroundAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const proceed = (...innerArgs: Parameters<T>) => original.apply(this, innerArgs);
return advice(proceed, this, args);
} as T;
},
/**
* ERROR:
* - Intercepts errors thrown by the original function or a rejected Promise
* - Optionally returns a fallback or rethrows
*/
[SIGNALS.ERROR]<T extends AnyFunction>(original: T, advice: ErrorAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
try {
const result = original.apply(this, args);
if (result instanceof Promise) {
// Handle async rejections
return result.catch((err: unknown) => {
return advice(err, this, args);
}) as ReturnType<T>;
}
return result;
} catch (err) {
// Synchronous error
return advice(err, this, args) as ReturnType<T>;
}
} as T;
},
};
/* -------------------------------------------------------------------------
* 6) Decorator Helper
* ------------------------------------------------------------------------ */
/** Checks if were decorating a class method. */
function isMethod(
_target: any,
descriptor?: PropertyDescriptor
): descriptor is PropertyDescriptor & { value: AnyFunction } {
return !!descriptor && typeof descriptor.value === 'function';
}
/* -------------------------------------------------------------------------
* 7) Wrapped Helpers (cutMethod, cut, aspect)
* ------------------------------------------------------------------------ */
/** Strictly typed wrapping for class methods. */
function cutMethod<T extends AnyFunction, A>(
descriptor: PropertyDescriptor & { value: T },
advice: A,
type: SIGNALS
): PropertyDescriptor {
const original = descriptor.value;
descriptor.value = SignalMap[type](original, advice as any); // Cast `any` or refine further
return descriptor;
}
/** Strictly typed wrapping for direct function usage. */
function cut<T extends AnyFunction, A>(target: T, advice: A, type: SIGNALS): T {
return SignalMap[type](target, advice as any);
}
interface AspectOptions<T extends SIGNALS, A> {
type: T;
advice: A;
}
/**
* The core aspect(...) function
* - Returns a decorator if used in that style
* - Otherwise, can wrap a function directly
*/
function aspect<T extends SIGNALS, A>({ type, advice }: AspectOptions<T, A>) {
// If type is invalid, produce a no-op decorator
if (!(type in SignalMap)) {
return function crosscut(
target: any,
_name?: string,
descriptor?: PropertyDescriptor
) {
return descriptor || target;
};
}
// Return a decorator function
return function crosscut(
target: any,
_name?: string,
descriptor?: PropertyDescriptor
): any {
// If used on a method
if (isMethod(target, descriptor)) {
return cutMethod(descriptor!, advice, type);
}
// If used directly on a function or something else
return cut(target, advice, type);
};
}
/* -------------------------------------------------------------------------
* 8) Overloaded Decorator/Function Wrappers
* - Each can be used as a decorator or direct wrapper
* ------------------------------------------------------------------------ */
/**
* `before`:
* Decorator usage => @before((ctx, args) => ...)
* Direct usage => myFn = before(myFn, (ctx, args) => ...)
*/
export function before<T extends AnyFunction>(
advice: BeforeAdvice<T>
): (target: any, name?: string, descriptor?: PropertyDescriptor) => any;
export function before<T extends AnyFunction>(fn: T, advice: BeforeAdvice<T>): T;
export function before<T extends AnyFunction>(
arg1: T | BeforeAdvice<T>,
arg2?: BeforeAdvice<T>
): any {
if (typeof arg1 === 'function' && typeof arg2 === 'function') {
return SignalMap[SIGNALS.BEFORE](arg1, arg2);
}
return aspect({ type: SIGNALS.BEFORE, advice: arg1 as BeforeAdvice<T> });
}
/**
* `after`:
* Decorator usage => @after((ctx, result, args) => ...)
* Direct usage => myFn = after(myFn, (ctx, result, args) => ...)
*/
export function after<T extends AnyFunction>(
advice: AfterAdvice<T>
): (target: any, name?: string, descriptor?: PropertyDescriptor) => any;
export function after<T extends AnyFunction>(fn: T, advice: AfterAdvice<T>): T;
export function after<T extends AnyFunction>(
arg1: T | AfterAdvice<T>,
arg2?: AfterAdvice<T>
): any {
if (typeof arg1 === 'function' && typeof arg2 === 'function') {
return SignalMap[SIGNALS.AFTER](arg1, arg2);
}
return aspect({ type: SIGNALS.AFTER, advice: arg1 as AfterAdvice<T> });
}
/**
* `around`:
* Decorator usage => @around((proceed, ctx, args) => ...)
* Direct usage => myFn = around(myFn, (proceed, ctx, args) => ...)
*/
export function around<T extends AnyFunction>(
advice: AroundAdvice<T>
): (target: any, name?: string, descriptor?: PropertyDescriptor) => any;
export function around<T extends AnyFunction>(fn: T, advice: AroundAdvice<T>): T;
export function around<T extends AnyFunction>(
arg1: T | AroundAdvice<T>,
arg2?: AroundAdvice<T>
): any {
if (typeof arg1 === 'function' && typeof arg2 === 'function') {
return SignalMap[SIGNALS.AROUND](arg1, arg2);
}
return aspect({ type: SIGNALS.AROUND, advice: arg1 as AroundAdvice<T> });
}
/**
* `error`:
* Decorator usage => @error((err, ctx, args) => ...)
* Direct usage => myFn = error(myFn, (err, ctx, args) => ...)
*/
export function error<T extends AnyFunction>(
advice: ErrorAdvice<T>
): (target: any, name?: string, descriptor?: PropertyDescriptor) => any;
export function error<T extends AnyFunction>(fn: T, advice: ErrorAdvice<T>): T;
export function error<T extends AnyFunction>(
arg1: T | ErrorAdvice<T>,
arg2?: ErrorAdvice<T>
): any {
if (typeof arg1 === 'function' && typeof arg2 === 'function') {
return SignalMap[SIGNALS.ERROR](arg1, arg2);
}
return aspect({ type: SIGNALS.ERROR, advice: arg1 as ErrorAdvice<T> });
}
/* -------------------------------------------------------------------------
* 9) Default Export
* ------------------------------------------------------------------------ */
export default {
SIGNALS,
before,
after,
around,
error,
aspect,
};

View File

@ -1,72 +0,0 @@
// fancy ES7 - Aspect - decorator
export enum SIGNALS {
BEFORE = <any>Symbol('before'),
AFTER = <any>Symbol('after'),
AROUND = <any>Symbol('around'),
ERROR = <any>Symbol('error')
}
const SignalMap = {
[SIGNALS.BEFORE](original, advice) {
return function before() {
advice(this, arguments);
return original.apply(this, arguments);
};
},
[SIGNALS.AFTER](original, advice) {
return function after() {
const ret = original.apply(this, arguments);
return advice(this, ret, arguments);
};
},
[SIGNALS.AROUND](original, advice) {
return function around() {
return advice(function () { original.apply(this, arguments); });
};
},
[SIGNALS.ERROR](original, advice) {
return function around() {
try {
return original.apply(this, arguments);
}
catch (err) {
return advice(err);
}
};
}
};
const isMethod = (target, descriptor) => descriptor && descriptor.value;
const cutMethod = (target, name, descriptor, advice, type) => {
const original = descriptor.value;
descriptor.value = SignalMap[type](original, advice);
return descriptor;
};
const cut = (target, advice, type) => {
return SignalMap[type](target, advice);
};
function aspect({ type, advice }) {
if (!(type in SignalMap)) {
return function crosscut(target, name, descriptor) {
return descriptor || target;
};
}
return function crosscut(target, name, descriptor) {
if (isMethod(target, descriptor)) {
return cutMethod(target, name, descriptor, advice, type);
}
return cut(target, advice, type);
};
}
export function before(advice) { return aspect({ type: SIGNALS.BEFORE, advice }); }
export function after(advice) { return aspect({ type: SIGNALS.AFTER, advice }); }
export function around(advice) { return aspect({ type: SIGNALS.AROUND, advice }); }
// export function error(advice) { return aspect({ type: SIGNALS.ERROR, advice }); }
export default {
before, after, around, aspect, SIGNALS
};

View File

@ -1,232 +0,0 @@
/* -------------------------------------------------------------------------
* aspects.ts
*
* A robust aspect system supporting:
* - before: optionally modifies arguments (sync or async)
* - after: optionally modifies return value (sync or async)
* - around: complete control over function invocation
* - error: intercept errors (sync or async)
*
* Only supports direct function wrappers (e.g. fn = before(fn, ...)).
* ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------
* 1) SIGNALS Enum (string-based to avoid symbol issues)
* ------------------------------------------------------------------------ */
export enum SIGNALS {
BEFORE = 'BEFORE',
AFTER = 'AFTER',
AROUND = 'AROUND',
ERROR = 'ERROR',
}
/* -------------------------------------------------------------------------
* 2) Basic Types
* ------------------------------------------------------------------------ */
type AnyFunction = (...args: any[]) => any;
/**
* If a function returns a Promise<T>, then its awaited type is T.
* Otherwise, it's just ReturnType<T>.
*/
type AwaitedReturn<T extends AnyFunction> =
T extends (...args: any[]) => Promise<infer U> ? U : ReturnType<T>;
/* -------------------------------------------------------------------------
* 3) Advice Signatures
* ------------------------------------------------------------------------ */
/**
* BEFORE advice:
* - Receives `context` (the `this` of the function)
* - Receives the original `args`
* - Can return either nothing (`void`) or new arguments (`Parameters<T>`)
* - Can be async, returning a Promise that resolves to new args or `void`
*/
export type BeforeAdvice<T extends AnyFunction> = (
context: ThisParameterType<T>,
args: Parameters<T>
) => void | Parameters<T> | Promise<void | Parameters<T>>;
/**
* AFTER advice:
* - Receives `context`, the original functions final (awaited) result,
* and the original arguments
* - Can return a new result (sync or async)
*/
export type AfterAdvice<T extends AnyFunction> = (
context: ThisParameterType<T>,
result: AwaitedReturn<T>,
args: Parameters<T>
) => AwaitedReturn<T> | Promise<AwaitedReturn<T>>;
/**
* AROUND advice:
* - Provides a `proceed(...args)` function that calls the original method
* - You can call `proceed` any number of times, or skip it
* - Supports both sync and async usage
*/
export type AroundAdvice<T extends AnyFunction> = (
proceed: (...args: Parameters<T>) => ReturnType<T>,
context: ThisParameterType<T>,
args: Parameters<T>
) => ReturnType<T>;
/**
* ERROR advice:
* - Intercepts errors thrown by the original function (sync or async)
* - Can return a fallback result or rethrow
*/
export type ErrorAdvice<T extends AnyFunction> = (
error: unknown,
context: ThisParameterType<T>,
args: Parameters<T>
) => ReturnType<T> | void;
/* -------------------------------------------------------------------------
* 4) ISignalMap: Each signal has a distinct function wrapper signature
* ------------------------------------------------------------------------ */
interface ISignalMap {
[SIGNALS.BEFORE]: <T extends AnyFunction>(original: T, advice: BeforeAdvice<T>) => T;
[SIGNALS.AFTER]: <T extends AnyFunction>(original: T, advice: AfterAdvice<T>) => T;
[SIGNALS.AROUND]: <T extends AnyFunction>(original: T, advice: AroundAdvice<T>) => T;
[SIGNALS.ERROR]: <T extends AnyFunction>(original: T, advice: ErrorAdvice<T>) => T;
}
/* -------------------------------------------------------------------------
* 5) The SignalMap Implementation
* - This is where the actual "wrapping" logic lives.
* ------------------------------------------------------------------------ */
const SignalMap: ISignalMap = {
/**
* BEFORE:
* - Possibly modifies arguments
* - If returns a Promise, we await it before calling original
* - If returns an array, we use that as new arguments
*/
[SIGNALS.BEFORE]<T extends AnyFunction>(original: T, advice: BeforeAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const maybeNewArgs = advice(this, args);
if (maybeNewArgs instanceof Promise) {
return maybeNewArgs.then((resolvedArgs) => {
const finalArgs = resolvedArgs || args;
const result = original.apply(this, finalArgs);
return (result instanceof Promise) ? result : Promise.resolve(result);
}) as ReturnType<T>;
} else {
const finalArgs = Array.isArray(maybeNewArgs) ? maybeNewArgs : args;
return original.apply(this, finalArgs);
}
} as T;
},
/**
* AFTER:
* - Possibly modifies the return value
* - If original is async, we chain on its promise
* - Advice can be sync or async
*/
[SIGNALS.AFTER]<T extends AnyFunction>(original: T, advice: AfterAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const result = original.apply(this, args);
if (result instanceof Promise) {
return result.then((unwrapped) => {
const maybeNewResult = advice(this, unwrapped, args);
return (maybeNewResult instanceof Promise) ? maybeNewResult : maybeNewResult;
}) as ReturnType<T>;
} else {
const maybeNewResult = advice(this, result as AwaitedReturn<T>, args);
if (maybeNewResult instanceof Promise) {
return maybeNewResult.then(r => r) as ReturnType<T>;
}
return maybeNewResult as ReturnType<T>;
}
} as T;
},
/**
* AROUND:
* - Full control over invocation
* - Typically you do: proceed(...args)
* - If you want to skip or call multiple times, you can
*/
[SIGNALS.AROUND]<T extends AnyFunction>(original: T, advice: AroundAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
const proceed = (...innerArgs: Parameters<T>) => original.apply(this, innerArgs);
return advice(proceed, this, args);
} as T;
},
/**
* ERROR:
* - Intercepts errors thrown by the original function or a rejected Promise
* - Optionally returns a fallback or rethrows
*/
[SIGNALS.ERROR]<T extends AnyFunction>(original: T, advice: ErrorAdvice<T>): T {
return function (this: ThisParameterType<T>, ...args: Parameters<T>): ReturnType<T> {
try {
const result = original.apply(this, args);
if (result instanceof Promise) {
// Handle async rejections
return result.catch((err: unknown) => {
return advice(err, this, args);
}) as ReturnType<T>;
}
return result;
} catch (err) {
// Synchronous error
return advice(err, this, args) as ReturnType<T>;
}
} as T;
},
};
/* -------------------------------------------------------------------------
* 6) Direct Usage Functions (no decorator support)
* ------------------------------------------------------------------------ */
/**
* `before`:
* Direct usage => myFn = before(myFn, (ctx, args) => ...)
*/
export function before<T extends AnyFunction>(fn: T, advice: BeforeAdvice<T>): T {
return SignalMap[SIGNALS.BEFORE](fn, advice);
}
/**
* `after`:
* Direct usage => myFn = after(myFn, (ctx, result, args) => ...)
*/
export function after<T extends AnyFunction>(fn: T, advice: AfterAdvice<T>): T {
return SignalMap[SIGNALS.AFTER](fn, advice);
}
/**
* `around`:
* Direct usage => myFn = around(myFn, (proceed, ctx, args) => ...)
*/
export function around<T extends AnyFunction>(fn: T, advice: AroundAdvice<T>): T {
return SignalMap[SIGNALS.AROUND](fn, advice);
}
/**
* `error`:
* Direct usage => myFn = error(myFn, (err, ctx, args) => ...)
*/
export function error<T extends AnyFunction>(fn: T, advice: ErrorAdvice<T>): T {
return SignalMap[SIGNALS.ERROR](fn, advice);
}
/* -------------------------------------------------------------------------
* 7) Default Export
* ------------------------------------------------------------------------ */
export default {
SIGNALS,
before,
after,
around,
error,
};

View File

@ -1,10 +1,11 @@
import * as path from 'path'
import { sync as exists } from '@polymech/fs/exists'
import { sync as read } from '@polymech/fs/read'
import { resolve, isFile } from '@polymech/osr-commons'
import { resolve, isFile } from '@polymech/commons'
import { detectAndHandle } from '../commands/handlers'
import { logger } from '../index'
import { IKBotOptions } from '../zod_types'
import { logger } from '../index.js'
import { IKBotOptions } from '../zod_types.js'
export const readStdin = async (timeoutMs: number = 100): Promise<Buffer> => {
return new Promise((resolve, reject) => {
@ -69,7 +70,7 @@ export const resolveQuery = async (options: IKBotOptions): Promise<string> => {
if (options.prompt) {
const queryPath = resolve(path.resolve(options.prompt) || '');
if (exists(queryPath) && isFile(queryPath)) {
const fileContent = read(queryPath, null) as Buffer;
const fileContent = read(queryPath, 'buffer') as Buffer;
try {
return await detectAndHandle(fileContent,options)
} catch (error) {

View File

@ -1,7 +1,7 @@
import * as path from 'path'
import { sync as write } from '@polymech/fs/write'
import { resolve } from '@polymech/osr-commons'
import { IKBotOptions } from '../zod_types'
import { resolve } from '@polymech/commons'
import { IKBotOptions } from '../zod_types.js'
export const dumpAsScript = async (opts: IKBotOptions) => {
if (!opts.dump) {

View File

@ -1,28 +1,9 @@
import * as path from 'path'
import { pathInfoEx, resolve } from '@polymech/osr-commons'
import { resolveConfig } from '@polymech/core'
import { isString } from '@polymech/core/primitives'
import { pathInfo, DEFAULT_ROOTS, DEFAULT_VARS } from '@polymech/osr-commons'
import * as fs from 'fs'
import { sync as read } from '@polymech/fs/read'
import { sync as dir } from '@polymech/fs/dir'
import { createItem as toNode } from '@polymech/fs/inspect'
import { INode } from '@polymech/fs/interfaces'
import { sync as exists } from '@polymech/fs/exists'
import { isFile, forward_slash } from '@polymech/osr-commons'
import { logger } from './index'
import { lookup } from 'mime-types'
import { globSync } from 'glob'
import { EXCLUDE_GLOB, MAX_FILE_SIZE } from './constants'
import { defaultMimeRegistry, IHandlerResult } from './mime-handlers'
import { pathInfoEx } from '@polymech/commons'
import { DEFAULT_ROOTS, DEFAULT_VARS } from '@polymech/commons'
import { IKBotTask } from './types'
export const variables = (options: IKBotTask) => {
const { model, router,baseURL } = options
export const variables = (options: IKBotTask) => {
const { model, router,baseURL } = options
let ret = {
model,
router,

View File

@ -3,21 +3,19 @@ import * as path from 'path'
import chalk from 'chalk'
import * as env from 'env-var'
import { sync as writeFS } from '@polymech/fs/write'
import { resolve } from '@polymech/osr-commons'
import { generate_interfaces, write, ZodMetaMap } from '@polymech/osr-commons'
import { resolve } from '@polymech/commons'
import { generate_interfaces, write, ZodMetaMap } from '@polymech/commons'
import { isString } from '@polymech/core/primitives'
import { API_PREFIX, LOGGING_DIRECTORY, PREFERENCES_FILE_NAME } from './constants'
import { API_PREFIX, LOGGING_DIRECTORY, PREFERENCES_FILE_NAME } from './constants.js'
export const get_var = (key: string ='') => env.get(key).asString() || env.get(key.replace(/-/g, '_')).asString() || env.get(key.replace(/_/g, '-')).asString()
export const HOME = (sub = '') => path.join(process.env[(process.platform == 'win32' ) ? 'USERPROFILE' : 'HOME'] || '', sub)
export const PREFERENCES_DEFAULT = (key: string = 'KBOT_PREFERENCES') => get_var(key) || path.join(HOME(`.${API_PREFIX}`), PREFERENCES_FILE_NAME)
import { Filters } from './filters'
import { models_dist } from './models'
import { defaultTemplate } from './tools'
import { Filters } from './filters.js'
import { models_dist } from './models.js'
import { defaultTemplate } from './tools.js'
export const E_Filters = z.enum(Object.keys(Filters) as any)