@rudderhq/cli 0.3.5-canary.2 → 0.3.5-canary.21
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 +308 -153
- package/dist/index.js.map +4 -4
- 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
|
|
|
@@ -1107,7 +1126,7 @@ var init_organization_intelligence_profile = __esm({
|
|
|
1107
1126
|
upsertOrganizationIntelligenceProfileSchema = z7.object({
|
|
1108
1127
|
agentRuntimeType: z7.enum(AGENT_RUNTIME_TYPES),
|
|
1109
1128
|
agentRuntimeConfig: organizationIntelligenceProfileConfigSchema.default({}),
|
|
1110
|
-
status: organizationIntelligenceProfileStatusSchema.optional().default("
|
|
1129
|
+
status: organizationIntelligenceProfileStatusSchema.optional().default("disabled")
|
|
1111
1130
|
});
|
|
1112
1131
|
}
|
|
1113
1132
|
});
|
|
@@ -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.",
|
|
@@ -7547,6 +7557,18 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
7547
7557
|
requiresRunId: false,
|
|
7548
7558
|
attachesRunIdWhenAvailable: true
|
|
7549
7559
|
},
|
|
7560
|
+
{
|
|
7561
|
+
id: "user.activity",
|
|
7562
|
+
command: "rudder user activity --user me --since today --json",
|
|
7563
|
+
category: "user",
|
|
7564
|
+
description: "Read a user-centered activity ledger with safe excerpts and provenance across chats, issue comments, approval comments, and user actor activity.",
|
|
7565
|
+
mutating: false,
|
|
7566
|
+
contract: "agent-v1",
|
|
7567
|
+
requiresOrgId: true,
|
|
7568
|
+
requiresAgentId: false,
|
|
7569
|
+
requiresRunId: false,
|
|
7570
|
+
attachesRunIdWhenAvailable: false
|
|
7571
|
+
},
|
|
7550
7572
|
{
|
|
7551
7573
|
id: "library.file.list",
|
|
7552
7574
|
command: "rudder library file list [directory]",
|
|
@@ -8145,6 +8167,7 @@ var CATEGORY_TITLES = {
|
|
|
8145
8167
|
runs: "Runs",
|
|
8146
8168
|
approval: "Approval",
|
|
8147
8169
|
skill: "Skill",
|
|
8170
|
+
user: "User",
|
|
8148
8171
|
library: "Library"
|
|
8149
8172
|
};
|
|
8150
8173
|
function getAgentCliCapabilities() {
|
|
@@ -9489,6 +9512,11 @@ function formatChatMessage(row, maxOutputChars = 1200) {
|
|
|
9489
9512
|
role: row.role,
|
|
9490
9513
|
kind: row.kind,
|
|
9491
9514
|
status: row.status,
|
|
9515
|
+
...row.runId ? {
|
|
9516
|
+
runId: row.runId,
|
|
9517
|
+
runCommand: `rudder runs get ${row.runId}`,
|
|
9518
|
+
transcriptCommand: `rudder runs transcript ${row.runId}`
|
|
9519
|
+
} : {},
|
|
9492
9520
|
createdAt: row.createdAt,
|
|
9493
9521
|
body: clip(row.body, 220),
|
|
9494
9522
|
transcriptEntries: row.transcriptSummary?.entryCount ?? row.transcript?.length ?? 0,
|
|
@@ -9501,6 +9529,11 @@ function formatChatTranscriptMessage(row, maxChars) {
|
|
|
9501
9529
|
role: row.role,
|
|
9502
9530
|
kind: row.kind,
|
|
9503
9531
|
status: row.status,
|
|
9532
|
+
...row.runId ? {
|
|
9533
|
+
runId: row.runId,
|
|
9534
|
+
runCommand: `rudder runs get ${row.runId}`,
|
|
9535
|
+
transcriptCommand: `rudder runs transcript ${row.runId}`
|
|
9536
|
+
} : {},
|
|
9504
9537
|
createdAt: row.createdAt,
|
|
9505
9538
|
body: clip(row.body, 220)
|
|
9506
9539
|
};
|
|
@@ -12241,6 +12274,59 @@ function parseCsv5(value) {
|
|
|
12241
12274
|
return rows.length > 0 ? rows : void 0;
|
|
12242
12275
|
}
|
|
12243
12276
|
|
|
12277
|
+
// src/commands/client/user.ts
|
|
12278
|
+
function appendParam(params, key, value) {
|
|
12279
|
+
if (value && value.trim()) params.set(key, value.trim());
|
|
12280
|
+
}
|
|
12281
|
+
function formatUserActivityItem(item) {
|
|
12282
|
+
const time = new Date(item.occurredAt);
|
|
12283
|
+
const hhmm = Number.isNaN(time.getTime()) ? item.occurredAt : time.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
12284
|
+
const related = item.related.find((entry) => entry.type === "issue" || entry.type === "chat" || entry.type === "approval");
|
|
12285
|
+
const label = related?.label || related?.id || item.source.id;
|
|
12286
|
+
const excerpt = item.excerpt ? ` - ${item.excerpt}` : "";
|
|
12287
|
+
return `${hhmm} ${item.kind} ${label}: ${item.summary}${excerpt}`;
|
|
12288
|
+
}
|
|
12289
|
+
function registerUserCommands(program) {
|
|
12290
|
+
const user = program.command("user").description("User-oriented Rudder context commands");
|
|
12291
|
+
addCommonClientOptions(
|
|
12292
|
+
user.command("activity").description("List a user's recent Rudder activity ledger").option("-O, --org-id <id>", "Organization ID").option("--user <id>", "User ID or 'me'", "me").option("--since <value>", "Start time: today, 24h, 7d, or ISO timestamp", "today").option("--until <value>", "End time: ISO timestamp").option("--include <items>", "Comma-separated sources: chat,comments,issues,approvals,activity").option("--agent-id <id>", "Filter by related agent ID").option("--project-id <id>", "Filter by related project ID").option("--issue-id <id>", "Filter by related issue ID").option("--limit <n>", "Maximum items to return").option("--cursor <cursor>", "Pagination cursor from a prior response").action(async (opts) => {
|
|
12293
|
+
try {
|
|
12294
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12295
|
+
const userId = opts.user?.trim() || "me";
|
|
12296
|
+
const params = new URLSearchParams();
|
|
12297
|
+
appendParam(params, "since", opts.since);
|
|
12298
|
+
appendParam(params, "until", opts.until);
|
|
12299
|
+
appendParam(params, "include", opts.include);
|
|
12300
|
+
appendParam(params, "agentId", opts.agentId);
|
|
12301
|
+
appendParam(params, "projectId", opts.projectId);
|
|
12302
|
+
appendParam(params, "issueId", opts.issueId);
|
|
12303
|
+
appendParam(params, "limit", opts.limit);
|
|
12304
|
+
appendParam(params, "cursor", opts.cursor);
|
|
12305
|
+
const query = params.toString();
|
|
12306
|
+
const path23 = `/api/orgs/${ctx.orgId}/users/${encodeURIComponent(userId)}/activity-ledger${query ? `?${query}` : ""}`;
|
|
12307
|
+
const result = await ctx.api.get(path23);
|
|
12308
|
+
if (ctx.json) {
|
|
12309
|
+
printOutput(result, { json: true });
|
|
12310
|
+
return;
|
|
12311
|
+
}
|
|
12312
|
+
if (!result?.items?.length) {
|
|
12313
|
+
printOutput([], { json: false });
|
|
12314
|
+
return;
|
|
12315
|
+
}
|
|
12316
|
+
for (const item of result.items) {
|
|
12317
|
+
console.log(formatUserActivityItem(item));
|
|
12318
|
+
}
|
|
12319
|
+
if (result.nextCursor) {
|
|
12320
|
+
console.log(`nextCursor=${result.nextCursor}`);
|
|
12321
|
+
}
|
|
12322
|
+
} catch (err) {
|
|
12323
|
+
handleCommandError(err);
|
|
12324
|
+
}
|
|
12325
|
+
}),
|
|
12326
|
+
{ includeCompany: false }
|
|
12327
|
+
);
|
|
12328
|
+
}
|
|
12329
|
+
|
|
12244
12330
|
// src/commands/configure.ts
|
|
12245
12331
|
init_home();
|
|
12246
12332
|
init_schema();
|
|
@@ -13035,7 +13121,7 @@ init_install2();
|
|
|
13035
13121
|
init_install();
|
|
13036
13122
|
import * as p15 from "@clack/prompts";
|
|
13037
13123
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "node:child_process";
|
|
13038
|
-
import { createHash } from "node:crypto";
|
|
13124
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
13039
13125
|
import { createWriteStream, constants as fsConstants, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
13040
13126
|
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
13127
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -13171,6 +13257,8 @@ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES = 2;
|
|
|
13171
13257
|
var DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
13172
13258
|
var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
|
|
13173
13259
|
var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
|
|
13260
|
+
var DESKTOP_INSTALL_LOCK_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
13261
|
+
var DESKTOP_INSTALL_LOCK_POLL_MS = 250;
|
|
13174
13262
|
function normalizeProgressTotal(totalBytes) {
|
|
13175
13263
|
return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
|
|
13176
13264
|
}
|
|
@@ -13814,6 +13902,70 @@ async function pathExists2(targetPath) {
|
|
|
13814
13902
|
return false;
|
|
13815
13903
|
}
|
|
13816
13904
|
}
|
|
13905
|
+
function resolveDesktopInstallLockPath(paths) {
|
|
13906
|
+
const installRootHash = createHash("sha256").update(path21.resolve(paths.installRoot)).digest("hex").slice(0, 16);
|
|
13907
|
+
return path21.join(path21.dirname(paths.appPath), `.rudder-desktop-install-${installRootHash}.lock`);
|
|
13908
|
+
}
|
|
13909
|
+
async function readDesktopInstallLock(lockPath) {
|
|
13910
|
+
try {
|
|
13911
|
+
const parsed = JSON.parse(await readFile6(lockPath, "utf8"));
|
|
13912
|
+
if (typeof parsed.pid !== "number" || !Number.isInteger(parsed.pid) || parsed.pid <= 0 || typeof parsed.lockId !== "string" || typeof parsed.installRoot !== "string" || typeof parsed.createdAt !== "string") {
|
|
13913
|
+
return null;
|
|
13914
|
+
}
|
|
13915
|
+
return {
|
|
13916
|
+
lockId: parsed.lockId,
|
|
13917
|
+
pid: parsed.pid,
|
|
13918
|
+
installRoot: parsed.installRoot,
|
|
13919
|
+
createdAt: parsed.createdAt
|
|
13920
|
+
};
|
|
13921
|
+
} catch {
|
|
13922
|
+
return null;
|
|
13923
|
+
}
|
|
13924
|
+
}
|
|
13925
|
+
async function withDesktopInstallLock(paths, fn, options = {}) {
|
|
13926
|
+
const lockPath = resolveDesktopInstallLockPath(paths);
|
|
13927
|
+
const lockDir = path21.dirname(lockPath);
|
|
13928
|
+
const timeoutMs = options.timeoutMs ?? DESKTOP_INSTALL_LOCK_TIMEOUT_MS;
|
|
13929
|
+
const pollMs = options.pollMs ?? DESKTOP_INSTALL_LOCK_POLL_MS;
|
|
13930
|
+
const startedAt = Date.now();
|
|
13931
|
+
const payload = {
|
|
13932
|
+
lockId: randomUUID(),
|
|
13933
|
+
pid: process.pid,
|
|
13934
|
+
installRoot: path21.resolve(paths.installRoot),
|
|
13935
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13936
|
+
};
|
|
13937
|
+
await mkdir3(lockDir, { recursive: true });
|
|
13938
|
+
while (true) {
|
|
13939
|
+
try {
|
|
13940
|
+
await writeFile3(lockPath, `${JSON.stringify(payload, null, 2)}
|
|
13941
|
+
`, { encoding: "utf8", flag: "wx" });
|
|
13942
|
+
break;
|
|
13943
|
+
} catch (error) {
|
|
13944
|
+
const err = error;
|
|
13945
|
+
if (err.code !== "EEXIST") throw error;
|
|
13946
|
+
const existing = await readDesktopInstallLock(lockPath);
|
|
13947
|
+
const stale = !existing || !processExists(existing.pid);
|
|
13948
|
+
if (stale) {
|
|
13949
|
+
await rm2(lockPath, { force: true });
|
|
13950
|
+
continue;
|
|
13951
|
+
}
|
|
13952
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
13953
|
+
throw new Error(
|
|
13954
|
+
`Timed out waiting for Rudder Desktop install lock for ${paths.appPath}. Held by pid ${existing.pid} for ${existing.installRoot}.`
|
|
13955
|
+
);
|
|
13956
|
+
}
|
|
13957
|
+
await delay2(pollMs);
|
|
13958
|
+
}
|
|
13959
|
+
}
|
|
13960
|
+
try {
|
|
13961
|
+
return await fn();
|
|
13962
|
+
} finally {
|
|
13963
|
+
const existing = await readDesktopInstallLock(lockPath);
|
|
13964
|
+
if (existing?.lockId === payload.lockId) {
|
|
13965
|
+
await rm2(lockPath, { force: true });
|
|
13966
|
+
}
|
|
13967
|
+
}
|
|
13968
|
+
}
|
|
13817
13969
|
function runChecked(command, args, options = {}) {
|
|
13818
13970
|
const result = spawnSync3(command, args, {
|
|
13819
13971
|
encoding: "utf8",
|
|
@@ -14266,152 +14418,154 @@ async function startCommand(opts) {
|
|
|
14266
14418
|
p15.outro(pc15.green("Dry run complete."));
|
|
14267
14419
|
return;
|
|
14268
14420
|
}
|
|
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;
|
|
14421
|
+
await withDesktopInstallLock(installPaths, async () => {
|
|
14422
|
+
const directReleaseVersion = resolveDesktopReleaseVersion(tag);
|
|
14423
|
+
const progressFactory = desktopProgressJson ? createDesktopProgressFactory() : createByteProgress;
|
|
14424
|
+
let release = null;
|
|
14326
14425
|
try {
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14426
|
+
release = await runStartPhase(
|
|
14427
|
+
"Resolving Desktop release...",
|
|
14428
|
+
"Desktop release resolved.",
|
|
14429
|
+
() => fetchGithubRelease(repo, tag),
|
|
14430
|
+
desktopProgressJson ? "resolving_release" : null
|
|
14431
|
+
);
|
|
14331
14432
|
} catch (error) {
|
|
14332
|
-
|
|
14333
|
-
if (selectedAssetKind !== "shell" || !fullCandidate) throw error;
|
|
14433
|
+
if (!directReleaseVersion) throw error;
|
|
14334
14434
|
p15.log.warn(
|
|
14335
|
-
`
|
|
14435
|
+
`Desktop release metadata could not be resolved; falling back to deterministic download URLs. ${formatFetchError(error)}`
|
|
14336
14436
|
);
|
|
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
14437
|
}
|
|
14345
|
-
|
|
14346
|
-
|
|
14347
|
-
|
|
14438
|
+
const releaseTag = release?.tag_name ?? (directReleaseVersion ? tag : null);
|
|
14439
|
+
if (!releaseTag) {
|
|
14440
|
+
throw new Error(`Unable to resolve Rudder Desktop release tag for ${repo}@${tag}.`);
|
|
14441
|
+
}
|
|
14442
|
+
const assetCandidates = resolveDesktopAssetCandidates({
|
|
14443
|
+
releaseAssets: release?.assets ?? [],
|
|
14444
|
+
target,
|
|
14445
|
+
repo,
|
|
14446
|
+
tag,
|
|
14447
|
+
directReleaseVersion,
|
|
14448
|
+
allowShellAssets: runtimeSupportsShellAssets
|
|
14449
|
+
});
|
|
14450
|
+
if (assetCandidates.length === 0) {
|
|
14451
|
+
throw new Error(`No Rudder Desktop portable asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14452
|
+
}
|
|
14453
|
+
const checksumAsset = selectChecksumAsset(release?.assets ?? []) ?? (directReleaseVersion ? buildGithubReleaseAsset(repo, tag, DESKTOP_CHECKSUM_ASSET_NAME) : null);
|
|
14454
|
+
const checksums = await downloadChecksums(checksumAsset, outputDir, progressFactory);
|
|
14455
|
+
let selectedCandidate;
|
|
14456
|
+
try {
|
|
14457
|
+
selectedCandidate = selectChecksummedDesktopAssetCandidate(assetCandidates, checksums);
|
|
14458
|
+
} catch (error) {
|
|
14459
|
+
throw new Error(`No checksummed Rudder Desktop asset found for ${target.platform}/${target.arch} in ${repo}@${releaseTag}.`);
|
|
14460
|
+
}
|
|
14461
|
+
for (const warning of selectedCandidate.warnings) p15.log.warn(warning);
|
|
14462
|
+
let selectedAsset = selectedCandidate.asset;
|
|
14463
|
+
let selectedAssetKind = selectedCandidate.kind;
|
|
14464
|
+
let expectedChecksum = selectedCandidate.expectedChecksum;
|
|
14465
|
+
const metadata = await readInstallMetadata(installPaths.metadataPath);
|
|
14466
|
+
if (isInstalledDesktopCurrent(metadata, releaseTag, selectedAsset.name, expectedChecksum) && await pathExists2(installPaths.executablePath)) {
|
|
14467
|
+
p15.log.success(`Rudder Desktop is already installed at ${pc15.cyan(installPaths.appPath)}.`);
|
|
14468
|
+
await runStartPhase(
|
|
14469
|
+
"Refreshing Desktop launchers...",
|
|
14470
|
+
"Desktop launchers ready.",
|
|
14471
|
+
async () => {
|
|
14472
|
+
await removeMacQuarantine(installPaths, target);
|
|
14473
|
+
await createPlatformLaunchers(installPaths, target);
|
|
14474
|
+
},
|
|
14475
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14476
|
+
);
|
|
14477
|
+
} else {
|
|
14478
|
+
let cachedAsset;
|
|
14479
|
+
try {
|
|
14480
|
+
cachedAsset = await downloadDesktopAssetWithCache(selectedAsset, expectedChecksum, {
|
|
14481
|
+
outputDir,
|
|
14482
|
+
progressFactory
|
|
14483
|
+
});
|
|
14484
|
+
} catch (error) {
|
|
14485
|
+
const fullCandidate = assetCandidates.find((candidate) => candidate.kind === "full");
|
|
14486
|
+
if (selectedAssetKind !== "shell" || !fullCandidate) throw error;
|
|
14487
|
+
p15.log.warn(
|
|
14488
|
+
`Layered Desktop shell asset download failed; falling back to the full portable asset. ${formatFetchError(error)}`
|
|
14489
|
+
);
|
|
14490
|
+
selectedAsset = fullCandidate.asset;
|
|
14491
|
+
selectedAssetKind = fullCandidate.kind;
|
|
14492
|
+
expectedChecksum = resolveAssetChecksum(checksums, selectedAsset.name);
|
|
14493
|
+
cachedAsset = await downloadDesktopAssetWithCache(selectedAsset, expectedChecksum, {
|
|
14494
|
+
outputDir,
|
|
14495
|
+
progressFactory
|
|
14496
|
+
});
|
|
14497
|
+
}
|
|
14498
|
+
if (cachedAsset.cacheStatus === "hit") {
|
|
14499
|
+
p15.log.success(`Desktop asset cache hit at ${pc15.cyan(cachedAsset.path)}.`);
|
|
14500
|
+
if (desktopProgressJson) {
|
|
14501
|
+
writeDesktopProgress({
|
|
14502
|
+
phase: "downloading_asset",
|
|
14503
|
+
message: `Desktop asset cache hit for ${selectedAsset.name}.`,
|
|
14504
|
+
percent: 100
|
|
14505
|
+
});
|
|
14506
|
+
}
|
|
14507
|
+
}
|
|
14508
|
+
const checksum = await runStartPhase(
|
|
14509
|
+
"Verifying Desktop checksum...",
|
|
14510
|
+
`Verified ${pc15.cyan(path21.basename(cachedAsset.path))}.`,
|
|
14511
|
+
() => assertChecksumMatch(cachedAsset.path, expectedChecksum),
|
|
14512
|
+
desktopProgressJson ? "verifying_checksum" : null
|
|
14513
|
+
);
|
|
14514
|
+
if (desktopProgressJson && opts.desktopWaitForApply === true) {
|
|
14348
14515
|
writeDesktopProgress({
|
|
14349
|
-
phase: "
|
|
14350
|
-
message:
|
|
14516
|
+
phase: "ready_to_install",
|
|
14517
|
+
message: "Desktop update is downloaded and verified.",
|
|
14351
14518
|
percent: 100
|
|
14352
14519
|
});
|
|
14520
|
+
await waitForDesktopApplySignal();
|
|
14521
|
+
writeDesktopProgress({
|
|
14522
|
+
phase: "preparing_restart",
|
|
14523
|
+
message: "Applying Desktop update..."
|
|
14524
|
+
});
|
|
14353
14525
|
}
|
|
14526
|
+
await runStartPhase(
|
|
14527
|
+
"Replacing existing Rudder Desktop if needed...",
|
|
14528
|
+
"Existing Desktop install is ready for replacement.",
|
|
14529
|
+
() => prepareForDesktopReplace(installPaths, target, { waitForActiveRuns: opts.waitForActiveRuns === true }),
|
|
14530
|
+
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
14531
|
+
);
|
|
14532
|
+
await runStartPhase(
|
|
14533
|
+
"Installing portable Desktop app...",
|
|
14534
|
+
`Installed Rudder Desktop to ${pc15.cyan(installPaths.appPath)}.`,
|
|
14535
|
+
() => installPortableDesktop(cachedAsset.path, installPaths, target),
|
|
14536
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14537
|
+
);
|
|
14538
|
+
await runStartPhase(
|
|
14539
|
+
"Preparing Desktop launchers...",
|
|
14540
|
+
"Desktop launchers ready.",
|
|
14541
|
+
async () => {
|
|
14542
|
+
await removeMacQuarantine(installPaths, target);
|
|
14543
|
+
await createPlatformLaunchers(installPaths, target);
|
|
14544
|
+
},
|
|
14545
|
+
desktopProgressJson ? "preparing_restart" : null
|
|
14546
|
+
);
|
|
14547
|
+
await writeInstallMetadata(installPaths, releaseTag, selectedAsset.name, checksum, selectedAssetKind);
|
|
14354
14548
|
}
|
|
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)}.`
|
|
14549
|
+
const desktopAssetPrune = await maybePruneDesktopAssetCache({
|
|
14550
|
+
protectedChecksums: [expectedChecksum]
|
|
14551
|
+
});
|
|
14552
|
+
if (desktopAssetPrune) {
|
|
14553
|
+
if (desktopAssetPrune.deleted.length > 0) {
|
|
14554
|
+
p15.log.success(
|
|
14555
|
+
`Pruned ${desktopAssetPrune.deleted.length} old Desktop asset cache(s), freed ${formatBytes(desktopAssetPrune.freedBytes)}.`
|
|
14556
|
+
);
|
|
14557
|
+
}
|
|
14558
|
+
for (const warning of desktopAssetPrune.warnings) p15.log.warn(warning);
|
|
14559
|
+
}
|
|
14560
|
+
if (opts.open !== false) {
|
|
14561
|
+
await runStartPhase(
|
|
14562
|
+
"Launching Rudder Desktop...",
|
|
14563
|
+
"Rudder Desktop launched.",
|
|
14564
|
+
() => launchDesktop(installPaths, target),
|
|
14565
|
+
desktopProgressJson ? "closing" : null
|
|
14403
14566
|
);
|
|
14404
14567
|
}
|
|
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
|
-
}
|
|
14568
|
+
});
|
|
14415
14569
|
}
|
|
14416
14570
|
p15.outro(pc15.green("Rudder start complete."));
|
|
14417
14571
|
}
|
|
@@ -14511,6 +14665,7 @@ function createProgram() {
|
|
|
14511
14665
|
registerAgentCommands(program);
|
|
14512
14666
|
registerApprovalCommands(program);
|
|
14513
14667
|
registerActivityCommands(program);
|
|
14668
|
+
registerUserCommands(program);
|
|
14514
14669
|
registerDashboardCommands(program);
|
|
14515
14670
|
registerSkillCommands(program);
|
|
14516
14671
|
registerLibraryCommands(program);
|