NODEDC_1C/llm_normalizer/backend/dist/runtime/inMemoryRuntimeAdapter.js

214 lines
7.1 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InMemoryRuntimeAdapter = void 0;
const nanoid_1 = require("nanoid");
const http_1 = require("../utils/http");
class InMemoryRuntimeAdapter {
runs = [];
tasks = [];
traces = [];
idempotencyCache = new Map();
now() {
return new Date().toISOString();
}
cacheKey(action, key) {
if (!key || !key.trim())
return null;
return `${action}:${key.trim()}`;
}
readIdempotency(action, idempotencyKey) {
const cache = this.cacheKey(action, idempotencyKey);
if (!cache)
return null;
return this.idempotencyCache.get(cache) ?? null;
}
writeIdempotency(action, idempotencyKey, value) {
const cache = this.cacheKey(action, idempotencyKey);
if (!cache)
return;
this.idempotencyCache.set(cache, value);
}
pushEvent(input) {
this.traces.push({
timestamp: this.now(),
level: input.level ?? "info",
service: "llm_normalizer_backend",
sessionId: input.sessionId,
runId: input.runId,
taskId: input.taskId ?? null,
eventType: input.eventType,
payload: input.payload
});
}
startRun(input) {
const cached = this.readIdempotency("startRun", input.idempotencyKey);
if (cached)
return cached;
const record = {
sessionId: input.sessionId ?? `session_${(0, nanoid_1.nanoid)(8)}`,
runId: `run_${(0, nanoid_1.nanoid)(10)}`,
status: "RUNNING",
initiator: input.initiator ?? "operator",
source: input.source ?? "gui",
createdAt: this.now(),
updatedAt: this.now(),
metadata: input.metadata ?? {}
};
this.runs.unshift(record);
this.pushEvent({
runId: record.runId,
sessionId: record.sessionId,
eventType: "RUN_STARTED",
payload: record.metadata
});
this.writeIdempotency("startRun", input.idempotencyKey, record);
return record;
}
finishRun(input) {
const cached = this.readIdempotency("finishRun", input.idempotencyKey);
if (cached)
return cached;
const record = this.runs.find((item) => item.runId === input.runId);
if (!record) {
throw new http_1.ApiError("RUN_NOT_FOUND", `Run not found: ${input.runId}`, 404);
}
record.status = input.status;
record.updatedAt = this.now();
record.source = input.source ?? record.source;
record.metadata = {
...(record.metadata ?? {}),
...(input.metadata ?? {}),
reason: input.reason ?? null
};
this.pushEvent({
runId: record.runId,
sessionId: record.sessionId,
eventType: `RUN_FINISHED_${input.status}`,
level: input.status === "ERROR" ? "error" : "info",
payload: { reason: input.reason ?? null }
});
this.writeIdempotency("finishRun", input.idempotencyKey, record);
return record;
}
listRuns() {
return [...this.runs];
}
getRun(runId) {
return this.runs.find((item) => item.runId === runId) ?? null;
}
enqueueTask(input) {
const cached = this.readIdempotency("enqueueTask", input.idempotencyKey);
if (cached)
return cached;
const run = this.getRun(input.runId);
if (!run) {
throw new http_1.ApiError("RUN_NOT_FOUND", `Run not found: ${input.runId}`, 404);
}
const task = {
taskId: `task_${(0, nanoid_1.nanoid)(10)}`,
runId: run.runId,
status: "QUEUED",
payload: input.payload,
source: input.source ?? "gui",
createdAt: this.now(),
updatedAt: this.now()
};
this.tasks.unshift(task);
this.pushEvent({
runId: run.runId,
sessionId: run.sessionId,
taskId: task.taskId,
eventType: "TASK_ENQUEUED",
payload: task.payload
});
this.writeIdempotency("enqueueTask", input.idempotencyKey, task);
return task;
}
claimTask() {
const task = this.tasks.find((item) => item.status === "QUEUED");
if (!task) {
return null;
}
task.status = "RUNNING";
task.updatedAt = this.now();
const run = this.getRun(task.runId);
if (run) {
this.pushEvent({
runId: run.runId,
sessionId: run.sessionId,
taskId: task.taskId,
eventType: "TASK_CLAIMED"
});
}
return task;
}
completeTask(input) {
const cached = this.readIdempotency("completeTask", input.idempotencyKey);
if (cached)
return cached;
const task = this.tasks.find((item) => item.taskId === input.taskId);
if (!task) {
throw new http_1.ApiError("TASK_NOT_FOUND", `Task not found: ${input.taskId}`, 404);
}
task.status = "DONE";
task.updatedAt = this.now();
task.result = input.result;
task.source = input.source ?? task.source;
const run = this.getRun(task.runId);
if (run) {
this.pushEvent({
runId: run.runId,
sessionId: run.sessionId,
taskId: task.taskId,
eventType: "TASK_DONE",
payload: input.result
});
}
this.writeIdempotency("completeTask", input.idempotencyKey, task);
return task;
}
failTask(input) {
const cached = this.readIdempotency("failTask", input.idempotencyKey);
if (cached)
return cached;
const task = this.tasks.find((item) => item.taskId === input.taskId);
if (!task) {
throw new http_1.ApiError("TASK_NOT_FOUND", `Task not found: ${input.taskId}`, 404);
}
task.status = "ERROR";
task.updatedAt = this.now();
task.error = input.error;
task.source = input.source ?? task.source;
const run = this.getRun(task.runId);
if (run) {
this.pushEvent({
runId: run.runId,
sessionId: run.sessionId,
taskId: task.taskId,
eventType: "TASK_ERROR",
level: "error",
payload: {
errorCode: input.error.code,
errorMessage: input.error.message
}
});
}
this.writeIdempotency("failTask", input.idempotencyKey, task);
return task;
}
getResults() {
return this.tasks.filter((item) => item.status === "DONE" || item.status === "ERROR");
}
getRunTrace(runId) {
return this.traces.filter((item) => item.runId === runId);
}
health() {
return {
ok: true,
queueDepth: this.tasks.filter((item) => item.status === "QUEUED").length,
runsTotal: this.runs.length
};
}
}
exports.InMemoryRuntimeAdapter = InMemoryRuntimeAdapter;