feat: add Node.js worker with Claude Code SDK

This commit is contained in:
2026-05-25 18:53:43 +02:00
parent 1e69b1aec2
commit d8d7e1a66f
3 changed files with 133 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
import express from "express";
import { query } from "@anthropic-ai/claude-code";
const app = express();
app.use(express.json({ limit: "10mb" }));
const PORT = process.env.WORKER_PORT || 3001;
const DEFAULT_MODEL = process.env.CLAUDE_MODEL || "claude-sonnet-4-6";
app.get("/health", (_req, res) => {
res.json({ status: "ok" });
});
app.post("/process", async (req, res) => {
const { prompt, system_prompt, model, session_id } = req.body;
if (!prompt) {
return res
.status(400)
.json({ success: false, error: "prompt is required" });
}
try {
const options = {
model: model || DEFAULT_MODEL,
systemPrompt: system_prompt || undefined,
allowedTools: [],
};
if (session_id) {
options.resume = session_id;
}
const messages = await query({
prompt,
options,
});
const resultText = messages
.filter((m) => m.type === "text")
.map((m) => m.text)
.join("\n");
const conversationId = messages.length > 0 ? messages[0].conversationId : null;
res.json({
success: true,
result: resultText,
session_id: conversationId || session_id,
});
} catch (error) {
console.error("Process error:", error.message);
res.json({
success: false,
error: error.message,
});
}
});
app.post("/summarize", async (req, res) => {
const { exchanges, mode } = req.body;
if (!exchanges || exchanges.length === 0) {
return res
.status(400)
.json({ success: false, error: "exchanges is required" });
}
const exchangeText = exchanges
.map((e, i) => `Exchange ${i + 1}:\nQ: ${e.prompt}\nA: ${e.result}`)
.join("\n\n");
const summaryPrompt =
mode === "complete"
? `Summarize these exchanges into a comprehensive overview. Be concise but thorough:\n\n${exchangeText}`
: `Summarize this exchange in 1-2 sentences:\n\n${exchangeText}`;
try {
const messages = await query({
prompt: summaryPrompt,
options: {
model: DEFAULT_MODEL,
systemPrompt:
"You are a summarizer. Respond with only the summary, no preamble.",
allowedTools: [],
},
});
const summaryText = messages
.filter((m) => m.type === "text")
.map((m) => m.text)
.join("\n");
res.json({
success: true,
summary: summaryText.trim(),
});
} catch (error) {
console.error("Summarize error:", error.message);
res.json({
success: false,
error: error.message,
});
}
});
app.listen(PORT, () => {
console.log(`Worker listening on port ${PORT}`);
});