openkbs 0.0.92 → 0.0.93
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
package/src/actions.js
CHANGED
|
@@ -1135,6 +1135,8 @@ async function fnAction(subCommand, args = []) {
|
|
|
1135
1135
|
return await fnEnvAction(kbToken, args[0], args.slice(1));
|
|
1136
1136
|
case 'invoke':
|
|
1137
1137
|
return await fnInvokeAction(kbToken, args[0], args.slice(1));
|
|
1138
|
+
case 'schedule':
|
|
1139
|
+
return await fnScheduleAction(kbToken, args[0], args.slice(1));
|
|
1138
1140
|
default:
|
|
1139
1141
|
console.log('Usage: openkbs fn <command> [options]');
|
|
1140
1142
|
console.log('');
|
|
@@ -1145,11 +1147,14 @@ async function fnAction(subCommand, args = []) {
|
|
|
1145
1147
|
console.log(' logs <name> View function logs');
|
|
1146
1148
|
console.log(' env <name> [KEY=value] View or set environment variables');
|
|
1147
1149
|
console.log(' invoke <name> [payload] Invoke a function');
|
|
1150
|
+
console.log(' schedule <name> [expr] View/set/enable/disable/remove schedule');
|
|
1148
1151
|
console.log('');
|
|
1149
1152
|
console.log('Options for push:');
|
|
1150
1153
|
console.log(' --region <region> Region (us-east-1, eu-central-1, ap-southeast-1)');
|
|
1151
1154
|
console.log(' --memory <mb> Memory size (128-3008 MB)');
|
|
1152
1155
|
console.log(' --timeout <seconds> Timeout (1-900 seconds)');
|
|
1156
|
+
console.log(' --schedule <expr> Schedule expression (e.g. "rate(1 hour)")');
|
|
1157
|
+
console.log(' --http-access Enable HTTP access for scheduled functions');
|
|
1153
1158
|
}
|
|
1154
1159
|
}
|
|
1155
1160
|
|
|
@@ -1182,8 +1187,9 @@ async function fnListAction(kbToken) {
|
|
|
1182
1187
|
functions.forEach(f => {
|
|
1183
1188
|
const name = f.functionName.padEnd(maxNameLen);
|
|
1184
1189
|
const region = f.region || 'unknown';
|
|
1185
|
-
const url = f.customUrl || f.functionUrl || 'N/A';
|
|
1186
|
-
|
|
1190
|
+
const url = f.customUrl || f.functionUrl || (f.schedule ? '(scheduled)' : 'N/A');
|
|
1191
|
+
const scheduleInfo = f.schedule ? ` [${f.schedule}]` : '';
|
|
1192
|
+
console.log(` ${name} ${region} ${url}${scheduleInfo}`);
|
|
1187
1193
|
});
|
|
1188
1194
|
} catch (error) {
|
|
1189
1195
|
console.red('Error listing functions:', error.message);
|
|
@@ -1201,6 +1207,8 @@ async function fnDeployAction(kbToken, functionName, args) {
|
|
|
1201
1207
|
let timeout = 30;
|
|
1202
1208
|
let runtime = null; // null = use default (nodejs24.x)
|
|
1203
1209
|
let handler = null; // null = use default (index.handler)
|
|
1210
|
+
let schedule = null;
|
|
1211
|
+
let httpAccess = null;
|
|
1204
1212
|
|
|
1205
1213
|
for (let i = 0; i < args.length; i++) {
|
|
1206
1214
|
if (args[i] === '--region' && args[i + 1]) {
|
|
@@ -1213,6 +1221,10 @@ async function fnDeployAction(kbToken, functionName, args) {
|
|
|
1213
1221
|
runtime = args[++i];
|
|
1214
1222
|
} else if (args[i] === '--handler' && args[i + 1]) {
|
|
1215
1223
|
handler = args[++i];
|
|
1224
|
+
} else if (args[i] === '--schedule' && args[i + 1]) {
|
|
1225
|
+
schedule = args[++i];
|
|
1226
|
+
} else if (args[i] === '--http-access') {
|
|
1227
|
+
httpAccess = true;
|
|
1216
1228
|
}
|
|
1217
1229
|
}
|
|
1218
1230
|
|
|
@@ -1273,12 +1285,14 @@ async function fnDeployAction(kbToken, functionName, args) {
|
|
|
1273
1285
|
if (existingFunc) {
|
|
1274
1286
|
// Update existing function
|
|
1275
1287
|
console.log('Updating existing function...');
|
|
1276
|
-
|
|
1288
|
+
const updateParams = {
|
|
1277
1289
|
token: kbToken,
|
|
1278
1290
|
action: 'updateElasticFunction',
|
|
1279
1291
|
functionName,
|
|
1280
1292
|
code
|
|
1281
|
-
}
|
|
1293
|
+
};
|
|
1294
|
+
if (schedule) updateParams.schedule = schedule;
|
|
1295
|
+
response = await makePostRequest(KB_API_URL, updateParams);
|
|
1282
1296
|
} else {
|
|
1283
1297
|
// Create new function
|
|
1284
1298
|
console.log('Creating new function...');
|
|
@@ -1293,6 +1307,8 @@ async function fnDeployAction(kbToken, functionName, args) {
|
|
|
1293
1307
|
};
|
|
1294
1308
|
if (runtime) createParams.runtime = runtime;
|
|
1295
1309
|
if (handler) createParams.handler = handler;
|
|
1310
|
+
if (schedule) createParams.schedule = schedule;
|
|
1311
|
+
if (httpAccess !== null) createParams.httpAccess = httpAccess;
|
|
1296
1312
|
response = await makePostRequest(KB_API_URL, createParams);
|
|
1297
1313
|
}
|
|
1298
1314
|
|
|
@@ -1307,6 +1323,9 @@ async function fnDeployAction(kbToken, functionName, args) {
|
|
|
1307
1323
|
if (response.customUrl) {
|
|
1308
1324
|
console.log(`Custom URL: ${response.customUrl}`);
|
|
1309
1325
|
}
|
|
1326
|
+
if (response.schedule) {
|
|
1327
|
+
console.log(`Schedule: ${response.schedule}`);
|
|
1328
|
+
}
|
|
1310
1329
|
} catch (error) {
|
|
1311
1330
|
console.red('Deploy failed:', error.message);
|
|
1312
1331
|
}
|
|
@@ -1336,6 +1355,71 @@ async function fnDeleteAction(kbToken, functionName) {
|
|
|
1336
1355
|
}
|
|
1337
1356
|
}
|
|
1338
1357
|
|
|
1358
|
+
async function fnScheduleAction(kbToken, functionName, args) {
|
|
1359
|
+
if (!functionName) {
|
|
1360
|
+
return console.red('Function name required. Usage: openkbs fn schedule <name> [expression|enable|disable|remove]');
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
const subCommand = args[0];
|
|
1364
|
+
|
|
1365
|
+
try {
|
|
1366
|
+
if (!subCommand) {
|
|
1367
|
+
// Show current schedule
|
|
1368
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1369
|
+
token: kbToken,
|
|
1370
|
+
action: 'getElasticFunction',
|
|
1371
|
+
functionName
|
|
1372
|
+
});
|
|
1373
|
+
if (response.error) return console.red('Error:', response.error);
|
|
1374
|
+
if (response.schedule) {
|
|
1375
|
+
console.log(`Schedule: ${response.schedule}`);
|
|
1376
|
+
console.log(`Name: ${response.scheduleName || 'N/A'}`);
|
|
1377
|
+
} else {
|
|
1378
|
+
console.log(`No schedule set for '${functionName}'.`);
|
|
1379
|
+
}
|
|
1380
|
+
} else if (subCommand === 'enable') {
|
|
1381
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1382
|
+
token: kbToken,
|
|
1383
|
+
action: 'updateElasticFunctionSchedule',
|
|
1384
|
+
functionName,
|
|
1385
|
+
enabled: true
|
|
1386
|
+
});
|
|
1387
|
+
if (response.error) return console.red('Error:', response.error);
|
|
1388
|
+
console.green(`Schedule for '${functionName}' enabled.`);
|
|
1389
|
+
} else if (subCommand === 'disable') {
|
|
1390
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1391
|
+
token: kbToken,
|
|
1392
|
+
action: 'updateElasticFunctionSchedule',
|
|
1393
|
+
functionName,
|
|
1394
|
+
enabled: false
|
|
1395
|
+
});
|
|
1396
|
+
if (response.error) return console.red('Error:', response.error);
|
|
1397
|
+
console.green(`Schedule for '${functionName}' disabled.`);
|
|
1398
|
+
} else if (subCommand === 'remove') {
|
|
1399
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1400
|
+
token: kbToken,
|
|
1401
|
+
action: 'updateElasticFunctionSchedule',
|
|
1402
|
+
functionName,
|
|
1403
|
+
schedule: null
|
|
1404
|
+
});
|
|
1405
|
+
if (response.error) return console.red('Error:', response.error);
|
|
1406
|
+
console.green(`Schedule for '${functionName}' removed.`);
|
|
1407
|
+
} else {
|
|
1408
|
+
// Set schedule expression
|
|
1409
|
+
const response = await makePostRequest(KB_API_URL, {
|
|
1410
|
+
token: kbToken,
|
|
1411
|
+
action: 'updateElasticFunctionSchedule',
|
|
1412
|
+
functionName,
|
|
1413
|
+
schedule: subCommand
|
|
1414
|
+
});
|
|
1415
|
+
if (response.error) return console.red('Error:', response.error);
|
|
1416
|
+
console.green(`Schedule for '${functionName}' set to: ${subCommand}`);
|
|
1417
|
+
}
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
console.red('Schedule operation failed:', error.message);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1339
1423
|
async function fnLogsAction(kbToken, functionName, args) {
|
|
1340
1424
|
if (!functionName) {
|
|
1341
1425
|
return console.red('Function name required. Usage: openkbs fn logs <name>');
|
|
@@ -2477,6 +2561,8 @@ async function elasticDeployAction() {
|
|
|
2477
2561
|
if (fnConfig.timeout) args.push('--timeout', String(fnConfig.timeout));
|
|
2478
2562
|
if (fnConfig.runtime) args.push('--runtime', fnConfig.runtime);
|
|
2479
2563
|
if (fnConfig.handler) args.push('--handler', fnConfig.handler);
|
|
2564
|
+
if (fnConfig.schedule) args.push('--schedule', fnConfig.schedule);
|
|
2565
|
+
if (fnConfig.httpAccess) args.push('--http-access');
|
|
2480
2566
|
|
|
2481
2567
|
console.log(` Deploying ${name}...`);
|
|
2482
2568
|
await fnDeployAction(kbToken, name, args);
|
|
@@ -100,7 +100,8 @@ my-platform/
|
|
|
100
100
|
},
|
|
101
101
|
"pulse": true,
|
|
102
102
|
"functions": [
|
|
103
|
-
{ "name": "api", "runtime": "nodejs24.x", "memory": 512, "timeout": 30 }
|
|
103
|
+
{ "name": "api", "runtime": "nodejs24.x", "memory": 512, "timeout": 30 },
|
|
104
|
+
{ "name": "cleanup", "schedule": "rate(1 hour)", "timeout": 900 }
|
|
104
105
|
],
|
|
105
106
|
"site": "./site"
|
|
106
107
|
}
|
|
@@ -127,7 +128,10 @@ openkbs destroy # Remove all resources (DANGEROUS)
|
|
|
127
128
|
```bash
|
|
128
129
|
openkbs fn list # List Lambda functions
|
|
129
130
|
openkbs fn push api # Deploy function
|
|
131
|
+
openkbs fn push cleanup --schedule "rate(1 hour)" # Deploy with schedule
|
|
130
132
|
openkbs fn logs api # View function logs
|
|
133
|
+
openkbs fn schedule cleanup # View schedule
|
|
134
|
+
openkbs fn schedule cleanup disable # Disable schedule
|
|
131
135
|
openkbs postgres shell # Connect to Postgres
|
|
132
136
|
openkbs storage ls # List S3 objects
|
|
133
137
|
openkbs pulse status # WebSocket status
|
|
@@ -246,6 +250,42 @@ Configure in `settings.json`:
|
|
|
246
250
|
|
|
247
251
|
Priority items are auto-injected into LLM context.
|
|
248
252
|
|
|
253
|
+
## Spec Mode
|
|
254
|
+
|
|
255
|
+
When the user is in **Spec Mode**, you act as a Product Manager helping define specifications.
|
|
256
|
+
|
|
257
|
+
### Workflow
|
|
258
|
+
1. Discuss requirements with the user — ask clarifying questions
|
|
259
|
+
2. Explore the codebase to understand the current architecture
|
|
260
|
+
3. Write the specification as a `.md` file in the `spec/` folder
|
|
261
|
+
4. Call `ExitPlanMode` to present the specification for user approval
|
|
262
|
+
5. If rejected or changes requested, revise and re-submit
|
|
263
|
+
|
|
264
|
+
### Spec File Format
|
|
265
|
+
Create files in `spec/` folder with descriptive names (e.g., `spec/user-authentication.md`):
|
|
266
|
+
|
|
267
|
+
- **Goals** — What this feature achieves
|
|
268
|
+
- **Requirements** — Functional requirements (numbered list)
|
|
269
|
+
- **User Stories** — As a [role], I want [action], so that [benefit]
|
|
270
|
+
- **Acceptance Criteria** — Testable conditions for completeness
|
|
271
|
+
- **Constraints** — Technical or business limitations
|
|
272
|
+
- **Out of Scope** — What is explicitly NOT included
|
|
273
|
+
|
|
274
|
+
### Markdown Features
|
|
275
|
+
The spec viewer supports GitHub Flavored Markdown (GFM). Use these for well-structured specs:
|
|
276
|
+
- **Tables** — for requirement matrices, field definitions, API specs
|
|
277
|
+
- **Task lists** — `- [ ]` / `- [x]` for checklists
|
|
278
|
+
- **Strikethrough** — `~~text~~` for deprecated items
|
|
279
|
+
- **Autolinks** — URLs are automatically linked
|
|
280
|
+
- **Headings, lists, bold, italic, code blocks** — all standard markdown
|
|
281
|
+
|
|
282
|
+
### Rules
|
|
283
|
+
- Do NOT write implementation code in spec mode
|
|
284
|
+
- Focus on WHAT to build, not HOW
|
|
285
|
+
- Keep specs concise and actionable
|
|
286
|
+
- One spec file per feature/topic
|
|
287
|
+
- Use tables for structured data (requirements, fields, APIs)
|
|
288
|
+
|
|
249
289
|
## Additional Resources
|
|
250
290
|
|
|
251
291
|
### Reference Documentation
|
|
@@ -23,7 +23,9 @@ OpenKBS provides managed cloud infrastructure that scales automatically.
|
|
|
23
23
|
},
|
|
24
24
|
"pulse": true,
|
|
25
25
|
"functions": [
|
|
26
|
-
{ "name": "
|
|
26
|
+
{ "name": "api", "runtime": "nodejs24.x", "memory": 512, "timeout": 30 },
|
|
27
|
+
{ "name": "cleanup", "runtime": "nodejs24.x", "memory": 256, "timeout": 900, "schedule": "rate(1 hour)" },
|
|
28
|
+
{ "name": "reports", "runtime": "nodejs24.x", "memory": 512, "timeout": 300, "schedule": "cron(0 12 * * ? *)" }
|
|
27
29
|
],
|
|
28
30
|
"site": "./site"
|
|
29
31
|
}
|
|
@@ -66,11 +68,62 @@ export const handler = async (event) => {
|
|
|
66
68
|
```bash
|
|
67
69
|
openkbs fn list # List all functions
|
|
68
70
|
openkbs fn push hello --region us-east-1 # Deploy function
|
|
71
|
+
openkbs fn push hello --schedule "rate(1 hour)" # Deploy with schedule
|
|
72
|
+
openkbs fn push hello --schedule "rate(1 hour)" --http-access # Schedule + HTTP
|
|
69
73
|
openkbs fn delete hello # Delete function
|
|
70
74
|
openkbs fn logs hello # View logs
|
|
71
75
|
openkbs fn env hello # View env vars
|
|
72
76
|
openkbs fn env hello API_KEY=secret # Set env var
|
|
73
77
|
openkbs fn invoke hello '{"test": true}' # Invoke function
|
|
78
|
+
openkbs fn schedule hello # View current schedule
|
|
79
|
+
openkbs fn schedule hello "rate(5 minutes)" # Set schedule
|
|
80
|
+
openkbs fn schedule hello enable # Enable schedule
|
|
81
|
+
openkbs fn schedule hello disable # Disable schedule
|
|
82
|
+
openkbs fn schedule hello remove # Remove schedule
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Scheduled Functions
|
|
86
|
+
|
|
87
|
+
Functions with a `schedule` field are invoked automatically by EventBridge Scheduler. By default, scheduled functions do **not** get HTTP access (no Function URL / CloudFront). Add `"httpAccess": true` to enable both.
|
|
88
|
+
|
|
89
|
+
**Schedule expressions:**
|
|
90
|
+
- `rate(1 hour)`, `rate(5 minutes)`, `rate(1 day)`
|
|
91
|
+
- `cron(0 12 * * ? *)` — daily at 12:00 UTC
|
|
92
|
+
- `cron(0/15 * * * ? *)` — every 15 minutes
|
|
93
|
+
|
|
94
|
+
**openkbs.json example:**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"functions": [
|
|
98
|
+
{ "name": "api", "runtime": "nodejs24.x", "memory": 512, "timeout": 30 },
|
|
99
|
+
{ "name": "cleanup", "schedule": "rate(1 hour)", "timeout": 900 },
|
|
100
|
+
{ "name": "reports", "schedule": "cron(0 12 * * ? *)", "httpAccess": true }
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Event payload** received by the Lambda handler:
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"source": "openkbs.scheduler",
|
|
109
|
+
"kbId": "abc123",
|
|
110
|
+
"functionName": "cleanup",
|
|
111
|
+
"scheduleExpression": "rate(1 hour)"
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Handler example:**
|
|
116
|
+
```javascript
|
|
117
|
+
export const handler = async (event) => {
|
|
118
|
+
if (event.source === 'openkbs.scheduler') {
|
|
119
|
+
// Invoked by schedule
|
|
120
|
+
console.log(`Running scheduled task: ${event.functionName}`);
|
|
121
|
+
// ... do work ...
|
|
122
|
+
return { statusCode: 200, body: 'OK' };
|
|
123
|
+
}
|
|
124
|
+
// Invoked via HTTP (if httpAccess is enabled)
|
|
125
|
+
return { statusCode: 200, body: JSON.stringify({ message: 'Hello' }) };
|
|
126
|
+
};
|
|
74
127
|
```
|
|
75
128
|
|
|
76
129
|
### Supported Runtimes
|
package/version.json
CHANGED