@rudderhq/cli 0.2.1 → 0.2.2-canary.0
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 +0 -2
- package/dist/index.js +273 -31
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,8 +8,6 @@ Rudder began from a fork of an early version of Paperclip. That gave us a practi
|
|
|
8
8
|
|
|
9
9
|
Rudder is built for the moment when agent work stops looking like a single prompt and starts looking like a real team.
|
|
10
10
|
|
|
11
|
-
Current status: V1 is under active development. The current north-star metric is the weekly count of real agent-work loops completed end-to-end through Rudder.
|
|
12
|
-
|
|
13
11
|
## The Design Idea
|
|
14
12
|
|
|
15
13
|
Rudder is shaped by a simple belief: the most useful way to work with agents is closer to the way humans coordinate with each other.
|
package/dist/index.js
CHANGED
|
@@ -117,6 +117,7 @@ var init_constants = __esm({
|
|
|
117
117
|
CHAT_MESSAGE_ROLES = ["user", "assistant", "system"];
|
|
118
118
|
CHAT_MESSAGE_KINDS = [
|
|
119
119
|
"message",
|
|
120
|
+
"ask_user",
|
|
120
121
|
"issue_proposal",
|
|
121
122
|
"operation_proposal",
|
|
122
123
|
"system_event"
|
|
@@ -579,7 +580,7 @@ var init_resource = __esm({
|
|
|
579
580
|
|
|
580
581
|
// ../packages/shared/src/validators/chat.ts
|
|
581
582
|
import { z as z5 } from "zod";
|
|
582
|
-
var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, addChatMessageSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema;
|
|
583
|
+
var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, addChatMessageSchema, chatRichReferenceDisplaySchema, chatIssueIdentifierSchema, chatAskUserIdentifierSchema, chatAskUserOptionSchema, chatAskUserQuestionSchema, chatAskUserRequestSchema, chatIssueRichReferenceSchema, chatIssueCommentRichReferenceSchema, chatRichReferenceSchema, chatRichReferencesSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema;
|
|
583
584
|
var init_chat = __esm({
|
|
584
585
|
"../packages/shared/src/validators/chat.ts"() {
|
|
585
586
|
"use strict";
|
|
@@ -616,6 +617,47 @@ var init_chat = __esm({
|
|
|
616
617
|
body: z5.string().trim().min(1).max(2e4),
|
|
617
618
|
editUserMessageId: z5.string().uuid().optional().nullable()
|
|
618
619
|
});
|
|
620
|
+
chatRichReferenceDisplaySchema = z5.enum(["card", "inline"]);
|
|
621
|
+
chatIssueIdentifierSchema = z5.string().trim().min(1).max(64).regex(/^[A-Z0-9][A-Z0-9-]*$/i);
|
|
622
|
+
chatAskUserIdentifierSchema = z5.string().trim().min(1).max(64).regex(/^[a-zA-Z0-9_-]+$/);
|
|
623
|
+
chatAskUserOptionSchema = z5.object({
|
|
624
|
+
id: chatAskUserIdentifierSchema,
|
|
625
|
+
label: z5.string().trim().min(1).max(80),
|
|
626
|
+
description: z5.string().trim().min(1).max(220).optional(),
|
|
627
|
+
recommended: z5.boolean().optional()
|
|
628
|
+
});
|
|
629
|
+
chatAskUserQuestionSchema = z5.object({
|
|
630
|
+
id: chatAskUserIdentifierSchema,
|
|
631
|
+
header: z5.string().trim().min(1).max(32).optional(),
|
|
632
|
+
question: z5.string().trim().min(1).max(240),
|
|
633
|
+
options: z5.array(chatAskUserOptionSchema).min(2).max(3),
|
|
634
|
+
allowFreeform: z5.boolean().optional()
|
|
635
|
+
});
|
|
636
|
+
chatAskUserRequestSchema = z5.object({
|
|
637
|
+
questions: z5.array(chatAskUserQuestionSchema).min(1).max(3)
|
|
638
|
+
});
|
|
639
|
+
chatIssueRichReferenceSchema = z5.object({
|
|
640
|
+
type: z5.literal("issue"),
|
|
641
|
+
issueId: z5.string().uuid().optional(),
|
|
642
|
+
identifier: chatIssueIdentifierSchema.optional(),
|
|
643
|
+
display: chatRichReferenceDisplaySchema.optional()
|
|
644
|
+
}).refine((value) => Boolean(value.issueId || value.identifier), {
|
|
645
|
+
message: "issueId or identifier is required"
|
|
646
|
+
});
|
|
647
|
+
chatIssueCommentRichReferenceSchema = z5.object({
|
|
648
|
+
type: z5.literal("issue_comment"),
|
|
649
|
+
issueId: z5.string().uuid().optional(),
|
|
650
|
+
identifier: chatIssueIdentifierSchema.optional(),
|
|
651
|
+
commentId: z5.string().uuid(),
|
|
652
|
+
display: chatRichReferenceDisplaySchema.optional()
|
|
653
|
+
}).refine((value) => Boolean(value.issueId || value.identifier), {
|
|
654
|
+
message: "issueId or identifier is required"
|
|
655
|
+
});
|
|
656
|
+
chatRichReferenceSchema = z5.union([
|
|
657
|
+
chatIssueRichReferenceSchema,
|
|
658
|
+
chatIssueCommentRichReferenceSchema
|
|
659
|
+
]);
|
|
660
|
+
chatRichReferencesSchema = z5.array(chatRichReferenceSchema).max(5);
|
|
619
661
|
createChatAttachmentMetadataSchema = z5.object({
|
|
620
662
|
messageId: z5.string().uuid()
|
|
621
663
|
});
|
|
@@ -2491,7 +2533,10 @@ var init_organization_skill_reference = __esm({
|
|
|
2491
2533
|
"para-memory-files",
|
|
2492
2534
|
"rudder",
|
|
2493
2535
|
"rudder-create-agent",
|
|
2494
|
-
"rudder-create-plugin"
|
|
2536
|
+
"rudder-create-plugin",
|
|
2537
|
+
"skill-creator",
|
|
2538
|
+
"skill-optimizer",
|
|
2539
|
+
"conversation-to-skill"
|
|
2495
2540
|
];
|
|
2496
2541
|
RUDDER_BUNDLED_SKILL_KEYS = new Set(
|
|
2497
2542
|
RUDDER_BUNDLED_SKILL_SLUGS.map((slug) => `rudder/${slug}`)
|
|
@@ -6132,6 +6177,103 @@ var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest
|
|
|
6132
6177
|
var DESKTOP_APP_NAME = "Rudder";
|
|
6133
6178
|
var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
|
|
6134
6179
|
var DESKTOP_CHECKSUM_ASSET_NAME = "SHASUMS256.txt";
|
|
6180
|
+
var GITHUB_ASSET_DOWNLOAD_ACCEPT = "application/octet-stream";
|
|
6181
|
+
function normalizeProgressTotal(totalBytes) {
|
|
6182
|
+
return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
|
|
6183
|
+
}
|
|
6184
|
+
function writeDesktopProgress(event) {
|
|
6185
|
+
const payload = {
|
|
6186
|
+
source: "rudder-desktop-update",
|
|
6187
|
+
...event,
|
|
6188
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
6189
|
+
};
|
|
6190
|
+
try {
|
|
6191
|
+
process.stdout.write(`${JSON.stringify(payload)}
|
|
6192
|
+
`);
|
|
6193
|
+
} catch (error) {
|
|
6194
|
+
const code = typeof error === "object" && error && "code" in error ? String(error.code) : "";
|
|
6195
|
+
if (code !== "EPIPE") throw error;
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
function desktopDownloadPhase(label) {
|
|
6199
|
+
return label.toLowerCase().includes("shasums") ? "downloading_checksums" : "downloading_asset";
|
|
6200
|
+
}
|
|
6201
|
+
function createDesktopProgressFactory() {
|
|
6202
|
+
return (label) => {
|
|
6203
|
+
const phase = desktopDownloadPhase(label);
|
|
6204
|
+
let latestReceivedBytes = 0;
|
|
6205
|
+
let latestTotalBytes = null;
|
|
6206
|
+
function emitByteProgress(message, receivedBytes, totalBytes) {
|
|
6207
|
+
const total = normalizeProgressTotal(totalBytes);
|
|
6208
|
+
writeDesktopProgress({
|
|
6209
|
+
phase,
|
|
6210
|
+
message,
|
|
6211
|
+
transferredBytes: Math.max(0, receivedBytes),
|
|
6212
|
+
...total === null ? {} : {
|
|
6213
|
+
totalBytes: total,
|
|
6214
|
+
percent: Math.max(0, Math.min(100, Math.floor(Math.max(0, receivedBytes) / total * 100)))
|
|
6215
|
+
}
|
|
6216
|
+
});
|
|
6217
|
+
}
|
|
6218
|
+
return {
|
|
6219
|
+
start(totalBytes) {
|
|
6220
|
+
latestReceivedBytes = 0;
|
|
6221
|
+
latestTotalBytes = totalBytes;
|
|
6222
|
+
emitByteProgress(label, 0, totalBytes);
|
|
6223
|
+
},
|
|
6224
|
+
update(receivedBytes, totalBytes) {
|
|
6225
|
+
latestReceivedBytes = receivedBytes;
|
|
6226
|
+
latestTotalBytes = totalBytes;
|
|
6227
|
+
emitByteProgress(label, receivedBytes, totalBytes);
|
|
6228
|
+
},
|
|
6229
|
+
finish(receivedBytes = latestReceivedBytes, totalBytes = latestTotalBytes) {
|
|
6230
|
+
latestReceivedBytes = receivedBytes;
|
|
6231
|
+
latestTotalBytes = totalBytes;
|
|
6232
|
+
emitByteProgress(`${label} complete`, receivedBytes, totalBytes);
|
|
6233
|
+
},
|
|
6234
|
+
fail() {
|
|
6235
|
+
writeDesktopProgress({
|
|
6236
|
+
phase,
|
|
6237
|
+
message: `${label} failed`,
|
|
6238
|
+
transferredBytes: Math.max(0, latestReceivedBytes),
|
|
6239
|
+
error: `${label} failed`
|
|
6240
|
+
});
|
|
6241
|
+
}
|
|
6242
|
+
};
|
|
6243
|
+
};
|
|
6244
|
+
}
|
|
6245
|
+
async function waitForDesktopApplySignal() {
|
|
6246
|
+
process.stdin.setEncoding("utf8");
|
|
6247
|
+
process.stdin.resume();
|
|
6248
|
+
await new Promise((resolve, reject) => {
|
|
6249
|
+
let buffer = "";
|
|
6250
|
+
const cleanup = () => {
|
|
6251
|
+
process.stdin.off("data", onData);
|
|
6252
|
+
process.stdin.off("end", onEnd);
|
|
6253
|
+
process.stdin.off("error", onError);
|
|
6254
|
+
};
|
|
6255
|
+
const onData = (chunk) => {
|
|
6256
|
+
buffer += chunk;
|
|
6257
|
+
const lines = buffer.split(/\r?\n/);
|
|
6258
|
+
buffer = lines.pop() ?? "";
|
|
6259
|
+
if (lines.some((line) => line.trim() === "apply")) {
|
|
6260
|
+
cleanup();
|
|
6261
|
+
resolve();
|
|
6262
|
+
}
|
|
6263
|
+
};
|
|
6264
|
+
const onEnd = () => {
|
|
6265
|
+
cleanup();
|
|
6266
|
+
reject(new Error("Desktop update apply signal ended before confirmation."));
|
|
6267
|
+
};
|
|
6268
|
+
const onError = (error) => {
|
|
6269
|
+
cleanup();
|
|
6270
|
+
reject(error);
|
|
6271
|
+
};
|
|
6272
|
+
process.stdin.on("data", onData);
|
|
6273
|
+
process.stdin.on("end", onEnd);
|
|
6274
|
+
process.stdin.on("error", onError);
|
|
6275
|
+
});
|
|
6276
|
+
}
|
|
6135
6277
|
function resolveCurrentCliVersion(env = process.env) {
|
|
6136
6278
|
const version = resolveCliVersion(import.meta.url, env);
|
|
6137
6279
|
return version === "0.0.0" ? "latest" : version;
|
|
@@ -6313,6 +6455,26 @@ function buildGithubReleaseAsset(repo, tag, assetName) {
|
|
|
6313
6455
|
browser_download_url: buildGithubReleaseAssetDownloadUrl(repo, tag, assetName)
|
|
6314
6456
|
};
|
|
6315
6457
|
}
|
|
6458
|
+
function uniqueAssetDownloadUrls(asset) {
|
|
6459
|
+
const urls = [asset.url, asset.browser_download_url].filter((url) => Boolean(url));
|
|
6460
|
+
return Array.from(new Set(urls));
|
|
6461
|
+
}
|
|
6462
|
+
function downloadHeadersForAssetUrl(asset, url) {
|
|
6463
|
+
return {
|
|
6464
|
+
Accept: url === asset.url ? GITHUB_ASSET_DOWNLOAD_ACCEPT : "*/*",
|
|
6465
|
+
"User-Agent": "rudder-cli-installer"
|
|
6466
|
+
};
|
|
6467
|
+
}
|
|
6468
|
+
function formatFetchError(error) {
|
|
6469
|
+
if (!(error instanceof Error)) return String(error);
|
|
6470
|
+
const cause = error.cause;
|
|
6471
|
+
if (cause instanceof Error) {
|
|
6472
|
+
const code = cause.code;
|
|
6473
|
+
const suffix = typeof code === "string" ? ` [${code}]` : "";
|
|
6474
|
+
return `${error.message}: ${cause.message}${suffix}`;
|
|
6475
|
+
}
|
|
6476
|
+
return error.message;
|
|
6477
|
+
}
|
|
6316
6478
|
function contentLengthFromHeaders(headers) {
|
|
6317
6479
|
const raw = headers.get("content-length");
|
|
6318
6480
|
if (!raw) return null;
|
|
@@ -6322,11 +6484,24 @@ function contentLengthFromHeaders(headers) {
|
|
|
6322
6484
|
async function downloadAsset(asset, outputDir, progressFactory = createByteProgress) {
|
|
6323
6485
|
mkdirSync(outputDir, { recursive: true });
|
|
6324
6486
|
const outputPath = path11.join(outputDir, path11.basename(asset.name));
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6487
|
+
let response = null;
|
|
6488
|
+
const failures = [];
|
|
6489
|
+
for (const url of uniqueAssetDownloadUrls(asset)) {
|
|
6490
|
+
try {
|
|
6491
|
+
const candidate = await fetch(url, {
|
|
6492
|
+
headers: downloadHeadersForAssetUrl(asset, url)
|
|
6493
|
+
});
|
|
6494
|
+
if (candidate.ok && candidate.body) {
|
|
6495
|
+
response = candidate;
|
|
6496
|
+
break;
|
|
6497
|
+
}
|
|
6498
|
+
failures.push(`Failed to download ${asset.name} from ${url} (${candidate.status}).`);
|
|
6499
|
+
} catch (error) {
|
|
6500
|
+
failures.push(`Failed to download ${asset.name} from ${url}: ${formatFetchError(error)}.`);
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
if (!response) {
|
|
6504
|
+
throw new Error(failures.join("\n"));
|
|
6330
6505
|
}
|
|
6331
6506
|
const totalBytes = contentLengthFromHeaders(response.headers);
|
|
6332
6507
|
const progress = progressFactory(`Downloading ${asset.name}`);
|
|
@@ -6401,9 +6576,25 @@ function runChecked(command, args, options = {}) {
|
|
|
6401
6576
|
const output = [result.stdout, result.stderr].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
|
|
6402
6577
|
throw new Error(`${command} ${args.join(" ")} failed${output ? `: ${output}` : ""}`);
|
|
6403
6578
|
}
|
|
6579
|
+
function formatCommandFailure(command, args, stdout, stderr) {
|
|
6580
|
+
const output = [stdout, stderr].filter((value) => typeof value === "string" && value.trim().length > 0).join("\n").trim();
|
|
6581
|
+
return `${command} ${args.join(" ")} failed${output ? `: ${output}` : ""}`;
|
|
6582
|
+
}
|
|
6404
6583
|
function powershellQuote(value) {
|
|
6405
6584
|
return `'${value.replaceAll("'", "''")}'`;
|
|
6406
6585
|
}
|
|
6586
|
+
function buildWindowsZipExtractCommand(zipPath, outputDir) {
|
|
6587
|
+
return { command: "tar.exe", args: ["-xf", zipPath, "-C", outputDir] };
|
|
6588
|
+
}
|
|
6589
|
+
function buildWindowsRobocopyMirrorCommand(sourcePath, destinationPath) {
|
|
6590
|
+
return {
|
|
6591
|
+
command: "robocopy.exe",
|
|
6592
|
+
args: [sourcePath, destinationPath, "/MIR", "/R:2", "/W:1", "/NFL", "/NDL", "/NJH", "/NJS", "/NP"]
|
|
6593
|
+
};
|
|
6594
|
+
}
|
|
6595
|
+
function isSuccessfulRobocopyExitCode(status) {
|
|
6596
|
+
return typeof status === "number" && status >= 0 && status <= 7;
|
|
6597
|
+
}
|
|
6407
6598
|
async function extractZip(zipPath, outputDir, target) {
|
|
6408
6599
|
await rm(outputDir, { recursive: true, force: true });
|
|
6409
6600
|
await mkdir2(outputDir, { recursive: true });
|
|
@@ -6412,13 +6603,8 @@ async function extractZip(zipPath, outputDir, target) {
|
|
|
6412
6603
|
return;
|
|
6413
6604
|
}
|
|
6414
6605
|
if (target.platform === "windows") {
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
"-ExecutionPolicy",
|
|
6418
|
-
"Bypass",
|
|
6419
|
-
"-Command",
|
|
6420
|
-
`Expand-Archive -LiteralPath ${powershellQuote(zipPath)} -DestinationPath ${powershellQuote(outputDir)} -Force`
|
|
6421
|
-
]);
|
|
6606
|
+
const command = buildWindowsZipExtractCommand(zipPath, outputDir);
|
|
6607
|
+
runChecked(command.command, command.args);
|
|
6422
6608
|
return;
|
|
6423
6609
|
}
|
|
6424
6610
|
throw new Error(`Zip assets are not supported for ${target.platform}.`);
|
|
@@ -6564,6 +6750,16 @@ async function installPortableDesktop(installerPath, paths, target) {
|
|
|
6564
6750
|
}
|
|
6565
6751
|
}
|
|
6566
6752
|
async function copyPortableAppBundle(sourcePath, destinationPath) {
|
|
6753
|
+
if (process.platform === "win32") {
|
|
6754
|
+
await mkdir2(destinationPath, { recursive: true });
|
|
6755
|
+
const command = buildWindowsRobocopyMirrorCommand(sourcePath, destinationPath);
|
|
6756
|
+
const result = spawnSync3(command.command, command.args, {
|
|
6757
|
+
encoding: "utf8",
|
|
6758
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
6759
|
+
});
|
|
6760
|
+
if (isSuccessfulRobocopyExitCode(result.status)) return;
|
|
6761
|
+
throw new Error(formatCommandFailure(command.command, command.args, result.stdout, result.stderr));
|
|
6762
|
+
}
|
|
6567
6763
|
await cp(sourcePath, destinationPath, { recursive: true, verbatimSymlinks: true });
|
|
6568
6764
|
}
|
|
6569
6765
|
async function removeMacQuarantine(paths, target) {
|
|
@@ -6651,15 +6847,28 @@ async function writeInstallMetadata(paths, releaseTag, assetName, assetChecksum)
|
|
|
6651
6847
|
await writeFile2(paths.metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
6652
6848
|
`, "utf8");
|
|
6653
6849
|
}
|
|
6654
|
-
async function runStartPhase(message, successMessage, task) {
|
|
6850
|
+
async function runStartPhase(message, successMessage, task, progressPhase) {
|
|
6851
|
+
if (progressPhase) {
|
|
6852
|
+
writeDesktopProgress({ phase: progressPhase, message });
|
|
6853
|
+
}
|
|
6655
6854
|
const spinner3 = p13.spinner();
|
|
6656
6855
|
spinner3.start(message);
|
|
6657
6856
|
try {
|
|
6658
6857
|
const result = await task();
|
|
6659
6858
|
spinner3.stop(successMessage);
|
|
6859
|
+
if (progressPhase) {
|
|
6860
|
+
writeDesktopProgress({ phase: progressPhase, message: successMessage });
|
|
6861
|
+
}
|
|
6660
6862
|
return result;
|
|
6661
6863
|
} catch (error) {
|
|
6662
6864
|
spinner3.stop(pc8.red(`${message} failed.`));
|
|
6865
|
+
if (progressPhase) {
|
|
6866
|
+
writeDesktopProgress({
|
|
6867
|
+
phase: "failed",
|
|
6868
|
+
message: `${message} failed.`,
|
|
6869
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6870
|
+
});
|
|
6871
|
+
}
|
|
6663
6872
|
throw error;
|
|
6664
6873
|
}
|
|
6665
6874
|
}
|
|
@@ -6670,6 +6879,12 @@ async function startCommand(opts) {
|
|
|
6670
6879
|
const repo = opts.repo?.trim() || DEFAULT_DESKTOP_RELEASE_REPO;
|
|
6671
6880
|
const version = opts.targetVersion?.trim() || opts.version?.trim() || resolveCurrentCliVersion();
|
|
6672
6881
|
const dryRun = opts.dryRun === true;
|
|
6882
|
+
const desktopProgressJson = opts.desktopProgressJson === true;
|
|
6883
|
+
if (desktopProgressJson) {
|
|
6884
|
+
process.stdout.on("error", (error) => {
|
|
6885
|
+
if (error.code !== "EPIPE") throw error;
|
|
6886
|
+
});
|
|
6887
|
+
}
|
|
6673
6888
|
if (!installCli && !installDesktop && !installRuntime) {
|
|
6674
6889
|
throw new Error("Nothing to start. Remove --no-cli, --no-runtime, or --no-desktop.");
|
|
6675
6890
|
}
|
|
@@ -6743,21 +6958,30 @@ async function startCommand(opts) {
|
|
|
6743
6958
|
return;
|
|
6744
6959
|
}
|
|
6745
6960
|
const directReleaseVersion = resolveDesktopReleaseVersion(tag);
|
|
6746
|
-
const progressFactory = createByteProgress;
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6961
|
+
const progressFactory = desktopProgressJson ? createDesktopProgressFactory() : createByteProgress;
|
|
6962
|
+
let release = null;
|
|
6963
|
+
try {
|
|
6964
|
+
release = await runStartPhase(
|
|
6965
|
+
"Resolving Desktop release...",
|
|
6966
|
+
"Desktop release resolved.",
|
|
6967
|
+
() => fetchGithubRelease(repo, tag),
|
|
6968
|
+
desktopProgressJson ? "resolving_release" : null
|
|
6969
|
+
);
|
|
6970
|
+
} catch (error) {
|
|
6971
|
+
if (!directReleaseVersion) throw error;
|
|
6972
|
+
p13.log.warn(
|
|
6973
|
+
`Desktop release metadata could not be resolved; falling back to deterministic download URLs. ${formatFetchError(error)}`
|
|
6974
|
+
);
|
|
6975
|
+
}
|
|
6976
|
+
const releaseTag = release?.tag_name ?? (directReleaseVersion ? tag : null);
|
|
6753
6977
|
if (!releaseTag) {
|
|
6754
6978
|
throw new Error(`Unable to resolve Rudder Desktop release tag for ${repo}@${tag}.`);
|
|
6755
6979
|
}
|
|
6756
|
-
const asset = directReleaseVersion ? buildGithubReleaseAsset(repo, tag, resolveDesktopAssetName(directReleaseVersion, target)) :
|
|
6980
|
+
const asset = selectDesktopAsset(release?.assets ?? [], target) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, resolveDesktopAssetName(directReleaseVersion, target)) : null);
|
|
6757
6981
|
if (!asset) {
|
|
6758
6982
|
throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
6759
6983
|
}
|
|
6760
|
-
const checksumAsset = directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) :
|
|
6984
|
+
const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) : null);
|
|
6761
6985
|
const checksums = await downloadChecksums(checksumAsset, outputDir, progressFactory);
|
|
6762
6986
|
const expectedChecksum = resolveAssetChecksum(checksums, asset.name);
|
|
6763
6987
|
const metadata = await readInstallMetadata(installPaths.metadataPath);
|
|
@@ -6769,24 +6993,40 @@ async function startCommand(opts) {
|
|
|
6769
6993
|
async () => {
|
|
6770
6994
|
await removeMacQuarantine(installPaths, target);
|
|
6771
6995
|
await createPlatformLaunchers(installPaths, target);
|
|
6772
|
-
}
|
|
6996
|
+
},
|
|
6997
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
6773
6998
|
);
|
|
6774
6999
|
} else {
|
|
6775
7000
|
const installerPath = await downloadAsset(asset, outputDir, progressFactory);
|
|
6776
7001
|
const checksum = await runStartPhase(
|
|
6777
7002
|
"Verifying Desktop checksum...",
|
|
6778
7003
|
`Verified ${pc8.cyan(path11.basename(installerPath))}.`,
|
|
6779
|
-
() => assertChecksumMatch(installerPath, expectedChecksum)
|
|
7004
|
+
() => assertChecksumMatch(installerPath, expectedChecksum),
|
|
7005
|
+
desktopProgressJson ? "verifying_checksum" : null
|
|
6780
7006
|
);
|
|
7007
|
+
if (desktopProgressJson && opts.desktopWaitForApply === true) {
|
|
7008
|
+
writeDesktopProgress({
|
|
7009
|
+
phase: "ready_to_install",
|
|
7010
|
+
message: "Desktop update is downloaded and verified.",
|
|
7011
|
+
percent: 100
|
|
7012
|
+
});
|
|
7013
|
+
await waitForDesktopApplySignal();
|
|
7014
|
+
writeDesktopProgress({
|
|
7015
|
+
phase: "preparing_restart",
|
|
7016
|
+
message: "Applying Desktop update..."
|
|
7017
|
+
});
|
|
7018
|
+
}
|
|
6781
7019
|
await runStartPhase(
|
|
6782
7020
|
"Replacing existing Rudder Desktop if needed...",
|
|
6783
7021
|
"Existing Desktop install is ready for replacement.",
|
|
6784
|
-
() => prepareForDesktopReplace(installPaths, target, { waitForActiveRuns: opts.waitForActiveRuns === true })
|
|
7022
|
+
() => prepareForDesktopReplace(installPaths, target, { waitForActiveRuns: opts.waitForActiveRuns === true }),
|
|
7023
|
+
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
6785
7024
|
);
|
|
6786
7025
|
await runStartPhase(
|
|
6787
7026
|
"Installing portable Desktop app...",
|
|
6788
7027
|
`Installed Rudder Desktop to ${pc8.cyan(installPaths.appPath)}.`,
|
|
6789
|
-
() => installPortableDesktop(installerPath, installPaths, target)
|
|
7028
|
+
() => installPortableDesktop(installerPath, installPaths, target),
|
|
7029
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
6790
7030
|
);
|
|
6791
7031
|
await runStartPhase(
|
|
6792
7032
|
"Preparing Desktop launchers...",
|
|
@@ -6794,7 +7034,8 @@ async function startCommand(opts) {
|
|
|
6794
7034
|
async () => {
|
|
6795
7035
|
await removeMacQuarantine(installPaths, target);
|
|
6796
7036
|
await createPlatformLaunchers(installPaths, target);
|
|
6797
|
-
}
|
|
7037
|
+
},
|
|
7038
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
6798
7039
|
);
|
|
6799
7040
|
await writeInstallMetadata(installPaths, releaseTag, asset.name, checksum);
|
|
6800
7041
|
}
|
|
@@ -6802,7 +7043,8 @@ async function startCommand(opts) {
|
|
|
6802
7043
|
await runStartPhase(
|
|
6803
7044
|
"Launching Rudder Desktop...",
|
|
6804
7045
|
"Rudder Desktop launched.",
|
|
6805
|
-
() => launchDesktop(installPaths, target)
|
|
7046
|
+
() => launchDesktop(installPaths, target),
|
|
7047
|
+
desktopProgressJson ? "closing" : null
|
|
6806
7048
|
);
|
|
6807
7049
|
}
|
|
6808
7050
|
}
|
|
@@ -11357,7 +11599,7 @@ function createProgram() {
|
|
|
11357
11599
|
});
|
|
11358
11600
|
loadRudderEnvFile(options.config);
|
|
11359
11601
|
});
|
|
11360
|
-
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("--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);
|
|
11602
|
+
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);
|
|
11361
11603
|
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);
|
|
11362
11604
|
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) => {
|
|
11363
11605
|
await doctor(opts);
|