mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
716 files rewritten, 30 renamed, same family mapping as the frontend pass.
Held back, and each for a reason rather than by oversight:
db_table values insights_hogfunction, insights_hogflow,
insights_hogfunctiontemplate, hogflow_templates.
Renaming a table is ALTER TABLE, so it ships as a
migration with the raw SQL in nodejs that names it.
hog_invocation_results a Datastore table with Kafka engine tables on it
products/review_hog the module path is the Django app path; moving it
moves app_label and every migration is recorded under
(app_label, name). That is the same history break as
renaming a migration file, one level up.
*/migrations/* five files, untouched
whogho an integration vendor
Checked: 395 of 397 changed Python files compile. The two that do not —
insightsql/database/database.py and temporal/schedule.py — fail identically at
origin/main under the same interpreter, because they use `type X = ...` and
`except*`, which need the 3.13 this repo pins and not the 3.9 doing the check.
Running the check against the original is what told those apart from a real
break.
Co-authored-by: Hanzo Dev <[email protected]>
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import clsx from 'clsx'
|
|
|
|
import { pngMascot } from 'lib/brand/mascot'
|
|
import { Markdown } from 'lib/elements/Markdown'
|
|
import { asDisplay } from 'scenes/persons/person-utils'
|
|
import { PersonIcon } from 'scenes/persons/PersonDisplay'
|
|
|
|
import { PersonType } from '~/types'
|
|
|
|
import { TranscriptTurn, parseTranscript } from './parseTranscript'
|
|
|
|
const MascotRobot = pngMascot()
|
|
|
|
interface TranscriptChatProps {
|
|
transcript: string
|
|
person: PersonType | null
|
|
identifier: string
|
|
}
|
|
|
|
export function TranscriptChat({ transcript, person, identifier }: TranscriptChatProps): JSX.Element {
|
|
const { leadingText, turns } = parseTranscript(transcript)
|
|
|
|
if (turns.length === 0 || leadingText) {
|
|
return (
|
|
<div data-attr="transcript-chat" data-parsed="false">
|
|
<Markdown className="text-sm leading-relaxed">{transcript}</Markdown>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div data-attr="transcript-chat" data-parsed="true" className="flex flex-col gap-3">
|
|
{turns.map((turn, index) => (
|
|
<TranscriptBubble key={index} turn={turn} person={person} identifier={identifier} />
|
|
))}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
interface TranscriptBubbleProps {
|
|
turn: TranscriptTurn
|
|
person: PersonType | null
|
|
identifier: string
|
|
}
|
|
|
|
function TranscriptBubble({ turn, person, identifier }: TranscriptBubbleProps): JSX.Element {
|
|
const isUser = turn.speaker === 'user'
|
|
return (
|
|
<div className={clsx('flex items-start gap-2', isUser ? 'flex-row-reverse' : 'flex-row')}>
|
|
<div className="shrink-0">
|
|
<TranscriptAvatar turn={turn} person={person} identifier={identifier} />
|
|
</div>
|
|
<div
|
|
className={clsx(
|
|
'rounded-lg border px-3 py-2 max-w-[85%] min-w-0',
|
|
isUser ? 'bg-accent-highlight-secondary' : 'bg-surface-primary'
|
|
)}
|
|
>
|
|
<div className="text-xs font-semibold mb-1 text-muted">{labelFor(turn, person, identifier)}</div>
|
|
<Markdown className="text-sm">{turn.text}</Markdown>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function TranscriptAvatar({ turn, person, identifier }: TranscriptBubbleProps): JSX.Element {
|
|
if (turn.speaker === 'ai') {
|
|
return (
|
|
<span
|
|
className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-surface-tertiary overflow-hidden"
|
|
title={turn.name}
|
|
>
|
|
<MascotRobot className="w-8 h-8 object-cover" />
|
|
</span>
|
|
)
|
|
}
|
|
|
|
if (turn.speaker === 'user') {
|
|
return <PersonIcon person={effectivePerson(person, identifier)} size="md" />
|
|
}
|
|
|
|
return <PersonIcon displayName={turn.name} size="md" />
|
|
}
|
|
|
|
function labelFor(turn: TranscriptTurn, person: PersonType | null, identifier: string): string {
|
|
if (turn.speaker === 'user') {
|
|
return asDisplay(effectivePerson(person, identifier))
|
|
}
|
|
return turn.name
|
|
}
|
|
|
|
function effectivePerson(person: PersonType | null, identifier: string): PersonType {
|
|
return person ?? { distinct_ids: [identifier], properties: {} }
|
|
}
|