@promptbook/cli 0.104.0-5 โ 0.104.0-7
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/src/app/agents/[agentName]/AgentProfileWrapper.tsx +3 -2
- package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +6 -2
- package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +15 -8
- 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 +53 -38
- package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +6 -2
- 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 +3 -2
- package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +3 -2
- package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +3 -2
- package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +3 -2
- package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +10 -2
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +8 -4
- package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +3 -1
- package/apps/agents-server/src/app/api/emails/incoming/sendgrid/route.ts +48 -0
- package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +11 -2
- package/apps/agents-server/src/components/Homepage/AgentCard.tsx +3 -1
- package/apps/agents-server/src/message-providers/email/sendgrid/parseInboundSendgridEmail.ts +49 -0
- package/apps/agents-server/src/utils/content/extractBodyContentFromHtml.ts +19 -0
- package/esm/index.es.js +8 -51
- 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/agent-source/createAgentModelRequirements.d.ts +6 -6
- package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +3 -3
- package/esm/typings/src/types/ModelRequirements.d.ts +38 -14
- package/esm/typings/src/types/typeAliases.d.ts +11 -1
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +8 -51
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/book-2.0/utils/generateGravatarUrl.d.ts +0 -10
|
@@ -8,6 +8,8 @@ import { notFound } from 'next/navigation';
|
|
|
8
8
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
9
9
|
import { getAgentName, getAgentProfile } from '../_utils';
|
|
10
10
|
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
11
|
+
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
12
|
+
import { NEXT_PUBLIC_SITE_URL } from '@/config';
|
|
11
13
|
|
|
12
14
|
export const generateMetadata = generateAgentMetadata;
|
|
13
15
|
|
|
@@ -44,7 +46,7 @@ export default async function AgentSystemMessagePage({ params }: { params: Promi
|
|
|
44
46
|
{agentProfile.meta.image && (
|
|
45
47
|
// eslint-disable-next-line @next/next/no-img-element
|
|
46
48
|
<img
|
|
47
|
-
src={agentProfile.meta.image
|
|
49
|
+
src={agentProfile.meta.image|| agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName, NEXT_PUBLIC_SITE_URL)}
|
|
48
50
|
alt={agentProfile.meta.fullname || agentName}
|
|
49
51
|
className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
|
|
50
52
|
/>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { $getTableName } from '../../../../../database/$getTableName';
|
|
2
|
+
import { $provideSupabaseForServer } from '../../../../../database/$provideSupabaseForServer';
|
|
3
|
+
import { parseInboundSendgridEmail } from '../../../../../message-providers/email/sendgrid/parseInboundSendgridEmail';
|
|
4
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
5
|
+
|
|
6
|
+
export async function POST(request: NextRequest) {
|
|
7
|
+
try {
|
|
8
|
+
const formData = await request.formData();
|
|
9
|
+
const rawEmail = formData.get('email');
|
|
10
|
+
|
|
11
|
+
if (typeof rawEmail !== 'string') {
|
|
12
|
+
return NextResponse.json({ error: 'Missing email field' }, { status: 400 });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const email = await parseInboundSendgridEmail(rawEmail);
|
|
16
|
+
|
|
17
|
+
const supabase = await $provideSupabaseForServer();
|
|
18
|
+
const { error } = await supabase
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
.from(await $getTableName('Message'))
|
|
21
|
+
.insert({
|
|
22
|
+
channel: 'EMAIL',
|
|
23
|
+
direction: 'INBOUND',
|
|
24
|
+
sender: email.sender,
|
|
25
|
+
recipients: email.recipients,
|
|
26
|
+
content: email.content,
|
|
27
|
+
metadata: {
|
|
28
|
+
subject: email.subject,
|
|
29
|
+
cc: email.cc,
|
|
30
|
+
...email.metadata,
|
|
31
|
+
},
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
|
+
} as any);
|
|
34
|
+
|
|
35
|
+
if (error) {
|
|
36
|
+
console.error('Failed to insert message', error);
|
|
37
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return NextResponse.json({ success: true });
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('Error processing inbound email', error);
|
|
43
|
+
return NextResponse.json(
|
|
44
|
+
{ error: error instanceof Error ? error.message : 'Unknown error' },
|
|
45
|
+
{ status: 500 },
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
4
|
+
import { AgentBasicInformation, string_agent_permanent_id } from '@promptbook-local/types';
|
|
4
5
|
import { RepeatIcon } from 'lucide-react';
|
|
5
6
|
import { useState } from 'react';
|
|
6
7
|
import { AgentQrCode } from './AgentQrCode';
|
|
7
8
|
import { QrCodeModal } from './QrCodeModal';
|
|
8
9
|
import { useAgentBackground } from './useAgentBackground';
|
|
10
|
+
import { NEXT_PUBLIC_SITE_URL } from '@/config';
|
|
9
11
|
|
|
10
12
|
type AgentProfileProps = {
|
|
11
13
|
/**
|
|
@@ -13,6 +15,11 @@ type AgentProfileProps = {
|
|
|
13
15
|
*/
|
|
14
16
|
readonly agent: AgentBasicInformation;
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* The permanent ID of the agent
|
|
20
|
+
*/
|
|
21
|
+
readonly permanentId: string_agent_permanent_id;
|
|
22
|
+
|
|
16
23
|
/**
|
|
17
24
|
* URL of the agent page
|
|
18
25
|
*
|
|
@@ -58,16 +65,18 @@ export function AgentProfile(props: AgentProfileProps) {
|
|
|
58
65
|
agent,
|
|
59
66
|
agentUrl = '',
|
|
60
67
|
agentEmail = '',
|
|
68
|
+
permanentId,
|
|
61
69
|
renderMenu,
|
|
62
70
|
children,
|
|
63
71
|
actions,
|
|
64
72
|
isHeadless = false,
|
|
65
73
|
className,
|
|
66
74
|
} = props;
|
|
75
|
+
console.log('!!!!', { agent });
|
|
67
76
|
const { meta, agentName } = agent;
|
|
68
77
|
const fullname = (meta.fullname as string) || agentName || 'Agent';
|
|
69
78
|
const personaDescription = agent.personaDescription || '';
|
|
70
|
-
const imageUrl =
|
|
79
|
+
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId, NEXT_PUBLIC_SITE_URL);
|
|
71
80
|
|
|
72
81
|
const [isQrModalOpen, setIsQrModalOpen] = useState(false);
|
|
73
82
|
const [isFlipped, setIsFlipped] = useState(false);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { NEXT_PUBLIC_SITE_URL } from '@/config';
|
|
4
|
+
import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
|
|
3
5
|
import { really_any } from '@promptbook-local/types';
|
|
4
6
|
import { EyeIcon, EyeOffIcon, RotateCcwIcon } from 'lucide-react';
|
|
5
7
|
import Link from 'next/link';
|
|
@@ -32,7 +34,7 @@ export function AgentCard({
|
|
|
32
34
|
}: AgentCardProps) {
|
|
33
35
|
const { meta, agentName } = agent;
|
|
34
36
|
const fullname = (meta.fullname as string) || agentName || 'Agent';
|
|
35
|
-
const imageUrl =
|
|
37
|
+
const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName, NEXT_PUBLIC_SITE_URL);
|
|
36
38
|
const personaDescription = agent.personaDescription || '';
|
|
37
39
|
|
|
38
40
|
const { brandColorLightHex, brandColorDarkHex, backgroundImage } = useAgentBackground(meta.color);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { string_markdown } from '@promptbook-local/types';
|
|
2
|
+
import { simpleParser } from 'mailparser';
|
|
3
|
+
import TurndownService from 'turndown';
|
|
4
|
+
import { extractBodyContentFromHtml } from '../../../utils/content/extractBodyContentFromHtml';
|
|
5
|
+
import type { InboundEmail } from '../_common/Email';
|
|
6
|
+
import { parseEmailAddress } from '../_common/utils/parseEmailAddress';
|
|
7
|
+
import { parseEmailAddresses } from '../_common/utils/parseEmailAddresses';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Function parseInboundSendgridEmail will parse raw inbound email from Sendgrid and return Email object
|
|
11
|
+
*/
|
|
12
|
+
export async function parseInboundSendgridEmail(rawEmail: string): Promise<InboundEmail> {
|
|
13
|
+
const parsedEmail = await simpleParser(rawEmail);
|
|
14
|
+
|
|
15
|
+
const toArray = !Array.isArray(parsedEmail.to)
|
|
16
|
+
? parsedEmail.to === undefined
|
|
17
|
+
? []
|
|
18
|
+
: [parsedEmail.to]
|
|
19
|
+
: parsedEmail.to;
|
|
20
|
+
const to = toArray.flatMap((_) => parseEmailAddresses(_.text));
|
|
21
|
+
|
|
22
|
+
const ccArray = !Array.isArray(parsedEmail.cc)
|
|
23
|
+
? parsedEmail.cc === undefined
|
|
24
|
+
? []
|
|
25
|
+
: [parsedEmail.cc]
|
|
26
|
+
: parsedEmail.cc;
|
|
27
|
+
const cc = ccArray.flatMap((_) => parseEmailAddresses(_.text));
|
|
28
|
+
|
|
29
|
+
const turndownService = new TurndownService();
|
|
30
|
+
|
|
31
|
+
const content = (parsedEmail.html
|
|
32
|
+
? turndownService.turndown(extractBodyContentFromHtml(parsedEmail.html))
|
|
33
|
+
: parsedEmail.text || '') as string_markdown;
|
|
34
|
+
|
|
35
|
+
const email: InboundEmail = {
|
|
36
|
+
channel: 'EMAIL',
|
|
37
|
+
direction: 'INBOUND',
|
|
38
|
+
sender: parseEmailAddress(parsedEmail.from?.text || '').fullEmail,
|
|
39
|
+
recipients: to.map((_) => _.fullEmail),
|
|
40
|
+
cc,
|
|
41
|
+
subject: parsedEmail.subject || '',
|
|
42
|
+
content,
|
|
43
|
+
attachments: [
|
|
44
|
+
/* <- TODO: [๐ฏ] Parse attachments */
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return email;
|
|
49
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { string_html } from '@promptbook-local/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extract the first heading from HTML
|
|
5
|
+
*
|
|
6
|
+
* @param contentText HTML
|
|
7
|
+
* @returns heading
|
|
8
|
+
*/
|
|
9
|
+
export function extractBodyContentFromHtml(html: string_html): string_html {
|
|
10
|
+
// Note: Not using DOMParser, because it's overkill for this simple task
|
|
11
|
+
|
|
12
|
+
const match = html.match(/<body[^>]*>(?<bodyContent>[\s\S]*)<\/body>/s);
|
|
13
|
+
|
|
14
|
+
if (!match) {
|
|
15
|
+
return html;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return match.groups!.bodyContent!;
|
|
19
|
+
}
|
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.104.0-
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.104.0-7';
|
|
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
|
|
@@ -57,6 +57,8 @@ const PROMPTBOOK_ENGINE_VERSION = '0.104.0-5';
|
|
|
57
57
|
* Core Promptbook server configuration.
|
|
58
58
|
*
|
|
59
59
|
* This server is also used for auto-federation in the Agents Server.
|
|
60
|
+
*
|
|
61
|
+
* @public exported from `@promptbook/core`
|
|
60
62
|
*/
|
|
61
63
|
const CORE_SERVER = {
|
|
62
64
|
title: 'Promptbook Core',
|
|
@@ -11402,11 +11404,7 @@ const modelCommandParser = {
|
|
|
11402
11404
|
// TODO: [๐] DRY
|
|
11403
11405
|
if ($taskJson.modelRequirements[command.key] !== undefined) {
|
|
11404
11406
|
if ($taskJson.modelRequirements[command.key] === command.value) {
|
|
11405
|
-
console.warn(`Multiple commands \`MODEL ${{
|
|
11406
|
-
modelName: 'NAME',
|
|
11407
|
-
modelVariant: 'VARIANT',
|
|
11408
|
-
maxTokens: '???',
|
|
11409
|
-
}[command.key]} ${command.value}\` in the task "${$taskJson.title || $taskJson.name}"`);
|
|
11407
|
+
console.warn(`Multiple commands \`MODEL ${command.key} ${command.value}\` in the task "${$taskJson.title || $taskJson.name}"`);
|
|
11410
11408
|
// <- TODO: [๐ฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
|
|
11411
11409
|
}
|
|
11412
11410
|
else {
|
|
@@ -19892,13 +19890,14 @@ class OpenAiCompatibleExecutionTools {
|
|
|
19892
19890
|
const modelName = currentModelRequirements.modelName || this.getDefaultImageGenerationModel().modelName;
|
|
19893
19891
|
const modelSettings = {
|
|
19894
19892
|
model: modelName,
|
|
19895
|
-
|
|
19896
|
-
|
|
19897
|
-
|
|
19893
|
+
size: currentModelRequirements.size,
|
|
19894
|
+
quality: currentModelRequirements.quality,
|
|
19895
|
+
style: currentModelRequirements.style,
|
|
19898
19896
|
};
|
|
19899
19897
|
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
19900
19898
|
const rawRequest = {
|
|
19901
19899
|
...modelSettings,
|
|
19900
|
+
size: modelSettings.size || '1024x1024',
|
|
19902
19901
|
prompt: rawPromptContent,
|
|
19903
19902
|
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
19904
19903
|
response_format: 'url', // TODO: [๐ง ] Maybe allow b64_json
|
|
@@ -26463,44 +26462,6 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
|
|
|
26463
26462
|
};
|
|
26464
26463
|
}
|
|
26465
26464
|
|
|
26466
|
-
/**
|
|
26467
|
-
* Generates a gravatar URL based on agent name for fallback avatar
|
|
26468
|
-
*
|
|
26469
|
-
* @param agentName The agent name to generate avatar for
|
|
26470
|
-
* @returns Gravatar URL
|
|
26471
|
-
*
|
|
26472
|
-
* @private - [๐คน] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
|
|
26473
|
-
*/
|
|
26474
|
-
function generateGravatarUrl(agentName) {
|
|
26475
|
-
// Use a default name if none provided
|
|
26476
|
-
const safeName = agentName || 'Anonymous Agent';
|
|
26477
|
-
// Create a simple hash from the name for consistent avatar
|
|
26478
|
-
let hash = 0;
|
|
26479
|
-
for (let i = 0; i < safeName.length; i++) {
|
|
26480
|
-
const char = safeName.charCodeAt(i);
|
|
26481
|
-
hash = (hash << 5) - hash + char;
|
|
26482
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
26483
|
-
}
|
|
26484
|
-
const avatarId = Math.abs(hash).toString();
|
|
26485
|
-
return `https://www.gravatar.com/avatar/${avatarId}?default=robohash&size=200&rating=x`;
|
|
26486
|
-
}
|
|
26487
|
-
|
|
26488
|
-
/**
|
|
26489
|
-
* Generates an image for the agent to use as profile image
|
|
26490
|
-
*
|
|
26491
|
-
* @param agentName The agent name to generate avatar for
|
|
26492
|
-
* @returns The placeholder profile image URL for the agent
|
|
26493
|
-
*
|
|
26494
|
-
* @public exported from `@promptbook/core`
|
|
26495
|
-
*/
|
|
26496
|
-
function generatePlaceholderAgentProfileImageUrl(agentName) {
|
|
26497
|
-
// Note: [๐คน] The fact that profile image is Gravatar is just implementation detail which should be hidden for consumer
|
|
26498
|
-
return generateGravatarUrl(agentName);
|
|
26499
|
-
}
|
|
26500
|
-
/**
|
|
26501
|
-
* TODO: [๐คน] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
|
|
26502
|
-
*/
|
|
26503
|
-
|
|
26504
26465
|
/**
|
|
26505
26466
|
* Computes SHA-256 hash of the agent source
|
|
26506
26467
|
*
|
|
@@ -26598,10 +26559,6 @@ function parseAgentSource(agentSource) {
|
|
|
26598
26559
|
const metaType = normalizeTo_camelCase(metaTypeRaw);
|
|
26599
26560
|
meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
|
|
26600
26561
|
}
|
|
26601
|
-
// Generate gravatar fallback if no meta image specified
|
|
26602
|
-
if (!meta.image) {
|
|
26603
|
-
meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
|
|
26604
|
-
}
|
|
26605
26562
|
// Generate fullname fallback if no meta fullname specified
|
|
26606
26563
|
if (!meta.fullname) {
|
|
26607
26564
|
meta.fullname = parseResult.agentName || createDefaultAgentName(agentSource);
|