@promptbook/cli 0.103.0-51 → 0.103.0-53
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/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]/AgentQrCode.tsx +3 -3
- 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/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 +12 -12
- 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 +46 -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/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 +62 -0
- package/apps/agents-server/src/app/docs/page.tsx +33 -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 +445 -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 +28 -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/middleware.ts +146 -93
- 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/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 +344 -11
- 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/AgentBasicInformation.d.ts +1 -0
- package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +7 -0
- package/esm/typings/src/book-2.0/agent-source/createCommitmentRegex.d.ts +2 -2
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +10 -0
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +6 -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/MESSAGE/AgentMessageCommitmentDefinition.d.ts +28 -0
- package/esm/typings/src/commitments/MESSAGE/UserMessageCommitmentDefinition.d.ts +28 -0
- package/esm/typings/src/commitments/META_COLOR/META_COLOR.d.ts +38 -0
- package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +2 -1
- package/esm/typings/src/commitments/index.d.ts +22 -1
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +9 -0
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +1 -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 +1 -1
- package/umd/index.umd.js +344 -11
- package/umd/index.umd.js.map +1 -1
|
@@ -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
|
+
*/
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
3
|
// import { BookEditor } from '@promptbook-local/components';
|
|
5
4
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
6
|
+
import { CodeIcon, HistoryIcon, NotebookPenIcon } from 'lucide-react';
|
|
8
7
|
import { headers } from 'next/headers';
|
|
9
8
|
import { notFound } from 'next/navigation';
|
|
10
9
|
import { Color } from '../../../../../../src/utils/color/Color';
|
|
11
10
|
import { withAlpha } from '../../../../../../src/utils/color/operators/withAlpha';
|
|
12
11
|
import { $sideEffect } from '../../../../../../src/utils/organization/$sideEffect';
|
|
12
|
+
import { AGENT_ACTIONS, getAgentName, getAgentProfile } from './_utils';
|
|
13
13
|
import { AgentChatWrapper } from './AgentChatWrapper';
|
|
14
14
|
import { AgentQrCode } from './AgentQrCode';
|
|
15
15
|
import { CopyField } from './CopyField';
|
|
16
16
|
import { generateAgentMetadata } from './generateAgentMetadata';
|
|
17
|
+
import { InstallPwaButton } from './InstallPwaButton';
|
|
18
|
+
import { ServiceWorkerRegister } from './ServiceWorkerRegister';
|
|
19
|
+
import { ClearAgentChatHistoryButton } from './ClearAgentChatHistoryButton';
|
|
20
|
+
import { ClearAgentChatFeedbackButton } from './ClearAgentChatFeedbackButton';
|
|
21
|
+
import { CloneAgentButton } from './CloneAgentButton';
|
|
22
|
+
import { isUserAdmin } from '../../../utils/isUserAdmin';
|
|
17
23
|
// import { Agent } from '@promptbook-local/core';
|
|
18
24
|
// import { RemoteLlmExecutionTools } from '@promptbook-local/remote-client';
|
|
19
25
|
// import { OpenAiAssistantExecutionTools } from '@promptbook-local/openai';
|
|
@@ -27,13 +33,12 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
27
33
|
|
|
28
34
|
$sideEffect(headers());
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
const agentName = await getAgentName(params);
|
|
37
|
+
const isAdmin = await isUserAdmin();
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
let agentSource;
|
|
39
|
+
let agentProfile;
|
|
35
40
|
try {
|
|
36
|
-
|
|
41
|
+
agentProfile = await getAgentProfile(agentName);
|
|
37
42
|
} catch (error) {
|
|
38
43
|
if (
|
|
39
44
|
error instanceof Error &&
|
|
@@ -45,7 +50,6 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
45
50
|
}
|
|
46
51
|
throw error;
|
|
47
52
|
}
|
|
48
|
-
const agentProfile = parseAgentSource(agentSource);
|
|
49
53
|
|
|
50
54
|
const { publicUrl } = await $provideServer();
|
|
51
55
|
|
|
@@ -58,13 +62,15 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
58
62
|
console.log('[🐱🚀]', { pageUrl: agentUrl });
|
|
59
63
|
|
|
60
64
|
// Extract brand color from meta
|
|
61
|
-
const brandColor = Color.from(agentProfile.meta.color ||
|
|
65
|
+
const brandColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
62
66
|
|
|
63
67
|
// Mock agent actions
|
|
64
|
-
const agentActions =
|
|
68
|
+
const agentActions = AGENT_ACTIONS;
|
|
65
69
|
|
|
66
70
|
return (
|
|
67
71
|
<div className="flex flex-col md:flex-row h-[calc(100vh-60px)] w-full overflow-hidden">
|
|
72
|
+
<ServiceWorkerRegister scope={`/agents/${encodeURIComponent(agentName)}/`} />
|
|
73
|
+
|
|
68
74
|
{/* Left sidebar: Profile info */}
|
|
69
75
|
<div
|
|
70
76
|
className="w-full md:w-[400px] flex flex-col gap-6 p-6 overflow-y-auto border-r bg-gray-50 flex-shrink-0"
|
|
@@ -78,7 +84,7 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
78
84
|
// eslint-disable-next-line @next/next/no-img-element
|
|
79
85
|
<img
|
|
80
86
|
src={agentProfile.meta.image as string}
|
|
81
|
-
alt={agentProfile.agentName || 'Agent'}
|
|
87
|
+
alt={agentProfile.meta.fullname || agentProfile.agentName || 'Agent'}
|
|
82
88
|
width={64}
|
|
83
89
|
height={64}
|
|
84
90
|
className="rounded-full object-cover border-2 aspect-square w-16 h-16"
|
|
@@ -86,7 +92,9 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
86
92
|
/>
|
|
87
93
|
)}
|
|
88
94
|
<div className="flex-1">
|
|
89
|
-
<h1 className="text-3xl font-bold text-gray-900 break-words">
|
|
95
|
+
<h1 className="text-3xl font-bold text-gray-900 break-words">
|
|
96
|
+
{agentProfile.meta.fullname || agentProfile.agentName}
|
|
97
|
+
</h1>
|
|
90
98
|
<span
|
|
91
99
|
className="inline-block mt-1 px-2 py-1 rounded text-xs font-semibold text-white"
|
|
92
100
|
style={{ backgroundColor: brandColor.toHex() }}
|
|
@@ -112,39 +120,53 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
112
120
|
</div>
|
|
113
121
|
</div>
|
|
114
122
|
|
|
115
|
-
<div className="flex flex-col gap-
|
|
123
|
+
<div className="flex flex-col gap-3 mt-auto">
|
|
116
124
|
<div className="flex gap-2">
|
|
117
125
|
<a
|
|
118
|
-
href={`/agents/${encodeURIComponent(agentName)}/chat`}
|
|
126
|
+
href={`/agents/${encodeURIComponent(agentName)}/book+chat`}
|
|
119
127
|
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
120
128
|
className="flex-1 inline-flex items-center justify-center whitespace-nowrap bg-white hover:bg-gray-100 text-gray-800 px-4 py-2 rounded shadow font-semibold transition border border-gray-200"
|
|
121
129
|
>
|
|
122
|
-
<
|
|
123
|
-
|
|
130
|
+
<NotebookPenIcon className="ml-2 w-4 h-4 mr-2" />
|
|
131
|
+
Edit
|
|
124
132
|
</a>
|
|
125
133
|
<a
|
|
126
|
-
href={`/agents/${encodeURIComponent(agentName)}/
|
|
134
|
+
href={`/agents/${encodeURIComponent(agentName)}/integration`}
|
|
127
135
|
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
128
136
|
className="flex-1 inline-flex items-center justify-center whitespace-nowrap bg-white hover:bg-gray-100 text-gray-800 px-4 py-2 rounded shadow font-semibold transition border border-gray-200"
|
|
129
137
|
>
|
|
130
|
-
<
|
|
131
|
-
|
|
138
|
+
<CodeIcon className="ml-2 w-4 h-4 mr-2" />
|
|
139
|
+
Integration
|
|
132
140
|
</a>
|
|
133
141
|
<a
|
|
134
|
-
href={`/agents/${encodeURIComponent(agentName)}/
|
|
135
|
-
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
142
|
+
href={`/agents/${encodeURIComponent(agentName)}/history`}
|
|
136
143
|
className="flex-1 inline-flex items-center justify-center whitespace-nowrap bg-white hover:bg-gray-100 text-gray-800 px-4 py-2 rounded shadow font-semibold transition border border-gray-200"
|
|
137
144
|
>
|
|
138
|
-
<
|
|
139
|
-
|
|
145
|
+
<HistoryIcon className="ml-2 w-4 h-4 mr-2" />
|
|
146
|
+
History
|
|
140
147
|
</a>
|
|
148
|
+
{isAdmin && <CloneAgentButton agentName={agentName} />}
|
|
149
|
+
<InstallPwaButton />
|
|
141
150
|
</div>
|
|
151
|
+
|
|
152
|
+
{isAdmin && (
|
|
153
|
+
<div className="border-t border-dashed border-gray-300 pt-3">
|
|
154
|
+
<h2 className="mb-2 text-xs font-semibold uppercase tracking-wide text-gray-600">
|
|
155
|
+
Maintenance
|
|
156
|
+
</h2>
|
|
157
|
+
<div className="flex flex-col gap-2">
|
|
158
|
+
<ClearAgentChatHistoryButton agentName={agentName} />
|
|
159
|
+
<ClearAgentChatFeedbackButton agentName={agentName} />
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
142
163
|
</div>
|
|
143
164
|
|
|
144
165
|
<div className="flex flex-col items-center gap-4 pt-6 border-t border-gray-200 w-full">
|
|
145
166
|
<div className="bg-white rounded-lg p-4 flex flex-col items-center shadow-sm border border-gray-100">
|
|
146
167
|
<AgentQrCode
|
|
147
168
|
agentName={agentProfile.agentName || 'Agent'}
|
|
169
|
+
meta={agentProfile.meta}
|
|
148
170
|
personaDescription={agentProfile.personaDescription}
|
|
149
171
|
agentUrl={agentUrl}
|
|
150
172
|
agentEmail={agentEmail}
|