@promptbook/cli 0.103.0-54 → 0.103.0-56
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 +0 -2
- package/apps/agents-server/package-lock.json +1163 -0
- package/apps/agents-server/package.json +6 -0
- package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +79 -6
- package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +171 -69
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +216 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +78 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileView.tsx +233 -0
- package/apps/agents-server/src/app/agents/[agentName]/CloneAgentButton.tsx +4 -4
- package/apps/agents-server/src/app/agents/[agentName]/InstallPwaButton.tsx +2 -2
- package/apps/agents-server/src/app/agents/[agentName]/QrCodeModal.tsx +90 -0
- package/apps/agents-server/src/app/agents/[agentName]/agentLinks.tsx +80 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +11 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/mcp/route.ts +203 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/route.ts +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/systemMessage/route.ts +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/openai/chat/completions/route.ts +3 -169
- package/apps/agents-server/src/app/agents/[agentName]/api/openai/models/route.ts +93 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/openai/v1/chat/completions/route.ts +10 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/openai/v1/models/route.ts +93 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/openrouter/chat/completions/route.ts +10 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/voice/route.ts +4 -0
- package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +9 -2
- package/apps/agents-server/src/app/agents/[agentName]/integration/SdkCodeTabs.tsx +31 -0
- package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +271 -30
- package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +182 -0
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +108 -165
- package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +61 -0
- package/apps/agents-server/src/app/api/auth/change-password/route.ts +75 -0
- package/apps/agents-server/src/app/api/chat-feedback/export/route.ts +55 -0
- package/apps/agents-server/src/app/api/chat-history/export/route.ts +55 -0
- package/apps/agents-server/src/app/api/openai/v1/chat/completions/route.ts +6 -0
- package/apps/agents-server/src/app/api/openai/v1/models/route.ts +65 -0
- package/apps/agents-server/src/app/docs/[docId]/page.tsx +12 -32
- package/apps/agents-server/src/app/docs/page.tsx +42 -17
- package/apps/agents-server/src/app/globals.css +129 -0
- package/apps/agents-server/src/app/layout.tsx +8 -2
- package/apps/agents-server/src/app/manifest.ts +1 -1
- package/apps/agents-server/src/components/ChangePasswordDialog/ChangePasswordDialog.tsx +41 -0
- package/apps/agents-server/src/components/ChangePasswordForm/ChangePasswordForm.tsx +159 -0
- package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +87 -0
- package/apps/agents-server/src/components/Header/Header.tsx +94 -38
- package/apps/agents-server/src/components/OpenMojiIcon/OpenMojiIcon.tsx +20 -0
- package/apps/agents-server/src/components/PrintButton/PrintButton.tsx +18 -0
- package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +18 -0
- package/apps/agents-server/src/database/migrations/2025-12-0070-chat-history-source.sql +2 -0
- package/apps/agents-server/src/database/schema.ts +6 -0
- package/apps/agents-server/src/middleware.ts +1 -1
- package/apps/agents-server/src/utils/convertToCsv.ts +31 -0
- package/apps/agents-server/src/utils/handleChatCompletion.ts +355 -0
- package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +100 -0
- package/apps/agents-server/src/utils/validateApiKey.ts +128 -0
- package/apps/agents-server/tailwind.config.ts +1 -1
- package/esm/index.es.js +1188 -175
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +4 -0
- package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
- package/esm/typings/src/commitments/CLOSED/CLOSED.d.ts +35 -0
- package/esm/typings/src/commitments/COMPONENT/COMPONENT.d.ts +28 -0
- package/esm/typings/src/commitments/FROM/FROM.d.ts +34 -0
- package/esm/typings/src/commitments/LANGUAGE/LANGUAGE.d.ts +35 -0
- package/esm/typings/src/commitments/META_COLOR/META_COLOR.d.ts +6 -0
- package/esm/typings/src/commitments/META_FONT/META_FONT.d.ts +42 -0
- package/esm/typings/src/commitments/OPEN/OPEN.d.ts +35 -0
- package/esm/typings/src/commitments/USE/USE.d.ts +53 -0
- package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +38 -0
- package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.test.d.ts +1 -0
- package/esm/typings/src/commitments/USE_MCP/USE_MCP.d.ts +37 -0
- package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +38 -0
- package/esm/typings/src/commitments/index.d.ts +12 -1
- package/esm/typings/src/playground/playground.d.ts +3 -0
- package/esm/typings/src/utils/color/Color.d.ts +8 -0
- package/esm/typings/src/utils/color/css-colors.d.ts +1 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +1180 -167
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/playground/playground1.d.ts +0 -2
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { $getTableName } from '../../../../database/$getTableName';
|
|
3
|
+
import { $provideSupabase } from '../../../../database/$provideSupabase';
|
|
4
|
+
import { convertToCsv } from '../../../../utils/convertToCsv';
|
|
5
|
+
import { isUserAdmin } from '../../../../utils/isUserAdmin';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Export chat feedback as CSV.
|
|
9
|
+
*
|
|
10
|
+
* Query params:
|
|
11
|
+
* - agentName: filter by agent name (optional)
|
|
12
|
+
*/
|
|
13
|
+
export async function GET(request: NextRequest) {
|
|
14
|
+
if (!(await isUserAdmin())) {
|
|
15
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const searchParams = request.nextUrl.searchParams;
|
|
20
|
+
const agentName = searchParams.get('agentName');
|
|
21
|
+
|
|
22
|
+
const supabase = $provideSupabase();
|
|
23
|
+
const table = await $getTableName('ChatFeedback');
|
|
24
|
+
|
|
25
|
+
let query = supabase.from(table).select('*');
|
|
26
|
+
|
|
27
|
+
if (agentName) {
|
|
28
|
+
query = query.eq('agentName', agentName);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
query = query.order('createdAt', { ascending: false });
|
|
32
|
+
|
|
33
|
+
const { data, error } = await query;
|
|
34
|
+
|
|
35
|
+
if (error) {
|
|
36
|
+
console.error('Export chat feedback error:', error);
|
|
37
|
+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const csv = convertToCsv((data || []) as Record<string, unknown>[]);
|
|
41
|
+
const filename = agentName
|
|
42
|
+
? `chat-feedback-${agentName}-${new Date().toISOString()}.csv`
|
|
43
|
+
: `chat-feedback-${new Date().toISOString()}.csv`;
|
|
44
|
+
|
|
45
|
+
return new NextResponse(csv, {
|
|
46
|
+
headers: {
|
|
47
|
+
'Content-Type': 'text/csv',
|
|
48
|
+
'Content-Disposition': `attachment; filename="${filename}"`,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('Export chat feedback error:', error);
|
|
53
|
+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { $getTableName } from '../../../../database/$getTableName';
|
|
3
|
+
import { $provideSupabase } from '../../../../database/$provideSupabase';
|
|
4
|
+
import { convertToCsv } from '../../../../utils/convertToCsv';
|
|
5
|
+
import { isUserAdmin } from '../../../../utils/isUserAdmin';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Export chat history as CSV.
|
|
9
|
+
*
|
|
10
|
+
* Query params:
|
|
11
|
+
* - agentName: filter by agent name (optional)
|
|
12
|
+
*/
|
|
13
|
+
export async function GET(request: NextRequest) {
|
|
14
|
+
if (!(await isUserAdmin())) {
|
|
15
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const searchParams = request.nextUrl.searchParams;
|
|
20
|
+
const agentName = searchParams.get('agentName');
|
|
21
|
+
|
|
22
|
+
const supabase = $provideSupabase();
|
|
23
|
+
const table = await $getTableName('ChatHistory');
|
|
24
|
+
|
|
25
|
+
let query = supabase.from(table).select('*');
|
|
26
|
+
|
|
27
|
+
if (agentName) {
|
|
28
|
+
query = query.eq('agentName', agentName);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
query = query.order('createdAt', { ascending: false });
|
|
32
|
+
|
|
33
|
+
const { data, error } = await query;
|
|
34
|
+
|
|
35
|
+
if (error) {
|
|
36
|
+
console.error('Export chat history error:', error);
|
|
37
|
+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const csv = convertToCsv((data || []) as Record<string, unknown>[]);
|
|
41
|
+
const filename = agentName
|
|
42
|
+
? `chat-history-${agentName}-${new Date().toISOString()}.csv`
|
|
43
|
+
: `chat-history-${new Date().toISOString()}.csv`;
|
|
44
|
+
|
|
45
|
+
return new NextResponse(csv, {
|
|
46
|
+
headers: {
|
|
47
|
+
'Content-Type': 'text/csv',
|
|
48
|
+
'Content-Disposition': `attachment; filename="${filename}"`,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('Export chat history error:', error);
|
|
53
|
+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
2
|
+
import { validateApiKey } from '@/src/utils/validateApiKey';
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GET /api/openai/v1/models
|
|
7
|
+
*
|
|
8
|
+
* Lists all available agents as models for the OpenAI-compatible API.
|
|
9
|
+
*/
|
|
10
|
+
export async function GET(request: NextRequest) {
|
|
11
|
+
// Validate API key explicitly (in addition to middleware)
|
|
12
|
+
const apiKeyValidation = await validateApiKey(request);
|
|
13
|
+
if (!apiKeyValidation.isValid) {
|
|
14
|
+
return NextResponse.json(
|
|
15
|
+
{
|
|
16
|
+
error: {
|
|
17
|
+
message: apiKeyValidation.error || 'Invalid API key',
|
|
18
|
+
type: 'authentication_error',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{ status: 401 },
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const collection = await $provideAgentCollectionForServer();
|
|
27
|
+
const agentNames = await collection.listAgents();
|
|
28
|
+
|
|
29
|
+
const models = agentNames.map((agentName) => ({
|
|
30
|
+
id: agentName,
|
|
31
|
+
object: 'model',
|
|
32
|
+
created: Math.floor(Date.now() / 1000), // We don't have creation date readily available in listAgents
|
|
33
|
+
owned_by: 'promptbook',
|
|
34
|
+
permission: [
|
|
35
|
+
{
|
|
36
|
+
id: `modelperm-${agentName}`,
|
|
37
|
+
object: 'model_permission',
|
|
38
|
+
created: Math.floor(Date.now() / 1000),
|
|
39
|
+
allow_create_engine: false,
|
|
40
|
+
allow_sampling: true,
|
|
41
|
+
allow_logprobs: false,
|
|
42
|
+
allow_search_indices: false,
|
|
43
|
+
allow_view: true,
|
|
44
|
+
allow_fine_tuning: false,
|
|
45
|
+
organization: '*',
|
|
46
|
+
group: null,
|
|
47
|
+
is_blocking: false,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
root: agentName,
|
|
51
|
+
parent: null,
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
return NextResponse.json({
|
|
55
|
+
object: 'list',
|
|
56
|
+
data: models,
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error('Error in models listing handler:', error);
|
|
60
|
+
return NextResponse.json(
|
|
61
|
+
{ error: { message: (error as Error).message || 'Internal Server Error', type: 'server_error' } },
|
|
62
|
+
{ status: 500 },
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { notFound } from 'next/navigation';
|
|
2
|
-
import ReactMarkdown from 'react-markdown';
|
|
3
2
|
import { BookCommitment } from '../../../../../../src/commitments/_base/BookCommitment';
|
|
4
3
|
import { getVisibleCommitmentDefinitions } from '../../../utils/getVisibleCommitmentDefinitions';
|
|
4
|
+
import { PrintButton } from '../../../components/PrintButton/PrintButton';
|
|
5
|
+
import { PrintHeader } from '../../../components/PrintHeader/PrintHeader';
|
|
6
|
+
import { DocumentationContent } from '../../../components/DocumentationContent/DocumentationContent';
|
|
5
7
|
|
|
6
8
|
type DocPageProps = {
|
|
7
9
|
params: Promise<{
|
|
@@ -25,38 +27,16 @@ export default async function DocPage(props: DocPageProps) {
|
|
|
25
27
|
|
|
26
28
|
return (
|
|
27
29
|
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
|
|
30
|
+
<PrintButton />
|
|
31
|
+
|
|
28
32
|
<div className="container mx-auto px-4 py-16">
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<span className="text-gray-400 font-normal ml-4 text-2xl">
|
|
37
|
-
/ {aliases.join(' / ')}
|
|
38
|
-
</span>
|
|
39
|
-
)}
|
|
40
|
-
</h1>
|
|
41
|
-
<span className="px-3 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-700">
|
|
42
|
-
Commitment
|
|
43
|
-
</span>
|
|
44
|
-
</div>
|
|
45
|
-
{primary.description && (
|
|
46
|
-
<p className="text-xl text-gray-600 leading-relaxed max-w-3xl">
|
|
47
|
-
{primary.description}
|
|
48
|
-
</p>
|
|
49
|
-
)}
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
<div className="p-8">
|
|
53
|
-
<article className="prose prose-lg prose-slate max-w-none prose-headings:font-bold prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-p:text-gray-600 prose-pre:bg-gray-50 prose-pre:border prose-pre:border-gray-200 prose-pre:text-gray-800">
|
|
54
|
-
<ReactMarkdown>
|
|
55
|
-
{primary.documentation}
|
|
56
|
-
</ReactMarkdown>
|
|
57
|
-
</article>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
33
|
+
<PrintHeader title={primary.type} />
|
|
34
|
+
|
|
35
|
+
<DocumentationContent
|
|
36
|
+
primary={primary}
|
|
37
|
+
aliases={aliases}
|
|
38
|
+
isPrintOnly={false}
|
|
39
|
+
/>
|
|
60
40
|
</div>
|
|
61
41
|
</div>
|
|
62
42
|
);
|
|
@@ -1,33 +1,58 @@
|
|
|
1
1
|
import Link from 'next/link';
|
|
2
2
|
import { Card } from '../../components/Homepage/Card';
|
|
3
3
|
import { Section } from '../../components/Homepage/Section';
|
|
4
|
+
import { OpenMojiIcon } from '../../components/OpenMojiIcon/OpenMojiIcon';
|
|
4
5
|
import { getVisibleCommitmentDefinitions } from '../../utils/getVisibleCommitmentDefinitions';
|
|
6
|
+
import { PrintButton } from '../../components/PrintButton/PrintButton';
|
|
7
|
+
import { PrintHeader } from '../../components/PrintHeader/PrintHeader';
|
|
8
|
+
import { DocumentationContent } from '../../components/DocumentationContent/DocumentationContent';
|
|
5
9
|
|
|
6
10
|
export default function DocsPage() {
|
|
7
11
|
const groupedCommitments = getVisibleCommitmentDefinitions();
|
|
8
12
|
|
|
9
13
|
return (
|
|
10
14
|
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
|
|
15
|
+
<PrintButton />
|
|
16
|
+
|
|
11
17
|
<div className="container mx-auto px-4 py-16">
|
|
12
|
-
<
|
|
18
|
+
<PrintHeader title="Full Documentation" />
|
|
19
|
+
|
|
20
|
+
{/* Screen view: Cards */}
|
|
21
|
+
<div className="print:hidden">
|
|
22
|
+
<Section title="Documentation">
|
|
23
|
+
{groupedCommitments.map(({ primary, aliases }) => (
|
|
24
|
+
<Link key={primary.type} href={`/docs/${primary.type}`} className="block h-full group">
|
|
25
|
+
<Card className="h-full group-hover:border-blue-500 transition-colors">
|
|
26
|
+
<h3 className="text-xl font-semibold mb-2 group-hover:text-blue-600 transition-colors">
|
|
27
|
+
<OpenMojiIcon icon={primary.icon} className="mr-2" />
|
|
28
|
+
{primary.type}
|
|
29
|
+
{aliases.length > 0 && (
|
|
30
|
+
<span className="text-gray-400 font-normal text-lg">
|
|
31
|
+
{' / '}
|
|
32
|
+
{aliases.join(' / ')}
|
|
33
|
+
</span>
|
|
34
|
+
)}
|
|
35
|
+
</h3>
|
|
36
|
+
{primary.description && <p className="text-gray-600 line-clamp-3">{primary.description}</p>}
|
|
37
|
+
</Card>
|
|
38
|
+
</Link>
|
|
39
|
+
))}
|
|
40
|
+
</Section>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
{/* Print view: Full Content */}
|
|
44
|
+
<div className="hidden print:block space-y-12">
|
|
13
45
|
{groupedCommitments.map(({ primary, aliases }) => (
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{aliases.join(' / ')}
|
|
23
|
-
</span>
|
|
24
|
-
)}
|
|
25
|
-
</h3>
|
|
26
|
-
{primary.description && <p className="text-gray-600 line-clamp-3">{primary.description}</p>}
|
|
27
|
-
</Card>
|
|
28
|
-
</Link>
|
|
46
|
+
<div key={primary.type} className="break-inside-avoid page-break-after-always">
|
|
47
|
+
<DocumentationContent
|
|
48
|
+
primary={primary}
|
|
49
|
+
aliases={aliases}
|
|
50
|
+
isPrintOnly={true}
|
|
51
|
+
/>
|
|
52
|
+
<hr className="my-8 border-gray-200" />
|
|
53
|
+
</div>
|
|
29
54
|
))}
|
|
30
|
-
</
|
|
55
|
+
</div>
|
|
31
56
|
</div>
|
|
32
57
|
</div>
|
|
33
58
|
);
|
|
@@ -54,6 +54,11 @@ body {
|
|
|
54
54
|
font-family: var(--font-barlow-condensed), 'OpenMojiBlack', Arial, Helvetica, sans-serif;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/* Poppins font for agent names and headings */
|
|
58
|
+
.font-poppins {
|
|
59
|
+
font-family: var(--font-poppins), 'Poppins', system-ui, -apple-system, sans-serif;
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
/* Custom utilities */
|
|
58
63
|
.line-clamp-2 {
|
|
59
64
|
display: -webkit-box;
|
|
@@ -135,6 +140,53 @@ textarea:focus-visible {
|
|
|
135
140
|
animation: spin 1s linear infinite;
|
|
136
141
|
}
|
|
137
142
|
|
|
143
|
+
/* Tailwind CSS animation utilities */
|
|
144
|
+
@keyframes fade-in {
|
|
145
|
+
from {
|
|
146
|
+
opacity: 0;
|
|
147
|
+
}
|
|
148
|
+
to {
|
|
149
|
+
opacity: 1;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@keyframes slide-in-from-top-2 {
|
|
154
|
+
from {
|
|
155
|
+
transform: translateY(-0.5rem);
|
|
156
|
+
}
|
|
157
|
+
to {
|
|
158
|
+
transform: translateY(0);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@keyframes zoom-in-95 {
|
|
163
|
+
from {
|
|
164
|
+
opacity: 0;
|
|
165
|
+
transform: scale(0.95);
|
|
166
|
+
}
|
|
167
|
+
to {
|
|
168
|
+
opacity: 1;
|
|
169
|
+
transform: scale(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.animate-in {
|
|
174
|
+
animation-duration: 200ms;
|
|
175
|
+
animation-fill-mode: both;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.fade-in {
|
|
179
|
+
animation-name: fade-in;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.slide-in-from-top-2 {
|
|
183
|
+
animation-name: slide-in-from-top-2;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.zoom-in-95 {
|
|
187
|
+
animation-name: zoom-in-95;
|
|
188
|
+
}
|
|
189
|
+
|
|
138
190
|
/* Gradient backgrounds */
|
|
139
191
|
.bg-gradient-to-br {
|
|
140
192
|
background-image: linear-gradient(to bottom right, var(--tw-gradient-stops));
|
|
@@ -145,3 +197,80 @@ textarea:focus-visible {
|
|
|
145
197
|
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
|
146
198
|
border: 1px solid #e2e8f0;
|
|
147
199
|
}
|
|
200
|
+
|
|
201
|
+
/* Print styles */
|
|
202
|
+
@media print {
|
|
203
|
+
@page {
|
|
204
|
+
margin: 2cm;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Hide UI elements */
|
|
208
|
+
header,
|
|
209
|
+
footer,
|
|
210
|
+
nav,
|
|
211
|
+
aside,
|
|
212
|
+
button:not(.print:block),
|
|
213
|
+
.no-print,
|
|
214
|
+
[role="complementary"],
|
|
215
|
+
#portal-root {
|
|
216
|
+
display: none !important;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Reset layout */
|
|
220
|
+
body,
|
|
221
|
+
main {
|
|
222
|
+
padding: 0 !important;
|
|
223
|
+
margin: 0 !important;
|
|
224
|
+
background: white !important;
|
|
225
|
+
min-height: auto !important;
|
|
226
|
+
width: 100% !important;
|
|
227
|
+
color: black !important;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Remove shadows and backgrounds for clean print */
|
|
231
|
+
* {
|
|
232
|
+
box-shadow: none !important;
|
|
233
|
+
text-shadow: none !important;
|
|
234
|
+
background-color: transparent !important;
|
|
235
|
+
background-image: none !important;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Ensure text visibility */
|
|
239
|
+
h1, h2, h3, h4, h5, h6, p, li, span, div {
|
|
240
|
+
color: black !important;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Links */
|
|
244
|
+
a {
|
|
245
|
+
text-decoration: underline;
|
|
246
|
+
color: black !important;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Preserve borders */
|
|
250
|
+
.border, .border-b, .border-t, .border-l, .border-r {
|
|
251
|
+
border-color: #ddd !important;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Page break control */
|
|
255
|
+
h1, h2 {
|
|
256
|
+
break-after: avoid;
|
|
257
|
+
page-break-after: avoid;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
p, li, pre, code {
|
|
261
|
+
break-inside: avoid;
|
|
262
|
+
page-break-inside: avoid;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Specific component overrides */
|
|
266
|
+
.card, .bg-white {
|
|
267
|
+
border: none !important;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/* Code blocks */
|
|
271
|
+
pre, code {
|
|
272
|
+
background-color: #f5f5f5 !important;
|
|
273
|
+
border: 1px solid #ddd !important;
|
|
274
|
+
white-space: pre-wrap !important;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import faviconLogoImage from '@/public/favicon.ico';
|
|
2
2
|
import { LayoutWrapper } from '@/src/components/LayoutWrapper/LayoutWrapper';
|
|
3
3
|
import type { Metadata } from 'next';
|
|
4
|
-
import { Barlow_Condensed } from 'next/font/google';
|
|
4
|
+
import { Barlow_Condensed, Poppins } from 'next/font/google';
|
|
5
5
|
import { getMetadata } from '../database/getMetadata';
|
|
6
6
|
import { $provideAgentCollectionForServer } from '../tools/$provideAgentCollectionForServer';
|
|
7
7
|
import { $provideServer } from '../tools/$provideServer';
|
|
@@ -15,6 +15,12 @@ const barlowCondensed = Barlow_Condensed({
|
|
|
15
15
|
variable: '--font-barlow-condensed',
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
const poppins = Poppins({
|
|
19
|
+
subsets: ['latin'],
|
|
20
|
+
weight: ['400', '500', '600', '700', '800'],
|
|
21
|
+
variable: '--font-poppins',
|
|
22
|
+
});
|
|
23
|
+
|
|
18
24
|
export async function generateMetadata(): Promise<Metadata> {
|
|
19
25
|
const { publicUrl } = await $provideServer();
|
|
20
26
|
const serverName = (await getMetadata('SERVER_NAME')) || 'Promptbook Agents Server';
|
|
@@ -98,7 +104,7 @@ export default async function RootLayout({
|
|
|
98
104
|
{/* Default favicon as a fallback */}
|
|
99
105
|
<link rel="icon" href={serverFaviconUrl} type="image/x-icon" />
|
|
100
106
|
</head>
|
|
101
|
-
<body className={`${barlowCondensed.variable} antialiased bg-white text-gray-900`}>
|
|
107
|
+
<body className={`${barlowCondensed.variable} ${poppins.variable} antialiased bg-white text-gray-900`}>
|
|
102
108
|
<LayoutWrapper
|
|
103
109
|
isAdmin={isAdmin}
|
|
104
110
|
currentUser={currentUser}
|
|
@@ -41,7 +41,7 @@ export default async function manifest(): Promise<MetadataRoute.Manifest> {
|
|
|
41
41
|
const description = agentProfile.meta.description || agentProfile.personaDescription || `Agent ${name}`;
|
|
42
42
|
|
|
43
43
|
// Extract brand color from meta
|
|
44
|
-
const brandColor = Color.
|
|
44
|
+
const brandColor = Color.fromSafe(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
45
45
|
const theme_color = brandColor.toHex();
|
|
46
46
|
const background_color = '#ffffff';
|
|
47
47
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { X } from 'lucide-react';
|
|
4
|
+
import { ChangePasswordForm } from '../ChangePasswordForm/ChangePasswordForm';
|
|
5
|
+
import { Portal } from '../Portal/Portal';
|
|
6
|
+
|
|
7
|
+
type ChangePasswordDialogProps = {
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function ChangePasswordDialog(props: ChangePasswordDialogProps) {
|
|
13
|
+
const { isOpen, onClose } = props;
|
|
14
|
+
|
|
15
|
+
if (!isOpen) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Portal>
|
|
21
|
+
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
|
22
|
+
<div className="relative w-full max-w-md bg-white rounded-lg shadow-lg border border-gray-200 p-6 animate-in zoom-in-95 duration-200">
|
|
23
|
+
<button
|
|
24
|
+
onClick={onClose}
|
|
25
|
+
className="absolute top-4 right-4 text-gray-400 hover:text-gray-500 transition-colors"
|
|
26
|
+
>
|
|
27
|
+
<X className="w-5 h-5" />
|
|
28
|
+
<span className="sr-only">Close</span>
|
|
29
|
+
</button>
|
|
30
|
+
|
|
31
|
+
<div className="mb-6">
|
|
32
|
+
<h2 className="text-xl font-semibold text-gray-900">Change Password</h2>
|
|
33
|
+
<p className="text-sm text-gray-500 mt-1">Update your password to keep your account secure</p>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<ChangePasswordForm onSuccess={onClose} />
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</Portal>
|
|
40
|
+
);
|
|
41
|
+
}
|