Skip to content

feat: bump chat-ui with inline artifact #675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e4ada3c
feat: bump chat-ui with inline artifact
thucpn Jun 3, 2025
03c7c45
bump chat-ui 0.5.0
thucpn Jun 3, 2025
b2f804c
update extractLastArtifact
thucpn Jun 3, 2025
b9f61c7
fix: imports
thucpn Jun 3, 2025
4be5c0e
fix: circle import
thucpn Jun 3, 2025
b493548
missing export
thucpn Jun 3, 2025
e3187fa
update document gen workflow
thucpn Jun 3, 2025
472dbc4
remove artifactEvent for annotations
thucpn Jun 3, 2025
dc73a34
update document
thucpn Jun 3, 2025
0d7a32f
Merge branch 'main' into tp/bump-chat-ui-with-inline-artifact
thucpn Jun 3, 2025
f59b46d
bump chat-ui 0.5.1 to fix parsing $
thucpn Jun 3, 2025
75409c9
bump chat-ui 0.5.2
thucpn Jun 4, 2025
bdd6242
toArtifactEvent internal
thucpn Jun 4, 2025
2165247
update doc to use toArtifactEvent
thucpn Jun 4, 2025
844c297
do workflow transformmation internal
thucpn Jun 4, 2025
41898dc
revert doc
thucpn Jun 4, 2025
1f0f01a
keep contract
thucpn Jun 4, 2025
1c59807
fix format
thucpn Jun 4, 2025
37d5236
update get_last_artifact to extract inline annotations in Python
thucpn Jun 4, 2025
d8668bf
fix imports
thucpn Jun 4, 2025
3ac65ca
Transforms ArtifactEvent to AgentStream with inline annotation format
thucpn Jun 4, 2025
980f212
Create thick-turtles-deny.md
thucpn Jun 4, 2025
cded3ae
donot use relative imports
thucpn Jun 4, 2025
31cc131
toInlineAnnotationEvent
thucpn Jun 4, 2025
27de941
to_inline_annotation_event in python
thucpn Jun 4, 2025
eff7631
refactor: move toInlineAnnotationEvent to inline.ts
thucpn Jun 4, 2025
e20f198
update comment
thucpn Jun 4, 2025
4dca89d
rename ArtifactTransform to InlineAnnotationTransformer
leehuwuj Jun 4, 2025
a3dd3c1
Merge branch 'main' into tp/bump-chat-ui-with-inline-artifact
thucpn Jun 5, 2025
5c1de3c
add codegen example
thucpn Jun 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/thick-turtles-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"create-llama": patch
"@llamaindex/server": patch
"@create-llama/llama-index-server": patch
---

feat: bump chat-ui with inline artifact
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { extractLastArtifact } from "@llamaindex/server";
import { artifactEvent, extractLastArtifact } from "@llamaindex/server";
import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex";

import {
Expand Down Expand Up @@ -52,19 +52,6 @@ const synthesizeAnswerEvent = workflowEvent<object>();

const uiEvent = workflowEvent<UIEvent>();

const artifactEvent = workflowEvent<{
type: "artifact";
data: {
type: "code";
created_at: number;
data: {
language: string;
file_name: string;
code: string;
};
};
}>();

export function workflowFactory(reqBody: any) {
const llm = Settings.llm;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { extractLastArtifact } from "@llamaindex/server";
import { artifactEvent, extractLastArtifact } from "@llamaindex/server";
import { ChatMemoryBuffer, MessageContent, Settings } from "llamaindex";

import {
Expand Down Expand Up @@ -55,19 +55,6 @@ const synthesizeAnswerEvent = workflowEvent<{

const uiEvent = workflowEvent<UIEvent>();

const artifactEvent = workflowEvent<{
type: "artifact";
data: {
type: "document";
created_at: number;
data: {
title: string;
content: string;
type: "markdown" | "html";
};
};
}>();

export function workflowFactory(reqBody: any) {
const llm = Settings.llm;

Expand Down
22 changes: 22 additions & 0 deletions packages/server/examples/code-gen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
This example demonstrates how to use the code generation workflow.

```ts
new LlamaIndexServer({
workflow: workflowFactory,
uiConfig: {
starterQuestions: [
"Generate a calculator app",
"Create a simple todo list app",
],
componentsDir: "components",
},
port: 3000,
}).start();
```

Export OpenAI API key and start the server in dev mode.

```bash
export OPENAI_API_KEY=<your-openai-api-key>
npx nodemon --exec tsx index.ts
```
132 changes: 132 additions & 0 deletions packages/server/examples/code-gen/components/ui_event.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { Markdown } from "@llamaindex/chat-ui/widgets";
import { ListChecks, Loader2, Wand2 } from "lucide-react";
import { useEffect, useState } from "react";

const STAGE_META = {
plan: {
icon: ListChecks,
badgeText: "Step 1/2: Planning",
gradient: "from-blue-100 via-blue-50 to-white",
progress: 33,
iconBg: "bg-blue-100 text-blue-600",
badge: "bg-blue-100 text-blue-700",
},
generate: {
icon: Wand2,
badgeText: "Step 2/2: Generating",
gradient: "from-violet-100 via-violet-50 to-white",
progress: 66,
iconBg: "bg-violet-100 text-violet-600",
badge: "bg-violet-100 text-violet-700",
},
};

function ArtifactWorkflowCard({ event }) {
const [visible, setVisible] = useState(event?.state !== "completed");
const [fade, setFade] = useState(false);

useEffect(() => {
if (event?.state === "completed") {
setVisible(false);
} else {
setVisible(true);
setFade(false);
}
}, [event?.state]);

if (!event || !visible) return null;

const { state, requirement } = event;
const meta = STAGE_META[state];

if (!meta) return null;

return (
<div className="flex min-h-[180px] w-full items-center justify-center py-2">
<Card
className={cn(
"w-full rounded-xl shadow-md transition-all duration-500",
"border-0",
fade && "pointer-events-none opacity-0",
`bg-gradient-to-br ${meta.gradient}`,
)}
style={{
boxShadow:
"0 2px 12px 0 rgba(80, 80, 120, 0.08), 0 1px 3px 0 rgba(80, 80, 120, 0.04)",
}}
>
<CardHeader className="flex flex-row items-center gap-2 px-3 pb-1 pt-2">
<div
className={cn(
"flex items-center justify-center rounded-full p-1",
meta.iconBg,
)}
>
<meta.icon className="h-5 w-5" />
</div>
<CardTitle className="flex items-center gap-2 text-base font-semibold">
<Badge className={cn("ml-1", meta.badge, "px-2 py-0.5 text-xs")}>
{meta.badgeText}
</Badge>
</CardTitle>
</CardHeader>
<CardContent className="px-3 py-1">
{state === "plan" && (
<div className="flex flex-col items-center gap-2 py-2">
<Loader2 className="mb-1 h-6 w-6 animate-spin text-blue-400" />
<div className="text-center text-sm font-medium text-blue-900">
Analyzing your request...
</div>
<Skeleton className="mt-1 h-3 w-1/2 rounded-full" />
</div>
)}
{state === "generate" && (
<div className="flex flex-col gap-2 py-2">
<div className="flex items-center gap-1">
<Loader2 className="h-4 w-4 animate-spin text-violet-400" />
<span className="text-sm font-medium text-violet-900">
Working on the requirement:
</span>
</div>
<div className="max-h-24 overflow-auto rounded-lg border border-violet-200 bg-violet-50 px-2 py-1 text-xs">
{requirement ? (
<Markdown content={requirement} />
) : (
<span className="italic text-violet-400">
No requirements available yet.
</span>
)}
</div>
</div>
)}
</CardContent>
<div className="px-3 pb-2 pt-1">
<Progress
value={meta.progress}
className={cn(
"h-1 rounded-full bg-gray-200",
state === "plan" && "bg-blue-200",
state === "generate" && "bg-violet-200",
)}
/>
</div>
</Card>
</div>
);
}

export default function Component({ events }) {
const aggregateEvents = () => {
if (!events || events.length === 0) return null;
return events[events.length - 1];
};

const event = aggregateEvents();

return <ArtifactWorkflowCard event={event} />;
}
20 changes: 20 additions & 0 deletions packages/server/examples/code-gen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { OpenAI } from "@llamaindex/openai";
import { LlamaIndexServer } from "@llamaindex/server";
import { Settings } from "llamaindex";
import { workflowFactory } from "./src/app/workflow";

Settings.llm = new OpenAI({
model: "gpt-4o-mini",
});

new LlamaIndexServer({
workflow: workflowFactory,
uiConfig: {
starterQuestions: [
"Generate a calculator app",
"Create a simple todo list app",
],
componentsDir: "components",
},
port: 3000,
}).start();
Loading
Loading