@promptbook/cli 0.112.0-88 → 0.112.0-90

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 (27) hide show
  1. package/apps/agents-server/next.config.ts +58 -3
  2. package/apps/agents-server/src/database/ensureAutomaticDatabaseMigrations.ts +8 -1
  3. package/apps/agents-server/src/database/runDatabaseMigrations.ts +31 -1
  4. package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +2 -2
  5. package/apps/agents-server/src/middleware/createMiddlewareRequestContext.ts +1 -1
  6. package/apps/agents-server/src/tools/$provideServer.ts +27 -0
  7. package/apps/agents-server/src/utils/serverRegistry.ts +117 -3
  8. package/esm/apps/agents-server/src/utils/serverRegistry.d.ts +6 -0
  9. package/esm/index.es.js +348 -17
  10. package/esm/index.es.js.map +1 -1
  11. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +31 -0
  12. package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +6 -0
  13. package/esm/src/version.d.ts +1 -1
  14. package/package.json +5 -3
  15. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +330 -8
  16. package/src/cli/cli-commands/agents-server/run.ts +2 -1
  17. package/src/cli/cli-commands/agents-server/startAgentsServer.ts +40 -16
  18. package/src/other/templates/getTemplatesPipelineCollection.ts +691 -794
  19. package/src/version.ts +2 -2
  20. package/src/versions.txt +2 -0
  21. package/umd/apps/agents-server/src/utils/serverRegistry.d.ts +6 -0
  22. package/umd/index.umd.js +346 -15
  23. package/umd/index.umd.js.map +1 -1
  24. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +31 -0
  25. package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +6 -0
  26. package/umd/src/version.d.ts +1 -1
  27. package/src/wizard/test/sub/subsub/subsubsub/.promptbook/executions-cache/8/c/report-whoami-6e340b9cffb37a98.json +0 -104
package/src/version.ts CHANGED
@@ -16,11 +16,11 @@ export const BOOK_LANGUAGE_VERSION: string_semantic_version = '2.0.0';
16
16
  * @generated
17
17
  * @see https://github.com/webgptorg/promptbook
18
18
  */
19
- export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.112.0-88';
19
+ export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.112.0-90';
20
20
 
21
21
  /**
22
22
  * Represents the version string of the Promptbook engine.
23
- * It follows semantic versioning (e.g., `0.112.0-82`).
23
+ * It follows semantic versioning (e.g., `0.112.0-89`).
24
24
  *
25
25
  * @generated
26
26
  */
package/src/versions.txt CHANGED
@@ -1125,3 +1125,5 @@
1125
1125
  0.112.0-81
1126
1126
  0.112.0-82
1127
1127
  0.112.0-88
1128
+ 0.112.0-89
1129
+ 0.112.0-90
@@ -65,6 +65,12 @@ export declare function listRegisteredServers(supabase: Pick<SupabaseClient, 'fr
65
65
  export declare function listRegisteredServersUsingServiceRole(options?: {
66
66
  readonly forceRefresh?: boolean;
67
67
  }): Promise<Array<ServerRecord>>;
68
+ /**
69
+ * Loads virtual server records from the comma-separated `SERVERS` environment variable.
70
+ *
71
+ * @returns Server records with deterministic table prefixes derived from normalized domains.
72
+ */
73
+ export declare function listEnvironmentRegisteredServers(): Array<ServerRecord>;
68
74
  /**
69
75
  * Finds one registered server by incoming host header.
70
76
  *
package/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-88';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-90';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -3104,6 +3104,31 @@
3104
3104
  * @private internal constant of `ptbk agents-server`
3105
3105
  */
3106
3106
  const DEFAULT_AGENTS_SERVER_NEXT_DIST_DIRECTORY_NAME = '.next';
3107
+ /**
3108
+ * Environment variable passed to the bundled Next app so webpack can resolve dependencies
3109
+ * installed beside `ptbk` even when the app sources are materialized into a project cache.
3110
+ *
3111
+ * @private internal constant of `ptbk agents-server`
3112
+ */
3113
+ const PTBK_AGENTS_SERVER_NODE_MODULES_PATH_ENV = 'PTBK_AGENTS_SERVER_NODE_MODULES_PATH';
3114
+ /**
3115
+ * Environment variable used only by the CLI-owned production build.
3116
+ *
3117
+ * @private internal constant of `ptbk agents-server`
3118
+ */
3119
+ const PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION_ENV = 'PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION';
3120
+ /**
3121
+ * Runtime copy metadata filename stored in the project-local materialized app root.
3122
+ *
3123
+ * @private internal constant of `ptbk agents-server`
3124
+ */
3125
+ const AGENTS_SERVER_MATERIALIZED_RUNTIME_CACHE_FILENAME = '.ptbk-agents-server-runtime-cache.json';
3126
+ /**
3127
+ * Directory segment used for Node package installs.
3128
+ *
3129
+ * @private internal constant of `ptbk agents-server`
3130
+ */
3131
+ const NODE_MODULES_DIRECTORY_NAME = 'node_modules';
3107
3132
  /**
3108
3133
  * Runtime paths copied into the CLI package and used by the Agents Server production build.
3109
3134
  *
@@ -3148,26 +3173,33 @@
3148
3173
  */
3149
3174
  async function ensureAgentsServerBuild(options = {}) {
3150
3175
  var _a, _b, _c, _d;
3151
- const appPath = (_a = options.appPath) !== null && _a !== void 0 ? _a : (await resolveAgentsServerAppPath());
3152
- const environment = (_b = options.environment) !== null && _b !== void 0 ? _b : process.env;
3176
+ const environment = (_a = options.environment) !== null && _a !== void 0 ? _a : process.env;
3153
3177
  const nextCliPath = resolveNextCliPath();
3178
+ const nodeModulesPath = resolveNodeModulesPath(nextCliPath);
3179
+ const appPath = await resolveAgentsServerBuildAppPath({
3180
+ sourceAppPath: (_b = options.appPath) !== null && _b !== void 0 ? _b : (await resolveAgentsServerAppPath()),
3181
+ nodeModulesPath,
3182
+ });
3183
+ const buildEnvironment = createAgentsServerRuntimeEnvironment(environment, nodeModulesPath, {
3184
+ isNextValidationIgnored: isAgentsServerAppPathMaterialized(appPath),
3185
+ });
3154
3186
  if (!options.isBuildForced &&
3155
3187
  (await isAgentsServerBuildCacheCurrent({
3156
3188
  appPath,
3157
- environment,
3189
+ environment: buildEnvironment,
3158
3190
  }))) {
3159
3191
  (_c = options.onBuildEvent) === null || _c === void 0 ? void 0 : _c.call(options, 'Using the cached Agents Server Next app build.');
3160
- return { appPath, nextCliPath };
3192
+ return { appPath, nextCliPath, nodeModulesPath };
3161
3193
  }
3162
3194
  (_d = options.onBuildEvent) === null || _d === void 0 ? void 0 : _d.call(options, 'Building the Agents Server Next app.');
3163
3195
  await runNextBuild({
3164
3196
  appPath,
3165
- environment,
3197
+ environment: buildEnvironment,
3166
3198
  nextCliPath,
3167
3199
  onBuildOutput: options.onBuildOutput,
3168
3200
  });
3169
- await writeAgentsServerBuildCache({ appPath, environment });
3170
- return { appPath, nextCliPath };
3201
+ await writeAgentsServerBuildCache({ appPath, environment: buildEnvironment });
3202
+ return { appPath, nextCliPath, nodeModulesPath };
3171
3203
  }
3172
3204
  /**
3173
3205
  * Returns true when the production build marker and source fingerprint still match.
@@ -3223,6 +3255,165 @@
3223
3255
  ${candidates.map((candidate) => `- \`${candidate}\``).join('\n')}
3224
3256
  `));
3225
3257
  }
3258
+ /**
3259
+ * Adds dependency-resolution environment required by the materialized Agents Server runtime.
3260
+ *
3261
+ * @private internal utility of `ptbk agents-server`
3262
+ */
3263
+ function createAgentsServerRuntimeEnvironment(environment, nodeModulesPath, options = {}) {
3264
+ return {
3265
+ ...environment,
3266
+ NODE_PATH: mergeNodePath(nodeModulesPath, environment.NODE_PATH),
3267
+ [PTBK_AGENTS_SERVER_NODE_MODULES_PATH_ENV]: nodeModulesPath,
3268
+ ...(options.isNextValidationIgnored
3269
+ ? {
3270
+ [PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION_ENV]: 'true',
3271
+ }
3272
+ : {}),
3273
+ };
3274
+ }
3275
+ /**
3276
+ * Uses the source checkout app directly, but copies npm-packaged app sources out of `node_modules`.
3277
+ *
3278
+ * @private internal utility of `ptbk agents-server`
3279
+ */
3280
+ async function resolveAgentsServerBuildAppPath(options) {
3281
+ if (!isPathInsideNodeModules(options.sourceAppPath)) {
3282
+ return options.sourceAppPath;
3283
+ }
3284
+ const sourceRuntimeRootPath = path.resolve(options.sourceAppPath, '..', '..');
3285
+ const materializedRuntimeRootPath = resolvePromptbookTemporaryPath(process.cwd(), 'agents-server', 'runtime');
3286
+ await synchronizeMaterializedAgentsServerRuntime({
3287
+ materializedRuntimeRootPath,
3288
+ nodeModulesPath: options.nodeModulesPath,
3289
+ sourceAppPath: options.sourceAppPath,
3290
+ sourceRuntimeRootPath,
3291
+ });
3292
+ return path.join(materializedRuntimeRootPath, 'apps', 'agents-server');
3293
+ }
3294
+ /**
3295
+ * Copies the bundled runtime into the launch project when the original app lives under `node_modules`.
3296
+ */
3297
+ async function synchronizeMaterializedAgentsServerRuntime(options) {
3298
+ const sourceFingerprint = await createAgentsServerBuildSourceFingerprint(options.sourceAppPath);
3299
+ const runtimeCache = await readAgentsServerMaterializedRuntimeCache(options.materializedRuntimeRootPath);
3300
+ const isRuntimeCurrent = (runtimeCache === null || runtimeCache === void 0 ? void 0 : runtimeCache.version) === AGENTS_SERVER_BUILD_CACHE_VERSION &&
3301
+ runtimeCache.sourceFingerprint === sourceFingerprint &&
3302
+ (await isAgentsServerAppPath(path.join(options.materializedRuntimeRootPath, 'apps', 'agents-server')));
3303
+ if (!isRuntimeCurrent) {
3304
+ await promises.rm(options.materializedRuntimeRootPath, { recursive: true, force: true });
3305
+ await promises.mkdir(options.materializedRuntimeRootPath, { recursive: true });
3306
+ for (const relativeInputPath of AGENTS_SERVER_BUILD_INPUT_RELATIVE_PATHS) {
3307
+ await copyAgentsServerRuntimePath({
3308
+ destinationPath: path.join(options.materializedRuntimeRootPath, relativeInputPath),
3309
+ sourcePath: path.join(options.sourceRuntimeRootPath, relativeInputPath),
3310
+ });
3311
+ }
3312
+ await assertMaterializedAgentsServerAppExists(options.materializedRuntimeRootPath);
3313
+ await writeAgentsServerMaterializedRuntimeCache(options.materializedRuntimeRootPath, sourceFingerprint);
3314
+ }
3315
+ await ensureMaterializedRuntimeNodeModulesLink({
3316
+ materializedRuntimeRootPath: options.materializedRuntimeRootPath,
3317
+ nodeModulesPath: options.nodeModulesPath,
3318
+ });
3319
+ }
3320
+ /**
3321
+ * Verifies that the materialized runtime contains a usable Next app before caching it.
3322
+ */
3323
+ async function assertMaterializedAgentsServerAppExists(materializedRuntimeRootPath) {
3324
+ const materializedAppPath = path.join(materializedRuntimeRootPath, 'apps', 'agents-server');
3325
+ if (await isAgentsServerAppPath(materializedAppPath)) {
3326
+ return;
3327
+ }
3328
+ throw new NotAllowed(_spaceTrim.spaceTrim(`
3329
+ Cannot prepare the bundled Agents Server runtime.
3330
+
3331
+ The materialized app path is missing required files:
3332
+ \`${materializedAppPath}\`
3333
+ `));
3334
+ }
3335
+ /**
3336
+ * Copies one source path into the materialized runtime, skipping generated or private files.
3337
+ */
3338
+ async function copyAgentsServerRuntimePath(options) {
3339
+ let sourceStats;
3340
+ try {
3341
+ sourceStats = await promises.stat(options.sourcePath);
3342
+ }
3343
+ catch (_a) {
3344
+ return;
3345
+ }
3346
+ await promises.mkdir(path.dirname(options.destinationPath), { recursive: true });
3347
+ if (sourceStats.isDirectory()) {
3348
+ await promises.cp(options.sourcePath, options.destinationPath, {
3349
+ recursive: true,
3350
+ filter: (sourcePath) => shouldCopyAgentsServerRuntimePath(sourcePath, options.sourcePath),
3351
+ });
3352
+ return;
3353
+ }
3354
+ if (sourceStats.isFile() && shouldCopyAgentsServerRuntimePath(options.sourcePath, path.dirname(options.sourcePath))) {
3355
+ await promises.cp(options.sourcePath, options.destinationPath);
3356
+ }
3357
+ }
3358
+ /**
3359
+ * Excludes build artifacts, dependency folders, private env files, and test sources.
3360
+ */
3361
+ function shouldCopyAgentsServerRuntimePath(sourcePath, sourceRootPath) {
3362
+ const sourceRelativePath = path.relative(sourceRootPath, sourcePath).replace(/\\/gu, '/');
3363
+ const sourcePathSegments = sourceRelativePath.split('/').filter(Boolean);
3364
+ const sourceBasename = path.basename(sourcePath);
3365
+ if (sourcePathSegments.some((sourcePathSegment) => AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES.has(sourcePathSegment))) {
3366
+ return false;
3367
+ }
3368
+ if (sourceBasename.startsWith('.env')) {
3369
+ return false;
3370
+ }
3371
+ return !AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(sourceBasename);
3372
+ }
3373
+ /**
3374
+ * Links the materialized runtime back to the package dependency tree used by the installed CLI.
3375
+ */
3376
+ async function ensureMaterializedRuntimeNodeModulesLink(options) {
3377
+ const nodeModulesLinkPath = path.join(options.materializedRuntimeRootPath, NODE_MODULES_DIRECTORY_NAME);
3378
+ try {
3379
+ const existingLinkStats = await promises.lstat(nodeModulesLinkPath);
3380
+ await promises.rm(nodeModulesLinkPath, {
3381
+ force: true,
3382
+ recursive: existingLinkStats.isDirectory() && !existingLinkStats.isSymbolicLink(),
3383
+ });
3384
+ }
3385
+ catch (_a) {
3386
+ // The link does not exist yet.
3387
+ }
3388
+ await promises.symlink(options.nodeModulesPath, nodeModulesLinkPath, process.platform === 'win32' ? 'junction' : 'dir');
3389
+ }
3390
+ /**
3391
+ * Reads and validates materialized runtime metadata.
3392
+ */
3393
+ async function readAgentsServerMaterializedRuntimeCache(materializedRuntimeRootPath) {
3394
+ try {
3395
+ const serializedRuntimeCache = await promises.readFile(path.join(materializedRuntimeRootPath, AGENTS_SERVER_MATERIALIZED_RUNTIME_CACHE_FILENAME), 'utf-8');
3396
+ const runtimeCache = JSON.parse(serializedRuntimeCache);
3397
+ if (runtimeCache.version !== AGENTS_SERVER_BUILD_CACHE_VERSION ||
3398
+ typeof runtimeCache.sourceFingerprint !== 'string') {
3399
+ return undefined;
3400
+ }
3401
+ return runtimeCache;
3402
+ }
3403
+ catch (_a) {
3404
+ return undefined;
3405
+ }
3406
+ }
3407
+ /**
3408
+ * Persists the source fingerprint used for the materialized runtime copy.
3409
+ */
3410
+ async function writeAgentsServerMaterializedRuntimeCache(materializedRuntimeRootPath, sourceFingerprint) {
3411
+ const runtimeCache = {
3412
+ version: AGENTS_SERVER_BUILD_CACHE_VERSION,
3413
+ sourceFingerprint,
3414
+ };
3415
+ await promises.writeFile(path.join(materializedRuntimeRootPath, AGENTS_SERVER_MATERIALIZED_RUNTIME_CACHE_FILENAME), `${JSON.stringify(runtimeCache, null, 4)}\n`, 'utf-8');
3416
+ }
3226
3417
  /**
3227
3418
  * Runs the finite Next production build used by local Agents Server commands.
3228
3419
  */
@@ -3347,6 +3538,41 @@
3347
3538
  var _a;
3348
3539
  return path.resolve(options.appPath, ((_a = options.environment) === null || _a === void 0 ? void 0 : _a.NEXT_DIST_DIR) || DEFAULT_AGENTS_SERVER_NEXT_DIST_DIRECTORY_NAME);
3349
3540
  }
3541
+ /**
3542
+ * Returns true when the app path points at the project-local materialized runtime.
3543
+ */
3544
+ function isAgentsServerAppPathMaterialized(appPath) {
3545
+ const normalizedAppPath = appPath.replace(/\\/gu, '/');
3546
+ const normalizedMaterializedRuntimePath = resolvePromptbookTemporaryPath(process.cwd(), 'agents-server', 'runtime').replace(/\\/gu, '/');
3547
+ return normalizedAppPath.includes(normalizedMaterializedRuntimePath);
3548
+ }
3549
+ /**
3550
+ * Returns true when one path is nested below a `node_modules` segment.
3551
+ */
3552
+ function isPathInsideNodeModules(path) {
3553
+ return path.split(/[\\/]+/u).includes(NODE_MODULES_DIRECTORY_NAME);
3554
+ }
3555
+ /**
3556
+ * Resolves the dependency root that contains the installed Next CLI.
3557
+ */
3558
+ function resolveNodeModulesPath(nextCliPath) {
3559
+ const normalizedNextCliPath = nextCliPath.replace(/\\/gu, '/');
3560
+ const marker = `/${NODE_MODULES_DIRECTORY_NAME}/next/`;
3561
+ const markerIndex = normalizedNextCliPath.lastIndexOf(marker);
3562
+ if (markerIndex === -1) {
3563
+ return path.resolve(nextCliPath, '..', '..', '..');
3564
+ }
3565
+ return normalizedNextCliPath.slice(0, markerIndex + marker.length - '/next/'.length);
3566
+ }
3567
+ /**
3568
+ * Prepends one dependency root to `NODE_PATH` while preserving any existing value.
3569
+ */
3570
+ function mergeNodePath(nodeModulesPath, nodePath) {
3571
+ if (!nodePath) {
3572
+ return nodeModulesPath;
3573
+ }
3574
+ return `${nodeModulesPath}${path.delimiter}${nodePath}`;
3575
+ }
3350
3576
  /**
3351
3577
  * Returns true when one path exists as a regular file.
3352
3578
  */
@@ -35882,6 +36108,12 @@
35882
36108
  * @private internal constant of `ptbk agents-server`
35883
36109
  */
35884
36110
  const PTBK_AGENTS_SERVER_SQLITE_PATH_ENV = 'PTBK_AGENTS_SERVER_SQLITE_PATH';
36111
+ /**
36112
+ * Optional hostname used by the internal Next server.
36113
+ *
36114
+ * @private internal constant of `ptbk agents-server`
36115
+ */
36116
+ const PTBK_HOSTNAME_ENV = 'PTBK_HOSTNAME';
35885
36117
  /**
35886
36118
  * Entropy size for the local-only token shared by the CLI pump and the Next app.
35887
36119
  *
@@ -35913,7 +36145,7 @@
35913
36145
  };
35914
36146
  process.once('exit', processExitHandler);
35915
36147
  try {
35916
- const { nextCliPath } = await ensureAgentsServerBuild({
36148
+ const buildArtifacts = await ensureAgentsServerBuild({
35917
36149
  appPath: runtimePaths.appPath,
35918
36150
  environment: childEnvironment,
35919
36151
  isBuildForced: options.isBuildForced,
@@ -35933,17 +36165,22 @@
35933
36165
  });
35934
36166
  },
35935
36167
  });
36168
+ const runtimeChildEnvironment = createAgentsServerRuntimeEnvironment(childEnvironment, buildArtifacts.nodeModulesPath);
36169
+ const builtRuntimePaths = {
36170
+ ...runtimePaths,
36171
+ appPath: buildArtifacts.appPath,
36172
+ };
35936
36173
  nextServerProcess = startNextServer({
35937
- nextCliPath,
36174
+ nextCliPath: buildArtifacts.nextCliPath,
35938
36175
  options,
35939
- runtimePaths,
35940
- childEnvironment,
36176
+ runtimePaths: builtRuntimePaths,
36177
+ childEnvironment: runtimeChildEnvironment,
35941
36178
  logStreams,
35942
36179
  state,
35943
36180
  });
35944
36181
  stopUserChatJobWorkerPump = startUserChatJobWorkerPump({
35945
36182
  port: options.port,
35946
- environment: childEnvironment,
36183
+ environment: runtimeChildEnvironment,
35947
36184
  logStreams,
35948
36185
  state,
35949
36186
  });
@@ -35969,6 +36206,8 @@
35969
36206
  }
35970
36207
  /**
35971
36208
  * Loads launch-directory `.env` values without overriding explicit process environment.
36209
+ *
36210
+ * @private internal utility of `ptbk agents-server`
35972
36211
  */
35973
36212
  function loadAgentsServerProjectEnvironment(launchWorkingDirectory) {
35974
36213
  dotenv__namespace.config({ path: path.join(launchWorkingDirectory, AGENTS_SERVER_PROJECT_ENV_FILE_NAME) });
@@ -35993,8 +36232,15 @@
35993
36232
  * Starts the production Next server and wires its logs into the foreground dashboard.
35994
36233
  */
35995
36234
  function startNextServer(options) {
36235
+ var _a;
35996
36236
  logRunnerEvent(options.logStreams.runner, 'Starting the Agents Server Next process.');
35997
- const commandProcess = child_process.spawn(process.execPath, [options.nextCliPath, 'start', '--port', String(options.options.port)], {
36237
+ const nextArguments = [options.nextCliPath, 'start', '--port', String(options.options.port)];
36238
+ const hostname = (_a = options.childEnvironment[PTBK_HOSTNAME_ENV]) === null || _a === void 0 ? void 0 : _a.trim();
36239
+ if (hostname) {
36240
+ nextArguments.push('--hostname', hostname);
36241
+ logRunnerEvent(options.logStreams.runner, `Binding Agents Server Next process to ${hostname}.`);
36242
+ }
36243
+ const commandProcess = child_process.spawn(process.execPath, nextArguments, {
35998
36244
  cwd: options.runtimePaths.appPath,
35999
36245
  env: options.childEnvironment,
36000
36246
  stdio: ['ignore', 'pipe', 'pipe'],
@@ -36326,6 +36572,7 @@
36326
36572
  command.description('Build the Agents Server Next app for later local startup');
36327
36573
  command.action(handleActionErrors(async () => {
36328
36574
  console.info(colors__default["default"].gray('Building Promptbook Agents Server.'));
36575
+ loadAgentsServerProjectEnvironment(process.cwd());
36329
36576
  await ensureAgentsServerBuild({ isBuildForced: true });
36330
36577
  }));
36331
36578
  }
@@ -67358,6 +67605,38 @@
67358
67605
  * Global source-of-truth table for server routing and migration targeting.
67359
67606
  */
67360
67607
  const SERVER_REGISTRY_TABLE_NAME = '_Server';
67608
+ /**
67609
+ * Environment variable with comma-separated standalone server domains.
67610
+ */
67611
+ const SERVERS_ENV_NAME = 'SERVERS';
67612
+ /**
67613
+ * Stable timestamp used by virtual server records derived from environment variables.
67614
+ */
67615
+ const ENVIRONMENT_SERVER_TIMESTAMP = '1970-01-01T00:00:00.000Z';
67616
+ /**
67617
+ * Loads virtual server records from the comma-separated `SERVERS` environment variable.
67618
+ *
67619
+ * @returns Server records with deterministic table prefixes derived from normalized domains.
67620
+ */
67621
+ function listEnvironmentRegisteredServers() {
67622
+ const rawServers = process.env[SERVERS_ENV_NAME];
67623
+ if (!rawServers) {
67624
+ return [];
67625
+ }
67626
+ const normalizedDomains = uniqueStrings$1(rawServers
67627
+ .split(',')
67628
+ .map((server) => normalizeServerDomain(server))
67629
+ .filter((server) => Boolean(server)));
67630
+ return normalizedDomains.map((domain, index) => ({
67631
+ id: -(index + 1),
67632
+ name: domain,
67633
+ environment: SERVER_ENVIRONMENT.PRODUCTION,
67634
+ domain,
67635
+ tablePrefix: buildEnvironmentServerTablePrefix(domain),
67636
+ createdAt: ENVIRONMENT_SERVER_TIMESTAMP,
67637
+ updatedAt: ENVIRONMENT_SERVER_TIMESTAMP,
67638
+ }));
67639
+ }
67361
67640
  /**
67362
67641
  * Normalizes one raw `_Server` row and validates required fields.
67363
67642
  *
@@ -67478,6 +67757,39 @@
67478
67757
  function isDefaultPortForProtocol(protocol, port) {
67479
67758
  return (protocol === 'http:' && port === '80') || (protocol === 'https:' && port === '443');
67480
67759
  }
67760
+ /**
67761
+ * Builds a deterministic table prefix from a normalized domain.
67762
+ *
67763
+ * @param domain - Normalized server domain.
67764
+ * @returns Prefix such as `server_www_example_com_`.
67765
+ */
67766
+ function buildEnvironmentServerTablePrefix(domain) {
67767
+ const prefixSuffix = domain
67768
+ .toLowerCase()
67769
+ .replace(/-/gu, '_dash_')
67770
+ .replace(/\./gu, '_')
67771
+ .replace(/:/gu, '_port_')
67772
+ .replace(/[^a-z0-9_]/gu, '_')
67773
+ .replace(/_+/gu, '_')
67774
+ .replace(/^_+|_+$/gu, '');
67775
+ return `server_${prefixSuffix}_`;
67776
+ }
67777
+ /**
67778
+ * Deduplicates non-empty strings while preserving input order.
67779
+ *
67780
+ * @param values - Raw string values.
67781
+ * @returns Unique non-empty strings.
67782
+ */
67783
+ function uniqueStrings$1(values) {
67784
+ const uniqueValues = [];
67785
+ for (const value of values) {
67786
+ if (!value || uniqueValues.includes(value)) {
67787
+ continue;
67788
+ }
67789
+ uniqueValues.push(value);
67790
+ }
67791
+ return uniqueValues;
67792
+ }
67481
67793
 
67482
67794
  /**
67483
67795
  * SQL query used to load all registered servers in a deterministic order.
@@ -67836,7 +68148,7 @@
67836
68148
  const client = await createPostgresClient(connectionString);
67837
68149
  try {
67838
68150
  await client.connect();
67839
- const registeredServers = await listRegisteredServersFromDatabase(client);
68151
+ const registeredServers = mergeRegisteredServers(await listRegisteredServersFromDatabase(client), listEnvironmentRegisteredServers());
67840
68152
  const hasExplicitDefaultPrefix = process.env[SUPABASE_TABLE_PREFIX_ENV_NAME] !== undefined;
67841
68153
  const configuredPrefixes = uniquePrefixes([
67842
68154
  ...(hasExplicitDefaultPrefix
@@ -67997,6 +68309,25 @@
67997
68309
  }
67998
68310
  return result;
67999
68311
  }
68312
+ /**
68313
+ * Combines database and environment registry rows, keeping database rows authoritative.
68314
+ *
68315
+ * @param databaseServers - Persistent `_Server` rows.
68316
+ * @param environmentServers - Virtual rows derived from `SERVERS`.
68317
+ * @returns Merged rows without duplicate domains.
68318
+ */
68319
+ function mergeRegisteredServers(databaseServers, environmentServers) {
68320
+ const seenDomains = new Set(databaseServers.map((server) => server.domain));
68321
+ const mergedServers = [...databaseServers];
68322
+ for (const environmentServer of environmentServers) {
68323
+ if (seenDomains.has(environmentServer.domain)) {
68324
+ continue;
68325
+ }
68326
+ mergedServers.push(environmentServer);
68327
+ seenDomains.add(environmentServer.domain);
68328
+ }
68329
+ return mergedServers;
68330
+ }
68000
68331
  /**
68001
68332
  * Creates one PostgreSQL client using the lazily loaded `pg` package.
68002
68333
  *