openkbs 0.0.65 → 0.0.66
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 +41 -85
- package/src/index.js +8 -9
- 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/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
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# XML Commands Reference
|
|
2
|
+
|
|
3
|
+
Commands are XML tags with JSON content that the LLM outputs. The backend parses these and executes corresponding functions.
|
|
4
|
+
|
|
5
|
+
## Command Pattern
|
|
6
|
+
|
|
7
|
+
```xml
|
|
8
|
+
<commandName>
|
|
9
|
+
{"param": "value"}
|
|
10
|
+
</commandName>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Self-closing commands (no parameters):
|
|
14
|
+
|
|
15
|
+
```xml
|
|
16
|
+
<commandName/>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## How Commands Work
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
LLM outputs: "Let me search. <googleSearch>{"query": "..."}</googleSearch>"
|
|
23
|
+
↓
|
|
24
|
+
handler.js parses XML tags
|
|
25
|
+
Matches against regex patterns in actions.js
|
|
26
|
+
Executes the async function
|
|
27
|
+
↓
|
|
28
|
+
Result returned with _meta_actions:
|
|
29
|
+
- ["REQUEST_CHAT_MODEL"] → send back to LLM
|
|
30
|
+
- [] → display to user, stop
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Implementing Commands
|
|
34
|
+
|
|
35
|
+
### In actions.js
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
export const getActions = (meta, event) => [
|
|
39
|
+
// Standard command
|
|
40
|
+
[/<commandName>([\s\S]*?)<\/commandName>/s, async (match) => {
|
|
41
|
+
const data = JSON.parse(match[1].trim());
|
|
42
|
+
// Execute logic
|
|
43
|
+
return {
|
|
44
|
+
type: 'RESULT_TYPE',
|
|
45
|
+
data: result,
|
|
46
|
+
_meta_actions: ["REQUEST_CHAT_MODEL"]
|
|
47
|
+
};
|
|
48
|
+
}],
|
|
49
|
+
|
|
50
|
+
// Self-closing command
|
|
51
|
+
[/<commandName\s*\/>/s, async () => {
|
|
52
|
+
// Execute logic
|
|
53
|
+
return { type: 'RESULT', _meta_actions: [] };
|
|
54
|
+
}]
|
|
55
|
+
];
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### In instructions.txt
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
<commandName>
|
|
62
|
+
{
|
|
63
|
+
"param1": "description",
|
|
64
|
+
"param2": "description"
|
|
65
|
+
}
|
|
66
|
+
</commandName>
|
|
67
|
+
Description: What this command does.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Standard Commands
|
|
71
|
+
|
|
72
|
+
### googleSearch
|
|
73
|
+
|
|
74
|
+
Search the web.
|
|
75
|
+
|
|
76
|
+
```xml
|
|
77
|
+
<googleSearch>
|
|
78
|
+
{"query": "search terms"}
|
|
79
|
+
</googleSearch>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### webpageToText
|
|
83
|
+
|
|
84
|
+
Extract text from a webpage.
|
|
85
|
+
|
|
86
|
+
```xml
|
|
87
|
+
<webpageToText>
|
|
88
|
+
{"url": "https://example.com"}
|
|
89
|
+
</webpageToText>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### createAIImage
|
|
93
|
+
|
|
94
|
+
Generate an AI image.
|
|
95
|
+
|
|
96
|
+
```xml
|
|
97
|
+
<createAIImage>
|
|
98
|
+
{
|
|
99
|
+
"prompt": "image description",
|
|
100
|
+
"aspect_ratio": "16:9"
|
|
101
|
+
}
|
|
102
|
+
</createAIImage>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Aspect ratios: `1:1`, `16:9`, `9:16`, `4:3`
|
|
106
|
+
|
|
107
|
+
### setMemory
|
|
108
|
+
|
|
109
|
+
Save data to memory.
|
|
110
|
+
|
|
111
|
+
```xml
|
|
112
|
+
<setMemory>
|
|
113
|
+
{
|
|
114
|
+
"itemId": "memory_key_name",
|
|
115
|
+
"value": {"any": "data"},
|
|
116
|
+
"expirationInMinutes": 1440
|
|
117
|
+
}
|
|
118
|
+
</setMemory>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### deleteItem
|
|
122
|
+
|
|
123
|
+
Delete a memory item.
|
|
124
|
+
|
|
125
|
+
```xml
|
|
126
|
+
<deleteItem>
|
|
127
|
+
{"itemId": "memory_key_name"}
|
|
128
|
+
</deleteItem>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### cleanupMemory
|
|
132
|
+
|
|
133
|
+
Remove expired memory items.
|
|
134
|
+
|
|
135
|
+
```xml
|
|
136
|
+
<cleanupMemory/>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### scheduleTask
|
|
140
|
+
|
|
141
|
+
Schedule a future task.
|
|
142
|
+
|
|
143
|
+
```xml
|
|
144
|
+
<scheduleTask>
|
|
145
|
+
{
|
|
146
|
+
"message": "Reminder text",
|
|
147
|
+
"delay": "2h"
|
|
148
|
+
}
|
|
149
|
+
</scheduleTask>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Delay formats: `30m` (minutes), `2h` (hours), `1d` (days)
|
|
153
|
+
Or specific time: `"time": "2024-12-25 10:00"`
|
|
154
|
+
|
|
155
|
+
### getScheduledTasks
|
|
156
|
+
|
|
157
|
+
List pending scheduled tasks.
|
|
158
|
+
|
|
159
|
+
```xml
|
|
160
|
+
<getScheduledTasks/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### deleteScheduledTask
|
|
164
|
+
|
|
165
|
+
Cancel a scheduled task.
|
|
166
|
+
|
|
167
|
+
```xml
|
|
168
|
+
<deleteScheduledTask>
|
|
169
|
+
{"timestamp": 1704067200000}
|
|
170
|
+
</deleteScheduledTask>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### sendTelegram
|
|
174
|
+
|
|
175
|
+
Send a Telegram message (requires Telegram integration).
|
|
176
|
+
|
|
177
|
+
```xml
|
|
178
|
+
<sendTelegram>
|
|
179
|
+
{"text": "Hello from agent!"}
|
|
180
|
+
</sendTelegram>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### sendTelegramPhoto
|
|
184
|
+
|
|
185
|
+
Send a photo to Telegram.
|
|
186
|
+
|
|
187
|
+
```xml
|
|
188
|
+
<sendTelegramPhoto>
|
|
189
|
+
{"url": "https://example.com/image.png", "caption": "Photo caption"}
|
|
190
|
+
</sendTelegramPhoto>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### createAIVideo
|
|
194
|
+
|
|
195
|
+
Generate an AI video.
|
|
196
|
+
|
|
197
|
+
```xml
|
|
198
|
+
<createAIVideo>
|
|
199
|
+
{
|
|
200
|
+
"prompt": "cinematic sunset timelapse",
|
|
201
|
+
"model": "sora-2",
|
|
202
|
+
"seconds": 8,
|
|
203
|
+
"size": "1280x720"
|
|
204
|
+
}
|
|
205
|
+
</createAIVideo>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Models: `sora-2`, `sora-2-pro`
|
|
209
|
+
Seconds: `4`, `8`, `12`
|
|
210
|
+
Sizes: `1280x720` (landscape), `720x1280` (portrait)
|
|
211
|
+
|
|
212
|
+
### continueVideoPolling
|
|
213
|
+
|
|
214
|
+
Check video generation status.
|
|
215
|
+
|
|
216
|
+
```xml
|
|
217
|
+
<continueVideoPolling>
|
|
218
|
+
{"videoId": "video_123456"}
|
|
219
|
+
</continueVideoPolling>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### deepResearch
|
|
223
|
+
|
|
224
|
+
Start autonomous research (5-20 minutes).
|
|
225
|
+
|
|
226
|
+
```xml
|
|
227
|
+
<deepResearch>
|
|
228
|
+
{
|
|
229
|
+
"query": "AI market trends 2025",
|
|
230
|
+
"previous_interaction_id": "optional_for_followup"
|
|
231
|
+
}
|
|
232
|
+
</deepResearch>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### continueDeepResearchPolling
|
|
236
|
+
|
|
237
|
+
Check research status.
|
|
238
|
+
|
|
239
|
+
```xml
|
|
240
|
+
<continueDeepResearchPolling>
|
|
241
|
+
{
|
|
242
|
+
"interactionId": "interaction_123",
|
|
243
|
+
"prepaidCredits": 50
|
|
244
|
+
}
|
|
245
|
+
</continueDeepResearchPolling>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### viewImage
|
|
249
|
+
|
|
250
|
+
Load image into LLM vision context.
|
|
251
|
+
|
|
252
|
+
```xml
|
|
253
|
+
<viewImage>
|
|
254
|
+
{"url": "https://example.com/image.jpg"}
|
|
255
|
+
</viewImage>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### archiveItems
|
|
259
|
+
|
|
260
|
+
Move items to VectorDB long-term storage.
|
|
261
|
+
|
|
262
|
+
```xml
|
|
263
|
+
<archiveItems>
|
|
264
|
+
["memory_item1", "memory_item2"]
|
|
265
|
+
</archiveItems>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### searchArchive
|
|
269
|
+
|
|
270
|
+
Semantic search in VectorDB.
|
|
271
|
+
|
|
272
|
+
```xml
|
|
273
|
+
<searchArchive>
|
|
274
|
+
{
|
|
275
|
+
"query": "find marketing strategies",
|
|
276
|
+
"topK": 10,
|
|
277
|
+
"minScore": 0
|
|
278
|
+
}
|
|
279
|
+
</searchArchive>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### publishWebPage
|
|
283
|
+
|
|
284
|
+
Publish HTML as static page.
|
|
285
|
+
|
|
286
|
+
```xml
|
|
287
|
+
<publishWebPage>
|
|
288
|
+
<!DOCTYPE html>
|
|
289
|
+
<html>
|
|
290
|
+
<head><title>My Page</title></head>
|
|
291
|
+
<body>Content here</body>
|
|
292
|
+
</html>
|
|
293
|
+
</publishWebPage>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## MCP Commands
|
|
297
|
+
|
|
298
|
+
MCP tools use a dynamic pattern:
|
|
299
|
+
|
|
300
|
+
```xml
|
|
301
|
+
<mcp_{server}_{toolName}>
|
|
302
|
+
{"param": "value"}
|
|
303
|
+
</mcp_{server}_{toolName}>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Brave Search
|
|
307
|
+
|
|
308
|
+
```xml
|
|
309
|
+
<mcp_brave-search_brave_web_search>
|
|
310
|
+
{"query": "search terms", "count": 10}
|
|
311
|
+
</mcp_brave-search_brave_web_search>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### GitHub
|
|
315
|
+
|
|
316
|
+
```xml
|
|
317
|
+
<mcp_github_search_repositories>
|
|
318
|
+
{"query": "language:typescript stars:>1000"}
|
|
319
|
+
</mcp_github_search_repositories>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Meta Actions
|
|
323
|
+
|
|
324
|
+
Control what happens after command execution:
|
|
325
|
+
|
|
326
|
+
```javascript
|
|
327
|
+
// Send result to LLM for follow-up
|
|
328
|
+
return { data: result, _meta_actions: ["REQUEST_CHAT_MODEL"] };
|
|
329
|
+
|
|
330
|
+
// Display to user, stop conversation
|
|
331
|
+
return { data: result, _meta_actions: [] };
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Use `["REQUEST_CHAT_MODEL"]` when:
|
|
335
|
+
- LLM needs to process the result
|
|
336
|
+
- Multi-step workflows
|
|
337
|
+
- Error handling
|
|
338
|
+
|
|
339
|
+
Use `[]` when:
|
|
340
|
+
- Final output (images, confirmations)
|
|
341
|
+
- No further processing needed
|
|
342
|
+
|
|
343
|
+
## Parallel Execution
|
|
344
|
+
|
|
345
|
+
Multiple commands in a single message execute in parallel via `Promise.all`:
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
<googleSearch>{"query": "topic 1"}</googleSearch>
|
|
349
|
+
<googleSearch>{"query": "topic 2"}</googleSearch>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Both searches run simultaneously.
|
|
353
|
+
|
|
354
|
+
## Error Handling
|
|
355
|
+
|
|
356
|
+
Return errors in a consistent format:
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
try {
|
|
360
|
+
// Execute command
|
|
361
|
+
} catch (e) {
|
|
362
|
+
return {
|
|
363
|
+
type: "ERROR",
|
|
364
|
+
error: e.message,
|
|
365
|
+
_meta_actions: ["REQUEST_CHAT_MODEL"]
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
The LLM receives the error and can inform the user or retry.
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# Elastic Services Reference
|
|
2
|
+
|
|
3
|
+
OpenKBS provides managed cloud infrastructure that scales automatically.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Service | Purpose | CLI Command |
|
|
8
|
+
|---------|---------|-------------|
|
|
9
|
+
| Functions | Serverless Lambda (Node.js, Java, Python) | `openkbs fn` |
|
|
10
|
+
| Postgres | Managed PostgreSQL (Neon) | `openkbs postgres` |
|
|
11
|
+
| Storage | S3 file storage | `openkbs storage` |
|
|
12
|
+
| Pulse | Real-time WebSocket pub/sub | `openkbs pulse` |
|
|
13
|
+
|
|
14
|
+
## Configuration (openkbs.json)
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"elastic": {
|
|
19
|
+
"functions": {
|
|
20
|
+
"hello": {
|
|
21
|
+
"runtime": "nodejs22.x",
|
|
22
|
+
"memory": 512,
|
|
23
|
+
"timeout": 30
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"postgres": true,
|
|
27
|
+
"storage": true,
|
|
28
|
+
"pulse": true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Deploy/Destroy
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
openkbs deploy # Deploy all configured services
|
|
37
|
+
openkbs destroy # Remove all services
|
|
38
|
+
openkbs stack # Show current stack status
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Functions (Lambda)
|
|
44
|
+
|
|
45
|
+
Serverless functions with automatic scaling.
|
|
46
|
+
|
|
47
|
+
### Create Function
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
mkdir -p functions/hello
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Create `functions/hello/index.mjs`:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
export const handler = async (event) => {
|
|
57
|
+
const body = JSON.parse(event.body || '{}');
|
|
58
|
+
return {
|
|
59
|
+
statusCode: 200,
|
|
60
|
+
body: JSON.stringify({ message: 'Hello', input: body })
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### CLI Commands
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
openkbs fn list # List all functions
|
|
69
|
+
openkbs fn push hello --region us-east-1 # Deploy function
|
|
70
|
+
openkbs fn delete hello # Delete function
|
|
71
|
+
openkbs fn logs hello # View logs
|
|
72
|
+
openkbs fn env hello # View env vars
|
|
73
|
+
openkbs fn env hello API_KEY=secret # Set env var
|
|
74
|
+
openkbs fn invoke hello '{"test": true}' # Invoke function
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Supported Runtimes
|
|
78
|
+
|
|
79
|
+
- `nodejs22.x`, `nodejs20.x`, `nodejs18.x`
|
|
80
|
+
- `python3.12`, `python3.11`
|
|
81
|
+
- `java21`, `java17`
|
|
82
|
+
|
|
83
|
+
### Access from Agent
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// In actions.js
|
|
87
|
+
const response = await fetch('https://fn.openkbs.com/YOUR_KB_ID/hello', {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
body: JSON.stringify({ data: 'value' })
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Postgres (Neon)
|
|
96
|
+
|
|
97
|
+
Managed PostgreSQL database.
|
|
98
|
+
|
|
99
|
+
### CLI Commands
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
openkbs postgres shell # Connect to psql
|
|
103
|
+
openkbs postgres connection-string # Get connection URL
|
|
104
|
+
openkbs postgres status # Show database info
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Access from Agent
|
|
108
|
+
|
|
109
|
+
Connection string is available as `POSTGRES_URL` environment variable:
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// In onRequest.js or actions.js
|
|
113
|
+
import pg from 'pg';
|
|
114
|
+
const { Pool } = pg;
|
|
115
|
+
|
|
116
|
+
const pool = new Pool({
|
|
117
|
+
connectionString: process.env.POSTGRES_URL,
|
|
118
|
+
ssl: { rejectUnauthorized: false }
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Add Dependency
|
|
125
|
+
|
|
126
|
+
In `src/Events/onRequest.json`:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"dependencies": {
|
|
131
|
+
"pg": "^8.13.1"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Storage (S3)
|
|
139
|
+
|
|
140
|
+
File storage with presigned URLs.
|
|
141
|
+
|
|
142
|
+
### CLI Commands
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
openkbs storage list # List buckets
|
|
146
|
+
openkbs storage list BUCKET_NAME # List files in bucket
|
|
147
|
+
openkbs storage upload FILE # Upload file
|
|
148
|
+
openkbs storage download FILE # Download file
|
|
149
|
+
openkbs storage delete FILE # Delete file
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Access from Agent
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
// Upload file
|
|
156
|
+
const uploaded = await openkbs.uploadImage(
|
|
157
|
+
base64Content,
|
|
158
|
+
'image.png',
|
|
159
|
+
'image/png'
|
|
160
|
+
);
|
|
161
|
+
console.log(uploaded.url); // Public URL
|
|
162
|
+
|
|
163
|
+
// Get presigned URL for upload
|
|
164
|
+
const presigned = await openkbs.kb({
|
|
165
|
+
action: 'getPresignedUploadUrl',
|
|
166
|
+
filename: 'document.pdf',
|
|
167
|
+
contentType: 'application/pdf'
|
|
168
|
+
});
|
|
169
|
+
// Returns: { uploadUrl, publicUrl }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Pulse (WebSocket)
|
|
175
|
+
|
|
176
|
+
Real-time messaging and pub/sub.
|
|
177
|
+
|
|
178
|
+
### CLI Commands
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
openkbs pulse status # Show Pulse status
|
|
182
|
+
openkbs pulse channels # List channels
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Access from Agent
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
// Publish message
|
|
189
|
+
await openkbs.pulse.publish('channel-name', {
|
|
190
|
+
type: 'notification',
|
|
191
|
+
data: { message: 'Hello subscribers!' }
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Subscribe (frontend)
|
|
195
|
+
const ws = new WebSocket(`wss://pulse.openkbs.com/${kbId}/channel-name`);
|
|
196
|
+
ws.onmessage = (event) => {
|
|
197
|
+
const data = JSON.parse(event.data);
|
|
198
|
+
console.log('Received:', data);
|
|
199
|
+
};
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Use Cases
|
|
203
|
+
|
|
204
|
+
- Real-time notifications
|
|
205
|
+
- Live updates to frontend
|
|
206
|
+
- Multi-user collaboration
|
|
207
|
+
- Event streaming
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Full-Stack Example
|
|
212
|
+
|
|
213
|
+
Complete Node.js application with all services:
|
|
214
|
+
|
|
215
|
+
### openkbs.json
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"elastic": {
|
|
220
|
+
"functions": {
|
|
221
|
+
"api": { "runtime": "nodejs22.x", "memory": 512 }
|
|
222
|
+
},
|
|
223
|
+
"postgres": true,
|
|
224
|
+
"storage": true,
|
|
225
|
+
"pulse": true
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### functions/api/index.mjs
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
import pg from 'pg';
|
|
234
|
+
const { Pool } = pg;
|
|
235
|
+
|
|
236
|
+
const pool = new Pool({
|
|
237
|
+
connectionString: process.env.POSTGRES_URL,
|
|
238
|
+
ssl: { rejectUnauthorized: false }
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
export const handler = async (event) => {
|
|
242
|
+
const { action, data } = JSON.parse(event.body || '{}');
|
|
243
|
+
|
|
244
|
+
switch (action) {
|
|
245
|
+
case 'list':
|
|
246
|
+
const result = await pool.query('SELECT * FROM items');
|
|
247
|
+
return { statusCode: 200, body: JSON.stringify(result.rows) };
|
|
248
|
+
|
|
249
|
+
case 'create':
|
|
250
|
+
await pool.query('INSERT INTO items (name) VALUES ($1)', [data.name]);
|
|
251
|
+
return { statusCode: 201, body: JSON.stringify({ success: true }) };
|
|
252
|
+
|
|
253
|
+
default:
|
|
254
|
+
return { statusCode: 400, body: JSON.stringify({ error: 'Unknown action' }) };
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Deploy
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
openkbs deploy
|
|
263
|
+
openkbs fn push api
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Java API Example
|
|
269
|
+
|
|
270
|
+
### functions/api/pom.xml
|
|
271
|
+
|
|
272
|
+
```xml
|
|
273
|
+
<dependencies>
|
|
274
|
+
<dependency>
|
|
275
|
+
<groupId>com.amazonaws</groupId>
|
|
276
|
+
<artifactId>aws-lambda-java-core</artifactId>
|
|
277
|
+
<version>1.2.3</version>
|
|
278
|
+
</dependency>
|
|
279
|
+
<dependency>
|
|
280
|
+
<groupId>org.postgresql</groupId>
|
|
281
|
+
<artifactId>postgresql</artifactId>
|
|
282
|
+
<version>42.7.4</version>
|
|
283
|
+
</dependency>
|
|
284
|
+
</dependencies>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Deploy Java Function
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
cd functions/api
|
|
291
|
+
mvn package
|
|
292
|
+
openkbs fn push api --runtime java21
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Python API Example
|
|
298
|
+
|
|
299
|
+
### functions/api/handler.py
|
|
300
|
+
|
|
301
|
+
```python
|
|
302
|
+
import json
|
|
303
|
+
import psycopg2
|
|
304
|
+
import os
|
|
305
|
+
|
|
306
|
+
def handler(event, context):
|
|
307
|
+
conn = psycopg2.connect(os.environ['POSTGRES_URL'])
|
|
308
|
+
cur = conn.cursor()
|
|
309
|
+
cur.execute("SELECT * FROM items")
|
|
310
|
+
rows = cur.fetchall()
|
|
311
|
+
return {
|
|
312
|
+
'statusCode': 200,
|
|
313
|
+
'body': json.dumps(rows)
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### requirements.txt
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
psycopg2-binary
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Deploy
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
openkbs fn push api --runtime python3.12
|
|
327
|
+
```
|