Initial commit: kage-research project files

This commit is contained in:
shokollm
2026-04-09 00:39:52 +00:00
commit 71fc8b4495
19 changed files with 5303 additions and 0 deletions

253
level4.ts Normal file
View File

@@ -0,0 +1,253 @@
/**
* Level 4: Hermes Connection
*
* Integration with Hermes gateway (Telegram)
*
* Flow:
* Telegram → Hermes → This Server → Queue → Worker → Response → Hermes → Telegram
*
* This creates a simple HTTP server that Hermes can call via webhook or tool.
*/
import { Agent, type AgentTool, type AgentMessage, type AgentEvent } from "@mariozechner/pi-agent-core";
import { registerBuiltInApiProviders } from "@mariozechner/pi-ai";
import type { Model } from "@mariozechner/pi-ai";
import { exec } from "child_process";
import http from "http";
// ============== CONFIG ==============
const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || "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";
process.env.OPENROUTER_API_KEY = OPENROUTER_API_KEY;
const model: Model<"openai-responses"> = {
id: "stepfun/step-3.5-flash:free",
name: "Step-3.5 Flash (Free)",
api: "openai-responses",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
output: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128000,
maxTokens: 8192,
};
const PORT = process.env.PORT || 3000;
// ============== TASK QUEUE (Simplified) ==============
interface Task {
id: string;
message: string;
chatId: string;
status: "pending" | "running" | "completed";
response?: string;
}
class SimpleQueue {
private tasks: Task[] = [];
private processing = false;
add(message: string, chatId: string): string {
const id = `task-${Date.now()}`;
this.tasks.push({ id, message, chatId, status: "pending" });
return id;
}
getNext(): Task | undefined {
const task = this.tasks.find(t => t.status === "pending");
if (task) {
task.status = "running";
}
return task;
}
complete(id: string, response: string) {
const task = this.tasks.find(t => t.id === id);
if (task) {
task.status = "completed";
task.response = response;
}
}
getByChat(chatId: string): Task | undefined {
return this.tasks.find(t => t.chatId === chatId && t.status === "completed");
}
size(): number {
return this.tasks.length;
}
}
// ============== AGENT ==============
class HermesAgent {
private agent: Agent;
private chatId?: string;
constructor(chatId?: string) {
this.chatId = chatId;
this.agent = new Agent({
initialState: {
systemPrompt: "You are a helpful coding assistant. Be concise and helpful.",
model: model,
tools: [] as any,
messages: [],
},
convertToLlm: (messages: AgentMessage[]) => {
return messages
.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult")
.map((m) => ({ role: m.role, content: m.content }));
},
});
}
async process(message: string): Promise<string> {
let response = "";
this.agent.subscribe((event) => {
if (event.type === "message_update") {
const ev = event as any;
if (ev.assistantMessageEvent?.type === "text_delta") {
response += ev.assistantMessageEvent.delta || "";
}
}
});
await this.agent.prompt(message);
return response || "No response";
}
}
// ============== HTTP SERVER ==============
const queue = new SimpleQueue();
const agent = new HermesAgent();
const server = http.createServer(async (req, res) => {
// CORS headers
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
if (req.method === "OPTIONS") {
res.writeHead(204);
res.end();
return;
}
// Parse URL
const url = new URL(req.url || "/", `http://localhost:${PORT}`);
// Routes
if (url.pathname === "/health") {
// Health check
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "ok", queueSize: queue.size() }));
return;
}
if (url.pathname === "/webhook" && req.method === "POST") {
// Receive message from Hermes (Telegram)
let body = "";
req.on("data", chunk => body += chunk);
req.on("end", async () => {
try {
const data = JSON.parse(body);
const message = data.message || data.text || data.content;
const chatId = data.chat_id || data.chatId || data.from?.id || "unknown";
console.log(`📥 Received from chat ${chatId}: ${message.substring(0, 50)}...`);
// Process with agent
const response = await agent.process(message);
console.log(`📤 Sending response: ${response.substring(0, 50)}...`);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({
success: true,
response,
chatId,
}));
} catch (error: any) {
console.error("❌ Error:", error.message);
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: error.message }));
}
});
return;
}
if (url.pathname === "/message" && req.method === "POST") {
// Alternative endpoint: send message directly
let body = "";
req.on("data", chunk => body += chunk);
req.on("end", async () => {
try {
const data = JSON.parse(body);
const message = data.message;
const chatId = data.chatId || "default";
console.log(`📥 Message from ${chatId}: ${message}`);
const response = await agent.process(message);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ response }));
} catch (error: any) {
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: error.message }));
}
});
return;
}
if (url.pathname === "/status" && req.method === "GET") {
// Get status
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({
status: "running",
queueSize: queue.size(),
}));
return;
}
// 404
res.writeHead(404, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "Not found" }));
});
// ============== MAIN ==============
async function main() {
console.log("🧪 Level 4: Hermes Connection\n");
registerBuiltInApiProviders();
// Start server
server.listen(PORT, () => {
console.log(`
🚀 Server running on http://localhost:${PORT}
📡 Endpoints:
GET /health - Health check
GET /status - Server status
POST /webhook - Receive from Hermes (Telegram)
POST /message - Send message directly
📝 Example curl:
curl -X POST http://localhost:${PORT}/message \\
-H "Content-Type: application/json" \\
-d '{"message": "Hello!", "chatId": "123"}'
`);
});
// Handle shutdown
process.on("SIGINT", () => {
console.log("\n🛑 Shutting down...");
server.close(() => {
console.log("✅ Server stopped");
process.exit(0);
});
});
}
main().catch(console.error);