Initial commit: Discord-Claude Gateway with event-driven agent runtime
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
import { execFile } from "node:child_process";
|
import { execFile } from "node:child_process";
|
||||||
|
import { writeFile, unlink } from "node:fs/promises";
|
||||||
|
import { join } from "node:path";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { randomUUID } from "node:crypto";
|
||||||
import type { Event, MessagePayload, HeartbeatPayload, CronPayload, HookPayload } from "./event-queue.js";
|
import type { Event, MessagePayload, HeartbeatPayload, CronPayload, HookPayload } from "./event-queue.js";
|
||||||
import type { MarkdownConfigLoader } from "./markdown-config-loader.js";
|
import type { MarkdownConfigLoader } from "./markdown-config-loader.js";
|
||||||
import type { SystemPromptAssembler } from "./system-prompt-assembler.js";
|
import type { SystemPromptAssembler } from "./system-prompt-assembler.js";
|
||||||
@@ -145,40 +149,53 @@ export class AgentRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private executeClaude(
|
private async executeClaude(
|
||||||
promptText: string,
|
promptText: string,
|
||||||
systemPrompt: string,
|
systemPrompt: string,
|
||||||
sessionId?: string,
|
sessionId?: string,
|
||||||
|
): Promise<ClaudeJsonResponse> {
|
||||||
|
// Write system prompt to a temp file to avoid CLI arg length limits
|
||||||
|
const tmpFile = join(tmpdir(), `aetheel-prompt-${randomUUID()}.txt`);
|
||||||
|
await writeFile(tmpFile, systemPrompt, "utf-8");
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await this.runClaude(promptText, tmpFile, sessionId);
|
||||||
|
} finally {
|
||||||
|
unlink(tmpFile).catch(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private runClaude(
|
||||||
|
promptText: string,
|
||||||
|
systemPromptFile: string,
|
||||||
|
sessionId?: string,
|
||||||
): Promise<ClaudeJsonResponse> {
|
): Promise<ClaudeJsonResponse> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const args: string[] = [
|
const args: string[] = [
|
||||||
"-p", promptText,
|
"-p", promptText,
|
||||||
"--output-format", "json",
|
"--output-format", "json",
|
||||||
"--system-prompt", systemPrompt,
|
"--system-prompt-file", systemPromptFile,
|
||||||
"--dangerously-skip-permissions",
|
"--dangerously-skip-permissions",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Resume existing session
|
|
||||||
if (sessionId) {
|
if (sessionId) {
|
||||||
args.push("--resume", sessionId);
|
args.push("--resume", sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allowed tools
|
|
||||||
if (this.config.allowedTools.length > 0) {
|
if (this.config.allowedTools.length > 0) {
|
||||||
args.push("--allowedTools", ...this.config.allowedTools);
|
args.push("--allowedTools", ...this.config.allowedTools);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max turns to prevent runaway loops
|
|
||||||
args.push("--max-turns", "25");
|
args.push("--max-turns", "25");
|
||||||
|
|
||||||
console.log(`[DEBUG] Spawning Claude CLI: ${this.config.claudeCliPath} ${args.slice(0, 4).join(" ")} ... (${args.length} args total)`);
|
console.log(`[DEBUG] Spawning Claude CLI: ${this.config.claudeCliPath} -p "${promptText}" --output-format json --system-prompt-file ${systemPromptFile} ... (${args.length} args total)`);
|
||||||
|
|
||||||
const child = execFile(
|
const child = execFile(
|
||||||
this.config.claudeCliPath,
|
this.config.claudeCliPath,
|
||||||
args,
|
args,
|
||||||
{
|
{
|
||||||
timeout: this.config.queryTimeoutMs,
|
timeout: this.config.queryTimeoutMs,
|
||||||
maxBuffer: 10 * 1024 * 1024, // 10MB
|
maxBuffer: 10 * 1024 * 1024,
|
||||||
encoding: "utf-8",
|
encoding: "utf-8",
|
||||||
},
|
},
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, stderr) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user