Initial import NDC_1C

This commit is contained in:
2026-03-26 10:38:25 +03:00
commit a162d77ef7
2943 changed files with 3615871 additions and 0 deletions
@@ -0,0 +1,263 @@
import { nanoid } from "nanoid";
import type { RuntimeAdapter } from "./runtimeAdapter";
import type { RunRecord, TaskRecord, TraceEvent } from "../types/accountingAgent";
import { ApiError } from "../utils/http";
export class InMemoryRuntimeAdapter implements RuntimeAdapter {
private runs: RunRecord[] = [];
private tasks: TaskRecord[] = [];
private traces: TraceEvent[] = [];
private idempotencyCache = new Map<string, unknown>();
private now(): string {
return new Date().toISOString();
}
private cacheKey(action: string, key?: string): string | null {
if (!key || !key.trim()) return null;
return `${action}:${key.trim()}`;
}
private readIdempotency<T>(action: string, idempotencyKey?: string): T | null {
const cache = this.cacheKey(action, idempotencyKey);
if (!cache) return null;
return (this.idempotencyCache.get(cache) as T | undefined) ?? null;
}
private writeIdempotency(action: string, idempotencyKey: string | undefined, value: unknown): void {
const cache = this.cacheKey(action, idempotencyKey);
if (!cache) return;
this.idempotencyCache.set(cache, value);
}
private pushEvent(input: {
runId: string;
sessionId: string;
taskId?: string | null;
level?: "info" | "warn" | "error";
eventType: string;
payload?: Record<string, unknown>;
}): void {
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
});
}
public startRun(input: {
sessionId?: string;
initiator?: string;
source?: string;
metadata?: Record<string, unknown>;
idempotencyKey?: string;
}): RunRecord {
const cached = this.readIdempotency<RunRecord>("startRun", input.idempotencyKey);
if (cached) return cached;
const record: RunRecord = {
sessionId: input.sessionId ?? `session_${nanoid(8)}`,
runId: `run_${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 as Record<string, unknown>
});
this.writeIdempotency("startRun", input.idempotencyKey, record);
return record;
}
public finishRun(input: {
runId: string;
status: "DONE" | "ERROR" | "CANCELLED";
source?: string;
reason?: string;
metadata?: Record<string, unknown>;
idempotencyKey?: string;
}): RunRecord {
const cached = this.readIdempotency<RunRecord>("finishRun", input.idempotencyKey);
if (cached) return cached;
const record = this.runs.find((item) => item.runId === input.runId);
if (!record) {
throw new 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;
}
public listRuns(): RunRecord[] {
return [...this.runs];
}
public getRun(runId: string): RunRecord | null {
return this.runs.find((item) => item.runId === runId) ?? null;
}
public enqueueTask(input: {
runId: string;
payload: Record<string, unknown>;
source?: string;
idempotencyKey?: string;
}): TaskRecord {
const cached = this.readIdempotency<TaskRecord>("enqueueTask", input.idempotencyKey);
if (cached) return cached;
const run = this.getRun(input.runId);
if (!run) {
throw new ApiError("RUN_NOT_FOUND", `Run not found: ${input.runId}`, 404);
}
const task: TaskRecord = {
taskId: `task_${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;
}
public claimTask(): TaskRecord | null {
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;
}
public completeTask(input: {
taskId: string;
result: Record<string, unknown>;
source?: string;
idempotencyKey?: string;
}): TaskRecord {
const cached = this.readIdempotency<TaskRecord>("completeTask", input.idempotencyKey);
if (cached) return cached;
const task = this.tasks.find((item) => item.taskId === input.taskId);
if (!task) {
throw new 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;
}
public failTask(input: {
taskId: string;
error: { code: string; message: string; details?: unknown };
source?: string;
idempotencyKey?: string;
}): TaskRecord {
const cached = this.readIdempotency<TaskRecord>("failTask", input.idempotencyKey);
if (cached) return cached;
const task = this.tasks.find((item) => item.taskId === input.taskId);
if (!task) {
throw new 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;
}
public getResults(): TaskRecord[] {
return this.tasks.filter((item) => item.status === "DONE" || item.status === "ERROR");
}
public getRunTrace(runId: string): TraceEvent[] {
return this.traces.filter((item) => item.runId === runId);
}
public health(): { ok: boolean; queueDepth: number; runsTotal: number } {
return {
ok: true,
queueDepth: this.tasks.filter((item) => item.status === "QUEUED").length,
runsTotal: this.runs.length
};
}
}
@@ -0,0 +1,43 @@
import type { RunRecord, TaskRecord, TraceEvent } from "../types/accountingAgent";
export interface RuntimeAdapter {
startRun(input: {
sessionId?: string;
initiator?: string;
source?: string;
metadata?: Record<string, unknown>;
idempotencyKey?: string;
}): RunRecord;
finishRun(input: {
runId: string;
status: "DONE" | "ERROR" | "CANCELLED";
source?: string;
reason?: string;
metadata?: Record<string, unknown>;
idempotencyKey?: string;
}): RunRecord;
listRuns(): RunRecord[];
getRun(runId: string): RunRecord | null;
enqueueTask(input: {
runId: string;
payload: Record<string, unknown>;
source?: string;
idempotencyKey?: string;
}): TaskRecord;
claimTask(): TaskRecord | null;
completeTask(input: {
taskId: string;
result: Record<string, unknown>;
source?: string;
idempotencyKey?: string;
}): TaskRecord;
failTask(input: {
taskId: string;
error: { code: string; message: string; details?: unknown };
source?: string;
idempotencyKey?: string;
}): TaskRecord;
getResults(): TaskRecord[];
getRunTrace(runId: string): TraceEvent[];
health(): { ok: boolean; queueDepth: number; runsTotal: number };
}