CoDEVX / lib /llm-response.ts
CodexMacTiger
feat: live package-scoped chat and thinking logs
837e3ac
import type { ChatResponse } from "./board-actions";
import type { ParsedCommand } from "./work-package-types";
function extractAssistantMessage(rawText: string) {
const trimmed = rawText.trim();
if (!trimmed) return "";
try {
const parsed = JSON.parse(trimmed) as
| {
assistantMessage?: unknown;
message?: unknown;
content?: unknown;
text?: unknown;
}
| string;
if (typeof parsed === "string") {
return parsed.trim();
}
const candidate =
parsed?.assistantMessage ??
parsed?.message ??
parsed?.content ??
parsed?.text;
if (typeof candidate === "string" && candidate.trim()) {
return candidate.trim();
}
} catch {
// ignore
}
return trimmed;
}
export function recoverInvalidLlmResponse(args: {
rawText: string;
parsedCommand?: ParsedCommand;
fallbackResponse?: ChatResponse;
}): ChatResponse {
const { rawText, parsedCommand, fallbackResponse } = args;
if (parsedCommand?.mode === "ask") {
return {
assistantMessage:
extractAssistantMessage(rawText) ||
"The model replied, but not in structured JSON. No board changes were applied.",
boardAction: { type: "none", workPackageId: null },
};
}
if (fallbackResponse) {
return fallbackResponse;
}
return {
assistantMessage:
rawText.trim() ||
"The model replied, but not in the required JSON contract. No board changes were applied.",
boardAction: { type: "none", workPackageId: null },
};
}