"use strict"; const { parseCotBlocks } = require("./cot-parser"); const DEFAULT_BASE_URL = process.env.TASK_BOARD_API_BASE || "http://127.0.0.1:3001"; const DEFAULT_TOKEN = process.env.TASK_BOARD_ADMIN_TOKEN || "dev-task-board-token"; function withAuthHeaders(token) { return { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }; } async function requestJson(baseUrl, token, path, method = "GET", payload) { const response = await fetch(`${baseUrl.replace(/\/+$/, "")}${path}`, { method, headers: withAuthHeaders(token), body: payload === undefined ? undefined : JSON.stringify(payload), }); const data = await response.json().catch(() => ({})); if (!response.ok) { throw new Error(data.error || `${method} ${path} failed: ${response.status}`); } return data; } async function upsertNode(node, options = {}) { const baseUrl = options.baseUrl || DEFAULT_BASE_URL; const token = options.token || DEFAULT_TOKEN; return requestJson(baseUrl, token, "/api/admin/nodes", "POST", node); } async function upsertEdge(edge, options = {}) { const baseUrl = options.baseUrl || DEFAULT_BASE_URL; const token = options.token || DEFAULT_TOKEN; return requestJson(baseUrl, token, "/api/admin/edges", "POST", edge); } function buildTurnNode(params) { const content = String(params.content || "").trim(); const ts = params.timestamp || new Date().toISOString(); const messageId = params.messageId ? String(params.messageId) : ""; return { id: messageId ? `turn-${messageId}` : undefined, conversationId: params.conversationId, parentId: params.parentId || null, nodeType: "thought", name: content.slice(0, 42) || "Turn", status: "completed", content, timestamps: { created: ts, started: ts, completed: ts, }, llmDiagnostics: params.llmDiagnostics || {}, notes: params.notes || "", }; } async function ingestMessage(params, options = {}) { const turnNode = buildTurnNode(params); const createdTurn = await upsertNode(turnNode, options); if (params.parentId) { await upsertEdge( { from: params.parentId, to: createdTurn.id, type: "hierarchy", }, options, ); } if (!params.parseCot) { return { turnNode: createdTurn, cotNodes: [] }; } const cot = parseCotBlocks(params.content || ""); const cotNodes = []; let previousId = createdTurn.id; for (const block of cot) { const cotNode = await upsertNode( { conversationId: params.conversationId, parentId: previousId, nodeType: block.nodeType, name: block.name, content: block.content, status: "completed", timestamps: { created: params.timestamp || new Date().toISOString(), }, }, options, ); await upsertEdge( { from: previousId, to: cotNode.id, type: "hierarchy", }, options, ); previousId = cotNode.id; cotNodes.push(cotNode); } return { turnNode: createdTurn, cotNodes }; } module.exports = { ingestMessage, upsertNode, upsertEdge, };