@rudderhq/cli 0.3.5-canary.2 → 0.3.5-canary.20
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 +240 -152
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -768,7 +768,7 @@ var init_adapter_skills = __esm({
|
|
|
768
768
|
|
|
769
769
|
// ../packages/shared/dist/validators/chat.js
|
|
770
770
|
import { z as z4 } from "zod";
|
|
771
|
-
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;
|
|
771
|
+
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, updateMessengerCustomGroupSchema, reorderMessengerCustomGroupsSchema, assignMessengerCustomGroupEntrySchema, reorderMessengerCustomGroupEntriesSchema;
|
|
772
772
|
var init_chat = __esm({
|
|
773
773
|
"../packages/shared/dist/validators/chat.js"() {
|
|
774
774
|
"use strict";
|
|
@@ -951,6 +951,25 @@ var init_chat = __esm({
|
|
|
951
951
|
updateMessengerThreadUserStateSchema = z4.object({
|
|
952
952
|
pinned: z4.boolean().optional()
|
|
953
953
|
});
|
|
954
|
+
createMessengerCustomGroupSchema = z4.object({
|
|
955
|
+
name: z4.string().trim().min(1).max(80),
|
|
956
|
+
icon: z4.string().trim().min(1).max(24).optional().nullable()
|
|
957
|
+
});
|
|
958
|
+
updateMessengerCustomGroupSchema = z4.object({
|
|
959
|
+
name: z4.string().trim().min(1).max(80).optional(),
|
|
960
|
+
icon: z4.string().trim().min(1).max(24).optional().nullable(),
|
|
961
|
+
collapsed: z4.boolean().optional(),
|
|
962
|
+
sortOrder: z4.number().int().min(0).optional()
|
|
963
|
+
});
|
|
964
|
+
reorderMessengerCustomGroupsSchema = z4.object({
|
|
965
|
+
groupIds: z4.array(z4.string().uuid()).max(200)
|
|
966
|
+
});
|
|
967
|
+
assignMessengerCustomGroupEntrySchema = z4.object({
|
|
968
|
+
threadKey: z4.string().trim().min(1).max(240)
|
|
969
|
+
});
|
|
970
|
+
reorderMessengerCustomGroupEntriesSchema = z4.object({
|
|
971
|
+
threadKeys: z4.array(z4.string().trim().min(1).max(240)).max(500)
|
|
972
|
+
});
|
|
954
973
|
}
|
|
955
974
|
});
|
|
956
975
|
|
|
@@ -7054,15 +7073,6 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
7054
7073
|
"",
|
|
7055
7074
|
"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.",
|
|
7056
7075
|
"",
|
|
7057
|
-
"## Self-Improvement and Automation Requests",
|
|
7058
|
-
"",
|
|
7059
|
-
"When the user asks to improve, optimize, or remember a workflow, treat it as a request to update the durable operating surface that controls future behavior, not as a request for advice only. First identify the surface: an automation, an agent-private skill, an organization skill, memory, instructions, or a project Library document. Then inspect the existing surface and apply the smallest governed update you are authorized to make.",
|
|
7060
|
-
"",
|
|
7061
|
-
"- For automation behavior, read the current automation or chat context first, then use the Rudder automation commands such as `rudder automation list`, `rudder automation get`, and `rudder automation update` instead of only describing what should change.",
|
|
7062
|
-
"- For skill improvement, find real evidence before editing: use `rudder runs by-skill <skill> --org-id <id>` or `rudder runs list --used-skill <skill>` to locate runs, then inspect the relevant transcripts or errors with `rudder runs transcript` / `rudder runs errors`.",
|
|
7063
|
-
"- For personal memory, use the `para-memory-files` skill; for agent-private skills, prefer `rudder agent skills create ... --enable` or editing `$AGENT_HOME/skills`; for organization skills, follow the bundled `rudder` skill's organization-skill workflow.",
|
|
7064
|
-
"- Do not silently mutate broad shared behavior when the request is ambiguous, risky, or outside your authority. Make the proposed change reviewable, ask for approval when needed, and report exactly which durable surface changed.",
|
|
7065
|
-
"",
|
|
7066
7076
|
"When you write issue comments or chat replies, match the language of the user's or board's most recent substantive message unless they explicitly ask for a different language.",
|
|
7067
7077
|
"When you mention a web page, issue URL, external dashboard, or other user-openable target in an issue comment or chat reply, write it as a clickable Markdown link with a descriptive label, for example `[NameSilo transfer page](https://www.namesilo.com/account_domain_manage_transfer.php)`. Do not put action URLs in backticks or code blocks unless you are showing literal code or a command.",
|
|
7068
7078
|
"",
|
|
@@ -7070,16 +7080,16 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
7070
7080
|
"",
|
|
7071
7081
|
"When you mention Rudder entities in any user-visible Markdown output, prefer Rudder's renderable Markdown link syntax over plain IDs, bare URLs, or backticked references so the UI can render chips and navigate correctly.",
|
|
7072
7082
|
"",
|
|
7073
|
-
"- Issues: use `[
|
|
7074
|
-
"- Agents: use `[
|
|
7075
|
-
"- Projects: use `[
|
|
7076
|
-
"- Chat threads: use `[
|
|
7077
|
-
"- Skills: use `[
|
|
7083
|
+
"- Issues: use `[](issue://<issue-id>)`; include `?c=<comment-id>` when linking to a specific comment.",
|
|
7084
|
+
"- Agents: use `[](agent://<agent-id>)` for reference-only links. In issue comments, use `[](agent://<agent-id>?intent=wake)` only when you intentionally want to wake that agent for attention or collaboration.",
|
|
7085
|
+
"- Projects: use `[](project://<project-id>)` when citing a Rudder project.",
|
|
7086
|
+
"- Chat threads: use `[](chat://<conversation-id>)` when citing a Rudder chat conversation.",
|
|
7087
|
+
"- Skills: use `[](skill://<skill-ref>)` when citing a Rudder skill reference. The skill ref may be an org skill, agent skill, bundled Rudder skill, or local-machine skill ref; the UI resolves the display label when metadata is available.",
|
|
7078
7088
|
'- Library files: use the `markdownLink` returned by `rudder library file ref "$RUDDER_PROJECT_LIBRARY_PATH/<relative-file>" --json`; do not hand-write `library-entry://...` links, and treat `library-file://...` as legacy path syntax only.',
|
|
7079
7089
|
"",
|
|
7080
7090
|
"Write these as normal Markdown links, not inside code spans or code blocks, unless you are literally documenting the syntax.",
|
|
7081
7091
|
"",
|
|
7082
|
-
"Mention-triggered comment wakes arrive with `RUDDER_WAKE_COMMENT_ID`; read that wake comment before acting. Issue comments can wake an agent only with an explicit wake-intent agent link serialized as `agent://agent-id?intent=wake`. Plain structured links such as `agent://agent-id` are reference-only links for rendering and navigation, and plain text agent names are not wake requests. Use wake-intent links only when you intentionally want to wake another agent for attention or collaboration; omit the wake intent for ordinary references. Mentioning an agent requests attention or collaboration; it does not transfer issue ownership unless the comment also makes an explicit handoff and normal checkout rules allow it.",
|
|
7092
|
+
"Mention-triggered comment wakes arrive with `RUDDER_WAKE_COMMENT_ID`; read that wake comment before acting. Issue comments can wake an agent only with an explicit wake-intent agent link serialized as `agent://agent-id?intent=wake`. Plain structured links such as `agent://agent-id` are reference-only links for rendering and navigation, and plain text agent names are not wake requests. Use wake-intent links only when you intentionally want to wake another agent for attention or collaboration; omit the wake intent for ordinary references. Mentioning an agent requests attention or collaboration; it does not transfer issue ownership unless the comment also makes an explicit handoff and normal checkout rules allow it. If a comment wakes you on an issue not assigned to you, including user-owned or unassigned issues, and the comment does not explicitly ask you to implement, modify files, close the issue, or take ownership, strictly respond to the comment's content instead of turning the wake into issue execution; answer questions, acknowledge corrections, explain status, or handle only the narrow action the comment explicitly requests.",
|
|
7083
7093
|
"",
|
|
7084
7094
|
"When an issue comment, done comment, or blocker comment cites visual evidence from a local screenshot/image path, attach the image with the Rudder CLI `--image <path>` option instead of leaving only the filesystem path in the text.",
|
|
7085
7095
|
"",
|
|
@@ -7111,7 +7121,7 @@ var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
|
|
|
7111
7121
|
"1. Identify yourself and inspect wake context, including `RUDDER_TASK_ID`, `RUDDER_WAKE_REASON`, `RUDDER_WAKE_COMMENT_ID`, and `RUDDER_APPROVAL_ID` when present.",
|
|
7112
7122
|
"2. Handle approval follow-up first: read the approval and linked issues, then close resolved work or comment on what remains.",
|
|
7113
7123
|
"3. 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.",
|
|
7114
|
-
"4. For mention wakes, read the wake comment before acting. Mentions request attention; they do not transfer ownership unless the comment explicitly says so.",
|
|
7124
|
+
"4. For mention wakes, read the wake comment before acting. Mentions request attention; they do not transfer ownership unless the comment explicitly says so. If the issue is not assigned to you, including user-owned or unassigned issues, and the comment does not explicitly ask you to implement, modify files, close the issue, or take ownership, respond to the comment itself instead of executing the whole issue.",
|
|
7115
7125
|
"5. Checkout before doing assignee task work. A `409` means another agent owns the task; do not retry it.",
|
|
7116
7126
|
"6. Load compact issue context, do one bounded useful chunk, and preserve evidence.",
|
|
7117
7127
|
"7. Before exiting active work, leave exactly one durable signal: progress, done, blocked, explicit handoff, or structured review decision.",
|
|
@@ -9489,6 +9499,11 @@ function formatChatMessage(row, maxOutputChars = 1200) {
|
|
|
9489
9499
|
role: row.role,
|
|
9490
9500
|
kind: row.kind,
|
|
9491
9501
|
status: row.status,
|
|
9502
|
+
...row.runId ? {
|
|
9503
|
+
runId: row.runId,
|
|
9504
|
+
runCommand: `rudder runs get ${row.runId}`,
|
|
9505
|
+
transcriptCommand: `rudder runs transcript ${row.runId}`
|
|
9506
|
+
} : {},
|
|
9492
9507
|
createdAt: row.createdAt,
|
|
9493
9508
|
body: clip(row.body, 220),
|
|
9494
9509
|
transcriptEntries: row.transcriptSummary?.entryCount ?? row.transcript?.length ?? 0,
|
|
@@ -9501,6 +9516,11 @@ function formatChatTranscriptMessage(row, maxChars) {
|
|
|
9501
9516
|
role: row.role,
|
|
9502
9517
|
kind: row.kind,
|
|
9503
9518
|
status: row.status,
|
|
9519
|
+
...row.runId ? {
|
|
9520
|
+
runId: row.runId,
|
|
9521
|
+
runCommand: `rudder runs get ${row.runId}`,
|
|
9522
|
+
transcriptCommand: `rudder runs transcript ${row.runId}`
|
|
9523
|
+
} : {},
|
|
9504
9524
|
createdAt: row.createdAt,
|
|
9505
9525
|
body: clip(row.body, 220)
|
|
9506
9526
|
};
|
|
@@ -13035,7 +13055,7 @@ init_install2();
|
|
|
13035
13055
|
init_install();
|
|
13036
13056
|
import * as p15 from "@clack/prompts";
|
|
13037
13057
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
|
|
13038
|
-
import { createHash } from "node:crypto";
|
|
13058
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
13039
13059
|
import { createWriteStream, constants as fsConstants, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
13040
13060
|
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";
|
|
13041
13061
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -13171,6 +13191,8 @@ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES = 2;
|
|
|
13171
13191
|
var DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
13172
13192
|
var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
|
|
13173
13193
|
var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
|
|
13194
|
+
var DESKTOP_INSTALL_LOCK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
13195
|
+
var DESKTOP_INSTALL_LOCK_POLL_MS = 250;
|
|
13174
13196
|
function normalizeProgressTotal(totalBytes) {
|
|
13175
13197
|
return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
|
|
13176
13198
|
}
|
|
@@ -13814,6 +13836,70 @@ async function pathExists2(targetPath) {
|
|
|
13814
13836
|
return false;
|
|
13815
13837
|
}
|
|
13816
13838
|
}
|
|
13839
|
+
function resolveDesktopInstallLockPath(paths) {
|
|
13840
|
+
const installRootHash = createHash("sha256").update(path21.resolve(paths.installRoot)).digest("hex").slice(0, 16);
|
|
13841
|
+
return path21.join(path21.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
|
|
13842
|
+
}
|
|
13843
|
+
async function readDesktopInstallLock(lockPath) {
|
|
13844
|
+
try {
|
|
13845
|
+
const parsed = JSON.parse(await readFile6(lockPath, "utf8"));
|
|
13846
|
+
if (typeof parsed.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0 || typeof parsed.lockId !== "string" || typeof parsed.installRoot !== "string" || typeof parsed.createdAt !== "string") {
|
|
13847
|
+
return null;
|
|
13848
|
+
}
|
|
13849
|
+
return {
|
|
13850
|
+
lockId: parsed.lockId,
|
|
13851
|
+
pid: parsed.pid,
|
|
13852
|
+
installRoot: parsed.installRoot,
|
|
13853
|
+
createdAt: parsed.createdAt
|
|
13854
|
+
};
|
|
13855
|
+
} catch {
|
|
13856
|
+
return null;
|
|
13857
|
+
}
|
|
13858
|
+
}
|
|
13859
|
+
async function withDesktopInstallLock(paths, fn, options = {}) {
|
|
13860
|
+
const lockPath = resolveDesktopInstallLockPath(paths);
|
|
13861
|
+
const lockDir = path21.dirname(lockPath);
|
|
13862
|
+
const timeoutMs = options.timeoutMs ?? DESKTOP_INSTALL_LOCK_TIMEOUT_MS;
|
|
13863
|
+
const pollMs = options.pollMs ?? DESKTOP_INSTALL_LOCK_POLL_MS;
|
|
13864
|
+
const startedAt = Date.now();
|
|
13865
|
+
const payload = {
|
|
13866
|
+
lockId: randomUUID(),
|
|
13867
|
+
pid: process.pid,
|
|
13868
|
+
installRoot: path21.resolve(paths.installRoot),
|
|
13869
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13870
|
+
};
|
|
13871
|
+
await mkdir3(lockDir, { recursive: true });
|
|
13872
|
+
while (true) {
|
|
13873
|
+
try {
|
|
13874
|
+
await writeFile3(lockPath, `${JSON.stringify(payload, null, 2)}
|
|
13875
|
+
`, { encoding: "utf8", flag: "wx" });
|
|
13876
|
+
break;
|
|
13877
|
+
} catch (error) {
|
|
13878
|
+
const err = error;
|
|
13879
|
+
if (err.code !== "EEXIST") throw error;
|
|
13880
|
+
const existing = await readDesktopInstallLock(lockPath);
|
|
13881
|
+
const stale = !existing || !processExists(existing.pid);
|
|
13882
|
+
if (stale) {
|
|
13883
|
+
await rm2(lockPath, { force: true });
|
|
13884
|
+
continue;
|
|
13885
|
+
}
|
|
13886
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
13887
|
+
throw new Error(
|
|
13888
|
+
`Timed out waiting for Rudder Desktop install lock for ${paths.appPath}. Held by pid ${existing.pid} for ${existing.installRoot}.`
|
|
13889
|
+
);
|
|
13890
|
+
}
|
|
13891
|
+
await delay2(pollMs);
|
|
13892
|
+
}
|
|
13893
|
+
}
|
|
13894
|
+
try {
|
|
13895
|
+
return await fn();
|
|
13896
|
+
} finally {
|
|
13897
|
+
const existing = await readDesktopInstallLock(lockPath);
|
|
13898
|
+
if (existing?.lockId === payload.lockId) {
|
|
13899
|
+
await rm2(lockPath, { force: true });
|
|
13900
|
+
}
|
|
13901
|
+
}
|
|
13902
|
+
}
|
|
13817
13903
|
function runChecked(command, args, options = {}) {
|
|
13818
13904
|
const result = spawnSync3(command, args, {
|
|
13819
13905
|
encoding: "utf8",
|
|
@@ -14266,152 +14352,154 @@ async function startCommand(opts) {
|
|
|
14266
14352
|
p15.outro(pc15.green("Dry run complete."));
|
|
14267
14353
|
return;
|
|
14268
14354
|
}
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
release = await runStartPhase(
|
|
14274
|
-
"Resolving Desktop release...",
|
|
14275
|
-
"Desktop release resolved.",
|
|
14276
|
-
() => fetchGithubRelease(repo, tag),
|
|
14277
|
-
desktopProgressJson ? "resolving_release" : null
|
|
14278
|
-
);
|
|
14279
|
-
} catch (error) {
|
|
14280
|
-
if (!directReleaseVersion) throw error;
|
|
14281
|
-
p15.log.warn(
|
|
14282
|
-
`Desktop release metadata could not be resolved; falling back to deterministic download URLs. ${formatFetchError(error)}`
|
|
14283
|
-
);
|
|
14284
|
-
}
|
|
14285
|
-
const releaseTag = release?.tag_name ?? (directReleaseVersion ? tag : null);
|
|
14286
|
-
if (!releaseTag) {
|
|
14287
|
-
throw new Error(`Unable to resolve Rudder Desktop release tag for ${repo}@${tag}.`);
|
|
14288
|
-
}
|
|
14289
|
-
const assetCandidates = resolveDesktopAssetCandidates({
|
|
14290
|
-
releaseAssets: release?.assets ?? [],
|
|
14291
|
-
target,
|
|
14292
|
-
repo,
|
|
14293
|
-
tag,
|
|
14294
|
-
directReleaseVersion,
|
|
14295
|
-
allowShellAssets: runtimeSupportsShellAssets
|
|
14296
|
-
});
|
|
14297
|
-
if (assetCandidates.length === 0) {
|
|
14298
|
-
throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14299
|
-
}
|
|
14300
|
-
const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) : null);
|
|
14301
|
-
const checksums = await downloadChecksums(checksumAsset, outputDir, progressFactory);
|
|
14302
|
-
let selectedCandidate;
|
|
14303
|
-
try {
|
|
14304
|
-
selectedCandidate = selectChecksummedDesktopAssetCandidate(assetCandidates, checksums);
|
|
14305
|
-
} catch (error) {
|
|
14306
|
-
throw new Error(`No checksummed Rudder Desktop asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14307
|
-
}
|
|
14308
|
-
for (const warning of selectedCandidate.warnings) p15.log.warn(warning);
|
|
14309
|
-
let selectedAsset = selectedCandidate.asset;
|
|
14310
|
-
let selectedAssetKind = selectedCandidate.kind;
|
|
14311
|
-
let expectedChecksum = selectedCandidate.expectedChecksum;
|
|
14312
|
-
const metadata = await readInstallMetadata(installPaths.metadataPath);
|
|
14313
|
-
if (isInstalledDesktopCurrent(metadata, releaseTag, selectedAsset.name, expectedChecksum) && await pathExists2(installPaths.executablePath)) {
|
|
14314
|
-
p15.log.success(`Rudder Desktop is already installed at ${pc15.cyan(installPaths.appPath)}.`);
|
|
14315
|
-
await runStartPhase(
|
|
14316
|
-
"Refreshing Desktop launchers...",
|
|
14317
|
-
"Desktop launchers ready.",
|
|
14318
|
-
async () => {
|
|
14319
|
-
await removeMacQuarantine(installPaths, target);
|
|
14320
|
-
await createPlatformLaunchers(installPaths, target);
|
|
14321
|
-
},
|
|
14322
|
-
desktopProgressJson ? "preparing_restart" : null
|
|
14323
|
-
);
|
|
14324
|
-
} else {
|
|
14325
|
-
let cachedAsset;
|
|
14355
|
+
await withDesktopInstallLock(installPaths, async () => {
|
|
14356
|
+
const directReleaseVersion = resolveDesktopReleaseVersion(tag);
|
|
14357
|
+
const progressFactory = desktopProgressJson ? createDesktopProgressFactory() : createByteProgress;
|
|
14358
|
+
let release = null;
|
|
14326
14359
|
try {
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14360
|
+
release = await runStartPhase(
|
|
14361
|
+
"Resolving Desktop release...",
|
|
14362
|
+
"Desktop release resolved.",
|
|
14363
|
+
() => fetchGithubRelease(repo, tag),
|
|
14364
|
+
desktopProgressJson ? "resolving_release" : null
|
|
14365
|
+
);
|
|
14331
14366
|
} catch (error) {
|
|
14332
|
-
|
|
14333
|
-
if (selectedAssetKind !== "shell" || !fullCandidate) throw error;
|
|
14367
|
+
if (!directReleaseVersion) throw error;
|
|
14334
14368
|
p15.log.warn(
|
|
14335
|
-
`
|
|
14369
|
+
`Desktop release metadata could not be resolved; falling back to deterministic download URLs. ${formatFetchError(error)}`
|
|
14336
14370
|
);
|
|
14337
|
-
selectedAsset = fullCandidate.asset;
|
|
14338
|
-
selectedAssetKind = fullCandidate.kind;
|
|
14339
|
-
expectedChecksum = resolveAssetChecksum(checksums, selectedAsset.name);
|
|
14340
|
-
cachedAsset = await downloadDesktopAssetWithCache(selectedAsset, expectedChecksum, {
|
|
14341
|
-
outputDir,
|
|
14342
|
-
progressFactory
|
|
14343
|
-
});
|
|
14344
14371
|
}
|
|
14345
|
-
|
|
14346
|
-
|
|
14347
|
-
|
|
14372
|
+
const releaseTag = release?.tag_name ?? (directReleaseVersion ? tag : null);
|
|
14373
|
+
if (!releaseTag) {
|
|
14374
|
+
throw new Error(`Unable to resolve Rudder Desktop release tag for ${repo}@${tag}.`);
|
|
14375
|
+
}
|
|
14376
|
+
const assetCandidates = resolveDesktopAssetCandidates({
|
|
14377
|
+
releaseAssets: release?.assets ?? [],
|
|
14378
|
+
target,
|
|
14379
|
+
repo,
|
|
14380
|
+
tag,
|
|
14381
|
+
directReleaseVersion,
|
|
14382
|
+
allowShellAssets: runtimeSupportsShellAssets
|
|
14383
|
+
});
|
|
14384
|
+
if (assetCandidates.length === 0) {
|
|
14385
|
+
throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14386
|
+
}
|
|
14387
|
+
const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) : null);
|
|
14388
|
+
const checksums = await downloadChecksums(checksumAsset, outputDir, progressFactory);
|
|
14389
|
+
let selectedCandidate;
|
|
14390
|
+
try {
|
|
14391
|
+
selectedCandidate = selectChecksummedDesktopAssetCandidate(assetCandidates, checksums);
|
|
14392
|
+
} catch (error) {
|
|
14393
|
+
throw new Error(`No checksummed Rudder Desktop asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14394
|
+
}
|
|
14395
|
+
for (const warning of selectedCandidate.warnings) p15.log.warn(warning);
|
|
14396
|
+
let selectedAsset = selectedCandidate.asset;
|
|
14397
|
+
let selectedAssetKind = selectedCandidate.kind;
|
|
14398
|
+
let expectedChecksum = selectedCandidate.expectedChecksum;
|
|
14399
|
+
const metadata = await readInstallMetadata(installPaths.metadataPath);
|
|
14400
|
+
if (isInstalledDesktopCurrent(metadata, releaseTag, selectedAsset.name, expectedChecksum) && await pathExists2(installPaths.executablePath)) {
|
|
14401
|
+
p15.log.success(`Rudder Desktop is already installed at ${pc15.cyan(installPaths.appPath)}.`);
|
|
14402
|
+
await runStartPhase(
|
|
14403
|
+
"Refreshing Desktop launchers...",
|
|
14404
|
+
"Desktop launchers ready.",
|
|
14405
|
+
async () => {
|
|
14406
|
+
await removeMacQuarantine(installPaths, target);
|
|
14407
|
+
await createPlatformLaunchers(installPaths, target);
|
|
14408
|
+
},
|
|
14409
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14410
|
+
);
|
|
14411
|
+
} else {
|
|
14412
|
+
let cachedAsset;
|
|
14413
|
+
try {
|
|
14414
|
+
cachedAsset = await downloadDesktopAssetWithCache(selectedAsset, expectedChecksum, {
|
|
14415
|
+
outputDir,
|
|
14416
|
+
progressFactory
|
|
14417
|
+
});
|
|
14418
|
+
} catch (error) {
|
|
14419
|
+
const fullCandidate = assetCandidates.find((candidate) => candidate.kind === "full");
|
|
14420
|
+
if (selectedAssetKind !== "shell" || !fullCandidate) throw error;
|
|
14421
|
+
p15.log.warn(
|
|
14422
|
+
`Layered Desktop shell asset download failed; falling back to the full portable asset. ${formatFetchError(error)}`
|
|
14423
|
+
);
|
|
14424
|
+
selectedAsset = fullCandidate.asset;
|
|
14425
|
+
selectedAssetKind = fullCandidate.kind;
|
|
14426
|
+
expectedChecksum = resolveAssetChecksum(checksums, selectedAsset.name);
|
|
14427
|
+
cachedAsset = await downloadDesktopAssetWithCache(selectedAsset, expectedChecksum, {
|
|
14428
|
+
outputDir,
|
|
14429
|
+
progressFactory
|
|
14430
|
+
});
|
|
14431
|
+
}
|
|
14432
|
+
if (cachedAsset.cacheStatus === "hit") {
|
|
14433
|
+
p15.log.success(`Desktop asset cache hit at ${pc15.cyan(cachedAsset.path)}.`);
|
|
14434
|
+
if (desktopProgressJson) {
|
|
14435
|
+
writeDesktopProgress({
|
|
14436
|
+
phase: "downloading_asset",
|
|
14437
|
+
message: `Desktop asset cache hit for ${selectedAsset.name}.`,
|
|
14438
|
+
percent: 100
|
|
14439
|
+
});
|
|
14440
|
+
}
|
|
14441
|
+
}
|
|
14442
|
+
const checksum = await runStartPhase(
|
|
14443
|
+
"Verifying Desktop checksum...",
|
|
14444
|
+
`Verified ${pc15.cyan(path21.basename(cachedAsset.path))}.`,
|
|
14445
|
+
() => assertChecksumMatch(cachedAsset.path, expectedChecksum),
|
|
14446
|
+
desktopProgressJson ? "verifying_checksum" : null
|
|
14447
|
+
);
|
|
14448
|
+
if (desktopProgressJson && opts.desktopWaitForApply === true) {
|
|
14348
14449
|
writeDesktopProgress({
|
|
14349
|
-
phase: "
|
|
14350
|
-
message:
|
|
14450
|
+
phase: "ready_to_install",
|
|
14451
|
+
message: "Desktop update is downloaded and verified.",
|
|
14351
14452
|
percent: 100
|
|
14352
14453
|
});
|
|
14454
|
+
await waitForDesktopApplySignal();
|
|
14455
|
+
writeDesktopProgress({
|
|
14456
|
+
phase: "preparing_restart",
|
|
14457
|
+
message: "Applying Desktop update..."
|
|
14458
|
+
});
|
|
14353
14459
|
}
|
|
14460
|
+
await runStartPhase(
|
|
14461
|
+
"Replacing existing Rudder Desktop if needed...",
|
|
14462
|
+
"Existing Desktop install is ready for replacement.",
|
|
14463
|
+
() => prepareForDesktopReplace(installPaths, target, { waitForActiveRuns: opts.waitForActiveRuns === true }),
|
|
14464
|
+
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
14465
|
+
);
|
|
14466
|
+
await runStartPhase(
|
|
14467
|
+
"Installing portable Desktop app...",
|
|
14468
|
+
`Installed Rudder Desktop to ${pc15.cyan(installPaths.appPath)}.`,
|
|
14469
|
+
() => installPortableDesktop(cachedAsset.path, installPaths, target),
|
|
14470
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14471
|
+
);
|
|
14472
|
+
await runStartPhase(
|
|
14473
|
+
"Preparing Desktop launchers...",
|
|
14474
|
+
"Desktop launchers ready.",
|
|
14475
|
+
async () => {
|
|
14476
|
+
await removeMacQuarantine(installPaths, target);
|
|
14477
|
+
await createPlatformLaunchers(installPaths, target);
|
|
14478
|
+
},
|
|
14479
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14480
|
+
);
|
|
14481
|
+
await writeInstallMetadata(installPaths, releaseTag, selectedAsset.name, checksum, selectedAssetKind);
|
|
14354
14482
|
}
|
|
14355
|
-
const
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
|
|
14361
|
-
|
|
14362
|
-
|
|
14363
|
-
|
|
14364
|
-
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
await
|
|
14368
|
-
|
|
14369
|
-
|
|
14370
|
-
|
|
14371
|
-
|
|
14372
|
-
}
|
|
14373
|
-
await runStartPhase(
|
|
14374
|
-
"Replacing existing Rudder Desktop if needed...",
|
|
14375
|
-
"Existing Desktop install is ready for replacement.",
|
|
14376
|
-
() => prepareForDesktopReplace(installPaths, target, { waitForActiveRuns: opts.waitForActiveRuns === true }),
|
|
14377
|
-
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
14378
|
-
);
|
|
14379
|
-
await runStartPhase(
|
|
14380
|
-
"Installing portable Desktop app...",
|
|
14381
|
-
`Installed Rudder Desktop to ${pc15.cyan(installPaths.appPath)}.`,
|
|
14382
|
-
() => installPortableDesktop(cachedAsset.path, installPaths, target),
|
|
14383
|
-
desktopProgressJson ? "preparing_restart" : null
|
|
14384
|
-
);
|
|
14385
|
-
await runStartPhase(
|
|
14386
|
-
"Preparing Desktop launchers...",
|
|
14387
|
-
"Desktop launchers ready.",
|
|
14388
|
-
async () => {
|
|
14389
|
-
await removeMacQuarantine(installPaths, target);
|
|
14390
|
-
await createPlatformLaunchers(installPaths, target);
|
|
14391
|
-
},
|
|
14392
|
-
desktopProgressJson ? "preparing_restart" : null
|
|
14393
|
-
);
|
|
14394
|
-
await writeInstallMetadata(installPaths, releaseTag, selectedAsset.name, checksum, selectedAssetKind);
|
|
14395
|
-
}
|
|
14396
|
-
const desktopAssetPrune = await maybePruneDesktopAssetCache({
|
|
14397
|
-
protectedChecksums: [expectedChecksum]
|
|
14398
|
-
});
|
|
14399
|
-
if (desktopAssetPrune) {
|
|
14400
|
-
if (desktopAssetPrune.deleted.length > 0) {
|
|
14401
|
-
p15.log.success(
|
|
14402
|
-
`Pruned ${desktopAssetPrune.deleted.length} old Desktop asset cache(s), freed ${formatBytes(desktopAssetPrune.freedBytes)}.`
|
|
14483
|
+
const desktopAssetPrune = await maybePruneDesktopAssetCache({
|
|
14484
|
+
protectedChecksums: [expectedChecksum]
|
|
14485
|
+
});
|
|
14486
|
+
if (desktopAssetPrune) {
|
|
14487
|
+
if (desktopAssetPrune.deleted.length > 0) {
|
|
14488
|
+
p15.log.success(
|
|
14489
|
+
`Pruned ${desktopAssetPrune.deleted.length} old Desktop asset cache(s), freed ${formatBytes(desktopAssetPrune.freedBytes)}.`
|
|
14490
|
+
);
|
|
14491
|
+
}
|
|
14492
|
+
for (const warning of desktopAssetPrune.warnings) p15.log.warn(warning);
|
|
14493
|
+
}
|
|
14494
|
+
if (opts.open !== false) {
|
|
14495
|
+
await runStartPhase(
|
|
14496
|
+
"Launching Rudder Desktop...",
|
|
14497
|
+
"Rudder Desktop launched.",
|
|
14498
|
+
() => launchDesktop(installPaths, target),
|
|
14499
|
+
desktopProgressJson ? "closing" : null
|
|
14403
14500
|
);
|
|
14404
14501
|
}
|
|
14405
|
-
|
|
14406
|
-
}
|
|
14407
|
-
if (opts.open !== false) {
|
|
14408
|
-
await runStartPhase(
|
|
14409
|
-
"Launching Rudder Desktop...",
|
|
14410
|
-
"Rudder Desktop launched.",
|
|
14411
|
-
() => launchDesktop(installPaths, target),
|
|
14412
|
-
desktopProgressJson ? "closing" : null
|
|
14413
|
-
);
|
|
14414
|
-
}
|
|
14502
|
+
});
|
|
14415
14503
|
}
|
|
14416
14504
|
p15.outro(pc15.green("Rudder start complete."));
|
|
14417
14505
|
}
|