Skip to content

feat: init @llama-flow/http pacakge #105

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 9 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .changeset/dirty-pugs-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@llama-flow/core": patch
"@llama-flow/http": patch
---

feat: update http protocol
8 changes: 8 additions & 0 deletions demo/waku/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
dist
.env*
*.tsbuildinfo
.cache
.DS_Store
*.pem
src/pages.gen.ts
18 changes: 18 additions & 0 deletions demo/waku/openapi-ts.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defaultPlugins, defineConfig } from "@hey-api/openapi-ts";

export default defineConfig({
input: "https://api.cloud.llamaindex.ai/api/openapi.json",
output: "src/lib/api",
plugins: [
...defaultPlugins,
"@hey-api/client-fetch",
"zod",
"@hey-api/schemas",
"@hey-api/sdk",
{
enums: "javascript",
identifierCase: "PascalCase",
name: "@hey-api/typescript",
},
],
});
34 changes: 34 additions & 0 deletions demo/waku/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "waku-project",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"postinstall": "openapi-ts",
"dev": "waku dev",
"build": "waku build",
"start": "waku start"
},
"dependencies": {
"@llama-flow/core": "latest",
"@llama-flow/http": "latest",
"@neondatabase/serverless": "^1.0.0",
"lucide-react": "^0.511.0",
"openai": "^4.95.1",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-server-dom-webpack": "19.1.0",
"stable-hash": "^0.0.5",
"waku": "0.22.4"
},
"devDependencies": {
"@hey-api/client-fetch": "^0.10.1",
"@hey-api/openapi-ts": "^0.67.5",
"@tailwindcss/postcss": "4.1.4",
"@types/react": "19.1.2",
"@types/react-dom": "19.1.2",
"postcss": "8.5.3",
"tailwindcss": "4.1.4",
"typescript": "5.8.3"
}
}
5 changes: 5 additions & 0 deletions demo/waku/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Binary file added demo/waku/public/images/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions demo/waku/src/components/RAG.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"use client";
import { createClient } from "@llama-flow/http/client";
import * as events from "../workflow/events";
import { useState, useCallback } from "react";

const { fetch } = createClient("/api/store", events);

export const RAG = () => {
const [list, setList] = useState<any[]>([]);
const [file, setFile] = useState<File | null>(null);

const handleFileInput = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
const selectedFiles = Array.from(e.target.files);
setFile(selectedFiles[0]!);
}
},
[],
);

return (
<section className="border-blue-400 -mx-4 mt-4 rounded-sm border p-4">
<div>
<input type="file" onChange={handleFileInput} id="file-upload" />
<button
onClick={async () => {
fetch({
file,
}).then((stream) => {
stream.forEach((event) => {
console.log(event);
if (event.data) {
setList((prev) => [...prev, `${event.data}`]);
}
});
});
}}
>
Run
</button>
</div>

<form
action={(form) => {
const search = form.get("search") as string;
fetch({
search,
}).then((stream) => {
stream.forEach((event) => {
console.log(event);
if (event.data) {
setList((prev) => [...prev, `${event.data}`]);
}
});
});
}}
>
<input
type="text"
name="search"
className="border-gray-400 mt-4 w-full rounded-sm border p-2"
placeholder="Search something..."
/>
<button type="submit" />
</form>

{list.map((item, index) => (
<div key={index} className="flex items-center gap-2">
<div className="text-sm max-h-12 max-w-64 overflow-scroll">
{item}
</div>
</div>
))}
</section>
);
};
18 changes: 18 additions & 0 deletions demo/waku/src/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const Footer = () => {
return (
<footer className="p-6 lg:fixed lg:bottom-0 lg:left-0">
<div>
visit{" "}
<a
href="https://waku.gg/"
target="_blank"
rel="noreferrer"
className="mt-4 inline-block underline"
>
waku.gg
</a>{" "}
to learn more
</div>
</footer>
);
};
11 changes: 11 additions & 0 deletions demo/waku/src/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Link } from "waku";

export const Header = () => {
return (
<header className="flex items-center gap-4 p-6 lg:fixed lg:left-0 lg:top-0">
<h2 className="text-lg font-bold tracking-tight">
<Link to="/">Waku starter</Link>
</h2>
</header>
);
};
39 changes: 39 additions & 0 deletions demo/waku/src/pages/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import "../styles.css";

import type { ReactNode } from "react";

import { Header } from "../components/header";
import { Footer } from "../components/footer";

type RootLayoutProps = { children: ReactNode };

export default async function RootLayout({ children }: RootLayoutProps) {
const data = await getData();

return (
<div className="font-['Nunito']">
<meta name="description" content={data.description} />
<link rel="icon" type="image/png" href={data.icon} />
<Header />
<main className="m-6 flex items-center *:min-h-64 *:min-w-64 lg:m-0 lg:min-h-svh lg:justify-center">
{children}
</main>
<Footer />
</div>
);
}

const getData = async () => {
const data = {
description: "An internet website!",
icon: "/images/favicon.png",
};

return data;
};

export const getConfig = async () => {
return {
render: "static",
} as const;
};
32 changes: 32 additions & 0 deletions demo/waku/src/pages/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Link } from "waku";

export default async function AboutPage() {
const data = await getData();

return (
<div>
<title>{data.title}</title>
<h1 className="text-4xl font-bold tracking-tight">{data.headline}</h1>
<p>{data.body}</p>
<Link to="/" className="mt-4 inline-block underline">
Return home
</Link>
</div>
);
}

const getData = async () => {
const data = {
title: "About",
headline: "About Waku",
body: "The minimal React framework",
};

return data;
};

export const getConfig = async () => {
return {
render: "static",
} as const;
};
26 changes: 26 additions & 0 deletions demo/waku/src/pages/api/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createServer } from "@llama-flow/http/server";
import { workflow } from "../../workflow/basic";
import { upload } from "../../workflow/llama-parse";
import { storeEvent, stopEvent, searchEvent } from "../../workflow/events";

process.on("unhandledRejection", (reason) => {
console.error("Unhandled Rejection at:", reason);
});

export const POST = createServer(
workflow,
async (data, sendEvent) => {
if (data.file) {
const file = data.file;
const job = await upload({
file,
});
const text = await job.markdown();
sendEvent(storeEvent.with(text));
} else if (data.search) {
const search = data.search;
sendEvent(searchEvent.with(search));
}
},
(stream) => stream.until(stopEvent),
);
30 changes: 30 additions & 0 deletions demo/waku/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { RAG } from "../components/RAG";

export default async function HomePage() {
const data = await getData();

return (
<div>
<title>{data.title}</title>
<h1 className="text-4xl font-bold tracking-tight">{data.headline}</h1>
<p>{data.body}</p>
<RAG />
</div>
);
}

const getData = async () => {
const data = {
title: "Waku",
headline: "Waku",
body: "Hello world!",
};

return data;
};

export const getConfig = async () => {
return {
render: "static",
} as const;
};
Loading