This commit is contained in:
Code 2025-01-30 00:50:58 +01:00
parent 5c11bb5d06
commit fae42d6c37
515 changed files with 87847 additions and 2240 deletions

View File

@ -1,12 +1,12 @@
{
"name": "@plastichub/osr-ai-tools",
"version": "0.3.1",
"version": "0.3.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@plastichub/osr-ai-tools",
"version": "0.3.1",
"version": "0.3.2",
"dependencies": {
"@plastichub/core": "^0.2.6",
"@plastichub/fs": "^0.13.41",
@ -16,12 +16,13 @@
"axios": "^1.7.9",
"cheerio": "^1.0.0",
"find-up": "^5.0.0",
"glob": "^11.0.1",
"inquirer": "^12.2.0",
"jsdom": "^25.0.1",
"marked": "^15.0.4",
"mime-types": "^2.1.35",
"nodemailer": "^6.9.16",
"openai": "^4.76.3",
"openai": "^4.80.1",
"p-map": "^4.0.0",
"puppeteer": "^23.11.1",
"screenshot-desktop": "^1.15.0",
@ -41,11 +42,11 @@
"devDependencies": {
"@types/jsdom": "^21.1.7",
"@types/marked": "^6.0.0",
"@types/node": "^18.19.68",
"@types/node": "^18.19.74",
"@types/nodemailer": "^6.4.17",
"@types/turndown": "^5.0.5",
"@types/yargs": "^17.0.33",
"ts-node": "^10.9.0",
"ts-node": "^10.9.2",
"typescript": "^4.9.5"
}
},
@ -610,6 +611,87 @@
"node": ">= 8.0.0"
}
},
"node_modules/@plastichub/fs/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@plastichub/fs/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/fs/node_modules/glob/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/fs/node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/@plastichub/fs/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/@plastichub/fs/node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/osr-commons": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@plastichub/osr-commons/-/osr-commons-0.5.3.tgz",
@ -637,93 +719,6 @@
"node": ">= 14.0.0"
}
},
"node_modules/@plastichub/osr-commons/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@plastichub/osr-commons/node_modules/glob": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/osr-commons/node_modules/jackspeak": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/osr-commons/node_modules/lru-cache": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@plastichub/osr-commons/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/osr-commons/node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@plastichub/osr-commons/node_modules/typescript": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
@ -898,9 +893,9 @@
}
},
"node_modules/@types/node": {
"version": "18.19.68",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz",
"integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==",
"version": "18.19.74",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.74.tgz",
"integrity": "sha512-HMwEkkifei3L605gFdV+/UwtpxP6JSzM+xFk2Ia6DNFSwSVBRh9qp5Tgf4lNFOMfPVuU0WnkcWpXZpgn5ufO4A==",
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
@ -2422,21 +2417,24 @@
}
},
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
"integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
@ -2520,15 +2518,15 @@
}
},
"node_modules/glob/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@ -2858,18 +2856,18 @@
"license": "ISC"
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/js-tokens": {
@ -3047,10 +3045,13 @@
}
},
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/mailsplit": {
"version": "5.4.2",
@ -3352,9 +3353,9 @@
}
},
"node_modules/openai": {
"version": "4.77.0",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.77.0.tgz",
"integrity": "sha512-WWacavtns/7pCUkOWvQIjyOfcdr9X+9n9Vvb0zFeKVDAqwCMDHB+iSr24SVaBAhplvSG6JrRXFpcNM9gWhOGIw==",
"version": "4.80.1",
"resolved": "https://registry.npmjs.org/openai/-/openai-4.80.1.tgz",
"integrity": "sha512-+6+bbXFwbIE88foZsBEt36bPkgZPdyFN82clAXG61gnHb2gXdZApDyRrcAHqEtpYICywpqaNo57kOm9dtnb7Cw==",
"license": "Apache-2.0",
"dependencies": {
"@types/node": "^18.11.18",
@ -3369,9 +3370,13 @@
"openai": "bin/cli"
},
"peerDependencies": {
"ws": "^8.18.0",
"zod": "^3.23.8"
},
"peerDependenciesMeta": {
"ws": {
"optional": true
},
"zod": {
"optional": true
}
@ -3617,16 +3622,16 @@
}
},
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": ">=16 || 14 >=14.18"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@ -3937,93 +3942,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/jackspeak": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/lru-cache": {
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
"license": "ISC",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/rimraf/node_modules/minimatch": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/path-scurry": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rotating-file-stream": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/rotating-file-stream/-/rotating-file-stream-3.2.5.tgz",

View File

@ -31,7 +31,7 @@
"marked": "^15.0.4",
"mime-types": "^2.1.35",
"nodemailer": "^6.9.16",
"openai": "^4.76.3",
"openai": "^4.80.1",
"p-map": "^4.0.0",
"puppeteer": "^23.11.1",
"screenshot-desktop": "^1.15.0",

View File

@ -0,0 +1,14 @@
node_modules
npm-debug.log
Dockefile
.dockerignore
.git
.gitignore
README.md
.env
.env.*
*.log
coverage
.kbot
dist
build

View File

@ -0,0 +1 @@
{}

37
packages/osr-code-bot/.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
# Deno
.deno
deno.lock
deno.json._decorators
# Dependencies
node_modules/
# Build output
build/
out/
# Environment files
.env*
!src/.env/
!src/.env/*md
# Generated files
.dts
types/
.D_Store
.vscode/!settings.json
# Logs
*.Log
*.Log.*
docs
docs-internal
systems/code-server-defaults
kbot-extensions
systems/workspace/kbot-docs
systems/.code-server/code-server-ipc.sock
systems/.code-server/User/workspaceStorage/
systems/code-server-defaults
systems/.code-server
kbot-tests
kbot-extensions

View File

@ -0,0 +1,49 @@
# Ignore node_modules directory
node_modules/
# Ignore log files
*.log
# Ignore temporary files
*.tmp
# Ignore coverage reports
coverage/
.kbot
docs
docs_
.env
report
.vscode
config
systems
tools.json
commit.json
docker.sh
pnpm-lock.yaml
package-lock.json
scripts
todos.md
tests
tmp
dist/node_modules
dist/data
dist/.kbot
dist/package-lock.json
# Logs
*.Log
*.Log.*
docs
docs-internal
systems/code-server-defaults
kbot-extensions
systems/workspace/kbot-docs
systems/.code-server/code-server-ipc.sock
systems/.code-server/User/workspaceStorage/
systems/code-server-defaults
systems/.code-server
kbot-tests
kbot-extensions

View File

@ -0,0 +1,2 @@
registry=https://registry.npmjs.org/
save-exact=true

View File

@ -0,0 +1,51 @@
# Travis CI Configuration
language: node_js
# Specify the operating systems
os:
- linux
- osx
- windows
# Specify the Node.js versions to test on
node_js:
- "node" # latest stable node
# Specific operating system and Node.js version combinations
matrix:
include:
# Linux (Ubuntu)
- os: linux
dist: ubuntu-latest
node_js: "node"
# macOS
- os: osx
node_js: "node"
# Windows
- os: windows
node_js: "node"
# Cache node_modules between builds
cache:
directories:
- node_modules
# Install dependencies
install:
- npm ci
# Run tests
script:
- npm test
# Before deployment scripts (optional)
before_deploy:
- npm run build
# Notifications
notifications:
email:
on_success: change
on_failure: always

View File

@ -0,0 +1,528 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "create",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"create",
"typescript",
"-p=../ai-tests",
"-n=test-simple",
"--app='Command-1 : Distance by car, using Google, output the result at a given path. Create a file at src/constants.ts with the following content: export const GOOGLE_API_KEY'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"../ai-tests/test-simple",
"--prompt='Add another command: create json schemas for functions in src/lib/*, using ts-json-schema-generator'",
"--output='../ai-tests/test-simple-modified'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:git",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}/tests/typescript",
"args": [
"init repository, using git tool",
"--logLevel=1",
"--router=openai",
"--model=gpt-4o",
"--disable='npm,terminal,user,interact,web,search'",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:templates:solidworks",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"../sw-test/",
"--prompt='create for each *.cs file a dedicated documentation (with example code), eg: src_file.md, link them in readme.md'",
"--template=./solidworks",
"--include='*.md,*.cs'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:prompt:docker",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='./systems/prompt-docker.md'",
"--template=typescript",
"--disable=npm",
"--include='systems/**'",
"--dump='./test.sh'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:iterator",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='for each file in src/commands/*.ts, write a report in /reports/commands/file_name.md (skip existing reports using the file_exists tool), detected problems, possible solutions, and a conclusion, and example code'",
//"--template=typescript",
"--disable=npm,terminal",
"--include='src/*.tsx,src/*.ts'",
"--disable=terminal",
"--dump='./test.sh'",
"--include='src/*.ts'",
"--disable=2",
"--include=false"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:search:google",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='search google, osr-plastic extruders; write it as markdown in ./tests/search/google.md'",
"--disable='npm,terminal'",
"--include='./tests/search/google'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:search:serpapi",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='Find all post industrial plastic traders in Dresden Germany, using serpapi (map), write it to ./tests/search/yammi.md'",
"--disable='npm,terminal'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:interact",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='use the interact tool to figure a person has psychopathic tendencies, ask at least 3 questions but not direct, store the result in prefs.json, as probabilty (merge), with reasons why; its for a llm study'",
"--template=typescript",
"--disable=npm",
"--include='tests/*.json'",
"--include='tests/*.md'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:web",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"./",
"--prompt='summarize https://community.preciousplastic.com/u/farm-fab-lab-by-plat-institute using the web tool, store the result ( and all found links ) in ./tests/summarize/oa-tests.md'",
"--disable=npm,terminal",
"--include='tests/*.md'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "deepseek",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"summarize https://community.preciousplastic.com/u/farm-fab-lab-by-plat-institute using the web tool, store the result ( and all found links ) in ./tests/summarize/oa-tests.md",
"--disable=npm,terminal,git,fs",
"--router=deepseek",
"--tools=fs"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "modify:tools:email",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'send John the latest wheather report for Tarragona, as email'",
"--disable='npm,terminal'",
"--include='tests/*.md'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal", // <= the relevant part
},
{
"type": "node",
"request": "launch",
"name": "modify:tools:terminal:astro",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'create static site with Astro, using terminal tool'",
"--disable='npm,git'",
"--path=./tests/astro-test"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "types",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"types"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "modify:tools:search",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'meaning of life, save to ./tests/search/meaning-of-life.md'",
"--logLevel=1",
"--include=src/commands/*.ts",
"--include=src/zod_schema.ts",
"--disable='npm,terminal,interact,git,search'",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "assistant:code",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'security audit for the given files, refer to code, and file names'",
"--include=src/zod_schema.ts",
"--disable='npm,terminal,interact,git,search'",
"--mode=assistant",
"--router=openai",
"--model=gpt-4o",
"--dst=./tests/assistant/code.md",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "assistant:pdf",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'total price(s) for all stainless parts (304), as markdown table, group by part prefixes'",
"--include=./tests/assistant/invoice.pdf",
"--disable='npm,terminal,interact,git,search'",
"--mode=assistant",
"--router=openai",
"--model=gpt-4o",
"--dst=./tests/assistant/invoice.md",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "assistant:md",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'identify all components (and brand), as markdown table, with location, with links, there are PIDs and a Controllino mini'",
"--include2=./docs_/*.md",
"--include=./tests/images/elzm-cab.jpg",
"--disable='npm,terminal,interact,git,search'",
"--router2=openai",
"--model2=gpt-4o",
"--mode=completion",
"--dst=./tests/assistant/elzm.md",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "modify:each:vars",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"summarize",
"--logLevel=1",
"--var-test=foo",
"--dry",
"--each=docs_/parameters.md",
"--dst=./tests/each/${SRC_DIR}/${SRC_NAME}-${MODEL}-${ROUTER}.md",
"--disable='npm,terminal,interact,git,search'",
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std",
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "modify:tools:test",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"'dd a custom help function for yargs, write to src/help.ts, apply in src/main.ts'",
"--logLevel=2",
"--include2='tests/images-random/*.jpg'",
"--include2='src/main.ts'",
"--include2='src/zod_schema.ts'",
"--include='tests/*.mp4'",
"--include='tests/images/*.jpg'",
"--include='C:\\Users\\zx\\Desktop\\osr\\tools-output.json'",
"--include='C:\\Users\\zx\\Desktop\\osr\\osr-code-bot\\docs_\\docker.md'",
"--include='D:\\Users\\mc007\\Desktop\\osr\\osr-search\\types2.js'",
"--disable='npm,terminal,search,interact,git'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**"
],
"outputCapture": "std",
"console": "integratedTerminal", // <= the relevant part
},
{
"type": "node",
"request": "launch",
"name": "modify:hono",
"skipFiles": [],
"program": "${workspaceFolder}\\main.js",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}",
"args": [
"modify",
"--path='../sw-test'",
"--prompt='take a screenshot (tool capture_screen), store the content as markdown in latest.md'"
],
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
],
"outputCapture": "std"
},
{
"type": "node",
"request": "launch",
"name": "Debug Current Test File",
"autoAttachChildProcesses": true,
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**"
],
"program": "${workspaceRoot}/node_modules/vitest/vitest.mjs",
"args": [
"run",
"${relativeFile}"
],
"smartStep": true,
"console": "integratedTerminal"
}
]
}

View File

@ -0,0 +1,205 @@
# @plastichub/code-bot
AI-powered command-line tool for code modifications and project management that supports multiple AI models and routers.
## Overview
Code-bot is a powerful CLI tool that helps developers automate code modifications, handle project management tasks, and integrate with various AI models for intelligent code and content assistance.
## Quick Start
### Installation Steps
KBot requires Node.js to run. It's recommended to use Node.js version 18 or higher.
1. Visit the official [Node.js website](https://nodejs.org/)
2. Download the LTS (Long Term Support) version for your operating system
3. Follow the installation wizard
4. Verify installation by opening a terminal and running:
```bash
node --version
npm --version
```
### API Keys
KBot supports both OpenRouter and OpenAI APIs. You'll need at least one of these set up.
#### OpenRouter API (Recommended)
1. Visit [OpenRouter](https://openrouter.ai/)
2. Sign up for an account
3. Navigate to the API Keys section
4. Create a new API key
#### OpenAI API (Optional)
1. Go to [OpenAI's platform](https://platform.openai.com/)
2. Create an account or sign in
3. Navigate to API keys section
4. Create a new secret key
### Installation using Node NPM package manager
```bash
npm install -g @plastichub/code-bot
```
## Configuration
### API Keys Setup
Create configuration at `$HOME/.osr/.config.json` (or export OSR_CONFIG with path to config.json):
```json
{
"openrouter": {
"key": "your-openrouter-key"
},
"openai": {
"key": "your-openai-key"
},
"email": {
"newsletter": {
"host": "host.org",
"port": 465,
"debug": true,
"transactionLog": true,
"auth": {
"user": "foo@bar.com",
"pass": "pass"
}
}
},
"google": {
"cse": "custom search engine id",
"api_key": "google custom search api key"
},
"serpapi": {
"key": "your SerpAPI key (optional, used for web searches(places, google maps))"
},
}
```
### Preferences Setup
Optionally, create `.kbot/preferences.md` in your project directory to customize AI interactions:
```markdown
## My Preferences
Gender : male
Location : New York, USA (eg: `send me all saunas next to me`)
Language : English
Occupation : software developer, Typescript
Age : 30+
## Contacts
My email address : example@email.com (eg: `send me latest hacker news`)
My wife's email address ("Anne") : example@email.com (eg: `send email to my wife, with latest local news')
## Content
When creating content
- always Markdown
- always add links
- when sending emails, always add 'Best regards, [Your Name]'
```
# Command Line Parameters
This document describes all available command line parameters.
## Core Parameters
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `path` | Target directory | `.` | No |
| `prompt` | The prompt. Supports file paths and environment variables | `./prompt.md` | No |
| `output` | Optional output path for modified files (Tool mode only) | - | No |
| `dst` | Optional destination path for the result, will substitute ${MODEL} and ${ROUTER} in the path. Used for "completion" mode | - | No |
| `model` | AI model to use for processing | `anthropic/claude-3.5-sonnet` | No |
| `router` | Router to use: openai or openrouter | `openrouter` | No |
| `mode` | Chat completion mode: "completion" (without tools) or "tools" | `tools` | No |
## File Selection & Tools
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `include` | Glob patterns to match files for processing. Supports multiple patterns, e.g. `--include=src/*.tsx,src/*.ts --include=package.json` | - | No |
| `disable` | Disable tools categories | `[]` | No |
| `disableTools` | List of specific tools to disable | `[]` | No |
## Configuration & Profiles
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `profile` | Path to profile for variables. Supports environment variables | `${POLYMECH-ROOT}/profile.json` | No |
| `env` | Environment (in profile) | `default` | No |
| `config` | Path to JSON configuration file (API keys). Supports environment variables | - | No |
| `preferences` | Path to preferences file (location, email, gender, etc). Supports environment variables | `./.kbot/preferences.md` | No |
## Debugging & Logging
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `logLevel` | Logging level for the application (0-4) | `2` | No |
| `logs` | Logging directory | `./.kbot` | No |
| `dump` | Create a script | - | No |
| `dry` | Dry run - only write out parameters without making API calls | `false` | No |
## Examples
```bash
# Basic usage with default parameters
kbot --prompt="What are the changes needed?"
# Specify model and router
kbot --model="gpt-4" --router="openai" --prompt="Analyze this code"
# Process specific files
kbot --include="src/*.ts" --include="package.json" --prompt="Check for security issues"
# Dry run with custom logging
kbot --dry=true --logLevel=4 --prompt="Test run"
```
## Environment Variables
Many path-based parameters support environment variables using the `${VARIABLE}` syntax:
- `${POLYMECH-ROOT}` - Root directory for Polymech
- `${OSR-ROOT}` - Root directory for OSR
Example:
```bash
kbot --profile="${POLYMECH-ROOT}/custom-profile.json"
```
# Working on Larger Directories
Since LLMs (Large Language Models) and providers are limited to very small 'context windows', it's necessary to feed them with smaller chunks instead. This document explains how to process larger directories efficiently.
## Directory Processing Example
Here's an example of how to walk through files and process them:
```bash
osr-cli each --main='kbot \"read ${KEY} and translate to german, save in docs/language code/filename.md\" --include=\"${REL}\" --include=\".kbot/preferences.md\"' --list="./docs/*.md" --cwd=.
```
### Parameter Explanation
- `each`: Command to process multiple files iteratively
- `--main`: The main command (`kbot`) to execute for each file
- `--include=\"${REL}\"` instructs kbot to include the current selected path
- `--include=\".kbot/preferences.md\"` instructs kbot to include additional preferences about the task (eg: translation specifics)
- `--list`: Specifies the file pattern to match
- Supports include patterns (e.g., `"./docs/*.md"`)
- `--cwd`: Sets the current working directory for the command execution. Default is the current directory (`.`)
**Note** requires `@plastichub/osr-cli-commons` to be installed globally:
```bash
npm i -g @plastichub/osr-cli-commons
```

View File

@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createClient = void 0;
const openai_1 = require("openai");
const index_1 = require("./index");
const config_1 = require("./config");
const createClient = (options) => {
const config = (0, config_1.loadConfig)(options);
let apiKey = options.api_key;
if (!config) {
index_1.logger.error("Config not found in $HOME/.osr/config.json. " +
"Optionally, export OSR_CONFIG with the path to the configuration file, ");
return undefined;
}
const router = options.router ?? "openrouter";
let baseURL = options.baseURL;
if (!options.baseURL) {
switch (router) {
case "openrouter":
apiKey = apiKey || config?.openrouter?.key;
if (!options.baseURL) {
baseURL = "https://openrouter.ai/api/v1";
}
break;
case "openai":
apiKey = apiKey || config?.openai?.key;
break;
case "deepseek":
apiKey = apiKey || config?.deepseek?.key;
if (!options.baseURL) {
baseURL = "https://api.deepseek.com";
}
break;
}
}
if (!apiKey) {
index_1.logger.error(`No ${router} key found. Please provide an "api_key", set it in the config, or pass it via JSON config.`);
return undefined;
}
if (router === "openrouter" && !options.model) {
options.model = "anthropic/claude-3.5-sonnet";
}
if (router === "openai" && !options.model) {
options.model = "gpt-4o";
}
if (router === "deepseek" && !options.model) {
options.model = "deepseek-chat";
}
index_1.logger.info(`Creating client with ${router} router, model ${options.model}, and API key ${apiKey} at ${baseURL}`);
return new openai_1.OpenAI({
apiKey,
baseURL,
});
};
exports.createClient = createClient;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBK0I7QUFDL0IsbUNBQWdDO0FBQ2hDLHFDQUFxQztBQUc5QixNQUFNLFlBQVksR0FBRyxDQUFDLE9BQXFCLEVBQUUsRUFBRTtJQUNsRCxNQUFNLE1BQU0sR0FBRyxJQUFBLG1CQUFVLEVBQUMsT0FBTyxDQUFDLENBQUE7SUFDbEMsSUFBSSxNQUFNLEdBQVcsT0FBTyxDQUFDLE9BQU8sQ0FBQTtJQUNwQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixjQUFNLENBQUMsS0FBSyxDQUNSLDhDQUE4QztZQUM5Qyx5RUFBeUUsQ0FDNUUsQ0FBQztRQUNGLE9BQU8sU0FBUyxDQUFBO0lBQ3BCLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLFlBQVksQ0FBQTtJQUM3QyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFBO0lBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkIsUUFBUSxNQUFNLEVBQUUsQ0FBQztZQUNiLEtBQUssWUFBWTtnQkFDYixNQUFNLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDO2dCQUMzQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNuQixPQUFPLEdBQUcsOEJBQThCLENBQUE7Z0JBQzVDLENBQUM7Z0JBQ0QsTUFBTTtZQUNWLEtBQUssUUFBUTtnQkFDVCxNQUFNLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDO2dCQUN2QyxNQUFNO1lBQ1YsS0FBSyxVQUFVO2dCQUNYLE1BQU0sR0FBRyxNQUFNLElBQUksTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ25CLE9BQU8sR0FBRywwQkFBMEIsQ0FBQTtnQkFDeEMsQ0FBQztnQkFDRCxNQUFNO1FBQ2QsQ0FBQztJQUNMLENBQUM7SUFFRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixjQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sTUFBTSw0RkFBNEYsQ0FBQyxDQUFDO1FBQ3ZILE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFJLE1BQU0sS0FBSyxZQUFZLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDNUMsT0FBTyxDQUFDLEtBQUssR0FBRyw2QkFBNkIsQ0FBQTtJQUNqRCxDQUFDO0lBRUQsSUFBSSxNQUFNLEtBQUssUUFBUSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3hDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFBO0lBQzVCLENBQUM7SUFFRCxJQUFJLE1BQU0sS0FBSyxVQUFVLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDMUMsT0FBTyxDQUFDLEtBQUssR0FBRyxlQUFlLENBQUE7SUFDbkMsQ0FBQztJQUVELGNBQU0sQ0FBQyxJQUFJLENBQUMsd0JBQXdCLE1BQU0sa0JBQWtCLE9BQU8sQ0FBQyxLQUFLLGlCQUFpQixNQUFNLE9BQU8sT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNqSCxPQUFPLElBQUksZUFBTSxDQUFDO1FBQ2QsTUFBTTtRQUNOLE9BQU87S0FDVixDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUF0RFksUUFBQSxZQUFZLGdCQXNEeEIifQ==

View File

@ -0,0 +1,77 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.collector = void 0;
const path_1 = __importDefault(require("path"));
const osr_log_1 = require("@plastichub/osr-log");
const osr_commons_1 = require("@plastichub/osr-commons");
const _1 = require("./");
const collector = (options, client) => {
return {
//OpenAI
onMessage: (message) => {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'openai-message.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onMessage', logFile);
logger.info(message);
},
onToolCall: async (message) => {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'tool-call.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onToolCall', logFile);
try {
const msg = { ...message, arguments: JSON.parse(message.arguments) };
logger.debug(msg);
}
catch (e) {
logger.debug(message);
}
},
onFunctionCallResult: (message) => {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'tool-call-result.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onFunctionCallResult', logFile);
try {
const msg = { message: JSON.parse(message) };
logger.debug(msg);
}
catch (e) {
logger.debug(message);
}
},
onChatCompletion: (message) => {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'completion.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onChatCompletion', logFile);
logger.debug(message);
},
onContent: (content) => {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'content.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onContent', logFile);
logger.debug(content);
},
onTool(category, name, args, result) {
const logFile = path_1.default.resolve(path_1.default.join((0, osr_commons_1.resolve)(options.logs), 'tool.json'));
const logger = (0, osr_log_1.winstonLogger)('collector:onTool', logFile);
logger.debug({ category, name, args, result });
},
onToolBefore: async (ctx, args) => {
try {
_1.logger.debug(`onToolBefore :${ctx.name}`);
}
catch (e) {
_1.logger.error(e);
}
return args;
},
onToolAfter: async (ctx, args, result) => {
try {
_1.logger.debug(`onToolAfter : ${ctx.name}`);
}
catch (e) {
_1.logger.error(e);
}
return result[0];
}
};
};
exports.collector = collector;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NvbGxlY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxnREFBdUI7QUFLdkIsaURBQW9EO0FBQ3BELHlEQUFpRDtBQUlqRCx5QkFBMkM7QUFHcEMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxPQUFxQixFQUFFLE1BQWMsRUFBYyxFQUFFO0lBQzNFLE9BQU87UUFDSCxRQUFRO1FBQ1IsU0FBUyxFQUFFLENBQUMsT0FBbUMsRUFBRSxFQUFFO1lBQy9DLE1BQU0sT0FBTyxHQUFHLGNBQUksQ0FBQyxPQUFPLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFBLHFCQUFPLEVBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLHFCQUFxQixDQUFDLENBQUMsQ0FBQTtZQUNyRixNQUFNLE1BQU0sR0FBRyxJQUFBLHVCQUFhLEVBQUMscUJBQXFCLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDNUQsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUN4QixDQUFDO1FBQ0QsVUFBVSxFQUFFLEtBQUssRUFBRSxPQUEyQyxFQUFFLEVBQUU7WUFDOUQsTUFBTSxPQUFPLEdBQUcsY0FBSSxDQUFDLE9BQU8sQ0FBQyxjQUFJLENBQUMsSUFBSSxDQUFDLElBQUEscUJBQU8sRUFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFBO1lBQ2hGLE1BQU0sTUFBTSxHQUFHLElBQUEsdUJBQWEsRUFBQyxzQkFBc0IsRUFBRSxPQUFPLENBQUMsQ0FBQTtZQUM3RCxJQUFJLENBQUM7Z0JBQ0QsTUFBTSxHQUFHLEdBQUcsRUFBRSxHQUFHLE9BQU8sRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQTtnQkFDcEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtZ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

View File

@ -0,0 +1,43 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.build = void 0;
const path_1 = __importDefault(require("path"));
const read_1 = require("@plastichub/fs/read");
const write_1 = require("@plastichub/fs/write");
const exists_1 = require("@plastichub/fs/exists");
const __1 = require("../");
const openai_1 = require("../models/openai");
const openrouter_1 = require("../models/openrouter");
const osr_commons_1 = require("@plastichub/osr-commons");
const build = async () => {
const examplesSrc = path_1.default.resolve(__dirname, '../docs_/examples.md');
if ((0, exists_1.sync)(examplesSrc)) {
const examples = (0, read_1.sync)(examplesSrc, 'string') || '';
const examplesPath = path_1.default.resolve(__dirname, '../src/docs-internal/examples.ts');
(0, write_1.sync)(examplesPath, `export const examples = ${JSON.stringify(examples)}`);
__1.logger.info(`Examples file generated " ${examplesPath}`);
}
else {
__1.logger.error(`Examples file not found ${examplesSrc}`);
}
const config = (0, osr_commons_1.CONFIG_DEFAULT)();
const modelsOpenAI = await (0, openai_1.fetchOpenAIModels)(config.openai.key);
const modelsOpenRouter = (await (0, openrouter_1.fetchOpenRouterModels)()).map((model) => {
return {
id: model.id,
name: model.name,
pricing: model.pricing,
context: model.context,
created: model.created
};
});
const modelsOpenAIPath = path_1.default.resolve(__dirname, '../src/models/cache/openai.ts');
(0, write_1.sync)(modelsOpenAIPath, `export const models = ${JSON.stringify(modelsOpenAI)}`);
const modelsOpenRouterPath = path_1.default.resolve(__dirname, '../src/models/cache/openrouter.ts');
(0, write_1.sync)(modelsOpenRouterPath, `export const models = ${JSON.stringify(modelsOpenRouter)}`);
};
exports.build = build;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvYnVpbGQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsZ0RBQXVCO0FBRXZCLDhDQUFrRDtBQUNsRCxnREFBb0Q7QUFDcEQsa0RBQXNEO0FBQ3RELDJCQUE0QjtBQUM1Qiw2Q0FBb0Q7QUFDcEQscURBQTZFO0FBQzdFLHlEQUF3RDtBQUdqRCxNQUFNLEtBQUssR0FBRyxLQUFLLElBQUksRUFBRTtJQUM5QixNQUFNLFdBQVcsR0FBSSxjQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxzQkFBc0IsQ0FBQyxDQUFBO0lBQ3BFLElBQUcsSUFBQSxhQUFNLEVBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUN2QixNQUFNLFFBQVEsR0FBRyxJQUFBLFdBQUksRUFBQyxXQUFXLEVBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ2pELE1BQU0sWUFBWSxHQUFHLGNBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLGtDQUFrQyxDQUFDLENBQUE7UUFDaEYsSUFBQSxZQUFLLEVBQUMsWUFBWSxFQUFDLDJCQUEyQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUN6RSxVQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixZQUFZLEVBQUUsQ0FBQyxDQUFBO0lBQzFELENBQUM7U0FBSSxDQUFDO1FBQ0osVUFBTSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsV0FBVyxFQUFFLENBQUMsQ0FBQTtJQUN4RCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBYyxHQUFTLENBQUE7SUFFdEMsTUFBTSxZQUFZLEdBQUksTUFBTSxJQUFBLDBCQUFpQixFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDaEUsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLE1BQU0sSUFBQSxrQ0FBcUIsR0FBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDckUsT0FBTztZQUNMLEVBQUUsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUNaLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSTtZQUNoQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztTQUN2QixDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDRixNQUFNLGdCQUFnQixHQUFHLGNBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLCtCQUErQixDQUFDLENBQUE7SUFDakYsSUFBQSxZQUFLLEVBQUMsZ0JBQWdCLEVBQUMseUJBQXlCLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBRS9FLE1BQU0sb0JBQW9CLEdBQUcsY0FBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsbUNBQW1DLENBQUMsQ0FBQTtJQUN6RixJQUFBLFlBQUssRUFBQyxvQkFBb0IsRUFBQyx5QkFBeUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQTtBQUN6RixDQUFDLENBQUE7QUE1QlksUUFBQSxLQUFLLFNBNEJqQiJ9

View File

@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.examples = void 0;
const marked_1 = require("marked");
const marked_terminal_1 = require("marked-terminal");
const examples_1 = require("../docs-internal/examples");
const examples = () => {
marked_1.marked.use((0, marked_terminal_1.markedTerminal)({
emoji: false,
}));
process.stdout.write((0, marked_1.marked)(examples_1.examples));
};
exports.examples = examples;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhhbXBsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvZXhhbXBsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQStCO0FBQy9CLHFEQUFnRDtBQUNoRCx3REFBK0Q7QUFFeEQsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFO0lBQzNCLGVBQU0sQ0FBQyxHQUFHLENBQUMsSUFBQSxnQ0FBYyxFQUN2QjtRQUNFLEtBQUssRUFBRSxLQUFLO0tBQ2IsQ0FDRixDQUFDLENBQUE7SUFDRixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFBLGVBQU0sRUFBQyxtQkFBTyxDQUFXLENBQUMsQ0FBQTtBQUNqRCxDQUFDLENBQUE7QUFQWSxRQUFBLFFBQVEsWUFPcEIifQ==

View File

@ -0,0 +1,40 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetch = void 0;
const path_1 = __importDefault(require("path"));
const write_1 = require("@plastichub/fs/write");
const __1 = require("..");
const openai_1 = require("../models/openai");
const openrouter_1 = require("../models/openrouter");
const osr_commons_1 = require("@plastichub/osr-commons");
const fetch = async () => {
const config = (0, osr_commons_1.CONFIG_DEFAULT)();
if (config.openai && config.openai.key) {
const modelsOpenAI = await (0, openai_1.fetchOpenAIModels)(config.openai.key);
if (modelsOpenAI) {
const modelsOpenAIPath = path_1.default.resolve((0, __1.module_root)(), 'openai.json');
(0, write_1.sync)(modelsOpenAIPath, modelsOpenAI);
__1.logger.info(`Fetched ${modelsOpenAI.length} OpenAI models, to ${modelsOpenAIPath}`);
}
else {
__1.logger.error(`Failed to fetch OpenAI models`);
}
}
const modelsOpenRouter = (await (0, openrouter_1.fetchOpenRouterModels)()).map((model) => {
return {
id: model.id,
name: model.name,
pricing: model.pricing,
context: model.context,
created: model.created
};
});
const modelsOpenRouterPath = path_1.default.resolve((0, __1.module_root)(), 'openrouter.json');
(0, write_1.sync)(modelsOpenRouterPath, modelsOpenRouter);
__1.logger.info(`Fetched ${modelsOpenRouter.length} OpenRouter models, to ${modelsOpenRouterPath}`);
};
exports.fetch = fetch;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmV0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvZmV0Y2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsZ0RBQXVCO0FBQ3ZCLGdEQUFvRDtBQUNwRCwwQkFBd0M7QUFDeEMsNkNBQW9EO0FBQ3BELHFEQUE0RDtBQUM1RCx5REFBd0Q7QUFFakQsTUFBTSxLQUFLLEdBQUcsS0FBSyxJQUFJLEVBQUU7SUFFOUIsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBYyxHQUFTLENBQUE7SUFDdEMsSUFBSSxNQUFNLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkMsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFBLDBCQUFpQixFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDL0QsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixNQUFNLGdCQUFnQixHQUFHLGNBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSxlQUFXLEdBQUUsRUFBRSxhQUFhLENBQUMsQ0FBQTtZQUNuRSxJQUFBLFlBQUssRUFBQyxnQkFBZ0IsRUFBRSxZQUFZLENBQUMsQ0FBQTtZQUNyQyxVQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsWUFBWSxDQUFDLE1BQU0sc0JBQXNCLGdCQUFnQixFQUFFLENBQUMsQ0FBQTtRQUNyRixDQUFDO2FBQU0sQ0FBQztZQUNOLFVBQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQTtRQUMvQyxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxNQUFNLElBQUEsa0NBQXFCLEdBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQ3JFLE9BQU87WUFDTCxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDWixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7WUFDaEIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztZQUN0QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87U0FDdkIsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFBO0lBQ0YsTUFBTSxvQkFBb0IsR0FBRyxjQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsZUFBVyxHQUFFLEVBQUUsaUJBQWlCLENBQUMsQ0FBQTtJQUMzRSxJQUFBLFlBQUssRUFBQyxvQkFBb0IsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFBO0lBQzdDLFVBQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxNQUFNLDBCQUEwQixvQkFBb0IsRUFBRSxDQUFDLENBQUE7QUFDakcsQ0FBQyxDQUFBO0FBMUJZLFFBQUEsS0FBSyxTQTBCakIifQ==

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseHandler = void 0;
class BaseHandler {
}
exports.BaseHandler = BaseHandler;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2hhbmRsZXJzL2Jhc2UtaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFLQSxNQUFzQixXQUFXO0NBR2hDO0FBSEQsa0NBR0MifQ==

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,70 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createHandlers = createHandlers;
exports.detectAndHandle = detectAndHandle;
const text_handler_1 = require("./text-handler");
const audio_handler_1 = require("./audio-handler");
const image_handler_1 = require("./image-handler");
const exists_1 = require("@plastichub/fs/exists");
const path = __importStar(require("path"));
function createHandlers(options) {
return [
new audio_handler_1.AudioHandler(options),
new image_handler_1.ImageHandler(options),
new text_handler_1.TextHandler(),
];
}
async function detectAndHandle(content, options) {
const handlers = createHandlers(options);
// Check if content is a file path
const contentStr = content.toString();
if ((0, exists_1.sync)(contentStr)) {
const filePath = path.resolve(contentStr);
for (const handler of handlers) {
if (await handler.canHandle(filePath, true)) {
return handler.handle(filePath, true);
}
}
}
// Handle as raw content
for (const handler of handlers) {
if (await handler.canHandle(content, false)) {
return handler.handle(content, false);
}
}
throw new Error('No suitable handler found for the input content');
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvaGFuZGxlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRQSx3Q0FNQztBQUVELDBDQXFCQztBQXBDRCxpREFBNEM7QUFDNUMsbURBQThDO0FBQzlDLG1EQUE4QztBQUM5QyxrREFBc0Q7QUFDdEQsMkNBQTRCO0FBRzVCLFNBQWdCLGNBQWMsQ0FBQyxPQUFxQjtJQUNsRCxPQUFPO1FBQ0wsSUFBSSw0QkFBWSxDQUFDLE9BQU8sQ0FBQztRQUN6QixJQUFJLDRCQUFZLENBQUMsT0FBTyxDQUFDO1FBQ3pCLElBQUksMEJBQVcsRUFBRTtLQUNsQixDQUFBO0FBQ0gsQ0FBQztBQUVNLEtBQUssVUFBVSxlQUFlLENBQUMsT0FBd0IsRUFBRSxPQUFxQjtJQUNuRixNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDeEMsa0NBQWtDO0lBQ2xDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN0QyxJQUFJLElBQUEsYUFBTSxFQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDdkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMxQyxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQy9CLElBQUksTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM1QyxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3hDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELHdCQUF3QjtJQUN4QixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQy9CLElBQUksTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzVDLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEMsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGlEQUFpRCxDQUFDLENBQUM7QUFDckUsQ0FBQyJ9

View File

@ -0,0 +1,68 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextHandler = void 0;
const base_handler_1 = require("./base-handler");
const read_1 = require("@plastichub/fs/read");
const path = __importStar(require("path"));
class TextHandler extends base_handler_1.BaseHandler {
async canHandle(content, isPath) {
if (isPath) {
// For file paths, check file extension
const ext = path.extname(content).toLowerCase();
return ['.txt', '.md', '.json', '.js', '.ts'].includes(ext);
}
// For raw content, try to decode as UTF-8 text
try {
if (Buffer.isBuffer(content)) {
content.toString('utf8');
}
return true;
}
catch {
return false;
}
}
async handle(content, isPath) {
if (isPath) {
// Read content from file
return (0, read_1.sync)(content, 'string');
}
// Return raw content as string
return Buffer.isBuffer(content) ? content.toString('utf8') : content;
}
}
exports.TextHandler = TextHandler;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2hhbmRsZXJzL3RleHQtaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxpREFBNkM7QUFDN0MsOENBQW1EO0FBQ25ELDJDQUE2QjtBQUU3QixNQUFhLFdBQVksU0FBUSwwQkFBVztJQUMxQyxLQUFLLENBQUMsU0FBUyxDQUFDLE9BQXdCLEVBQUUsTUFBZTtRQUN2RCxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsdUNBQXVDO1lBQ3ZDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBaUIsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzFELE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFFRCwrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDO1lBQ0gsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQzdCLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0IsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQXdCLEVBQUUsTUFBZTtRQUNwRCxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gseUJBQXlCO1lBQ3pCLE9BQU8sSUFBQSxXQUFJLEVBQUMsT0FBaUIsRUFBRSxRQUFRLENBQVcsQ0FBQztRQUNyRCxDQUFDO1FBRUQsK0JBQStCO1FBQy9CLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ3ZFLENBQUM7Q0FDRjtBQTVCRCxrQ0E0QkMifQ==

View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.help = void 0;
const marked_1 = require("marked");
const marked_terminal_1 = require("marked-terminal");
const zod_schema_1 = require("../zod_schema");
const osr_commons_1 = require("@plastichub/osr-commons");
const zod_1 = require("zod");
const help = () => {
const schema = (0, zod_schema_1.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 zod_1.z.ZodOptional;
const defaultValue = (0, osr_commons_1.getDefaultValue)(def);
const description = (0, osr_commons_1.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_1.marked.use((0, marked_terminal_1.markedTerminal)({
emoji: false
}));
const content = (0, marked_1.marked)(md.join('\n'));
process.stdout.write(content);
return content;
};
exports.help = help;
exports.default = async (argv) => {
return (0, exports.help)();
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9oZWxwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUErQjtBQUMvQixxREFBZ0Q7QUFFaEQsOENBQTZDO0FBQzdDLHlEQUF5RTtBQUN6RSw2QkFBdUI7QUFFaEIsTUFBTSxJQUFJLEdBQUcsR0FBRyxFQUFFO0lBQ3ZCLE1BQU0sTUFBTSxHQUFHLElBQUEsMEJBQWEsR0FBRSxDQUFBO0lBQzlCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFBO0lBQ3BDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUE7SUFFMUIsTUFBTSxFQUFFLEdBQUc7UUFDVCwrQkFBK0I7UUFDL0IsRUFBRTtRQUNGLFNBQVM7UUFDVCxpQ0FBaUM7UUFDakMsS0FBSztRQUNMLEVBQUU7UUFDRixnQkFBZ0I7UUFDaEIsRUFBRTtRQUNGLElBQUksSUFBSSxlQUFlO1FBQ3ZCLEVBQUU7UUFDRixZQUFZO1FBQ1osRUFBRTtLQUNILENBQUE7SUFFRCx5QkFBeUI7SUFDekIsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxHQUFHLFlBQVksT0FBQyxDQUFDLFdBQVcsQ0FBQTtRQUUvQyxNQUFNLFlBQVksR0FBRyxJQUFBLDZCQUFlLEVBQUMsR0FBRyxDQUFDLENBQUE7UUFDekMsTUFBTSxXQUFXLEdBQUcsSUFBQSw0QkFBYyxFQUFDLEdBQUcsQ0FBQyxDQUFBO1FBRXZDLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQyxDQUFBO1FBQ25CLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDWCxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixXQUFXLEVBQUUsQ0FBQyxDQUFBO1FBQ3RDLElBQUksWUFBWSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQy9CLEVBQUUsQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN6RCxDQUFDO1FBQ0QsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDaEQsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUNiLENBQUM7SUFFRCxlQUFNLENBQUMsR0FBRyxDQUFDLElBQUEsZ0NBQWMsRUFBQztRQUN4QixLQUFLLEVBQUUsS0FBSztLQUNiLENBQUMsQ0FBQyxDQUFBO0lBQ0gsTUFBTSxPQUFPLEdBQVcsSUFBQSxlQUFNLEVBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBVyxDQUFDO0lBQ3hELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQzdCLE9BQU8sT0FBTyxDQUFBO0FBQ2hCLENBQUMsQ0FBQTtBQTNDWSxRQUFBLElBQUksUUEyQ2hCO0FBRUQsa0JBQWUsS0FBSyxFQUFFLElBQVMsRUFBRSxFQUFFO0lBQ2pDLE9BQU8sSUFBQSxZQUFJLEdBQUUsQ0FBQTtBQUNmLENBQUMsQ0FBQSJ9

View File

@ -0,0 +1,142 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.init = void 0;
const dir_1 = require("@plastichub/fs/dir");
const exists_1 = require("@plastichub/fs/exists");
const write_1 = require("@plastichub/fs/write");
const path = __importStar(require("path"));
const tslog_1 = require("tslog");
const constants_1 = require("../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"
}
};
const init = async (argv) => {
const logger = new tslog_1.Logger({
hideLogPositionForProduction: true,
maskPlaceholder: '***',
name: constants_1.MODULE_NAME,
prettyLogTemplate: "{{logLevelName}}\t[{{filePathWithLine}}{{name}}]\t",
});
const kbotDir = path.resolve(path.join(process.cwd(), `.${constants_1.MODULE_NAME}`));
if (!(0, exists_1.sync)(kbotDir)) {
(0, dir_1.sync)(kbotDir);
}
// Create preferences file if it doesn't exist
const preferencesPath = path.resolve(kbotDir, 'preferences.md');
if (!(0, exists_1.sync)(preferencesPath)) {
(0, write_1.sync)(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 (!(0, exists_1.sync)(configPath)) {
(0, write_1.sync)(configPath, CONFIG_TEMPLATE);
logger.info(`📋 Created configuration file: ${configPath}`);
}
else {
logger.info(`📋 Configuration file already exists: ${configPath}`);
}
logger.info('📋 Initialization complete!');
return 0;
};
exports.init = init;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9pbml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDRDQUFnRDtBQUNoRCxrREFBc0Q7QUFDdEQsZ0RBQW9EO0FBQ3BELDJDQUE0QjtBQUU1QixpQ0FBK0I7QUFDL0IsNENBQTBDO0FBRTFDLE1BQU0sb0JBQW9CLEdBQUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0F5QjVCLENBQUE7QUFFRCxNQUFNLGVBQWUsR0FBRztJQUN0QixPQUFPLEVBQUU7UUFDUCxVQUFVLEVBQUUscUJBQXFCO1FBQ2pDLFVBQVUsRUFBRSxLQUFLO0tBQ2xCO0lBQ0QsV0FBVyxFQUFFO1FBQ1gsS0FBSyxFQUFFLHFCQUFxQjtLQUM3QjtJQUNELFVBQVUsRUFBRTtRQUNWLEtBQUssRUFBRSxtQkFBbUI7S0FDM0I7SUFDRCxTQUFTLEVBQUU7UUFDVCxLQUFLLEVBQUUsa0JBQWtCO0tBQzFCO0lBQ0QsUUFBUSxFQUFFO1FBQ1IsS0FBSyxFQUFFLGlCQUFpQjtLQUN6QjtJQUNELFNBQVMsRUFBRTtRQUNULEtBQUssRUFBRSxrQkFBa0I7S0FDMUI7SUFDRCxRQUFRLEVBQUU7UUFDUixLQUFLLEVBQUUsaUJBQWlCO0tBQ3pCO0lBQ0QsWUFBWSxFQUFFO1FBQ1osS0FBSyxFQUFFLHFCQUFxQjtLQUM3QjtJQUNELFFBQVEsRUFBRTtRQUNSLEtBQUssRUFBRSxpQkFBaUI7S0FDekI7SUFDRCxZQUFZLEVBQUU7UUFDWixLQUFLLEVBQUUscUJBQXFCO0tBQzdCO0lBQ0QsVUFBVSxFQUFFO1FBQ1YsS0FBSyxFQUFFLG1CQUFtQjtLQUMzQjtJQUNELFFBQVEsRUFBRTtRQUNSLEtBQUssRUFBRSxpQkFBaUI7UUFDeEIsU0FBUyxFQUFFLHFCQUFxQjtLQUNqQztDQUNGLENBQUE7QUFFTSxNQUFNLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBZSxFQUFFLEVBQUU7SUFDNUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxjQUFNLENBQVU7UUFDakMsNEJBQTRCLEVBQUUsSUFBSTtRQUNsQyxlQUFlLEVBQUUsS0FBSztRQUN0QixJQUFJLEVBQUUsdUJBQVc7UUFDakIsaUJBQWlCLEVBQUUsb0RBQW9EO0tBQ3hFLENBQUMsQ0FBQTtJQUNGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSx1QkFBVyxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3pFLElBQUksQ0FBQyxJQUFBLGFBQU0sRUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3JCLElBQUEsVUFBRyxFQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQ2QsQ0FBQztJQUNELDhDQUE4QztJQUM5QyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsQ0FBQyxDQUFBO0lBQy9ELElBQUksQ0FBQyxJQUFBLGFBQU0sRUFBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzdCLElBQUEsWUFBSyxFQUFDLGVBQWUsRUFBRSxvQkFBb0IsQ0FBQyxDQUFBO1FBQzVDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0NBQWdDLGVBQWUsRUFBRSxDQUFDLENBQUE7SUFDaEUsQ0FBQztTQUFJLENBQUM7UUFDSixNQUFNLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxlQUFlLEVBQUUsQ0FBQyxDQUFBO0lBQ3ZFLENBQUM7SUFFRCx5Q0FBeUM7SUFDekMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUE7SUFDdkQsSUFBSSxDQUFDLElBQUEsYUFBTSxFQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDeEIsSUFBQSxZQUFLLEVBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLFVBQVUsRUFBRSxDQUFDLENBQUE7SUFDN0QsQ0FBQztTQUFJLENBQUM7UUFDSixNQUFNLENBQUMsSUFBSSxDQUFDLHlDQUF5QyxVQUFVLEVBQUUsQ0FBQyxDQUFBO0lBQ3BFLENBQUM7SUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUE7SUFDMUMsT0FBTyxDQUFDLENBQUE7QUFDVixDQUFDLENBQUE7QUE5QlksUUFBQSxJQUFJLFFBOEJoQiJ9

View File

@ -0,0 +1,212 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAssistant = exports.createOpenAIFile = void 0;
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const __1 = require("../");
const run_completion_1 = require("./run-completion");
const source_1 = require("../source");
const prompt_1 = require("../prompt");
const console_1 = require("console");
const 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"
};
const createOpenAIFile = async (client, filePath, purpose = 'assistants') => {
return client.files.create({
file: fs.createReadStream(filePath),
purpose: purpose
});
};
exports.createOpenAIFile = createOpenAIFile;
/*
class EventHandler extends EventEmitter {
constructor(client) {
super();
// this.client = client;
}
async onEvent(event) {
try {
console.log(event);
// Retrieve events that are denoted with 'requires_action'
// since these will have our tool_calls
if (event.event === "thread.run.requires_action") {
await this.handleRequiresAction(
event.data,
event.data.id,
event.data.thread_id,
);
}
} catch (error) {
console.error("Error handling event:", error);
}
}
async handleRequiresAction(data, runId, threadId) {
try {
const toolOutputs =
data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {
if (toolCall.function.name === "getCurrentTemperature") {
return {
tool_call_id: toolCall.id,
output: "57",
};
} else if (toolCall.function.name === "getRainProbability") {
return {
tool_call_id: toolCall.id,
output: "0.06",
};
}
});
// Submit all the tool outputs at the same time
await this.submitToolOutputs(toolOutputs, runId, threadId);
} catch (error) {
console.error("Error processing required action:", error);
}
}
async submitToolOutputs(toolOutputs, runId, threadId) {
try {
// Use the submitToolOutputsStream helper
const stream = this.client.beta.threads.runs.submitToolOutputsStream(
threadId,
runId,
{ tool_outputs: toolOutputs },
);
for await (const event of stream) {
this.emit("event", event);
}
} catch (error) {
console.error("Error submitting tool outputs:", error);
}
}
}
*/
const runAssistant = async (client, params, options) => {
const sessionId = Date.now().toString();
const sessionMessages = {
sessionId,
prompt: options.prompt,
timestamp: new Date().toISOString(),
messages: []
};
if (options.dry) {
__1.logger.info('Dry run - skipping API call');
return {
result: 'DRY RUN',
sessionMessages,
result_raw: {},
toolCalls: []
};
}
const logMessage = (message, sessionId, prompt) => {
return {
...message,
timestamp: new Date().toISOString(),
sessionId,
prompt
};
};
let result = null;
const prompt_ = await (0, prompt_1.prompt)(options);
const assistant = await client.beta.assistants.create({
name: "Documents Assistant",
model: params.model,
tools: [{ type: "file_search" }, ...params.tools],
});
let files = (0, source_1.glob)(path.resolve(options.path), options.include) || [];
files = files.filter((f) => path.extname(f) in supported);
const attachments = await Promise.all(files.map(async (file) => {
const file_id = await (0, exports.createOpenAIFile)(client, file);
return {
file_id: file_id.id,
tools: [{ type: "file_search" }]
};
}));
const thread = await client.beta.threads.create({
messages: [
{
role: "user",
content: prompt_.content,
attachments: attachments,
}
],
});
let defer;
try {
defer = new Promise((resolve, reject) => {
const stream = client.beta.threads.runs
.stream(thread.id, {
assistant_id: assistant.id,
})
//.on("textCreated", (args) => logger.trace("assistant >",args))
.on("toolCallCreated", (event) => __1.logger.debug("Assistant : " + event.type))
.on("messageDone", async (event) => {
if (event.content[0].type === "text") {
resolve(event.content[0]);
}
});
return stream;
});
}
catch (e) {
__1.logger.error(`Failed to run assistant: ${e.message}`, console_1.error);
}
const ret = await defer;
return await (0, run_completion_1.onCompletion)(ret.text.value, options);
};
exports.runAssistant = runAssistant;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLWFzc2lzdGFudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9ydW4tYXNzaXN0YW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJDQUE0QjtBQUM1Qix1Q0FBd0I7QUFHeEIsMkJBQTRCO0FBQzVCLHFEQUErQztBQUMvQyxzQ0FBZ0M7QUFDaEMsc0NBQWtDO0FBQ2xDLHFDQUErQjtBQUUvQixNQUFNLFNBQVMsR0FBMkI7SUFDeEMsSUFBSSxFQUFFLFVBQVU7SUFDaEIsTUFBTSxFQUFFLFlBQVk7SUFDcEIsS0FBSyxFQUFFLGVBQWU7SUFDdEIsTUFBTSxFQUFFLFVBQVU7SUFDbEIsTUFBTSxFQUFFLG9CQUFvQjtJQUM1QixPQUFPLEVBQUUseUVBQXlFO0lBQ2xGLEtBQUssRUFBRSxlQUFlO0lBQ3RCLE9BQU8sRUFBRSxXQUFXO0lBQ3BCLE9BQU8sRUFBRSxhQUFhO0lBQ3RCLEtBQUssRUFBRSxpQkFBaUI7SUFDeEIsT0FBTyxFQUFFLGtCQUFrQjtJQUMzQixLQUFLLEVBQUUsZUFBZTtJQUN0QixNQUFNLEVBQUUsaUJBQWlCO0lBQ3pCLE1BQU0sRUFBRSxZQUFZO0lBQ3BCLE9BQU8sRUFBRSwyRUFBMkU7SUFDcEYsS0FBSyxFQUFFLGVBQWUsRUFBVSxpQ0FBaUM7SUFDakUsS0FBSyxFQUFFLGFBQWE7SUFDcEIsS0FBSyxFQUFFLGtCQUFrQjtJQUN6QixNQUFNLEVBQUUsWUFBWTtJQUNwQixLQUFLLEVBQUUsd0JBQXdCO0lBQy9CLE1BQU0sRUFBRSxZQUFZO0NBQ3JCLENBQUM7QUFFSyxNQUFNLGdCQUFnQixHQUFHLEtBQUssRUFBRSxNQUFjLEVBQUUsUUFBZ0IsRUFBRSxVQUFrQixZQUFZLEVBQUUsRUFBRTtJQUN6RyxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3pCLElBQUksRUFBRSxFQUFFLENBQUMsZ0JBQWdC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

View File

@ -0,0 +1,81 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.runCompletion = exports.onCompletion = void 0;
const marked_1 = require("marked");
const marked_terminal_1 = require("marked-terminal");
const path = __importStar(require("path"));
const write_1 = require("@plastichub/fs/write");
const osr_commons_1 = require("@plastichub/osr-commons");
const __1 = require("../");
const script_1 = require("../utils/script");
const filters_1 = require("../filters");
const onCompletion = async (result = "", options) => {
result = (0, filters_1.applyFilters)(result, options.filters || []);
if (options.dst) {
const dstPath = path.resolve((0, osr_commons_1.resolve)(options.dst, false, {
...options.variables,
MODEL: path.parse(options.model).name,
ROUTER: options.router,
}));
(0, write_1.sync)(dstPath, result);
__1.logger.debug(`Wrote completion result to ${dstPath}`);
}
else {
marked_1.marked.use((0, marked_terminal_1.markedTerminal)({
emoji: false,
}));
const content = (0, marked_1.marked)(result);
process.stdout.write(content);
}
(0, script_1.dumpAsScript)(options);
return result;
};
exports.onCompletion = onCompletion;
const runCompletion = async (client, params, options) => {
if (options.dry) {
__1.logger.info('Dry run - skipping API call');
return false;
}
const completion = await client.chat.completions.create({
model: options.model,
messages: params.messages,
});
const result = completion.choices[0].message.content;
(0, exports.onCompletion)(result, options);
return result;
};
exports.runCompletion = runCompletion;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLWNvbXBsZXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvcnVuLWNvbXBsZXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsbUNBQStCO0FBQy9CLHFEQUFnRDtBQUNoRCwyQ0FBNEI7QUFDNUIsZ0RBQW9EO0FBQ3BELHlEQUFpRDtBQUNqRCwyQkFBNEI7QUFDNUIsNENBQThDO0FBQzlDLHdDQUFpRDtBQUUxQyxNQUFNLFlBQVksR0FBRyxLQUFLLEVBQUUsU0FBYyxFQUFFLEVBQUUsT0FBa0IsRUFBRSxFQUFFO0lBQ3pFLE1BQU0sR0FBRyxJQUFBLHNCQUFZLEVBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxPQUFtQixJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQ2hFLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSxxQkFBTyxFQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFO1lBQ3ZELEdBQUcsT0FBTyxDQUFDLFNBQVM7WUFDcEIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUk7WUFDckMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1NBQ3ZCLENBQUMsQ0FBQyxDQUFBO1FBQ0gsSUFBQSxZQUFLLEVBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3RCLFVBQU0sQ0FBQyxLQUFLLENBQUMsOEJBQThCLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFDdkQsQ0FBQztTQUFNLENBQUM7UUFDTixlQUFNLENBQUMsR0FBRyxDQUFDLElBQUEsZ0NBQWMsRUFBQztZQUN4QixLQUFLLEVBQUUsS0FBSztTQUNiLENBQUMsQ0FBQyxDQUFBO1FBQ0gsTUFBTSxPQUFPLEdBQVcsSUFBQSxlQUFNLEVBQUMsTUFBTSxDQUFXLENBQUM7UUFDakQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDL0IsQ0FBQztJQUNELElBQUEscUJBQVksRUFBQyxPQUFPLENBQUMsQ0FBQTtJQUNyQixPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMsQ0FBQTtBQW5CWSxRQUFBLFlBQVksZ0JBbUJ4QjtBQUVNLE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxNQUFjLEVBQUUsTUFBVyxFQUFFLE9BQWtCLEVBQUUsRUFBRTtJQUNyRixJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNoQixVQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUE7UUFDMUMsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7UUFDdEQsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1FBQ3BCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtLQUMxQixDQUFDLENBQUE7SUFDRixNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUE7SUFDcEQsSUFBQSxvQkFBWSxFQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUM3QixPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMsQ0FBQTtBQVpZLFFBQUEsYUFBYSxpQkFZekIifQ==

View File

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runTools = void 0;
const content_1 = require("../utils/content");
const __1 = require("../");
const run_completion_1 = require("./run-completion");
const runTools = async (client, params, options) => {
const sessionId = Date.now().toString();
const sessionMessages = {
sessionId,
prompt: options.prompt,
timestamp: new Date().toISOString(),
messages: []
};
if (options.dry) {
__1.logger.info('Dry run - skipping API call');
return {
result: 'DRY RUN',
sessionMessages,
result_raw: {},
toolCalls: []
};
}
const logMessage = (message, sessionId, prompt) => {
return {
...message,
timestamp: new Date().toISOString(),
sessionId,
prompt
};
};
let runner = null;
try {
runner = await client.beta.chat.completions.runTools(params)
.on('message', (message) => {
options.collector.onMessage(logMessage(message, sessionId, options.prompt));
})
.on('functionCall', (tool) => {
return options.collector.onToolCall(logMessage(tool, sessionId, options.prompt));
})
.on('functionCallResult', (a) => {
options.collector.onFunctionCallResult(a);
})
.on('chatCompletion', options.collector.onChatCompletion)
.on('content', options.collector.onContent);
}
catch (e) {
__1.logger.trace(e);
}
let result = (0, content_1.content)(runner);
try {
result = await runner.finalChatCompletion();
}
catch (error) {
if (error.message.includes("(reading 'map')")) {
__1.logger.error('Failed to complete runner: credits :)', error.message, error.message, error);
return;
}
__1.logger.error('Failed to complete runner:', error.message, error.issues);
return;
}
const ret = (0, content_1.content)(result);
return await (0, run_completion_1.onCompletion)(ret, options);
};
exports.runTools = runTools;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLXRvb2xzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL3J1bi10b29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSw4Q0FBMEM7QUFDMUMsMkJBQTRCO0FBQzVCLHFEQUErQztBQUV4QyxNQUFNLFFBQVEsR0FBRyxLQUFLLEVBQUUsTUFBYyxFQUFFLE1BQVcsRUFBRSxPQUFrQixFQUFFLEVBQUU7SUFDaEYsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFBO0lBQ3ZDLE1BQU0sZUFBZSxHQUFHO1FBQ3RCLFNBQVM7UUFDVCxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1FBQ25DLFFBQVEsRUFBRSxFQUFFO0tBQ2IsQ0FBQTtJQUNELElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLFVBQU0sQ0FBQyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQTtRQUMxQyxPQUFPO1lBQ0wsTUFBTSxFQUFFLFNBQVM7WUFDakIsZUFBZTtZQUNmLFVBQVUsRUFBRSxFQUFFO1lBQ2QsU0FBUyxFQUFFLEVBQUU7U0FDZCxDQUFBO0lBQ0gsQ0FBQztJQUNELE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBWSxFQUFFLFNBQWlCLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDN0QsT0FBTztZQUNMLEdBQUcsT0FBTztZQUNWLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtZQUNuQyxTQUFTO1lBQ1QsTUFBTTtTQUNQLENBQUE7SUFDSCxDQUFDLENBQUE7SUFDRCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUE7SUFDakIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUE2QyxDQUFDO2FBQ2hHLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFtQyxFQUFFLEVBQUU7WUFDckQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7UUFDN0UsQ0FBQyxDQUFDO2FBQ0QsRUFBRSxDQUFDLGNBQWMsRUFBRSxDQUFDLElBQXdDLEVBQUUsRUFBRTtZQUMvRCxPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFBO1FBQ2xGLENBQUMsQ0FBQzthQUNELEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzlCLE9BQU8sQ0FBQyxTQUFTLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDM0MsQ0FBQyxDQUFDO2FBQ0QsRUFBRSxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUM7YUFDeEQsRUFBRSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQy9DLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsVUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNqQixDQUFDO0lBRUQsSUFBSSxNQUFNLEdBQUcsSUFBQSxpQkFBTyxFQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQzVCLElBQUksQ0FBQztRQUNILE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO0lBQzdDLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7WUFDOUMsVUFBTSxDQUFDLEtBQUssQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDMUYsT0FBTTtRQUNSLENBQUM7UUFDRCxVQUFNLENBQUMsS0FBSyxDQUFDLDRCQUE0QixFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZFLE9BQU07SUFDUixDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsSUFBQSxpQkFBTyxFQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQzNCLE9BQU8sTUFBTSxJQUFBLDZCQUFZLEVBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFBO0FBQ3pDLENBQUMsQ0FBQTtBQXpEWSxRQUFBLFFBQVEsWUF5RHBCIn0=

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,65 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadConfig = void 0;
const path = __importStar(require("path"));
const osr_commons_1 = require("@plastichub/osr-commons");
const index_1 = require("./index");
const exists_1 = require("@plastichub/fs/exists");
const read_1 = require("@plastichub/fs/read");
const env_1 = require("./utils/env");
const loadConfig = (options) => {
if (options.config) {
try {
const configPath = path.resolve((0, osr_commons_1.resolve)(options.config, false, (0, env_1.env_vars)()));
if ((0, exists_1.sync)(configPath)) {
const parsedConfig = (0, read_1.sync)(configPath, 'json');
return parsedConfig;
}
else {
index_1.logger.error(`Config file not found: ${configPath}`);
}
}
catch (error) {
index_1.logger.error(`Failed to parse config JSON: ${error.message}`);
}
}
else {
const config = (0, osr_commons_1.CONFIG_DEFAULT)();
return config;
}
};
exports.loadConfig = loadConfig;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFDQSwyQ0FBNEI7QUFDNUIseURBQWlFO0FBQ2pFLG1DQUFpQztBQUNqQyxrREFBc0Q7QUFDdEQsOENBQWtEO0FBRWxELHFDQUFzQztBQUMvQixNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQXFCLEVBQUUsRUFBRTtJQUNoRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUM7WUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEscUJBQU8sRUFBQyxPQUFPLENBQUMsTUFBTSxFQUFDLEtBQUssRUFBQyxJQUFBLGNBQVEsR0FBRSxDQUFDLENBQUMsQ0FBQTtZQUN6RSxJQUFLLElBQUEsYUFBTSxFQUFDLFVBQVUsQ0FBQyxFQUFHLENBQUM7Z0JBQ3ZCLE1BQU0sWUFBWSxHQUFHLElBQUEsV0FBSSxFQUFDLFVBQVUsRUFBQyxNQUFNLENBQUMsQ0FBQTtnQkFDNUMsT0FBTyxZQUFZLENBQUE7WUFDdkIsQ0FBQztpQkFBSSxDQUFDO2dCQUNGLGNBQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLFVBQVUsRUFBRSxDQUFDLENBQUE7WUFDeEQsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEtBQVMsRUFBRSxDQUFDO1lBQ2pCLGNBQU0sQ0FBQyxLQUFLLENBQUMsZ0NBQWdDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBQ2pFLENBQUM7SUFDTCxDQUFDO1NBQUksQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLElBQUEsNEJBQWMsR0FBUyxDQUFBO1FBQ3RDLE9BQU8sTUFBTSxDQUFBO0lBQ2pCLENBQUM7QUFDTCxDQUFDLENBQUE7QUFqQlksUUFBQSxVQUFVLGNBaUJ0QiJ9

View File

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MAX_FILE_SIZE = exports.EXCLUDE_GLOB = exports.MODULE_NAME = void 0;
exports.MODULE_NAME = 'kbot';
exports.EXCLUDE_GLOB = [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/coverage/**",
"*.log",
".kbot",
".git"
];
exports.MAX_FILE_SIZE = 1024 * 1024 * 2;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBYSxRQUFBLFdBQVcsR0FBRyxNQUFNLENBQUE7QUFDcEIsUUFBQSxZQUFZLEdBQUc7SUFDeEIsb0JBQW9CO0lBQ3BCLFlBQVk7SUFDWixhQUFhO0lBQ2IsZ0JBQWdCO0lBQ2hCLE9BQU87SUFDUCxPQUFPO0lBQ1AsTUFBTTtDQUNULENBQUE7QUFDWSxRQUFBLGFBQWEsR0FBRyxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQSJ9

16
packages/osr-code-bot/dist/.npmignore vendored Normal file
View File

@ -0,0 +1,16 @@
# Ignore node_modules directory
node_modules/
# Ignore log files
*.log
# Ignore temporary files
*.tmp
# Ignore coverage reports
coverage/
.kbot
*.exe
package-lock.json
tests

205
packages/osr-code-bot/dist/README.md vendored Normal file
View File

@ -0,0 +1,205 @@
# @plastichub/code-bot
AI-powered command-line tool for code modifications and project management that supports multiple AI models and routers.
## Overview
Code-bot is a powerful CLI tool that helps developers automate code modifications, handle project management tasks, and integrate with various AI models for intelligent code and content assistance.
## Quick Start
### Installation Steps
KBot requires Node.js to run. It's recommended to use Node.js version 18 or higher.
1. Visit the official [Node.js website](https://nodejs.org/)
2. Download the LTS (Long Term Support) version for your operating system
3. Follow the installation wizard
4. Verify installation by opening a terminal and running:
```bash
node --version
npm --version
```
### API Keys
KBot supports both OpenRouter and OpenAI APIs. You'll need at least one of these set up.
#### OpenRouter API (Recommended)
1. Visit [OpenRouter](https://openrouter.ai/)
2. Sign up for an account
3. Navigate to the API Keys section
4. Create a new API key
#### OpenAI API (Optional)
1. Go to [OpenAI's platform](https://platform.openai.com/)
2. Create an account or sign in
3. Navigate to API keys section
4. Create a new secret key
### Installation using Node NPM package manager
```bash
npm install -g @plastichub/code-bot
```
## Configuration
### API Keys Setup
Create configuration at `$HOME/.osr/.config.json` (or export OSR_CONFIG with path to config.json):
```json
{
"openrouter": {
"key": "your-openrouter-key"
},
"openai": {
"key": "your-openai-key"
},
"email": {
"newsletter": {
"host": "host.org",
"port": 465,
"debug": true,
"transactionLog": true,
"auth": {
"user": "foo@bar.com",
"pass": "pass"
}
}
},
"google": {
"cse": "custom search engine id",
"api_key": "google custom search api key"
},
"serpapi": {
"key": "your SerpAPI key (optional, used for web searches(places, google maps))"
},
}
```
### Preferences Setup
Optionally, create `.kbot/preferences.md` in your project directory to customize AI interactions:
```markdown
## My Preferences
Gender : male
Location : New York, USA (eg: `send me all saunas next to me`)
Language : English
Occupation : software developer, Typescript
Age : 30+
## Contacts
My email address : example@email.com (eg: `send me latest hacker news`)
My wife's email address ("Anne") : example@email.com (eg: `send email to my wife, with latest local news')
## Content
When creating content
- always Markdown
- always add links
- when sending emails, always add 'Best regards, [Your Name]'
```
# Command Line Parameters
This document describes all available command line parameters.
## Core Parameters
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `path` | Target directory | `.` | No |
| `prompt` | The prompt. Supports file paths and environment variables | `./prompt.md` | No |
| `output` | Optional output path for modified files (Tool mode only) | - | No |
| `dst` | Optional destination path for the result, will substitute ${MODEL} and ${ROUTER} in the path. Used for "completion" mode | - | No |
| `model` | AI model to use for processing | `anthropic/claude-3.5-sonnet` | No |
| `router` | Router to use: openai or openrouter | `openrouter` | No |
| `mode` | Chat completion mode: "completion" (without tools) or "tools" | `tools` | No |
## File Selection & Tools
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `include` | Glob patterns to match files for processing. Supports multiple patterns, e.g. `--include=src/*.tsx,src/*.ts --include=package.json` | - | No |
| `disable` | Disable tools categories | `[]` | No |
| `disableTools` | List of specific tools to disable | `[]` | No |
## Configuration & Profiles
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `profile` | Path to profile for variables. Supports environment variables | `${POLYMECH-ROOT}/profile.json` | No |
| `env` | Environment (in profile) | `default` | No |
| `config` | Path to JSON configuration file (API keys). Supports environment variables | - | No |
| `preferences` | Path to preferences file (location, email, gender, etc). Supports environment variables | `./.kbot/preferences.md` | No |
## Debugging & Logging
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `logLevel` | Logging level for the application (0-4) | `2` | No |
| `logs` | Logging directory | `./.kbot` | No |
| `dump` | Create a script | - | No |
| `dry` | Dry run - only write out parameters without making API calls | `false` | No |
## Examples
```bash
# Basic usage with default parameters
kbot --prompt="What are the changes needed?"
# Specify model and router
kbot --model="gpt-4" --router="openai" --prompt="Analyze this code"
# Process specific files
kbot --include="src/*.ts" --include="package.json" --prompt="Check for security issues"
# Dry run with custom logging
kbot --dry=true --logLevel=4 --prompt="Test run"
```
## Environment Variables
Many path-based parameters support environment variables using the `${VARIABLE}` syntax:
- `${POLYMECH-ROOT}` - Root directory for Polymech
- `${OSR-ROOT}` - Root directory for OSR
Example:
```bash
kbot --profile="${POLYMECH-ROOT}/custom-profile.json"
```
# Working on Larger Directories
Since LLMs (Large Language Models) and providers are limited to very small 'context windows', it's necessary to feed them with smaller chunks instead. This document explains how to process larger directories efficiently.
## Directory Processing Example
Here's an example of how to walk through files and process them:
```bash
osr-cli each --main='kbot \"read ${KEY} and translate to german, save in docs/language code/filename.md\" --include=\"${REL}\" --include=\".kbot/preferences.md\"' --list="./docs/*.md" --cwd=.
```
### Parameter Explanation
- `each`: Command to process multiple files iteratively
- `--main`: The main command (`kbot`) to execute for each file
- `--include=\"${REL}\"` instructs kbot to include the current selected path
- `--include=\".kbot/preferences.md\"` instructs kbot to include additional preferences about the task (eg: translation specifics)
- `--list`: Specifies the file pattern to match
- Supports include patterns (e.g., `"./docs/*.md"`)
- `--cwd`: Sets the current working directory for the command execution. Default is the current directory (`.`)
**Note** requires `@plastichub/osr-cli-commons` to be installed globally:
```bash
npm i -g @plastichub/osr-cli-commons
```

View File

@ -0,0 +1,293 @@
{
"timestamp": 1738015382028,
"models": [
{
"id": "gpt-4o-audio-preview-2024-10-01",
"object": "model",
"created": 1727389042,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-audio-preview",
"object": "model",
"created": 1734387424,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview",
"object": "model",
"created": 1727659998,
"owned_by": "system"
},
{
"id": "gpt-4o",
"object": "model",
"created": 1715367049,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-audio-preview-2024-12-17",
"object": "model",
"created": 1734115920,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-realtime-preview",
"object": "model",
"created": 1734387380,
"owned_by": "system"
},
{
"id": "dall-e-2",
"object": "model",
"created": 1698798177,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo",
"object": "model",
"created": 1677610602,
"owned_by": "openai"
},
{
"id": "o1-preview-2024-09-12",
"object": "model",
"created": 1725648865,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-0125",
"object": "model",
"created": 1706048358,
"owned_by": "system"
},
{
"id": "o1-preview",
"object": "model",
"created": 1725648897,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-instruct",
"object": "model",
"created": 1692901427,
"owned_by": "system"
},
{
"id": "babbage-002",
"object": "model",
"created": 1692634615,
"owned_by": "system"
},
{
"id": "o1-mini",
"object": "model",
"created": 1725649008,
"owned_by": "system"
},
{
"id": "o1-mini-2024-09-12",
"object": "model",
"created": 1725648979,
"owned_by": "system"
},
{
"id": "whisper-1",
"object": "model",
"created": 1677532384,
"owned_by": "openai-internal"
},
{
"id": "dall-e-3",
"object": "model",
"created": 1698785189,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview-2024-10-01",
"object": "model",
"created": 1727131766,
"owned_by": "system"
},
{
"id": "gpt-4-1106-preview",
"object": "model",
"created": 1698957206,
"owned_by": "system"
},
{
"id": "omni-moderation-latest",
"object": "model",
"created": 1731689265,
"owned_by": "system"
},
{
"id": "omni-moderation-2024-09-26",
"object": "model",
"created": 1732734466,
"owned_by": "system"
},
{
"id": "tts-1-hd-1106",
"object": "model",
"created": 1699053533,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-2024-07-18",
"object": "model",
"created": 1721172717,
"owned_by": "system"
},
{
"id": "gpt-4",
"object": "model",
"created": 1687882411,
"owned_by": "openai"
},
{
"id": "tts-1-hd",
"object": "model",
"created": 1699046015,
"owned_by": "system"
},
{
"id": "davinci-002",
"object": "model",
"created": 1692634301,
"owned_by": "system"
},
{
"id": "text-embedding-ada-002",
"object": "model",
"created": 1671217299,
"owned_by": "openai-internal"
},
{
"id": "gpt-4-turbo",
"object": "model",
"created": 1712361441,
"owned_by": "system"
},
{
"id": "tts-1",
"object": "model",
"created": 1681940951,
"owned_by": "openai-internal"
},
{
"id": "tts-1-1106",
"object": "model",
"created": 1699053241,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-instruct-0914",
"object": "model",
"created": 1694122472,
"owned_by": "system"
},
{
"id": "gpt-4-0125-preview",
"object": "model",
"created": 1706037612,
"owned_by": "system"
},
{
"id": "gpt-4-turbo-preview",
"object": "model",
"created": 1706037777,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-realtime-preview-2024-12-17",
"object": "model",
"created": 1734112601,
"owned_by": "system"
},
{
"id": "gpt-4o-audio-preview",
"object": "model",
"created": 1727460443,
"owned_by": "system"
},
{
"id": "gpt-4-0613",
"object": "model",
"created": 1686588896,
"owned_by": "openai"
},
{
"id": "gpt-4o-2024-05-13",
"object": "model",
"created": 1715368132,
"owned_by": "system"
},
{
"id": "text-embedding-3-small",
"object": "model",
"created": 1705948997,
"owned_by": "system"
},
{
"id": "gpt-4-turbo-2024-04-09",
"object": "model",
"created": 1712601677,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-1106",
"object": "model",
"created": 1698959748,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-16k",
"object": "model",
"created": 1683758102,
"owned_by": "openai-internal"
},
{
"id": "gpt-4o-audio-preview-2024-12-17",
"object": "model",
"created": 1734034239,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview-2024-12-17",
"object": "model",
"created": 1733945430,
"owned_by": "system"
},
{
"id": "gpt-4o-mini",
"object": "model",
"created": 1721172741,
"owned_by": "system"
},
{
"id": "text-embedding-3-large",
"object": "model",
"created": 1705953180,
"owned_by": "system"
},
{
"id": "gpt-4o-2024-08-06",
"object": "model",
"created": 1722814719,
"owned_by": "system"
},
{
"id": "gpt-4o-2024-11-20",
"object": "model",
"created": 1731975040,
"owned_by": "system"
},
{
"id": "chatgpt-4o-latest",
"object": "model",
"created": 1723515131,
"owned_by": "system"
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,173 @@
/*!
* prr
* (c) 2013 Rod Vagg <rod@vagg.org>
* https://github.com/rvagg/prr
* License: MIT
*/
/*!
*
* Copyright 2009-2017 Kris Kowal under the terms of the MIT
* license found at https://github.com/kriskowal/q/blob/v1/LICENSE
*
* With parts by Tyler Close
* Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
* at http://www.opensource.org/licenses/mit-license.html
* Forked at ref_send.js version: 2009-05-11
*
* With parts by Mark Miller
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*!
* Tmp
*
* Copyright (c) 2011-2017 KARASZI Istvan <github@spam.raszi.hu>
*
* MIT Licensed
*/
/*!
* fill-range <https://github.com/jonschlinkert/fill-range>
*
* Copyright (c) 2014-present, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* glob-base <https://github.com/jonschlinkert/glob-base>
*
* Copyright (c) 2015, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* humanize-ms - index.js
* Copyright(c) 2014 dead_horse <dead_horse@qq.com>
* MIT Licensed
*/
/*!
* is-dotfile <https://github.com/jonschlinkert/is-dotfile>
*
* Copyright (c) 2015-2017, Jon Schlinkert.
* Released under the MIT License.
*/
/*!
* is-extglob <https://github.com/jonschlinkert/is-extglob>
*
* Copyright (c) 2014-2015, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* is-extglob <https://github.com/jonschlinkert/is-extglob>
*
* Copyright (c) 2014-2016, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* is-glob <https://github.com/jonschlinkert/is-glob>
*
* Copyright (c) 2014-2015, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* is-glob <https://github.com/jonschlinkert/is-glob>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/
/*!
* is-number <https://github.com/jonschlinkert/is-number>
*
* Copyright (c) 2014-present, Jon Schlinkert.
* Released under the MIT License.
*/
/*!
* mime-db
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015-2022 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* mime-types
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* parse-glob <https://github.com/jonschlinkert/parse-glob>
*
* Copyright (c) 2015, Jon Schlinkert.
* Licensed under the MIT License.
*/
/*!
* to-regex-range <https://github.com/micromatch/to-regex-range>
*
* Copyright (c) 2015-present, Jon Schlinkert.
* Released under the MIT License.
*/
/*! Based on fetch-blob. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> & David Frank */
/*! node-domexception. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/*! showdown v 2.1.0 - 21-04-2022 */
/*!*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @license
* web-streams-polyfill v4.0.0-beta.3
* Copyright 2021 Mattias Buelens, Diwank Singh Tomer and other contributors.
* This code is released under the MIT license.
* SPDX-License-Identifier: MIT
*/
/**
* @preserve
* JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013)
*
* @author <a href="mailto:jensyt@gmail.com">Jens Taylor</a>
* @see http://github.com/homebrewing/brauhaus-diff
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*/

1345
packages/osr-code-bot/dist/package-lock.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

20
packages/osr-code-bot/dist/package.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"name": "@plastichub/kbot",
"version": "1.1.7",
"main": "main_node.js",
"author": "",
"license": "ISC",
"description": "",
"bin": {
"kbot": "./main_node.js"
},
"dependencies": {
"node-emoji": "^2.2.0"
},
"publishConfig": {
"access": "public"
},
"optionalDependencies": {
"puppeteer": "^23.11.1"
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,108 @@
# @plastichub/code-bot
AI-powered command-line tool for code modifications and project management that supports multiple AI models and routers.
## Overview
Code-bot is a powerful CLI tool that helps developers automate code modifications, handle project management tasks, and integrate with various AI models for intelligent code and content assistance.
## Quick Start
### Installation Steps
KBot requires Node.js to run. It's recommended to use Node.js version 18 or higher.
1. Visit the official [Node.js website](https://nodejs.org/)
2. Download the LTS (Long Term Support) version for your operating system
3. Follow the installation wizard
4. Verify installation by opening a terminal and running:
```bash
node --version
npm --version
```
### API Keys
KBot supports both OpenRouter and OpenAI APIs. You'll need at least one of these set up.
#### OpenRouter API (Recommended)
1. Visit [OpenRouter](https://openrouter.ai/)
2. Sign up for an account
3. Navigate to the API Keys section
4. Create a new API key
#### OpenAI API (Optional)
1. Go to [OpenAI's platform](https://platform.openai.com/)
2. Create an account or sign in
3. Navigate to API keys section
4. Create a new secret key
### Installation using Node NPM package manager
```bash
npm install -g @plastichub/code-bot
```
## Configuration
### API Keys Setup
Create configuration at `$HOME/.osr/.config.json` (or export OSR_CONFIG with path to config.json):
```json
{
"openrouter": {
"key": "your-openrouter-key"
},
"openai": {
"key": "your-openai-key"
},
"email": {
"newsletter": {
"host": "host.org",
"port": 465,
"debug": true,
"transactionLog": true,
"auth": {
"user": "foo@bar.com",
"pass": "pass"
}
}
},
"google": {
"cse": "custom search engine id",
"api_key": "google custom search api key"
},
"serpapi": {
"key": "your SerpAPI key (optional, used for web searches(places, google maps))"
},
}
```
### Preferences Setup
Optionally, create `.kbot/preferences.md` in your project directory to customize AI interactions:
```markdown
## My Preferences
Gender : male
Location : New York, USA (eg: `send me all saunas next to me`)
Language : English
Occupation : software developer, Typescript
Age : 30+
## Contacts
My email address : example@email.com (eg: `send me latest hacker news`)
My wife's email address ("Anne") : example@email.com (eg: `send email to my wife, with latest local news')
## Content
When creating content
- always Markdown
- always add links
- when sending emails, always add 'Best regards, [Your Name]'
```

View File

@ -0,0 +1,28 @@
# Working on Larger Directories
Since LLMs (Large Language Models) and providers are limited to very small 'context windows', it's necessary to feed them with smaller chunks instead. This document explains how to process larger directories efficiently.
## Directory Processing Example
Here's an example of how to walk through files and process them:
```bash
osr-cli each --main='kbot \"read ${KEY} and translate to german, save in docs/language code/filename.md\" --include=\"${REL}\" --include=\".kbot/preferences.md\"' --list="./docs/*.md" --cwd=.
```
### Parameter Explanation
- `each`: Command to process multiple files iteratively
- `--main`: The main command (`kbot`) to execute for each file
- `--include=\"${REL}\"` instructs kbot to include the current selected path
- `--include=\".kbot/preferences.md\"` instructs kbot to include additional preferences about the task (eg: translation specifics)
- `--list`: Specifies the file pattern to match
- Supports include patterns (e.g., `"./docs/*.md"`)
- `--cwd`: Sets the current working directory for the command execution. Default is the current directory (`.`)
**Note** requires `@plastichub/osr-cli-commons` to be installed globally:
```bash
npm i -g @plastichub/osr-cli-commons
```

View File

@ -0,0 +1,18 @@
## CLI
- [ ] run
- [ ] each
## Lib
- [ ] run
## Tool
- [ ] run
## API
- [ ] run

View File

@ -0,0 +1,58 @@
# Docker Usage
## Quick Start
To quickly get started with kbot using Docker, run:
```bash
docker run -d -p 8080:8080 plastichub/kbot
```
This command:
- Runs the container in detached mode (`-d`)
- Maps port 8080 from the container to port 8080 on your host machine (`-p 8080:8080`)
- Uses the official plastichub/kbot image
## Container Configuration
### Environment Variables
The Docker container can be configured using environment variables:
```bash
docker run -d \
-p 8080:8080 \
-e OSR_CONFIG='{"openrouter":{"key":"your-key"}}' \
plastichub/kbot
```
### Volumes
To persist data or use custom configurations:
```bash
docker run -d \
-p 8080:8080 \
-v $(pwd):/workspace \
plastichub/kbot
```
### Docker Compose
Example docker-compose.yml:
```yaml
version: '3'
services:
kbot:
image: plastichub/kbot
ports:
- "8080:8080"
volumes:
- .:/workspace
```
Run with:
```bash
docker-compose up -d
```

View File

@ -0,0 +1,6 @@
echo "Start code-server in $(pwd)"
docker run \
-p 8080:8080 \
-v "$(pwd -W)":/workspace \
-v "C:\\Users\\zx\\.osr/:/root/.osr/" \
plastichub/kbot

View File

@ -0,0 +1,145 @@
# CLI Examples
## Basic Commands
### Modify Project Files
```bash
# Basic project modification
kbot "Add error handling to API endpoints"
# Using stdin for prompt
echo "Add error handling to API endpoints" | kbot
# Pipe file content as prompt
cat prompt.txt | kbot
# Specify files using include patterns
kbot --include "src/**/*.ts" "Update TypeScript types"
kbot "Add unit tests for src/commands/*" --include="./src/commands/*.ts"
```
### View Logs
```bash
# View modification history
kbot log .
```
### Node.js API Projects
```bash
# Add API endpoints
kbot --include "src/routes/*.ts" "Add authentication middleware"
# Update API models
kbot --include "src/models/*.ts" "Add validation"
```
## Advanced Features
### Using Profiles
Profiles allow you to define variables that can be used across your project and templates. These variables can be accessed using `${VARIABLE_NAME}` syntax in your tools and template partials.
```bash
# Use a specific profile file
kbot "Update configuration" --profile=./profiles/profile.json
# Use environment-specific variables
kbot "Configure for Hugo release" --profile=./profiles/profile.json --env=hugo-release
```
Example profile.json structure:
```json
{
"variables" : {
"foo": "bar"
},
"env": {
"hugo-release": {
"variables":{
"GIT_USER": "hugo-deployer",
"DEPLOY_TARGET": "production"
}
}
}
}
```
- Top-level variables are used as defaults
- Environment-specific variables (specified by --env) override defaults
- Variables can be used in tools and template partials using ${VARIABLE_NAME} syntax
### Custom Output Path
```bash
# Save modifications to different directory
kbot --output ./modified "Refactor code"
```
### AI Model Selection
```bash
# Use specific OpenAI model
kbot --router openai --model gpt-4 "Optimize code"
# Use Anthropic Claude
kbot --model anthropic/claude-3-opus "Add documentation"
```
### Tool Control
```bash
# Disable specific tools
kbot --disable git "Update code without git commits"
# Disable multiple tool categories
kbot --disable fs,npm,git "Analyze code only"
```
### File Selection
```bash
# Multiple include patterns
kbot --include "src/**/*.ts" --include "test/**/*.ts" "Update types"
# Exclude patterns
kbot --include "src/**/*.ts" --include "!src/generated/**" "Refactor code"
```
### Environment and Profile
```bash
# Use specific environment
kbot --env production "Add production configs"
# Custom profile path
kbot --profile ./custom-profile.json --env production
```
### Scripting
```bash
# Generate modification script
kbot --dump ./modify-script.sh "Add types"
```
### Input Types
The tool supports different types of input:
```bash
# Text input through stdin
echo "Add error handling" | kbot
# Piping files
cat my-prompt.md | kbot
# Specifying a file
kbot my-prompt.md
```

View File

@ -0,0 +1,2 @@
# Installation Guide for IKBot

View File

@ -0,0 +1,69 @@
# Command Line Parameters
This document describes all available command line parameters.
## Core Parameters
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `path` | Target directory | `.` | No |
| `prompt` | The prompt. Supports file paths and environment variables | `./prompt.md` | No |
| `output` | Optional output path for modified files (Tool mode only) | - | No |
| `dst` | Optional destination path for the result, will substitute ${MODEL} and ${ROUTER} in the path. Used for "completion" mode | - | No |
| `model` | AI model to use for processing | `anthropic/claude-3.5-sonnet` | No |
| `router` | Router to use: openai or openrouter | `openrouter` | No |
| `mode` | Chat completion mode: "completion" (without tools) or "tools" | `tools` | No |
## File Selection & Tools
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `include` | Glob patterns to match files for processing. Supports multiple patterns, e.g. `--include=src/*.tsx,src/*.ts --include=package.json` | - | No |
| `disable` | Disable tools categories | `[]` | No |
| `disableTools` | List of specific tools to disable | `[]` | No |
## Configuration & Profiles
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `profile` | Path to profile for variables. Supports environment variables | `${POLYMECH-ROOT}/profile.json` | No |
| `env` | Environment (in profile) | `default` | No |
| `config` | Path to JSON configuration file (API keys). Supports environment variables | - | No |
| `preferences` | Path to preferences file (location, email, gender, etc). Supports environment variables | `./.kbot/preferences.md` | No |
## Debugging & Logging
| Parameter | Description | Default | Required |
|-----------|-------------|---------|----------|
| `logLevel` | Logging level for the application (0-4) | `2` | No |
| `logs` | Logging directory | `./.kbot` | No |
| `dump` | Create a script | - | No |
| `dry` | Dry run - only write out parameters without making API calls | `false` | No |
## Examples
```bash
# Basic usage with default parameters
kbot --prompt="What are the changes needed?"
# Specify model and router
kbot --model="gpt-4" --router="openai" --prompt="Analyze this code"
# Process specific files
kbot --include="src/*.ts" --include="package.json" --prompt="Check for security issues"
# Dry run with custom logging
kbot --dry=true --logLevel=4 --prompt="Test run"
```
## Environment Variables
Many path-based parameters support environment variables using the `${VARIABLE}` syntax:
- `${POLYMECH-ROOT}` - Root directory for Polymech
- `${OSR-ROOT}` - Root directory for OSR
Example:
```bash
kbot --profile="${POLYMECH-ROOT}/custom-profile.json"
```

View File

@ -0,0 +1,49 @@
# KBot Configuration Parameters
## Core Configuration
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| mode | enum (completion, tools, assistant) | tools | Chat completion mode: <br>- 'completion': no tool support, use --dst to save output <br>- 'tools': allows tools usage <br>- 'assistant': supports documents (PDF, DOCX, etc.) |
| model | string | - | AI model to use for processing |
| router | string | openrouter | Router to use: openai, openrouter or deepseek |
| api_key | string | - | Explicit API key to use |
| baseURL | string | - | Base URL for the API |
## Paths & Files
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| path | string | . | Target directory |
| prompt | string | ./prompt.md | The prompt. Supports file paths and env variables |
| output | string | - | Optional output path for modified files (Tool mode only) |
| dst | string | - | Optional destination path for the result |
| preferences | string | ./.kbot/preferences.md | Path to preferences file |
| logs | string | ./.kbot | Logging directory |
| config | string | - | Path to JSON configuration file |
## Tools & Filters
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| tools | string[] | [defaultTools] | List of tools to use |
| disable | string[] | [] | Disable tools categories |
| disableTools | string[] | [] | List of specific tools to disable |
| filters | string[] | '' | Filters to apply to the output |
## Other Options
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| env | string | default | Environment (in profile) |
| logLevel | number | 2 | Logging level for the application |
| dump | string | - | Create a script |
| variables | Record<string, string> | {} | Variables to use |
| dry | boolean | false | Dry run - only write out parameters |
## File Selection
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| each | string | - | Glob pattern to run for each matching file |
| include | string[] | - | Comma separated glob patterns or paths |

View File

@ -0,0 +1,81 @@
# Personal Preferences Configuration
The `.kbot/preferences.md` file is used to store personal information and preferences that help the AI assistant provide more personalized and contextual responses.
## File Location
The preferences file should be located at:
```
.kbot/preferences.md
```
## File Structure
The preferences file uses Markdown format and is structured into several sections:
### Personal Information
```markdown
## My Preferences
Gender : [gender]
Location : [city, country]
Language : [primary language, preferred language]
Occupation : [job title, specialties]
Age : [age range]
```
### Contact Information
```markdown
## Contacts
My email address : [your email]
[Additional contacts with descriptions]
```
### Content Preferences
```markdown
## Content
When creating content
- [content formatting preferences]
- [communication style preferences]
- [email signature preferences]
- [language preferences for specific contacts]
- [search preferences]
```
## Example Configuration
Here's an example of a complete preferences file:
```markdown
## My Preferences
Gender : male
Location : Tarragona, Spain
Language : German, prefer english
Occupation : software developer, Typescript
Age : 45+
## Contacts
My email address : example@email.com
My wife's email (Anne) : anne@email.com
## Content
When creating content
- always Markdown
- always add links
- when sending emails, always add 'kind regards, [Your Name]'
- when sending emails to [Contact], always in [specific language]
- when searching for news, always add links to videos, search via Google and other news outlets
```
## Updating Preferences
You can update your preferences by directly editing the `.kbot/preferences.md` file. Changes take effect immediately for new interactions with the AI assistant.

View File

@ -0,0 +1,35 @@
## Core
- history/session
- run mode: streaming
- extensions: gui
- logging : system, file logger, notification, popup
- filters: in/out (incl. tools)
- input/output formats: md, csv, xls, docx, pdf
- splitters
- pipes: n8n/nodered/stdio
- docs: custom help command
- router: ollama
- bundle: ESM & Deno
## Models
- task->match
## Prompt
- evaluation -> refine
## Tools
### Web
- external agents: https://github.com/Skyvern-AI/skyvern
- multiple scrapers: puppeteer / cherio / API
- Rapid API composer

View File

@ -0,0 +1,86 @@
# LLM Tools Documentation
## Filesystem Tools (fs)
- `list_files`: List all files in a directory
- Parameters:
- directory: (string, required) Directory path to list files from
- pattern: (string, optional) Glob pattern for filtering files
- `remove_file`: Remove a file at given path
- Parameters:
- path: (string, required) Path of the file to remove
- `rename_file`: Rename or move a file or directory
- Parameters:
- src: (string, required) Source path
- dst: (string, required) Destination path
- `modify_project_files`: Modify existing project files
- Parameters:
- files: (array, required) Array of file objects with path and content
- `create_project_structure`: Create project structure with files and folders
- Parameters:
- files: (array, required) Array of file objects with path and content
- `create_file`: Creates a file, given a path and content
- Parameters:
- file: (object, required) Object containing path and content
- `read_file`: Read a file at given path
- Parameters:
- file: (object, required) Object containing path
## NPM Tools (npm)
- `build_project`: Build project using pnpm build command
- Parameters: None required
- `run_npm`: Run an npm/pnpm command
- Parameters:
- command: (string, required) Command to run (e.g. install, test, etc)
- args: (array, optional) Additional arguments for the command
- `install_dependency`: Install a dependency using npm
- Parameters:
- dependencies: (array, required) Array of dependency names
## Git Tools (git)
- `init_repository`: Initialize a new git repository if not exists
- Parameters: None required
- `commit_files_git`: Commit files using git
- Parameters:
- files: (array, required) Array of file paths to commit
- message: (string, required) Commit message
## Terminal Tools (terminal)
- `execute_command`: Execute a terminal command and capture output
- Parameters:
- command: (string, required) Command to execute
- args: (array, optional) Command arguments
- cwd: (string, optional) Working directory for command execution
- background: (boolean, optional) Run command in background (non-blocking)
- window: (boolean, optional) Open command in new terminal window
- detached: (boolean, optional) Run process detached from parent
## Interactive Tools (interact)
- `ask_question`: Ask user a simple question and get response
- Parameters:
- question: (string, required) Question to ask the user
- default: (string, optional) Default answer
- `choose_option`: Ask user to choose from multiple options
- Parameters:
- message: (string, required) Message to show the user
- choices: (array, required) List of choices
- multiple: (boolean, optional) Allow multiple selections
## User Tools (user)
- `capture_screen`: Capture a screenshot of the entire screen or a specific region
- Parameters: None required

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.assistant_supported = exports.module_root = exports.run = exports.logger = void 0;
const path_1 = __importDefault(require("path"));
const osr_log_1 = require("@plastichub/osr-log");
const osr_commons_1 = require("@plastichub/osr-commons");
const constants_1 = require("./constants");
exports.logger = (0, osr_log_1.createLogger)('llm-tools');
var run_1 = require("./commands/run");
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return run_1.run; } });
const isWindows = process.platform === 'win32';
const module_root = () => path_1.default.resolve(path_1.default.join((0, osr_commons_1.get_var)(isWindows ? 'HOMEPATH' : 'HOME'), `.${constants_1.MODULE_NAME}`));
exports.module_root = module_root;
exports.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsZ0RBQXVCO0FBR3ZCLGlEQUFrRDtBQUNsRCx5REFBaUU7QUFDakUsMkNBQXlDO0FBQzVCLFFBQUEsTUFBTSxHQUFvQixJQUFBLHNCQUFZLEVBQUMsV0FBVyxDQUFDLENBQUE7QUFDaEUsc0NBQW9DO0FBQTNCLDBGQUFBLEdBQUcsT0FBQTtBQUNaLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxDQUFBO0FBQ3ZDLE1BQU0sV0FBVyxHQUFHLEdBQUcsRUFBRSxDQUFDLGNBQUksQ0FBQyxPQUFPLENBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxJQUFBLHFCQUFPLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksdUJBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQTtBQUF6RyxRQUFBLFdBQVcsZUFBOEY7QUFFekcsUUFBQSxtQkFBbUIsR0FBMkI7SUFDdkQsSUFBSSxFQUFFLFVBQVU7SUFDaEIsTUFBTSxFQUFFLFlBQVk7SUFDcEIsS0FBSyxFQUFFLGVBQWU7SUFDdEIsTUFBTSxFQUFFLFVBQVU7SUFDbEIsTUFBTSxFQUFFLG9CQUFvQjtJQUM1QixPQUFPLEVBQUUseUVBQXlFO0lBQ2xGLEtBQUssRUFBRSxlQUFlO0lBQ3RCLE9BQU8sRUFBRSxXQUFXO0lBQ3BCLE9BQU8sRUFBRSxhQUFhO0lBQ3RCLEtBQUssRUFBRSxpQkFBaUI7SUFDeEIsT0FBTyxFQUFFLGtCQUFrQjtJQUMzQixLQUFLLEVBQUUsZUFBZTtJQUN0QixNQUFNLEVBQUUsaUJBQWlCO0lBQ3pCLE1BQU0sRUFBRSxZQUFZO0lBQ3BCLE9BQU8sRUFBRSwyRUFBMkU7SUFDcEYsS0FBSyxFQUFFLGVBQWUsRUFBVSxpQ0FBaUM7SUFDakUsS0FBSyxFQUFFLGFBQWE7SUFDcEIsS0FBSyxFQUFFLGtCQUFrQjtJQUN6QixNQUFNLEVBQUUsWUFBWTtJQUNwQixLQUFLLEVBQUUsd0JBQXdCO0lBQy9CLE1BQU0sRUFBRSxZQUFZO0NBQ3JCLENBQUMifQ==

View File

@ -0,0 +1,46 @@
#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.logger = void 0;
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const run_1 = require("./commands/run");
const osr_log_1 = require("@plastichub/osr-log");
const zod_schema_1 = require("./zod_schema");
const osr_commons_1 = require("@plastichub/osr-commons");
const help_1 = __importDefault(require("./commands/help"));
const examples_1 = require("./commands/examples");
const init_1 = require("./commands/init");
const build_1 = require("./commands/build");
const fetch_1 = require("./commands/fetch");
exports.logger = (0, osr_log_1.createLogger)('llm-tools');
const modify = async (argv) => {
const ret = await (0, run_1.run)(argv);
return ret;
};
const yargOptions = {
onKey: ((_yargs, key, options) => {
switch (key) {
case 'prompt':
{
return _yargs.positional(key, options);
}
}
})
};
(0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
.command('init', 'Initialize KBot configuration', (yargs) => (0, osr_commons_1.toYargs)(yargs, (0, zod_schema_1.OptionsSchema)(), yargOptions), init_1.init)
.command('modify [prompt]', 'Modify an existing project', (yargs) => (0, osr_commons_1.toYargs)(yargs, (0, zod_schema_1.OptionsSchema)(), yargOptions), modify)
.command('types', 'Generate types', (yargs) => { }, (argv) => (0, zod_schema_1.types)())
.command('build', 'Build kbot essentials', (yargs) => { }, (argv) => (0, build_1.build)())
.command('fetch', "Fetch models, to $HOME/.kbot/", (yargs) => { }, (argv) => (0, fetch_1.fetch)())
.command('help-md', 'Generate markdown help', (yargs) => { }, help_1.default)
.command('examples', 'Show examples', (yargs) => { }, examples_1.examples)
.command(['modify [prompt]', '$0'], 'Default command modify', (yargs) => (0, osr_commons_1.toYargs)(yargs, (0, zod_schema_1.OptionsSchema)(), yargOptions), modify)
.help()
.wrap(yargs_1.default.terminalWidth() - 20)
.parse();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQSxrREFBeUI7QUFDekIsMkNBQXVDO0FBQ3ZDLHdDQUFvQztBQUVwQyxpREFBa0Q7QUFDbEQsNkNBQW1EO0FBRW5ELHlEQUFpRDtBQUNqRCwyREFBeUM7QUFDekMsa0RBQThDO0FBQzlDLDBDQUFzQztBQUN0Qyw0Q0FBd0M7QUFDeEMsNENBQXdDO0FBRTNCLFFBQUEsTUFBTSxHQUFvQixJQUFBLHNCQUFZLEVBQUMsV0FBVyxDQUFDLENBQUE7QUFDaEUsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLElBQWUsRUFBRSxFQUFFO0lBQ3ZDLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBQSxTQUFHLEVBQUMsSUFBaUIsQ0FBQyxDQUFBO0lBQ3hDLE9BQU8sR0FBRyxDQUFBO0FBQ1osQ0FBQyxDQUFBO0FBQ0QsTUFBTSxXQUFXLEdBQVE7SUFDdkIsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQy9CLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDWixLQUFLLFFBQVE7Z0JBQ1gsQ0FBQztvQkFDQyxPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFBO2dCQUN4QyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQztDQUNILENBQUE7QUFFRCxJQUFBLGVBQUssRUFBQyxJQUFBLGlCQUFPLEVBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ3pCLE9BQU8sQ0FDTixNQUFNLEVBQ04sK0JBQStCLEVBQy9CLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFBLHFCQUFPLEVBQUMsS0FBSyxFQUFFLElBQUEsMEJBQWEsR0FBRSxFQUFFLFdBQVcsQ0FBQyxFQUN2RCxXQUFJLENBQ0w7S0FDQSxPQUFPLENBQ04saUJBQWlCLEVBQ2pCLDRCQUE0QixFQUM1QixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBQSxxQkFBTyxFQUFDLEtBQUssRUFBRSxJQUFBLDBCQUFhLEdBQUUsRUFBRSxXQUFXLENBQUMsRUFDdkQsTUFBTSxDQUNQO0tBQ0EsT0FBTyxDQUNOLE9BQU8sRUFDUCxnQkFBZ0IsRUFDaEIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFDZCxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBQSxrQkFBSyxHQUFFLENBQ2xCO0tBQ0EsT0FBTyxDQUNOLE9BQU8sRUFDUCx1QkFBdUIsRUFDdkIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFDZCxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBQSxhQUFLLEdBQUUsQ0FDbEI7S0FDQSxPQUFPLENBQ04sT0FBTyxFQUNQLCtCQUErQixFQUMvQixDQUFDLEtBQUssRUFBRSxFQUFFLEdBQUcsQ0FBQyxFQUNkLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFBLGFBQUssR0FBRSxDQUNsQjtLQUNBLE9BQU8sQ0FDTixTQUFTLEVBQ1Qsd0JBQXdCLEVBQ3hCLENBQUMsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ2QsY0FBVyxDQUNaO0tBQ0EsT0FBTyxDQUNOLFVBQVUsRUFDVixlQUFlLEVBQ2YsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFDZCxtQkFBUSxDQUNUO0tBQ0EsT0FBTyxDQUFDLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLEVBQUUsd0JBQXdCLEVBQzFELENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFBLHFCQUFPLEVBQUMsS0FBSyxFQUFFLElBQUEsMEJBQWEsR0FBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLE1BQU0sQ0FBQztLQUNqRSxJQUFJLEVBQUU7S0FDTixJQUFJLENBQUMsZUFBSyxDQUFDLGFBQWEsRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUNoQyxLQUFLLEVBQUUsQ0FBQSJ9

View File

@ -0,0 +1,97 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultMimeRegistry = exports.MimeHandlerRegistry = exports.TextHandler = exports.PDFHandler = exports.ImageHandler = void 0;
const path = __importStar(require("path"));
const source_1 = require("./source");
const read_1 = require("@plastichub/fs/read");
class ImageHandler {
handle(filePath, relativePath) {
return {
role: "user",
content: [
{
type: "image_url",
image_url: {
url: (0, source_1.base64)(filePath)
}
}
]
};
}
}
exports.ImageHandler = ImageHandler;
class PDFHandler {
handle(filePath, relativePath) {
return {
path: relativePath,
content: (0, source_1.base64)(filePath),
role: "user",
name: path.parse(filePath).base
};
}
}
exports.PDFHandler = PDFHandler;
class TextHandler {
handle(filePath, relativePath) {
return {
role: "user",
path: relativePath,
content: (0, read_1.sync)(filePath).toString()
};
}
}
exports.TextHandler = TextHandler;
class MimeHandlerRegistry {
constructor() {
this.handlers = new Map();
}
registerHandler(mimeType, handler) {
this.handlers.set(mimeType, handler);
}
getHandler(mimeType) {
// For mime types like 'image/png', try to match 'image/*' if specific type not found
const [type] = mimeType.split('/');
return this.handlers.get(mimeType) || this.handlers.get(`${type}/*`) || null;
}
}
exports.MimeHandlerRegistry = MimeHandlerRegistry;
// Create and export a pre-configured registry
exports.defaultMimeRegistry = new MimeHandlerRegistry();
// Register default handlers
exports.defaultMimeRegistry.registerHandler('image/*', new ImageHandler());
exports.defaultMimeRegistry.registerHandler('application/pdf', new PDFHandler());
exports.defaultMimeRegistry.registerHandler('text/*', new TextHandler());
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWltZS1oYW5kbGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9taW1lLWhhbmRsZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJDQUE0QjtBQUM1QixxQ0FBaUM7QUFDakMsOENBQWtEO0FBWWxELE1BQWEsWUFBWTtJQUN2QixNQUFNLENBQUMsUUFBZ0IsRUFBRSxZQUFvQjtRQUMzQyxPQUFPO1lBQ0wsSUFBSSxFQUFFLE1BQU07WUFDWixPQUFPLEVBQUU7Z0JBQ1A7b0JBQ0UsSUFBSSxFQUFFLFdBQVc7b0JBQ2pCLFNBQVMsRUFBRTt3QkFDVCxHQUFHLEVBQUUsSUFBQSxlQUFNLEVBQUMsUUFBUSxDQUFDO3FCQUN0QjtpQkFDRjthQUNGO1NBQ0YsQ0FBQTtJQUNILENBQUM7Q0FDRjtBQWRELG9DQWNDO0FBRUQsTUFBYSxVQUFVO0lBQ3JCLE1BQU0sQ0FBQyxRQUFnQixFQUFFLFlBQW9CO1FBQzNDLE9BQU87WUFDTCxJQUFJLEVBQUUsWUFBWTtZQUNsQixPQUFPLEVBQUUsSUFBQSxlQUFNLEVBQUMsUUFBUSxDQUFDO1lBQ3pCLElBQUksRUFBRSxNQUFNO1lBQ1osSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSTtTQUNoQyxDQUFBO0lBQ0gsQ0FBQztDQUNGO0FBVEQsZ0NBU0M7QUFFRCxNQUFhLFdBQVc7SUFDdEIsTUFBTSxDQUFDLFFBQWdCLEVBQUUsWUFBb0I7UUFDM0MsT0FBTztZQUNMLElBQUksRUFBRSxNQUFNO1lBQ1osSUFBSSxFQUFFLFlBQVk7WUFDbEIsT0FBTyxFQUFFLElBQUEsV0FBSSxFQUFDLFFBQVEsQ0FBQyxDQUFDLFFBQVEsRUFBRTtTQUNuQyxDQUFBO0lBQ0gsQ0FBQztDQUNGO0FBUkQsa0NBUUM7QUFFRCxNQUFhLG1CQUFtQjtJQUFoQztRQUNVLGFBQVEsR0FBOEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQVcxRCxDQUFDO0lBVEMsZUFBZSxDQUFDLFFBQWdCLEVBQUUsT0FBcUI7UUFDckQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxVQUFVLENBQUMsUUFBZ0I7UUFDekIscUZBQXFGO1FBQ3JGLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQztJQUMvRSxDQUFDO0NBQ0Y7QUFaRCxrREFZQztBQUVELDhDQUE4QztBQUNqQyxRQUFBLG1CQUFtQixHQUFHLElBQUksbUJBQW1CLEVBQUUsQ0FBQztBQUU3RCw0QkFBNEI7QUFDNUIsMkJBQW1CLENBQUMsZUFBZSxDQUFDLFNBQVMsRUFBRSxJQUFJLFlBQVksRUFBRSxDQUFDLENBQUM7QUFDbkUsMkJBQW1CLENBQUMsZUFBZSxDQUFDLGlCQUFpQixFQUFFLElBQUksVUFBVSxFQUFFLENBQUMsQ0FBQztBQUN6RSwyQkFBbUIsQ0FBQyxlQUFlLENBQUMsUUFBUSxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsQ0FBQyJ9

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,293 @@
{
"timestamp": 1738177440286,
"models": [
{
"id": "gpt-4o-audio-preview-2024-10-01",
"object": "model",
"created": 1727389042,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-audio-preview",
"object": "model",
"created": 1734387424,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-audio-preview-2024-12-17",
"object": "model",
"created": 1734115920,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-realtime-preview",
"object": "model",
"created": 1734387380,
"owned_by": "system"
},
{
"id": "dall-e-2",
"object": "model",
"created": 1698798177,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo",
"object": "model",
"created": 1677610602,
"owned_by": "openai"
},
{
"id": "o1-preview-2024-09-12",
"object": "model",
"created": 1725648865,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-0125",
"object": "model",
"created": 1706048358,
"owned_by": "system"
},
{
"id": "o1-preview",
"object": "model",
"created": 1725648897,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-instruct",
"object": "model",
"created": 1692901427,
"owned_by": "system"
},
{
"id": "babbage-002",
"object": "model",
"created": 1692634615,
"owned_by": "system"
},
{
"id": "o1-mini-2024-09-12",
"object": "model",
"created": 1725648979,
"owned_by": "system"
},
{
"id": "whisper-1",
"object": "model",
"created": 1677532384,
"owned_by": "openai-internal"
},
{
"id": "dall-e-3",
"object": "model",
"created": 1698785189,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview-2024-10-01",
"object": "model",
"created": 1727131766,
"owned_by": "system"
},
{
"id": "gpt-4-1106-preview",
"object": "model",
"created": 1698957206,
"owned_by": "system"
},
{
"id": "omni-moderation-latest",
"object": "model",
"created": 1731689265,
"owned_by": "system"
},
{
"id": "omni-moderation-2024-09-26",
"object": "model",
"created": 1732734466,
"owned_by": "system"
},
{
"id": "tts-1-hd-1106",
"object": "model",
"created": 1699053533,
"owned_by": "system"
},
{
"id": "gpt-4",
"object": "model",
"created": 1687882411,
"owned_by": "openai"
},
{
"id": "gpt-4-0613",
"object": "model",
"created": 1686588896,
"owned_by": "openai"
},
{
"id": "tts-1-hd",
"object": "model",
"created": 1699046015,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-2024-07-18",
"object": "model",
"created": 1721172717,
"owned_by": "system"
},
{
"id": "gpt-4o-mini",
"object": "model",
"created": 1721172741,
"owned_by": "system"
},
{
"id": "davinci-002",
"object": "model",
"created": 1692634301,
"owned_by": "system"
},
{
"id": "gpt-4o-2024-05-13",
"object": "model",
"created": 1715368132,
"owned_by": "system"
},
{
"id": "text-embedding-ada-002",
"object": "model",
"created": 1671217299,
"owned_by": "openai-internal"
},
{
"id": "gpt-4o",
"object": "model",
"created": 1715367049,
"owned_by": "system"
},
{
"id": "gpt-4o-2024-08-06",
"object": "model",
"created": 1722814719,
"owned_by": "system"
},
{
"id": "gpt-4-turbo",
"object": "model",
"created": 1712361441,
"owned_by": "system"
},
{
"id": "tts-1",
"object": "model",
"created": 1681940951,
"owned_by": "openai-internal"
},
{
"id": "tts-1-1106",
"object": "model",
"created": 1699053241,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-instruct-0914",
"object": "model",
"created": 1694122472,
"owned_by": "system"
},
{
"id": "gpt-4-turbo-preview",
"object": "model",
"created": 1706037777,
"owned_by": "system"
},
{
"id": "gpt-4o-mini-realtime-preview-2024-12-17",
"object": "model",
"created": 1734112601,
"owned_by": "system"
},
{
"id": "gpt-4o-audio-preview",
"object": "model",
"created": 1727460443,
"owned_by": "system"
},
{
"id": "gpt-4o-2024-11-20",
"object": "model",
"created": 1731975040,
"owned_by": "system"
},
{
"id": "text-embedding-3-small",
"object": "model",
"created": 1705948997,
"owned_by": "system"
},
{
"id": "chatgpt-4o-latest",
"object": "model",
"created": 1723515131,
"owned_by": "system"
},
{
"id": "gpt-4-turbo-2024-04-09",
"object": "model",
"created": 1712601677,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-1106",
"object": "model",
"created": 1698959748,
"owned_by": "system"
},
{
"id": "gpt-3.5-turbo-16k",
"object": "model",
"created": 1683758102,
"owned_by": "openai-internal"
},
{
"id": "gpt-4o-audio-preview-2024-12-17",
"object": "model",
"created": 1734034239,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview-2024-12-17",
"object": "model",
"created": 1733945430,
"owned_by": "system"
},
{
"id": "gpt-4o-realtime-preview",
"object": "model",
"created": 1727659998,
"owned_by": "system"
},
{
"id": "gpt-4-0125-preview",
"object": "model",
"created": 1706037612,
"owned_by": "system"
},
{
"id": "o1-mini",
"object": "model",
"created": 1725649008,
"owned_by": "system"
},
{
"id": "text-embedding-3-large",
"object": "model",
"created": 1705953180,
"owned_by": "system"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,111 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.models = exports.models_dist = void 0;
const chalk_1 = __importDefault(require("chalk"));
const path = __importStar(require("path"));
const read_1 = require("@plastichub/fs/read");
const exists_1 = require("@plastichub/fs/exists");
const index_1 = require("../index");
const openrouter_1 = require("./openrouter");
const openai_1 = require("./openai");
const openai_2 = require("../models/openai");
const osr_commons_1 = require("@plastichub/osr-commons");
const openai_3 = require("./cache/openai");
const openrouter_2 = require("./cache/openrouter");
const models_dist = () => {
let or_models = openrouter_2.models;
let oai_models = openai_3.models;
let deepseek_models = [
{
"id": "deepseek-chat",
"name": "deepseek-chat"
},
{
"id": "deepseek-reasoner",
"name": "deepseek-reasoner"
},
];
const modelsOpenAIPath = path.resolve((0, index_1.module_root)(), 'openai.json');
if ((0, exists_1.sync)(modelsOpenAIPath)) {
oai_models = (0, read_1.sync)(modelsOpenAIPath, 'json');
}
const modelsRouterPath = path.resolve((0, index_1.module_root)(), 'openrouter.json');
if ((0, exists_1.sync)(modelsRouterPath)) {
or_models = (0, read_1.sync)(modelsRouterPath, 'json');
}
const models = [];
models.push(chalk_1.default.magenta.bold('\n OpenRouter models:\n'));
models.push(...(0, openrouter_1.listModelsAsStrings)(or_models));
models.push(chalk_1.default.magenta.bold('\n OpenAI models:\n'));
models.push(...(0, openai_1.listModelsAsStrings)(oai_models));
models.push('-----\n');
models.push(chalk_1.default.magenta.bold('\n Deepseek models:\n'));
models.push(...(0, openai_1.listModelsAsStrings)(deepseek_models));
models.push('-----\n');
return models;
};
exports.models_dist = models_dist;
const models = () => {
const models = [];
const openRouterPath = path.resolve(openrouter_1.CACHE_PATH);
if (!(0, exists_1.sync)(openRouterPath)) {
(0, openrouter_1.fetchOpenRouterModels)();
}
if ((0, exists_1.sync)(openRouterPath)) {
const modelData = (0, read_1.sync)(openRouterPath, 'json');
models.push(chalk_1.default.magenta.bold('\n OpenRouter models:\n'));
models.push(...(0, openrouter_1.listModelsAsStrings)(modelData.models));
}
index_1.logger.debug('Openrouter models cache: ', openai_1.CACHE_PATH);
const openAIPath = path.resolve(openai_1.CACHE_PATH);
const config = (0, osr_commons_1.CONFIG_DEFAULT)();
if (!(0, exists_1.sync)(openAIPath) && config?.openai?.key) {
(0, openai_2.fetchOpenAIModels)(config.openai.key);
}
if ((0, exists_1.sync)(openAIPath)) {
const modelData = (0, read_1.sync)(openAIPath, 'json');
models.push(chalk_1.default.magenta.bold('\n OpenAI models:\n'));
models.push(...(0, openai_1.listModelsAsStrings)(modelData.models));
}
index_1.logger.debug('OpenAI models cache: ', openai_1.CACHE_PATH);
models.push('-----\n');
return models;
};
exports.models = models;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbW9kZWxzL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLGtEQUF5QjtBQUN6QiwyQ0FBNEI7QUFFNUIsOENBQWtEO0FBQ2xELGtEQUFzRDtBQUV0RCxvQ0FBOEM7QUFDOUMsNkNBQXVMO0FBQ3ZMLHFDQUFnSjtBQUNoSiw2Q0FBb0Q7QUFDcEQseURBQXdEO0FBRXhELDJDQUF1RDtBQUN2RCxtREFBK0Q7QUFFeEQsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFO0lBRTlCLElBQUksU0FBUyxHQUFHLG1CQUFnQixDQUFBO0lBQ2hDLElBQUksVUFBVSxHQUFHLGVBQVksQ0FBQTtJQUM3QixJQUFJLGVBQWUsR0FBRztRQUNsQjtZQUNFLElBQUksRUFBRSxlQUFlO1lBQ3JCLE1BQU0sRUFBRSxlQUFlO1NBQ3hCO1FBQ0Q7WUFDRSxJQUFJLEVBQUUsbUJBQW1CO1lBQ3pCLE1BQU0sRUFBRSxtQkFBbUI7U0FDNUI7S0FDSixDQUFBO0lBRUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsbUJBQVcsR0FBRSxFQUFFLGFBQWEsQ0FBQyxDQUFBO0lBQ25FLElBQUcsSUFBQSxhQUFNLEVBQUMsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO1FBQzVCLFVBQVUsR0FBRyxJQUFBLFdBQUksRUFBQyxnQkFBZ0IsRUFBRSxNQUFNLENBQVEsQ0FBQTtJQUNwRCxDQUFDO0lBRUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsbUJBQVcsR0FBRSxFQUFFLGlCQUFpQixDQUFDLENBQUE7SUFDdkUsSUFBRyxJQUFBLGFBQU0sRUFBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7UUFDNUIsU0FBUyxHQUFHLElBQUEsV0FBSSxFQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBUSxD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

View File

@ -0,0 +1,94 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CACHE_PATH = void 0;
exports.fetchOpenAIModels = fetchOpenAIModels;
exports.listModelsAsStrings = listModelsAsStrings;
const openai_1 = require("openai");
const path = __importStar(require("path"));
const index_1 = require("../index");
const exists_1 = require("@plastichub/fs/exists");
const read_1 = require("@plastichub/fs/read");
const write_1 = require("@plastichub/fs/write");
exports.CACHE_PATH = path.resolve(path.join(path.parse(__filename).dir), 'data', 'openai_models.json');
const CACHE_DURATION = 24 * 60 * 60 * 1000;
async function readFromCache(cachePath = exports.CACHE_PATH) {
try {
if (!(0, exists_1.sync)(cachePath)) {
return null;
}
const cacheData = (0, read_1.sync)(cachePath);
const now = Date.now();
if (now - cacheData.timestamp > CACHE_DURATION) {
//return null
}
return cacheData.models;
}
catch (error) {
index_1.logger.error('Error reading from cache:', error);
return null;
}
}
function writeToCache(models, cachePath = exports.CACHE_PATH) {
try {
const cacheData = {
timestamp: Date.now(),
models
};
(0, write_1.sync)(cachePath, cacheData);
}
catch (error) {
index_1.logger.error('Error writing to cache:', error);
}
}
async function fetchOpenAIModels(apiKey, cachePath = exports.CACHE_PATH) {
try {
const openai = new openai_1.OpenAI({ apiKey });
const response = await openai.models.list();
const models = response.data;
index_1.logger.info(`Fetched ${models.length} OpenAI models, to ${cachePath}`);
writeToCache(models, cachePath);
return models;
}
catch (error) {
index_1.logger.error('Error fetching OpenAI models:', error);
throw error;
}
}
function listModelsAsStrings(models) {
models = models.sort((a, b) => a.id.localeCompare(b.id));
return models.map((model) => `${model.id}`);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbmFpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21vZGVscy9vcGVuYWkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBbURBLDhDQVlDO0FBQ0Qsa0RBR0M7QUFuRUQsbUNBQStCO0FBRS9CLDJDQUE0QjtBQUM1QixvQ0FBaUM7QUFFakMsa0RBQXNEO0FBQ3RELDhDQUFrRDtBQUNsRCxnREFBb0Q7QUFjdkMsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLG9CQUFvQixDQUFDLENBQUE7QUFDM0csTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFBO0FBRTFDLEtBQUssVUFBVSxhQUFhLENBQUMsWUFBb0Isa0JBQVU7SUFDdkQsSUFBSSxDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUEsYUFBTSxFQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDckIsT0FBTyxJQUFJLENBQUE7UUFDZixDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBQSxXQUFJLEVBQUMsU0FBUyxDQUFpQixDQUFBO1FBQ2pELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUN0QixJQUFJLEdBQUcsR0FBRyxTQUFTLENBQUMsU0FBUyxHQUFHLGNBQWMsRUFBRSxDQUFDO1lBQzdDLGFBQWE7UUFDakIsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQTtJQUMzQixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNiLGNBQU0sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsS0FBSyxDQUFDLENBQUE7UUFDaEQsT0FBTyxJQUFJLENBQUE7SUFDZixDQUFDO0FBQ0wsQ0FBQztBQUNELFNBQVMsWUFBWSxDQUFDLE1BQXFCLEVBQUUsWUFBb0Isa0JBQVU7SUFDdkUsSUFBSSxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQWlCO1lBQzVCLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ3JCLE1BQU07U0FDVCxDQUFBO1FBQ0QsSUFBQSxZQUFLLEVBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBQy9CLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsY0FBTSxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUNsRCxDQUFDO0FBQ0wsQ0FBQztBQUNNLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxNQUFjLEVBQUUsWUFBb0Isa0JBQVU7SUFDbEYsSUFBSSxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFNLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQ3JDLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUMzQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFBO1FBQzVCLGNBQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxNQUFNLENBQUMsTUFBTSxzQkFBc0IsU0FBUyxFQUFFLENBQUMsQ0FBQTtRQUN0RSxZQUFZLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBQy9CLE9BQU8sTUFBTSxDQUFBO0lBQ2pCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2IsY0FBTSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsRUFBRSxLQUFLLENBQUMsQ0FBQTtRQUNwRCxNQUFNLEtBQUssQ0FBQTtJQUNmLENBQUM7QUFDTCxDQUFDO0FBQ0QsU0FBZ0IsbUJBQW1CLENBQUMsTUFBcUI7SUFDckQsTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUN4RCxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDaEQsQ0FBQyJ9

View File

@ -0,0 +1,117 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchOpenRouterModels = exports.readFromCache = exports.CACHE_PATH = void 0;
exports.findFreeModels = findFreeModels;
exports.findFreePromptModels = findFreePromptModels;
exports.findFreeCompletionModels = findFreeCompletionModels;
exports.findFreeImageModels = findFreeImageModels;
exports.listModelsAsStrings = listModelsAsStrings;
const axios_1 = __importDefault(require("axios"));
const path = __importStar(require("path"));
const index_1 = require("../index");
const exists_1 = require("@plastichub/fs/exists");
const read_1 = require("@plastichub/fs/read");
const write_1 = require("@plastichub/fs/write");
exports.CACHE_PATH = path.resolve(path.join(path.parse(__filename).dir), 'data', 'openrouter_models.json');
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
const readFromCache = (cachePath = exports.CACHE_PATH) => {
try {
if (!(0, exists_1.sync)(cachePath)) {
return null;
}
const cacheData = (0, read_1.sync)(cachePath, 'json');
const now = Date.now();
if (now - cacheData.timestamp > CACHE_DURATION) {
//return null
}
return cacheData.models;
}
catch (error) {
index_1.logger.error('Error reading from cache:', error);
return null;
}
};
exports.readFromCache = readFromCache;
function writeToCache(models, cachePath = exports.CACHE_PATH) {
const cacheData = {
timestamp: Date.now(),
models
};
(0, write_1.sync)(cachePath, cacheData);
}
const fetchOpenRouterModels = async (cachePath = exports.CACHE_PATH) => {
try {
// If no cache or expired, fetch from API
const response = await axios_1.default.get('https://openrouter.ai/api/v1/models', {
params: {
// supported_parameters: 'tools'
}
});
writeToCache(response.data.data);
index_1.logger.debug(`Fetched ${response.data.data.length} OpenRouter models to ${cachePath}`);
return response.data.data;
}
catch (error) {
index_1.logger.error('Error fetching OpenRouter models:', error);
throw error;
}
};
exports.fetchOpenRouterModels = fetchOpenRouterModels;
function findFreeModels(models) {
return models.filter((model) => model.pricing.prompt === 0 &&
model.pricing.completion === 0 &&
model.pricing.image === 0);
}
function findFreePromptModels(models) {
return models.filter((model) => model.pricing.prompt === 0);
}
function findFreeCompletionModels(models) {
return models.filter((model) => model.pricing.completion === 0);
}
function findFreeImageModels(models) {
return models.filter((model) => model.pricing.image === 0);
}
function listModelsAsStrings(models) {
models = models.sort((a, b) => a.name.localeCompare(b.name));
return models.map((model) => {
const isFree = model.name.includes('free');
return `${model.id} | ${isFree ? 'free' : 'paid'}`;
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbnJvdXRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tb2RlbHMvb3BlbnJvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtRkEsd0NBT0M7QUFDRCxvREFFQztBQUVELDREQUVDO0FBRUQsa0RBRUM7QUFDRCxrREFNQztBQTVHRCxrREFBeUI7QUFDekIsMkNBQTZCO0FBQzdCLG9DQUFpQztBQUVqQyxrREFBc0Q7QUFDdEQsOENBQWtEO0FBQ2xELGdEQUFvRDtBQTZCdkMsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLHdCQUF3QixDQUFDLENBQUE7QUFFL0csTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsMkJBQTJCO0FBRWhFLE1BQU0sYUFBYSxHQUFHLENBQUMsWUFBb0Isa0JBQVUsRUFBcUMsRUFBRTtJQUNqRyxJQUFJLENBQUM7UUFDSCxJQUFJLENBQUMsSUFBQSxhQUFNLEVBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUN2QixPQUFPLElBQUksQ0FBQTtRQUNiLENBQUM7UUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFBLFdBQUksRUFBQyxTQUFTLEVBQUUsTUFBTSxDQUFpQixDQUFDO1FBQzFELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLEdBQUcsR0FBRyxTQUFTLENBQUMsU0FBUyxHQUFHLGNBQWMsRUFBRSxDQUFDO1lBQy9DLGFBQWE7UUFDZixDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUMsTUFBYSxDQUFDO0lBQ2pDLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FB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

13482
packages/osr-code-bot/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
{
"name": "@plastichub/code-bot",
"version": "0.3.4",
"publishConfig": {
"access": "public"
},
"bin": {
"kbotd": "./main.js"
},
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsc -p . --watch",
"lint": "eslint src --ext .ts",
"test": "vitest run",
"test2:watch": "vitest",
"test2:coverage": "vitest run --coverage",
"webpack": "webpack --config webpack.config.js --stats-error-details",
"exe:win": "cd dist && nexe -i main_node.js -o kbot.exe --build --temp=../../temp-kbot --verbose",
"exe:lnx": "cd dist && nexe -i main_node.js -o kbot --build --temp=../../temp-kbot --verbose"
},
"dependencies": {
"@astrojs/ts-plugin": "1.10.4",
"@plastichub/core": "^0.2.6",
"@plastichub/fs": "^0.13.40",
"@plastichub/osr-ai-tools": "file:../osr-ai-tools",
"@plastichub/osr-commons": "0.5.3",
"@plastichub/osr-log": "0.1.6",
"axios": "1.7.9",
"chalk": "4.0.0",
"emojilib": "4.0.1",
"free-astro-components": "1.1.1",
"glob": "11.0.1",
"marked": "14.1.4",
"marked-terminal": "7.2.1",
"mime-types": "2.1.35",
"openai": "4.80.1",
"p-map": "^4.0.0",
"tslog": "^4.9.3",
"yargs": "17.7.2",
"zod": "3.24.1"
},
"keywords": [
"ai",
"code-assistant",
"gpt",
"bolt.new",
"cursor",
"code-generation",
"pair-programming",
"copilot",
"code-completion",
"natural-language-processing",
"machine-learning",
"autonomous-coding",
"code-analysis",
"code-suggestions",
"code-intelligence",
"refactoring-assistant",
"code-documentation",
"semantic-analysis",
"code-review"
],
"devDependencies": {
"@types/node": "22.10.2",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitest/coverage-v8": "^2.1.8",
"eslint": "^8.57.1",
"ts-json-schema-generator": "^2.3.0",
"ts-loader": "9.5.1",
"tsx": "^4.5.0",
"typescript": "^5.7.2",
"vitest": "^2.1.8",
"webpack": "5.97.1",
"webpack-cli": "6.0.1",
"webpack-visualizer-plugin2": "1.1.0",
"zod-to-json-schema": "3.24.1"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
# Personal Preferences Configuration
This file stores personal information and preferences to help the AI assistant provide more personalized and contextual responses.
## My Preferences
Gender : male
Location : Sentmenat, Barcelona, Spain
Language : German, prefer english
Occupation : software developer, Typescript
Age : 45+
## Contacts
My email address : cgoflyn@gmail.com
My wife's email (Anne) : barbier.anne13@gmail.com
## Content
When creating content
- always Markdown
- always add links to sources
- when sending emails, always add 'kind regards, Guenter'
- when sending emails to Anne, always in french
- when searching for news, always add links to videos, search via Google and other news outlets
- always include the prompt in the result
- Markdown
- always new lines after headings
- no need to test file for existence

View File

@ -0,0 +1,60 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.load = void 0;
const osr_commons_1 = require("@plastichub/osr-commons");
const exists_1 = require("@plastichub/fs/exists");
const path = __importStar(require("node:path"));
const profile_1 = require("@plastichub/osr-commons/profile");
const env_1 = require("./utils/env");
const testPath = (profilePath) => {
if (!profilePath) {
return;
}
const ret = path.resolve((0, osr_commons_1.resolve)(profilePath, false, (0, env_1.env_vars)()));
if ((0, exists_1.sync)(ret))
return ret;
};
const load = async (options) => {
let profile = { includes: [], variables: {}, env: {} };
let profilePath = testPath(options.profile || path.join(options.logs, 'profile.json'));
if (!profilePath || !(0, exists_1.sync)(profilePath) || !(0, osr_commons_1.isFile)(profilePath)) {
return profile.variables;
}
profile = (0, profile_1.parseProfile)(profilePath, profile, { env: options.env || 'default' }) || profile;
return profile.variables;
};
exports.load = load;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9wcm9maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLHlEQUF5RDtBQUN6RCxrREFBc0Q7QUFDdEQsZ0RBQWlDO0FBQ2pDLDZEQUE4RDtBQUM5RCxxQ0FBc0M7QUFFdEMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxXQUFtQixFQUFFLEVBQUU7SUFDckMsSUFBRyxDQUFDLFdBQVcsRUFBQyxDQUFDO1FBQ2IsT0FBTTtJQUNWLENBQUM7SUFDRCxNQUFNLEdBQUcsR0FBRSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEscUJBQU8sRUFBQyxXQUFXLEVBQUUsS0FBSyxFQUFFLElBQUEsY0FBUSxHQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2hFLElBQUcsSUFBQSxhQUFNLEVBQUMsR0FBRyxDQUFDO1FBQUUsT0FBTyxHQUFHLENBQUE7QUFDOUIsQ0FBQyxDQUFBO0FBRU0sTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLE9BQWtCLEVBQW1DLEVBQUU7SUFDOUUsSUFBSSxPQUFPLEdBQUcsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFBO0lBQ3RELElBQUksV0FBVyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFBO0lBQ3RGLElBQUcsQ0FBQyxXQUFXLElBQUksQ0FBQyxJQUFBLGFBQU0sRUFBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUEsb0JBQU0sRUFBQyxXQUFXLENBQUMsRUFBQyxDQUFDO1FBQzdELE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQTtJQUM1QixDQUFDO0lBQ0QsT0FBTyxHQUFHLElBQUEsc0JBQVksRUFBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLElBQUksU0FBUyxFQUFFLENBQUMsSUFBSSxPQUFPLENBQUE7SUFDMUYsT0FBTyxPQUFPLENBQUMsU0FBUyxDQUFBO0FBQzVCLENBQUMsQ0FBQTtBQVJZLFFBQUEsSUFBSSxRQVFoQiJ9

View File

@ -0,0 +1,13 @@
{
"includes": [],
"variables": {
"GIT_REPO": "https://git.polymech.io/",
"GIT_USER": "osr-plastic"
},
"env": {
"hugo-release":{
"includes": [],
"variables": {}
}
}
}

View File

@ -0,0 +1,59 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.preferences = exports.prompt = void 0;
const input_1 = require("./utils/input");
const read_1 = require("@plastichub/fs/read");
const osr_commons_1 = require("@plastichub/osr-commons");
const path = __importStar(require("path"));
const env_1 = require("./utils/env");
const prompt = async (opts) => {
const input = await (0, input_1.resolveQuery)(opts);
return {
role: "user",
content: input || ''
};
};
exports.prompt = prompt;
const preferences = async (opts) => {
const preferencesPath = path.resolve((0, osr_commons_1.resolve)(opts.preferences, false, (0, env_1.env_vars)()));
const preferences = (0, read_1.sync)(preferencesPath, 'string');
return {
role: "user",
content: preferences || ''
};
};
exports.preferences = preferences;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL3Byb21wdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFDQSx5Q0FBNEM7QUFFNUMsOENBQWtEO0FBQ2xELHlEQUFpRDtBQUNqRCwyQ0FBNEI7QUFDNUIscUNBQXNDO0FBQy9CLE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxJQUFlLEVBQW1ELEVBQUU7SUFDN0YsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFBLG9CQUFZLEVBQUMsSUFBSSxDQUFDLENBQUE7SUFDdEMsT0FBTztRQUNILElBQUksRUFBRSxNQUFNO1FBQ1osT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO0tBQ3ZCLENBQUE7QUFDTCxDQUFDLENBQUE7QUFOWSxRQUFBLE1BQU0sVUFNbEI7QUFDTSxNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUUsSUFBZSxFQUFtRCxFQUFFO0lBQ2xHLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSxxQkFBTyxFQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxFQUFFLElBQUEsY0FBUSxHQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xGLE1BQU0sV0FBVyxHQUFHLElBQUEsV0FBSSxFQUFDLGVBQWUsRUFBRSxRQUFRLENBQVcsQ0FBQTtJQUM3RCxPQUFPO1FBQ0gsSUFBSSxFQUFFLE1BQU07UUFDWixPQUFPLEVBQUUsV0FBVyxJQUFJLEVBQUU7S0FDN0IsQ0FBQTtBQUNMLENBQUMsQ0FBQTtBQVBZLFFBQUEsV0FBVyxlQU92QiJ9

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
npm run webpack
sh scripts/update-readme.sh
cp README.md dist/README.md

View File

@ -0,0 +1,8 @@
kbotd modify \
--path=. \
--template=typescript \
--query="./.kbot/todos-docker.md" \
--include="./package.json" \
--include="systems/*" \
--include="!code-server*" \
--disable="npm,terminal"

View File

@ -0,0 +1,7 @@
kbotd modify \
--prompt="./.kbot/docs.md" \
--include="./src/commands/run.ts" \
--include="./src/zod_schema.ts" \
--logLevel=2

View File

@ -0,0 +1,3 @@
cat ./docs_/README.md > ./README.md
cat ./docs_/parameters.md >> ./README.md
cat ./docs_/advanced.md >> ./README.md

View File

@ -0,0 +1,10 @@
kbotd modify \
--path=. \
--prompt="./.kbot/todos.md" \
--mode=completion \
--router2=openai \
--model=openai/gpt-4-32k \
--include2="src/commands/run.ts" \
--include2="src/commands/run-tools.ts" \
--disable="npm,terminal,git,user,search,email" \
--dst="./.kbot/todos-log.md"

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,78 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { loadConfig } from '../config'
import { createClient } from '../client'
import * as fs from 'fs'
vi.mock('fs')
vi.mock('@plastichub/osr-commons', () => ({
CONFIG_DEFAULT: () => ({
openrouter: { key: 'default-openrouter-key' },
openai: { key: 'default-openai-key' }
})
}))
vi.mock('.', () => ({
logger: {
error: vi.fn(),
debug: vi.fn()
}
}))
describe('loadConfig', () => {
beforeEach(() => {
vi.resetAllMocks()
})
it('should load config with API key from options', () => {
const options = { api_key: 'test-key' }
const result = loadConfig(options)
expect(result.apiKey).toBe('test-key')
})
it('should load config from JSON string', () => {
const options = {
config: '{"openrouter":{"key":"json-key"}}'
}
const result = loadConfig(options)
expect(result.jsonConfig?.openrouter?.key).toBe('json-key')
})
it('should load config from JSON file', () => {
vi.mocked(fs.readFileSync).mockReturnValue('{"openrouter":{"key":"file-key"}}')
const options = { config: 'config.json' }
const result = loadConfig(options)
expect(result.jsonConfig?.openrouter?.key).toBe('file-key')
})
it('should handle invalid JSON config', () => {
const options = { config: 'invalid-json' }
const result = loadConfig(options)
expect(result.jsonConfig).toBeUndefined()
})
})
describe('createClient', () => {
beforeEach(() => {
vi.resetAllMocks()
process.env.API_KEY = undefined
})
afterEach(() => {
vi.resetAllMocks()
})
it('should create OpenRouter client with API key from options', () => {
const client = createClient({ api_key: 'test-key', router: 'openrouter' })
expect(client).toBeDefined()
})
it('should create OpenAI client with API key from options', () => {
const client = createClient({ api_key: 'test-key', router: 'openai' })
expect(client).toBeDefined()
})
it('should return undefined for unknown router', () => {
const client = createClient({ api_key: 'test-key', router: 'unknown' as any })
expect(client).toBeUndefined()
})
})

View File

@ -0,0 +1,98 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import {resolve_package_path, template_path, load } from '../templates'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as read } from '@plastichub/fs/read'
import { filesEx as include } from '@plastichub/osr-commons/_glob'
import * as path from 'path'
import { logger } from '../'
vi.mock('@plastichub/fs/exists')
vi.mock('@plastichub/fs/read')
vi.mock('@plastichub/osr-commons/_glob')
vi.mock('@plastichub/osr-commons', () => ({
resolve: vi.fn((path) => path),
substitute: vi.fn((x, y) => y)
}))
vi.mock('path', async () => {
const actual = await vi.importActual('path')
return {
...(actual as any),
resolve: vi.fn((p) => p),
join: vi.fn((...paths) => paths.join('/')),
parse: vi.fn((p) => ({ name: p.split('/').pop()?.split('.')[0] }))
}
})
vi.mock('../', () => ({
logger: {
warn: vi.fn(),
error: vi.fn(),
debug: vi.fn()
}
}))
describe('templates', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe('template_path', () => {
it('should return resolved path if template exists', () => {
vi.mocked(exists).mockReturnValue(true)
const options = { template: 'test-template', path: './' }
const result = template_path(options)
expect(result).toBe('test-template')
expect(exists).toHaveBeenCalledWith('test-template')
})
it('should check project path if direct path does not exist', () => {
vi.mocked(exists).mockReturnValueOnce(false).mockReturnValueOnce(true)
const options = { template: 'test-template', path: './project' }
const result = template_path(options)
expect(result).toBe('./project/test-template')
})
it('should use template root if template not found in direct or project paths', () => {
vi.mocked(exists).mockReturnValue(false)
const options = {
template: 'test-template',
path: './project',
templateRoot: '/templates'
}
const result = template_path(options)
expect(result).toBe('/templates/ai-template-test-template')
expect(logger.warn).toHaveBeenCalledWith('Template root /templates does not exist.')
})
it('should use default template root if not provided', () => {
vi.mocked(exists).mockReturnValue(false)
const options = { template: 'test-template', path: './project' }
const result = template_path(options)
expect(result).toBe('${POLYMECH-ROOT}/ai-template-test-template')
})
})
describe('load', () => {
it('should handle non-existent target directory', () => {
vi.mocked(exists).mockReturnValue(false)
const options = { path: './nonexistent' }
const result = load(options)
expect(result).toEqual({
include: [
"!node_modules/**/*",
"!dist/**/*",
"!build/**/*",
"!coverage/**/*",
"!*.log",
"!.kbot",
"!.git",
"*"
],
messages: [],
tools: ['fs', 'git', 'interact', 'terminal', 'search']
})
expect(logger.error).toHaveBeenCalledWith(
'Target directory ./nonexistent does not exist.'
)
})
})
})

View File

@ -0,0 +1,60 @@
import { OpenAI } from 'openai'
import { logger } from './index'
import { loadConfig } from './config'
import { IKBotOptions } from './zod_types'
export const createClient = (options: IKBotOptions) => {
const config = loadConfig(options)
let apiKey: string = options.api_key
if (!config) {
logger.error(
"Config not found in $HOME/.osr/config.json. " +
"Optionally, export OSR_CONFIG with the path to the configuration file, "
);
return undefined
}
const router = options.router ?? "openrouter"
let baseURL = options.baseURL
if (!options.baseURL) {
switch (router) {
case "openrouter":
apiKey = apiKey || config?.openrouter?.key;
if (!options.baseURL) {
baseURL = "https://openrouter.ai/api/v1"
}
break;
case "openai":
apiKey = apiKey || config?.openai?.key;
break;
case "deepseek":
apiKey = apiKey || config?.deepseek?.key;
if (!options.baseURL) {
baseURL = "https://api.deepseek.com"
}
break;
}
}
if (!apiKey) {
logger.error(`No ${router} key found. Please provide an "api_key", set it in the config, or pass it via JSON config.`);
return undefined;
}
if (router === "openrouter" && !options.model) {
options.model = "anthropic/claude-3.5-sonnet"
}
if (router === "openai" && !options.model) {
options.model = "gpt-4o"
}
if (router === "deepseek" && !options.model) {
options.model = "deepseek-chat"
}
logger.info(`Creating client with ${router} router, model ${options.model}, and API key ${apiKey} at ${baseURL}`)
return new OpenAI({
apiKey,
baseURL,
})
}

View File

@ -0,0 +1,74 @@
import path from 'path'
import OpenAI from 'openai'
//import { ChatCompletion, ChatCompletionMessage, ChatCompletionMessageParam } from 'openai/resources'
//import { } from 'openai/resources'
import { ICollector } from '@plastichub/osr-ai-tools/types'
import { winstonLogger, } from '@plastichub/osr-log'
import { resolve } from '@plastichub/osr-commons'
import { RunnableFunctionWithParse } from 'openai/lib/RunnableFunction'
import { IKBotOptions } from './zod_types'
import { logger as loggerIntern } from './'
import { ChatCompletion, ChatCompletionMessage, ChatCompletionMessageParam } from 'openai/resources/index.mjs'
export const collector = (options: IKBotOptions, client: OpenAI): ICollector => {
return {
//OpenAI
onMessage: (message: ChatCompletionMessageParam) => {
const logFile = path.resolve(path.join(resolve(options.logs), 'openai-message.json'))
const logger = winstonLogger('collector:onMessage', logFile)
logger.info(message)
},
onToolCall: async (message: ChatCompletionMessage.FunctionCall) => {
const logFile = path.resolve(path.join(resolve(options.logs), 'tool-call.json'))
const logger = winstonLogger('collector:onToolCall', logFile)
try {
const msg = { ...message, arguments: JSON.parse(message.arguments) }
logger.debug(msg)
} catch (e) {
logger.debug(message)
}
},
onFunctionCallResult: (message: string) => {
const logFile = path.resolve(path.join(resolve(options.logs), 'tool-call-result.json'))
const logger = winstonLogger('collector:onFunctionCallResult', logFile)
try {
const msg = { message: JSON.parse(message) }
logger.debug(msg)
} catch (e) {
logger.debug(message)
}
},
onChatCompletion: (message: ChatCompletion) => {
const logFile = path.resolve(path.join(resolve(options.logs), 'completion.json'))
const logger = winstonLogger('collector:onChatCompletion', logFile)
logger.debug(message)
},
onContent: (content: string) => {
const logFile = path.resolve(path.join(resolve(options.logs), 'content.json'))
const logger = winstonLogger('collector:onContent', logFile)
logger.debug(content)
},
onTool(category, name, args, result) {
const logFile = path.resolve(path.join(resolve(options.logs), 'tool.json'))
const logger = winstonLogger('collector:onTool', logFile)
logger.debug({ category, name, args, result })
},
onToolBefore: async (ctx: RunnableFunctionWithParse<any>, args: any) => {
try{
loggerIntern.debug(`onToolBefore :${ctx.name}`)
}catch(e){
loggerIntern.error(e)
}
return args
},
onToolAfter: async (ctx: RunnableFunctionWithParse<any>, args: any, result?: any) => {
try {
loggerIntern.debug(`onToolAfter : ${ctx.name}`)
} catch (e) {
loggerIntern.error(e)
}
return result[0]
}
}
}

View File

@ -0,0 +1,40 @@
import path from 'path'
import { sync as read } from '@plastichub/fs/read'
import { sync as write } from '@plastichub/fs/write'
import { sync as exists } from '@plastichub/fs/exists'
import { logger } from '../'
import { fetchOpenAIModels } from '../models/openai'
import { fetchOpenRouterModels, OpenRouterModel } from '../models/openrouter'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
import { arch } from 'os'
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() as any
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)}`)
}

View File

@ -0,0 +1,12 @@
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) as string)
}

View File

@ -0,0 +1,34 @@
import path from 'path'
import { sync as write } from '@plastichub/fs/write'
import { logger, module_root } from '..'
import { fetchOpenAIModels } from '../models/openai'
import { fetchOpenRouterModels } from '../models/openrouter'
import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
export const fetch = async () => {
const config = CONFIG_DEFAULT() as any
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}`)
}

View File

@ -0,0 +1,257 @@
import * as path from 'path'
import * as fs from 'fs'
import { BaseHandler } from './base-handler';
import { logger } from '../../index'
import { createClient } from '../../client';
import { toFile } from "openai"
import { IKBotOptions } from '../../zod_types';
/**
* Hex bytes for the "ID3" tag (ID3v2 header).
* Typically found at the beginning of an MP3 file that contains ID3 metadata.
*/
export const ID3_HEADER_BYTES = new Uint8Array([0x49, 0x44, 0x33]);
/**
* Possible first two bytes (frame sync) of an MP3 file without an ID3 tag.
* Commonly:
* - 0xFF 0xFB for MPEG-1 Layer III
* - 0xFF 0xF3 for MPEG-2 Layer III
* - 0xFF 0xF2 for MPEG-2.5 Layer III
*/
export const MP3_FRAME_SYNC_PATTERNS: Uint8Array[] = [
new Uint8Array([0xFF, 0xFB]),
new Uint8Array([0xFF, 0xF3]),
new Uint8Array([0xFF, 0xF2]),
];
const isMp3File = (fileBuffer: ArrayBuffer): boolean => {
const byteView = new Uint8Array(fileBuffer);
// Check if the file starts with ID3 bytes
if (
byteView[0] === ID3_HEADER_BYTES[0] &&
byteView[1] === ID3_HEADER_BYTES[1] &&
byteView[2] === ID3_HEADER_BYTES[2]
) {
return true;
}
// Or check if it starts with a known frame sync pattern
return MP3_FRAME_SYNC_PATTERNS.some((pattern) => {
return byteView[0] === pattern[0] && byteView[1] === pattern[1];
});
}
/**
* "RIFF" in ASCII
* 0x52 = R
* 0x49 = I
* 0x46 = F
* 0x46 = F
*/
export const WAV_RIFF_HEADER = new Uint8Array([0x52, 0x49, 0x46, 0x46]);
/**
* "WAVE" in ASCII
* 0x57 = W
* 0x41 = A
* 0x56 = V
* 0x45 = E
*/
export const WAV_WAVE_HEADER = new Uint8Array([0x57, 0x41, 0x56, 0x45]);
/**
* Checks if the provided file buffer is likely a WAV file.
* - Must start with "RIFF" (bytes 03)
* - Must have "WAVE" at bytes 811
*/
export function isWavFile(fileBuffer: ArrayBuffer): boolean {
const byteView = new Uint8Array(fileBuffer);
// Safety check: we need at least 12 bytes to validate "RIFF" + "WAVE" positions
if (byteView.length < 12) {
return false;
}
// Check the "RIFF" part (bytes 0..3)
if (
byteView[0] !== WAV_RIFF_HEADER[0] ||
byteView[1] !== WAV_RIFF_HEADER[1] ||
byteView[2] !== WAV_RIFF_HEADER[2] ||
byteView[3] !== WAV_RIFF_HEADER[3]
) {
return false;
}
// Check the "WAVE" part (bytes 8..11)
if (
byteView[8] !== WAV_WAVE_HEADER[0] ||
byteView[9] !== WAV_WAVE_HEADER[1] ||
byteView[10] !== WAV_WAVE_HEADER[2] ||
byteView[11] !== WAV_WAVE_HEADER[3]
) {
return false;
}
return true;
}
/**
* "ftyp" in ASCII (0x66 = f, 0x74 = t, 0x79 = y, 0x70 = p).
*/
export const FTYP_BOX_HEADER = new Uint8Array([0x66, 0x74, 0x79, 0x70]);
/**
* Common major/compatible brand signatures for M4A.
* - "M4A " (0x4D 0x34 0x41 0x20)
* - "mp42" (0x6D 0x70 0x34 0x32)
* - "isom" (0x69 0x73 0x6F 0x6D)
*
* Note: Some M4A files might list different/older brand combos,
* but these are the most common.
*/
export const M4A_BRANDS: Uint8Array[] = [
new Uint8Array([0x4D, 0x34, 0x41, 0x20]), // "M4A "
new Uint8Array([0x6D, 0x70, 0x34, 0x32]), // "mp42"
new Uint8Array([0x69, 0x73, 0x6F, 0x6D]), // "isom"
];
/**
* Checks if the provided file buffer likely represents an M4A.
*
* Basic check:
* 1. Must have at least 12 bytes (4 bytes size + "ftyp" + brand).
* 2. Bytes [4..7] should be "f t y p".
* 3. Bytes [8..11] should match a known brand (e.g., "M4A ", "mp42", "isom").
*
* @param fileBuffer The raw file data as an ArrayBuffer
* @returns boolean indicating if this is likely an M4A
*/
export function isM4AFile(fileBuffer: ArrayBuffer): boolean {
const byteView = new Uint8Array(fileBuffer);
// We need at least 12 bytes to check: [0..3] size, [4..7] 'ftyp', [8..11] brand
if (byteView.length < 12) {
return false;
}
// Check that bytes [4..7] == "ftyp"
if (
byteView[4] !== FTYP_BOX_HEADER[0] ||
byteView[5] !== FTYP_BOX_HEADER[1] ||
byteView[6] !== FTYP_BOX_HEADER[2] ||
byteView[7] !== FTYP_BOX_HEADER[3]
) {
return false;
}
// Extract the 4-byte brand at [8..11]
const brandBytes = byteView.subarray(8, 12);
// Check if brandBytes matches any known brand
const matchesKnownBrand = M4A_BRANDS.some((brand) => {
return (
brandBytes[0] === brand[0] &&
brandBytes[1] === brand[1] &&
brandBytes[2] === brand[2] &&
brandBytes[3] === brand[3]
);
});
return matchesKnownBrand;
}
const createBuffer = (path: string): Buffer | null => {
try {
const buffer = fs.readFileSync(path)
return buffer;
} catch (error) {
console.error('Error creating buffer:', error);
return null;
}
}
const getAudioFileType = (filePath: string | Buffer): { fileName: string; mimeType: string } => {
const ext = typeof filePath === 'string' ? path.extname(filePath).toLowerCase() : null;
if (ext) {
switch (ext) {
case '.mp3':
return { fileName: 'audio.mp3', mimeType: 'audio/mpeg' };
case '.m4a':
return { fileName: 'audio.m4a', mimeType: 'audio/m4a' };
case '.wav':
return { fileName: 'audio.wav', mimeType: 'audio/wav' };
}
}
// If no ext or not a string (buffer), detect from content
const buffer = Buffer.isBuffer(filePath) ? filePath : fs.readFileSync(filePath as string);
if (isMp3File(buffer)) {
return { fileName: 'audio.mp3', mimeType: 'audio/mpeg' };
} else if (isM4AFile(buffer)) {
return { fileName: 'audio.m4a', mimeType: 'audio/m4a' };
} else if (isWavFile(buffer)) {
return { fileName: 'audio.wav', mimeType: 'audio/wav' };
}
throw new Error('Unsupported audio format');
};
export class AudioHandler extends BaseHandler {
private options: IKBotOptions;
constructor(options: IKBotOptions) {
super();
this.options = options;
}
async canHandle(content: Buffer | string, isPath: boolean): Promise<boolean> {
if (isPath) {
// Check file extension for paths
const ext = path.extname(content as string).toLowerCase();
return ['.wav', '.mp3', '.m4a'].includes(ext);
}
// Check content type for buffers
if (!Buffer.isBuffer(content)) return false;
return isMp3File(content) || isWavFile(content) || isM4AFile(content);
}
async handle(content: Buffer | string, isPath: boolean): Promise<string> {
const client = createClient({...this.options,router: 'openai'})
if (!client) {
throw new Error('Failed to create OpenAI client for audio transcription');
}
try {
let audioType: { fileName: string; mimeType: string };
if (isPath) {
const filePath = content as string;
audioType = getAudioFileType(filePath);
} else {
audioType = getAudioFileType(content as Buffer);
}
const file = await toFile(createBuffer(content as string), audioType.fileName, { type: audioType.mimeType });
if (!file) {
logger.error('Error converting source to file');
throw new Error('Failed to create file for transcription');
}
logger.debug(`Transcribing audio content... ${audioType.fileName} : ${audioType.mimeType}`);
const transcription = await client.audio.transcriptions.create({
file,
model: 'whisper-1',
response_format: "verbose_json",
});
if (transcription && transcription.text) {
logger.info('Successfully transcribed audio content');
return transcription.text;
} else {
throw new Error('No transcription text received from OpenAI');
}
} catch (error) {
logger.error('Failed to transcribe audio:', (error as Error).message);
throw new Error(`Audio transcription failed: ${(error as Error).message}`);
}
}
}

View File

@ -0,0 +1,9 @@
export interface IHandler {
canHandle(content: Buffer | string, isPath: boolean): Promise<boolean>;
handle(content: Buffer | string, isPath: boolean): Promise<string>;
}
export abstract class BaseHandler implements IHandler {
abstract canHandle(content: Buffer | string, isPath: boolean): Promise<boolean>;
abstract handle(content: Buffer | string, isPath: boolean): Promise<string>;
}

View File

@ -0,0 +1,142 @@
import { BaseHandler } from './base-handler'
import * as path from 'path'
import { sync as read } from '@plastichub/fs/read'
import { createClient } from '../../client'
import { logger } from '../../index'
import { toFile } from 'openai'
import { IKBotOptions } from '../../zod_types'
// Common image file signatures/magic numbers
const IMAGE_SIGNATURES = {
// JPEG/JPG start with FF D8
JPEG: new Uint8Array([0xFF, 0xD8]),
// PNG start with 89 50 4E 47 0D 0A 1A 0A
PNG: new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
// GIF starts with either GIF87a or GIF89a
GIF87a: new Uint8Array([0x47, 0x49, 0x46, 0x38, 0x37, 0x61]),
GIF89a: new Uint8Array([0x47, 0x49, 0x46, 0x38, 0x39, 0x61])
};
const isImageContent = (buffer: Buffer): boolean => {
if (!buffer || buffer.length < 8) return false;
// Check JPEG
if (buffer[0] === IMAGE_SIGNATURES.JPEG[0] && buffer[1] === IMAGE_SIGNATURES.JPEG[1]) {
return true;
}
// Check PNG
if (IMAGE_SIGNATURES.PNG.every((byte, i) => buffer[i] === byte)) {
return true;
}
// Check GIF
const isGif87a = IMAGE_SIGNATURES.GIF87a.every((byte, i) => buffer[i] === byte);
const isGif89a = IMAGE_SIGNATURES.GIF89a.every((byte, i) => buffer[i] === byte);
if (isGif87a || isGif89a) {
return true;
}
return false;
};
export const getImageType = (filePath: string | Buffer): { fileName: string; mimeType: string } => {
if (typeof filePath === 'string') {
const ext = path.extname(filePath).toLowerCase();
switch (ext) {
case '.jpg':
case '.jpeg':
return { fileName: 'image.jpg', mimeType: 'image/jpeg' };
case '.png':
return { fileName: 'image.png', mimeType: 'image/png' };
case '.gif':
return { fileName: 'image.gif', mimeType: 'image/gif' };
}
}
// Detect from content
const buffer = Buffer.isBuffer(filePath) ? filePath : read(filePath as string);
if (!buffer) throw new Error('Could not read image content');
if (buffer[0] === IMAGE_SIGNATURES.JPEG[0] && buffer[1] === IMAGE_SIGNATURES.JPEG[1]) {
return { fileName: 'image.jpg', mimeType: 'image/jpeg' };
}
if (IMAGE_SIGNATURES.PNG.every((byte, i) => buffer[i] === byte)) {
return { fileName: 'image.png', mimeType: 'image/png' };
}
if (IMAGE_SIGNATURES.GIF87a.every((byte, i) => buffer[i] === byte) ||
IMAGE_SIGNATURES.GIF89a.every((byte, i) => buffer[i] === byte)) {
return { fileName: 'image.gif', mimeType: 'image/gif' };
}
throw new Error('Unsupported image format');
};
export class ImageHandler extends BaseHandler {
private options: IKBotOptions;
constructor(options: IKBotOptions) {
super();
this.options = options;
}
async canHandle(content: Buffer | string, isPath: boolean): Promise<boolean> {
try {
if (isPath) {
const ext = path.extname(content as string).toLowerCase();
return ['.jpg', '.jpeg', '.png', '.gif'].includes(ext);
}
return Buffer.isBuffer(content) && isImageContent(content);
} catch {
return false;
}
}
async handle(content: Buffer | string, isPath: boolean): Promise<string> {
const client = createClient({...this.options, router: 'openai'});
if (!client) {
throw new Error('Failed to create OpenAI client for image analysis');
}
try {
const imageType = getImageType(content);
const buffer = isPath ? read(content as string) : content as Buffer;
if (!buffer) {
throw new Error('Failed to read image content');
}
const file = await toFile(buffer as Buffer, imageType.fileName, { type: imageType.mimeType });
if (!file) {
throw new Error('Failed to create file for vision analysis');
}
logger.debug(`Analyzing image content... ${imageType.fileName} : ${imageType.mimeType}`);
const response = await client.chat.completions.create({
model: 'gpt-4-vision-preview',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image in detail, focusing on relevant technical or content aspects:' },
{ type: 'image_url', image_url: { url: `data:${imageType.mimeType};base64,${buffer.toString('base64')}` } }
],
},
],
max_tokens: 1500,
});
if (response.choices[0]?.message?.content) {
logger.info('Successfully analyzed image content');
return response.choices[0].message.content;
} else {
throw new Error('No analysis received from OpenAI');
}
} catch (error) {
logger.error('Failed to analyze image:', (error as Error).message);
throw new Error(`Image analysis failed: ${(error as Error).message}`);
}
}
}

View File

@ -0,0 +1,38 @@
import { IHandler } from './base-handler'
import { TextHandler } from './text-handler'
import { AudioHandler } from './audio-handler'
import { ImageHandler } from './image-handler'
import { sync as exists } from '@plastichub/fs/exists'
import * as path from 'path'
import { IKBotOptions } from '../../zod_types'
export function createHandlers(options: IKBotOptions): IHandler[] {
return [
new AudioHandler(options),
new ImageHandler(options),
new TextHandler(),
]
}
export async function detectAndHandle(content: Buffer | string, options: IKBotOptions): Promise<string> {
const handlers = createHandlers(options)
// Check if content is a file path
const contentStr = content.toString();
if (exists(contentStr)) {
const filePath = path.resolve(contentStr);
for (const handler of handlers) {
if (await handler.canHandle(filePath, true)) {
return handler.handle(filePath, true);
}
}
}
// Handle as raw content
for (const handler of handlers) {
if (await handler.canHandle(content, false)) {
return handler.handle(content, false);
}
}
throw new Error('No suitable handler found for the input content');
}

View File

@ -0,0 +1,33 @@
import { BaseHandler } from './base-handler';
import { sync as read } from '@plastichub/fs/read';
import * as path from 'path';
export class TextHandler extends BaseHandler {
async canHandle(content: Buffer | string, isPath: boolean): Promise<boolean> {
if (isPath) {
// For file paths, check file extension
const ext = path.extname(content as string).toLowerCase();
return ['.txt', '.md', '.json', '.js', '.ts'].includes(ext);
}
// For raw content, try to decode as UTF-8 text
try {
if (Buffer.isBuffer(content)) {
content.toString('utf8');
}
return true;
} catch {
return false;
}
}
async handle(content: Buffer | string, isPath: boolean): Promise<string> {
if (isPath) {
// Read content from file
return read(content as string, 'string') as string;
}
// Return raw content as string
return Buffer.isBuffer(content) ? content.toString('utf8') : content;
}
}

View File

@ -0,0 +1,55 @@
import { marked } from 'marked'
import { markedTerminal } from 'marked-terminal'
import { OptionsSchema } from '../zod_schema'
import { getDefaultValue, getDescription } from '@plastichub/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: string = marked(md.join('\n')) as string;
process.stdout.write(content)
return content
}
export default async (argv: any) => {
return help()
}

View File

@ -0,0 +1,107 @@
import { sync as dir } from '@plastichub/fs/dir'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as write } from '@plastichub/fs/write'
import * as path from 'path'
import { IKBotTask } from '../types'
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: IKBotTask) => {
const logger = new Logger<unknown>({
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
}

View File

@ -0,0 +1,5 @@
import * as path from 'path'
import { sync as read } from '@plastichub/fs/read'
import { sync as exists } from '@plastichub/fs/exists'
import { Logger } from 'tslog'
import { logger } from '../'

View File

@ -0,0 +1,75 @@
// src/markdown-blessed.ts
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).
*/
const customRenderer = {
image({ href, title, text }: Tokens.Image): string {
// Provide a textual placeholder instead of an actual image
return `\n[IMAGE: ${text || 'No Alt'}](${href || 'No Href'})\n`;
},
// (Optional) you can override other renderer methods here
};
// We tell Marked to use our custom renderer
// Alternatively, you can pass { renderer: customRenderer } directly to marked().
marked.use({ renderer: customRenderer });
/**
* Renders the given Markdown string in a Blessed terminal UI.
*
* @param markdownContent - The Markdown content to display.
*/
export function displayMarkdown(markdownContent: string): void {
// 1) Create Blessed screen
const screen = blessed.screen({
smartCSR: true,
title: 'Markdown Example with Blessed'
});
// 2) Create a scrollable box for the text
const box = blessed.box({
parent: screen,
top: 'center',
left: 'center',
width: '100%',
height: '100%',
keys: true,
vi: true,
mouse: true,
border: 'none',
alwaysScroll: true,
scrollable: true
});
// 3) Parse the markdown into a string using our renderer
const parsedContent = marked(markdownContent);
// 4) Set the box content
box.setContent(parsedContent);
// 5) Focus and render
box.focus();
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

@ -0,0 +1,187 @@
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'
const supported: Record<string, string> = {
".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"
};
export const createOpenAIFile = async (client: OpenAI, filePath: string, purpose: string = 'assistants') => {
return client.files.create({
file: fs.createReadStream(filePath),
purpose: purpose as any
})
}
/*
class EventHandler extends EventEmitter {
constructor(client) {
super();
// this.client = client;
}
async onEvent(event) {
try {
console.log(event);
// Retrieve events that are denoted with 'requires_action'
// since these will have our tool_calls
if (event.event === "thread.run.requires_action") {
await this.handleRequiresAction(
event.data,
event.data.id,
event.data.thread_id,
);
}
} catch (error) {
console.error("Error handling event:", error);
}
}
async handleRequiresAction(data, runId, threadId) {
try {
const toolOutputs =
data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {
if (toolCall.function.name === "getCurrentTemperature") {
return {
tool_call_id: toolCall.id,
output: "57",
};
} else if (toolCall.function.name === "getRainProbability") {
return {
tool_call_id: toolCall.id,
output: "0.06",
};
}
});
// Submit all the tool outputs at the same time
await this.submitToolOutputs(toolOutputs, runId, threadId);
} catch (error) {
console.error("Error processing required action:", error);
}
}
async submitToolOutputs(toolOutputs, runId, threadId) {
try {
// Use the submitToolOutputsStream helper
const stream = this.client.beta.threads.runs.submitToolOutputsStream(
threadId,
runId,
{ tool_outputs: toolOutputs },
);
for await (const event of stream) {
this.emit("event", event);
}
} catch (error) {
console.error("Error submitting tool outputs:", error);
}
}
}
*/
export const runAssistant = async (client: OpenAI, params: any, options: IKBotTask) => {
const sessionId = Date.now().toString()
const sessionMessages = {
sessionId,
prompt: options.prompt,
timestamp: new Date().toISOString(),
messages: []
}
if (options.dry) {
logger.info('Dry run - skipping API call')
return {
result: 'DRY RUN',
sessionMessages,
result_raw: {},
toolCalls: []
}
}
const logMessage = (message: any, sessionId: string, prompt) => {
return {
...message,
timestamp: new Date().toISOString(),
sessionId,
prompt
}
}
let result = null
const prompt_ = await prompt(options)
const assistant = await client.beta.assistants.create({
name: "Documents Assistant",
model: params.model,
tools: [{ type: "file_search" }, ...params.tools],
})
let files = glob(path.resolve(options.path), options.include) || []
files = files.filter((f) => path.extname(f) in supported)
const attachments = await Promise.all(files.map(async (file: string) => {
const file_id = await createOpenAIFile(client, file)
return {
file_id: file_id.id,
tools: [{ type: "file_search" }]
}
}))
const thread = await client.beta.threads.create({
messages: [
{
role: "user",
content: prompt_.content,
attachments: attachments as any,
}
],
})
let defer
try {
defer = new Promise((resolve, reject) => {
const stream = client.beta.threads.runs
.stream(thread.id, {
assistant_id: assistant.id,
})
//.on("textCreated", (args) => logger.trace("assistant >",args))
.on("toolCallCreated", (event) => logger.debug("Assistant : " + event.type))
.on("messageDone", async (event) => {
if (event.content[0].type === "text") {
resolve(event.content[0])
}
})
return stream
})
} catch (e) {
logger.error(`Failed to run assistant: ${e.message}`, error)
}
const ret = await defer
return await onCompletion(ret.text.value, options)
}

View File

@ -0,0 +1,45 @@
import { IKBotTask } from '../types'
import OpenAI from 'openai'
import { marked } from 'marked'
import { markedTerminal } from 'marked-terminal'
import * as path from 'path'
import { sync as write } from '@plastichub/fs/write'
import { resolve } from '@plastichub/osr-commons'
import { logger } from '../'
import { dumpAsScript } from '../utils/script'
import { applyFilters, Filter } from '../filters'
export const onCompletion = async (result: any = "", options: IKBotTask) => {
result = applyFilters(result, options.filters as Filter[] || [])
if (options.dst) {
const dstPath = path.resolve(resolve(options.dst, false, {
...options.variables,
MODEL: path.parse(options.model).name,
ROUTER: options.router,
}))
write(dstPath, result)
logger.debug(`Wrote completion result to ${dstPath}`)
} else {
marked.use(markedTerminal({
emoji: false,
}))
const content: string = marked(result) as string;
process.stdout.write(content)
}
dumpAsScript(options)
return result
}
export const runCompletion = async (client: OpenAI, params: any, options: IKBotTask) =>{
if (options.dry) {
logger.info('Dry run - skipping API call')
return false
}
const completion = await client.chat.completions.create({
model: options.model,
messages: params.messages,
})
const result = completion.choices[0].message.content
onCompletion(result, options)
return result
}

View File

@ -0,0 +1,29 @@
import { globSync } from 'glob'
import * as path from 'path'
import { forward_slash } from '@plastichub/osr-commons'
import { logger } from '../'
import { IKBotTask } from '@plastichub/osr-ai-tools/types'
export const runEach = async (opts: IKBotTask, processRun: (args: IKBotTask) => Promise<any>) {\n const ret = []
if (opts.each) {
const matches = globSync(opts.each, {
cwd: path.resolve(opts.path),
absolute: false
})
if(matches.length === 0) {
logger.warn(`No files matching pattern ${opts.each} found in ${opts.path}`)
return ret
}
logger.info(`Processing ${matches.length} files matching pattern ${opts.each}...`)
for (const file of matches) {
logger.info(`Processing ${file}...`)
const fileOpts = { ...opts }
fileOpts.include = [ forward_slash(file)]
ret.push(await processRun(fileOpts))
}
} else {
ret.push(await processRun(opts))
}
return ret
}

View File

@ -0,0 +1,66 @@
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'
export const runTools = async (client: OpenAI, params: any, options: IKBotTask) => {
const sessionId = Date.now().toString()
const sessionMessages = {
sessionId,
prompt: options.prompt,
timestamp: new Date().toISOString(),
messages: []
}
if (options.dry) {
logger.info('Dry run - skipping API call')
return {
result: 'DRY RUN',
sessionMessages,
result_raw: {},
toolCalls: []
}
}
const logMessage = (message: any, sessionId: string, prompt) => {
return {
...message,
timestamp: new Date().toISOString(),
sessionId,
prompt
}
}
let runner = null
try {
runner = await client.beta.chat.completions.runTools(params as ChatCompletionToolRunnerParams<any>)
.on('message', (message: ChatCompletionMessageParam) => {
options.collector.onMessage(logMessage(message, sessionId, options.prompt))
})
.on('functionCall', (tool: ChatCompletionMessage.FunctionCall) => {
return options.collector.onToolCall(logMessage(tool, sessionId, options.prompt))
})
.on('functionCallResult', (a) => {
options.collector.onFunctionCallResult(a)
})
.on('chatCompletion', options.collector.onChatCompletion)
.on('content', options.collector.onContent)
} catch (e) {
logger.trace(e)
}
let result = content(runner)
try {
result = await runner.finalChatCompletion()
} catch (error) {
if (error.message.includes("(reading 'map')")) {
logger.error('Failed to complete runner: credits :)', error.message, error.message, error)
return
}
logger.error('Failed to complete runner:', error.message, error.issues)
return
}
const ret = content(result)
return await onCompletion(ret, options)
}

View File

@ -0,0 +1,127 @@
import * as path from 'path'
import { sync as dir } from '@plastichub/fs/dir'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as write } from '@plastichub/fs/write'
import { forward_slash, resolve } from '@plastichub/osr-commons'
import { globSync } from 'glob'
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 { ChatCompletionType } from '../zod_schema'
import { runCompletion } from './run-completion'
import { runTools } from './run-tools'
import { runAssistant } from './run-assistant'
import { IKBotTask } from '@plastichub/osr-ai-tools/types'
const processRun = async (opts: IKBotTask) => {
let options: IKBotTask = null
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.variables = await loadProfile(opts)
try {
options = OptionsSchema().parse(opts) as any
} catch (error) {
logger.error('Failed to parse options:', error.message, error.issues)
return
}
const client = createClient(options)
options.variables = { ...options.variables, ...variables(options) }
if (!client) {
logger.error('Failed to create client')
return
}
options.client = client
options.collector = collector(options, client)
// Resolve files and messages
let messages: Array<ChatCompletionMessageParam> = []
let files = await get(path.resolve(options.path), options.include) || []
files = files.map(f => { return { ...f, role: 'user' } })
messages = [...messages as any, ...files]
messages.push(await prompt(opts))
messages.push(await preferences(opts))
const params = {
model: options.model,
messages,
tools: []
} as ChatCompletionToolRunnerParams<any>
if (options.mode === ChatCompletionType.TOOLS || options.mode === ChatCompletionType.ASSISTANT) {
params.tools = await loadTools(options)
params.tool_choice = 'auto'
params.parallel_tool_calls = false
}
const logDir = path.resolve(resolve(opts.logs))
const paramsPath = path.join(logDir, 'params.json')
write(paramsPath, JSON.stringify({ ...params }, null, 2))
logger.debug(`Read ${files.length} files from project ${path.resolve(options.path)} with ${options.include}`, files.map(f => f.path), options.variables, params.tools.map(t => `${t.function.name} : ${t.function.description}`))
let ret = null
try {
switch (options.mode) {
case ChatCompletionType.COMPLETION:
ret = await runCompletion(client, params, options)
break
case ChatCompletionType.TOOLS:
ret = await runTools(client, params, options)
break
case ChatCompletionType.ASSISTANT:
ret = await runAssistant(client, params, options)
break
default:
throw new Error(`Unsupported mode: ${options.mode}`)
}
} catch (e) {
logger.error(`Error running ${options.mode} mode: ${e.message}`)
}
opts.variables['LAST'] = ret
return ret
}
export const run = async (opts: IKBotTask) => {
const ret = []
if (opts.each) {
const matches = globSync(opts.each, {
cwd: path.resolve(opts.path),
absolute: false
})
if (matches.length === 0) {
logger.warn(`No files matching pattern ${opts.each} found in ${opts.path}`)
return ret
}
logger.info(`Processing ${matches.length} files matching pattern ${opts.each}...`)
for (const file of matches) {
const fileOpts = { ...opts }
fileOpts.include = [forward_slash(file)]
ret.push(await processRun(fileOpts))
}
} else {
ret.push(await processRun(opts))
}
return ret
}

View File

@ -0,0 +1,28 @@
import * as fs from 'fs'
import * as path from 'path'
import { CONFIG_DEFAULT, resolve } from '@plastichub/osr-commons'
import { logger } from './index'
import { sync as exists } from '@plastichub/fs/exists'
import { sync as read } from '@plastichub/fs/read'
import { IKBotOptions } from './zod_types'
import { env_vars } from './utils/env'
export const loadConfig = (options: IKBotOptions) => {
if (options.config) {
try {
const configPath = path.resolve(resolve(options.config,false,env_vars()))
if ( exists(configPath) ) {
const parsedConfig = read(configPath,'json')
return parsedConfig
}else{
logger.error(`Config file not found: ${configPath}`)
}
} catch (error:any) {
logger.error(`Failed to parse config JSON: ${error.message}`)
}
}else{
const config = CONFIG_DEFAULT() as any
return config
}
}

View File

@ -0,0 +1,11 @@
export const MODULE_NAME = 'kbot'
export const EXCLUDE_GLOB = [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/coverage/**",
"*.log",
".kbot",
".git"
]
export const MAX_FILE_SIZE = 1024 * 1024 * 2

View File

@ -0,0 +1,136 @@
import { isString } from '@plastichub/core/primitives'
import { logger } from './'
export type Filter = (json: string) => any
export const extractFirstCodeBlock = (markdown: string): string | null => {
const regex = /```(\w+\n)?([\s\S]*?)```/
const match = regex.exec(markdown)
if (match && match[2]) {
return match[2].trim()
}
return markdown
}
export const extractCodeBlocks = (markdown: string): string => {
const codeBlocks: string[] = []
const regex = /```([\s\S]*?)```/g
let match
while ((match = regex.exec(markdown)) !== null) {
codeBlocks.push(match[1])
}
return codeBlocks[0]
}
function isEscapedJsonString(input: string): boolean {
if (typeof input !== 'string' || !input.startsWith('"') || !input.endsWith('"')) {
return false;
}
try {
const ret = JSON.parse(input)
return false
} catch (error) {
return true;
}
}
const unescapeJsonString = (json: string): string => {
if (isEscapedJsonString(json)) {
return json
}
// Use regex to replace common escape sequences
const unescapedString = json
.replace(/\\n/g, '\n')
.replace(/\\"/g, '"')
.replace(/\\\\/g, '\\')
.replace(/(\")/g, "\"")
.replace(/\\b/g, '\b')
.replace(/\\f/g, '\f')
.replace(/\\r/g, '\r')
.replace(/\\t/g, '\t');
// Handle unicode escape sequences (\uXXXX)
return unescapedString.replace(/\\u([\d\w]{4})/gi, (match, grp) => {
return String.fromCharCode(parseInt(grp, 16));
});
}
const alphanumericSort = (arr: string[]) => {
arr = isString(arr) ? JSON.parse(arr) : arr
return JSON.stringify(arr.sort((a, b) => {
const aParts = a.match(/(\d+)|(\D+)/g) || [];
const bParts = b.match(/(\d+)|(\D+)/g) || [];
for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) {
const aPart = aParts[i];
const bPart = bParts[i];
if (isNaN(parseInt(aPart, 10)) || isNaN(parseInt(bPart, 10))) {
// Non-numeric parts, compare as strings
if (aPart !== bPart) {
return aPart < bPart ? -1 : 1;
}
} else {
// Numeric parts, compare as numbers
const aNum = parseInt(aPart, 10);
const bNum = parseInt(bPart, 10);
if (aNum !== bNum) {
return aNum - bNum;
}
}
}
// If everything else is equal, compare by length (shorter first)
return aParts.length - bParts.length;
}), null, 2)
}
export const JSONParse = (json: string) => {
try {
return JSON.parse(json)
} catch (error) {
return null
}
}
export const trim = (str: string) => str ? str.trim() : null
export const extractJsonCodeBlock = (markdown: string): string | null => {
const regex = /```json([\s\S]*?)```/g
const match = regex.exec(markdown)
let ret = match ? match[1] : '{}'
try {
return JSON.stringify(JSON.parse(ret), null, 2)
} catch (error) {
return ret
}
}
const JSONPretty = (json: string) => {
return JSON.stringify(JSON.parse(json), null, 2)
}
export const Filters = {
JSON: extractJsonCodeBlock,
JSONUnescape: unescapeJsonString,
JSONPretty,
AlphaSort: alphanumericSort,
code: extractFirstCodeBlock,
JSONParse,
trim
}
export const applyFilters = (value: string, filters: Filter[]) => {
if (!value) {
return ''
}
(filters as Filter[]).forEach((f) => {
try {
let _ret = f(value)
if (_ret) {
value = _ret
} else {
logger.warn(`applyFilters: filter returned null : ${value}`, f.toString())
}
} catch (error) {
logger.error(`Error applying filter: ${error.message}`)
}
})
return value
}

View File

@ -0,0 +1,34 @@
import path from 'path'
import { Logger } from 'tslog'
import { createLogger } from '@plastichub/osr-log'
import { CONFIG_DEFAULT, get_var } from '@plastichub/osr-commons'
import { MODULE_NAME } from './constants'
export const logger: Logger<unknown> = 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: Record<string, string> = {
".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"
};

Some files were not shown because too many files have changed in this diff Show More