Files
agentdock/console/tests/mock-runner.mjs
T

81 lines
5.3 KiB
JavaScript

import crypto from "node:crypto";
import http from "node:http";
import express from "express";
import { WebSocketServer } from "ws";
const token = process.env.RUNNER_TOKEN || "test-runner-token-that-is-at-least-32-characters";
const tools = [
["codex", "Codex", "OpenAI", "CX", "codex", "0.149.0"],
["claude", "Claude Code", "Anthropic", "CC", "claude", "2.1.241"],
["codebuddy", "CodeBuddy", "Tencent", "CB", "codebuddy", "2.137.1"],
["kimi", "Kimi CLI", "Moonshot AI", "KM", "kimi", "0.38.0"],
["opencode", "OpenCode", "SST / Open source", "OC", "opencode", "1.18.21"],
["qwen", "Qwen Code", "Alibaba", "QW", "qwen", "0.22.0"],
["dsh", "DeepSeek Harness", "DeepSeek", "DS", "dsh", "0.1.1-rc.2"],
].map(([id, name, vendor, mono, command, version]) => ({ id, name, vendor, mono, command, version, installed: true, status: "stopped", profiles: id === "dsh" ? ["headless"] : [] }));
const sessions = [];
const integrations = {
ccSwitch: {
installed: true,
version: "cc-switch 5.10.2",
initialized: true,
apps: [
{ id: "claude", toolId: "claude", name: "Claude Code", currentProviderId: "anthropic", providers: [{ id: "anthropic", name: "Anthropic", endpoint: "https://api.anthropic.com", active: true }, { id: "relay", name: "Team Relay", endpoint: "https://relay.example", active: false }] },
{ id: "codex", toolId: "codex", name: "Codex", currentProviderId: "codex-official", providers: [{ id: "codex-official", name: "OpenAI Official", endpoint: null, active: true }] },
{ id: "open-code", toolId: "opencode", name: "OpenCode", currentProviderId: "openrouter", providers: [{ id: "openrouter", name: "OpenRouter", endpoint: "https://openrouter.ai", active: true }] },
],
unsupportedToolIds: ["codebuddy", "kimi", "qwen", "dsh"],
},
multica: {
installed: true,
version: "multica 0.1.53",
daemon: { status: "stopped", supervision: { mode: "unsupervised" } },
config: { configured: false, serverUrl: null, appUrl: null, workspaceId: null },
supportedToolIds: ["claude", "codex", "codebuddy", "kimi", "opencode"],
},
};
const app = express();
app.use(express.json());
app.use((req, res, next) => req.headers.authorization === `Bearer ${token}` ? next() : res.status(401).json({ error: "Unauthorized" }));
app.get("/health", (_req, res) => res.json({ ok: true }));
app.get("/tools", (_req, res) => res.json({ tools: tools.map((tool) => ({ ...tool, status: sessions.some((session) => session.tool === tool.id && session.status === "running") ? "running" : "stopped" })) }));
app.get("/projects", (_req, res) => res.json({ projects: ["demo-app", "website"] }));
app.get("/sessions", (_req, res) => res.json({ sessions }));
app.get("/integrations", (_req, res) => res.json({ integrations }));
app.get("/sessions/:id/output", (_req, res) => res.type("text/plain").send("AgentDock local QA session\r\n"));
app.get("/sessions/:id/diff", (_req, res) => res.type("text/plain").send("diff --git a/src/app.js b/src/app.js\n--- a/src/app.js\n+++ b/src/app.js\n@@ -1 +1 @@\n-old\n+new\n"));
app.post("/sessions", (req, res) => {
const tool = tools.find((item) => item.id === req.body.tool);
const session = { id: crypto.randomUUID(), tool: tool.id, toolName: tool.name, project: req.body.project || ".", purpose: req.body.purpose || "task", initialInput: req.body.initialInput || "", profile: req.body.profile || null, model: req.body.model || null, status: "running", pid: 4242, createdAt: new Date().toISOString(), endedAt: null, exitCode: null, signal: null };
sessions.unshift(session);
res.status(201).json({ session });
});
app.post("/sessions/:id/input", (_req, res) => res.status(204).end());
app.post("/sessions/:id/resize", (_req, res) => res.status(204).end());
app.post("/sessions/:id/stop", (req, res) => { const session = sessions.find((item) => item.id === req.params.id); if (session) { session.status = "stopped"; session.endedAt = new Date().toISOString(); } res.status(204).end(); });
app.post("/integrations/cc-switch/:app/switch", (req, res) => {
const appConfig = integrations.ccSwitch.apps.find((item) => item.id === req.params.app);
if (!appConfig) return res.status(400).json({ error: "Unsupported CC Switch application" });
appConfig.currentProviderId = req.body.providerId;
appConfig.providers.forEach((provider) => { provider.active = provider.id === req.body.providerId; });
res.json({ integrations });
});
app.post("/integrations/cc-switch/:app/import-live", (_req, res) => res.json({ integrations }));
const server = http.createServer(app);
const sockets = new WebSocketServer({ noServer: true });
server.on("upgrade", (request, socket, head) => {
const url = new URL(request.url, "http://localhost");
const match = url.pathname.match(/^\/ws\/sessions\/([a-f0-9-]+)$/);
if (!match || url.searchParams.get("token") !== token) return socket.destroy();
sockets.handleUpgrade(request, socket, head, (client) => {
client.send(JSON.stringify({ type: "snapshot", data: "\u001b[36mAgentDock local QA session\u001b[0m\r\n$ CLI ready\r\n" }));
client.on("message", (raw) => {
const message = JSON.parse(raw.toString());
if (message.type === "input" && message.data.trim()) client.send(JSON.stringify({ type: "output", data: `\r\nreceived: ${message.data}` }));
});
});
});
server.listen(4174, "127.0.0.1", () => console.log("mock runner listening on 4174"));