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 +1 -1
- package/src/actions.js +52 -0
- package/src/index.js +8 -6
- 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 +2 -2
package/package.json
CHANGED
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
|
-
|
|
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
|
|
@@ -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,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,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,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