@ebowwa/stack 0.1.2 → 0.1.3
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/dist/index.js +65 -1
- package/package.json +1 -1
- package/src/index.ts +83 -7
package/dist/index.js
CHANGED
|
@@ -57619,7 +57619,71 @@ Prompt: ${prompt.slice(0, 100)}...`;
|
|
|
57619
57619
|
if (!this.config.api)
|
|
57620
57620
|
return;
|
|
57621
57621
|
const port = this.config.api.port ?? 8911;
|
|
57622
|
-
|
|
57622
|
+
const host = this.config.api.host ?? "0.0.0.0";
|
|
57623
|
+
const server = Bun.serve({
|
|
57624
|
+
port,
|
|
57625
|
+
host,
|
|
57626
|
+
fetch: async (req) => {
|
|
57627
|
+
const url = new URL(req.url);
|
|
57628
|
+
const path = url.pathname;
|
|
57629
|
+
const corsHeaders = {
|
|
57630
|
+
"Access-Control-Allow-Origin": "*",
|
|
57631
|
+
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
57632
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
57633
|
+
};
|
|
57634
|
+
if (req.method === "OPTIONS") {
|
|
57635
|
+
return new Response(null, { headers: corsHeaders });
|
|
57636
|
+
}
|
|
57637
|
+
try {
|
|
57638
|
+
if (path === "/api/status" && req.method === "GET") {
|
|
57639
|
+
return Response.json(this.getStatusJSON(), { headers: corsHeaders });
|
|
57640
|
+
}
|
|
57641
|
+
if (path === "/api/ralph-loops" && req.method === "GET") {
|
|
57642
|
+
return Response.json(this.listRalphLoopsJSON(), { headers: corsHeaders });
|
|
57643
|
+
}
|
|
57644
|
+
if (path === "/api/ralph-loops" && req.method === "POST") {
|
|
57645
|
+
const body = await req.json();
|
|
57646
|
+
const prompt = body.prompt;
|
|
57647
|
+
if (!prompt) {
|
|
57648
|
+
return Response.json({ error: "Missing prompt" }, { status: 400, headers: corsHeaders });
|
|
57649
|
+
}
|
|
57650
|
+
const result = await this.startRalphLoop(prompt);
|
|
57651
|
+
return Response.json({ message: result }, { headers: corsHeaders });
|
|
57652
|
+
}
|
|
57653
|
+
const match = path.match(/^\/api\/ralph-loops\/(.+)$/);
|
|
57654
|
+
if (match && req.method === "DELETE") {
|
|
57655
|
+
const result = await this.stopRalphLoop(match[1]);
|
|
57656
|
+
return Response.json({ message: result }, { headers: corsHeaders });
|
|
57657
|
+
}
|
|
57658
|
+
if (path === "/health") {
|
|
57659
|
+
return Response.json({ status: "ok" }, { headers: corsHeaders });
|
|
57660
|
+
}
|
|
57661
|
+
return Response.json({ error: "Not found" }, { status: 404, headers: corsHeaders });
|
|
57662
|
+
} catch (error) {
|
|
57663
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
57664
|
+
return Response.json({ error: errorMsg }, { status: 500, headers: corsHeaders });
|
|
57665
|
+
}
|
|
57666
|
+
}
|
|
57667
|
+
});
|
|
57668
|
+
console.log(`[Stack] API running on http://${host}:${port}`);
|
|
57669
|
+
}
|
|
57670
|
+
getStatusJSON() {
|
|
57671
|
+
return {
|
|
57672
|
+
node: this.config.node.name,
|
|
57673
|
+
channels: {
|
|
57674
|
+
ssh: this.state.channels.ssh,
|
|
57675
|
+
telegram: this.state.channels.telegram
|
|
57676
|
+
},
|
|
57677
|
+
api: {
|
|
57678
|
+
enabled: this.state.api.enabled,
|
|
57679
|
+
port: this.state.api.port
|
|
57680
|
+
},
|
|
57681
|
+
ralphLoops: this.state.ralphLoops.size,
|
|
57682
|
+
uptime: Math.floor((Date.now() - this.state.started.getTime()) / 1000)
|
|
57683
|
+
};
|
|
57684
|
+
}
|
|
57685
|
+
listRalphLoopsJSON() {
|
|
57686
|
+
return Array.from(this.state.ralphLoops.values());
|
|
57623
57687
|
}
|
|
57624
57688
|
async start() {
|
|
57625
57689
|
console.log(`[Stack] Starting ${this.config.node.name}...`);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -367,20 +367,96 @@ export class Stack {
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
// ============================================================
|
|
370
|
-
// HTTP API
|
|
370
|
+
// HTTP API
|
|
371
371
|
// ============================================================
|
|
372
372
|
|
|
373
373
|
private startAPI(): void {
|
|
374
374
|
if (!this.config.api) return;
|
|
375
375
|
|
|
376
376
|
const port = this.config.api.port ?? 8911;
|
|
377
|
-
|
|
377
|
+
const host = this.config.api.host ?? "0.0.0.0";
|
|
378
|
+
|
|
379
|
+
const server = Bun.serve({
|
|
380
|
+
port,
|
|
381
|
+
host,
|
|
382
|
+
fetch: async (req) => {
|
|
383
|
+
const url = new URL(req.url);
|
|
384
|
+
const path = url.pathname;
|
|
385
|
+
|
|
386
|
+
// CORS headers
|
|
387
|
+
const corsHeaders = {
|
|
388
|
+
"Access-Control-Allow-Origin": "*",
|
|
389
|
+
"Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS",
|
|
390
|
+
"Access-Control-Allow-Headers": "Content-Type",
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
if (req.method === "OPTIONS") {
|
|
394
|
+
return new Response(null, { headers: corsHeaders });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
// GET /api/status
|
|
399
|
+
if (path === "/api/status" && req.method === "GET") {
|
|
400
|
+
return Response.json(this.getStatusJSON(), { headers: corsHeaders });
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// GET /api/ralph-loops
|
|
404
|
+
if (path === "/api/ralph-loops" && req.method === "GET") {
|
|
405
|
+
return Response.json(this.listRalphLoopsJSON(), { headers: corsHeaders });
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// POST /api/ralph-loops
|
|
409
|
+
if (path === "/api/ralph-loops" && req.method === "POST") {
|
|
410
|
+
const body = await req.json();
|
|
411
|
+
const prompt = body.prompt;
|
|
412
|
+
if (!prompt) {
|
|
413
|
+
return Response.json({ error: "Missing prompt" }, { status: 400, headers: corsHeaders });
|
|
414
|
+
}
|
|
415
|
+
const result = await this.startRalphLoop(prompt);
|
|
416
|
+
return Response.json({ message: result }, { headers: corsHeaders });
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// DELETE /api/ralph-loops/:id
|
|
420
|
+
const match = path.match(/^\/api\/ralph-loops\/(.+)$/);
|
|
421
|
+
if (match && req.method === "DELETE") {
|
|
422
|
+
const result = await this.stopRalphLoop(match[1]);
|
|
423
|
+
return Response.json({ message: result }, { headers: corsHeaders });
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// GET /health
|
|
427
|
+
if (path === "/health") {
|
|
428
|
+
return Response.json({ status: "ok" }, { headers: corsHeaders });
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return Response.json({ error: "Not found" }, { status: 404, headers: corsHeaders });
|
|
432
|
+
} catch (error) {
|
|
433
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
434
|
+
return Response.json({ error: errorMsg }, { status: 500, headers: corsHeaders });
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
console.log(`[Stack] API running on http://${host}:${port}`);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private getStatusJSON(): object {
|
|
443
|
+
return {
|
|
444
|
+
node: this.config.node.name,
|
|
445
|
+
channels: {
|
|
446
|
+
ssh: this.state.channels.ssh,
|
|
447
|
+
telegram: this.state.channels.telegram,
|
|
448
|
+
},
|
|
449
|
+
api: {
|
|
450
|
+
enabled: this.state.api.enabled,
|
|
451
|
+
port: this.state.api.port,
|
|
452
|
+
},
|
|
453
|
+
ralphLoops: this.state.ralphLoops.size,
|
|
454
|
+
uptime: Math.floor((Date.now() - this.state.started.getTime()) / 1000),
|
|
455
|
+
};
|
|
456
|
+
}
|
|
378
457
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
// GET /api/ralph-loops - List Ralph loops
|
|
382
|
-
// POST /api/ralph-loops - Start Ralph loop
|
|
383
|
-
// DELETE /api/ralph-loops/:id - Stop Ralph loop
|
|
458
|
+
private listRalphLoopsJSON(): object[] {
|
|
459
|
+
return Array.from(this.state.ralphLoops.values());
|
|
384
460
|
}
|
|
385
461
|
|
|
386
462
|
// ============================================================
|