mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-10 08:48:29 +00:00
fix: document view is broken in log view
This commit is contained in:
parent
2281dab166
commit
a14b83d66d
220
apps/webapp/app/components/common/styled-markdown.tsx
Normal file
220
apps/webapp/app/components/common/styled-markdown.tsx
Normal file
@ -0,0 +1,220 @@
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import type { Components } from "react-markdown";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
const markdownComponents: Components = {
|
||||
h1: ({ className, ...props }) => (
|
||||
<h1
|
||||
className={cn("mt-2 mb-1 text-3xl font-bold tracking-tight", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h2: ({ className, ...props }) => (
|
||||
<h2
|
||||
className={cn(
|
||||
"mt-2 mb-1 text-2xl font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h3: ({ className, ...props }) => (
|
||||
<h3
|
||||
className={cn(
|
||||
"mt-2 mb-1 text-xl font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h4: ({ className, ...props }) => (
|
||||
<h4
|
||||
className={cn(
|
||||
"mt-1.5 mb-0.5 text-lg font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h5: ({ className, ...props }) => (
|
||||
<h5
|
||||
className={cn(
|
||||
"mt-1.5 mb-0.5 text-base font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h6: ({ className, ...props }) => (
|
||||
<h6
|
||||
className={cn(
|
||||
"mt-1.5 mb-0.5 text-sm font-semibold tracking-tight",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
p: ({ className, ...props }) => (
|
||||
<p
|
||||
className={cn(
|
||||
"mb-1 leading-normal [&:not(:first-child)]:mt-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
ul: ({ className, ...props }) => (
|
||||
<ul
|
||||
className={cn(
|
||||
"my-1 ml-5 flex list-disc flex-col space-y-0 marker:text-gray-700 dark:marker:text-gray-400",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
ol: ({ className, ...props }) => (
|
||||
<ol
|
||||
className={cn(
|
||||
"my-1 ml-5 list-decimal space-y-0 marker:text-gray-700 dark:marker:text-gray-400",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
li: ({ className, ...props }) => (
|
||||
<li className={cn("py-0.5 pl-1 leading-normal", className)} {...props} />
|
||||
),
|
||||
blockquote: ({ className, ...props }) => (
|
||||
<blockquote
|
||||
className={cn(
|
||||
"mt-1 mb-1 border-l-4 border-gray-300 pl-4 text-gray-700 italic dark:border-gray-600 dark:text-gray-300",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
code: ({ className, inline, ...props }: any) =>
|
||||
inline ? (
|
||||
<code
|
||||
className={cn(
|
||||
"rounded bg-gray-100 px-1.5 py-0.5 font-mono text-sm text-gray-800 dark:bg-gray-800 dark:text-gray-200",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<code
|
||||
className={cn(
|
||||
"block rounded-lg bg-gray-100 p-4 font-mono text-sm text-gray-800 dark:bg-gray-800 dark:text-gray-200",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
pre: ({ className, ...props }) => (
|
||||
<pre
|
||||
className={cn(
|
||||
"mb-1 overflow-x-auto rounded-lg bg-gray-100 p-4 dark:bg-gray-800",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
a: ({ className, ...props }) => (
|
||||
<a
|
||||
className={cn(
|
||||
"font-medium text-blue-600 underline underline-offset-4 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
hr: ({ className, ...props }) => (
|
||||
<hr
|
||||
className={cn(
|
||||
"my-2 border-t border-gray-300 dark:border-gray-600",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
table: ({ className, ...props }) => (
|
||||
<div className="mb-1 w-full overflow-auto">
|
||||
<table
|
||||
className={cn(
|
||||
"w-full border-collapse border border-gray-300 dark:border-gray-600",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
thead: ({ className, ...props }) => (
|
||||
<thead
|
||||
className={cn("bg-gray-100 dark:bg-gray-800", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
tbody: ({ className, ...props }) => (
|
||||
<tbody className={cn("", className)} {...props} />
|
||||
),
|
||||
tr: ({ className, ...props }) => (
|
||||
<tr
|
||||
className={cn("border-b border-gray-300 dark:border-gray-600", className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
th: ({ className, ...props }) => (
|
||||
<th
|
||||
className={cn(
|
||||
"border border-gray-300 px-4 py-2 text-left font-semibold dark:border-gray-600",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
td: ({ className, ...props }) => (
|
||||
<td
|
||||
className={cn(
|
||||
"border border-gray-300 px-4 py-2 dark:border-gray-600",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
strong: ({ className, ...props }) => (
|
||||
<strong className={cn("font-bold", className)} {...props} />
|
||||
),
|
||||
em: ({ className, ...props }) => (
|
||||
<em className={cn("italic", className)} {...props} />
|
||||
),
|
||||
};
|
||||
|
||||
interface StyledMarkdownProps {
|
||||
children: string;
|
||||
className?: string;
|
||||
components?: Components;
|
||||
}
|
||||
|
||||
export function StyledMarkdown({
|
||||
children,
|
||||
className,
|
||||
components,
|
||||
}: StyledMarkdownProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"max-w-none",
|
||||
"[&_ul_ul]:my-0.5 [&_ul_ul]:ml-4",
|
||||
"[&_ol_ol]:my-0.5 [&_ol_ol]:ml-4",
|
||||
"[&_ul_ol]:my-0.5 [&_ul_ol]:ml-4",
|
||||
"[&_ol_ul]:my-0.5 [&_ol_ul]:ml-4",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<ReactMarkdown components={{ ...markdownComponents, ...components }}>
|
||||
{children}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -9,6 +9,7 @@ import { cn, formatString } from "~/lib/utils";
|
||||
import { getStatusColor } from "./utils";
|
||||
import { format } from "date-fns";
|
||||
import { SpaceDropdown } from "../spaces/space-dropdown";
|
||||
import { StyledMarkdown } from "../common/styled-markdown";
|
||||
|
||||
interface LogDetailsProps {
|
||||
log: LogItem;
|
||||
@ -214,7 +215,7 @@ export function LogDetails({ log }: LogDetailsProps) {
|
||||
{/* Log Content */}
|
||||
<div className="mb-4 w-full break-words whitespace-pre-wrap">
|
||||
<div className="rounded-md">
|
||||
<Markdown>{log.ingestText}</Markdown>
|
||||
<StyledMarkdown>{log.ingestText}</StyledMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -254,7 +255,7 @@ export function LogDetails({ log }: LogDetailsProps) {
|
||||
Content
|
||||
</div>
|
||||
<div className="text-sm break-words whitespace-pre-wrap">
|
||||
<Markdown>{episode.content}</Markdown>
|
||||
<StyledMarkdown>{episode.content}</StyledMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,7 @@ import type { StatementNode } from "@core/types";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { useNavigate } from "@remix-run/react";
|
||||
import Markdown from "react-markdown";
|
||||
import { StyledMarkdown } from "../common/styled-markdown";
|
||||
|
||||
export interface Episode {
|
||||
uuid: string;
|
||||
@ -54,7 +55,7 @@ export function SpaceEpisodeCard({ episode }: SpaceFactCardProps) {
|
||||
>
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="inline-flex min-h-[24px] min-w-[0px] shrink items-center justify-start">
|
||||
<Markdown>{displayText}</Markdown>
|
||||
<StyledMarkdown>{displayText.slice(0, 300)}</StyledMarkdown>
|
||||
</div>
|
||||
<div className="text-muted-foreground flex shrink-0 items-center justify-end gap-2 text-xs">
|
||||
<Badge variant="secondary" className="rounded text-xs">
|
||||
|
||||
@ -131,7 +131,9 @@ export const getIngestionQueueForFrontend = async (
|
||||
(log.output as any)?.episodes?.length > 0
|
||||
) {
|
||||
// For DOCUMENT type: get episode details and space information for all episodes
|
||||
const episodeIds = (log.output as any)?.episodes;
|
||||
const episodeIds = (log.output as any)?.episodes.map(
|
||||
(e: any) => e.episodeUuid,
|
||||
);
|
||||
|
||||
// Fetch all episode details in parallel
|
||||
const episodeDetailsPromises = episodeIds.map((episodeId: string) =>
|
||||
|
||||
@ -55,7 +55,7 @@ const SummaryResultSchema = z.object({
|
||||
const CONFIG = {
|
||||
maxEpisodesForSummary: 20, // Limit episodes for performance
|
||||
minEpisodesForSummary: 1, // Minimum episodes to generate summary
|
||||
summaryEpisodeThreshold: 10, // Minimum new episodes required to trigger summary (configurable)
|
||||
summaryEpisodeThreshold: 5, // Minimum new episodes required to trigger summary (configurable)
|
||||
};
|
||||
|
||||
export const spaceSummaryQueue = queue({
|
||||
@ -85,7 +85,11 @@ export const spaceSummaryTask = task({
|
||||
});
|
||||
|
||||
// Generate summary for the single space
|
||||
const summaryResult = await generateSpaceSummary(spaceId, userId, triggerSource);
|
||||
const summaryResult = await generateSpaceSummary(
|
||||
spaceId,
|
||||
userId,
|
||||
triggerSource,
|
||||
);
|
||||
|
||||
if (summaryResult) {
|
||||
// Store the summary
|
||||
@ -192,7 +196,10 @@ async function generateSpaceSummary(
|
||||
const lastSummaryEpisodeCount = space.contextCount || 0;
|
||||
const episodeDifference = currentEpisodeCount - lastSummaryEpisodeCount;
|
||||
|
||||
if (episodeDifference < CONFIG.summaryEpisodeThreshold) {
|
||||
if (
|
||||
episodeDifference < CONFIG.summaryEpisodeThreshold ||
|
||||
lastSummaryEpisodeCount === 0
|
||||
) {
|
||||
logger.info(
|
||||
`Skipping summary generation for space ${spaceId}: only ${episodeDifference} new episodes (threshold: ${CONFIG.summaryEpisodeThreshold})`,
|
||||
{
|
||||
@ -200,7 +207,7 @@ async function generateSpaceSummary(
|
||||
lastSummaryEpisodeCount,
|
||||
episodeDifference,
|
||||
threshold: CONFIG.summaryEpisodeThreshold,
|
||||
}
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}
|
||||
@ -211,7 +218,7 @@ async function generateSpaceSummary(
|
||||
currentEpisodeCount,
|
||||
lastSummaryEpisodeCount,
|
||||
episodeDifference,
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -361,9 +368,15 @@ async function generateUnifiedSummary(
|
||||
|
||||
// Space summary generation requires HIGH complexity (creative synthesis, narrative generation)
|
||||
let responseText = "";
|
||||
await makeModelCall(false, prompt, (text: string) => {
|
||||
responseText = text;
|
||||
}, undefined, 'high');
|
||||
await makeModelCall(
|
||||
false,
|
||||
prompt,
|
||||
(text: string) => {
|
||||
responseText = text;
|
||||
},
|
||||
undefined,
|
||||
"high",
|
||||
);
|
||||
|
||||
return parseSummaryResponse(responseText);
|
||||
} catch (error) {
|
||||
|
||||
@ -113,10 +113,6 @@ model ConversationHistory {
|
||||
model IngestionQueue {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Relations
|
||||
space Space? @relation(fields: [spaceId], references: [id])
|
||||
spaceId String?
|
||||
|
||||
// Queue metadata
|
||||
data Json // The actual data to be processed
|
||||
output Json? // The processed output data
|
||||
@ -472,29 +468,29 @@ model RecallLog {
|
||||
}
|
||||
|
||||
model Space {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
autoMode Boolean @default(false)
|
||||
summary String?
|
||||
themes String[]
|
||||
statementCount Int?
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
autoMode Boolean @default(false)
|
||||
summary String?
|
||||
themes String[]
|
||||
contextCount Int? // Count of context items in this space (episodes, statements, etc.)
|
||||
|
||||
status String?
|
||||
|
||||
icon String?
|
||||
|
||||
lastPatternTrigger DateTime?
|
||||
statementCountAtLastTrigger Int?
|
||||
lastPatternTrigger DateTime?
|
||||
summaryGeneratedAt DateTime?
|
||||
contextCountAtLastTrigger Int? // Context count when pattern was last triggered
|
||||
|
||||
// Relations
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id])
|
||||
workspaceId String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
IngestionQueue IngestionQueue[]
|
||||
SpacePattern SpacePattern[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
SpacePattern SpacePattern[]
|
||||
}
|
||||
|
||||
model SpacePattern {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user