Skip to content
Snippets Groups Projects
Commit 21cd88ca authored by yisding's avatar yisding
Browse files

prettier

parent 0660d9e2
No related branches found
No related tags found
No related merge requests found
Showing
with 150 additions and 144 deletions
...@@ -89,7 +89,7 @@ Check out our NextJS playground at https://llama-playground.vercel.app/. The sou ...@@ -89,7 +89,7 @@ Check out our NextJS playground at https://llama-playground.vercel.app/. The sou
If you're using NextJS App Router, you'll need to use the NodeJS runtime (default) and add the follow config to your next.config.js to have it use imports/exports in the same way Node does. If you're using NextJS App Router, you'll need to use the NodeJS runtime (default) and add the follow config to your next.config.js to have it use imports/exports in the same way Node does.
```js ```js
export const runtime = "nodejs" // default export const runtime = "nodejs"; // default
``` ```
```js ```js
......
...@@ -11,7 +11,7 @@ LlamaIndex currently officially supports NodeJS 18 and NodeJS 20. ...@@ -11,7 +11,7 @@ LlamaIndex currently officially supports NodeJS 18 and NodeJS 20.
If you're using NextJS App Router route handlers/serverless functions, you'll need to use the NodeJS mode: If you're using NextJS App Router route handlers/serverless functions, you'll need to use the NodeJS mode:
```js ```js
export const runtime = "nodejs" // default export const runtime = "nodejs"; // default
``` ```
and you'll need to add an exception for pdf-parse in your next.config.js and you'll need to add an exception for pdf-parse in your next.config.js
......
import { ChatMessage, OpenAI, SimpleChatEngine } from "llamaindex"; import { ChatMessage, SimpleChatEngine } from "llamaindex";
import {Anthropic} from "../../packages/core/src/llm/LLM";
import { stdin as input, stdout as output } from "node:process"; import { stdin as input, stdout as output } from "node:process";
import readline from "node:readline/promises"; import readline from "node:readline/promises";
import { Anthropic } from "../../packages/core/src/llm/LLM";
async function main() { async function main() {
const query: string = ` const query: string = `
......
import { MongoClient } from "mongodb"; import { MongoClient } from "mongodb";
import { VectorStoreIndex } from "../../packages/core/src/indices";
import { Document } from "../../packages/core/src/Node"; import { Document } from "../../packages/core/src/Node";
import { VectorStoreIndex } from "../../packages/core/src/indices";
import { SimpleMongoReader } from "../../packages/core/src/readers/SimpleMongoReader"; import { SimpleMongoReader } from "../../packages/core/src/readers/SimpleMongoReader";
import { stdin as input, stdout as output } from "node:process"; import { stdin as input, stdout as output } from "node:process";
......
import { Portkey } from "llamaindex"; import { Portkey } from "llamaindex";
(async () => { (async () => {
const llms = [{ const llms = [{}];
}]
const portkey = new Portkey({ const portkey = new Portkey({
mode: "single", mode: "single",
llms: [{ llms: [
provider:"anyscale", {
virtual_key:"anyscale-3b3c04", provider: "anyscale",
model: "meta-llama/Llama-2-13b-chat-hf", virtual_key: "anyscale-3b3c04",
max_tokens: 2000 model: "meta-llama/Llama-2-13b-chat-hf",
}] max_tokens: 2000,
},
],
}); });
const result = portkey.stream_chat([ const result = portkey.stream_chat([
{ role: "system", content: "You are a helpful assistant." }, { role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Tell me a joke." } { role: "user", content: "Tell me a joke." },
]); ]);
for await (const res of result) { for await (const res of result) {
process.stdout.write(res) process.stdout.write(res);
} }
})(); })();
import { Portkey } from "llamaindex"; import { Portkey } from "llamaindex";
(async () => { (async () => {
const llms = [{ const llms = [{}];
}]
const portkey = new Portkey({ const portkey = new Portkey({
mode: "single", mode: "single",
llms: [{ llms: [
provider:"anyscale", {
virtual_key:"anyscale-3b3c04", provider: "anyscale",
model: "meta-llama/Llama-2-13b-chat-hf", virtual_key: "anyscale-3b3c04",
max_tokens: 2000 model: "meta-llama/Llama-2-13b-chat-hf",
}] max_tokens: 2000,
},
],
}); });
const result = portkey.stream_chat([ const result = portkey.stream_chat([
{ role: "system", content: "You are a helpful assistant." }, { role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Tell me a joke." } { role: "user", content: "Tell me a joke." },
]); ]);
for await (const res of result) { for await (const res of result) {
process.stdout.write(res) process.stdout.write(res);
} }
})(); })();
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"scripts": { "scripts": {
"build": "turbo run build", "build": "turbo run build",
"dev": "turbo run dev", "dev": "turbo run dev",
"format": "prettier --write \"**/*.{ts,tsx,md}\"", "format": "prettier --write \"**/*.{js,jsx,ts,tsx,md}\"",
"lint": "turbo run lint", "lint": "turbo run lint",
"prepare": "husky install", "prepare": "husky install",
"test": "turbo run test", "test": "turbo run test",
...@@ -12,17 +12,17 @@ ...@@ -12,17 +12,17 @@
}, },
"devDependencies": { "devDependencies": {
"@turbo/gen": "^1.10.16", "@turbo/gen": "^1.10.16",
"@types/jest": "^29.5.6", "@types/jest": "^29.5.8",
"eslint": "^8.52.0", "eslint": "^8.53.0",
"eslint-config-custom": "workspace:*", "eslint-config-custom": "workspace:*",
"husky": "^8.0.3", "husky": "^8.0.3",
"jest": "^29.7.0", "jest": "^29.7.0",
"prettier": "^3.0.3", "prettier": "^3.1.0",
"prettier-plugin-organize-imports": "^3.2.3", "prettier-plugin-organize-imports": "^3.2.4",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"turbo": "^1.10.16" "turbo": "^1.10.16"
}, },
"packageManager": "pnpm@8.10.4+sha256.df3202c6c8fd345be5ba6a4199297582d5bebf8963822aa3344f4cd2b8be8d43", "packageManager": "pnpm@8.10.5+sha256.a4bd9bb7b48214bbfcd95f264bd75bb70d100e5d4b58808f5cd6ab40c6ac21c5",
"dependencies": { "dependencies": {
"@changesets/cli": "^2.26.2" "@changesets/cli": "^2.26.2"
}, },
......
import { encodingForModel, TiktokenModel } from "js-tiktoken"; import { encodingForModel } from "js-tiktoken";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { Event, EventTag, EventType } from "./callbacks/CallbackManager"; import { Event, EventTag, EventType } from "./callbacks/CallbackManager";
...@@ -27,7 +27,7 @@ class GlobalsHelper { ...@@ -27,7 +27,7 @@ class GlobalsHelper {
const numberArray = Array.from(tokens); const numberArray = Array.from(tokens);
const text = encoding.decode(numberArray); const text = encoding.decode(numberArray);
const uint8Array = new TextEncoder().encode(text); const uint8Array = new TextEncoder().encode(text);
return new TextDecoder().decode(uint8Array); return new TextDecoder().decode(uint8Array);
}, },
}; };
} }
...@@ -39,10 +39,10 @@ class GlobalsHelper { ...@@ -39,10 +39,10 @@ class GlobalsHelper {
if (!this.defaultTokenizer) { if (!this.defaultTokenizer) {
this.initDefaultTokenizer(); this.initDefaultTokenizer();
} }
return this.defaultTokenizer!.encode.bind(this.defaultTokenizer); return this.defaultTokenizer!.encode.bind(this.defaultTokenizer);
} }
tokenizerDecoder(encoding?: string) { tokenizerDecoder(encoding?: string) {
if (encoding && encoding !== Tokenizers.CL100K_BASE) { if (encoding && encoding !== Tokenizers.CL100K_BASE) {
throw new Error(`Tokenizer encoding ${encoding} not yet supported`); throw new Error(`Tokenizer encoding ${encoding} not yet supported`);
...@@ -50,7 +50,7 @@ class GlobalsHelper { ...@@ -50,7 +50,7 @@ class GlobalsHelper {
if (!this.defaultTokenizer) { if (!this.defaultTokenizer) {
this.initDefaultTokenizer(); this.initDefaultTokenizer();
} }
return this.defaultTokenizer!.decode.bind(this.defaultTokenizer); return this.defaultTokenizer!.decode.bind(this.defaultTokenizer);
} }
......
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { Event } from "./callbacks/CallbackManager";
import { BaseNodePostprocessor } from "./indices/BaseNodePostprocessor";
import { NodeWithScore, TextNode } from "./Node"; import { NodeWithScore, TextNode } from "./Node";
import { import {
BaseQuestionGenerator, BaseQuestionGenerator,
...@@ -12,6 +10,8 @@ import { CompactAndRefine, ResponseSynthesizer } from "./ResponseSynthesizer"; ...@@ -12,6 +10,8 @@ import { CompactAndRefine, ResponseSynthesizer } from "./ResponseSynthesizer";
import { BaseRetriever } from "./Retriever"; import { BaseRetriever } from "./Retriever";
import { ServiceContext, serviceContextFromDefaults } from "./ServiceContext"; import { ServiceContext, serviceContextFromDefaults } from "./ServiceContext";
import { QueryEngineTool, ToolMetadata } from "./Tool"; import { QueryEngineTool, ToolMetadata } from "./Tool";
import { Event } from "./callbacks/CallbackManager";
import { BaseNodePostprocessor } from "./indices/BaseNodePostprocessor";
/** /**
* A query engine is a question answerer that can use one or more steps. * A query engine is a question answerer that can use one or more steps.
......
export * from "./callbacks/CallbackManager";
export * from "./ChatEngine"; export * from "./ChatEngine";
export * from "./ChatHistory"; export * from "./ChatHistory";
export * from "./constants";
export * from "./Embedding"; export * from "./Embedding";
export * from "./GlobalsHelper"; export * from "./GlobalsHelper";
export * from "./indices";
export * from "./llm/LLM";
export * from "./Node"; export * from "./Node";
export * from "./NodeParser"; export * from "./NodeParser";
export * from "./OutputParser"; export * from "./OutputParser";
...@@ -13,17 +9,21 @@ export * from "./Prompt"; ...@@ -13,17 +9,21 @@ export * from "./Prompt";
export * from "./PromptHelper"; export * from "./PromptHelper";
export * from "./QueryEngine"; export * from "./QueryEngine";
export * from "./QuestionGenerator"; export * from "./QuestionGenerator";
export * from "./readers/base";
export * from "./readers/CSVReader";
export * from "./readers/MarkdownReader";
export * from "./readers/NotionReader";
export * from "./readers/PDFReader";
export * from "./readers/HTMLReader";
export * from "./readers/SimpleDirectoryReader";
export * from "./Response"; export * from "./Response";
export * from "./ResponseSynthesizer"; export * from "./ResponseSynthesizer";
export * from "./Retriever"; export * from "./Retriever";
export * from "./ServiceContext"; export * from "./ServiceContext";
export * from "./storage";
export * from "./TextSplitter"; export * from "./TextSplitter";
export * from "./Tool"; export * from "./Tool";
export * from "./callbacks/CallbackManager";
export * from "./constants";
export * from "./indices";
export * from "./llm/LLM";
export * from "./readers/CSVReader";
export * from "./readers/HTMLReader";
export * from "./readers/MarkdownReader";
export * from "./readers/NotionReader";
export * from "./readers/PDFReader";
export * from "./readers/SimpleDirectoryReader";
export * from "./readers/base";
export * from "./storage";
...@@ -10,11 +10,11 @@ import { ...@@ -10,11 +10,11 @@ import {
ServiceContext, ServiceContext,
serviceContextFromDefaults, serviceContextFromDefaults,
} from "../../ServiceContext"; } from "../../ServiceContext";
import { BaseDocumentStore, RefDocInfo } from "../../storage/docStore/types";
import { import {
StorageContext, StorageContext,
storageContextFromDefaults, storageContextFromDefaults,
} from "../../storage/StorageContext"; } from "../../storage/StorageContext";
import { BaseDocumentStore, RefDocInfo } from "../../storage/docStore/types";
import { import {
BaseIndex, BaseIndex,
BaseIndexInit, BaseIndexInit,
......
...@@ -32,7 +32,11 @@ export class VectorIndexRetriever implements BaseRetriever { ...@@ -32,7 +32,11 @@ export class VectorIndexRetriever implements BaseRetriever {
this.similarityTopK = similarityTopK ?? DEFAULT_SIMILARITY_TOP_K; this.similarityTopK = similarityTopK ?? DEFAULT_SIMILARITY_TOP_K;
} }
async retrieve(query: string, parentEvent?: Event, preFilters?: unknown): Promise<NodeWithScore[]> { async retrieve(
query: string,
parentEvent?: Event,
preFilters?: unknown,
): Promise<NodeWithScore[]> {
const queryEmbedding = const queryEmbedding =
await this.serviceContext.embedModel.getQueryEmbedding(query); await this.serviceContext.embedModel.getQueryEmbedding(query);
......
import _ from "lodash"; import _ from "lodash";
import { LLMOptions, Portkey } from "portkey-ai"; import { LLMOptions, Portkey } from "portkey-ai";
export const readEnv = (env: string, default_val?: string): string | undefined => { export const readEnv = (
if (typeof process !== 'undefined') { env: string,
return process.env?.[env] ?? default_val; default_val?: string,
): string | undefined => {
if (typeof process !== "undefined") {
return process.env?.[env] ?? default_val;
} }
return default_val; return default_val;
}; };
...@@ -12,23 +15,23 @@ interface PortkeyOptions { ...@@ -12,23 +15,23 @@ interface PortkeyOptions {
apiKey?: string; apiKey?: string;
baseURL?: string; baseURL?: string;
mode?: string; mode?: string;
llms?: [LLMOptions] | null llms?: [LLMOptions] | null;
} }
export class PortkeySession { export class PortkeySession {
portkey: Portkey; portkey: Portkey;
constructor(options:PortkeyOptions = {}) { constructor(options: PortkeyOptions = {}) {
if (!options.apiKey) { if (!options.apiKey) {
options.apiKey = readEnv('PORTKEY_API_KEY') options.apiKey = readEnv("PORTKEY_API_KEY");
} }
if (!options.baseURL) { if (!options.baseURL) {
options.baseURL = readEnv('PORTKEY_BASE_URL', "https://api.portkey.ai") options.baseURL = readEnv("PORTKEY_BASE_URL", "https://api.portkey.ai");
} }
this.portkey = new Portkey({}); this.portkey = new Portkey({});
this.portkey.llms = [{}] this.portkey.llms = [{}];
if (!options.apiKey) { if (!options.apiKey) {
throw new Error("Set Portkey ApiKey in PORTKEY_API_KEY env variable"); throw new Error("Set Portkey ApiKey in PORTKEY_API_KEY env variable");
} }
...@@ -59,4 +62,3 @@ export function getPortkeySession(options: PortkeyOptions = {}) { ...@@ -59,4 +62,3 @@ export function getPortkeySession(options: PortkeyOptions = {}) {
} }
return session; return session;
} }
import mammoth from "mammoth"; import mammoth from "mammoth";
import { Document } from "../Node"; import { Document } from "../Node";
import { DEFAULT_FS } from "../storage/constants";
import { GenericFileSystem } from "../storage/FileSystem"; import { GenericFileSystem } from "../storage/FileSystem";
import { DEFAULT_FS } from "../storage/constants";
import { BaseReader } from "./base"; import { BaseReader } from "./base";
export class DocxReader implements BaseReader { export class DocxReader implements BaseReader {
......
...@@ -79,10 +79,10 @@ const program = new Commander.Command(packageJson.name) ...@@ -79,10 +79,10 @@ const program = new Commander.Command(packageJson.name)
const packageManager = !!program.useNpm const packageManager = !!program.useNpm
? "npm" ? "npm"
: !!program.usePnpm : !!program.usePnpm
? "pnpm" ? "pnpm"
: !!program.useYarn : !!program.useYarn
? "yarn" ? "yarn"
: getPkgManager(); : getPkgManager();
async function run(): Promise<void> { async function run(): Promise<void> {
const conf = new Conf({ projectName: "create-llama" }); const conf = new Conf({ projectName: "create-llama" });
...@@ -235,8 +235,8 @@ async function run(): Promise<void> { ...@@ -235,8 +235,8 @@ async function run(): Promise<void> {
program.framework === "express" program.framework === "express"
? "Express " ? "Express "
: program.framework === "fastapi" : program.framework === "fastapi"
? "FastAPI (Python) " ? "FastAPI (Python) "
: "", : "",
); );
const { frontend } = await prompts({ const { frontend } = await prompts({
onState: onPromptState, onState: onPromptState,
...@@ -364,8 +364,8 @@ async function notifyUpdate(): Promise<void> { ...@@ -364,8 +364,8 @@ async function notifyUpdate(): Promise<void> {
packageManager === "yarn" packageManager === "yarn"
? "yarn global add create-llama@latest" ? "yarn global add create-llama@latest"
: packageManager === "pnpm" : packageManager === "pnpm"
? "pnpm add -g create-llama@latest" ? "pnpm add -g create-llama@latest"
: "npm i -g create-llama@latest"; : "npm i -g create-llama@latest";
console.log( console.log(
yellow(bold("A new version of `create-llama` is available!")) + yellow(bold("A new version of `create-llama` is available!")) +
......
"use client" "use client";
import React, { FC, memo } from "react" import { Check, Copy, Download } from "lucide-react";
import { Check, Copy, Download } from "lucide-react" import { FC, memo } from "react";
import { Prism, SyntaxHighlighterProps } from "react-syntax-highlighter" import { Prism, SyntaxHighlighterProps } from "react-syntax-highlighter";
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism" import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { Button } from "../button" import { Button } from "../button";
import { useCopyToClipboard } from "./use-copy-to-clipboard" import { useCopyToClipboard } from "./use-copy-to-clipboard";
// TODO: Remove this when @type/react-syntax-highlighter is updated // TODO: Remove this when @type/react-syntax-highlighter is updated
const SyntaxHighlighter = Prism as unknown as FC<SyntaxHighlighterProps> const SyntaxHighlighter = Prism as unknown as FC<SyntaxHighlighterProps>;
interface Props { interface Props {
language: string language: string;
value: string value: string;
} }
interface languageMap { interface languageMap {
[key: string]: string | undefined [key: string]: string | undefined;
} }
export const programmingLanguages: languageMap = { export const programmingLanguages: languageMap = {
...@@ -45,52 +45,52 @@ export const programmingLanguages: languageMap = { ...@@ -45,52 +45,52 @@ export const programmingLanguages: languageMap = {
html: ".html", html: ".html",
css: ".css", css: ".css",
// add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
} };
export const generateRandomString = (length: number, lowercase = false) => { export const generateRandomString = (length: number, lowercase = false) => {
const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789" // excluding similar looking characters like Z, 2, I, 1, O, 0 const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789"; // excluding similar looking characters like Z, 2, I, 1, O, 0
let result = "" let result = "";
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length)) result += chars.charAt(Math.floor(Math.random() * chars.length));
} }
return lowercase ? result.toLowerCase() : result return lowercase ? result.toLowerCase() : result;
} };
const CodeBlock: FC<Props> = memo(({ language, value }) => { const CodeBlock: FC<Props> = memo(({ language, value }) => {
const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }) const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 });
const downloadAsFile = () => { const downloadAsFile = () => {
if (typeof window === "undefined") { if (typeof window === "undefined") {
return return;
} }
const fileExtension = programmingLanguages[language] || ".file" const fileExtension = programmingLanguages[language] || ".file";
const suggestedFileName = `file-${generateRandomString( const suggestedFileName = `file-${generateRandomString(
3, 3,
true true,
)}${fileExtension}` )}${fileExtension}`;
const fileName = window.prompt("Enter file name" || "", suggestedFileName) const fileName = window.prompt("Enter file name" || "", suggestedFileName);
if (!fileName) { if (!fileName) {
// User pressed cancel on prompt. // User pressed cancel on prompt.
return return;
} }
const blob = new Blob([value], { type: "text/plain" }) const blob = new Blob([value], { type: "text/plain" });
const url = URL.createObjectURL(blob) const url = URL.createObjectURL(blob);
const link = document.createElement("a") const link = document.createElement("a");
link.download = fileName link.download = fileName;
link.href = url link.href = url;
link.style.display = "none" link.style.display = "none";
document.body.appendChild(link) document.body.appendChild(link);
link.click() link.click();
document.body.removeChild(link) document.body.removeChild(link);
URL.revokeObjectURL(url) URL.revokeObjectURL(url);
} };
const onCopy = () => { const onCopy = () => {
if (isCopied) return if (isCopied) return;
copyToClipboard(value) copyToClipboard(value);
} };
return ( return (
<div className="codeblock relative w-full bg-zinc-950 font-sans"> <div className="codeblock relative w-full bg-zinc-950 font-sans">
...@@ -132,8 +132,8 @@ const CodeBlock: FC<Props> = memo(({ language, value }) => { ...@@ -132,8 +132,8 @@ const CodeBlock: FC<Props> = memo(({ language, value }) => {
{value} {value}
</SyntaxHighlighter> </SyntaxHighlighter>
</div> </div>
) );
}) });
CodeBlock.displayName = "CodeBlock" CodeBlock.displayName = "CodeBlock";
export { CodeBlock } export { CodeBlock };
...@@ -2,4 +2,4 @@ import ChatInput from "./chat-input"; ...@@ -2,4 +2,4 @@ import ChatInput from "./chat-input";
import ChatMessages from "./chat-messages"; import ChatMessages from "./chat-messages";
export { type ChatHandler, type Message } from "./chat.interface"; export { type ChatHandler, type Message } from "./chat.interface";
export { ChatMessages, ChatInput }; export { ChatInput, ChatMessages };
import { FC, memo } from "react" import { FC, memo } from "react";
import ReactMarkdown, { Options } from "react-markdown" import ReactMarkdown, { Options } from "react-markdown";
import remarkGfm from "remark-gfm" import remarkGfm from "remark-gfm";
import remarkMath from "remark-math" import remarkMath from "remark-math";
import { CodeBlock } from "./codeblock" import { CodeBlock } from "./codeblock";
const MemoizedReactMarkdown: FC<Options> = memo( const MemoizedReactMarkdown: FC<Options> = memo(
ReactMarkdown, ReactMarkdown,
(prevProps, nextProps) => (prevProps, nextProps) =>
prevProps.children === nextProps.children && prevProps.children === nextProps.children &&
prevProps.className === nextProps.className prevProps.className === nextProps.className,
) );
export default function Markdown({ content }: { content: string }) { export default function Markdown({ content }: { content: string }) {
return ( return (
...@@ -19,27 +19,27 @@ export default function Markdown({ content }: { content: string }) { ...@@ -19,27 +19,27 @@ export default function Markdown({ content }: { content: string }) {
remarkPlugins={[remarkGfm, remarkMath]} remarkPlugins={[remarkGfm, remarkMath]}
components={{ components={{
p({ children }) { p({ children }) {
return <p className="mb-2 last:mb-0">{children}</p> return <p className="mb-2 last:mb-0">{children}</p>;
}, },
code({ node, inline, className, children, ...props }) { code({ node, inline, className, children, ...props }) {
if (children.length) { if (children.length) {
if (children[0] == "") { if (children[0] == "") {
return ( return (
<span className="mt-1 animate-pulse cursor-default"></span> <span className="mt-1 animate-pulse cursor-default"></span>
) );
} }
children[0] = (children[0] as string).replace("`▍`", "") children[0] = (children[0] as string).replace("`▍`", "");
} }
const match = /language-(\w+)/.exec(className || "") const match = /language-(\w+)/.exec(className || "");
if (inline) { if (inline) {
return ( return (
<code className={className} {...props}> <code className={className} {...props}>
{children} {children}
</code> </code>
) );
} }
return ( return (
...@@ -49,11 +49,11 @@ export default function Markdown({ content }: { content: string }) { ...@@ -49,11 +49,11 @@ export default function Markdown({ content }: { content: string }) {
value={String(children).replace(/\n$/, "")} value={String(children).replace(/\n$/, "")}
{...props} {...props}
/> />
) );
}, },
}} }}
> >
{content} {content}
</MemoizedReactMarkdown> </MemoizedReactMarkdown>
) );
} }
'use client' "use client";
import * as React from 'react' import * as React from "react";
export interface useCopyToClipboardProps { export interface useCopyToClipboardProps {
timeout?: number timeout?: number;
} }
export function useCopyToClipboard({ export function useCopyToClipboard({
timeout = 2000 timeout = 2000,
}: useCopyToClipboardProps) { }: useCopyToClipboardProps) {
const [isCopied, setIsCopied] = React.useState<Boolean>(false) const [isCopied, setIsCopied] = React.useState<Boolean>(false);
const copyToClipboard = (value: string) => { const copyToClipboard = (value: string) => {
if (typeof window === 'undefined' || !navigator.clipboard?.writeText) { if (typeof window === "undefined" || !navigator.clipboard?.writeText) {
return return;
} }
if (!value) { if (!value) {
return return;
} }
navigator.clipboard.writeText(value).then(() => { navigator.clipboard.writeText(value).then(() => {
setIsCopied(true) setIsCopied(true);
setTimeout(() => { setTimeout(() => {
setIsCopied(false) setIsCopied(false);
}, timeout) }, timeout);
}) });
} };
return { isCopied, copyToClipboard } return { isCopied, copyToClipboard };
} }
...@@ -3,4 +3,4 @@ import ChatMessages from "./chat-messages"; ...@@ -3,4 +3,4 @@ import ChatMessages from "./chat-messages";
export type { ChatInputProps } from "./chat-input"; export type { ChatInputProps } from "./chat-input";
export type { Message } from "./chat-messages"; export type { Message } from "./chat-messages";
export { ChatMessages, ChatInput }; export { ChatInput, ChatMessages };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment