@promptbook/cli 0.104.0-6 → 0.104.0-8
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/config.ts +1 -3
- package/apps/agents-server/src/app/admin/browser-test/BrowserTestClient.tsx +85 -0
- package/apps/agents-server/src/app/admin/browser-test/page.tsx +13 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +49 -10
- package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +0 -3
- package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +5 -2
- package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/getAgentDefaultAvatarPrompt.ts +31 -0
- package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/route.ts +56 -38
- package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +10 -1
- package/apps/agents-server/src/app/agents/[agentName]/images/page.tsx +200 -0
- package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-fullhd.png/route.tsx +5 -4
- package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +5 -4
- package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +8 -1
- package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +8 -1
- package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +7 -2
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +3 -4
- package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +15 -3
- package/apps/agents-server/src/app/api/browser-test/screenshot/route.ts +30 -0
- package/apps/agents-server/src/app/humans.txt/route.ts +1 -1
- package/apps/agents-server/src/app/page.tsx +4 -2
- package/apps/agents-server/src/app/recycle-bin/page.tsx +3 -1
- package/apps/agents-server/src/app/robots.txt/route.ts +1 -1
- package/apps/agents-server/src/app/security.txt/route.ts +1 -1
- package/apps/agents-server/src/app/sitemap.xml/route.ts +4 -5
- package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +22 -13
- package/apps/agents-server/src/components/Header/Header.tsx +4 -0
- package/apps/agents-server/src/components/Homepage/AgentCard.tsx +46 -9
- package/apps/agents-server/src/components/Homepage/AgentsList.tsx +32 -14
- package/apps/agents-server/src/components/Homepage/DeletedAgentsList.tsx +22 -6
- package/apps/agents-server/src/components/Homepage/ExternalAgentsSection.tsx +12 -3
- package/apps/agents-server/src/components/Homepage/ExternalAgentsSectionClient.tsx +19 -10
- package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +2 -0
- package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +12 -10
- package/apps/agents-server/src/tools/$provideBrowserForServer.ts +29 -0
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +1 -1
- package/esm/index.es.js +8 -9
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +8 -0
- package/esm/typings/src/_packages/core.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +2 -0
- package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +2 -2
- package/esm/typings/src/types/ModelRequirements.d.ts +38 -14
- package/esm/typings/src/types/typeAliases.d.ts +7 -1
- package/esm/typings/src/utils/color/utils/colorToDataUrl.d.ts +2 -1
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +8 -9
- package/umd/index.umd.js.map +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
2
|
+
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
3
|
import { serializeError } from '@promptbook-local/utils';
|
|
3
4
|
import { ImageResponse } from 'next/og';
|
|
4
5
|
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
@@ -21,6 +22,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
21
22
|
const agentProfile = await getAgentProfile(agentName);
|
|
22
23
|
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
23
24
|
const backgroundColor = agentColor.then(grayscale(0.5));
|
|
25
|
+
const { publicUrl } = await $provideServer();
|
|
24
26
|
|
|
25
27
|
return new ImageResponse(
|
|
26
28
|
(
|
|
@@ -48,10 +50,9 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
48
50
|
<img
|
|
49
51
|
style={{
|
|
50
52
|
width: '80%',
|
|
51
|
-
backgroundColor: agentColor.toHex(),
|
|
52
|
-
borderRadius: '50%',
|
|
53
|
+
// backgroundColor: agentColor.toHex(),
|
|
53
54
|
}}
|
|
54
|
-
src={
|
|
55
|
+
src={`${publicUrl.href}agents/${agentProfile.permanentId || agentName}/images/icon-256.png`}
|
|
55
56
|
alt="Agent Icon"
|
|
56
57
|
/>
|
|
57
58
|
</div>
|
|
@@ -25,6 +25,7 @@ export const generateMetadata = generateAgentMetadata;
|
|
|
25
25
|
|
|
26
26
|
export default async function AgentIntegrationPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
27
27
|
$sideEffect(headers());
|
|
28
|
+
|
|
28
29
|
const agentName = await getAgentName(params);
|
|
29
30
|
const isAdmin = await isUserAdmin();
|
|
30
31
|
|
|
@@ -187,7 +188,13 @@ export default async function AgentIntegrationPage({ params }: { params: Promise
|
|
|
187
188
|
{agentProfile.meta.image && (
|
|
188
189
|
// eslint-disable-next-line @next/next/no-img-element
|
|
189
190
|
<img
|
|
190
|
-
src={
|
|
191
|
+
src={
|
|
192
|
+
agentProfile.meta.image ||
|
|
193
|
+
generatePlaceholderAgentProfileImageUrl(
|
|
194
|
+
agentProfile.permanentId || agentName,
|
|
195
|
+
publicUrl,
|
|
196
|
+
)
|
|
197
|
+
}
|
|
191
198
|
alt={agentProfile.meta.fullname || agentName}
|
|
192
199
|
className="w-16 h-16 rounded-full object-cover border-2"
|
|
193
200
|
style={{ borderColor: primaryColor }}
|
|
@@ -18,6 +18,7 @@ export const generateMetadata = generateAgentMetadata;
|
|
|
18
18
|
|
|
19
19
|
export default async function AgentLinksPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
20
20
|
$sideEffect(headers());
|
|
21
|
+
|
|
21
22
|
const agentName = await getAgentName(params);
|
|
22
23
|
|
|
23
24
|
let agentProfile;
|
|
@@ -56,7 +57,13 @@ export default async function AgentLinksPage({ params }: { params: Promise<{ age
|
|
|
56
57
|
{agentProfile.meta.image && (
|
|
57
58
|
// eslint-disable-next-line @next/next/no-img-element
|
|
58
59
|
<img
|
|
59
|
-
src={
|
|
60
|
+
src={
|
|
61
|
+
agentProfile.meta.image ||
|
|
62
|
+
generatePlaceholderAgentProfileImageUrl(
|
|
63
|
+
agentProfile.permanentId || agentName,
|
|
64
|
+
publicUrl,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
60
67
|
alt={agentProfile.meta.fullname || agentName}
|
|
61
68
|
className="w-16 h-16 rounded-full object-cover border-2"
|
|
62
69
|
style={{ borderColor: primaryColor }}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
1
2
|
import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
2
3
|
import { serializeError } from '@promptbook-local/utils';
|
|
3
4
|
import { ImageResponse } from 'next/og';
|
|
@@ -24,6 +25,7 @@ export default async function Image({ params }: { params: Promise<{ agentName: s
|
|
|
24
25
|
const agentProfile = await getAgentProfile(agentName);
|
|
25
26
|
const agentColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
26
27
|
const backgroundColor = agentColor.then(grayscale(0.5));
|
|
28
|
+
const { publicUrl } = await $provideServer();
|
|
27
29
|
|
|
28
30
|
return new ImageResponse(
|
|
29
31
|
(
|
|
@@ -53,11 +55,14 @@ export default async function Image({ params }: { params: Promise<{ agentName: s
|
|
|
53
55
|
width: '80%',
|
|
54
56
|
backgroundColor: agentColor.toHex(),
|
|
55
57
|
borderRadius: '50%',
|
|
58
|
+
aspectRatio: '1 / 1',
|
|
56
59
|
}}
|
|
57
60
|
src={
|
|
58
61
|
agentProfile.meta.image ||
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
generatePlaceholderAgentProfileImageUrl(
|
|
63
|
+
agentProfile.permanentId || agentName,
|
|
64
|
+
publicUrl,
|
|
65
|
+
)
|
|
61
66
|
}
|
|
62
67
|
alt="Agent Icon"
|
|
63
68
|
/>
|
|
@@ -27,6 +27,7 @@ export default async function AgentPage({
|
|
|
27
27
|
const isAdmin = await isUserAdmin();
|
|
28
28
|
const { headless: headlessParam } = await searchParams;
|
|
29
29
|
const isHeadless = headlessParam !== undefined;
|
|
30
|
+
const { publicUrl } = await $provideServer();
|
|
30
31
|
|
|
31
32
|
let agentProfile;
|
|
32
33
|
try {
|
|
@@ -44,8 +45,6 @@ export default async function AgentPage({
|
|
|
44
45
|
throw error;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
const { publicUrl } = await $provideServer();
|
|
48
|
-
|
|
49
48
|
// Build agent page URL for QR and copy
|
|
50
49
|
const agentUrl = `${publicUrl.href}${encodeURIComponent(agentName)}`;
|
|
51
50
|
// <- TODO: [🐱🚀] Better
|
|
@@ -64,6 +63,7 @@ export default async function AgentPage({
|
|
|
64
63
|
<AgentProfileWrapper
|
|
65
64
|
agent={agentProfile}
|
|
66
65
|
agentUrl={agentUrl}
|
|
66
|
+
publicUrl={publicUrl}
|
|
67
67
|
agentEmail={agentEmail}
|
|
68
68
|
agentName={agentName}
|
|
69
69
|
brandColorHex={brandColorHex}
|
|
@@ -97,8 +97,7 @@ export default async function AgentPage({
|
|
|
97
97
|
brandColorHex={brandColorHex}
|
|
98
98
|
avatarSrc={
|
|
99
99
|
agentProfile.meta.image ||
|
|
100
|
-
agentProfile.permanentId ||
|
|
101
|
-
generatePlaceholderAgentProfileImageUrl(agentName)
|
|
100
|
+
generatePlaceholderAgentProfileImageUrl(agentProfile.permanentId || agentName, publicUrl)
|
|
102
101
|
}
|
|
103
102
|
isDeleted={isDeleted}
|
|
104
103
|
/>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
5
|
+
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
4
6
|
import { ArrowLeftIcon, FileTextIcon } from 'lucide-react';
|
|
5
7
|
import { headers } from 'next/headers';
|
|
6
8
|
import Link from 'next/link';
|
|
@@ -8,12 +10,14 @@ import { notFound } from 'next/navigation';
|
|
|
8
10
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
9
11
|
import { getAgentName, getAgentProfile } from '../_utils';
|
|
10
12
|
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
11
|
-
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
12
13
|
|
|
13
14
|
export const generateMetadata = generateAgentMetadata;
|
|
14
15
|
|
|
15
16
|
export default async function AgentSystemMessagePage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
16
17
|
$sideEffect(headers());
|
|
18
|
+
|
|
19
|
+
const { publicUrl } = await $provideServer();
|
|
20
|
+
|
|
17
21
|
const agentName = await getAgentName(params);
|
|
18
22
|
|
|
19
23
|
let agentProfile;
|
|
@@ -45,7 +49,13 @@ export default async function AgentSystemMessagePage({ params }: { params: Promi
|
|
|
45
49
|
{agentProfile.meta.image && (
|
|
46
50
|
// eslint-disable-next-line @next/next/no-img-element
|
|
47
51
|
<img
|
|
48
|
-
src={
|
|
52
|
+
src={
|
|
53
|
+
agentProfile.meta.image ||
|
|
54
|
+
generatePlaceholderAgentProfileImageUrl(
|
|
55
|
+
agentProfile.permanentId || agentName,
|
|
56
|
+
publicUrl,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
49
59
|
alt={agentProfile.meta.fullname || agentName}
|
|
50
60
|
className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
|
|
51
61
|
/>
|
|
@@ -77,7 +87,9 @@ export default async function AgentSystemMessagePage({ params }: { params: Promi
|
|
|
77
87
|
<div className="mt-6 bg-blue-50 rounded-lg p-4 border border-blue-200">
|
|
78
88
|
<h3 className="text-md font-semibold text-blue-900 mb-2">Model Requirements</h3>
|
|
79
89
|
<div className="text-sm text-blue-800">
|
|
80
|
-
<p
|
|
90
|
+
<p>
|
|
91
|
+
<strong>Model Variant:</strong> CHAT
|
|
92
|
+
</p>
|
|
81
93
|
{/* TODO: [🧠] Add more model requirements if available */}
|
|
82
94
|
</div>
|
|
83
95
|
</div>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { $provideBrowserForServer } from '@/src/tools/$provideBrowserForServer';
|
|
2
|
+
import { serializeError } from '@promptbook-local/utils';
|
|
3
|
+
import { NextResponse } from 'next/server';
|
|
4
|
+
import { assertsError } from '../../../../../../../src/errors/assertsError';
|
|
5
|
+
|
|
6
|
+
export async function GET() {
|
|
7
|
+
try {
|
|
8
|
+
const browserContext = await $provideBrowserForServer();
|
|
9
|
+
|
|
10
|
+
const page = await browserContext.newPage();
|
|
11
|
+
|
|
12
|
+
await page.goto('https://ptbk.io');
|
|
13
|
+
const screenshotBuffer = await page.screenshot();
|
|
14
|
+
|
|
15
|
+
// await page.close();
|
|
16
|
+
// Do not close browser
|
|
17
|
+
// <- TODO: !!!! Fix
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
return new NextResponse(new Blob([screenshotBuffer as any]), {
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'image/png',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
} catch (error) {
|
|
26
|
+
assertsError(error);
|
|
27
|
+
console.error('Error taking screenshot:', error);
|
|
28
|
+
return NextResponse.json({ error: serializeError(error) }, { status: 500 });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -6,7 +6,7 @@ import { NextResponse } from 'next/server';
|
|
|
6
6
|
export const dynamic = 'force-dynamic';
|
|
7
7
|
|
|
8
8
|
export async function GET() {
|
|
9
|
-
const txt = generateHumansTxt();
|
|
9
|
+
const txt = await generateHumansTxt();
|
|
10
10
|
return new NextResponse(txt, {
|
|
11
11
|
headers: {
|
|
12
12
|
'Content-Type': 'text/plain',
|
|
@@ -34,6 +34,8 @@ const calendarWithSeconds = {
|
|
|
34
34
|
export default async function HomePage() {
|
|
35
35
|
$sideEffect(/* Note: [🐶] This will ensure dynamic rendering of page and avoid Next.js pre-render */ headers());
|
|
36
36
|
|
|
37
|
+
const { publicUrl } = await $provideServer();
|
|
38
|
+
|
|
37
39
|
const currentUser = await getCurrentUser();
|
|
38
40
|
const isAdmin = await isUserAdmin(); /* <- TODO: [👹] Here should be user permissions */
|
|
39
41
|
|
|
@@ -94,9 +96,9 @@ export default async function HomePage() {
|
|
|
94
96
|
return (
|
|
95
97
|
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
|
|
96
98
|
<div className="container mx-auto px-4 py-16">
|
|
97
|
-
<AgentsList agents={[...agents]} isAdmin={isAdmin} />
|
|
99
|
+
<AgentsList agents={[...agents]} isAdmin={isAdmin} publicUrl={publicUrl} />
|
|
98
100
|
|
|
99
|
-
<ExternalAgentsSectionClient />
|
|
101
|
+
<ExternalAgentsSectionClient publicUrl={publicUrl} />
|
|
100
102
|
|
|
101
103
|
{isAdmin && <UsersList allowCreate={false} />}
|
|
102
104
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
2
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
2
3
|
import { TrashIcon } from 'lucide-react';
|
|
3
4
|
import Link from 'next/link';
|
|
4
5
|
import { DeletedAgentsList } from '../../components/Homepage/DeletedAgentsList';
|
|
@@ -9,6 +10,7 @@ export const metadata = {
|
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export default async function RecycleBinPage() {
|
|
13
|
+
const { publicUrl } = await $provideServer();
|
|
12
14
|
const collection = await $provideAgentCollectionForServer();
|
|
13
15
|
const deletedAgents = await collection.listDeletedAgents();
|
|
14
16
|
const isAdmin = await isUserAdmin();
|
|
@@ -34,7 +36,7 @@ export default async function RecycleBinPage() {
|
|
|
34
36
|
</Link>
|
|
35
37
|
</div>
|
|
36
38
|
) : (
|
|
37
|
-
<DeletedAgentsList agents={deletedAgents} isAdmin={isAdmin} />
|
|
39
|
+
<DeletedAgentsList agents={deletedAgents} isAdmin={isAdmin} publicUrl={publicUrl} />
|
|
38
40
|
)}
|
|
39
41
|
</div>
|
|
40
42
|
</div>
|
|
@@ -6,7 +6,7 @@ import { NextResponse } from 'next/server';
|
|
|
6
6
|
export const dynamic = 'force-dynamic';
|
|
7
7
|
|
|
8
8
|
export async function GET() {
|
|
9
|
-
const txt = generateRobotsTxt();
|
|
9
|
+
const txt = await generateRobotsTxt();
|
|
10
10
|
return new NextResponse(txt, {
|
|
11
11
|
headers: {
|
|
12
12
|
'Content-Type': 'text/plain',
|
|
@@ -6,7 +6,7 @@ import { NextResponse } from 'next/server';
|
|
|
6
6
|
export const dynamic = 'force-dynamic';
|
|
7
7
|
|
|
8
8
|
export async function GET() {
|
|
9
|
-
const txt = generateSecurityTxt();
|
|
9
|
+
const txt = await generateSecurityTxt();
|
|
10
10
|
return new NextResponse(txt, {
|
|
11
11
|
headers: {
|
|
12
12
|
'Content-Type': 'text/plain',
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
// Dynamic sitemap.xml for Agents Server
|
|
2
2
|
|
|
3
|
-
import { NEXT_PUBLIC_SITE_URL } from '@/config';
|
|
4
3
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
5
5
|
import { spaceTrim } from '@promptbook-local/utils';
|
|
6
6
|
import { NextResponse } from 'next/server';
|
|
7
7
|
|
|
8
8
|
export const dynamic = 'force-dynamic';
|
|
9
9
|
|
|
10
10
|
export async function GET() {
|
|
11
|
+
const { publicUrl } = await $provideServer();
|
|
12
|
+
|
|
11
13
|
const collection = await $provideAgentCollectionForServer();
|
|
12
14
|
|
|
13
15
|
// Assume collection.listAgents() returns an array of agent names
|
|
14
16
|
const agents = await collection.listAgents();
|
|
15
17
|
|
|
16
|
-
// Get base URL from environment or config
|
|
17
|
-
const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
|
|
18
|
-
|
|
19
18
|
const urls = agents
|
|
20
19
|
.map(
|
|
21
20
|
({ permanentId, agentName }) =>
|
|
22
|
-
`<url><loc>${
|
|
21
|
+
`<url><loc>${publicUrl.href}agents/${encodeURIComponent(permanentId || agentName)}</loc></url>`,
|
|
23
22
|
)
|
|
24
23
|
.join('\n');
|
|
25
24
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { colorToDataUrl } from '@promptbook-local/color';
|
|
3
4
|
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
4
5
|
import { AgentBasicInformation, string_agent_permanent_id } from '@promptbook-local/types';
|
|
5
6
|
import { RepeatIcon } from 'lucide-react';
|
|
@@ -26,6 +27,11 @@ type AgentProfileProps = {
|
|
|
26
27
|
*/
|
|
27
28
|
readonly agentUrl?: string;
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Base URL of the agents server
|
|
32
|
+
*/
|
|
33
|
+
readonly publicUrl: URL;
|
|
34
|
+
|
|
29
35
|
/**
|
|
30
36
|
* Email of the agent
|
|
31
37
|
*/
|
|
@@ -64,6 +70,7 @@ export function AgentProfile(props: AgentProfileProps) {
|
|
|
64
70
|
agent,
|
|
65
71
|
agentUrl = '',
|
|
66
72
|
agentEmail = '',
|
|
73
|
+
publicUrl,
|
|
67
74
|
permanentId,
|
|
68
75
|
renderMenu,
|
|
69
76
|
children,
|
|
@@ -71,11 +78,11 @@ export function AgentProfile(props: AgentProfileProps) {
|
|
|
71
78
|
isHeadless = false,
|
|
72
79
|
className,
|
|
73
80
|
} = props;
|
|
74
|
-
|
|
81
|
+
|
|
75
82
|
const { meta, agentName } = agent;
|
|
76
83
|
const fullname = (meta.fullname as string) || agentName || 'Agent';
|
|
77
84
|
const personaDescription = agent.personaDescription || '';
|
|
78
|
-
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId);
|
|
85
|
+
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId, publicUrl);
|
|
79
86
|
|
|
80
87
|
const [isQrModalOpen, setIsQrModalOpen] = useState(false);
|
|
81
88
|
const [isFlipped, setIsFlipped] = useState(false);
|
|
@@ -153,17 +160,19 @@ export function AgentProfile(props: AgentProfileProps) {
|
|
|
153
160
|
// ['cornerShape' as really_any /* <- Note: `cornerShape` is non standard CSS property */]: 'squircle ',
|
|
154
161
|
}}
|
|
155
162
|
>
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
|
164
|
+
<img
|
|
165
|
+
src={imageUrl}
|
|
166
|
+
alt={fullname}
|
|
167
|
+
className="w-full h-full object-cover"
|
|
168
|
+
// width={1024}
|
|
169
|
+
// height={1792}
|
|
170
|
+
// <- TODO: [🤐] DRY
|
|
171
|
+
style={{
|
|
172
|
+
objectFit: 'cover',
|
|
173
|
+
backgroundImage: `url(${colorToDataUrl(brandColorLightHex)})`,
|
|
174
|
+
}}
|
|
175
|
+
/>
|
|
167
176
|
|
|
168
177
|
{/* Flip hint icon */}
|
|
169
178
|
<div className="absolute bottom-2 md:bottom-4 right-2 md:right-4 bg-black/30 p-1 md:p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
|
|
@@ -8,14 +8,50 @@ import { AgentBasicInformation } from '../../../../../src/book-2.0/agent-source/
|
|
|
8
8
|
import { useAgentBackground } from '../AgentProfile/useAgentBackground';
|
|
9
9
|
|
|
10
10
|
type AgentCardProps = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @@@
|
|
13
|
+
*/
|
|
14
|
+
readonly agent: AgentBasicInformation;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @@@
|
|
18
|
+
*/
|
|
19
|
+
readonly href: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Base URL of the agents server
|
|
23
|
+
*/
|
|
24
|
+
readonly publicUrl: URL;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @@@
|
|
28
|
+
*/
|
|
29
|
+
readonly isAdmin?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @@@
|
|
33
|
+
*/
|
|
34
|
+
readonly onDelete?: (agentIdentifier: string) => void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @@@
|
|
38
|
+
*/
|
|
39
|
+
readonly onClone?: (agentIdentifier: string) => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @@@
|
|
43
|
+
*/
|
|
44
|
+
readonly onToggleVisibility?: (agentIdentifier: string) => void;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @@@
|
|
48
|
+
*/
|
|
49
|
+
readonly onRestore?: (agentIdentifier: string) => void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @@@
|
|
53
|
+
*/
|
|
54
|
+
readonly visibility?: 'PUBLIC' | 'PRIVATE';
|
|
19
55
|
};
|
|
20
56
|
|
|
21
57
|
const ACTION_BUTTON_CLASSES =
|
|
@@ -25,6 +61,7 @@ export function AgentCard({
|
|
|
25
61
|
agent,
|
|
26
62
|
href,
|
|
27
63
|
isAdmin,
|
|
64
|
+
publicUrl,
|
|
28
65
|
onDelete,
|
|
29
66
|
onClone,
|
|
30
67
|
onToggleVisibility,
|
|
@@ -33,7 +70,7 @@ export function AgentCard({
|
|
|
33
70
|
}: AgentCardProps) {
|
|
34
71
|
const { meta, agentName } = agent;
|
|
35
72
|
const fullname = (meta.fullname as string) || agentName || 'Agent';
|
|
36
|
-
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName);
|
|
73
|
+
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName, publicUrl);
|
|
37
74
|
const personaDescription = agent.personaDescription || '';
|
|
38
75
|
|
|
39
76
|
const { brandColorLightHex, brandColorDarkHex, backgroundImage } = useAgentBackground(meta.color);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Client Component for rendering and deleting agents
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
-
import React, { useState } from 'react';
|
|
5
|
-
import { useRouter } from 'next/navigation';
|
|
6
4
|
import { TrashIcon } from 'lucide-react';
|
|
7
5
|
import Link from 'next/link';
|
|
6
|
+
import { useRouter } from 'next/navigation';
|
|
7
|
+
import { useState } from 'react';
|
|
8
8
|
import { AddAgentButton } from '../../app/AddAgentButton';
|
|
9
9
|
import { AgentCard } from './AgentCard';
|
|
10
10
|
import { Section } from './Section';
|
|
@@ -16,16 +16,29 @@ type AgentWithVisibility = AgentBasicInformation & {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
type AgentsListProps = {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @@@
|
|
21
|
+
*/
|
|
22
|
+
readonly agents: AgentWithVisibility[];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @@@
|
|
26
|
+
*/
|
|
27
|
+
readonly isAdmin: boolean;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Base URL of the agents server
|
|
31
|
+
*/
|
|
32
|
+
readonly publicUrl: URL;
|
|
21
33
|
};
|
|
22
34
|
|
|
23
|
-
export function AgentsList(
|
|
35
|
+
export function AgentsList(props: AgentsListProps) {
|
|
36
|
+
const { agents: initialAgents, isAdmin, publicUrl } = props;
|
|
24
37
|
const router = useRouter();
|
|
25
38
|
const [agents, setAgents] = useState(Array.from(initialAgents));
|
|
26
39
|
|
|
27
40
|
const handleDelete = async (agentIdentifier: string) => {
|
|
28
|
-
const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
41
|
+
const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
29
42
|
if (!agent) return;
|
|
30
43
|
if (!window.confirm(`Delete agent "${agent.agentName}"? It will be moved to Recycle Bin.`)) return;
|
|
31
44
|
|
|
@@ -45,12 +58,14 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
|
|
|
45
58
|
};
|
|
46
59
|
|
|
47
60
|
const handleClone = async (agentIdentifier: string) => {
|
|
48
|
-
const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
61
|
+
const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
49
62
|
if (!agent) return;
|
|
50
63
|
if (!window.confirm(`Clone agent "${agent.agentName}"?`)) return;
|
|
51
64
|
|
|
52
65
|
try {
|
|
53
|
-
const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/clone`, {
|
|
66
|
+
const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/clone`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
});
|
|
54
69
|
if (response.ok) {
|
|
55
70
|
const newAgent = await response.json();
|
|
56
71
|
setAgents([...agents, newAgent]);
|
|
@@ -64,7 +79,7 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
|
|
|
64
79
|
};
|
|
65
80
|
|
|
66
81
|
const handleToggleVisibility = async (agentIdentifier: string) => {
|
|
67
|
-
const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
82
|
+
const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
68
83
|
if (!agent) return;
|
|
69
84
|
|
|
70
85
|
const newVisibility = agent.visibility === 'PUBLIC' ? 'PRIVATE' : 'PUBLIC';
|
|
@@ -78,11 +93,13 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
|
|
|
78
93
|
|
|
79
94
|
if (response.ok) {
|
|
80
95
|
// Update the local state
|
|
81
|
-
setAgents(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
setAgents(
|
|
97
|
+
agents.map((a) =>
|
|
98
|
+
a.permanentId === agent.permanentId || a.agentName === agent.agentName
|
|
99
|
+
? { ...a, visibility: newVisibility }
|
|
100
|
+
: a,
|
|
101
|
+
),
|
|
102
|
+
);
|
|
86
103
|
router.refresh(); // Refresh server data to ensure consistency
|
|
87
104
|
} else {
|
|
88
105
|
alert('Failed to update agent visibility');
|
|
@@ -95,6 +112,7 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
|
|
|
95
112
|
<AgentCard
|
|
96
113
|
key={agent.permanentId || agent.agentName}
|
|
97
114
|
agent={agent}
|
|
115
|
+
publicUrl={publicUrl}
|
|
98
116
|
href={`/agents/${encodeURIComponent(agent.permanentId || agent.agentName)}`}
|
|
99
117
|
isAdmin={isAdmin}
|
|
100
118
|
onDelete={handleDelete}
|
|
@@ -1,26 +1,41 @@
|
|
|
1
1
|
// Client Component for rendering deleted agents
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { useState } from 'react';
|
|
5
5
|
import { AgentCard } from './AgentCard';
|
|
6
6
|
|
|
7
7
|
import { AgentBasicInformation } from '../../../../../src/book-2.0/agent-source/AgentBasicInformation';
|
|
8
8
|
|
|
9
9
|
type DeletedAgentsListProps = {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* @@@
|
|
12
|
+
*/
|
|
13
|
+
readonly agents: readonly AgentBasicInformation[];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @@@
|
|
17
|
+
*/
|
|
18
|
+
readonly isAdmin: boolean;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Base URL of the agents server
|
|
22
|
+
*/
|
|
23
|
+
readonly publicUrl: URL;
|
|
12
24
|
};
|
|
13
25
|
|
|
14
|
-
export function DeletedAgentsList(
|
|
26
|
+
export function DeletedAgentsList(props: DeletedAgentsListProps) {
|
|
27
|
+
const { agents: initialAgents, isAdmin, publicUrl } = props;
|
|
15
28
|
const [agents, setAgents] = useState(Array.from(initialAgents));
|
|
16
29
|
|
|
17
30
|
const handleRestore = async (agentIdentifier: string) => {
|
|
18
|
-
const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
31
|
+
const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
|
|
19
32
|
if (!agent) return;
|
|
20
33
|
if (!window.confirm(`Restore agent "${agent.agentName}"?`)) return;
|
|
21
34
|
|
|
22
35
|
try {
|
|
23
|
-
const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/restore`, {
|
|
36
|
+
const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/restore`, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
});
|
|
24
39
|
if (response.ok) {
|
|
25
40
|
// Update local state immediately
|
|
26
41
|
setAgents(agents.filter((a) => a.permanentId !== agent.permanentId && a.agentName !== agent.agentName));
|
|
@@ -40,6 +55,7 @@ export function DeletedAgentsList({ agents: initialAgents, isAdmin }: DeletedAge
|
|
|
40
55
|
<AgentCard
|
|
41
56
|
key={agent.permanentId || agent.agentName}
|
|
42
57
|
agent={agent}
|
|
58
|
+
publicUrl={publicUrl}
|
|
43
59
|
href={`/agents/${encodeURIComponent(agent.permanentId || agent.agentName)}`}
|
|
44
60
|
isAdmin={isAdmin}
|
|
45
61
|
onRestore={handleRestore}
|