openkbs 0.0.32 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MODIFY.md +45 -20
- package/README.md +4 -0
- package/package.json +2 -1
- package/scripts/deploy-templates.js +43 -0
- package/src/actions.js +5 -2
- package/src/utils.js +64 -2
package/MODIFY.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
####
|
|
1
|
+
#### USER-DEFINED REQUIREMENTS
|
|
2
2
|
|
|
3
3
|
Define any additional features, integrations, or behavior modifications
|
|
4
4
|
|
|
5
|
-
####
|
|
6
|
-
|
|
5
|
+
#### USER-DEFINED REQUIREMENTS END
|
|
7
6
|
|
|
8
7
|
# OpenKBS Framework Technical Guide (For AI Coding Agents)
|
|
9
8
|
|
|
9
|
+
OpenKBS is claud AI platform designed to build, deploy and integrate AI agents and applications.
|
|
10
10
|
This guide provides a brief overview of developing backend and frontend logic for your OpenKBS app/agent.
|
|
11
11
|
|
|
12
12
|
## Project Structure Overview
|
|
@@ -14,8 +14,8 @@ This guide provides a brief overview of developing backend and frontend logic fo
|
|
|
14
14
|
A typical OpenKBS project has the following key directories:
|
|
15
15
|
|
|
16
16
|
* **`src/`**: Contains your custom source code.
|
|
17
|
-
* **`Events/`**: Houses backend event handlers.
|
|
18
|
-
* `actions.js`: Example file commonly used for shared logic/tools definitions.
|
|
17
|
+
* **`Events/`**: Houses backend LLM event handlers.
|
|
18
|
+
* `actions.js`: Example file commonly used for shared backend logic/tools definitions.
|
|
19
19
|
* `onRequest.js`: Handles incoming user messages before LLM processing.
|
|
20
20
|
* `onRequest.json`: NPM dependencies for `onRequest.js`.
|
|
21
21
|
* `onResponse.js`: Handles LLM responses before sending to the user.
|
|
@@ -32,25 +32,23 @@ A typical OpenKBS project has the following key directories:
|
|
|
32
32
|
* `instructions.txt`: Instructions for the LLM.
|
|
33
33
|
* `icon.png`: Application icon.
|
|
34
34
|
|
|
35
|
-
####
|
|
36
|
-
|
|
35
|
+
#### Backend Handlers
|
|
36
|
+
- Files with names starting with "on" (like onRequest.js) are called handler
|
|
37
|
+
- Each handler functions as NodeJS execution entry point executed by the platform upon certain events.
|
|
38
|
+
- use ES6, user import, do not use require()
|
|
37
39
|
|
|
38
40
|
#### onRequest and onResponse Handlers
|
|
39
41
|
|
|
40
|
-
The core of the OpenKBS backend framework revolves around the `onRequest` and `onResponse` event handlers.
|
|
41
|
-
These handlers act as middleware, intercepting messages
|
|
42
|
-
|
|
43
|
-
* **`onRequest` Handler:** This handler is invoked every time a user sends a message to the chat. It provides an opportunity to pre-process the user's input, extract commands and perform actions based on the user's message. The `onRequest.js` file must export a function that receives `request` and `metadata` parameters and returns a modified request object.
|
|
44
|
-
|
|
45
|
-
* **`onResponse` Handler:** This handler is invoked after the LLM generates a response. It allows post-processing of the LLM's output, execution of commands based on the LLM's intentions. The `onResponse.js` file must export a function that receives `response` and `metadata` parameters and returns a modified response object.
|
|
42
|
+
The core of the OpenKBS backend framework revolves around the `onRequest` and `onResponse` Node.js backend event handlers.
|
|
43
|
+
These handlers act as middleware, intercepting user messages and messages generated by the LLM.
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
- onRequest handler is invoked every time a user sends a message to the chat. It provides an opportunity to process the user's input, extract commands and perform actions based on the user's message.
|
|
46
|
+
- onResponse handler is invoked after the LLM generates a response. It allows processing of the LLM's output, execution of commands based on the LLM's message.
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
#### NPM Dependencies for Backend Handlers
|
|
50
49
|
|
|
51
|
-
1.
|
|
52
|
-
2. If
|
|
53
|
-
3. Example: If utils.js uses node-fetch and is imported by onRequest.js, then node-fetch must be in onRequest.json
|
|
50
|
+
1. If a file imports an NPM dependency and is then imported by a handler, this dependency must be defined in the handler's corresponding json file
|
|
51
|
+
2. Example: If actions.js imports got and onRequest.js imports actions.js, then got must be in onRequest.json
|
|
54
52
|
|
|
55
53
|
|
|
56
54
|
## Backend Dependencies
|
|
@@ -59,7 +57,7 @@ To use external NPM packages in your backend event handlers, you must declare th
|
|
|
59
57
|
|
|
60
58
|
**Example: Using https module with an API key**
|
|
61
59
|
|
|
62
|
-
1. **Declare dependencies** in both `src/Events/onRequest.json` and `src/Events/onResponse.json` (as each handler have separate build):
|
|
60
|
+
1. **Declare dependencies** in both `src/Events/onRequest.json` and `src/Events/onResponse.json` (as each handler have separate Node.js build):
|
|
63
61
|
```json
|
|
64
62
|
{
|
|
65
63
|
"dependencies": {
|
|
@@ -71,6 +69,7 @@ To use external NPM packages in your backend event handlers, you must declare th
|
|
|
71
69
|
2. **Implement in any JavaScript file** (actions.js is just an example name):
|
|
72
70
|
|
|
73
71
|
```javascript
|
|
72
|
+
import got from 'got';
|
|
74
73
|
export const getActions = (meta) => {
|
|
75
74
|
return [
|
|
76
75
|
[/\/?getNews\("(.*)"\)/, async (match) => {
|
|
@@ -83,7 +82,7 @@ export const getActions = (meta) => {
|
|
|
83
82
|
];
|
|
84
83
|
};
|
|
85
84
|
```
|
|
86
|
-
|
|
85
|
+
|
|
87
86
|
## Secrets Management
|
|
88
87
|
OpenKBS provides a secure way to handle sensitive information using the `{{secrets.your_secret_name}}` syntax.
|
|
89
88
|
Never hardcode secrets in the code, if any secrets are provided by the user replace them with placeholders syntax above.
|
|
@@ -104,4 +103,30 @@ You can execute the following commands:
|
|
|
104
103
|
Description: """
|
|
105
104
|
Get the latest news
|
|
106
105
|
"""
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Important Coding guidelines
|
|
109
|
+
- Organize new features across multiple files (like Events/utils.js) rather than adding everything to actions.js
|
|
110
|
+
- Similar for Frontend: keep newly implemented React components outside contentRender.js for maintainability.
|
|
111
|
+
- Keep in mind onRenderChatMessage is not a React component but simple JS function
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
#### onRenderChatMessage injected functions
|
|
115
|
+
These functions are automatically injected by the framework to onRenderChatMessage, providing access to system features
|
|
116
|
+
```
|
|
117
|
+
// Where functions are injected
|
|
118
|
+
const onRenderChatMessage = async (params) => {
|
|
119
|
+
const { APIResponseComponent, theme, setBlockingLoading, setSystemAlert, RequestChatAPI,
|
|
120
|
+
kbUserData, generateMsgId, messages, msgIndex } = params;
|
|
121
|
+
...
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
// Shows toast notifications in top-right corner
|
|
127
|
+
setSystemAlert({
|
|
128
|
+
msg: 'Payment successful',
|
|
129
|
+
type: 'success', //'error'|'success'|'info'
|
|
130
|
+
duration: 5000
|
|
131
|
+
});
|
|
107
132
|
```
|
package/README.md
CHANGED
|
@@ -597,6 +597,8 @@ The `openkbs` object provides a set of utility functions and services to interac
|
|
|
597
597
|
|
|
598
598
|
* **`openkbs.googleSearch(q, params)`:** Performs a Google search using the provided query and parameters.
|
|
599
599
|
|
|
600
|
+
* **`openkbs.sendMail(email, subject, content)`:** Sends an email to the specified recipient
|
|
601
|
+
|
|
600
602
|
* **`openkbs.documentToText(documentURL, params)`:** Extracts text from various document formats.
|
|
601
603
|
|
|
602
604
|
* **`openkbs.imageToText(imageUrl, params)`:** Extracts text from an image.
|
|
@@ -619,6 +621,8 @@ The `openkbs` object provides a set of utility functions and services to interac
|
|
|
619
621
|
|
|
620
622
|
* **`openkbs.clientHeaders`:** Exposes client headers for accessing information like IP address, location, etc. (e.g., `openkbs.clientHeaders['x-forwarded-for']`).
|
|
621
623
|
|
|
624
|
+
* **`openkbs.createEmbeddings(input, model)`:** Create embeddings from input text
|
|
625
|
+
|
|
622
626
|
**Example SDK Usage:**
|
|
623
627
|
|
|
624
628
|
```javascript
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openkbs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.34",
|
|
4
4
|
"description": "OpenKBS - Command Line Interface",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"deploy:linux": "aws s3 cp build/openkbs-linux-x64 s3://openkbs-downloads/cli/linux/openkbs && aws s3 cp build/openkbs-linux-arm64 s3://openkbs-downloads/cli/linux/openkbs-arm64",
|
|
10
10
|
"deploy:macos": "aws s3 cp build/openkbs-macos-arm64 s3://openkbs-downloads/cli/macos/openkbs && aws s3 cp build/openkbs-macos-x64 s3://openkbs-downloads/cli/macos/openkbs-x64",
|
|
11
11
|
"deploy:win": "aws s3 cp build/openkbs-win-x64.exe s3://openkbs-downloads/cli/windows/openkbs.exe && aws s3 cp build/openkbs-win-arm64.exe s3://openkbs-downloads/cli/windows/openkbs-arm64.exe",
|
|
12
|
+
"deploy:templates": "node scripts/deploy-templates.js",
|
|
12
13
|
"postinstall": "node src/install.js"
|
|
13
14
|
},
|
|
14
15
|
"bin": {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
|
|
6
|
+
|
|
7
|
+
const s3Client = new S3Client({ region: 'us-east-1' });
|
|
8
|
+
const BUCKET = 'openkbs-downloads';
|
|
9
|
+
const TEMPLATES_DIR = path.join(__dirname, '../templates');
|
|
10
|
+
|
|
11
|
+
async function uploadDirectory(localPath, s3Prefix) {
|
|
12
|
+
const items = await fs.readdir(localPath, { withFileTypes: true });
|
|
13
|
+
|
|
14
|
+
for (const item of items) {
|
|
15
|
+
const itemPath = path.join(localPath, item.name);
|
|
16
|
+
const s3Key = `${s3Prefix}/${item.name}`;
|
|
17
|
+
|
|
18
|
+
if (item.isDirectory()) {
|
|
19
|
+
await uploadDirectory(itemPath, s3Key);
|
|
20
|
+
} else {
|
|
21
|
+
const fileContent = await fs.readFile(itemPath);
|
|
22
|
+
await s3Client.send(new PutObjectCommand({
|
|
23
|
+
Bucket: BUCKET,
|
|
24
|
+
Key: s3Key,
|
|
25
|
+
Body: fileContent
|
|
26
|
+
}));
|
|
27
|
+
console.log(`Uploaded: ${s3Key}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function deployTemplates() {
|
|
33
|
+
try {
|
|
34
|
+
console.log('Deploying templates to S3...');
|
|
35
|
+
await uploadDirectory(TEMPLATES_DIR, 'templates');
|
|
36
|
+
console.log('Templates deployed successfully!');
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Error deploying templates:', error);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
deployTemplates();
|
package/src/actions.js
CHANGED
|
@@ -10,10 +10,10 @@ const {
|
|
|
10
10
|
fetchAndSaveSettings, downloadFiles, downloadIcon, updateKB, uploadFiles, generateKey, generateMnemonic,
|
|
11
11
|
reset, bold, red, yellow, green, createKB, saveLocalKBData, listKBs, deleteKBFile,
|
|
12
12
|
deleteKB, buildPackage, replacePlaceholderInFiles, buildNodePackage, initByTemplateAction, modifyKB,
|
|
13
|
-
listKBsSharedWithMe
|
|
13
|
+
listKBsSharedWithMe, downloadTemplates
|
|
14
14
|
} = require("./utils");
|
|
15
15
|
|
|
16
|
-
const TEMPLATE_DIR = path.join(
|
|
16
|
+
const TEMPLATE_DIR = path.join(os.homedir(), '.openkbs', 'templates');
|
|
17
17
|
const jwtPath = path.join(os.homedir(), '.openkbs', 'clientJWT');
|
|
18
18
|
const generateTransactionId = () => `${+new Date()}-${Math.floor(100000 + Math.random() * 900000)}`;
|
|
19
19
|
|
|
@@ -298,6 +298,9 @@ async function cloneAction(kbId) {
|
|
|
298
298
|
|
|
299
299
|
async function createByTemplateAction(name) {
|
|
300
300
|
try {
|
|
301
|
+
// Download templates from S3 first
|
|
302
|
+
await downloadTemplates();
|
|
303
|
+
|
|
301
304
|
const targetDir = path.join(process.cwd(), name);
|
|
302
305
|
|
|
303
306
|
if (fs.existsSync(targetDir)) {
|
package/src/utils.js
CHANGED
|
@@ -10,7 +10,7 @@ const { exec } = require('child_process');
|
|
|
10
10
|
const readline = require('readline');
|
|
11
11
|
const Spinner = require('cli-spinner').Spinner;
|
|
12
12
|
|
|
13
|
-
const TEMPLATE_DIR = path.join(
|
|
13
|
+
const TEMPLATE_DIR = path.join(os.homedir(), '.openkbs', 'templates');
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Encrypts the given text using AES encryption with a passphrase.
|
|
@@ -1021,6 +1021,64 @@ async function buildLocalFilesMap(localDir, namespaces) {
|
|
|
1021
1021
|
return filesMap;
|
|
1022
1022
|
}
|
|
1023
1023
|
|
|
1024
|
+
async function downloadTemplates() {
|
|
1025
|
+
try {
|
|
1026
|
+
const templatesDir = TEMPLATE_DIR;
|
|
1027
|
+
await fs.ensureDir(templatesDir);
|
|
1028
|
+
|
|
1029
|
+
// Clear existing templates
|
|
1030
|
+
await fs.emptyDir(templatesDir);
|
|
1031
|
+
|
|
1032
|
+
// Download templates from S3
|
|
1033
|
+
await downloadTemplatesFromS3(templatesDir);
|
|
1034
|
+
|
|
1035
|
+
} catch (error) {
|
|
1036
|
+
console.error('Error downloading templates:', error);
|
|
1037
|
+
throw error;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
async function downloadTemplatesFromS3(targetDir) {
|
|
1042
|
+
const s3Client = new S3Client({ region: 'us-east-1' });
|
|
1043
|
+
const { ListObjectsV2Command, GetObjectCommand } = require('@aws-sdk/client-s3');
|
|
1044
|
+
|
|
1045
|
+
const bucket = 'openkbs-downloads';
|
|
1046
|
+
const prefix = 'templates/';
|
|
1047
|
+
|
|
1048
|
+
// List all objects in templates folder
|
|
1049
|
+
const listResponse = await s3Client.send(new ListObjectsV2Command({
|
|
1050
|
+
Bucket: bucket,
|
|
1051
|
+
Prefix: prefix
|
|
1052
|
+
}));
|
|
1053
|
+
|
|
1054
|
+
// Download all files in parallel
|
|
1055
|
+
const downloadPromises = (listResponse.Contents || []).map(async (obj) => {
|
|
1056
|
+
const key = obj.Key;
|
|
1057
|
+
const relativePath = key.substring(prefix.length);
|
|
1058
|
+
|
|
1059
|
+
// Skip if it's a directory marker
|
|
1060
|
+
if (relativePath.endsWith('/')) return;
|
|
1061
|
+
|
|
1062
|
+
const localPath = path.join(targetDir, relativePath);
|
|
1063
|
+
|
|
1064
|
+
// Ensure directory exists
|
|
1065
|
+
await fs.ensureDir(path.dirname(localPath));
|
|
1066
|
+
|
|
1067
|
+
// Download file
|
|
1068
|
+
const response = await s3Client.send(new GetObjectCommand({
|
|
1069
|
+
Bucket: bucket,
|
|
1070
|
+
Key: key
|
|
1071
|
+
}));
|
|
1072
|
+
|
|
1073
|
+
const fileContent = await streamToBuffer(response.Body);
|
|
1074
|
+
await fs.writeFile(localPath, fileContent);
|
|
1075
|
+
console.log(relativePath);
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
// Wait for all downloads to complete
|
|
1079
|
+
await Promise.all(downloadPromises);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1024
1082
|
const generateKey = (passphrase) => {
|
|
1025
1083
|
const salt = 'salt';
|
|
1026
1084
|
const iterations = 1000;
|
|
@@ -1054,6 +1112,9 @@ const replacePlaceholderInFiles = (dir, name) => {
|
|
|
1054
1112
|
|
|
1055
1113
|
async function initByTemplateAction(params) {
|
|
1056
1114
|
try {
|
|
1115
|
+
// Download templates from S3 first
|
|
1116
|
+
await downloadTemplates();
|
|
1117
|
+
|
|
1057
1118
|
const targetDir = process.cwd();
|
|
1058
1119
|
|
|
1059
1120
|
// Copy all files and folders, skipping existing ones
|
|
@@ -1077,5 +1138,6 @@ module.exports = {
|
|
|
1077
1138
|
KB_API_URL, AUTH_API_URL, decryptKBFields, fetchLocalKBData, fetchKBJWT, createAccountIdFromPublicKey, signPayload,
|
|
1078
1139
|
listFiles, getUserProfile, getKB, fetchAndSaveSettings, downloadIcon, downloadFiles, updateKB, uploadFiles, generateKey,
|
|
1079
1140
|
generateMnemonic, reset, bold, red, yellow, green, cyan, createKB, getClientJWT, saveLocalKBData, listKBs, deleteKBFile,
|
|
1080
|
-
deleteKB, buildPackage, replacePlaceholderInFiles, buildNodePackage, initByTemplateAction, modifyKB, listKBsSharedWithMe
|
|
1141
|
+
deleteKB, buildPackage, replacePlaceholderInFiles, buildNodePackage, initByTemplateAction, modifyKB, listKBsSharedWithMe,
|
|
1142
|
+
downloadTemplates
|
|
1081
1143
|
}
|