openkbs 0.0.28 → 0.0.30

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 ADDED
@@ -0,0 +1,72 @@
1
+ #### HUMAN-DEFINED REQUIREMENTS
2
+
3
+ Define any additional features, integrations, or behavior modifications
4
+
5
+ #### HUMAN-DEFINED REQUIREMENTS END
6
+
7
+
8
+ # OpenKBS Framework Technical Guide (For AI Coding Agents)
9
+
10
+ This guide provides a brief overview of developing backend and frontend logic for your OpenKBS app/agent.
11
+
12
+ ## Project Structure Overview
13
+
14
+ A typical OpenKBS project has the following key directories:
15
+
16
+ * **`src/`**: Contains your custom source code.
17
+ * **`Events/`**: Houses backend event handlers.
18
+ * `actions.js`: Often used for shared logic/tool definitions.
19
+ * `onRequest.js`: Handles incoming user messages before LLM processing.
20
+ * `onRequest.json`: NPM dependencies for `onRequest.js`.
21
+ * `onResponse.js`: Handles LLM responses before sending to the user.
22
+ * `onResponse.json`: NPM dependencies for `onResponse.js`.
23
+ * `onPublicAPIRequest.js`: Handles unauthenticated public API calls.
24
+ * `onPublicAPIRequest.json`: Dependencies for `onPublicAPIRequest.js`.
25
+ * `onAddMessages.js`: Handles messages added via the `chatAddMessages` API.
26
+ * `onAddMessages.json`: Dependencies for `onAddMessages.js`.
27
+ * **`Frontend/`**: Contains frontend customization logic.
28
+ * `contentRender.js`: Custom UI rendering for chat messages, headers, etc.
29
+ * `contentRender.json`: NPM dependencies for `contentRender.js`.
30
+ * **`app/`**: Application-level configuration.
31
+ * `settings.json`: Core application settings (model, vendor, etc.).
32
+ * `instructions.txt`: Instructions for the LLM.
33
+ * `icon.png`: Application icon.
34
+
35
+ ## Backend Dependencies and Secrets Management
36
+
37
+ To use external NPM packages in your backend event handlers, you must declare them in the corresponding `.json` file.
38
+ OpenKBS also provides a secure way to handle sensitive information using the `{{secrets.your_secret_name}}` syntax.
39
+
40
+ **Example: Using axios with an API key**
41
+
42
+ 1. **Declare dependency in `src/Events/onRequest.json` and `src/Events/onResponse.json` **:
43
+ ```json
44
+ {
45
+ "dependencies": {
46
+ "axios": "^1.6.2"
47
+ }
48
+ }
49
+ ```
50
+
51
+ 2. **Implement and use in `src/Events/actions.js`**:
52
+ ```javascript
53
+ import axios from 'axios';
54
+
55
+ export const getActions = (meta) => {
56
+ return [
57
+ [/\/?getNews\("(.*)"\)/, async (match) => {
58
+ const topic = match[1];
59
+ const response = await axios.get('https://newsapi.org/v2/everything', {
60
+ params: {
61
+ q: topic,
62
+ apiKey: '{{secrets.news_api_key}}' // Securely injected at runtime
63
+ }
64
+ });
65
+ return { result: response.data.articles, ...meta };
66
+ }],
67
+ // ... other actions
68
+ ];
69
+ };
70
+ ```
71
+
72
+ Define `news_api_key` in your application's secrets manager on the OpenKBS platform. The platform will inject the actual value at runtime, keeping your credentials secure while enabling you to make API calls with authenticated services.
package/README.md CHANGED
@@ -23,6 +23,7 @@ deploy and integrate AI agents and applications.
23
23
  - [onAddMessages Event Handler](#onaddmessages-event-handler)
24
24
  - [Meta Actions](#meta-actions)
25
25
  - [SDK](#sdk)
26
+ - [Managing Secrets](#managing-secrets)
26
27
  - [Application Settings](#application-settings)
27
28
  - [LLM Instructions](#llm-instructions)
28
29
  - [Execution Environment](#execution-environment)
@@ -631,6 +632,17 @@ const encryptedValue = await openkbs.encrypt(userData);
631
632
 
632
633
  ```
633
634
 
635
+ #### Managing Secrets
636
+ To securely manage sensitive information like API keys or database passwords within your backend event handlers (`onRequest`, `onResponse`, etc.), use the `{{secrets.your_secret_name}}` syntax.
637
+
638
+ Define the placeholder in your code:
639
+
640
+ ```javascript
641
+ const apiKey = '{{secrets.external_api_key}}';
642
+ const dbPassword = '{{secrets.db_password}}';
643
+ ```
644
+ The actual values for `external_api_key` and `db_password` are set securely within the OpenKBS platform's file manager for your application. These values are injected at runtime and are never committed to your code repository, ensuring your secrets remain confidential.
645
+
634
646
  #### Application Settings
635
647
  `app/settings.json`
636
648
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openkbs",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "OpenKBS - Command Line Interface",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/actions.js CHANGED
@@ -3,6 +3,7 @@ const os = require('os');
3
3
  const path = require('path');
4
4
  const express = require('express');
5
5
  const { exec, execSync } = require('child_process');
6
+ const https = require('https');
6
7
 
7
8
  const {
8
9
  fetchLocalKBData, fetchKBJWT, createAccountIdFromPublicKey, signPayload, getUserProfile, getKB,
@@ -359,6 +360,20 @@ async function deleteKBAction(kbId) {
359
360
  }
360
361
 
361
362
  async function modifyAction(prompt, files, options) {
363
+ // Check if MODIFY.md file exists in current directory
364
+ const modifyFilePath = path.join(process.cwd(), 'MODIFY.md');
365
+ const modifyFileExists = await fs.pathExists(modifyFilePath);
366
+
367
+ // If MODIFY.md doesn't exist, download it first
368
+ if (!modifyFileExists) {
369
+ console.yellow('MODIFY.md file not found. Downloading it first...');
370
+ try {
371
+ await downloadModifyAction();
372
+ } catch (error) {
373
+ console.yellow('Could not download MODIFY.md, continuing without it...');
374
+ }
375
+ }
376
+
362
377
  const { kbId } = await fetchLocalKBData();
363
378
  const {kbToken} = await fetchKBJWT(kbId);
364
379
  const kbData = await getKB(kbToken);
@@ -455,6 +470,43 @@ function installFrontendPackageAction(packageName) {
455
470
  }
456
471
  }
457
472
 
473
+ async function downloadModifyAction() {
474
+ const url = 'https://raw.githubusercontent.com/open-kbs/openkbs/refs/heads/main/MODIFY.md';
475
+ const filePath = path.join(process.cwd(), 'MODIFY.md');
476
+
477
+ console.log(`Downloading MODIFY.md template from GitHub...`);
478
+
479
+ return new Promise((resolve, reject) => {
480
+ https.get(url, (response) => {
481
+ if (response.statusCode === 200) {
482
+ const file = fs.createWriteStream(filePath);
483
+ response.pipe(file);
484
+
485
+ file.on('finish', () => {
486
+ file.close();
487
+ console.green(`Successfully downloaded MODIFY.md to ${filePath}`);
488
+ resolve();
489
+ });
490
+
491
+ file.on('error', (err) => {
492
+ fs.unlink(filePath, () => {}); // Delete the file if there was an error
493
+ console.red(`Error writing to file: ${err.message}`);
494
+ reject(err);
495
+ });
496
+ } else if (response.statusCode === 404) {
497
+ console.red(`File not found at ${url}`);
498
+ reject(new Error('File not found'));
499
+ } else {
500
+ console.red(`Failed to download file. Status code: ${response.statusCode}`);
501
+ reject(new Error(`HTTP Status Code: ${response.statusCode}`));
502
+ }
503
+ }).on('error', (err) => {
504
+ console.red(`Error downloading file: ${err.message}`);
505
+ reject(err);
506
+ });
507
+ });
508
+ }
509
+
458
510
  module.exports = {
459
511
  signAction,
460
512
  loginAction,
@@ -470,5 +522,6 @@ module.exports = {
470
522
  initByTemplateAction,
471
523
  logoutAction,
472
524
  installFrontendPackageAction,
473
- modifyAction
525
+ modifyAction,
526
+ downloadModifyAction
474
527
  };
package/src/index.js CHANGED
@@ -12,7 +12,7 @@ const {
12
12
  deleteKBAction,
13
13
  deleteFileAction,
14
14
  describeAction, deployAction, createByTemplateAction, initByTemplateAction,
15
- logoutAction, installFrontendPackageAction, modifyAction
15
+ logoutAction, installFrontendPackageAction, modifyAction, downloadModifyAction
16
16
  } = require('./actions');
17
17
 
18
18
 
@@ -141,4 +141,16 @@ program
141
141
  .description('Log out from OpenKBS by deleting the locally stored session token.')
142
142
  .action(logoutAction);
143
143
 
144
+ program
145
+ .command('init-modify')
146
+ .description('Download the latest MODIFY.md template from GitHub to help with KB modifications')
147
+ .action(downloadModifyAction)
148
+ .addHelpText('after', `
149
+ Examples:
150
+ $ openkbs init-modify
151
+
152
+ This will download the MODIFY.md template file from the OpenKBS GitHub repository to your current directory.
153
+ This file will be automatically included when you run the 'openkbs modify' command.
154
+ `);
155
+
144
156
  program.parse(process.argv);
package/src/utils.js CHANGED
@@ -311,6 +311,18 @@ async function modifyKB(kbToken, kbData, prompt, files, options) {
311
311
  const { kbId, key } = kbData;
312
312
  const url = options?.chatURL || CHAT_API_URL;
313
313
 
314
+ // Try to find and add MODIFY.md file
315
+ const modifyFilePath = path.join(process.cwd(), 'MODIFY.md');
316
+ let hasModifyFile = false;
317
+
318
+ try {
319
+ if (await fs.pathExists(modifyFilePath)) {
320
+ hasModifyFile = true;
321
+ }
322
+ } catch (error) {
323
+ console.error('Error checking for MODIFY.md:', error);
324
+ }
325
+
314
326
  if (!files || files.length === 0) {
315
327
  try {
316
328
  const srcFiles = await getAllFiles('./src');
@@ -320,6 +332,11 @@ async function modifyKB(kbToken, kbData, prompt, files, options) {
320
332
  console.error('Error getting files from directories:', error);
321
333
  }
322
334
  }
335
+
336
+ // Add MODIFY.md to files list if it exists
337
+ if (hasModifyFile && !files.includes(modifyFilePath)) {
338
+ files.push(modifyFilePath);
339
+ }
323
340
 
324
341
  const fileContents = await Promise.all(files.map(async (filePath) => {
325
342
  try {