enzostvs HF Staff commited on
Commit
318e485
·
1 Parent(s): 050d6a1
app/api/ask/route.ts CHANGED
@@ -78,19 +78,10 @@ export async function POST(request: Request) {
78
  : []),
79
  {
80
  role: "user",
81
- content: `
82
- ${prompt}
83
- ${
84
- mentions?.length > 0
85
- ? `\n\nHere are the informations about the model or dataset that the user has mentioned to use: ${mentions
86
- .map(
87
- (mention: any) =>
88
- `Library: ${mention.library_name}\nPipeline: ${mention.pipeline_tag}\nModel: ${mention.model_id}\nReadme for more information: \n${mention.readme}`
89
- )
90
- .join("\n")}`
91
- : ""
92
- }
93
- `,
94
  },
95
  ],
96
  stream: true,
 
78
  : []),
79
  {
80
  role: "user",
81
+ content: `${
82
+ redesignMd?.url &&
83
+ `Redesign the following website ${redesignMd.url}, try to use the same images and content, but you can still improve it if needed. Do the best version possibile. Here is the markdown:\n ${redesignMd.md} \n\n`
84
+ }${prompt}`,
 
 
 
 
 
 
 
 
 
85
  },
86
  ],
87
  stream: true,
components/ask-ai/ask-ai.tsx CHANGED
@@ -1,6 +1,6 @@
1
  "use client";
2
  import { ArrowUp, Paintbrush, X } from "lucide-react";
3
- import { useState } from "react";
4
  import { HiStop } from "react-icons/hi2";
5
  import { useLocalStorage, useMount } from "react-use";
6
  import { useRouter } from "next/navigation";
@@ -15,8 +15,6 @@ import { Redesign } from "./redesign";
15
  import { Uploader } from "./uploader";
16
  import { InputMentions } from "./input-mentions";
17
 
18
- // todo: send redesignMd to callAi + add it to the prompt
19
-
20
  export function AskAI({
21
  initialPrompt,
22
  className,
@@ -34,6 +32,7 @@ export function AskAI({
34
  isHistoryView?: boolean;
35
  projectName?: string;
36
  }) {
 
37
  const [prompt, setPrompt] = useState(initialPrompt ?? "");
38
  const [model = MODELS[0].value, setModel] = useLocalStorage<string>(
39
  "model",
@@ -81,6 +80,9 @@ export function AskAI({
81
 
82
  const onSubmit = () => {
83
  if (isHistoryView) return;
 
 
 
84
  callAi({ prompt, model, onComplete, provider, redesignMd });
85
  };
86
 
@@ -92,6 +94,7 @@ export function AskAI({
92
  )}
93
  >
94
  <InputMentions
 
95
  files={files}
96
  prompt={prompt}
97
  setPrompt={setPrompt}
@@ -145,7 +148,11 @@ export function AskAI({
145
  <Button
146
  size="icon-sm"
147
  className="rounded-full!"
148
- disabled={!prompt.trim() || isLoading || isHistoryView}
 
 
 
 
149
  onClick={onSubmit}
150
  >
151
  <ArrowUp />
 
1
  "use client";
2
  import { ArrowUp, Paintbrush, X } from "lucide-react";
3
+ import { useRef, useState } from "react";
4
  import { HiStop } from "react-icons/hi2";
5
  import { useLocalStorage, useMount } from "react-use";
6
  import { useRouter } from "next/navigation";
 
15
  import { Uploader } from "./uploader";
16
  import { InputMentions } from "./input-mentions";
17
 
 
 
18
  export function AskAI({
19
  initialPrompt,
20
  className,
 
32
  isHistoryView?: boolean;
33
  projectName?: string;
34
  }) {
35
+ const contentEditableRef = useRef<HTMLDivElement | null>(null);
36
  const [prompt, setPrompt] = useState(initialPrompt ?? "");
37
  const [model = MODELS[0].value, setModel] = useLocalStorage<string>(
38
  "model",
 
80
 
81
  const onSubmit = () => {
82
  if (isHistoryView) return;
83
+ if (contentEditableRef.current) {
84
+ contentEditableRef.current.innerHTML = "";
85
+ }
86
  callAi({ prompt, model, onComplete, provider, redesignMd });
87
  };
88
 
 
94
  )}
95
  >
96
  <InputMentions
97
+ ref={contentEditableRef}
98
  files={files}
99
  prompt={prompt}
100
  setPrompt={setPrompt}
 
148
  <Button
149
  size="icon-sm"
150
  className="rounded-full!"
151
+ disabled={
152
+ isHistoryView ||
153
+ isLoading ||
154
+ (prompt.trim() === "" && !redesignMd)
155
+ }
156
  onClick={onSubmit}
157
  >
158
  <ArrowUp />
components/ask-ai/input-mentions.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useRef, useState, useEffect } from "react";
2
  import { useClickAway } from "react-use";
3
  import { useQueryClient } from "@tanstack/react-query";
4
 
@@ -7,12 +7,14 @@ import { File } from "@/lib/type";
7
  import { Braces, FileCode, FileText } from "lucide-react";
8
 
9
  export function InputMentions({
 
10
  prompt,
11
  files,
12
  setPrompt,
13
  redesignMdUrl,
14
  onSubmit,
15
  }: {
 
16
  prompt: string;
17
  files?: File[] | null;
18
  redesignMdUrl?: string;
@@ -22,7 +24,6 @@ export function InputMentions({
22
  const queryClient = useQueryClient();
23
  const [showMentionDropdown, setShowMentionDropdown] = useState(false);
24
  const [, setMentionSearch] = useState("");
25
- const contentEditableRef = useRef<HTMLDivElement>(null);
26
  const dropdownRef = useRef<HTMLDivElement>(null);
27
  const [results, setResults] = useState<File[]>([]);
28
 
@@ -51,10 +52,10 @@ export function InputMentions({
51
  };
52
 
53
  const extractPromptWithIds = (): string => {
54
- if (!contentEditableRef.current) return "";
55
 
56
  let text = "";
57
- const childNodes = contentEditableRef.current.childNodes;
58
 
59
  for (let i = 0; i < childNodes.length; i++) {
60
  const node = childNodes[i];
@@ -77,7 +78,7 @@ export function InputMentions({
77
  textBeforeCursor: string;
78
  } => {
79
  const selection = window.getSelection();
80
- if (!selection || !contentEditableRef.current) {
81
  return { detect: false, textBeforeCursor: "" };
82
  }
83
 
@@ -113,10 +114,10 @@ export function InputMentions({
113
  };
114
 
115
  const handleInput = async () => {
116
- if (!contentEditableRef.current) return;
117
- const text = getTextContent(contentEditableRef.current);
118
  if (text.trim() === "") {
119
- contentEditableRef.current.innerHTML = "";
120
  }
121
  setPrompt(text);
122
 
@@ -150,7 +151,7 @@ export function InputMentions({
150
  };
151
 
152
  const insertMention = (mentionId: string) => {
153
- if (!contentEditableRef.current) return;
154
 
155
  const selection = window.getSelection();
156
  if (!selection || selection.rangeCount === 0) return;
@@ -201,7 +202,7 @@ export function InputMentions({
201
  selection.removeAllRanges();
202
  selection.addRange(newRange);
203
 
204
- const newText = getTextContent(contentEditableRef.current);
205
  setPrompt(newText);
206
  setShowMentionDropdown(false);
207
  setMentionSearch("");
@@ -217,8 +218,8 @@ export function InputMentions({
217
  setPrompt(promptWithIds);
218
  onSubmit();
219
 
220
- if (contentEditableRef.current) {
221
- contentEditableRef.current.innerHTML = "";
222
  }
223
  setPrompt("");
224
  setShowMentionDropdown(false);
@@ -228,12 +229,8 @@ export function InputMentions({
228
  };
229
 
230
  useEffect(() => {
231
- if (
232
- contentEditableRef.current &&
233
- prompt === "" &&
234
- contentEditableRef.current.innerHTML !== ""
235
- ) {
236
- contentEditableRef.current.innerHTML = "";
237
  }
238
  }, [prompt]);
239
 
@@ -247,12 +244,12 @@ export function InputMentions({
247
  <div className="relative">
248
  <div
249
  id="prompt-input"
250
- ref={contentEditableRef}
251
  contentEditable
252
  className="pb-2 min-h-10 max-h-[130px] overflow-y-auto w-full h-full resize-none outline-none text-primary text-sm bg-transparent empty:before:block empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground empty:before:pointer-events-none"
253
  data-placeholder={
254
  redesignMdUrl
255
- ? `Ask me anything about ${redesignMdUrl}...`
256
  : files && files.length > 0
257
  ? "Ask me anything. Type @ to mention a file..."
258
  : "Ask me anything..."
 
1
+ import { useRef, useState, useEffect, RefObject } from "react";
2
  import { useClickAway } from "react-use";
3
  import { useQueryClient } from "@tanstack/react-query";
4
 
 
7
  import { Braces, FileCode, FileText } from "lucide-react";
8
 
9
  export function InputMentions({
10
+ ref,
11
  prompt,
12
  files,
13
  setPrompt,
14
  redesignMdUrl,
15
  onSubmit,
16
  }: {
17
+ ref: RefObject<HTMLDivElement | null>;
18
  prompt: string;
19
  files?: File[] | null;
20
  redesignMdUrl?: string;
 
24
  const queryClient = useQueryClient();
25
  const [showMentionDropdown, setShowMentionDropdown] = useState(false);
26
  const [, setMentionSearch] = useState("");
 
27
  const dropdownRef = useRef<HTMLDivElement>(null);
28
  const [results, setResults] = useState<File[]>([]);
29
 
 
52
  };
53
 
54
  const extractPromptWithIds = (): string => {
55
+ if (!ref.current) return "";
56
 
57
  let text = "";
58
+ const childNodes = ref.current.childNodes;
59
 
60
  for (let i = 0; i < childNodes.length; i++) {
61
  const node = childNodes[i];
 
78
  textBeforeCursor: string;
79
  } => {
80
  const selection = window.getSelection();
81
+ if (!selection || !ref.current) {
82
  return { detect: false, textBeforeCursor: "" };
83
  }
84
 
 
114
  };
115
 
116
  const handleInput = async () => {
117
+ if (!ref.current) return;
118
+ const text = getTextContent(ref.current);
119
  if (text.trim() === "") {
120
+ ref.current.innerHTML = "";
121
  }
122
  setPrompt(text);
123
 
 
151
  };
152
 
153
  const insertMention = (mentionId: string) => {
154
+ if (!ref.current) return;
155
 
156
  const selection = window.getSelection();
157
  if (!selection || selection.rangeCount === 0) return;
 
202
  selection.removeAllRanges();
203
  selection.addRange(newRange);
204
 
205
+ const newText = getTextContent(ref.current);
206
  setPrompt(newText);
207
  setShowMentionDropdown(false);
208
  setMentionSearch("");
 
218
  setPrompt(promptWithIds);
219
  onSubmit();
220
 
221
+ if (ref.current) {
222
+ ref.current.innerHTML = "";
223
  }
224
  setPrompt("");
225
  setShowMentionDropdown(false);
 
229
  };
230
 
231
  useEffect(() => {
232
+ if (ref.current && prompt === "" && ref.current.innerHTML !== "") {
233
+ ref.current.innerHTML = "";
 
 
 
 
234
  }
235
  }, [prompt]);
236
 
 
244
  <div className="relative">
245
  <div
246
  id="prompt-input"
247
+ ref={ref}
248
  contentEditable
249
  className="pb-2 min-h-10 max-h-[130px] overflow-y-auto w-full h-full resize-none outline-none text-primary text-sm bg-transparent empty:before:block empty:before:content-[attr(data-placeholder)] empty:before:text-muted-foreground empty:before:pointer-events-none"
250
  data-placeholder={
251
  redesignMdUrl
252
+ ? `I'll redesign ${redesignMdUrl}, want to add something?`
253
  : files && files.length > 0
254
  ? "Ask me anything. Type @ to mention a file..."
255
  : "Ask me anything..."
components/code/index.tsx CHANGED
@@ -13,12 +13,12 @@ import { AppEditorMonacoEditor } from "./monaco-editor";
13
  import { Button } from "@/components/ui/button";
14
  import { cn } from "@/lib/utils";
15
  import Loading from "../loading";
16
- import { useManualUpdates } from "../projects/useManualUpdates";
17
  import { ProjectWithCommits } from "@/actions/projects";
18
 
 
 
19
  export function AppEditorCode() {
20
  const queryClient = useQueryClient();
21
- const { isManuallyUpdatedSameAsFiles } = useManualUpdates();
22
  const { repoId } = useParams<{ repoId: string }>();
23
 
24
  const [isFileExplorerCollapsed, setIsFileExplorerCollapsed] = useState(true);
@@ -175,12 +175,11 @@ export function AppEditorCode() {
175
  </p>
176
  </div>
177
  <div className="flex items-center justify-end gap-2">
178
- {!isSavingChangesSuccess ||
179
- (!isSavingChanges && (
180
- <Button size="xs" variant="secondary" onClick={undoChanges}>
181
- Undo
182
- </Button>
183
- ))}
184
 
185
  {isSavingChangesSuccess || isSavingChangesError ? (
186
  <Button
 
13
  import { Button } from "@/components/ui/button";
14
  import { cn } from "@/lib/utils";
15
  import Loading from "../loading";
 
16
  import { ProjectWithCommits } from "@/actions/projects";
17
 
18
+ // todo: while no them setted but in dark mode, the dark theme is not setted correctly.
19
+
20
  export function AppEditorCode() {
21
  const queryClient = useQueryClient();
 
22
  const { repoId } = useParams<{ repoId: string }>();
23
 
24
  const [isFileExplorerCollapsed, setIsFileExplorerCollapsed] = useState(true);
 
175
  </p>
176
  </div>
177
  <div className="flex items-center justify-end gap-2">
178
+ {!isSavingChangesSuccess && !isSavingChanges && (
179
+ <Button size="xs" variant="secondary" onClick={undoChanges}>
180
+ Undo
181
+ </Button>
182
+ )}
 
183
 
184
  {isSavingChangesSuccess || isSavingChangesError ? (
185
  <Button
components/editor/index.tsx CHANGED
@@ -74,12 +74,12 @@ export function AppEditor({
74
  return (
75
  <SandpackProvider
76
  template="static"
77
- // options={{
78
- // initMode: "immediate",
79
- // autoReload: false,
80
- // recompileDelay: 3000,
81
- // recompileMode: "immediate",
82
- // }}
83
  files={sandpackFiles}
84
  // id={projectName}
85
  // key={projectName}
 
74
  return (
75
  <SandpackProvider
76
  template="static"
77
+ options={{
78
+ initMode: "immediate",
79
+ autoReload: false,
80
+ recompileDelay: 3000,
81
+ recompileMode: "immediate",
82
+ }}
83
  files={sandpackFiles}
84
  // id={projectName}
85
  // key={projectName}
components/user-menu/index.tsx CHANGED
@@ -32,14 +32,14 @@ export function UserMenu() {
32
  newUrl.searchParams.delete("signin");
33
  window.history.replaceState({}, "", newUrl.toString());
34
 
35
- signIn("huggingface", { callbackUrl: "/" });
36
  }
37
  }
38
  }, [session, status]);
39
 
40
  const handleSignIn = () => {
41
  if (window.location.hostname === "localhost") {
42
- signIn("huggingface", { callbackUrl: "/" });
43
  return;
44
  }
45
  const targetUrl = "https://enzostvs-deepsite-v4-demo.hf.space";
@@ -66,7 +66,7 @@ export function UserMenu() {
66
  if (!isOnTargetPage) {
67
  window.open(`${targetUrl}?signin=true`, "_blank");
68
  } else {
69
- signIn("huggingface", { callbackUrl: "/" });
70
  }
71
  };
72
 
 
32
  newUrl.searchParams.delete("signin");
33
  window.history.replaceState({}, "", newUrl.toString());
34
 
35
+ signIn("huggingface", { callbackUrl: "/deepsite" });
36
  }
37
  }
38
  }, [session, status]);
39
 
40
  const handleSignIn = () => {
41
  if (window.location.hostname === "localhost") {
42
+ signIn("huggingface", { callbackUrl: "/deepsite" });
43
  return;
44
  }
45
  const targetUrl = "https://enzostvs-deepsite-v4-demo.hf.space";
 
66
  if (!isOnTargetPage) {
67
  window.open(`${targetUrl}?signin=true`, "_blank");
68
  } else {
69
+ signIn("huggingface", { callbackUrl: "/deepsite" });
70
  }
71
  };
72
 
lib/auth.ts CHANGED
@@ -52,12 +52,13 @@ export const authConfig = {
52
  authorized({ auth, request: { nextUrl } }) {
53
  const isLoggedIn = !!auth?.user;
54
  const isOnNew = nextUrl.pathname.startsWith("/new");
55
-
56
  const pathSegments = nextUrl.pathname.split("/").filter(Boolean);
57
- const isOnProjectPage = pathSegments.length >= 2 &&
58
- !nextUrl.pathname.startsWith("/new") &&
59
- !nextUrl.pathname.startsWith("/api");
60
-
 
61
  if (isOnProjectPage || isOnNew) {
62
  if (isLoggedIn) return true;
63
  return false;
@@ -73,4 +74,3 @@ export const authConfig = {
73
  } satisfies NextAuthConfig;
74
 
75
  export const { handlers, auth, signIn, signOut } = NextAuth(authConfig);
76
-
 
52
  authorized({ auth, request: { nextUrl } }) {
53
  const isLoggedIn = !!auth?.user;
54
  const isOnNew = nextUrl.pathname.startsWith("/new");
55
+
56
  const pathSegments = nextUrl.pathname.split("/").filter(Boolean);
57
+ const isOnProjectPage =
58
+ pathSegments.length >= 2 &&
59
+ !nextUrl.pathname.startsWith("/new") &&
60
+ !nextUrl.pathname.startsWith("/api");
61
+
62
  if (isOnProjectPage || isOnNew) {
63
  if (isLoggedIn) return true;
64
  return false;
 
74
  } satisfies NextAuthConfig;
75
 
76
  export const { handlers, auth, signIn, signOut } = NextAuth(authConfig);
 
lib/format.ts CHANGED
@@ -9,6 +9,8 @@ import {
9
  } from "./prompts";
10
  import { File } from "./type";
11
 
 
 
12
  /**
13
  * Validates that a filename has an extension.
14
  * Returns the filename if valid, null otherwise.
 
9
  } from "./prompts";
10
  import { File } from "./type";
11
 
12
+ // todo: the Editing stuffs in message doesnt show when it"s a SEARCH and REPLACE operation, I mean it shows it but only at the end of the message, not during the generation. fix that.
13
+
14
  /**
15
  * Validates that a filename has an extension.
16
  * Returns the filename if valid, null otherwise.
next.config.ts CHANGED
@@ -1,14 +1,13 @@
1
  import type { NextConfig } from "next";
2
 
3
  const nextConfig: NextConfig = {
4
- // todo: active this before deployment in production.
5
- // basePath: '/deepsite',
6
- // assetPrefix: '/deepsite',
7
  // async redirects() {
8
  // return [
9
  // {
10
- // source: '/',
11
- // destination: '/deepsite',
12
  // permanent: true,
13
  // basePath: false,
14
  // },
 
1
  import type { NextConfig } from "next";
2
 
3
  const nextConfig: NextConfig = {
4
+ // basePath: "/deepsite",
5
+ // assetPrefix: "/deepsite",
 
6
  // async redirects() {
7
  // return [
8
  // {
9
+ // source: "/",
10
+ // destination: "/deepsite",
11
  // permanent: true,
12
  // basePath: false,
13
  // },