@promptbook/cli 0.103.0-56 → 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 +1220 -47
- package/apps/agents-server/package.json +4 -1
- package/apps/agents-server/src/app/actions.ts +3 -1
- package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +72 -6
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +20 -7
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +44 -0
- package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +7 -3
- package/apps/agents-server/src/app/agents/[agentName]/layout.tsx +41 -0
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +47 -100
- package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +11 -2
- package/apps/agents-server/src/app/embed/page.tsx +2 -2
- package/apps/agents-server/src/app/layout.tsx +8 -24
- package/apps/agents-server/src/app/manifest.ts +8 -3
- 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/LayoutWrapper/LayoutWrapper.tsx +7 -6
- package/apps/agents-server/src/database/metadataDefaults.ts +6 -0
- package/esm/index.es.js +65 -10
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +2 -2
- package/esm/typings/src/_packages/types.index.d.ts +6 -0
- 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/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/USE_BROWSER/USE_BROWSER.d.ts +4 -0
- package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +6 -0
- 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/types/typeAliases.d.ts +6 -0
- package/esm/typings/src/utils/color/Color.d.ts +1 -1
- 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 +65 -10
- package/umd/index.umd.js.map +1 -1
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileView.tsx +0 -233
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +0 -29
- /package/apps/agents-server/src/{app/agents/[agentName] → components/AgentProfile}/QrCodeModal.tsx +0 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { AgentBasicInformation } from '@promptbook-local/types';
|
|
4
|
+
import { RepeatIcon } from 'lucide-react';
|
|
5
|
+
import { useMemo, useState } from 'react';
|
|
6
|
+
import spaceTrim from 'spacetrim';
|
|
7
|
+
import { Color } from '../../../../../src/utils/color/Color';
|
|
8
|
+
import { darken } from '../../../../../src/utils/color/operators/darken';
|
|
9
|
+
import { lighten } from '../../../../../src/utils/color/operators/lighten';
|
|
10
|
+
import { AgentQrCode } from './AgentQrCode';
|
|
11
|
+
import { QrCodeModal } from './QrCodeModal';
|
|
12
|
+
|
|
13
|
+
type AgentProfileProps = {
|
|
14
|
+
/**
|
|
15
|
+
* The agent to display
|
|
16
|
+
*/
|
|
17
|
+
readonly agent: AgentBasicInformation;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* URL of the agent page
|
|
21
|
+
*
|
|
22
|
+
* @default undefined - If not provided, some features like QR code for link might be disabled or use generic link
|
|
23
|
+
*/
|
|
24
|
+
readonly agentUrl?: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Email of the agent
|
|
28
|
+
*/
|
|
29
|
+
readonly agentEmail?: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Content for the menu (top right)
|
|
33
|
+
*
|
|
34
|
+
* @param props.onShowQrCode - Function to open QR code modal
|
|
35
|
+
*/
|
|
36
|
+
readonly renderMenu?: (props: { onShowQrCode: () => void }) => React.ReactNode;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Content for the chat area
|
|
40
|
+
*/
|
|
41
|
+
readonly children?: React.ReactNode;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Content for the secondary actions (links)
|
|
45
|
+
*/
|
|
46
|
+
readonly actions?: React.ReactNode;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* If true, hides the menu and actions for fullscreen/embedded view
|
|
50
|
+
*/
|
|
51
|
+
readonly isHeadless?: boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* CSS class name
|
|
55
|
+
*/
|
|
56
|
+
readonly className?: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function AgentProfile(props: AgentProfileProps) {
|
|
60
|
+
const {
|
|
61
|
+
agent,
|
|
62
|
+
agentUrl = '',
|
|
63
|
+
agentEmail = '',
|
|
64
|
+
renderMenu,
|
|
65
|
+
children,
|
|
66
|
+
actions,
|
|
67
|
+
isHeadless = false,
|
|
68
|
+
className,
|
|
69
|
+
} = props;
|
|
70
|
+
const { meta, agentName } = agent;
|
|
71
|
+
const fullname = (meta.fullname as string) || agentName || 'Agent';
|
|
72
|
+
const personaDescription = agent.personaDescription || '';
|
|
73
|
+
const imageUrl = (meta.image as string) || null;
|
|
74
|
+
|
|
75
|
+
const [isQrModalOpen, setIsQrModalOpen] = useState(false);
|
|
76
|
+
const [isFlipped, setIsFlipped] = useState(false);
|
|
77
|
+
|
|
78
|
+
// Dynamic Font Loading
|
|
79
|
+
const fontString = meta.font;
|
|
80
|
+
let fontStyle: React.CSSProperties = {};
|
|
81
|
+
|
|
82
|
+
if (fontString) {
|
|
83
|
+
// [🧠] TODO: Properly parse font string to get family name
|
|
84
|
+
const primaryFont = fontString.split(',')[0].trim().replace(/['"]/g, '');
|
|
85
|
+
fontStyle = {
|
|
86
|
+
fontFamily: fontString,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Compute Colors and Background
|
|
91
|
+
const { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage } = useMemo(() => {
|
|
92
|
+
// [🧠] Default color should be imported constant, but for now hardcoded fallback
|
|
93
|
+
const PROMPTBOOK_COLOR_HEX = '#f15b24'; // TODO: Import PROMPTBOOK_COLOR
|
|
94
|
+
const brandColorString = meta.color || PROMPTBOOK_COLOR_HEX;
|
|
95
|
+
|
|
96
|
+
let brandColor;
|
|
97
|
+
try {
|
|
98
|
+
brandColor = Color.fromSafe(brandColorString.split(',')[0].trim());
|
|
99
|
+
} catch {
|
|
100
|
+
brandColor = Color.fromHex(PROMPTBOOK_COLOR_HEX);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const brandColorHex = brandColor.toHex();
|
|
104
|
+
const brandColorLightHex = brandColor.then(lighten(0.2)).toHex();
|
|
105
|
+
const brandColorDarkHex = brandColor.then(darken(0.15)).toHex();
|
|
106
|
+
|
|
107
|
+
// Generate Noisy SVG Background
|
|
108
|
+
const color1 = brandColor;
|
|
109
|
+
// const color2 = brandColors[1] || brandColors[0]!; // Use secondary color if available?
|
|
110
|
+
// For simplicity using primary color for now or derive second one
|
|
111
|
+
const color2 = brandColor;
|
|
112
|
+
|
|
113
|
+
// [🧠] Make colors much lighter for the background
|
|
114
|
+
const color1Light = color1.then(lighten(0.3)).toHex();
|
|
115
|
+
const color1Main = color1.toHex();
|
|
116
|
+
const color1Dark = color1.then(darken(0.3)).toHex();
|
|
117
|
+
|
|
118
|
+
const color2Light = color2.then(lighten(0.3)).toHex();
|
|
119
|
+
const color2Main = color2.toHex();
|
|
120
|
+
const color2Dark = color2.then(darken(0.3)).toHex();
|
|
121
|
+
|
|
122
|
+
const svgContent = spaceTrim(`
|
|
123
|
+
<svg xmlns="http://www.w3.org/2000/svg"
|
|
124
|
+
viewBox="0 0 1920 1080"
|
|
125
|
+
width="1920" height="1080"
|
|
126
|
+
preserveAspectRatio="xMidYMid slice">
|
|
127
|
+
<defs>
|
|
128
|
+
<!-- Bottom-left -->
|
|
129
|
+
<radialGradient id="grad1" cx="0%" cy="100%" r="90%">
|
|
130
|
+
<stop offset="0%" stop-color="${color1Light}" />
|
|
131
|
+
<stop offset="50%" stop-color="${color1Main}" />
|
|
132
|
+
<stop offset="100%" stop-color="${color1Dark}" />
|
|
133
|
+
</radialGradient>
|
|
134
|
+
|
|
135
|
+
<!-- Bottom-right -->
|
|
136
|
+
<radialGradient id="grad2" cx="100%" cy="100%" r="90%">
|
|
137
|
+
<stop offset="0%" stop-color="${color2Light}" />
|
|
138
|
+
<stop offset="50%" stop-color="${color2Main}" />
|
|
139
|
+
<stop offset="100%" stop-color="${color2Dark}" />
|
|
140
|
+
</radialGradient>
|
|
141
|
+
|
|
142
|
+
<!-- White top fade -->
|
|
143
|
+
<linearGradient id="whiteTopGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
144
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="1" />
|
|
145
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0.3" />
|
|
146
|
+
</linearGradient>
|
|
147
|
+
|
|
148
|
+
<!-- Strong grain -->
|
|
149
|
+
<filter id="grain" x="-10%" y="-10%" width="120%" height="120%">
|
|
150
|
+
<feTurbulence type="fractalNoise" baseFrequency="3.5" numOctaves="3" seed="8" result="noise" />
|
|
151
|
+
<feComponentTransfer>
|
|
152
|
+
<feFuncR type="linear" slope="3.5" intercept="-1.2" />
|
|
153
|
+
<feFuncG type="linear" slope="3.5" intercept="-1.2" />
|
|
154
|
+
<feFuncB type="linear" slope="3.5" intercept="-1.2" />
|
|
155
|
+
<feFuncA type="table" tableValues="0 0.8" />
|
|
156
|
+
</feComponentTransfer>
|
|
157
|
+
</filter>
|
|
158
|
+
</defs>
|
|
159
|
+
|
|
160
|
+
<!-- White base -->
|
|
161
|
+
<rect width="100%" height="100%" fill="#ffffff" />
|
|
162
|
+
|
|
163
|
+
<!-- Gradients -->
|
|
164
|
+
<rect width="100%" height="100%" fill="url(#grad1)" />
|
|
165
|
+
<rect width="100%" height="100%" fill="url(#grad2)" style="mix-blend-mode:screen; opacity:0.85" />
|
|
166
|
+
|
|
167
|
+
<!-- White fade on top -->
|
|
168
|
+
<rect width="100%" height="100%" fill="url(#whiteTopGrad)" />
|
|
169
|
+
|
|
170
|
+
<!-- Strong visible noise -->
|
|
171
|
+
<rect width="100%" height="100%" filter="url(#grain)"
|
|
172
|
+
style="mix-blend-mode:soft-light; opacity:1.2" />
|
|
173
|
+
</svg>
|
|
174
|
+
`);
|
|
175
|
+
|
|
176
|
+
const backgroundImage = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
|
|
177
|
+
|
|
178
|
+
return { brandColorHex, brandColorLightHex, brandColorDarkHex, backgroundImage };
|
|
179
|
+
}, [meta.color]);
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<>
|
|
183
|
+
{fontString && (
|
|
184
|
+
<style jsx global>{`
|
|
185
|
+
@import url('https://fonts.googleapis.com/css2?family=${encodeURIComponent(
|
|
186
|
+
fontString.split(',')[0].trim().replace(/['"]/g, ''),
|
|
187
|
+
)}:wght@400;600;700&display=swap');
|
|
188
|
+
`}</style>
|
|
189
|
+
)}
|
|
190
|
+
|
|
191
|
+
{/* Full-screen background with agent color */}
|
|
192
|
+
<div
|
|
193
|
+
className={`w-full flex flex-col items-center justify-center p-6 md:p-12 relative overflow-hidden ${
|
|
194
|
+
isHeadless ? 'min-h-screen' : 'min-h-[calc(100vh-60px)]'
|
|
195
|
+
} ${className || ''}`}
|
|
196
|
+
style={{
|
|
197
|
+
background: `url("${backgroundImage}")`,
|
|
198
|
+
backgroundSize: 'cover',
|
|
199
|
+
backgroundPosition: 'center',
|
|
200
|
+
...fontStyle,
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
{/* Options menu in top right */}
|
|
204
|
+
{!isHeadless && renderMenu && (
|
|
205
|
+
<div className="absolute top-4 right-4 z-[9999]">
|
|
206
|
+
{renderMenu({ onShowQrCode: () => setIsQrModalOpen(true) })}
|
|
207
|
+
</div>
|
|
208
|
+
)}
|
|
209
|
+
|
|
210
|
+
{/* Main profile content */}
|
|
211
|
+
<div className="relative z-10 flex flex-col md:flex-row items-center md:items-start gap-8 md:gap-12 max-w-5xl w-full">
|
|
212
|
+
{/* Agent image card (Flippable) */}
|
|
213
|
+
<div className="flex-shrink-0 perspective-1000 group" style={{ perspective: '1000px' }}>
|
|
214
|
+
<div
|
|
215
|
+
className="relative w-72 md:w-80 transition-all duration-700 transform-style-3d cursor-pointer"
|
|
216
|
+
style={{
|
|
217
|
+
aspectRatio: '1 / 1.618', // Golden Ratio
|
|
218
|
+
transformStyle: 'preserve-3d',
|
|
219
|
+
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
|
220
|
+
}}
|
|
221
|
+
onClick={() => setIsFlipped(!isFlipped)}
|
|
222
|
+
>
|
|
223
|
+
{/* Front of Card (Image) */}
|
|
224
|
+
<div
|
|
225
|
+
className="absolute inset-0 w-full h-full backface-hidden rounded-3xl shadow-2xl overflow-hidden backdrop-blur-sm"
|
|
226
|
+
style={{
|
|
227
|
+
backfaceVisibility: 'hidden',
|
|
228
|
+
backgroundColor: brandColorDarkHex,
|
|
229
|
+
boxShadow: `0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px ${brandColorLightHex}40`,
|
|
230
|
+
}}
|
|
231
|
+
>
|
|
232
|
+
{imageUrl ? (
|
|
233
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
234
|
+
<img src={imageUrl} alt={fullname} className="w-full h-full object-cover" />
|
|
235
|
+
) : (
|
|
236
|
+
<div
|
|
237
|
+
className="w-full h-full flex items-center justify-center text-8xl font-bold text-white/80"
|
|
238
|
+
style={{ backgroundColor: brandColorDarkHex }}
|
|
239
|
+
>
|
|
240
|
+
{fullname.charAt(0).toUpperCase()}
|
|
241
|
+
</div>
|
|
242
|
+
)}
|
|
243
|
+
|
|
244
|
+
{/* Flip hint icon */}
|
|
245
|
+
<div className="absolute bottom-4 right-4 bg-black/30 p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
|
|
246
|
+
<RepeatIcon className="w-5 h-5" />
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
|
|
250
|
+
{/* Back of Card (QR Code) */}
|
|
251
|
+
<div
|
|
252
|
+
className="absolute inset-0 w-full h-full backface-hidden rounded-3xl shadow-2xl overflow-hidden backdrop-blur-sm flex flex-col items-center justify-center p-6"
|
|
253
|
+
style={{
|
|
254
|
+
backfaceVisibility: 'hidden',
|
|
255
|
+
transform: 'rotateY(180deg)',
|
|
256
|
+
background: `linear-gradient(135deg, ${brandColorLightHex} 0%, #ffffff 100%)`,
|
|
257
|
+
boxShadow: `0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px ${brandColorLightHex}40`,
|
|
258
|
+
}}
|
|
259
|
+
>
|
|
260
|
+
<div className="transform scale-90 md:scale-100">
|
|
261
|
+
<AgentQrCode
|
|
262
|
+
agentName={agentName}
|
|
263
|
+
agentUrl={agentUrl}
|
|
264
|
+
agentEmail={agentEmail}
|
|
265
|
+
personaDescription={personaDescription}
|
|
266
|
+
meta={meta}
|
|
267
|
+
isJustVcardShown
|
|
268
|
+
/>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
{/* Flip hint icon */}
|
|
272
|
+
<div className="absolute bottom-4 right-4 bg-black/10 p-2 rounded-full text-black/50 backdrop-blur-md">
|
|
273
|
+
<RepeatIcon className="w-5 h-5" />
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
{/* Agent info */}
|
|
280
|
+
<div className="flex flex-col items-center md:items-start text-center md:text-left gap-6">
|
|
281
|
+
{/* Agent name with custom font */}
|
|
282
|
+
<h1
|
|
283
|
+
className="text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 tracking-tight"
|
|
284
|
+
style={{
|
|
285
|
+
textShadow: '0 2px 20px rgba(255, 255, 255, 0.5)',
|
|
286
|
+
}}
|
|
287
|
+
>
|
|
288
|
+
{fullname}
|
|
289
|
+
</h1>
|
|
290
|
+
|
|
291
|
+
{/* Short description */}
|
|
292
|
+
<p className="text-lg md:text-xl text-gray-700 max-w-lg leading-relaxed font-medium">
|
|
293
|
+
{personaDescription}
|
|
294
|
+
</p>
|
|
295
|
+
|
|
296
|
+
{/* Chat */}
|
|
297
|
+
<div className="w-full">{children}</div>
|
|
298
|
+
|
|
299
|
+
{/* Secondary Actions */}
|
|
300
|
+
{!isHeadless && (
|
|
301
|
+
<div className="flex flex-wrap justify-center md:justify-start items-center gap-4 md:gap-6 mt-2">
|
|
302
|
+
{actions}
|
|
303
|
+
</div>
|
|
304
|
+
)}
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
{/* Subtle gradient overlay at bottom */}
|
|
309
|
+
<div
|
|
310
|
+
className="absolute bottom-0 left-0 right-0 h-32 pointer-events-none"
|
|
311
|
+
style={{
|
|
312
|
+
background: `linear-gradient(to top, ${brandColorDarkHex}40, transparent)`,
|
|
313
|
+
}}
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
|
|
317
|
+
{/* QR Code Modal */}
|
|
318
|
+
<QrCodeModal
|
|
319
|
+
isOpen={isQrModalOpen}
|
|
320
|
+
onClose={() => setIsQrModalOpen(false)}
|
|
321
|
+
agentName={agentName}
|
|
322
|
+
meta={meta}
|
|
323
|
+
personaDescription={personaDescription}
|
|
324
|
+
agentUrl={agentUrl}
|
|
325
|
+
agentEmail={agentEmail}
|
|
326
|
+
brandColorHex={brandColorHex}
|
|
327
|
+
/>
|
|
328
|
+
</>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* TODO: !!!! Use 3D badge @see https://vercel.com/blog/building-an-interactive-3d-event-badge-with-react-three-fiber
|
|
334
|
+
*/
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { string_book } from '@promptbook-local/types';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
import { parseAgentSource } from '../../../../../src/book-2.0/agent-source/parseAgentSource';
|
|
6
|
+
import { AgentProfile } from './AgentProfile';
|
|
7
|
+
|
|
8
|
+
type AgentProfileFromSourceProps = Omit<React.ComponentProps<typeof AgentProfile>, 'agent'> & {
|
|
9
|
+
/**
|
|
10
|
+
* Source code of the agent (book)
|
|
11
|
+
*/
|
|
12
|
+
readonly source: string_book;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function AgentProfileFromSource(props: AgentProfileFromSourceProps) {
|
|
16
|
+
const { source, ...rest } = props;
|
|
17
|
+
|
|
18
|
+
const agent = useMemo(() => {
|
|
19
|
+
return parseAgentSource(source);
|
|
20
|
+
}, [source]);
|
|
21
|
+
|
|
22
|
+
return <AgentProfile agent={agent} {...rest} />;
|
|
23
|
+
}
|
package/apps/agents-server/src/{app/agents/[agentName] → components/AgentProfile}/AgentQrCode.tsx
RENAMED
|
@@ -8,9 +8,12 @@ import spaceTrim from 'spacetrim';
|
|
|
8
8
|
type AgentQrCodeProps = Pick<AgentBasicInformation, 'agentName' | 'personaDescription' | 'meta'> & {
|
|
9
9
|
agentUrl: string;
|
|
10
10
|
agentEmail: string;
|
|
11
|
+
|
|
12
|
+
isJustVcardShown?: boolean;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
export function AgentQrCode(
|
|
15
|
+
export function AgentQrCode(props: AgentQrCodeProps) {
|
|
16
|
+
const { agentName, agentUrl, agentEmail, personaDescription, meta, isJustVcardShown } = props;
|
|
14
17
|
const [mode, setMode] = useState<'contact' | 'link'>('contact');
|
|
15
18
|
|
|
16
19
|
// TODO: [🧠] Should we include more info in VCARD?
|
|
@@ -27,6 +30,10 @@ export function AgentQrCode({ agentName, agentUrl, agentEmail, personaDescriptio
|
|
|
27
30
|
const qrValue = mode === 'contact' ? vcard : agentUrl;
|
|
28
31
|
const label = mode === 'contact' ? 'Scan to add contact' : 'Scan to open agent';
|
|
29
32
|
|
|
33
|
+
if (isJustVcardShown) {
|
|
34
|
+
return <PromptbookQrCode value={vcard} className="" size={250} />;
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
return (
|
|
31
38
|
<div className="flex flex-col items-center">
|
|
32
39
|
<div className="flex bg-gray-100 p-1 rounded-lg mb-4">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { usePathname } from 'next/navigation';
|
|
3
|
+
import { usePathname, useSearchParams } from 'next/navigation';
|
|
4
4
|
import { AgentBasicInformation } from '../../../../../src/book-2.0/agent-source/AgentBasicInformation';
|
|
5
5
|
import type { UserInfo } from '../../utils/getCurrentUser';
|
|
6
6
|
import { Footer, type FooterLink } from '../Footer/Footer';
|
|
@@ -28,12 +28,13 @@ export function LayoutWrapper({
|
|
|
28
28
|
footerLinks,
|
|
29
29
|
}: LayoutWrapperProps) {
|
|
30
30
|
const pathname = usePathname();
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
31
|
+
const searchParams = useSearchParams();
|
|
32
|
+
const isHeadless = searchParams.has('headless');
|
|
33
|
+
// const isAdminChatPage = pathname?.startsWith('/admin/chat-history') || pathname?.startsWith('/admin/chat-feedback');
|
|
34
|
+
const isHeaderHidden = false; // pathname?.includes('/chat') && !isAdminChatPage;
|
|
35
|
+
const isFooterHiddenOnPage = pathname ? /^\/agents\/[^/]+\/(book|chat|book\+chat)$/.test(pathname) : false;
|
|
35
36
|
|
|
36
|
-
if (isHeaderHidden) {
|
|
37
|
+
if (isHeaderHidden || isHeadless) {
|
|
37
38
|
return <main className={`pt-0`}>{children}</main>;
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -61,6 +61,12 @@ export const metadataDefaults = [
|
|
|
61
61
|
note: 'Maximum size of file that can be uploaded in MB.',
|
|
62
62
|
type: 'NUMBER',
|
|
63
63
|
},
|
|
64
|
+
{
|
|
65
|
+
key: 'NAME_POOL',
|
|
66
|
+
value: 'ENGLISH',
|
|
67
|
+
note: 'Language for generating new agent names. Possible values: ENGLISH, CZECH.',
|
|
68
|
+
type: 'TEXT_SINGLE_LINE',
|
|
69
|
+
},
|
|
64
70
|
] as const satisfies ReadonlyArray<{
|
|
65
71
|
key: string;
|
|
66
72
|
value: string;
|
package/esm/index.es.js
CHANGED
|
@@ -47,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
47
47
|
* @generated
|
|
48
48
|
* @see https://github.com/webgptorg/promptbook
|
|
49
49
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-66';
|
|
51
51
|
/**
|
|
52
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -374,15 +374,33 @@ class Color {
|
|
|
374
374
|
* @param color
|
|
375
375
|
* @returns Color object
|
|
376
376
|
*/
|
|
377
|
-
static from(color) {
|
|
378
|
-
if (color
|
|
377
|
+
static from(color, _isSingleValue = false) {
|
|
378
|
+
if (color === '') {
|
|
379
|
+
throw new Error(`Can not create color from empty string`);
|
|
380
|
+
}
|
|
381
|
+
else if (color instanceof Color) {
|
|
379
382
|
return take(color);
|
|
380
383
|
}
|
|
381
384
|
else if (Color.isColor(color)) {
|
|
382
385
|
return take(color);
|
|
383
386
|
}
|
|
384
387
|
else if (typeof color === 'string') {
|
|
385
|
-
|
|
388
|
+
try {
|
|
389
|
+
return Color.fromString(color);
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
// <- Note: Can not use `assertsError(error)` here because it causes circular dependency
|
|
393
|
+
if (_isSingleValue) {
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
const parts = color.split(/[\s+,;|]/);
|
|
397
|
+
if (parts.length > 0) {
|
|
398
|
+
return Color.from(parts[0].trim(), true);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
throw new Error(`Can not create color from given string "${color}"`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
386
404
|
}
|
|
387
405
|
else {
|
|
388
406
|
console.error({ color });
|
|
@@ -22454,15 +22472,19 @@ const _FormattedBookInMarkdownTranspilerRegistration = $bookTranspilersRegister.
|
|
|
22454
22472
|
*
|
|
22455
22473
|
* @private - TODO: [🧠] Maybe should be public?
|
|
22456
22474
|
*/
|
|
22457
|
-
function createCommitmentRegex(commitment, aliases = []) {
|
|
22475
|
+
function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
|
|
22458
22476
|
const allCommitments = [commitment, ...aliases];
|
|
22459
22477
|
const patterns = allCommitments.map((c) => {
|
|
22460
22478
|
const escapedCommitment = c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
22461
22479
|
return escapedCommitment.split(/\s+/).join('\\s+');
|
|
22462
22480
|
});
|
|
22463
22481
|
const keywordPattern = patterns.join('|');
|
|
22464
|
-
|
|
22465
|
-
|
|
22482
|
+
if (requiresContent) {
|
|
22483
|
+
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
|
|
22484
|
+
}
|
|
22485
|
+
else {
|
|
22486
|
+
return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
|
|
22487
|
+
}
|
|
22466
22488
|
}
|
|
22467
22489
|
/**
|
|
22468
22490
|
* Generates a regex pattern to match a specific commitment type
|
|
@@ -22495,12 +22517,20 @@ class BaseCommitmentDefinition {
|
|
|
22495
22517
|
this.type = type;
|
|
22496
22518
|
this.aliases = aliases;
|
|
22497
22519
|
}
|
|
22520
|
+
/**
|
|
22521
|
+
* Whether this commitment requires content.
|
|
22522
|
+
* If true, regex will match only if there is content after the commitment keyword.
|
|
22523
|
+
* If false, regex will match even if there is no content.
|
|
22524
|
+
*/
|
|
22525
|
+
get requiresContent() {
|
|
22526
|
+
return true;
|
|
22527
|
+
}
|
|
22498
22528
|
/**
|
|
22499
22529
|
* Creates a regex pattern to match this commitment in agent source
|
|
22500
22530
|
* Uses the existing createCommitmentRegex function as internal helper
|
|
22501
22531
|
*/
|
|
22502
22532
|
createRegex() {
|
|
22503
|
-
return createCommitmentRegex(this.type, this.aliases);
|
|
22533
|
+
return createCommitmentRegex(this.type, this.aliases, this.requiresContent);
|
|
22504
22534
|
}
|
|
22505
22535
|
/**
|
|
22506
22536
|
* Creates a regex pattern to match just the commitment type
|
|
@@ -22652,6 +22682,12 @@ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
22652
22682
|
constructor() {
|
|
22653
22683
|
super('CLOSED');
|
|
22654
22684
|
}
|
|
22685
|
+
/**
|
|
22686
|
+
* The `CLOSED` commitment is standalone.
|
|
22687
|
+
*/
|
|
22688
|
+
get requiresContent() {
|
|
22689
|
+
return false;
|
|
22690
|
+
}
|
|
22655
22691
|
/**
|
|
22656
22692
|
* Short one-line description of CLOSED.
|
|
22657
22693
|
*/
|
|
@@ -25331,6 +25367,12 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
25331
25367
|
constructor() {
|
|
25332
25368
|
super('USE BROWSER', ['BROWSER']);
|
|
25333
25369
|
}
|
|
25370
|
+
/**
|
|
25371
|
+
* The `USE BROWSER` commitment is standalone.
|
|
25372
|
+
*/
|
|
25373
|
+
get requiresContent() {
|
|
25374
|
+
return false;
|
|
25375
|
+
}
|
|
25334
25376
|
/**
|
|
25335
25377
|
* Short one-line description of USE BROWSER.
|
|
25336
25378
|
*/
|
|
@@ -26171,11 +26213,11 @@ function parseAgentSource(agentSource) {
|
|
|
26171
26213
|
continue;
|
|
26172
26214
|
}
|
|
26173
26215
|
if (commitment.type === 'META COLOR') {
|
|
26174
|
-
meta.color =
|
|
26216
|
+
meta.color = normalizeSeparator(commitment.content);
|
|
26175
26217
|
continue;
|
|
26176
26218
|
}
|
|
26177
26219
|
if (commitment.type === 'META FONT') {
|
|
26178
|
-
meta.font =
|
|
26220
|
+
meta.font = normalizeSeparator(commitment.content);
|
|
26179
26221
|
continue;
|
|
26180
26222
|
}
|
|
26181
26223
|
if (commitment.type !== 'META') {
|
|
@@ -26211,6 +26253,19 @@ function parseAgentSource(agentSource) {
|
|
|
26211
26253
|
parameters,
|
|
26212
26254
|
};
|
|
26213
26255
|
}
|
|
26256
|
+
/**
|
|
26257
|
+
* Normalizes the separator in the content
|
|
26258
|
+
*
|
|
26259
|
+
* @param content - The content to normalize
|
|
26260
|
+
* @returns The content with normalized separators
|
|
26261
|
+
*/
|
|
26262
|
+
function normalizeSeparator(content) {
|
|
26263
|
+
const trimmed = spaceTrim$2(content);
|
|
26264
|
+
if (trimmed.includes(',')) {
|
|
26265
|
+
return trimmed;
|
|
26266
|
+
}
|
|
26267
|
+
return trimmed.split(/\s+/).join(', ');
|
|
26268
|
+
}
|
|
26214
26269
|
/**
|
|
26215
26270
|
* TODO: [🕛] Unite `AgentBasicInformation`, `ChatParticipant`, `LlmExecutionTools` + `LlmToolsMetadata`
|
|
26216
26271
|
*/
|