@promptbook/cli 0.104.0-5 โ†’ 0.104.0-6

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.
Files changed (26) hide show
  1. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +3 -2
  2. package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +6 -2
  3. package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +14 -8
  4. package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +5 -2
  5. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-fullhd.png/route.tsx +2 -2
  6. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +2 -2
  7. package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +2 -2
  8. package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +2 -2
  9. package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +6 -2
  10. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +7 -4
  11. package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +2 -1
  12. package/apps/agents-server/src/app/api/emails/incoming/sendgrid/route.ts +48 -0
  13. package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +10 -2
  14. package/apps/agents-server/src/components/Homepage/AgentCard.tsx +2 -1
  15. package/apps/agents-server/src/message-providers/email/sendgrid/parseInboundSendgridEmail.ts +49 -0
  16. package/apps/agents-server/src/utils/content/extractBodyContentFromHtml.ts +19 -0
  17. package/esm/index.es.js +1 -43
  18. package/esm/index.es.js.map +1 -1
  19. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirements.d.ts +6 -6
  20. package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +3 -3
  21. package/esm/typings/src/types/typeAliases.d.ts +4 -0
  22. package/esm/typings/src/version.d.ts +1 -1
  23. package/package.json +1 -1
  24. package/umd/index.umd.js +1 -43
  25. package/umd/index.umd.js.map +1 -1
  26. package/esm/typings/src/book-2.0/utils/generateGravatarUrl.d.ts +0 -10
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { AgentBasicInformation } from '@promptbook-local/types';
3
+ import { AgentBasicInformation, string_agent_name } from '@promptbook-local/types';
4
4
  import { AgentProfile } from '../../../components/AgentProfile/AgentProfile';
5
5
  import { AgentOptionsMenu } from './AgentOptionsMenu';
6
6
 
@@ -8,7 +8,7 @@ type AgentProfileWrapperProps = {
8
8
  agent: AgentBasicInformation;
9
9
  agentUrl: string;
10
10
  agentEmail: string;
11
- agentName: string;
11
+ agentName: string_agent_name;
12
12
  brandColorHex: string;
13
13
  isAdmin: boolean;
14
14
  isHeadless: boolean;
@@ -27,6 +27,7 @@ export function AgentProfileWrapper(props: AgentProfileWrapperProps) {
27
27
  <AgentProfile
28
28
  agent={agent}
29
29
  agentUrl={agentUrl}
30
+ permanentId={permanentId || agentName}
30
31
  agentEmail={agentEmail}
31
32
  isHeadless={isHeadless}
32
33
  renderMenu={({ onShowQrCode }) => (
@@ -13,7 +13,11 @@ export async function getAgentName(params: Promise<{ agentName: string }>) {
13
13
  export async function getAgentProfile(agentName: string) {
14
14
  const collection = await $provideAgentCollectionForServer();
15
15
  const agentSource = await collection.getAgentSource(agentName);
16
- return parseAgentSource(agentSource);
16
+ const agentProfile = parseAgentSource(agentSource);
17
+
18
+ console.log('!!!!', { agentSource, agentProfile });
19
+
20
+ return agentProfile;
17
21
  }
18
22
 
19
23
  export async function isAgentDeleted(agentName: string): Promise<boolean> {
@@ -33,5 +37,5 @@ export async function isAgentDeleted(agentName: string): Promise<boolean> {
33
37
  }
34
38
 
35
39
  /**
36
- * TODO: Split to multiple files
40
+ * TODO: Split to multiple files, refactor
37
41
  */
@@ -1,6 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import Editor from '@monaco-editor/react';
4
+ import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
5
+ import { AgentBasicInformation } from '@promptbook-local/types';
4
6
  import { ArrowLeftIcon, ChevronDownIcon, CodeIcon } from 'lucide-react';
5
7
  import Link from 'next/link';
6
8
  import { useCallback, useEffect, useState } from 'react';
@@ -29,7 +31,7 @@ function getLanguageFromTranspiler(transpilerName?: string): string {
29
31
 
30
32
  export default function AgentCodePage({ params }: { params: Promise<{ agentName: string }> }) {
31
33
  const [agentName, setAgentName] = useState<string>('');
32
- const [agentProfile, setAgentProfile] = useState<unknown>(null);
34
+ const [agentProfile, setAgentProfile] = useState<AgentBasicInformation | null>(null);
33
35
  const [transpilers, setTranspilers] = useState<Transpiler[]>([]);
34
36
  const [selectedTranspiler, setSelectedTranspiler] = useState<Transpiler | null>(null);
35
37
  const [transpiledCode, setTranspiledCode] = useState<string>('');
@@ -114,13 +116,17 @@ export default function AgentCodePage({ params }: { params: Promise<{ agentName:
114
116
  {/* Header */}
115
117
  <div className="p-6 border-b border-gray-200 flex items-center gap-4">
116
118
  {/* eslint-disable @typescript-eslint/no-explicit-any, @next/next/no-img-element */}
117
- {(agentProfile as any)?.meta?.image && (
118
- <img
119
- src={(agentProfile as any).meta.image as string}
120
- alt={(agentProfile as any).meta.fullname || agentName}
121
- className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
122
- />
123
- )}
119
+
120
+ <img
121
+ src={
122
+ agentProfile.meta.image ||
123
+ agentProfile.permanentId ||
124
+ generatePlaceholderAgentProfileImageUrl(agentName)
125
+ }
126
+ alt={agentProfile.meta.fullname || agentName}
127
+ className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
128
+ />
129
+
124
130
  <div className="flex-1">
125
131
  {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
126
132
  <h1 className="text-2xl font-bold text-gray-900">
@@ -1,4 +1,4 @@
1
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
1
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
2
2
  import { serializeError } from '@promptbook-local/utils';
3
3
  import { ImageResponse } from 'next/og';
4
4
  import { assertsError } from '../../../../../../../../src/errors/assertsError';
@@ -45,7 +45,10 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
45
45
  >
46
46
  {/* Note: `next/image` is not working propperly with `next/og` */}
47
47
  {/* eslint-disable-next-line @next/next/no-img-element */}
48
- <img src={agentProfile.meta.image!} alt="Agent Icon" />
48
+ <img
49
+ src={agentProfile.meta.image || agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName)}
50
+ alt="Agent Icon"
51
+ />
49
52
  </div>
50
53
  </div>
51
54
  ),
@@ -1,4 +1,4 @@
1
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
1
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
2
2
  import { serializeError } from '@promptbook-local/utils';
3
3
  import { ImageResponse } from 'next/og';
4
4
  import { assertsError } from '../../../../../../../../src/errors/assertsError';
@@ -51,7 +51,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
51
51
  backgroundColor: agentColor.toHex(),
52
52
  borderRadius: '50%',
53
53
  }}
54
- src={agentProfile.meta.image!}
54
+ src={agentProfile.meta.image || agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName)}
55
55
  alt="Agent Icon"
56
56
  />
57
57
  </div>
@@ -1,4 +1,4 @@
1
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
1
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
2
2
  import { serializeError } from '@promptbook-local/utils';
3
3
  import { ImageResponse } from 'next/og';
4
4
  import { assertsError } from '../../../../../../../../src/errors/assertsError';
@@ -51,7 +51,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
51
51
  backgroundColor: agentColor.toHex(),
52
52
  borderRadius: '50%',
53
53
  }}
54
- src={agentProfile.meta.image!}
54
+ src={agentProfile.meta.image || agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName)}
55
55
  alt="Agent Icon"
56
56
  />
57
57
  </div>
@@ -4,7 +4,7 @@ import { $getTableName } from '@/src/database/$getTableName';
4
4
  import { $provideSupabase } from '@/src/database/$provideSupabase';
5
5
  import { $provideServer } from '@/src/tools/$provideServer';
6
6
  import { isUserAdmin } from '@/src/utils/isUserAdmin';
7
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
7
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
8
8
  import { ArrowLeftIcon, BoxIcon, CodeIcon, GlobeIcon, ServerIcon, TerminalIcon } from 'lucide-react';
9
9
  import { headers } from 'next/headers';
10
10
  import Link from 'next/link';
@@ -187,7 +187,7 @@ export default async function AgentIntegrationPage({ params }: { params: Promise
187
187
  {agentProfile.meta.image && (
188
188
  // eslint-disable-next-line @next/next/no-img-element
189
189
  <img
190
- src={agentProfile.meta.image as string}
190
+ src={agentProfile.meta.image || agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName)}
191
191
  alt={agentProfile.meta.fullname || agentName}
192
192
  className="w-16 h-16 rounded-full object-cover border-2"
193
193
  style={{ borderColor: primaryColor }}
@@ -1,7 +1,7 @@
1
1
  'use server';
2
2
 
3
3
  import { $provideServer } from '@/src/tools/$provideServer';
4
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
4
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
5
5
  import { ArrowLeftIcon, CodeIcon, HomeIcon, LinkIcon, ShareIcon } from 'lucide-react';
6
6
  import { headers } from 'next/headers';
7
7
  import Link from 'next/link';
@@ -56,7 +56,7 @@ export default async function AgentLinksPage({ params }: { params: Promise<{ age
56
56
  {agentProfile.meta.image && (
57
57
  // eslint-disable-next-line @next/next/no-img-element
58
58
  <img
59
- src={agentProfile.meta.image as string}
59
+ src={agentProfile.meta.image || agentProfile.permanentId || generatePlaceholderAgentProfileImageUrl(agentName)}
60
60
  alt={agentProfile.meta.fullname || agentName}
61
61
  className="w-16 h-16 rounded-full object-cover border-2"
62
62
  style={{ borderColor: primaryColor }}
@@ -1,4 +1,4 @@
1
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
1
+ import { generatePlaceholderAgentProfileImageUrl, PROMPTBOOK_COLOR } from '@promptbook-local/core';
2
2
  import { serializeError } from '@promptbook-local/utils';
3
3
  import { ImageResponse } from 'next/og';
4
4
  import { assertsError } from '../../../../../../src/errors/assertsError';
@@ -54,7 +54,11 @@ export default async function Image({ params }: { params: Promise<{ agentName: s
54
54
  backgroundColor: agentColor.toHex(),
55
55
  borderRadius: '50%',
56
56
  }}
57
- src={agentProfile.meta.image!}
57
+ src={
58
+ agentProfile.meta.image ||
59
+ agentProfile.permanentId ||
60
+ generatePlaceholderAgentProfileImageUrl(agentProfile.permanentId || agentName)
61
+ }
58
62
  alt="Agent Icon"
59
63
  />
60
64
  </div>
@@ -3,17 +3,16 @@
3
3
  import { $provideServer } from '@/src/tools/$provideServer';
4
4
  import { isUserAdmin } from '@/src/utils/isUserAdmin';
5
5
  import { saturate } from '@promptbook-local/color';
6
- import { PROMPTBOOK_COLOR } from '@promptbook-local/core';
7
- import { NotFoundError } from '@promptbook-local/core';
6
+ import { generatePlaceholderAgentProfileImageUrl, NotFoundError, PROMPTBOOK_COLOR } from '@promptbook-local/core';
8
7
  import { notFound } from 'next/navigation';
9
8
  import { Color } from '../../../../../../src/utils/color/Color';
9
+ import { DeletedAgentBanner } from '../../../components/DeletedAgentBanner';
10
10
  import { getAgentName, getAgentProfile, isAgentDeleted } from './_utils';
11
11
  import { getAgentLinks } from './agentLinks';
12
12
  import { AgentProfileChat } from './AgentProfileChat';
13
13
  import { AgentProfileWrapper } from './AgentProfileWrapper';
14
14
  import { generateAgentMetadata } from './generateAgentMetadata';
15
15
  import { ServiceWorkerRegister } from './ServiceWorkerRegister';
16
- import { DeletedAgentBanner } from '../../../components/DeletedAgentBanner';
17
16
 
18
17
  export const generateMetadata = generateAgentMetadata;
19
18
 
@@ -96,7 +95,11 @@ export default async function AgentPage({
96
95
  agentName={agentName}
97
96
  fullname={fullname}
98
97
  brandColorHex={brandColorHex}
99
- avatarSrc={agentProfile.meta.image!}
98
+ avatarSrc={
99
+ agentProfile.meta.image ||
100
+ agentProfile.permanentId ||
101
+ generatePlaceholderAgentProfileImageUrl(agentName)
102
+ }
100
103
  isDeleted={isDeleted}
101
104
  />
102
105
  </AgentProfileWrapper>
@@ -8,6 +8,7 @@ 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';
11
12
 
12
13
  export const generateMetadata = generateAgentMetadata;
13
14
 
@@ -44,7 +45,7 @@ export default async function AgentSystemMessagePage({ params }: { params: Promi
44
45
  {agentProfile.meta.image && (
45
46
  // eslint-disable-next-line @next/next/no-img-element
46
47
  <img
47
- src={agentProfile.meta.image as string}
48
+ src={agentProfile.meta.image|| agentProfile.permanentId ||generatePlaceholderAgentProfileImageUrl(agentName)}
48
49
  alt={agentProfile.meta.fullname || agentName}
49
50
  className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
50
51
  />
@@ -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,6 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { AgentBasicInformation } from '@promptbook-local/types';
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';
@@ -13,6 +14,11 @@ type AgentProfileProps = {
13
14
  */
14
15
  readonly agent: AgentBasicInformation;
15
16
 
17
+ /**
18
+ * The permanent ID of the agent
19
+ */
20
+ readonly permanentId: string_agent_permanent_id;
21
+
16
22
  /**
17
23
  * URL of the agent page
18
24
  *
@@ -58,16 +64,18 @@ export function AgentProfile(props: AgentProfileProps) {
58
64
  agent,
59
65
  agentUrl = '',
60
66
  agentEmail = '',
67
+ permanentId,
61
68
  renderMenu,
62
69
  children,
63
70
  actions,
64
71
  isHeadless = false,
65
72
  className,
66
73
  } = props;
74
+ console.log('!!!!', { agent });
67
75
  const { meta, agentName } = agent;
68
76
  const fullname = (meta.fullname as string) || agentName || 'Agent';
69
77
  const personaDescription = agent.personaDescription || '';
70
- const imageUrl = (meta.image as string) || null;
78
+ const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId);
71
79
 
72
80
  const [isQrModalOpen, setIsQrModalOpen] = useState(false);
73
81
  const [isFlipped, setIsFlipped] = useState(false);
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
3
4
  import { really_any } from '@promptbook-local/types';
4
5
  import { EyeIcon, EyeOffIcon, RotateCcwIcon } from 'lucide-react';
5
6
  import Link from 'next/link';
@@ -32,7 +33,7 @@ export function AgentCard({
32
33
  }: AgentCardProps) {
33
34
  const { meta, agentName } = agent;
34
35
  const fullname = (meta.fullname as string) || agentName || 'Agent';
35
- const imageUrl = (meta.image as string) || null;
36
+ const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName);
36
37
  const personaDescription = agent.personaDescription || '';
37
38
 
38
39
  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-5';
50
+ const PROMPTBOOK_ENGINE_VERSION = '0.104.0-6';
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
@@ -26463,44 +26463,6 @@ async function createAgentModelRequirementsWithCommitments(agentSource, modelNam
26463
26463
  };
26464
26464
  }
26465
26465
 
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
26466
  /**
26505
26467
  * Computes SHA-256 hash of the agent source
26506
26468
  *
@@ -26598,10 +26560,6 @@ function parseAgentSource(agentSource) {
26598
26560
  const metaType = normalizeTo_camelCase(metaTypeRaw);
26599
26561
  meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
26600
26562
  }
26601
- // Generate gravatar fallback if no meta image specified
26602
- if (!meta.image) {
26603
- meta.image = generatePlaceholderAgentProfileImageUrl(parseResult.agentName || '!!');
26604
- }
26605
26563
  // Generate fullname fallback if no meta fullname specified
26606
26564
  if (!meta.fullname) {
26607
26565
  meta.fullname = parseResult.agentName || createDefaultAgentName(agentSource);