fix(frontend): restore Molecular CoT log parser
This commit is contained in:
100
frontend/src/lib/logs/parseCot.ts
Normal file
100
frontend/src/lib/logs/parseCot.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
// #region Logs.ParseCot [C:3] [TYPE Module] [SEMANTICS logs,cot,parse,task]
|
||||
// @defgroup Logs Parse Molecular CoT records and normalize task log entries for display.
|
||||
|
||||
// #region Logs.ParseCot.Message [C:2] [TYPE Function] [SEMANTICS logs,cot,parse]
|
||||
// @ingroup Logs
|
||||
// @BRIEF Parse a valid Molecular CoT JSON log record, returning null for ordinary log text.
|
||||
export type CotMarker = "REASON" | "REFLECT" | "EXPLORE";
|
||||
|
||||
export interface CotMessage {
|
||||
marker: CotMarker;
|
||||
intent: string;
|
||||
src?: string;
|
||||
trace_id?: string;
|
||||
span_id?: string;
|
||||
task_id?: string;
|
||||
level?: string;
|
||||
payload?: Record<string, unknown>;
|
||||
error?: string;
|
||||
raw: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function stringField(value: unknown): string | undefined {
|
||||
return typeof value === "string" ? value : undefined;
|
||||
}
|
||||
|
||||
function objectField(value: unknown): Record<string, unknown> | undefined {
|
||||
return value !== null && typeof value === "object" && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function parseCotMessage(message: unknown): CotMessage | null {
|
||||
if (typeof message !== "string" || !message.trim().startsWith("{")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let parsed: Record<string, unknown>;
|
||||
try {
|
||||
parsed = JSON.parse(message) as Record<string, unknown>;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const marker = stringField(parsed.marker);
|
||||
const intent = stringField(parsed.intent);
|
||||
if (
|
||||
(marker !== "REASON" && marker !== "REFLECT" && marker !== "EXPLORE") ||
|
||||
!intent
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const payload = objectField(parsed.payload);
|
||||
return {
|
||||
marker,
|
||||
intent,
|
||||
src: stringField(parsed.src),
|
||||
trace_id: stringField(parsed.trace_id),
|
||||
span_id: stringField(parsed.span_id),
|
||||
task_id: stringField(parsed.task_id) ?? stringField(payload?.task_id),
|
||||
level: stringField(parsed.level),
|
||||
payload,
|
||||
error: stringField(parsed.error),
|
||||
raw: parsed,
|
||||
};
|
||||
}
|
||||
// #endregion Logs.ParseCot.Message
|
||||
|
||||
// #region Logs.ParseCot.TaskLogToViewEntry [C:3] [TYPE Function] [SEMANTICS logs,cot,task,normalize]
|
||||
// @ingroup Logs
|
||||
// @BRIEF Normalize an API task log record while preserving parsed CoT metadata when present.
|
||||
export function taskLogToViewEntry(
|
||||
entry: Record<string, unknown>,
|
||||
index: number,
|
||||
) {
|
||||
const rawMessage = typeof entry.message === "string" ? entry.message : "";
|
||||
const cot = parseCotMessage(rawMessage);
|
||||
const timestamp = stringField(entry.timestamp) ?? stringField(entry.ts) ?? "";
|
||||
const level = stringField(entry.level) ?? cot?.level ?? "INFO";
|
||||
const metadata = objectField(entry.metadata);
|
||||
|
||||
return {
|
||||
id: stringField(entry.id) ?? `${timestamp}-${index}-${level}`,
|
||||
ts: timestamp,
|
||||
level,
|
||||
domain: "task",
|
||||
task_id: stringField(entry.task_id) ?? cot?.task_id,
|
||||
source: stringField(entry.source),
|
||||
marker: cot?.marker,
|
||||
intent: cot?.intent,
|
||||
trace_id: cot?.trace_id,
|
||||
span_id: cot?.span_id,
|
||||
payload: cot?.payload ?? metadata,
|
||||
error: cot?.error,
|
||||
rawMessage,
|
||||
};
|
||||
}
|
||||
// #endregion Logs.ParseCot.TaskLogToViewEntry
|
||||
|
||||
// #endregion Logs.ParseCot
|
||||
Reference in New Issue
Block a user