openkbs 0.0.65 → 0.0.67
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 +0 -2
- package/package.json +1 -1
- package/src/actions.js +93 -85
- package/src/index.js +16 -15
- package/templates/.claude/skills/openkbs/SKILL.md +184 -0
- package/templates/.claude/skills/openkbs/metadata.json +1 -0
- package/templates/.claude/skills/openkbs/reference/backend-sdk.md +428 -0
- package/templates/.claude/skills/openkbs/reference/commands.md +370 -0
- package/templates/.claude/skills/openkbs/reference/elastic-services.md +327 -0
- package/templates/.claude/skills/openkbs/reference/frontend-sdk.md +299 -0
- package/templates/platform/README.md +70 -0
- package/templates/platform/agents/assistant/app/instructions.txt +25 -0
- package/templates/platform/agents/assistant/app/settings.json +17 -0
- package/templates/platform/agents/assistant/src/Events/actions.js +81 -0
- package/templates/platform/agents/assistant/src/Events/onResponse.js +41 -0
- package/templates/platform/agents/assistant/src/Events/onResponse.json +3 -0
- package/templates/platform/agents/assistant/src/Frontend/contentRender.js +26 -0
- package/templates/platform/agents/assistant/src/Frontend/contentRender.json +10 -0
- package/templates/platform/functions/api/index.mjs +69 -0
- package/templates/platform/openkbs.json +14 -0
- package/templates/platform/site/index.html +76 -0
- package/version.json +3 -3
- package/templates/.openkbs/knowledge/metadata.json +0 -3
- package/templates/CLAUDE.md +0 -655
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/app/icon.png +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/app/instructions.txt +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/app/settings.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/scripts/run_job.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/scripts/utils/agent_client.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/actions.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/handler.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/onRequest.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/onRequest.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/onResponse.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Events/onResponse.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Frontend/contentRender.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-copywriter-agent/src/Frontend/contentRender.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/README.md +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/app/instructions.txt +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/app/settings.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Events/actions.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Events/onRequest.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Events/onRequest.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Events/onResponse.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Events/onResponse.json +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Frontend/contentRender.js +0 -0
- /package/templates/{.openkbs/knowledge → .claude/skills/openkbs}/examples/ai-marketing-agent/src/Frontend/contentRender.json +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# OpenKBS · [](https://github.com/open-kbs/openkbs-chat/blob/main/LICENSE) [](https://www.npmjs.com/package/openkbs)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
3
|
OpenKBS is an extendable AI service designed to build,
|
|
6
4
|
deploy and integrate AI agents and applications.
|
|
7
5
|
|
package/package.json
CHANGED
package/src/actions.js
CHANGED
|
@@ -611,20 +611,11 @@ async function downloadModifyAction() {
|
|
|
611
611
|
});
|
|
612
612
|
}
|
|
613
613
|
|
|
614
|
-
async function
|
|
614
|
+
async function updateSkillsAction(silent = false) {
|
|
615
615
|
try {
|
|
616
|
-
const
|
|
617
|
-
const metadataPath = path.join(
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
// Check if .openkbs/knowledge directory exists
|
|
621
|
-
if (!fs.existsSync(knowledgeDir)) {
|
|
622
|
-
if (!silent) {
|
|
623
|
-
console.red('Knowledge directory not found. Please ensure you are in an OpenKBS project directory.');
|
|
624
|
-
}
|
|
625
|
-
return;
|
|
626
|
-
}
|
|
627
|
-
|
|
616
|
+
const skillsDir = path.join(process.cwd(), '.claude', 'skills', 'openkbs');
|
|
617
|
+
const metadataPath = path.join(skillsDir, 'metadata.json');
|
|
618
|
+
|
|
628
619
|
// Get local metadata version
|
|
629
620
|
let localVersion = null;
|
|
630
621
|
if (fs.existsSync(metadataPath)) {
|
|
@@ -635,15 +626,14 @@ async function updateKnowledgeAction(silent = false) {
|
|
|
635
626
|
if (!silent) {
|
|
636
627
|
console.red('Error reading local metadata.json:', error.message);
|
|
637
628
|
}
|
|
638
|
-
return;
|
|
639
629
|
}
|
|
640
630
|
}
|
|
641
|
-
|
|
631
|
+
|
|
642
632
|
// Check remote version from S3
|
|
643
633
|
const https = require('https');
|
|
644
634
|
const bucket = 'openkbs-downloads';
|
|
645
|
-
const remoteMetadataKey = 'templates/.openkbs/
|
|
646
|
-
|
|
635
|
+
const remoteMetadataKey = 'templates/.claude/skills/openkbs/metadata.json';
|
|
636
|
+
|
|
647
637
|
let remoteVersion = null;
|
|
648
638
|
try {
|
|
649
639
|
const fileUrl = `https://${bucket}.s3.amazonaws.com/${remoteMetadataKey}`;
|
|
@@ -654,7 +644,7 @@ async function updateKnowledgeAction(silent = false) {
|
|
|
654
644
|
res.on('end', () => resolve(data));
|
|
655
645
|
}).on('error', reject);
|
|
656
646
|
});
|
|
657
|
-
|
|
647
|
+
|
|
658
648
|
const remoteMetadata = JSON.parse(remoteMetadataContent);
|
|
659
649
|
remoteVersion = remoteMetadata.version;
|
|
660
650
|
} catch (error) {
|
|
@@ -663,26 +653,23 @@ async function updateKnowledgeAction(silent = false) {
|
|
|
663
653
|
}
|
|
664
654
|
return;
|
|
665
655
|
}
|
|
666
|
-
|
|
656
|
+
|
|
667
657
|
// Compare versions
|
|
668
658
|
if (localVersion === remoteVersion) {
|
|
669
|
-
console.green('
|
|
659
|
+
console.green('OpenKBS skill is already up to date.');
|
|
670
660
|
return;
|
|
671
661
|
}
|
|
672
|
-
|
|
673
|
-
console.log(`Updating
|
|
674
|
-
|
|
675
|
-
// Download updated
|
|
676
|
-
await
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
console.green('Knowledge base updated successfully!');
|
|
682
|
-
|
|
662
|
+
|
|
663
|
+
console.log(`Updating OpenKBS skill from version ${localVersion || 'not installed'} to ${remoteVersion}...`);
|
|
664
|
+
|
|
665
|
+
// Download updated skill files from S3
|
|
666
|
+
await downloadSkillsFromS3(skillsDir);
|
|
667
|
+
|
|
668
|
+
console.green('OpenKBS skill updated successfully!');
|
|
669
|
+
|
|
683
670
|
} catch (error) {
|
|
684
671
|
if (!silent) {
|
|
685
|
-
console.red('Error updating
|
|
672
|
+
console.red('Error updating skills:', error.message);
|
|
686
673
|
}
|
|
687
674
|
}
|
|
688
675
|
}
|
|
@@ -744,8 +731,8 @@ async function updateCliAction() {
|
|
|
744
731
|
console.red('Error fetching CLI version metadata:', error.message);
|
|
745
732
|
}
|
|
746
733
|
|
|
747
|
-
// Also update
|
|
748
|
-
await
|
|
734
|
+
// Also update skills silently
|
|
735
|
+
await updateSkillsAction(true);
|
|
749
736
|
|
|
750
737
|
} catch (error) {
|
|
751
738
|
console.red('Error updating CLI:', error.message);
|
|
@@ -816,14 +803,17 @@ function compareVersions(version1, version2) {
|
|
|
816
803
|
}
|
|
817
804
|
|
|
818
805
|
|
|
819
|
-
async function
|
|
806
|
+
async function downloadSkillsFromS3(targetDir) {
|
|
820
807
|
const https = require('https');
|
|
821
808
|
const bucket = 'openkbs-downloads';
|
|
822
|
-
const prefix = 'templates/.openkbs/
|
|
809
|
+
const prefix = 'templates/.claude/skills/openkbs/';
|
|
823
810
|
const baseUrl = `https://${bucket}.s3.amazonaws.com`;
|
|
824
|
-
|
|
811
|
+
|
|
825
812
|
try {
|
|
826
|
-
//
|
|
813
|
+
// Ensure directory exists
|
|
814
|
+
await fs.ensureDir(targetDir);
|
|
815
|
+
|
|
816
|
+
// List all objects in skills folder
|
|
827
817
|
const listUrl = `${baseUrl}/?list-type=2&prefix=${prefix}`;
|
|
828
818
|
const listXml = await new Promise((resolve, reject) => {
|
|
829
819
|
https.get(listUrl, (res) => {
|
|
@@ -832,28 +822,28 @@ async function downloadKnowledgeFromS3(targetDir) {
|
|
|
832
822
|
res.on('end', () => resolve(data));
|
|
833
823
|
}).on('error', reject);
|
|
834
824
|
});
|
|
835
|
-
|
|
825
|
+
|
|
836
826
|
// Parse XML to extract object keys
|
|
837
827
|
const keyMatches = listXml.match(/<Key>([^<]+)<\/Key>/g) || [];
|
|
838
828
|
const keys = keyMatches.map(match => match.replace(/<\/?Key>/g, ''));
|
|
839
|
-
|
|
829
|
+
|
|
840
830
|
if (keys.length === 0) {
|
|
841
|
-
console.yellow('No
|
|
831
|
+
console.yellow('No skill files found in remote repository.');
|
|
842
832
|
return;
|
|
843
833
|
}
|
|
844
|
-
|
|
834
|
+
|
|
845
835
|
// Download all files in parallel
|
|
846
836
|
const downloadPromises = keys.map(async (key) => {
|
|
847
837
|
const relativePath = key.substring(prefix.length);
|
|
848
|
-
|
|
838
|
+
|
|
849
839
|
// Skip if it's a directory marker
|
|
850
840
|
if (relativePath.endsWith('/') || relativePath === '') return;
|
|
851
|
-
|
|
841
|
+
|
|
852
842
|
const localPath = path.join(targetDir, relativePath);
|
|
853
|
-
|
|
843
|
+
|
|
854
844
|
// Ensure directory exists
|
|
855
845
|
await fs.ensureDir(path.dirname(localPath));
|
|
856
|
-
|
|
846
|
+
|
|
857
847
|
// Download file
|
|
858
848
|
const fileUrl = `${baseUrl}/${key}`;
|
|
859
849
|
const fileContent = await new Promise((resolve, reject) => {
|
|
@@ -864,49 +854,15 @@ async function downloadKnowledgeFromS3(targetDir) {
|
|
|
864
854
|
}).on('error', reject);
|
|
865
855
|
});
|
|
866
856
|
await fs.writeFile(localPath, fileContent);
|
|
867
|
-
|
|
857
|
+
|
|
868
858
|
console.log(`Downloaded: ${relativePath}`);
|
|
869
859
|
});
|
|
870
|
-
|
|
860
|
+
|
|
871
861
|
await Promise.all(downloadPromises);
|
|
872
|
-
|
|
873
|
-
} catch (error) {
|
|
874
|
-
console.red('Error downloading knowledge files from S3:', error.message);
|
|
875
|
-
throw error;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
862
|
|
|
879
|
-
async function downloadClaudeMdFromS3(claudeMdPath) {
|
|
880
|
-
const https = require('https');
|
|
881
|
-
const bucket = 'openkbs-downloads';
|
|
882
|
-
const claudeMdKey = 'templates/CLAUDE.md';
|
|
883
|
-
|
|
884
|
-
try {
|
|
885
|
-
// Download CLAUDE.md file from S3
|
|
886
|
-
const fileUrl = `https://${bucket}.s3.amazonaws.com/${claudeMdKey}`;
|
|
887
|
-
const fileContent = await new Promise((resolve, reject) => {
|
|
888
|
-
https.get(fileUrl, (res) => {
|
|
889
|
-
if (res.statusCode === 404) {
|
|
890
|
-
reject(new Error('NoSuchKey'));
|
|
891
|
-
return;
|
|
892
|
-
}
|
|
893
|
-
const chunks = [];
|
|
894
|
-
res.on('data', (chunk) => chunks.push(chunk));
|
|
895
|
-
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
896
|
-
}).on('error', reject);
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
await fs.writeFile(claudeMdPath, fileContent);
|
|
900
|
-
|
|
901
|
-
console.log('Downloaded: CLAUDE.md');
|
|
902
|
-
|
|
903
863
|
} catch (error) {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
} else {
|
|
907
|
-
console.red('Error downloading CLAUDE.md:', error.message);
|
|
908
|
-
throw error;
|
|
909
|
-
}
|
|
864
|
+
console.red('Error downloading skill files from S3:', error.message);
|
|
865
|
+
throw error;
|
|
910
866
|
}
|
|
911
867
|
}
|
|
912
868
|
|
|
@@ -2457,6 +2413,14 @@ async function elasticStatusAction() {
|
|
|
2457
2413
|
*/
|
|
2458
2414
|
async function stackAction(subCommand, args = []) {
|
|
2459
2415
|
switch (subCommand) {
|
|
2416
|
+
case 'create':
|
|
2417
|
+
const stackName = args[0];
|
|
2418
|
+
if (!stackName) {
|
|
2419
|
+
console.red('Error: Stack name is required');
|
|
2420
|
+
console.log('Usage: openkbs stack create <name>');
|
|
2421
|
+
process.exit(1);
|
|
2422
|
+
}
|
|
2423
|
+
return await stackCreateAction(stackName);
|
|
2460
2424
|
case 'deploy':
|
|
2461
2425
|
return await elasticDeployAction();
|
|
2462
2426
|
case 'destroy':
|
|
@@ -2469,10 +2433,54 @@ async function stackAction(subCommand, args = []) {
|
|
|
2469
2433
|
console.log('Commands:');
|
|
2470
2434
|
console.log(' deploy Deploy all resources from openkbs.json');
|
|
2471
2435
|
console.log(' destroy Delete all resources (DANGEROUS)');
|
|
2436
|
+
console.log(' create Create new platform stack');
|
|
2472
2437
|
console.log(' status Show status of all resources');
|
|
2473
2438
|
}
|
|
2474
2439
|
}
|
|
2475
2440
|
|
|
2441
|
+
/**
|
|
2442
|
+
* Create a new platform stack from template
|
|
2443
|
+
*/
|
|
2444
|
+
async function stackCreateAction(name) {
|
|
2445
|
+
try {
|
|
2446
|
+
// Download templates from S3 first
|
|
2447
|
+
await downloadTemplates();
|
|
2448
|
+
|
|
2449
|
+
const platformTemplateDir = path.join(TEMPLATE_DIR, 'platform');
|
|
2450
|
+
const targetDir = path.join(process.cwd(), name);
|
|
2451
|
+
|
|
2452
|
+
if (!fs.existsSync(platformTemplateDir)) {
|
|
2453
|
+
console.red('Error: Platform template not found. Run "openkbs update" first.');
|
|
2454
|
+
process.exit(1);
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
if (fs.existsSync(targetDir)) {
|
|
2458
|
+
console.red(`Error: Directory ${name} already exists.`);
|
|
2459
|
+
process.exit(1);
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
// Copy platform template
|
|
2463
|
+
fs.copySync(platformTemplateDir, targetDir);
|
|
2464
|
+
|
|
2465
|
+
// Replace placeholders in all files
|
|
2466
|
+
replacePlaceholderInFiles(targetDir, name);
|
|
2467
|
+
|
|
2468
|
+
console.green(`\nPlatform stack "${name}" created successfully!\n`);
|
|
2469
|
+
console.log('Structure:');
|
|
2470
|
+
console.log(` ${name}/`);
|
|
2471
|
+
console.log(' ├── agents/ # AI agents (each with app/ and src/)');
|
|
2472
|
+
console.log(' ├── functions/ # Serverless Lambda functions');
|
|
2473
|
+
console.log(' ├── site/ # Static site for whitelabel');
|
|
2474
|
+
console.log(' └── openkbs.json # Elastic services config\n');
|
|
2475
|
+
console.log('Next steps:');
|
|
2476
|
+
console.log(` cd ${name}`);
|
|
2477
|
+
console.log(' openkbs deploy # Deploy elastic services');
|
|
2478
|
+
console.log(' openkbs fn push api # Deploy the API function');
|
|
2479
|
+
} catch (error) {
|
|
2480
|
+
console.red(`Error during stack create:`, error.message);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2476
2484
|
module.exports = {
|
|
2477
2485
|
signAction,
|
|
2478
2486
|
loginAction,
|
|
@@ -2490,7 +2498,7 @@ module.exports = {
|
|
|
2490
2498
|
installFrontendPackageAction,
|
|
2491
2499
|
modifyAction,
|
|
2492
2500
|
downloadModifyAction,
|
|
2493
|
-
|
|
2501
|
+
updateSkillsAction,
|
|
2494
2502
|
updateCliAction,
|
|
2495
2503
|
publishAction,
|
|
2496
2504
|
unpublishAction,
|
package/src/index.js
CHANGED
|
@@ -13,7 +13,7 @@ const {
|
|
|
13
13
|
deleteFileAction,
|
|
14
14
|
describeAction, deployAction, createByTemplateAction, initByTemplateAction,
|
|
15
15
|
logoutAction, installFrontendPackageAction, modifyAction, downloadModifyAction,
|
|
16
|
-
|
|
16
|
+
updateSkillsAction, updateCliAction, publishAction, unpublishAction,
|
|
17
17
|
fnAction,
|
|
18
18
|
siteAction,
|
|
19
19
|
storageAction,
|
|
@@ -143,16 +143,18 @@ Reads openkbs.json and deletes:
|
|
|
143
143
|
`);
|
|
144
144
|
|
|
145
145
|
program
|
|
146
|
-
.command('stack <subcommand>')
|
|
147
|
-
.description('Manage stack resources (deploy, destroy, status)')
|
|
148
|
-
.action((subCommand) => stackAction(subCommand))
|
|
146
|
+
.command('stack <subcommand> [args...]')
|
|
147
|
+
.description('Manage stack resources (create, deploy, destroy, status)')
|
|
148
|
+
.action((subCommand, args) => stackAction(subCommand, args))
|
|
149
149
|
.addHelpText('after', `
|
|
150
150
|
Commands:
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
create <name> Create new platform stack from template
|
|
152
|
+
deploy Deploy all resources from openkbs.json
|
|
153
|
+
destroy Delete all resources (DANGEROUS)
|
|
154
|
+
status Show status of all resources
|
|
154
155
|
|
|
155
156
|
Examples:
|
|
157
|
+
$ openkbs stack create my-platform
|
|
156
158
|
$ openkbs stack deploy
|
|
157
159
|
$ openkbs stack status
|
|
158
160
|
$ openkbs stack destroy
|
|
@@ -194,25 +196,24 @@ This file will be automatically included when you run the 'openkbs modify' comma
|
|
|
194
196
|
|
|
195
197
|
program
|
|
196
198
|
.command('update [target]')
|
|
197
|
-
.description('Update OpenKBS CLI or
|
|
199
|
+
.description('Update OpenKBS CLI or skills (default: CLI)')
|
|
198
200
|
.action((target) => {
|
|
199
201
|
if (!target) {
|
|
200
202
|
updateCliAction();
|
|
201
|
-
} else if (target === '
|
|
202
|
-
|
|
203
|
+
} else if (target === 'skills') {
|
|
204
|
+
updateSkillsAction();
|
|
203
205
|
} else {
|
|
204
|
-
console.error(`Unknown update target: ${target}.
|
|
206
|
+
console.error(`Unknown update target: ${target}. Supported: skills`);
|
|
205
207
|
process.exit(1);
|
|
206
208
|
}
|
|
207
209
|
})
|
|
208
210
|
.addHelpText('after', `
|
|
209
211
|
Examples:
|
|
210
212
|
$ openkbs update
|
|
211
|
-
|
|
213
|
+
Check for CLI updates and install them.
|
|
212
214
|
|
|
213
|
-
$ openkbs update
|
|
214
|
-
|
|
215
|
-
and update it if necessary.
|
|
215
|
+
$ openkbs update skills
|
|
216
|
+
Update .claude/skills/openkbs/ with latest OpenKBS skill files.
|
|
216
217
|
`);
|
|
217
218
|
|
|
218
219
|
program
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openkbs
|
|
3
|
+
description: OpenKBS AI agent development framework. Use when creating, modifying, or deploying AI agents with backend handlers (onRequest, onResponse, actions.js), frontend components (contentRender.js), or elastic services (functions, postgres, storage, pulse). Trigger keywords: openkbs, kb, agent, handler, contentRender, elastic, memory, scheduled task.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenKBS Development
|
|
7
|
+
|
|
8
|
+
OpenKBS is a framework for building AI-powered applications - from simple agents to full-stack platforms.
|
|
9
|
+
|
|
10
|
+
## Two Usage Modes
|
|
11
|
+
|
|
12
|
+
### 1. Agent-Only Mode
|
|
13
|
+
Build a single conversational AI agent with backend handlers and custom UI.
|
|
14
|
+
```
|
|
15
|
+
openkbs create my-agent
|
|
16
|
+
openkbs push
|
|
17
|
+
```
|
|
18
|
+
Simplest way to get started - just an agent with memory, commands, and custom frontend.
|
|
19
|
+
|
|
20
|
+
### 2. Platform Mode (Full-Stack)
|
|
21
|
+
Build complete SaaS platforms that **include agents** plus additional infrastructure.
|
|
22
|
+
```
|
|
23
|
+
openkbs deploy # Deploy from openkbs.json
|
|
24
|
+
openkbs stack status # View deployed resources
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Platform mode extends agent capabilities with:
|
|
28
|
+
- **Multiple Agents**: Run several agents on one platform (in `agents/` folder)
|
|
29
|
+
- **Elastic Functions**: Serverless Lambda (Node.js, Python, Java)
|
|
30
|
+
- **Elastic Postgres**: Managed PostgreSQL (Neon) for relational data
|
|
31
|
+
- **Elastic Storage**: S3 buckets + CloudFront CDN for files
|
|
32
|
+
- **Elastic Pulse**: Real-time WebSocket pub/sub
|
|
33
|
+
- **Whitelabel**: Custom domains (`example.com`) with static site (`site/` folder)
|
|
34
|
+
|
|
35
|
+
**Architecture Note**: The whitelabel itself is a KB with its own `kbId` (a service agent, not user-facing). This "parent" kbId is used throughout the stack for elastic services. Each agent in `agents/` has its own separate `kbId`. All agents share the platform's elastic services via the parent kbId.
|
|
36
|
+
|
|
37
|
+
## Project Structure
|
|
38
|
+
|
|
39
|
+
### Agent Structure
|
|
40
|
+
```
|
|
41
|
+
my-agent/
|
|
42
|
+
├── app/
|
|
43
|
+
│ ├── settings.json # Agent configuration (model, itemTypes, MCP)
|
|
44
|
+
│ └── instructions.txt # System prompt for LLM
|
|
45
|
+
├── src/
|
|
46
|
+
│ ├── Events/
|
|
47
|
+
│ │ ├── onRequest.js # Pre-process user messages
|
|
48
|
+
│ │ ├── onResponse.js # Parse LLM output, execute commands
|
|
49
|
+
│ │ ├── actions.js # Command implementations
|
|
50
|
+
│ │ ├── onCronjob.js # Scheduled periodic tasks
|
|
51
|
+
│ │ └── onPublicAPIRequest.js # Webhook handler
|
|
52
|
+
│ └── Frontend/
|
|
53
|
+
│ ├── contentRender.js # Custom React UI
|
|
54
|
+
│ └── contentRender.json # Frontend dependencies
|
|
55
|
+
└── openkbs.json # Elastic services config
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Platform Structure
|
|
59
|
+
```
|
|
60
|
+
my-platform/
|
|
61
|
+
├── agents/ # Multiple AI agents
|
|
62
|
+
│ ├── marketing-assistant/ # Each agent has full structure
|
|
63
|
+
│ │ ├── app/
|
|
64
|
+
│ │ │ ├── settings.json
|
|
65
|
+
│ │ │ └── instructions.txt
|
|
66
|
+
│ │ └── src/
|
|
67
|
+
│ │ ├── Events/
|
|
68
|
+
│ │ │ ├── onRequest.js
|
|
69
|
+
│ │ │ ├── onResponse.js
|
|
70
|
+
│ │ │ └── actions.js
|
|
71
|
+
│ │ └── Frontend/
|
|
72
|
+
│ │ └── contentRender.js
|
|
73
|
+
│ └── support-agent/ # Another agent
|
|
74
|
+
│ ├── app/
|
|
75
|
+
│ └── src/
|
|
76
|
+
├── functions/ # Serverless Lambda functions
|
|
77
|
+
│ └── api/
|
|
78
|
+
│ └── index.mjs
|
|
79
|
+
├── site/ # Static site for whitelabel domain
|
|
80
|
+
│ └── index.html
|
|
81
|
+
└── openkbs.json # Elastic services config
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### openkbs.json
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"elastic": {
|
|
88
|
+
"postgres": true,
|
|
89
|
+
"storage": true,
|
|
90
|
+
"pulse": true,
|
|
91
|
+
"functions": {
|
|
92
|
+
"api": { "runtime": "nodejs22.x", "memory": 512 }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Quick Commands
|
|
99
|
+
|
|
100
|
+
### Agent Commands
|
|
101
|
+
```bash
|
|
102
|
+
openkbs create <name> # Create new agent
|
|
103
|
+
openkbs push # Deploy to cloud
|
|
104
|
+
openkbs pull # Download from cloud
|
|
105
|
+
openkbs update skills # Update this skill
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Platform Commands
|
|
109
|
+
```bash
|
|
110
|
+
openkbs deploy # Deploy all elastic services
|
|
111
|
+
openkbs stack status # Show deployed resources
|
|
112
|
+
openkbs destroy # Remove all resources (DANGEROUS)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Elastic Services
|
|
116
|
+
```bash
|
|
117
|
+
openkbs fn list # List Lambda functions
|
|
118
|
+
openkbs fn push api # Deploy function
|
|
119
|
+
openkbs fn logs api # View function logs
|
|
120
|
+
openkbs postgres shell # Connect to Postgres
|
|
121
|
+
openkbs storage ls # List S3 objects
|
|
122
|
+
openkbs pulse status # WebSocket status
|
|
123
|
+
openkbs site push # Deploy static site
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Backend Handler Pattern
|
|
127
|
+
|
|
128
|
+
Commands are XML tags with JSON content that the LLM outputs:
|
|
129
|
+
|
|
130
|
+
```xml
|
|
131
|
+
<commandName>{"param": "value"}</commandName>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The `handler.js` parses these tags, matches regex patterns in `actions.js`, and executes async functions:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// actions.js pattern
|
|
138
|
+
[/<googleSearch>([\s\S]*?)<\/googleSearch>/s, async (match) => {
|
|
139
|
+
const data = JSON.parse(match[1].trim());
|
|
140
|
+
const results = await openkbs.googleSearch(data.query);
|
|
141
|
+
return {
|
|
142
|
+
type: 'SEARCH_RESULTS',
|
|
143
|
+
data: results,
|
|
144
|
+
_meta_actions: ["REQUEST_CHAT_MODEL"] // Loop back to LLM
|
|
145
|
+
};
|
|
146
|
+
}]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Meta Actions
|
|
150
|
+
|
|
151
|
+
Control flow after command execution:
|
|
152
|
+
|
|
153
|
+
- `["REQUEST_CHAT_MODEL"]` - Send result back to LLM for processing
|
|
154
|
+
- `[]` - Display result to user, stop conversation
|
|
155
|
+
|
|
156
|
+
## Memory System
|
|
157
|
+
|
|
158
|
+
Configure in `settings.json`:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"itemTypes": {
|
|
163
|
+
"memory": {
|
|
164
|
+
"attributes": [
|
|
165
|
+
{ "attrName": "itemId", "attrType": "itemId", "encrypted": false },
|
|
166
|
+
{ "attrName": "body", "attrType": "body", "encrypted": true }
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"options": {
|
|
171
|
+
"priorityItems": [{ "prefix": "memory_", "limit": 100 }]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Priority items are auto-injected into LLM context.
|
|
177
|
+
|
|
178
|
+
## Additional Resources
|
|
179
|
+
|
|
180
|
+
- For backend SDK methods, see [reference/backend-sdk.md](reference/backend-sdk.md)
|
|
181
|
+
- For frontend React patterns, see [reference/frontend-sdk.md](reference/frontend-sdk.md)
|
|
182
|
+
- For XML command definitions, see [reference/commands.md](reference/commands.md)
|
|
183
|
+
- For elastic services, see [reference/elastic-services.md](reference/elastic-services.md)
|
|
184
|
+
- For complete examples, see [examples/](examples/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version": "0.1.0"}
|