@rudderhq/cli 0.3.6-canary.9 → 0.4.1

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/dist/index.js CHANGED
@@ -572,6 +572,13 @@ var init_constants = __esm({
572
572
  }
573
573
  });
574
574
 
575
+ // ../packages/shared/dist/agent-run.js
576
+ var init_agent_run = __esm({
577
+ "../packages/shared/dist/agent-run.js"() {
578
+ "use strict";
579
+ }
580
+ });
581
+
575
582
  // ../packages/shared/dist/types/observability.js
576
583
  var init_observability = __esm({
577
584
  "../packages/shared/dist/types/observability.js"() {
@@ -607,6 +614,7 @@ var init_instance = __esm({
607
614
  }).strict();
608
615
  patchInstanceNotificationSettingsSchema = instanceNotificationSettingsSchema.partial();
609
616
  instanceLangfuseSettingsSchema = z.object({
617
+ installed: z.boolean().default(false),
610
618
  enabled: z.boolean().default(false),
611
619
  baseUrl: z.string().url().default("http://localhost:3000"),
612
620
  publicKey: z.string().default(""),
@@ -784,7 +792,7 @@ var init_adapter_skills = __esm({
784
792
 
785
793
  // ../packages/shared/dist/validators/chat.js
786
794
  import { z as z4 } from "zod";
787
- var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, addChatMessageSchema, chatRichReferenceDisplaySchema, chatIssueIdentifierSchema, chatAskUserIdentifierSchema, chatAskUserOptionSchema, chatAskUserQuestionSchema, chatAskUserRequestSchema, chatIssueRichReferenceSchema, chatIssueCommentRichReferenceSchema, chatRichReferenceSchema, chatRichReferencesSchema, chatAutomationCreateSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema, updateMessengerThreadUserStateSchema, createMessengerCustomGroupSchema, createMessengerCustomGroupWithEntriesSchema, updateMessengerCustomGroupSchema, reorderMessengerCustomGroupsSchema, assignMessengerCustomGroupEntrySchema, reorderMessengerCustomGroupEntriesSchema;
795
+ var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, forkChatConversationSchema, addChatMessageSchema, chatQueuedMessagePayloadSchema, createChatQueuedMessageSchema, updateChatQueuedMessageSchema, cancelChatQueuedMessageSchema, steerChatQueuedMessageSchema, chatRichReferenceDisplaySchema, chatIssueIdentifierSchema, chatAskUserIdentifierSchema, chatAskUserOptionSchema, chatAskUserQuestionSchema, chatAskUserRequestSchema, chatIssueRichReferenceSchema, chatIssueCommentRichReferenceSchema, chatRichReferenceSchema, chatRichReferencesSchema, chatAutomationCreateSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema, updateMessengerThreadUserStateSchema, createMessengerCustomGroupSchema, createMessengerCustomGroupWithEntriesSchema, updateMessengerCustomGroupSchema, reorderMessengerCustomGroupsSchema, assignMessengerCustomGroupEntrySchema, reorderMessengerCustomGroupEntriesSchema;
788
796
  var init_chat = __esm({
789
797
  "../packages/shared/dist/validators/chat.js"() {
790
798
  "use strict";
@@ -817,9 +825,39 @@ var init_chat = __esm({
817
825
  primaryIssueId: z4.string().uuid().optional().nullable(),
818
826
  resolvedAt: z4.string().datetime().optional().nullable()
819
827
  });
828
+ forkChatConversationSchema = z4.object({
829
+ sourceMessageId: z4.string().uuid().optional().nullable(),
830
+ title: z4.string().trim().min(1).max(200).optional()
831
+ });
820
832
  addChatMessageSchema = z4.object({
821
833
  body: z4.string().trim().min(1).max(2e4),
822
- editUserMessageId: z4.string().uuid().optional().nullable()
834
+ editUserMessageId: z4.string().uuid().optional().nullable(),
835
+ queuedMessageId: z4.string().uuid().optional().nullable()
836
+ });
837
+ chatQueuedMessagePayloadSchema = z4.object({
838
+ body: z4.string().trim().min(1).max(2e4),
839
+ attachmentIds: z4.array(z4.string().uuid()).optional().default([]),
840
+ projectId: z4.string().uuid().optional().nullable(),
841
+ skillRefs: z4.array(z4.string().trim().min(1).max(240)).optional().default([]),
842
+ accessMode: z4.string().trim().min(1).max(120).optional().nullable(),
843
+ model: z4.string().trim().min(1).max(120).optional().nullable(),
844
+ effort: z4.string().trim().min(1).max(120).optional().nullable(),
845
+ metadata: z4.record(z4.unknown()).optional().nullable()
846
+ });
847
+ createChatQueuedMessageSchema = z4.object({
848
+ clientMutationId: z4.string().trim().min(1).max(120),
849
+ expectedGenerationId: z4.string().uuid().optional().nullable(),
850
+ payload: chatQueuedMessagePayloadSchema
851
+ });
852
+ updateChatQueuedMessageSchema = z4.object({
853
+ version: z4.number().int().positive(),
854
+ payload: chatQueuedMessagePayloadSchema
855
+ });
856
+ cancelChatQueuedMessageSchema = z4.object({
857
+ version: z4.number().int().positive().optional()
858
+ });
859
+ steerChatQueuedMessageSchema = z4.object({
860
+ expectedActiveGenerationId: z4.string().uuid().optional().nullable()
823
861
  });
824
862
  chatRichReferenceDisplaySchema = z4.enum(["card", "inline"]);
825
863
  chatIssueIdentifierSchema = z4.string().trim().min(1).max(64).regex(/^[A-Z0-9][A-Z0-9-]*$/i);
@@ -972,12 +1010,14 @@ var init_chat = __esm({
972
1010
  icon: z4.string().trim().min(1).max(24).optional().nullable()
973
1011
  });
974
1012
  createMessengerCustomGroupWithEntriesSchema = createMessengerCustomGroupSchema.extend({
975
- threadKeys: z4.array(z4.string().trim().min(1).max(240)).min(1).max(50)
1013
+ threadKeys: z4.array(z4.string().trim().min(1).max(240)).min(1).max(50),
1014
+ autoGenerateName: z4.boolean().optional()
976
1015
  });
977
1016
  updateMessengerCustomGroupSchema = z4.object({
978
1017
  name: z4.string().trim().min(1).max(80).optional(),
979
1018
  icon: z4.string().trim().min(1).max(24).optional().nullable(),
980
1019
  collapsed: z4.boolean().optional(),
1020
+ pinned: z4.boolean().optional(),
981
1021
  sortOrder: z4.number().int().min(0).optional()
982
1022
  });
983
1023
  reorderMessengerCustomGroupsSchema = z4.object({
@@ -2985,6 +3025,7 @@ var init_api = __esm({
2985
3025
  secrets: `${API_PREFIX}/secrets`,
2986
3026
  costs: `${API_PREFIX}/costs`,
2987
3027
  activity: `${API_PREFIX}/activity`,
3028
+ agentRuns: `${API_PREFIX}/agent-runs`,
2988
3029
  dashboard: `${API_PREFIX}/dashboard`,
2989
3030
  sidebarBadges: `${API_PREFIX}/sidebar-badges`,
2990
3031
  invites: `${API_PREFIX}/invites`,
@@ -3183,6 +3224,7 @@ var init_config_schema = __esm({
3183
3224
  })
3184
3225
  });
3185
3226
  langfuseConfigSchema = z28.object({
3227
+ installed: z28.boolean().optional(),
3186
3228
  enabled: z28.boolean().default(false),
3187
3229
  baseUrl: z28.string().url().default("http://localhost:3000"),
3188
3230
  publicKey: z28.string().optional(),
@@ -3260,6 +3302,7 @@ var init_dist = __esm({
3260
3302
  "../packages/shared/dist/index.js"() {
3261
3303
  "use strict";
3262
3304
  init_constants();
3305
+ init_agent_run();
3263
3306
  init_observability();
3264
3307
  init_workspace_backup();
3265
3308
  init_validators();
@@ -3491,8 +3534,8 @@ var init_env = __esm({
3491
3534
  });
3492
3535
 
3493
3536
  // src/runtime/install.ts
3494
- import { spawnSync } from "node:child_process";
3495
- import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
3537
+ import { execFileSync, spawnSync } from "node:child_process";
3538
+ import { cp, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
3496
3539
  import { createRequire } from "node:module";
3497
3540
  import path4 from "node:path";
3498
3541
  import { pathToFileURL } from "node:url";
@@ -3561,23 +3604,6 @@ async function hasRequiredRuntimePlatformDependencies(cacheDir) {
3561
3604
  if (!platformPackage) return true;
3562
3605
  return await canResolveRuntimePackage(cacheDir, platformPackage);
3563
3606
  }
3564
- async function assertRequiredRuntimePlatformDependencies(cacheDir, command, output) {
3565
- if (!await canResolveRuntimePackage(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return;
3566
- const platformPackage = resolveEmbeddedPostgresPlatformPackage();
3567
- if (!platformPackage || await canResolveRuntimePackage(cacheDir, platformPackage)) return;
3568
- throw new RuntimeInstallError(
3569
- `Rudder runtime installation is missing required platform package ${platformPackage}. Re-run manually: ${command}`,
3570
- {
3571
- cacheDir,
3572
- command,
3573
- output: [
3574
- output,
3575
- `Missing required optional dependency: ${platformPackage}`,
3576
- "Your npm registry, mirror, proxy, or cache may have skipped the embedded PostgreSQL platform package."
3577
- ].filter((line) => line.trim().length > 0).join("\n")
3578
- }
3579
- );
3580
- }
3581
3607
  async function isRuntimeCacheHit(options) {
3582
3608
  const packageName = options.packageName ?? RUNTIME_NPM_PACKAGE_NAME;
3583
3609
  const packageVersion = resolveRuntimePackageVersion(options.version);
@@ -3600,7 +3626,9 @@ async function ensureRuntimeInstalled(options) {
3600
3626
  const cacheDir = resolveRuntimeCacheDir(packageVersion, options.homeDir);
3601
3627
  const packageSpec = resolveRuntimePackageSpec(packageVersion, packageName);
3602
3628
  const command = formatRuntimeInstallCommand(cacheDir, packageSpec);
3629
+ const preparePostgresPayload = options.preparePostgresPayload === true;
3603
3630
  if (await isRuntimeCacheHit({ cacheDir, version: packageVersion, packageName })) {
3631
+ const postgresPayload2 = await stageRuntimePostgresPayload(cacheDir, preparePostgresPayload);
3604
3632
  await touchRuntimeInstallMetadata(cacheDir);
3605
3633
  const prune2 = await maybePruneRuntimeCache({
3606
3634
  homeDir: options.homeDir,
@@ -3608,37 +3636,75 @@ async function ensureRuntimeInstalled(options) {
3608
3636
  enabled: options.pruneRuntimeCache !== false,
3609
3637
  retention: options.retention
3610
3638
  });
3611
- return { status: "hit", cacheDir, packageSpec, command, output: "", ...prune2 ? { prune: prune2 } : {} };
3639
+ return withPostgresPayload(
3640
+ { status: "hit", cacheDir, packageSpec, command, output: "", ...prune2 ? { prune: prune2 } : {} },
3641
+ postgresPayload2
3642
+ );
3643
+ }
3644
+ const spawnSyncImpl = options.spawnSyncImpl ?? spawnSync;
3645
+ const existingRuntimeOutput = await tryRepairExistingRuntimePackage({
3646
+ spawnSyncImpl,
3647
+ cacheDir,
3648
+ packageName,
3649
+ packageVersion
3650
+ });
3651
+ if (existingRuntimeOutput !== null) {
3652
+ const postgresPayload2 = await stageRuntimePostgresPayload(cacheDir, preparePostgresPayload);
3653
+ const metadata2 = {
3654
+ version: 1,
3655
+ packageName,
3656
+ packageVersion,
3657
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
3658
+ lastUsedAt: (/* @__PURE__ */ new Date()).toISOString()
3659
+ };
3660
+ await writeRuntimeInstallMetadata(cacheDir, metadata2);
3661
+ const prune2 = await maybePruneRuntimeCache({
3662
+ homeDir: options.homeDir,
3663
+ requestedVersion: packageVersion,
3664
+ enabled: options.pruneRuntimeCache !== false,
3665
+ retention: options.retention
3666
+ });
3667
+ return withPostgresPayload(
3668
+ { status: "installed", cacheDir, packageSpec, command, output: existingRuntimeOutput, ...prune2 ? { prune: prune2 } : {} },
3669
+ postgresPayload2
3670
+ );
3612
3671
  }
3613
3672
  await rm(cacheDir, { recursive: true, force: true });
3614
3673
  await mkdir(cacheDir, { recursive: true });
3615
- await writeFile(path4.join(cacheDir, "package.json"), `${JSON.stringify({ private: true, type: "module" }, null, 2)}
3674
+ await writeFile(path4.join(cacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
3616
3675
  `, "utf8");
3617
- const spawnSyncImpl = options.spawnSyncImpl ?? spawnSync;
3618
3676
  const result = runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec);
3619
- const output = collectSpawnOutput(result);
3677
+ let output = collectSpawnOutput(result);
3620
3678
  if (result.status !== 0 && packageVersion !== "latest" && isVersionNotFoundError(output)) {
3621
3679
  const fallbackVersion = "latest";
3622
3680
  const fallbackCacheDir = resolveRuntimeCacheDir(fallbackVersion, options.homeDir);
3623
3681
  const fallbackSpec = resolveRuntimePackageSpec(fallbackVersion, packageName);
3624
3682
  if (await isRuntimeCacheHit({ cacheDir: fallbackCacheDir, version: fallbackVersion, packageName })) {
3683
+ const fallbackPostgresPayload = await stageRuntimePostgresPayload(fallbackCacheDir, preparePostgresPayload);
3625
3684
  await touchRuntimeInstallMetadata(fallbackCacheDir);
3626
- return {
3627
- status: "hit",
3628
- cacheDir: fallbackCacheDir,
3629
- packageSpec: fallbackSpec,
3630
- command: formatRuntimeInstallCommand(fallbackCacheDir, fallbackSpec),
3631
- output: ""
3632
- };
3685
+ return withPostgresPayload(
3686
+ {
3687
+ status: "hit",
3688
+ cacheDir: fallbackCacheDir,
3689
+ packageSpec: fallbackSpec,
3690
+ command: formatRuntimeInstallCommand(fallbackCacheDir, fallbackSpec),
3691
+ output: ""
3692
+ },
3693
+ fallbackPostgresPayload
3694
+ );
3633
3695
  }
3634
3696
  await rm(fallbackCacheDir, { recursive: true, force: true });
3635
3697
  await mkdir(fallbackCacheDir, { recursive: true });
3636
- await writeFile(path4.join(fallbackCacheDir, "package.json"), `${JSON.stringify({ private: true, type: "module" }, null, 2)}
3698
+ await writeFile(path4.join(fallbackCacheDir, "package.json"), `${JSON.stringify(RUNTIME_CACHE_PACKAGE_JSON, null, 2)}
3637
3699
  `, "utf8");
3638
3700
  const fallbackResult = runNpmRuntimeInstall(spawnSyncImpl, fallbackCacheDir, fallbackSpec);
3639
- const fallbackOutput = collectSpawnOutput(fallbackResult);
3701
+ let fallbackOutput = collectSpawnOutput(fallbackResult);
3640
3702
  if (fallbackResult.status === 0) {
3641
- await assertRequiredRuntimePlatformDependencies(fallbackCacheDir, formatRuntimeInstallCommand(fallbackCacheDir, fallbackSpec), fallbackOutput);
3703
+ fallbackOutput = collectOutputParts(
3704
+ fallbackOutput,
3705
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, fallbackCacheDir)
3706
+ );
3707
+ const postgresPayload2 = await stageRuntimePostgresPayload(fallbackCacheDir, preparePostgresPayload);
3642
3708
  const fallbackMetadata = {
3643
3709
  version: 1,
3644
3710
  packageName,
@@ -3647,13 +3713,16 @@ async function ensureRuntimeInstalled(options) {
3647
3713
  lastUsedAt: (/* @__PURE__ */ new Date()).toISOString()
3648
3714
  };
3649
3715
  await writeRuntimeInstallMetadata(fallbackCacheDir, fallbackMetadata);
3650
- return {
3651
- status: "installed",
3652
- cacheDir: fallbackCacheDir,
3653
- packageSpec: fallbackSpec,
3654
- command: formatRuntimeInstallCommand(fallbackCacheDir, fallbackSpec),
3655
- output: fallbackOutput
3656
- };
3716
+ return withPostgresPayload(
3717
+ {
3718
+ status: "installed",
3719
+ cacheDir: fallbackCacheDir,
3720
+ packageSpec: fallbackSpec,
3721
+ command: formatRuntimeInstallCommand(fallbackCacheDir, fallbackSpec),
3722
+ output: fallbackOutput
3723
+ },
3724
+ postgresPayload2
3725
+ );
3657
3726
  }
3658
3727
  }
3659
3728
  if (result.status !== 0) {
@@ -3662,7 +3731,11 @@ async function ensureRuntimeInstalled(options) {
3662
3731
  { cacheDir, command, output }
3663
3732
  );
3664
3733
  }
3665
- await assertRequiredRuntimePlatformDependencies(cacheDir, command, output);
3734
+ output = collectOutputParts(
3735
+ output,
3736
+ await ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir)
3737
+ );
3738
+ const postgresPayload = await stageRuntimePostgresPayload(cacheDir, preparePostgresPayload);
3666
3739
  const metadata = {
3667
3740
  version: 1,
3668
3741
  packageName,
@@ -3677,7 +3750,13 @@ async function ensureRuntimeInstalled(options) {
3677
3750
  enabled: options.pruneRuntimeCache !== false,
3678
3751
  retention: options.retention
3679
3752
  });
3680
- return { status: "installed", cacheDir, packageSpec, command, output, ...prune ? { prune } : {} };
3753
+ return withPostgresPayload(
3754
+ { status: "installed", cacheDir, packageSpec, command, output, ...prune ? { prune } : {} },
3755
+ postgresPayload
3756
+ );
3757
+ }
3758
+ function resolveRuntimePostgresPayloadBinDir(cacheDir, platform = process.platform, arch = process.arch) {
3759
+ return path4.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR, runtimePostgresPlatformSegment(platform, arch), "bin");
3681
3760
  }
3682
3761
  function resolveRuntimeServerEntrypoint(cacheDir, packageName = RUNTIME_NPM_PACKAGE_NAME) {
3683
3762
  return createRequire(path4.join(cacheDir, "package.json")).resolve(packageName);
@@ -3700,9 +3779,204 @@ function runNpmRuntimeInstall(spawnSyncImpl, cacheDir, packageSpec) {
3700
3779
  function formatRuntimeInstallCommand(cacheDir, packageSpec) {
3701
3780
  return `npm install --prefix ${cacheDir} ${RUNTIME_NPM_INSTALL_FLAGS.join(" ")} ${packageSpec}`;
3702
3781
  }
3782
+ function formatRuntimePlatformRepairCommand(cacheDir, packageSpec) {
3783
+ return `npm pack ${packageSpec} --registry=${NPM_PUBLIC_REGISTRY_URL} --silent, then extract it into ${path4.join(cacheDir, "node_modules")}`;
3784
+ }
3703
3785
  function collectSpawnOutput(result) {
3704
3786
  return [result.stdout, result.stderr, result.error instanceof Error ? result.error.message : null].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
3705
3787
  }
3788
+ function collectOutputParts(...parts) {
3789
+ return parts.filter((part) => part.trim().length > 0).join("\n").trim();
3790
+ }
3791
+ function withPostgresPayload(result, postgresPayload) {
3792
+ return {
3793
+ ...result,
3794
+ output: collectOutputParts(result.output, postgresPayload.output),
3795
+ ...postgresPayload.binDir ? { postgresPayloadBinDir: postgresPayload.binDir } : {}
3796
+ };
3797
+ }
3798
+ function runtimePackageJsonPath(cacheDir, packageName) {
3799
+ return path4.join(cacheDir, "node_modules", ...packageName.split("/"), "package.json");
3800
+ }
3801
+ async function readRuntimePackageJson(cacheDir, packageName) {
3802
+ try {
3803
+ return JSON.parse(await readFile(runtimePackageJsonPath(cacheDir, packageName), "utf8"));
3804
+ } catch {
3805
+ return null;
3806
+ }
3807
+ }
3808
+ async function tryRepairExistingRuntimePackage(options) {
3809
+ const runtimePackage = await readRuntimePackageJson(options.cacheDir, options.packageName);
3810
+ if (!runtimePackage) return null;
3811
+ if (options.packageVersion !== "latest" && runtimePackage.version !== options.packageVersion) return null;
3812
+ const output = await ensureRequiredEmbeddedPostgresPlatformPackage(options.spawnSyncImpl, options.cacheDir);
3813
+ return await hasRequiredRuntimePlatformDependencies(options.cacheDir) ? output : null;
3814
+ }
3815
+ async function resolveEmbeddedPostgresPlatformPackageSpec(cacheDir) {
3816
+ if (!await canResolveRuntimePackage(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME)) return null;
3817
+ const packageName = resolveEmbeddedPostgresPlatformPackage();
3818
+ if (!packageName) return null;
3819
+ const embeddedPostgresPackage = await readRuntimePackageJson(cacheDir, EMBEDDED_POSTGRES_PACKAGE_NAME);
3820
+ const versionRange = embeddedPostgresPackage?.optionalDependencies?.[packageName];
3821
+ const packageVersion = normalizeOptionalDependencyVersion(versionRange);
3822
+ return packageVersion ? `${packageName}@${packageVersion}` : packageName;
3823
+ }
3824
+ async function ensureRequiredEmbeddedPostgresPlatformPackage(spawnSyncImpl, cacheDir) {
3825
+ const packageSpec = await resolveEmbeddedPostgresPlatformPackageSpec(cacheDir);
3826
+ if (!packageSpec) return "";
3827
+ const packageName = packageNameFromSpec(packageSpec);
3828
+ if (packageName && await canResolveRuntimePackage(cacheDir, packageName)) return "";
3829
+ await removeRuntimeInstallLocks(cacheDir);
3830
+ const result = await installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName);
3831
+ const output = collectSpawnOutput(result);
3832
+ if (result.status === 0 && packageName && await canResolveRuntimePackage(cacheDir, packageName)) {
3833
+ return output;
3834
+ }
3835
+ const command = formatRuntimePlatformRepairCommand(cacheDir, packageSpec);
3836
+ throw new RuntimeInstallError(
3837
+ `Rudder runtime installation is missing required platform package ${packageName || packageSpec}. Re-run manually: ${command}`,
3838
+ { cacheDir, command, output }
3839
+ );
3840
+ }
3841
+ async function installRuntimePackageInStaging(spawnSyncImpl, cacheDir, packageSpec, packageName) {
3842
+ const stagingDir = path4.join(cacheDir, `.platform-repair-${process.pid}-${Date.now()}`);
3843
+ await mkdir(stagingDir, { recursive: true });
3844
+ try {
3845
+ const packResult = runNpmPack(spawnSyncImpl, packageSpec, stagingDir);
3846
+ if (packResult.status !== 0) return packResult;
3847
+ const packFilename = parseNpmPackFilename(packResult.stdout);
3848
+ if (!packFilename) {
3849
+ return createSyntheticSpawnResult(1, "", `Unable to parse npm pack output for ${packageSpec}.`);
3850
+ }
3851
+ const archivePath = path4.join(stagingDir, packFilename);
3852
+ const targetDir = path4.dirname(runtimePackageJsonPath(cacheDir, packageName));
3853
+ await mkdir(path4.dirname(targetDir), { recursive: true });
3854
+ await rm(targetDir, { recursive: true, force: true });
3855
+ await mkdir(targetDir, { recursive: true });
3856
+ const extractResult = runTarExtract(spawnSyncImpl, archivePath, targetDir);
3857
+ return combineSpawnResults(packResult, extractResult);
3858
+ } finally {
3859
+ await rm(stagingDir, { recursive: true, force: true });
3860
+ }
3861
+ }
3862
+ function runNpmPack(spawnSyncImpl, packageSpec, destinationDir) {
3863
+ return spawnSyncImpl(
3864
+ process.platform === "win32" ? "npm.cmd" : "npm",
3865
+ ["pack", packageSpec, "--pack-destination", destinationDir, ...RUNTIME_NPM_PACK_FLAGS],
3866
+ {
3867
+ encoding: "utf8",
3868
+ stdio: ["ignore", "pipe", "pipe"],
3869
+ env: { ...process.env, ...NPM_PLATFORM_REPAIR_ENV },
3870
+ ...process.platform === "win32" ? { shell: true, windowsHide: true } : {}
3871
+ }
3872
+ );
3873
+ }
3874
+ function runTarExtract(spawnSyncImpl, archivePath, targetDir) {
3875
+ return spawnSyncImpl(
3876
+ "tar",
3877
+ ["-xzf", archivePath, "-C", targetDir, "--strip-components", "1"],
3878
+ {
3879
+ encoding: "utf8",
3880
+ stdio: ["ignore", "pipe", "pipe"],
3881
+ ...process.platform === "win32" ? { windowsHide: true } : {}
3882
+ }
3883
+ );
3884
+ }
3885
+ function parseNpmPackFilename(stdout) {
3886
+ if (typeof stdout !== "string") return null;
3887
+ const filename = stdout.trim().split(/\r?\n/).filter(Boolean).at(-1);
3888
+ return filename?.endsWith(".tgz") ? filename : null;
3889
+ }
3890
+ function createSyntheticSpawnResult(status, stdout, stderr) {
3891
+ return { status, stdout, stderr };
3892
+ }
3893
+ function combineSpawnResults(...results) {
3894
+ const last = results.at(-1);
3895
+ return {
3896
+ status: last?.status ?? 0,
3897
+ stdout: results.map((result) => result.stdout).filter(Boolean).join("\n"),
3898
+ stderr: results.map((result) => result.stderr).filter(Boolean).join("\n"),
3899
+ error: results.find((result) => result.error)?.error
3900
+ };
3901
+ }
3902
+ async function removeRuntimeInstallLocks(cacheDir) {
3903
+ await Promise.all([
3904
+ rm(path4.join(cacheDir, "package-lock.json"), { force: true }),
3905
+ rm(path4.join(cacheDir, "node_modules", ".package-lock.json"), { force: true })
3906
+ ]);
3907
+ }
3908
+ function packageNameFromSpec(packageSpec) {
3909
+ if (!packageSpec.startsWith("@")) {
3910
+ const versionSeparator2 = packageSpec.indexOf("@");
3911
+ return versionSeparator2 === -1 ? packageSpec : packageSpec.slice(0, versionSeparator2);
3912
+ }
3913
+ const versionSeparator = packageSpec.indexOf("@", 1);
3914
+ return versionSeparator === -1 ? packageSpec : packageSpec.slice(0, versionSeparator);
3915
+ }
3916
+ function normalizeOptionalDependencyVersion(versionRange) {
3917
+ const trimmed = versionRange?.trim();
3918
+ if (!trimmed) return null;
3919
+ const exactVersion = /^[~^]\s*([0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?)$/.exec(trimmed);
3920
+ return exactVersion?.[1] ?? trimmed;
3921
+ }
3922
+ function runtimePostgresPlatformSegment(platform = process.platform, arch = process.arch) {
3923
+ return `${platform}-${arch}`;
3924
+ }
3925
+ function runtimePostgresExecutableName(baseName) {
3926
+ return process.platform === "win32" ? `${baseName}.exe` : baseName;
3927
+ }
3928
+ async function assertRuntimePostgresBinDirComplete(cacheDir, binDir) {
3929
+ const requiredBinaries = ["initdb", "pg_ctl", "postgres"];
3930
+ const missing = [];
3931
+ for (const binary of requiredBinaries) {
3932
+ const binaryPath = path4.join(binDir, runtimePostgresExecutableName(binary));
3933
+ try {
3934
+ await stat(binaryPath);
3935
+ } catch {
3936
+ missing.push(binaryPath);
3937
+ }
3938
+ }
3939
+ if (missing.length > 0) {
3940
+ throw new RuntimeInstallError(
3941
+ `${RUDDER_POSTGRES_BIN_DIR_ENV} must contain PostgreSQL 18.4 initdb, pg_ctl, and postgres binaries; missing ${missing.join(", ")}`,
3942
+ { cacheDir, command: "validate PostgreSQL 18.4 runtime payload", output: "" }
3943
+ );
3944
+ }
3945
+ }
3946
+ async function isRuntimePostgresPayloadUsable(cacheDir, binDir) {
3947
+ try {
3948
+ await assertRuntimePostgresBinDirComplete(cacheDir, binDir);
3949
+ const postgresBinary = path4.join(binDir, runtimePostgresExecutableName("postgres"));
3950
+ const result = execFileSync(postgresBinary, ["--version"], { encoding: "utf8" });
3951
+ return /\bPostgreSQL\)?\s+18\.4\b/i.test(result);
3952
+ } catch {
3953
+ return false;
3954
+ }
3955
+ }
3956
+ async function stageRuntimePostgresPayload(cacheDir, enabled) {
3957
+ const targetRuntimeDir = path4.join(cacheDir, RUNTIME_POSTGRES_PAYLOAD_DIR);
3958
+ const targetBinDir = resolveRuntimePostgresPayloadBinDir(cacheDir);
3959
+ if (await isRuntimePostgresPayloadUsable(cacheDir, targetBinDir)) {
3960
+ return { output: "", binDir: targetBinDir };
3961
+ }
3962
+ if (!enabled) return { output: "" };
3963
+ const sourceBinDir = process.env[RUDDER_POSTGRES_BIN_DIR_ENV]?.trim();
3964
+ if (!sourceBinDir) return { output: "" };
3965
+ const resolvedSourceBinDir = path4.resolve(sourceBinDir);
3966
+ await assertRuntimePostgresBinDirComplete(cacheDir, resolvedSourceBinDir);
3967
+ const postgresBinary = path4.join(resolvedSourceBinDir, runtimePostgresExecutableName("postgres"));
3968
+ const result = execFileSync(postgresBinary, ["--version"], { encoding: "utf8" });
3969
+ if (!/\bPostgreSQL\)?\s+18\.4\b/i.test(result)) {
3970
+ throw new RuntimeInstallError(
3971
+ `${RUDDER_POSTGRES_BIN_DIR_ENV} must contain PostgreSQL 18.4 production binaries; got ${result.trim() || "unknown version"}`,
3972
+ { cacheDir, command: `${postgresBinary} --version`, output: result }
3973
+ );
3974
+ }
3975
+ await rm(targetRuntimeDir, { recursive: true, force: true });
3976
+ await mkdir(path4.dirname(targetBinDir), { recursive: true });
3977
+ await cp(resolvedSourceBinDir, targetBinDir, { recursive: true });
3978
+ return { output: `staged PostgreSQL 18.4 runtime payload at ${targetBinDir}`, binDir: targetBinDir };
3979
+ }
3706
3980
  function isVersionNotFoundError(output) {
3707
3981
  const normalized = output.toLowerCase();
3708
3982
  return normalized.includes("enoent") || normalized.includes("etarget") || normalized.includes("no matching version found");
@@ -3928,19 +4202,34 @@ function parseRuntimeVersion(version) {
3928
4202
  canaryNumber: canaryMatch ? Number(canaryMatch[1]) : null
3929
4203
  };
3930
4204
  }
3931
- var RUNTIME_NPM_PACKAGE_NAME, RUNTIME_METADATA_FILE, DEFAULT_RUNTIME_CACHE_MAX_ENTRIES, DEFAULT_RUNTIME_CACHE_MAX_AGE_MS, DEFAULT_RUNTIME_CACHE_MAX_BYTES, DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS, RUNTIME_NPM_INSTALL_FLAGS, EMBEDDED_POSTGRES_PACKAGE_NAME, RuntimeInstallError;
4205
+ var RUNTIME_NPM_PACKAGE_NAME, NPM_PUBLIC_REGISTRY_URL, RUNTIME_METADATA_FILE, RUNTIME_POSTGRES_PAYLOAD_DIR, DEFAULT_RUNTIME_CACHE_MAX_ENTRIES, DEFAULT_RUNTIME_CACHE_MAX_AGE_MS, DEFAULT_RUNTIME_CACHE_MAX_BYTES, DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS, RUNTIME_NPM_INSTALL_FLAGS, RUNTIME_NPM_PACK_FLAGS, EMBEDDED_POSTGRES_PACKAGE_NAME, RUDDER_POSTGRES_BIN_DIR_ENV, RUNTIME_CACHE_PACKAGE_JSON, NPM_PLATFORM_REPAIR_ENV, RuntimeInstallError;
3932
4206
  var init_install = __esm({
3933
4207
  "src/runtime/install.ts"() {
3934
4208
  "use strict";
3935
4209
  init_home();
3936
4210
  RUNTIME_NPM_PACKAGE_NAME = "@rudderhq/server";
4211
+ NPM_PUBLIC_REGISTRY_URL = "https://registry.npmjs.org";
3937
4212
  RUNTIME_METADATA_FILE = "runtime.json";
4213
+ RUNTIME_POSTGRES_PAYLOAD_DIR = "postgres-18.4";
3938
4214
  DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 2;
3939
4215
  DEFAULT_RUNTIME_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
3940
4216
  DEFAULT_RUNTIME_CACHE_MAX_BYTES = 2 * 1024 * 1024 * 1024;
3941
4217
  DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 0;
3942
4218
  RUNTIME_NPM_INSTALL_FLAGS = ["--omit=dev", "--include=optional", "--no-audit", "--no-fund"];
4219
+ RUNTIME_NPM_PACK_FLAGS = ["--registry", NPM_PUBLIC_REGISTRY_URL, "--silent"];
3943
4220
  EMBEDDED_POSTGRES_PACKAGE_NAME = "embedded-postgres";
4221
+ RUDDER_POSTGRES_BIN_DIR_ENV = "RUDDER_POSTGRES_BIN_DIR";
4222
+ RUNTIME_CACHE_PACKAGE_JSON = {
4223
+ name: "rudder-runtime-cache",
4224
+ version: "0.0.0",
4225
+ private: true,
4226
+ type: "module"
4227
+ };
4228
+ NPM_PLATFORM_REPAIR_ENV = {
4229
+ npm_config_registry: NPM_PUBLIC_REGISTRY_URL,
4230
+ npm_config_update_notifier: "false",
4231
+ NO_UPDATE_NOTIFIER: "1"
4232
+ };
3944
4233
  RuntimeInstallError = class extends Error {
3945
4234
  cacheDir;
3946
4235
  command;
@@ -3991,9 +4280,15 @@ async function loadServerRuntimeModule(options) {
3991
4280
  }
3992
4281
  const installOptions = {
3993
4282
  version: options.version,
3994
- homeDir: options.homeDir
4283
+ homeDir: options.homeDir,
4284
+ preparePostgresPayload: true
3995
4285
  };
3996
4286
  const runtime = await ensureRuntimeInstalled(installOptions);
4287
+ if (!process.env[RUDDER_POSTGRES_BIN_DIR_ENV2]?.trim()) {
4288
+ if (runtime.postgresPayloadBinDir && fs3.existsSync(runtime.postgresPayloadBinDir)) {
4289
+ process.env[RUDDER_POSTGRES_BIN_DIR_ENV2] = runtime.postgresPayloadBinDir;
4290
+ }
4291
+ }
3997
4292
  options.onRuntimeInstalled?.(runtime);
3998
4293
  return await importRuntimeServerModule(runtime.cacheDir);
3999
4294
  }
@@ -4016,10 +4311,12 @@ async function startServerFromModule(mod) {
4016
4311
  takeoverOnVersionMismatch: true
4017
4312
  });
4018
4313
  }
4314
+ var RUDDER_POSTGRES_BIN_DIR_ENV2;
4019
4315
  var init_server_entry = __esm({
4020
4316
  "src/runtime/server-entry.ts"() {
4021
4317
  "use strict";
4022
4318
  init_install();
4319
+ RUDDER_POSTGRES_BIN_DIR_ENV2 = "RUDDER_POSTGRES_BIN_DIR";
4023
4320
  }
4024
4321
  });
4025
4322
 
@@ -5622,7 +5919,7 @@ var init_doctor = __esm({
5622
5919
  });
5623
5920
 
5624
5921
  // src/install.ts
5625
- import { execFileSync, spawnSync as spawnSync2 } from "node:child_process";
5922
+ import { execFileSync as execFileSync2, spawnSync as spawnSync2 } from "node:child_process";
5626
5923
  function normalizePath(value) {
5627
5924
  return (value ?? "").replaceAll("\\", "/").toLowerCase();
5628
5925
  }
@@ -5651,10 +5948,10 @@ function isTransientBinaryPath(candidatePath) {
5651
5948
  const normalized = normalizePath(candidatePath);
5652
5949
  return normalized.includes("/_npx/");
5653
5950
  }
5654
- function hasGlobalInstalledPackage(packageName, execFileSyncImpl = execFileSync) {
5951
+ function hasGlobalInstalledPackage(packageName, execFileSyncImpl = execFileSync2) {
5655
5952
  return getGlobalInstalledPackageVersion(packageName, execFileSyncImpl) !== null;
5656
5953
  }
5657
- function getGlobalInstalledPackageVersion(packageName, execFileSyncImpl = execFileSync) {
5954
+ function getGlobalInstalledPackageVersion(packageName, execFileSyncImpl = execFileSync2) {
5658
5955
  try {
5659
5956
  const output = execFileSyncImpl(
5660
5957
  process.platform === "win32" ? "npm.cmd" : "npm",
@@ -5670,7 +5967,7 @@ function getGlobalInstalledPackageVersion(packageName, execFileSyncImpl = execFi
5670
5967
  return null;
5671
5968
  }
5672
5969
  }
5673
- function hasPersistentBinaryOnPath(execFileSyncImpl = execFileSync) {
5970
+ function hasPersistentBinaryOnPath(execFileSyncImpl = execFileSync2) {
5674
5971
  const { command, args } = resolveCommandLookupExecutable();
5675
5972
  try {
5676
5973
  const output = execFileSyncImpl(command, args, {
@@ -5685,7 +5982,7 @@ function hasPersistentBinaryOnPath(execFileSyncImpl = execFileSync) {
5685
5982
  }
5686
5983
  function detectPersistentCliState(options = {}) {
5687
5984
  const env = options.env ?? process.env;
5688
- const execFileSyncImpl = options.execFileSyncImpl ?? execFileSync;
5985
+ const execFileSyncImpl = options.execFileSyncImpl ?? execFileSync2;
5689
5986
  const installSpec = resolvePersistentCliInstallSpec(env);
5690
5987
  const usingNpx = isLikelyNpxExecutionContext(options.entryPath ?? process.argv[1], env);
5691
5988
  if (!usingNpx) {
@@ -7270,6 +7567,15 @@ function isMaintainerOnlySkillTarget(candidate) {
7270
7567
  const normalized = normalizePathSlashes(candidate);
7271
7568
  return normalized.includes("/server/resources/bundled-skills/") || normalized.includes("/.agents/skills/");
7272
7569
  }
7570
+ function parseObject(value) {
7571
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
7572
+ return {};
7573
+ }
7574
+ return value;
7575
+ }
7576
+ function asString(value, fallback) {
7577
+ return typeof value === "string" && value.length > 0 ? value : fallback;
7578
+ }
7273
7579
 
7274
7580
  // ../packages/agent-runtime-utils/dist/server-utils.prompts.js
7275
7581
  var RUDDER_AGENT_OPERATING_CONTRACT = [
@@ -7293,7 +7599,7 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
7293
7599
  "- `library:projects/<project-key>/...` is the Rudder product locator for those files, not the Markdown link syntax and not a reason to route ordinary local edits through the CLI.",
7294
7600
  '- When you create or update a durable Library file, always include a user-visible Markdown link to that file in your final chat reply or issue comment. Use `rudder library file ref "$RUDDER_PROJECT_LIBRARY_PATH/<relative-file>" --json` and paste the returned `markdownLink`; do not pass the absolute `$RUDDER_PROJECT_LIBRARY_ROOT/...` path to `ref`, and do not hand-write `library-entry://...` or `library-file://...` links.',
7295
7601
  '- If `$RUDDER_PROJECT_LIBRARY_ROOT` is unset or inaccessible, use `rudder library file get/put "$RUDDER_PROJECT_LIBRARY_PATH/<relative-file>"` as the remote or restricted runtime fallback.',
7296
- "- Use `/tmp` only for transient scratch files and temporary verification files; do not put durable work product there.",
7602
+ "- Use `$RUDDER_RUNTIME_TMPDIR` for transient scratch files and temporary verification files when it is set; otherwise use `/tmp`. Do not put durable work product there.",
7297
7603
  "- Local trusted runtimes may expose the host operator home as `$RUDDER_OPERATOR_HOME`; use it only when a local skill or script intentionally needs operator-owned desktop app or CLI state. Do not replace `$HOME` with it.",
7298
7604
  "",
7299
7605
  "When you create or copy a skill under `$AGENT_HOME/skills/<slug>/`, check the agent's Skills snapshot before claiming it will load in future runs. If it is installed but not enabled, say exactly that future runs will not load it until enabled, and offer to enable it with `rudder agent skills enable <agent-id> <selection-ref>` when you have permission.",
@@ -7340,16 +7646,16 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
7340
7646
  var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
7341
7647
  "# Rudder Heartbeat Instruction",
7342
7648
  "",
7343
- "This section is injected by Rudder for heartbeat scene runs. It is the platform-owned timed-wakeup pipeline.",
7649
+ "This section is injected by Rudder only for heartbeat scene runs. It is the platform-owned heartbeat/self-check pipeline.",
7344
7650
  "",
7345
7651
  "## Heartbeat Pipeline",
7346
7652
  "",
7347
7653
  "1. Identify yourself and inspect wake context, including `RUDDER_TASK_ID`, `RUDDER_WAKE_REASON`, `RUDDER_WAKE_COMMENT_ID`, and `RUDDER_APPROVAL_ID` when present.",
7348
7654
  "2. Local Planning Check:",
7349
7655
  " ",
7350
- " 1. Read today's plan from `$AGENT_HOME/memory/YYYY-MM-DD.md` under \"## Today's Plan\". You need to clearly know your work plan for today, and work according to the plan.",
7351
- " 2. Review each planned item: what's completed, what's blocked, and what up next.",
7352
- " 3. Record progress updates in the daily notes.",
7656
+ "- Read today's plan from `$AGENT_HOME/memory/YYYY-MM-DD.md` under \"## Today's Plan\". You need to clearly know your work plan for today, and work according to the plan.",
7657
+ "- Review each planned item: what's completed, what's blocked, and what up next.",
7658
+ "- Record progress updates in the daily notes.",
7353
7659
  " ",
7354
7660
  "3.Then handle approval follow-up: read the approval and linked issues, then close resolved work or comment on what remains.",
7355
7661
  "4. Inspect your Rudder inbox. Prioritize reviewer rows in `in_review` or `blocked`, then assignee `in_progress`, then assignee `todo`. Do not look for unassigned work.",
@@ -7357,8 +7663,8 @@ var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
7357
7663
  "6. Checkout before doing assignee task work. A `409` means another agent owns the task; do not retry it.",
7358
7664
  "7. Load compact issue context, do one bounded useful chunk, and preserve evidence.",
7359
7665
  "8. Before exiting active work, leave exactly one durable signal: progress, done, blocked, explicit handoff, or structured review decision.",
7360
- "9. Treat passive follow-up as close-out governance, not a fresh assignment.",
7361
- "10. Treat review close-out follow-up as review governance; free-form accept/reject text is not a durable decision.",
7666
+ "9. Treat passive follow-up as issue follow-up, not a fresh assignment.",
7667
+ "10. Treat review close-out follow-up as review follow-up; free-form accept/reject text is not a durable decision.",
7362
7668
  "",
7363
7669
  "Use the Rudder control-plane interface available in this runtime. CLI-capable runtimes should use the bundled `rudder` skill for command details, Library handoff rules, organization-skill workflow, and control-plane best practices. HTTP compatibility runtimes should follow the explicit HTTP workflow in their wake text; that workflow overrides CLI command guidance."
7364
7670
  ].join("\n");
@@ -7381,25 +7687,48 @@ async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
7381
7687
  return null;
7382
7688
  }
7383
7689
  async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames) {
7690
+ return removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames);
7691
+ }
7692
+ async function readRudderMaterializedSkillSource(target) {
7693
+ const manifestPath = path9.join(target, ".rudder", "materialized-skill.json");
7694
+ const raw = await fs6.readFile(manifestPath, "utf8").catch(() => null);
7695
+ if (!raw)
7696
+ return null;
7697
+ try {
7698
+ const parsed = parseObject(JSON.parse(raw));
7699
+ const sourcePath = asString(parsed.sourcePath, "").trim();
7700
+ return sourcePath.length > 0 ? path9.resolve(sourcePath) : null;
7701
+ } catch {
7702
+ return null;
7703
+ }
7704
+ }
7705
+ async function removeUnselectedRudderSkillSymlinks(skillsHome, allowedSkillNames, knownSkillSources = []) {
7384
7706
  const allowed = new Set(Array.from(allowedSkillNames));
7707
+ const knownSources = new Set(Array.from(knownSkillSources).map((value) => value.trim()).filter(Boolean).map((value) => path9.resolve(value)));
7385
7708
  try {
7386
7709
  const entries = await fs6.readdir(skillsHome, { withFileTypes: true });
7387
7710
  const removed = [];
7388
7711
  for (const entry of entries) {
7389
- if (allowed.has(entry.name))
7390
- continue;
7391
7712
  const target = path9.join(skillsHome, entry.name);
7392
7713
  const existing = await fs6.lstat(target).catch(() => null);
7393
- if (!existing?.isSymbolicLink())
7714
+ if (!existing)
7394
7715
  continue;
7395
- const linkedPath = await fs6.readlink(target).catch(() => null);
7396
- if (!linkedPath)
7716
+ let isRudderManagedSkill = false;
7717
+ if (existing.isSymbolicLink()) {
7718
+ const linkedPath = await fs6.readlink(target).catch(() => null);
7719
+ if (!linkedPath)
7720
+ continue;
7721
+ const resolvedLinkedPath = path9.isAbsolute(linkedPath) ? linkedPath : path9.resolve(path9.dirname(target), linkedPath);
7722
+ isRudderManagedSkill = knownSources.has(path9.resolve(resolvedLinkedPath)) || isMaintainerOnlySkillTarget(linkedPath) || isMaintainerOnlySkillTarget(resolvedLinkedPath);
7723
+ } else if (existing.isDirectory()) {
7724
+ const materializedSource = await readRudderMaterializedSkillSource(target);
7725
+ isRudderManagedSkill = materializedSource !== null && knownSources.has(materializedSource);
7726
+ }
7727
+ if (!isRudderManagedSkill)
7397
7728
  continue;
7398
- const resolvedLinkedPath = path9.isAbsolute(linkedPath) ? linkedPath : path9.resolve(path9.dirname(target), linkedPath);
7399
- if (!isMaintainerOnlySkillTarget(linkedPath) && !isMaintainerOnlySkillTarget(resolvedLinkedPath)) {
7729
+ if (allowed.has(entry.name))
7400
7730
  continue;
7401
- }
7402
- await fs6.unlink(target);
7731
+ await fs6.rm(target, { recursive: true, force: true });
7403
7732
  removed.push(entry.name);
7404
7733
  }
7405
7734
  return removed;
@@ -13668,7 +13997,7 @@ import * as p15 from "@clack/prompts";
13668
13997
  import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
13669
13998
  import { createHash, randomUUID } from "node:crypto";
13670
13999
  import { createWriteStream, constants as fsConstants, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
13671
- import { access, chmod, copyFile, cp, mkdir as mkdir3, mkdtemp, readdir as readdir3, readFile as readFile6, rm as rm2, stat as stat4, utimes, writeFile as writeFile3 } from "node:fs/promises";
14000
+ import { access, chmod, copyFile, cp as cp2, mkdir as mkdir3, mkdtemp, readdir as readdir3, readFile as readFile6, rm as rm2, stat as stat4, utimes, writeFile as writeFile3 } from "node:fs/promises";
13672
14001
  import { homedir, tmpdir } from "node:os";
13673
14002
  import path21 from "node:path";
13674
14003
  import { Readable, Transform } from "node:stream";
@@ -13963,6 +14292,9 @@ function resolveDesktopReleaseTag(version) {
13963
14292
  function isExactRuntimePackageSpec(version, packageSpec) {
13964
14293
  return version !== "latest" && packageSpec === resolveRuntimePackageSpec(version);
13965
14294
  }
14295
+ function runtimeSupportsDesktopShellAssets(version, runtime) {
14296
+ return isExactRuntimePackageSpec(version, runtime.packageSpec) && Boolean(runtime.postgresPayloadBinDir);
14297
+ }
13966
14298
  function resolveDesktopAssetTarget(platform = process.platform, arch = process.arch) {
13967
14299
  if (platform === "darwin") {
13968
14300
  if (arch !== "x64" && arch !== "arm64") {
@@ -14843,7 +15175,7 @@ async function copyPortableAppBundle(sourcePath, destinationPath) {
14843
15175
  if (isSuccessfulRobocopyExitCode(result.status)) return;
14844
15176
  throw new Error(formatCommandFailure(command.command, command.args, result.stdout, result.stderr));
14845
15177
  }
14846
- await cp(sourcePath, destinationPath, { recursive: true, verbatimSymlinks: true });
15178
+ await cp2(sourcePath, destinationPath, { recursive: true, verbatimSymlinks: true });
14847
15179
  }
14848
15180
  async function removeMacQuarantine(paths, target) {
14849
15181
  if (target.platform !== "macos") return;
@@ -14958,7 +15290,8 @@ async function runStartPhase(message, successMessage, task, progressPhase) {
14958
15290
  }
14959
15291
  async function startCommand(opts) {
14960
15292
  const installCli = opts.cli !== false;
14961
- const installDesktop = opts.desktop !== false;
15293
+ const serverOnly = opts.serverOnly === true;
15294
+ const installDesktop = !serverOnly && opts.desktop !== false;
14962
15295
  const installRuntime = opts.runtime !== false;
14963
15296
  const repo = opts.repo?.trim() || DEFAULT_DESKTOP_RELEASE_REPO;
14964
15297
  const version = opts.targetVersion?.trim() || opts.version?.trim() || resolveCurrentCliVersion();
@@ -14971,9 +15304,9 @@ async function startCommand(opts) {
14971
15304
  });
14972
15305
  }
14973
15306
  if (!installCli && !installDesktop && !installRuntime) {
14974
- throw new Error("Nothing to start. Remove --no-cli, --no-runtime, or --no-desktop.");
15307
+ throw new Error("Nothing to start. Remove --no-cli, --no-runtime, --no-desktop, or --server-only.");
14975
15308
  }
14976
- p15.intro(pc15.bgCyan(pc15.black(" rudder start ")));
15309
+ p15.intro(pc15.bgCyan(pc15.black(serverOnly ? " rudder start --server-only " : " rudder start ")));
14977
15310
  if (opts.versionCheck !== false) {
14978
15311
  const updateNotice = await getCliUpdateNotice(version);
14979
15312
  if (updateNotice) p15.log.warn(updateNotice);
@@ -14986,11 +15319,14 @@ async function startCommand(opts) {
14986
15319
  const spinner3 = p15.spinner();
14987
15320
  spinner3.start("Installing or reusing Rudder runtime...");
14988
15321
  try {
14989
- const runtime = await ensureRuntimeInstalled({ version });
14990
- runtimeSupportsShellAssets = isExactRuntimePackageSpec(version, runtime.packageSpec);
15322
+ const runtime = await ensureRuntimeInstalled({ version, preparePostgresPayload: true });
15323
+ runtimeSupportsShellAssets = runtimeSupportsDesktopShellAssets(version, runtime);
14991
15324
  spinner3.stop(
14992
15325
  runtime.status === "hit" ? `Rudder runtime cache hit at ${pc15.cyan(runtime.cacheDir)}.` : `Rudder runtime installed at ${pc15.cyan(runtime.cacheDir)}.`
14993
15326
  );
15327
+ if (!runtime.postgresPayloadBinDir && installDesktop) {
15328
+ p15.log.warn("Rudder runtime cache has no PostgreSQL 18.4 payload; the full portable Desktop asset will be used.");
15329
+ }
14994
15330
  if (!runtimeSupportsShellAssets && installDesktop) {
14995
15331
  p15.log.warn("Rudder runtime did not resolve to the exact Desktop version; the full portable Desktop asset will be used.");
14996
15332
  }
@@ -15198,6 +15534,9 @@ async function startCommand(opts) {
15198
15534
  );
15199
15535
  }
15200
15536
  });
15537
+ } else if (serverOnly) {
15538
+ p15.log.step("Server-only install");
15539
+ p15.log.message("Desktop app installation was skipped. Start the server with `rudder run` and open the printed local URL in a browser.");
15201
15540
  }
15202
15541
  p15.outro(pc15.green("Rudder start complete."));
15203
15542
  }
@@ -15268,7 +15607,7 @@ function createProgram() {
15268
15607
  });
15269
15608
  loadRudderEnvFile(options.config);
15270
15609
  });
15271
- program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
15610
+ program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--server-only", "Prepare the Rudder server runtime and persistent CLI without installing Desktop").option("--no-cli", "Skip persistent CLI installation").option("--no-runtime", "Skip Rudder runtime installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--target-version <version>", "Rudder version to start; avoids the root CLI version flag").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--output-dir <path>", "Directory for downloaded desktop release assets").option("--desktop-install-dir <path>", "Directory for the portable Desktop install").option("--no-open", "Install Desktop without launching it").option("--wait-for-active-runs", "Wait for active Rudder runs to finish before replacing Desktop", false).option("--desktop-progress-json", "Emit newline-delimited Desktop update progress events").option("--desktop-wait-for-apply", "Wait for an apply signal after downloading and verifying the Desktop update", false).option("--no-version-check", "Skip checking npm for a newer Rudder CLI version").option("--dry-run", "Print the start actions without changing the machine", false).action(startCommand);
15272
15611
  program.command("onboard").description("Interactive first-run setup wizard").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("-y, --yes", "Accept defaults (quickstart + start immediately)", false).option("--run", "Start Rudder immediately after saving config", false).action(onboard);
15273
15612
  program.command("doctor").description("Run diagnostic checks on your Rudder setup").option("-c, --config <path>", "Path to config file").option("-d, --data-dir <path>", DATA_DIR_OPTION_HELP).option("--repair", "Attempt to repair issues automatically").alias("--fix").option("-y, --yes", "Skip repair confirmation prompts").action(async (opts) => {
15274
15613
  await doctor(opts);