@promptbook/cli 0.104.0-7 โ†’ 0.104.0-8

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 (39) hide show
  1. package/apps/agents-server/config.ts +1 -3
  2. package/apps/agents-server/src/app/admin/browser-test/BrowserTestClient.tsx +85 -0
  3. package/apps/agents-server/src/app/admin/browser-test/page.tsx +13 -0
  4. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +49 -10
  5. package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +0 -3
  6. package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +4 -2
  7. package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/route.ts +5 -2
  8. package/apps/agents-server/src/app/agents/[agentName]/images/icon-256.png/route.tsx +10 -2
  9. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-fullhd.png/route.tsx +5 -5
  10. package/apps/agents-server/src/app/agents/[agentName]/images/screenshot-phone.png/route.tsx +5 -5
  11. package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +8 -2
  12. package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +8 -2
  13. package/apps/agents-server/src/app/agents/[agentName]/opengraph-image.tsx +4 -3
  14. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +3 -5
  15. package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +15 -4
  16. package/apps/agents-server/src/app/api/browser-test/screenshot/route.ts +30 -0
  17. package/apps/agents-server/src/app/humans.txt/route.ts +1 -1
  18. package/apps/agents-server/src/app/page.tsx +4 -2
  19. package/apps/agents-server/src/app/recycle-bin/page.tsx +3 -1
  20. package/apps/agents-server/src/app/robots.txt/route.ts +1 -1
  21. package/apps/agents-server/src/app/security.txt/route.ts +1 -1
  22. package/apps/agents-server/src/app/sitemap.xml/route.ts +4 -5
  23. package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +22 -14
  24. package/apps/agents-server/src/components/Header/Header.tsx +4 -0
  25. package/apps/agents-server/src/components/Homepage/AgentCard.tsx +46 -10
  26. package/apps/agents-server/src/components/Homepage/AgentsList.tsx +32 -14
  27. package/apps/agents-server/src/components/Homepage/DeletedAgentsList.tsx +22 -6
  28. package/apps/agents-server/src/components/Homepage/ExternalAgentsSection.tsx +12 -3
  29. package/apps/agents-server/src/components/Homepage/ExternalAgentsSectionClient.tsx +19 -10
  30. package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +2 -0
  31. package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +12 -10
  32. package/apps/agents-server/src/tools/$provideBrowserForServer.ts +29 -0
  33. package/apps/agents-server/src/tools/$provideCdnForServer.ts +1 -1
  34. package/esm/index.es.js +1 -1
  35. package/esm/typings/src/book-2.0/utils/generatePlaceholderAgentProfileImageUrl.d.ts +2 -2
  36. package/esm/typings/src/utils/color/utils/colorToDataUrl.d.ts +2 -1
  37. package/esm/typings/src/version.d.ts +1 -1
  38. package/package.json +1 -1
  39. package/umd/index.umd.js +1 -1
@@ -1,25 +1,24 @@
1
1
  // Dynamic sitemap.xml for Agents Server
2
2
 
3
- import { NEXT_PUBLIC_SITE_URL } from '@/config';
4
3
  import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
4
+ import { $provideServer } from '@/src/tools/$provideServer';
5
5
  import { spaceTrim } from '@promptbook-local/utils';
6
6
  import { NextResponse } from 'next/server';
7
7
 
8
8
  export const dynamic = 'force-dynamic';
9
9
 
10
10
  export async function GET() {
11
+ const { publicUrl } = await $provideServer();
12
+
11
13
  const collection = await $provideAgentCollectionForServer();
12
14
 
13
15
  // Assume collection.listAgents() returns an array of agent names
14
16
  const agents = await collection.listAgents();
15
17
 
16
- // Get base URL from environment or config
17
- const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
18
-
19
18
  const urls = agents
20
19
  .map(
21
20
  ({ permanentId, agentName }) =>
22
- `<url><loc>${baseUrl}agents/${encodeURIComponent(permanentId || agentName)}</loc></url>`,
21
+ `<url><loc>${publicUrl.href}agents/${encodeURIComponent(permanentId || agentName)}</loc></url>`,
23
22
  )
24
23
  .join('\n');
25
24
 
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { colorToDataUrl } from '@promptbook-local/color';
3
4
  import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
4
5
  import { AgentBasicInformation, string_agent_permanent_id } from '@promptbook-local/types';
5
6
  import { RepeatIcon } from 'lucide-react';
@@ -7,7 +8,6 @@ import { useState } from 'react';
7
8
  import { AgentQrCode } from './AgentQrCode';
8
9
  import { QrCodeModal } from './QrCodeModal';
9
10
  import { useAgentBackground } from './useAgentBackground';
10
- import { NEXT_PUBLIC_SITE_URL } from '@/config';
11
11
 
12
12
  type AgentProfileProps = {
13
13
  /**
@@ -27,6 +27,11 @@ type AgentProfileProps = {
27
27
  */
28
28
  readonly agentUrl?: string;
29
29
 
30
+ /**
31
+ * Base URL of the agents server
32
+ */
33
+ readonly publicUrl: URL;
34
+
30
35
  /**
31
36
  * Email of the agent
32
37
  */
@@ -65,6 +70,7 @@ export function AgentProfile(props: AgentProfileProps) {
65
70
  agent,
66
71
  agentUrl = '',
67
72
  agentEmail = '',
73
+ publicUrl,
68
74
  permanentId,
69
75
  renderMenu,
70
76
  children,
@@ -72,11 +78,11 @@ export function AgentProfile(props: AgentProfileProps) {
72
78
  isHeadless = false,
73
79
  className,
74
80
  } = props;
75
- console.log('!!!!', { agent });
81
+
76
82
  const { meta, agentName } = agent;
77
83
  const fullname = (meta.fullname as string) || agentName || 'Agent';
78
84
  const personaDescription = agent.personaDescription || '';
79
- const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId, NEXT_PUBLIC_SITE_URL);
85
+ const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(permanentId, publicUrl);
80
86
 
81
87
  const [isQrModalOpen, setIsQrModalOpen] = useState(false);
82
88
  const [isFlipped, setIsFlipped] = useState(false);
@@ -154,17 +160,19 @@ export function AgentProfile(props: AgentProfileProps) {
154
160
  // ['cornerShape' as really_any /* <- Note: `cornerShape` is non standard CSS property */]: 'squircle ',
155
161
  }}
156
162
  >
157
- {imageUrl ? (
158
- // eslint-disable-next-line @next/next/no-img-element
159
- <img src={imageUrl} alt={fullname} className="w-full h-full object-cover" />
160
- ) : (
161
- <div
162
- className="w-full h-full flex items-center justify-center text-3xl md:text-8xl font-bold text-white/80"
163
- style={{ backgroundColor: brandColorDarkHex }}
164
- >
165
- {fullname.charAt(0).toUpperCase()}
166
- </div>
167
- )}
163
+ {/* eslint-disable-next-line @next/next/no-img-element */}
164
+ <img
165
+ src={imageUrl}
166
+ alt={fullname}
167
+ className="w-full h-full object-cover"
168
+ // width={1024}
169
+ // height={1792}
170
+ // <- TODO: [๐Ÿค] DRY
171
+ style={{
172
+ objectFit: 'cover',
173
+ backgroundImage: `url(${colorToDataUrl(brandColorLightHex)})`,
174
+ }}
175
+ />
168
176
 
169
177
  {/* Flip hint icon */}
170
178
  <div className="absolute bottom-2 md:bottom-4 right-2 md:right-4 bg-black/30 p-1 md:p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
@@ -305,6 +305,10 @@ export function Header(props: HeaderProps) {
305
305
  label: 'Chat feedback',
306
306
  href: '/admin/chat-feedback',
307
307
  },
308
+ {
309
+ label: 'Browser',
310
+ href: '/admin/browser-test',
311
+ },
308
312
  ],
309
313
  },
310
314
  {
@@ -1,6 +1,5 @@
1
1
  'use client';
2
2
 
3
- import { NEXT_PUBLIC_SITE_URL } from '@/config';
4
3
  import { generatePlaceholderAgentProfileImageUrl } from '@promptbook-local/core';
5
4
  import { really_any } from '@promptbook-local/types';
6
5
  import { EyeIcon, EyeOffIcon, RotateCcwIcon } from 'lucide-react';
@@ -9,14 +8,50 @@ import { AgentBasicInformation } from '../../../../../src/book-2.0/agent-source/
9
8
  import { useAgentBackground } from '../AgentProfile/useAgentBackground';
10
9
 
11
10
  type AgentCardProps = {
12
- agent: AgentBasicInformation;
13
- href: string;
14
- isAdmin?: boolean;
15
- onDelete?: (agentIdentifier: string) => void;
16
- onClone?: (agentIdentifier: string) => void;
17
- onToggleVisibility?: (agentIdentifier: string) => void;
18
- onRestore?: (agentIdentifier: string) => void;
19
- visibility?: 'PUBLIC' | 'PRIVATE';
11
+ /**
12
+ * @@@
13
+ */
14
+ readonly agent: AgentBasicInformation;
15
+
16
+ /**
17
+ * @@@
18
+ */
19
+ readonly href: string;
20
+
21
+ /**
22
+ * Base URL of the agents server
23
+ */
24
+ readonly publicUrl: URL;
25
+
26
+ /**
27
+ * @@@
28
+ */
29
+ readonly isAdmin?: boolean;
30
+
31
+ /**
32
+ * @@@
33
+ */
34
+ readonly onDelete?: (agentIdentifier: string) => void;
35
+
36
+ /**
37
+ * @@@
38
+ */
39
+ readonly onClone?: (agentIdentifier: string) => void;
40
+
41
+ /**
42
+ * @@@
43
+ */
44
+ readonly onToggleVisibility?: (agentIdentifier: string) => void;
45
+
46
+ /**
47
+ * @@@
48
+ */
49
+ readonly onRestore?: (agentIdentifier: string) => void;
50
+
51
+ /**
52
+ * @@@
53
+ */
54
+ readonly visibility?: 'PUBLIC' | 'PRIVATE';
20
55
  };
21
56
 
22
57
  const ACTION_BUTTON_CLASSES =
@@ -26,6 +61,7 @@ export function AgentCard({
26
61
  agent,
27
62
  href,
28
63
  isAdmin,
64
+ publicUrl,
29
65
  onDelete,
30
66
  onClone,
31
67
  onToggleVisibility,
@@ -34,7 +70,7 @@ export function AgentCard({
34
70
  }: AgentCardProps) {
35
71
  const { meta, agentName } = agent;
36
72
  const fullname = (meta.fullname as string) || agentName || 'Agent';
37
- const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName, NEXT_PUBLIC_SITE_URL);
73
+ const imageUrl = meta.image || generatePlaceholderAgentProfileImageUrl(agentName, publicUrl);
38
74
  const personaDescription = agent.personaDescription || '';
39
75
 
40
76
  const { brandColorLightHex, brandColorDarkHex, backgroundImage } = useAgentBackground(meta.color);
@@ -1,10 +1,10 @@
1
1
  // Client Component for rendering and deleting agents
2
2
  'use client';
3
3
 
4
- import React, { useState } from 'react';
5
- import { useRouter } from 'next/navigation';
6
4
  import { TrashIcon } from 'lucide-react';
7
5
  import Link from 'next/link';
6
+ import { useRouter } from 'next/navigation';
7
+ import { useState } from 'react';
8
8
  import { AddAgentButton } from '../../app/AddAgentButton';
9
9
  import { AgentCard } from './AgentCard';
10
10
  import { Section } from './Section';
@@ -16,16 +16,29 @@ type AgentWithVisibility = AgentBasicInformation & {
16
16
  };
17
17
 
18
18
  type AgentsListProps = {
19
- agents: AgentWithVisibility[];
20
- isAdmin: boolean;
19
+ /**
20
+ * @@@
21
+ */
22
+ readonly agents: AgentWithVisibility[];
23
+
24
+ /**
25
+ * @@@
26
+ */
27
+ readonly isAdmin: boolean;
28
+
29
+ /**
30
+ * Base URL of the agents server
31
+ */
32
+ readonly publicUrl: URL;
21
33
  };
22
34
 
23
- export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps) {
35
+ export function AgentsList(props: AgentsListProps) {
36
+ const { agents: initialAgents, isAdmin, publicUrl } = props;
24
37
  const router = useRouter();
25
38
  const [agents, setAgents] = useState(Array.from(initialAgents));
26
39
 
27
40
  const handleDelete = async (agentIdentifier: string) => {
28
- const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
41
+ const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
29
42
  if (!agent) return;
30
43
  if (!window.confirm(`Delete agent "${agent.agentName}"? It will be moved to Recycle Bin.`)) return;
31
44
 
@@ -45,12 +58,14 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
45
58
  };
46
59
 
47
60
  const handleClone = async (agentIdentifier: string) => {
48
- const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
61
+ const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
49
62
  if (!agent) return;
50
63
  if (!window.confirm(`Clone agent "${agent.agentName}"?`)) return;
51
64
 
52
65
  try {
53
- const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/clone`, { method: 'POST' });
66
+ const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/clone`, {
67
+ method: 'POST',
68
+ });
54
69
  if (response.ok) {
55
70
  const newAgent = await response.json();
56
71
  setAgents([...agents, newAgent]);
@@ -64,7 +79,7 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
64
79
  };
65
80
 
66
81
  const handleToggleVisibility = async (agentIdentifier: string) => {
67
- const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
82
+ const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
68
83
  if (!agent) return;
69
84
 
70
85
  const newVisibility = agent.visibility === 'PUBLIC' ? 'PRIVATE' : 'PUBLIC';
@@ -78,11 +93,13 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
78
93
 
79
94
  if (response.ok) {
80
95
  // Update the local state
81
- setAgents(agents.map(a =>
82
- a.permanentId === agent.permanentId || a.agentName === agent.agentName
83
- ? { ...a, visibility: newVisibility }
84
- : a
85
- ));
96
+ setAgents(
97
+ agents.map((a) =>
98
+ a.permanentId === agent.permanentId || a.agentName === agent.agentName
99
+ ? { ...a, visibility: newVisibility }
100
+ : a,
101
+ ),
102
+ );
86
103
  router.refresh(); // Refresh server data to ensure consistency
87
104
  } else {
88
105
  alert('Failed to update agent visibility');
@@ -95,6 +112,7 @@ export function AgentsList({ agents: initialAgents, isAdmin }: AgentsListProps)
95
112
  <AgentCard
96
113
  key={agent.permanentId || agent.agentName}
97
114
  agent={agent}
115
+ publicUrl={publicUrl}
98
116
  href={`/agents/${encodeURIComponent(agent.permanentId || agent.agentName)}`}
99
117
  isAdmin={isAdmin}
100
118
  onDelete={handleDelete}
@@ -1,26 +1,41 @@
1
1
  // Client Component for rendering deleted agents
2
2
  'use client';
3
3
 
4
- import React, { useState } from 'react';
4
+ import { useState } from 'react';
5
5
  import { AgentCard } from './AgentCard';
6
6
 
7
7
  import { AgentBasicInformation } from '../../../../../src/book-2.0/agent-source/AgentBasicInformation';
8
8
 
9
9
  type DeletedAgentsListProps = {
10
- agents: readonly AgentBasicInformation[];
11
- isAdmin: boolean;
10
+ /**
11
+ * @@@
12
+ */
13
+ readonly agents: readonly AgentBasicInformation[];
14
+
15
+ /**
16
+ * @@@
17
+ */
18
+ readonly isAdmin: boolean;
19
+
20
+ /**
21
+ * Base URL of the agents server
22
+ */
23
+ readonly publicUrl: URL;
12
24
  };
13
25
 
14
- export function DeletedAgentsList({ agents: initialAgents, isAdmin }: DeletedAgentsListProps) {
26
+ export function DeletedAgentsList(props: DeletedAgentsListProps) {
27
+ const { agents: initialAgents, isAdmin, publicUrl } = props;
15
28
  const [agents, setAgents] = useState(Array.from(initialAgents));
16
29
 
17
30
  const handleRestore = async (agentIdentifier: string) => {
18
- const agent = agents.find(a => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
31
+ const agent = agents.find((a) => a.permanentId === agentIdentifier || a.agentName === agentIdentifier);
19
32
  if (!agent) return;
20
33
  if (!window.confirm(`Restore agent "${agent.agentName}"?`)) return;
21
34
 
22
35
  try {
23
- const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/restore`, { method: 'POST' });
36
+ const response = await fetch(`/api/agents/${encodeURIComponent(agentIdentifier)}/restore`, {
37
+ method: 'POST',
38
+ });
24
39
  if (response.ok) {
25
40
  // Update local state immediately
26
41
  setAgents(agents.filter((a) => a.permanentId !== agent.permanentId && a.agentName !== agent.agentName));
@@ -40,6 +55,7 @@ export function DeletedAgentsList({ agents: initialAgents, isAdmin }: DeletedAge
40
55
  <AgentCard
41
56
  key={agent.permanentId || agent.agentName}
42
57
  agent={agent}
58
+ publicUrl={publicUrl}
43
59
  href={`/agents/${encodeURIComponent(agent.permanentId || agent.agentName)}`}
44
60
  isAdmin={isAdmin}
45
61
  onRestore={handleRestore}
@@ -3,16 +3,25 @@ import { AgentCard } from './AgentCard';
3
3
  import { Section } from './Section';
4
4
 
5
5
  type ExternalAgentsSectionProps = {
6
- agentsByServer: AgentsByServer[];
6
+ /**
7
+ * @@@
8
+ */
9
+ readonly agentsByServer: AgentsByServer[];
10
+
11
+ /**
12
+ * Base URL of the agents server
13
+ */
14
+ readonly publicUrl: URL;
7
15
  };
8
16
 
9
- export function ExternalAgentsSection({ agentsByServer }: ExternalAgentsSectionProps) {
17
+ export function ExternalAgentsSection(props: ExternalAgentsSectionProps) {
18
+ const { agentsByServer, publicUrl } = props;
10
19
  return (
11
20
  <>
12
21
  {agentsByServer.map(({ serverUrl, agents }) => (
13
22
  <Section key={serverUrl} title={`Agents from ${new URL(serverUrl).hostname} (${agents.length})`}>
14
23
  {agents.map((agent) => (
15
- <AgentCard key={agent.url} agent={agent} href={agent.url} />
24
+ <AgentCard key={agent.url} agent={agent} href={agent.url} publicUrl={publicUrl} />
16
25
  ))}
17
26
  </Section>
18
27
  ))}
@@ -15,7 +15,15 @@ type ServerState = {
15
15
  error?: string;
16
16
  };
17
17
 
18
- export function ExternalAgentsSectionClient() {
18
+ type ExternalAgentsSectionClientProps = {
19
+ /**
20
+ * Base URL of the agents server
21
+ */
22
+ readonly publicUrl: URL;
23
+ };
24
+
25
+ export function ExternalAgentsSectionClient(props: ExternalAgentsSectionClientProps) {
26
+ const { publicUrl } = props;
19
27
  const [servers, setServers] = useState<Record<string, ServerState>>({});
20
28
  const [initialLoading, setInitialLoading] = useState(true);
21
29
 
@@ -26,24 +34,23 @@ export function ExternalAgentsSectionClient() {
26
34
  try {
27
35
  const response = await fetch('/api/federated-agents');
28
36
  if (!response.ok) throw new Error('Failed to fetch federated servers');
29
-
37
+
30
38
  const data: FederatedServersResponse = await response.json();
31
-
39
+
32
40
  if (isCancelled) return;
33
41
 
34
42
  const initialServerState: Record<string, ServerState> = {};
35
- data.federatedServers.forEach(serverUrl => {
43
+ data.federatedServers.forEach((serverUrl) => {
36
44
  initialServerState[serverUrl] = { status: 'loading', agents: [] };
37
45
  });
38
-
46
+
39
47
  setServers(initialServerState);
40
48
  setInitialLoading(false);
41
49
 
42
50
  // Fetch agents for each server independently
43
- data.federatedServers.forEach(serverUrl => {
51
+ data.federatedServers.forEach((serverUrl) => {
44
52
  fetchAgentsForServer(serverUrl);
45
53
  });
46
-
47
54
  } catch (error) {
48
55
  console.error('Failed to load federated servers list', error);
49
56
  if (!isCancelled) setInitialLoading(false);
@@ -80,7 +87,9 @@ export function ExternalAgentsSectionClient() {
80
87
  const response = await fetch(proxyUrl);
81
88
 
82
89
  if (!response.ok) {
83
- throw new Error(`Failed to fetch agents from ${serverUrl} via proxy (Status: ${response.status})`);
90
+ throw new Error(
91
+ `Failed to fetch agents from ${serverUrl} via proxy (Status: ${response.status})`,
92
+ );
84
93
  }
85
94
 
86
95
  const data = await response.json();
@@ -134,7 +143,7 @@ export function ExternalAgentsSectionClient() {
134
143
 
135
144
  return (
136
145
  <>
137
- {serverUrls.map(serverUrl => {
146
+ {serverUrls.map((serverUrl) => {
138
147
  const state = servers[serverUrl];
139
148
  const hostname = (() => {
140
149
  try {
@@ -169,7 +178,7 @@ export function ExternalAgentsSectionClient() {
169
178
  return (
170
179
  <Section key={serverUrl} title={`Agents from ${hostname} (${state.agents.length})`}>
171
180
  {state.agents.map((agent) => (
172
- <AgentCard key={agent.url} agent={agent} href={agent.url} />
181
+ <AgentCard key={agent.url} agent={agent} href={agent.url} publicUrl={publicUrl} />
173
182
  ))}
174
183
  </Section>
175
184
  );
@@ -1,4 +1,5 @@
1
1
  import {
2
+ NEXT_PUBLIC_SITE_URL,
2
3
  NEXT_PUBLIC_VERCEL_BRANCH_URL,
3
4
  NEXT_PUBLIC_VERCEL_ENV,
4
5
  NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
@@ -24,6 +25,7 @@ import { TechInfoCard } from '../Homepage/TechInfoCard';
24
25
  export default function VercelDeploymentCard() {
25
26
  return (
26
27
  <TechInfoCard title="Vercel Deployment">
28
+ <p className="text-gray-600">NEXT_PUBLIC_SITE_URL: {NEXT_PUBLIC_SITE_URL?.href || 'undefined'}</p>
27
29
  <p className="text-gray-600">NEXT_PUBLIC_VERCEL_ENV: {NEXT_PUBLIC_VERCEL_ENV}</p>
28
30
  <p className="text-gray-600">NEXT_PUBLIC_VERCEL_TARGET_ENV: {NEXT_PUBLIC_VERCEL_TARGET_ENV}</p>
29
31
  <p className="text-gray-600">NEXT_PUBLIC_VERCEL_URL: {NEXT_PUBLIC_VERCEL_URL}</p>
@@ -1,26 +1,28 @@
1
1
  // Utility to generate content for robots.txt, security.txt, and humans.txt [DRY]
2
2
 
3
- import { NEXT_PUBLIC_SITE_URL } from '@/config';
3
+ import { $provideServer } from '@/src/tools/$provideServer';
4
4
 
5
- // Get base URL from environment or config
6
- const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
7
-
8
- export function generateRobotsTxt(): string {
9
- return ['User-agent: *', `Sitemap: ${baseUrl}sitemap.xml`, ''].join('\n');
5
+ export async function generateRobotsTxt(): Promise<string> {
6
+ const { publicUrl } = await $provideServer();
7
+ return ['User-agent: *', `Sitemap: ${publicUrl.href}sitemap.xml`, ''].join('\n');
10
8
  }
11
9
 
12
- export function generateSecurityTxt(): string {
10
+ export async function generateSecurityTxt(): Promise<string> {
11
+ const { publicUrl } = await $provideServer();
13
12
  // See https://securitytxt.org/ for more fields
14
13
  return [
15
14
  `Contact: mailto:security@ptbk.io`,
16
15
  `Expires: ${new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]}`,
17
- `Canonical: ${baseUrl}security.txt`,
16
+ `Canonical: ${publicUrl.href}security.txt`,
18
17
  '',
19
18
  ].join('\n');
20
19
  }
21
20
 
22
- export function generateHumansTxt(): string {
23
- return ['/* TEAM */', 'Developer: Promptbook Team', `Site: https://ptbk.io`, `Instance: ${baseUrl}`].join('\n');
21
+ export async function generateHumansTxt(): Promise<string> {
22
+ const { publicUrl } = await $provideServer();
23
+ return ['/* TEAM */', 'Developer: Promptbook Team', `Site: https://ptbk.io`, `Instance: ${publicUrl.href}`].join(
24
+ '\n',
25
+ );
24
26
  }
25
27
 
26
28
  /**
@@ -0,0 +1,29 @@
1
+ import { locateChrome } from 'locate-app';
2
+ import { join } from 'path';
3
+ import { BrowserContext, chromium } from 'playwright';
4
+
5
+ /**
6
+ * Cache of browser instance
7
+ *
8
+ * @private internal cache for `$provideBrowserForServer`
9
+ */
10
+ let browserInstance: BrowserContext | null = null;
11
+
12
+ /**
13
+ * @@@
14
+ */
15
+ export async function $provideBrowserForServer(): Promise<BrowserContext> {
16
+ if (browserInstance === null /* || !browserInstance.isConnected() */) {
17
+ console.log('Launching new browser instance...');
18
+ browserInstance = await chromium.launchPersistentContext(
19
+ join(process.cwd(), '.promptbook', 'puppeteer', 'user-data'),
20
+ {
21
+ executablePath: await locateChrome(),
22
+ headless: false,
23
+ // defaultViewport: null,
24
+ // downloadsPath
25
+ },
26
+ );
27
+ }
28
+ return browserInstance;
29
+ }
@@ -11,7 +11,7 @@ import { IIFilesStorageWithCdn } from '../utils/cdn/interfaces/IFilesStorage';
11
11
  let cdn: IIFilesStorageWithCdn | null = null;
12
12
 
13
13
  /**
14
- * [๐Ÿฑโ€๐Ÿš€]
14
+ * @@@
15
15
  */
16
16
  export function $provideCdnForServer(): IIFilesStorageWithCdn {
17
17
  if (!cdn) {
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-7';
50
+ const PROMPTBOOK_ENGINE_VERSION = '0.104.0-8';
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
@@ -1,4 +1,4 @@
1
- import type { string_agent_name, string_agent_permanent_id, string_url_image } from '../../types/typeAliases';
1
+ import type { string_agent_name, string_agent_permanent_id, string_url, string_url_image } from '../../types/typeAliases';
2
2
  /**
3
3
  * Generates an image for the agent to use as profile image
4
4
  *
@@ -7,7 +7,7 @@ import type { string_agent_name, string_agent_permanent_id, string_url_image } f
7
7
  *
8
8
  * @public exported from `@promptbook/core`
9
9
  */
10
- export declare function generatePlaceholderAgentProfileImageUrl(agentIdOrName: string_agent_permanent_id | string_agent_name, agentsServerUrl?: URL): string_url_image;
10
+ export declare function generatePlaceholderAgentProfileImageUrl(agentIdOrName: string_agent_permanent_id | string_agent_name, agentsServerUrl?: URL | string_url): string_url_image;
11
11
  /**
12
12
  * TODO: [๐Ÿคน] Figure out best placeholder image generator https://i.pravatar.cc/1000?u=568
13
13
  */
@@ -1,10 +1,11 @@
1
+ import { string_color, string_data_url, string_url_image } from '../../../types/typeAliases';
1
2
  import { Color } from '../Color';
2
3
  /**
3
4
  * Makes data url from color
4
5
  *
5
6
  * @public exported from `@promptbook/color`
6
7
  */
7
- export declare function colorToDataUrl(color: Color): string;
8
+ export declare function colorToDataUrl(color: Color | string_color): string_data_url & string_url_image;
8
9
  /**
9
10
  * TODO: Make as functions NOT const
10
11
  */
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
15
15
  export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
16
16
  /**
17
17
  * Represents the version string of the Promptbook engine.
18
- * It follows semantic versioning (e.g., `0.104.0-6`).
18
+ * It follows semantic versioning (e.g., `0.104.0-7`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/cli",
3
- "version": "0.104.0-7",
3
+ "version": "0.104.0-8",
4
4
  "description": "Promptbook: Turn your company's scattered knowledge into AI ready books",
5
5
  "private": false,
6
6
  "sideEffects": false,
package/umd/index.umd.js CHANGED
@@ -56,7 +56,7 @@
56
56
  * @generated
57
57
  * @see https://github.com/webgptorg/promptbook
58
58
  */
59
- const PROMPTBOOK_ENGINE_VERSION = '0.104.0-7';
59
+ const PROMPTBOOK_ENGINE_VERSION = '0.104.0-8';
60
60
  /**
61
61
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
62
62
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name