@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.
Files changed (62) hide show
  1. package/apps/agents-server/README.md +3 -3
  2. package/apps/agents-server/playwright.config.ts +2 -1
  3. package/apps/agents-server/src/app/admin/code-runners/CodeRunnersClient.tsx +358 -19
  4. package/apps/agents-server/src/app/admin/database/page.tsx +2 -1
  5. package/apps/agents-server/src/app/admin/servers/CreateServerDialog.tsx +46 -505
  6. package/apps/agents-server/src/app/admin/servers/ServersClient.tsx +23 -11
  7. package/apps/agents-server/src/app/admin/servers/ServersRegistryApi.ts +5 -0
  8. package/apps/agents-server/src/app/admin/servers/ServersRegistryDnsTypes.ts +87 -0
  9. package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +258 -128
  10. package/apps/agents-server/src/app/admin/servers/useCreateServerWizard.ts +46 -334
  11. package/apps/agents-server/src/app/admin/servers/useServersRegistryState.ts +26 -2
  12. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +435 -0
  13. package/apps/agents-server/src/app/admin/update/page.tsx +14 -0
  14. package/apps/agents-server/src/app/api/admin/code-runners/authentication/route.ts +197 -0
  15. package/apps/agents-server/src/app/api/admin/code-runners/route.ts +4 -35
  16. package/apps/agents-server/src/app/api/admin/servers/[serverId]/route.ts +10 -5
  17. package/apps/agents-server/src/app/api/admin/servers/route.ts +97 -6
  18. package/apps/agents-server/src/app/api/admin/update/route.ts +52 -0
  19. package/apps/agents-server/src/app/api/auth/login/route.ts +8 -0
  20. package/apps/agents-server/src/app/api/auth/logout/route.ts +10 -2
  21. package/apps/agents-server/src/app/page.tsx +10 -0
  22. package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +6 -0
  23. package/apps/agents-server/src/database/$provideClientSql.ts +4 -17
  24. package/apps/agents-server/src/database/$provideDatabaseAdminExecutor.ts +3 -24
  25. package/apps/agents-server/src/database/$providePostgresPool.ts +27 -0
  26. package/apps/agents-server/src/database/$provideSupabaseForServer.ts +11 -1
  27. package/apps/agents-server/src/database/agentsServerDatabaseMode.ts +20 -1
  28. package/apps/agents-server/src/database/postgres/$provideLocalPostgresSupabase.ts +1261 -0
  29. package/apps/agents-server/src/languages/ServerTranslationKeys.ts +1 -0
  30. package/apps/agents-server/src/languages/translations/czech.yaml +1 -0
  31. package/apps/agents-server/src/languages/translations/english.yaml +1 -0
  32. package/apps/agents-server/src/middleware.ts +32 -0
  33. package/apps/agents-server/src/tools/$provideServer.ts +2 -2
  34. package/apps/agents-server/src/utils/codeRunnerAuthentication.ts +394 -0
  35. package/apps/agents-server/src/utils/codeRunnerConfiguration.ts +67 -0
  36. package/apps/agents-server/src/utils/serverManagement/standaloneVpsServerMetadata.ts +145 -0
  37. package/apps/agents-server/src/utils/serverRegistry.ts +7 -6
  38. package/apps/agents-server/src/utils/session.ts +37 -9
  39. package/apps/agents-server/src/utils/shibboleth/createShibbolethAuthenticationLogPayload.ts +173 -0
  40. package/apps/agents-server/src/utils/shibboleth/writeShibbolethAuthenticationLog.ts +27 -0
  41. package/apps/agents-server/src/utils/standaloneVpsDnsDiagnostics.ts +258 -0
  42. package/apps/agents-server/src/utils/standaloneVpsRawIpBootstrap.ts +87 -0
  43. package/apps/agents-server/src/utils/vpsConfiguration.ts +87 -15
  44. package/apps/agents-server/src/utils/vpsSelfUpdate.ts +664 -0
  45. package/esm/apps/agents-server/src/database/agentsServerDatabaseMode.d.ts +9 -1
  46. package/esm/apps/agents-server/src/utils/serverRegistry.d.ts +1 -1
  47. package/esm/index.es.js +8 -6
  48. package/esm/index.es.js.map +1 -1
  49. package/esm/src/version.d.ts +1 -1
  50. package/package.json +1 -1
  51. package/src/book-components/Chat/utils/renderMarkdown.ts +1 -3
  52. package/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.ts +1 -1
  53. package/src/other/templates/getTemplatesPipelineCollection.ts +698 -755
  54. package/src/scrapers/document/DocumentScraper.ts +1 -1
  55. package/src/scrapers/document-legacy/LegacyDocumentScraper.ts +1 -1
  56. package/src/version.ts +2 -2
  57. package/src/versions.txt +1 -0
  58. package/umd/apps/agents-server/src/database/agentsServerDatabaseMode.d.ts +9 -1
  59. package/umd/apps/agents-server/src/utils/serverRegistry.d.ts +1 -1
  60. package/umd/index.umd.js +8 -6
  61. package/umd/index.umd.js.map +1 -1
  62. package/umd/src/version.d.ts +1 -1
@@ -1,20 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { Loader2, Plus, Trash2, X } from 'lucide-react';
3
+ import { Loader2, Plus, Upload, X } from 'lucide-react';
4
4
  import type { ChangeEvent, RefObject } from 'react';
5
5
  import { Dialog } from '../../../components/Portal/Dialog';
6
- import { SecretInput } from '../../../components/SecretInput/SecretInput';
7
- import { SERVER_LANGUAGE_OPTIONS } from '../../../languages/ServerLanguageRegistry';
8
- import { CHAT_FEEDBACK_MODE_OPTIONS } from '../../../utils/chatFeedbackMode';
9
- import { MANAGED_SERVER_ENVIRONMENT_OPTIONS } from './useServersRegistryState';
10
6
  import {
11
- CREATE_SERVER_BOOLEAN_FEATURE_FLAGS,
12
- CREATE_SERVER_WIZARD_STEPS,
13
7
  type CreateServerWizardError,
14
8
  type CreateServerWizardState,
15
- type UpdateCreateServerAdditionalUser,
16
- type UpdateCreateServerAdminField,
17
- type UpdateCreateServerInitialSetting,
18
9
  type UpdateCreateServerWizardField,
19
10
  } from './useCreateServerWizard';
20
11
 
@@ -26,13 +17,6 @@ import {
26
17
  const INPUT_CLASS_NAME =
27
18
  'w-full rounded-md border border-gray-300 px-3 py-2 text-sm text-gray-900 shadow-sm focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200';
28
19
 
29
- /**
30
- * Shared textarea class used across the create-server dialog.
31
- *
32
- * @private function of <ServersClient/>
33
- */
34
- const TEXTAREA_CLASS_NAME = `${INPUT_CLASS_NAME} min-h-[120px]`;
35
-
36
20
  /**
37
21
  * Shared secondary button styling used by the create-server dialog.
38
22
  *
@@ -49,30 +33,12 @@ const SECONDARY_BUTTON_CLASS_NAME =
49
33
  const PRIMARY_BUTTON_CLASS_NAME =
50
34
  'inline-flex items-center gap-2 rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60';
51
35
 
52
- /**
53
- * Shared destructive button styling used by the create-server dialog.
54
- *
55
- * @private function of <ServersClient/>
56
- */
57
- const DANGER_BUTTON_CLASS_NAME =
58
- 'inline-flex items-center gap-2 rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white hover:bg-red-700 disabled:cursor-not-allowed disabled:opacity-60';
59
-
60
36
  /**
61
37
  * Props consumed by `CreateServerDialog`.
62
38
  *
63
39
  * @private function of <ServersClient/>
64
40
  */
65
41
  type CreateServerDialogProps = {
66
- /**
67
- * Adds a new optional bootstrap user row.
68
- */
69
- readonly addAdditionalUser: () => void;
70
-
71
- /**
72
- * Derived table-prefix preview for the current identifier.
73
- */
74
- readonly derivedWizardTablePrefix: string;
75
-
76
42
  /**
77
43
  * Persists the current wizard as a new server.
78
44
  */
@@ -83,21 +49,6 @@ type CreateServerDialogProps = {
83
49
  */
84
50
  readonly handleIconUpload: (event: ChangeEvent<HTMLInputElement>) => Promise<void>;
85
51
 
86
- /**
87
- * Moves the wizard one step backward.
88
- */
89
- readonly handleWizardBack: () => void;
90
-
91
- /**
92
- * Moves the wizard one step forward.
93
- */
94
- readonly handleWizardNext: () => Promise<void>;
95
-
96
- /**
97
- * Jumps to a specific wizard step when allowed.
98
- */
99
- readonly handleWizardStepSelection: (nextStep: number) => Promise<void>;
100
-
101
52
  /**
102
53
  * Hidden file input reference used for icon uploads.
103
54
  */
@@ -118,11 +69,6 @@ type CreateServerDialogProps = {
118
69
  */
119
70
  readonly isUploadingIcon: boolean;
120
71
 
121
- /**
122
- * Removes one optional bootstrap user row.
123
- */
124
- readonly removeAdditionalUser: (index: number) => void;
125
-
126
72
  /**
127
73
  * Requests closing the dialog while respecting the dirty-state guard.
128
74
  */
@@ -133,21 +79,6 @@ type CreateServerDialogProps = {
133
79
  */
134
80
  readonly resetWizard: () => void;
135
81
 
136
- /**
137
- * Updates one optional bootstrap user row.
138
- */
139
- readonly updateAdditionalUser: UpdateCreateServerAdditionalUser;
140
-
141
- /**
142
- * Updates the required admin user fields.
143
- */
144
- readonly updateAdminUser: UpdateCreateServerAdminField;
145
-
146
- /**
147
- * Updates one initial settings field.
148
- */
149
- readonly updateInitialSetting: UpdateCreateServerInitialSetting;
150
-
151
82
  /**
152
83
  * Updates one top-level wizard field.
153
84
  */
@@ -162,49 +93,6 @@ type CreateServerDialogProps = {
162
93
  * Current create-server form state.
163
94
  */
164
95
  readonly wizardState: CreateServerWizardState;
165
-
166
- /**
167
- * Current wizard step index.
168
- */
169
- readonly wizardStep: number;
170
- };
171
-
172
- /**
173
- * Props consumed by the profile-step helper.
174
- *
175
- * @private function of <ServersClient/>
176
- */
177
- type CreateServerProfileStepProps = {
178
- readonly derivedWizardTablePrefix: string;
179
- readonly handleIconUpload: (event: ChangeEvent<HTMLInputElement>) => Promise<void>;
180
- readonly iconInputRef: RefObject<HTMLInputElement | null>;
181
- readonly isUploadingIcon: boolean;
182
- readonly updateWizardField: UpdateCreateServerWizardField;
183
- readonly wizardState: CreateServerWizardState;
184
- };
185
-
186
- /**
187
- * Props consumed by the users-step helper.
188
- *
189
- * @private function of <ServersClient/>
190
- */
191
- type CreateServerUsersStepProps = {
192
- readonly addAdditionalUser: () => void;
193
- readonly removeAdditionalUser: (index: number) => void;
194
- readonly updateAdditionalUser: UpdateCreateServerAdditionalUser;
195
- readonly updateAdminUser: UpdateCreateServerAdminField;
196
- readonly wizardState: CreateServerWizardState;
197
- };
198
-
199
- /**
200
- * Props consumed by the settings-step helper.
201
- *
202
- * @private function of <ServersClient/>
203
- */
204
- type CreateServerSettingsStepProps = {
205
- readonly derivedWizardTablePrefix: string;
206
- readonly updateInitialSetting: UpdateCreateServerInitialSetting;
207
- readonly wizardState: CreateServerWizardState;
208
96
  };
209
97
 
210
98
  /**
@@ -224,23 +112,22 @@ function downloadTextFile(filename: string, content: string): void {
224
112
  }
225
113
 
226
114
  /**
227
- * Renders the profile step of the create-server wizard.
115
+ * Renders the visible fields of the simplified create-server flow.
228
116
  *
229
- * @param props - Step props.
230
- * @returns Profile-step form fields.
117
+ * @param props - Form props.
118
+ * @returns Simplified server setup form.
231
119
  */
232
- function CreateServerProfileStep(props: CreateServerProfileStepProps) {
233
- const {
234
- derivedWizardTablePrefix,
235
- handleIconUpload,
236
- iconInputRef,
237
- isUploadingIcon,
238
- updateWizardField,
239
- wizardState,
240
- } = props;
120
+ function CreateServerForm(props: {
121
+ readonly handleIconUpload: (event: ChangeEvent<HTMLInputElement>) => Promise<void>;
122
+ readonly iconInputRef: RefObject<HTMLInputElement | null>;
123
+ readonly isUploadingIcon: boolean;
124
+ readonly updateWizardField: UpdateCreateServerWizardField;
125
+ readonly wizardState: CreateServerWizardState;
126
+ }) {
127
+ const { handleIconUpload, iconInputRef, isUploadingIcon, updateWizardField, wizardState } = props;
241
128
 
242
129
  return (
243
- <div className="grid gap-4 md:grid-cols-2">
130
+ <div className="space-y-5">
244
131
  <div>
245
132
  <label htmlFor="create-server-name" className="mb-1 block text-sm font-medium text-gray-700">
246
133
  Server name
@@ -254,53 +141,8 @@ function CreateServerProfileStep(props: CreateServerProfileStepProps) {
254
141
  placeholder="Acme Support"
255
142
  />
256
143
  </div>
144
+
257
145
  <div>
258
- <label htmlFor="create-server-identifier" className="mb-1 block text-sm font-medium text-gray-700">
259
- Identifier / slug
260
- </label>
261
- <input
262
- id="create-server-identifier"
263
- type="text"
264
- value={wizardState.identifier}
265
- onChange={(event) => updateWizardField('identifier', event.target.value.toLowerCase())}
266
- className={`${INPUT_CLASS_NAME} font-mono`}
267
- placeholder="acme-support"
268
- />
269
- <p className="mt-1 text-xs text-gray-500">Use lowercase letters, numbers, and hyphens only.</p>
270
- </div>
271
- <div>
272
- <label htmlFor="create-server-table-prefix" className="mb-1 block text-sm font-medium text-gray-700">
273
- Derived table prefix
274
- </label>
275
- <input
276
- id="create-server-table-prefix"
277
- type="text"
278
- value={derivedWizardTablePrefix}
279
- readOnly
280
- className={`${INPUT_CLASS_NAME} bg-gray-50 font-mono text-gray-600`}
281
- placeholder="server_AcmeSupport_"
282
- />
283
- </div>
284
- <div>
285
- <label htmlFor="create-server-environment" className="mb-1 block text-sm font-medium text-gray-700">
286
- Environment
287
- </label>
288
- <select
289
- id="create-server-environment"
290
- value={wizardState.environment}
291
- onChange={(event) =>
292
- updateWizardField('environment', event.target.value as CreateServerWizardState['environment'])
293
- }
294
- className={INPUT_CLASS_NAME}
295
- >
296
- {MANAGED_SERVER_ENVIRONMENT_OPTIONS.map((environment) => (
297
- <option key={environment} value={environment}>
298
- {environment}
299
- </option>
300
- ))}
301
- </select>
302
- </div>
303
- <div className="md:col-span-2">
304
146
  <label htmlFor="create-server-domain" className="mb-1 block text-sm font-medium text-gray-700">
305
147
  Domain
306
148
  </label>
@@ -313,18 +155,19 @@ function CreateServerProfileStep(props: CreateServerProfileStepProps) {
313
155
  placeholder="acme-support.ptbk.io"
314
156
  />
315
157
  </div>
316
- <div className="md:col-span-2">
158
+
159
+ <div>
317
160
  <label htmlFor="create-server-icon-url" className="mb-1 block text-sm font-medium text-gray-700">
318
161
  Server icon
319
162
  </label>
320
- <div className="flex flex-col gap-3 lg:flex-row">
163
+ <div className="flex flex-col gap-3 sm:flex-row">
321
164
  <input
322
165
  id="create-server-icon-url"
323
166
  type="text"
324
167
  value={wizardState.iconUrl}
325
168
  onChange={(event) => updateWizardField('iconUrl', event.target.value)}
326
169
  className={INPUT_CLASS_NAME}
327
- placeholder="Leave blank to keep the default icon"
170
+ placeholder="Optional icon URL"
328
171
  />
329
172
  <input
330
173
  ref={iconInputRef}
@@ -339,8 +182,8 @@ function CreateServerProfileStep(props: CreateServerProfileStepProps) {
339
182
  disabled={isUploadingIcon}
340
183
  className={SECONDARY_BUTTON_CLASS_NAME}
341
184
  >
342
- {isUploadingIcon ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
343
- Upload icon
185
+ {isUploadingIcon ? <Loader2 className="h-4 w-4 animate-spin" /> : <Upload className="h-4 w-4" />}
186
+ Upload
344
187
  </button>
345
188
  </div>
346
189
  {wizardState.iconUrl ? (
@@ -352,251 +195,21 @@ function CreateServerProfileStep(props: CreateServerProfileStepProps) {
352
195
  className="h-16 w-16 rounded-lg object-cover"
353
196
  />
354
197
  </div>
355
- ) : (
356
- <p className="mt-2 text-xs text-gray-500">
357
- Leave the icon empty to keep the default branding assets.
358
- </p>
359
- )}
360
- </div>
361
- </div>
362
- );
363
- }
364
-
365
- /**
366
- * Renders the users step of the create-server wizard.
367
- *
368
- * @param props - Step props.
369
- * @returns User-step form fields.
370
- */
371
- function CreateServerUsersStep(props: CreateServerUsersStepProps) {
372
- const { addAdditionalUser, removeAdditionalUser, updateAdditionalUser, updateAdminUser, wizardState } = props;
373
-
374
- return (
375
- <div className="space-y-6">
376
- <div className="rounded-xl border border-gray-200 bg-gray-50 p-4">
377
- <div className="mb-4">
378
- <h3 className="text-base font-semibold text-gray-900">Required admin user</h3>
379
- <p className="mt-1 text-sm text-gray-500">
380
- This admin belongs to the new server itself, not necessarily to the creating user.
381
- </p>
382
- </div>
383
- <div className="grid gap-4 md:grid-cols-2">
384
- <div>
385
- <label
386
- htmlFor="create-server-admin-username"
387
- className="mb-1 block text-sm font-medium text-gray-700"
388
- >
389
- Admin username
390
- </label>
391
- <input
392
- id="create-server-admin-username"
393
- type="text"
394
- value={wizardState.adminUser.username}
395
- onChange={(event) => updateAdminUser('username', event.target.value)}
396
- className={INPUT_CLASS_NAME}
397
- placeholder="admin"
398
- />
399
- </div>
400
- <SecretInput
401
- label="Admin password"
402
- value={wizardState.adminUser.password}
403
- onChange={(event) => updateAdminUser('password', event.target.value)}
404
- placeholder="Required"
405
- helperText="Password validation uses the same rules as the existing server admin flow."
406
- />
407
- </div>
408
- </div>
409
-
410
- <div className="space-y-4">
411
- <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
412
- <div>
413
- <h3 className="text-base font-semibold text-gray-900">Additional users</h3>
414
- <p className="mt-1 text-sm text-gray-500">
415
- Optional bootstrap users created immediately after migrations finish.
416
- </p>
417
- </div>
418
- <button type="button" onClick={addAdditionalUser} className={SECONDARY_BUTTON_CLASS_NAME}>
419
- <Plus className="h-4 w-4" />
420
- Add user
421
- </button>
422
- </div>
423
-
424
- {wizardState.additionalUsers.length === 0 ? (
425
- <div className="rounded-lg border border-dashed border-gray-300 bg-gray-50 p-4 text-sm text-gray-500">
426
- No extra users will be created unless you add them here.
427
- </div>
428
- ) : (
429
- <div className="space-y-3">
430
- {wizardState.additionalUsers.map((user, index) => (
431
- <div
432
- key={`wizard-user-${index}`}
433
- className="rounded-xl border border-gray-200 bg-white p-4"
434
- >
435
- <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_160px_auto]">
436
- <div>
437
- <label
438
- htmlFor={`create-server-user-${index}-username`}
439
- className="mb-1 block text-sm font-medium text-gray-700"
440
- >
441
- Username
442
- </label>
443
- <input
444
- id={`create-server-user-${index}-username`}
445
- type="text"
446
- value={user.username}
447
- onChange={(event) =>
448
- updateAdditionalUser(index, 'username', event.target.value)
449
- }
450
- className={INPUT_CLASS_NAME}
451
- placeholder={`user-${index + 1}`}
452
- />
453
- </div>
454
- <SecretInput
455
- label="Password"
456
- value={user.password}
457
- onChange={(event) =>
458
- updateAdditionalUser(index, 'password', event.target.value)
459
- }
460
- placeholder="Required"
461
- />
462
- <label className="flex items-center gap-3 rounded-md border border-gray-200 bg-gray-50 px-3 py-2 text-sm font-medium text-gray-700 lg:mt-7">
463
- <input
464
- type="checkbox"
465
- checked={user.isAdmin}
466
- onChange={(event) =>
467
- updateAdditionalUser(index, 'isAdmin', event.target.checked)
468
- }
469
- className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
470
- />
471
- Admin
472
- </label>
473
- <div className="flex items-end">
474
- <button
475
- type="button"
476
- onClick={() => removeAdditionalUser(index)}
477
- className={`${DANGER_BUTTON_CLASS_NAME} w-full justify-center lg:mt-7`}
478
- >
479
- <Trash2 className="h-4 w-4" />
480
- Remove
481
- </button>
482
- </div>
483
- </div>
484
- </div>
485
- ))}
486
- </div>
487
- )}
488
- </div>
489
- </div>
490
- );
491
- }
492
-
493
- /**
494
- * Renders the settings step of the create-server wizard.
495
- *
496
- * @param props - Step props.
497
- * @returns Settings-step form fields.
498
- */
499
- function CreateServerSettingsStep(props: CreateServerSettingsStepProps) {
500
- const { derivedWizardTablePrefix, updateInitialSetting, wizardState } = props;
501
-
502
- return (
503
- <div className="space-y-6">
504
- <div className="grid gap-4 md:grid-cols-2">
505
- <div>
506
- <label htmlFor="create-server-language" className="mb-1 block text-sm font-medium text-gray-700">
507
- Initial language
508
- </label>
509
- <select
510
- id="create-server-language"
511
- value={wizardState.initialSettings.language}
512
- onChange={(event) => updateInitialSetting('language', event.target.value)}
513
- className={INPUT_CLASS_NAME}
514
- >
515
- {SERVER_LANGUAGE_OPTIONS.map((option) => (
516
- <option key={option.value} value={option.value}>
517
- {option.label}
518
- </option>
519
- ))}
520
- </select>
521
- </div>
522
- <div className="rounded-xl border border-gray-200 bg-gray-50 p-4 text-sm text-gray-600">
523
- <p className="font-semibold text-gray-900">Bootstrap summary</p>
524
- <p className="mt-2">
525
- The new server will be created as <strong>{wizardState.name || 'Unnamed server'}</strong> on{' '}
526
- <strong>{wizardState.domain || 'pending domain'}</strong> with prefix{' '}
527
- <code>{derivedWizardTablePrefix || 'pending prefix'}</code>.
528
- </p>
529
- <p className="mt-2">
530
- Bootstrap users: <strong>{1 + wizardState.additionalUsers.length}</strong>
531
- </p>
532
- </div>
533
- <div className="md:col-span-2">
534
- <label
535
- htmlFor="create-server-homepage-message"
536
- className="mb-1 block text-sm font-medium text-gray-700"
537
- >
538
- Homepage message
539
- </label>
540
- <textarea
541
- id="create-server-homepage-message"
542
- value={wizardState.initialSettings.homepageMessage}
543
- onChange={(event) => updateInitialSetting('homepageMessage', event.target.value)}
544
- className={TEXTAREA_CLASS_NAME}
545
- placeholder="Optional markdown shown on the new server homepage."
546
- />
547
- </div>
548
- <div>
549
- <label
550
- htmlFor="create-server-feedback-mode"
551
- className="mb-1 block text-sm font-medium text-gray-700"
552
- >
553
- Chat feedback mode
554
- </label>
555
- <select
556
- id="create-server-feedback-mode"
557
- value={wizardState.initialSettings.feedbackMode}
558
- onChange={(event) =>
559
- updateInitialSetting(
560
- 'feedbackMode',
561
- event.target.value as CreateServerWizardState['initialSettings']['feedbackMode'],
562
- )
563
- }
564
- className={INPUT_CLASS_NAME}
565
- >
566
- {CHAT_FEEDBACK_MODE_OPTIONS.map((option) => (
567
- <option key={option.value} value={option.value}>
568
- {option.label}
569
- </option>
570
- ))}
571
- </select>
572
- </div>
198
+ ) : null}
573
199
  </div>
574
200
 
575
- <div className="grid gap-3 md:grid-cols-2">
576
- {CREATE_SERVER_BOOLEAN_FEATURE_FLAGS.map((flag) => (
577
- <label
578
- key={flag.key}
579
- className="flex items-start gap-3 rounded-xl border border-gray-200 bg-gray-50 p-4"
580
- >
581
- <input
582
- type="checkbox"
583
- checked={wizardState.initialSettings[flag.key]}
584
- onChange={(event) => updateInitialSetting(flag.key, event.target.checked)}
585
- className="mt-1 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
586
- />
587
- <div>
588
- <div className="text-sm font-semibold text-gray-900">{flag.title}</div>
589
- <div className="mt-1 text-sm text-gray-500">{flag.description}</div>
590
- </div>
591
- </label>
592
- ))}
201
+ <div className="rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm text-gray-600">
202
+ <p className="font-semibold text-gray-900">Admin user exists</p>
203
+ <p className="mt-1">
204
+ The installer-created <span className="font-mono">admin</span> user is used for this server.
205
+ </p>
593
206
  </div>
594
207
  </div>
595
208
  );
596
209
  }
597
210
 
598
211
  /**
599
- * Renders the multi-step create-server dialog.
212
+ * Renders the simplified create-server dialog.
600
213
  *
601
214
  * @param props - Dialog props.
602
215
  * @returns Modal dialog when open, otherwise `null`.
@@ -605,68 +218,30 @@ function CreateServerSettingsStep(props: CreateServerSettingsStepProps) {
605
218
  */
606
219
  export function CreateServerDialog(props: CreateServerDialogProps) {
607
220
  const {
608
- addAdditionalUser,
609
- derivedWizardTablePrefix,
610
221
  handleCreateServer,
611
222
  handleIconUpload,
612
- handleWizardBack,
613
- handleWizardNext,
614
- handleWizardStepSelection,
615
223
  iconInputRef,
616
224
  isCreatingServer,
617
225
  isOpen,
618
226
  isUploadingIcon,
619
- removeAdditionalUser,
620
227
  requestClose,
621
228
  resetWizard,
622
- updateAdditionalUser,
623
- updateAdminUser,
624
- updateInitialSetting,
625
229
  updateWizardField,
626
230
  wizardError,
627
231
  wizardState,
628
- wizardStep,
629
232
  } = props;
630
233
 
631
234
  if (!isOpen) {
632
235
  return null;
633
236
  }
634
237
 
635
- const currentStepContent =
636
- wizardStep === 0 ? (
637
- <CreateServerProfileStep
638
- derivedWizardTablePrefix={derivedWizardTablePrefix}
639
- handleIconUpload={handleIconUpload}
640
- iconInputRef={iconInputRef}
641
- isUploadingIcon={isUploadingIcon}
642
- updateWizardField={updateWizardField}
643
- wizardState={wizardState}
644
- />
645
- ) : wizardStep === 1 ? (
646
- <CreateServerUsersStep
647
- addAdditionalUser={addAdditionalUser}
648
- removeAdditionalUser={removeAdditionalUser}
649
- updateAdditionalUser={updateAdditionalUser}
650
- updateAdminUser={updateAdminUser}
651
- wizardState={wizardState}
652
- />
653
- ) : (
654
- <CreateServerSettingsStep
655
- derivedWizardTablePrefix={derivedWizardTablePrefix}
656
- updateInitialSetting={updateInitialSetting}
657
- wizardState={wizardState}
658
- />
659
- );
660
-
661
238
  return (
662
- <Dialog onClose={requestClose} className="mx-4 w-full max-w-5xl overflow-hidden">
239
+ <Dialog onClose={requestClose} className="mx-4 w-full max-w-2xl overflow-hidden">
663
240
  <div className="max-h-[90vh] overflow-y-auto">
664
241
  <div className="flex items-start justify-between gap-4 border-b border-gray-200 px-6 py-5">
665
242
  <div>
666
243
  <h2 className="text-xl font-semibold text-gray-900">Create new server</h2>
667
- <p className="mt-1 text-sm text-gray-500">
668
- Create a server with its initial users and settings.
669
- </p>
244
+ <p className="mt-1 text-sm text-gray-500">Add the public server identity and domain.</p>
670
245
  </div>
671
246
  <button
672
247
  type="button"
@@ -679,27 +254,6 @@ export function CreateServerDialog(props: CreateServerDialogProps) {
679
254
  </div>
680
255
 
681
256
  <div className="space-y-6 px-6 py-6">
682
- <div className="grid gap-3 md:grid-cols-3">
683
- {CREATE_SERVER_WIZARD_STEPS.map((step, index) => (
684
- <button
685
- key={step.title}
686
- type="button"
687
- onClick={() => void handleWizardStepSelection(index)}
688
- className={`rounded-xl border p-4 text-left transition ${
689
- index === wizardStep
690
- ? 'border-blue-500 bg-blue-50 text-blue-700 shadow-sm'
691
- : index < wizardStep
692
- ? 'border-emerald-200 bg-emerald-50 text-emerald-700'
693
- : 'border-gray-200 bg-white text-gray-700 hover:border-gray-300 hover:bg-gray-50'
694
- }`}
695
- >
696
- <div className="text-xs font-semibold uppercase tracking-wide">Step {index + 1}</div>
697
- <div className="mt-1 text-base font-semibold">{step.title}</div>
698
- <div className="mt-1 text-sm text-current/80">{step.description}</div>
699
- </button>
700
- ))}
701
- </div>
702
-
703
257
  {wizardError ? (
704
258
  <div className="rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-800">
705
259
  <p className="font-semibold">Server creation failed</p>
@@ -719,7 +273,7 @@ export function CreateServerDialog(props: CreateServerDialogProps) {
719
273
  Download SQL dump
720
274
  </button>
721
275
  <span className="text-xs text-red-700">
722
- If you need manual recovery, send the dump to support@ptbk.io.
276
+ Send the dump to support@ptbk.io if manual recovery is needed.
723
277
  </span>
724
278
  </div>
725
279
  ) : (
@@ -730,7 +284,13 @@ export function CreateServerDialog(props: CreateServerDialogProps) {
730
284
  </div>
731
285
  ) : null}
732
286
 
733
- {currentStepContent}
287
+ <CreateServerForm
288
+ handleIconUpload={handleIconUpload}
289
+ iconInputRef={iconInputRef}
290
+ isUploadingIcon={isUploadingIcon}
291
+ updateWizardField={updateWizardField}
292
+ wizardState={wizardState}
293
+ />
734
294
 
735
295
  <div className="flex flex-col gap-3 border-t border-gray-100 pt-6 sm:flex-row sm:items-center sm:justify-between">
736
296
  <p className="text-xs text-gray-500">
@@ -747,36 +307,17 @@ export function CreateServerDialog(props: CreateServerDialogProps) {
747
307
  </button>
748
308
  <button
749
309
  type="button"
750
- onClick={handleWizardBack}
751
- disabled={wizardStep === 0 || isCreatingServer}
752
- className={SECONDARY_BUTTON_CLASS_NAME}
310
+ onClick={() => void handleCreateServer()}
311
+ disabled={isCreatingServer || isUploadingIcon}
312
+ className={PRIMARY_BUTTON_CLASS_NAME}
753
313
  >
754
- Back
314
+ {isCreatingServer ? (
315
+ <Loader2 className="h-4 w-4 animate-spin" />
316
+ ) : (
317
+ <Plus className="h-4 w-4" />
318
+ )}
319
+ Create server
755
320
  </button>
756
- {wizardStep < CREATE_SERVER_WIZARD_STEPS.length - 1 ? (
757
- <button
758
- type="button"
759
- onClick={() => void handleWizardNext()}
760
- disabled={isCreatingServer || isUploadingIcon}
761
- className={PRIMARY_BUTTON_CLASS_NAME}
762
- >
763
- Next
764
- </button>
765
- ) : (
766
- <button
767
- type="button"
768
- onClick={() => void handleCreateServer()}
769
- disabled={isCreatingServer || isUploadingIcon}
770
- className={PRIMARY_BUTTON_CLASS_NAME}
771
- >
772
- {isCreatingServer ? (
773
- <Loader2 className="h-4 w-4 animate-spin" />
774
- ) : (
775
- <Plus className="h-4 w-4" />
776
- )}
777
- Create server
778
- </button>
779
- )}
780
321
  </div>
781
322
  </div>
782
323
  </div>