@promptbook/cli 0.112.0-93 → 0.112.0-96
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 +8 -1
- package/apps/agents-server/playwright.config.ts +2 -0
- package/apps/agents-server/src/app/admin/_components/AdminConfigurationShell.tsx +13 -7
- package/apps/agents-server/src/app/admin/code-runners/CodeRunnersClient.tsx +225 -0
- package/apps/agents-server/src/app/admin/code-runners/page.tsx +14 -0
- package/apps/agents-server/src/app/admin/database/DatabaseAdminClient.tsx +38 -0
- package/apps/agents-server/src/app/admin/database/DatabaseAdminStudioSurface.tsx +42 -0
- package/apps/agents-server/src/app/admin/database/page.tsx +33 -0
- package/apps/agents-server/src/app/admin/environment/EnvironmentVariablesClient.tsx +259 -0
- package/apps/agents-server/src/app/admin/environment/page.tsx +21 -0
- package/apps/agents-server/src/app/admin/logs/LogsClient.tsx +78 -0
- package/apps/agents-server/src/app/admin/logs/page.tsx +14 -0
- package/apps/agents-server/src/app/admin/servers/ServersClient.tsx +64 -33
- package/apps/agents-server/src/app/admin/servers/ServersRegistryApi.ts +5 -0
- package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +15 -2
- package/apps/agents-server/src/app/admin/servers/page.tsx +3 -3
- package/apps/agents-server/src/app/admin/servers/useServersRegistryState.ts +12 -2
- package/apps/agents-server/src/app/api/admin/code-runners/route.ts +104 -0
- package/apps/agents-server/src/app/api/admin/database/studio/route.ts +113 -0
- package/apps/agents-server/src/app/api/admin/environment/route.ts +65 -0
- package/apps/agents-server/src/app/api/admin/logs/route.ts +24 -0
- package/apps/agents-server/src/app/api/admin/servers/[serverId]/route.ts +79 -3
- package/apps/agents-server/src/app/api/admin/servers/route.ts +36 -1
- package/apps/agents-server/src/app/layout.tsx +1 -0
- package/apps/agents-server/src/app/page.tsx +101 -1
- package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +27 -4
- package/apps/agents-server/src/database/$provideClientSql.ts +2 -6
- package/apps/agents-server/src/database/$provideDatabaseAdminExecutor.ts +273 -0
- package/apps/agents-server/src/database/resolvePostgresConnectionString.ts +26 -0
- package/apps/agents-server/src/database/sqlite/$provideAgentsServerSqliteDatabase.ts +83 -0
- package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +20 -71
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +5 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +5 -0
- package/apps/agents-server/src/languages/translations/english.yaml +5 -0
- package/apps/agents-server/src/tools/$provideServer.ts +27 -0
- package/apps/agents-server/src/utils/serverRegistry.ts +20 -1
- package/apps/agents-server/src/utils/session.ts +123 -2
- package/apps/agents-server/src/utils/vpsConfiguration.ts +550 -0
- package/esm/index.es.js +1 -1
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-components/Chat/utils/renderMarkdown.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +3 -1
- package/src/book-components/Chat/MarkdownContent/MarkdownContent.tsx +9 -398
- package/src/book-components/Chat/utils/renderMarkdown.ts +323 -8
- package/src/other/templates/getTemplatesPipelineCollection.ts +712 -829
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +1 -1
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-components/Chat/utils/renderMarkdown.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -120,6 +120,7 @@ header.logOut: Odhlásit se
|
|
|
120
120
|
header.changePassword: Změnit heslo
|
|
121
121
|
header.menuLabel: Nabídka
|
|
122
122
|
header.myAccount: Můj účet
|
|
123
|
+
header.superAdmin: Super administrace
|
|
123
124
|
header.administration: Administrace
|
|
124
125
|
header.monitoringAndUsage: Monitoring a využití
|
|
125
126
|
header.integrationsAndKeys: Integrace a klíče
|
|
@@ -134,6 +135,10 @@ header.mockedChats: Ukázkové chaty
|
|
|
134
135
|
header.viewAllUsers: Zobrazit všechny uživatele
|
|
135
136
|
header.createNewUser: Vytvořit nového uživatele
|
|
136
137
|
header.servers: Servery
|
|
138
|
+
header.environmentVariables: Proměnné prostředí
|
|
139
|
+
header.database: Databáze
|
|
140
|
+
header.logs: Logy
|
|
141
|
+
header.codeRunners: Code runnery
|
|
137
142
|
header.models: Modely
|
|
138
143
|
header.openApiDocumentation: Dokumentace OpenAPI
|
|
139
144
|
header.apiTokens: API tokeny
|
|
@@ -122,6 +122,7 @@ header.logOut: Log out
|
|
|
122
122
|
header.changePassword: Change Password
|
|
123
123
|
header.menuLabel: Menu
|
|
124
124
|
header.myAccount: My Account
|
|
125
|
+
header.superAdmin: Super Admin
|
|
125
126
|
header.administration: Administration
|
|
126
127
|
header.monitoringAndUsage: Monitoring & Usage
|
|
127
128
|
header.integrationsAndKeys: Integrations & Keys
|
|
@@ -136,6 +137,10 @@ header.mockedChats: Mocked Chats
|
|
|
136
137
|
header.viewAllUsers: View all users
|
|
137
138
|
header.createNewUser: Create new user
|
|
138
139
|
header.servers: Servers
|
|
140
|
+
header.environmentVariables: Environment variables
|
|
141
|
+
header.database: Database
|
|
142
|
+
header.logs: Logs
|
|
143
|
+
header.codeRunners: Code runners
|
|
139
144
|
header.models: Models
|
|
140
145
|
header.openApiDocumentation: OpenAPI Documentation
|
|
141
146
|
header.apiTokens: API Tokens
|
|
@@ -55,6 +55,14 @@ const getCachedProvidedServer = cache(async (): Promise<ProvidedServer> => {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
if (!resolvedSqliteServer) {
|
|
58
|
+
if (isIpAddressHost(requestHost)) {
|
|
59
|
+
return {
|
|
60
|
+
id: null,
|
|
61
|
+
publicUrl: resolveFallbackPublicUrl(requestHost),
|
|
62
|
+
tablePrefix: SUPABASE_TABLE_PREFIX,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
throw new Error(`Server with host "${requestHost}" is not registered in SERVERS`);
|
|
59
67
|
}
|
|
60
68
|
|
|
@@ -156,3 +164,22 @@ function isLocalDevelopmentHost(host: string | null): boolean {
|
|
|
156
164
|
normalizedHost.startsWith('[::1]:')
|
|
157
165
|
);
|
|
158
166
|
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Checks whether the current request host is a raw IP address.
|
|
170
|
+
*
|
|
171
|
+
* @param host - Raw request host.
|
|
172
|
+
* @returns `true` when the host is IPv4 or IPv6.
|
|
173
|
+
*/
|
|
174
|
+
function isIpAddressHost(host: string | null): boolean {
|
|
175
|
+
if (!host) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const hostname = host
|
|
180
|
+
.trim()
|
|
181
|
+
.replace(/^\[(.+)\](?::\d+)?$/u, '$1')
|
|
182
|
+
.replace(/:\d+$/u, '');
|
|
183
|
+
|
|
184
|
+
return /^\d{1,3}(?:\.\d{1,3}){3}$/u.test(hostname) || hostname.includes(':');
|
|
185
|
+
}
|
|
@@ -241,7 +241,11 @@ export function createServerPublicUrl(domain: string): URL {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
const protocol =
|
|
244
|
-
normalizedDomain.startsWith('localhost') ||
|
|
244
|
+
normalizedDomain.startsWith('localhost') ||
|
|
245
|
+
normalizedDomain.startsWith('127.0.0.1') ||
|
|
246
|
+
isIpAddressHost(normalizedDomain)
|
|
247
|
+
? 'http'
|
|
248
|
+
: 'https';
|
|
245
249
|
return new URL(`${protocol}://${normalizedDomain}`);
|
|
246
250
|
}
|
|
247
251
|
|
|
@@ -435,6 +439,21 @@ function hasHttpProtocol(value: string): boolean {
|
|
|
435
439
|
return value.startsWith('http://') || value.startsWith('https://');
|
|
436
440
|
}
|
|
437
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Checks whether a normalized host is a raw IPv4 or IPv6 address.
|
|
444
|
+
*
|
|
445
|
+
* @param host - Normalized host or host with port.
|
|
446
|
+
* @returns `true` for raw IP hosts.
|
|
447
|
+
*/
|
|
448
|
+
function isIpAddressHost(host: string): boolean {
|
|
449
|
+
const hostname = host
|
|
450
|
+
.trim()
|
|
451
|
+
.replace(/^\[(.+)\](?::\d+)?$/u, '$1')
|
|
452
|
+
.replace(/:\d+$/u, '');
|
|
453
|
+
|
|
454
|
+
return /^\d{1,3}(?:\.\d{1,3}){3}$/u.test(hostname) || hostname.includes(':');
|
|
455
|
+
}
|
|
456
|
+
|
|
438
457
|
/**
|
|
439
458
|
* Checks whether a port is implicit for the given protocol and can be omitted.
|
|
440
459
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHmac } from 'crypto';
|
|
2
|
-
import { cookies } from 'next/headers';
|
|
2
|
+
import { cookies, headers } from 'next/headers';
|
|
3
3
|
import { cache } from 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -30,6 +30,36 @@ export type SessionUser = {
|
|
|
30
30
|
readonly isGlobalAdmin?: boolean;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Request details used to decide whether the auth cookie may require HTTPS.
|
|
35
|
+
*/
|
|
36
|
+
export type SessionCookieSecurityContext = {
|
|
37
|
+
/**
|
|
38
|
+
* Current deployment mode.
|
|
39
|
+
*/
|
|
40
|
+
readonly isProduction: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Raw `Host` header.
|
|
43
|
+
*/
|
|
44
|
+
readonly host: string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Raw forwarded host header emitted by the reverse proxy.
|
|
47
|
+
*/
|
|
48
|
+
readonly forwardedHost: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Raw forwarded protocol header emitted by the reverse proxy.
|
|
51
|
+
*/
|
|
52
|
+
readonly forwardedProto: string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Comma-separated configured domain list from `SERVERS`.
|
|
55
|
+
*/
|
|
56
|
+
readonly configuredServers: string | null | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Known standalone VPS public IP address.
|
|
59
|
+
*/
|
|
60
|
+
readonly publicIpAddress: string | null | undefined;
|
|
61
|
+
};
|
|
62
|
+
|
|
33
63
|
/**
|
|
34
64
|
* Signs a session payload and serializes it into the cookie token format.
|
|
35
65
|
*
|
|
@@ -77,6 +107,42 @@ export function parseSessionToken(token: string | null | undefined): SessionUser
|
|
|
77
107
|
}
|
|
78
108
|
}
|
|
79
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Decides whether the session cookie should keep the `Secure` flag for the current request.
|
|
112
|
+
*
|
|
113
|
+
* This keeps production-domain logins protected by HTTPS while allowing the standalone
|
|
114
|
+
* VPS bootstrap flow to authenticate over `http://<IP_ADDRESS>` before any domain exists.
|
|
115
|
+
*
|
|
116
|
+
* @param context - Request and deployment details used for the decision.
|
|
117
|
+
* @returns `true` when the cookie should require HTTPS.
|
|
118
|
+
*/
|
|
119
|
+
export function shouldUseSecureSessionCookieForRequest(context: SessionCookieSecurityContext): boolean {
|
|
120
|
+
if (!context.isProduction) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (parseConfiguredServers(context.configuredServers).length > 0) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const requestHost = normalizeHost(context.forwardedHost ?? context.host);
|
|
129
|
+
if (!requestHost || !isIpAddressHost(requestHost)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const forwardedProtocol = (context.forwardedProto || '').split(',')[0]?.trim().toLowerCase() || '';
|
|
134
|
+
if (forwardedProtocol === 'https') {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const configuredPublicIpAddress = normalizeHost(context.publicIpAddress || '');
|
|
139
|
+
if (configuredPublicIpAddress && requestHost !== configuredPublicIpAddress) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
80
146
|
/**
|
|
81
147
|
* Persists the provided session payload into the signed session cookie.
|
|
82
148
|
*
|
|
@@ -84,10 +150,11 @@ export function parseSessionToken(token: string | null | undefined): SessionUser
|
|
|
84
150
|
*/
|
|
85
151
|
export async function setSession(user: SessionUser) {
|
|
86
152
|
const token = serializeSessionToken(user);
|
|
153
|
+
const secure = await shouldUseSecureSessionCookie();
|
|
87
154
|
|
|
88
155
|
(await cookies()).set(SESSION_COOKIE_NAME, token, {
|
|
89
156
|
httpOnly: true,
|
|
90
|
-
secure
|
|
157
|
+
secure,
|
|
91
158
|
path: '/',
|
|
92
159
|
maxAge: 60 * 60 * 24 * 365 * 2, // 2 years
|
|
93
160
|
});
|
|
@@ -120,3 +187,57 @@ const getCachedSession = cache(async (): Promise<SessionUser | null> => {
|
|
|
120
187
|
export async function getSession(): Promise<SessionUser | null> {
|
|
121
188
|
return getCachedSession();
|
|
122
189
|
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Resolves the runtime cookie security decision from the current request headers.
|
|
193
|
+
*
|
|
194
|
+
* @returns `true` when the session cookie should keep the `Secure` flag.
|
|
195
|
+
*/
|
|
196
|
+
async function shouldUseSecureSessionCookie(): Promise<boolean> {
|
|
197
|
+
const headerStore = await headers();
|
|
198
|
+
|
|
199
|
+
return shouldUseSecureSessionCookieForRequest({
|
|
200
|
+
isProduction: process.env.NODE_ENV === 'production',
|
|
201
|
+
host: headerStore.get('host'),
|
|
202
|
+
forwardedHost: headerStore.get('x-forwarded-host'),
|
|
203
|
+
forwardedProto: headerStore.get('x-forwarded-proto'),
|
|
204
|
+
configuredServers: process.env.SERVERS,
|
|
205
|
+
publicIpAddress: process.env.PTBK_PUBLIC_IP_ADDRESS,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Parses the configured `SERVERS` CSV into non-empty entries.
|
|
211
|
+
*
|
|
212
|
+
* @param configuredServers - Raw environment value.
|
|
213
|
+
* @returns Normalized list of configured domains.
|
|
214
|
+
*/
|
|
215
|
+
function parseConfiguredServers(configuredServers: string | null | undefined): Array<string> {
|
|
216
|
+
return (configuredServers || '')
|
|
217
|
+
.split(',')
|
|
218
|
+
.map((server) => server.trim())
|
|
219
|
+
.filter(Boolean);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Checks whether a host string points to a raw IPv4 or IPv6 address.
|
|
224
|
+
*
|
|
225
|
+
* @param host - Host header or hostname.
|
|
226
|
+
* @returns `true` when the host is a raw IP address.
|
|
227
|
+
*/
|
|
228
|
+
function isIpAddressHost(host: string): boolean {
|
|
229
|
+
return /^\d{1,3}(?:\.\d{1,3}){3}$/u.test(host) || host.includes(':');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Removes ports and IPv6 brackets from host-like strings.
|
|
234
|
+
*
|
|
235
|
+
* @param host - Raw host header value.
|
|
236
|
+
* @returns Normalized bare hostname or IP address.
|
|
237
|
+
*/
|
|
238
|
+
function normalizeHost(host: string | null | undefined): string {
|
|
239
|
+
return (host || '')
|
|
240
|
+
.trim()
|
|
241
|
+
.replace(/^\[(.+)\](?::\d+)?$/u, '$1')
|
|
242
|
+
.replace(/:\d+$/u, '');
|
|
243
|
+
}
|