@rudderhq/cli 0.1.0-canary.2 → 0.1.0-canary.4
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/README.md +2 -1
- package/dist/index.js +405 -64
- package/dist/index.js.map +3 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1109,7 +1109,7 @@ var init_secret = __esm({
|
|
|
1109
1109
|
|
|
1110
1110
|
// ../packages/shared/src/validators/agent.ts
|
|
1111
1111
|
import { z as z10 } from "zod";
|
|
1112
|
-
var agentPermissionsSchema, agentInstructionsBundleModeSchema, updateAgentInstructionsBundleSchema, upsertAgentInstructionsFileSchema, agentRuntimeConfigSchema, optionalAgentNameSchema, createAgentSchema, createAgentHireSchema, updateAgentSchema, updateAgentInstructionsPathSchema, createAgentKeySchema, wakeAgentSchema, resetAgentSessionSchema, testAgentRuntimeEnvironmentSchema, updateAgentPermissionsSchema;
|
|
1112
|
+
var agentPermissionsSchema, agentInstructionsBundleModeSchema, updateAgentInstructionsBundleSchema, upsertAgentInstructionsFileSchema, agentRuntimeConfigSchema, optionalAgentNameSchema, uploadedAgentIconSchema, customAgentIconSchema, agentIconSchema, createAgentSchema, createAgentHireSchema, updateAgentSchema, updateAgentInstructionsPathSchema, createAgentKeySchema, wakeAgentSchema, resetAgentSessionSchema, testAgentRuntimeEnvironmentSchema, updateAgentPermissionsSchema;
|
|
1113
1113
|
var init_agent = __esm({
|
|
1114
1114
|
"../packages/shared/src/validators/agent.ts"() {
|
|
1115
1115
|
"use strict";
|
|
@@ -1150,11 +1150,28 @@ var init_agent = __esm({
|
|
|
1150
1150
|
},
|
|
1151
1151
|
z10.string().trim().min(1).optional()
|
|
1152
1152
|
);
|
|
1153
|
+
uploadedAgentIconSchema = z10.string().regex(
|
|
1154
|
+
/^asset:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
1155
|
+
"Invalid uploaded avatar reference"
|
|
1156
|
+
);
|
|
1157
|
+
customAgentIconSchema = z10.string().trim().min(1).max(24).refine((value) => !value.toLowerCase().startsWith("asset:"), "Invalid uploaded avatar reference").refine((value) => !/[<>\u0000-\u001f\u007f]/u.test(value), "Icon cannot contain markup or control characters");
|
|
1158
|
+
agentIconSchema = z10.preprocess(
|
|
1159
|
+
(value) => {
|
|
1160
|
+
if (typeof value !== "string") return value;
|
|
1161
|
+
const trimmed = value.trim();
|
|
1162
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1163
|
+
},
|
|
1164
|
+
z10.union([
|
|
1165
|
+
z10.enum(AGENT_ICON_NAMES),
|
|
1166
|
+
uploadedAgentIconSchema,
|
|
1167
|
+
customAgentIconSchema
|
|
1168
|
+
]).nullable()
|
|
1169
|
+
);
|
|
1153
1170
|
createAgentSchema = z10.object({
|
|
1154
1171
|
name: optionalAgentNameSchema,
|
|
1155
1172
|
role: z10.enum(AGENT_ROLES).optional().default("general"),
|
|
1156
1173
|
title: z10.string().optional().nullable(),
|
|
1157
|
-
icon:
|
|
1174
|
+
icon: agentIconSchema.optional(),
|
|
1158
1175
|
reportsTo: z10.string().uuid().optional().nullable(),
|
|
1159
1176
|
capabilities: z10.string().optional().nullable(),
|
|
1160
1177
|
desiredSkills: z10.array(z10.string().min(1)).optional(),
|
|
@@ -7866,6 +7883,9 @@ function isTransientBinaryPath(candidatePath) {
|
|
|
7866
7883
|
return normalized.includes("/_npx/");
|
|
7867
7884
|
}
|
|
7868
7885
|
function hasGlobalInstalledPackage(packageName, execFileSyncImpl = execFileSync) {
|
|
7886
|
+
return getGlobalInstalledPackageVersion(packageName, execFileSyncImpl) !== null;
|
|
7887
|
+
}
|
|
7888
|
+
function getGlobalInstalledPackageVersion(packageName, execFileSyncImpl = execFileSync) {
|
|
7869
7889
|
try {
|
|
7870
7890
|
const output = execFileSyncImpl(
|
|
7871
7891
|
process.platform === "win32" ? "npm.cmd" : "npm",
|
|
@@ -7876,9 +7896,9 @@ function hasGlobalInstalledPackage(packageName, execFileSyncImpl = execFileSync)
|
|
|
7876
7896
|
}
|
|
7877
7897
|
);
|
|
7878
7898
|
const parsed = JSON.parse(output);
|
|
7879
|
-
return
|
|
7899
|
+
return parsed.dependencies?.[packageName]?.version ?? null;
|
|
7880
7900
|
} catch {
|
|
7881
|
-
return
|
|
7901
|
+
return null;
|
|
7882
7902
|
}
|
|
7883
7903
|
}
|
|
7884
7904
|
function hasPersistentBinaryOnPath(execFileSyncImpl = execFileSync) {
|
|
@@ -9878,21 +9898,25 @@ ${err instanceof Error ? err.message : String(err)}`
|
|
|
9878
9898
|
|
|
9879
9899
|
// src/commands/start.ts
|
|
9880
9900
|
init_install();
|
|
9881
|
-
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
9901
|
+
import { spawn, spawnSync as spawnSync2 } from "node:child_process";
|
|
9882
9902
|
import { createHash as createHash3 } from "node:crypto";
|
|
9883
|
-
import { createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync } from "node:fs";
|
|
9884
|
-
import { chmod, mkdtemp } from "node:fs/promises";
|
|
9885
|
-
import { tmpdir } from "node:os";
|
|
9903
|
+
import { constants as fsConstants, createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync } from "node:fs";
|
|
9904
|
+
import { access, chmod, copyFile, cp, mkdtemp, mkdir, readFile as readFile3, readdir as readdir2, rm, writeFile as writeFile2 } from "node:fs/promises";
|
|
9905
|
+
import { homedir, tmpdir } from "node:os";
|
|
9886
9906
|
import path9 from "node:path";
|
|
9887
9907
|
import { Readable } from "node:stream";
|
|
9888
9908
|
import { pipeline } from "node:stream/promises";
|
|
9909
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
9889
9910
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
9890
9911
|
import * as p13 from "@clack/prompts";
|
|
9891
9912
|
import pc8 from "picocolors";
|
|
9892
9913
|
var DEFAULT_DESKTOP_RELEASE_REPO = "Undertone0809/rudder";
|
|
9914
|
+
var DESKTOP_UPDATE_QUIT_ARG = "--rudder-update-quit";
|
|
9893
9915
|
var STABLE_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
|
|
9894
9916
|
var CANARY_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9]+$/;
|
|
9895
9917
|
var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest";
|
|
9918
|
+
var DESKTOP_APP_NAME = "Rudder";
|
|
9919
|
+
var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
|
|
9896
9920
|
function resolveCurrentCliVersion(env = process.env) {
|
|
9897
9921
|
const envPackageName = env.npm_package_name?.trim();
|
|
9898
9922
|
const envPackageVersion = env.npm_package_version?.trim();
|
|
@@ -9916,6 +9940,9 @@ function resolveCliInstallSpec(version, env = process.env) {
|
|
|
9916
9940
|
if (version && version !== "latest") return `${CLI_NPM_PACKAGE_NAME}@${version}`;
|
|
9917
9941
|
return resolvePersistentCliInstallSpec(env);
|
|
9918
9942
|
}
|
|
9943
|
+
function isPersistentCliVersionCurrent(version, installedVersion) {
|
|
9944
|
+
return Boolean(version && version !== "latest" && installedVersion === version);
|
|
9945
|
+
}
|
|
9919
9946
|
function compareStableSemver(a, b) {
|
|
9920
9947
|
const aMatch = a.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)$/);
|
|
9921
9948
|
const bMatch = b.match(/^([0-9]+)\.([0-9]+)\.([0-9]+)$/);
|
|
@@ -9955,18 +9982,59 @@ function resolveDesktopReleaseTag(version) {
|
|
|
9955
9982
|
if (STABLE_SEMVER_RE.test(version)) return `v${version}`;
|
|
9956
9983
|
if (CANARY_SEMVER_RE.test(version)) return `canary/v${version}`;
|
|
9957
9984
|
throw new Error(
|
|
9958
|
-
`Desktop
|
|
9985
|
+
`Desktop release lookup requires a release version like 0.1.0 or 0.1.0-canary.0. Received ${version}.`
|
|
9959
9986
|
);
|
|
9960
9987
|
}
|
|
9961
9988
|
function resolveDesktopAssetTarget(platform = process.platform, arch = process.arch) {
|
|
9962
|
-
|
|
9963
|
-
|
|
9964
|
-
|
|
9989
|
+
if (platform === "darwin") {
|
|
9990
|
+
if (arch !== "x64" && arch !== "arm64") {
|
|
9991
|
+
throw new Error(`Rudder Desktop does not publish portable assets for ${platform}/${arch}.`);
|
|
9992
|
+
}
|
|
9993
|
+
return { platform: "macos", arch, extension: ".zip" };
|
|
9965
9994
|
}
|
|
9966
|
-
if (platform === "
|
|
9967
|
-
if (platform === "
|
|
9968
|
-
|
|
9969
|
-
|
|
9995
|
+
if (platform === "win32") return { platform: "windows", arch: "x64", extension: ".zip" };
|
|
9996
|
+
if (platform === "linux") {
|
|
9997
|
+
if (arch !== "x64") {
|
|
9998
|
+
throw new Error(`Rudder Desktop does not publish portable assets for ${platform}/${arch}.`);
|
|
9999
|
+
}
|
|
10000
|
+
return { platform: "linux", arch: "x64", extension: ".AppImage" };
|
|
10001
|
+
}
|
|
10002
|
+
throw new Error(`Rudder Desktop does not publish portable assets for ${platform}.`);
|
|
10003
|
+
}
|
|
10004
|
+
function resolveDefaultDesktopInstallRoot(target, env = process.env, homeDir = homedir()) {
|
|
10005
|
+
if (target.platform === "macos") return path9.join(homeDir, "Applications");
|
|
10006
|
+
if (target.platform === "windows") {
|
|
10007
|
+
const localAppData = env.LOCALAPPDATA?.trim() || path9.join(homeDir, "AppData", "Local");
|
|
10008
|
+
return path9.join(localAppData, "Programs", DESKTOP_APP_NAME);
|
|
10009
|
+
}
|
|
10010
|
+
return path9.join(homeDir, ".local", "share", "rudder");
|
|
10011
|
+
}
|
|
10012
|
+
function resolveDesktopInstallPaths(target, installRoot) {
|
|
10013
|
+
const root = path9.resolve(installRoot);
|
|
10014
|
+
if (target.platform === "macos") {
|
|
10015
|
+
const appPath2 = path9.join(root, `${DESKTOP_APP_NAME}.app`);
|
|
10016
|
+
return {
|
|
10017
|
+
installRoot: root,
|
|
10018
|
+
appPath: appPath2,
|
|
10019
|
+
executablePath: path9.join(appPath2, "Contents", "MacOS", DESKTOP_APP_NAME),
|
|
10020
|
+
metadataPath: path9.join(root, DESKTOP_METADATA_FILE)
|
|
10021
|
+
};
|
|
10022
|
+
}
|
|
10023
|
+
if (target.platform === "windows") {
|
|
10024
|
+
return {
|
|
10025
|
+
installRoot: root,
|
|
10026
|
+
appPath: root,
|
|
10027
|
+
executablePath: path9.join(root, `${DESKTOP_APP_NAME}.exe`),
|
|
10028
|
+
metadataPath: path9.join(root, DESKTOP_METADATA_FILE)
|
|
10029
|
+
};
|
|
10030
|
+
}
|
|
10031
|
+
const appPath = path9.join(root, `${DESKTOP_APP_NAME}.AppImage`);
|
|
10032
|
+
return {
|
|
10033
|
+
installRoot: root,
|
|
10034
|
+
appPath,
|
|
10035
|
+
executablePath: appPath,
|
|
10036
|
+
metadataPath: path9.join(root, DESKTOP_METADATA_FILE)
|
|
10037
|
+
};
|
|
9970
10038
|
}
|
|
9971
10039
|
function normalizeAssetName(name) {
|
|
9972
10040
|
return name.toLowerCase().replaceAll("_", "-").replaceAll(" ", "-");
|
|
@@ -9979,6 +10047,7 @@ function scoreDesktopAsset(asset, target) {
|
|
|
9979
10047
|
let score = 1;
|
|
9980
10048
|
if (normalized.includes("rudder")) score += 2;
|
|
9981
10049
|
if (normalized.includes(target.platform)) score += 4;
|
|
10050
|
+
if (normalized.includes("portable")) score += 6;
|
|
9982
10051
|
if (target.platform === "macos" && (normalized.includes("macos") || normalized.includes("darwin") || normalized.includes("mac-"))) {
|
|
9983
10052
|
score += 4;
|
|
9984
10053
|
}
|
|
@@ -10044,28 +10113,284 @@ function parseChecksumFile(contents) {
|
|
|
10044
10113
|
}
|
|
10045
10114
|
return checksums;
|
|
10046
10115
|
}
|
|
10047
|
-
|
|
10048
|
-
|
|
10116
|
+
function resolveAssetChecksum(checksums, assetName) {
|
|
10117
|
+
const expected = checksums.get(path9.basename(assetName));
|
|
10118
|
+
if (!expected) {
|
|
10119
|
+
throw new Error(`Desktop release checksums do not include ${path9.basename(assetName)}.`);
|
|
10120
|
+
}
|
|
10121
|
+
return expected;
|
|
10122
|
+
}
|
|
10123
|
+
function assertChecksumMatch(filePath, expected) {
|
|
10124
|
+
const actual = checksumForFile(filePath);
|
|
10125
|
+
if (actual !== expected.toLowerCase()) {
|
|
10126
|
+
throw new Error(`Checksum mismatch for ${path9.basename(filePath)}.`);
|
|
10127
|
+
}
|
|
10128
|
+
return actual;
|
|
10129
|
+
}
|
|
10130
|
+
async function downloadChecksums(checksumAsset, outputDir) {
|
|
10131
|
+
if (!checksumAsset) {
|
|
10132
|
+
throw new Error("Desktop release is missing SHASUMS256.txt.");
|
|
10133
|
+
}
|
|
10049
10134
|
const checksumPath = await downloadAsset(checksumAsset, outputDir);
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
|
|
10055
|
-
|
|
10135
|
+
return parseChecksumFile(readFileSync(checksumPath, "utf8"));
|
|
10136
|
+
}
|
|
10137
|
+
async function pathExists(targetPath) {
|
|
10138
|
+
try {
|
|
10139
|
+
await access(targetPath, fsConstants.F_OK);
|
|
10140
|
+
return true;
|
|
10141
|
+
} catch {
|
|
10142
|
+
return false;
|
|
10056
10143
|
}
|
|
10057
|
-
return true;
|
|
10058
10144
|
}
|
|
10059
|
-
function
|
|
10145
|
+
function runChecked(command, args, options = {}) {
|
|
10146
|
+
const result = spawnSync2(command, args, {
|
|
10147
|
+
encoding: "utf8",
|
|
10148
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
10149
|
+
...options
|
|
10150
|
+
});
|
|
10151
|
+
if (result.status === 0) return;
|
|
10152
|
+
const output = [result.stdout, result.stderr].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
|
|
10153
|
+
throw new Error(`${command} ${args.join(" ")} failed${output ? `: ${output}` : ""}`);
|
|
10154
|
+
}
|
|
10155
|
+
function powershellQuote(value) {
|
|
10156
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
10157
|
+
}
|
|
10158
|
+
async function extractZip(zipPath, outputDir, target) {
|
|
10159
|
+
await rm(outputDir, { recursive: true, force: true });
|
|
10160
|
+
await mkdir(outputDir, { recursive: true });
|
|
10161
|
+
if (target.platform === "macos") {
|
|
10162
|
+
runChecked("ditto", ["-x", "-k", zipPath, outputDir]);
|
|
10163
|
+
return;
|
|
10164
|
+
}
|
|
10165
|
+
if (target.platform === "windows") {
|
|
10166
|
+
runChecked("powershell.exe", [
|
|
10167
|
+
"-NoProfile",
|
|
10168
|
+
"-ExecutionPolicy",
|
|
10169
|
+
"Bypass",
|
|
10170
|
+
"-Command",
|
|
10171
|
+
`Expand-Archive -LiteralPath ${powershellQuote(zipPath)} -DestinationPath ${powershellQuote(outputDir)} -Force`
|
|
10172
|
+
]);
|
|
10173
|
+
return;
|
|
10174
|
+
}
|
|
10175
|
+
throw new Error(`Zip assets are not supported for ${target.platform}.`);
|
|
10176
|
+
}
|
|
10177
|
+
async function findPath(root, predicate, maxDepth = 5) {
|
|
10178
|
+
async function visit(dir, depth) {
|
|
10179
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
10180
|
+
for (const entry of entries) {
|
|
10181
|
+
const fullPath = path9.join(dir, entry.name);
|
|
10182
|
+
if (predicate(fullPath, entry.isDirectory())) return fullPath;
|
|
10183
|
+
if (entry.isDirectory() && depth < maxDepth) {
|
|
10184
|
+
const nested = await visit(fullPath, depth + 1);
|
|
10185
|
+
if (nested) return nested;
|
|
10186
|
+
}
|
|
10187
|
+
}
|
|
10188
|
+
return null;
|
|
10189
|
+
}
|
|
10190
|
+
return await visit(root, 0);
|
|
10191
|
+
}
|
|
10192
|
+
async function findMacApp(extractDir) {
|
|
10193
|
+
const direct = path9.join(extractDir, `${DESKTOP_APP_NAME}.app`);
|
|
10194
|
+
if (await pathExists(direct)) return direct;
|
|
10195
|
+
const found = await findPath(extractDir, (filePath, isDirectory) => isDirectory && path9.basename(filePath) === `${DESKTOP_APP_NAME}.app`);
|
|
10196
|
+
if (!found) throw new Error(`Portable macOS archive did not contain ${DESKTOP_APP_NAME}.app.`);
|
|
10197
|
+
return found;
|
|
10198
|
+
}
|
|
10199
|
+
async function findWindowsAppDir(extractDir) {
|
|
10200
|
+
const direct = path9.join(extractDir, `${DESKTOP_APP_NAME}.exe`);
|
|
10201
|
+
if (await pathExists(direct)) return extractDir;
|
|
10202
|
+
const executable = await findPath(extractDir, (filePath, isDirectory) => !isDirectory && path9.basename(filePath).toLowerCase() === `${DESKTOP_APP_NAME.toLowerCase()}.exe`);
|
|
10203
|
+
if (!executable) throw new Error(`Portable Windows archive did not contain ${DESKTOP_APP_NAME}.exe.`);
|
|
10204
|
+
return path9.dirname(executable);
|
|
10205
|
+
}
|
|
10206
|
+
async function readInstallMetadata(metadataPath) {
|
|
10207
|
+
try {
|
|
10208
|
+
const parsed = JSON.parse(await readFile3(metadataPath, "utf8"));
|
|
10209
|
+
if (parsed.version !== 1) return null;
|
|
10210
|
+
return parsed;
|
|
10211
|
+
} catch {
|
|
10212
|
+
return null;
|
|
10213
|
+
}
|
|
10214
|
+
}
|
|
10215
|
+
function isInstalledDesktopCurrent(metadata, releaseTag, assetName, assetChecksum) {
|
|
10216
|
+
return Boolean(
|
|
10217
|
+
metadata && metadata.releaseTag === releaseTag && metadata.assetName === assetName && metadata.assetChecksum === assetChecksum
|
|
10218
|
+
);
|
|
10219
|
+
}
|
|
10220
|
+
function buildForceQuitCommand(target) {
|
|
10221
|
+
if (target.platform === "windows") return { command: "taskkill.exe", args: ["/IM", `${DESKTOP_APP_NAME}.exe`, "/T", "/F"] };
|
|
10222
|
+
return { command: "pkill", args: ["-x", DESKTOP_APP_NAME] };
|
|
10223
|
+
}
|
|
10224
|
+
function forceQuitDesktopProcesses(target) {
|
|
10225
|
+
const command = buildForceQuitCommand(target);
|
|
10226
|
+
spawnSync2(command.command, command.args, { stdio: "ignore" });
|
|
10227
|
+
}
|
|
10228
|
+
function isRunningInsideDesktopExecutable() {
|
|
10229
|
+
return path9.basename(process.execPath).toLowerCase().startsWith(DESKTOP_APP_NAME.toLowerCase());
|
|
10230
|
+
}
|
|
10231
|
+
async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
|
|
10232
|
+
const startedAt = Date.now();
|
|
10233
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
10234
|
+
if (await pathExists(responsePath)) {
|
|
10235
|
+
return JSON.parse(await readFile3(responsePath, "utf8"));
|
|
10236
|
+
}
|
|
10237
|
+
await delay(200);
|
|
10238
|
+
}
|
|
10239
|
+
return null;
|
|
10240
|
+
}
|
|
10241
|
+
async function requestDesktopQuit(executablePath, target) {
|
|
10242
|
+
if (!await pathExists(executablePath)) return { ok: true, status: "not_running" };
|
|
10243
|
+
const responsePath = path9.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
|
|
10244
|
+
const result = spawnSync2(executablePath, [`${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`], {
|
|
10245
|
+
stdio: "ignore",
|
|
10246
|
+
timeout: 5e3
|
|
10247
|
+
});
|
|
10248
|
+
if (result.error && target.platform === "windows") {
|
|
10249
|
+
return null;
|
|
10250
|
+
}
|
|
10251
|
+
try {
|
|
10252
|
+
return await waitForUpdateQuitResponse(responsePath);
|
|
10253
|
+
} finally {
|
|
10254
|
+
await rm(responsePath, { force: true });
|
|
10255
|
+
}
|
|
10256
|
+
}
|
|
10257
|
+
async function removePathWithRetry(targetPath, attempts = 5) {
|
|
10258
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
10259
|
+
try {
|
|
10260
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
10261
|
+
if (!await pathExists(targetPath)) return true;
|
|
10262
|
+
} catch {
|
|
10263
|
+
}
|
|
10264
|
+
await delay(500);
|
|
10265
|
+
}
|
|
10266
|
+
return false;
|
|
10267
|
+
}
|
|
10268
|
+
async function prepareForDesktopReplace(paths, target) {
|
|
10269
|
+
const hasManagedExecutable = await pathExists(paths.executablePath);
|
|
10270
|
+
if (hasManagedExecutable) {
|
|
10271
|
+
const quitResponse = await requestDesktopQuit(paths.executablePath, target);
|
|
10272
|
+
if (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs") {
|
|
10273
|
+
throw new Error(
|
|
10274
|
+
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}. Stop active work, then rerun start.`
|
|
10275
|
+
);
|
|
10276
|
+
}
|
|
10277
|
+
await delay(1e3);
|
|
10278
|
+
} else if (!isRunningInsideDesktopExecutable()) {
|
|
10279
|
+
forceQuitDesktopProcesses(target);
|
|
10280
|
+
}
|
|
10281
|
+
const replacePath = target.platform === "windows" ? paths.installRoot : paths.appPath;
|
|
10282
|
+
if (await removePathWithRetry(replacePath)) return;
|
|
10283
|
+
forceQuitDesktopProcesses(target);
|
|
10284
|
+
await delay(1e3);
|
|
10285
|
+
if (await removePathWithRetry(replacePath, 6)) return;
|
|
10286
|
+
throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
|
|
10287
|
+
}
|
|
10288
|
+
async function installPortableDesktop(installerPath, paths, target) {
|
|
10289
|
+
await mkdir(paths.installRoot, { recursive: true });
|
|
10290
|
+
if (target.platform === "linux") {
|
|
10291
|
+
await copyFile(installerPath, paths.appPath);
|
|
10292
|
+
await chmod(paths.appPath, 493);
|
|
10293
|
+
return;
|
|
10294
|
+
}
|
|
10295
|
+
const extractDir = await mkdtemp(path9.join(tmpdir(), "rudder-desktop-extract."));
|
|
10296
|
+
try {
|
|
10297
|
+
await extractZip(installerPath, extractDir, target);
|
|
10298
|
+
if (target.platform === "macos") {
|
|
10299
|
+
const appSource2 = await findMacApp(extractDir);
|
|
10300
|
+
await cp(appSource2, paths.appPath, { recursive: true });
|
|
10301
|
+
return;
|
|
10302
|
+
}
|
|
10303
|
+
const appSource = await findWindowsAppDir(extractDir);
|
|
10304
|
+
await mkdir(path9.dirname(paths.installRoot), { recursive: true });
|
|
10305
|
+
await cp(appSource, paths.installRoot, { recursive: true });
|
|
10306
|
+
} finally {
|
|
10307
|
+
await rm(extractDir, { recursive: true, force: true });
|
|
10308
|
+
}
|
|
10309
|
+
}
|
|
10310
|
+
async function removeMacQuarantine(paths, target) {
|
|
10311
|
+
if (target.platform !== "macos") return;
|
|
10312
|
+
const result = spawnSync2("xattr", ["-dr", "com.apple.quarantine", paths.appPath], { stdio: "ignore" });
|
|
10313
|
+
if (result.status !== 0) {
|
|
10314
|
+
p13.log.warn(`Could not remove macOS quarantine attributes from ${paths.appPath}.`);
|
|
10315
|
+
}
|
|
10316
|
+
}
|
|
10317
|
+
function quoteDesktopExec(value) {
|
|
10318
|
+
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
10319
|
+
}
|
|
10320
|
+
function buildLinuxDesktopEntry(executablePath) {
|
|
10321
|
+
return [
|
|
10322
|
+
"[Desktop Entry]",
|
|
10323
|
+
"Type=Application",
|
|
10324
|
+
"Name=Rudder",
|
|
10325
|
+
`Exec=${quoteDesktopExec(executablePath)}`,
|
|
10326
|
+
"Terminal=false",
|
|
10327
|
+
"Categories=Development;",
|
|
10328
|
+
""
|
|
10329
|
+
].join("\n");
|
|
10330
|
+
}
|
|
10331
|
+
async function writeLinuxLaunchers(paths) {
|
|
10332
|
+
const desktopDir = path9.join(homedir(), ".local", "share", "applications");
|
|
10333
|
+
await mkdir(desktopDir, { recursive: true });
|
|
10334
|
+
await writeFile2(path9.join(desktopDir, "rudder.desktop"), buildLinuxDesktopEntry(paths.executablePath), "utf8");
|
|
10335
|
+
const binDir = path9.join(homedir(), ".local", "bin");
|
|
10336
|
+
await mkdir(binDir, { recursive: true });
|
|
10337
|
+
const wrapperPath = path9.join(binDir, "rudder-desktop");
|
|
10338
|
+
const escaped = paths.executablePath.replaceAll("'", `'"'"'`);
|
|
10339
|
+
await writeFile2(wrapperPath, `#!/bin/sh
|
|
10340
|
+
exec '${escaped}' "$@"
|
|
10341
|
+
`, "utf8");
|
|
10342
|
+
await chmod(wrapperPath, 493);
|
|
10343
|
+
}
|
|
10344
|
+
function buildWindowsShortcutScript(executablePath) {
|
|
10345
|
+
const appData = process.env.APPDATA?.trim() || path9.join(homedir(), "AppData", "Roaming");
|
|
10346
|
+
const shortcutPath = path9.join(appData, "Microsoft", "Windows", "Start Menu", "Programs", "Rudder.lnk");
|
|
10347
|
+
return [
|
|
10348
|
+
"$shell = New-Object -ComObject WScript.Shell",
|
|
10349
|
+
`$shortcut = $shell.CreateShortcut(${powershellQuote(shortcutPath)})`,
|
|
10350
|
+
`$shortcut.TargetPath = ${powershellQuote(executablePath)}`,
|
|
10351
|
+
`$shortcut.WorkingDirectory = ${powershellQuote(path9.dirname(executablePath))}`,
|
|
10352
|
+
"$shortcut.Save()"
|
|
10353
|
+
].join("; ");
|
|
10354
|
+
}
|
|
10355
|
+
async function createPlatformLaunchers(paths, target) {
|
|
10356
|
+
if (target.platform === "linux") {
|
|
10357
|
+
await writeLinuxLaunchers(paths);
|
|
10358
|
+
return;
|
|
10359
|
+
}
|
|
10360
|
+
if (target.platform === "windows") {
|
|
10361
|
+
const result = spawnSync2("powershell.exe", [
|
|
10362
|
+
"-NoProfile",
|
|
10363
|
+
"-ExecutionPolicy",
|
|
10364
|
+
"Bypass",
|
|
10365
|
+
"-Command",
|
|
10366
|
+
buildWindowsShortcutScript(paths.executablePath)
|
|
10367
|
+
], { stdio: "ignore" });
|
|
10368
|
+
if (result.status !== 0) p13.log.warn("Could not create the Windows Start Menu shortcut.");
|
|
10369
|
+
}
|
|
10370
|
+
}
|
|
10371
|
+
function launchDesktop(paths, target) {
|
|
10060
10372
|
if (target.platform === "macos") {
|
|
10061
|
-
|
|
10373
|
+
spawn("open", [paths.appPath], { detached: true, stdio: "ignore" }).unref();
|
|
10062
10374
|
return;
|
|
10063
10375
|
}
|
|
10064
10376
|
if (target.platform === "windows") {
|
|
10065
|
-
|
|
10377
|
+
spawn("cmd.exe", ["/c", "start", "", paths.executablePath], { detached: true, stdio: "ignore" }).unref();
|
|
10066
10378
|
return;
|
|
10067
10379
|
}
|
|
10068
|
-
|
|
10380
|
+
spawn(paths.executablePath, [], { detached: true, stdio: "ignore" }).unref();
|
|
10381
|
+
}
|
|
10382
|
+
async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum) {
|
|
10383
|
+
mkdirSync2(path9.dirname(paths.metadataPath), { recursive: true });
|
|
10384
|
+
const metadata = {
|
|
10385
|
+
version: 1,
|
|
10386
|
+
releaseTag,
|
|
10387
|
+
assetName,
|
|
10388
|
+
assetChecksum,
|
|
10389
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
10390
|
+
};
|
|
10391
|
+
mkdirSync2(paths.installRoot, { recursive: true });
|
|
10392
|
+
await writeFile2(paths.metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
10393
|
+
`, "utf8");
|
|
10069
10394
|
}
|
|
10070
10395
|
async function startCommand(opts) {
|
|
10071
10396
|
const installCli = opts.cli !== false;
|
|
@@ -10084,8 +10409,11 @@ async function startCommand(opts) {
|
|
|
10084
10409
|
if (installCli) {
|
|
10085
10410
|
const installSpec = resolveCliInstallSpec(version);
|
|
10086
10411
|
const command = `npm install --global ${installSpec}`;
|
|
10412
|
+
const installedVersion = getGlobalInstalledPackageVersion(CLI_NPM_PACKAGE_NAME);
|
|
10087
10413
|
p13.log.step("Preparing persistent CLI");
|
|
10088
|
-
if (
|
|
10414
|
+
if (isPersistentCliVersionCurrent(version, installedVersion)) {
|
|
10415
|
+
p13.log.success(`${pc8.cyan("rudder")} CLI ${version} is already installed.`);
|
|
10416
|
+
} else if (dryRun) {
|
|
10089
10417
|
p13.log.message(`[dry-run] ${command}`);
|
|
10090
10418
|
} else {
|
|
10091
10419
|
p13.log.message(pc8.dim(`Running: ${command}`));
|
|
@@ -10100,32 +10428,45 @@ async function startCommand(opts) {
|
|
|
10100
10428
|
if (installDesktop) {
|
|
10101
10429
|
const target = resolveDesktopAssetTarget();
|
|
10102
10430
|
const tag = resolveDesktopReleaseTag(version);
|
|
10431
|
+
const installRoot = opts.desktopInstallDir ? path9.resolve(opts.desktopInstallDir) : resolveDefaultDesktopInstallRoot(target);
|
|
10432
|
+
const installPaths = resolveDesktopInstallPaths(target, installRoot);
|
|
10103
10433
|
const outputDir = opts.outputDir ? path9.resolve(opts.outputDir) : await mkdtemp(path9.join(tmpdir(), "rudder-desktop-installer."));
|
|
10104
|
-
p13.log.step("
|
|
10434
|
+
p13.log.step("Installing desktop app");
|
|
10105
10435
|
p13.log.message(`Release: ${pc8.cyan(`${repo}@${tag}`)}`);
|
|
10106
10436
|
p13.log.message(`Target: ${pc8.cyan(`${target.platform}/${target.arch}`)}`);
|
|
10437
|
+
p13.log.message(`Install: ${pc8.cyan(installPaths.appPath)}`);
|
|
10107
10438
|
if (dryRun) {
|
|
10108
|
-
p13.log.message(`[dry-run] Would resolve and
|
|
10439
|
+
p13.log.message(`[dry-run] Would resolve, download, verify, install, and ${opts.open === false ? "not launch" : "launch"} Rudder Desktop.`);
|
|
10109
10440
|
p13.outro(pc8.green("Dry run complete."));
|
|
10110
10441
|
return;
|
|
10111
10442
|
}
|
|
10112
10443
|
const release = await fetchGithubRelease(repo, tag);
|
|
10113
10444
|
const asset = selectDesktopAsset(release.assets ?? [], target);
|
|
10114
10445
|
if (!asset) {
|
|
10115
|
-
throw new Error(`No Rudder Desktop
|
|
10116
|
-
}
|
|
10117
|
-
const
|
|
10118
|
-
const
|
|
10119
|
-
|
|
10120
|
-
|
|
10446
|
+
throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${release.tag_name}.`);
|
|
10447
|
+
}
|
|
10448
|
+
const checksums = await downloadChecksums(selectChecksumAsset(release.assets ?? []), outputDir);
|
|
10449
|
+
const expectedChecksum = resolveAssetChecksum(checksums, asset.name);
|
|
10450
|
+
const metadata = await readInstallMetadata(installPaths.metadataPath);
|
|
10451
|
+
if (isInstalledDesktopCurrent(metadata, release.tag_name, asset.name, expectedChecksum) && await pathExists(installPaths.executablePath)) {
|
|
10452
|
+
p13.log.success(`Rudder Desktop is already installed at ${pc8.cyan(installPaths.appPath)}.`);
|
|
10453
|
+
await removeMacQuarantine(installPaths, target);
|
|
10454
|
+
await createPlatformLaunchers(installPaths, target);
|
|
10455
|
+
} else {
|
|
10456
|
+
const installerPath = await downloadAsset(asset, outputDir);
|
|
10457
|
+
const checksum = assertChecksumMatch(installerPath, expectedChecksum);
|
|
10458
|
+
p13.log.success(`Downloaded and verified ${pc8.cyan(path9.basename(installerPath))}`);
|
|
10459
|
+
p13.log.message("Replacing existing Rudder Desktop if needed.");
|
|
10460
|
+
await prepareForDesktopReplace(installPaths, target);
|
|
10461
|
+
await installPortableDesktop(installerPath, installPaths, target);
|
|
10462
|
+
await removeMacQuarantine(installPaths, target);
|
|
10463
|
+
await createPlatformLaunchers(installPaths, target);
|
|
10464
|
+
await writeInstallMetadata(installPaths, release.tag_name, asset.name, checksum);
|
|
10465
|
+
p13.log.success(`Installed Rudder Desktop to ${pc8.cyan(installPaths.appPath)}.`);
|
|
10121
10466
|
}
|
|
10122
|
-
p13.log.success(`Downloaded ${pc8.cyan(path9.basename(installerPath))}`);
|
|
10123
|
-
if (checksumVerified) p13.log.success("Verified SHA-256 checksum.");
|
|
10124
10467
|
if (opts.open !== false) {
|
|
10125
|
-
|
|
10126
|
-
p13.log.
|
|
10127
|
-
} else {
|
|
10128
|
-
p13.log.message(`Installer path: ${pc8.cyan(installerPath)}`);
|
|
10468
|
+
launchDesktop(installPaths, target);
|
|
10469
|
+
p13.log.success("Rudder Desktop launched.");
|
|
10129
10470
|
}
|
|
10130
10471
|
}
|
|
10131
10472
|
p13.outro(pc8.green("Rudder start complete."));
|
|
@@ -10167,7 +10508,7 @@ async function addAllowedHostname(host, opts) {
|
|
|
10167
10508
|
}
|
|
10168
10509
|
|
|
10169
10510
|
// src/commands/heartbeat-run.ts
|
|
10170
|
-
import { setTimeout as
|
|
10511
|
+
import { setTimeout as delay2 } from "node:timers/promises";
|
|
10171
10512
|
import pc19 from "picocolors";
|
|
10172
10513
|
|
|
10173
10514
|
// ../packages/agent-runtimes/claude-local/src/cli/format-event.ts
|
|
@@ -11160,7 +11501,7 @@ function getCLIAdapter(type) {
|
|
|
11160
11501
|
import pc18 from "picocolors";
|
|
11161
11502
|
|
|
11162
11503
|
// src/client/board-auth.ts
|
|
11163
|
-
import { spawn } from "node:child_process";
|
|
11504
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
11164
11505
|
import fs10 from "node:fs";
|
|
11165
11506
|
import path10 from "node:path";
|
|
11166
11507
|
import pc17 from "picocolors";
|
|
@@ -11277,16 +11618,16 @@ function openUrl(url) {
|
|
|
11277
11618
|
const platform = process.platform;
|
|
11278
11619
|
try {
|
|
11279
11620
|
if (platform === "darwin") {
|
|
11280
|
-
const child2 =
|
|
11621
|
+
const child2 = spawn2("open", [url], { detached: true, stdio: "ignore" });
|
|
11281
11622
|
child2.unref();
|
|
11282
11623
|
return true;
|
|
11283
11624
|
}
|
|
11284
11625
|
if (platform === "win32") {
|
|
11285
|
-
const child2 =
|
|
11626
|
+
const child2 = spawn2("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" });
|
|
11286
11627
|
child2.unref();
|
|
11287
11628
|
return true;
|
|
11288
11629
|
}
|
|
11289
|
-
const child =
|
|
11630
|
+
const child = spawn2("xdg-open", [url], { detached: true, stdio: "ignore" });
|
|
11290
11631
|
child.unref();
|
|
11291
11632
|
return true;
|
|
11292
11633
|
} catch {
|
|
@@ -12015,7 +12356,7 @@ async function heartbeatRun(opts) {
|
|
|
12015
12356
|
logOffset += Buffer.byteLength(logResult.content, "utf8");
|
|
12016
12357
|
}
|
|
12017
12358
|
}
|
|
12018
|
-
await
|
|
12359
|
+
await delay2(POLL_INTERVAL_MS);
|
|
12019
12360
|
}
|
|
12020
12361
|
if (finalStatus) {
|
|
12021
12362
|
if (!debug && stdoutJsonBuffer.trim()) {
|
|
@@ -12230,7 +12571,7 @@ function registerContextCommands(program) {
|
|
|
12230
12571
|
}
|
|
12231
12572
|
|
|
12232
12573
|
// src/commands/client/company.ts
|
|
12233
|
-
import { mkdir, readdir as
|
|
12574
|
+
import { mkdir as mkdir2, readdir as readdir3, readFile as readFile4, stat, writeFile as writeFile3 } from "node:fs/promises";
|
|
12234
12575
|
import path14 from "node:path";
|
|
12235
12576
|
import * as p16 from "@clack/prompts";
|
|
12236
12577
|
import pc22 from "picocolors";
|
|
@@ -12963,7 +13304,7 @@ function normalizeGithubImportSource(input, refOverride) {
|
|
|
12963
13304
|
}
|
|
12964
13305
|
return buildGithubImportUrl({ owner, repo, ref });
|
|
12965
13306
|
}
|
|
12966
|
-
async function
|
|
13307
|
+
async function pathExists2(inputPath) {
|
|
12967
13308
|
try {
|
|
12968
13309
|
await stat(path14.resolve(inputPath));
|
|
12969
13310
|
return true;
|
|
@@ -12972,7 +13313,7 @@ async function pathExists(inputPath) {
|
|
|
12972
13313
|
}
|
|
12973
13314
|
}
|
|
12974
13315
|
async function collectPackageFiles(root, current, files) {
|
|
12975
|
-
const entries = await
|
|
13316
|
+
const entries = await readdir3(current, { withFileTypes: true });
|
|
12976
13317
|
for (const entry of entries) {
|
|
12977
13318
|
if (entry.name.startsWith(".git")) continue;
|
|
12978
13319
|
const absolutePath = path14.join(current, entry.name);
|
|
@@ -12983,14 +13324,14 @@ async function collectPackageFiles(root, current, files) {
|
|
|
12983
13324
|
if (!entry.isFile()) continue;
|
|
12984
13325
|
const relativePath = path14.relative(root, absolutePath).replace(/\\/g, "/");
|
|
12985
13326
|
if (!shouldIncludePortableFile(relativePath)) continue;
|
|
12986
|
-
files[relativePath] = readPortableFileEntry(relativePath, await
|
|
13327
|
+
files[relativePath] = readPortableFileEntry(relativePath, await readFile4(absolutePath));
|
|
12987
13328
|
}
|
|
12988
13329
|
}
|
|
12989
13330
|
async function resolveInlineSourceFromPath(inputPath) {
|
|
12990
13331
|
const resolved = path14.resolve(inputPath);
|
|
12991
13332
|
const resolvedStat = await stat(resolved);
|
|
12992
13333
|
if (resolvedStat.isFile() && path14.extname(resolved).toLowerCase() === ".zip") {
|
|
12993
|
-
const archive = await readZipArchive(await
|
|
13334
|
+
const archive = await readZipArchive(await readFile4(resolved));
|
|
12994
13335
|
const filteredFiles = Object.fromEntries(
|
|
12995
13336
|
Object.entries(archive.files).filter(([relativePath]) => shouldIncludePortableFile(relativePath))
|
|
12996
13337
|
);
|
|
@@ -13009,16 +13350,16 @@ async function resolveInlineSourceFromPath(inputPath) {
|
|
|
13009
13350
|
}
|
|
13010
13351
|
async function writeExportToFolder(outDir, exported) {
|
|
13011
13352
|
const root = path14.resolve(outDir);
|
|
13012
|
-
await
|
|
13353
|
+
await mkdir2(root, { recursive: true });
|
|
13013
13354
|
for (const [relativePath, content] of Object.entries(exported.files)) {
|
|
13014
13355
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
13015
13356
|
const filePath = path14.join(root, normalized);
|
|
13016
|
-
await
|
|
13357
|
+
await mkdir2(path14.dirname(filePath), { recursive: true });
|
|
13017
13358
|
const writeValue = portableFileEntryToWriteValue(content);
|
|
13018
13359
|
if (typeof writeValue === "string") {
|
|
13019
|
-
await
|
|
13360
|
+
await writeFile3(filePath, writeValue, "utf8");
|
|
13020
13361
|
} else {
|
|
13021
|
-
await
|
|
13362
|
+
await writeFile3(filePath, writeValue);
|
|
13022
13363
|
}
|
|
13023
13364
|
}
|
|
13024
13365
|
}
|
|
@@ -13029,7 +13370,7 @@ async function confirmOverwriteExportDirectory(outDir) {
|
|
|
13029
13370
|
if (!stats.isDirectory()) {
|
|
13030
13371
|
throw new Error(`Export output path ${root} exists and is not a directory.`);
|
|
13031
13372
|
}
|
|
13032
|
-
const entries = await
|
|
13373
|
+
const entries = await readdir3(root);
|
|
13033
13374
|
if (entries.length === 0) return;
|
|
13034
13375
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
13035
13376
|
throw new Error(`Export output directory ${root} already contains files. Re-run interactively or choose an empty directory.`);
|
|
@@ -13226,7 +13567,7 @@ function registerCompanyCommands(program) {
|
|
|
13226
13567
|
throw new Error("Target existing organization requires --org-id (or context default orgId).");
|
|
13227
13568
|
}
|
|
13228
13569
|
let sourcePayload;
|
|
13229
|
-
const treatAsLocalPath = !isHttpUrl(from) && await
|
|
13570
|
+
const treatAsLocalPath = !isHttpUrl(from) && await pathExists2(from);
|
|
13230
13571
|
const isGithubSource = isGithubUrl(from) || isGithubShorthand(from) && !treatAsLocalPath;
|
|
13231
13572
|
if (isHttpUrl(from) || isGithubSource) {
|
|
13232
13573
|
if (!isGithubUrl(from) && !isGithubShorthand(from)) {
|
|
@@ -14272,7 +14613,7 @@ function filterIssueRows(rows, match) {
|
|
|
14272
14613
|
init_src();
|
|
14273
14614
|
|
|
14274
14615
|
// ../packages/agent-runtime-utils/src/server-utils.ts
|
|
14275
|
-
import { constants as
|
|
14616
|
+
import { constants as fsConstants2, promises as fs12 } from "node:fs";
|
|
14276
14617
|
import path15 from "node:path";
|
|
14277
14618
|
var MAX_CAPTURE_BYTES = 4 * 1024 * 1024;
|
|
14278
14619
|
var MAX_EXCERPT_BYTES = 32 * 1024;
|
|
@@ -19173,7 +19514,7 @@ var DATA_DIR_OPTION_HELP = "Rudder data directory root (isolates state from ~/.r
|
|
|
19173
19514
|
var LOCAL_ENV_OPTION_HELP = "Local environment profile (dev, prod_local, e2e)";
|
|
19174
19515
|
function createProgram() {
|
|
19175
19516
|
const program = new Command();
|
|
19176
|
-
program.name("rudder").description("Rudder CLI \u2014 setup, diagnose, and configure your instance").version("0.1.0-canary.
|
|
19517
|
+
program.name("rudder").description("Rudder CLI \u2014 setup, diagnose, and configure your instance").version("0.1.0-canary.4");
|
|
19177
19518
|
program.option("--local-env <name>", LOCAL_ENV_OPTION_HELP);
|
|
19178
19519
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
19179
19520
|
const options = actionCommand.optsWithGlobals();
|
|
@@ -19185,7 +19526,7 @@ function createProgram() {
|
|
|
19185
19526
|
});
|
|
19186
19527
|
loadRudderEnvFile(options.config);
|
|
19187
19528
|
});
|
|
19188
|
-
program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--no-cli", "Skip persistent CLI installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").option("--repo <owner/repo>", "GitHub repository that hosts desktop releases").option("--output-dir <path>", "Directory for
|
|
19529
|
+
program.command("start").description("Start Rudder Desktop and prepare the matching persistent CLI").option("--no-cli", "Skip persistent CLI installation").option("--no-desktop", "Skip desktop app installation").option("--version <version>", "Rudder version to start (default: current CLI version)").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("--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);
|
|
19189
19530
|
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);
|
|
19190
19531
|
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) => {
|
|
19191
19532
|
await doctor(opts);
|