@promptbook/cli 0.103.0-52 → 0.103.0-54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/agents-server/README.md +1 -1
- package/apps/agents-server/config.ts +3 -3
- package/apps/agents-server/next.config.ts +1 -1
- package/apps/agents-server/public/sw.js +16 -0
- package/apps/agents-server/src/app/AddAgentButton.tsx +24 -4
- package/apps/agents-server/src/app/actions.ts +15 -13
- package/apps/agents-server/src/app/admin/api-tokens/ApiTokensClient.tsx +186 -0
- package/apps/agents-server/src/app/admin/api-tokens/page.tsx +13 -0
- package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +541 -0
- package/apps/agents-server/src/app/admin/chat-feedback/page.tsx +22 -0
- package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +532 -0
- package/apps/agents-server/src/app/admin/chat-history/page.tsx +21 -0
- package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +241 -27
- package/apps/agents-server/src/app/admin/models/page.tsx +22 -0
- package/apps/agents-server/src/app/admin/users/[userId]/UserDetailClient.tsx +131 -0
- package/apps/agents-server/src/app/admin/users/[userId]/page.tsx +21 -0
- package/apps/agents-server/src/app/admin/users/page.tsx +18 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +10 -2
- package/apps/agents-server/src/app/agents/[agentName]/ClearAgentChatFeedbackButton.tsx +63 -0
- package/apps/agents-server/src/app/agents/[agentName]/ClearAgentChatHistoryButton.tsx +63 -0
- package/apps/agents-server/src/app/agents/[agentName]/CloneAgentButton.tsx +41 -0
- package/apps/agents-server/src/app/agents/[agentName]/InstallPwaButton.tsx +74 -0
- package/apps/agents-server/src/app/agents/[agentName]/ServiceWorkerRegister.tsx +24 -0
- package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +19 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/agents/route.ts +67 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/openai/chat/completions/route.ts +176 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +3 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/voice/route.ts +177 -0
- package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +3 -0
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/AgentBookAndChat.tsx +53 -1
- package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +11 -11
- package/apps/agents-server/src/app/agents/[agentName]/history/RestoreVersionButton.tsx +46 -0
- package/apps/agents-server/src/app/agents/[agentName]/history/actions.ts +12 -0
- package/apps/agents-server/src/app/agents/[agentName]/history/page.tsx +62 -0
- package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +80 -0
- package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-fullhd.png/route.tsx +92 -0
- package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +92 -0
- package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +61 -0
- package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +102 -0
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +64 -24
- package/apps/agents-server/src/app/api/agents/[agentName]/clone/route.ts +47 -0
- package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +19 -0
- package/apps/agents-server/src/app/api/agents/route.ts +22 -13
- package/apps/agents-server/src/app/api/api-tokens/route.ts +76 -0
- package/apps/agents-server/src/app/api/auth/login/route.ts +6 -44
- package/apps/agents-server/src/app/api/chat-feedback/[id]/route.ts +38 -0
- package/apps/agents-server/src/app/api/chat-feedback/route.ts +157 -0
- package/apps/agents-server/src/app/api/chat-history/[id]/route.ts +37 -0
- package/apps/agents-server/src/app/api/chat-history/route.ts +147 -0
- package/apps/agents-server/src/app/api/federated-agents/route.ts +17 -0
- package/apps/agents-server/src/app/api/upload/route.ts +9 -1
- package/apps/agents-server/src/app/docs/[docId]/page.tsx +63 -0
- package/apps/agents-server/src/app/docs/page.tsx +34 -0
- package/apps/agents-server/src/app/layout.tsx +29 -3
- package/apps/agents-server/src/app/manifest.ts +109 -0
- package/apps/agents-server/src/app/page.tsx +8 -45
- package/apps/agents-server/src/app/recycle-bin/RestoreAgentButton.tsx +40 -0
- package/apps/agents-server/src/app/recycle-bin/actions.ts +27 -0
- package/apps/agents-server/src/app/recycle-bin/page.tsx +58 -0
- package/apps/agents-server/src/app/restricted/page.tsx +33 -0
- package/apps/agents-server/src/app/test/og-image/README.md +1 -0
- package/apps/agents-server/src/app/test/og-image/opengraph-image.tsx +37 -0
- package/apps/agents-server/src/app/test/og-image/page.tsx +22 -0
- package/apps/agents-server/src/components/Footer/Footer.tsx +175 -0
- package/apps/agents-server/src/components/Header/Header.tsx +450 -79
- package/apps/agents-server/src/components/Homepage/AgentCard.tsx +46 -14
- package/apps/agents-server/src/components/Homepage/AgentsList.tsx +58 -0
- package/apps/agents-server/src/components/Homepage/Card.tsx +1 -1
- package/apps/agents-server/src/components/Homepage/ExternalAgentsSection.tsx +21 -0
- package/apps/agents-server/src/components/Homepage/ExternalAgentsSectionClient.tsx +183 -0
- package/apps/agents-server/src/components/Homepage/ModelsSection.tsx +75 -0
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +29 -3
- package/apps/agents-server/src/components/LoginDialog/LoginDialog.tsx +18 -17
- package/apps/agents-server/src/components/Portal/Portal.tsx +38 -0
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +82 -131
- package/apps/agents-server/src/components/UsersList/useUsersAdmin.ts +139 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +38 -6
- package/apps/agents-server/src/database/migrations/2025-12-0010-llm-cache.sql +12 -0
- package/apps/agents-server/src/database/migrations/2025-12-0060-api-tokens.sql +13 -0
- package/apps/agents-server/src/database/schema.ts +51 -0
- package/apps/agents-server/src/middleware.ts +193 -92
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +3 -7
- package/apps/agents-server/src/tools/$provideExecutionToolsForServer.ts +10 -1
- package/apps/agents-server/src/tools/$provideServer.ts +2 -2
- package/apps/agents-server/src/utils/authenticateUser.ts +42 -0
- package/apps/agents-server/src/utils/cache/SupabaseCacheStorage.ts +55 -0
- package/apps/agents-server/src/utils/cdn/classes/VercelBlobStorage.ts +63 -0
- package/apps/agents-server/src/utils/chatFeedbackAdmin.ts +96 -0
- package/apps/agents-server/src/utils/chatHistoryAdmin.ts +96 -0
- package/apps/agents-server/src/utils/getEffectiveFederatedServers.ts +22 -0
- package/apps/agents-server/src/utils/getFederatedAgents.ts +31 -8
- package/apps/agents-server/src/utils/getFederatedServersFromMetadata.ts +10 -0
- package/apps/agents-server/src/utils/getVisibleCommitmentDefinitions.ts +12 -0
- package/apps/agents-server/src/utils/isUserAdmin.ts +2 -2
- package/apps/agents-server/vercel.json +7 -0
- package/esm/index.es.js +279 -2
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +8 -1
- package/esm/typings/src/_packages/components.index.d.ts +2 -0
- package/esm/typings/src/_packages/core.index.d.ts +6 -0
- package/esm/typings/src/_packages/types.index.d.ts +2 -0
- package/esm/typings/src/_packages/utils.index.d.ts +2 -0
- package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +7 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +4 -0
- package/esm/typings/src/book-components/_common/HamburgerMenu/HamburgerMenu.d.ts +12 -0
- package/esm/typings/src/book-components/icons/MicIcon.d.ts +8 -0
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +17 -0
- package/esm/typings/src/commitments/ACTION/ACTION.d.ts +4 -0
- package/esm/typings/src/commitments/DELETE/DELETE.d.ts +4 -0
- package/esm/typings/src/commitments/FORMAT/FORMAT.d.ts +4 -0
- package/esm/typings/src/commitments/GOAL/GOAL.d.ts +4 -0
- package/esm/typings/src/commitments/KNOWLEDGE/KNOWLEDGE.d.ts +4 -0
- package/esm/typings/src/commitments/MEMORY/MEMORY.d.ts +4 -0
- package/esm/typings/src/commitments/MESSAGE/AgentMessageCommitmentDefinition.d.ts +32 -0
- package/esm/typings/src/commitments/MESSAGE/InitialMessageCommitmentDefinition.d.ts +4 -0
- package/esm/typings/src/commitments/MESSAGE/MESSAGE.d.ts +4 -0
- package/esm/typings/src/commitments/MESSAGE/UserMessageCommitmentDefinition.d.ts +32 -0
- package/esm/typings/src/commitments/META/META.d.ts +4 -0
- package/esm/typings/src/commitments/META_COLOR/META_COLOR.d.ts +4 -0
- package/esm/typings/src/commitments/META_IMAGE/META_IMAGE.d.ts +4 -0
- package/esm/typings/src/commitments/META_LINK/META_LINK.d.ts +4 -0
- package/esm/typings/src/commitments/MODEL/MODEL.d.ts +4 -0
- package/esm/typings/src/commitments/NOTE/NOTE.d.ts +4 -0
- package/esm/typings/src/commitments/PERSONA/PERSONA.d.ts +4 -0
- package/esm/typings/src/commitments/RULE/RULE.d.ts +4 -0
- package/esm/typings/src/commitments/SAMPLE/SAMPLE.d.ts +4 -0
- package/esm/typings/src/commitments/SCENARIO/SCENARIO.d.ts +4 -0
- package/esm/typings/src/commitments/STYLE/STYLE.d.ts +4 -0
- package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +5 -0
- package/esm/typings/src/commitments/_base/CommitmentDefinition.d.ts +5 -0
- package/esm/typings/src/commitments/_base/NotYetImplementedCommitmentDefinition.d.ts +4 -0
- package/esm/typings/src/commitments/index.d.ts +20 -1
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +9 -0
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +2 -1
- package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +10 -1
- package/esm/typings/src/utils/normalization/normalizeMessageText.d.ts +9 -0
- package/esm/typings/src/utils/normalization/normalizeMessageText.test.d.ts +1 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +279 -2
- package/umd/index.umd.js.map +1 -1
- package/apps/agents-server/src/utils/cdn/classes/DigitalOceanSpaces.ts +0 -119
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { ResizablePanelsAuto } from '@common/components/ResizablePanelsAuto/ResizablePanelsAuto';
|
|
4
4
|
import { string_agent_url, string_book } from '@promptbook-local/types';
|
|
5
|
-
import {
|
|
5
|
+
import { Book, MessageSquare } from 'lucide-react';
|
|
6
|
+
import { useEffect, useState } from 'react';
|
|
6
7
|
import { AgentChatWrapper } from '../AgentChatWrapper';
|
|
8
|
+
import { BookEditorWrapper } from '../book/BookEditorWrapper';
|
|
7
9
|
|
|
8
10
|
type AgentBookAndChatProps = {
|
|
9
11
|
agentName: string;
|
|
@@ -13,6 +15,56 @@ type AgentBookAndChatProps = {
|
|
|
13
15
|
|
|
14
16
|
export function AgentBookAndChat(props: AgentBookAndChatProps) {
|
|
15
17
|
const { agentName, initialAgentSource, agentUrl } = props;
|
|
18
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
19
|
+
const [activeTab, setActiveTab] = useState<'book' | 'chat'>('chat');
|
|
20
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
setIsMounted(true);
|
|
24
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 1024);
|
|
25
|
+
checkMobile();
|
|
26
|
+
window.addEventListener('resize', checkMobile);
|
|
27
|
+
return () => window.removeEventListener('resize', checkMobile);
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
if (!isMounted) {
|
|
31
|
+
return <div className="w-full h-full bg-white" />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (isMobile) {
|
|
35
|
+
return (
|
|
36
|
+
<div className="flex flex-col h-full w-full bg-white">
|
|
37
|
+
<div className="flex-grow overflow-hidden relative">
|
|
38
|
+
<div className={`w-full h-full ${activeTab === 'book' ? 'block' : 'hidden'}`}>
|
|
39
|
+
<BookEditorWrapper agentName={agentName} initialAgentSource={initialAgentSource} />
|
|
40
|
+
</div>
|
|
41
|
+
<div className={`w-full h-full ${activeTab === 'chat' ? 'block' : 'hidden'}`}>
|
|
42
|
+
<AgentChatWrapper agentUrl={agentUrl} />
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
<div className="flex-shrink-0 h-16 bg-white border-t border-gray-200 flex shadow-[0_-4px_6px_-1px_rgba(0,0,0,0.05)] z-10">
|
|
46
|
+
<button
|
|
47
|
+
onClick={() => setActiveTab('book')}
|
|
48
|
+
className={`flex-1 flex flex-col items-center justify-center gap-1 transition-colors ${
|
|
49
|
+
activeTab === 'book' ? 'text-blue-600 bg-blue-50/50' : 'text-gray-500 hover:bg-gray-50'
|
|
50
|
+
}`}
|
|
51
|
+
>
|
|
52
|
+
<Book className="w-5 h-5" />
|
|
53
|
+
<span className="text-xs font-medium">Info</span>
|
|
54
|
+
</button>
|
|
55
|
+
<button
|
|
56
|
+
onClick={() => setActiveTab('chat')}
|
|
57
|
+
className={`flex-1 flex flex-col items-center justify-center gap-1 transition-colors ${
|
|
58
|
+
activeTab === 'chat' ? 'text-blue-600 bg-blue-50/50' : 'text-gray-500 hover:bg-gray-50'
|
|
59
|
+
}`}
|
|
60
|
+
>
|
|
61
|
+
<MessageSquare className="w-5 h-5" />
|
|
62
|
+
<span className="text-xs font-medium">Chat</span>
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
16
68
|
|
|
17
69
|
return (
|
|
18
70
|
<ResizablePanelsAuto name={`agent-book-and-chat-${agentName}`} className="w-full h-full">
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { $
|
|
2
|
-
import { parseAgentSource } from '@promptbook-local/core';
|
|
1
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
3
2
|
import { Metadata } from 'next';
|
|
3
|
+
import { getAgentName, getAgentProfile } from './_utils';
|
|
4
4
|
|
|
5
5
|
export async function generateAgentMetadata({ params }: { params: Promise<{ agentName: string }> }): Promise<Metadata> {
|
|
6
|
-
|
|
7
|
-
agentName =
|
|
6
|
+
const { publicUrl } = await $provideServer();
|
|
7
|
+
const agentName = await getAgentName(params);
|
|
8
8
|
|
|
9
9
|
try {
|
|
10
|
-
const
|
|
11
|
-
const agentSource = await collection.getAgentSource(agentName);
|
|
12
|
-
const agentProfile = parseAgentSource(agentSource);
|
|
10
|
+
const agentProfile = await getAgentProfile(agentName);
|
|
13
11
|
|
|
14
12
|
const title = agentProfile.meta.fullname || agentProfile.agentName;
|
|
15
13
|
const description = agentProfile.meta.description || agentProfile.personaDescription || undefined;
|
|
@@ -17,22 +15,24 @@ export async function generateAgentMetadata({ params }: { params: Promise<{ agen
|
|
|
17
15
|
// Extract image from meta
|
|
18
16
|
const image = agentProfile.meta.image;
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
const metadata = {
|
|
19
|
+
metadataBase: publicUrl,
|
|
21
20
|
title,
|
|
22
21
|
description,
|
|
22
|
+
icons: image ? { icon: image } : undefined,
|
|
23
23
|
openGraph: {
|
|
24
24
|
title,
|
|
25
25
|
description,
|
|
26
26
|
type: 'website',
|
|
27
|
-
images: image ? [{ url: image }] : undefined,
|
|
28
27
|
},
|
|
29
28
|
twitter: {
|
|
30
29
|
card: 'summary_large_image',
|
|
31
30
|
title,
|
|
32
31
|
description,
|
|
33
|
-
images: image ? [image] : undefined,
|
|
34
32
|
},
|
|
35
|
-
};
|
|
33
|
+
} satisfies Metadata;
|
|
34
|
+
|
|
35
|
+
return metadata;
|
|
36
36
|
} catch (error) {
|
|
37
37
|
console.warn(`Failed to generate metadata for agent ${agentName}`, error);
|
|
38
38
|
return {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { RefreshCcwIcon } from 'lucide-react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { restoreAgentVersion } from './actions';
|
|
7
|
+
|
|
8
|
+
type RestoreVersionButtonProps = {
|
|
9
|
+
agentName: string;
|
|
10
|
+
historyId: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function RestoreVersionButton({ agentName, historyId }: RestoreVersionButtonProps) {
|
|
14
|
+
const router = useRouter();
|
|
15
|
+
const [isRestoring, setIsRestoring] = useState(false);
|
|
16
|
+
|
|
17
|
+
const handleRestore = async () => {
|
|
18
|
+
if (!confirm('Are you sure you want to restore this version? Current changes will be saved to history.')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
setIsRestoring(true);
|
|
24
|
+
await restoreAgentVersion(agentName, historyId);
|
|
25
|
+
router.refresh();
|
|
26
|
+
router.push(`/agents/${agentName}`);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('Failed to restore version:', error);
|
|
29
|
+
alert('Failed to restore version');
|
|
30
|
+
} finally {
|
|
31
|
+
setIsRestoring(false);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<button
|
|
37
|
+
onClick={handleRestore}
|
|
38
|
+
disabled={isRestoring}
|
|
39
|
+
className="flex items-center gap-2 px-3 py-1 text-sm bg-white border border-gray-300 rounded hover:bg-gray-50 text-gray-700 disabled:opacity-50"
|
|
40
|
+
title="Restore this version"
|
|
41
|
+
>
|
|
42
|
+
<RefreshCcwIcon className={`w-3 h-3 ${isRestoring ? 'animate-spin' : ''}`} />
|
|
43
|
+
{isRestoring ? 'Restoring...' : 'Restore'}
|
|
44
|
+
</button>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { revalidatePath } from 'next/cache';
|
|
5
|
+
|
|
6
|
+
export async function restoreAgentVersion(agentName: string, historyId: number) {
|
|
7
|
+
const collection = await $provideAgentCollectionForServer();
|
|
8
|
+
await collection.restoreAgent(historyId);
|
|
9
|
+
|
|
10
|
+
revalidatePath(`/agents/${agentName}`);
|
|
11
|
+
revalidatePath(`/agents/${agentName}/history`);
|
|
12
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
2
|
+
import { HistoryIcon } from 'lucide-react';
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { RestoreVersionButton } from './RestoreVersionButton';
|
|
5
|
+
|
|
6
|
+
export const metadata = {
|
|
7
|
+
title: 'Agent History',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default async function AgentHistoryPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
11
|
+
const { agentName } = await params;
|
|
12
|
+
const collection = await $provideAgentCollectionForServer();
|
|
13
|
+
const history = await collection.listAgentHistory(agentName);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="container mx-auto p-6 max-w-4xl">
|
|
17
|
+
<header className="flex items-center gap-4 mb-8">
|
|
18
|
+
<div className="bg-blue-100 p-3 rounded-full">
|
|
19
|
+
<HistoryIcon className="w-8 h-8 text-blue-600" />
|
|
20
|
+
</div>
|
|
21
|
+
<div>
|
|
22
|
+
<h1 className="text-3xl font-bold text-gray-900">History: {agentName}</h1>
|
|
23
|
+
<p className="text-gray-600">
|
|
24
|
+
Previous versions of this agent. <Link href={`/agents/${agentName}`} className="text-blue-600 hover:underline">Back to agent</Link>
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
{history.length === 0 ? (
|
|
30
|
+
<div className="text-center py-12 bg-gray-50 rounded-lg border border-dashed border-gray-300">
|
|
31
|
+
<p className="text-gray-500 text-lg">No history found</p>
|
|
32
|
+
</div>
|
|
33
|
+
) : (
|
|
34
|
+
<div className="relative border-l border-gray-200 ml-4">
|
|
35
|
+
{history.map((item, index) => (
|
|
36
|
+
<div key={item.id} className="mb-8 ml-6">
|
|
37
|
+
<span className="absolute flex items-center justify-center w-6 h-6 bg-blue-100 rounded-full -left-3 ring-8 ring-white">
|
|
38
|
+
<span className="w-3 h-3 bg-blue-600 rounded-full"></span>
|
|
39
|
+
</span>
|
|
40
|
+
<div className="p-4 bg-white border border-gray-200 rounded-lg shadow-sm">
|
|
41
|
+
<div className="flex justify-between items-start mb-2">
|
|
42
|
+
<div>
|
|
43
|
+
<time className="block mb-1 text-sm font-normal leading-none text-gray-400">
|
|
44
|
+
{new Date(item.createdAt).toLocaleString()}
|
|
45
|
+
</time>
|
|
46
|
+
<h3 className="text-lg font-semibold text-gray-900">
|
|
47
|
+
Version {history.length - index}
|
|
48
|
+
</h3>
|
|
49
|
+
<p className="text-sm text-gray-500">
|
|
50
|
+
Hash: <code className="bg-gray-100 px-1 rounded">{item.agentHash.substring(0, 8)}</code>
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
<RestoreVersionButton agentName={agentName} historyId={item.id} />
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
|
+
import { serializeError } from '@promptbook-local/utils';
|
|
3
|
+
import { ImageResponse } from 'next/og';
|
|
4
|
+
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
5
|
+
import { Color } from '../../../../../../../../src/utils/color/Color';
|
|
6
|
+
import { keepUnused } from '../../../../../../../../src/utils/organization/keepUnused';
|
|
7
|
+
import { getAgentName, getAgentProfile } from '../../_utils';
|
|
8
|
+
|
|
9
|
+
const size = {
|
|
10
|
+
width: 256,
|
|
11
|
+
height: 256,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export async function GET(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
15
|
+
keepUnused(request /* <- Note: We dont need `request` parameter */);
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const agentName = await getAgentName(params);
|
|
19
|
+
const agentProfile = await getAgentProfile(agentName);
|
|
20
|
+
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
21
|
+
|
|
22
|
+
return new ImageResponse(
|
|
23
|
+
(
|
|
24
|
+
<div
|
|
25
|
+
style={{
|
|
26
|
+
width: '100%',
|
|
27
|
+
height: '100%',
|
|
28
|
+
backgroundColor: 'transparent',
|
|
29
|
+
display: 'flex',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
justifyContent: 'center',
|
|
32
|
+
borderRadius: '50%',
|
|
33
|
+
overflow: 'hidden',
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<div
|
|
37
|
+
style={{
|
|
38
|
+
width: '100%',
|
|
39
|
+
height: '100%',
|
|
40
|
+
backgroundColor: agentColor.toHex(),
|
|
41
|
+
display: 'flex',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{/* Note: `next/image` is not working propperly with `next/og` */}
|
|
47
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
48
|
+
<img src={agentProfile.meta.image!} alt="Agent Icon" />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
),
|
|
52
|
+
{
|
|
53
|
+
...size,
|
|
54
|
+
emoji: 'openmoji',
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
assertsError(error);
|
|
59
|
+
|
|
60
|
+
console.error(error);
|
|
61
|
+
|
|
62
|
+
return new Response(
|
|
63
|
+
JSON.stringify(
|
|
64
|
+
serializeError(error),
|
|
65
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
66
|
+
null,
|
|
67
|
+
4,
|
|
68
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
69
|
+
),
|
|
70
|
+
{
|
|
71
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
72
|
+
headers: { 'Content-Type': 'application/json' },
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* TODO: [🦚] DRY
|
|
80
|
+
*/
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
|
+
import { serializeError } from '@promptbook-local/utils';
|
|
3
|
+
import { ImageResponse } from 'next/og';
|
|
4
|
+
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
5
|
+
import { Color } from '../../../../../../../../src/utils/color/Color';
|
|
6
|
+
import { textColor } from '../../../../../../../../src/utils/color/operators/furthest';
|
|
7
|
+
import { grayscale } from '../../../../../../../../src/utils/color/operators/grayscale';
|
|
8
|
+
import { keepUnused } from '../../../../../../../../src/utils/organization/keepUnused';
|
|
9
|
+
import { getAgentName, getAgentProfile } from '../../_utils';
|
|
10
|
+
|
|
11
|
+
const size = {
|
|
12
|
+
width: 1920,
|
|
13
|
+
height: 1080,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function GET(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
17
|
+
keepUnused(request /* <- Note: We dont need `request` parameter */);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const agentName = await getAgentName(params);
|
|
21
|
+
const agentProfile = await getAgentProfile(agentName);
|
|
22
|
+
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
23
|
+
const backgroundColor = agentColor.then(grayscale(0.5));
|
|
24
|
+
|
|
25
|
+
return new ImageResponse(
|
|
26
|
+
(
|
|
27
|
+
<div
|
|
28
|
+
style={{
|
|
29
|
+
width: '100%',
|
|
30
|
+
height: '100%',
|
|
31
|
+
backgroundColor: backgroundColor.toHex(),
|
|
32
|
+
color: agentColor.then(textColor).toHex(),
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
width: '40%',
|
|
41
|
+
display: 'flex',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{/* Note: `next/image` is not working propperly with `next/og` */}
|
|
47
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
48
|
+
<img
|
|
49
|
+
style={{
|
|
50
|
+
width: '80%',
|
|
51
|
+
backgroundColor: agentColor.toHex(),
|
|
52
|
+
borderRadius: '50%',
|
|
53
|
+
}}
|
|
54
|
+
src={agentProfile.meta.image!}
|
|
55
|
+
alt="Agent Icon"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
<div style={{ width: '60%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
59
|
+
<h1 style={{ fontSize: '110px' }}>{agentProfile.meta.fullname || agentName}</h1>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
),
|
|
63
|
+
{
|
|
64
|
+
...size,
|
|
65
|
+
emoji: 'openmoji',
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
assertsError(error);
|
|
70
|
+
|
|
71
|
+
console.error(error);
|
|
72
|
+
|
|
73
|
+
return new Response(
|
|
74
|
+
JSON.stringify(
|
|
75
|
+
serializeError(error),
|
|
76
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
77
|
+
null,
|
|
78
|
+
4,
|
|
79
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
80
|
+
),
|
|
81
|
+
{
|
|
82
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
83
|
+
headers: { 'Content-Type': 'application/json' },
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* TODO: [🦚] DRY
|
|
91
|
+
* TODO: [🦚] This should be the true screenshot NOT just image + Agent name
|
|
92
|
+
*/
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
|
+
import { serializeError } from '@promptbook-local/utils';
|
|
3
|
+
import { ImageResponse } from 'next/og';
|
|
4
|
+
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
5
|
+
import { Color } from '../../../../../../../../src/utils/color/Color';
|
|
6
|
+
import { textColor } from '../../../../../../../../src/utils/color/operators/furthest';
|
|
7
|
+
import { grayscale } from '../../../../../../../../src/utils/color/operators/grayscale';
|
|
8
|
+
import { keepUnused } from '../../../../../../../../src/utils/organization/keepUnused';
|
|
9
|
+
import { getAgentName, getAgentProfile } from '../../_utils';
|
|
10
|
+
|
|
11
|
+
const size = {
|
|
12
|
+
width: 1080,
|
|
13
|
+
height: 1920,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export async function GET(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
17
|
+
keepUnused(request /* <- Note: We dont need `request` parameter */);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const agentName = await getAgentName(params);
|
|
21
|
+
const agentProfile = await getAgentProfile(agentName);
|
|
22
|
+
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
23
|
+
const backgroundColor = agentColor.then(grayscale(0.5));
|
|
24
|
+
|
|
25
|
+
return new ImageResponse(
|
|
26
|
+
(
|
|
27
|
+
<div
|
|
28
|
+
style={{
|
|
29
|
+
width: '100%',
|
|
30
|
+
height: '100%',
|
|
31
|
+
backgroundColor: backgroundColor.toHex(),
|
|
32
|
+
color: agentColor.then(textColor).toHex(),
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
style={{
|
|
40
|
+
width: '40%',
|
|
41
|
+
display: 'flex',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{/* Note: `next/image` is not working propperly with `next/og` */}
|
|
47
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
48
|
+
<img
|
|
49
|
+
style={{
|
|
50
|
+
width: '80%',
|
|
51
|
+
backgroundColor: agentColor.toHex(),
|
|
52
|
+
borderRadius: '50%',
|
|
53
|
+
}}
|
|
54
|
+
src={agentProfile.meta.image!}
|
|
55
|
+
alt="Agent Icon"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
<div style={{ width: '60%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
59
|
+
<h1 style={{ fontSize: '110px' }}>{agentProfile.meta.fullname || agentName}</h1>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
),
|
|
63
|
+
{
|
|
64
|
+
...size,
|
|
65
|
+
emoji: 'openmoji',
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
assertsError(error);
|
|
70
|
+
|
|
71
|
+
console.error(error);
|
|
72
|
+
|
|
73
|
+
return new Response(
|
|
74
|
+
JSON.stringify(
|
|
75
|
+
serializeError(error),
|
|
76
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
77
|
+
null,
|
|
78
|
+
4,
|
|
79
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
80
|
+
),
|
|
81
|
+
{
|
|
82
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
83
|
+
headers: { 'Content-Type': 'application/json' },
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* TODO: [🦚] DRY
|
|
91
|
+
* TODO: [🦚] This should be the true screenshot NOT just image + Agent name
|
|
92
|
+
*/
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
5
|
+
import { PromptbookAgent } from '@promptbook-local/components';
|
|
6
|
+
import { parseAgentSource } from '@promptbook-local/core';
|
|
7
|
+
import { headers } from 'next/headers';
|
|
8
|
+
import spaceTrim from 'spacetrim';
|
|
9
|
+
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
10
|
+
import { CodePreview } from '../../../../../../_common/components/CodePreview/CodePreview';
|
|
11
|
+
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
12
|
+
|
|
13
|
+
export const generateMetadata = generateAgentMetadata;
|
|
14
|
+
|
|
15
|
+
export default async function AgentChatPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
16
|
+
$sideEffect(headers());
|
|
17
|
+
let { agentName } = await params;
|
|
18
|
+
agentName = decodeURIComponent(agentName);
|
|
19
|
+
|
|
20
|
+
const collection = await $provideAgentCollectionForServer();
|
|
21
|
+
const agentSource = await collection.getAgentSource(agentName);
|
|
22
|
+
const { meta } = parseAgentSource(agentSource);
|
|
23
|
+
const { fullname, color, image, ...restMeta } = meta;
|
|
24
|
+
const { publicUrl } = await $provideServer();
|
|
25
|
+
const agentUrl = `${publicUrl.href}agents/${encodeURIComponent(agentName)}`;
|
|
26
|
+
|
|
27
|
+
const code = spaceTrim(
|
|
28
|
+
(block) => `
|
|
29
|
+
|
|
30
|
+
import { PromptbookAgent } from '@promptbook/components';
|
|
31
|
+
|
|
32
|
+
export function YourComponent() {
|
|
33
|
+
return(
|
|
34
|
+
<PromptbookAgent
|
|
35
|
+
agentUrl="${agentUrl}"
|
|
36
|
+
meta={${block(JSON.stringify({ fullname, color, image, ...restMeta }, null, 4))}}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
`,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<main className="w-screen h-screen p-4">
|
|
46
|
+
<h1 className="text-2xl font-bold p-4 border-b">{meta.fullname || agentName} Integration Code</h1>
|
|
47
|
+
<p className="mt-4 mb-8 text-gray-600">
|
|
48
|
+
Use the following code to integrate the <strong>{meta.fullname || agentName}</strong> agent into your
|
|
49
|
+
React application using the <code>{'<PromptbookAgent />'}</code> component.
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<CodePreview code={code} />
|
|
53
|
+
<PromptbookAgent agentUrl={agentUrl} meta={meta} />
|
|
54
|
+
</main>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* TODO: Make this page better, bring from Promptbook.Studio
|
|
60
|
+
* TODO: [🚗] Components and pages here should be just tiny UI wraper around proper agent logic and conponents
|
|
61
|
+
*/
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
|
+
import { serializeError } from '@promptbook-local/utils';
|
|
3
|
+
import { ImageResponse } from 'next/og';
|
|
4
|
+
import { assertsError } from '../../../../../../src/errors/assertsError';
|
|
5
|
+
import { Color } from '../../../../../../src/utils/color/Color';
|
|
6
|
+
import { textColor } from '../../../../../../src/utils/color/operators/furthest';
|
|
7
|
+
import { grayscale } from '../../../../../../src/utils/color/operators/grayscale';
|
|
8
|
+
import { getAgentName, getAgentProfile } from './_utils';
|
|
9
|
+
|
|
10
|
+
// export const runtime = 'edge';
|
|
11
|
+
// <- Note: On Vercel Edge runtime some modules are not working *(like `crypto`)*
|
|
12
|
+
|
|
13
|
+
export const alt = 'Agent Profile';
|
|
14
|
+
export const size = {
|
|
15
|
+
width: 1200,
|
|
16
|
+
height: 630,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const contentType = 'image/png';
|
|
20
|
+
|
|
21
|
+
export default async function Image({ params }: { params: Promise<{ agentName: string }> }) {
|
|
22
|
+
try {
|
|
23
|
+
const agentName = await getAgentName(params);
|
|
24
|
+
const agentProfile = await getAgentProfile(agentName);
|
|
25
|
+
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
26
|
+
const backgroundColor = agentColor.then(grayscale(0.5));
|
|
27
|
+
|
|
28
|
+
return new ImageResponse(
|
|
29
|
+
(
|
|
30
|
+
<div
|
|
31
|
+
style={{
|
|
32
|
+
width: '100%',
|
|
33
|
+
height: '100%',
|
|
34
|
+
backgroundColor: backgroundColor.toHex(),
|
|
35
|
+
color: agentColor.then(textColor).toHex(),
|
|
36
|
+
display: 'flex',
|
|
37
|
+
alignItems: 'center',
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
<div
|
|
42
|
+
style={{
|
|
43
|
+
width: '50%',
|
|
44
|
+
display: 'flex',
|
|
45
|
+
alignItems: 'center',
|
|
46
|
+
justifyContent: 'center',
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
{/* Note: `next/image` is not working propperly with `next/og` */}
|
|
50
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
51
|
+
<img
|
|
52
|
+
style={{
|
|
53
|
+
width: '80%',
|
|
54
|
+
backgroundColor: agentColor.toHex(),
|
|
55
|
+
borderRadius: '50%',
|
|
56
|
+
}}
|
|
57
|
+
src={agentProfile.meta.image!}
|
|
58
|
+
alt="Agent Icon"
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
<div
|
|
62
|
+
style={{
|
|
63
|
+
width: '50%',
|
|
64
|
+
display: 'flex',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
justifyContent: 'center',
|
|
67
|
+
textAlign: 'center',
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
<h1 style={{ fontSize: '100px' }}>{agentProfile.meta.fullname || agentName}</h1>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
),
|
|
74
|
+
{
|
|
75
|
+
...size,
|
|
76
|
+
emoji: 'openmoji',
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
assertsError(error);
|
|
81
|
+
|
|
82
|
+
console.error(error);
|
|
83
|
+
|
|
84
|
+
return new Response(
|
|
85
|
+
JSON.stringify(
|
|
86
|
+
serializeError(error),
|
|
87
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
88
|
+
null,
|
|
89
|
+
4,
|
|
90
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
91
|
+
),
|
|
92
|
+
{
|
|
93
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
94
|
+
headers: { 'Content-Type': 'application/json' },
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* TODO: [🦚] DRY
|
|
102
|
+
*/
|