@rudderhq/cli 0.3.6-canary.0 → 0.3.6-canary.10
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 +555 -76
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -572,6 +572,13 @@ var init_constants = __esm({
|
|
|
572
572
|
}
|
|
573
573
|
});
|
|
574
574
|
|
|
575
|
+
// ../packages/shared/dist/agent-run.js
|
|
576
|
+
var init_agent_run = __esm({
|
|
577
|
+
"../packages/shared/dist/agent-run.js"() {
|
|
578
|
+
"use strict";
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
|
|
575
582
|
// ../packages/shared/dist/types/observability.js
|
|
576
583
|
var init_observability = __esm({
|
|
577
584
|
"../packages/shared/dist/types/observability.js"() {
|
|
@@ -784,7 +791,7 @@ var init_adapter_skills = __esm({
|
|
|
784
791
|
|
|
785
792
|
// ../packages/shared/dist/validators/chat.js
|
|
786
793
|
import { z as z4 } from "zod";
|
|
787
|
-
var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, addChatMessageSchema, chatRichReferenceDisplaySchema, chatIssueIdentifierSchema, chatAskUserIdentifierSchema, chatAskUserOptionSchema, chatAskUserQuestionSchema, chatAskUserRequestSchema, chatIssueRichReferenceSchema, chatIssueCommentRichReferenceSchema, chatRichReferenceSchema, chatRichReferencesSchema, chatAutomationCreateSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema, updateMessengerThreadUserStateSchema, createMessengerCustomGroupSchema, updateMessengerCustomGroupSchema, reorderMessengerCustomGroupsSchema, assignMessengerCustomGroupEntrySchema, reorderMessengerCustomGroupEntriesSchema;
|
|
794
|
+
var chatConversationStatusSchema, chatIssueCreationModeSchema, chatMessageRoleSchema, chatMessageKindSchema, chatMessageStatusSchema, chatContextEntityTypeSchema, createChatContextLinkSchema, createChatConversationSchema, setChatProjectContextSchema, updateChatConversationSchema, addChatMessageSchema, chatRichReferenceDisplaySchema, chatIssueIdentifierSchema, chatAskUserIdentifierSchema, chatAskUserOptionSchema, chatAskUserQuestionSchema, chatAskUserRequestSchema, chatIssueRichReferenceSchema, chatIssueCommentRichReferenceSchema, chatRichReferenceSchema, chatRichReferencesSchema, chatAutomationCreateSchema, createChatAttachmentMetadataSchema, chatIssueProposalSchema, convertChatToIssueSchema, chatOperationProposalSchema, resolveChatOperationProposalSchema, updateChatConversationUserStateSchema, updateMessengerThreadUserStateSchema, createMessengerCustomGroupSchema, createMessengerCustomGroupWithEntriesSchema, updateMessengerCustomGroupSchema, reorderMessengerCustomGroupsSchema, assignMessengerCustomGroupEntrySchema, reorderMessengerCustomGroupEntriesSchema;
|
|
788
795
|
var init_chat = __esm({
|
|
789
796
|
"../packages/shared/dist/validators/chat.js"() {
|
|
790
797
|
"use strict";
|
|
@@ -971,6 +978,9 @@ var init_chat = __esm({
|
|
|
971
978
|
name: z4.string().trim().min(1).max(80),
|
|
972
979
|
icon: z4.string().trim().min(1).max(24).optional().nullable()
|
|
973
980
|
});
|
|
981
|
+
createMessengerCustomGroupWithEntriesSchema = createMessengerCustomGroupSchema.extend({
|
|
982
|
+
threadKeys: z4.array(z4.string().trim().min(1).max(240)).min(1).max(50)
|
|
983
|
+
});
|
|
974
984
|
updateMessengerCustomGroupSchema = z4.object({
|
|
975
985
|
name: z4.string().trim().min(1).max(80).optional(),
|
|
976
986
|
icon: z4.string().trim().min(1).max(24).optional().nullable(),
|
|
@@ -1768,7 +1778,7 @@ var init_agent = __esm({
|
|
|
1768
1778
|
|
|
1769
1779
|
// ../packages/shared/dist/validators/agent-integration.js
|
|
1770
1780
|
import { z as z13 } from "zod";
|
|
1771
|
-
var agentIntegrationProviderSchema, agentIntegrationStatusSchema, agentIntegrationTransportSchema, agentIntegrationProviderRegionSchema, agentIntegrationChatTypeSchema, agentIntegrationDropReasonSchema, agentIntegrationOutboundStatusSchema, createAgentIntegrationSchema;
|
|
1781
|
+
var agentIntegrationProviderSchema, agentIntegrationStatusSchema, agentIntegrationTransportSchema, agentIntegrationProviderRegionSchema, agentIntegrationChatTypeSchema, agentIntegrationDropReasonSchema, agentIntegrationOutboundStatusSchema, createAgentIntegrationSchema, connectAgentIntegrationSchema, feishuEventHeaderSchema, feishuSenderIdSchema, feishuMessageMentionSchema, feishuMessageSchema, feishuEventSchema, mockFeishuInboundEventSchema;
|
|
1772
1782
|
var init_agent_integration = __esm({
|
|
1773
1783
|
"../packages/shared/dist/validators/agent-integration.js"() {
|
|
1774
1784
|
"use strict";
|
|
@@ -1792,6 +1802,59 @@ var init_agent_integration = __esm({
|
|
|
1792
1802
|
installerUserId: z13.string().min(1).optional().nullable(),
|
|
1793
1803
|
manageUrl: z13.string().url().optional().nullable()
|
|
1794
1804
|
});
|
|
1805
|
+
connectAgentIntegrationSchema = createAgentIntegrationSchema.omit({ agentId: true });
|
|
1806
|
+
feishuEventHeaderSchema = z13.object({
|
|
1807
|
+
event_id: z13.string().min(1).optional(),
|
|
1808
|
+
app_id: z13.string().min(1).optional(),
|
|
1809
|
+
token: z13.string().min(1).optional(),
|
|
1810
|
+
create_time: z13.string().min(1).optional()
|
|
1811
|
+
}).passthrough();
|
|
1812
|
+
feishuSenderIdSchema = z13.object({
|
|
1813
|
+
open_id: z13.string().min(1).optional(),
|
|
1814
|
+
union_id: z13.string().min(1).optional()
|
|
1815
|
+
}).passthrough();
|
|
1816
|
+
feishuMessageMentionSchema = z13.object({
|
|
1817
|
+
key: z13.string().optional(),
|
|
1818
|
+
id: feishuSenderIdSchema.optional()
|
|
1819
|
+
}).passthrough();
|
|
1820
|
+
feishuMessageSchema = z13.object({
|
|
1821
|
+
message_id: z13.string().min(1).optional(),
|
|
1822
|
+
chat_id: z13.string().min(1).optional(),
|
|
1823
|
+
chat_type: agentIntegrationChatTypeSchema.optional(),
|
|
1824
|
+
message_type: z13.string().min(1).optional(),
|
|
1825
|
+
content: z13.string().optional(),
|
|
1826
|
+
mentions: z13.array(feishuMessageMentionSchema).optional(),
|
|
1827
|
+
parent_id: z13.string().min(1).optional().nullable()
|
|
1828
|
+
}).passthrough();
|
|
1829
|
+
feishuEventSchema = z13.object({
|
|
1830
|
+
sender: z13.object({
|
|
1831
|
+
sender_id: feishuSenderIdSchema.optional()
|
|
1832
|
+
}).passthrough().optional(),
|
|
1833
|
+
message: feishuMessageSchema.optional()
|
|
1834
|
+
}).passthrough();
|
|
1835
|
+
mockFeishuInboundEventSchema = z13.object({
|
|
1836
|
+
type: z13.string().min(1).optional(),
|
|
1837
|
+
token: z13.string().min(1).optional(),
|
|
1838
|
+
challenge: z13.string().min(1).optional(),
|
|
1839
|
+
mockVerificationToken: z13.string().min(1).optional(),
|
|
1840
|
+
mockEncryptKey: z13.string().min(1).optional(),
|
|
1841
|
+
eventId: z13.string().min(1).optional(),
|
|
1842
|
+
appId: z13.string().min(1).optional(),
|
|
1843
|
+
botOpenId: z13.string().min(1).optional().nullable(),
|
|
1844
|
+
chatId: z13.string().min(1).optional(),
|
|
1845
|
+
chatType: agentIntegrationChatTypeSchema.optional(),
|
|
1846
|
+
messageId: z13.string().min(1).optional(),
|
|
1847
|
+
senderOpenId: z13.string().min(1).optional(),
|
|
1848
|
+
senderUnionId: z13.string().min(1).optional().nullable(),
|
|
1849
|
+
body: z13.string().optional(),
|
|
1850
|
+
commandBody: z13.string().optional(),
|
|
1851
|
+
addressedToBot: z13.boolean().optional(),
|
|
1852
|
+
messageType: z13.string().min(1).optional(),
|
|
1853
|
+
parentMessageId: z13.string().min(1).optional().nullable(),
|
|
1854
|
+
receivedAt: z13.string().datetime().optional(),
|
|
1855
|
+
header: feishuEventHeaderSchema.optional(),
|
|
1856
|
+
event: feishuEventSchema.optional()
|
|
1857
|
+
}).passthrough();
|
|
1795
1858
|
}
|
|
1796
1859
|
});
|
|
1797
1860
|
|
|
@@ -2929,6 +2992,7 @@ var init_api = __esm({
|
|
|
2929
2992
|
secrets: `${API_PREFIX}/secrets`,
|
|
2930
2993
|
costs: `${API_PREFIX}/costs`,
|
|
2931
2994
|
activity: `${API_PREFIX}/activity`,
|
|
2995
|
+
agentRuns: `${API_PREFIX}/agent-runs`,
|
|
2932
2996
|
dashboard: `${API_PREFIX}/dashboard`,
|
|
2933
2997
|
sidebarBadges: `${API_PREFIX}/sidebar-badges`,
|
|
2934
2998
|
invites: `${API_PREFIX}/invites`,
|
|
@@ -2987,6 +3051,19 @@ var init_project_url_key = __esm({
|
|
|
2987
3051
|
}
|
|
2988
3052
|
});
|
|
2989
3053
|
|
|
3054
|
+
// ../packages/shared/dist/short-refs.js
|
|
3055
|
+
var SHORT_REF_PREFIX_BY_KIND, SHORT_REF_KIND_BY_PREFIX;
|
|
3056
|
+
var init_short_refs = __esm({
|
|
3057
|
+
"../packages/shared/dist/short-refs.js"() {
|
|
3058
|
+
"use strict";
|
|
3059
|
+
SHORT_REF_PREFIX_BY_KIND = {
|
|
3060
|
+
agent: "agt",
|
|
3061
|
+
issue_comment: "cmt"
|
|
3062
|
+
};
|
|
3063
|
+
SHORT_REF_KIND_BY_PREFIX = Object.fromEntries(Object.entries(SHORT_REF_PREFIX_BY_KIND).map(([kind, prefix]) => [prefix, kind]));
|
|
3064
|
+
}
|
|
3065
|
+
});
|
|
3066
|
+
|
|
2990
3067
|
// ../packages/shared/dist/token-usage.js
|
|
2991
3068
|
var init_token_usage = __esm({
|
|
2992
3069
|
"../packages/shared/dist/token-usage.js"() {
|
|
@@ -3191,6 +3268,7 @@ var init_dist = __esm({
|
|
|
3191
3268
|
"../packages/shared/dist/index.js"() {
|
|
3192
3269
|
"use strict";
|
|
3193
3270
|
init_constants();
|
|
3271
|
+
init_agent_run();
|
|
3194
3272
|
init_observability();
|
|
3195
3273
|
init_workspace_backup();
|
|
3196
3274
|
init_validators();
|
|
@@ -3202,6 +3280,7 @@ var init_dist = __esm({
|
|
|
3202
3280
|
init_organization_url_key();
|
|
3203
3281
|
init_project_mentions();
|
|
3204
3282
|
init_project_url_key();
|
|
3283
|
+
init_short_refs();
|
|
3205
3284
|
init_token_usage();
|
|
3206
3285
|
init_issue_activity();
|
|
3207
3286
|
init_config_schema();
|
|
@@ -6966,7 +7045,7 @@ function printOutput(data, opts = {}) {
|
|
|
6966
7045
|
}
|
|
6967
7046
|
function formatInlineRecord(record, opts = {}) {
|
|
6968
7047
|
const displayRecord = shouldShowFullIds(opts.fullIds) ? record : toCliShortIdOutput(record);
|
|
6969
|
-
const keyOrder = ["identifier", "id", "name", "status", "priority", "title", "action"];
|
|
7048
|
+
const keyOrder = ["identifier", "shortRef", "id", "name", "status", "priority", "title", "action"];
|
|
6970
7049
|
const seen = /* @__PURE__ */ new Set();
|
|
6971
7050
|
const parts = [];
|
|
6972
7051
|
for (const key of keyOrder) {
|
|
@@ -7237,6 +7316,7 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
7237
7316
|
"",
|
|
7238
7317
|
"- Issues: use `[](issue://<issue-id>)`; include `?c=<comment-id>` when linking to a specific comment.",
|
|
7239
7318
|
"- 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.",
|
|
7319
|
+
"- Automations: use `[](automation://<automation-id>)` when citing a Rudder automation.",
|
|
7240
7320
|
"- Projects: use `[](project://<project-id>)` when citing a Rudder project.",
|
|
7241
7321
|
"- Chat threads: use `[](chat://<conversation-id>)` when citing a Rudder chat conversation.",
|
|
7242
7322
|
"- 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.",
|
|
@@ -7252,7 +7332,7 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
7252
7332
|
"",
|
|
7253
7333
|
"You MUST use the `para-memory-files` skill for all memory operations: storing facts, writing daily notes, creating entities, running weekly synthesis, recalling past context, and managing shared work notes. The skill defines your three-layer memory system (knowledge graph, daily notes, tacit knowledge), the PARA folder structure, atomic fact schemas, memory decay rules, and recall conventions.",
|
|
7254
7334
|
"",
|
|
7255
|
-
"Keep stable preferences and operating lessons in `$AGENT_HOME/instructions/MEMORY.md`. Use `$AGENT_HOME/memory/YYYY-MM-DD.md` for daily notes and `$AGENT_HOME/life/` for structured long-term memory;
|
|
7335
|
+
"Keep stable preferences and operating lessons in `$AGENT_HOME/instructions/MEMORY.md`. Use `$AGENT_HOME/memory/YYYY-MM-DD.md` for daily notes and `$AGENT_HOME/life/` for structured long-term memory. Rudder injects bounded today/yesterday daily-memory excerpts in the startup context bundle; open the files directly when you need full detail.",
|
|
7256
7336
|
"",
|
|
7257
7337
|
"Invoke it whenever you need to remember, retrieve, or organize anything.",
|
|
7258
7338
|
"",
|
|
@@ -7269,19 +7349,25 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
|
7269
7349
|
var RUDDER_AGENT_HEARTBEAT_INSTRUCTION = [
|
|
7270
7350
|
"# Rudder Heartbeat Instruction",
|
|
7271
7351
|
"",
|
|
7272
|
-
"This section is injected by Rudder for heartbeat scene runs. It is the platform-owned timed-wakeup pipeline
|
|
7352
|
+
"This section is injected by Rudder for heartbeat scene runs. It is the platform-owned timed-wakeup pipeline.",
|
|
7273
7353
|
"",
|
|
7274
7354
|
"## Heartbeat Pipeline",
|
|
7275
7355
|
"",
|
|
7276
7356
|
"1. Identify yourself and inspect wake context, including `RUDDER_TASK_ID`, `RUDDER_WAKE_REASON`, `RUDDER_WAKE_COMMENT_ID`, and `RUDDER_APPROVAL_ID` when present.",
|
|
7277
|
-
"2.
|
|
7278
|
-
"
|
|
7279
|
-
"
|
|
7280
|
-
"
|
|
7281
|
-
"
|
|
7282
|
-
"
|
|
7283
|
-
"
|
|
7284
|
-
"
|
|
7357
|
+
"2. Local Planning Check:",
|
|
7358
|
+
" ",
|
|
7359
|
+
" 1. Read today's plan from `$AGENT_HOME/memory/YYYY-MM-DD.md` under \"## Today's Plan\". You need to clearly know your work plan for today, and work according to the plan.",
|
|
7360
|
+
" 2. Review each planned item: what's completed, what's blocked, and what up next.",
|
|
7361
|
+
" 3. Record progress updates in the daily notes.",
|
|
7362
|
+
" ",
|
|
7363
|
+
"3.Then handle approval follow-up: read the approval and linked issues, then close resolved work or comment on what remains.",
|
|
7364
|
+
"4. Inspect your Rudder inbox. Prioritize reviewer rows in `in_review` or `blocked`, then assignee `in_progress`, then assignee `todo`. Do not look for unassigned work.",
|
|
7365
|
+
"5. 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.",
|
|
7366
|
+
"6. Checkout before doing assignee task work. A `409` means another agent owns the task; do not retry it.",
|
|
7367
|
+
"7. Load compact issue context, do one bounded useful chunk, and preserve evidence.",
|
|
7368
|
+
"8. Before exiting active work, leave exactly one durable signal: progress, done, blocked, explicit handoff, or structured review decision.",
|
|
7369
|
+
"9. Treat passive follow-up as close-out governance, not a fresh assignment.",
|
|
7370
|
+
"10. Treat review close-out follow-up as review governance; free-form accept/reject text is not a durable decision.",
|
|
7285
7371
|
"",
|
|
7286
7372
|
"Use the Rudder control-plane interface available in this runtime. CLI-capable runtimes should use the bundled `rudder` skill for command details, Library handoff rules, organization-skill workflow, and control-plane best practices. HTTP compatibility runtimes should follow the explicit HTTP workflow in their wake text; that workflow overrides CLI command guidance."
|
|
7287
7373
|
].join("\n");
|
|
@@ -7390,9 +7476,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
7390
7476
|
},
|
|
7391
7477
|
{
|
|
7392
7478
|
id: "agent.get",
|
|
7393
|
-
command: "rudder agent get <agent-id-or-shortname>",
|
|
7479
|
+
command: "rudder agent get <agent-id-or-shortname-or-agt-ref>",
|
|
7394
7480
|
category: "agent",
|
|
7395
|
-
description: "Read one agent by id or
|
|
7481
|
+
description: "Read one agent by id, shortname, or agt_<uuid-prefix> short ref.",
|
|
7396
7482
|
mutating: false,
|
|
7397
7483
|
contract: "compat",
|
|
7398
7484
|
requiresOrgId: false,
|
|
@@ -7546,9 +7632,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
7546
7632
|
},
|
|
7547
7633
|
{
|
|
7548
7634
|
id: "issue.context",
|
|
7549
|
-
command: "rudder issue context <issue>",
|
|
7635
|
+
command: "rudder issue context <issue> [--wake-comment-id <comment-id-or-cmt-ref>]",
|
|
7550
7636
|
category: "issue",
|
|
7551
|
-
description: "Read the compact heartbeat context for an issue
|
|
7637
|
+
description: "Read the compact heartbeat context for an issue; wake comments may be addressed by full id or cmt_<uuid-prefix>.",
|
|
7552
7638
|
mutating: false,
|
|
7553
7639
|
contract: "agent-v1",
|
|
7554
7640
|
requiresOrgId: false,
|
|
@@ -7582,9 +7668,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
7582
7668
|
},
|
|
7583
7669
|
{
|
|
7584
7670
|
id: "issue.comments.list",
|
|
7585
|
-
command: "rudder issue comments list <issue>",
|
|
7671
|
+
command: "rudder issue comments list <issue> [--after <comment-id-or-cmt-ref>]",
|
|
7586
7672
|
category: "issue",
|
|
7587
|
-
description: "List issue comments, optionally only newer comments after a
|
|
7673
|
+
description: "List issue comments, optionally only newer comments after a full comment id or cmt_<uuid-prefix> with --after.",
|
|
7588
7674
|
mutating: false,
|
|
7589
7675
|
contract: "agent-v1",
|
|
7590
7676
|
requiresOrgId: false,
|
|
@@ -7594,9 +7680,9 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
7594
7680
|
},
|
|
7595
7681
|
{
|
|
7596
7682
|
id: "issue.comments.get",
|
|
7597
|
-
command: "rudder issue comments get <issue> <comment-id>",
|
|
7683
|
+
command: "rudder issue comments get <issue> <comment-id-or-cmt-ref>",
|
|
7598
7684
|
category: "issue",
|
|
7599
|
-
description: "Read one issue comment by id.",
|
|
7685
|
+
description: "Read one issue comment by full id or cmt_<uuid-prefix> scoped to the issue.",
|
|
7600
7686
|
mutating: false,
|
|
7601
7687
|
contract: "agent-v1",
|
|
7602
7688
|
requiresOrgId: false,
|
|
@@ -8373,6 +8459,26 @@ function formatAgentCliCapabilitiesHumanReadable(capabilities = getAgentCliCapab
|
|
|
8373
8459
|
return lines.join("\n").trimEnd();
|
|
8374
8460
|
}
|
|
8375
8461
|
|
|
8462
|
+
// src/commands/client/help.ts
|
|
8463
|
+
function formatExamplesAndCautions(notes) {
|
|
8464
|
+
const sections = [];
|
|
8465
|
+
if (notes.examples?.length) {
|
|
8466
|
+
sections.push(["Examples:", ...notes.examples.map(formatHelpExample)].join("\n"));
|
|
8467
|
+
}
|
|
8468
|
+
if (notes.cautions?.length) {
|
|
8469
|
+
sections.push(["Cautions:", ...notes.cautions.map((caution) => ` - ${caution}`)].join("\n"));
|
|
8470
|
+
}
|
|
8471
|
+
return sections.length > 0 ? `
|
|
8472
|
+
${sections.join("\n\n")}` : "";
|
|
8473
|
+
}
|
|
8474
|
+
function formatHelpExample(example) {
|
|
8475
|
+
if (typeof example === "string") {
|
|
8476
|
+
return ` ${example}`;
|
|
8477
|
+
}
|
|
8478
|
+
return ` ${example.description}
|
|
8479
|
+
${example.command}`;
|
|
8480
|
+
}
|
|
8481
|
+
|
|
8376
8482
|
// src/commands/client/agent.ts
|
|
8377
8483
|
var __moduleDir = path10.dirname(fileURLToPath3(import.meta.url));
|
|
8378
8484
|
function codexSkillsHome() {
|
|
@@ -8537,6 +8643,7 @@ function registerAgentCommands(program) {
|
|
|
8537
8643
|
for (const row of rows) {
|
|
8538
8644
|
console.log(
|
|
8539
8645
|
formatInlineRecord({
|
|
8646
|
+
shortRef: row.shortRef,
|
|
8540
8647
|
id: row.id,
|
|
8541
8648
|
name: row.name,
|
|
8542
8649
|
role: row.role,
|
|
@@ -8689,7 +8796,22 @@ function registerAgentCommands(program) {
|
|
|
8689
8796
|
})
|
|
8690
8797
|
);
|
|
8691
8798
|
addCommonClientOptions(
|
|
8692
|
-
skills.command("enable").description(getAgentCliCapabilityById("agent.skills.enable").description).argument("<agentId>", "Agent ID").argument("<selectionRefs...>", "Skill selection refs to enable").
|
|
8799
|
+
skills.command("enable").description(getAgentCliCapabilityById("agent.skills.enable").description).argument("<agentId>", "Agent ID").argument("<selectionRefs...>", "Skill selection refs to enable").addHelpText("after", formatExamplesAndCautions({
|
|
8800
|
+
examples: [
|
|
8801
|
+
{
|
|
8802
|
+
description: "Add skills while preserving the agent's existing enabled set:",
|
|
8803
|
+
command: "rudder agent skills enable <agent-id> rudder/rudder local/abc123/custom-skill"
|
|
8804
|
+
},
|
|
8805
|
+
{
|
|
8806
|
+
description: "Enable one newly created private skill and inspect the resulting snapshot:",
|
|
8807
|
+
command: "rudder agent skills enable <agent-id> <selection-ref> --json"
|
|
8808
|
+
}
|
|
8809
|
+
],
|
|
8810
|
+
cautions: [
|
|
8811
|
+
"This is additive and preserves existing enabled optional skills.",
|
|
8812
|
+
"After creating or copying a private skill, enable it before claiming future runs will load it."
|
|
8813
|
+
]
|
|
8814
|
+
})).action(async (agentId, selectionRefs, opts) => {
|
|
8693
8815
|
try {
|
|
8694
8816
|
const ctx = resolveCommandContext(opts);
|
|
8695
8817
|
const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/enable`, {
|
|
@@ -8705,7 +8827,22 @@ function registerAgentCommands(program) {
|
|
|
8705
8827
|
skills.command("sync").description(getAgentCliCapabilityById("agent.skills.sync").description).argument("<agentId>", "Agent ID").requiredOption(
|
|
8706
8828
|
"--desired-skills <csv>",
|
|
8707
8829
|
"Comma-separated desired skill refs (for example rudder/rudder)"
|
|
8708
|
-
).
|
|
8830
|
+
).addHelpText("after", formatExamplesAndCautions({
|
|
8831
|
+
examples: [
|
|
8832
|
+
{
|
|
8833
|
+
description: "Replace the optional enabled set with an explicitly preserved CSV:",
|
|
8834
|
+
command: 'rudder agent skills sync <agent-id> --desired-skills "rudder/rudder,local/abc123/custom-skill"'
|
|
8835
|
+
},
|
|
8836
|
+
{
|
|
8837
|
+
description: "Clear optional skills only when that is the intended final state:",
|
|
8838
|
+
command: 'rudder agent skills sync <agent-id> --desired-skills "" --json'
|
|
8839
|
+
}
|
|
8840
|
+
],
|
|
8841
|
+
cautions: [
|
|
8842
|
+
"Sync replaces the full optional enabled-skill set; use enable for additive changes.",
|
|
8843
|
+
"Preserve every existing desired skill in the CSV unless you intentionally want to disable it."
|
|
8844
|
+
]
|
|
8845
|
+
})).action(async (agentId, opts) => {
|
|
8709
8846
|
try {
|
|
8710
8847
|
const ctx = resolveCommandContext(opts);
|
|
8711
8848
|
const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/sync`, {
|
|
@@ -8994,7 +9131,22 @@ function registerApprovalCommands(program) {
|
|
|
8994
9131
|
{ includeCompany: false }
|
|
8995
9132
|
);
|
|
8996
9133
|
addCommonClientOptions(
|
|
8997
|
-
approval.command("approve").description("Approve an approval request").argument("<approvalId>", "Approval ID").option("--decision-note <text>", "Decision note").option("--decided-by-user-id <id>", "Decision actor user ID").
|
|
9134
|
+
approval.command("approve").description("Approve an approval request").argument("<approvalId>", "Approval ID").option("--decision-note <text>", "Decision note").option("--decided-by-user-id <id>", "Decision actor user ID").addHelpText("after", formatExamplesAndCautions({
|
|
9135
|
+
examples: [
|
|
9136
|
+
{
|
|
9137
|
+
description: "Read the approval payload before deciding:",
|
|
9138
|
+
command: "rudder approval get <approval-id> --json"
|
|
9139
|
+
},
|
|
9140
|
+
{
|
|
9141
|
+
description: "Record the durable approval decision with concise context:",
|
|
9142
|
+
command: 'rudder approval approve <approval-id> --decision-note "Approved after reviewing linked issues" --json'
|
|
9143
|
+
}
|
|
9144
|
+
],
|
|
9145
|
+
cautions: [
|
|
9146
|
+
"Read the approval and linked issues before approving; this is a governed mutation.",
|
|
9147
|
+
"approval approve/reject use --decision-note, while approval comment uses --body-file."
|
|
9148
|
+
]
|
|
9149
|
+
})).action(async (approvalId, opts) => {
|
|
8998
9150
|
try {
|
|
8999
9151
|
const ctx = resolveCommandContext(opts);
|
|
9000
9152
|
const payload = resolveApprovalSchema.parse({
|
|
@@ -9053,7 +9205,22 @@ function registerApprovalCommands(program) {
|
|
|
9053
9205
|
})
|
|
9054
9206
|
);
|
|
9055
9207
|
addCommonClientOptions(
|
|
9056
|
-
approval.command("comment").description(getAgentCliCapabilityById("approval.comment").description).argument("<approvalId>", "Approval ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").
|
|
9208
|
+
approval.command("comment").description(getAgentCliCapabilityById("approval.comment").description).argument("<approvalId>", "Approval ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").addHelpText("after", formatExamplesAndCautions({
|
|
9209
|
+
examples: [
|
|
9210
|
+
{
|
|
9211
|
+
description: "Add a longer Markdown discussion note without deciding:",
|
|
9212
|
+
command: "rudder approval comment <approval-id> --body-file ./approval-note.md --json"
|
|
9213
|
+
},
|
|
9214
|
+
{
|
|
9215
|
+
description: "Ask a short follow-up from stdin:",
|
|
9216
|
+
command: "printf '%s\\n' 'Need one more linked issue checked.' | rudder approval comment <approval-id> --body-file -"
|
|
9217
|
+
}
|
|
9218
|
+
],
|
|
9219
|
+
cautions: [
|
|
9220
|
+
"Comments do not approve or reject; use approve/reject/request-revision for the durable decision.",
|
|
9221
|
+
"Use --body-file for multiline Markdown. Do not pass decision notes here."
|
|
9222
|
+
]
|
|
9223
|
+
})).action(async (approvalId, opts) => {
|
|
9057
9224
|
try {
|
|
9058
9225
|
const ctx = resolveCommandContext(opts);
|
|
9059
9226
|
const body = await resolveBodyFile(opts.bodyFile);
|
|
@@ -9345,7 +9512,22 @@ function registerAutomationCommands(program) {
|
|
|
9345
9512
|
})
|
|
9346
9513
|
);
|
|
9347
9514
|
addCommonClientOptions(
|
|
9348
|
-
automation.command("run").description(getAgentCliCapabilityById("automation.run").description).argument("<automationId>", "Automation ID").option("--trigger-id <id>", "Trigger ID").option("--payload <json>", "Manual run payload JSON").option("--idempotency-key <key>", "Idempotency key").option("--source <source>", "Run source", "manual").
|
|
9515
|
+
automation.command("run").description(getAgentCliCapabilityById("automation.run").description).argument("<automationId>", "Automation ID").option("--trigger-id <id>", "Trigger ID").option("--payload <json>", "Manual run payload JSON").option("--idempotency-key <key>", "Idempotency key").option("--source <source>", "Run source", "manual").addHelpText("after", formatExamplesAndCautions({
|
|
9516
|
+
examples: [
|
|
9517
|
+
{
|
|
9518
|
+
description: "Run a verified automation manually with an explicit payload:",
|
|
9519
|
+
command: `rudder automation run <automation-id> --payload '{"manual":true}' --json`
|
|
9520
|
+
},
|
|
9521
|
+
{
|
|
9522
|
+
description: "Retry a trigger-specific smoke run with duplicate protection:",
|
|
9523
|
+
command: "rudder automation run <automation-id> --trigger-id <trigger-id> --idempotency-key zst-123-smoke"
|
|
9524
|
+
}
|
|
9525
|
+
],
|
|
9526
|
+
cautions: [
|
|
9527
|
+
"Confirm the automation and trigger target before running; manual runs can create tracked issues or chats.",
|
|
9528
|
+
"Use an idempotency key for retried manual invocations so duplicate work is easier to detect."
|
|
9529
|
+
]
|
|
9530
|
+
})).action(async (automationId, opts) => {
|
|
9349
9531
|
try {
|
|
9350
9532
|
const ctx = resolveCommandContext(opts);
|
|
9351
9533
|
const payload = runAutomationSchema.parse({
|
|
@@ -9535,7 +9717,22 @@ function registerChatCommands(program) {
|
|
|
9535
9717
|
})
|
|
9536
9718
|
);
|
|
9537
9719
|
addCommonClientOptions(
|
|
9538
|
-
chat.command("read").description(getAgentCliCapabilityById("chat.read").description).argument("<chatId>", "Chat conversation ID").option("--include-transcript", "Include assistant transcript entries").option("--include-output", "Alias for --include-transcript").option("--include-outputs", "Alias for --include-transcript").option("--limit <n>", "Maximum recent messages", "20").option("--turn-limit <n>", "Alias for --limit for chat turn snapshots").option("--cursor <cursor>", "Stable message cursor returned in page.nextCursor").option("--max-output-chars <n>", "Maximum transcript output chars for human output", "1200").
|
|
9720
|
+
chat.command("read").description(getAgentCliCapabilityById("chat.read").description).argument("<chatId>", "Chat conversation ID").option("--include-transcript", "Include assistant transcript entries").option("--include-output", "Alias for --include-transcript").option("--include-outputs", "Alias for --include-transcript").option("--limit <n>", "Maximum recent messages", "20").option("--turn-limit <n>", "Alias for --limit for chat turn snapshots").option("--cursor <cursor>", "Stable message cursor returned in page.nextCursor").option("--max-output-chars <n>", "Maximum transcript output chars for human output", "1200").addHelpText("after", formatExamplesAndCautions({
|
|
9721
|
+
examples: [
|
|
9722
|
+
{
|
|
9723
|
+
description: "Read a bounded conversation page with transcript output when needed:",
|
|
9724
|
+
command: "rudder chat read <chat-id> --turn-limit 20 --include-output"
|
|
9725
|
+
},
|
|
9726
|
+
{
|
|
9727
|
+
description: "Continue from a stable cursor in scripts:",
|
|
9728
|
+
command: "rudder chat read <chat-id> --cursor <nextCursor> --json"
|
|
9729
|
+
}
|
|
9730
|
+
],
|
|
9731
|
+
cautions: [
|
|
9732
|
+
"Read bounded pages first; long chats can include large transcript payloads.",
|
|
9733
|
+
"Use --include-output only when transcript output is needed for diagnosis."
|
|
9734
|
+
]
|
|
9735
|
+
})).action(async (chatId, opts) => {
|
|
9539
9736
|
try {
|
|
9540
9737
|
const ctx = resolveCommandContext(opts);
|
|
9541
9738
|
const [conversation, page] = await Promise.all([
|
|
@@ -9583,7 +9780,22 @@ function registerChatCommands(program) {
|
|
|
9583
9780
|
{ includeCompany: false }
|
|
9584
9781
|
);
|
|
9585
9782
|
addCommonClientOptions(
|
|
9586
|
-
chat.command("send").description(getAgentCliCapabilityById("chat.send").description).argument("<chatId>", "Chat conversation ID").option("--body <text>", "Message body").option("--edit-user-message-id <id>", "Regenerate/edit from a prior user message").
|
|
9783
|
+
chat.command("send").description(getAgentCliCapabilityById("chat.send").description).argument("<chatId>", "Chat conversation ID").option("--body <text>", "Message body").option("--edit-user-message-id <id>", "Regenerate/edit from a prior user message").addHelpText("after", formatExamplesAndCautions({
|
|
9784
|
+
examples: [
|
|
9785
|
+
{
|
|
9786
|
+
description: "Append a short agent-authored status note:",
|
|
9787
|
+
command: 'rudder chat send <chat-id> --body "Status: validation is running"'
|
|
9788
|
+
},
|
|
9789
|
+
{
|
|
9790
|
+
description: "Send a longer or multiline note through stdin:",
|
|
9791
|
+
command: "printf '%s\\n' 'Multiline note' | rudder chat send <chat-id>"
|
|
9792
|
+
}
|
|
9793
|
+
],
|
|
9794
|
+
cautions: [
|
|
9795
|
+
"chat send accepts --body or stdin; it does not support --body-file.",
|
|
9796
|
+
"Agent-authenticated sends append an agent-authored message and do not start a new assistant reply."
|
|
9797
|
+
]
|
|
9798
|
+
})).action(async (chatId, opts) => {
|
|
9587
9799
|
try {
|
|
9588
9800
|
const ctx = resolveCommandContext(opts);
|
|
9589
9801
|
const body = opts.body ?? await readStdin();
|
|
@@ -11177,7 +11389,22 @@ function registerIssueCommands(program) {
|
|
|
11177
11389
|
})
|
|
11178
11390
|
);
|
|
11179
11391
|
addCommonClientOptions(
|
|
11180
|
-
issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the comment; may be repeated", collectImagePath, []).option("--reopen", "Reopen if issue is done/cancelled").
|
|
11392
|
+
issue.command("comment").description(getAgentCliCapabilityById("issue.comment").description).argument("<issueId>", "Issue ID").option("--body-file <path>", "Read comment body from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the comment; may be repeated", collectImagePath, []).option("--reopen", "Reopen if issue is done/cancelled").addHelpText("after", formatExamplesAndCautions({
|
|
11393
|
+
examples: [
|
|
11394
|
+
{
|
|
11395
|
+
description: "Progress update with attached screenshot evidence:",
|
|
11396
|
+
command: "rudder issue comment ZST-123 --body-file ./progress.md --image ./screenshot.png --json"
|
|
11397
|
+
},
|
|
11398
|
+
{
|
|
11399
|
+
description: "Short stdin status when a separate file is unnecessary:",
|
|
11400
|
+
command: "printf '%s\\n' 'Short status' | rudder issue comment ZST-123 --body-file -"
|
|
11401
|
+
}
|
|
11402
|
+
],
|
|
11403
|
+
cautions: [
|
|
11404
|
+
"Use --body-file for multiline Markdown; the old --body option is intentionally rejected.",
|
|
11405
|
+
"Attach local visual evidence with --image instead of leaving only a filesystem path in the comment."
|
|
11406
|
+
]
|
|
11407
|
+
})).action(async (issueId, opts) => {
|
|
11181
11408
|
try {
|
|
11182
11409
|
const ctx = resolveCommandContext(opts);
|
|
11183
11410
|
const bodyText = await resolveFileTextInput({
|
|
@@ -11205,7 +11432,22 @@ function registerIssueCommands(program) {
|
|
|
11205
11432
|
issue.command("review").description(getAgentCliCapabilityById("issue.review").description).argument("<issueId>", "Issue ID").requiredOption(
|
|
11206
11433
|
"--decision <decision>",
|
|
11207
11434
|
"Review decision: approve, request_changes, needs_followup, or blocked"
|
|
11208
|
-
).option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").
|
|
11435
|
+
).option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").addHelpText("after", formatExamplesAndCautions({
|
|
11436
|
+
examples: [
|
|
11437
|
+
{
|
|
11438
|
+
description: "Return implementation work with durable review feedback:",
|
|
11439
|
+
command: "rudder issue review ZST-123 --decision request_changes --comment-file ./review.md --json"
|
|
11440
|
+
},
|
|
11441
|
+
{
|
|
11442
|
+
description: "Approve after reading the issue evidence and validation:",
|
|
11443
|
+
command: "rudder issue review ZST-123 --decision approve --comment-file ./review.md"
|
|
11444
|
+
}
|
|
11445
|
+
],
|
|
11446
|
+
cautions: [
|
|
11447
|
+
"Free-form comments are not durable review decisions; use this command for approve/request_changes/etc.",
|
|
11448
|
+
"Approving an implementation issue can move it to done, so use request_changes when returning it for fixes."
|
|
11449
|
+
]
|
|
11450
|
+
})).action(async (issueId, opts) => {
|
|
11209
11451
|
try {
|
|
11210
11452
|
const ctx = resolveCommandContext(opts);
|
|
11211
11453
|
const decision = parseReviewDecision(opts.decision);
|
|
@@ -11245,7 +11487,22 @@ function registerIssueCommands(program) {
|
|
|
11245
11487
|
})
|
|
11246
11488
|
);
|
|
11247
11489
|
addCommonClientOptions(
|
|
11248
|
-
issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").option("--comment-file <path>", "Read required completion comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the completion comment; may be repeated", collectImagePath, []).
|
|
11490
|
+
issue.command("done").description(getAgentCliCapabilityById("issue.done").description).argument("<issueId>", "Issue ID").option("--comment-file <path>", "Read required completion comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the completion comment; may be repeated", collectImagePath, []).addHelpText("after", formatExamplesAndCautions({
|
|
11491
|
+
examples: [
|
|
11492
|
+
{
|
|
11493
|
+
description: "Close out with validation summary and visual evidence:",
|
|
11494
|
+
command: "rudder issue done ZST-123 --comment-file ./done.md --image ./screenshot.png --json"
|
|
11495
|
+
},
|
|
11496
|
+
{
|
|
11497
|
+
description: "Read the completion note from stdin in scripts:",
|
|
11498
|
+
command: "rudder issue done ZST-123 --comment-file - < ./done.md"
|
|
11499
|
+
}
|
|
11500
|
+
],
|
|
11501
|
+
cautions: [
|
|
11502
|
+
"Include validation evidence and commit/push status in the completion comment.",
|
|
11503
|
+
"If the server reports a run ownership conflict, stop and inspect the issue/run instead of retrying blindly."
|
|
11504
|
+
]
|
|
11505
|
+
})).action(async (issueId, opts) => {
|
|
11249
11506
|
try {
|
|
11250
11507
|
const ctx = resolveCommandContext(opts);
|
|
11251
11508
|
const commentText = await resolveFileTextInput({
|
|
@@ -11288,7 +11545,7 @@ function registerIssueCommands(program) {
|
|
|
11288
11545
|
);
|
|
11289
11546
|
const comments = issue.command("comments").description("Issue comment operations");
|
|
11290
11547
|
addCommonClientOptions(
|
|
11291
|
-
comments.command("list").description(getAgentCliCapabilityById("issue.comments.list").description).argument("<issueId>", "Issue ID").option("--after <commentId>", "Only return comments after this comment ID").option("--order <order>", "Comment ordering (asc or desc)", "desc").action(async (issueId, opts) => {
|
|
11548
|
+
comments.command("list").description(getAgentCliCapabilityById("issue.comments.list").description).argument("<issueId>", "Issue ID").option("--after <commentId>", "Only return comments after this full comment ID or cmt_<uuid-prefix>").option("--order <order>", "Comment ordering (asc or desc)", "desc").action(async (issueId, opts) => {
|
|
11292
11549
|
try {
|
|
11293
11550
|
const ctx = resolveCommandContext(opts);
|
|
11294
11551
|
const params = new URLSearchParams();
|
|
@@ -11305,7 +11562,7 @@ function registerIssueCommands(program) {
|
|
|
11305
11562
|
})
|
|
11306
11563
|
);
|
|
11307
11564
|
addCommonClientOptions(
|
|
11308
|
-
comments.command("get").description(getAgentCliCapabilityById("issue.comments.get").description).argument("<issueId>", "Issue ID").argument("<commentId>", "
|
|
11565
|
+
comments.command("get").description(getAgentCliCapabilityById("issue.comments.get").description).argument("<issueId>", "Issue ID").argument("<commentId>", "Full comment ID or cmt_<uuid-prefix>").action(async (issueId, commentId, opts) => {
|
|
11309
11566
|
try {
|
|
11310
11567
|
const ctx = resolveCommandContext(opts);
|
|
11311
11568
|
const row = await ctx.api.get(`/api/issues/${issueId}/comments/${commentId}`);
|
|
@@ -11624,7 +11881,22 @@ function registerLibraryCommands(program) {
|
|
|
11624
11881
|
{ includeCompany: true }
|
|
11625
11882
|
);
|
|
11626
11883
|
addCommonClientOptions(
|
|
11627
|
-
file.command("ref").description(getAgentCliCapabilityById("library.file.ref").description).argument("<filePath>", "Library file path").
|
|
11884
|
+
file.command("ref").description(getAgentCliCapabilityById("library.file.ref").description).argument("<filePath>", "Library file path").addHelpText("after", formatExamplesAndCautions({
|
|
11885
|
+
examples: [
|
|
11886
|
+
{
|
|
11887
|
+
description: "Return the renderable Markdown link for a known Library file:",
|
|
11888
|
+
command: "rudder library file ref projects/rudder/proposals/plan.md --json"
|
|
11889
|
+
},
|
|
11890
|
+
{
|
|
11891
|
+
description: "Reference a file under the current project Library path:",
|
|
11892
|
+
command: 'rudder library file ref "$RUDDER_PROJECT_LIBRARY_PATH/proposals/plan.md" --json'
|
|
11893
|
+
}
|
|
11894
|
+
],
|
|
11895
|
+
cautions: [
|
|
11896
|
+
"Pass the Library-relative path, not an absolute filesystem path.",
|
|
11897
|
+
"Use the returned markdownLink in issue comments instead of hand-writing library-entry URLs."
|
|
11898
|
+
]
|
|
11899
|
+
})).action(async (filePath, opts) => {
|
|
11628
11900
|
try {
|
|
11629
11901
|
await printLibraryFileReference(filePath, opts);
|
|
11630
11902
|
} catch (err) {
|
|
@@ -11634,7 +11906,22 @@ function registerLibraryCommands(program) {
|
|
|
11634
11906
|
{ includeCompany: true }
|
|
11635
11907
|
);
|
|
11636
11908
|
addCommonClientOptions(
|
|
11637
|
-
file.command("put").description(getAgentCliCapabilityById("library.file.put").description).argument("<filePath>", "Library file path").option("--body-file <path>", "Read file content from a file, or '-' for stdin").
|
|
11909
|
+
file.command("put").description(getAgentCliCapabilityById("library.file.put").description).argument("<filePath>", "Library file path").option("--body-file <path>", "Read file content from a file, or '-' for stdin").addHelpText("after", formatExamplesAndCautions({
|
|
11910
|
+
examples: [
|
|
11911
|
+
{
|
|
11912
|
+
description: "Upload a durable Markdown artifact from a local file:",
|
|
11913
|
+
command: "rudder library file put projects/rudder/proposals/plan.md --body-file ./plan.md --json"
|
|
11914
|
+
},
|
|
11915
|
+
{
|
|
11916
|
+
description: "Write a small generated artifact from stdin:",
|
|
11917
|
+
command: "printf '%s\\n' '# Plan' | rudder library file put projects/rudder/proposals/plan.md --body-file -"
|
|
11918
|
+
}
|
|
11919
|
+
],
|
|
11920
|
+
cautions: [
|
|
11921
|
+
"Use --body-file for content; the old --body option is intentionally rejected.",
|
|
11922
|
+
"For local trusted runs, prefer writing durable files under the project Library root, then use file ref for the renderable link."
|
|
11923
|
+
]
|
|
11924
|
+
})).action(async (filePath, opts) => {
|
|
11638
11925
|
try {
|
|
11639
11926
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11640
11927
|
const body = await resolveBodyFileInput(opts.bodyFile);
|
|
@@ -11921,7 +12208,22 @@ function registerProjectCommands(program) {
|
|
|
11921
12208
|
{ includeCompany: false }
|
|
11922
12209
|
);
|
|
11923
12210
|
addCommonClientOptions(
|
|
11924
|
-
project.command("create").description(getAgentCliCapabilityById("project.create").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--name <name>", "Project name").option("--description <text>", "Project description").option("--status <status>", "Project status").option("--goal-id <id>", "Primary goal ID").option("--goal-ids <csv>", "Comma-separated goal IDs").option("--lead-agent-id <id>", "Lead agent ID").option("--target-date <date>", "Target date").option("--color <value>", "Project color or supported gradient token").
|
|
12211
|
+
project.command("create").description(getAgentCliCapabilityById("project.create").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--name <name>", "Project name").option("--description <text>", "Project description").option("--status <status>", "Project status").option("--goal-id <id>", "Primary goal ID").option("--goal-ids <csv>", "Comma-separated goal IDs").option("--lead-agent-id <id>", "Lead agent ID").option("--target-date <date>", "Target date").option("--color <value>", "Project color or supported gradient token").addHelpText("after", formatExamplesAndCautions({
|
|
12212
|
+
examples: [
|
|
12213
|
+
{
|
|
12214
|
+
description: "Create a new active workstream after confirming it does not already exist:",
|
|
12215
|
+
command: 'rudder project create --org-id <org-id> --name "Rudder dev" --status in_progress --json'
|
|
12216
|
+
},
|
|
12217
|
+
{
|
|
12218
|
+
description: "Create a project tied to a goal and responsible agent:",
|
|
12219
|
+
command: 'rudder project create --org-id <org-id> --name "Release" --goal-id <goal-id> --lead-agent-id <agent-id>'
|
|
12220
|
+
}
|
|
12221
|
+
],
|
|
12222
|
+
cautions: [
|
|
12223
|
+
"Project mutations are organization-scoped; pass --org-id when context might be ambiguous.",
|
|
12224
|
+
"Use existing project IDs/shortnames for updates instead of creating duplicate project containers."
|
|
12225
|
+
]
|
|
12226
|
+
})).action(async (opts) => {
|
|
11925
12227
|
try {
|
|
11926
12228
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11927
12229
|
const payload = createProjectSchema.parse({
|
|
@@ -11943,7 +12245,22 @@ function registerProjectCommands(program) {
|
|
|
11943
12245
|
{ includeCompany: false }
|
|
11944
12246
|
);
|
|
11945
12247
|
addCommonClientOptions(
|
|
11946
|
-
project.command("update").description(getAgentCliCapabilityById("project.update").description).argument("<projectIdOrShortname>", "Project ID or shortname").option("-O, --org-id <id>", "Organization ID for shortname resolution").option("--name <name>", "Project name").option("--description <text>", "Project description").option("--status <status>", "Project status").option("--goal-id <id>", "Primary goal ID").option("--goal-ids <csv>", "Comma-separated goal IDs").option("--lead-agent-id <id>", "Lead agent ID").option("--target-date <date>", "Target date").option("--color <value>", "Project color or supported gradient token").option("--archived-at <iso8601|null>", "Set archivedAt timestamp or literal 'null'").
|
|
12248
|
+
project.command("update").description(getAgentCliCapabilityById("project.update").description).argument("<projectIdOrShortname>", "Project ID or shortname").option("-O, --org-id <id>", "Organization ID for shortname resolution").option("--name <name>", "Project name").option("--description <text>", "Project description").option("--status <status>", "Project status").option("--goal-id <id>", "Primary goal ID").option("--goal-ids <csv>", "Comma-separated goal IDs").option("--lead-agent-id <id>", "Lead agent ID").option("--target-date <date>", "Target date").option("--color <value>", "Project color or supported gradient token").option("--archived-at <iso8601|null>", "Set archivedAt timestamp or literal 'null'").addHelpText("after", formatExamplesAndCautions({
|
|
12249
|
+
examples: [
|
|
12250
|
+
{
|
|
12251
|
+
description: "Move a known project shortname under the intended org:",
|
|
12252
|
+
command: "rudder project update rudder-dev --org-id <org-id> --status in_progress --json"
|
|
12253
|
+
},
|
|
12254
|
+
{
|
|
12255
|
+
description: "Unarchive a verified project id:",
|
|
12256
|
+
command: "rudder project update <project-id> --archived-at null"
|
|
12257
|
+
}
|
|
12258
|
+
],
|
|
12259
|
+
cautions: [
|
|
12260
|
+
"Shortname resolution needs the intended organization; include --org-id for cross-org local contexts.",
|
|
12261
|
+
"Archiving and unarchiving changes project visibility, so verify the target with project get first."
|
|
12262
|
+
]
|
|
12263
|
+
})).action(async (projectRef, opts) => {
|
|
11947
12264
|
try {
|
|
11948
12265
|
const ctx = resolveCommandContext(opts);
|
|
11949
12266
|
const payload = updateProjectSchema.parse({
|
|
@@ -11986,7 +12303,22 @@ function projectPath(projectRef, orgId) {
|
|
|
11986
12303
|
function registerRunsCommands(program) {
|
|
11987
12304
|
const runs = program.command("runs").description("Run debugging operations");
|
|
11988
12305
|
addCommonClientOptions(
|
|
11989
|
-
runs.command("list").description(getAgentCliCapabilityById("runs.list").description).option("-O, --org-id <id>", "Organization ID").option("--updated-after <iso>", "Only runs updated after this timestamp").option("--run-id-prefix <prefix>", "Filter by run ID prefix").option("--agent-id <id>", "Filter by agent ID").option("--status <status>", "Filter by run status").option("--runtime <type>", "Filter by runtime type").option("--issue-id <id>", "Filter by linked issue ID").option("--used-skill <key-or-name>", "Filter by skill actually used during the run").option("--loaded-skill <key-or-name>", "Filter by skill loaded for the run").option("--created-before <iso>", "Only runs created before this timestamp").option("--limit <n>", "Maximum rows", "200").
|
|
12306
|
+
runs.command("list").description(getAgentCliCapabilityById("runs.list").description).option("-O, --org-id <id>", "Organization ID").option("--updated-after <iso>", "Only runs updated after this timestamp").option("--run-id-prefix <prefix>", "Filter by run ID prefix").option("--agent-id <id>", "Filter by agent ID").option("--status <status>", "Filter by run status").option("--runtime <type>", "Filter by runtime type").option("--issue-id <id>", "Filter by linked issue ID").option("--used-skill <key-or-name>", "Filter by skill actually used during the run").option("--loaded-skill <key-or-name>", "Filter by skill loaded for the run").option("--created-before <iso>", "Only runs created before this timestamp").option("--limit <n>", "Maximum rows", "200").addHelpText("after", formatExamplesAndCautions({
|
|
12307
|
+
examples: [
|
|
12308
|
+
{
|
|
12309
|
+
description: "Find recent failures for one agent before opening transcripts:",
|
|
12310
|
+
command: "rudder runs list --org-id <org-id> --agent-id <agent-id> --status failed --limit 20"
|
|
12311
|
+
},
|
|
12312
|
+
{
|
|
12313
|
+
description: "Collect skill-specific evidence for a linked issue:",
|
|
12314
|
+
command: "rudder runs list --org-id <org-id> --issue-id ZST-123 --used-skill release-maintainer --json"
|
|
12315
|
+
}
|
|
12316
|
+
],
|
|
12317
|
+
cautions: [
|
|
12318
|
+
"Filter first by org, agent, issue, status, skill, or time; do not start by dumping broad run history.",
|
|
12319
|
+
"Use runs errors or runs transcript for detail instead of expecting list to return full debug payloads."
|
|
12320
|
+
]
|
|
12321
|
+
})).action(async (opts) => {
|
|
11990
12322
|
try {
|
|
11991
12323
|
assertSingleSkillFilter(opts);
|
|
11992
12324
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
@@ -12051,7 +12383,22 @@ function registerRunsCommands(program) {
|
|
|
12051
12383
|
})
|
|
12052
12384
|
);
|
|
12053
12385
|
addCommonClientOptions(
|
|
12054
|
-
runs.command("transcript").description(getAgentCliCapabilityById("runs.transcript").description).argument("<runId>", "Run ID or short run ID").option("--errors-only", "Show only error transcript rows").option("--around-error <id>", "Show context around a run error id such as step-12").option("--context-turns <n>", "Turns around --around-error", "1").option("--cursor <cursor>", "Stable transcript cursor returned in page.nextCursor").option("--turn-limit <n>", "Maximum turns to return", "20").option("--chronological", "Show oldest-first instead of default newest-first").option("--narrative", "Use a narrative human layout").option("--max-chars <n>", "Maximum output characters per row", "1200").option("--max-output-chars <n>", "Alias for --max-chars").option("--include-output", "Include row output in compact human transcript rows").option("--include-outputs", "Alias for --include-output").
|
|
12386
|
+
runs.command("transcript").description(getAgentCliCapabilityById("runs.transcript").description).argument("<runId>", "Run ID or short run ID").option("--errors-only", "Show only error transcript rows").option("--around-error <id>", "Show context around a run error id such as step-12").option("--context-turns <n>", "Turns around --around-error", "1").option("--cursor <cursor>", "Stable transcript cursor returned in page.nextCursor").option("--turn-limit <n>", "Maximum turns to return", "20").option("--chronological", "Show oldest-first instead of default newest-first").option("--narrative", "Use a narrative human layout").option("--max-chars <n>", "Maximum output characters per row", "1200").option("--max-output-chars <n>", "Alias for --max-chars").option("--include-output", "Include row output in compact human transcript rows").option("--include-outputs", "Alias for --include-output").addHelpText("after", formatExamplesAndCautions({
|
|
12387
|
+
examples: [
|
|
12388
|
+
{
|
|
12389
|
+
description: "Inspect the neighborhood around a failing step:",
|
|
12390
|
+
command: "rudder runs transcript <run-id> --around-error step-12 --context-turns 2"
|
|
12391
|
+
},
|
|
12392
|
+
{
|
|
12393
|
+
description: "Reconstruct a bounded chronological decision trail:",
|
|
12394
|
+
command: "rudder runs transcript <run-id> --chronological --turn-limit 30 --include-output"
|
|
12395
|
+
}
|
|
12396
|
+
],
|
|
12397
|
+
cautions: [
|
|
12398
|
+
"Human output is compact and clipped by default; use --json only when a script needs the full payload.",
|
|
12399
|
+
"Use --around-error from runs errors when investigating a failure instead of reading the entire run first."
|
|
12400
|
+
]
|
|
12401
|
+
})).action(async (runId, opts) => {
|
|
12055
12402
|
try {
|
|
12056
12403
|
const ctx = resolveCommandContext(opts);
|
|
12057
12404
|
const payload = await ctx.api.get(
|
|
@@ -12070,7 +12417,22 @@ function registerRunsCommands(program) {
|
|
|
12070
12417
|
})
|
|
12071
12418
|
);
|
|
12072
12419
|
addCommonClientOptions(
|
|
12073
|
-
runs.command("errors").description(getAgentCliCapabilityById("runs.errors").description).argument("<runId>", "Run ID or short run ID").option("--max-chars <n>", "Maximum output characters per error", "1200").
|
|
12420
|
+
runs.command("errors").description(getAgentCliCapabilityById("runs.errors").description).argument("<runId>", "Run ID or short run ID").option("--max-chars <n>", "Maximum output characters per error", "1200").addHelpText("after", formatExamplesAndCautions({
|
|
12421
|
+
examples: [
|
|
12422
|
+
{
|
|
12423
|
+
description: "Start failed-run investigation with error summaries:",
|
|
12424
|
+
command: "rudder runs errors <run-id>"
|
|
12425
|
+
},
|
|
12426
|
+
{
|
|
12427
|
+
description: "Increase clipped error output for scripts or reports:",
|
|
12428
|
+
command: "rudder runs errors <run-id> --max-chars 4000 --json"
|
|
12429
|
+
}
|
|
12430
|
+
],
|
|
12431
|
+
cautions: [
|
|
12432
|
+
"Start here for failed runs, then follow the transcript context command returned for the relevant step.",
|
|
12433
|
+
"Increase --max-chars deliberately; large tool outputs can be noisy and expensive to inspect."
|
|
12434
|
+
]
|
|
12435
|
+
})).action(async (runId, opts) => {
|
|
12074
12436
|
try {
|
|
12075
12437
|
const ctx = resolveCommandContext(opts);
|
|
12076
12438
|
const params = new URLSearchParams();
|
|
@@ -12365,7 +12727,22 @@ function registerSkillCommands(program) {
|
|
|
12365
12727
|
{ includeCompany: false }
|
|
12366
12728
|
);
|
|
12367
12729
|
addCommonClientOptions(
|
|
12368
|
-
skill.command("file").description(getAgentCliCapabilityById("skill.file").description).argument("<skillId>", "Skill ID").option("-O, --org-id <id>", "Organization ID").option("--path <path>", "Skill package file path", "SKILL.md").
|
|
12730
|
+
skill.command("file").description(getAgentCliCapabilityById("skill.file").description).argument("<skillId>", "Skill ID").option("-O, --org-id <id>", "Organization ID").option("--path <path>", "Skill package file path", "SKILL.md").addHelpText("after", formatExamplesAndCautions({
|
|
12731
|
+
examples: [
|
|
12732
|
+
{
|
|
12733
|
+
description: "Read the main skill trigger and workflow instructions:",
|
|
12734
|
+
command: "rudder skill file <skill-uuid> --path SKILL.md --org-id <org-id>"
|
|
12735
|
+
},
|
|
12736
|
+
{
|
|
12737
|
+
description: "Inspect a specific reference file in the skill package:",
|
|
12738
|
+
command: "rudder skill file <skill-uuid> --path references/usage.md --json"
|
|
12739
|
+
}
|
|
12740
|
+
],
|
|
12741
|
+
cautions: [
|
|
12742
|
+
"Prefer the skill UUID for slashful keys such as local/<hash>/<slug>.",
|
|
12743
|
+
"Read SKILL.md before assuming a skill's trigger or workflow behavior."
|
|
12744
|
+
]
|
|
12745
|
+
})).action(async (skillId, opts) => {
|
|
12369
12746
|
try {
|
|
12370
12747
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12371
12748
|
const query = new URLSearchParams({ path: opts.path ?? "SKILL.md" });
|
|
@@ -12380,7 +12757,22 @@ function registerSkillCommands(program) {
|
|
|
12380
12757
|
{ includeCompany: false }
|
|
12381
12758
|
);
|
|
12382
12759
|
addCommonClientOptions(
|
|
12383
|
-
skill.command("import").description(getAgentCliCapabilityById("skill.import").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--source <source>", "Skill source (local path, URL, or repo ref)").
|
|
12760
|
+
skill.command("import").description(getAgentCliCapabilityById("skill.import").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--source <source>", "Skill source (local path, URL, or repo ref)").addHelpText("after", formatExamplesAndCautions({
|
|
12761
|
+
examples: [
|
|
12762
|
+
{
|
|
12763
|
+
description: "Import a durable organization-shared skill package:",
|
|
12764
|
+
command: "rudder skill import --org-id <org-id> --source /abs/path/to/skill --json"
|
|
12765
|
+
},
|
|
12766
|
+
{
|
|
12767
|
+
description: "List imported skills afterward to get stable ids:",
|
|
12768
|
+
command: "rudder skill list --org-id <org-id> --json"
|
|
12769
|
+
}
|
|
12770
|
+
],
|
|
12771
|
+
cautions: [
|
|
12772
|
+
"Import organization-shared skills from durable shared paths, not disposable agent-private work directories.",
|
|
12773
|
+
"Importing a skill does not automatically enable it for every agent; update agent skill selections separately."
|
|
12774
|
+
]
|
|
12775
|
+
})).action(async (opts) => {
|
|
12384
12776
|
try {
|
|
12385
12777
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12386
12778
|
const payload = organizationSkillImportSchema.parse({ source: opts.source });
|
|
@@ -13405,6 +13797,7 @@ function createByteProgress(label, options = {}) {
|
|
|
13405
13797
|
init_version();
|
|
13406
13798
|
var DEFAULT_DESKTOP_RELEASE_REPO = "Undertone0809/rudder";
|
|
13407
13799
|
var DESKTOP_UPDATE_QUIT_ARG = "--rudder-update-quit";
|
|
13800
|
+
var DESKTOP_UPDATE_FORCE_ARG = "--rudder-update-force";
|
|
13408
13801
|
var STABLE_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+$/;
|
|
13409
13802
|
var CANARY_SEMVER_RE = /^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9]+$/;
|
|
13410
13803
|
var CLI_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@rudderhq%2fcli/latest";
|
|
@@ -13488,7 +13881,7 @@ function createDesktopProgressFactory() {
|
|
|
13488
13881
|
async function waitForDesktopApplySignal() {
|
|
13489
13882
|
process.stdin.setEncoding("utf8");
|
|
13490
13883
|
process.stdin.resume();
|
|
13491
|
-
await new Promise((resolve, reject) => {
|
|
13884
|
+
return await new Promise((resolve, reject) => {
|
|
13492
13885
|
let buffer = "";
|
|
13493
13886
|
const cleanup = () => {
|
|
13494
13887
|
process.stdin.off("data", onData);
|
|
@@ -13499,9 +13892,15 @@ async function waitForDesktopApplySignal() {
|
|
|
13499
13892
|
buffer += chunk;
|
|
13500
13893
|
const lines = buffer.split(/\r?\n/);
|
|
13501
13894
|
buffer = lines.pop() ?? "";
|
|
13502
|
-
|
|
13895
|
+
const commands = lines.map((line) => line.trim());
|
|
13896
|
+
if (commands.includes("force-apply")) {
|
|
13503
13897
|
cleanup();
|
|
13504
|
-
resolve();
|
|
13898
|
+
resolve({ force: true });
|
|
13899
|
+
return;
|
|
13900
|
+
}
|
|
13901
|
+
if (commands.includes("apply")) {
|
|
13902
|
+
cleanup();
|
|
13903
|
+
resolve({ force: false });
|
|
13505
13904
|
}
|
|
13506
13905
|
};
|
|
13507
13906
|
const onEnd = () => {
|
|
@@ -14214,14 +14613,6 @@ function isInstalledDesktopCurrent(metadata, releaseTag, assetName, assetChecksu
|
|
|
14214
14613
|
metadata && metadata.releaseTag === releaseTag && metadata.assetName === assetName && metadata.assetChecksum === assetChecksum
|
|
14215
14614
|
);
|
|
14216
14615
|
}
|
|
14217
|
-
function buildForceQuitCommand(target) {
|
|
14218
|
-
if (target.platform === "windows") return { command: "taskkill.exe", args: ["/IM", `${DESKTOP_APP_NAME}.exe`, "/T", "/F"] };
|
|
14219
|
-
return { command: "pkill", args: ["-x", DESKTOP_APP_NAME] };
|
|
14220
|
-
}
|
|
14221
|
-
function forceQuitDesktopProcesses(target) {
|
|
14222
|
-
const command = buildForceQuitCommand(target);
|
|
14223
|
-
spawnSync3(command.command, command.args, { stdio: "ignore" });
|
|
14224
|
-
}
|
|
14225
14616
|
function forceQuitDesktopProcess(pid, target) {
|
|
14226
14617
|
if (target.platform === "windows") {
|
|
14227
14618
|
spawnSync3("taskkill.exe", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore" });
|
|
@@ -14232,8 +14623,35 @@ function forceQuitDesktopProcess(pid, target) {
|
|
|
14232
14623
|
} catch {
|
|
14233
14624
|
}
|
|
14234
14625
|
}
|
|
14235
|
-
function
|
|
14236
|
-
return
|
|
14626
|
+
function quotePowerShellString(value) {
|
|
14627
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
14628
|
+
}
|
|
14629
|
+
function findDesktopExecutablePids(executablePath, target) {
|
|
14630
|
+
if (target.platform === "windows") {
|
|
14631
|
+
const result2 = spawnSync3("powershell.exe", [
|
|
14632
|
+
"-NoProfile",
|
|
14633
|
+
"-Command",
|
|
14634
|
+
`Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq ${quotePowerShellString(executablePath)} } | Select-Object -ExpandProperty ProcessId`
|
|
14635
|
+
], {
|
|
14636
|
+
encoding: "utf8",
|
|
14637
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
14638
|
+
});
|
|
14639
|
+
if (result2.status !== 0) return [];
|
|
14640
|
+
return result2.stdout.split(/\r?\n/).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid);
|
|
14641
|
+
}
|
|
14642
|
+
const result = spawnSync3("ps", ["-eo", "pid=,args="], {
|
|
14643
|
+
encoding: "utf8",
|
|
14644
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
14645
|
+
});
|
|
14646
|
+
if (result.status !== 0) return [];
|
|
14647
|
+
return result.stdout.split(/\r?\n/).flatMap((line) => {
|
|
14648
|
+
const match = line.match(/^\s*(\d+)\s+(.+)$/);
|
|
14649
|
+
if (!match) return [];
|
|
14650
|
+
const pid = Number.parseInt(match[1], 10);
|
|
14651
|
+
const commandLine = match[2];
|
|
14652
|
+
const matchesExecutable = commandLine === executablePath || commandLine.startsWith(`${executablePath} `);
|
|
14653
|
+
return matchesExecutable && pid !== process.pid ? [pid] : [];
|
|
14654
|
+
});
|
|
14237
14655
|
}
|
|
14238
14656
|
async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
|
|
14239
14657
|
const startedAt = Date.now();
|
|
@@ -14245,10 +14663,13 @@ async function waitForUpdateQuitResponse(responsePath, timeoutMs = 8e3) {
|
|
|
14245
14663
|
}
|
|
14246
14664
|
return null;
|
|
14247
14665
|
}
|
|
14248
|
-
async function requestDesktopQuit(executablePath, target) {
|
|
14666
|
+
async function requestDesktopQuit(executablePath, target, options = {}) {
|
|
14249
14667
|
if (!await pathExists2(executablePath)) return { ok: true, status: "not_running" };
|
|
14250
14668
|
const responsePath = path21.join(tmpdir(), `rudder-update-quit-${process.pid}-${Date.now()}.json`);
|
|
14251
|
-
const result = spawnSync3(executablePath, [
|
|
14669
|
+
const result = spawnSync3(executablePath, [
|
|
14670
|
+
`${DESKTOP_UPDATE_QUIT_ARG}=${responsePath}`,
|
|
14671
|
+
...options.forceUpdate ? [DESKTOP_UPDATE_FORCE_ARG] : []
|
|
14672
|
+
], {
|
|
14252
14673
|
stdio: "ignore",
|
|
14253
14674
|
timeout: 5e3
|
|
14254
14675
|
});
|
|
@@ -14256,7 +14677,7 @@ async function requestDesktopQuit(executablePath, target) {
|
|
|
14256
14677
|
return null;
|
|
14257
14678
|
}
|
|
14258
14679
|
try {
|
|
14259
|
-
return await waitForUpdateQuitResponse(responsePath);
|
|
14680
|
+
return await waitForUpdateQuitResponse(responsePath, options.responseTimeoutMs);
|
|
14260
14681
|
} finally {
|
|
14261
14682
|
await rm2(responsePath, { force: true });
|
|
14262
14683
|
}
|
|
@@ -14285,6 +14706,12 @@ async function waitForProcessExit(pid, timeoutMs = 2e4, intervalMs = 250) {
|
|
|
14285
14706
|
}
|
|
14286
14707
|
return !processExists(pid);
|
|
14287
14708
|
}
|
|
14709
|
+
async function waitForProcessesExit(pids, waitForExit) {
|
|
14710
|
+
const uniquePids = [...new Set(pids)];
|
|
14711
|
+
if (uniquePids.length === 0) return true;
|
|
14712
|
+
const results = await Promise.all(uniquePids.map((pid) => waitForExit(pid)));
|
|
14713
|
+
return results.every(Boolean);
|
|
14714
|
+
}
|
|
14288
14715
|
async function removePathWithRetry(targetPath, attempts = 5) {
|
|
14289
14716
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
14290
14717
|
try {
|
|
@@ -14297,50 +14724,98 @@ async function removePathWithRetry(targetPath, attempts = 5) {
|
|
|
14297
14724
|
return false;
|
|
14298
14725
|
}
|
|
14299
14726
|
async function prepareForDesktopReplace(paths, target, options = {}) {
|
|
14300
|
-
const forceQuit = options.forceQuitDesktopProcesses ?? forceQuitDesktopProcesses;
|
|
14301
14727
|
const forceQuitPid = options.forceQuitDesktopProcess ?? forceQuitDesktopProcess;
|
|
14302
14728
|
const waitForExit = options.waitForDesktopProcessExit ?? waitForProcessExit;
|
|
14729
|
+
const findPids = options.findDesktopExecutablePids ?? findDesktopExecutablePids;
|
|
14730
|
+
async function forceQuitPidAndConfirm(pid) {
|
|
14731
|
+
forceQuitPid(pid, target);
|
|
14732
|
+
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14733
|
+
if (!await waitForExit(pid)) {
|
|
14734
|
+
throw new Error(`Rudder Desktop process ${pid} did not exit after force-quit fallback. Close Rudder and rerun start.`);
|
|
14735
|
+
}
|
|
14736
|
+
}
|
|
14737
|
+
async function forceQuitPidsAndConfirm(pids) {
|
|
14738
|
+
const uniquePids = [...new Set(pids)];
|
|
14739
|
+
for (const pid of uniquePids) {
|
|
14740
|
+
forceQuitPid(pid, target);
|
|
14741
|
+
}
|
|
14742
|
+
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14743
|
+
if (!await waitForProcessesExit(uniquePids, waitForExit)) {
|
|
14744
|
+
throw new Error(`Rudder Desktop process${uniquePids.length === 1 ? "" : "es"} ${uniquePids.join(", ")} did not exit after force-quit fallback. Close Rudder and rerun start.`);
|
|
14745
|
+
}
|
|
14746
|
+
}
|
|
14747
|
+
let quitPid = null;
|
|
14748
|
+
let managedExecutablePids = [];
|
|
14303
14749
|
const hasManagedExecutable = await pathExists2(paths.executablePath);
|
|
14304
14750
|
if (hasManagedExecutable) {
|
|
14305
|
-
|
|
14306
|
-
|
|
14751
|
+
managedExecutablePids = findPids(paths.executablePath, target);
|
|
14752
|
+
const requestQuit = () => requestDesktopQuit(paths.executablePath, target, {
|
|
14753
|
+
forceUpdate: options.forceUpdate,
|
|
14754
|
+
responseTimeoutMs: options.updateQuitResponseTimeoutMs
|
|
14755
|
+
});
|
|
14756
|
+
let quitResponse = await requestQuit();
|
|
14757
|
+
while (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs" && options.waitForActiveRuns && !options.forceUpdate) {
|
|
14307
14758
|
p15.log.warn(
|
|
14308
14759
|
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}; waiting before replacing Desktop.`
|
|
14309
14760
|
);
|
|
14310
14761
|
await delay2(options.activeRunPollIntervalMs ?? 15e3);
|
|
14311
|
-
quitResponse = await
|
|
14762
|
+
quitResponse = await requestQuit();
|
|
14312
14763
|
}
|
|
14313
14764
|
if (quitResponse && !quitResponse.ok && quitResponse.status === "active_runs") {
|
|
14765
|
+
if (!options.forceUpdate) {
|
|
14766
|
+
throw new Error(
|
|
14767
|
+
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}. Stop active work, then rerun start.`
|
|
14768
|
+
);
|
|
14769
|
+
}
|
|
14314
14770
|
throw new Error(
|
|
14315
|
-
`Rudder Desktop has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"}. Stop active work, then rerun start.`
|
|
14771
|
+
`Rudder Desktop still has ${quitResponse.totalRuns} active run${quitResponse.totalRuns === 1 ? "" : "s"} after the force-update request. Stop active work, then rerun start.`
|
|
14316
14772
|
);
|
|
14317
14773
|
}
|
|
14318
|
-
|
|
14774
|
+
if (quitResponse && !quitResponse.ok && quitResponse.status === "failed") {
|
|
14775
|
+
throw new Error(quitResponse.message);
|
|
14776
|
+
}
|
|
14777
|
+
quitPid = readUpdateQuitPid(quitResponse);
|
|
14319
14778
|
if (quitPid) {
|
|
14320
14779
|
p15.log.info(`Waiting for existing Rudder Desktop process ${quitPid} to exit before replacing it.`);
|
|
14321
14780
|
if (!await waitForExit(quitPid)) {
|
|
14322
14781
|
p15.log.warn(`Rudder Desktop process ${quitPid} did not exit in time; attempting force-quit fallback.`);
|
|
14323
|
-
|
|
14324
|
-
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14782
|
+
await forceQuitPidAndConfirm(quitPid);
|
|
14325
14783
|
}
|
|
14326
14784
|
} else if (isLegacyUnconfirmedUpdateQuit(quitResponse)) {
|
|
14327
14785
|
const graceMs = options.legacyUpdateQuitGraceMs ?? LEGACY_UPDATE_QUIT_GRACE_MS;
|
|
14328
14786
|
p15.log.warn(
|
|
14329
|
-
`Existing Rudder Desktop acknowledged update quit without a process id; waiting ${Math.ceil(graceMs / 1e3)}s before
|
|
14787
|
+
`Existing Rudder Desktop acknowledged update quit without a process id; waiting ${Math.ceil(graceMs / 1e3)}s before replacement.`
|
|
14330
14788
|
);
|
|
14331
14789
|
await delay2(graceMs);
|
|
14332
|
-
|
|
14333
|
-
|
|
14790
|
+
if (managedExecutablePids.length > 0 && !await waitForProcessesExit(managedExecutablePids, waitForExit)) {
|
|
14791
|
+
p15.log.warn(
|
|
14792
|
+
`Existing Rudder Desktop did not exit after acknowledging update quit; attempting path-scoped force-quit for process${managedExecutablePids.length === 1 ? "" : "es"} ${managedExecutablePids.join(", ")}.`
|
|
14793
|
+
);
|
|
14794
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14795
|
+
}
|
|
14796
|
+
} else if (!quitResponse) {
|
|
14797
|
+
if (options.forceUpdate && managedExecutablePids.length > 0) {
|
|
14798
|
+
p15.log.warn(
|
|
14799
|
+
`Existing Rudder Desktop did not respond to the update quit request; attempting path-scoped force-quit for process${managedExecutablePids.length === 1 ? "" : "es"} ${managedExecutablePids.join(", ")}.`
|
|
14800
|
+
);
|
|
14801
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14802
|
+
} else {
|
|
14803
|
+
throw new Error("Existing Rudder Desktop did not respond to the update quit request. Close Rudder and rerun start.");
|
|
14804
|
+
}
|
|
14334
14805
|
} else {
|
|
14335
14806
|
await delay2(options.updateQuitForceDelayMs ?? UPDATE_QUIT_FORCE_DELAY_MS);
|
|
14336
14807
|
}
|
|
14337
|
-
} else if (!isRunningInsideDesktopExecutable()) {
|
|
14338
|
-
forceQuit(target);
|
|
14339
14808
|
}
|
|
14340
14809
|
const replacePath = target.platform === "windows" ? paths.installRoot : paths.appPath;
|
|
14341
14810
|
if (await removePathWithRetry(replacePath)) return;
|
|
14342
|
-
|
|
14343
|
-
|
|
14811
|
+
if (!quitPid) {
|
|
14812
|
+
if (managedExecutablePids.length > 0) {
|
|
14813
|
+
await forceQuitPidsAndConfirm(managedExecutablePids);
|
|
14814
|
+
if (await removePathWithRetry(replacePath, 6)) return;
|
|
14815
|
+
}
|
|
14816
|
+
throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
|
|
14817
|
+
}
|
|
14818
|
+
await forceQuitPidAndConfirm(quitPid);
|
|
14344
14819
|
if (await removePathWithRetry(replacePath, 6)) return;
|
|
14345
14820
|
throw new Error(`Failed to replace existing Rudder Desktop at ${replacePath}. Close Rudder and rerun start.`);
|
|
14346
14821
|
}
|
|
@@ -14673,22 +15148,26 @@ async function startCommand(opts) {
|
|
|
14673
15148
|
() => assertChecksumMatch(cachedAsset.path, expectedChecksum),
|
|
14674
15149
|
desktopProgressJson ? "verifying_checksum" : null
|
|
14675
15150
|
);
|
|
15151
|
+
let applySignal = null;
|
|
14676
15152
|
if (desktopProgressJson && opts.desktopWaitForApply === true) {
|
|
14677
15153
|
writeDesktopProgress({
|
|
14678
15154
|
phase: "ready_to_install",
|
|
14679
15155
|
message: "Desktop update is downloaded and verified.",
|
|
14680
15156
|
percent: 100
|
|
14681
15157
|
});
|
|
14682
|
-
await waitForDesktopApplySignal();
|
|
15158
|
+
applySignal = await waitForDesktopApplySignal();
|
|
14683
15159
|
writeDesktopProgress({
|
|
14684
15160
|
phase: "preparing_restart",
|
|
14685
|
-
message: "Applying Desktop update..."
|
|
15161
|
+
message: applySignal.force ? "Applying Desktop update and quitting active runs..." : "Applying Desktop update..."
|
|
14686
15162
|
});
|
|
14687
15163
|
}
|
|
14688
15164
|
await runStartPhase(
|
|
14689
15165
|
"Replacing existing Rudder Desktop if needed...",
|
|
14690
15166
|
"Existing Desktop install is ready for replacement.",
|
|
14691
|
-
() => prepareForDesktopReplace(installPaths, target, {
|
|
15167
|
+
() => prepareForDesktopReplace(installPaths, target, {
|
|
15168
|
+
waitForActiveRuns: opts.waitForActiveRuns === true,
|
|
15169
|
+
forceUpdate: applySignal?.force === true
|
|
15170
|
+
}),
|
|
14692
15171
|
desktopProgressJson ? opts.waitForActiveRuns === true ? "waiting_for_active_runs" : "preparing_restart" : null
|
|
14693
15172
|
);
|
|
14694
15173
|
await runStartPhase(
|