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 CHANGED
@@ -1,12 +1,12 @@
1
- #### HUMAN-DEFINED REQUIREMENTS
1
+ #### USER-DEFINED REQUIREMENTS
2
2
 
3
3
  Define any additional features, integrations, or behavior modifications
4
4
 
5
- #### HUMAN-DEFINED REQUIREMENTS END
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
- #### Important Coding guidelines
36
- Organize new features across multiple files (like Events/utils.js) rather than adding everything to actions.js; export functionality from separate modules and import them in actions.js as needed.
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 before and after they are processed by the LLM.
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
- #### NPM Dependencies for Handlers
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
- **Important**: Files with names starting with "on" (like onRequest.js) are entry points for Node.js builds:
48
+ #### NPM Dependencies for Backend Handlers
50
49
 
51
- 1. Each handler has its own build process
52
- 2. If a file imports node-fetch, then node-fetch must be in that handler's JSON file
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.32",
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(__dirname, '../templates');
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(__dirname, '../templates');
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
  }