@promptbook/cli 0.103.0-55 → 0.103.0-66
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/TODO.txt +5 -1
- package/apps/agents-server/package-lock.json +2336 -0
- package/apps/agents-server/package.json +9 -0
- package/apps/agents-server/src/app/actions.ts +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +282 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +91 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +44 -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]/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/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/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]/generateAgentMetadata.ts +7 -3
- 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]/layout.tsx +41 -0
- package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +61 -97
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +47 -157
- package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +70 -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/embed/page.tsx +2 -2
- package/apps/agents-server/src/app/globals.css +129 -0
- package/apps/agents-server/src/app/layout.tsx +16 -26
- package/apps/agents-server/src/app/manifest.ts +9 -4
- package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +334 -0
- package/apps/agents-server/src/components/AgentProfile/AgentProfileFromSource.tsx +23 -0
- package/apps/agents-server/src/{app/agents/[agentName] → components/AgentProfile}/AgentQrCode.tsx +8 -1
- package/apps/agents-server/src/components/AgentProfile/QrCodeModal.tsx +90 -0
- package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +87 -0
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +7 -6
- 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/metadataDefaults.ts +6 -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/utils/handleChatCompletion.ts +186 -14
- package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +13 -6
- package/apps/agents-server/src/utils/validateApiKey.ts +128 -0
- package/apps/agents-server/tailwind.config.ts +1 -1
- package/esm/index.es.js +953 -474
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +2 -2
- package/esm/typings/src/_packages/core.index.d.ts +6 -8
- package/esm/typings/src/_packages/types.index.d.ts +7 -1
- package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -1
- package/esm/typings/src/book-2.0/agent-source/createCommitmentRegex.d.ts +1 -1
- package/esm/typings/src/book-components/Chat/AgentChat/AgentChat.d.ts +3 -0
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +6 -0
- package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgentIntegration.d.ts +52 -0
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgentSeamlessIntegration.d.ts +14 -0
- package/esm/typings/src/book-components/icons/SendIcon.d.ts +3 -0
- package/esm/typings/src/commitments/CLOSED/CLOSED.d.ts +4 -0
- package/esm/typings/src/commitments/CLOSED/CLOSED.test.d.ts +4 -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/USE/USE.d.ts +53 -0
- package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +42 -0
- package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.test.d.ts +1 -0
- package/esm/typings/src/commitments/{IMPORTANT/IMPORTANT.d.ts → USE_MCP/USE_MCP.d.ts} +16 -5
- package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +38 -0
- package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +6 -0
- package/esm/typings/src/commitments/index.d.ts +93 -1
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +3 -1
- package/esm/typings/src/other/templates/getTemplatesPipelineCollection.d.ts +1 -1
- package/esm/typings/src/playground/playground.d.ts +3 -0
- package/esm/typings/src/types/typeAliases.d.ts +6 -0
- package/esm/typings/src/utils/color/Color.d.ts +9 -1
- package/esm/typings/src/utils/color/css-colors.d.ts +1 -0
- package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +6 -0
- package/esm/typings/src/utils/random/CzechNamePool.d.ts +7 -0
- package/esm/typings/src/utils/random/EnglishNamePool.d.ts +7 -0
- package/esm/typings/src/utils/random/NamePool.d.ts +17 -0
- package/esm/typings/src/utils/random/getNamePool.d.ts +10 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +902 -423
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +0 -29
- package/esm/typings/src/commitments/registry.d.ts +0 -68
- package/esm/typings/src/playground/playground1.d.ts +0 -2
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
4
|
-
import { Color } from '../../../../../../../src/utils/color/Color';
|
|
5
|
-
import { withAlpha } from '../../../../../../../src/utils/color/operators/withAlpha';
|
|
6
4
|
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
7
|
-
import { ArrowLeftIcon,
|
|
5
|
+
import { ArrowLeftIcon, CodeIcon, HomeIcon, LinkIcon, ShareIcon } from 'lucide-react';
|
|
8
6
|
import { headers } from 'next/headers';
|
|
9
7
|
import Link from 'next/link';
|
|
10
8
|
import { notFound } from 'next/navigation';
|
|
9
|
+
import { Color } from '../../../../../../../src/utils/color/Color';
|
|
10
|
+
import { withAlpha } from '../../../../../../../src/utils/color/operators/withAlpha';
|
|
11
11
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
12
|
+
import { getAgentExternalLinks, getAgentLinks } from '../agentLinks';
|
|
12
13
|
import { CopyField } from '../CopyField';
|
|
13
14
|
import { getAgentName, getAgentProfile } from '../_utils';
|
|
14
15
|
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
15
16
|
|
|
16
17
|
export const generateMetadata = generateAgentMetadata;
|
|
17
18
|
|
|
18
|
-
export default async function AgentLinksPage({
|
|
19
|
-
params,
|
|
20
|
-
}: {
|
|
21
|
-
params: Promise<{ agentName: string }>;
|
|
22
|
-
}) {
|
|
19
|
+
export default async function AgentLinksPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
23
20
|
$sideEffect(headers());
|
|
24
21
|
const agentName = await getAgentName(params);
|
|
25
22
|
|
|
@@ -39,7 +36,7 @@ export default async function AgentLinksPage({
|
|
|
39
36
|
|
|
40
37
|
const { publicUrl } = await $provideServer();
|
|
41
38
|
const baseUrl = `${publicUrl.href}agents/${encodeURIComponent(agentName)}`;
|
|
42
|
-
|
|
39
|
+
|
|
43
40
|
// Extract brand color from meta
|
|
44
41
|
const brandColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
45
42
|
const backgroundColor = (await brandColor.then(withAlpha(0.05))).toHex();
|
|
@@ -47,19 +44,15 @@ export default async function AgentLinksPage({
|
|
|
47
44
|
const primaryColor = (await brandColor).toHex();
|
|
48
45
|
|
|
49
46
|
return (
|
|
50
|
-
<div
|
|
47
|
+
<div
|
|
51
48
|
className="min-h-screen p-6 md:p-12 flex flex-col items-center"
|
|
52
49
|
style={{
|
|
53
50
|
backgroundColor,
|
|
54
51
|
}}
|
|
55
52
|
>
|
|
56
53
|
<div className="w-full max-w-3xl bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
|
57
|
-
|
|
58
54
|
{/* Header */}
|
|
59
|
-
<div
|
|
60
|
-
className="p-6 border-b flex items-center gap-4"
|
|
61
|
-
style={{ borderColor }}
|
|
62
|
-
>
|
|
55
|
+
<div className="p-6 border-b flex items-center gap-4" style={{ borderColor }}>
|
|
63
56
|
{agentProfile.meta.image && (
|
|
64
57
|
// eslint-disable-next-line @next/next/no-img-element
|
|
65
58
|
<img
|
|
@@ -70,15 +63,13 @@ export default async function AgentLinksPage({
|
|
|
70
63
|
/>
|
|
71
64
|
)}
|
|
72
65
|
<div className="flex-1">
|
|
73
|
-
<h1 className="text-2xl font-bold text-gray-900">
|
|
74
|
-
{agentProfile.meta.fullname || agentName}
|
|
75
|
-
</h1>
|
|
66
|
+
<h1 className="text-2xl font-bold text-gray-900">{agentProfile.meta.fullname || agentName}</h1>
|
|
76
67
|
<p className="text-gray-500 flex items-center gap-2">
|
|
77
68
|
<LinkIcon className="w-4 h-4" />
|
|
78
69
|
Signpost & Links
|
|
79
70
|
</p>
|
|
80
71
|
</div>
|
|
81
|
-
<Link
|
|
72
|
+
<Link
|
|
82
73
|
href={`/agents/${encodeURIComponent(agentName)}`}
|
|
83
74
|
className="p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-full transition-colors"
|
|
84
75
|
title="Back to Agent"
|
|
@@ -88,7 +79,6 @@ export default async function AgentLinksPage({
|
|
|
88
79
|
</div>
|
|
89
80
|
|
|
90
81
|
<div className="divide-y divide-gray-100">
|
|
91
|
-
|
|
92
82
|
{/* API Endpoints */}
|
|
93
83
|
<div className="p-6">
|
|
94
84
|
<h2 className="text-lg font-semibold text-gray-800 mb-4 flex items-center gap-2">
|
|
@@ -97,26 +87,36 @@ export default async function AgentLinksPage({
|
|
|
97
87
|
</h2>
|
|
98
88
|
<div className="grid gap-4">
|
|
99
89
|
<div>
|
|
100
|
-
<h3 className="text-sm font-medium text-gray-700 mb-1">
|
|
101
|
-
|
|
102
|
-
|
|
90
|
+
<h3 className="text-sm font-medium text-gray-700 mb-1">
|
|
91
|
+
OpenAI Compatible Chat Completion
|
|
92
|
+
</h3>
|
|
93
|
+
<p className="text-xs text-gray-500 mb-2">
|
|
94
|
+
Standard OpenAI API endpoint for chat completions.
|
|
95
|
+
</p>
|
|
96
|
+
<CopyField label="Endpoint URL" value={`${baseUrl}/api/openai/v1/chat/completions`} />
|
|
103
97
|
</div>
|
|
104
|
-
|
|
98
|
+
|
|
105
99
|
<div>
|
|
106
100
|
<h3 className="text-sm font-medium text-gray-700 mb-1">OpenRouter Compatible</h3>
|
|
107
|
-
<p className="text-xs text-gray-500 mb-2">
|
|
101
|
+
<p className="text-xs text-gray-500 mb-2">
|
|
102
|
+
Endpoint compatible with OpenRouter API format.
|
|
103
|
+
</p>
|
|
108
104
|
<CopyField label="Endpoint URL" value={`${baseUrl}/api/openrouter/chat/completions`} />
|
|
109
105
|
</div>
|
|
110
106
|
|
|
111
107
|
<div>
|
|
112
108
|
<h3 className="text-sm font-medium text-gray-700 mb-1">Model Context Protocol (MCP)</h3>
|
|
113
|
-
<p className="text-xs text-gray-500 mb-2">
|
|
109
|
+
<p className="text-xs text-gray-500 mb-2">
|
|
110
|
+
Endpoint for Model Context Protocol integration.
|
|
111
|
+
</p>
|
|
114
112
|
<CopyField label="Endpoint URL" value={`${baseUrl}/api/mcp`} />
|
|
115
113
|
</div>
|
|
116
114
|
|
|
117
115
|
<div>
|
|
118
116
|
<h3 className="text-sm font-medium text-gray-700 mb-1">Model Requirements</h3>
|
|
119
|
-
<p className="text-xs text-gray-500 mb-2">
|
|
117
|
+
<p className="text-xs text-gray-500 mb-2">
|
|
118
|
+
Get requirements and capabilities of the model.
|
|
119
|
+
</p>
|
|
120
120
|
<CopyField label="Endpoint URL" value={`${baseUrl}/api/modelRequirements`} />
|
|
121
121
|
</div>
|
|
122
122
|
</div>
|
|
@@ -129,50 +129,25 @@ export default async function AgentLinksPage({
|
|
|
129
129
|
Agent Resources
|
|
130
130
|
</h2>
|
|
131
131
|
<div className="grid md:grid-cols-2 gap-4">
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
<div className="flex items-center gap-3 mb-2">
|
|
152
|
-
<div className="p-2 rounded-lg bg-purple-50 text-purple-600 group-hover:bg-purple-100 transition-colors">
|
|
153
|
-
<HistoryIcon className="w-5 h-5" />
|
|
154
|
-
</div>
|
|
155
|
-
<span className="font-medium text-gray-900">History & Feedback</span>
|
|
156
|
-
</div>
|
|
157
|
-
<p className="text-sm text-gray-500">
|
|
158
|
-
View past conversations and provide feedback.
|
|
159
|
-
</p>
|
|
160
|
-
</Link>
|
|
161
|
-
|
|
162
|
-
<Link
|
|
163
|
-
href={`/agents/${encodeURIComponent(agentName)}/integration`}
|
|
164
|
-
className="block p-4 rounded-lg border border-gray-200 hover:border-gray-300 hover:shadow-md transition-all group bg-white"
|
|
165
|
-
>
|
|
166
|
-
<div className="flex items-center gap-3 mb-2">
|
|
167
|
-
<div className="p-2 rounded-lg bg-green-50 text-green-600 group-hover:bg-green-100 transition-colors">
|
|
168
|
-
<CodeIcon className="w-5 h-5" />
|
|
169
|
-
</div>
|
|
170
|
-
<span className="font-medium text-gray-900">Integration Guide</span>
|
|
171
|
-
</div>
|
|
172
|
-
<p className="text-sm text-gray-500">
|
|
173
|
-
Learn how to integrate this agent into your applications.
|
|
174
|
-
</p>
|
|
175
|
-
</Link>
|
|
132
|
+
{getAgentLinks(agentName)
|
|
133
|
+
.filter((link) =>
|
|
134
|
+
['Chat with Agent', 'History & Feedback', 'Integration'].includes(link.title),
|
|
135
|
+
)
|
|
136
|
+
.map((link) => (
|
|
137
|
+
<Link
|
|
138
|
+
key={link.href}
|
|
139
|
+
href={link.href}
|
|
140
|
+
className="block p-4 rounded-lg border border-gray-200 hover:border-gray-300 hover:shadow-md transition-all group bg-white"
|
|
141
|
+
>
|
|
142
|
+
<div className="flex items-center gap-3 mb-2">
|
|
143
|
+
<div className="p-2 rounded-lg bg-gray-50 text-gray-600 group-hover:bg-gray-100 transition-colors">
|
|
144
|
+
<link.icon className="w-5 h-5" />
|
|
145
|
+
</div>
|
|
146
|
+
<span className="font-medium text-gray-900">{link.title}</span>
|
|
147
|
+
</div>
|
|
148
|
+
<p className="text-sm text-gray-500">{link.description}</p>
|
|
149
|
+
</Link>
|
|
150
|
+
))}
|
|
176
151
|
</div>
|
|
177
152
|
</div>
|
|
178
153
|
|
|
@@ -183,34 +158,23 @@ export default async function AgentLinksPage({
|
|
|
183
158
|
Promptbook Ecosystem
|
|
184
159
|
</h2>
|
|
185
160
|
<div className="grid md:grid-cols-2 gap-4">
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<
|
|
195
|
-
<div
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
target="_blank"
|
|
202
|
-
rel="noopener noreferrer"
|
|
203
|
-
className="flex items-center gap-3 p-3 rounded-lg bg-white border border-gray-200 hover:border-gray-300 transition-colors"
|
|
204
|
-
>
|
|
205
|
-
<CodeIcon className="w-5 h-5 text-gray-400" />
|
|
206
|
-
<div>
|
|
207
|
-
<div className="font-medium text-gray-900">GitHub Repository</div>
|
|
208
|
-
<div className="text-xs text-gray-500">Star us and contribute to the project</div>
|
|
209
|
-
</div>
|
|
210
|
-
</a>
|
|
161
|
+
{getAgentExternalLinks().map((link) => (
|
|
162
|
+
<a
|
|
163
|
+
key={link.href}
|
|
164
|
+
href={link.href}
|
|
165
|
+
target={link.target}
|
|
166
|
+
rel={link.rel}
|
|
167
|
+
className="flex items-center gap-3 p-3 rounded-lg bg-white border border-gray-200 hover:border-gray-300 transition-colors"
|
|
168
|
+
>
|
|
169
|
+
<link.icon className="w-5 h-5 text-gray-400" />
|
|
170
|
+
<div>
|
|
171
|
+
<div className="font-medium text-gray-900">{link.title}</div>
|
|
172
|
+
<div className="text-xs text-gray-500">{link.description}</div>
|
|
173
|
+
</div>
|
|
174
|
+
</a>
|
|
175
|
+
))}
|
|
211
176
|
</div>
|
|
212
177
|
</div>
|
|
213
|
-
|
|
214
178
|
</div>
|
|
215
179
|
</div>
|
|
216
180
|
</div>
|
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
// import { BookEditor } from '@promptbook-local/components';
|
|
4
3
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
4
|
+
import { isUserAdmin } from '@/src/utils/isUserAdmin';
|
|
5
|
+
import { saturate } from '@promptbook-local/color';
|
|
5
6
|
import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
|
|
6
|
-
import { CodeIcon, HistoryIcon, MessageCircleQuestionIcon, MessageSquareIcon, NotebookPenIcon } from 'lucide-react';
|
|
7
|
-
import { headers } from 'next/headers';
|
|
8
7
|
import { notFound } from 'next/navigation';
|
|
9
8
|
import { Color } from '../../../../../../src/utils/color/Color';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { AgentQrCode } from './AgentQrCode';
|
|
15
|
-
import { CopyField } from './CopyField';
|
|
9
|
+
import { getAgentName, getAgentProfile } from './_utils';
|
|
10
|
+
import { getAgentLinks } from './agentLinks';
|
|
11
|
+
import { AgentProfileChat } from './AgentProfileChat';
|
|
12
|
+
import { AgentProfileWrapper } from './AgentProfileWrapper';
|
|
16
13
|
import { generateAgentMetadata } from './generateAgentMetadata';
|
|
17
|
-
import { InstallPwaButton } from './InstallPwaButton';
|
|
18
14
|
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';
|
|
23
|
-
// import { Agent } from '@promptbook-local/core';
|
|
24
|
-
// import { RemoteLlmExecutionTools } from '@promptbook-local/remote-client';
|
|
25
|
-
// import { OpenAiAssistantExecutionTools } from '@promptbook-local/openai';
|
|
26
15
|
|
|
27
16
|
export const generateMetadata = generateAgentMetadata;
|
|
28
17
|
|
|
@@ -31,17 +20,12 @@ export default async function AgentPage({
|
|
|
31
20
|
searchParams,
|
|
32
21
|
}: {
|
|
33
22
|
params: Promise<{ agentName: string }>;
|
|
34
|
-
searchParams: Promise<{
|
|
23
|
+
searchParams: Promise<{ headless?: string }>;
|
|
35
24
|
}) {
|
|
36
|
-
// const [apiKey, setApiKey] = useStateInLocalStorage<string>('openai-apiKey', () => '');
|
|
37
|
-
// const [isApiKeyVisible, setIsApiKeyVisible] = useState(false);
|
|
38
|
-
// const [isApiKeySectionCollapsed, setIsApiKeySectionCollapsed] = useState(!!apiKey);
|
|
39
|
-
|
|
40
|
-
$sideEffect(headers());
|
|
41
|
-
|
|
42
|
-
const { message } = await searchParams;
|
|
43
25
|
const agentName = await getAgentName(params);
|
|
44
26
|
const isAdmin = await isUserAdmin();
|
|
27
|
+
const { headless: headlessParam } = await searchParams;
|
|
28
|
+
const isHeadless = headlessParam !== undefined;
|
|
45
29
|
|
|
46
30
|
let agentProfile;
|
|
47
31
|
try {
|
|
@@ -66,145 +50,51 @@ export default async function AgentPage({
|
|
|
66
50
|
|
|
67
51
|
const agentEmail = `${agentName}@${publicUrl.hostname}`;
|
|
68
52
|
|
|
69
|
-
|
|
53
|
+
const brandColor = Color.fromSafe(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
54
|
+
const brandColorHex = brandColor.then(saturate(-0.5)).toHex();
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
const brandColor = Color.from(agentProfile.meta.color || PROMPTBOOK_COLOR);
|
|
73
|
-
|
|
74
|
-
// Mock agent actions
|
|
75
|
-
const agentActions = AGENT_ACTIONS;
|
|
56
|
+
const fullname = (agentProfile.meta.fullname || agentProfile.agentName || 'Agent') as string;
|
|
76
57
|
|
|
77
58
|
return (
|
|
78
|
-
|
|
59
|
+
<>
|
|
79
60
|
<ServiceWorkerRegister scope={`/agents/${encodeURIComponent(agentName)}/`} />
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
src={agentProfile.meta.image as string}
|
|
94
|
-
alt={agentProfile.meta.fullname || agentProfile.agentName || 'Agent'}
|
|
95
|
-
width={64}
|
|
96
|
-
height={64}
|
|
97
|
-
className="rounded-full object-cover border-2 aspect-square w-16 h-16"
|
|
98
|
-
style={{ borderColor: brandColor.toHex() }}
|
|
99
|
-
/>
|
|
100
|
-
)}
|
|
101
|
-
<div className="flex-1">
|
|
102
|
-
<h1 className="text-3xl font-bold text-gray-900 break-words">
|
|
103
|
-
{agentProfile.meta.fullname || agentProfile.agentName}
|
|
104
|
-
</h1>
|
|
105
|
-
<span
|
|
106
|
-
className="inline-block mt-1 px-2 py-1 rounded text-xs font-semibold text-white"
|
|
107
|
-
style={{ backgroundColor: brandColor.toHex() }}
|
|
108
|
-
>
|
|
109
|
-
Agent
|
|
110
|
-
</span>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<p className="text-gray-700">{agentProfile.personaDescription}</p>
|
|
115
|
-
|
|
116
|
-
<div className="flex flex-col gap-2">
|
|
117
|
-
<h2 className="text-sm font-semibold text-gray-700 uppercase tracking-wide">Capabilities</h2>
|
|
118
|
-
<div className="flex flex-wrap gap-2">
|
|
119
|
-
{agentActions.map((action) => (
|
|
120
|
-
<span
|
|
121
|
-
key={action}
|
|
122
|
-
className="px-3 py-1 bg-white text-gray-700 rounded-full text-xs font-medium border border-gray-200 shadow-sm"
|
|
123
|
-
>
|
|
124
|
-
{action}
|
|
125
|
-
</span>
|
|
126
|
-
))}
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
|
|
130
|
-
<div className="flex flex-col gap-3 mt-auto">
|
|
131
|
-
<div className="flex gap-2">
|
|
132
|
-
<a
|
|
133
|
-
href={`/agents/${encodeURIComponent(agentName)}/book+chat`}
|
|
134
|
-
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
135
|
-
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"
|
|
136
|
-
>
|
|
137
|
-
<NotebookPenIcon className="ml-2 w-4 h-4 mr-2" />
|
|
138
|
-
Edit
|
|
139
|
-
</a>
|
|
140
|
-
<a
|
|
141
|
-
href={`/agents/${encodeURIComponent(agentName)}/integration`}
|
|
142
|
-
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
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"
|
|
144
|
-
>
|
|
145
|
-
<CodeIcon className="ml-2 w-4 h-4 mr-2" />
|
|
146
|
-
Integration
|
|
147
|
-
</a>
|
|
148
|
-
<a
|
|
149
|
-
href={`/agents/${encodeURIComponent(agentName)}/history`}
|
|
150
|
-
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"
|
|
151
|
-
>
|
|
152
|
-
<HistoryIcon className="ml-2 w-4 h-4 mr-2" />
|
|
153
|
-
History
|
|
154
|
-
</a>
|
|
155
|
-
{isAdmin && <CloneAgentButton agentName={agentName} />}
|
|
156
|
-
<InstallPwaButton />
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
|
-
{isAdmin && (
|
|
160
|
-
<div className="border-t border-dashed border-gray-300 pt-3">
|
|
161
|
-
<h2 className="mb-2 text-xs font-semibold uppercase tracking-wide text-gray-600">
|
|
162
|
-
Maintenance
|
|
163
|
-
</h2>
|
|
164
|
-
<div className="flex flex-col gap-2">
|
|
165
|
-
<a
|
|
166
|
-
href={`/admin/chat-history?agentName=${encodeURIComponent(agentName)}`}
|
|
167
|
-
className="inline-flex items-center justify-center whitespace-nowrap rounded-md border border-gray-300 bg-white px-3 py-1.5 text-xs font-semibold text-gray-700 shadow-sm hover:bg-gray-50"
|
|
168
|
-
>
|
|
169
|
-
<MessageSquareIcon className="mr-2 w-3 h-3" />
|
|
170
|
-
Chat history
|
|
171
|
-
</a>
|
|
61
|
+
<AgentProfileWrapper
|
|
62
|
+
agent={agentProfile}
|
|
63
|
+
agentUrl={agentUrl}
|
|
64
|
+
agentEmail={agentEmail}
|
|
65
|
+
agentName={agentName}
|
|
66
|
+
brandColorHex={brandColorHex}
|
|
67
|
+
isAdmin={isAdmin}
|
|
68
|
+
isHeadless={isHeadless}
|
|
69
|
+
actions={
|
|
70
|
+
<>
|
|
71
|
+
{getAgentLinks(agentName)
|
|
72
|
+
.filter((link) => ['Edit Book', 'Integration', 'All Links'].includes(link.title))
|
|
73
|
+
.map((link) => (
|
|
172
74
|
<a
|
|
173
|
-
|
|
174
|
-
|
|
75
|
+
key={link.href}
|
|
76
|
+
href={link.href}
|
|
77
|
+
className="flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors group"
|
|
78
|
+
title={link.title}
|
|
175
79
|
>
|
|
176
|
-
<
|
|
177
|
-
|
|
80
|
+
<div className="p-2 rounded-full bg-white/40 group-hover:bg-white/60 transition-colors shadow-sm">
|
|
81
|
+
<link.icon className="w-5 h-5" />
|
|
82
|
+
</div>
|
|
83
|
+
<span className="font-medium text-sm">{link.title}</span>
|
|
178
84
|
</a>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
agentUrl={agentUrl}
|
|
193
|
-
agentEmail={agentEmail}
|
|
194
|
-
/>
|
|
195
|
-
</div>
|
|
196
|
-
<div className="flex flex-col gap-2 w-full">
|
|
197
|
-
<CopyField label="Agent Page URL" value={agentUrl} />
|
|
198
|
-
<CopyField label="Agent Email" value={agentEmail} />
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
{/* Main content: Chat */}
|
|
204
|
-
<div className="flex-1 relative h-full bg-white">
|
|
205
|
-
<AgentChatWrapper agentUrl={agentUrl} defaultMessage={message as string} />
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
85
|
+
))}
|
|
86
|
+
</>
|
|
87
|
+
}
|
|
88
|
+
>
|
|
89
|
+
<AgentProfileChat
|
|
90
|
+
agentUrl={agentUrl}
|
|
91
|
+
agentName={agentName}
|
|
92
|
+
fullname={fullname}
|
|
93
|
+
brandColorHex={brandColorHex}
|
|
94
|
+
avatarSrc={agentProfile.meta.image!}
|
|
95
|
+
/>
|
|
96
|
+
</AgentProfileWrapper>
|
|
97
|
+
</>
|
|
208
98
|
);
|
|
209
99
|
}
|
|
210
100
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
5
|
+
import { PromptbookAgentIntegration } 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 WebsiteIntegrationAgentPage({ 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
|
+
<PromptbookAgentIntegration
|
|
54
|
+
formfactor="profile"
|
|
55
|
+
agentUrl={agentUrl}
|
|
56
|
+
meta={meta}
|
|
57
|
+
style={{
|
|
58
|
+
width: '400px',
|
|
59
|
+
height: '600px',
|
|
60
|
+
// outline: `2px solid red`
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
</main>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* TODO: Make this page better, bring from Promptbook.Studio
|
|
69
|
+
* TODO: [🚗] Components and pages here should be just tiny UI wraper around proper agent logic and conponents
|
|
70
|
+
*/
|
|
@@ -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
|
+
}
|