@promptbook/cli 0.112.0-96 → 0.112.0-97
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 +3 -3
- package/apps/agents-server/playwright.config.ts +2 -1
- package/apps/agents-server/src/app/admin/code-runners/CodeRunnersClient.tsx +358 -19
- package/apps/agents-server/src/app/admin/database/page.tsx +2 -1
- package/apps/agents-server/src/app/admin/servers/CreateServerDialog.tsx +46 -505
- package/apps/agents-server/src/app/admin/servers/ServersClient.tsx +23 -11
- package/apps/agents-server/src/app/admin/servers/ServersRegistryApi.ts +5 -0
- package/apps/agents-server/src/app/admin/servers/ServersRegistryDnsTypes.ts +87 -0
- package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +258 -128
- package/apps/agents-server/src/app/admin/servers/useCreateServerWizard.ts +46 -334
- package/apps/agents-server/src/app/admin/servers/useServersRegistryState.ts +26 -2
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +435 -0
- package/apps/agents-server/src/app/admin/update/page.tsx +14 -0
- package/apps/agents-server/src/app/api/admin/code-runners/authentication/route.ts +197 -0
- package/apps/agents-server/src/app/api/admin/code-runners/route.ts +4 -35
- package/apps/agents-server/src/app/api/admin/servers/[serverId]/route.ts +10 -5
- package/apps/agents-server/src/app/api/admin/servers/route.ts +97 -6
- package/apps/agents-server/src/app/api/admin/update/route.ts +52 -0
- package/apps/agents-server/src/app/api/auth/login/route.ts +8 -0
- package/apps/agents-server/src/app/api/auth/logout/route.ts +10 -2
- package/apps/agents-server/src/app/page.tsx +10 -0
- package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +6 -0
- package/apps/agents-server/src/database/$provideClientSql.ts +4 -17
- package/apps/agents-server/src/database/$provideDatabaseAdminExecutor.ts +3 -24
- package/apps/agents-server/src/database/$providePostgresPool.ts +27 -0
- package/apps/agents-server/src/database/$provideSupabaseForServer.ts +11 -1
- package/apps/agents-server/src/database/agentsServerDatabaseMode.ts +20 -1
- package/apps/agents-server/src/database/postgres/$provideLocalPostgresSupabase.ts +1261 -0
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +1 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +1 -0
- package/apps/agents-server/src/languages/translations/english.yaml +1 -0
- package/apps/agents-server/src/middleware.ts +32 -0
- package/apps/agents-server/src/tools/$provideServer.ts +2 -2
- package/apps/agents-server/src/utils/codeRunnerAuthentication.ts +394 -0
- package/apps/agents-server/src/utils/codeRunnerConfiguration.ts +67 -0
- package/apps/agents-server/src/utils/serverManagement/standaloneVpsServerMetadata.ts +145 -0
- package/apps/agents-server/src/utils/serverRegistry.ts +7 -6
- package/apps/agents-server/src/utils/session.ts +37 -9
- package/apps/agents-server/src/utils/shibboleth/createShibbolethAuthenticationLogPayload.ts +173 -0
- package/apps/agents-server/src/utils/shibboleth/writeShibbolethAuthenticationLog.ts +27 -0
- package/apps/agents-server/src/utils/standaloneVpsDnsDiagnostics.ts +258 -0
- package/apps/agents-server/src/utils/standaloneVpsRawIpBootstrap.ts +87 -0
- package/apps/agents-server/src/utils/vpsConfiguration.ts +87 -15
- package/apps/agents-server/src/utils/vpsSelfUpdate.ts +664 -0
- package/esm/apps/agents-server/src/database/agentsServerDatabaseMode.d.ts +9 -1
- package/esm/apps/agents-server/src/utils/serverRegistry.d.ts +1 -1
- package/esm/index.es.js +8 -6
- package/esm/index.es.js.map +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-components/Chat/utils/renderMarkdown.ts +1 -3
- package/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.ts +1 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +698 -755
- package/src/scrapers/document/DocumentScraper.ts +1 -1
- package/src/scrapers/document-legacy/LegacyDocumentScraper.ts +1 -1
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/apps/agents-server/src/database/agentsServerDatabaseMode.d.ts +9 -1
- package/umd/apps/agents-server/src/utils/serverRegistry.d.ts +1 -1
- package/umd/index.umd.js +8 -6
- package/umd/index.umd.js.map +1 -1
- package/umd/src/version.d.ts +1 -1
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import { execFile } from 'child_process';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { NextResponse } from 'next/server';
|
|
4
2
|
import { isUserGlobalAdmin } from '@/src/utils/isUserGlobalAdmin';
|
|
3
|
+
import { readConfiguredCodeRunner, resolveCodeRunnerStatus } from '@/src/utils/codeRunnerConfiguration';
|
|
5
4
|
import {
|
|
6
5
|
applyVpsCodeRunnerConfiguration,
|
|
7
|
-
listVpsEnvironmentVariables,
|
|
8
6
|
updateVpsEnvironmentVariables,
|
|
9
7
|
} from '@/src/utils/vpsConfiguration';
|
|
10
8
|
|
|
11
|
-
const execFileAsync = promisify(execFile);
|
|
12
|
-
|
|
13
9
|
/**
|
|
14
10
|
* Loads configured code-runner settings from the editable VPS environment.
|
|
15
11
|
*/
|
|
@@ -19,16 +15,11 @@ export async function GET() {
|
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
try {
|
|
22
|
-
const
|
|
23
|
-
const environmentByKey = Object.fromEntries(
|
|
24
|
-
snapshot.variables.map((variable) => [variable.key, variable.value]),
|
|
25
|
-
) as Record<string, string>;
|
|
18
|
+
const configuredCodeRunner = await readConfiguredCodeRunner();
|
|
26
19
|
|
|
27
20
|
return NextResponse.json({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
thinkingLevel: environmentByKey.PTBK_THINKING_LEVEL || process.env.PTBK_THINKING_LEVEL || 'xhigh',
|
|
31
|
-
status: await resolveRunnerStatus(environmentByKey.PTBK_AGENT || process.env.PTBK_AGENT || 'github-copilot'),
|
|
21
|
+
...configuredCodeRunner,
|
|
22
|
+
status: await resolveCodeRunnerStatus(configuredCodeRunner.agent),
|
|
32
23
|
});
|
|
33
24
|
} catch (error) {
|
|
34
25
|
return NextResponse.json(
|
|
@@ -80,25 +71,3 @@ export async function PATCH(request: Request) {
|
|
|
80
71
|
);
|
|
81
72
|
}
|
|
82
73
|
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Resolves a short runner-authentication status for the configured runner.
|
|
86
|
-
*
|
|
87
|
-
* @param agent - Runner id.
|
|
88
|
-
* @returns Human-readable status.
|
|
89
|
-
*/
|
|
90
|
-
async function resolveRunnerStatus(agent: string): Promise<string> {
|
|
91
|
-
if (agent !== 'github-copilot') {
|
|
92
|
-
return 'Status check is currently available for GitHub Copilot CLI only.';
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
const { stdout, stderr } = await execFileAsync('copilot', ['auth', 'status'], {
|
|
97
|
-
timeout: 10_000,
|
|
98
|
-
maxBuffer: 128 * 1024,
|
|
99
|
-
});
|
|
100
|
-
return [stdout, stderr].filter(Boolean).join('\n').trim() || 'GitHub Copilot CLI returned no status output.';
|
|
101
|
-
} catch (error) {
|
|
102
|
-
return error instanceof Error ? error.message : 'GitHub Copilot CLI status check failed.';
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
-
import {
|
|
2
|
+
import { isAgentsServerStandaloneMode } from '../../../../../database/agentsServerDatabaseMode';
|
|
3
3
|
import { resolveCurrentServerRegistryContext } from '../../../../../utils/currentServerRegistryContext';
|
|
4
4
|
import { isUserGlobalAdmin } from '../../../../../utils/isUserGlobalAdmin';
|
|
5
5
|
import {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
updateManagedServer,
|
|
16
16
|
type UpdateServerInput,
|
|
17
17
|
} from '../../../../../utils/serverManagement';
|
|
18
|
+
import { applyStandaloneVpsServerMetadata } from '../../../../../utils/serverManagement/standaloneVpsServerMetadata';
|
|
18
19
|
import {
|
|
19
20
|
applyVpsRuntimeConfiguration,
|
|
20
21
|
listConfiguredVpsDomains,
|
|
@@ -36,8 +37,12 @@ export async function PATCH(request: Request, context: { params: Promise<{ serve
|
|
|
36
37
|
const body = (await request.json()) as Omit<UpdateServerInput, 'id'>;
|
|
37
38
|
const parsedServerId = parseManagedServerId(serverId);
|
|
38
39
|
|
|
39
|
-
if (
|
|
40
|
+
if (isAgentsServerStandaloneMode()) {
|
|
40
41
|
const updatedServer = await updateStandaloneVpsServerDomain(parsedServerId, body.domain);
|
|
42
|
+
await applyStandaloneVpsServerMetadata({
|
|
43
|
+
tablePrefix: updatedServer.tablePrefix,
|
|
44
|
+
name: body.name,
|
|
45
|
+
});
|
|
41
46
|
return NextResponse.json({ server: updatedServer });
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -71,7 +76,7 @@ export async function DELETE(_request: Request, context: { params: Promise<{ ser
|
|
|
71
76
|
const { serverId } = await context.params;
|
|
72
77
|
const parsedServerId = parseManagedServerId(serverId);
|
|
73
78
|
|
|
74
|
-
if (
|
|
79
|
+
if (isAgentsServerStandaloneMode()) {
|
|
75
80
|
await deleteStandaloneVpsServerDomain(parsedServerId);
|
|
76
81
|
return NextResponse.json({
|
|
77
82
|
success: true,
|
|
@@ -126,7 +131,7 @@ async function updateStandaloneVpsServerDomain(serverId: number, rawDomain: stri
|
|
|
126
131
|
const domains = await listConfiguredVpsDomains();
|
|
127
132
|
const nextDomains = domains.map((domain, index) => (index === serverIndex ? normalizedDomain : domain));
|
|
128
133
|
await updateConfiguredVpsDomains(nextDomains);
|
|
129
|
-
await applyVpsRuntimeConfiguration();
|
|
134
|
+
await applyVpsRuntimeConfiguration({ isProcessRestartEnabled: false });
|
|
130
135
|
|
|
131
136
|
const updatedServer = listEnvironmentRegisteredServers().find((server) => server.domain === normalizedDomain);
|
|
132
137
|
if (!updatedServer) {
|
|
@@ -150,5 +155,5 @@ async function deleteStandaloneVpsServerDomain(serverId: number): Promise<void>
|
|
|
150
155
|
|
|
151
156
|
const domains = await listConfiguredVpsDomains();
|
|
152
157
|
await updateConfiguredVpsDomains(domains.filter((_domain, index) => index !== serverIndex));
|
|
153
|
-
await applyVpsRuntimeConfiguration();
|
|
158
|
+
await applyVpsRuntimeConfiguration({ isProcessRestartEnabled: false });
|
|
154
159
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
-
import {
|
|
2
|
+
import { spaceTrim } from 'spacetrim';
|
|
3
|
+
import { DatabaseError } from '../../../../../../../src/errors/DatabaseError';
|
|
4
|
+
import { isAgentsServerStandaloneMode } from '../../../../database/agentsServerDatabaseMode';
|
|
3
5
|
import { resolveCurrentServerRegistryContext } from '../../../../utils/currentServerRegistryContext';
|
|
4
6
|
import { isUserAdmin } from '../../../../utils/isUserAdmin';
|
|
5
7
|
import { isUserGlobalAdmin } from '../../../../utils/isUserGlobalAdmin';
|
|
8
|
+
import { buildServerTablePrefix } from '../../../../utils/buildServerTablePrefix';
|
|
6
9
|
import {
|
|
7
10
|
createServerPublicUrl,
|
|
8
11
|
listEnvironmentRegisteredServers,
|
|
@@ -14,6 +17,12 @@ import {
|
|
|
14
17
|
resolveManagedServerErrorStatus,
|
|
15
18
|
type CreateServerInput,
|
|
16
19
|
} from '../../../../utils/serverManagement';
|
|
20
|
+
import { ManagedServerInputNormalizer } from '../../../../utils/serverManagement/ManagedServerInputNormalizer';
|
|
21
|
+
import {
|
|
22
|
+
applyStandaloneVpsServerMetadata,
|
|
23
|
+
resolveStandaloneVpsServerDisplayName,
|
|
24
|
+
} from '../../../../utils/serverManagement/standaloneVpsServerMetadata';
|
|
25
|
+
import { createStandaloneVpsDomainDnsDiagnostic } from '../../../../utils/standaloneVpsDnsDiagnostics';
|
|
17
26
|
import {
|
|
18
27
|
applyVpsRuntimeConfiguration,
|
|
19
28
|
listConfiguredVpsDomains,
|
|
@@ -32,10 +41,15 @@ export async function GET() {
|
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
const context = await resolveCurrentServerRegistryContext();
|
|
44
|
+
const servers = isAgentsServerStandaloneMode()
|
|
45
|
+
? await createStandaloneVpsServersResponse(context.registeredServers)
|
|
46
|
+
: context.registeredServers;
|
|
47
|
+
|
|
35
48
|
return NextResponse.json({
|
|
36
|
-
servers
|
|
49
|
+
servers,
|
|
37
50
|
currentServerId: context.currentServer?.id ?? null,
|
|
38
51
|
canEdit: await isUserGlobalAdmin(),
|
|
52
|
+
isStandaloneVps: isAgentsServerStandaloneMode(),
|
|
39
53
|
});
|
|
40
54
|
} catch (error) {
|
|
41
55
|
return NextResponse.json(
|
|
@@ -47,6 +61,30 @@ export async function GET() {
|
|
|
47
61
|
}
|
|
48
62
|
}
|
|
49
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Enriches standalone VPS server rows with display metadata and DNS diagnostics.
|
|
66
|
+
*
|
|
67
|
+
* @param servers - Virtual standalone server rows.
|
|
68
|
+
* @returns Browser-safe server rows with DNS setup guidance.
|
|
69
|
+
*/
|
|
70
|
+
async function createStandaloneVpsServersResponse(
|
|
71
|
+
servers: Awaited<ReturnType<typeof resolveCurrentServerRegistryContext>>['registeredServers'],
|
|
72
|
+
) {
|
|
73
|
+
const primaryDomain = servers[0]?.domain ?? null;
|
|
74
|
+
|
|
75
|
+
return Promise.all(
|
|
76
|
+
servers.map(async (server) => ({
|
|
77
|
+
...server,
|
|
78
|
+
name: await resolveStandaloneVpsServerDisplayName(server),
|
|
79
|
+
dnsDiagnostic: await createStandaloneVpsDomainDnsDiagnostic({
|
|
80
|
+
domain: server.domain,
|
|
81
|
+
publicIpAddress: process.env.PTBK_PUBLIC_IP_ADDRESS,
|
|
82
|
+
fallbackCnameTargetDomain: primaryDomain && primaryDomain !== server.domain ? primaryDomain : null,
|
|
83
|
+
}),
|
|
84
|
+
})),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
50
88
|
/**
|
|
51
89
|
* Creates a new same-instance server.
|
|
52
90
|
*
|
|
@@ -57,17 +95,25 @@ export async function POST(request: Request) {
|
|
|
57
95
|
try {
|
|
58
96
|
assertGlobalAdminAccess(await isUserGlobalAdmin());
|
|
59
97
|
|
|
60
|
-
const body = (await request.json()) as CreateServerInput;
|
|
61
|
-
if (
|
|
98
|
+
const body = withEnvironmentAdminUser((await request.json()) as CreateServerInput);
|
|
99
|
+
if (isAgentsServerStandaloneMode()) {
|
|
62
100
|
const normalizedDomain = normalizeServerDomain(body.domain);
|
|
63
101
|
if (!normalizedDomain) {
|
|
64
102
|
return NextResponse.json({ error: 'A valid domain is required.' }, { status: 400 });
|
|
65
103
|
}
|
|
104
|
+
const tablePrefix = normalizeStandaloneVpsCreateServerTablePrefix(body);
|
|
66
105
|
|
|
67
106
|
const existingDomains = await listConfiguredVpsDomains();
|
|
68
|
-
await updateConfiguredVpsDomains([...existingDomains, normalizedDomain]);
|
|
69
|
-
await applyVpsRuntimeConfiguration();
|
|
107
|
+
await updateConfiguredVpsDomains([...existingDomains, normalizedDomain], { tablePrefix });
|
|
108
|
+
await applyVpsRuntimeConfiguration({ isProcessRestartEnabled: false });
|
|
70
109
|
const createdServer = listEnvironmentRegisteredServers().find((server) => server.domain === normalizedDomain);
|
|
110
|
+
if (createdServer) {
|
|
111
|
+
await applyStandaloneVpsServerMetadata({
|
|
112
|
+
tablePrefix: createdServer.tablePrefix,
|
|
113
|
+
name: body.name,
|
|
114
|
+
iconUrl: body.iconUrl,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
71
117
|
|
|
72
118
|
return NextResponse.json(
|
|
73
119
|
{
|
|
@@ -107,3 +153,48 @@ export async function POST(request: Request) {
|
|
|
107
153
|
);
|
|
108
154
|
}
|
|
109
155
|
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Uses the installer-managed environment admin when the browser no longer collects admin credentials.
|
|
159
|
+
*
|
|
160
|
+
* @param input - Raw create-server payload.
|
|
161
|
+
* @returns Payload compatible with the existing managed-server bootstrap flow.
|
|
162
|
+
*/
|
|
163
|
+
function withEnvironmentAdminUser(input: CreateServerInput): CreateServerInput {
|
|
164
|
+
const adminPassword = process.env.ADMIN_PASSWORD || input.adminUser?.password || '';
|
|
165
|
+
const adminUsername = input.adminUser?.username?.trim() || 'admin';
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
...input,
|
|
169
|
+
adminUser: {
|
|
170
|
+
username: adminUsername,
|
|
171
|
+
password: adminPassword,
|
|
172
|
+
isAdmin: true,
|
|
173
|
+
},
|
|
174
|
+
additionalUsers: input.additionalUsers || [],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Validates the generated server table prefix used by standalone VPS setup.
|
|
180
|
+
*
|
|
181
|
+
* @param input - Create-server payload with generated identifier and table prefix.
|
|
182
|
+
* @returns Validated server-level table prefix.
|
|
183
|
+
*/
|
|
184
|
+
function normalizeStandaloneVpsCreateServerTablePrefix(input: CreateServerInput): string {
|
|
185
|
+
const identifier = ManagedServerInputNormalizer.normalizeServerIdentifier(input.identifier);
|
|
186
|
+
const tablePrefix = ManagedServerInputNormalizer.validateServerTablePrefix(input.tablePrefix);
|
|
187
|
+
const expectedTablePrefix = buildServerTablePrefix(identifier);
|
|
188
|
+
|
|
189
|
+
if (tablePrefix !== expectedTablePrefix) {
|
|
190
|
+
throw new DatabaseError(
|
|
191
|
+
spaceTrim(`
|
|
192
|
+
Table prefix \`${tablePrefix}\` does not match generated server identifier \`${identifier}\`.
|
|
193
|
+
|
|
194
|
+
Expected \`${expectedTablePrefix}\`.
|
|
195
|
+
`),
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return tablePrefix;
|
|
200
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { isUserGlobalAdmin } from '@/src/utils/isUserGlobalAdmin';
|
|
3
|
+
import { readVpsSelfUpdateOverview, startVpsSelfUpdate } from '@/src/utils/vpsSelfUpdate';
|
|
4
|
+
|
|
5
|
+
export const runtime = 'nodejs';
|
|
6
|
+
export const dynamic = 'force-dynamic';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Loads the current standalone VPS self-update overview for the super-admin UI.
|
|
10
|
+
*/
|
|
11
|
+
export async function GET() {
|
|
12
|
+
if (!(await isUserGlobalAdmin())) {
|
|
13
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
return NextResponse.json(await readVpsSelfUpdateOverview());
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return NextResponse.json(
|
|
20
|
+
{ error: error instanceof Error ? error.message : 'Failed to load the update overview.' },
|
|
21
|
+
{ status: 500 },
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Starts a detached standalone VPS self-update for the selected environment.
|
|
28
|
+
*/
|
|
29
|
+
export async function POST(request: Request) {
|
|
30
|
+
if (!(await isUserGlobalAdmin())) {
|
|
31
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const body = (await request.json().catch(() => null)) as
|
|
36
|
+
| {
|
|
37
|
+
readonly environment?: string;
|
|
38
|
+
}
|
|
39
|
+
| null;
|
|
40
|
+
|
|
41
|
+
if (!body?.environment || typeof body.environment !== 'string') {
|
|
42
|
+
return NextResponse.json({ error: 'Update environment is required.' }, { status: 400 });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return NextResponse.json(await startVpsSelfUpdate(body.environment), { status: 202 });
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return NextResponse.json(
|
|
48
|
+
{ error: error instanceof Error ? error.message : 'Failed to start the update.' },
|
|
49
|
+
{ status: 500 },
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { authenticateUser } from '../../../../utils/authenticateUser';
|
|
2
2
|
import { setSession } from '../../../../utils/session';
|
|
3
|
+
import { writeShibbolethAuthenticationLog } from '../../../../utils/shibboleth/writeShibbolethAuthenticationLog';
|
|
3
4
|
import { NextResponse } from 'next/server';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -7,6 +8,13 @@ import { NextResponse } from 'next/server';
|
|
|
7
8
|
*/
|
|
8
9
|
export async function POST(request: Request) {
|
|
9
10
|
try {
|
|
11
|
+
writeShibbolethAuthenticationLog(request.headers, {
|
|
12
|
+
event: 'login-route-request',
|
|
13
|
+
pathname: '/api/auth/login',
|
|
14
|
+
method: request.method,
|
|
15
|
+
hasSessionCookie: (request.headers.get('cookie') || '').includes('sessionToken='),
|
|
16
|
+
});
|
|
17
|
+
|
|
10
18
|
const body = await request.json();
|
|
11
19
|
const { username, password } = body;
|
|
12
20
|
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import { clearSession } from '../../../../utils/session';
|
|
2
1
|
import { NextResponse } from 'next/server';
|
|
2
|
+
import { clearSession } from '../../../../utils/session';
|
|
3
|
+
import { writeShibbolethAuthenticationLog } from '../../../../utils/shibboleth/writeShibbolethAuthenticationLog';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Handles post.
|
|
6
7
|
*/
|
|
7
|
-
export async function POST() {
|
|
8
|
+
export async function POST(request: Request) {
|
|
9
|
+
writeShibbolethAuthenticationLog(request.headers, {
|
|
10
|
+
event: 'logout-route-request',
|
|
11
|
+
pathname: '/api/auth/logout',
|
|
12
|
+
method: request.method,
|
|
13
|
+
hasSessionCookie: (request.headers.get('cookie') || '').includes('sessionToken='),
|
|
14
|
+
});
|
|
15
|
+
|
|
8
16
|
await clearSession();
|
|
9
17
|
return NextResponse.json({ success: true });
|
|
10
18
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
resolveRegisteredServerByHost,
|
|
14
14
|
type ServerRecord,
|
|
15
15
|
} from '../utils/serverRegistry';
|
|
16
|
+
import { isStandaloneVpsRawIpBootstrapActive } from '../utils/standaloneVpsRawIpBootstrap';
|
|
16
17
|
import { getHomePageAgents } from './_data/getHomePageAgents';
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -77,6 +78,15 @@ async function resolveIpAddressRouting(host: string | null): Promise<'LOGIN' | '
|
|
|
77
78
|
return (await isUserGlobalAdmin()) ? 'CONFIGURE' : 'LOGIN';
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
if (
|
|
82
|
+
isStandaloneVpsRawIpBootstrapActive({
|
|
83
|
+
nextPublicSiteUrl: process.env.NEXT_PUBLIC_SITE_URL,
|
|
84
|
+
publicIpAddress: process.env.PTBK_PUBLIC_IP_ADDRESS,
|
|
85
|
+
})
|
|
86
|
+
) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
if (registeredServers.length === 1) {
|
|
81
91
|
redirect(createServerPublicUrl(registeredServers[0]!.domain).href);
|
|
82
92
|
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Code2,
|
|
4
4
|
Globe2,
|
|
5
5
|
KeyRound,
|
|
6
|
+
RefreshCw,
|
|
6
7
|
Settings2,
|
|
7
8
|
UserRound,
|
|
8
9
|
Wrench,
|
|
@@ -202,6 +203,11 @@ export function buildHeaderSystemMenuItems({
|
|
|
202
203
|
},
|
|
203
204
|
...(isGlobalAdmin
|
|
204
205
|
? [
|
|
206
|
+
{
|
|
207
|
+
label: translate('header.update'),
|
|
208
|
+
href: '/admin/update',
|
|
209
|
+
icon: RefreshCw,
|
|
210
|
+
} as SubMenuItem,
|
|
205
211
|
{
|
|
206
212
|
label: translate('header.database'),
|
|
207
213
|
href: '/admin/database',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { $isRunningInNode } from '@promptbook-local/utils';
|
|
2
|
-
import {
|
|
3
|
-
import { resolvePostgresConnectionString } from './resolvePostgresConnectionString';
|
|
2
|
+
import { $providePostgresPool } from './$providePostgresPool';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* SQL tagged-template executor used by server routes and utilities.
|
|
@@ -31,13 +30,6 @@ export type ClientSqlExecutor = ClientSql & {
|
|
|
31
30
|
readonly raw: ClientSqlRaw;
|
|
32
31
|
};
|
|
33
32
|
|
|
34
|
-
/**
|
|
35
|
-
* Shared PostgreSQL pool reused across all requests in the server process.
|
|
36
|
-
*
|
|
37
|
-
* @private internal singleton of Agents Server database layer
|
|
38
|
-
*/
|
|
39
|
-
let clientPool: Pool | undefined;
|
|
40
|
-
|
|
41
33
|
/**
|
|
42
34
|
* Provides SQL tagged-template client for server-side PostgreSQL access.
|
|
43
35
|
*
|
|
@@ -48,12 +40,7 @@ export async function $provideClientSql(): Promise<ClientSqlExecutor> {
|
|
|
48
40
|
throw new Error('Function `$provideClientSql` can only be used in Node.js runtime.');
|
|
49
41
|
}
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
clientPool = new Pool({
|
|
53
|
-
connectionString: resolvePostgresConnectionString(),
|
|
54
|
-
ssl: { rejectUnauthorized: false },
|
|
55
|
-
});
|
|
56
|
-
}
|
|
43
|
+
const clientPool = $providePostgresPool();
|
|
57
44
|
|
|
58
45
|
const executeTemplate = async <TRow = Array<Record<string, unknown>>>(
|
|
59
46
|
templateStrings: TemplateStringsArray,
|
|
@@ -68,7 +55,7 @@ export async function $provideClientSql(): Promise<ClientSqlExecutor> {
|
|
|
68
55
|
}
|
|
69
56
|
|
|
70
57
|
const text = textChunks.join('');
|
|
71
|
-
const result = await clientPool
|
|
58
|
+
const result = await clientPool.query(text, [...templateValues]);
|
|
72
59
|
return result.rows as TRow;
|
|
73
60
|
};
|
|
74
61
|
|
|
@@ -76,7 +63,7 @@ export async function $provideClientSql(): Promise<ClientSqlExecutor> {
|
|
|
76
63
|
text: string,
|
|
77
64
|
values: ReadonlyArray<unknown> = [],
|
|
78
65
|
): Promise<TRow> => {
|
|
79
|
-
const result = await clientPool
|
|
66
|
+
const result = await clientPool.query(text, [...values]);
|
|
80
67
|
return result.rows as TRow;
|
|
81
68
|
};
|
|
82
69
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { StudioBFFSqlLintDetails, StudioBFFSqlLintResult } from '@prisma/studio-core/data/bff';
|
|
2
|
-
import { Pool,
|
|
2
|
+
import type { Pool, PoolClient } from 'pg';
|
|
3
|
+
import { $providePostgresPool } from './$providePostgresPool';
|
|
3
4
|
import { isAgentsServerSqliteMode } from './agentsServerDatabaseMode';
|
|
4
|
-
import { resolvePostgresConnectionString } from './resolvePostgresConnectionString';
|
|
5
5
|
import {
|
|
6
6
|
$provideAgentsServerSqliteDatabase,
|
|
7
7
|
type AgentsServerSqliteDatabase,
|
|
@@ -31,11 +31,6 @@ export type DatabaseAdminExecutor = {
|
|
|
31
31
|
readonly lintSql: (details: StudioBFFSqlLintDetails) => Promise<StudioBFFSqlLintResult>;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
* Shared PostgreSQL pool for Embedded Prisma Studio requests.
|
|
36
|
-
*/
|
|
37
|
-
let databaseAdminPostgresPool: Pool | null = null;
|
|
38
|
-
|
|
39
34
|
/**
|
|
40
35
|
* Provides a raw SQL executor for the configured Agents Server database backend.
|
|
41
36
|
*
|
|
@@ -53,7 +48,7 @@ export function $provideDatabaseAdminExecutor(): DatabaseAdminExecutor {
|
|
|
53
48
|
* @returns PostgreSQL-backed database admin executor.
|
|
54
49
|
*/
|
|
55
50
|
function $providePostgresDatabaseAdminExecutor(): DatabaseAdminExecutor {
|
|
56
|
-
const pool = $
|
|
51
|
+
const pool = $providePostgresPool();
|
|
57
52
|
|
|
58
53
|
return {
|
|
59
54
|
execute: (query) => executePostgresDatabaseAdminQuery(pool, query),
|
|
@@ -82,22 +77,6 @@ function $provideSqliteDatabaseAdminExecutor(): DatabaseAdminExecutor {
|
|
|
82
77
|
};
|
|
83
78
|
}
|
|
84
79
|
|
|
85
|
-
/**
|
|
86
|
-
* Provides the shared PostgreSQL connection pool for raw database admin access.
|
|
87
|
-
*
|
|
88
|
-
* @returns Shared PostgreSQL pool.
|
|
89
|
-
*/
|
|
90
|
-
function $provideDatabaseAdminPostgresPool(): Pool {
|
|
91
|
-
if (!databaseAdminPostgresPool) {
|
|
92
|
-
databaseAdminPostgresPool = new Pool({
|
|
93
|
-
connectionString: resolvePostgresConnectionString(),
|
|
94
|
-
ssl: { rejectUnauthorized: false },
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return databaseAdminPostgresPool;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
80
|
/**
|
|
102
81
|
* Executes one PostgreSQL query for Embedded Prisma Studio.
|
|
103
82
|
*
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
import { resolvePostgresConnectionString } from './resolvePostgresConnectionString';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared PostgreSQL pool reused across the Agents Server process.
|
|
6
|
+
*
|
|
7
|
+
* @private internal singleton of Agents Server database layer
|
|
8
|
+
*/
|
|
9
|
+
let postgresPool: Pool | null = null;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Provides the shared PostgreSQL pool used by raw SQL helpers and local PostgreSQL adapters.
|
|
13
|
+
*
|
|
14
|
+
* @returns Shared PostgreSQL pool.
|
|
15
|
+
*
|
|
16
|
+
* @private exported from Agents Server database utilities
|
|
17
|
+
*/
|
|
18
|
+
export function $providePostgresPool(): Pool {
|
|
19
|
+
if (!postgresPool) {
|
|
20
|
+
postgresPool = new Pool({
|
|
21
|
+
connectionString: resolvePostgresConnectionString(),
|
|
22
|
+
ssl: { rejectUnauthorized: false },
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return postgresPool;
|
|
27
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
1
2
|
import { $isRunningInNode } from '@promptbook-local/utils';
|
|
2
3
|
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
-
import { isAgentsServerSqliteMode } from './agentsServerDatabaseMode';
|
|
4
|
+
import { isAgentsServerPostgresMode, isAgentsServerSqliteMode } from './agentsServerDatabaseMode';
|
|
4
5
|
import { $provideLocalSqliteSupabase } from './sqlite/$provideLocalSqliteSupabase';
|
|
5
6
|
import { AgentsServerDatabase } from './schema';
|
|
6
7
|
|
|
8
|
+
const requirePostgresSupabase = createRequire(__filename);
|
|
9
|
+
|
|
7
10
|
/**
|
|
8
11
|
* Internal cache for `$provideSupabaseForServer`
|
|
9
12
|
*
|
|
@@ -32,6 +35,13 @@ export function $provideSupabaseForServer(): SupabaseClient<AgentsServerDatabase
|
|
|
32
35
|
return $provideLocalSqliteSupabase() as SupabaseClient<AgentsServerDatabase>;
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
if (isAgentsServerPostgresMode()) {
|
|
39
|
+
const { $provideLocalPostgresSupabase } = requirePostgresSupabase(
|
|
40
|
+
'./postgres/$provideLocalPostgresSupabase',
|
|
41
|
+
) as typeof import('./postgres/$provideLocalPostgresSupabase');
|
|
42
|
+
return $provideLocalPostgresSupabase() as SupabaseClient<AgentsServerDatabase>;
|
|
43
|
+
}
|
|
44
|
+
|
|
35
45
|
if (!supabase) {
|
|
36
46
|
// Create a single supabase client for interacting with your database
|
|
37
47
|
supabase = createClient<AgentsServerDatabase>(
|
|
@@ -11,7 +11,7 @@ export const AGENTS_SERVER_SQLITE_PATH_ENV_NAME = 'PTBK_AGENTS_SERVER_SQLITE_PAT
|
|
|
11
11
|
/**
|
|
12
12
|
* Supported Agents Server database backends.
|
|
13
13
|
*/
|
|
14
|
-
export type AgentsServerDatabaseMode = 'supabase' | 'sqlite';
|
|
14
|
+
export type AgentsServerDatabaseMode = 'supabase' | 'sqlite' | 'postgres';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Resolves the configured Agents Server database backend.
|
|
@@ -23,6 +23,10 @@ export function resolveAgentsServerDatabaseMode(): AgentsServerDatabaseMode {
|
|
|
23
23
|
return 'sqlite';
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
if (rawMode === 'postgres' || rawMode === 'postgresql') {
|
|
27
|
+
return 'postgres';
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
return 'supabase';
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -32,3 +36,18 @@ export function resolveAgentsServerDatabaseMode(): AgentsServerDatabaseMode {
|
|
|
32
36
|
export function isAgentsServerSqliteMode(): boolean {
|
|
33
37
|
return resolveAgentsServerDatabaseMode() === 'sqlite';
|
|
34
38
|
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns whether the Agents Server is using the standalone PostgreSQL backend.
|
|
42
|
+
*/
|
|
43
|
+
export function isAgentsServerPostgresMode(): boolean {
|
|
44
|
+
return resolveAgentsServerDatabaseMode() === 'postgres';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Returns whether the Agents Server is using a standalone local database backend.
|
|
49
|
+
*/
|
|
50
|
+
export function isAgentsServerStandaloneMode(): boolean {
|
|
51
|
+
const databaseMode = resolveAgentsServerDatabaseMode();
|
|
52
|
+
return databaseMode === 'sqlite' || databaseMode === 'postgres';
|
|
53
|
+
}
|