openkbs 0.0.34 → 0.0.35

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.
Files changed (26) hide show
  1. package/package.json +1 -1
  2. package/src/actions.js +115 -1
  3. package/src/index.js +22 -1
  4. package/src/utils.js +9 -1
  5. package/templates/.openkbs/knowledge/README.md +34 -0
  6. package/templates/.openkbs/knowledge/examples/ai-copywriter/app/icon.png +0 -0
  7. package/templates/.openkbs/knowledge/examples/ai-copywriter/app/instructions.txt +61 -0
  8. package/templates/.openkbs/knowledge/examples/ai-copywriter/app/settings.json +13 -0
  9. package/templates/.openkbs/knowledge/examples/ai-copywriter/run_agent.js +120 -0
  10. package/templates/.openkbs/knowledge/examples/ai-copywriter/src/Events/actions.js +152 -0
  11. package/templates/.openkbs/knowledge/examples/ai-copywriter/src/Events/onResponse.js +59 -0
  12. package/templates/.openkbs/knowledge/examples/ai-copywriter/src/Events/onResponse.json +4 -0
  13. package/templates/.openkbs/knowledge/examples/ai-copywriter/src/Frontend/contentRender.js +26 -0
  14. package/templates/.openkbs/knowledge/examples/ai-copywriter/src/Frontend/contentRender.json +10 -0
  15. package/templates/.openkbs/knowledge/metadata.json +3 -0
  16. package/templates/CLAUDE.md +15 -0
  17. package/ON_PREMISES.md +0 -215
  18. package/examples/cloud-master/actions.js +0 -34
  19. package/examples/cloud-master/ai1.png +0 -0
  20. package/examples/cloud-master/ai2.png +0 -0
  21. package/examples/cloud-master/ai3.png +0 -0
  22. package/examples/cloud-master/backup.png +0 -0
  23. package/examples/cloud-master/contentRender.js +0 -255
  24. package/examples/cloud-master/instructions.txt +0 -77
  25. package/examples/cloud-master/llama-loaded.png +0 -0
  26. package/examples/cloud-master/sd3-loaded.png +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openkbs",
3
- "version": "0.0.34",
3
+ "version": "0.0.35",
4
4
  "description": "OpenKBS - Command Line Interface",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/actions.js CHANGED
@@ -538,6 +538,119 @@ async function downloadModifyAction() {
538
538
  });
539
539
  }
540
540
 
541
+ async function updateKnowledgeAction() {
542
+ try {
543
+ const knowledgeDir = path.join(process.cwd(), '.openkbs', 'knowledge');
544
+ const metadataPath = path.join(knowledgeDir, 'metadata.json');
545
+
546
+ // Check if .openkbs/knowledge directory exists
547
+ if (!fs.existsSync(knowledgeDir)) {
548
+ console.red('Knowledge directory not found. Please ensure you are in an OpenKBS project directory.');
549
+ return;
550
+ }
551
+
552
+ // Get local metadata version
553
+ let localVersion = null;
554
+ if (fs.existsSync(metadataPath)) {
555
+ try {
556
+ const localMetadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
557
+ localVersion = localMetadata.version;
558
+ } catch (error) {
559
+ console.red('Error reading local metadata.json:', error.message);
560
+ return;
561
+ }
562
+ }
563
+
564
+ // Check remote version from S3
565
+ const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
566
+ const s3Client = new S3Client({ region: 'us-east-1' });
567
+ const bucket = 'openkbs-downloads';
568
+ const remoteMetadataKey = 'templates/.openkbs/knowledge/metadata.json';
569
+
570
+ let remoteVersion = null;
571
+ try {
572
+ const response = await s3Client.send(new GetObjectCommand({
573
+ Bucket: bucket,
574
+ Key: remoteMetadataKey
575
+ }));
576
+
577
+ const remoteMetadataContent = await response.Body.transformToString();
578
+ const remoteMetadata = JSON.parse(remoteMetadataContent);
579
+ remoteVersion = remoteMetadata.version;
580
+ } catch (error) {
581
+ console.red('Error fetching remote metadata:', error.message);
582
+ return;
583
+ }
584
+
585
+ // Compare versions
586
+ if (localVersion === remoteVersion) {
587
+ console.green('Knowledge base is already up to date.');
588
+ return;
589
+ }
590
+
591
+ console.log(`Updating knowledge base from version ${localVersion || 'unknown'} to ${remoteVersion}...`);
592
+
593
+ // Download updated knowledge files from S3
594
+ await downloadKnowledgeFromS3(knowledgeDir);
595
+
596
+ console.green('Knowledge base updated successfully!');
597
+
598
+ } catch (error) {
599
+ console.red('Error updating knowledge base:', error.message);
600
+ }
601
+ }
602
+
603
+ async function downloadKnowledgeFromS3(targetDir) {
604
+ const { S3Client, ListObjectsV2Command, GetObjectCommand } = require("@aws-sdk/client-s3");
605
+ const s3Client = new S3Client({ region: 'us-east-1' });
606
+ const bucket = 'openkbs-downloads';
607
+ const prefix = 'templates/.openkbs/knowledge/';
608
+
609
+ try {
610
+ // List all objects in knowledge folder
611
+ const listResponse = await s3Client.send(new ListObjectsV2Command({
612
+ Bucket: bucket,
613
+ Prefix: prefix
614
+ }));
615
+
616
+ if (!listResponse.Contents || listResponse.Contents.length === 0) {
617
+ console.yellow('No knowledge files found in remote repository.');
618
+ return;
619
+ }
620
+
621
+ // Download all files in parallel
622
+ const downloadPromises = listResponse.Contents.map(async (obj) => {
623
+ const key = obj.Key;
624
+ const relativePath = key.substring(prefix.length);
625
+
626
+ // Skip if it's a directory marker
627
+ if (relativePath.endsWith('/') || relativePath === '') return;
628
+
629
+ const localPath = path.join(targetDir, relativePath);
630
+
631
+ // Ensure directory exists
632
+ await fs.ensureDir(path.dirname(localPath));
633
+
634
+ // Download file
635
+ const response = await s3Client.send(new GetObjectCommand({
636
+ Bucket: bucket,
637
+ Key: key
638
+ }));
639
+
640
+ const fileContent = await response.Body.transformToByteArray();
641
+ await fs.writeFile(localPath, fileContent);
642
+
643
+ console.log(`Downloaded: ${relativePath}`);
644
+ });
645
+
646
+ await Promise.all(downloadPromises);
647
+
648
+ } catch (error) {
649
+ console.red('Error downloading knowledge files from S3:', error.message);
650
+ throw error;
651
+ }
652
+ }
653
+
541
654
  module.exports = {
542
655
  signAction,
543
656
  loginAction,
@@ -554,5 +667,6 @@ module.exports = {
554
667
  logoutAction,
555
668
  installFrontendPackageAction,
556
669
  modifyAction,
557
- downloadModifyAction
670
+ downloadModifyAction,
671
+ updateKnowledgeAction
558
672
  };
package/src/index.js CHANGED
@@ -12,7 +12,8 @@ const {
12
12
  deleteKBAction,
13
13
  deleteFileAction,
14
14
  describeAction, deployAction, createByTemplateAction, initByTemplateAction,
15
- logoutAction, installFrontendPackageAction, modifyAction, downloadModifyAction
15
+ logoutAction, installFrontendPackageAction, modifyAction, downloadModifyAction,
16
+ updateKnowledgeAction
16
17
  } = require('./actions');
17
18
 
18
19
 
@@ -153,4 +154,24 @@ This will download the MODIFY.md template file from the OpenKBS GitHub repositor
153
154
  This file will be automatically included when you run the 'openkbs modify' command.
154
155
  `);
155
156
 
157
+ program
158
+ .command('update')
159
+ .argument('<target>', 'The target to update (currently supports: knowledge)')
160
+ .description('Update project components from remote repository')
161
+ .action((target) => {
162
+ if (target === 'knowledge') {
163
+ updateKnowledgeAction();
164
+ } else {
165
+ console.error(`Unknown update target: ${target}. Currently supported: knowledge`);
166
+ process.exit(1);
167
+ }
168
+ })
169
+ .addHelpText('after', `
170
+ Examples:
171
+ $ openkbs update knowledge
172
+
173
+ This will check if your local .openkbs/knowledge directory is up to date with the remote repository
174
+ and update it if necessary.
175
+ `);
176
+
156
177
  program.parse(process.argv);
package/src/utils.js CHANGED
@@ -970,8 +970,14 @@ async function uploadFiles(namespaces, kbId, kbToken, location = 'origin', targe
970
970
  const localDir = dist ? path.join(process.cwd(), 'cache') : path.join(process.cwd(), 'src');
971
971
  const filesMap = await buildLocalFilesMap(localDir, namespaces);
972
972
  let filesToUpload = [];
973
+ const isInOpenKBSFolder = (fileName) => fileName.startsWith('.openkbs/') || fileName.includes('/.openkbs/');
973
974
 
974
975
  if (targetFile) {
976
+ // Skip if target file is in .openkbs folder
977
+ if (isInOpenKBSFolder(targetFile)) {
978
+ console.log(`Skipping file in .openkbs folder: ${targetFile}`);
979
+ return false;
980
+ }
975
981
  const isDistFile = targetFile.startsWith('Events/dist') || targetFile.startsWith('Frontend/dist');
976
982
  if (filesMap[targetFile] && ((dist && isDistFile) || (!dist && !isDistFile))) {
977
983
  filesToUpload.push({ ...filesMap[targetFile], fileName: targetFile });
@@ -979,8 +985,10 @@ async function uploadFiles(namespaces, kbId, kbToken, location = 'origin', targe
979
985
  return false; // File not found locally or not in the correct folder
980
986
  }
981
987
  } else {
982
- // No target file, upload all files based on the dist parameter
988
+ // No target file, upload all files based on the dist parameter, excluding .openkbs files
983
989
  filesToUpload = Object.keys(filesMap).filter(fileName => {
990
+ // Skip files in .openkbs folder
991
+ if (isInOpenKBSFolder(fileName)) return false;
984
992
  const isDistFile = fileName.startsWith('Events/dist') || fileName.startsWith('Frontend/dist');
985
993
  return dist ? isDistFile : !isDistFile;
986
994
  }).map(fileName => {
@@ -0,0 +1,34 @@
1
+ # OpenKBS Development Guidelines
2
+
3
+ ## Development Flow
4
+
5
+ 1. **Read existing code first:**
6
+ - `./app/` folder (settings, instructions, etc.)
7
+ - `./src/` folder (all Events and Frontend files)
8
+
9
+ 2. **Assess implementation requirements:**
10
+ - **Minor changes only**: Simple modifications to existing code that don't require framework knowledge
11
+ - **Framework implementation needed**: New features, new event handlers, new frontend components, or placeholder app development
12
+
13
+ 3. **For framework implementation:**
14
+ - Read all source code in `.openkbs/knowledge/examples/`
15
+ - Study complete working applications to understand OpenKBS patterns
16
+ - Never guess framework methods or variables - always reference examples
17
+
18
+ ## When Examples Are Required
19
+
20
+ - New OpenKBS application development (placeholder app)
21
+ - Adding new event handlers (onRequest, onResponse, etc.)
22
+ - Creating new frontend components
23
+ - Implementing OpenKBS-specific functionality
24
+ - Any framework-related implementation
25
+
26
+ ## When Examples May Not Be Needed
27
+
28
+ - Simple text changes to existing files
29
+ - Minor bug fixes in existing code
30
+ - Configuration adjustments that don't involve framework methods
31
+
32
+ ## Critical Rule
33
+
34
+ **When in doubt, read the examples.** They contain all necessary framework knowledge for proper OpenKBS implementation.
@@ -0,0 +1,61 @@
1
+ You are an autonomous agent for crafting intelligent, creative, and consistent content:
2
+
3
+ Job:
4
+ - Find and open at least one site that have correct, reliable and detailed information about the product
5
+ - paraphrase and enrich it and generate a SEO friendly product description
6
+ - Always search the official website of the manufacturer (Brand) and find information about the product from there.
7
+ - If you see additional instructions in PROCESS_PRODUCT, execute them.
8
+ - When you have obtained all the necessary information, output JOB_COMPLETED response.
9
+
10
+ Guidelines:
11
+ - use webpageToText command to read websites content in details
12
+ - Always output one command per response and wait for the response before continuing
13
+ - If an API call fails, so that you can't extract a required data, retry with different website or search query
14
+ - When searching for product information, use the format: Product Name + Product Code.
15
+ - Once all necessary information is obtained, deliver the final result using the following JSON format
16
+
17
+ Output Format Success:
18
+ {
19
+ "type": "JOB_COMPLETED",
20
+ "productID": "[productID]",
21
+ "productDescription": "[short plain text description]",
22
+ "metaDescription": "...",
23
+ "images": [{"url": "...", "title": "..."}, ...],
24
+ "attributes": {"size": "L", ...},
25
+ "videos": [
26
+ {"url": "[video1_url]", "title": "[video1_title]"},
27
+ {"url": "[video2_url]", "title": "[video2_title]"}
28
+ ]
29
+ }
30
+
31
+ Description: """
32
+ Use this JSON format to output the final job response
33
+ """
34
+
35
+ Output Format Failed:
36
+ {"type": "JOB_FAILED", "reason": "fail reason summary"}
37
+ Description: """
38
+ Output this JSON format if you can't extract the required data
39
+ """
40
+
41
+ List of API commands you can use to accomplish the Task:
42
+
43
+ /googleSearch("query")
44
+ Description: """
45
+ Get results from Google Search API.
46
+ """
47
+
48
+ /youtubeSearch("query")
49
+ Description: """
50
+ Get results from youtube Search API.
51
+ """
52
+
53
+ /googleImageSearch("query")
54
+ Description: """
55
+ Get results from google Image Search
56
+ """
57
+
58
+ /webpageToText("URL")
59
+ Description: """
60
+ Use this API to open/read a web pages like product pages.
61
+ """
@@ -0,0 +1,13 @@
1
+ {
2
+ "chatVendor": "anthropic",
3
+ "kbDescription": "An autonomous AI powerhouse for content generation",
4
+ "kbTitle": "Copywriter",
5
+ "model": "claude-3-5-haiku-20241022",
6
+ "inputTools": [
7
+ "imageToText"
8
+ ],
9
+ "embeddingModel": "none",
10
+ "embeddingDimension": "none",
11
+ "searchEngine": "IndexedDB",
12
+ "itemTypes": {}
13
+ }
@@ -0,0 +1,120 @@
1
+ const https = require('https');
2
+ const fs = require('fs');
3
+ const readline = require('readline');
4
+ const path = require('path');
5
+
6
+ const settings = JSON.parse(fs.readFileSync('app/settings.json', 'utf8'));
7
+ const secretsPath = path.join('.openkbs', 'secrets.json');
8
+ let apiKey;
9
+
10
+ const message = `PROCESS_PRODUCT:
11
+ Product Name: iPhone 14 Pro Max
12
+ Product Code: MQ9X3RX/A
13
+ ID: 97649
14
+
15
+ find at least 2 images and 2 videos
16
+ `;
17
+
18
+ if (!settings.kbId) {
19
+ console.log('First use: "openkbs push" To create the agent')
20
+ return;
21
+ }
22
+
23
+ // Function to read the API key from secrets.json
24
+ function getApiKey() {
25
+ if (fs.existsSync(secretsPath)) {
26
+ const secrets = JSON.parse(fs.readFileSync(secretsPath, 'utf8'));
27
+ return secrets.apiKey;
28
+ }
29
+ return null;
30
+ }
31
+
32
+ function promptForApiKey() {
33
+ return new Promise((resolve) => {
34
+ const rl = readline.createInterface({
35
+ input: process.stdin,
36
+ output: process.stdout
37
+ });
38
+
39
+ console.log(`Please generate an API key from: https://${settings.kbId}.apps.openkbs.com/?tab=access&createAPIKey=api-${+new Date()}`);
40
+
41
+ rl.question('Enter your API key: ', (key) => {
42
+ rl.close();
43
+ resolve(key);
44
+ });
45
+
46
+ rl._writeToOutput = (str) => rl.output.write(rl.line ? "*" : str);
47
+ });
48
+ }
49
+
50
+ function saveApiKey(key) {
51
+ if (!fs.existsSync('.openkbs')) {
52
+ fs.mkdirSync('.openkbs');
53
+ }
54
+ fs.writeFileSync(secretsPath, JSON.stringify({ apiKey: key }, null, 2));
55
+ }
56
+
57
+ async function main() {
58
+ apiKey = getApiKey();
59
+
60
+ if (!apiKey) {
61
+ apiKey = await promptForApiKey();
62
+ console.log('\n')
63
+ saveApiKey(apiKey);
64
+ }
65
+
66
+ const app = { kbId: settings.kbId, apiKey };
67
+
68
+ const chatTitle = "Task " + new Date().getTime();
69
+ startJob(chatTitle, message, app).then(chatId => {
70
+ console.log(`Job ${chatId} created.\nWorking ...`);
71
+ pollForMessages(chatId, app);
72
+ }).catch(console.error);
73
+ }
74
+
75
+ function startJob(chatTitle, data, app) {
76
+ return makeRequest('https://chat.openkbs.com/', { ...app, chatTitle, message: data })
77
+ .then(res => {
78
+ try {
79
+ return JSON.parse(res)[0].createdChatId;
80
+ } catch (error) {
81
+ fs.unlinkSync(secretsPath);
82
+ throw 'Authentication failed.';
83
+ }
84
+ });
85
+ }
86
+
87
+ function makeRequest(url, payload) {
88
+ return new Promise((resolve, reject) => {
89
+ const { hostname, pathname } = new URL(url);
90
+ const req = https.request({
91
+ hostname, path: pathname, method: 'POST',
92
+ headers: { 'Content-Type': 'application/json' }
93
+ }, res => {
94
+ let data = '';
95
+ res.on('data', chunk => data += chunk);
96
+ res.on('end', () => resolve(data));
97
+ }).on('error', reject);
98
+
99
+ req.write(JSON.stringify(payload));
100
+ req.end();
101
+ });
102
+ }
103
+
104
+ function pollForMessages(chatId, app) {
105
+ const payload = { ...app, action: 'getChatMessages', chatId, decryptContent: true };
106
+ const interval = setInterval(() => {
107
+ makeRequest('https://chat.openkbs.com/', payload).then(jsonString => {
108
+ const messages = JSON.parse(jsonString)[0].data.messages;
109
+ for (const message of messages) {
110
+ if (message.role === 'system' && /{"type"\s*:\s*"(JOB_COMPLETED|JOB_FAILED)".*?}/s.test(message.content)) {
111
+ console.log(JSON.parse(message.content).data[0]);
112
+ clearInterval(interval);
113
+ return;
114
+ }
115
+ }
116
+ }).catch(console.error);
117
+ }, 1000);
118
+ }
119
+
120
+ main();
@@ -0,0 +1,152 @@
1
+ const extractJSONFromText = (text) => {
2
+ let braceCount = 0, startIndex = text.indexOf('{');
3
+ if (startIndex === -1) return null;
4
+
5
+ for (let i = startIndex; i < text.length; i++) {
6
+ if (text[i] === '{') braceCount++;
7
+ if (text[i] === '}' && --braceCount === 0) {
8
+ try {
9
+ return JSON.parse(text.slice(startIndex, i + 1));
10
+ } catch {
11
+ return null;
12
+ }
13
+ }
14
+ }
15
+ return null;
16
+ }
17
+
18
+ export const getActions = () => [
19
+ [/[\s\S]*"type"\s*:\s*"JOB_COMPLETED"[\s\S]*/, async (match, event) => {
20
+ const parsedData = extractJSONFromText(match[0]);
21
+ if (parsedData && parsedData.type === "JOB_COMPLETED") {
22
+ await openkbs.chats({
23
+ action: "updateChat",
24
+ title: await openkbs.encrypt(parsedData?.name),
25
+ chatIcon: '🟢',
26
+ chatId: event?.payload?.chatId
27
+ })
28
+
29
+ return parsedData;
30
+ }
31
+ }],
32
+
33
+
34
+ [/[\s\S]*"type"\s*:\s*"JOB_FAILED"[\s\S]*/, async (match, event) => {
35
+ const json = extractJSONFromText(match[0]);
36
+ if (json && json.type === "JOB_FAILED") {
37
+ await openkbs.chats({
38
+ action: "updateChat",
39
+ title: await openkbs.encrypt(json.reason),
40
+ chatIcon: '🔴',
41
+ chatId: event?.payload?.chatId
42
+ })
43
+ }
44
+ }],
45
+
46
+ [/\/?googleSearch\("(.*?)"(?:,\s*(\d+))?\)/, async (match) => {
47
+ const q = match[1];
48
+ const limit = match[2] ? parseInt(match[2]) : 5;
49
+
50
+ try {
51
+ const response = await openkbs.googleSearch(q, {});
52
+ const data = response?.map(({ title, link, snippet, pagemap }) => ({
53
+ title, link, snippet, image: pagemap?.metatags?.[0]?.["og:image"]
54
+ })).slice(0, limit);
55
+
56
+ if(!data?.length) return { data: { error: "No results found" } };
57
+ return { data };
58
+ } catch (e) {
59
+ return { error: e.message };
60
+ }
61
+ }],
62
+
63
+ [/\/?youtubeSearch\("(.*?)"(?:,\s*(\d+))?\)/, async (match) => {
64
+ const q = match[1];
65
+ const limit = match[2] ? parseInt(match[2]) : 5;
66
+ try {
67
+ const response = await openkbs.googleSearch(q + ' site:youtube.com', { videoOnly: true });
68
+ const data = response?.map(({ title, link, snippet, pagemap }) => ({
69
+ title,
70
+ link: link.replace('www.youtube.com/watch?v=', 'youtu.be/'),
71
+ snippet,
72
+ thumbnail: pagemap?.videoobject?.[0]?.thumbnailurl || pagemap?.metatags?.[0]?.["og:image"],
73
+ duration: pagemap?.videoobject?.[0]?.duration,
74
+ channel: pagemap?.metatags?.[0]?.["og:site_name"],
75
+ })).filter(item => item.link.includes('youtu')).slice(0, limit);
76
+
77
+ if(!data?.length) return { data: { error: "No YouTube videos found" } };
78
+ return { data };
79
+ } catch (e) {
80
+ return { error: e.message };
81
+ }
82
+ }],
83
+
84
+ [/\/?googleImageSearch\("(.*?)"(?:,\s*(\d+))?\)/, async (match) => {
85
+ const q = match[1];
86
+ const limit = match[2] ? parseInt(match[2]) : 10;
87
+
88
+ try {
89
+ const response = await openkbs.googleSearch(q, { searchType: 'image' });
90
+ const data = response?.map(({ title, link, snippet, pagemap }) => {
91
+ const imageObj = pagemap?.cse_image?.[0];
92
+ const thumbnail = imageObj?.src || pagemap?.metatags?.[0]?.["og:image"] || link;
93
+ return {
94
+ title,
95
+ link: link,
96
+ snippet,
97
+ image: thumbnail
98
+ };
99
+ })?.slice(0, limit);
100
+
101
+ if (!data?.length) return { data: { error: "No image results found" } };
102
+ return { data };
103
+
104
+ } catch (e) {
105
+ return { error: e.message };
106
+ }
107
+ }],
108
+
109
+ [/\/?webpageToText\("(.*)"\)/, async (match) => {
110
+ try {
111
+ let response = await openkbs.webpageToText(match[1]);
112
+
113
+ // limit output length
114
+ if (response?.content?.length > 5000) {
115
+ response.content = response.content.substring(0, 5000);
116
+ }
117
+ if(!response?.url) return { data: { error: "Unable to read website" } };
118
+ return { data: response };
119
+ } catch (e) {
120
+ return { error: e.response?.data || e };
121
+ }
122
+ }],
123
+
124
+ [/\/?documentToText\("(.*)"\)/, async (match) => {
125
+ try {
126
+ let response = await openkbs.documentToText(match[1]);
127
+
128
+ // limit output length
129
+ if (response?.text?.length > 5000) {
130
+ response.text = response.text.substring(0, 5000);
131
+ }
132
+
133
+ return { data: response };
134
+ } catch (e) {
135
+ return { error: e.response.data };
136
+ }
137
+ }],
138
+
139
+ [/\/?imageToText\("(.*)"\)/, async (match) => {
140
+ try {
141
+ let response = await openkbs.imageToText(match[1]);
142
+
143
+ if (response?.detections?.[0]?.txt) {
144
+ response = { detections: response?.detections?.[0]?.txt };
145
+ }
146
+
147
+ return { data: response };
148
+ } catch (e) {
149
+ return { error: e.response.data };
150
+ }
151
+ }],
152
+ ];
@@ -0,0 +1,59 @@
1
+ import {getActions} from './actions.js';
2
+
3
+ export const handler = async (event) => {
4
+ const maxSelfInvokeMessagesCount = 60;
5
+ const lastMessage = event.payload.messages[event.payload.messages.length - 1].content;
6
+
7
+ // Check if this is a JOB_COMPLETED or JOB_FAILED event
8
+ const isJobCompleted = /"type"\s*:\s*"JOB_COMPLETED"/.test(lastMessage);
9
+ const isJobFailed = /"type"\s*:\s*"JOB_FAILED"/.test(lastMessage);
10
+
11
+ const actions = getActions();
12
+
13
+ const matchingActions = actions.reduce((acc, [regex, action]) => {
14
+ const matches = [...lastMessage.matchAll(new RegExp(regex, 'g'))];
15
+ matches.forEach(match => {
16
+ acc.push(action(match, event));
17
+ });
18
+ return acc;
19
+ }, []);
20
+
21
+ const isJobFinished = isJobCompleted || isJobFailed;
22
+
23
+ const meta = {
24
+ _meta_actions:
25
+ (
26
+ event?.payload?.messages?.length > maxSelfInvokeMessagesCount ||
27
+ isJobFinished && (matchingActions.length === 1 || lastMessage.role === 'system')
28
+ )
29
+ ? []
30
+ : ["REQUEST_CHAT_MODEL"]
31
+ }
32
+
33
+ if (matchingActions.length > 0) {
34
+ try {
35
+ const results = await Promise.all(matchingActions);
36
+
37
+ if (results?.[0]?.data?.some?.(o => o?.type === 'image_url')) {
38
+ return {
39
+ ...results[0],
40
+ ...meta
41
+ };
42
+ }
43
+
44
+ return {
45
+ type: 'RESPONSE',
46
+ data: results,
47
+ ...meta
48
+ };
49
+ } catch (error) {
50
+ return {
51
+ type: 'ERROR',
52
+ error: error.message,
53
+ ...meta
54
+ };
55
+ }
56
+ }
57
+
58
+ return { type: 'CONTINUE' };
59
+ };
@@ -0,0 +1,26 @@
1
+ import React, { useEffect } from "react";
2
+
3
+ const onRenderChatMessage = async (params) => {
4
+ return;
5
+ };
6
+
7
+ const Header = ({ setRenderSettings }) => {
8
+ useEffect(() => {
9
+ setRenderSettings({
10
+ inputLabelsQuickSend: true,
11
+ disableBalanceView: false,
12
+ disableSentLabel: false,
13
+ disableChatAvatar: false,
14
+ disableChatModelsSelect: false,
15
+ disableContextItems: false,
16
+ disableCopyButton: false,
17
+ disableEmojiButton: false,
18
+ disableTextToSpeechButton: false,
19
+ disableMobileLeftButton: false,
20
+ });
21
+ }, [setRenderSettings]);
22
+ }
23
+
24
+ const exports = { onRenderChatMessage, Header };
25
+ window.contentRender = exports;
26
+ export default exports;
@@ -0,0 +1,10 @@
1
+ {
2
+ "dependencies": {
3
+ "react": "^18.2.0 (fixed)",
4
+ "react-dom": "^18.2.0 (fixed)",
5
+ "@mui/material": "^5.16.1 (fixed)",
6
+ "@mui/icons-material": "^5.16.1 (fixed)",
7
+ "@emotion/react": "^11.10.6 (fixed)",
8
+ "@emotion/styled": "^11.10.6 (fixed)"
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "version": "0.0.1"
3
+ }
@@ -0,0 +1,15 @@
1
+ # Claude Code Instructions
2
+
3
+ ## Initial Setup
4
+ 1. First, update the knowledge base to ensure you have the latest information:
5
+ ```bash
6
+ openkbs update knowledge
7
+ ```
8
+
9
+ 2. Then read the project contribution guidelines:
10
+ ```bash
11
+ # Read the knowledge base README for detailed instructions
12
+ .openkbs/knowledge/README.md
13
+ ```
14
+
15
+ This file contains comprehensive instructions on how to contribute to this OpenKBS project.
package/ON_PREMISES.md DELETED
@@ -1,215 +0,0 @@
1
-
2
- ### Running the Backend Locally (On-Premises)
3
-
4
- To run the backend services of your AI application locally, follow these steps. This allows you to manage chat services, code execution, and AI LLM services on your own infrastructure.
5
-
6
- #### Running the Chat Service Locally
7
-
8
- 1. **Start the Chat Service**:
9
- - Open a new terminal and navigate to the root folder of your application.
10
- - Run the following command:
11
-
12
- ```bash
13
- npm run chat
14
- ```
15
-
16
- - If LocalStack is not installed, you will receive instructions on how to install it based on your platform.
17
- - Open another terminal, navigate to `/tmp`, and install LocalStack using the suggested commands and retrun `npm run chat`
18
-
19
-
20
- 4. **Configure OpenAI Key**:
21
- - Enter your `OPENAI_KEY` when prompted. This key will be stored at `~/.openkbs/.env`.
22
-
23
- 5. **Access the Local Chat Service**:
24
- - Refresh your browser at `http://{kbId}.apps.localhost:38593/chat`.
25
- - You will see "On-Premises" in green text, indicating that your OpenKBS instance is using the local chat server to communicate with the OpenAI streaming API.
26
- - You can remove the cloud models options by setting `"enableCloudModels": false` in `config.json`
27
-
28
- #### Running the Code Execution Service Locally
29
-
30
- 1. **Start the Code Execution Service**:
31
- - Open another terminal tab, navigate to the root folder of your KB app, and run:
32
-
33
- ```bash
34
- npm run code
35
- ```
36
-
37
- 2. **Enter Secrets**:
38
- - You may be prompted to enter any secret placeholders in your `./src/Events/actions.js`. By default, this includes `googlesearch_api_key` and `googlesearch_engine_id`.
39
- - You can press enter to skip, but for using Google Search as an AI tool, it's recommended to fill them. Google provides 100 free searches per day.
40
-
41
- Congratulations! The LLM can now execute NodeJS code directly on your machine!
42
-
43
- #### Enhancing Your Application with Code Execution
44
-
45
- To utilize the code execution feature, follow these steps:
46
-
47
- 1. **Update `contentRender.js`**:
48
- - Modify your local `contentRender.js` file to match the version found at [contentRender.js](./examples/cloud-master/contentRender.js). This update will provide the necessary UI components for local code execution and response rendering.
49
-
50
- 2. **Update `instructions.txt`**:
51
- - Edit your local `instructions.txt` file to include the instructions found at [instructions.txt](./examples/cloud-master/instructions.txt). These instructions will guide the LLM on how to output code and other API commands for execution by the OpenKBS framework.
52
-
53
- 3. **Push the new instructions**:
54
- - we have to push the instructions which are stored encrypted at OpenKBS registry:
55
- ```bash
56
- openkbs push origin app/instructions.txt
57
- ```
58
- - push to localstack to build and deploy all Node.js events - ./src/Events
59
- ```bash
60
- openkbs push localstack
61
- ```
62
- 4. **Requesting the AI to Perform Tasks on Your PC and AWS Cloud**:
63
- - Instruct the AI to list your desktop files, review the code, click `execute`, and click `send`:
64
- ```
65
- List my desktop files
66
- ```
67
- - Instruct the AI to create an S3 bucket and backup your desktop images to it:
68
- ```
69
- Create an S3 bucket and back up my desktop images to it
70
- ```
71
- ![backup.png](examples%2Fcloud-master%2Fbackup.png)
72
- ---
73
-
74
- ## Installing openkbs-ai-server and Integrating Llama 3.1 and Stable Diffusion 3 Locally
75
-
76
- ![llama-loaded.png](examples%2Fcloud-master%2Fllama-loaded.png)
77
-
78
- To set up the `openkbs-ai-server` and integrate advanced AI models like Llama 3.1 and Stable Diffusion 3 on your local machine, follow the steps outlined below.
79
-
80
- ### Prerequisites
81
-
82
- Ensure you have the following prerequisites installed and configured:
83
-
84
- - Ubuntu 22.04 or a compatible Linux distribution.
85
- - Python 3.10 and virtual environment tools.
86
- - Node.js and npm.
87
- - NVIDIA or AMD GPU drivers, depending on your hardware.
88
-
89
- Please follow the installation on [GitHub](https://github.com/open-kbs/openkbs-ai-server).
90
-
91
- ### Step 1: Checkout, Build, and Run
92
-
93
- Clone the `openkbs-ai-server` repository and set up the environment:
94
-
95
- ```bash
96
- git clone git@github.com:open-kbs/openkbs-ai-server.git
97
- cd openkbs-ai-server/cluster
98
- npm i
99
- cd ..
100
- python -m venv .env
101
- source .env/bin/activate
102
- ```
103
-
104
- **IMPORTANT: SELECT THE CORRECT GPU INSTRUCTIONS BELOW. DO NOT EXECUTE BOTH.**
105
-
106
- #### **FOR AMD GPUS:**
107
-
108
- **ONLY FOLLOW THESE INSTRUCTIONS IF YOU HAVE AN AMD GPU.**
109
-
110
- Install necessary libraries and Python packages:
111
-
112
- ```bash
113
- sudo apt-get install -y libjpeg-dev libpng-dev
114
- pip install wheel setuptools
115
- pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/rocm6.1/
116
- pip install -r ./models/requirements_AMD.txt
117
- ```
118
-
119
- #### **FOR NVIDIA GPUS:**
120
-
121
- **ONLY FOLLOW THESE INSTRUCTIONS IF YOU HAVE AN NVIDIA GPU.**
122
-
123
- Install the required Python packages:
124
-
125
- ```bash
126
- pip install torch
127
- pip install -r ./models/requirements_NVIDIA.txt
128
- ```
129
-
130
- ### Step 2: Configure Hugging Face Authentication
131
-
132
- Log in to Hugging Face to access the AI models:
133
-
134
- ```bash
135
- huggingface-cli login
136
- ```
137
-
138
- Enter your Hugging Face token when prompted.
139
-
140
- ### Step 3: Install Global Node.js Packages
141
-
142
- Install global Node.js packages required for running the server:
143
-
144
- ```bash
145
- npm install -g pm2 nodemon react-scripts
146
- ```
147
-
148
- ### Step 4: Start the AI Server
149
-
150
- Launch the AI server using the provided script:
151
-
152
- ```bash
153
- ./start.sh
154
- ```
155
-
156
- This command will start both the frontend and backend services using pm2. Your default web browser should automatically open to [http://localhost:7080/register](http://localhost:7080/register), where you can register the admin account for the AI server.
157
-
158
- ### Step 5: Install AI Models
159
-
160
- In the AI server admin panel, search for and install the following models:
161
-
162
- - **Llama-3.1-8B-Instruct**: Ensure you have access to [Llama-3.1-8B-Instruct](https://huggingface.co/meta-llama/Llama-3.1-8B-Instruct) on Hugging Face.
163
- - **Stable Diffusion 3**: Ensure you have access to [Stable Diffusion 3](https://huggingface.co/stabilityai/stable-diffusion-3-medium) on Hugging Face.
164
-
165
- After installation, restart your chat server to apply the changes.
166
-
167
- ### Step 6: Integrate Stable Diffusion under Events actions, so that Llama can call it
168
-
169
- Go to your app root folder
170
- ```bash
171
- cd my-pc-agent
172
- ```
173
-
174
- Add to `./src/Events/actions.js`
175
- ```javascript
176
- [/\/?textToImage\("(.*)"\)/, async (match) => {
177
- try {
178
- const response = await axios.get(`http://localhost:8080/pipe/stabilityai--stable-diffusion-3-medium-diffusers--default?prompt=${encodeURIComponent(match[1])}`, {
179
- responseType: 'arraybuffer'
180
- });
181
-
182
- const base64Data = Buffer.from(response.data, 'binary').toString('base64');
183
- const contentType = response.headers['content-type'];
184
- const imageSrc = `data:${contentType};base64,${base64Data}`;
185
-
186
- return { type: 'SAVED_CHAT_IMAGE', imageSrc, ...meta };
187
- } catch (error) {
188
- console.error('Error fetching image:', error);
189
- throw error; // or handle the error as needed
190
- }
191
- }]
192
- ```
193
-
194
- Push the changes:
195
- ```bash
196
- openkbs push localstack
197
- ```
198
- ### Step 7: Test Llama agent
199
-
200
- Once the models are installed and the server is running, select `Llama-3.1-8B-Inst` in your Chat Models selection and type in the chat:
201
-
202
- ```
203
- Hey Llama, search Google for the latest AI news and wait, then generate news image. Finally, use a template function to create an HTML page hosted on the S3 bucket 'ai-news-openkbs'.
204
- ```
205
-
206
- ![ai1.png](examples%2Fcloud-master%2Fai1.png)
207
-
208
- ![llama-loaded.png](examples%2Fcloud-master%2Fllama-loaded.png)
209
-
210
- ![sd3-loaded.png](examples%2Fcloud-master%2Fsd3-loaded.png)
211
-
212
- ![ai2.png](examples%2Fcloud-master%2Fai2.png)
213
-
214
- ![ai3.png](examples%2Fcloud-master%2Fai3.png)
215
- Have fun!
@@ -1,34 +0,0 @@
1
- export const getActions = (meta) => [
2
- [/\/?googleSearch\("(.*)"\)/, async (match) => {
3
- const q = match[1];
4
- try {
5
- const noSecrets = '{{secrets.googlesearch_api_key}}'.includes('secrets.googlesearch_api_key');
6
- const params = { q, ...(noSecrets ? {} : { key: '{{secrets.googlesearch_api_key}}', cx: '{{secrets.googlesearch_engine_id}}' }) };
7
- const response = noSecrets
8
- ? await openkbs.googleSearch(params.q, params)
9
- : (await axios.get('https://www.googleapis.com/customsearch/v1', { params }))?.data?.items;
10
- const data = response?.map(({ title, link, snippet, pagemap }) => ({
11
- title, link, snippet, image: pagemap?.metatags?.[0]?.["og:image"]
12
- }));
13
- return { data, ...meta };
14
- } catch (e) {
15
- return { error: e.response.data, ...meta };
16
- }
17
- }],
18
- [/\/?textToImage\("(.*)"\)/, async (match) => {
19
- try {
20
- const response = await axios.get(`http://localhost:8080/pipe/stabilityai--stable-diffusion-3-medium-diffusers--default?prompt=${encodeURIComponent(match[1])}`, {
21
- responseType: 'arraybuffer'
22
- });
23
-
24
- const base64Data = Buffer.from(response.data, 'binary').toString('base64');
25
- const contentType = response.headers['content-type'];
26
- const imageSrc = `data:${contentType};base64,${base64Data}`;
27
-
28
- return { type: 'SAVED_CHAT_IMAGE', imageSrc, ...meta };
29
- } catch (error) {
30
- console.error('Error fetching image:', error);
31
- throw error; // or handle the error as needed
32
- }
33
- }]
34
- ];
Binary file
Binary file
Binary file
Binary file
@@ -1,255 +0,0 @@
1
- import React, { useState, useEffect, useRef } from "react";
2
- import { IconButton, Tooltip, LinearProgress } from '@mui/material';
3
- import CloseIcon from "@mui/icons-material/Close";
4
- import SendIcon from "@mui/icons-material/Send";
5
- import { FileCopy, PlayArrow } from "@mui/icons-material";
6
- import { AppBar, Toolbar, Typography } from '@mui/material';
7
- import { MoreVert as MenuIcon, AccountCircle as AccountIcon } from '@mui/icons-material';
8
-
9
- // Inject custom styles
10
- const style = document.createElement('style');
11
- style.innerHTML = `
12
- .codeContainer, .codeContainer code {
13
- background-color: #0d0d0d !important;
14
- color: white !important;
15
- text-shadow: none !important;
16
- border-radius: 10px !important;
17
- font-size: 13px !important;
18
- }
19
- .codeContainer * {
20
- background-color: #0d0d0d !important;
21
- }
22
- @keyframes pulseButton {
23
- 0% { transform: scale(1); }
24
- 50% { transform: scale(1.5); }
25
- 100% { transform: scale(1); }
26
- }
27
- .pulseButton {
28
- animation: 0.7s pulse 2;
29
- }
30
- `;
31
- document.head.appendChild(style);
32
-
33
- // Utility function to parse JSON safely
34
- function parseJSON(str) {
35
- try {
36
- if (str && typeof str === 'string' && (str[0] === '{' || str[0] === '[')) {
37
- return JSON.parse(str);
38
- }
39
- } catch {}
40
- }
41
-
42
- // Check if code contains ES6 syntax or JSX
43
- export const containsES6SyntaxOrJSX = (code) => {
44
- const es6Patterns = [/\bimport\b/, /\bexport\b/];
45
- const jsxPattern = /<([A-Za-z][A-Za-z0-9]*)(\s+[A-Za-z0-9\-]+(\s*=\s*{[^}]*}|="[^"]*"|='[^']*'|=[^>\s]+)?)*\s*\/?>/;
46
- return es6Patterns.some(pattern => pattern.test(code)) || jsxPattern.test(code);
47
- };
48
-
49
- const isMobile = window.innerWidth < 960;
50
-
51
- export function CodeViewer(props) {
52
- const [response, setResponse] = useState(null);
53
- const [codeRunLoading, setCodeRunLoading] = useState(false);
54
- const [isLongContent, setIsLongContent] = useState(false);
55
- const [prismHeight, setPrismHeight] = useState(0);
56
- const responseRef = useRef(null);
57
- const prismRef = useRef(null);
58
- const [tooltipOpen, setTooltipOpen] = useState(true);
59
-
60
- const handleTooltipClose = () => setTooltipOpen(false);
61
- const handleTooltipOpen = () => setTooltipOpen(true);
62
-
63
- const { source, onClose, styleCopy, noCopy, limitedWidth, styleClose, execute, ...restProps } = props;
64
- const { ReactPrismjs, APIResponseComponent, CopyToClipboard } = props.params;
65
- const { RequestChatAPI, kbUserData, generateMsgId, msgIndex, messages, setSystemAlert, KB, axios } = props.params;
66
-
67
- const isLastMessage = msgIndex >= (messages?.filter(msg => msg?.content)?.length - 1);
68
- const canExecute = execute && props?.language?.includes('javascript') && !containsES6SyntaxOrJSX(source);
69
-
70
- useEffect(() => {
71
- const lineCount = source ? source.split('\n').length : 0;
72
- setIsLongContent(lineCount > 25);
73
- }, [source]);
74
-
75
- useEffect(() => {
76
- if (response && responseRef.current) {
77
- responseRef.current.scrollIntoView({ behavior: 'smooth' });
78
- }
79
- }, [response]);
80
-
81
- useEffect(() => {
82
- if (prismRef.current) {
83
- setPrismHeight(prismRef.current.clientHeight);
84
- }
85
- }, [source]);
86
-
87
- const runCode = async () => {
88
- try {
89
- const code = source.includes('module.exports')
90
- ? source
91
- : `const handler = async (event) => { ${source} }; module.exports = { handler };`;
92
- setCodeRunLoading(true);
93
- const response = await axios.post(`http://localhost:38595`, {
94
- walletPrivateKey: KB?.walletPrivateKey,
95
- walletPublicKey: KB?.walletPublicKey,
96
- accountId: KB?.accountId,
97
- userCode:code,
98
- AESKey: KB?.key
99
- });
100
-
101
- setCodeRunLoading(false);
102
- setResponse(response?.data?.error ? JSON.stringify(response.data) : JSON.stringify(response.data));
103
- } catch (error) {
104
- setCodeRunLoading(false);
105
- setResponse(`Error: ${error?.response?.status || error.message}`);
106
- }
107
- };
108
-
109
- const preStyle = {
110
- whiteSpace: limitedWidth ? 'pre-wrap' : undefined,
111
- wordBreak: limitedWidth ? 'break-all' : undefined,
112
- ...restProps.style
113
- };
114
- const colorIcon = '#e7e7e7';
115
- const oneliner = !(source?.split?.('\n')?.length > 1);
116
-
117
- const handleOnCopy = () => {
118
- setSystemAlert && setSystemAlert({ msg: 'Copied to clipboard', type: 'success', duration: 1500 });
119
- props?.onCopy && props.onCopy();
120
- };
121
-
122
- const formattedResponse = parseJSON(response) || { response }
123
-
124
- return (
125
- <div style={{ paddingBottom: 2, position: 'relative', display: 'inline-block', maxWidth: '100%', minWidth: '350px', overflowX: 'auto' }}>
126
- {oneliner && <div style={{ height: '40px' }}></div>}
127
- {onClose && (
128
- <IconButton onClick={onClose} style={styleClose}>
129
- <CloseIcon style={{ opacity: 0.7, fontSize: '1rem', color: colorIcon }} />
130
- </IconButton>
131
- )}
132
- <div ref={prismRef}>
133
- <ReactPrismjs {...{ source, style: preStyle, ...restProps }} />
134
- </div>
135
- {!codeRunLoading && (
136
- <>
137
- <CopyToClipboard text={source || ''}>
138
- <IconButton onClick={handleOnCopy} style={{ position: 'absolute', top: `${prismHeight - 30}px`, right: '0px', zIndex: 10, color: 'rgba(11, 11, 11, 0.54)' }}>
139
- {!noCopy && <FileCopy style={{ opacity: 0.7, color: colorIcon }} />}
140
- </IconButton>
141
- </CopyToClipboard>
142
- {canExecute && (
143
- <Tooltip title="Execute" arrow onMouseEnter={handleTooltipClose} onMouseLeave={handleTooltipOpen} open={isLastMessage && !response && !codeRunLoading && tooltipOpen} placement={"top"}>
144
- <IconButton onClick={runCode} style={{ position: 'absolute', top: `${prismHeight - 30}px`, right: '36px', animation: isLastMessage && !response && !codeRunLoading && 'pulseButton 1.5s infinite', ...styleCopy }}>
145
- <PlayArrow style={{ color: '#e7e7e7' }} />
146
- </IconButton>
147
- </Tooltip>
148
- )}
149
- </>
150
- )}
151
- {codeRunLoading ? (
152
- <LinearProgress />
153
- ) : (
154
- response && (
155
- <div ref={responseRef} style={{ position: 'relative', paddingTop: '30px' }}>
156
- <APIResponseComponent open={false} showResponseSize={true} JSONData={formattedResponse} enableClipboard={true} />
157
- <>
158
- <CopyToClipboard text={response || ''}>
159
- <IconButton onClick={handleOnCopy} style={{ position: 'absolute', top: '35px', right: '0px' }}>
160
- <FileCopy style={{ opacity: 0.7, color: '#3D86C9' }} />
161
- </IconButton>
162
- </CopyToClipboard>
163
- {isLastMessage && (
164
- <Tooltip title="Send Response" arrow open={isLastMessage} placement={"top"}>
165
- <IconButton onClick={async () => {
166
- await RequestChatAPI([...messages, {
167
- role: 'user',
168
- content: typeof response === 'number' ? response.toString() : response,
169
- userId: kbUserData().chatUsername,
170
- msgId: generateMsgId()
171
- }]);
172
- }} style={{ position: 'absolute', top: '35px', right: '36px', animation: 'pulseButton 1.5s infinite' }}>
173
- <SendIcon style={{ opacity: 0.9, color: '#3D86C9' }} />
174
- </IconButton>
175
- </Tooltip>
176
- )}
177
- </>
178
- </div>
179
- )
180
- )}
181
- </div>
182
- );
183
- }
184
-
185
- const onRenderChatMessage = async (params) => {
186
- const { content } = params.messages[params.msgIndex];
187
- if (content.match(/```/)) {
188
- let language = null;
189
- const output = [];
190
-
191
- content.split('\n').forEach(line => {
192
- if (!language) {
193
- language = /```(?<language>\w+)/g.exec(line)?.groups?.language;
194
- output.push(language ? { language, code: '' } : line);
195
- } else if (line.match(/```/)) {
196
- language = null;
197
- } else {
198
- output[output.length - 1].code += line + '\n';
199
- }
200
- });
201
-
202
- return output.map((o, i) =>
203
- typeof o === 'string'
204
- ? <p key={`a${i}`} style={{ marginTop: '0px', marginBottom: '0px' }}>{o}</p>
205
- : <div key={`a${i}`}>
206
- <CodeViewer
207
- key={`ab${i}`}
208
- params={{ ...params, i }}
209
- limitedWidth={isMobile}
210
- execute={true}
211
- className="codeContainer"
212
- language={o.language}
213
- source={o.code}
214
- />
215
- </div>
216
- );
217
- }
218
- }
219
-
220
- const Header = ({ setRenderSettings}) => {
221
- useEffect(() => {
222
- setRenderSettings({
223
- disableShareButton: true,
224
- disableBalanceView: true,
225
- disableSentLabel: false,
226
- disableChatAvatar: false,
227
- disableChatModelsSelect: false,
228
- disableContextItems: false,
229
- disableCopyButton: false,
230
- disableEmojiButton: false,
231
- disableTextToSpeechButton: false,
232
- disableMobileLeftButton: false,
233
- });
234
- }, [setRenderSettings]);
235
-
236
- return (
237
- <AppBar position="absolute" style={{ zIndex: 2000, flexGrow: 1, textAlign: 'left' }}>
238
- <Toolbar>
239
- <IconButton edge="start" color="inherit" aria-label="menu" style={{ marginRight: '16px' }}>
240
- <MenuIcon />
241
- </IconButton>
242
- <Typography variant="h6" style={{ flexGrow: 1 }}>
243
- My PC Agent
244
- </Typography>
245
- <IconButton edge="end" color="inherit" aria-label="account">
246
- <AccountIcon />
247
- </IconButton>
248
- </Toolbar>
249
- </AppBar>
250
- );
251
- }
252
-
253
- const exports = { onRenderChatMessage, Header };
254
- window.contentRender = exports;
255
- export default exports;
@@ -1,77 +0,0 @@
1
- You are an AI assistant, assist users with their inquiries and tasks efficiently.
2
- - Always output one action per message and wait for a response before continuing.
3
- - When asked to generate HTML, always enclose the response in `<html>{your implementation}</html>` tags.
4
-
5
- API_COMMANDS_INSTRUCTIONS:
6
-
7
- Guidelines:
8
- - always ouput any commands on by one, and wait for the response
9
-
10
- Here are some API commands you can use to assist users:
11
-
12
- /googleSearch("query")
13
- Description: """
14
- Get results from Google Search API.
15
- """
16
- $InputLabel = """Let me Search in Google!"""
17
- $InputValue = """Search in google for the latest news"""
18
-
19
- /textToImage("image prompt")
20
- Description: """
21
- Generates images by text prompt (English only supported).
22
-
23
- A good prompt needs to be detailed and specific.
24
- A good process is to look through a list of keyword categories and decide whether you want to use any of them.
25
- The keyword categories are:
26
-
27
- Subject - The subject is what you want to see in the image. A common mistake is not writing enough about the subjects. (e.g., beautiful and powerful mysterious sorceress, smile, sitting on a rock, lightning magic, hat, detailed leather clothing with gemstones, dress, castle background)
28
- Medium - Medium is the material used to make artwork. Some examples are illustration, oil painting, 3D rendering, and photography. Medium has a strong effect because one keyword alone can dramatically change the style. (e.g., digital art)
29
- Style - The style refers to the artistic style of the image. Examples include impressionist, surrealist, pop art, etc. (e.g., impressionist, surrealist, pop art)
30
- Resolution - Resolution represents how sharp and detailed the image is. Let’s add keywords highly detailed and sharp focus. (e.g., highly detailed, sharp focus, 8k)
31
- Additional details - Additional details are sweeteners added to modify an image. We will add sci-fi and dystopian to add some vibe to the image. (e.g., sci-fi, dystopian)
32
- Color - You can control the overall color of the image by adding color keywords. The colors you specified may appear as a tone or in objects. (e.g., iridescent gold)
33
- Lighting - Any photographer would tell you lighting is key to creating successful images. Lighting keywords can have a huge effect on how the image looks. Let’s add studio lighting to make it studio photo-like. (e.g., studio lighting)
34
- Remarks - You may have noticed the images are already pretty good with only a few keywords added. More is not always better when building a prompt. You often don’t need many keywords to get good images.
35
- """
36
- $InputLabel = """Let me Generate Image!"""
37
- $InputValue = """Generate a cover image for a health and weight loss campaign"""
38
-
39
-
40
- FUNCTION_EXECUTION_INSTRUCTIONS:
41
-
42
- You can also use Node.js code to perform tasks on the user's local PC or perform AWS code using the provided template functions.
43
-
44
- Guidelines:
45
-
46
- - Output only one Template Function per message.
47
- - Functions always export the handler function at the end.
48
- - Once you output a function, it will be executed (as it is) on the user's PC and you will get the response.
49
- - Before performing any specific operations, first explore the available resources to understand their structure and contents. This could involve listing available items, such as tables in a database, files in a directory, or objects in a cloud storage bucket.
50
- - Once the resources are identified, gather detailed information about their structure and attributes. This might include describing the schema of a database table, examining metadata of files, or reviewing properties of cloud resources.
51
- - If the initial exploration does not provide sufficient information, inspect a sample of the resource to gain a deeper understanding of its structure and contents. This could involve selecting a few records from a database, opening a few files, or downloading a few objects from cloud storage.
52
- - Avoid using placeholder variables in the code. Instead, request the necessary information from the user to generate fully functional and executable code.
53
- - Common env variables process.env.HOME
54
-
55
- By following these steps, you can ensure a comprehensive understanding of the resources you are working with
56
-
57
- Template Functions:
58
-
59
- ```javascript
60
- const AWS = require('aws-sdk'); // require example 1
61
- const dns = require('dns'); // require example 2
62
- const { promisify } = require('util'); // require example 3
63
-
64
- AWS.config.update({ region: 'us-east-1' });
65
-
66
- const handler = async () => {
67
- // Generate code here to perform the desired operations and get a response.
68
-
69
-
70
- // code Examples:
71
- // return await new AWS.S3().listBuckets().promise();
72
- // return await promisify(dns.resolveAny)('example.net')
73
-
74
- };
75
-
76
- module.exports = { handler };
77
- ```