@promptbook/cli 0.103.0-48 → 0.103.0-50
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/README.md +1 -1
- package/apps/agents-server/TODO.txt +6 -5
- package/apps/agents-server/config.ts +130 -0
- package/apps/agents-server/next.config.ts +1 -1
- package/apps/agents-server/public/fonts/OpenMoji-black-glyf.woff2 +0 -0
- package/apps/agents-server/public/fonts/download-font.js +22 -0
- package/apps/agents-server/src/app/[agentName]/[...rest]/page.tsx +11 -0
- package/apps/agents-server/src/app/[agentName]/page.tsx +1 -0
- package/apps/agents-server/src/app/actions.ts +37 -2
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +68 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentQrCode.tsx +55 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentUrlCopy.tsx +4 -5
- package/apps/agents-server/src/app/agents/[agentName]/CopyField.tsx +44 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +8 -8
- package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +121 -25
- package/apps/agents-server/src/app/agents/[agentName]/api/feedback/route.ts +54 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/route.ts +6 -6
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/systemMessage/route.ts +3 -3
- package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +29 -10
- package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +4 -5
- package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +9 -2
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/AgentBookAndChat.tsx +23 -0
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/{AgentBookAndChatComponent.tsx → AgentBookAndChatComponent.tsx.todo} +4 -4
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx +28 -17
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx.todo +21 -0
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentChatWrapper.tsx +34 -4
- package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +4 -1
- package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +42 -0
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +117 -106
- package/apps/agents-server/src/app/agents/page.tsx +1 -1
- package/apps/agents-server/src/app/api/agents/route.ts +34 -0
- package/apps/agents-server/src/app/api/auth/login/route.ts +65 -0
- package/apps/agents-server/src/app/api/auth/logout/route.ts +7 -0
- package/apps/agents-server/src/app/api/metadata/route.ts +116 -0
- package/apps/agents-server/src/app/api/upload/route.ts +7 -3
- package/apps/agents-server/src/app/api/users/[username]/route.ts +75 -0
- package/apps/agents-server/src/app/api/users/route.ts +71 -0
- package/apps/agents-server/src/app/globals.css +35 -1
- package/apps/agents-server/src/app/layout.tsx +43 -23
- package/apps/agents-server/src/app/metadata/MetadataClient.tsx +271 -0
- package/apps/agents-server/src/app/metadata/page.tsx +13 -0
- package/apps/agents-server/src/app/not-found.tsx +5 -0
- package/apps/agents-server/src/app/page.tsx +117 -46
- package/apps/agents-server/src/components/Auth/AuthControls.tsx +123 -0
- package/apps/agents-server/src/components/ErrorPage/ErrorPage.tsx +33 -0
- package/apps/agents-server/src/components/ForbiddenPage/ForbiddenPage.tsx +15 -0
- package/apps/agents-server/src/components/Header/Header.tsx +146 -0
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +27 -0
- package/apps/agents-server/src/components/LoginDialog/LoginDialog.tsx +40 -0
- package/apps/agents-server/src/components/LoginForm/LoginForm.tsx +109 -0
- package/apps/agents-server/src/components/NotFoundPage/NotFoundPage.tsx +17 -0
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +190 -0
- package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +60 -0
- package/apps/agents-server/src/database/$getTableName.ts +18 -0
- package/apps/agents-server/src/database/$provideSupabase.ts +2 -2
- package/apps/agents-server/src/database/$provideSupabaseForServer.ts +3 -3
- package/apps/agents-server/src/database/getMetadata.ts +31 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +37 -0
- package/apps/agents-server/src/database/schema.sql +81 -33
- package/apps/agents-server/src/database/schema.ts +35 -1
- package/apps/agents-server/src/middleware.ts +200 -0
- package/apps/agents-server/src/tools/$provideAgentCollectionForServer.ts +11 -7
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +1 -1
- package/apps/agents-server/src/tools/$provideExecutionToolsForServer.ts +11 -13
- package/apps/agents-server/src/tools/$provideOpenAiAssistantExecutionToolsForServer.ts +7 -7
- package/apps/agents-server/src/tools/$provideServer.ts +39 -0
- package/apps/agents-server/src/utils/auth.ts +33 -0
- package/apps/agents-server/src/utils/cdn/utils/nameToSubfolderPath.ts +1 -1
- package/apps/agents-server/src/utils/getCurrentUser.ts +32 -0
- package/apps/agents-server/src/utils/getFederatedAgents.ts +66 -0
- package/apps/agents-server/src/utils/isIpAllowed.ts +101 -0
- package/apps/agents-server/src/utils/isUserAdmin.ts +31 -0
- package/apps/agents-server/src/utils/session.ts +50 -0
- package/apps/agents-server/tailwind.config.ts +2 -0
- package/esm/index.es.js +147 -31
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +1 -0
- package/esm/typings/src/_packages/components.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +2 -0
- package/esm/typings/src/_packages/utils.index.d.ts +2 -0
- package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +12 -2
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +20 -0
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +14 -8
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabaseOptions.d.ts +10 -0
- package/esm/typings/src/commitments/MESSAGE/InitialMessageCommitmentDefinition.d.ts +28 -0
- package/esm/typings/src/commitments/index.d.ts +2 -1
- package/esm/typings/src/config.d.ts +1 -0
- package/esm/typings/src/errors/DatabaseError.d.ts +2 -2
- package/esm/typings/src/errors/WrappedError.d.ts +2 -2
- package/esm/typings/src/execution/ExecutionTask.d.ts +2 -2
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +6 -1
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizardOrCli.d.ts +2 -2
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +19 -3
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +13 -1
- package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +11 -2
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +6 -1
- package/esm/typings/src/remote-server/startAgentServer.d.ts +2 -2
- package/esm/typings/src/utils/color/Color.d.ts +7 -0
- package/esm/typings/src/utils/color/Color.test.d.ts +1 -0
- package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -2
- package/esm/typings/src/utils/misc/computeHash.d.ts +11 -0
- package/esm/typings/src/utils/misc/computeHash.test.d.ts +1 -0
- package/esm/typings/src/utils/organization/$sideEffect.d.ts +2 -2
- package/esm/typings/src/utils/organization/$side_effect.d.ts +2 -2
- package/esm/typings/src/utils/organization/TODO_USE.d.ts +2 -2
- package/esm/typings/src/utils/organization/keepUnused.d.ts +2 -2
- package/esm/typings/src/utils/organization/preserve.d.ts +3 -3
- package/esm/typings/src/utils/organization/really_any.d.ts +7 -0
- package/esm/typings/src/utils/serialization/asSerializable.d.ts +2 -2
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +147 -31
- package/umd/index.umd.js.map +1 -1
- package/apps/agents-server/config.ts.todo +0 -38
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { loginAction } from '@/src/app/actions';
|
|
4
|
+
import { Loader2, Lock, User } from 'lucide-react';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
|
|
7
|
+
type LoginFormProps = {
|
|
8
|
+
onSuccess?: () => void;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function LoginForm(props: LoginFormProps) {
|
|
13
|
+
const { onSuccess, className } = props;
|
|
14
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
15
|
+
const [error, setError] = useState<string | null>(null);
|
|
16
|
+
|
|
17
|
+
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
setIsLoading(true);
|
|
20
|
+
setError(null);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const formData = new FormData(event.currentTarget);
|
|
24
|
+
const result = await loginAction(formData);
|
|
25
|
+
|
|
26
|
+
if (result.success) {
|
|
27
|
+
if (onSuccess) {
|
|
28
|
+
onSuccess();
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
setError(result.message || 'An error occurred');
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
setError('An unexpected error occurred');
|
|
35
|
+
console.error(error);
|
|
36
|
+
} finally {
|
|
37
|
+
setIsLoading(false);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<form onSubmit={handleSubmit} className={`space-y-4 ${className || ''}`}>
|
|
43
|
+
<div className="space-y-2">
|
|
44
|
+
<label
|
|
45
|
+
htmlFor="username"
|
|
46
|
+
className="text-sm font-medium text-gray-700 block"
|
|
47
|
+
>
|
|
48
|
+
Username
|
|
49
|
+
</label>
|
|
50
|
+
<div className="relative">
|
|
51
|
+
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
|
|
52
|
+
<User className="w-4 h-4" />
|
|
53
|
+
</div>
|
|
54
|
+
<input
|
|
55
|
+
id="username"
|
|
56
|
+
name="username"
|
|
57
|
+
type="text"
|
|
58
|
+
required
|
|
59
|
+
className="block w-full pl-10 h-10 rounded-md border border-gray-300 bg-white px-3 py-2 text-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-promptbook-blue focus:border-transparent disabled:opacity-50"
|
|
60
|
+
placeholder="Enter your username"
|
|
61
|
+
/>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div className="space-y-2">
|
|
66
|
+
<label
|
|
67
|
+
htmlFor="password"
|
|
68
|
+
className="text-sm font-medium text-gray-700 block"
|
|
69
|
+
>
|
|
70
|
+
Password
|
|
71
|
+
</label>
|
|
72
|
+
<div className="relative">
|
|
73
|
+
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none text-gray-400">
|
|
74
|
+
<Lock className="w-4 h-4" />
|
|
75
|
+
</div>
|
|
76
|
+
<input
|
|
77
|
+
id="password"
|
|
78
|
+
name="password"
|
|
79
|
+
type="password"
|
|
80
|
+
required
|
|
81
|
+
className="block w-full pl-10 h-10 rounded-md border border-gray-300 bg-white px-3 py-2 text-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-promptbook-blue focus:border-transparent disabled:opacity-50"
|
|
82
|
+
placeholder="Enter your password"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{error && (
|
|
88
|
+
<div className="p-3 text-sm text-red-500 bg-red-50 border border-red-200 rounded-md">
|
|
89
|
+
{error}
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
<button
|
|
94
|
+
type="submit"
|
|
95
|
+
disabled={isLoading}
|
|
96
|
+
className="w-full inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-promptbook-blue-dark text-white hover:bg-promptbook-blue-dark/90 focus:outline-none focus:ring-2 focus:ring-promptbook-blue focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none transition-colors"
|
|
97
|
+
>
|
|
98
|
+
{isLoading ? (
|
|
99
|
+
<>
|
|
100
|
+
<Loader2 className="mr-2 w-4 h-4 animate-spin" />
|
|
101
|
+
Logging in...
|
|
102
|
+
</>
|
|
103
|
+
) : (
|
|
104
|
+
'Log in'
|
|
105
|
+
)}
|
|
106
|
+
</button>
|
|
107
|
+
</form>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
import { ErrorPage } from '../ErrorPage/ErrorPage';
|
|
3
|
+
|
|
4
|
+
export function NotFoundPage() {
|
|
5
|
+
return (
|
|
6
|
+
<ErrorPage title="404 Not Found" message="The page you are looking for does not exist.">
|
|
7
|
+
<div className="flex justify-center">
|
|
8
|
+
<Link
|
|
9
|
+
href="/"
|
|
10
|
+
className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
|
|
11
|
+
>
|
|
12
|
+
Go Home
|
|
13
|
+
</Link>
|
|
14
|
+
</div>
|
|
15
|
+
</ErrorPage>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
type User = {
|
|
6
|
+
id: number;
|
|
7
|
+
username: string;
|
|
8
|
+
createdAt: string;
|
|
9
|
+
updatedAt: string;
|
|
10
|
+
isAdmin: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function UsersList() {
|
|
14
|
+
const [users, setUsers] = useState<User[]>([]);
|
|
15
|
+
const [loading, setLoading] = useState(true);
|
|
16
|
+
const [error, setError] = useState<string | null>(null);
|
|
17
|
+
const [newUsername, setNewUsername] = useState('');
|
|
18
|
+
const [newPassword, setNewPassword] = useState('');
|
|
19
|
+
const [newIsAdmin, setNewIsAdmin] = useState(false);
|
|
20
|
+
|
|
21
|
+
const fetchUsers = async () => {
|
|
22
|
+
try {
|
|
23
|
+
setLoading(true);
|
|
24
|
+
const response = await fetch('/api/users');
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
if (response.status === 401) {
|
|
27
|
+
// Not authorized, maybe session expired
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
throw new Error('Failed to fetch users');
|
|
31
|
+
}
|
|
32
|
+
const data = await response.json();
|
|
33
|
+
setUsers(data);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
setError(err instanceof Error ? err.message : 'An error occurred');
|
|
36
|
+
} finally {
|
|
37
|
+
setLoading(false);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
fetchUsers();
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const handleCreateUser = async (e: React.FormEvent) => {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
setError(null);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const response = await fetch('/api/users', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
body: JSON.stringify({
|
|
54
|
+
username: newUsername,
|
|
55
|
+
password: newPassword,
|
|
56
|
+
isAdmin: newIsAdmin,
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const data = await response.json();
|
|
62
|
+
throw new Error(data.error || 'Failed to create user');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setNewUsername('');
|
|
66
|
+
setNewPassword('');
|
|
67
|
+
setNewIsAdmin(false);
|
|
68
|
+
fetchUsers();
|
|
69
|
+
} catch (err) {
|
|
70
|
+
setError(err instanceof Error ? err.message : 'An error occurred');
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const handleDeleteUser = async (username: string) => {
|
|
75
|
+
if (!confirm(`Are you sure you want to delete user ${username}?`)) return;
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(`/api/users/${username}`, {
|
|
79
|
+
method: 'DELETE',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
const data = await response.json();
|
|
84
|
+
throw new Error(data.error || 'Failed to delete user');
|
|
85
|
+
}
|
|
86
|
+
fetchUsers();
|
|
87
|
+
} catch (err) {
|
|
88
|
+
setError(err instanceof Error ? err.message : 'An error occurred');
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleToggleAdmin = async (username: string, currentIsAdmin: boolean) => {
|
|
93
|
+
try {
|
|
94
|
+
const response = await fetch(`/api/users/${username}`, {
|
|
95
|
+
method: 'PATCH',
|
|
96
|
+
headers: { 'Content-Type': 'application/json' },
|
|
97
|
+
body: JSON.stringify({ isAdmin: !currentIsAdmin }),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
const data = await response.json();
|
|
102
|
+
throw new Error(data.error || 'Failed to update user');
|
|
103
|
+
}
|
|
104
|
+
fetchUsers();
|
|
105
|
+
} catch (err) {
|
|
106
|
+
setError(err instanceof Error ? err.message : 'An error occurred');
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (loading) return <div>Loading users...</div>;
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div className="space-y-6">
|
|
114
|
+
<h2 className="text-3xl text-gray-900 mt-16 mb-4">Users ({users.length})</h2>
|
|
115
|
+
|
|
116
|
+
{error && <div className="bg-red-100 text-red-700 p-3 rounded">{error}</div>}
|
|
117
|
+
|
|
118
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
119
|
+
{users.map((user) => (
|
|
120
|
+
<div key={user.id} className="block p-6 bg-white rounded-lg shadow-md border border-gray-200">
|
|
121
|
+
<div className="flex justify-between items-start">
|
|
122
|
+
<div>
|
|
123
|
+
<h3 className="text-xl font-semibold text-gray-900">{user.username}</h3>
|
|
124
|
+
{user.isAdmin && <span className="inline-block bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded mt-1">Admin</span>}
|
|
125
|
+
<p className="text-gray-500 text-sm mt-2">Created: {new Date(user.createdAt).toLocaleDateString()}</p>
|
|
126
|
+
</div>
|
|
127
|
+
<div className="space-x-2">
|
|
128
|
+
<button
|
|
129
|
+
onClick={() => handleToggleAdmin(user.username, user.isAdmin)}
|
|
130
|
+
className="text-sm text-blue-600 hover:text-blue-800"
|
|
131
|
+
>
|
|
132
|
+
{user.isAdmin ? 'Remove Admin' : 'Make Admin'}
|
|
133
|
+
</button>
|
|
134
|
+
<button
|
|
135
|
+
onClick={() => handleDeleteUser(user.username)}
|
|
136
|
+
className="text-sm text-red-600 hover:text-red-800"
|
|
137
|
+
>
|
|
138
|
+
Delete
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
))}
|
|
144
|
+
|
|
145
|
+
{/* Create User Form */}
|
|
146
|
+
<div className="block p-6 bg-gray-50 rounded-lg border border-dashed border-gray-300">
|
|
147
|
+
<h3 className="text-lg font-semibold text-gray-700 mb-4">Add New User</h3>
|
|
148
|
+
<form onSubmit={handleCreateUser} className="space-y-3">
|
|
149
|
+
<div>
|
|
150
|
+
<input
|
|
151
|
+
type="text"
|
|
152
|
+
placeholder="Username"
|
|
153
|
+
value={newUsername}
|
|
154
|
+
onChange={(e) => setNewUsername(e.target.value)}
|
|
155
|
+
className="w-full p-2 border border-gray-300 rounded"
|
|
156
|
+
required
|
|
157
|
+
/>
|
|
158
|
+
</div>
|
|
159
|
+
<div>
|
|
160
|
+
<input
|
|
161
|
+
type="password"
|
|
162
|
+
placeholder="Password"
|
|
163
|
+
value={newPassword}
|
|
164
|
+
onChange={(e) => setNewPassword(e.target.value)}
|
|
165
|
+
className="w-full p-2 border border-gray-300 rounded"
|
|
166
|
+
required
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
<div className="flex items-center">
|
|
170
|
+
<input
|
|
171
|
+
type="checkbox"
|
|
172
|
+
id="newIsAdmin"
|
|
173
|
+
checked={newIsAdmin}
|
|
174
|
+
onChange={(e) => setNewIsAdmin(e.target.checked)}
|
|
175
|
+
className="mr-2"
|
|
176
|
+
/>
|
|
177
|
+
<label htmlFor="newIsAdmin" className="text-gray-700">Is Admin</label>
|
|
178
|
+
</div>
|
|
179
|
+
<button
|
|
180
|
+
type="submit"
|
|
181
|
+
className="w-full bg-blue-600 text-white p-2 rounded hover:bg-blue-700 transition-colors"
|
|
182
|
+
>
|
|
183
|
+
Create User
|
|
184
|
+
</button>
|
|
185
|
+
</form>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NEXT_PUBLIC_VERCEL_BRANCH_URL,
|
|
3
|
+
NEXT_PUBLIC_VERCEL_ENV,
|
|
4
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
|
|
5
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME,
|
|
6
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE,
|
|
7
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF,
|
|
8
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
|
|
9
|
+
NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA,
|
|
10
|
+
NEXT_PUBLIC_VERCEL_GIT_PROVIDER,
|
|
11
|
+
NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID,
|
|
12
|
+
NEXT_PUBLIC_VERCEL_GIT_REPO_ID,
|
|
13
|
+
NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER,
|
|
14
|
+
NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG,
|
|
15
|
+
NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL,
|
|
16
|
+
NEXT_PUBLIC_VERCEL_TARGET_ENV,
|
|
17
|
+
NEXT_PUBLIC_VERCEL_URL,
|
|
18
|
+
} from '@/config';
|
|
19
|
+
import Link from 'next/link';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* [♐️] Expose Vercel environment variables to indentify the deployment
|
|
23
|
+
*/
|
|
24
|
+
export default function VercelDeploymentCard() {
|
|
25
|
+
return (
|
|
26
|
+
<Link
|
|
27
|
+
href="#"
|
|
28
|
+
className="block p-6 bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300 border border-gray-200 hover:border-blue-400"
|
|
29
|
+
>
|
|
30
|
+
<h2 className="text-2xl font-semibold text-gray-900 mb-4">Vercel Deployment</h2>
|
|
31
|
+
|
|
32
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_ENV: {NEXT_PUBLIC_VERCEL_ENV}</p>
|
|
33
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_TARGET_ENV: {NEXT_PUBLIC_VERCEL_TARGET_ENV}</p>
|
|
34
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_URL: {NEXT_PUBLIC_VERCEL_URL}</p>
|
|
35
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_BRANCH_URL: {NEXT_PUBLIC_VERCEL_BRANCH_URL}</p>
|
|
36
|
+
<p className="text-gray-600">
|
|
37
|
+
NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL: {NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}
|
|
38
|
+
</p>
|
|
39
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_PROVIDER: {NEXT_PUBLIC_VERCEL_GIT_PROVIDER}</p>
|
|
40
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER: {NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER}</p>
|
|
41
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG: {NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG}</p>
|
|
42
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_REPO_ID: {NEXT_PUBLIC_VERCEL_GIT_REPO_ID}</p>
|
|
43
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA: {NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA}</p>
|
|
44
|
+
<p className="text-gray-600">
|
|
45
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE: {NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE}
|
|
46
|
+
</p>
|
|
47
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF: {NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF}</p>
|
|
48
|
+
<p className="text-gray-600">
|
|
49
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME: {NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME}
|
|
50
|
+
</p>
|
|
51
|
+
<p className="text-gray-600">
|
|
52
|
+
NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN: {NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN}
|
|
53
|
+
</p>
|
|
54
|
+
<p className="text-gray-600">NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA: {NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA}</p>
|
|
55
|
+
<p className="text-gray-600">
|
|
56
|
+
NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID: {NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID}
|
|
57
|
+
</p>
|
|
58
|
+
</Link>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { $provideServer } from '../tools/$provideServer';
|
|
2
|
+
import { AgentsServerDatabase } from './schema';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type representing the non-prefixed table names in the AgentsServerDatabase public schema
|
|
6
|
+
*/
|
|
7
|
+
type string_table_name = keyof AgentsServerDatabase['public']['Tables'];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the Supabase table name with prefix if it is configured
|
|
11
|
+
*
|
|
12
|
+
* @param tableName - The original table name
|
|
13
|
+
* @returns The prefixed table name
|
|
14
|
+
*/
|
|
15
|
+
export async function $getTableName<TTable extends string_table_name>(tableName: TTable): Promise<TTable> {
|
|
16
|
+
const { tablePrefix } = await $provideServer();
|
|
17
|
+
return `${tablePrefix}${tableName}` as TTable;
|
|
18
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { AgentsDatabaseSchema } from '@promptbook-local/types';
|
|
2
1
|
import { $isRunningInBrowser, $isRunningInNode, $isRunningInWebWorker } from '@promptbook-local/utils';
|
|
3
2
|
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
4
3
|
import { $provideSupabaseForBrowser } from './$provideSupabaseForBrowser';
|
|
5
4
|
import { $provideSupabaseForServer } from './$provideSupabaseForServer';
|
|
6
5
|
import { $provideSupabaseForWorker } from './$provideSupabaseForWorker';
|
|
6
|
+
import { AgentsServerDatabase } from './schema';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Get supabase client in any environment
|
|
@@ -12,7 +12,7 @@ import { $provideSupabaseForWorker } from './$provideSupabaseForWorker';
|
|
|
12
12
|
*
|
|
13
13
|
* @returns instance of supabase client
|
|
14
14
|
*/
|
|
15
|
-
export function $provideSupabase(): SupabaseClient<
|
|
15
|
+
export function $provideSupabase(): SupabaseClient<AgentsServerDatabase> {
|
|
16
16
|
if ($isRunningInNode()) {
|
|
17
17
|
return $provideSupabaseForServer();
|
|
18
18
|
} else if ($isRunningInBrowser()) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AgentsDatabaseSchema } from '@promptbook-local/types';
|
|
2
1
|
import { $isRunningInNode } from '@promptbook-local/utils';
|
|
3
2
|
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
import { AgentsServerDatabase } from './schema';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Internal cache for `$provideSupabaseForServer`
|
|
@@ -8,7 +8,7 @@ import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
|
8
8
|
* @private
|
|
9
9
|
* @singleton
|
|
10
10
|
*/
|
|
11
|
-
let supabase: SupabaseClient<
|
|
11
|
+
let supabase: SupabaseClient<AgentsServerDatabase>;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Get supabase client
|
|
@@ -27,7 +27,7 @@ export function $provideSupabaseForServer(): typeof supabase {
|
|
|
27
27
|
|
|
28
28
|
if (!supabase) {
|
|
29
29
|
// Create a single supabase client for interacting with your database
|
|
30
|
-
supabase = createClient<
|
|
30
|
+
supabase = createClient<AgentsServerDatabase>(
|
|
31
31
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
32
32
|
process.env.SUPABASE_SERVICE_ROLE_KEY!,
|
|
33
33
|
{
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { $getTableName } from './$getTableName';
|
|
2
|
+
import { $provideSupabase } from './$provideSupabase';
|
|
3
|
+
import { metadataDefaults } from './metadataDefaults';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get metadata value by key
|
|
7
|
+
*
|
|
8
|
+
* @param key - The key of the metadata
|
|
9
|
+
* @returns The value of the metadata or default value if not found
|
|
10
|
+
*/
|
|
11
|
+
export async function getMetadata(key: string): Promise<string | null> {
|
|
12
|
+
const supabase = $provideSupabase();
|
|
13
|
+
const table = await $getTableName('Metadata');
|
|
14
|
+
|
|
15
|
+
const { data } = await supabase
|
|
16
|
+
.from(table)
|
|
17
|
+
.select('value')
|
|
18
|
+
.eq('key', key)
|
|
19
|
+
.single();
|
|
20
|
+
|
|
21
|
+
if (data) {
|
|
22
|
+
return data.value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const defaultValue = metadataDefaults.find((m) => m.key === key);
|
|
26
|
+
if (defaultValue) {
|
|
27
|
+
return defaultValue.value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const metadataDefaults = [
|
|
2
|
+
{
|
|
3
|
+
key: 'SERVER_NAME',
|
|
4
|
+
value: 'Promptbook Agents Server',
|
|
5
|
+
note: 'The name of the server displayed in the heading bar',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
key: 'SERVER_DESCRIPTION',
|
|
9
|
+
value: 'Agents server powered by Promptbook',
|
|
10
|
+
note: 'The description of the server displayed in the search engine results',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
key: 'SERVER_URL',
|
|
14
|
+
value: 'https://ptbk.io',
|
|
15
|
+
note: 'The URL of the server',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
key: 'SERVER_LOGO_URL',
|
|
19
|
+
value: '',
|
|
20
|
+
note: 'The URL of the logo displayed in the heading bar',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'SERVER_FAVICON_URL',
|
|
24
|
+
value: '',
|
|
25
|
+
note: 'The URL of the favicon',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: 'RESTRICT_IP',
|
|
29
|
+
value: '',
|
|
30
|
+
note: 'Comma separated list of allowed IPs or CIDR ranges. If set, only clients from these IPs are allowed to access the server.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: 'FEDERATED_SERVERS',
|
|
34
|
+
value: '',
|
|
35
|
+
note: 'Comma separated list of federated servers URLs. The server will look to all federated servers and list their agents.',
|
|
36
|
+
},
|
|
37
|
+
] as const;
|