openkbs 0.0.66 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openkbs",
3
- "version": "0.0.66",
3
+ "version": "0.0.67",
4
4
  "description": "OpenKBS - Command Line Interface",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/actions.js CHANGED
@@ -2413,6 +2413,14 @@ async function elasticStatusAction() {
2413
2413
  */
2414
2414
  async function stackAction(subCommand, args = []) {
2415
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);
2416
2424
  case 'deploy':
2417
2425
  return await elasticDeployAction();
2418
2426
  case 'destroy':
@@ -2425,10 +2433,54 @@ async function stackAction(subCommand, args = []) {
2425
2433
  console.log('Commands:');
2426
2434
  console.log(' deploy Deploy all resources from openkbs.json');
2427
2435
  console.log(' destroy Delete all resources (DANGEROUS)');
2436
+ console.log(' create Create new platform stack');
2428
2437
  console.log(' status Show status of all resources');
2429
2438
  }
2430
2439
  }
2431
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
+
2432
2484
  module.exports = {
2433
2485
  signAction,
2434
2486
  loginAction,
package/src/index.js CHANGED
@@ -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
- deploy Deploy all resources from openkbs.json
152
- destroy Delete all resources (DANGEROUS)
153
- status Show status of all resources
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
@@ -0,0 +1,70 @@
1
+ # {{APP_NAME}} Platform
2
+
3
+ OpenKBS full-stack platform with AI agents, serverless functions, and static site.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ {{APP_NAME}}/
9
+ ├── agents/ # AI agents
10
+ │ └── assistant/ # Sample assistant agent
11
+ │ ├── app/
12
+ │ │ ├── settings.json
13
+ │ │ └── instructions.txt
14
+ │ └── src/
15
+ │ ├── Events/
16
+ │ └── Frontend/
17
+ ├── functions/ # Serverless Lambda functions
18
+ │ └── api/
19
+ │ └── index.mjs # Sample API endpoint
20
+ ├── site/ # Static site for whitelabel
21
+ │ └── index.html
22
+ ├── openkbs.json # Elastic services configuration
23
+ └── README.md
24
+ ```
25
+
26
+ ## Deploy
27
+
28
+ ```bash
29
+ # Deploy elastic services (postgres, storage, pulse)
30
+ openkbs deploy
31
+
32
+ # Deploy the API function
33
+ openkbs fn push api
34
+
35
+ # Deploy static site
36
+ openkbs site push
37
+
38
+ # Deploy an agent
39
+ cd agents/assistant
40
+ openkbs push
41
+ ```
42
+
43
+ ## Elastic Services
44
+
45
+ Enabled in `openkbs.json`:
46
+
47
+ - **Postgres**: `openkbs postgres shell` to connect
48
+ - **Storage**: `openkbs storage ls` to list files
49
+ - **Pulse**: `openkbs pulse status` for WebSocket info
50
+ - **Functions**: `openkbs fn list` to see deployed functions
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ # Check stack status
56
+ openkbs stack status
57
+
58
+ # View function logs
59
+ openkbs fn logs api
60
+
61
+ # Invoke function locally
62
+ openkbs fn invoke api '{"action": "hello"}'
63
+ ```
64
+
65
+ ## URLs
66
+
67
+ After deployment:
68
+ - Site: `https://YOUR_DOMAIN/`
69
+ - API: `https://fn.openkbs.com/YOUR_KB_ID/api`
70
+ - Agent: `https://YOUR_KB_ID.apps.openkbs.com`
@@ -0,0 +1,25 @@
1
+ You are an AI assistant for {{APP_NAME}}.
2
+
3
+ ## Available Commands
4
+
5
+ <googleSearch>
6
+ {"query": "search terms"}
7
+ </googleSearch>
8
+ Search the web for information.
9
+
10
+ <setMemory>
11
+ {"itemId": "memory_key", "value": "data to remember"}
12
+ </setMemory>
13
+ Save data to memory. The itemId must start with "memory_".
14
+
15
+ <deleteItem>
16
+ {"itemId": "memory_key"}
17
+ </deleteItem>
18
+ Delete a memory item.
19
+
20
+ ## Guidelines
21
+
22
+ 1. Be helpful and concise
23
+ 2. Use commands when needed to assist the user
24
+ 3. Remember important information using setMemory
25
+ 4. Search the web when you need current information
@@ -0,0 +1,17 @@
1
+ {
2
+ "kbTitle": "{{APP_NAME}} Assistant",
3
+ "kbDescription": "AI assistant for {{APP_NAME}} platform",
4
+ "model": "anthropic/claude-sonnet-4-20250514",
5
+ "maxTokens": 16000,
6
+ "itemTypes": {
7
+ "memory": {
8
+ "attributes": [
9
+ { "attrName": "itemId", "attrType": "itemId", "encrypted": false },
10
+ { "attrName": "body", "attrType": "body", "encrypted": true }
11
+ ]
12
+ }
13
+ },
14
+ "options": {
15
+ "priorityItems": [{ "prefix": "memory_", "limit": 50 }]
16
+ }
17
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Command actions for {{APP_NAME}} Assistant
3
+ */
4
+
5
+ export const getActions = (meta, event) => [
6
+ // Google Search
7
+ [/<googleSearch>([\s\S]*?)<\/googleSearch>/s, async (match) => {
8
+ try {
9
+ const data = JSON.parse(match[1].trim());
10
+ const results = await openkbs.googleSearch(data.query);
11
+
12
+ const formatted = results?.slice(0, 5).map(({ title, link, snippet }) => ({
13
+ title, link, snippet
14
+ }));
15
+
16
+ return {
17
+ type: 'SEARCH_RESULTS',
18
+ data: formatted,
19
+ ...meta,
20
+ _meta_actions: ["REQUEST_CHAT_MODEL"]
21
+ };
22
+ } catch (e) {
23
+ return { error: e.message, ...meta, _meta_actions: ["REQUEST_CHAT_MODEL"] };
24
+ }
25
+ }],
26
+
27
+ // Set Memory
28
+ [/<setMemory>([\s\S]*?)<\/setMemory>/s, async (match) => {
29
+ try {
30
+ const data = JSON.parse(match[1].trim());
31
+
32
+ if (!data.itemId?.startsWith('memory_')) {
33
+ return {
34
+ type: "MEMORY_ERROR",
35
+ error: "itemId must start with 'memory_'",
36
+ _meta_actions: ["REQUEST_CHAT_MODEL"]
37
+ };
38
+ }
39
+
40
+ try {
41
+ await openkbs.updateItem({
42
+ itemType: 'memory',
43
+ itemId: data.itemId,
44
+ body: { value: data.value, updatedAt: new Date().toISOString() }
45
+ });
46
+ } catch (e) {
47
+ await openkbs.createItem({
48
+ itemType: 'memory',
49
+ itemId: data.itemId,
50
+ body: { value: data.value, updatedAt: new Date().toISOString() }
51
+ });
52
+ }
53
+
54
+ return {
55
+ type: "MEMORY_SAVED",
56
+ itemId: data.itemId,
57
+ ...meta,
58
+ _meta_actions: ["REQUEST_CHAT_MODEL"]
59
+ };
60
+ } catch (e) {
61
+ return { error: e.message, ...meta, _meta_actions: ["REQUEST_CHAT_MODEL"] };
62
+ }
63
+ }],
64
+
65
+ // Delete Item
66
+ [/<deleteItem>([\s\S]*?)<\/deleteItem>/s, async (match) => {
67
+ try {
68
+ const data = JSON.parse(match[1].trim());
69
+ await openkbs.deleteItem(data.itemId);
70
+
71
+ return {
72
+ type: "ITEM_DELETED",
73
+ itemId: data.itemId,
74
+ ...meta,
75
+ _meta_actions: ["REQUEST_CHAT_MODEL"]
76
+ };
77
+ } catch (e) {
78
+ return { error: e.message, ...meta, _meta_actions: ["REQUEST_CHAT_MODEL"] };
79
+ }
80
+ }]
81
+ ];
@@ -0,0 +1,41 @@
1
+ import { getActions } from './actions.js';
2
+
3
+ export const handler = async (event) => {
4
+ const response = event?.payload?.response?.content ?? event?.payload?.response;
5
+ if (!response) return { type: 'EMPTY_RESPONSE' };
6
+
7
+ const meta = {
8
+ role: 'tool',
9
+ name: 'command_executor',
10
+ msgId: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
11
+ };
12
+
13
+ const actions = getActions(meta, event);
14
+ const results = [];
15
+
16
+ for (const [pattern, handler] of actions) {
17
+ const matches = response.matchAll(new RegExp(pattern.source, pattern.flags + 'g'));
18
+ for (const match of matches) {
19
+ results.push(handler(match));
20
+ }
21
+ }
22
+
23
+ if (results.length === 0) {
24
+ return { type: 'NO_COMMANDS', _meta_actions: [] };
25
+ }
26
+
27
+ const resolved = await Promise.all(results);
28
+
29
+ if (resolved.length === 1) {
30
+ return resolved[0];
31
+ }
32
+
33
+ return {
34
+ type: 'MULTI_COMMAND_RESULT',
35
+ results: resolved,
36
+ ...meta,
37
+ _meta_actions: resolved.some(r => r._meta_actions?.includes("REQUEST_CHAT_MODEL"))
38
+ ? ["REQUEST_CHAT_MODEL"]
39
+ : []
40
+ };
41
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "dependencies": {}
3
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+
3
+ const onRenderChatMessage = async (params) => {
4
+ const { content, role } = params.messages[params.msgIndex];
5
+
6
+ // Hide tool messages
7
+ if (role === 'tool') {
8
+ return JSON.stringify({ type: 'HIDDEN_MESSAGE' });
9
+ }
10
+
11
+ return null; // Default rendering
12
+ };
13
+
14
+ const Header = ({ setRenderSettings }) => {
15
+ React.useEffect(() => {
16
+ setRenderSettings({
17
+ disableBalanceView: true
18
+ });
19
+ }, [setRenderSettings]);
20
+
21
+ return null;
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,69 @@
1
+ /**
2
+ * Example API function for {{APP_NAME}} platform
3
+ *
4
+ * Endpoint: https://fn.openkbs.com/YOUR_KB_ID/api
5
+ *
6
+ * This function has access to:
7
+ * - process.env.POSTGRES_URL (if postgres enabled)
8
+ * - process.env.KB_ID (your whitelabel kbId)
9
+ */
10
+
11
+ export const handler = async (event) => {
12
+ const body = JSON.parse(event.body || '{}');
13
+ const { action, data } = body;
14
+
15
+ // CORS headers
16
+ const headers = {
17
+ 'Content-Type': 'application/json',
18
+ 'Access-Control-Allow-Origin': '*',
19
+ 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
20
+ 'Access-Control-Allow-Headers': 'Content-Type'
21
+ };
22
+
23
+ // Handle preflight
24
+ if (event.httpMethod === 'OPTIONS') {
25
+ return { statusCode: 200, headers, body: '' };
26
+ }
27
+
28
+ try {
29
+ switch (action) {
30
+ case 'hello':
31
+ return {
32
+ statusCode: 200,
33
+ headers,
34
+ body: JSON.stringify({
35
+ message: 'Hello from {{APP_NAME}} API!',
36
+ timestamp: new Date().toISOString(),
37
+ input: data
38
+ })
39
+ };
40
+
41
+ case 'health':
42
+ return {
43
+ statusCode: 200,
44
+ headers,
45
+ body: JSON.stringify({
46
+ status: 'healthy',
47
+ kbId: process.env.KB_ID,
48
+ hasPostgres: !!process.env.POSTGRES_URL
49
+ })
50
+ };
51
+
52
+ default:
53
+ return {
54
+ statusCode: 400,
55
+ headers,
56
+ body: JSON.stringify({
57
+ error: 'Unknown action',
58
+ availableActions: ['hello', 'health']
59
+ })
60
+ };
61
+ }
62
+ } catch (error) {
63
+ return {
64
+ statusCode: 500,
65
+ headers,
66
+ body: JSON.stringify({ error: error.message })
67
+ };
68
+ }
69
+ };
@@ -0,0 +1,14 @@
1
+ {
2
+ "elastic": {
3
+ "postgres": true,
4
+ "storage": true,
5
+ "pulse": true,
6
+ "functions": {
7
+ "api": {
8
+ "runtime": "nodejs22.x",
9
+ "memory": 512,
10
+ "timeout": 30
11
+ }
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{APP_NAME}}</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body {
10
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
11
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
12
+ min-height: 100vh;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ }
17
+ .container {
18
+ background: white;
19
+ padding: 3rem;
20
+ border-radius: 16px;
21
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
22
+ text-align: center;
23
+ max-width: 500px;
24
+ }
25
+ h1 { color: #333; margin-bottom: 1rem; }
26
+ p { color: #666; margin-bottom: 2rem; line-height: 1.6; }
27
+ .btn {
28
+ display: inline-block;
29
+ padding: 12px 24px;
30
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
31
+ color: white;
32
+ text-decoration: none;
33
+ border-radius: 8px;
34
+ font-weight: 600;
35
+ transition: transform 0.2s, box-shadow 0.2s;
36
+ }
37
+ .btn:hover {
38
+ transform: translateY(-2px);
39
+ box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
40
+ }
41
+ .links { margin-top: 2rem; }
42
+ .links a { color: #667eea; margin: 0 10px; }
43
+ </style>
44
+ </head>
45
+ <body>
46
+ <div class="container">
47
+ <h1>{{APP_NAME}}</h1>
48
+ <p>Your OpenKBS platform is ready. Deploy agents, functions, and build your AI-powered application.</p>
49
+ <a href="#" class="btn" onclick="testAPI()">Test API</a>
50
+ <div class="links">
51
+ <a href="https://openkbs.com/docs">Documentation</a>
52
+ <a href="https://github.com/open-kbs/openkbs">GitHub</a>
53
+ </div>
54
+ <pre id="result" style="margin-top: 2rem; text-align: left; background: #f5f5f5; padding: 1rem; border-radius: 8px; display: none;"></pre>
55
+ </div>
56
+ <script>
57
+ async function testAPI() {
58
+ const result = document.getElementById('result');
59
+ result.style.display = 'block';
60
+ result.textContent = 'Loading...';
61
+ try {
62
+ // Replace YOUR_KB_ID with actual kbId after deployment
63
+ const response = await fetch('/api', {
64
+ method: 'POST',
65
+ headers: { 'Content-Type': 'application/json' },
66
+ body: JSON.stringify({ action: 'hello', data: { test: true } })
67
+ });
68
+ const data = await response.json();
69
+ result.textContent = JSON.stringify(data, null, 2);
70
+ } catch (e) {
71
+ result.textContent = 'Error: ' + e.message + '\n\nMake sure to deploy the API function first:\nopenkbs fn push api';
72
+ }
73
+ }
74
+ </script>
75
+ </body>
76
+ </html>
package/version.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.66",
2
+ "version": "0.0.67",
3
3
  "releaseDate": "2026-01-04",
4
- "releaseNotes": "OpenKBS CLI version 0.0.66"
4
+ "releaseNotes": "OpenKBS CLI version 0.0.67"
5
5
  }