MingruiZhang commited on
Commit
66e93d1
1 Parent(s): abb7588

add agent api

Browse files
app/project/[projectId]/page.tsx CHANGED
@@ -1,5 +1,5 @@
1
  import MediaGrid from '@/components/project/MediaGrid';
2
- import { fetchProjectMedia } from '@/lib/fetch/clef';
3
  import { Suspense } from 'react';
4
  import Loading from '../loading';
5
  import Chat from '@/components/project/Chat';
 
1
  import MediaGrid from '@/components/project/MediaGrid';
2
+ import { fetchProjectMedia } from '@/lib/fetch';
3
  import { Suspense } from 'react';
4
  import Loading from '../loading';
5
  import Chat from '@/components/project/Chat';
components/project/Chat.tsx CHANGED
@@ -1,6 +1,6 @@
1
  'use client';
2
 
3
- import { MediaDetails } from '@/lib/fetch/clef';
4
  import useChatWithMedia from '@/lib/hooks/useChatWithMedia';
5
  import React from 'react';
6
  import { ChatList } from '../chat/ChatList';
 
1
  'use client';
2
 
3
+ import { MediaDetails } from '@/lib/fetch';
4
  import useChatWithMedia from '@/lib/hooks/useChatWithMedia';
5
  import React from 'react';
6
  import { ChatList } from '../chat/ChatList';
components/project/MediaGrid.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { MediaDetails } from '@/lib/fetch/clef';
2
  import MediaTile from './MediaTile';
3
 
4
  export default function MediaGrid({
 
1
+ import { MediaDetails } from '@/lib/fetch';
2
  import MediaTile from './MediaTile';
3
 
4
  export default function MediaGrid({
components/project/MediaTile.tsx CHANGED
@@ -5,7 +5,7 @@ import {
5
  TooltipContent,
6
  TooltipTrigger,
7
  } from '@/components/ui/Tooltip';
8
- import { MediaDetails } from '@/lib/fetch/clef';
9
 
10
  export interface MediaTileProps {
11
  media: MediaDetails;
 
5
  TooltipContent,
6
  TooltipTrigger,
7
  } from '@/components/ui/Tooltip';
8
+ import { MediaDetails } from '@/lib/fetch';
9
 
10
  export interface MediaTileProps {
11
  media: MediaDetails;
components/sidebar/ProjectCard.tsx CHANGED
@@ -1,6 +1,6 @@
1
  'use client';
2
 
3
- import { ProjectBaseInfo } from '@/lib/fetch/clef';
4
  import { format } from 'date-fns';
5
  import Link from 'next/link';
6
  import { useParams } from 'next/navigation';
 
1
  'use client';
2
 
3
+ import { ProjectBaseInfo } from '@/lib/fetch';
4
  import { format } from 'date-fns';
5
  import Link from 'next/link';
6
  import { useParams } from 'next/navigation';
components/sidebar/ProjectListSideBar.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { fetchRecentProjectList } from '@/lib/fetch/clef';
2
  import ProjectCard from './ProjectCard';
3
 
4
  export interface ProjectListSideBarProps {}
 
1
+ import { fetchRecentProjectList } from '@/lib/fetch';
2
  import ProjectCard from './ProjectCard';
3
 
4
  export interface ProjectListSideBarProps {}
lib/fetch/{clef.ts → index.ts} RENAMED
@@ -1,5 +1,4 @@
1
  import { auth } from '@/auth';
2
- import { redirect } from 'next/navigation';
3
  import { v5 as uuidV5 } from 'uuid';
4
 
5
  interface ApiResponse<T> {
@@ -8,11 +7,21 @@ interface ApiResponse<T> {
8
  data: T;
9
  }
10
 
11
- const clefApiBuilder = <Params extends object | void, Resp>(path: string) => {
 
 
 
 
 
 
 
 
12
  return async (params: Params): Promise<Resp> => {
13
  const session = await auth();
14
  if (!session?.user?.email) {
15
- redirect('/');
 
 
16
  }
17
 
18
  const adminEmail = session.user.email;
@@ -25,24 +34,41 @@ const clefApiBuilder = <Params extends object | void, Resp>(path: string) => {
25
  bucket: 'fake_bucket',
26
  };
27
 
28
- const baseURL = `https://app.landing.ai/${path}`;
 
29
 
 
30
  // Create a URL object with query params
31
  const url = new URL(baseURL);
32
- Object.entries(params ?? {}).forEach(([key, value]) =>
33
- url.searchParams.append(key, value),
34
- );
 
 
35
 
36
- const res = await fetch(url.toString(), {
 
37
  headers: {
38
- 'Content-Type': 'application/json',
39
- sessionuser: JSON.stringify(sessionUser),
40
  'X-ROUTE': 'mingruizhang-landing',
41
  },
42
- });
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  if (!res.ok) {
45
- console.error('ERROR: fetch data failure', res.status);
46
  // This will activate the closest `error.js` Error Boundary
47
  throw new Error('Failed to fetch data');
48
  }
@@ -68,7 +94,7 @@ export type ProjectBaseInfo = {
68
  * 3. projects not containing media or only contain sample media
69
  * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
70
  */
71
- export const fetchRecentProjectList = clefApiBuilder<void, ProjectBaseInfo[]>(
72
  'api/admin/projects/recent',
73
  );
74
 
@@ -86,11 +112,24 @@ export type MediaDetails = {
86
  orientation: number;
87
  };
88
  };
 
89
  /**
90
  * Randomly fetch 10 media from a given project
91
  * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
92
  */
93
- export const fetchProjectMedia = clefApiBuilder<
94
  { projectId: number },
95
  MediaDetails[]
96
  >('api/admin/project/media');
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import { auth } from '@/auth';
 
2
  import { v5 as uuidV5 } from 'uuid';
3
 
4
  interface ApiResponse<T> {
 
7
  data: T;
8
  }
9
 
10
+ const apiBuilder = <Params extends object | void, Resp>(
11
+ path: string,
12
+ options?: {
13
+ // default to GET
14
+ method: 'GET' | 'POST';
15
+ // default to 'app'
16
+ prefix: 'api' | 'app' | 'api.dev' | 'app.dev';
17
+ },
18
+ ) => {
19
  return async (params: Params): Promise<Resp> => {
20
  const session = await auth();
21
  if (!session?.user?.email) {
22
+ throw new Response('Unauthorized', {
23
+ status: 401,
24
+ });
25
  }
26
 
27
  const adminEmail = session.user.email;
 
34
  bucket: 'fake_bucket',
35
  };
36
 
37
+ const prefix = options?.prefix ?? 'app';
38
+ const baseURL = `https://${prefix}.landing.ai/${path}`;
39
 
40
+ const method = options?.method ?? 'GET';
41
  // Create a URL object with query params
42
  const url = new URL(baseURL);
43
+ if (method === 'GET') {
44
+ Object.entries(params ?? {}).forEach(([key, value]) =>
45
+ url.searchParams.append(key, value),
46
+ );
47
+ }
48
 
49
+ const fetchParams: RequestInit = {
50
+ method: options?.method ?? 'GET',
51
  headers: {
52
+ sessionuser: JSON.stringify(sessionUser), // faked production user
53
+ apikey: 'land_sk_DKeoYtaZZrYqJ9TMMiXe4BIQgJcZ0s3XAoB0JT3jv73FFqnr6k', // dev key
54
  'X-ROUTE': 'mingruizhang-landing',
55
  },
56
+ };
57
+
58
+ if (method === 'POST' && params instanceof Object) {
59
+ const formData = new FormData();
60
+ for (const [key, value] of Object.entries(params)) {
61
+ formData.append(key, value);
62
+ }
63
+
64
+ fetchParams.body = formData;
65
+ }
66
+ console.log('[Ming] ~ return ~ fetchParams:', fetchParams, url.toString());
67
+
68
+ const res = await fetch(url.toString(), fetchParams);
69
 
70
  if (!res.ok) {
71
+ console.error('ERROR: fetch data failure', res.status, res.statusText);
72
  // This will activate the closest `error.js` Error Boundary
73
  throw new Error('Failed to fetch data');
74
  }
 
94
  * 3. projects not containing media or only contain sample media
95
  * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
96
  */
97
+ export const fetchRecentProjectList = apiBuilder<void, ProjectBaseInfo[]>(
98
  'api/admin/projects/recent',
99
  );
100
 
 
112
  orientation: number;
113
  };
114
  };
115
+
116
  /**
117
  * Randomly fetch 10 media from a given project
118
  * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
119
  */
120
+ export const fetchProjectMedia = apiBuilder<
121
  { projectId: number },
122
  MediaDetails[]
123
  >('api/admin/project/media');
124
+
125
+ /**
126
+ * Call vision agent
127
+ * @author https://github.com/landing-ai/public-rest-api/pull/36
128
+ */
129
+ export const postAgentChat = apiBuilder<
130
+ { input: string; image: string },
131
+ MediaDetails[]
132
+ >('v1/agent/chat?agent_class=vision_agent', {
133
+ method: 'POST',
134
+ prefix: 'api.dev',
135
+ });
lib/hooks/useChatWithMedia.ts CHANGED
@@ -1,7 +1,7 @@
1
  import { useChat, type Message } from 'ai/react';
2
  import { toast } from 'react-hot-toast';
3
  import { useEffect, useState } from 'react';
4
- import { MediaDetails } from '../fetch/clef';
5
  import { MessageWithSelectedDataset } from '../types';
6
 
7
  const useChatWithMedia = (mediaList: MediaDetails[]) => {
 
1
  import { useChat, type Message } from 'ai/react';
2
  import { toast } from 'react-hot-toast';
3
  import { useEffect, useState } from 'react';
4
+ import { MediaDetails } from '../fetch';
5
  import { MessageWithSelectedDataset } from '../types';
6
 
7
  const useChatWithMedia = (mediaList: MediaDetails[]) => {
package.json CHANGED
@@ -20,9 +20,6 @@
20
  "@radix-ui/react-slot": "^1.0.2",
21
  "@radix-ui/react-switch": "^1.0.3",
22
  "@radix-ui/react-tooltip": "^1.0.7",
23
- "@vercel/analytics": "^1.1.2",
24
- "@vercel/kv": "^1.0.1",
25
- "@vercel/og": "^0.6.2",
26
  "ai": "^2.2.31",
27
  "class-variance-authority": "^0.7.0",
28
  "clsx": "^2.1.0",
 
20
  "@radix-ui/react-slot": "^1.0.2",
21
  "@radix-ui/react-switch": "^1.0.3",
22
  "@radix-ui/react-tooltip": "^1.0.7",
 
 
 
23
  "ai": "^2.2.31",
24
  "class-variance-authority": "^0.7.0",
25
  "clsx": "^2.1.0",