@promptbook/cli 0.104.0-0 → 0.104.0-2
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/next.config.ts +2 -2
- package/apps/agents-server/package.json +6 -1
- package/apps/agents-server/public/fonts/OpenMoji-color-cbdt.woff2 +0 -0
- package/apps/agents-server/scripts/generate-reserved-paths/generate-reserved-paths.ts +50 -0
- package/apps/agents-server/scripts/generate-reserved-paths/tsconfig.json +19 -0
- package/apps/agents-server/src/app/AddAgentButton.tsx +4 -3
- package/apps/agents-server/src/app/actions.ts +17 -5
- package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +15 -11
- package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +51 -7
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +32 -2
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +2 -0
- package/apps/agents-server/src/app/agents/[agentName]/_utils.ts +18 -0
- package/apps/agents-server/src/app/agents/[agentName]/agentLinks.tsx +8 -8
- package/apps/agents-server/src/app/agents/[agentName]/api/agents/route.ts +17 -26
- package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +17 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +1 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/voice/route.ts +1 -1
- package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +20 -16
- package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +15 -2
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx +15 -2
- package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +12 -0
- package/apps/agents-server/src/app/agents/[agentName]/code/api/route.ts +66 -0
- package/apps/agents-server/src/app/agents/[agentName]/code/page.tsx +211 -0
- package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +5 -0
- package/apps/agents-server/src/app/agents/[agentName]/history/actions.ts +2 -2
- package/apps/agents-server/src/app/agents/[agentName]/integration/WebsiteIntegrationTabs.tsx +26 -0
- package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +23 -6
- package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +2 -2
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +12 -6
- package/apps/agents-server/src/app/agents/[agentName]/system-message/page.tsx +87 -0
- package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +35 -18
- package/apps/agents-server/src/app/api/admin-email/route.ts +12 -0
- package/apps/agents-server/src/app/api/agents/[agentName]/restore/route.ts +19 -0
- package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +42 -0
- package/apps/agents-server/src/app/api/agents/route.ts +29 -4
- package/apps/agents-server/src/app/api/docs/book.md/route.ts +58 -0
- package/apps/agents-server/src/app/api/embed.js/route.ts +87 -67
- package/apps/agents-server/src/app/api/federated-agents/route.ts +12 -0
- package/apps/agents-server/src/app/api/images/[filename]/route.ts +107 -0
- package/apps/agents-server/src/app/api/upload/route.ts +119 -45
- package/apps/agents-server/src/app/docs/[docId]/page.tsx +2 -3
- package/apps/agents-server/src/app/docs/page.tsx +12 -12
- package/apps/agents-server/src/app/embed/layout.tsx +31 -0
- package/apps/agents-server/src/app/embed/page.tsx +22 -9
- package/apps/agents-server/src/app/globals.css +140 -33
- package/apps/agents-server/src/app/layout.tsx +27 -22
- package/apps/agents-server/src/app/page.tsx +50 -4
- package/apps/agents-server/src/app/recycle-bin/actions.ts +20 -14
- package/apps/agents-server/src/app/recycle-bin/page.tsx +25 -41
- package/apps/agents-server/src/app/sitemap.xml/route.ts +6 -3
- package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +6 -97
- package/apps/agents-server/src/components/AgentProfile/useAgentBackground.ts +97 -0
- package/apps/agents-server/src/components/DeletedAgentBanner.tsx +26 -0
- package/apps/agents-server/src/components/DocsToolbar/DocsToolbar.tsx +38 -0
- package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +11 -9
- package/apps/agents-server/src/components/Footer/Footer.tsx +5 -5
- package/apps/agents-server/src/components/ForgottenPasswordDialog/ForgottenPasswordDialog.tsx +61 -0
- package/apps/agents-server/src/components/Header/Header.tsx +79 -35
- package/apps/agents-server/src/components/Homepage/AgentCard.tsx +85 -20
- package/apps/agents-server/src/components/Homepage/AgentsList.tsx +72 -12
- package/apps/agents-server/src/components/Homepage/DeletedAgentsList.tsx +50 -0
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +3 -2
- package/apps/agents-server/src/components/LoginForm/LoginForm.tsx +50 -1
- package/apps/agents-server/src/components/NotFoundPage/NotFoundPage.tsx +7 -2
- package/apps/agents-server/src/components/OpenMojiIcon/OpenMojiIcon.tsx +16 -7
- package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -4
- package/apps/agents-server/src/components/RegisterUserDialog/RegisterUserDialog.tsx +61 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +19 -1
- package/apps/agents-server/src/database/migrations/2025-12-0240-agent-public-id.sql +3 -0
- package/apps/agents-server/src/database/migrations/2025-12-0360-agent-deleted-at.sql +1 -0
- package/apps/agents-server/src/database/migrations/2025-12-0370-image-table.sql +19 -0
- package/apps/agents-server/src/database/migrations/2025-12-0380-agent-visibility.sql +1 -0
- package/apps/agents-server/src/database/migrations/2025-12-0390-upload-tracking.sql +20 -0
- package/apps/agents-server/src/database/migrations/2025-12-0401-file-upload-status.sql +13 -0
- package/apps/agents-server/src/database/migrations/2025-12-0640-openai-assistant-cache.sql +12 -0
- package/apps/agents-server/src/database/schema.ts +109 -0
- package/apps/agents-server/src/generated/reservedPaths.ts +27 -0
- package/apps/agents-server/src/middleware.ts +7 -20
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +6 -1
- package/apps/agents-server/src/utils/cdn/classes/TrackedFilesStorage.ts +57 -0
- package/apps/agents-server/src/utils/cdn/classes/VercelBlobStorage.ts +4 -0
- package/apps/agents-server/src/utils/cdn/interfaces/IFilesStorage.ts +18 -0
- package/apps/agents-server/src/utils/getUserIdFromRequest.ts +33 -0
- package/apps/agents-server/src/utils/handleChatCompletion.ts +60 -4
- package/apps/agents-server/src/utils/normalization/filenameToPrompt.ts +21 -0
- package/apps/agents-server/src/utils/validateApiKey.ts +2 -1
- package/esm/index.es.js +140 -27
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/types.index.d.ts +6 -2
- package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +6 -1
- package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +5 -1
- package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +5 -0
- package/esm/typings/src/book-components/Chat/CodeBlock/CodeBlock.d.ts +13 -0
- package/esm/typings/src/book-components/Chat/MarkdownContent/MarkdownContent.d.ts +1 -0
- package/esm/typings/src/book-components/_common/Dropdown/Dropdown.d.ts +2 -2
- package/esm/typings/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +56 -0
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +13 -7
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +6 -0
- package/esm/typings/src/commitments/DICTIONARY/DICTIONARY.d.ts +46 -0
- package/esm/typings/src/commitments/index.d.ts +2 -1
- package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +1 -1
- package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +1 -1
- package/esm/typings/src/types/typeAliases.d.ts +12 -0
- package/esm/typings/src/utils/environment/$detectRuntimeEnvironment.d.ts +4 -4
- package/esm/typings/src/utils/environment/$isRunningInBrowser.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInJest.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInNode.d.ts +1 -1
- package/esm/typings/src/utils/environment/$isRunningInWebWorker.d.ts +1 -1
- package/esm/typings/src/utils/markdown/extractAllBlocksFromMarkdown.d.ts +2 -2
- package/esm/typings/src/utils/markdown/extractOneBlockFromMarkdown.d.ts +2 -2
- package/esm/typings/src/utils/random/$randomBase58.d.ts +12 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +146 -33
- package/umd/index.umd.js.map +1 -1
- package/apps/agents-server/package-lock.json +0 -27
- package/apps/agents-server/public/fonts/download-font.js +0 -22
- package/apps/agents-server/src/components/PrintButton/PrintButton.tsx +0 -18
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
4
|
+
import { ArrowLeftIcon, FileTextIcon } from 'lucide-react';
|
|
5
|
+
import { headers } from 'next/headers';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import { notFound } from 'next/navigation';
|
|
8
|
+
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
9
|
+
import { getAgentName, getAgentProfile } from '../_utils';
|
|
10
|
+
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
11
|
+
|
|
12
|
+
export const generateMetadata = generateAgentMetadata;
|
|
13
|
+
|
|
14
|
+
export default async function AgentSystemMessagePage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
15
|
+
$sideEffect(headers());
|
|
16
|
+
const agentName = await getAgentName(params);
|
|
17
|
+
|
|
18
|
+
let agentProfile;
|
|
19
|
+
let agentSource;
|
|
20
|
+
try {
|
|
21
|
+
agentProfile = await getAgentProfile(agentName);
|
|
22
|
+
const collection = await $provideAgentCollectionForServer();
|
|
23
|
+
agentSource = await collection.getAgentSource(agentName);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (
|
|
26
|
+
error instanceof Error &&
|
|
27
|
+
(error.message.includes('Cannot coerce the result to a single JSON object') ||
|
|
28
|
+
error.message.includes('JSON object requested, multiple (or no) results returned'))
|
|
29
|
+
) {
|
|
30
|
+
notFound();
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// For now, we'll display the agent source as the system message
|
|
36
|
+
// TODO: [🧠] This might need to be the actual generated system message from the Agent class
|
|
37
|
+
const systemMessage = agentSource || 'No system message available';
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="min-h-screen p-6 md:p-12 flex flex-col items-center bg-gray-50">
|
|
41
|
+
<div className="w-full max-w-4xl bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
|
42
|
+
{/* Header */}
|
|
43
|
+
<div className="p-6 border-b border-gray-200 flex items-center gap-4">
|
|
44
|
+
{agentProfile.meta.image && (
|
|
45
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
46
|
+
<img
|
|
47
|
+
src={agentProfile.meta.image as string}
|
|
48
|
+
alt={agentProfile.meta.fullname || agentName}
|
|
49
|
+
className="w-16 h-16 rounded-full object-cover border-2 border-gray-200"
|
|
50
|
+
/>
|
|
51
|
+
)}
|
|
52
|
+
<div className="flex-1">
|
|
53
|
+
<h1 className="text-2xl font-bold text-gray-900">{agentProfile.meta.fullname || agentName}</h1>
|
|
54
|
+
<p className="text-gray-500 flex items-center gap-2">
|
|
55
|
+
<FileTextIcon className="w-4 h-4" />
|
|
56
|
+
System Message
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
<Link
|
|
60
|
+
href={`/agents/${encodeURIComponent(agentName)}`}
|
|
61
|
+
className="p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-full transition-colors"
|
|
62
|
+
title="Back to Agent"
|
|
63
|
+
>
|
|
64
|
+
<ArrowLeftIcon className="w-6 h-6" />
|
|
65
|
+
</Link>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div className="p-6">
|
|
69
|
+
<div className="bg-gray-50 rounded-lg p-4 border border-gray-200">
|
|
70
|
+
<h2 className="text-lg font-semibold text-gray-900 mb-3">Generated System Message</h2>
|
|
71
|
+
<pre className="text-sm text-gray-700 whitespace-pre-wrap font-mono bg-white p-4 rounded border border-gray-200 overflow-x-auto">
|
|
72
|
+
{systemMessage}
|
|
73
|
+
</pre>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className="mt-6 bg-blue-50 rounded-lg p-4 border border-blue-200">
|
|
77
|
+
<h3 className="text-md font-semibold text-blue-900 mb-2">Model Requirements</h3>
|
|
78
|
+
<div className="text-sm text-blue-800">
|
|
79
|
+
<p><strong>Model Variant:</strong> CHAT</p>
|
|
80
|
+
{/* TODO: [🧠] Add more model requirements if available */}
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
@@ -7,8 +7,9 @@ import { parseAgentSource } from '@promptbook-local/core';
|
|
|
7
7
|
import { headers } from 'next/headers';
|
|
8
8
|
import spaceTrim from 'spacetrim';
|
|
9
9
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
10
|
-
import {
|
|
10
|
+
import { just } from '../../../../../../../src/utils/organization/just';
|
|
11
11
|
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
12
|
+
import { WebsiteIntegrationTabs } from '../integration/WebsiteIntegrationTabs';
|
|
12
13
|
|
|
13
14
|
export const generateMetadata = generateAgentMetadata;
|
|
14
15
|
|
|
@@ -24,20 +25,31 @@ export default async function WebsiteIntegrationAgentPage({ params }: { params:
|
|
|
24
25
|
const { publicUrl } = await $provideServer();
|
|
25
26
|
const agentUrl = `${publicUrl.href}agents/${encodeURIComponent(agentName)}`;
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
+
const reactCode = spaceTrim(
|
|
28
29
|
(block) => `
|
|
29
|
-
|
|
30
|
-
import { PromptbookAgent } from '@promptbook/components';
|
|
30
|
+
import { PromptbookAgentIntegration } from '@promptbook/components';
|
|
31
31
|
|
|
32
32
|
export function YourComponent() {
|
|
33
33
|
return(
|
|
34
|
-
<
|
|
34
|
+
<PromptbookAgentIntegration
|
|
35
35
|
agentUrl="${agentUrl}"
|
|
36
36
|
meta={${block(JSON.stringify({ fullname, color, image, ...restMeta }, null, 4))}}
|
|
37
37
|
/>
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
`,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// HTML Integration Code - use single quotes for meta attribute to allow JSON with double quotes inside
|
|
44
|
+
const metaJsonString = JSON.stringify({ fullname, color, image, ...restMeta }, null, 4);
|
|
45
|
+
const htmlCode = spaceTrim(
|
|
46
|
+
(block) => `
|
|
47
|
+
<script src="${publicUrl.href}api/embed.js" async defer></script>
|
|
48
|
+
|
|
49
|
+
<promptbook-agent-integration
|
|
50
|
+
agent-url="${agentUrl}"
|
|
51
|
+
meta='${block(metaJsonString)}'
|
|
52
|
+
/>
|
|
41
53
|
`,
|
|
42
54
|
);
|
|
43
55
|
|
|
@@ -49,19 +61,24 @@ export default async function WebsiteIntegrationAgentPage({ params }: { params:
|
|
|
49
61
|
React application using the <code>{'<PromptbookAgent />'}</code> component.
|
|
50
62
|
</p>
|
|
51
63
|
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
<WebsiteIntegrationTabs reactCode={reactCode} htmlCode={htmlCode} />
|
|
65
|
+
{just(false) && (
|
|
66
|
+
<PromptbookAgentIntegration
|
|
67
|
+
// formfactor="profile"
|
|
68
|
+
agentUrl={agentUrl}
|
|
69
|
+
meta={meta}
|
|
70
|
+
style={
|
|
71
|
+
{
|
|
72
|
+
// width: '400px',
|
|
73
|
+
// height: '600px',
|
|
74
|
+
// outline: `2px solid red`
|
|
75
|
+
}
|
|
62
76
|
}
|
|
63
|
-
|
|
64
|
-
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
{htmlCode}
|
|
80
|
+
{just(true) && <div dangerouslySetInnerHTML={{ __html: htmlCode }} />}
|
|
81
|
+
{just(true) && <div dangerouslySetInnerHTML={{ __html: `<h1>Test</h1>` }} />}
|
|
65
82
|
</main>
|
|
66
83
|
);
|
|
67
84
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getMetadata } from '../../../database/getMetadata';
|
|
2
|
+
import { NextResponse } from 'next/server';
|
|
3
|
+
|
|
4
|
+
export async function GET() {
|
|
5
|
+
try {
|
|
6
|
+
const adminEmail = await getMetadata('ADMIN_EMAIL');
|
|
7
|
+
return NextResponse.json({ adminEmail });
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error('Failed to get admin email:', error);
|
|
10
|
+
return NextResponse.json({ adminEmail: 'support@ptbk.io' }, { status: 500 });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// POST /api/agents/[agentName]/restore - restore deleted agent
|
|
2
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
3
|
+
import { TODO_any } from '@promptbook-local/types';
|
|
4
|
+
import { NextResponse } from 'next/server';
|
|
5
|
+
|
|
6
|
+
export async function POST(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
7
|
+
const { agentName } = await params;
|
|
8
|
+
const collection = await $provideAgentCollectionForServer();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
await collection.restoreAgent(agentName);
|
|
12
|
+
return NextResponse.json({ success: true });
|
|
13
|
+
} catch (error) {
|
|
14
|
+
return NextResponse.json(
|
|
15
|
+
{ success: false, error: (error as TODO_any)?.message || 'Failed to restore agent' },
|
|
16
|
+
{ status: 500 },
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,8 +1,50 @@
|
|
|
1
1
|
// DELETE /api/agents/[agentName]
|
|
2
|
+
// PATCH /api/agents/[agentName] - update agent visibility
|
|
3
|
+
// POST /api/agents/[agentName]/restore - restore deleted agent
|
|
4
|
+
import { $getTableName } from '@/src/database/$getTableName';
|
|
5
|
+
import { $provideSupabaseForServer } from '@/src/database/$provideSupabaseForServer';
|
|
2
6
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
7
|
+
import { $provideServer } from '@/src/tools/$provideServer';
|
|
3
8
|
import { TODO_any } from '@promptbook-local/types';
|
|
4
9
|
import { NextResponse } from 'next/server';
|
|
5
10
|
|
|
11
|
+
export async function PATCH(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
12
|
+
const { agentName } = await params;
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const body = await request.json();
|
|
16
|
+
const { visibility }: { visibility: 'PUBLIC' | 'PRIVATE' } = body;
|
|
17
|
+
|
|
18
|
+
if (!visibility || !['PUBLIC', 'PRIVATE'].includes(visibility)) {
|
|
19
|
+
return NextResponse.json(
|
|
20
|
+
{ success: false, error: 'Invalid visibility value. Must be PUBLIC or PRIVATE.' },
|
|
21
|
+
{ status: 400 },
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const supabase = $provideSupabaseForServer();
|
|
26
|
+
const { tablePrefix } = await $provideServer();
|
|
27
|
+
|
|
28
|
+
const updateResult = await supabase
|
|
29
|
+
.from(await $getTableName(`Agent`))
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
.update({ visibility } as any)
|
|
32
|
+
.or(`agentName.eq.${agentName},permanentId.eq.${agentName}`)
|
|
33
|
+
.is('deletedAt', null);
|
|
34
|
+
|
|
35
|
+
if (updateResult.error) {
|
|
36
|
+
return NextResponse.json({ success: false, error: updateResult.error.message }, { status: 500 });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return NextResponse.json({ success: true });
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return NextResponse.json(
|
|
42
|
+
{ success: false, error: (error as TODO_any)?.message || 'Failed to update agent visibility' },
|
|
43
|
+
{ status: 500 },
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
6
48
|
export async function DELETE(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
7
49
|
const { agentName } = await params;
|
|
8
50
|
const collection = await $provideAgentCollectionForServer();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { $getTableName } from '@/src/database/$getTableName';
|
|
1
2
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
2
3
|
import { NextResponse } from 'next/server';
|
|
4
|
+
import { $provideSupabaseForServer } from '../../../database/$provideSupabaseForServer';
|
|
3
5
|
import { $provideAgentCollectionForServer } from '../../../tools/$provideAgentCollectionForServer';
|
|
4
6
|
import { getFederatedServersFromMetadata } from '../../../utils/getFederatedServersFromMetadata';
|
|
5
7
|
|
|
@@ -8,13 +10,36 @@ export const dynamic = 'force-dynamic';
|
|
|
8
10
|
export async function GET() {
|
|
9
11
|
try {
|
|
10
12
|
const collection = await $provideAgentCollectionForServer();
|
|
11
|
-
const
|
|
13
|
+
const allAgents = await collection.listAgents();
|
|
12
14
|
const federatedServers = await getFederatedServersFromMetadata();
|
|
13
|
-
const { publicUrl } = await $provideServer();
|
|
15
|
+
const { publicUrl, tablePrefix } = await $provideServer();
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
// Filter to only include PUBLIC agents for federated API
|
|
18
|
+
const supabase = $provideSupabaseForServer();
|
|
19
|
+
const visibilityResult = await supabase
|
|
20
|
+
.from(await $getTableName(`Agent`))
|
|
21
|
+
.select('agentName, visibility')
|
|
22
|
+
.is('deletedAt', null);
|
|
23
|
+
|
|
24
|
+
let publicAgents = allAgents;
|
|
25
|
+
if (!visibilityResult.error) {
|
|
26
|
+
const visibilityMap = new Map(
|
|
27
|
+
visibilityResult.data.map((item: { agentName: string; visibility: 'PUBLIC' | 'PRIVATE' }) => [
|
|
28
|
+
item.agentName,
|
|
29
|
+
item.visibility,
|
|
30
|
+
]),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// Only include PUBLIC agents in federated API
|
|
34
|
+
publicAgents = allAgents.filter((agent) => {
|
|
35
|
+
const visibility = visibilityMap.get(agent.agentName);
|
|
36
|
+
return visibility === 'PUBLIC';
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const agentsWithUrl = publicAgents.map((agent) => ({
|
|
16
41
|
...agent,
|
|
17
|
-
url: `${publicUrl.href}agents/${encodeURIComponent(agent.agentName)}`,
|
|
42
|
+
url: `${publicUrl.href}agents/${encodeURIComponent(agent.permanentId || agent.agentName)}`,
|
|
18
43
|
}));
|
|
19
44
|
|
|
20
45
|
const response = NextResponse.json({
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import spaceTrim from 'spacetrim';
|
|
3
|
+
import { getGroupedCommitmentDefinitions } from '../../../../../../../src/commitments';
|
|
4
|
+
|
|
5
|
+
export const dynamic = 'force-static';
|
|
6
|
+
|
|
7
|
+
export async function GET(request: NextRequest) {
|
|
8
|
+
const groupedCommitments = getGroupedCommitmentDefinitions();
|
|
9
|
+
|
|
10
|
+
const content = spaceTrim(
|
|
11
|
+
(block) => `
|
|
12
|
+
# Promptbook Documentation
|
|
13
|
+
|
|
14
|
+
Promptbook is a language for defining AI agents. It is based on Markdown and uses a set of commitments to define the behavior of the agent.
|
|
15
|
+
|
|
16
|
+
## Commitments
|
|
17
|
+
|
|
18
|
+
The following commands (commitments) are available in Promptbook:
|
|
19
|
+
|
|
20
|
+
${block(
|
|
21
|
+
groupedCommitments
|
|
22
|
+
.map(({ primary, aliases }) => {
|
|
23
|
+
const title = primary.type;
|
|
24
|
+
const description = primary.description;
|
|
25
|
+
const documentation = primary.documentation;
|
|
26
|
+
const aliasList = aliases.length > 0 ? `**Aliases:** ${aliases.join(', ')}` : '';
|
|
27
|
+
|
|
28
|
+
return spaceTrim(
|
|
29
|
+
(block) => `
|
|
30
|
+
### ${title}
|
|
31
|
+
|
|
32
|
+
${description}
|
|
33
|
+
|
|
34
|
+
${aliasList}
|
|
35
|
+
|
|
36
|
+
#### Usage
|
|
37
|
+
|
|
38
|
+
${block(getSafeCodeBlock(documentation))}
|
|
39
|
+
`,
|
|
40
|
+
);
|
|
41
|
+
})
|
|
42
|
+
.join('\n\n'),
|
|
43
|
+
)}
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return new NextResponse(content, {
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'text/markdown; charset=utf-8',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getSafeCodeBlock(content: string, lang = 'markdown'): string {
|
|
55
|
+
const maxBackticks = Math.max(0, ...(content.match(/`+/g) || []).map((m) => m.length));
|
|
56
|
+
const fence = '`'.repeat(Math.max(3, maxBackticks + 1));
|
|
57
|
+
return `${fence}${lang}\n${content}\n${fence}`;
|
|
58
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { spaceTrim } from '@promptbook-local/utils';
|
|
1
2
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
3
|
|
|
3
4
|
export async function GET(request: NextRequest) {
|
|
@@ -5,84 +6,103 @@ export async function GET(request: NextRequest) {
|
|
|
5
6
|
const host = request.nextUrl.host;
|
|
6
7
|
const baseUrl = `${protocol}//${host}`;
|
|
7
8
|
|
|
8
|
-
const script = `
|
|
9
|
-
(
|
|
10
|
-
if (customElements.get('promptbook-agent')) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
9
|
+
const script = spaceTrim(`
|
|
10
|
+
console.info('[🔌] Promptbook integration script from ${baseUrl}');
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
12
|
+
(function() {
|
|
13
|
+
if (customElements.get('promptbook-agent-integration')) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
class PromptbookAgentIntegrationElement extends HTMLElement {
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
console.info('[🔌] Initializing <promptbook-agent-integration/>',this);
|
|
21
|
+
this.iframe = null;
|
|
22
|
+
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
24
|
+
static get observedAttributes() {
|
|
25
|
+
return ['agent-url', 'meta'];
|
|
26
|
+
}
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
connectedCallback() {
|
|
29
|
+
this.render();
|
|
30
|
+
window.addEventListener('message', this.handleMessage.bind(this));
|
|
31
|
+
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
33
|
+
disconnectedCallback() {
|
|
34
|
+
window.removeEventListener('message', this.handleMessage.bind(this));
|
|
35
|
+
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.iframe.style.height = '650px';
|
|
44
|
-
this.iframe.style.maxHeight = '90vh';
|
|
45
|
-
this.iframe.style.maxWidth = '90vw';
|
|
46
|
-
this.iframe.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
|
47
|
-
this.iframe.style.borderRadius = '12px';
|
|
48
|
-
} else {
|
|
49
|
-
this.iframe.style.width = '60px';
|
|
50
|
-
this.iframe.style.height = '60px';
|
|
51
|
-
this.iframe.style.boxShadow = 'none';
|
|
52
|
-
this.iframe.style.borderRadius = '0';
|
|
37
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
38
|
+
if ((name === 'agent-url' || name === 'meta') && oldValue !== newValue) {
|
|
39
|
+
this.render();
|
|
40
|
+
}
|
|
53
41
|
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
42
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
43
|
+
handleMessage(event) {
|
|
44
|
+
if (event.data && event.data.type === 'PROMPTBOOK_AGENT_RESIZE') {
|
|
45
|
+
if (event.data.isOpen) {
|
|
46
|
+
// Match PromptbookAgentSeamlessIntegration.module.css dimensions
|
|
47
|
+
// Window is 380x600 + 20px padding on each side
|
|
48
|
+
this.iframe.style.width = '420px';
|
|
49
|
+
this.iframe.style.height = '640px';
|
|
50
|
+
this.iframe.style.maxHeight = 'calc(80vh + 40px)';
|
|
51
|
+
this.iframe.style.maxWidth = 'calc(100vw - 20px)';
|
|
52
|
+
} else {
|
|
53
|
+
// Closed state - button area with padding and shadow space
|
|
54
|
+
// Button is ~140px wide + 20px right margin + shadow space
|
|
55
|
+
this.iframe.style.width = '180px';
|
|
56
|
+
this.iframe.style.height = '100px';
|
|
57
|
+
this.iframe.style.maxHeight = 'none';
|
|
58
|
+
this.iframe.style.maxWidth = 'none';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.iframe.style.border = 'none';
|
|
65
|
-
this.iframe.style.position = 'fixed';
|
|
66
|
-
this.iframe.style.bottom = '20px';
|
|
67
|
-
this.iframe.style.right = '20px';
|
|
68
|
-
this.iframe.style.width = '60px';
|
|
69
|
-
this.iframe.style.height = '60px';
|
|
70
|
-
this.iframe.style.zIndex = '2147483647'; // Max z-index
|
|
71
|
-
this.iframe.style.transition = 'width 0.3s ease, height 0.3s ease';
|
|
72
|
-
this.iframe.style.backgroundColor = 'transparent';
|
|
73
|
-
this.iframe.setAttribute('allow', 'microphone'); // Allow microphone if needed for voice
|
|
74
|
-
this.shadowRoot.appendChild(this.iframe);
|
|
75
|
-
}
|
|
63
|
+
render() {
|
|
64
|
+
const agentUrl = this.getAttribute('agent-url');
|
|
65
|
+
if (!agentUrl) return;
|
|
76
66
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
if (!this.iframe) {
|
|
68
|
+
this.attachShadow({ mode: 'open' });
|
|
69
|
+
this.iframe = document.createElement('iframe');
|
|
70
|
+
this.iframe.style.border = 'none';
|
|
71
|
+
this.iframe.style.position = 'fixed';
|
|
72
|
+
this.iframe.style.bottom = '0';
|
|
73
|
+
this.iframe.style.right = '0';
|
|
74
|
+
// Initial size for the closed button state (with padding and shadow space)
|
|
75
|
+
this.iframe.style.width = '180px';
|
|
76
|
+
this.iframe.style.height = '100px';
|
|
77
|
+
this.iframe.style.zIndex = '2147483647'; // Max z-index
|
|
78
|
+
this.iframe.style.transition = 'width 0.3s ease, height 0.3s ease';
|
|
79
|
+
this.iframe.style.backgroundColor = 'transparent';
|
|
80
|
+
this.iframe.setAttribute('allow', 'microphone'); // Allow microphone if needed for voice
|
|
81
|
+
this.shadowRoot.appendChild(this.iframe);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Construct embed URL pointing to the Next.js page we created
|
|
85
|
+
let embedUrl = '${baseUrl}/embed?agentUrl=' + encodeURIComponent(agentUrl);
|
|
86
|
+
|
|
87
|
+
// Add meta parameter if provided
|
|
88
|
+
const metaAttr = this.getAttribute('meta');
|
|
89
|
+
if (metaAttr) {
|
|
90
|
+
try {
|
|
91
|
+
// Validate that it's valid JSON
|
|
92
|
+
JSON.parse(metaAttr);
|
|
93
|
+
embedUrl += '&meta=' + encodeURIComponent(metaAttr);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.error('[🔌] Invalid meta JSON:', e);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
this.iframe.src = embedUrl;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
})();
|
|
85
|
-
|
|
103
|
+
customElements.define('promptbook-agent-integration', PromptbookAgentIntegrationElement);
|
|
104
|
+
})();
|
|
105
|
+
`);
|
|
86
106
|
|
|
87
107
|
return new NextResponse(script, {
|
|
88
108
|
headers: {
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { getFederatedServersFromMetadata } from '../../../utils/getFederatedServersFromMetadata';
|
|
3
|
+
import { getMetadata } from '../../../database/getMetadata';
|
|
4
|
+
import { getCurrentUser } from '../../../utils/getCurrentUser';
|
|
3
5
|
|
|
4
6
|
export const dynamic = 'force-dynamic';
|
|
5
7
|
|
|
6
8
|
export async function GET() {
|
|
7
9
|
try {
|
|
10
|
+
const currentUser = await getCurrentUser();
|
|
11
|
+
const showFederatedServersPublicly = ((await getMetadata('SHOW_FEDERATED_SERVERS_PUBLICLY')) || 'false') === 'true';
|
|
12
|
+
|
|
13
|
+
// Only show federated servers if user is authenticated or if SHOW_FEDERATED_SERVERS_PUBLICLY is true
|
|
14
|
+
if (!currentUser && !showFederatedServersPublicly) {
|
|
15
|
+
return NextResponse.json({
|
|
16
|
+
federatedServers: [],
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
8
20
|
const federatedServers = await getFederatedServersFromMetadata();
|
|
9
21
|
|
|
10
22
|
return NextResponse.json({
|