feat: 接入本地执行内核与运行面板
This commit is contained in:
1 parent
32ca0a1af8
commit
6a2cc24898
23 files changed
+2937
-41
No files matched your search
@@ -0,0 +1,86 @@
|
||||
import { app, type WebContents } from "electron";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { FlowDefinition, RunEvent } from "../../shared/types";
|
||||
import { loadCatalog } from "../catalog";
|
||||
import { runFlow } from "../engine/runtime";
|
||||
import { BrowserSession } from "../browser/session";
|
||||
|
||||
const active = new Map<string, AbortController>();
|
||||
let currentRunId: string | null = null;
|
||||
|
||||
function newRunId(): string {
|
||||
return `run_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
|
||||
}
|
||||
|
||||
export function startRun(flow: FlowDefinition, sender: WebContents): { runId: string } {
|
||||
if (currentRunId) active.get(currentRunId)?.abort();
|
||||
|
||||
const runId = newRunId();
|
||||
const root = path.join(app.getPath("userData"), "runs", runId);
|
||||
const evidenceDir = path.join(root, "evidence");
|
||||
fs.mkdirSync(evidenceDir, { recursive: true });
|
||||
|
||||
const controller = new AbortController();
|
||||
active.set(runId, controller);
|
||||
currentRunId = runId;
|
||||
|
||||
const catalog = loadCatalog();
|
||||
const components = new Map(catalog.components.map((item) => [item.id, item]));
|
||||
|
||||
const emit = (event: Omit<RunEvent, "runId">) => {
|
||||
if (!sender.isDestroyed()) sender.send("run:event", { ...event, runId });
|
||||
};
|
||||
const log: (message: string, level?: "info" | "warn" | "error", nodeId?: string) => void = (
|
||||
message,
|
||||
level = "info",
|
||||
nodeId
|
||||
) => emit({ type: "node.log", nodeId, level, message });
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
const result = await runFlow(flow, {
|
||||
runId,
|
||||
evidenceDir,
|
||||
signal: controller.signal,
|
||||
emit,
|
||||
log,
|
||||
componentOf: (node) => components.get(node.componentId)
|
||||
});
|
||||
fs.writeFileSync(path.join(root, "run.json"), JSON.stringify(result, null, 2), "utf8");
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
emit({ type: "run.finished", status: "failed", durationMs: 0, error: { code: "unknown", reason: message } });
|
||||
fs.writeFileSync(
|
||||
path.join(root, "run.json"),
|
||||
JSON.stringify({ runId, status: "failed", error: message }, null, 2),
|
||||
"utf8"
|
||||
);
|
||||
} finally {
|
||||
active.delete(runId);
|
||||
if (currentRunId === runId) currentRunId = null;
|
||||
}
|
||||
})();
|
||||
|
||||
return { runId };
|
||||
}
|
||||
|
||||
export function stopRun(runId?: string): boolean {
|
||||
const id = runId || currentRunId;
|
||||
if (!id) return false;
|
||||
const controller = active.get(id);
|
||||
if (!controller) return false;
|
||||
controller.abort();
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function closeBrowserSession(): Promise<void> {
|
||||
if (globalThis.__rpaBrowserWindow && !globalThis.__rpaBrowserWindow.isDestroyed()) {
|
||||
const session = await BrowserSession.create();
|
||||
await session.close();
|
||||
}
|
||||
}
|
||||
|
||||
export function isRunning(): boolean {
|
||||
return currentRunId !== null;
|
||||
}
|
||||
Reference in new issue
Block a user