openkbs 0.0.53 → 0.0.55
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/README.md +1490 -202
- package/package.json +2 -1
- package/src/actions.js +345 -1
- package/src/index.js +17 -1
- package/templates/.openkbs/knowledge/examples/ai-copywriter-agent/app/instructions.txt +44 -9
- package/templates/.openkbs/knowledge/examples/ai-copywriter-agent/src/Events/actions.js +43 -42
- package/templates/.openkbs/knowledge/examples/ai-copywriter-agent/src/Events/handler.js +14 -8
- package/templates/.openkbs/knowledge/examples/ai-copywriter-agent/src/Frontend/contentRender.js +95 -12
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/README.md +64 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/app/instructions.txt +160 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/app/settings.json +7 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Events/actions.js +258 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Events/onRequest.js +13 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Events/onRequest.json +3 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Events/onResponse.js +13 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Events/onResponse.json +3 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Frontend/contentRender.js +170 -0
- package/templates/.openkbs/knowledge/examples/ai-marketing-agent/src/Frontend/contentRender.json +3 -0
- package/templates/.openkbs/knowledge/metadata.json +1 -1
- package/templates/CLAUDE.md +593 -222
- package/templates/app/instructions.txt +13 -1
- package/templates/app/settings.json +5 -6
- package/templates/src/Events/actions.js +43 -9
- package/templates/src/Events/handler.js +24 -25
- package/templates/webpack.contentRender.config.js +8 -2
- package/version.json +3 -3
- package/MODIFY.md +0 -132
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openkbs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.55",
|
|
4
4
|
"description": "OpenKBS - Command Line Interface",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@aws-sdk/client-s3": "^3.658.1",
|
|
39
|
+
"archiver": "^7.0.1",
|
|
39
40
|
"bip39": "^3.1.0",
|
|
40
41
|
"cli-spinner": "^0.2.10",
|
|
41
42
|
"commander": "^12.1.0",
|
package/src/actions.js
CHANGED
|
@@ -837,6 +837,349 @@ async function downloadClaudeMdFromS3(claudeMdPath) {
|
|
|
837
837
|
}
|
|
838
838
|
}
|
|
839
839
|
|
|
840
|
+
// ===== Elastic Functions Commands =====
|
|
841
|
+
|
|
842
|
+
async function fnAction(subCommand, args = []) {
|
|
843
|
+
const localKBData = await fetchLocalKBData();
|
|
844
|
+
const kbId = localKBData?.kbId;
|
|
845
|
+
|
|
846
|
+
if (!kbId) {
|
|
847
|
+
return console.red('No KB found. Please run this command in a KB project directory.');
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
const { kbToken } = await fetchKBJWT(kbId);
|
|
851
|
+
|
|
852
|
+
switch (subCommand) {
|
|
853
|
+
case 'list':
|
|
854
|
+
return await fnListAction(kbToken);
|
|
855
|
+
case 'deploy':
|
|
856
|
+
return await fnDeployAction(kbToken, args[0], args.slice(1));
|
|
857
|
+
case 'delete':
|
|
858
|
+
return await fnDeleteAction(kbToken, args[0]);
|
|
859
|
+
case 'logs':
|
|
860
|
+
return await fnLogsAction(kbToken, args[0], args.slice(1));
|
|
861
|
+
case 'env':
|
|
862
|
+
return await fnEnvAction(kbToken, args[0], args.slice(1));
|
|
863
|
+
case 'invoke':
|
|
864
|
+
return await fnInvokeAction(kbToken, args[0], args.slice(1));
|
|
865
|
+
default:
|
|
866
|
+
console.log('Usage: openkbs fn <command> [options]');
|
|
867
|
+
console.log('');
|
|
868
|
+
console.log('Commands:');
|
|
869
|
+
console.log(' list List all elastic functions');
|
|
870
|
+
console.log(' deploy <name> Deploy a function from ./functions/<name>/');
|
|
871
|
+
console.log(' delete <name> Delete a function');
|
|
872
|
+
console.log(' logs <name> View function logs');
|
|
873
|
+
console.log(' env <name> [KEY=value] View or set environment variables');
|
|
874
|
+
console.log(' invoke <name> [payload] Invoke a function');
|
|
875
|
+
console.log('');
|
|
876
|
+
console.log('Options for deploy:');
|
|
877
|
+
console.log(' --region <region> Region (us-east-2, eu-central-1, ap-southeast-1)');
|
|
878
|
+
console.log(' --memory <mb> Memory size (128-3008 MB)');
|
|
879
|
+
console.log(' --timeout <seconds> Timeout (1-900 seconds)');
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
async function fnListAction(kbToken) {
|
|
884
|
+
try {
|
|
885
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
886
|
+
token: kbToken,
|
|
887
|
+
action: 'listElasticFunctions'
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
if (response.error) {
|
|
891
|
+
return console.red('Error:', response.error);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
const functions = response.functions || [];
|
|
895
|
+
|
|
896
|
+
if (functions.length === 0) {
|
|
897
|
+
console.log('No elastic functions found.');
|
|
898
|
+
console.log('');
|
|
899
|
+
console.log('Create a function:');
|
|
900
|
+
console.log(' 1. Create directory: mkdir -p functions/hello');
|
|
901
|
+
console.log(' 2. Create handler: echo "export const handler = async (event) => ({ body: \'Hello!\' });" > functions/hello/index.mjs');
|
|
902
|
+
console.log(' 3. Deploy: openkbs fn deploy hello --region us-east-2');
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
console.log('Elastic Functions:\n');
|
|
907
|
+
const maxNameLen = Math.max(...functions.map(f => f.functionName.length), 10);
|
|
908
|
+
|
|
909
|
+
functions.forEach(f => {
|
|
910
|
+
const name = f.functionName.padEnd(maxNameLen);
|
|
911
|
+
const region = f.region || 'unknown';
|
|
912
|
+
const url = f.customUrl || f.functionUrl || 'N/A';
|
|
913
|
+
console.log(` ${name} ${region} ${url}`);
|
|
914
|
+
});
|
|
915
|
+
} catch (error) {
|
|
916
|
+
console.red('Error listing functions:', error.message);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
async function fnDeployAction(kbToken, functionName, args) {
|
|
921
|
+
if (!functionName) {
|
|
922
|
+
return console.red('Function name required. Usage: openkbs fn deploy <name>');
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// Parse arguments
|
|
926
|
+
let region = 'us-east-2';
|
|
927
|
+
let memorySize = 256;
|
|
928
|
+
let timeout = 30;
|
|
929
|
+
|
|
930
|
+
for (let i = 0; i < args.length; i++) {
|
|
931
|
+
if (args[i] === '--region' && args[i + 1]) {
|
|
932
|
+
region = args[++i];
|
|
933
|
+
} else if (args[i] === '--memory' && args[i + 1]) {
|
|
934
|
+
memorySize = parseInt(args[++i]);
|
|
935
|
+
} else if (args[i] === '--timeout' && args[i + 1]) {
|
|
936
|
+
timeout = parseInt(args[++i]);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const functionDir = path.join(process.cwd(), 'functions', functionName);
|
|
941
|
+
|
|
942
|
+
if (!await fs.pathExists(functionDir)) {
|
|
943
|
+
return console.red(`Function directory not found: ${functionDir}`);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
console.log(`Deploying function '${functionName}' to ${region}...`);
|
|
947
|
+
|
|
948
|
+
try {
|
|
949
|
+
// Create a zip of the function directory
|
|
950
|
+
const archiver = require('archiver');
|
|
951
|
+
const { PassThrough } = require('stream');
|
|
952
|
+
|
|
953
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
954
|
+
const chunks = [];
|
|
955
|
+
const passThrough = new PassThrough();
|
|
956
|
+
|
|
957
|
+
passThrough.on('data', chunk => chunks.push(chunk));
|
|
958
|
+
|
|
959
|
+
await new Promise((resolve, reject) => {
|
|
960
|
+
passThrough.on('end', resolve);
|
|
961
|
+
passThrough.on('error', reject);
|
|
962
|
+
archive.on('error', reject);
|
|
963
|
+
|
|
964
|
+
archive.pipe(passThrough);
|
|
965
|
+
archive.directory(functionDir, false);
|
|
966
|
+
archive.finalize();
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
const zipBuffer = Buffer.concat(chunks);
|
|
970
|
+
const code = zipBuffer.toString('base64');
|
|
971
|
+
|
|
972
|
+
// Check if function exists
|
|
973
|
+
const listResponse = await makePostRequest(KB_API_URL, {
|
|
974
|
+
token: kbToken,
|
|
975
|
+
action: 'listElasticFunctions'
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
const existingFunc = listResponse.functions?.find(f => f.functionName === functionName);
|
|
979
|
+
|
|
980
|
+
let response;
|
|
981
|
+
if (existingFunc) {
|
|
982
|
+
// Update existing function
|
|
983
|
+
console.log('Updating existing function...');
|
|
984
|
+
response = await makePostRequest(KB_API_URL, {
|
|
985
|
+
token: kbToken,
|
|
986
|
+
action: 'updateElasticFunction',
|
|
987
|
+
functionName,
|
|
988
|
+
code
|
|
989
|
+
});
|
|
990
|
+
} else {
|
|
991
|
+
// Create new function
|
|
992
|
+
console.log('Creating new function...');
|
|
993
|
+
response = await makePostRequest(KB_API_URL, {
|
|
994
|
+
token: kbToken,
|
|
995
|
+
action: 'createElasticFunction',
|
|
996
|
+
functionName,
|
|
997
|
+
code,
|
|
998
|
+
region,
|
|
999
|
+
memorySize,
|
|
1000
|
+
timeout
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
if (response.error) {
|
|
1005
|
+
return console.red('Deploy failed:', response.error);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
console.green('Deploy successful!');
|
|
1009
|
+
if (response.functionUrl) {
|
|
1010
|
+
console.log(`Lambda URL: ${response.functionUrl}`);
|
|
1011
|
+
}
|
|
1012
|
+
if (response.customUrl) {
|
|
1013
|
+
console.log(`Custom URL: ${response.customUrl}`);
|
|
1014
|
+
}
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
console.red('Deploy failed:', error.message);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
async function fnDeleteAction(kbToken, functionName) {
|
|
1021
|
+
if (!functionName) {
|
|
1022
|
+
return console.red('Function name required. Usage: openkbs fn delete <name>');
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
try {
|
|
1026
|
+
console.log(`Deleting function '${functionName}'...`);
|
|
1027
|
+
|
|
1028
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1029
|
+
token: kbToken,
|
|
1030
|
+
action: 'deleteElasticFunction',
|
|
1031
|
+
functionName
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
if (response.error) {
|
|
1035
|
+
return console.red('Delete failed:', response.error);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
console.green(`Function '${functionName}' deleted successfully.`);
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
console.red('Delete failed:', error.message);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
async function fnLogsAction(kbToken, functionName, args) {
|
|
1045
|
+
if (!functionName) {
|
|
1046
|
+
return console.red('Function name required. Usage: openkbs fn logs <name>');
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
try {
|
|
1050
|
+
let limit = 50;
|
|
1051
|
+
for (let i = 0; i < args.length; i++) {
|
|
1052
|
+
if (args[i] === '--limit' && args[i + 1]) {
|
|
1053
|
+
limit = parseInt(args[++i]);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1058
|
+
token: kbToken,
|
|
1059
|
+
action: 'getElasticFunctionLogs',
|
|
1060
|
+
functionName,
|
|
1061
|
+
limit
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
if (response.error) {
|
|
1065
|
+
return console.red('Error:', response.error);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
if (!response.events || response.events.length === 0) {
|
|
1069
|
+
console.log('No logs found. Function may not have been invoked yet.');
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
console.log(`Logs for '${functionName}':\n`);
|
|
1074
|
+
response.events.forEach(event => {
|
|
1075
|
+
const time = new Date(event.timestamp).toISOString();
|
|
1076
|
+
console.log(`[${time}] ${event.message}`);
|
|
1077
|
+
});
|
|
1078
|
+
} catch (error) {
|
|
1079
|
+
console.red('Error fetching logs:', error.message);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
async function fnEnvAction(kbToken, functionName, args) {
|
|
1084
|
+
if (!functionName) {
|
|
1085
|
+
return console.red('Function name required. Usage: openkbs fn env <name> [KEY=value ...]');
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
try {
|
|
1089
|
+
if (args.length === 0) {
|
|
1090
|
+
// Show current env vars
|
|
1091
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1092
|
+
token: kbToken,
|
|
1093
|
+
action: 'getElasticFunction',
|
|
1094
|
+
functionName
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
if (response.error) {
|
|
1098
|
+
return console.red('Error:', response.error);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
console.log(`Environment variables for '${functionName}':\n`);
|
|
1102
|
+
const env = response.env || {};
|
|
1103
|
+
if (Object.keys(env).length === 0) {
|
|
1104
|
+
console.log(' (none)');
|
|
1105
|
+
} else {
|
|
1106
|
+
Object.entries(env).forEach(([key, value]) => {
|
|
1107
|
+
console.log(` ${key}=${value}`);
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
} else {
|
|
1111
|
+
// Set env vars
|
|
1112
|
+
const env = {};
|
|
1113
|
+
args.forEach(arg => {
|
|
1114
|
+
const [key, ...valueParts] = arg.split('=');
|
|
1115
|
+
if (key && valueParts.length > 0) {
|
|
1116
|
+
env[key] = valueParts.join('=');
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
if (Object.keys(env).length === 0) {
|
|
1121
|
+
return console.red('Invalid format. Use: openkbs fn env <name> KEY=value');
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
console.log(`Setting environment variables for '${functionName}'...`);
|
|
1125
|
+
|
|
1126
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1127
|
+
token: kbToken,
|
|
1128
|
+
action: 'setElasticFunctionEnv',
|
|
1129
|
+
functionName,
|
|
1130
|
+
env
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
if (response.error) {
|
|
1134
|
+
return console.red('Error:', response.error);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
console.green('Environment variables updated.');
|
|
1138
|
+
}
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
console.red('Error:', error.message);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
async function fnInvokeAction(kbToken, functionName, args) {
|
|
1145
|
+
if (!functionName) {
|
|
1146
|
+
return console.red('Function name required. Usage: openkbs fn invoke <name> [payload]');
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
try {
|
|
1150
|
+
let payload = {};
|
|
1151
|
+
if (args.length > 0) {
|
|
1152
|
+
try {
|
|
1153
|
+
payload = JSON.parse(args.join(' '));
|
|
1154
|
+
} catch (e) {
|
|
1155
|
+
return console.red('Invalid JSON payload');
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
console.log(`Invoking '${functionName}'...`);
|
|
1160
|
+
|
|
1161
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1162
|
+
token: kbToken,
|
|
1163
|
+
action: 'invokeElasticFunction',
|
|
1164
|
+
functionName,
|
|
1165
|
+
payload
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
if (response.error) {
|
|
1169
|
+
return console.red('Error:', response.error);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
console.log('\nResponse:');
|
|
1173
|
+
console.log(JSON.stringify(response.payload, null, 2));
|
|
1174
|
+
|
|
1175
|
+
if (response.functionError) {
|
|
1176
|
+
console.red('\nFunction Error:', response.functionError);
|
|
1177
|
+
}
|
|
1178
|
+
} catch (error) {
|
|
1179
|
+
console.red('Error invoking function:', error.message);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
840
1183
|
module.exports = {
|
|
841
1184
|
signAction,
|
|
842
1185
|
loginAction,
|
|
@@ -857,5 +1200,6 @@ module.exports = {
|
|
|
857
1200
|
updateKnowledgeAction,
|
|
858
1201
|
updateCliAction,
|
|
859
1202
|
publishAction,
|
|
860
|
-
unpublishAction
|
|
1203
|
+
unpublishAction,
|
|
1204
|
+
fnAction
|
|
861
1205
|
};
|
package/src/index.js
CHANGED
|
@@ -13,7 +13,8 @@ const {
|
|
|
13
13
|
deleteFileAction,
|
|
14
14
|
describeAction, deployAction, createByTemplateAction, initByTemplateAction,
|
|
15
15
|
logoutAction, installFrontendPackageAction, modifyAction, downloadModifyAction,
|
|
16
|
-
updateKnowledgeAction, updateCliAction, publishAction, unpublishAction
|
|
16
|
+
updateKnowledgeAction, updateCliAction, publishAction, unpublishAction,
|
|
17
|
+
fnAction
|
|
17
18
|
} = require('./actions');
|
|
18
19
|
|
|
19
20
|
|
|
@@ -197,4 +198,19 @@ Examples:
|
|
|
197
198
|
This will unpublish your KB from the domain example.com
|
|
198
199
|
`);
|
|
199
200
|
|
|
201
|
+
program
|
|
202
|
+
.command('fn [subCommand] [args...]')
|
|
203
|
+
.description('Manage Elastic Functions (serverless Lambda functions)')
|
|
204
|
+
.action((subCommand, args) => fnAction(subCommand, args))
|
|
205
|
+
.addHelpText('after', `
|
|
206
|
+
Examples:
|
|
207
|
+
$ openkbs fn list List all functions
|
|
208
|
+
$ openkbs fn deploy hello --region us-east-2 Deploy function from ./functions/hello/
|
|
209
|
+
$ openkbs fn delete hello Delete a function
|
|
210
|
+
$ openkbs fn logs hello View function logs
|
|
211
|
+
$ openkbs fn env hello View environment variables
|
|
212
|
+
$ openkbs fn env hello API_KEY=secret Set environment variable
|
|
213
|
+
$ openkbs fn invoke hello '{"test": true}' Invoke a function
|
|
214
|
+
`);
|
|
215
|
+
|
|
200
216
|
program.parse(process.argv);
|
|
@@ -38,24 +38,59 @@ Description: """
|
|
|
38
38
|
Output this JSON format if you can't extract the required data
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
LIST OF AVAILABLE COMMANDS:
|
|
42
|
+
To execute a command, output it as text and wait for system response.
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
<googleSearch>
|
|
45
|
+
{
|
|
46
|
+
"query": "search query"
|
|
47
|
+
}
|
|
48
|
+
</googleSearch>
|
|
44
49
|
Description: """
|
|
45
50
|
Get results from Google Search API.
|
|
46
51
|
"""
|
|
47
52
|
|
|
48
|
-
|
|
53
|
+
<youtubeSearch>
|
|
54
|
+
{
|
|
55
|
+
"query": "search query"
|
|
56
|
+
}
|
|
57
|
+
</youtubeSearch>
|
|
49
58
|
Description: """
|
|
50
|
-
Get results from
|
|
59
|
+
Get results from YouTube Search API.
|
|
51
60
|
"""
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
<googleImageSearch>
|
|
63
|
+
{
|
|
64
|
+
"query": "search query"
|
|
65
|
+
}
|
|
66
|
+
</googleImageSearch>
|
|
54
67
|
Description: """
|
|
55
|
-
Get results from
|
|
68
|
+
Get results from Google Image Search.
|
|
56
69
|
"""
|
|
57
70
|
|
|
58
|
-
|
|
71
|
+
<webpageToText>
|
|
72
|
+
{
|
|
73
|
+
"url": "https://example.com/page"
|
|
74
|
+
}
|
|
75
|
+
</webpageToText>
|
|
59
76
|
Description: """
|
|
60
|
-
Use this API to open/read
|
|
61
|
-
"""
|
|
77
|
+
Use this API to open/read web pages like product pages.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
<documentToText>
|
|
81
|
+
{
|
|
82
|
+
"url": "https://example.com/document.pdf"
|
|
83
|
+
}
|
|
84
|
+
</documentToText>
|
|
85
|
+
Description: """
|
|
86
|
+
Extract text from documents (PDF, DOC, etc.).
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
<imageToText>
|
|
90
|
+
{
|
|
91
|
+
"url": "https://example.com/image.png"
|
|
92
|
+
}
|
|
93
|
+
</imageToText>
|
|
94
|
+
Description: """
|
|
95
|
+
OCR - Extract text from images.
|
|
96
|
+
"""
|
|
@@ -15,7 +15,7 @@ const extractJSONFromText = (text) => {
|
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export const getActions = () => [
|
|
18
|
+
export const getActions = (meta) => [
|
|
19
19
|
// IMPORTANT: Actions returning JOB_COMPLETED or JOB_FAILED stop agent execution and return final result
|
|
20
20
|
[/[\s\S]*"type"\s*:\s*"JOB_COMPLETED"[\s\S]*/, async (match, event) => {
|
|
21
21
|
const parsedData = extractJSONFromText(match[0]);
|
|
@@ -31,7 +31,6 @@ export const getActions = () => [
|
|
|
31
31
|
}
|
|
32
32
|
}],
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
[/[\s\S]*"type"\s*:\s*"JOB_FAILED"[\s\S]*/, async (match, event) => {
|
|
36
35
|
const parsedData = extractJSONFromText(match[0]);
|
|
37
36
|
if (parsedData && parsedData.type === "JOB_FAILED") {
|
|
@@ -45,24 +44,26 @@ export const getActions = () => [
|
|
|
45
44
|
}
|
|
46
45
|
}],
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
// Google Search with XML+JSON format
|
|
48
|
+
[/<googleSearch>([\s\S]*?)<\/googleSearch>/s, async (match) => {
|
|
50
49
|
try {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
50
|
+
const data = JSON.parse(match[1].trim());
|
|
51
|
+
const response = await openkbs.googleSearch(data.query);
|
|
52
|
+
const results = response?.map(({ title, link, snippet, pagemap }) => ({
|
|
53
53
|
title, link, snippet, image: pagemap?.metatags?.[0]?.["og:image"]
|
|
54
54
|
}));
|
|
55
|
-
return { data };
|
|
55
|
+
return { data: results, ...meta };
|
|
56
56
|
} catch (e) {
|
|
57
|
-
return { error: e.message };
|
|
57
|
+
return { error: e.message, ...meta };
|
|
58
58
|
}
|
|
59
59
|
}],
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
// YouTube Search with XML+JSON format
|
|
62
|
+
[/<youtubeSearch>([\s\S]*?)<\/youtubeSearch>/s, async (match) => {
|
|
63
63
|
try {
|
|
64
|
-
const
|
|
65
|
-
const
|
|
64
|
+
const data = JSON.parse(match[1].trim());
|
|
65
|
+
const response = await openkbs.googleSearch(data.query + ' site:youtube.com', { videoOnly: true });
|
|
66
|
+
const results = response?.map(({ title, link, snippet, pagemap }) => ({
|
|
66
67
|
title,
|
|
67
68
|
link: link.replace('www.youtube.com/watch?v=', 'youtu.be/'),
|
|
68
69
|
snippet,
|
|
@@ -70,62 +71,62 @@ export const getActions = () => [
|
|
|
70
71
|
duration: pagemap?.videoobject?.[0]?.duration,
|
|
71
72
|
channel: pagemap?.metatags?.[0]?.["og:site_name"],
|
|
72
73
|
})).filter(item => item.link.includes('youtu'));
|
|
73
|
-
return { data };
|
|
74
|
+
return { data: results, ...meta };
|
|
74
75
|
} catch (e) {
|
|
75
|
-
return { error: e.message };
|
|
76
|
+
return { error: e.message, ...meta };
|
|
76
77
|
}
|
|
77
78
|
}],
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
// Google Image Search with XML+JSON format
|
|
81
|
+
[/<googleImageSearch>([\s\S]*?)<\/googleImageSearch>/s, async (match) => {
|
|
81
82
|
try {
|
|
82
|
-
const
|
|
83
|
-
const
|
|
83
|
+
const data = JSON.parse(match[1].trim());
|
|
84
|
+
const response = await openkbs.googleSearch(data.query, { searchType: 'image' });
|
|
85
|
+
const results = response?.map(({ title, link, snippet, pagemap }) => {
|
|
84
86
|
const imageObj = pagemap?.cse_image?.[0];
|
|
85
87
|
const thumbnail = imageObj?.src || pagemap?.metatags?.[0]?.["og:image"] || link;
|
|
86
|
-
return {
|
|
87
|
-
title,
|
|
88
|
-
link: link,
|
|
89
|
-
snippet,
|
|
90
|
-
image: thumbnail
|
|
91
|
-
};
|
|
88
|
+
return { title, link, snippet, image: thumbnail };
|
|
92
89
|
});
|
|
93
|
-
return { data };
|
|
90
|
+
return { data: results, ...meta };
|
|
94
91
|
} catch (e) {
|
|
95
|
-
return { error: e.message };
|
|
92
|
+
return { error: e.message, ...meta };
|
|
96
93
|
}
|
|
97
94
|
}],
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
// Webpage to Text with XML+JSON format
|
|
97
|
+
[/<webpageToText>([\s\S]*?)<\/webpageToText>/s, async (match) => {
|
|
100
98
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return { data:
|
|
99
|
+
const data = JSON.parse(match[1].trim());
|
|
100
|
+
let response = await openkbs.webpageToText(data.url);
|
|
101
|
+
if (!response?.url) return { data: { error: "Unable to read website" }, ...meta };
|
|
102
|
+
return { data: response, ...meta };
|
|
104
103
|
} catch (e) {
|
|
105
|
-
return { error: e.response?.data || e };
|
|
104
|
+
return { error: e.response?.data || e.message, ...meta };
|
|
106
105
|
}
|
|
107
106
|
}],
|
|
108
107
|
|
|
109
|
-
|
|
108
|
+
// Document to Text with XML+JSON format
|
|
109
|
+
[/<documentToText>([\s\S]*?)<\/documentToText>/s, async (match) => {
|
|
110
110
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const data = JSON.parse(match[1].trim());
|
|
112
|
+
let response = await openkbs.documentToText(data.url);
|
|
113
|
+
return { data: response, ...meta };
|
|
113
114
|
} catch (e) {
|
|
114
|
-
return { error: e.response
|
|
115
|
+
return { error: e.response?.data || e.message, ...meta };
|
|
115
116
|
}
|
|
116
117
|
}],
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
// Image to Text (OCR) with XML+JSON format
|
|
120
|
+
[/<imageToText>([\s\S]*?)<\/imageToText>/s, async (match) => {
|
|
119
121
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
const data = JSON.parse(match[1].trim());
|
|
123
|
+
let response = await openkbs.imageToText(data.url);
|
|
122
124
|
if (response?.detections?.[0]?.txt) {
|
|
123
125
|
response = { detections: response?.detections?.[0]?.txt };
|
|
124
126
|
}
|
|
125
|
-
|
|
126
|
-
return { data: response };
|
|
127
|
+
return { data: response, ...meta };
|
|
127
128
|
} catch (e) {
|
|
128
|
-
return { error: e.response
|
|
129
|
+
return { error: e.response?.data || e.message, ...meta };
|
|
129
130
|
}
|
|
130
131
|
}],
|
|
131
|
-
];
|
|
132
|
+
];
|
|
@@ -2,7 +2,14 @@ import {getActions} from './actions.js';
|
|
|
2
2
|
|
|
3
3
|
export const backendHandler = async (event) => {
|
|
4
4
|
const lastMessage = event.payload.messages[event.payload.messages.length - 1];
|
|
5
|
-
const
|
|
5
|
+
const reachedMessageLimit = event?.payload?.messages?.length > 60;
|
|
6
|
+
|
|
7
|
+
// Meta for continuing chat model requests
|
|
8
|
+
const meta = {
|
|
9
|
+
_meta_actions: reachedMessageLimit ? [] : ["REQUEST_CHAT_MODEL"]
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const actions = getActions(meta);
|
|
6
13
|
|
|
7
14
|
const matchingActions = actions.reduce((acc, [regex, action]) => {
|
|
8
15
|
const matches = [...lastMessage.content.matchAll(new RegExp(regex, 'g'))];
|
|
@@ -12,31 +19,30 @@ export const backendHandler = async (event) => {
|
|
|
12
19
|
return acc;
|
|
13
20
|
}, []);
|
|
14
21
|
|
|
15
|
-
const reachedMessageLimit = event?.payload?.messages?.length > 60;
|
|
16
|
-
|
|
17
22
|
if (matchingActions.length > 0) {
|
|
18
23
|
try {
|
|
19
24
|
const results = await Promise.all(matchingActions);
|
|
20
25
|
|
|
21
26
|
// IMPORTANT: Actions returning JOB_COMPLETED or JOB_FAILED stop agent execution and return final result
|
|
22
|
-
const isOnlyJobCompletion = results.length === 1 &&
|
|
27
|
+
const isOnlyJobCompletion = results.length === 1 &&
|
|
23
28
|
(results[0]?.type === 'JOB_COMPLETED' || results[0]?.type === 'JOB_FAILED');
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
// Override meta for job completion
|
|
31
|
+
const finalMeta = {
|
|
26
32
|
_meta_actions: (reachedMessageLimit || isOnlyJobCompletion) ? [] : ["REQUEST_CHAT_MODEL"]
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
if (results?.[0]?.data?.some?.(o => o?.type === 'image_url')) {
|
|
30
36
|
return {
|
|
31
37
|
...results[0],
|
|
32
|
-
...
|
|
38
|
+
...finalMeta
|
|
33
39
|
};
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
return {
|
|
37
43
|
type: 'RESPONSE',
|
|
38
44
|
data: results,
|
|
39
|
-
...
|
|
45
|
+
...finalMeta
|
|
40
46
|
};
|
|
41
47
|
} catch (error) {
|
|
42
48
|
return {
|