@rudderhq/cli 0.3.4-canary.3 → 0.3.4-canary.30
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 +2484 -1449
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// ../packages/shared/dist/constants.js
|
|
13
|
-
var ORGANIZATION_STATUSES, ORGANIZATION_INTELLIGENCE_PROFILE_PURPOSES, ORGANIZATION_INTELLIGENCE_PROFILE_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_RUNTIME_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX, AGENT_AVATAR_BACKGROUND_PRESET_IDS, ISSUE_STATUSES, ISSUE_PRIORITIES, CALENDAR_SOURCE_TYPES, CALENDAR_OWNER_TYPES, CALENDAR_VISIBILITIES, CALENDAR_SOURCE_STATUSES, CALENDAR_EVENT_KINDS, CALENDAR_EVENT_STATUSES, CALENDAR_SOURCE_MODES, CHAT_CONVERSATION_STATUSES, CHAT_ISSUE_CREATION_MODES, CHAT_MESSAGE_ROLES, CHAT_MESSAGE_KINDS, CHAT_MESSAGE_STATUSES, CHAT_CONTEXT_ENTITY_TYPES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ORGANIZATION_RESOURCE_KINDS, ORGANIZATION_RESOURCE_SOURCE_TYPES, PROJECT_RESOURCE_ATTACHMENT_ROLES, AUTOMATION_STATUSES, AUTOMATION_CONCURRENCY_POLICIES, AUTOMATION_CATCH_UP_POLICIES, AUTOMATION_OUTPUT_MODES, AUTOMATION_TRIGGER_SIGNING_MODES, PROJECT_COLORS, APPROVAL_TYPES, SECRET_PROVIDERS, STORAGE_PROVIDERS, BILLING_TYPES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_UI_SLOT_TYPES, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
|
|
13
|
+
var ORGANIZATION_STATUSES, ORGANIZATION_INTELLIGENCE_PROFILE_PURPOSES, ORGANIZATION_INTELLIGENCE_PROFILE_STATUSES, DEPLOYMENT_MODES, DEPLOYMENT_EXPOSURES, AUTH_BASE_URL_MODES, AGENT_STATUSES, AGENT_RUNTIME_TYPES, AGENT_ROLES, AGENT_ICON_NAMES, AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX, AGENT_AVATAR_BACKGROUND_PRESET_IDS, ISSUE_STATUSES, ISSUE_PRIORITIES, CALENDAR_SOURCE_TYPES, CALENDAR_OWNER_TYPES, CALENDAR_VISIBILITIES, CALENDAR_SOURCE_STATUSES, CALENDAR_EVENT_KINDS, CALENDAR_EVENT_STATUSES, CALENDAR_SOURCE_MODES, CHAT_CONVERSATION_STATUSES, CHAT_ISSUE_CREATION_MODES, CHAT_MESSAGE_ROLES, CHAT_MESSAGE_KINDS, CHAT_MESSAGE_STATUSES, CHAT_CONTEXT_ENTITY_TYPES, GOAL_LEVELS, GOAL_STATUSES, PROJECT_STATUSES, ORGANIZATION_RESOURCE_KINDS, ORGANIZATION_RESOURCE_SOURCE_TYPES, PROJECT_RESOURCE_ATTACHMENT_ROLES, AUTOMATION_STATUSES, AUTOMATION_CONCURRENCY_POLICIES, AUTOMATION_CATCH_UP_POLICIES, AUTOMATION_OUTPUT_MODES, AUTOMATION_TRIGGER_SIGNING_MODES, PROJECT_COLORS, PROJECT_ICONS, APPROVAL_TYPES, SECRET_PROVIDERS, STORAGE_PROVIDERS, BILLING_TYPES, FINANCE_EVENT_KINDS, FINANCE_DIRECTIONS, FINANCE_UNITS, BUDGET_SCOPE_TYPES, BUDGET_METRICS, BUDGET_WINDOW_KINDS, BUDGET_INCIDENT_RESOLUTION_ACTIONS, INVITE_JOIN_TYPES, JOIN_REQUEST_TYPES, JOIN_REQUEST_STATUSES, PERMISSION_KEYS, PLUGIN_STATUSES, PLUGIN_CATEGORIES, PLUGIN_CAPABILITIES, PLUGIN_UI_SLOT_TYPES, PLUGIN_RESERVED_COMPANY_ROUTE_SEGMENTS, PLUGIN_LAUNCHER_PLACEMENT_ZONES, PLUGIN_LAUNCHER_ACTIONS, PLUGIN_LAUNCHER_BOUNDS, PLUGIN_LAUNCHER_RENDER_ENVIRONMENTS, PLUGIN_UI_SLOT_ENTITY_TYPES, PLUGIN_STATE_SCOPE_KINDS;
|
|
14
14
|
var init_constants = __esm({
|
|
15
15
|
"../packages/shared/dist/constants.js"() {
|
|
16
16
|
"use strict";
|
|
@@ -186,6 +186,24 @@ var init_constants = __esm({
|
|
|
186
186
|
"linear-gradient(135deg, #475569 0%, #0f766e 100%)",
|
|
187
187
|
"linear-gradient(135deg, #334155 0%, #7c3aed 100%)"
|
|
188
188
|
];
|
|
189
|
+
PROJECT_ICONS = [
|
|
190
|
+
"folder",
|
|
191
|
+
"book",
|
|
192
|
+
"plane",
|
|
193
|
+
"globe",
|
|
194
|
+
"code",
|
|
195
|
+
"rocket",
|
|
196
|
+
"target",
|
|
197
|
+
"lightbulb",
|
|
198
|
+
"wrench",
|
|
199
|
+
"shield",
|
|
200
|
+
"database",
|
|
201
|
+
"megaphone",
|
|
202
|
+
"palette",
|
|
203
|
+
"users",
|
|
204
|
+
"calendar",
|
|
205
|
+
"package"
|
|
206
|
+
];
|
|
189
207
|
APPROVAL_TYPES = [
|
|
190
208
|
"hire_agent",
|
|
191
209
|
"approve_ceo_strategy",
|
|
@@ -278,7 +296,6 @@ var init_constants = __esm({
|
|
|
278
296
|
"project.workspaces.read",
|
|
279
297
|
"issues.read",
|
|
280
298
|
"issue.comments.read",
|
|
281
|
-
"issue.documents.read",
|
|
282
299
|
"agents.read",
|
|
283
300
|
"goals.read",
|
|
284
301
|
"goals.create",
|
|
@@ -289,7 +306,6 @@ var init_constants = __esm({
|
|
|
289
306
|
"issues.create",
|
|
290
307
|
"issues.update",
|
|
291
308
|
"issue.comments.create",
|
|
292
|
-
"issue.documents.write",
|
|
293
309
|
"agents.pause",
|
|
294
310
|
"agents.resume",
|
|
295
311
|
"agents.invoke",
|
|
@@ -428,7 +444,7 @@ var init_workspace_backup = __esm({
|
|
|
428
444
|
|
|
429
445
|
// ../packages/shared/dist/validators/instance.js
|
|
430
446
|
import { z } from "zod";
|
|
431
|
-
var instanceLocaleSchema, instanceGeneralSettingsSchema, patchInstanceGeneralSettingsSchema, instanceNotificationSettingsSchema, patchInstanceNotificationSettingsSchema, instanceLangfuseSettingsSchema, patchInstanceLangfuseSettingsSchema, OPERATOR_PROFILE_MORE_ABOUT_YOU_MAX_LENGTH, operatorProfileSettingsSchema, patchOperatorProfileSettingsSchema, instancePathPickerSelectionTypeSchema, instancePathPickerRequestSchema, instancePathPickerResultSchema;
|
|
447
|
+
var instanceLocaleSchema, instanceGeneralSettingsSchema, patchInstanceGeneralSettingsSchema, instanceNotificationSettingsSchema, patchInstanceNotificationSettingsSchema, instanceLangfuseSettingsSchema, patchInstanceLangfuseSettingsSchema, OPERATOR_PROFILE_MORE_ABOUT_YOU_MAX_LENGTH, operatorProfileSettingsSchema, patchOperatorProfileSettingsSchema, KEYBOARD_SHORTCUT_ACTION_IDS, keyboardShortcutActionIdSchema, keyboardShortcutBindingSchema, keyboardShortcutPreferenceSchema, keyboardShortcutSettingsSchema, instancePathPickerSelectionTypeSchema, instancePathPickerRequestSchema, instancePathPickerResultSchema;
|
|
432
448
|
var init_instance = __esm({
|
|
433
449
|
"../packages/shared/dist/validators/instance.js"() {
|
|
434
450
|
"use strict";
|
|
@@ -468,6 +484,43 @@ var init_instance = __esm({
|
|
|
468
484
|
moreAboutYou: z.string().max(OPERATOR_PROFILE_MORE_ABOUT_YOU_MAX_LENGTH).default("")
|
|
469
485
|
}).strict();
|
|
470
486
|
patchOperatorProfileSettingsSchema = operatorProfileSettingsSchema.partial();
|
|
487
|
+
KEYBOARD_SHORTCUT_ACTION_IDS = [
|
|
488
|
+
"commandPalette.open",
|
|
489
|
+
"settings.open",
|
|
490
|
+
"issue.create",
|
|
491
|
+
"sidebar.toggle",
|
|
492
|
+
"panel.toggle"
|
|
493
|
+
];
|
|
494
|
+
keyboardShortcutActionIdSchema = z.enum(KEYBOARD_SHORTCUT_ACTION_IDS);
|
|
495
|
+
keyboardShortcutBindingSchema = z.object({
|
|
496
|
+
key: z.string().trim().min(1).max(64),
|
|
497
|
+
code: z.string().trim().min(1).max(80).optional(),
|
|
498
|
+
metaKey: z.boolean().optional(),
|
|
499
|
+
ctrlKey: z.boolean().optional(),
|
|
500
|
+
altKey: z.boolean().optional(),
|
|
501
|
+
shiftKey: z.boolean().optional()
|
|
502
|
+
}).strict();
|
|
503
|
+
keyboardShortcutPreferenceSchema = z.object({
|
|
504
|
+
actionId: keyboardShortcutActionIdSchema,
|
|
505
|
+
bindings: z.array(keyboardShortcutBindingSchema).max(4).optional(),
|
|
506
|
+
disabled: z.boolean().optional()
|
|
507
|
+
}).strict();
|
|
508
|
+
keyboardShortcutSettingsSchema = z.object({
|
|
509
|
+
shortcuts: z.array(keyboardShortcutPreferenceSchema).max(KEYBOARD_SHORTCUT_ACTION_IDS.length).default([])
|
|
510
|
+
}).strict().superRefine((value, ctx) => {
|
|
511
|
+
const seen = /* @__PURE__ */ new Set();
|
|
512
|
+
value.shortcuts.forEach((shortcut, index) => {
|
|
513
|
+
if (seen.has(shortcut.actionId)) {
|
|
514
|
+
ctx.addIssue({
|
|
515
|
+
code: z.ZodIssueCode.custom,
|
|
516
|
+
message: `Duplicate shortcut action id: ${shortcut.actionId}`,
|
|
517
|
+
path: ["shortcuts", index, "actionId"]
|
|
518
|
+
});
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
seen.add(shortcut.actionId);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
471
524
|
instancePathPickerSelectionTypeSchema = z.enum(["file", "directory"]);
|
|
472
525
|
instancePathPickerRequestSchema = z.object({
|
|
473
526
|
selectionType: instancePathPickerSelectionTypeSchema
|
|
@@ -912,6 +965,7 @@ var init_chat = __esm({
|
|
|
912
965
|
chatRichReferencesSchema = z8.array(chatRichReferenceSchema).max(5);
|
|
913
966
|
chatAutomationCreateSchema = z8.object({
|
|
914
967
|
title: z8.string().trim().min(1).max(200),
|
|
968
|
+
instructions: z8.string().trim().max(2e4).optional().nullable(),
|
|
915
969
|
description: z8.string().trim().max(2e4).optional().nullable(),
|
|
916
970
|
projectId: z8.string().uuid().optional().nullable(),
|
|
917
971
|
goalId: z8.string().uuid().optional().nullable(),
|
|
@@ -927,7 +981,10 @@ var init_chat = __esm({
|
|
|
927
981
|
label: z8.string().trim().max(120).optional().nullable(),
|
|
928
982
|
enabled: z8.boolean().optional().default(true)
|
|
929
983
|
})
|
|
930
|
-
})
|
|
984
|
+
}).transform(({ description, instructions, ...value }) => ({
|
|
985
|
+
...value,
|
|
986
|
+
instructions: instructions === void 0 ? description : instructions
|
|
987
|
+
}));
|
|
931
988
|
createChatAttachmentMetadataSchema = z8.object({
|
|
932
989
|
messageId: z8.string().uuid()
|
|
933
990
|
});
|
|
@@ -1571,7 +1628,7 @@ function validateProjectWorkspace(value, ctx) {
|
|
|
1571
1628
|
});
|
|
1572
1629
|
}
|
|
1573
1630
|
}
|
|
1574
|
-
var executionWorkspaceStrategySchema, projectExecutionWorkspacePolicySchema, projectWorkspaceSourceTypeSchema, projectWorkspaceVisibilitySchema, projectWorkspaceFields, projectColorValues, legacyProjectColorSchema, projectColorSchema, createProjectWorkspaceSchema, updateProjectWorkspaceSchema, projectFields, createProjectSchema, updateProjectSchema;
|
|
1631
|
+
var executionWorkspaceStrategySchema, projectExecutionWorkspacePolicySchema, projectWorkspaceSourceTypeSchema, projectWorkspaceVisibilitySchema, projectWorkspaceFields, projectColorValues, legacyProjectColorSchema, projectColorSchema, projectIconSchema, createProjectWorkspaceSchema, updateProjectWorkspaceSchema, projectFields, createProjectSchema, updateProjectSchema;
|
|
1575
1632
|
var init_project = __esm({
|
|
1576
1633
|
"../packages/shared/dist/validators/project.js"() {
|
|
1577
1634
|
"use strict";
|
|
@@ -1617,6 +1674,7 @@ var init_project = __esm({
|
|
|
1617
1674
|
projectColorValues = new Set(PROJECT_COLORS);
|
|
1618
1675
|
legacyProjectColorSchema = z13.string().regex(/^#[0-9a-fA-F]{6}$/);
|
|
1619
1676
|
projectColorSchema = z13.string().refine((value) => legacyProjectColorSchema.safeParse(value).success || projectColorValues.has(value), "Color must be a 6-digit hex value or a supported project gradient");
|
|
1677
|
+
projectIconSchema = z13.enum(PROJECT_ICONS);
|
|
1620
1678
|
createProjectWorkspaceSchema = z13.object({
|
|
1621
1679
|
...projectWorkspaceFields,
|
|
1622
1680
|
isPrimary: z13.boolean().optional().default(false)
|
|
@@ -1635,6 +1693,7 @@ var init_project = __esm({
|
|
|
1635
1693
|
leadAgentId: z13.string().uuid().optional().nullable(),
|
|
1636
1694
|
targetDate: z13.string().optional().nullable(),
|
|
1637
1695
|
color: projectColorSchema.optional().nullable(),
|
|
1696
|
+
icon: projectIconSchema.optional().nullable(),
|
|
1638
1697
|
executionWorkspacePolicy: projectExecutionWorkspacePolicySchema.optional().nullable(),
|
|
1639
1698
|
resourceAttachments: z13.array(projectResourceAttachmentInputSchema).optional(),
|
|
1640
1699
|
newResources: z13.array(createProjectInlineResourceSchema).optional(),
|
|
@@ -1649,12 +1708,12 @@ var init_project = __esm({
|
|
|
1649
1708
|
|
|
1650
1709
|
// ../packages/shared/dist/validators/issue.js
|
|
1651
1710
|
import { z as z14 } from "zod";
|
|
1652
|
-
var
|
|
1711
|
+
var runWorkspaceStrategySchema, issueRunWorkspaceSettingsSchema, issueAssigneeAdapterOverridesSchema, createIssueSchema, createIssueLabelSchema, updateIssueLabelSchema, updateIssueSchema, reorderIssueSchema, checkoutIssueSchema, addIssueCommentSchema, updateIssueCommentSchema, reportIssueCommitSchema, linkIssueApprovalSchema, createIssueAttachmentMetadataSchema, createIssueWorkspaceAttachmentSchema, ISSUE_DOCUMENT_FORMATS, issueDocumentFormatSchema, createLibraryDocumentSchema, updateLibraryDocumentSchema, restoreLibraryDocumentRevisionSchema;
|
|
1653
1712
|
var init_issue = __esm({
|
|
1654
1713
|
"../packages/shared/dist/validators/issue.js"() {
|
|
1655
1714
|
"use strict";
|
|
1656
1715
|
init_constants();
|
|
1657
|
-
|
|
1716
|
+
runWorkspaceStrategySchema = z14.object({
|
|
1658
1717
|
type: z14.enum(["project_primary", "git_worktree", "adapter_managed", "cloud_sandbox"]).optional(),
|
|
1659
1718
|
baseRef: z14.string().optional().nullable(),
|
|
1660
1719
|
branchTemplate: z14.string().optional().nullable(),
|
|
@@ -1662,9 +1721,9 @@ var init_issue = __esm({
|
|
|
1662
1721
|
provisionCommand: z14.string().optional().nullable(),
|
|
1663
1722
|
teardownCommand: z14.string().optional().nullable()
|
|
1664
1723
|
}).strict();
|
|
1665
|
-
|
|
1724
|
+
issueRunWorkspaceSettingsSchema = z14.object({
|
|
1666
1725
|
mode: z14.enum(["inherit", "shared_workspace", "isolated_workspace", "operator_branch", "reuse_existing", "agent_default"]).optional(),
|
|
1667
|
-
workspaceStrategy:
|
|
1726
|
+
workspaceStrategy: runWorkspaceStrategySchema.optional().nullable(),
|
|
1668
1727
|
workspaceRuntime: z14.record(z14.unknown()).optional().nullable()
|
|
1669
1728
|
}).strict();
|
|
1670
1729
|
issueAssigneeAdapterOverridesSchema = z14.object({
|
|
@@ -1687,7 +1746,19 @@ var init_issue = __esm({
|
|
|
1687
1746
|
requestDepth: z14.number().int().nonnegative().optional().default(0),
|
|
1688
1747
|
billingCode: z14.string().optional().nullable(),
|
|
1689
1748
|
assigneeAgentRuntimeOverrides: issueAssigneeAdapterOverridesSchema.optional().nullable(),
|
|
1749
|
+
runWorkspaceId: z14.string().uuid().optional().nullable(),
|
|
1750
|
+
runWorkspacePreference: z14.enum([
|
|
1751
|
+
"inherit",
|
|
1752
|
+
"shared_workspace",
|
|
1753
|
+
"isolated_workspace",
|
|
1754
|
+
"operator_branch",
|
|
1755
|
+
"reuse_existing",
|
|
1756
|
+
"agent_default"
|
|
1757
|
+
]).optional().nullable(),
|
|
1758
|
+
runWorkspaceSettings: issueRunWorkspaceSettingsSchema.optional().nullable(),
|
|
1759
|
+
/** @deprecated Use runWorkspaceId. */
|
|
1690
1760
|
executionWorkspaceId: z14.string().uuid().optional().nullable(),
|
|
1761
|
+
/** @deprecated Use runWorkspacePreference. */
|
|
1691
1762
|
executionWorkspacePreference: z14.enum([
|
|
1692
1763
|
"inherit",
|
|
1693
1764
|
"shared_workspace",
|
|
@@ -1696,7 +1767,8 @@ var init_issue = __esm({
|
|
|
1696
1767
|
"reuse_existing",
|
|
1697
1768
|
"agent_default"
|
|
1698
1769
|
]).optional().nullable(),
|
|
1699
|
-
|
|
1770
|
+
/** @deprecated Use runWorkspaceSettings. */
|
|
1771
|
+
executionWorkspaceSettings: issueRunWorkspaceSettingsSchema.optional().nullable(),
|
|
1700
1772
|
labelIds: z14.array(z14.string().uuid()).optional()
|
|
1701
1773
|
});
|
|
1702
1774
|
createIssueLabelSchema = z14.object({
|
|
@@ -1753,14 +1825,6 @@ var init_issue = __esm({
|
|
|
1753
1825
|
});
|
|
1754
1826
|
ISSUE_DOCUMENT_FORMATS = ["markdown"];
|
|
1755
1827
|
issueDocumentFormatSchema = z14.enum(ISSUE_DOCUMENT_FORMATS);
|
|
1756
|
-
issueDocumentKeySchema = z14.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/, "Document key must be lowercase letters, numbers, _ or -");
|
|
1757
|
-
upsertIssueDocumentSchema = z14.object({
|
|
1758
|
-
title: z14.string().trim().max(200).nullable().optional(),
|
|
1759
|
-
format: issueDocumentFormatSchema,
|
|
1760
|
-
body: z14.string().max(524288),
|
|
1761
|
-
changeSummary: z14.string().trim().max(500).nullable().optional(),
|
|
1762
|
-
baseRevisionId: z14.string().uuid().nullable().optional()
|
|
1763
|
-
});
|
|
1764
1828
|
createLibraryDocumentSchema = z14.object({
|
|
1765
1829
|
title: z14.string().trim().max(200).nullable().optional(),
|
|
1766
1830
|
format: issueDocumentFormatSchema.optional().default("markdown"),
|
|
@@ -1814,6 +1878,8 @@ var init_work_product = __esm({
|
|
|
1814
1878
|
]);
|
|
1815
1879
|
createIssueWorkProductSchema = z15.object({
|
|
1816
1880
|
projectId: z15.string().uuid().optional().nullable(),
|
|
1881
|
+
runWorkspaceId: z15.string().uuid().optional().nullable(),
|
|
1882
|
+
/** @deprecated Use runWorkspaceId. */
|
|
1817
1883
|
executionWorkspaceId: z15.string().uuid().optional().nullable(),
|
|
1818
1884
|
runtimeServiceId: z15.string().uuid().optional().nullable(),
|
|
1819
1885
|
type: issueWorkProductTypeSchema,
|
|
@@ -1835,19 +1901,19 @@ var init_work_product = __esm({
|
|
|
1835
1901
|
|
|
1836
1902
|
// ../packages/shared/dist/validators/execution-workspace.js
|
|
1837
1903
|
import { z as z16 } from "zod";
|
|
1838
|
-
var
|
|
1904
|
+
var runWorkspaceStatusSchema, updateRunWorkspaceSchema;
|
|
1839
1905
|
var init_execution_workspace = __esm({
|
|
1840
1906
|
"../packages/shared/dist/validators/execution-workspace.js"() {
|
|
1841
1907
|
"use strict";
|
|
1842
|
-
|
|
1908
|
+
runWorkspaceStatusSchema = z16.enum([
|
|
1843
1909
|
"active",
|
|
1844
1910
|
"idle",
|
|
1845
1911
|
"in_review",
|
|
1846
1912
|
"archived",
|
|
1847
1913
|
"cleanup_failed"
|
|
1848
1914
|
]);
|
|
1849
|
-
|
|
1850
|
-
status:
|
|
1915
|
+
updateRunWorkspaceSchema = z16.object({
|
|
1916
|
+
status: runWorkspaceStatusSchema.optional(),
|
|
1851
1917
|
cleanupEligibleAt: z16.string().datetime().optional().nullable(),
|
|
1852
1918
|
cleanupReason: z16.string().optional().nullable(),
|
|
1853
1919
|
metadata: z16.record(z16.unknown()).optional().nullable()
|
|
@@ -1923,22 +1989,31 @@ var init_approval = __esm({
|
|
|
1923
1989
|
|
|
1924
1990
|
// ../packages/shared/dist/validators/automation.js
|
|
1925
1991
|
import { z as z20 } from "zod";
|
|
1992
|
+
function normalizeAutomationInstructions(value) {
|
|
1993
|
+
const { instructions, ...rest } = value;
|
|
1994
|
+
return {
|
|
1995
|
+
...rest,
|
|
1996
|
+
description: instructions === void 0 ? value.description : instructions
|
|
1997
|
+
};
|
|
1998
|
+
}
|
|
1926
1999
|
function normalizeAutomationNotifications(value) {
|
|
1927
2000
|
if (value.outputMode !== "chat_output" || !value.notifyOnIssueCreated)
|
|
1928
2001
|
return value;
|
|
1929
2002
|
return { ...value, notifyOnIssueCreated: false };
|
|
1930
2003
|
}
|
|
1931
|
-
var
|
|
2004
|
+
var automationTextFieldSchema, automationBodyFieldsSchema, createAutomationSchema, updateAutomationSchema, baseTriggerSchema, createAutomationTriggerSchema, updateAutomationTriggerSchema, runAutomationSchema, rotateAutomationTriggerSecretSchema;
|
|
1932
2005
|
var init_automation = __esm({
|
|
1933
2006
|
"../packages/shared/dist/validators/automation.js"() {
|
|
1934
2007
|
"use strict";
|
|
1935
2008
|
init_constants();
|
|
1936
|
-
|
|
2009
|
+
automationTextFieldSchema = z20.string().optional().nullable();
|
|
2010
|
+
automationBodyFieldsSchema = z20.object({
|
|
1937
2011
|
projectId: z20.string().uuid().optional().nullable().default(null),
|
|
1938
2012
|
goalId: z20.string().uuid().optional().nullable(),
|
|
1939
2013
|
parentIssueId: z20.string().uuid().optional().nullable(),
|
|
1940
2014
|
title: z20.string().trim().min(1).max(200),
|
|
1941
|
-
|
|
2015
|
+
instructions: automationTextFieldSchema,
|
|
2016
|
+
description: automationTextFieldSchema,
|
|
1942
2017
|
assigneeAgentId: z20.string().uuid(),
|
|
1943
2018
|
priority: z20.enum(ISSUE_PRIORITIES).optional().default("medium"),
|
|
1944
2019
|
status: z20.enum(AUTOMATION_STATUSES).optional().default("active"),
|
|
@@ -1948,7 +2023,7 @@ var init_automation = __esm({
|
|
|
1948
2023
|
chatConversationId: z20.string().uuid().optional().nullable().default(null),
|
|
1949
2024
|
notifyOnIssueCreated: z20.boolean().optional().default(false)
|
|
1950
2025
|
});
|
|
1951
|
-
createAutomationSchema =
|
|
2026
|
+
createAutomationSchema = automationBodyFieldsSchema.superRefine((value, ctx) => {
|
|
1952
2027
|
if (value.chatConversationId) {
|
|
1953
2028
|
ctx.addIssue({
|
|
1954
2029
|
code: z20.ZodIssueCode.custom,
|
|
@@ -1956,8 +2031,8 @@ var init_automation = __esm({
|
|
|
1956
2031
|
message: "Chat output creates an automation-owned conversation; existing chats cannot be selected"
|
|
1957
2032
|
});
|
|
1958
2033
|
}
|
|
1959
|
-
}).transform(normalizeAutomationNotifications);
|
|
1960
|
-
updateAutomationSchema =
|
|
2034
|
+
}).transform(normalizeAutomationInstructions).transform(normalizeAutomationNotifications);
|
|
2035
|
+
updateAutomationSchema = automationBodyFieldsSchema.partial().superRefine((value, ctx) => {
|
|
1961
2036
|
if (value.chatConversationId) {
|
|
1962
2037
|
ctx.addIssue({
|
|
1963
2038
|
code: z20.ZodIssueCode.custom,
|
|
@@ -1965,7 +2040,7 @@ var init_automation = __esm({
|
|
|
1965
2040
|
message: "Chat output creates an automation-owned conversation; existing chats cannot be selected"
|
|
1966
2041
|
});
|
|
1967
2042
|
}
|
|
1968
|
-
}).transform(normalizeAutomationNotifications);
|
|
2043
|
+
}).transform(normalizeAutomationInstructions).transform(normalizeAutomationNotifications);
|
|
1969
2044
|
baseTriggerSchema = z20.object({
|
|
1970
2045
|
label: z20.string().trim().max(120).optional().nullable(),
|
|
1971
2046
|
enabled: z20.boolean().optional().default(true)
|
|
@@ -2713,7 +2788,7 @@ var init_organization_skill_reference = __esm({
|
|
|
2713
2788
|
});
|
|
2714
2789
|
|
|
2715
2790
|
// ../packages/shared/dist/project-mentions.js
|
|
2716
|
-
var AGENT_AVATAR_UUID_RE, AGENT_ASSET_ICON_RE, AGENT_DICEBEAR_NOTIONISTS_ICON_RE, PROJECT_COLOR_VALUES, AGENT_AVATAR_BACKGROUND_VALUES;
|
|
2791
|
+
var AGENT_AVATAR_UUID_RE, AGENT_ASSET_ICON_RE, AGENT_DICEBEAR_NOTIONISTS_ICON_RE, PROJECT_COLOR_VALUES, PROJECT_ICON_VALUES, AGENT_AVATAR_BACKGROUND_VALUES;
|
|
2717
2792
|
var init_project_mentions = __esm({
|
|
2718
2793
|
"../packages/shared/dist/project-mentions.js"() {
|
|
2719
2794
|
"use strict";
|
|
@@ -2722,12 +2797,13 @@ var init_project_mentions = __esm({
|
|
|
2722
2797
|
AGENT_ASSET_ICON_RE = new RegExp(`^asset:${AGENT_AVATAR_UUID_RE}(?:\\?bg=([a-z0-9-]+))?$`, "i");
|
|
2723
2798
|
AGENT_DICEBEAR_NOTIONISTS_ICON_RE = new RegExp(`^${AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX}${AGENT_AVATAR_UUID_RE}(?:\\?bg=([a-z0-9-]+))?$`, "i");
|
|
2724
2799
|
PROJECT_COLOR_VALUES = new Set(PROJECT_COLORS);
|
|
2800
|
+
PROJECT_ICON_VALUES = new Set(PROJECT_ICONS);
|
|
2725
2801
|
AGENT_AVATAR_BACKGROUND_VALUES = new Set(AGENT_AVATAR_BACKGROUND_PRESET_IDS);
|
|
2726
2802
|
}
|
|
2727
2803
|
});
|
|
2728
2804
|
|
|
2729
2805
|
// ../packages/shared/dist/issue-activity.js
|
|
2730
|
-
var ISSUE_UPDATE_ACTIVITY_METADATA_KEYS, LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELDS, ISSUE_UPDATE_ACTIVITY_METADATA_KEY_SET, LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELD_SET;
|
|
2806
|
+
var ISSUE_UPDATE_ACTIVITY_METADATA_KEYS, LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELDS, INTERNAL_ISSUE_UPDATE_ACTIVITY_FIELDS, ISSUE_UPDATE_ACTIVITY_METADATA_KEY_SET, LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELD_SET, INTERNAL_ISSUE_UPDATE_ACTIVITY_FIELD_SET;
|
|
2731
2807
|
var init_issue_activity = __esm({
|
|
2732
2808
|
"../packages/shared/dist/issue-activity.js"() {
|
|
2733
2809
|
"use strict";
|
|
@@ -2743,8 +2819,19 @@ var init_issue_activity = __esm({
|
|
|
2743
2819
|
"normalizedReason"
|
|
2744
2820
|
];
|
|
2745
2821
|
LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELDS = ["description", "title"];
|
|
2822
|
+
INTERNAL_ISSUE_UPDATE_ACTIVITY_FIELDS = [
|
|
2823
|
+
"executionWorkspaceId",
|
|
2824
|
+
"executionWorkspacePreference",
|
|
2825
|
+
"executionWorkspaceSettings",
|
|
2826
|
+
"currentExecutionWorkspace",
|
|
2827
|
+
"runWorkspaceId",
|
|
2828
|
+
"runWorkspacePreference",
|
|
2829
|
+
"runWorkspaceSettings",
|
|
2830
|
+
"currentRunWorkspace"
|
|
2831
|
+
];
|
|
2746
2832
|
ISSUE_UPDATE_ACTIVITY_METADATA_KEY_SET = new Set(ISSUE_UPDATE_ACTIVITY_METADATA_KEYS);
|
|
2747
2833
|
LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELD_SET = new Set(LOW_SIGNAL_ISSUE_UPDATE_ACTIVITY_FIELDS);
|
|
2834
|
+
INTERNAL_ISSUE_UPDATE_ACTIVITY_FIELD_SET = new Set(INTERNAL_ISSUE_UPDATE_ACTIVITY_FIELDS);
|
|
2748
2835
|
}
|
|
2749
2836
|
});
|
|
2750
2837
|
|
|
@@ -10665,54 +10752,6 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
10665
10752
|
requiresRunId: false,
|
|
10666
10753
|
attachesRunIdWhenAvailable: true
|
|
10667
10754
|
},
|
|
10668
|
-
{
|
|
10669
|
-
id: "issue.documents.list",
|
|
10670
|
-
command: "rudder issue documents list <issue>",
|
|
10671
|
-
category: "issue",
|
|
10672
|
-
description: "List issue documents.",
|
|
10673
|
-
mutating: false,
|
|
10674
|
-
contract: "agent-v1",
|
|
10675
|
-
requiresOrgId: false,
|
|
10676
|
-
requiresAgentId: false,
|
|
10677
|
-
requiresRunId: false,
|
|
10678
|
-
attachesRunIdWhenAvailable: false
|
|
10679
|
-
},
|
|
10680
|
-
{
|
|
10681
|
-
id: "issue.documents.get",
|
|
10682
|
-
command: "rudder issue documents get <issue> <key>",
|
|
10683
|
-
category: "issue",
|
|
10684
|
-
description: "Read one issue document by key.",
|
|
10685
|
-
mutating: false,
|
|
10686
|
-
contract: "agent-v1",
|
|
10687
|
-
requiresOrgId: false,
|
|
10688
|
-
requiresAgentId: false,
|
|
10689
|
-
requiresRunId: false,
|
|
10690
|
-
attachesRunIdWhenAvailable: false
|
|
10691
|
-
},
|
|
10692
|
-
{
|
|
10693
|
-
id: "issue.documents.put",
|
|
10694
|
-
command: "rudder issue documents put <issue> <key> --body-file <path>",
|
|
10695
|
-
category: "issue",
|
|
10696
|
-
description: "Legacy create or update of a DB-backed issue document; prefer `rudder library file put` for durable project files.",
|
|
10697
|
-
mutating: true,
|
|
10698
|
-
contract: "compat",
|
|
10699
|
-
requiresOrgId: false,
|
|
10700
|
-
requiresAgentId: false,
|
|
10701
|
-
requiresRunId: false,
|
|
10702
|
-
attachesRunIdWhenAvailable: true
|
|
10703
|
-
},
|
|
10704
|
-
{
|
|
10705
|
-
id: "issue.documents.revisions",
|
|
10706
|
-
command: "rudder issue documents revisions <issue> <key>",
|
|
10707
|
-
category: "issue",
|
|
10708
|
-
description: "List revisions for an issue document.",
|
|
10709
|
-
mutating: false,
|
|
10710
|
-
contract: "agent-v1",
|
|
10711
|
-
requiresOrgId: false,
|
|
10712
|
-
requiresAgentId: false,
|
|
10713
|
-
requiresRunId: false,
|
|
10714
|
-
attachesRunIdWhenAvailable: false
|
|
10715
|
-
},
|
|
10716
10755
|
{
|
|
10717
10756
|
id: "project.list",
|
|
10718
10757
|
command: "rudder project list --org-id <id>",
|
|
@@ -10765,7 +10804,7 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
10765
10804
|
id: "library.file.list",
|
|
10766
10805
|
command: "rudder library file list [directory]",
|
|
10767
10806
|
category: "library",
|
|
10768
|
-
description: "List
|
|
10807
|
+
description: "List Library files and folders; file rows include `libraryEntryId` when a strong reference can be generated.",
|
|
10769
10808
|
mutating: false,
|
|
10770
10809
|
contract: "agent-v1",
|
|
10771
10810
|
requiresOrgId: true,
|
|
@@ -10777,7 +10816,31 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
10777
10816
|
id: "library.file.get",
|
|
10778
10817
|
command: "rudder library file get <path>",
|
|
10779
10818
|
category: "library",
|
|
10780
|
-
description: "
|
|
10819
|
+
description: "Fallback read when local filesystem access is unavailable; JSON includes `mentionHref` and `markdownLink`.",
|
|
10820
|
+
mutating: false,
|
|
10821
|
+
contract: "agent-v1",
|
|
10822
|
+
requiresOrgId: true,
|
|
10823
|
+
requiresAgentId: false,
|
|
10824
|
+
requiresRunId: false,
|
|
10825
|
+
attachesRunIdWhenAvailable: false
|
|
10826
|
+
},
|
|
10827
|
+
{
|
|
10828
|
+
id: "library.file.ref",
|
|
10829
|
+
command: "rudder library file ref <path>",
|
|
10830
|
+
category: "library",
|
|
10831
|
+
description: "Return the stable Markdown reference for one Library file without printing file content.",
|
|
10832
|
+
mutating: false,
|
|
10833
|
+
contract: "agent-v1",
|
|
10834
|
+
requiresOrgId: true,
|
|
10835
|
+
requiresAgentId: false,
|
|
10836
|
+
requiresRunId: false,
|
|
10837
|
+
attachesRunIdWhenAvailable: false
|
|
10838
|
+
},
|
|
10839
|
+
{
|
|
10840
|
+
id: "library.file.link",
|
|
10841
|
+
command: "rudder library file link <path>",
|
|
10842
|
+
category: "library",
|
|
10843
|
+
description: "Compatibility alias for `rudder library file ref <path>`.",
|
|
10781
10844
|
mutating: false,
|
|
10782
10845
|
contract: "agent-v1",
|
|
10783
10846
|
requiresOrgId: true,
|
|
@@ -10789,7 +10852,7 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
10789
10852
|
id: "library.file.put",
|
|
10790
10853
|
command: "rudder library file put <path> --body-file <path>",
|
|
10791
10854
|
category: "library",
|
|
10792
|
-
description: "
|
|
10855
|
+
description: "Fallback create/update when local filesystem access is unavailable; JSON includes `mentionHref` and `markdownLink`.",
|
|
10793
10856
|
mutating: true,
|
|
10794
10857
|
contract: "agent-v1",
|
|
10795
10858
|
requiresOrgId: true,
|
|
@@ -10952,403 +11015,1493 @@ var AGENT_CLI_CAPABILITIES = [
|
|
|
10952
11015
|
requiresAgentId: false,
|
|
10953
11016
|
requiresRunId: false,
|
|
10954
11017
|
attachesRunIdWhenAvailable: true
|
|
10955
|
-
}
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
}
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
}
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
}
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11018
|
+
},
|
|
11019
|
+
{
|
|
11020
|
+
id: "automation.list",
|
|
11021
|
+
command: "rudder automation list --org-id <id>",
|
|
11022
|
+
category: "automation",
|
|
11023
|
+
description: "List automations for an organization with compact local filters.",
|
|
11024
|
+
mutating: false,
|
|
11025
|
+
contract: "agent-v1",
|
|
11026
|
+
requiresOrgId: true,
|
|
11027
|
+
requiresAgentId: false,
|
|
11028
|
+
requiresRunId: false,
|
|
11029
|
+
attachesRunIdWhenAvailable: false
|
|
11030
|
+
},
|
|
11031
|
+
{
|
|
11032
|
+
id: "automation.get",
|
|
11033
|
+
command: "rudder automation get <automation-id>",
|
|
11034
|
+
category: "automation",
|
|
11035
|
+
description: "Read one automation detail including triggers and recent runs.",
|
|
11036
|
+
mutating: false,
|
|
11037
|
+
contract: "agent-v1",
|
|
11038
|
+
requiresOrgId: false,
|
|
11039
|
+
requiresAgentId: false,
|
|
11040
|
+
requiresRunId: false,
|
|
11041
|
+
attachesRunIdWhenAvailable: false
|
|
11042
|
+
},
|
|
11043
|
+
{
|
|
11044
|
+
id: "automation.runs",
|
|
11045
|
+
command: "rudder automation runs <automation-id>",
|
|
11046
|
+
category: "automation",
|
|
11047
|
+
description: "List recent runs for one automation.",
|
|
11048
|
+
mutating: false,
|
|
11049
|
+
contract: "agent-v1",
|
|
11050
|
+
requiresOrgId: false,
|
|
11051
|
+
requiresAgentId: false,
|
|
11052
|
+
requiresRunId: false,
|
|
11053
|
+
attachesRunIdWhenAvailable: false
|
|
11054
|
+
},
|
|
11055
|
+
{
|
|
11056
|
+
id: "automation.triggers.list",
|
|
11057
|
+
command: "rudder automation triggers list <automation-id>",
|
|
11058
|
+
category: "automation",
|
|
11059
|
+
description: "List triggers configured for one automation.",
|
|
11060
|
+
mutating: false,
|
|
11061
|
+
contract: "agent-v1",
|
|
11062
|
+
requiresOrgId: false,
|
|
11063
|
+
requiresAgentId: false,
|
|
11064
|
+
requiresRunId: false,
|
|
11065
|
+
attachesRunIdWhenAvailable: false
|
|
11066
|
+
},
|
|
11067
|
+
{
|
|
11068
|
+
id: "automation.create",
|
|
11069
|
+
command: "rudder automation create --org-id <id> --title <title> --assignee-agent-id <id>",
|
|
11070
|
+
category: "automation",
|
|
11071
|
+
description: "Create an automation through the governed automation API.",
|
|
11072
|
+
mutating: true,
|
|
11073
|
+
contract: "agent-v1",
|
|
11074
|
+
requiresOrgId: true,
|
|
11075
|
+
requiresAgentId: false,
|
|
11076
|
+
requiresRunId: false,
|
|
11077
|
+
attachesRunIdWhenAvailable: true
|
|
11078
|
+
},
|
|
11079
|
+
{
|
|
11080
|
+
id: "automation.update",
|
|
11081
|
+
command: "rudder automation update <automation-id>",
|
|
11082
|
+
category: "automation",
|
|
11083
|
+
description: "Update automation fields through the governed automation API.",
|
|
11084
|
+
mutating: true,
|
|
11085
|
+
contract: "agent-v1",
|
|
11086
|
+
requiresOrgId: false,
|
|
11087
|
+
requiresAgentId: false,
|
|
11088
|
+
requiresRunId: false,
|
|
11089
|
+
attachesRunIdWhenAvailable: true
|
|
11090
|
+
},
|
|
11091
|
+
{
|
|
11092
|
+
id: "automation.enable",
|
|
11093
|
+
command: "rudder automation enable <automation-id>",
|
|
11094
|
+
category: "automation",
|
|
11095
|
+
description: "Enable an automation by setting status to active.",
|
|
11096
|
+
mutating: true,
|
|
11097
|
+
contract: "agent-v1",
|
|
11098
|
+
requiresOrgId: false,
|
|
11099
|
+
requiresAgentId: false,
|
|
11100
|
+
requiresRunId: false,
|
|
11101
|
+
attachesRunIdWhenAvailable: true
|
|
11102
|
+
},
|
|
11103
|
+
{
|
|
11104
|
+
id: "automation.disable",
|
|
11105
|
+
command: "rudder automation disable <automation-id>",
|
|
11106
|
+
category: "automation",
|
|
11107
|
+
description: "Disable an automation by setting status to paused.",
|
|
11108
|
+
mutating: true,
|
|
11109
|
+
contract: "agent-v1",
|
|
11110
|
+
requiresOrgId: false,
|
|
11111
|
+
requiresAgentId: false,
|
|
11112
|
+
requiresRunId: false,
|
|
11113
|
+
attachesRunIdWhenAvailable: true
|
|
11114
|
+
},
|
|
11115
|
+
{
|
|
11116
|
+
id: "automation.run",
|
|
11117
|
+
command: "rudder automation run <automation-id>",
|
|
11118
|
+
category: "automation",
|
|
11119
|
+
description: "Trigger a manual automation run.",
|
|
11120
|
+
mutating: true,
|
|
11121
|
+
contract: "agent-v1",
|
|
11122
|
+
requiresOrgId: false,
|
|
11123
|
+
requiresAgentId: false,
|
|
11124
|
+
requiresRunId: false,
|
|
11125
|
+
attachesRunIdWhenAvailable: true
|
|
11126
|
+
},
|
|
11127
|
+
{
|
|
11128
|
+
id: "chat.list",
|
|
11129
|
+
command: "rudder chat list --org-id <id>",
|
|
11130
|
+
category: "chat",
|
|
11131
|
+
description: "List chat conversations without dumping full message history.",
|
|
11132
|
+
mutating: false,
|
|
11133
|
+
contract: "agent-v1",
|
|
11134
|
+
requiresOrgId: true,
|
|
11135
|
+
requiresAgentId: false,
|
|
11136
|
+
requiresRunId: false,
|
|
11137
|
+
attachesRunIdWhenAvailable: false
|
|
11138
|
+
},
|
|
11139
|
+
{
|
|
11140
|
+
id: "chat.search",
|
|
11141
|
+
command: "rudder chat search <query> --org-id <id>",
|
|
11142
|
+
category: "chat",
|
|
11143
|
+
description: "Search chats with bounded snippets and optional scope filtering.",
|
|
11144
|
+
mutating: false,
|
|
11145
|
+
contract: "agent-v1",
|
|
11146
|
+
requiresOrgId: true,
|
|
11147
|
+
requiresAgentId: false,
|
|
11148
|
+
requiresRunId: false,
|
|
11149
|
+
attachesRunIdWhenAvailable: false
|
|
11150
|
+
},
|
|
11151
|
+
{
|
|
11152
|
+
id: "chat.get",
|
|
11153
|
+
command: "rudder chat get <chat-id>",
|
|
11154
|
+
category: "chat",
|
|
11155
|
+
description: "Read one chat conversation record.",
|
|
11156
|
+
mutating: false,
|
|
11157
|
+
contract: "agent-v1",
|
|
11158
|
+
requiresOrgId: false,
|
|
11159
|
+
requiresAgentId: false,
|
|
11160
|
+
requiresRunId: false,
|
|
11161
|
+
attachesRunIdWhenAvailable: false
|
|
11162
|
+
},
|
|
11163
|
+
{
|
|
11164
|
+
id: "chat.messages",
|
|
11165
|
+
command: "rudder chat messages <chat-id> [--limit <n>] [--cursor <cursor>] [--include-transcript]",
|
|
11166
|
+
category: "chat",
|
|
11167
|
+
description: "Read bounded chat messages with page cursors; transcript output is omitted unless requested.",
|
|
11168
|
+
mutating: false,
|
|
11169
|
+
contract: "agent-v1",
|
|
11170
|
+
requiresOrgId: false,
|
|
11171
|
+
requiresAgentId: false,
|
|
11172
|
+
requiresRunId: false,
|
|
11173
|
+
attachesRunIdWhenAvailable: false
|
|
11174
|
+
},
|
|
11175
|
+
{
|
|
11176
|
+
id: "chat.transcript",
|
|
11177
|
+
command: "rudder chat transcript <chat-id> [--limit <n>] [--cursor <cursor>] [--max-output-chars <n>]",
|
|
11178
|
+
category: "chat",
|
|
11179
|
+
description: "Read paginated chat messages with assistant transcript entries clipped in human output.",
|
|
11180
|
+
mutating: false,
|
|
11181
|
+
contract: "agent-v1",
|
|
11182
|
+
requiresOrgId: false,
|
|
11183
|
+
requiresAgentId: false,
|
|
11184
|
+
requiresRunId: false,
|
|
11185
|
+
attachesRunIdWhenAvailable: false
|
|
11186
|
+
},
|
|
11187
|
+
{
|
|
11188
|
+
id: "chat.read",
|
|
11189
|
+
command: "rudder chat read <chat-id> [--turn-limit <n>] [--cursor <cursor>] [--include-output]",
|
|
11190
|
+
category: "chat",
|
|
11191
|
+
description: "Read a bounded recent-message snapshot for one chat with page cursors.",
|
|
11192
|
+
mutating: false,
|
|
11193
|
+
contract: "agent-v1",
|
|
11194
|
+
requiresOrgId: false,
|
|
11195
|
+
requiresAgentId: false,
|
|
11196
|
+
requiresRunId: false,
|
|
11197
|
+
attachesRunIdWhenAvailable: false
|
|
11198
|
+
},
|
|
11199
|
+
{
|
|
11200
|
+
id: "chat.create",
|
|
11201
|
+
command: "rudder chat create --org-id <id>",
|
|
11202
|
+
category: "chat",
|
|
11203
|
+
description: "Create a chat conversation.",
|
|
11204
|
+
mutating: true,
|
|
11205
|
+
contract: "agent-v1",
|
|
11206
|
+
requiresOrgId: true,
|
|
11207
|
+
requiresAgentId: false,
|
|
11208
|
+
requiresRunId: false,
|
|
11209
|
+
attachesRunIdWhenAvailable: true
|
|
11210
|
+
},
|
|
11211
|
+
{
|
|
11212
|
+
id: "chat.send",
|
|
11213
|
+
command: "rudder chat send <chat-id> --body <text>",
|
|
11214
|
+
category: "chat",
|
|
11215
|
+
description: "Send a chat message and persist the assistant reply through the server.",
|
|
11216
|
+
mutating: true,
|
|
11217
|
+
contract: "agent-v1",
|
|
11218
|
+
requiresOrgId: false,
|
|
11219
|
+
requiresAgentId: false,
|
|
11220
|
+
requiresRunId: false,
|
|
11221
|
+
attachesRunIdWhenAvailable: true
|
|
11222
|
+
},
|
|
11223
|
+
{
|
|
11224
|
+
id: "chat.archive",
|
|
11225
|
+
command: "rudder chat archive <chat-id>",
|
|
11226
|
+
category: "chat",
|
|
11227
|
+
description: "Archive a chat conversation without deleting it.",
|
|
11228
|
+
mutating: true,
|
|
11229
|
+
contract: "agent-v1",
|
|
11230
|
+
requiresOrgId: false,
|
|
11231
|
+
requiresAgentId: false,
|
|
11232
|
+
requiresRunId: false,
|
|
11233
|
+
attachesRunIdWhenAvailable: true
|
|
11234
|
+
},
|
|
11235
|
+
{
|
|
11236
|
+
id: "runs.list",
|
|
11237
|
+
command: "rudder runs list --org-id <id>",
|
|
11238
|
+
category: "runs",
|
|
11239
|
+
description: "List observed agent runs with filters for status, agent, issue, runtime, and time.",
|
|
11240
|
+
mutating: false,
|
|
11241
|
+
contract: "agent-v1",
|
|
11242
|
+
requiresOrgId: true,
|
|
11243
|
+
requiresAgentId: false,
|
|
11244
|
+
requiresRunId: false,
|
|
11245
|
+
attachesRunIdWhenAvailable: false
|
|
11246
|
+
},
|
|
11247
|
+
{
|
|
11248
|
+
id: "runs.get",
|
|
11249
|
+
command: "rudder runs get <run-id>",
|
|
11250
|
+
category: "runs",
|
|
11251
|
+
description: "Read one observed run detail.",
|
|
11252
|
+
mutating: false,
|
|
11253
|
+
contract: "agent-v1",
|
|
11254
|
+
requiresOrgId: false,
|
|
11255
|
+
requiresAgentId: false,
|
|
11256
|
+
requiresRunId: false,
|
|
11257
|
+
attachesRunIdWhenAvailable: false
|
|
11258
|
+
},
|
|
11259
|
+
{
|
|
11260
|
+
id: "runs.events",
|
|
11261
|
+
command: "rudder runs events <run-id>",
|
|
11262
|
+
category: "runs",
|
|
11263
|
+
description: "List persisted run events.",
|
|
11264
|
+
mutating: false,
|
|
11265
|
+
contract: "agent-v1",
|
|
11266
|
+
requiresOrgId: false,
|
|
11267
|
+
requiresAgentId: false,
|
|
11268
|
+
requiresRunId: false,
|
|
11269
|
+
attachesRunIdWhenAvailable: false
|
|
11270
|
+
},
|
|
11271
|
+
{
|
|
11272
|
+
id: "runs.log",
|
|
11273
|
+
command: "rudder runs log <run-id>",
|
|
11274
|
+
category: "runs",
|
|
11275
|
+
description: "Read stored run log content with clipped human output.",
|
|
11276
|
+
mutating: false,
|
|
11277
|
+
contract: "agent-v1",
|
|
11278
|
+
requiresOrgId: false,
|
|
11279
|
+
requiresAgentId: false,
|
|
11280
|
+
requiresRunId: false,
|
|
11281
|
+
attachesRunIdWhenAvailable: false
|
|
11282
|
+
},
|
|
11283
|
+
{
|
|
11284
|
+
id: "runs.transcript",
|
|
11285
|
+
command: "rudder runs transcript <run-id> [--turn-limit <n>] [--cursor <cursor>] [--include-output]",
|
|
11286
|
+
category: "runs",
|
|
11287
|
+
description: "Read the server-normalized run transcript; human output is compact and JSON includes full entries.",
|
|
11288
|
+
mutating: false,
|
|
11289
|
+
contract: "agent-v1",
|
|
11290
|
+
requiresOrgId: false,
|
|
11291
|
+
requiresAgentId: false,
|
|
11292
|
+
requiresRunId: false,
|
|
11293
|
+
attachesRunIdWhenAvailable: false
|
|
11294
|
+
},
|
|
11295
|
+
{
|
|
11296
|
+
id: "runs.errors",
|
|
11297
|
+
command: "rudder runs errors <run-id>",
|
|
11298
|
+
category: "runs",
|
|
11299
|
+
description: "List failed tool calls, stderr, runtime failures, and jump-to-context commands.",
|
|
11300
|
+
mutating: false,
|
|
11301
|
+
contract: "agent-v1",
|
|
11302
|
+
requiresOrgId: false,
|
|
11303
|
+
requiresAgentId: false,
|
|
11304
|
+
requiresRunId: false,
|
|
11305
|
+
attachesRunIdWhenAvailable: false
|
|
11306
|
+
},
|
|
11307
|
+
{
|
|
11308
|
+
id: "runs.cancel",
|
|
11309
|
+
command: "rudder runs cancel <run-id>",
|
|
11310
|
+
category: "runs",
|
|
11311
|
+
description: "Cancel a heartbeat run through the governed server route.",
|
|
11312
|
+
mutating: true,
|
|
11313
|
+
contract: "agent-v1",
|
|
11314
|
+
requiresOrgId: false,
|
|
11315
|
+
requiresAgentId: false,
|
|
11316
|
+
requiresRunId: false,
|
|
11317
|
+
attachesRunIdWhenAvailable: true
|
|
11318
|
+
},
|
|
11319
|
+
{
|
|
11320
|
+
id: "runs.retry",
|
|
11321
|
+
command: "rudder runs retry <run-id>",
|
|
11322
|
+
category: "runs",
|
|
11323
|
+
description: "Retry a failed, timed out, or cancelled run through the governed server route.",
|
|
11324
|
+
mutating: true,
|
|
11325
|
+
contract: "agent-v1",
|
|
11326
|
+
requiresOrgId: false,
|
|
11327
|
+
requiresAgentId: false,
|
|
11328
|
+
requiresRunId: false,
|
|
11329
|
+
attachesRunIdWhenAvailable: true
|
|
11330
|
+
}
|
|
11331
|
+
];
|
|
11332
|
+
var CATEGORY_TITLES = {
|
|
11333
|
+
agent: "Agent",
|
|
11334
|
+
issue: "Issue",
|
|
11335
|
+
project: "Project",
|
|
11336
|
+
automation: "Automation",
|
|
11337
|
+
chat: "Chat",
|
|
11338
|
+
runs: "Runs",
|
|
11339
|
+
approval: "Approval",
|
|
11340
|
+
skill: "Skill",
|
|
11341
|
+
library: "Library"
|
|
11342
|
+
};
|
|
11343
|
+
function getAgentCliCapabilities() {
|
|
11344
|
+
return AGENT_CLI_CAPABILITIES.map((entry) => ({ ...entry }));
|
|
11345
|
+
}
|
|
11346
|
+
function getAgentCliCapabilityById(id) {
|
|
11347
|
+
const entry = AGENT_CLI_CAPABILITIES.find((capability) => capability.id === id);
|
|
11348
|
+
if (!entry) {
|
|
11349
|
+
throw new Error(`Unknown agent CLI capability: ${id}`);
|
|
11350
|
+
}
|
|
11351
|
+
return entry;
|
|
11352
|
+
}
|
|
11353
|
+
function buildAgentCliCapabilitiesManifest(contract = "agent-v1") {
|
|
11354
|
+
const capabilities = AGENT_CLI_CAPABILITIES.filter((entry) => contract === "all" || entry.contract === contract).map((entry) => ({
|
|
11355
|
+
...entry,
|
|
11356
|
+
agentV1: entry.contract === "agent-v1"
|
|
11357
|
+
}));
|
|
11358
|
+
return {
|
|
11359
|
+
schema: "rudder.agent-capabilities/v1",
|
|
11360
|
+
contract,
|
|
11361
|
+
defaults: {
|
|
11362
|
+
orgIdEnvVar: "RUDDER_ORG_ID",
|
|
11363
|
+
agentIdEnvVar: "RUDDER_AGENT_ID",
|
|
11364
|
+
runIdEnvVar: "RUDDER_RUN_ID",
|
|
11365
|
+
jsonErrors: "stderr-error-envelope"
|
|
11366
|
+
},
|
|
11367
|
+
capabilities
|
|
11368
|
+
};
|
|
11369
|
+
}
|
|
11370
|
+
function formatAgentCliCapabilitiesHumanReadable(capabilities = getAgentCliCapabilities()) {
|
|
11371
|
+
const lines = [];
|
|
11372
|
+
for (const category of Object.keys(CATEGORY_TITLES)) {
|
|
11373
|
+
const entries = capabilities.filter((capability) => capability.category === category);
|
|
11374
|
+
if (entries.length === 0) continue;
|
|
11375
|
+
lines.push(`${CATEGORY_TITLES[category]} commands:`);
|
|
11376
|
+
for (const entry of entries) {
|
|
11377
|
+
const tags = [
|
|
11378
|
+
entry.contract,
|
|
11379
|
+
entry.mutating ? "mutating" : "read-only",
|
|
11380
|
+
entry.requiresOrgId ? "org" : null,
|
|
11381
|
+
entry.requiresAgentId ? "agent" : null,
|
|
11382
|
+
entry.attachesRunIdWhenAvailable ? "run-id" : null
|
|
11383
|
+
].filter(Boolean);
|
|
11384
|
+
lines.push(`- ${entry.command} \u2014 ${entry.description} [${tags.join(", ")}]`);
|
|
11385
|
+
}
|
|
11386
|
+
lines.push("");
|
|
11387
|
+
}
|
|
11388
|
+
return lines.join("\n").trimEnd();
|
|
11389
|
+
}
|
|
11390
|
+
|
|
11391
|
+
// src/commands/client/issue.ts
|
|
11392
|
+
function registerIssueCommands(program) {
|
|
11393
|
+
const issue = program.command("issue").description("Issue operations");
|
|
11394
|
+
addCommonClientOptions(
|
|
11395
|
+
issue.command("list").description("List issues for an organization").option("-O, --org-id <id>", "Organization ID").option("--status <csv>", "Comma-separated statuses").option("--assignee-agent-id <id>", "Filter by assignee agent ID").option("--project-id <id>", "Filter by project ID").option("--query <text>", "Server-side search on identifier/title/description/comments").option("--match <text>", "Local text match on identifier/title/description").action(async (opts) => {
|
|
11396
|
+
try {
|
|
11397
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11398
|
+
const rows = await ctx.api.get(buildIssueListPath(ctx.orgId, opts, opts.query)) ?? [];
|
|
11399
|
+
const filtered = filterIssueRows(rows, opts.match);
|
|
11400
|
+
printIssueRows(filtered, ctx.json);
|
|
11401
|
+
} catch (err) {
|
|
11402
|
+
handleCommandError(err);
|
|
11403
|
+
}
|
|
11404
|
+
}),
|
|
11405
|
+
{ includeCompany: false }
|
|
11406
|
+
);
|
|
11407
|
+
addCommonClientOptions(
|
|
11408
|
+
issue.command("search").description(getAgentCliCapabilityById("issue.search").description).argument("<query>", "Server-side issue search query").option("-O, --org-id <id>", "Organization ID").option("--status <csv>", "Comma-separated statuses").option("--assignee-agent-id <id>", "Filter by assignee agent ID").option("--project-id <id>", "Filter by project ID").action(async (query, opts) => {
|
|
11409
|
+
try {
|
|
11410
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11411
|
+
const rows = await ctx.api.get(buildIssueListPath(ctx.orgId, opts, query)) ?? [];
|
|
11412
|
+
printIssueRows(rows, ctx.json);
|
|
11413
|
+
} catch (err) {
|
|
11414
|
+
handleCommandError(err);
|
|
11415
|
+
}
|
|
11416
|
+
}),
|
|
11417
|
+
{ includeCompany: false }
|
|
11418
|
+
);
|
|
11419
|
+
addCommonClientOptions(
|
|
11420
|
+
issue.command("get").description(getAgentCliCapabilityById("issue.get").description).argument("<idOrIdentifier>", "Issue ID or identifier").action(async (idOrIdentifier, opts) => {
|
|
11421
|
+
try {
|
|
11422
|
+
const ctx = resolveCommandContext(opts);
|
|
11423
|
+
const row = await ctx.api.get(`/api/issues/${idOrIdentifier}`);
|
|
11424
|
+
printOutput(row, { json: ctx.json });
|
|
11425
|
+
} catch (err) {
|
|
11426
|
+
handleCommandError(err);
|
|
11427
|
+
}
|
|
11428
|
+
})
|
|
11429
|
+
);
|
|
11430
|
+
addCommonClientOptions(
|
|
11431
|
+
issue.command("context").description(getAgentCliCapabilityById("issue.context").description).argument("<issueId>", "Issue ID or identifier").option("--wake-comment-id <id>", "Fetch one wake comment in the heartbeat context response").action(async (issueId, opts) => {
|
|
11432
|
+
try {
|
|
11433
|
+
const ctx = resolveCommandContext(opts);
|
|
11434
|
+
const params = new URLSearchParams();
|
|
11435
|
+
if (opts.wakeCommentId) params.set("wakeCommentId", opts.wakeCommentId);
|
|
11436
|
+
const query = params.toString();
|
|
11437
|
+
const row = await ctx.api.get(
|
|
11438
|
+
`/api/issues/${issueId}/heartbeat-context${query ? `?${query}` : ""}`
|
|
11439
|
+
);
|
|
11440
|
+
printOutput(row, { json: ctx.json });
|
|
11441
|
+
} catch (err) {
|
|
11442
|
+
handleCommandError(err);
|
|
11443
|
+
}
|
|
11444
|
+
})
|
|
11445
|
+
);
|
|
11446
|
+
addCommonClientOptions(
|
|
11447
|
+
issue.command("labels").description("Issue label operations").command("list").description("List issue labels for an organization").option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
11448
|
+
try {
|
|
11449
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11450
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/labels`) ?? [];
|
|
11451
|
+
printOutput(rows, { json: ctx.json });
|
|
11452
|
+
} catch (err) {
|
|
11453
|
+
handleCommandError(err);
|
|
11454
|
+
}
|
|
11455
|
+
}),
|
|
11456
|
+
{ includeCompany: false }
|
|
11457
|
+
);
|
|
11458
|
+
addCommonClientOptions(
|
|
11459
|
+
issue.command("create").description(getAgentCliCapabilityById("issue.create").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--label-id <id>", "Issue label ID; may be repeated", collectNonEmptyOption("--label-id"), []).option("--label <name>", "Issue label name to resolve exactly; may be repeated", collectNonEmptyOption("--label"), []).action(async (opts) => {
|
|
11460
|
+
try {
|
|
11461
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11462
|
+
const labelIds = await resolveIssueLabelIds(ctx, opts);
|
|
11463
|
+
const payload = createIssueSchema.parse({
|
|
11464
|
+
title: opts.title,
|
|
11465
|
+
description: opts.description,
|
|
11466
|
+
status: opts.status,
|
|
11467
|
+
priority: opts.priority,
|
|
11468
|
+
assigneeAgentId: opts.assigneeAgentId,
|
|
11469
|
+
projectId: opts.projectId,
|
|
11470
|
+
goalId: opts.goalId,
|
|
11471
|
+
parentId: opts.parentId,
|
|
11472
|
+
requestDepth: parseOptionalInt(opts.requestDepth),
|
|
11473
|
+
billingCode: opts.billingCode,
|
|
11474
|
+
labelIds: labelIds.length > 0 ? labelIds : void 0
|
|
11475
|
+
});
|
|
11476
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/issues`, payload);
|
|
11477
|
+
printOutput(created, { json: ctx.json });
|
|
11478
|
+
} catch (err) {
|
|
11479
|
+
handleCommandError(err);
|
|
11480
|
+
}
|
|
11481
|
+
}),
|
|
11482
|
+
{ includeCompany: false }
|
|
11483
|
+
);
|
|
11484
|
+
addCommonClientOptions(
|
|
11485
|
+
issue.command("update").description(getAgentCliCapabilityById("issue.update").description).argument("<issueId>", "Issue ID").option("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--status <status>", "Issue status").option("--priority <priority>", "Issue priority").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-id <id>", "Parent issue ID").option("--request-depth <n>", "Request depth integer").option("--billing-code <code>", "Billing code").option("--comment-file <path>", "Read optional update comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the update comment; may be repeated", collectImagePath, []).option("--hidden-at <iso8601|null>", "Set hiddenAt timestamp or literal 'null'").action(async (issueId, opts) => {
|
|
11486
|
+
try {
|
|
11487
|
+
const ctx = resolveCommandContext(opts);
|
|
11488
|
+
const commentText = await resolveFileTextInput({
|
|
11489
|
+
file: opts.commentFile,
|
|
11490
|
+
fileOption: "--comment-file",
|
|
11491
|
+
removedTextOption: "--comment",
|
|
11492
|
+
required: false
|
|
11493
|
+
});
|
|
11494
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
|
|
11495
|
+
const payload = updateIssueSchema.parse({
|
|
11496
|
+
title: opts.title,
|
|
11497
|
+
description: opts.description,
|
|
11498
|
+
status: opts.status,
|
|
11499
|
+
priority: opts.priority,
|
|
11500
|
+
assigneeAgentId: opts.assigneeAgentId,
|
|
11501
|
+
projectId: opts.projectId,
|
|
11502
|
+
goalId: opts.goalId,
|
|
11503
|
+
parentId: opts.parentId,
|
|
11504
|
+
requestDepth: parseOptionalInt(opts.requestDepth),
|
|
11505
|
+
billingCode: opts.billingCode,
|
|
11506
|
+
comment,
|
|
11507
|
+
hiddenAt: parseHiddenAt(opts.hiddenAt)
|
|
11508
|
+
});
|
|
11509
|
+
const updated = await ctx.api.patch(`/api/issues/${issueId}`, payload);
|
|
11510
|
+
printOutput(updated, { json: ctx.json });
|
|
11511
|
+
} catch (err) {
|
|
11512
|
+
handleCommandError(err);
|
|
11513
|
+
}
|
|
11514
|
+
})
|
|
11515
|
+
);
|
|
11516
|
+
addCommonClientOptions(
|
|
11517
|
+
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").action(async (issueId, opts) => {
|
|
11518
|
+
try {
|
|
11519
|
+
const ctx = resolveCommandContext(opts);
|
|
11520
|
+
const bodyText = await resolveFileTextInput({
|
|
11521
|
+
file: opts.bodyFile,
|
|
11522
|
+
fileOption: "--body-file",
|
|
11523
|
+
removedTextOption: "--body",
|
|
11524
|
+
required: true
|
|
11525
|
+
});
|
|
11526
|
+
const body = await appendUploadedIssueImages(ctx, issueId, bodyText, opts.image);
|
|
11527
|
+
const payload = addIssueCommentSchema.parse({
|
|
11528
|
+
body,
|
|
11529
|
+
reopen: opts.reopen
|
|
11530
|
+
});
|
|
11531
|
+
const comment = await ctx.api.post(`/api/issues/${issueId}/comments`, payload);
|
|
11532
|
+
if (!isIssueCommentResponse(comment)) {
|
|
11533
|
+
throw new Error("Issue comment request completed without a persisted comment response");
|
|
11534
|
+
}
|
|
11535
|
+
printOutput(comment, { json: ctx.json });
|
|
11536
|
+
} catch (err) {
|
|
11537
|
+
handleCommandError(err);
|
|
11538
|
+
}
|
|
11539
|
+
})
|
|
11540
|
+
);
|
|
11541
|
+
addCommonClientOptions(
|
|
11542
|
+
issue.command("review").description(getAgentCliCapabilityById("issue.review").description).argument("<issueId>", "Issue ID").requiredOption(
|
|
11543
|
+
"--decision <decision>",
|
|
11544
|
+
"Review decision: approve, request_changes, needs_followup, or blocked"
|
|
11545
|
+
).option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").action(async (issueId, opts) => {
|
|
11546
|
+
try {
|
|
11547
|
+
const ctx = resolveCommandContext(opts);
|
|
11548
|
+
const decision = parseReviewDecision(opts.decision);
|
|
11549
|
+
const comment = await resolveFileTextInput({
|
|
11550
|
+
file: opts.commentFile,
|
|
11551
|
+
fileOption: "--comment-file",
|
|
11552
|
+
removedTextOption: "--comment",
|
|
11553
|
+
required: true
|
|
11554
|
+
});
|
|
11555
|
+
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11556
|
+
reviewDecision: decision,
|
|
11557
|
+
comment
|
|
11558
|
+
});
|
|
11559
|
+
printOutput(updated, { json: ctx.json });
|
|
11560
|
+
} catch (err) {
|
|
11561
|
+
handleCommandError(err);
|
|
11562
|
+
}
|
|
11563
|
+
})
|
|
11564
|
+
);
|
|
11565
|
+
addCommonClientOptions(
|
|
11566
|
+
issue.command("commit").description(getAgentCliCapabilityById("issue.commit").description).argument("<issueId>", "Issue ID").requiredOption("--sha <sha>", "Commit SHA").requiredOption("--message <subject>", "Commit subject or message").option("--branch <name>", "Branch name").option("--repo-path <path>", "Repository path").option("--workspace-path <path>", "Workspace path").option("--count <n>", "Number of commits represented by this report").action(async (issueId, opts) => {
|
|
11567
|
+
try {
|
|
11568
|
+
const ctx = resolveCommandContext(opts);
|
|
11569
|
+
const payload = reportIssueCommitSchema.parse({
|
|
11570
|
+
sha: opts.sha,
|
|
11571
|
+
message: opts.message,
|
|
11572
|
+
branch: opts.branch,
|
|
11573
|
+
repoPath: opts.repoPath,
|
|
11574
|
+
workspacePath: opts.workspacePath,
|
|
11575
|
+
commitCount: parseOptionalInt(opts.count)
|
|
11576
|
+
});
|
|
11577
|
+
const reported = await ctx.api.post(`/api/issues/${issueId}/commit`, payload);
|
|
11578
|
+
printOutput(reported, { json: ctx.json });
|
|
11579
|
+
} catch (err) {
|
|
11580
|
+
handleCommandError(err);
|
|
11581
|
+
}
|
|
11582
|
+
})
|
|
11583
|
+
);
|
|
11584
|
+
addCommonClientOptions(
|
|
11585
|
+
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, []).action(async (issueId, opts) => {
|
|
11586
|
+
try {
|
|
11587
|
+
const ctx = resolveCommandContext(opts);
|
|
11588
|
+
const commentText = await resolveFileTextInput({
|
|
11589
|
+
file: opts.commentFile,
|
|
11590
|
+
fileOption: "--comment-file",
|
|
11591
|
+
removedTextOption: "--comment",
|
|
11592
|
+
required: true
|
|
11593
|
+
});
|
|
11594
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
|
|
11595
|
+
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11596
|
+
status: "done",
|
|
11597
|
+
comment
|
|
11598
|
+
});
|
|
11599
|
+
printOutput(updated, { json: ctx.json });
|
|
11600
|
+
} catch (err) {
|
|
11601
|
+
handleCommandError(err);
|
|
11602
|
+
}
|
|
11603
|
+
})
|
|
11604
|
+
);
|
|
11605
|
+
addCommonClientOptions(
|
|
11606
|
+
issue.command("block").description(getAgentCliCapabilityById("issue.block").description).argument("<issueId>", "Issue ID").option("--comment-file <path>", "Read required blocker comment from a file, or '-' for stdin").option("--image <path>", "Image file to upload and append to the blocker comment; may be repeated", collectImagePath, []).action(async (issueId, opts) => {
|
|
11607
|
+
try {
|
|
11608
|
+
const ctx = resolveCommandContext(opts);
|
|
11609
|
+
const commentText = await resolveFileTextInput({
|
|
11610
|
+
file: opts.commentFile,
|
|
11611
|
+
fileOption: "--comment-file",
|
|
11612
|
+
removedTextOption: "--comment",
|
|
11613
|
+
required: true
|
|
11614
|
+
});
|
|
11615
|
+
const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
|
|
11616
|
+
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11617
|
+
status: "blocked",
|
|
11618
|
+
comment
|
|
11619
|
+
});
|
|
11620
|
+
printOutput(updated, { json: ctx.json });
|
|
11621
|
+
} catch (err) {
|
|
11622
|
+
handleCommandError(err);
|
|
11623
|
+
}
|
|
11624
|
+
})
|
|
11625
|
+
);
|
|
11626
|
+
const comments = issue.command("comments").description("Issue comment operations");
|
|
11627
|
+
addCommonClientOptions(
|
|
11628
|
+
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) => {
|
|
11629
|
+
try {
|
|
11630
|
+
const ctx = resolveCommandContext(opts);
|
|
11631
|
+
const params = new URLSearchParams();
|
|
11632
|
+
if (opts.after) params.set("after", opts.after);
|
|
11633
|
+
if (opts.order) params.set("order", opts.order);
|
|
11634
|
+
const query = params.toString();
|
|
11635
|
+
const rows = await ctx.api.get(
|
|
11636
|
+
`/api/issues/${issueId}/comments${query ? `?${query}` : ""}`
|
|
11637
|
+
) ?? [];
|
|
11638
|
+
printOutput(rows, { json: ctx.json });
|
|
11639
|
+
} catch (err) {
|
|
11640
|
+
handleCommandError(err);
|
|
11641
|
+
}
|
|
11642
|
+
})
|
|
11643
|
+
);
|
|
11644
|
+
addCommonClientOptions(
|
|
11645
|
+
comments.command("get").description(getAgentCliCapabilityById("issue.comments.get").description).argument("<issueId>", "Issue ID").argument("<commentId>", "Comment ID").action(async (issueId, commentId, opts) => {
|
|
11646
|
+
try {
|
|
11647
|
+
const ctx = resolveCommandContext(opts);
|
|
11648
|
+
const row = await ctx.api.get(`/api/issues/${issueId}/comments/${commentId}`);
|
|
11649
|
+
printOutput(row, { json: ctx.json });
|
|
11650
|
+
} catch (err) {
|
|
11651
|
+
handleCommandError(err);
|
|
11652
|
+
}
|
|
11653
|
+
})
|
|
11654
|
+
);
|
|
11655
|
+
addCommonClientOptions(
|
|
11656
|
+
issue.command("checkout").description(getAgentCliCapabilityById("issue.checkout").description).argument("<issueId>", "Issue ID").option("--agent-id <id>", "Agent ID (defaults to RUDDER_AGENT_ID)").option(
|
|
11657
|
+
"--expected-statuses <csv>",
|
|
11658
|
+
"Expected current statuses",
|
|
11659
|
+
"todo,backlog,blocked"
|
|
11660
|
+
).action(async (issueId, opts) => {
|
|
11661
|
+
try {
|
|
11662
|
+
const ctx = resolveCommandContext(opts);
|
|
11663
|
+
const agentId = opts.agentId?.trim() || ctx.agentId;
|
|
11664
|
+
if (!agentId) {
|
|
11665
|
+
throw new Error("Agent ID is required. Pass --agent-id or set RUDDER_AGENT_ID.");
|
|
11666
|
+
}
|
|
11667
|
+
const payload = checkoutIssueSchema.parse({
|
|
11668
|
+
agentId,
|
|
11669
|
+
expectedStatuses: parseCsv(opts.expectedStatuses)
|
|
11670
|
+
});
|
|
11671
|
+
const updated = await ctx.api.post(`/api/issues/${issueId}/checkout`, payload);
|
|
11672
|
+
printOutput(updated, { json: ctx.json });
|
|
11673
|
+
} catch (err) {
|
|
11674
|
+
handleCommandError(err);
|
|
11675
|
+
}
|
|
11676
|
+
})
|
|
11677
|
+
);
|
|
11678
|
+
addCommonClientOptions(
|
|
11679
|
+
issue.command("release").description(getAgentCliCapabilityById("issue.release").description).argument("<issueId>", "Issue ID").action(async (issueId, opts) => {
|
|
11680
|
+
try {
|
|
11681
|
+
const ctx = resolveCommandContext(opts);
|
|
11682
|
+
const updated = await ctx.api.post(`/api/issues/${issueId}/release`, {});
|
|
11683
|
+
printOutput(updated, { json: ctx.json });
|
|
11684
|
+
} catch (err) {
|
|
11685
|
+
handleCommandError(err);
|
|
11686
|
+
}
|
|
11687
|
+
})
|
|
11688
|
+
);
|
|
11689
|
+
}
|
|
11690
|
+
function collectImagePath(value, previous) {
|
|
11691
|
+
const trimmed = value.trim();
|
|
11692
|
+
if (!trimmed) {
|
|
11693
|
+
throw new Error("--image path cannot be empty");
|
|
11694
|
+
}
|
|
11695
|
+
return [...previous, trimmed];
|
|
11696
|
+
}
|
|
11697
|
+
function collectNonEmptyOption(optionName) {
|
|
11698
|
+
return (value, previous) => {
|
|
11699
|
+
const trimmed = value.trim();
|
|
11700
|
+
if (!trimmed) {
|
|
11701
|
+
throw new Error(`${optionName} cannot be empty`);
|
|
11702
|
+
}
|
|
11703
|
+
return [...previous, trimmed];
|
|
11704
|
+
};
|
|
11705
|
+
}
|
|
11706
|
+
async function resolveFileTextInput(opts) {
|
|
11707
|
+
if (opts.removedTextOption && process.argv.includes(opts.removedTextOption)) {
|
|
11708
|
+
throw new Error(`${opts.removedTextOption} was removed; write the body to a file and use ${opts.fileOption} <path> or ${opts.fileOption} - for stdin`);
|
|
11709
|
+
}
|
|
11710
|
+
const hasFile = opts.file !== void 0;
|
|
11711
|
+
if (hasFile) return readTextInputFile(opts.file, opts.fileOption);
|
|
11712
|
+
if (opts.required) {
|
|
11713
|
+
throw new Error(`Provide ${opts.fileOption} <path>; use ${opts.fileOption} - for stdin`);
|
|
11714
|
+
}
|
|
11715
|
+
return void 0;
|
|
11716
|
+
}
|
|
11717
|
+
async function readTextInputFile(inputPath, optionName) {
|
|
11718
|
+
if (inputPath === "-") {
|
|
11719
|
+
return readStdinText();
|
|
11720
|
+
}
|
|
11721
|
+
const resolvedPath = path16.resolve(process.cwd(), inputPath);
|
|
11722
|
+
return readFile4(resolvedPath, "utf8").catch((err) => {
|
|
11723
|
+
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
11724
|
+
});
|
|
11725
|
+
}
|
|
11726
|
+
async function readStdinText() {
|
|
11727
|
+
const chunks = [];
|
|
11728
|
+
for await (const chunk of process.stdin) {
|
|
11729
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
11730
|
+
}
|
|
11731
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
11732
|
+
}
|
|
11733
|
+
async function resolveIssueLabelIds(ctx, opts) {
|
|
11734
|
+
const explicitIds = opts.labelId ?? [];
|
|
11735
|
+
const names = opts.label ?? [];
|
|
11736
|
+
if (names.length === 0 && explicitIds.length > 0) return [...new Set(explicitIds)];
|
|
11737
|
+
if (names.length === 0 && opts.parentId) return [];
|
|
11738
|
+
const labels = await ctx.api.get(`/api/orgs/${ctx.orgId}/labels`) ?? [];
|
|
11739
|
+
if (names.length === 0) {
|
|
11740
|
+
if (ctx.agentId && labels.length >= 5) {
|
|
11741
|
+
throw new Error(
|
|
11742
|
+
`Organization has ${labels.length} issue labels. Choose at least one with --label-id <id> or --label <name>. Available labels: ${formatAvailableLabelNames(labels)}`
|
|
11743
|
+
);
|
|
11744
|
+
}
|
|
11745
|
+
return [];
|
|
11746
|
+
}
|
|
11747
|
+
const resolvedIds = names.map((name) => {
|
|
11748
|
+
const exact = labels.find((label) => label.name === name) ?? labels.find((label) => label.name.toLowerCase() === name.toLowerCase());
|
|
11749
|
+
if (!exact) {
|
|
11750
|
+
throw new Error(`Unknown issue label "${name}". Available labels: ${formatAvailableLabelNames(labels)}`);
|
|
11751
|
+
}
|
|
11752
|
+
return exact.id;
|
|
11753
|
+
});
|
|
11754
|
+
return [.../* @__PURE__ */ new Set([...explicitIds, ...resolvedIds])];
|
|
11755
|
+
}
|
|
11756
|
+
function formatAvailableLabelNames(labels) {
|
|
11757
|
+
return labels.map((label) => label.name).join(", ") || "(none)";
|
|
11758
|
+
}
|
|
11759
|
+
async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
|
|
11760
|
+
const paths = imagePaths ?? [];
|
|
11761
|
+
if (paths.length === 0) return body;
|
|
11762
|
+
const issue = await ctx.api.get(`/api/issues/${issueId}`);
|
|
11763
|
+
if (!issue) {
|
|
11764
|
+
throw new Error("Issue not found");
|
|
11765
|
+
}
|
|
11766
|
+
const links = [];
|
|
11767
|
+
for (const imagePath of paths) {
|
|
11768
|
+
const attachment = await uploadIssueCommentImage(ctx, issue, imagePath);
|
|
11769
|
+
links.push(formatAttachmentMarkdown(attachment));
|
|
11770
|
+
}
|
|
11771
|
+
const base = body?.trimEnd() ?? "";
|
|
11772
|
+
const imageBlock = links.join("\n");
|
|
11773
|
+
return base ? `${base}
|
|
11774
|
+
|
|
11775
|
+
${imageBlock}` : imageBlock;
|
|
11776
|
+
}
|
|
11777
|
+
async function uploadIssueCommentImage(ctx, issue, imagePath) {
|
|
11778
|
+
const resolvedPath = path16.resolve(process.cwd(), imagePath);
|
|
11779
|
+
const stats = await stat4(resolvedPath).catch((err) => {
|
|
11780
|
+
throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
11781
|
+
});
|
|
11782
|
+
if (!stats.isFile()) {
|
|
11783
|
+
throw new Error(`Image path must be a file: ${imagePath}`);
|
|
11784
|
+
}
|
|
11785
|
+
const filename = path16.basename(resolvedPath);
|
|
11786
|
+
const contentType = inferCommentImageContentType(filename);
|
|
11787
|
+
const buffer = await readFile4(resolvedPath);
|
|
11788
|
+
if (buffer.length <= 0) {
|
|
11789
|
+
throw new Error(`Image is empty: ${imagePath}`);
|
|
11790
|
+
}
|
|
11791
|
+
const form = new FormData();
|
|
11792
|
+
form.set("usage", "comment_inline");
|
|
11793
|
+
form.set("file", new Blob([buffer], { type: contentType }), filename);
|
|
11794
|
+
const attachment = await ctx.api.postForm(
|
|
11795
|
+
`/api/orgs/${issue.orgId}/issues/${issue.id}/attachments`,
|
|
11796
|
+
form
|
|
11797
|
+
);
|
|
11798
|
+
if (!attachment) {
|
|
11799
|
+
throw new Error(`Image upload returned no attachment: ${imagePath}`);
|
|
11800
|
+
}
|
|
11801
|
+
return attachment;
|
|
11802
|
+
}
|
|
11803
|
+
function inferCommentImageContentType(filename) {
|
|
11804
|
+
const ext = path16.extname(filename).toLowerCase();
|
|
11805
|
+
switch (ext) {
|
|
11806
|
+
case ".png":
|
|
11807
|
+
return "image/png";
|
|
11808
|
+
case ".jpg":
|
|
11809
|
+
case ".jpeg":
|
|
11810
|
+
return "image/jpeg";
|
|
11811
|
+
case ".webp":
|
|
11812
|
+
return "image/webp";
|
|
11813
|
+
case ".gif":
|
|
11814
|
+
return "image/gif";
|
|
11815
|
+
default:
|
|
11816
|
+
throw new Error(`Unsupported comment image type: ${filename}. Use PNG, JPEG, WebP, or GIF.`);
|
|
11817
|
+
}
|
|
11818
|
+
}
|
|
11819
|
+
function formatAttachmentMarkdown(attachment) {
|
|
11820
|
+
const alt = escapeMarkdownAltText(attachment.originalFilename ?? "image");
|
|
11821
|
+
return ``;
|
|
11822
|
+
}
|
|
11823
|
+
function escapeMarkdownAltText(value) {
|
|
11824
|
+
return value.replaceAll("\\", "\\\\").replaceAll("]", "\\]");
|
|
11825
|
+
}
|
|
11826
|
+
function parseCsv(value) {
|
|
11827
|
+
if (!value) return [];
|
|
11828
|
+
return value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
11829
|
+
}
|
|
11830
|
+
function parseOptionalInt(value) {
|
|
11831
|
+
if (value === void 0) return void 0;
|
|
11832
|
+
const parsed = Number.parseInt(value, 10);
|
|
11833
|
+
if (!Number.isFinite(parsed)) {
|
|
11834
|
+
throw new Error(`Invalid integer value: ${value}`);
|
|
11835
|
+
}
|
|
11836
|
+
return parsed;
|
|
11837
|
+
}
|
|
11838
|
+
function parseHiddenAt(value) {
|
|
11839
|
+
if (value === void 0) return void 0;
|
|
11840
|
+
if (value.trim().toLowerCase() === "null") return null;
|
|
11841
|
+
return value;
|
|
11842
|
+
}
|
|
11843
|
+
function parseReviewDecision(value) {
|
|
11844
|
+
const normalized = value.trim();
|
|
11845
|
+
if (normalized === "approve" || normalized === "request_changes" || normalized === "needs_followup" || normalized === "blocked") {
|
|
11846
|
+
return normalized;
|
|
11847
|
+
}
|
|
11848
|
+
throw new Error("Invalid review decision. Use approve, request_changes, needs_followup, or blocked.");
|
|
11849
|
+
}
|
|
11850
|
+
function isIssueCommentResponse(value) {
|
|
11851
|
+
return Boolean(
|
|
11852
|
+
value && typeof value.id === "string" && value.id.trim().length > 0 && typeof value.issueId === "string" && value.issueId.trim().length > 0 && typeof value.body === "string"
|
|
11853
|
+
);
|
|
11854
|
+
}
|
|
11855
|
+
function filterIssueRows(rows, match) {
|
|
11856
|
+
if (!match?.trim()) return rows;
|
|
11857
|
+
const needle = match.trim().toLowerCase();
|
|
11858
|
+
return rows.filter((row) => {
|
|
11859
|
+
const text6 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
|
|
11860
|
+
return text6.includes(needle);
|
|
11861
|
+
});
|
|
11862
|
+
}
|
|
11863
|
+
function buildIssueListPath(orgId, opts, searchQuery) {
|
|
11864
|
+
const params = new URLSearchParams();
|
|
11865
|
+
if (opts.status) params.set("status", opts.status);
|
|
11866
|
+
if (opts.assigneeAgentId) params.set("assigneeAgentId", opts.assigneeAgentId);
|
|
11867
|
+
if (opts.projectId) params.set("projectId", opts.projectId);
|
|
11868
|
+
if (searchQuery?.trim()) {
|
|
11869
|
+
params.set("q", searchQuery.trim());
|
|
11870
|
+
params.set("searchFields", "title,description,comment");
|
|
11871
|
+
}
|
|
11872
|
+
const query = params.toString();
|
|
11873
|
+
return `/api/orgs/${orgId}/issues${query ? `?${query}` : ""}`;
|
|
11874
|
+
}
|
|
11875
|
+
function printIssueRows(rows, json) {
|
|
11876
|
+
if (json) {
|
|
11877
|
+
printOutput(rows, { json: true });
|
|
11878
|
+
return;
|
|
11879
|
+
}
|
|
11880
|
+
if (rows.length === 0) {
|
|
11881
|
+
printOutput([], { json: false });
|
|
11882
|
+
return;
|
|
11883
|
+
}
|
|
11884
|
+
for (const item of rows) {
|
|
11885
|
+
console.log(
|
|
11886
|
+
formatInlineRecord({
|
|
11887
|
+
identifier: item.identifier,
|
|
11888
|
+
id: item.id,
|
|
11889
|
+
status: item.status,
|
|
11890
|
+
priority: item.priority,
|
|
11891
|
+
assigneeAgentId: item.assigneeAgentId,
|
|
11892
|
+
assigneeUserId: item.assigneeUserId,
|
|
11893
|
+
title: item.title,
|
|
11894
|
+
projectId: item.projectId,
|
|
11895
|
+
updatedAt: item.updatedAt,
|
|
11896
|
+
...item.searchMatch ? { match: formatIssueSearchMatch(item.searchMatch) } : {}
|
|
11897
|
+
})
|
|
11898
|
+
);
|
|
11899
|
+
}
|
|
11900
|
+
}
|
|
11901
|
+
function formatIssueSearchMatch(match) {
|
|
11902
|
+
const commentSuffix = match.commentId ? `#${match.commentId}` : "";
|
|
11903
|
+
return `${match.field}${commentSuffix}: ${match.snippet}`;
|
|
11904
|
+
}
|
|
11905
|
+
|
|
11906
|
+
// src/commands/client/project.ts
|
|
11907
|
+
init_dist();
|
|
11908
|
+
function registerProjectCommands(program) {
|
|
11909
|
+
const project = program.command("project").description("Project operations");
|
|
11910
|
+
addCommonClientOptions(
|
|
11911
|
+
project.command("list").description(getAgentCliCapabilityById("project.list").description).option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
11912
|
+
try {
|
|
11913
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11914
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/projects`) ?? [];
|
|
11915
|
+
printOutput(rows, { json: ctx.json });
|
|
11916
|
+
} catch (err) {
|
|
11917
|
+
handleCommandError(err);
|
|
11918
|
+
}
|
|
11919
|
+
}),
|
|
11920
|
+
{ includeCompany: false }
|
|
11921
|
+
);
|
|
11922
|
+
addCommonClientOptions(
|
|
11923
|
+
project.command("get").description(getAgentCliCapabilityById("project.get").description).argument("<projectIdOrShortname>", "Project ID or shortname").option("-O, --org-id <id>", "Organization ID for shortname resolution").action(async (projectRef, opts) => {
|
|
11924
|
+
try {
|
|
11925
|
+
const ctx = resolveCommandContext(opts);
|
|
11926
|
+
const row = await ctx.api.get(projectPath(projectRef, ctx.orgId));
|
|
11927
|
+
printOutput(row, { json: ctx.json });
|
|
11928
|
+
} catch (err) {
|
|
11929
|
+
handleCommandError(err);
|
|
11930
|
+
}
|
|
11931
|
+
}),
|
|
11932
|
+
{ includeCompany: false }
|
|
11933
|
+
);
|
|
11934
|
+
addCommonClientOptions(
|
|
11935
|
+
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").action(async (opts) => {
|
|
11936
|
+
try {
|
|
11937
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11938
|
+
const payload = createProjectSchema.parse({
|
|
11939
|
+
name: opts.name,
|
|
11940
|
+
description: opts.description,
|
|
11120
11941
|
status: opts.status,
|
|
11121
|
-
priority: opts.priority,
|
|
11122
|
-
assigneeAgentId: opts.assigneeAgentId,
|
|
11123
|
-
projectId: opts.projectId,
|
|
11124
11942
|
goalId: opts.goalId,
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
hiddenAt: parseHiddenAt(opts.hiddenAt)
|
|
11943
|
+
goalIds: parseCsv2(opts.goalIds),
|
|
11944
|
+
leadAgentId: opts.leadAgentId,
|
|
11945
|
+
targetDate: opts.targetDate,
|
|
11946
|
+
color: opts.color
|
|
11130
11947
|
});
|
|
11131
|
-
const
|
|
11948
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/projects`, payload);
|
|
11949
|
+
printOutput(created, { json: ctx.json });
|
|
11950
|
+
} catch (err) {
|
|
11951
|
+
handleCommandError(err);
|
|
11952
|
+
}
|
|
11953
|
+
}),
|
|
11954
|
+
{ includeCompany: false }
|
|
11955
|
+
);
|
|
11956
|
+
addCommonClientOptions(
|
|
11957
|
+
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'").action(async (projectRef, opts) => {
|
|
11958
|
+
try {
|
|
11959
|
+
const ctx = resolveCommandContext(opts);
|
|
11960
|
+
const payload = updateProjectSchema.parse({
|
|
11961
|
+
name: opts.name,
|
|
11962
|
+
description: opts.description,
|
|
11963
|
+
status: opts.status,
|
|
11964
|
+
goalId: opts.goalId,
|
|
11965
|
+
goalIds: parseCsv2(opts.goalIds),
|
|
11966
|
+
leadAgentId: opts.leadAgentId,
|
|
11967
|
+
targetDate: opts.targetDate,
|
|
11968
|
+
color: opts.color,
|
|
11969
|
+
archivedAt: parseNullableOption(opts.archivedAt)
|
|
11970
|
+
});
|
|
11971
|
+
const updated = await ctx.api.patch(projectPath(projectRef, ctx.orgId), payload);
|
|
11132
11972
|
printOutput(updated, { json: ctx.json });
|
|
11133
11973
|
} catch (err) {
|
|
11134
11974
|
handleCommandError(err);
|
|
11135
11975
|
}
|
|
11976
|
+
}),
|
|
11977
|
+
{ includeCompany: false }
|
|
11978
|
+
);
|
|
11979
|
+
}
|
|
11980
|
+
function parseCsv2(value) {
|
|
11981
|
+
if (!value) return void 0;
|
|
11982
|
+
const items = value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
11983
|
+
return items.length > 0 ? items : void 0;
|
|
11984
|
+
}
|
|
11985
|
+
function parseNullableOption(value) {
|
|
11986
|
+
if (value === void 0) return void 0;
|
|
11987
|
+
return value === "null" ? null : value;
|
|
11988
|
+
}
|
|
11989
|
+
function projectPath(projectRef, orgId) {
|
|
11990
|
+
const params = new URLSearchParams();
|
|
11991
|
+
if (orgId) params.set("orgId", orgId);
|
|
11992
|
+
const query = params.toString();
|
|
11993
|
+
return `/api/projects/${encodeURIComponent(projectRef)}${query ? `?${query}` : ""}`;
|
|
11994
|
+
}
|
|
11995
|
+
|
|
11996
|
+
// src/commands/client/agent.ts
|
|
11997
|
+
init_dist();
|
|
11998
|
+
|
|
11999
|
+
// ../packages/agent-runtime-utils/dist/server-utils.process.js
|
|
12000
|
+
var MAX_CAPTURE_BYTES = 4 * 1024 * 1024;
|
|
12001
|
+
var MAX_EXCERPT_BYTES = 32 * 1024;
|
|
12002
|
+
var RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES = [
|
|
12003
|
+
"../../server/resources/bundled-skills",
|
|
12004
|
+
"../../skills",
|
|
12005
|
+
"../../../../../server/resources/bundled-skills"
|
|
12006
|
+
];
|
|
12007
|
+
function normalizePathSlashes(value) {
|
|
12008
|
+
return value.replaceAll("\\", "/");
|
|
12009
|
+
}
|
|
12010
|
+
function isMaintainerOnlySkillTarget(candidate) {
|
|
12011
|
+
const normalized = normalizePathSlashes(candidate);
|
|
12012
|
+
return normalized.includes("/server/resources/bundled-skills/") || normalized.includes("/.agents/skills/");
|
|
12013
|
+
}
|
|
12014
|
+
|
|
12015
|
+
// ../packages/agent-runtime-utils/dist/server-utils.prompts.js
|
|
12016
|
+
var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
12017
|
+
"# Rudder Agent Operating Contract",
|
|
12018
|
+
"",
|
|
12019
|
+
"Your home directory is `$AGENT_HOME`. Everything personal to you -- life, memory, knowledge -- lives there. Other agents may have their own folders and you may update them when necessary.",
|
|
12020
|
+
"",
|
|
12021
|
+
"Use these paths consistently:",
|
|
12022
|
+
"",
|
|
12023
|
+
"- Personal instructions live under `$AGENT_HOME/instructions`.",
|
|
12024
|
+
"- Personal memory lives under `$AGENT_HOME/memory`.",
|
|
12025
|
+
"- Tacit memory instruction lives at `$AGENT_HOME/instructions/MEMORY.md` and is automatically loaded when present.",
|
|
12026
|
+
"- Personal skills live under `$AGENT_HOME/skills`.",
|
|
12027
|
+
"- Shared organization workspace root lives under `$RUDDER_ORG_WORKSPACE_ROOT`.",
|
|
12028
|
+
"- Shared organization skills live under `$RUDDER_ORG_SKILLS_DIR`.",
|
|
12029
|
+
"- Project Library root lives under `$RUDDER_PROJECT_LIBRARY_ROOT` when the run has project context.",
|
|
12030
|
+
"- Project Library locator lives in `$RUDDER_PROJECT_LIBRARY_PATH` when the run has project context, for example `projects/<project-key>`.",
|
|
12031
|
+
'- Library-backed project resources use `sourceType: "library"`; their `locator` points into `library:projects/<project-key>/`.',
|
|
12032
|
+
"- Project Context is explicit operator-curated context, not the whole knowledge boundary. When it is insufficient, inspect broader Library and org workspace know-how before concluding context is missing.",
|
|
12033
|
+
"- In local trusted runs, durable generated project work files should be written directly under `$RUDDER_PROJECT_LIBRARY_ROOT` with normal filesystem tools.",
|
|
12034
|
+
"- `library:projects/<project-key>/...` is the Rudder product locator for those files, not the Markdown link syntax and not a reason to route ordinary local edits through the CLI.",
|
|
12035
|
+
'- When you create or update a durable Library file, always include a user-visible Markdown link to that file in your final chat reply or issue comment. Use `rudder library file ref "$RUDDER_PROJECT_LIBRARY_PATH/<relative-file>" --json` and paste the returned `markdownLink`; do not pass the absolute `$RUDDER_PROJECT_LIBRARY_ROOT/...` path to `ref`, and do not hand-write `library-entry://...` or `library-file://...` links.',
|
|
12036
|
+
'- If `$RUDDER_PROJECT_LIBRARY_ROOT` is unset or inaccessible, use `rudder library file get/put "$RUDDER_PROJECT_LIBRARY_PATH/<relative-file>"` as the remote or restricted runtime fallback.',
|
|
12037
|
+
"- Use `/tmp` only for transient scratch files and temporary verification files; do not put durable work product there.",
|
|
12038
|
+
"- Local trusted runtimes may expose the host operator home as `$RUDDER_OPERATOR_HOME`; use it only when a local skill or script intentionally needs operator-owned desktop app or CLI state. Do not replace `$HOME` with it.",
|
|
12039
|
+
"",
|
|
12040
|
+
"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.",
|
|
12041
|
+
"",
|
|
12042
|
+
"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.",
|
|
12043
|
+
"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.",
|
|
12044
|
+
"",
|
|
12045
|
+
"## Rudder Renderable Links",
|
|
12046
|
+
"",
|
|
12047
|
+
"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.",
|
|
12048
|
+
"",
|
|
12049
|
+
"- Issues: use `[<identifier-or-title>](issue://<issue-id>?r=<identifier>)`; include `&c=<comment-id>` when linking to a specific comment.",
|
|
12050
|
+
"- Agents: use `[<agent-name>](agent://<agent-id>)` for reference-only links. Use `[<agent-name>](agent://<agent-id>?intent=wake)` only when you deliberately want an issue-composer mention to wake that agent.",
|
|
12051
|
+
"- Projects: use `[<project-name>](project://<project-id>)` when citing a Rudder project.",
|
|
12052
|
+
"- Chat threads: use `[<chat-title>](chat://<conversation-id>?t=<url-encoded-title>)` when citing a Rudder chat conversation.",
|
|
12053
|
+
'- 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.',
|
|
12054
|
+
"",
|
|
12055
|
+
"Write these as normal Markdown links, not inside code spans or code blocks, unless you are literally documenting the syntax.",
|
|
12056
|
+
"",
|
|
12057
|
+
"Mention-triggered comment wakes arrive with `RUDDER_WAKE_COMMENT_ID`; read that wake comment before acting. Board/operator issue comments can wake an agent with a plain `@AgentName` token or an issue-composer agent mention serialized as `agent://agent-id?intent=wake`. Plain structured links such as `agent://agent-id` are reference-only links for rendering and navigation. Agent-authored issue comments do not fan out peer wakeups by default; use reviewer, assignment, or explicit handoff workflow instead. 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.",
|
|
12058
|
+
"",
|
|
12059
|
+
"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.",
|
|
12060
|
+
"",
|
|
12061
|
+
"## Memory and Shared Work Notes",
|
|
12062
|
+
"",
|
|
12063
|
+
"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.",
|
|
12064
|
+
"",
|
|
12065
|
+
"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; those files are not auto-loaded.",
|
|
12066
|
+
"",
|
|
12067
|
+
"Invoke it whenever you need to remember, retrieve, or organize anything.",
|
|
12068
|
+
"",
|
|
12069
|
+
"## Safety Considerations",
|
|
12070
|
+
"",
|
|
12071
|
+
"- Never exfiltrate secrets or private data.",
|
|
12072
|
+
"- Do not perform any destructive commands unless explicitly requested by the board."
|
|
12073
|
+
].join("\n");
|
|
12074
|
+
|
|
12075
|
+
// ../packages/agent-runtime-utils/dist/server-utils.cli.js
|
|
12076
|
+
import { promises as fs13 } from "node:fs";
|
|
12077
|
+
import path17 from "node:path";
|
|
12078
|
+
async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
|
|
12079
|
+
const candidates = [
|
|
12080
|
+
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path17.resolve(moduleDir, relativePath)),
|
|
12081
|
+
...additionalCandidates.map((candidate) => path17.resolve(candidate))
|
|
12082
|
+
];
|
|
12083
|
+
const seenRoots = /* @__PURE__ */ new Set();
|
|
12084
|
+
for (const root of candidates) {
|
|
12085
|
+
if (seenRoots.has(root))
|
|
12086
|
+
continue;
|
|
12087
|
+
seenRoots.add(root);
|
|
12088
|
+
const isDirectory = await fs13.stat(root).then((stats) => stats.isDirectory()).catch(() => false);
|
|
12089
|
+
if (isDirectory)
|
|
12090
|
+
return root;
|
|
12091
|
+
}
|
|
12092
|
+
return null;
|
|
12093
|
+
}
|
|
12094
|
+
async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames) {
|
|
12095
|
+
const allowed = new Set(Array.from(allowedSkillNames));
|
|
12096
|
+
try {
|
|
12097
|
+
const entries = await fs13.readdir(skillsHome, { withFileTypes: true });
|
|
12098
|
+
const removed = [];
|
|
12099
|
+
for (const entry of entries) {
|
|
12100
|
+
if (allowed.has(entry.name))
|
|
12101
|
+
continue;
|
|
12102
|
+
const target = path17.join(skillsHome, entry.name);
|
|
12103
|
+
const existing = await fs13.lstat(target).catch(() => null);
|
|
12104
|
+
if (!existing?.isSymbolicLink())
|
|
12105
|
+
continue;
|
|
12106
|
+
const linkedPath = await fs13.readlink(target).catch(() => null);
|
|
12107
|
+
if (!linkedPath)
|
|
12108
|
+
continue;
|
|
12109
|
+
const resolvedLinkedPath = path17.isAbsolute(linkedPath) ? linkedPath : path17.resolve(path17.dirname(target), linkedPath);
|
|
12110
|
+
if (!isMaintainerOnlySkillTarget(linkedPath) && !isMaintainerOnlySkillTarget(resolvedLinkedPath)) {
|
|
12111
|
+
continue;
|
|
12112
|
+
}
|
|
12113
|
+
await fs13.unlink(target);
|
|
12114
|
+
removed.push(entry.name);
|
|
12115
|
+
}
|
|
12116
|
+
return removed;
|
|
12117
|
+
} catch {
|
|
12118
|
+
return [];
|
|
12119
|
+
}
|
|
12120
|
+
}
|
|
12121
|
+
|
|
12122
|
+
// src/commands/client/agent.ts
|
|
12123
|
+
import fs14 from "node:fs/promises";
|
|
12124
|
+
import os2 from "node:os";
|
|
12125
|
+
import path18 from "node:path";
|
|
12126
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
12127
|
+
var __moduleDir = path18.dirname(fileURLToPath3(import.meta.url));
|
|
12128
|
+
function codexSkillsHome() {
|
|
12129
|
+
const fromEnv = process.env.CODEX_HOME?.trim();
|
|
12130
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".codex");
|
|
12131
|
+
return path18.join(base, "skills");
|
|
12132
|
+
}
|
|
12133
|
+
function claudeSkillsHome() {
|
|
12134
|
+
const fromEnv = process.env.CLAUDE_HOME?.trim();
|
|
12135
|
+
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".claude");
|
|
12136
|
+
return path18.join(base, "skills");
|
|
12137
|
+
}
|
|
12138
|
+
async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
12139
|
+
const summary = {
|
|
12140
|
+
tool,
|
|
12141
|
+
target: targetSkillsDir,
|
|
12142
|
+
linked: [],
|
|
12143
|
+
removed: [],
|
|
12144
|
+
skipped: [],
|
|
12145
|
+
failed: []
|
|
12146
|
+
};
|
|
12147
|
+
await fs14.mkdir(targetSkillsDir, { recursive: true });
|
|
12148
|
+
const entries = await fs14.readdir(sourceSkillsDir, { withFileTypes: true });
|
|
12149
|
+
summary.removed = await removeMaintainerOnlySkillSymlinks(
|
|
12150
|
+
targetSkillsDir,
|
|
12151
|
+
entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
12152
|
+
);
|
|
12153
|
+
for (const entry of entries) {
|
|
12154
|
+
if (!entry.isDirectory()) continue;
|
|
12155
|
+
const source = path18.join(sourceSkillsDir, entry.name);
|
|
12156
|
+
const target = path18.join(targetSkillsDir, entry.name);
|
|
12157
|
+
const existing = await fs14.lstat(target).catch(() => null);
|
|
12158
|
+
if (existing) {
|
|
12159
|
+
if (existing.isSymbolicLink()) {
|
|
12160
|
+
let linkedPath = null;
|
|
12161
|
+
try {
|
|
12162
|
+
linkedPath = await fs14.readlink(target);
|
|
12163
|
+
} catch (err) {
|
|
12164
|
+
await fs14.unlink(target);
|
|
12165
|
+
try {
|
|
12166
|
+
await fs14.symlink(source, target);
|
|
12167
|
+
summary.linked.push(entry.name);
|
|
12168
|
+
continue;
|
|
12169
|
+
} catch (linkErr) {
|
|
12170
|
+
summary.failed.push({
|
|
12171
|
+
name: entry.name,
|
|
12172
|
+
error: err instanceof Error && linkErr instanceof Error ? `${err.message}; then ${linkErr.message}` : err instanceof Error ? err.message : `Failed to recover broken symlink: ${String(err)}`
|
|
12173
|
+
});
|
|
12174
|
+
continue;
|
|
12175
|
+
}
|
|
12176
|
+
}
|
|
12177
|
+
const resolvedLinkedPath = path18.isAbsolute(linkedPath) ? linkedPath : path18.resolve(path18.dirname(target), linkedPath);
|
|
12178
|
+
const linkedTargetExists = await fs14.stat(resolvedLinkedPath).then(() => true).catch(() => false);
|
|
12179
|
+
if (!linkedTargetExists) {
|
|
12180
|
+
await fs14.unlink(target);
|
|
12181
|
+
} else {
|
|
12182
|
+
summary.skipped.push(entry.name);
|
|
12183
|
+
continue;
|
|
12184
|
+
}
|
|
12185
|
+
} else {
|
|
12186
|
+
summary.skipped.push(entry.name);
|
|
12187
|
+
continue;
|
|
12188
|
+
}
|
|
12189
|
+
}
|
|
12190
|
+
try {
|
|
12191
|
+
await fs14.symlink(source, target);
|
|
12192
|
+
summary.linked.push(entry.name);
|
|
12193
|
+
} catch (err) {
|
|
12194
|
+
summary.failed.push({
|
|
12195
|
+
name: entry.name,
|
|
12196
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12197
|
+
});
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
return summary;
|
|
12201
|
+
}
|
|
12202
|
+
function buildAgentEnvExports(input) {
|
|
12203
|
+
const escaped = (value) => value.replace(/'/g, `'"'"'`);
|
|
12204
|
+
return [
|
|
12205
|
+
`export RUDDER_API_URL='${escaped(input.apiBase)}'`,
|
|
12206
|
+
`export RUDDER_ORG_ID='${escaped(input.orgId)}'`,
|
|
12207
|
+
`export RUDDER_AGENT_ID='${escaped(input.agentId)}'`,
|
|
12208
|
+
`export RUDDER_API_KEY='${escaped(input.apiKey)}'`
|
|
12209
|
+
].join("\n");
|
|
12210
|
+
}
|
|
12211
|
+
function registerAgentCommands(program) {
|
|
12212
|
+
const agent = program.command("agent").description("Agent operations");
|
|
12213
|
+
const config = agent.command("config").description("Agent configuration discovery and redacted snapshots");
|
|
12214
|
+
addCommonClientOptions(
|
|
12215
|
+
agent.command("me").description(getAgentCliCapabilityById("agent.me").description).action(async (opts) => {
|
|
12216
|
+
try {
|
|
12217
|
+
const ctx = resolveCommandContext(opts);
|
|
12218
|
+
const row = await ctx.api.get("/api/agents/me");
|
|
12219
|
+
printOutput(row, { json: ctx.json });
|
|
12220
|
+
} catch (err) {
|
|
12221
|
+
handleCommandError(err);
|
|
12222
|
+
}
|
|
11136
12223
|
})
|
|
11137
12224
|
);
|
|
11138
12225
|
addCommonClientOptions(
|
|
11139
|
-
|
|
12226
|
+
agent.command("inbox").description(getAgentCliCapabilityById("agent.inbox").description).action(async (opts) => {
|
|
11140
12227
|
try {
|
|
11141
12228
|
const ctx = resolveCommandContext(opts);
|
|
11142
|
-
const
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
12229
|
+
const rows = await ctx.api.get("/api/agents/me/inbox-lite") ?? [];
|
|
12230
|
+
if (ctx.json) {
|
|
12231
|
+
printOutput(rows, { json: true });
|
|
12232
|
+
return;
|
|
12233
|
+
}
|
|
12234
|
+
if (rows.length === 0) {
|
|
12235
|
+
printOutput([], { json: false });
|
|
12236
|
+
return;
|
|
12237
|
+
}
|
|
12238
|
+
for (const row of rows) {
|
|
12239
|
+
console.log(
|
|
12240
|
+
formatInlineRecord({
|
|
12241
|
+
identifier: row.identifier,
|
|
12242
|
+
id: row.id,
|
|
12243
|
+
relationship: row.relationship ?? "assignee",
|
|
12244
|
+
status: row.status,
|
|
12245
|
+
priority: row.priority,
|
|
12246
|
+
title: row.title,
|
|
12247
|
+
projectId: row.projectId,
|
|
12248
|
+
goalId: row.goalId,
|
|
12249
|
+
parentId: row.parentId,
|
|
12250
|
+
updatedAt: row.updatedAt
|
|
12251
|
+
})
|
|
12252
|
+
);
|
|
11156
12253
|
}
|
|
11157
|
-
printOutput(comment, { json: ctx.json });
|
|
11158
12254
|
} catch (err) {
|
|
11159
12255
|
handleCommandError(err);
|
|
11160
12256
|
}
|
|
11161
12257
|
})
|
|
11162
12258
|
);
|
|
11163
12259
|
addCommonClientOptions(
|
|
11164
|
-
|
|
11165
|
-
"--decision <decision>",
|
|
11166
|
-
"Review decision: approve, request_changes, needs_followup, or blocked"
|
|
11167
|
-
).option("--comment-file <path>", "Read required review comment from a file, or '-' for stdin").action(async (issueId, opts) => {
|
|
12260
|
+
agent.command("capabilities").description(getAgentCliCapabilityById("agent.capabilities").description).option("--contract <name>", "Capability subset to show (agent-v1 or all)", "agent-v1").action(async (opts) => {
|
|
11168
12261
|
try {
|
|
11169
|
-
const
|
|
11170
|
-
const
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
});
|
|
11177
|
-
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11178
|
-
reviewDecision: decision,
|
|
11179
|
-
comment
|
|
11180
|
-
});
|
|
11181
|
-
printOutput(updated, { json: ctx.json });
|
|
12262
|
+
const contract = opts.contract === "all" ? "all" : "agent-v1";
|
|
12263
|
+
const capabilities = getAgentCliCapabilities().filter((entry) => contract === "all" ? true : entry.contract === contract);
|
|
12264
|
+
if (opts.json) {
|
|
12265
|
+
printOutput(buildAgentCliCapabilitiesManifest(contract), { json: true });
|
|
12266
|
+
return;
|
|
12267
|
+
}
|
|
12268
|
+
console.log(formatAgentCliCapabilitiesHumanReadable(capabilities));
|
|
11182
12269
|
} catch (err) {
|
|
11183
12270
|
handleCommandError(err);
|
|
11184
12271
|
}
|
|
11185
12272
|
})
|
|
11186
12273
|
);
|
|
11187
12274
|
addCommonClientOptions(
|
|
11188
|
-
|
|
12275
|
+
agent.command("list").description(getAgentCliCapabilityById("agent.list").description).option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
11189
12276
|
try {
|
|
11190
|
-
const ctx = resolveCommandContext(opts);
|
|
11191
|
-
const
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
12277
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12278
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/agents`) ?? [];
|
|
12279
|
+
if (ctx.json) {
|
|
12280
|
+
printOutput(rows, { json: true });
|
|
12281
|
+
return;
|
|
12282
|
+
}
|
|
12283
|
+
if (rows.length === 0) {
|
|
12284
|
+
printOutput([], { json: false });
|
|
12285
|
+
return;
|
|
12286
|
+
}
|
|
12287
|
+
for (const row of rows) {
|
|
12288
|
+
console.log(
|
|
12289
|
+
formatInlineRecord({
|
|
12290
|
+
id: row.id,
|
|
12291
|
+
name: row.name,
|
|
12292
|
+
role: row.role,
|
|
12293
|
+
status: row.status,
|
|
12294
|
+
reportsTo: row.reportsTo,
|
|
12295
|
+
budgetMonthlyCents: row.budgetMonthlyCents,
|
|
12296
|
+
spentMonthlyCents: row.spentMonthlyCents
|
|
12297
|
+
})
|
|
12298
|
+
);
|
|
12299
|
+
}
|
|
11201
12300
|
} catch (err) {
|
|
11202
12301
|
handleCommandError(err);
|
|
11203
12302
|
}
|
|
11204
|
-
})
|
|
12303
|
+
}),
|
|
12304
|
+
{ includeCompany: false }
|
|
11205
12305
|
);
|
|
11206
12306
|
addCommonClientOptions(
|
|
11207
|
-
|
|
12307
|
+
config.command("index").description(getAgentCliCapabilityById("agent.config.index").description).action(async (opts) => {
|
|
11208
12308
|
try {
|
|
11209
12309
|
const ctx = resolveCommandContext(opts);
|
|
11210
|
-
const
|
|
11211
|
-
|
|
11212
|
-
fileOption: "--comment-file",
|
|
11213
|
-
removedTextOption: "--comment",
|
|
11214
|
-
required: true
|
|
11215
|
-
});
|
|
11216
|
-
const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
|
|
11217
|
-
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11218
|
-
status: "done",
|
|
11219
|
-
comment
|
|
11220
|
-
});
|
|
11221
|
-
printOutput(updated, { json: ctx.json });
|
|
12310
|
+
const doc = await ctx.api.get("/llms/agent-configuration.txt");
|
|
12311
|
+
printOutput(doc ?? "", { json: ctx.json });
|
|
11222
12312
|
} catch (err) {
|
|
11223
12313
|
handleCommandError(err);
|
|
11224
12314
|
}
|
|
11225
12315
|
})
|
|
11226
12316
|
);
|
|
11227
12317
|
addCommonClientOptions(
|
|
11228
|
-
|
|
12318
|
+
config.command("doc").description(getAgentCliCapabilityById("agent.config.doc").description).argument("<agentRuntimeType>", "Agent runtime type").action(async (agentRuntimeType, opts) => {
|
|
11229
12319
|
try {
|
|
11230
12320
|
const ctx = resolveCommandContext(opts);
|
|
11231
|
-
const
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
required: true
|
|
11236
|
-
});
|
|
11237
|
-
const comment = await appendUploadedIssueImages(ctx, issueId, commentText, opts.image);
|
|
11238
|
-
const updated = await ctx.api.patch(`/api/issues/${issueId}`, {
|
|
11239
|
-
status: "blocked",
|
|
11240
|
-
comment
|
|
11241
|
-
});
|
|
11242
|
-
printOutput(updated, { json: ctx.json });
|
|
12321
|
+
const doc = await ctx.api.get(
|
|
12322
|
+
`/llms/agent-configuration/${encodeURIComponent(agentRuntimeType)}.txt`
|
|
12323
|
+
);
|
|
12324
|
+
printOutput(doc ?? "", { json: ctx.json });
|
|
11243
12325
|
} catch (err) {
|
|
11244
12326
|
handleCommandError(err);
|
|
11245
12327
|
}
|
|
11246
12328
|
})
|
|
11247
12329
|
);
|
|
11248
|
-
const comments = issue.command("comments").description("Issue comment operations");
|
|
11249
12330
|
addCommonClientOptions(
|
|
11250
|
-
|
|
12331
|
+
config.command("list").description(getAgentCliCapabilityById("agent.config.list").description).option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
12332
|
+
try {
|
|
12333
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12334
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/agent-configurations`) ?? [];
|
|
12335
|
+
if (ctx.json) {
|
|
12336
|
+
printOutput(rows, { json: true });
|
|
12337
|
+
return;
|
|
12338
|
+
}
|
|
12339
|
+
if (rows.length === 0) {
|
|
12340
|
+
printOutput([], { json: false });
|
|
12341
|
+
return;
|
|
12342
|
+
}
|
|
12343
|
+
for (const row of rows) {
|
|
12344
|
+
console.log(
|
|
12345
|
+
formatInlineRecord({
|
|
12346
|
+
id: row.id,
|
|
12347
|
+
name: row.name,
|
|
12348
|
+
role: row.role,
|
|
12349
|
+
status: row.status,
|
|
12350
|
+
agentRuntimeType: row.agentRuntimeType,
|
|
12351
|
+
reportsTo: row.reportsTo,
|
|
12352
|
+
updatedAt: row.updatedAt
|
|
12353
|
+
})
|
|
12354
|
+
);
|
|
12355
|
+
}
|
|
12356
|
+
} catch (err) {
|
|
12357
|
+
handleCommandError(err);
|
|
12358
|
+
}
|
|
12359
|
+
}),
|
|
12360
|
+
{ includeCompany: false }
|
|
12361
|
+
);
|
|
12362
|
+
addCommonClientOptions(
|
|
12363
|
+
config.command("get").description(getAgentCliCapabilityById("agent.config.get").description).argument("<agentId>", "Agent ID or shortname/url-key").option("-O, --org-id <id>", "Organization ID").action(async (agentId, opts) => {
|
|
11251
12364
|
try {
|
|
11252
12365
|
const ctx = resolveCommandContext(opts);
|
|
11253
|
-
const
|
|
11254
|
-
if (
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
) ?? [];
|
|
11260
|
-
printOutput(rows, { json: ctx.json });
|
|
12366
|
+
const query = new URLSearchParams();
|
|
12367
|
+
if (ctx.orgId) query.set("orgId", ctx.orgId);
|
|
12368
|
+
const row = await ctx.api.get(
|
|
12369
|
+
`/api/agents/${encodeURIComponent(agentId)}/configuration${query.size > 0 ? `?${query.toString()}` : ""}`
|
|
12370
|
+
);
|
|
12371
|
+
printOutput(row, { json: ctx.json });
|
|
11261
12372
|
} catch (err) {
|
|
11262
12373
|
handleCommandError(err);
|
|
11263
12374
|
}
|
|
11264
12375
|
})
|
|
11265
12376
|
);
|
|
11266
12377
|
addCommonClientOptions(
|
|
11267
|
-
|
|
12378
|
+
agent.command("icons").description(getAgentCliCapabilityById("agent.icons").description).action(async (opts) => {
|
|
11268
12379
|
try {
|
|
11269
12380
|
const ctx = resolveCommandContext(opts);
|
|
11270
|
-
const
|
|
11271
|
-
printOutput(
|
|
12381
|
+
const doc = await ctx.api.get("/llms/agent-icons.txt");
|
|
12382
|
+
printOutput(doc ?? "", { json: ctx.json });
|
|
11272
12383
|
} catch (err) {
|
|
11273
12384
|
handleCommandError(err);
|
|
11274
12385
|
}
|
|
11275
12386
|
})
|
|
11276
12387
|
);
|
|
11277
|
-
const
|
|
12388
|
+
const skills = agent.command("skills").description("Agent skill selection operations");
|
|
11278
12389
|
addCommonClientOptions(
|
|
11279
|
-
|
|
12390
|
+
skills.command("create").description(getAgentCliCapabilityById("agent.skills.create").description).argument("[agent-id]", "Agent ID; defaults to RUDDER_AGENT_ID").requiredOption("--name <name>", "Skill display name").option("--slug <slug>", "Skill short name").option("--description <text>", "Skill description").option("--markdown <markdown>", "Full SKILL.md content").option("--markdown-file <path>", "Read full SKILL.md content from a local file").option("--enable", "Enable the created private skill for future runs").action(async (agentIdArg, opts) => {
|
|
11280
12391
|
try {
|
|
11281
12392
|
const ctx = resolveCommandContext(opts);
|
|
11282
|
-
const
|
|
11283
|
-
|
|
12393
|
+
const agentId = agentIdArg?.trim() || ctx.agentId;
|
|
12394
|
+
if (!agentId) {
|
|
12395
|
+
throw new Error("Agent ID is required. Pass [agent-id] or set RUDDER_AGENT_ID.");
|
|
12396
|
+
}
|
|
12397
|
+
if (opts.markdown && opts.markdownFile) {
|
|
12398
|
+
throw new Error("Pass only one of --markdown or --markdown-file.");
|
|
12399
|
+
}
|
|
12400
|
+
const markdown = opts.markdownFile ? await fs14.readFile(path18.resolve(opts.markdownFile), "utf8") : opts.markdown;
|
|
12401
|
+
const payload = organizationSkillCreateSchema.parse({
|
|
12402
|
+
name: opts.name,
|
|
12403
|
+
slug: opts.slug?.trim() || null,
|
|
12404
|
+
description: opts.description?.trim() || null,
|
|
12405
|
+
markdown: markdown ?? null
|
|
12406
|
+
});
|
|
12407
|
+
const created = await ctx.api.post(
|
|
12408
|
+
`/api/agents/${encodeURIComponent(agentId)}/skills/private`,
|
|
12409
|
+
payload
|
|
12410
|
+
);
|
|
12411
|
+
if (!created) {
|
|
12412
|
+
throw new Error("Failed to create agent skill");
|
|
12413
|
+
}
|
|
12414
|
+
let enabledSnapshot = null;
|
|
12415
|
+
if (opts.enable) {
|
|
12416
|
+
enabledSnapshot = await ctx.api.post(
|
|
12417
|
+
`/api/agents/${encodeURIComponent(agentId)}/skills/enable`,
|
|
12418
|
+
{ skills: [created.selectionKey] }
|
|
12419
|
+
);
|
|
12420
|
+
}
|
|
12421
|
+
const result = { created, enabledSnapshot };
|
|
12422
|
+
if (ctx.json) {
|
|
12423
|
+
printOutput(result, { json: true });
|
|
12424
|
+
return;
|
|
12425
|
+
}
|
|
12426
|
+
console.log(
|
|
12427
|
+
formatInlineRecord({
|
|
12428
|
+
key: created.key,
|
|
12429
|
+
selectionKey: created.selectionKey,
|
|
12430
|
+
sourceClass: created.sourceClass,
|
|
12431
|
+
sourcePath: created.sourcePath,
|
|
12432
|
+
enabled: Boolean(enabledSnapshot?.desiredSkills.includes(created.selectionKey)),
|
|
12433
|
+
detail: opts.enable ? "Created and enabled. Future runs will load this skill." : "Created, not enabled. Future runs will not load it until enabled."
|
|
12434
|
+
})
|
|
12435
|
+
);
|
|
11284
12436
|
} catch (err) {
|
|
11285
12437
|
handleCommandError(err);
|
|
11286
12438
|
}
|
|
11287
12439
|
})
|
|
11288
12440
|
);
|
|
11289
12441
|
addCommonClientOptions(
|
|
11290
|
-
|
|
12442
|
+
skills.command("enable").description(getAgentCliCapabilityById("agent.skills.enable").description).argument("<agentId>", "Agent ID").argument("<selectionRefs...>", "Skill selection refs to enable").action(async (agentId, selectionRefs, opts) => {
|
|
11291
12443
|
try {
|
|
11292
12444
|
const ctx = resolveCommandContext(opts);
|
|
11293
|
-
const
|
|
11294
|
-
|
|
12445
|
+
const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/enable`, {
|
|
12446
|
+
skills: selectionRefs
|
|
12447
|
+
});
|
|
12448
|
+
printOutput(snapshot, { json: ctx.json });
|
|
11295
12449
|
} catch (err) {
|
|
11296
12450
|
handleCommandError(err);
|
|
11297
12451
|
}
|
|
11298
12452
|
})
|
|
11299
12453
|
);
|
|
11300
12454
|
addCommonClientOptions(
|
|
11301
|
-
|
|
12455
|
+
skills.command("sync").description(getAgentCliCapabilityById("agent.skills.sync").description).argument("<agentId>", "Agent ID").requiredOption(
|
|
12456
|
+
"--desired-skills <csv>",
|
|
12457
|
+
"Comma-separated desired skill refs (for example rudder/rudder)"
|
|
12458
|
+
).action(async (agentId, opts) => {
|
|
11302
12459
|
try {
|
|
11303
12460
|
const ctx = resolveCommandContext(opts);
|
|
11304
|
-
const
|
|
11305
|
-
|
|
11306
|
-
fileOption: "--body-file",
|
|
11307
|
-
removedTextOption: "--body",
|
|
11308
|
-
required: true
|
|
11309
|
-
});
|
|
11310
|
-
const payload = upsertIssueDocumentSchema.parse({
|
|
11311
|
-
title: opts.title,
|
|
11312
|
-
format: opts.format,
|
|
11313
|
-
body,
|
|
11314
|
-
changeSummary: opts.changeSummary,
|
|
11315
|
-
baseRevisionId: opts.baseRevisionId
|
|
12461
|
+
const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/sync`, {
|
|
12462
|
+
desiredSkills: parseCsv3(opts.desiredSkills)
|
|
11316
12463
|
});
|
|
11317
|
-
|
|
11318
|
-
printOutput(row, { json: ctx.json });
|
|
12464
|
+
printOutput(snapshot, { json: ctx.json });
|
|
11319
12465
|
} catch (err) {
|
|
11320
12466
|
handleCommandError(err);
|
|
11321
12467
|
}
|
|
11322
12468
|
})
|
|
11323
12469
|
);
|
|
11324
12470
|
addCommonClientOptions(
|
|
11325
|
-
|
|
12471
|
+
agent.command("get").description(getAgentCliCapabilityById("agent.get").description).argument("<agentId>", "Agent ID or shortname/url-key").option("-O, --org-id <id>", "Organization ID").action(async (agentId, opts) => {
|
|
11326
12472
|
try {
|
|
11327
12473
|
const ctx = resolveCommandContext(opts);
|
|
11328
|
-
const
|
|
11329
|
-
|
|
12474
|
+
const query = new URLSearchParams();
|
|
12475
|
+
if (ctx.orgId) query.set("orgId", ctx.orgId);
|
|
12476
|
+
const row = await ctx.api.get(
|
|
12477
|
+
`/api/agents/${encodeURIComponent(agentId)}${query.size > 0 ? `?${query.toString()}` : ""}`
|
|
12478
|
+
);
|
|
12479
|
+
printOutput(row, { json: ctx.json });
|
|
11330
12480
|
} catch (err) {
|
|
11331
12481
|
handleCommandError(err);
|
|
11332
12482
|
}
|
|
11333
12483
|
})
|
|
11334
12484
|
);
|
|
11335
12485
|
addCommonClientOptions(
|
|
11336
|
-
|
|
11337
|
-
"--expected-statuses <csv>",
|
|
11338
|
-
"Expected current statuses",
|
|
11339
|
-
"todo,backlog,blocked"
|
|
11340
|
-
).action(async (issueId, opts) => {
|
|
12486
|
+
agent.command("update").description(getAgentCliCapabilityById("agent.update").description).argument("[agentId]", "Agent ID or shortname/url-key; defaults to RUDDER_AGENT_ID").option("-O, --org-id <id>", "Organization ID").option("--name <name>", "Agent display name").option("--role <role>", "Agent organization role").option("--title <title>", "Agent title shown in mentions and agent labels").option("--clear-title", "Clear the agent title").option("--capabilities <text>", "Agent capabilities/description text").option("--capabilities-file <path>", "Read agent capabilities/description from a local file").option("--description <text>", "Alias for --capabilities").option("--description-file <path>", "Alias for --capabilities-file").option("--clear-capabilities", "Clear the agent capabilities/description").option("--clear-description", "Alias for --clear-capabilities").option("--reports-to <agent-id>", "Manager agent ID").option("--clear-reports-to", "Clear the manager relationship").action(async (agentIdArg, opts) => {
|
|
11341
12487
|
try {
|
|
11342
12488
|
const ctx = resolveCommandContext(opts);
|
|
11343
|
-
const agentId =
|
|
12489
|
+
const agentId = agentIdArg?.trim() || ctx.agentId;
|
|
11344
12490
|
if (!agentId) {
|
|
11345
|
-
throw new Error("Agent ID is required. Pass
|
|
12491
|
+
throw new Error("Agent ID is required. Pass [agent-id] or set RUDDER_AGENT_ID.");
|
|
11346
12492
|
}
|
|
11347
|
-
const
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
12493
|
+
const patch = await buildAgentUpdatePatch(opts);
|
|
12494
|
+
if (Object.keys(patch).length === 0) {
|
|
12495
|
+
throw new Error(
|
|
12496
|
+
"No agent fields to update. Pass --name, --role, --title, --capabilities, --description, or --reports-to."
|
|
12497
|
+
);
|
|
12498
|
+
}
|
|
12499
|
+
const query = new URLSearchParams();
|
|
12500
|
+
if (ctx.orgId) query.set("orgId", ctx.orgId);
|
|
12501
|
+
const updated = await ctx.api.patch(
|
|
12502
|
+
`/api/agents/${encodeURIComponent(agentId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
|
|
12503
|
+
patch
|
|
12504
|
+
);
|
|
11352
12505
|
printOutput(updated, { json: ctx.json });
|
|
11353
12506
|
} catch (err) {
|
|
11354
12507
|
handleCommandError(err);
|
|
@@ -11356,243 +12509,193 @@ function registerIssueCommands(program) {
|
|
|
11356
12509
|
})
|
|
11357
12510
|
);
|
|
11358
12511
|
addCommonClientOptions(
|
|
11359
|
-
|
|
12512
|
+
agent.command("hire").description(getAgentCliCapabilityById("agent.hire").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--payload <json>", "Hire payload as JSON object").action(async (opts) => {
|
|
11360
12513
|
try {
|
|
11361
|
-
const ctx = resolveCommandContext(opts);
|
|
11362
|
-
const
|
|
11363
|
-
|
|
12514
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12515
|
+
const payloadJson = parseJsonObject(opts.payload, "payload");
|
|
12516
|
+
const payload = createAgentHireSchema.parse(payloadJson);
|
|
12517
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/agent-hires`, payload);
|
|
12518
|
+
printOutput(created, { json: ctx.json });
|
|
11364
12519
|
} catch (err) {
|
|
11365
12520
|
handleCommandError(err);
|
|
11366
12521
|
}
|
|
11367
|
-
})
|
|
12522
|
+
}),
|
|
12523
|
+
{ includeCompany: false }
|
|
12524
|
+
);
|
|
12525
|
+
addCommonClientOptions(
|
|
12526
|
+
agent.command("local-cli").description(
|
|
12527
|
+
"Create an agent API key, optionally install local Rudder skills for direct Codex/Claude CLI use, and print shell exports"
|
|
12528
|
+
).argument("<agentRef>", "Agent ID or shortname/url-key").option("-O, --org-id <id>", "Organization ID").option("--key-name <name>", "API key label", "local-cli").option(
|
|
12529
|
+
"--no-install-skills",
|
|
12530
|
+
"Skip the optional local Codex/Claude skill installation step"
|
|
12531
|
+
).action(async (agentRef, opts) => {
|
|
12532
|
+
try {
|
|
12533
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12534
|
+
const query = new URLSearchParams({ orgId: ctx.orgId ?? "" });
|
|
12535
|
+
const agentRow = await ctx.api.get(
|
|
12536
|
+
`/api/agents/${encodeURIComponent(agentRef)}?${query.toString()}`
|
|
12537
|
+
);
|
|
12538
|
+
if (!agentRow) {
|
|
12539
|
+
throw new Error(`Agent not found: ${agentRef}`);
|
|
12540
|
+
}
|
|
12541
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
12542
|
+
const keyName = opts.keyName?.trim() ? opts.keyName.trim() : `local-cli-${now}`;
|
|
12543
|
+
const key = await ctx.api.post(`/api/agents/${agentRow.id}/keys`, { name: keyName });
|
|
12544
|
+
if (!key) {
|
|
12545
|
+
throw new Error("Failed to create API key");
|
|
12546
|
+
}
|
|
12547
|
+
const installSummaries = [];
|
|
12548
|
+
if (opts.installSkills !== false) {
|
|
12549
|
+
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path18.resolve(process.cwd(), "skills")]);
|
|
12550
|
+
if (!skillsDir) {
|
|
12551
|
+
throw new Error(
|
|
12552
|
+
"Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
|
|
12553
|
+
);
|
|
12554
|
+
}
|
|
12555
|
+
installSummaries.push(
|
|
12556
|
+
await installSkillsForTarget(skillsDir, codexSkillsHome(), "codex"),
|
|
12557
|
+
await installSkillsForTarget(skillsDir, claudeSkillsHome(), "claude")
|
|
12558
|
+
);
|
|
12559
|
+
}
|
|
12560
|
+
const exportsText = buildAgentEnvExports({
|
|
12561
|
+
apiBase: ctx.api.apiBase,
|
|
12562
|
+
orgId: agentRow.orgId,
|
|
12563
|
+
agentId: agentRow.id,
|
|
12564
|
+
apiKey: key.token
|
|
12565
|
+
});
|
|
12566
|
+
if (ctx.json) {
|
|
12567
|
+
printOutput(
|
|
12568
|
+
{
|
|
12569
|
+
agent: {
|
|
12570
|
+
id: agentRow.id,
|
|
12571
|
+
name: agentRow.name,
|
|
12572
|
+
urlKey: agentRow.urlKey,
|
|
12573
|
+
orgId: agentRow.orgId
|
|
12574
|
+
},
|
|
12575
|
+
key: {
|
|
12576
|
+
id: key.id,
|
|
12577
|
+
name: key.name,
|
|
12578
|
+
createdAt: key.createdAt,
|
|
12579
|
+
token: key.token
|
|
12580
|
+
},
|
|
12581
|
+
skills: installSummaries,
|
|
12582
|
+
exports: exportsText
|
|
12583
|
+
},
|
|
12584
|
+
{ json: true }
|
|
12585
|
+
);
|
|
12586
|
+
return;
|
|
12587
|
+
}
|
|
12588
|
+
console.log(`Agent: ${agentRow.name} (${agentRow.id})`);
|
|
12589
|
+
console.log(`API key created: ${key.name} (${key.id})`);
|
|
12590
|
+
if (installSummaries.length > 0) {
|
|
12591
|
+
for (const summary of installSummaries) {
|
|
12592
|
+
console.log(
|
|
12593
|
+
`${summary.tool}: linked=${summary.linked.length} removed=${summary.removed.length} skipped=${summary.skipped.length} failed=${summary.failed.length} target=${summary.target}`
|
|
12594
|
+
);
|
|
12595
|
+
for (const failed of summary.failed) {
|
|
12596
|
+
console.log(` failed ${failed.name}: ${failed.error}`);
|
|
12597
|
+
}
|
|
12598
|
+
}
|
|
12599
|
+
}
|
|
12600
|
+
console.log("");
|
|
12601
|
+
console.log("# Run this in your shell before launching codex/claude:");
|
|
12602
|
+
console.log(exportsText);
|
|
12603
|
+
} catch (err) {
|
|
12604
|
+
handleCommandError(err);
|
|
12605
|
+
}
|
|
12606
|
+
}),
|
|
12607
|
+
{ includeCompany: false }
|
|
11368
12608
|
);
|
|
11369
12609
|
}
|
|
11370
|
-
function
|
|
11371
|
-
const
|
|
11372
|
-
if (
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
}
|
|
11377
|
-
function collectNonEmptyOption(optionName) {
|
|
11378
|
-
return (value, previous) => {
|
|
11379
|
-
const trimmed = value.trim();
|
|
11380
|
-
if (!trimmed) {
|
|
11381
|
-
throw new Error(`${optionName} cannot be empty`);
|
|
11382
|
-
}
|
|
11383
|
-
return [...previous, trimmed];
|
|
11384
|
-
};
|
|
11385
|
-
}
|
|
11386
|
-
async function resolveFileTextInput(opts) {
|
|
11387
|
-
if (opts.removedTextOption && process.argv.includes(opts.removedTextOption)) {
|
|
11388
|
-
throw new Error(`${opts.removedTextOption} was removed; write the body to a file and use ${opts.fileOption} <path> or ${opts.fileOption} - for stdin`);
|
|
11389
|
-
}
|
|
11390
|
-
const hasFile = opts.file !== void 0;
|
|
11391
|
-
if (hasFile) return readTextInputFile(opts.file, opts.fileOption);
|
|
11392
|
-
if (opts.required) {
|
|
11393
|
-
throw new Error(`Provide ${opts.fileOption} <path>; use ${opts.fileOption} - for stdin`);
|
|
11394
|
-
}
|
|
11395
|
-
return void 0;
|
|
11396
|
-
}
|
|
11397
|
-
async function readTextInputFile(inputPath, optionName) {
|
|
11398
|
-
if (inputPath === "-") {
|
|
11399
|
-
return readStdinText();
|
|
11400
|
-
}
|
|
11401
|
-
const resolvedPath = path16.resolve(process.cwd(), inputPath);
|
|
11402
|
-
return readFile4(resolvedPath, "utf8").catch((err) => {
|
|
11403
|
-
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
11404
|
-
});
|
|
11405
|
-
}
|
|
11406
|
-
async function readStdinText() {
|
|
11407
|
-
const chunks = [];
|
|
11408
|
-
for await (const chunk of process.stdin) {
|
|
11409
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
11410
|
-
}
|
|
11411
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
11412
|
-
}
|
|
11413
|
-
async function resolveIssueLabelIds(ctx, opts) {
|
|
11414
|
-
const explicitIds = opts.labelId ?? [];
|
|
11415
|
-
const names = opts.label ?? [];
|
|
11416
|
-
if (names.length === 0 && explicitIds.length > 0) return [...new Set(explicitIds)];
|
|
11417
|
-
if (names.length === 0 && opts.parentId) return [];
|
|
11418
|
-
const labels = await ctx.api.get(`/api/orgs/${ctx.orgId}/labels`) ?? [];
|
|
11419
|
-
if (names.length === 0) {
|
|
11420
|
-
if (ctx.agentId && labels.length >= 5) {
|
|
11421
|
-
throw new Error(
|
|
11422
|
-
`Organization has ${labels.length} issue labels. Choose at least one with --label-id <id> or --label <name>. Available labels: ${formatAvailableLabelNames(labels)}`
|
|
11423
|
-
);
|
|
11424
|
-
}
|
|
11425
|
-
return [];
|
|
11426
|
-
}
|
|
11427
|
-
const resolvedIds = names.map((name) => {
|
|
11428
|
-
const exact = labels.find((label) => label.name === name) ?? labels.find((label) => label.name.toLowerCase() === name.toLowerCase());
|
|
11429
|
-
if (!exact) {
|
|
11430
|
-
throw new Error(`Unknown issue label "${name}". Available labels: ${formatAvailableLabelNames(labels)}`);
|
|
11431
|
-
}
|
|
11432
|
-
return exact.id;
|
|
11433
|
-
});
|
|
11434
|
-
return [.../* @__PURE__ */ new Set([...explicitIds, ...resolvedIds])];
|
|
11435
|
-
}
|
|
11436
|
-
function formatAvailableLabelNames(labels) {
|
|
11437
|
-
return labels.map((label) => label.name).join(", ") || "(none)";
|
|
11438
|
-
}
|
|
11439
|
-
async function appendUploadedIssueImages(ctx, issueId, body, imagePaths) {
|
|
11440
|
-
const paths = imagePaths ?? [];
|
|
11441
|
-
if (paths.length === 0) return body;
|
|
11442
|
-
const issue = await ctx.api.get(`/api/issues/${issueId}`);
|
|
11443
|
-
if (!issue) {
|
|
11444
|
-
throw new Error("Issue not found");
|
|
12610
|
+
async function buildAgentUpdatePatch(opts) {
|
|
12611
|
+
const rawPatch = {};
|
|
12612
|
+
if (opts.name !== void 0) rawPatch.name = opts.name;
|
|
12613
|
+
if (opts.role !== void 0) rawPatch.role = opts.role;
|
|
12614
|
+
if (opts.title !== void 0 && opts.clearTitle) {
|
|
12615
|
+
throw new Error("Pass only one of --title or --clear-title.");
|
|
11445
12616
|
}
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
|
|
11449
|
-
|
|
12617
|
+
if (opts.title !== void 0) rawPatch.title = opts.title;
|
|
12618
|
+
if (opts.clearTitle) rawPatch.title = null;
|
|
12619
|
+
if (opts.reportsTo !== void 0 && opts.clearReportsTo) {
|
|
12620
|
+
throw new Error("Pass only one of --reports-to or --clear-reports-to.");
|
|
11450
12621
|
}
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
const
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
12622
|
+
if (opts.reportsTo !== void 0) rawPatch.reportsTo = opts.reportsTo;
|
|
12623
|
+
if (opts.clearReportsTo) rawPatch.reportsTo = null;
|
|
12624
|
+
const capabilitiesInputs = [
|
|
12625
|
+
opts.capabilities !== void 0 ? "--capabilities" : null,
|
|
12626
|
+
opts.capabilitiesFile !== void 0 ? "--capabilities-file" : null,
|
|
12627
|
+
opts.description !== void 0 ? "--description" : null,
|
|
12628
|
+
opts.descriptionFile !== void 0 ? "--description-file" : null
|
|
12629
|
+
].filter(Boolean);
|
|
12630
|
+
const clearCapabilities = opts.clearCapabilities || opts.clearDescription;
|
|
12631
|
+
if (capabilitiesInputs.length > 1) {
|
|
12632
|
+
throw new Error(
|
|
12633
|
+
"Pass only one of --capabilities, --capabilities-file, --description, or --description-file."
|
|
12634
|
+
);
|
|
11464
12635
|
}
|
|
11465
|
-
|
|
11466
|
-
|
|
11467
|
-
const buffer = await readFile4(resolvedPath);
|
|
11468
|
-
if (buffer.length <= 0) {
|
|
11469
|
-
throw new Error(`Image is empty: ${imagePath}`);
|
|
12636
|
+
if (capabilitiesInputs.length > 0 && clearCapabilities) {
|
|
12637
|
+
throw new Error("Pass either capabilities/description input or a clear flag, not both.");
|
|
11470
12638
|
}
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
`/api/orgs/${issue.orgId}/issues/${issue.id}/attachments`,
|
|
11476
|
-
form
|
|
11477
|
-
);
|
|
11478
|
-
if (!attachment) {
|
|
11479
|
-
throw new Error(`Image upload returned no attachment: ${imagePath}`);
|
|
12639
|
+
if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
|
|
12640
|
+
if (opts.description !== void 0) rawPatch.capabilities = opts.description;
|
|
12641
|
+
if (opts.capabilitiesFile !== void 0) {
|
|
12642
|
+
rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.capabilitiesFile), "utf8");
|
|
11480
12643
|
}
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
function inferCommentImageContentType(filename) {
|
|
11484
|
-
const ext = path16.extname(filename).toLowerCase();
|
|
11485
|
-
switch (ext) {
|
|
11486
|
-
case ".png":
|
|
11487
|
-
return "image/png";
|
|
11488
|
-
case ".jpg":
|
|
11489
|
-
case ".jpeg":
|
|
11490
|
-
return "image/jpeg";
|
|
11491
|
-
case ".webp":
|
|
11492
|
-
return "image/webp";
|
|
11493
|
-
case ".gif":
|
|
11494
|
-
return "image/gif";
|
|
11495
|
-
default:
|
|
11496
|
-
throw new Error(`Unsupported comment image type: ${filename}. Use PNG, JPEG, WebP, or GIF.`);
|
|
12644
|
+
if (opts.descriptionFile !== void 0) {
|
|
12645
|
+
rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.descriptionFile), "utf8");
|
|
11497
12646
|
}
|
|
12647
|
+
if (clearCapabilities) rawPatch.capabilities = null;
|
|
12648
|
+
return updateAgentSchema.parse(rawPatch);
|
|
11498
12649
|
}
|
|
11499
|
-
function
|
|
11500
|
-
const alt = escapeMarkdownAltText(attachment.originalFilename ?? "image");
|
|
11501
|
-
return ``;
|
|
11502
|
-
}
|
|
11503
|
-
function escapeMarkdownAltText(value) {
|
|
11504
|
-
return value.replaceAll("\\", "\\\\").replaceAll("]", "\\]");
|
|
11505
|
-
}
|
|
11506
|
-
function parseCsv(value) {
|
|
12650
|
+
function parseCsv3(value) {
|
|
11507
12651
|
if (!value) return [];
|
|
11508
|
-
return value.split(",").map((
|
|
11509
|
-
}
|
|
11510
|
-
function parseOptionalInt(value) {
|
|
11511
|
-
if (value === void 0) return void 0;
|
|
11512
|
-
const parsed = Number.parseInt(value, 10);
|
|
11513
|
-
if (!Number.isFinite(parsed)) {
|
|
11514
|
-
throw new Error(`Invalid integer value: ${value}`);
|
|
11515
|
-
}
|
|
11516
|
-
return parsed;
|
|
11517
|
-
}
|
|
11518
|
-
function parseHiddenAt(value) {
|
|
11519
|
-
if (value === void 0) return void 0;
|
|
11520
|
-
if (value.trim().toLowerCase() === "null") return null;
|
|
11521
|
-
return value;
|
|
11522
|
-
}
|
|
11523
|
-
function parseReviewDecision(value) {
|
|
11524
|
-
const normalized = value.trim();
|
|
11525
|
-
if (normalized === "approve" || normalized === "request_changes" || normalized === "needs_followup" || normalized === "blocked") {
|
|
11526
|
-
return normalized;
|
|
11527
|
-
}
|
|
11528
|
-
throw new Error("Invalid review decision. Use approve, request_changes, needs_followup, or blocked.");
|
|
11529
|
-
}
|
|
11530
|
-
function isIssueCommentResponse(value) {
|
|
11531
|
-
return Boolean(
|
|
11532
|
-
value && typeof value.id === "string" && value.id.trim().length > 0 && typeof value.issueId === "string" && value.issueId.trim().length > 0 && typeof value.body === "string"
|
|
11533
|
-
);
|
|
11534
|
-
}
|
|
11535
|
-
function filterIssueRows(rows, match) {
|
|
11536
|
-
if (!match?.trim()) return rows;
|
|
11537
|
-
const needle = match.trim().toLowerCase();
|
|
11538
|
-
return rows.filter((row) => {
|
|
11539
|
-
const text6 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
|
|
11540
|
-
return text6.includes(needle);
|
|
11541
|
-
});
|
|
11542
|
-
}
|
|
11543
|
-
function buildIssueListPath(orgId, opts, searchQuery) {
|
|
11544
|
-
const params = new URLSearchParams();
|
|
11545
|
-
if (opts.status) params.set("status", opts.status);
|
|
11546
|
-
if (opts.assigneeAgentId) params.set("assigneeAgentId", opts.assigneeAgentId);
|
|
11547
|
-
if (opts.projectId) params.set("projectId", opts.projectId);
|
|
11548
|
-
if (searchQuery?.trim()) {
|
|
11549
|
-
params.set("q", searchQuery.trim());
|
|
11550
|
-
params.set("searchFields", "title,description,comment");
|
|
11551
|
-
}
|
|
11552
|
-
const query = params.toString();
|
|
11553
|
-
return `/api/orgs/${orgId}/issues${query ? `?${query}` : ""}`;
|
|
12652
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
11554
12653
|
}
|
|
11555
|
-
function
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
for (const item of rows) {
|
|
11565
|
-
console.log(
|
|
11566
|
-
formatInlineRecord({
|
|
11567
|
-
identifier: item.identifier,
|
|
11568
|
-
id: item.id,
|
|
11569
|
-
status: item.status,
|
|
11570
|
-
priority: item.priority,
|
|
11571
|
-
assigneeAgentId: item.assigneeAgentId,
|
|
11572
|
-
assigneeUserId: item.assigneeUserId,
|
|
11573
|
-
title: item.title,
|
|
11574
|
-
projectId: item.projectId,
|
|
11575
|
-
updatedAt: item.updatedAt,
|
|
11576
|
-
...item.searchMatch ? { match: formatIssueSearchMatch(item.searchMatch) } : {}
|
|
11577
|
-
})
|
|
11578
|
-
);
|
|
12654
|
+
function parseJsonObject(value, name) {
|
|
12655
|
+
try {
|
|
12656
|
+
const parsed = JSON.parse(value);
|
|
12657
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
12658
|
+
throw new Error(`${name} must be a JSON object`);
|
|
12659
|
+
}
|
|
12660
|
+
return parsed;
|
|
12661
|
+
} catch (err) {
|
|
12662
|
+
throw new Error(`Invalid ${name} JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
11579
12663
|
}
|
|
11580
12664
|
}
|
|
11581
|
-
function formatIssueSearchMatch(match) {
|
|
11582
|
-
const commentSuffix = match.commentId ? `#${match.commentId}` : "";
|
|
11583
|
-
return `${match.field}${commentSuffix}: ${match.snippet}`;
|
|
11584
|
-
}
|
|
11585
12665
|
|
|
11586
|
-
// src/commands/client/
|
|
12666
|
+
// src/commands/client/approval.ts
|
|
11587
12667
|
init_dist();
|
|
11588
|
-
|
|
11589
|
-
|
|
12668
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
12669
|
+
import path19 from "node:path";
|
|
12670
|
+
function registerApprovalCommands(program) {
|
|
12671
|
+
const approval = program.command("approval").description("Approval operations");
|
|
11590
12672
|
addCommonClientOptions(
|
|
11591
|
-
|
|
12673
|
+
approval.command("list").description("List approvals for an organization").option("-O, --org-id <id>", "Organization ID").option("--status <status>", "Status filter").action(async (opts) => {
|
|
11592
12674
|
try {
|
|
11593
12675
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11594
|
-
const
|
|
11595
|
-
|
|
12676
|
+
const params = new URLSearchParams();
|
|
12677
|
+
if (opts.status) params.set("status", opts.status);
|
|
12678
|
+
const query = params.toString();
|
|
12679
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/approvals${query ? `?${query}` : ""}`) ?? [];
|
|
12680
|
+
if (ctx.json) {
|
|
12681
|
+
printOutput(rows, { json: true });
|
|
12682
|
+
return;
|
|
12683
|
+
}
|
|
12684
|
+
if (rows.length === 0) {
|
|
12685
|
+
printOutput([], { json: false });
|
|
12686
|
+
return;
|
|
12687
|
+
}
|
|
12688
|
+
for (const row of rows) {
|
|
12689
|
+
console.log(
|
|
12690
|
+
formatInlineRecord({
|
|
12691
|
+
id: row.id,
|
|
12692
|
+
type: row.type,
|
|
12693
|
+
status: row.status,
|
|
12694
|
+
requestedByAgentId: row.requestedByAgentId,
|
|
12695
|
+
requestedByUserId: row.requestedByUserId
|
|
12696
|
+
})
|
|
12697
|
+
);
|
|
12698
|
+
}
|
|
11596
12699
|
} catch (err) {
|
|
11597
12700
|
handleCommandError(err);
|
|
11598
12701
|
}
|
|
@@ -11600,32 +12703,39 @@ function registerProjectCommands(program) {
|
|
|
11600
12703
|
{ includeCompany: false }
|
|
11601
12704
|
);
|
|
11602
12705
|
addCommonClientOptions(
|
|
11603
|
-
|
|
12706
|
+
approval.command("get").description(getAgentCliCapabilityById("approval.get").description).argument("<approvalId>", "Approval ID").action(async (approvalId, opts) => {
|
|
11604
12707
|
try {
|
|
11605
12708
|
const ctx = resolveCommandContext(opts);
|
|
11606
|
-
const row = await ctx.api.get(
|
|
12709
|
+
const row = await ctx.api.get(`/api/approvals/${approvalId}`);
|
|
11607
12710
|
printOutput(row, { json: ctx.json });
|
|
11608
12711
|
} catch (err) {
|
|
11609
12712
|
handleCommandError(err);
|
|
11610
12713
|
}
|
|
11611
|
-
})
|
|
11612
|
-
{ includeCompany: false }
|
|
12714
|
+
})
|
|
11613
12715
|
);
|
|
11614
12716
|
addCommonClientOptions(
|
|
11615
|
-
|
|
12717
|
+
approval.command("issues").description(getAgentCliCapabilityById("approval.issues").description).argument("<approvalId>", "Approval ID").action(async (approvalId, opts) => {
|
|
12718
|
+
try {
|
|
12719
|
+
const ctx = resolveCommandContext(opts);
|
|
12720
|
+
const rows = await ctx.api.get(`/api/approvals/${approvalId}/issues`) ?? [];
|
|
12721
|
+
printOutput(rows, { json: ctx.json });
|
|
12722
|
+
} catch (err) {
|
|
12723
|
+
handleCommandError(err);
|
|
12724
|
+
}
|
|
12725
|
+
})
|
|
12726
|
+
);
|
|
12727
|
+
addCommonClientOptions(
|
|
12728
|
+
approval.command("create").description(getAgentCliCapabilityById("approval.create").description).option("-O, --org-id <id>", "Organization ID").requiredOption("--type <type>", "Approval type (hire_agent|approve_ceo_strategy)").requiredOption("--payload <json>", "Approval payload as JSON object").option("--requested-by-agent-id <id>", "Requesting agent ID").option("--issue-ids <csv>", "Comma-separated linked issue IDs").action(async (opts) => {
|
|
11616
12729
|
try {
|
|
11617
12730
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11618
|
-
const
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
leadAgentId: opts.leadAgentId,
|
|
11625
|
-
targetDate: opts.targetDate,
|
|
11626
|
-
color: opts.color
|
|
12731
|
+
const payloadJson = parseJsonObject2(opts.payload, "payload");
|
|
12732
|
+
const payload = createApprovalSchema.parse({
|
|
12733
|
+
type: opts.type,
|
|
12734
|
+
payload: payloadJson,
|
|
12735
|
+
requestedByAgentId: opts.requestedByAgentId,
|
|
12736
|
+
issueIds: parseCsv4(opts.issueIds)
|
|
11627
12737
|
});
|
|
11628
|
-
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/
|
|
12738
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/approvals`, payload);
|
|
11629
12739
|
printOutput(created, { json: ctx.json });
|
|
11630
12740
|
} catch (err) {
|
|
11631
12741
|
handleCommandError(err);
|
|
@@ -11634,312 +12744,132 @@ function registerProjectCommands(program) {
|
|
|
11634
12744
|
{ includeCompany: false }
|
|
11635
12745
|
);
|
|
11636
12746
|
addCommonClientOptions(
|
|
11637
|
-
|
|
12747
|
+
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").action(async (approvalId, opts) => {
|
|
11638
12748
|
try {
|
|
11639
12749
|
const ctx = resolveCommandContext(opts);
|
|
11640
|
-
const payload =
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
status: opts.status,
|
|
11644
|
-
goalId: opts.goalId,
|
|
11645
|
-
goalIds: parseCsv2(opts.goalIds),
|
|
11646
|
-
leadAgentId: opts.leadAgentId,
|
|
11647
|
-
targetDate: opts.targetDate,
|
|
11648
|
-
color: opts.color,
|
|
11649
|
-
archivedAt: parseNullableOption(opts.archivedAt)
|
|
12750
|
+
const payload = resolveApprovalSchema.parse({
|
|
12751
|
+
decisionNote: opts.decisionNote,
|
|
12752
|
+
decidedByUserId: opts.decidedByUserId
|
|
11650
12753
|
});
|
|
11651
|
-
const updated = await ctx.api.
|
|
12754
|
+
const updated = await ctx.api.post(`/api/approvals/${approvalId}/approve`, payload);
|
|
11652
12755
|
printOutput(updated, { json: ctx.json });
|
|
11653
12756
|
} catch (err) {
|
|
11654
12757
|
handleCommandError(err);
|
|
11655
12758
|
}
|
|
11656
|
-
})
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11668
|
-
}
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
const query = params.toString();
|
|
11673
|
-
return `/api/projects/${encodeURIComponent(projectRef)}${query ? `?${query}` : ""}`;
|
|
11674
|
-
}
|
|
11675
|
-
|
|
11676
|
-
// src/commands/client/agent.ts
|
|
11677
|
-
init_dist();
|
|
11678
|
-
|
|
11679
|
-
// ../packages/agent-runtime-utils/dist/server-utils.process.js
|
|
11680
|
-
var MAX_CAPTURE_BYTES = 4 * 1024 * 1024;
|
|
11681
|
-
var MAX_EXCERPT_BYTES = 32 * 1024;
|
|
11682
|
-
var RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES = [
|
|
11683
|
-
"../../server/resources/bundled-skills",
|
|
11684
|
-
"../../skills",
|
|
11685
|
-
"../../../../../server/resources/bundled-skills"
|
|
11686
|
-
];
|
|
11687
|
-
function normalizePathSlashes(value) {
|
|
11688
|
-
return value.replaceAll("\\", "/");
|
|
11689
|
-
}
|
|
11690
|
-
function isMaintainerOnlySkillTarget(candidate) {
|
|
11691
|
-
const normalized = normalizePathSlashes(candidate);
|
|
11692
|
-
return normalized.includes("/server/resources/bundled-skills/") || normalized.includes("/.agents/skills/");
|
|
11693
|
-
}
|
|
11694
|
-
|
|
11695
|
-
// ../packages/agent-runtime-utils/dist/server-utils.prompts.js
|
|
11696
|
-
var RUDDER_AGENT_OPERATING_CONTRACT = [
|
|
11697
|
-
"# Rudder Agent Operating Contract",
|
|
11698
|
-
"",
|
|
11699
|
-
"Your home directory is `$AGENT_HOME`. Everything personal to you -- life, memory, knowledge -- lives there. Other agents may have their own folders and you may update them when necessary.",
|
|
11700
|
-
"",
|
|
11701
|
-
"Use these paths consistently:",
|
|
11702
|
-
"",
|
|
11703
|
-
"- Personal instructions live under `$AGENT_HOME/instructions`.",
|
|
11704
|
-
"- Personal memory lives under `$AGENT_HOME/memory`.",
|
|
11705
|
-
"- Tacit memory instruction lives at `$AGENT_HOME/instructions/MEMORY.md` and is automatically loaded when present.",
|
|
11706
|
-
"- Personal skills live under `$AGENT_HOME/skills`.",
|
|
11707
|
-
"- Shared organization workspace root lives under `$RUDDER_ORG_WORKSPACE_ROOT`.",
|
|
11708
|
-
"- Shared organization skills live under `$RUDDER_ORG_SKILLS_DIR`.",
|
|
11709
|
-
'- Library-backed project resources use `sourceType: "library"`; their `locator` points into `library:projects/<project-name>/`.',
|
|
11710
|
-
"- Project Context is explicit operator-curated context, not the whole knowledge boundary. When it is insufficient, inspect broader Library and org workspace know-how before concluding context is missing.",
|
|
11711
|
-
"- Durable generated project work files should be written under `library:projects/<project-name>/`.",
|
|
11712
|
-
"- When you create or update a durable Library file, always include a user-visible Markdown link to that file in your final chat reply or issue comment. Use `library-file://file?p=<url-encoded-relative-path>&t=<url-encoded-title>` for Library file links.",
|
|
11713
|
-
"- Use `/tmp` only for transient scratch files and temporary verification files; do not put durable work product there.",
|
|
11714
|
-
"- Local trusted runtimes may expose the host operator home as `$RUDDER_OPERATOR_HOME`; use it only when a local skill or script intentionally needs operator-owned desktop app or CLI state. Do not replace `$HOME` with it.",
|
|
11715
|
-
"",
|
|
11716
|
-
"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.",
|
|
11717
|
-
"",
|
|
11718
|
-
"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.",
|
|
11719
|
-
"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.",
|
|
11720
|
-
"",
|
|
11721
|
-
"Mention-triggered comment wakes arrive with `RUDDER_WAKE_COMMENT_ID`; read that wake comment before acting. Board/operator issue comments can wake an agent with a plain `@AgentName` token or an issue-composer agent mention serialized as `agent://agent-id?intent=wake`. Plain structured links such as `agent://agent-id` are reference-only links for rendering and navigation. Agent-authored issue comments do not fan out peer wakeups by default; use reviewer, assignment, or explicit handoff workflow instead. 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.",
|
|
11722
|
-
"",
|
|
11723
|
-
"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.",
|
|
11724
|
-
"",
|
|
11725
|
-
"## Memory and Shared Work Notes",
|
|
11726
|
-
"",
|
|
11727
|
-
"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.",
|
|
11728
|
-
"",
|
|
11729
|
-
"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; those files are not auto-loaded.",
|
|
11730
|
-
"",
|
|
11731
|
-
"Invoke it whenever you need to remember, retrieve, or organize anything.",
|
|
11732
|
-
"",
|
|
11733
|
-
"## Safety Considerations",
|
|
11734
|
-
"",
|
|
11735
|
-
"- Never exfiltrate secrets or private data.",
|
|
11736
|
-
"- Do not perform any destructive commands unless explicitly requested by the board."
|
|
11737
|
-
].join("\n");
|
|
11738
|
-
|
|
11739
|
-
// ../packages/agent-runtime-utils/dist/server-utils.cli.js
|
|
11740
|
-
import { promises as fs13 } from "node:fs";
|
|
11741
|
-
import path17 from "node:path";
|
|
11742
|
-
async function resolveRudderSkillsDir(moduleDir, additionalCandidates = []) {
|
|
11743
|
-
const candidates = [
|
|
11744
|
-
...RUDDER_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path17.resolve(moduleDir, relativePath)),
|
|
11745
|
-
...additionalCandidates.map((candidate) => path17.resolve(candidate))
|
|
11746
|
-
];
|
|
11747
|
-
const seenRoots = /* @__PURE__ */ new Set();
|
|
11748
|
-
for (const root of candidates) {
|
|
11749
|
-
if (seenRoots.has(root))
|
|
11750
|
-
continue;
|
|
11751
|
-
seenRoots.add(root);
|
|
11752
|
-
const isDirectory = await fs13.stat(root).then((stats) => stats.isDirectory()).catch(() => false);
|
|
11753
|
-
if (isDirectory)
|
|
11754
|
-
return root;
|
|
11755
|
-
}
|
|
11756
|
-
return null;
|
|
11757
|
-
}
|
|
11758
|
-
async function removeMaintainerOnlySkillSymlinks(skillsHome, allowedSkillNames) {
|
|
11759
|
-
const allowed = new Set(Array.from(allowedSkillNames));
|
|
11760
|
-
try {
|
|
11761
|
-
const entries = await fs13.readdir(skillsHome, { withFileTypes: true });
|
|
11762
|
-
const removed = [];
|
|
11763
|
-
for (const entry of entries) {
|
|
11764
|
-
if (allowed.has(entry.name))
|
|
11765
|
-
continue;
|
|
11766
|
-
const target = path17.join(skillsHome, entry.name);
|
|
11767
|
-
const existing = await fs13.lstat(target).catch(() => null);
|
|
11768
|
-
if (!existing?.isSymbolicLink())
|
|
11769
|
-
continue;
|
|
11770
|
-
const linkedPath = await fs13.readlink(target).catch(() => null);
|
|
11771
|
-
if (!linkedPath)
|
|
11772
|
-
continue;
|
|
11773
|
-
const resolvedLinkedPath = path17.isAbsolute(linkedPath) ? linkedPath : path17.resolve(path17.dirname(target), linkedPath);
|
|
11774
|
-
if (!isMaintainerOnlySkillTarget(linkedPath) && !isMaintainerOnlySkillTarget(resolvedLinkedPath)) {
|
|
11775
|
-
continue;
|
|
11776
|
-
}
|
|
11777
|
-
await fs13.unlink(target);
|
|
11778
|
-
removed.push(entry.name);
|
|
11779
|
-
}
|
|
11780
|
-
return removed;
|
|
11781
|
-
} catch {
|
|
11782
|
-
return [];
|
|
11783
|
-
}
|
|
11784
|
-
}
|
|
11785
|
-
|
|
11786
|
-
// src/commands/client/agent.ts
|
|
11787
|
-
import fs14 from "node:fs/promises";
|
|
11788
|
-
import os2 from "node:os";
|
|
11789
|
-
import path18 from "node:path";
|
|
11790
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
11791
|
-
var __moduleDir = path18.dirname(fileURLToPath3(import.meta.url));
|
|
11792
|
-
function codexSkillsHome() {
|
|
11793
|
-
const fromEnv = process.env.CODEX_HOME?.trim();
|
|
11794
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".codex");
|
|
11795
|
-
return path18.join(base, "skills");
|
|
11796
|
-
}
|
|
11797
|
-
function claudeSkillsHome() {
|
|
11798
|
-
const fromEnv = process.env.CLAUDE_HOME?.trim();
|
|
11799
|
-
const base = fromEnv && fromEnv.length > 0 ? fromEnv : path18.join(os2.homedir(), ".claude");
|
|
11800
|
-
return path18.join(base, "skills");
|
|
11801
|
-
}
|
|
11802
|
-
async function installSkillsForTarget(sourceSkillsDir, targetSkillsDir, tool) {
|
|
11803
|
-
const summary = {
|
|
11804
|
-
tool,
|
|
11805
|
-
target: targetSkillsDir,
|
|
11806
|
-
linked: [],
|
|
11807
|
-
removed: [],
|
|
11808
|
-
skipped: [],
|
|
11809
|
-
failed: []
|
|
11810
|
-
};
|
|
11811
|
-
await fs14.mkdir(targetSkillsDir, { recursive: true });
|
|
11812
|
-
const entries = await fs14.readdir(sourceSkillsDir, { withFileTypes: true });
|
|
11813
|
-
summary.removed = await removeMaintainerOnlySkillSymlinks(
|
|
11814
|
-
targetSkillsDir,
|
|
11815
|
-
entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
12759
|
+
})
|
|
12760
|
+
);
|
|
12761
|
+
addCommonClientOptions(
|
|
12762
|
+
approval.command("reject").description("Reject an approval request").argument("<approvalId>", "Approval ID").option("--decision-note <text>", "Decision note").option("--decided-by-user-id <id>", "Decision actor user ID").action(async (approvalId, opts) => {
|
|
12763
|
+
try {
|
|
12764
|
+
const ctx = resolveCommandContext(opts);
|
|
12765
|
+
const payload = resolveApprovalSchema.parse({
|
|
12766
|
+
decisionNote: opts.decisionNote,
|
|
12767
|
+
decidedByUserId: opts.decidedByUserId
|
|
12768
|
+
});
|
|
12769
|
+
const updated = await ctx.api.post(`/api/approvals/${approvalId}/reject`, payload);
|
|
12770
|
+
printOutput(updated, { json: ctx.json });
|
|
12771
|
+
} catch (err) {
|
|
12772
|
+
handleCommandError(err);
|
|
12773
|
+
}
|
|
12774
|
+
})
|
|
11816
12775
|
);
|
|
11817
|
-
for (const entry of entries) {
|
|
11818
|
-
if (!entry.isDirectory()) continue;
|
|
11819
|
-
const source = path18.join(sourceSkillsDir, entry.name);
|
|
11820
|
-
const target = path18.join(targetSkillsDir, entry.name);
|
|
11821
|
-
const existing = await fs14.lstat(target).catch(() => null);
|
|
11822
|
-
if (existing) {
|
|
11823
|
-
if (existing.isSymbolicLink()) {
|
|
11824
|
-
let linkedPath = null;
|
|
11825
|
-
try {
|
|
11826
|
-
linkedPath = await fs14.readlink(target);
|
|
11827
|
-
} catch (err) {
|
|
11828
|
-
await fs14.unlink(target);
|
|
11829
|
-
try {
|
|
11830
|
-
await fs14.symlink(source, target);
|
|
11831
|
-
summary.linked.push(entry.name);
|
|
11832
|
-
continue;
|
|
11833
|
-
} catch (linkErr) {
|
|
11834
|
-
summary.failed.push({
|
|
11835
|
-
name: entry.name,
|
|
11836
|
-
error: err instanceof Error && linkErr instanceof Error ? `${err.message}; then ${linkErr.message}` : err instanceof Error ? err.message : `Failed to recover broken symlink: ${String(err)}`
|
|
11837
|
-
});
|
|
11838
|
-
continue;
|
|
11839
|
-
}
|
|
11840
|
-
}
|
|
11841
|
-
const resolvedLinkedPath = path18.isAbsolute(linkedPath) ? linkedPath : path18.resolve(path18.dirname(target), linkedPath);
|
|
11842
|
-
const linkedTargetExists = await fs14.stat(resolvedLinkedPath).then(() => true).catch(() => false);
|
|
11843
|
-
if (!linkedTargetExists) {
|
|
11844
|
-
await fs14.unlink(target);
|
|
11845
|
-
} else {
|
|
11846
|
-
summary.skipped.push(entry.name);
|
|
11847
|
-
continue;
|
|
11848
|
-
}
|
|
11849
|
-
} else {
|
|
11850
|
-
summary.skipped.push(entry.name);
|
|
11851
|
-
continue;
|
|
11852
|
-
}
|
|
11853
|
-
}
|
|
11854
|
-
try {
|
|
11855
|
-
await fs14.symlink(source, target);
|
|
11856
|
-
summary.linked.push(entry.name);
|
|
11857
|
-
} catch (err) {
|
|
11858
|
-
summary.failed.push({
|
|
11859
|
-
name: entry.name,
|
|
11860
|
-
error: err instanceof Error ? err.message : String(err)
|
|
11861
|
-
});
|
|
11862
|
-
}
|
|
11863
|
-
}
|
|
11864
|
-
return summary;
|
|
11865
|
-
}
|
|
11866
|
-
function buildAgentEnvExports(input) {
|
|
11867
|
-
const escaped = (value) => value.replace(/'/g, `'"'"'`);
|
|
11868
|
-
return [
|
|
11869
|
-
`export RUDDER_API_URL='${escaped(input.apiBase)}'`,
|
|
11870
|
-
`export RUDDER_ORG_ID='${escaped(input.orgId)}'`,
|
|
11871
|
-
`export RUDDER_AGENT_ID='${escaped(input.agentId)}'`,
|
|
11872
|
-
`export RUDDER_API_KEY='${escaped(input.apiKey)}'`
|
|
11873
|
-
].join("\n");
|
|
11874
|
-
}
|
|
11875
|
-
function registerAgentCommands(program) {
|
|
11876
|
-
const agent = program.command("agent").description("Agent operations");
|
|
11877
|
-
const config = agent.command("config").description("Agent configuration discovery and redacted snapshots");
|
|
11878
12776
|
addCommonClientOptions(
|
|
11879
|
-
|
|
12777
|
+
approval.command("request-revision").description("Request revision for an approval").argument("<approvalId>", "Approval ID").option("--decision-note <text>", "Decision note").option("--decided-by-user-id <id>", "Decision actor user ID").action(async (approvalId, opts) => {
|
|
11880
12778
|
try {
|
|
11881
12779
|
const ctx = resolveCommandContext(opts);
|
|
11882
|
-
const
|
|
11883
|
-
|
|
12780
|
+
const payload = requestApprovalRevisionSchema.parse({
|
|
12781
|
+
decisionNote: opts.decisionNote,
|
|
12782
|
+
decidedByUserId: opts.decidedByUserId
|
|
12783
|
+
});
|
|
12784
|
+
const updated = await ctx.api.post(`/api/approvals/${approvalId}/request-revision`, payload);
|
|
12785
|
+
printOutput(updated, { json: ctx.json });
|
|
11884
12786
|
} catch (err) {
|
|
11885
12787
|
handleCommandError(err);
|
|
11886
12788
|
}
|
|
11887
12789
|
})
|
|
11888
12790
|
);
|
|
11889
12791
|
addCommonClientOptions(
|
|
11890
|
-
|
|
12792
|
+
approval.command("resubmit").description(getAgentCliCapabilityById("approval.resubmit").description).argument("<approvalId>", "Approval ID").option("--payload <json>", "Payload JSON object").action(async (approvalId, opts) => {
|
|
11891
12793
|
try {
|
|
11892
12794
|
const ctx = resolveCommandContext(opts);
|
|
11893
|
-
const
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
}
|
|
11898
|
-
if (rows.length === 0) {
|
|
11899
|
-
printOutput([], { json: false });
|
|
11900
|
-
return;
|
|
11901
|
-
}
|
|
11902
|
-
for (const row of rows) {
|
|
11903
|
-
console.log(
|
|
11904
|
-
formatInlineRecord({
|
|
11905
|
-
identifier: row.identifier,
|
|
11906
|
-
id: row.id,
|
|
11907
|
-
relationship: row.relationship ?? "assignee",
|
|
11908
|
-
status: row.status,
|
|
11909
|
-
priority: row.priority,
|
|
11910
|
-
title: row.title,
|
|
11911
|
-
projectId: row.projectId,
|
|
11912
|
-
goalId: row.goalId,
|
|
11913
|
-
parentId: row.parentId,
|
|
11914
|
-
updatedAt: row.updatedAt
|
|
11915
|
-
})
|
|
11916
|
-
);
|
|
11917
|
-
}
|
|
12795
|
+
const payload = resubmitApprovalSchema.parse({
|
|
12796
|
+
payload: opts.payload ? parseJsonObject2(opts.payload, "payload") : void 0
|
|
12797
|
+
});
|
|
12798
|
+
const updated = await ctx.api.post(`/api/approvals/${approvalId}/resubmit`, payload);
|
|
12799
|
+
printOutput(updated, { json: ctx.json });
|
|
11918
12800
|
} catch (err) {
|
|
11919
12801
|
handleCommandError(err);
|
|
11920
12802
|
}
|
|
11921
12803
|
})
|
|
11922
12804
|
);
|
|
11923
12805
|
addCommonClientOptions(
|
|
11924
|
-
|
|
12806
|
+
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").action(async (approvalId, opts) => {
|
|
11925
12807
|
try {
|
|
11926
|
-
const
|
|
11927
|
-
const
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
}
|
|
11932
|
-
console.log(formatAgentCliCapabilitiesHumanReadable(capabilities));
|
|
12808
|
+
const ctx = resolveCommandContext(opts);
|
|
12809
|
+
const body = await resolveBodyFile(opts.bodyFile);
|
|
12810
|
+
const created = await ctx.api.post(`/api/approvals/${approvalId}/comments`, {
|
|
12811
|
+
body
|
|
12812
|
+
});
|
|
12813
|
+
printOutput(created, { json: ctx.json });
|
|
11933
12814
|
} catch (err) {
|
|
11934
12815
|
handleCommandError(err);
|
|
11935
12816
|
}
|
|
11936
12817
|
})
|
|
11937
12818
|
);
|
|
12819
|
+
}
|
|
12820
|
+
async function resolveBodyFile(inputPath) {
|
|
12821
|
+
if (!inputPath) {
|
|
12822
|
+
throw new Error("Provide --body-file <path>; use --body-file - for stdin");
|
|
12823
|
+
}
|
|
12824
|
+
return readTextInputFile2(inputPath, "--body-file");
|
|
12825
|
+
}
|
|
12826
|
+
async function readTextInputFile2(inputPath, optionName) {
|
|
12827
|
+
if (inputPath === "-") {
|
|
12828
|
+
return readStdinText2();
|
|
12829
|
+
}
|
|
12830
|
+
const resolvedPath = path19.resolve(process.cwd(), inputPath);
|
|
12831
|
+
return readFile5(resolvedPath, "utf8").catch((err) => {
|
|
12832
|
+
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
12833
|
+
});
|
|
12834
|
+
}
|
|
12835
|
+
async function readStdinText2() {
|
|
12836
|
+
const chunks = [];
|
|
12837
|
+
for await (const chunk of process.stdin) {
|
|
12838
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
12839
|
+
}
|
|
12840
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
12841
|
+
}
|
|
12842
|
+
function parseCsv4(value) {
|
|
12843
|
+
if (!value) return void 0;
|
|
12844
|
+
const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
12845
|
+
return rows.length > 0 ? rows : void 0;
|
|
12846
|
+
}
|
|
12847
|
+
function parseJsonObject2(value, name) {
|
|
12848
|
+
try {
|
|
12849
|
+
const parsed = JSON.parse(value);
|
|
12850
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
12851
|
+
throw new Error(`${name} must be a JSON object`);
|
|
12852
|
+
}
|
|
12853
|
+
return parsed;
|
|
12854
|
+
} catch (err) {
|
|
12855
|
+
throw new Error(`Invalid ${name} JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
12856
|
+
}
|
|
12857
|
+
}
|
|
12858
|
+
|
|
12859
|
+
// src/commands/client/activity.ts
|
|
12860
|
+
function registerActivityCommands(program) {
|
|
12861
|
+
const activity = program.command("activity").description("Activity log operations");
|
|
11938
12862
|
addCommonClientOptions(
|
|
11939
|
-
|
|
12863
|
+
activity.command("list").description("List organization activity log entries").option("-O, --org-id <id>", "Organization ID").option("--agent-id <id>", "Filter by agent ID").option("--entity-type <type>", "Filter by entity type").option("--entity-id <id>", "Filter by entity ID").action(async (opts) => {
|
|
11940
12864
|
try {
|
|
11941
12865
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11942
|
-
const
|
|
12866
|
+
const params = new URLSearchParams();
|
|
12867
|
+
if (opts.agentId) params.set("agentId", opts.agentId);
|
|
12868
|
+
if (opts.entityType) params.set("entityType", opts.entityType);
|
|
12869
|
+
if (opts.entityId) params.set("entityId", opts.entityId);
|
|
12870
|
+
const query = params.toString();
|
|
12871
|
+
const path23 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
|
|
12872
|
+
const rows = await ctx.api.get(path23) ?? [];
|
|
11943
12873
|
if (ctx.json) {
|
|
11944
12874
|
printOutput(rows, { json: true });
|
|
11945
12875
|
return;
|
|
@@ -11952,12 +12882,12 @@ function registerAgentCommands(program) {
|
|
|
11952
12882
|
console.log(
|
|
11953
12883
|
formatInlineRecord({
|
|
11954
12884
|
id: row.id,
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
12885
|
+
action: row.action,
|
|
12886
|
+
actorType: row.actorType,
|
|
12887
|
+
actorId: row.actorId,
|
|
12888
|
+
entityType: row.entityType,
|
|
12889
|
+
entityId: row.entityId,
|
|
12890
|
+
createdAt: String(row.createdAt)
|
|
11961
12891
|
})
|
|
11962
12892
|
);
|
|
11963
12893
|
}
|
|
@@ -11967,35 +12897,34 @@ function registerAgentCommands(program) {
|
|
|
11967
12897
|
}),
|
|
11968
12898
|
{ includeCompany: false }
|
|
11969
12899
|
);
|
|
12900
|
+
}
|
|
12901
|
+
|
|
12902
|
+
// src/commands/client/dashboard.ts
|
|
12903
|
+
function registerDashboardCommands(program) {
|
|
12904
|
+
const dashboard = program.command("dashboard").description("Dashboard summary operations");
|
|
11970
12905
|
addCommonClientOptions(
|
|
11971
|
-
|
|
11972
|
-
try {
|
|
11973
|
-
const ctx = resolveCommandContext(opts);
|
|
11974
|
-
const doc = await ctx.api.get("/llms/agent-configuration.txt");
|
|
11975
|
-
printOutput(doc ?? "", { json: ctx.json });
|
|
11976
|
-
} catch (err) {
|
|
11977
|
-
handleCommandError(err);
|
|
11978
|
-
}
|
|
11979
|
-
})
|
|
11980
|
-
);
|
|
11981
|
-
addCommonClientOptions(
|
|
11982
|
-
config.command("doc").description(getAgentCliCapabilityById("agent.config.doc").description).argument("<agentRuntimeType>", "Agent runtime type").action(async (agentRuntimeType, opts) => {
|
|
12906
|
+
dashboard.command("get").description("Get dashboard summary for an organization").option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
11983
12907
|
try {
|
|
11984
|
-
const ctx = resolveCommandContext(opts);
|
|
11985
|
-
const
|
|
11986
|
-
|
|
11987
|
-
);
|
|
11988
|
-
printOutput(doc ?? "", { json: ctx.json });
|
|
12908
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12909
|
+
const row = await ctx.api.get(`/api/orgs/${ctx.orgId}/dashboard`);
|
|
12910
|
+
printOutput(row, { json: ctx.json });
|
|
11989
12911
|
} catch (err) {
|
|
11990
12912
|
handleCommandError(err);
|
|
11991
12913
|
}
|
|
11992
|
-
})
|
|
12914
|
+
}),
|
|
12915
|
+
{ includeCompany: false }
|
|
11993
12916
|
);
|
|
12917
|
+
}
|
|
12918
|
+
|
|
12919
|
+
// src/commands/client/skill.ts
|
|
12920
|
+
init_dist();
|
|
12921
|
+
function registerSkillCommands(program) {
|
|
12922
|
+
const skill = program.command("skill").description("Organization skill library operations");
|
|
11994
12923
|
addCommonClientOptions(
|
|
11995
|
-
|
|
12924
|
+
skill.command("list").description(getAgentCliCapabilityById("skill.list").description).option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
|
|
11996
12925
|
try {
|
|
11997
12926
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
11998
|
-
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/
|
|
12927
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/skills`) ?? [];
|
|
11999
12928
|
if (ctx.json) {
|
|
12000
12929
|
printOutput(rows, { json: true });
|
|
12001
12930
|
return;
|
|
@@ -12008,12 +12937,12 @@ function registerAgentCommands(program) {
|
|
|
12008
12937
|
console.log(
|
|
12009
12938
|
formatInlineRecord({
|
|
12010
12939
|
id: row.id,
|
|
12940
|
+
key: row.key,
|
|
12941
|
+
slug: row.slug,
|
|
12011
12942
|
name: row.name,
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
reportsTo: row.reportsTo,
|
|
12016
|
-
updatedAt: row.updatedAt
|
|
12943
|
+
sourceBadge: row.sourceBadge,
|
|
12944
|
+
compatibility: row.compatibility,
|
|
12945
|
+
attachedAgentCount: row.attachedAgentCount
|
|
12017
12946
|
})
|
|
12018
12947
|
);
|
|
12019
12948
|
}
|
|
@@ -12024,342 +12953,232 @@ function registerAgentCommands(program) {
|
|
|
12024
12953
|
{ includeCompany: false }
|
|
12025
12954
|
);
|
|
12026
12955
|
addCommonClientOptions(
|
|
12027
|
-
|
|
12956
|
+
skill.command("get").description(getAgentCliCapabilityById("skill.get").description).argument("<skillId>", "Skill ID").option("-O, --org-id <id>", "Organization ID").action(async (skillId, opts) => {
|
|
12028
12957
|
try {
|
|
12029
|
-
const ctx = resolveCommandContext(opts);
|
|
12030
|
-
const
|
|
12031
|
-
if (ctx.orgId) query.set("orgId", ctx.orgId);
|
|
12032
|
-
const row = await ctx.api.get(
|
|
12033
|
-
`/api/agents/${encodeURIComponent(agentId)}/configuration${query.size > 0 ? `?${query.toString()}` : ""}`
|
|
12034
|
-
);
|
|
12958
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12959
|
+
const row = await ctx.api.get(`/api/orgs/${ctx.orgId}/skills/${skillId}`);
|
|
12035
12960
|
printOutput(row, { json: ctx.json });
|
|
12036
12961
|
} catch (err) {
|
|
12037
12962
|
handleCommandError(err);
|
|
12038
12963
|
}
|
|
12039
|
-
})
|
|
12040
|
-
|
|
12041
|
-
addCommonClientOptions(
|
|
12042
|
-
agent.command("icons").description(getAgentCliCapabilityById("agent.icons").description).action(async (opts) => {
|
|
12043
|
-
try {
|
|
12044
|
-
const ctx = resolveCommandContext(opts);
|
|
12045
|
-
const doc = await ctx.api.get("/llms/agent-icons.txt");
|
|
12046
|
-
printOutput(doc ?? "", { json: ctx.json });
|
|
12047
|
-
} catch (err) {
|
|
12048
|
-
handleCommandError(err);
|
|
12049
|
-
}
|
|
12050
|
-
})
|
|
12964
|
+
}),
|
|
12965
|
+
{ includeCompany: false }
|
|
12051
12966
|
);
|
|
12052
|
-
const skills = agent.command("skills").description("Agent skill selection operations");
|
|
12053
12967
|
addCommonClientOptions(
|
|
12054
|
-
|
|
12968
|
+
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").action(async (skillId, opts) => {
|
|
12055
12969
|
try {
|
|
12056
|
-
const ctx = resolveCommandContext(opts);
|
|
12057
|
-
const
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
}
|
|
12061
|
-
if (opts.markdown && opts.markdownFile) {
|
|
12062
|
-
throw new Error("Pass only one of --markdown or --markdown-file.");
|
|
12063
|
-
}
|
|
12064
|
-
const markdown = opts.markdownFile ? await fs14.readFile(path18.resolve(opts.markdownFile), "utf8") : opts.markdown;
|
|
12065
|
-
const payload = organizationSkillCreateSchema.parse({
|
|
12066
|
-
name: opts.name,
|
|
12067
|
-
slug: opts.slug?.trim() || null,
|
|
12068
|
-
description: opts.description?.trim() || null,
|
|
12069
|
-
markdown: markdown ?? null
|
|
12070
|
-
});
|
|
12071
|
-
const created = await ctx.api.post(
|
|
12072
|
-
`/api/agents/${encodeURIComponent(agentId)}/skills/private`,
|
|
12073
|
-
payload
|
|
12074
|
-
);
|
|
12075
|
-
if (!created) {
|
|
12076
|
-
throw new Error("Failed to create agent skill");
|
|
12077
|
-
}
|
|
12078
|
-
let enabledSnapshot = null;
|
|
12079
|
-
if (opts.enable) {
|
|
12080
|
-
enabledSnapshot = await ctx.api.post(
|
|
12081
|
-
`/api/agents/${encodeURIComponent(agentId)}/skills/enable`,
|
|
12082
|
-
{ skills: [created.selectionKey] }
|
|
12083
|
-
);
|
|
12084
|
-
}
|
|
12085
|
-
const result = { created, enabledSnapshot };
|
|
12086
|
-
if (ctx.json) {
|
|
12087
|
-
printOutput(result, { json: true });
|
|
12088
|
-
return;
|
|
12089
|
-
}
|
|
12090
|
-
console.log(
|
|
12091
|
-
formatInlineRecord({
|
|
12092
|
-
key: created.key,
|
|
12093
|
-
selectionKey: created.selectionKey,
|
|
12094
|
-
sourceClass: created.sourceClass,
|
|
12095
|
-
sourcePath: created.sourcePath,
|
|
12096
|
-
enabled: Boolean(enabledSnapshot?.desiredSkills.includes(created.selectionKey)),
|
|
12097
|
-
detail: opts.enable ? "Created and enabled. Future runs will load this skill." : "Created, not enabled. Future runs will not load it until enabled."
|
|
12098
|
-
})
|
|
12970
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12971
|
+
const query = new URLSearchParams({ path: opts.path ?? "SKILL.md" });
|
|
12972
|
+
const row = await ctx.api.get(
|
|
12973
|
+
`/api/orgs/${ctx.orgId}/skills/${skillId}/files?${query.toString()}`
|
|
12099
12974
|
);
|
|
12975
|
+
printOutput(row, { json: ctx.json });
|
|
12100
12976
|
} catch (err) {
|
|
12101
12977
|
handleCommandError(err);
|
|
12102
12978
|
}
|
|
12103
|
-
})
|
|
12979
|
+
}),
|
|
12980
|
+
{ includeCompany: false }
|
|
12104
12981
|
);
|
|
12105
12982
|
addCommonClientOptions(
|
|
12106
|
-
|
|
12983
|
+
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)").action(async (opts) => {
|
|
12107
12984
|
try {
|
|
12108
|
-
const ctx = resolveCommandContext(opts);
|
|
12109
|
-
const
|
|
12110
|
-
|
|
12111
|
-
});
|
|
12112
|
-
printOutput(snapshot, { json: ctx.json });
|
|
12985
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12986
|
+
const payload = organizationSkillImportSchema.parse({ source: opts.source });
|
|
12987
|
+
const result = await ctx.api.post(`/api/orgs/${ctx.orgId}/skills/import`, payload);
|
|
12988
|
+
printOutput(result, { json: ctx.json });
|
|
12113
12989
|
} catch (err) {
|
|
12114
12990
|
handleCommandError(err);
|
|
12115
12991
|
}
|
|
12116
|
-
})
|
|
12992
|
+
}),
|
|
12993
|
+
{ includeCompany: false }
|
|
12117
12994
|
);
|
|
12118
12995
|
addCommonClientOptions(
|
|
12119
|
-
|
|
12120
|
-
"--desired-skills <csv>",
|
|
12121
|
-
"Comma-separated desired skill refs (for example rudder/rudder)"
|
|
12122
|
-
).action(async (agentId, opts) => {
|
|
12996
|
+
skill.command("scan-local").description(getAgentCliCapabilityById("skill.scan-local").description).option("-O, --org-id <id>", "Organization ID").option("--roots <csv>", "Comma-separated local roots to scan").action(async (opts) => {
|
|
12123
12997
|
try {
|
|
12124
|
-
const ctx = resolveCommandContext(opts);
|
|
12125
|
-
const
|
|
12126
|
-
|
|
12998
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12999
|
+
const payload = organizationSkillLocalScanRequestSchema.parse({
|
|
13000
|
+
roots: parseCsv5(opts.roots)
|
|
12127
13001
|
});
|
|
12128
|
-
|
|
13002
|
+
const result = await ctx.api.post(
|
|
13003
|
+
`/api/orgs/${ctx.orgId}/skills/scan-local`,
|
|
13004
|
+
payload
|
|
13005
|
+
);
|
|
13006
|
+
printOutput(result, { json: ctx.json });
|
|
12129
13007
|
} catch (err) {
|
|
12130
13008
|
handleCommandError(err);
|
|
12131
13009
|
}
|
|
12132
|
-
})
|
|
13010
|
+
}),
|
|
13011
|
+
{ includeCompany: false }
|
|
12133
13012
|
);
|
|
12134
13013
|
addCommonClientOptions(
|
|
12135
|
-
|
|
13014
|
+
skill.command("scan-projects").description(getAgentCliCapabilityById("skill.scan-projects").description).option("-O, --org-id <id>", "Organization ID").option("--project-ids <csv>", "Comma-separated project IDs").option("--workspace-ids <csv>", "Comma-separated workspace IDs").action(async (opts) => {
|
|
12136
13015
|
try {
|
|
12137
|
-
const ctx = resolveCommandContext(opts);
|
|
12138
|
-
const
|
|
12139
|
-
|
|
12140
|
-
|
|
12141
|
-
|
|
13016
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
13017
|
+
const payload = organizationSkillProjectScanRequestSchema.parse({
|
|
13018
|
+
projectIds: parseCsv5(opts.projectIds),
|
|
13019
|
+
workspaceIds: parseCsv5(opts.workspaceIds)
|
|
13020
|
+
});
|
|
13021
|
+
const result = await ctx.api.post(
|
|
13022
|
+
`/api/orgs/${ctx.orgId}/skills/scan-projects`,
|
|
13023
|
+
payload
|
|
12142
13024
|
);
|
|
12143
|
-
printOutput(
|
|
13025
|
+
printOutput(result, { json: ctx.json });
|
|
12144
13026
|
} catch (err) {
|
|
12145
13027
|
handleCommandError(err);
|
|
12146
13028
|
}
|
|
12147
|
-
})
|
|
13029
|
+
}),
|
|
13030
|
+
{ includeCompany: false }
|
|
13031
|
+
);
|
|
13032
|
+
}
|
|
13033
|
+
function parseCsv5(value) {
|
|
13034
|
+
if (!value) return void 0;
|
|
13035
|
+
const rows = value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
13036
|
+
return rows.length > 0 ? rows : void 0;
|
|
13037
|
+
}
|
|
13038
|
+
|
|
13039
|
+
// src/commands/client/library.ts
|
|
13040
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
13041
|
+
import path20 from "node:path";
|
|
13042
|
+
function toLibraryFileLinkResult(detail) {
|
|
13043
|
+
return {
|
|
13044
|
+
filePath: detail.filePath,
|
|
13045
|
+
libraryEntryId: detail.libraryEntryId,
|
|
13046
|
+
mentionHref: detail.mentionHref,
|
|
13047
|
+
markdownLink: detail.markdownLink
|
|
13048
|
+
};
|
|
13049
|
+
}
|
|
13050
|
+
async function printLibraryFileReference(filePath, opts) {
|
|
13051
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
13052
|
+
const search = new URLSearchParams();
|
|
13053
|
+
search.set("path", filePath.trim());
|
|
13054
|
+
const result = await ctx.api.get(
|
|
13055
|
+
`/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`
|
|
12148
13056
|
);
|
|
13057
|
+
if (!result) throw new Error("Library file not found");
|
|
13058
|
+
printOutput(toLibraryFileLinkResult(result), { json: ctx.json });
|
|
13059
|
+
}
|
|
13060
|
+
function registerLibraryCommands(program) {
|
|
13061
|
+
const library = program.command("library").description("Library file operations");
|
|
13062
|
+
const file = library.command("file").description("Library file operations");
|
|
12149
13063
|
addCommonClientOptions(
|
|
12150
|
-
|
|
13064
|
+
file.command("list").description(getAgentCliCapabilityById("library.file.list").description).argument("[directoryPath]", "Library directory path", "projects").action(async (directoryPath, opts) => {
|
|
12151
13065
|
try {
|
|
12152
|
-
const ctx = resolveCommandContext(opts);
|
|
12153
|
-
const
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
const
|
|
12158
|
-
|
|
12159
|
-
throw new Error(
|
|
12160
|
-
"No agent fields to update. Pass --name, --role, --title, --capabilities, --description, or --reports-to."
|
|
12161
|
-
);
|
|
12162
|
-
}
|
|
12163
|
-
const query = new URLSearchParams();
|
|
12164
|
-
if (ctx.orgId) query.set("orgId", ctx.orgId);
|
|
12165
|
-
const updated = await ctx.api.patch(
|
|
12166
|
-
`/api/agents/${encodeURIComponent(agentId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
|
|
12167
|
-
patch
|
|
13066
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
13067
|
+
const search = new URLSearchParams();
|
|
13068
|
+
const normalizedPath = directoryPath.trim();
|
|
13069
|
+
if (normalizedPath) search.set("path", normalizedPath);
|
|
13070
|
+
const query = search.toString();
|
|
13071
|
+
const result = await ctx.api.get(
|
|
13072
|
+
`/api/orgs/${ctx.orgId}/workspace/files${query ? `?${query}` : ""}`
|
|
12168
13073
|
);
|
|
12169
|
-
printOutput(
|
|
13074
|
+
printOutput(result, { json: ctx.json });
|
|
12170
13075
|
} catch (err) {
|
|
12171
13076
|
handleCommandError(err);
|
|
12172
13077
|
}
|
|
12173
|
-
})
|
|
13078
|
+
}),
|
|
13079
|
+
{ includeCompany: true }
|
|
12174
13080
|
);
|
|
12175
13081
|
addCommonClientOptions(
|
|
12176
|
-
|
|
13082
|
+
file.command("get").description(getAgentCliCapabilityById("library.file.get").description).argument("<filePath>", "Library file path").action(async (filePath, opts) => {
|
|
12177
13083
|
try {
|
|
12178
13084
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12179
|
-
const
|
|
12180
|
-
|
|
12181
|
-
const
|
|
12182
|
-
|
|
13085
|
+
const search = new URLSearchParams();
|
|
13086
|
+
search.set("path", filePath.trim());
|
|
13087
|
+
const result = await ctx.api.get(
|
|
13088
|
+
`/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`
|
|
13089
|
+
);
|
|
13090
|
+
printOutput(result, { json: ctx.json });
|
|
12183
13091
|
} catch (err) {
|
|
12184
13092
|
handleCommandError(err);
|
|
12185
13093
|
}
|
|
12186
13094
|
}),
|
|
12187
|
-
{ includeCompany:
|
|
13095
|
+
{ includeCompany: true }
|
|
12188
13096
|
);
|
|
12189
13097
|
addCommonClientOptions(
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
13098
|
+
file.command("link").description(getAgentCliCapabilityById("library.file.link").description).argument("<filePath>", "Library file path").action(async (filePath, opts) => {
|
|
13099
|
+
try {
|
|
13100
|
+
await printLibraryFileReference(filePath, opts);
|
|
13101
|
+
} catch (err) {
|
|
13102
|
+
handleCommandError(err);
|
|
13103
|
+
}
|
|
13104
|
+
}),
|
|
13105
|
+
{ includeCompany: true }
|
|
13106
|
+
);
|
|
13107
|
+
addCommonClientOptions(
|
|
13108
|
+
file.command("ref").description(getAgentCliCapabilityById("library.file.ref").description).argument("<filePath>", "Library file path").action(async (filePath, opts) => {
|
|
13109
|
+
try {
|
|
13110
|
+
await printLibraryFileReference(filePath, opts);
|
|
13111
|
+
} catch (err) {
|
|
13112
|
+
handleCommandError(err);
|
|
13113
|
+
}
|
|
13114
|
+
}),
|
|
13115
|
+
{ includeCompany: true }
|
|
13116
|
+
);
|
|
13117
|
+
addCommonClientOptions(
|
|
13118
|
+
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").action(async (filePath, opts) => {
|
|
12196
13119
|
try {
|
|
12197
13120
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12198
|
-
const
|
|
12199
|
-
const
|
|
12200
|
-
|
|
13121
|
+
const body = await resolveBodyFileInput(opts.bodyFile);
|
|
13122
|
+
const search = new URLSearchParams();
|
|
13123
|
+
search.set("path", filePath.trim());
|
|
13124
|
+
const updatePath = `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`;
|
|
13125
|
+
const updated = await ctx.api.patch(
|
|
13126
|
+
updatePath,
|
|
13127
|
+
{ content: body },
|
|
13128
|
+
{ ignoreNotFound: true }
|
|
12201
13129
|
);
|
|
12202
|
-
if (
|
|
12203
|
-
|
|
12204
|
-
}
|
|
12205
|
-
const now = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
|
|
12206
|
-
const keyName = opts.keyName?.trim() ? opts.keyName.trim() : `local-cli-${now}`;
|
|
12207
|
-
const key = await ctx.api.post(`/api/agents/${agentRow.id}/keys`, { name: keyName });
|
|
12208
|
-
if (!key) {
|
|
12209
|
-
throw new Error("Failed to create API key");
|
|
12210
|
-
}
|
|
12211
|
-
const installSummaries = [];
|
|
12212
|
-
if (opts.installSkills !== false) {
|
|
12213
|
-
const skillsDir = await resolveRudderSkillsDir(__moduleDir, [path18.resolve(process.cwd(), "skills")]);
|
|
12214
|
-
if (!skillsDir) {
|
|
12215
|
-
throw new Error(
|
|
12216
|
-
"Could not locate local Rudder skills directory. Expected ./skills in the repo checkout."
|
|
12217
|
-
);
|
|
12218
|
-
}
|
|
12219
|
-
installSummaries.push(
|
|
12220
|
-
await installSkillsForTarget(skillsDir, codexSkillsHome(), "codex"),
|
|
12221
|
-
await installSkillsForTarget(skillsDir, claudeSkillsHome(), "claude")
|
|
12222
|
-
);
|
|
12223
|
-
}
|
|
12224
|
-
const exportsText = buildAgentEnvExports({
|
|
12225
|
-
apiBase: ctx.api.apiBase,
|
|
12226
|
-
orgId: agentRow.orgId,
|
|
12227
|
-
agentId: agentRow.id,
|
|
12228
|
-
apiKey: key.token
|
|
12229
|
-
});
|
|
12230
|
-
if (ctx.json) {
|
|
12231
|
-
printOutput(
|
|
12232
|
-
{
|
|
12233
|
-
agent: {
|
|
12234
|
-
id: agentRow.id,
|
|
12235
|
-
name: agentRow.name,
|
|
12236
|
-
urlKey: agentRow.urlKey,
|
|
12237
|
-
orgId: agentRow.orgId
|
|
12238
|
-
},
|
|
12239
|
-
key: {
|
|
12240
|
-
id: key.id,
|
|
12241
|
-
name: key.name,
|
|
12242
|
-
createdAt: key.createdAt,
|
|
12243
|
-
token: key.token
|
|
12244
|
-
},
|
|
12245
|
-
skills: installSummaries,
|
|
12246
|
-
exports: exportsText
|
|
12247
|
-
},
|
|
12248
|
-
{ json: true }
|
|
12249
|
-
);
|
|
13130
|
+
if (updated) {
|
|
13131
|
+
printOutput(updated, { json: ctx.json });
|
|
12250
13132
|
return;
|
|
12251
13133
|
}
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
`${summary.tool}: linked=${summary.linked.length} removed=${summary.removed.length} skipped=${summary.skipped.length} failed=${summary.failed.length} target=${summary.target}`
|
|
12258
|
-
);
|
|
12259
|
-
for (const failed of summary.failed) {
|
|
12260
|
-
console.log(` failed ${failed.name}: ${failed.error}`);
|
|
12261
|
-
}
|
|
12262
|
-
}
|
|
12263
|
-
}
|
|
12264
|
-
console.log("");
|
|
12265
|
-
console.log("# Run this in your shell before launching codex/claude:");
|
|
12266
|
-
console.log(exportsText);
|
|
13134
|
+
const created = await ctx.api.post(
|
|
13135
|
+
`/api/orgs/${ctx.orgId}/workspace/file`,
|
|
13136
|
+
{ filePath: filePath.trim(), content: body }
|
|
13137
|
+
);
|
|
13138
|
+
printOutput(created, { json: ctx.json });
|
|
12267
13139
|
} catch (err) {
|
|
12268
13140
|
handleCommandError(err);
|
|
12269
13141
|
}
|
|
12270
13142
|
}),
|
|
12271
|
-
{ includeCompany:
|
|
12272
|
-
);
|
|
12273
|
-
}
|
|
12274
|
-
async function
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
if (opts.role !== void 0) rawPatch.role = opts.role;
|
|
12278
|
-
if (opts.title !== void 0 && opts.clearTitle) {
|
|
12279
|
-
throw new Error("Pass only one of --title or --clear-title.");
|
|
12280
|
-
}
|
|
12281
|
-
if (opts.title !== void 0) rawPatch.title = opts.title;
|
|
12282
|
-
if (opts.clearTitle) rawPatch.title = null;
|
|
12283
|
-
if (opts.reportsTo !== void 0 && opts.clearReportsTo) {
|
|
12284
|
-
throw new Error("Pass only one of --reports-to or --clear-reports-to.");
|
|
12285
|
-
}
|
|
12286
|
-
if (opts.reportsTo !== void 0) rawPatch.reportsTo = opts.reportsTo;
|
|
12287
|
-
if (opts.clearReportsTo) rawPatch.reportsTo = null;
|
|
12288
|
-
const capabilitiesInputs = [
|
|
12289
|
-
opts.capabilities !== void 0 ? "--capabilities" : null,
|
|
12290
|
-
opts.capabilitiesFile !== void 0 ? "--capabilities-file" : null,
|
|
12291
|
-
opts.description !== void 0 ? "--description" : null,
|
|
12292
|
-
opts.descriptionFile !== void 0 ? "--description-file" : null
|
|
12293
|
-
].filter(Boolean);
|
|
12294
|
-
const clearCapabilities = opts.clearCapabilities || opts.clearDescription;
|
|
12295
|
-
if (capabilitiesInputs.length > 1) {
|
|
12296
|
-
throw new Error(
|
|
12297
|
-
"Pass only one of --capabilities, --capabilities-file, --description, or --description-file."
|
|
12298
|
-
);
|
|
12299
|
-
}
|
|
12300
|
-
if (capabilitiesInputs.length > 0 && clearCapabilities) {
|
|
12301
|
-
throw new Error("Pass either capabilities/description input or a clear flag, not both.");
|
|
13143
|
+
{ includeCompany: true }
|
|
13144
|
+
);
|
|
13145
|
+
}
|
|
13146
|
+
async function resolveBodyFileInput(inputPath) {
|
|
13147
|
+
if (process.argv.includes("--body")) {
|
|
13148
|
+
throw new Error("--body was removed; write the body to a file and use --body-file <path> or --body-file - for stdin");
|
|
12302
13149
|
}
|
|
12303
|
-
if (
|
|
12304
|
-
|
|
12305
|
-
if (opts.capabilitiesFile !== void 0) {
|
|
12306
|
-
rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.capabilitiesFile), "utf8");
|
|
13150
|
+
if (inputPath === void 0) {
|
|
13151
|
+
throw new Error("Provide --body-file <path>; use --body-file - for stdin");
|
|
12307
13152
|
}
|
|
12308
|
-
if (
|
|
12309
|
-
|
|
13153
|
+
if (inputPath === "-") {
|
|
13154
|
+
return readStdinText3();
|
|
12310
13155
|
}
|
|
12311
|
-
|
|
12312
|
-
return
|
|
12313
|
-
}
|
|
12314
|
-
|
|
12315
|
-
if (!value) return [];
|
|
12316
|
-
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
13156
|
+
const resolvedPath = path20.resolve(process.cwd(), inputPath);
|
|
13157
|
+
return readFile6(resolvedPath, "utf8").catch((err) => {
|
|
13158
|
+
throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
13159
|
+
});
|
|
12317
13160
|
}
|
|
12318
|
-
function
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
throw new Error(`${name} must be a JSON object`);
|
|
12323
|
-
}
|
|
12324
|
-
return parsed;
|
|
12325
|
-
} catch (err) {
|
|
12326
|
-
throw new Error(`Invalid ${name} JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
13161
|
+
async function readStdinText3() {
|
|
13162
|
+
const chunks = [];
|
|
13163
|
+
for await (const chunk of process.stdin) {
|
|
13164
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
12327
13165
|
}
|
|
13166
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
12328
13167
|
}
|
|
12329
13168
|
|
|
12330
|
-
// src/commands/client/
|
|
13169
|
+
// src/commands/client/automation.ts
|
|
12331
13170
|
init_dist();
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
function registerApprovalCommands(program) {
|
|
12335
|
-
const approval = program.command("approval").description("Approval operations");
|
|
13171
|
+
function registerAutomationCommands(program) {
|
|
13172
|
+
const automation = program.command("automation").description("Automation operations");
|
|
12336
13173
|
addCommonClientOptions(
|
|
12337
|
-
|
|
13174
|
+
automation.command("list").description(getAgentCliCapabilityById("automation.list").description).option("-O, --org-id <id>", "Organization ID").option("--status <status>", "Filter by automation status").option("--assignee-agent-id <id>", "Filter by assignee agent ID").option("--project-id <id>", "Filter by project ID").option("--output-mode <mode>", "Filter by output mode").action(async (opts) => {
|
|
12338
13175
|
try {
|
|
12339
13176
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12340
|
-
const
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
printOutput(rows, { json: true });
|
|
12346
|
-
return;
|
|
12347
|
-
}
|
|
12348
|
-
if (rows.length === 0) {
|
|
12349
|
-
printOutput([], { json: false });
|
|
12350
|
-
return;
|
|
12351
|
-
}
|
|
12352
|
-
for (const row of rows) {
|
|
12353
|
-
console.log(
|
|
12354
|
-
formatInlineRecord({
|
|
12355
|
-
id: row.id,
|
|
12356
|
-
type: row.type,
|
|
12357
|
-
status: row.status,
|
|
12358
|
-
requestedByAgentId: row.requestedByAgentId,
|
|
12359
|
-
requestedByUserId: row.requestedByUserId
|
|
12360
|
-
})
|
|
12361
|
-
);
|
|
12362
|
-
}
|
|
13177
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/automations`) ?? [];
|
|
13178
|
+
const filtered = rows.filter(
|
|
13179
|
+
(row) => (!opts.status || row.status === opts.status) && (!opts.assigneeAgentId || row.assigneeAgentId === opts.assigneeAgentId) && (!opts.projectId || row.projectId === opts.projectId) && (!opts.outputMode || row.outputMode === opts.outputMode)
|
|
13180
|
+
);
|
|
13181
|
+
printOutput(ctx.json ? filtered : filtered.map(formatAutomationListItem), { json: ctx.json });
|
|
12363
13182
|
} catch (err) {
|
|
12364
13183
|
handleCommandError(err);
|
|
12365
13184
|
}
|
|
@@ -12367,10 +13186,10 @@ function registerApprovalCommands(program) {
|
|
|
12367
13186
|
{ includeCompany: false }
|
|
12368
13187
|
);
|
|
12369
13188
|
addCommonClientOptions(
|
|
12370
|
-
|
|
13189
|
+
automation.command("get").description(getAgentCliCapabilityById("automation.get").description).argument("<automationId>", "Automation ID").action(async (automationId, opts) => {
|
|
12371
13190
|
try {
|
|
12372
13191
|
const ctx = resolveCommandContext(opts);
|
|
12373
|
-
const row = await ctx.api.get(`/api/
|
|
13192
|
+
const row = await ctx.api.get(`/api/automations/${encodeURIComponent(automationId)}`);
|
|
12374
13193
|
printOutput(row, { json: ctx.json });
|
|
12375
13194
|
} catch (err) {
|
|
12376
13195
|
handleCommandError(err);
|
|
@@ -12378,59 +13197,51 @@ function registerApprovalCommands(program) {
|
|
|
12378
13197
|
})
|
|
12379
13198
|
);
|
|
12380
13199
|
addCommonClientOptions(
|
|
12381
|
-
|
|
13200
|
+
automation.command("runs").description(getAgentCliCapabilityById("automation.runs").description).argument("<automationId>", "Automation ID").option("--limit <n>", "Maximum runs to return", "50").action(async (automationId, opts) => {
|
|
12382
13201
|
try {
|
|
12383
13202
|
const ctx = resolveCommandContext(opts);
|
|
12384
|
-
const
|
|
12385
|
-
|
|
13203
|
+
const params = new URLSearchParams();
|
|
13204
|
+
if (opts.limit) params.set("limit", opts.limit);
|
|
13205
|
+
const rows = await ctx.api.get(
|
|
13206
|
+
`/api/automations/${encodeURIComponent(automationId)}/runs?${params.toString()}`
|
|
13207
|
+
) ?? [];
|
|
13208
|
+
printOutput(ctx.json ? rows : rows.map(formatAutomationRun), { json: ctx.json });
|
|
12386
13209
|
} catch (err) {
|
|
12387
13210
|
handleCommandError(err);
|
|
12388
13211
|
}
|
|
12389
13212
|
})
|
|
12390
13213
|
);
|
|
12391
13214
|
addCommonClientOptions(
|
|
12392
|
-
|
|
13215
|
+
automation.command("triggers").description("Automation trigger operations").command("list").description(getAgentCliCapabilityById("automation.triggers.list").description).argument("<automationId>", "Automation ID").action(async (automationId, opts) => {
|
|
12393
13216
|
try {
|
|
12394
|
-
const ctx = resolveCommandContext(opts
|
|
12395
|
-
const
|
|
12396
|
-
const
|
|
12397
|
-
|
|
12398
|
-
payload: payloadJson,
|
|
12399
|
-
requestedByAgentId: opts.requestedByAgentId,
|
|
12400
|
-
issueIds: parseCsv4(opts.issueIds)
|
|
12401
|
-
});
|
|
12402
|
-
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/approvals`, payload);
|
|
12403
|
-
printOutput(created, { json: ctx.json });
|
|
13217
|
+
const ctx = resolveCommandContext(opts);
|
|
13218
|
+
const row = await ctx.api.get(`/api/automations/${encodeURIComponent(automationId)}`);
|
|
13219
|
+
const triggers = row?.triggers ?? [];
|
|
13220
|
+
printOutput(triggers, { json: ctx.json });
|
|
12404
13221
|
} catch (err) {
|
|
12405
13222
|
handleCommandError(err);
|
|
12406
13223
|
}
|
|
12407
|
-
})
|
|
12408
|
-
{ includeCompany: false }
|
|
13224
|
+
})
|
|
12409
13225
|
);
|
|
12410
13226
|
addCommonClientOptions(
|
|
12411
|
-
|
|
13227
|
+
automation.command("create").description(getAgentCliCapabilityById("automation.create").description).option("-O, --org-id <id>", "Organization ID").option("--payload <json>", "Raw automation create payload JSON").option("--title <title>", "Automation title").option("--instructions <text>", "Automation run instructions").option("--description <text>", "Deprecated alias for --instructions").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-issue-id <id>", "Parent issue ID").option("--priority <priority>", "Issue priority for tracked output").option("--status <status>", "Automation status").option("--output-mode <mode>", "Automation output mode").option("--concurrency-policy <policy>", "Automation concurrency policy").option("--catch-up-policy <policy>", "Automation catch-up policy").option("--notify-on-issue-created", "Notify when tracked issue output is created").action(async (opts) => {
|
|
12412
13228
|
try {
|
|
12413
|
-
const ctx = resolveCommandContext(opts);
|
|
12414
|
-
const payload =
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
});
|
|
12418
|
-
const updated = await ctx.api.post(`/api/approvals/${approvalId}/approve`, payload);
|
|
12419
|
-
printOutput(updated, { json: ctx.json });
|
|
13229
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
13230
|
+
const payload = createAutomationSchema.parse(buildAutomationPayload(opts));
|
|
13231
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/automations`, payload);
|
|
13232
|
+
printOutput(created, { json: ctx.json });
|
|
12420
13233
|
} catch (err) {
|
|
12421
13234
|
handleCommandError(err);
|
|
12422
13235
|
}
|
|
12423
|
-
})
|
|
13236
|
+
}),
|
|
13237
|
+
{ includeCompany: false }
|
|
12424
13238
|
);
|
|
12425
13239
|
addCommonClientOptions(
|
|
12426
|
-
|
|
13240
|
+
automation.command("update").description(getAgentCliCapabilityById("automation.update").description).argument("<automationId>", "Automation ID").option("--payload <json>", "Raw automation update payload JSON").option("--title <title>", "Automation title").option("--instructions <text>", "Automation run instructions").option("--description <text>", "Deprecated alias for --instructions").option("--assignee-agent-id <id>", "Assignee agent ID").option("--project-id <id>", "Project ID").option("--goal-id <id>", "Goal ID").option("--parent-issue-id <id>", "Parent issue ID").option("--priority <priority>", "Issue priority for tracked output").option("--status <status>", "Automation status").option("--output-mode <mode>", "Automation output mode").option("--concurrency-policy <policy>", "Automation concurrency policy").option("--catch-up-policy <policy>", "Automation catch-up policy").option("--notify-on-issue-created", "Notify when tracked issue output is created").action(async (automationId, opts) => {
|
|
12427
13241
|
try {
|
|
12428
13242
|
const ctx = resolveCommandContext(opts);
|
|
12429
|
-
const payload =
|
|
12430
|
-
|
|
12431
|
-
decidedByUserId: opts.decidedByUserId
|
|
12432
|
-
});
|
|
12433
|
-
const updated = await ctx.api.post(`/api/approvals/${approvalId}/reject`, payload);
|
|
13243
|
+
const payload = updateAutomationSchema.parse(buildAutomationPayload(opts));
|
|
13244
|
+
const updated = await ctx.api.patch(`/api/automations/${encodeURIComponent(automationId)}`, payload);
|
|
12434
13245
|
printOutput(updated, { json: ctx.json });
|
|
12435
13246
|
} catch (err) {
|
|
12436
13247
|
handleCommandError(err);
|
|
@@ -12438,14 +13249,12 @@ function registerApprovalCommands(program) {
|
|
|
12438
13249
|
})
|
|
12439
13250
|
);
|
|
12440
13251
|
addCommonClientOptions(
|
|
12441
|
-
|
|
13252
|
+
automation.command("enable").description(getAgentCliCapabilityById("automation.enable").description).argument("<automationId>", "Automation ID").action(async (automationId, opts) => {
|
|
12442
13253
|
try {
|
|
12443
13254
|
const ctx = resolveCommandContext(opts);
|
|
12444
|
-
const
|
|
12445
|
-
|
|
12446
|
-
decidedByUserId: opts.decidedByUserId
|
|
13255
|
+
const updated = await ctx.api.patch(`/api/automations/${encodeURIComponent(automationId)}`, {
|
|
13256
|
+
status: "active"
|
|
12447
13257
|
});
|
|
12448
|
-
const updated = await ctx.api.post(`/api/approvals/${approvalId}/request-revision`, payload);
|
|
12449
13258
|
printOutput(updated, { json: ctx.json });
|
|
12450
13259
|
} catch (err) {
|
|
12451
13260
|
handleCommandError(err);
|
|
@@ -12453,13 +13262,12 @@ function registerApprovalCommands(program) {
|
|
|
12453
13262
|
})
|
|
12454
13263
|
);
|
|
12455
13264
|
addCommonClientOptions(
|
|
12456
|
-
|
|
13265
|
+
automation.command("disable").description(getAgentCliCapabilityById("automation.disable").description).argument("<automationId>", "Automation ID").action(async (automationId, opts) => {
|
|
12457
13266
|
try {
|
|
12458
13267
|
const ctx = resolveCommandContext(opts);
|
|
12459
|
-
const
|
|
12460
|
-
|
|
13268
|
+
const updated = await ctx.api.patch(`/api/automations/${encodeURIComponent(automationId)}`, {
|
|
13269
|
+
status: "paused"
|
|
12461
13270
|
});
|
|
12462
|
-
const updated = await ctx.api.post(`/api/approvals/${approvalId}/resubmit`, payload);
|
|
12463
13271
|
printOutput(updated, { json: ctx.json });
|
|
12464
13272
|
} catch (err) {
|
|
12465
13273
|
handleCommandError(err);
|
|
@@ -12467,161 +13275,374 @@ function registerApprovalCommands(program) {
|
|
|
12467
13275
|
})
|
|
12468
13276
|
);
|
|
12469
13277
|
addCommonClientOptions(
|
|
12470
|
-
|
|
13278
|
+
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").action(async (automationId, opts) => {
|
|
12471
13279
|
try {
|
|
12472
13280
|
const ctx = resolveCommandContext(opts);
|
|
12473
|
-
const
|
|
12474
|
-
|
|
12475
|
-
|
|
13281
|
+
const payload = runAutomationSchema.parse({
|
|
13282
|
+
triggerId: opts.triggerId,
|
|
13283
|
+
payload: opts.payload ? parseJsonOption(opts.payload, "--payload") : void 0,
|
|
13284
|
+
idempotencyKey: opts.idempotencyKey,
|
|
13285
|
+
source: opts.source
|
|
12476
13286
|
});
|
|
12477
|
-
|
|
13287
|
+
const run = await ctx.api.post(`/api/automations/${encodeURIComponent(automationId)}/run`, payload);
|
|
13288
|
+
printOutput(run, { json: ctx.json });
|
|
12478
13289
|
} catch (err) {
|
|
12479
13290
|
handleCommandError(err);
|
|
12480
13291
|
}
|
|
12481
13292
|
})
|
|
12482
13293
|
);
|
|
12483
13294
|
}
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
13295
|
+
function buildAutomationPayload(opts) {
|
|
13296
|
+
return {
|
|
13297
|
+
...parseJsonObjectOption(opts.payload, "--payload"),
|
|
13298
|
+
...definedRecord({
|
|
13299
|
+
title: opts.title,
|
|
13300
|
+
instructions: opts.instructions ?? opts.description,
|
|
13301
|
+
assigneeAgentId: opts.assigneeAgentId,
|
|
13302
|
+
projectId: opts.projectId,
|
|
13303
|
+
goalId: opts.goalId,
|
|
13304
|
+
parentIssueId: opts.parentIssueId,
|
|
13305
|
+
priority: opts.priority,
|
|
13306
|
+
status: opts.status,
|
|
13307
|
+
outputMode: opts.outputMode,
|
|
13308
|
+
concurrencyPolicy: opts.concurrencyPolicy,
|
|
13309
|
+
catchUpPolicy: opts.catchUpPolicy,
|
|
13310
|
+
notifyOnIssueCreated: opts.notifyOnIssueCreated
|
|
13311
|
+
})
|
|
13312
|
+
};
|
|
12489
13313
|
}
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
13314
|
+
function definedRecord(record) {
|
|
13315
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== void 0));
|
|
13316
|
+
}
|
|
13317
|
+
function parseJsonOption(value, label) {
|
|
13318
|
+
try {
|
|
13319
|
+
return JSON.parse(value);
|
|
13320
|
+
} catch (error) {
|
|
13321
|
+
throw new Error(`${label} must be valid JSON`);
|
|
12493
13322
|
}
|
|
12494
|
-
const resolvedPath = path19.resolve(process.cwd(), inputPath);
|
|
12495
|
-
return readFile5(resolvedPath, "utf8").catch((err) => {
|
|
12496
|
-
throw new Error(`Unable to read ${optionName} ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
12497
|
-
});
|
|
12498
13323
|
}
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
13324
|
+
function parseJsonObjectOption(value, label) {
|
|
13325
|
+
if (!value) return {};
|
|
13326
|
+
const parsed = parseJsonOption(value, label);
|
|
13327
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
13328
|
+
throw new Error(`${label} must be a JSON object`);
|
|
12503
13329
|
}
|
|
12504
|
-
return
|
|
13330
|
+
return parsed;
|
|
12505
13331
|
}
|
|
12506
|
-
function
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
13332
|
+
function formatAutomationListItem(row) {
|
|
13333
|
+
const nextRunAt = row.triggers.map((trigger) => trigger.nextRunAt).filter(Boolean).sort()[0] ?? null;
|
|
13334
|
+
return {
|
|
13335
|
+
id: row.id,
|
|
13336
|
+
title: row.title,
|
|
13337
|
+
status: row.status,
|
|
13338
|
+
assigneeAgentId: row.assigneeAgentId,
|
|
13339
|
+
outputMode: row.outputMode,
|
|
13340
|
+
lastRun: row.lastRun?.status ?? "-",
|
|
13341
|
+
nextRunAt
|
|
13342
|
+
};
|
|
12510
13343
|
}
|
|
12511
|
-
function
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
}
|
|
13344
|
+
function formatAutomationRun(row) {
|
|
13345
|
+
return {
|
|
13346
|
+
id: row.id,
|
|
13347
|
+
status: row.status,
|
|
13348
|
+
source: row.source,
|
|
13349
|
+
triggeredAt: row.triggeredAt,
|
|
13350
|
+
linkedIssue: row.linkedIssue?.identifier ?? row.linkedIssueId ?? "-",
|
|
13351
|
+
linkedChatConversationId: row.linkedChatConversationId ?? "-",
|
|
13352
|
+
failureReason: row.failureReason ?? "-"
|
|
13353
|
+
};
|
|
12521
13354
|
}
|
|
12522
13355
|
|
|
12523
|
-
// src/commands/client/
|
|
12524
|
-
|
|
12525
|
-
|
|
13356
|
+
// src/commands/client/chat.ts
|
|
13357
|
+
init_dist();
|
|
13358
|
+
function registerChatCommands(program) {
|
|
13359
|
+
const chat = program.command("chat").description("Chat operations");
|
|
12526
13360
|
addCommonClientOptions(
|
|
12527
|
-
|
|
13361
|
+
chat.command("list").description(getAgentCliCapabilityById("chat.list").description).option("-O, --org-id <id>", "Organization ID").option("--status <status>", "active, resolved, archived, or all", "active").option("--query <text>", "Server-side chat search query").option("--limit <n>", "Maximum rows to print").action(async (opts) => {
|
|
12528
13362
|
try {
|
|
12529
13363
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12530
|
-
const
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12557
|
-
|
|
13364
|
+
const rows = await listChats(ctx, opts);
|
|
13365
|
+
printOutput(ctx.json ? rows : rows.map(formatChatConversation), { json: ctx.json });
|
|
13366
|
+
} catch (err) {
|
|
13367
|
+
handleCommandError(err);
|
|
13368
|
+
}
|
|
13369
|
+
}),
|
|
13370
|
+
{ includeCompany: false }
|
|
13371
|
+
);
|
|
13372
|
+
addCommonClientOptions(
|
|
13373
|
+
chat.command("search").description(getAgentCliCapabilityById("chat.search").description).argument("<query>", "Search query").option("-O, --org-id <id>", "Organization ID").option("--status <status>", "active, resolved, archived, or all", "all").option("--scope <scope>", "Search scope: all, title, summary, messages", "all").option("--limit <n>", "Maximum rows to print", "20").option("--snippet-chars <n>", "Maximum snippet characters", "220").action(async (query, opts) => {
|
|
13374
|
+
try {
|
|
13375
|
+
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
13376
|
+
const rows = await listChats(ctx, { ...opts, query });
|
|
13377
|
+
const filtered = filterChatSearchRows(rows, query, opts.scope ?? "all").slice(0, parseLimit(opts.limit, rows.length));
|
|
13378
|
+
const snippetChars = parseLimit(opts.snippetChars, 220);
|
|
13379
|
+
printOutput(
|
|
13380
|
+
ctx.json ? filtered : filtered.map((row) => formatChatSearchResult(row, snippetChars)),
|
|
13381
|
+
{ json: ctx.json }
|
|
13382
|
+
);
|
|
13383
|
+
} catch (err) {
|
|
13384
|
+
handleCommandError(err);
|
|
13385
|
+
}
|
|
13386
|
+
}),
|
|
13387
|
+
{ includeCompany: false }
|
|
13388
|
+
);
|
|
13389
|
+
addCommonClientOptions(
|
|
13390
|
+
chat.command("get").description(getAgentCliCapabilityById("chat.get").description).argument("<chatId>", "Chat conversation ID").action(async (chatId, opts) => {
|
|
13391
|
+
try {
|
|
13392
|
+
const ctx = resolveCommandContext(opts);
|
|
13393
|
+
const row = await ctx.api.get(`/api/chats/${encodeURIComponent(chatId)}`);
|
|
13394
|
+
printOutput(row, { json: ctx.json });
|
|
13395
|
+
} catch (err) {
|
|
13396
|
+
handleCommandError(err);
|
|
13397
|
+
}
|
|
13398
|
+
})
|
|
13399
|
+
);
|
|
13400
|
+
addCommonClientOptions(
|
|
13401
|
+
chat.command("messages").description(getAgentCliCapabilityById("chat.messages").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 messages to print").option("--cursor <cursor>", "Stable message cursor returned in page.nextCursor").option("--max-output-chars <n>", "Maximum transcript output chars for human output", "1200").action(async (chatId, opts) => {
|
|
13402
|
+
try {
|
|
13403
|
+
const ctx = resolveCommandContext(opts);
|
|
13404
|
+
const page = await getChatMessagesPage(ctx, chatId, {
|
|
13405
|
+
includeTranscript: includesChatTranscript(opts),
|
|
13406
|
+
limit: opts.limit,
|
|
13407
|
+
cursor: opts.cursor
|
|
13408
|
+
});
|
|
13409
|
+
printOutput(
|
|
13410
|
+
ctx.json ? page : page.messages.map((message) => formatChatMessage(message, parseLimit(opts.maxOutputChars, 1200))),
|
|
13411
|
+
{ json: ctx.json }
|
|
13412
|
+
);
|
|
13413
|
+
} catch (err) {
|
|
13414
|
+
handleCommandError(err);
|
|
13415
|
+
}
|
|
13416
|
+
})
|
|
13417
|
+
);
|
|
13418
|
+
addCommonClientOptions(
|
|
13419
|
+
chat.command("transcript").description(getAgentCliCapabilityById("chat.transcript").description).argument("<chatId>", "Chat conversation ID").option("--limit <n>", "Maximum messages to print").option("--cursor <cursor>", "Stable message cursor returned in page.nextCursor").option("--max-chars <n>", "Maximum transcript chars per message", "1200").option("--max-output-chars <n>", "Alias for --max-chars").action(async (chatId, opts) => {
|
|
13420
|
+
try {
|
|
13421
|
+
const ctx = resolveCommandContext(opts);
|
|
13422
|
+
const page = await getChatMessagesPage(ctx, chatId, {
|
|
13423
|
+
includeTranscript: true,
|
|
13424
|
+
limit: opts.limit,
|
|
13425
|
+
cursor: opts.cursor
|
|
13426
|
+
});
|
|
13427
|
+
const maxChars = parseLimit(opts.maxOutputChars ?? opts.maxChars, 1200);
|
|
13428
|
+
printOutput(
|
|
13429
|
+
ctx.json ? page : page.messages.flatMap((message) => formatChatTranscriptMessage(message, maxChars)),
|
|
13430
|
+
{ json: ctx.json }
|
|
13431
|
+
);
|
|
13432
|
+
} catch (err) {
|
|
13433
|
+
handleCommandError(err);
|
|
13434
|
+
}
|
|
13435
|
+
})
|
|
13436
|
+
);
|
|
13437
|
+
addCommonClientOptions(
|
|
13438
|
+
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").action(async (chatId, opts) => {
|
|
13439
|
+
try {
|
|
13440
|
+
const ctx = resolveCommandContext(opts);
|
|
13441
|
+
const [conversation, page] = await Promise.all([
|
|
13442
|
+
ctx.api.get(`/api/chats/${encodeURIComponent(chatId)}`),
|
|
13443
|
+
getChatMessagesPage(ctx, chatId, {
|
|
13444
|
+
includeTranscript: includesChatTranscript(opts),
|
|
13445
|
+
limit: opts.turnLimit ?? opts.limit,
|
|
13446
|
+
cursor: opts.cursor
|
|
13447
|
+
})
|
|
13448
|
+
]);
|
|
13449
|
+
const payload = {
|
|
13450
|
+
conversation,
|
|
13451
|
+
messages: page.messages,
|
|
13452
|
+
page: page.page
|
|
13453
|
+
};
|
|
13454
|
+
printOutput(
|
|
13455
|
+
ctx.json ? payload : page.messages.map((message) => formatChatMessage(message, parseLimit(opts.maxOutputChars, 1200))),
|
|
13456
|
+
{ json: ctx.json }
|
|
13457
|
+
);
|
|
12558
13458
|
} catch (err) {
|
|
12559
13459
|
handleCommandError(err);
|
|
12560
13460
|
}
|
|
12561
|
-
})
|
|
12562
|
-
{ includeCompany: false }
|
|
13461
|
+
})
|
|
12563
13462
|
);
|
|
12564
|
-
}
|
|
12565
|
-
|
|
12566
|
-
// src/commands/client/dashboard.ts
|
|
12567
|
-
function registerDashboardCommands(program) {
|
|
12568
|
-
const dashboard = program.command("dashboard").description("Dashboard summary operations");
|
|
12569
13463
|
addCommonClientOptions(
|
|
12570
|
-
|
|
13464
|
+
chat.command("create").description(getAgentCliCapabilityById("chat.create").description).option("-O, --org-id <id>", "Organization ID").option("--payload <json>", "Raw chat create payload JSON").option("--title <title>", "Chat title").option("--summary <text>", "Chat summary").option("--preferred-agent-id <id>", "Preferred agent ID").option("--issue-creation-mode <mode>", "Issue creation mode").option("--plan-mode", "Create a plan-mode chat").action(async (opts) => {
|
|
12571
13465
|
try {
|
|
12572
13466
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12573
|
-
const
|
|
12574
|
-
|
|
13467
|
+
const payload = createChatConversationSchema.parse({
|
|
13468
|
+
...parseJsonObjectOption2(opts.payload, "--payload"),
|
|
13469
|
+
...definedRecord2({
|
|
13470
|
+
title: opts.title,
|
|
13471
|
+
summary: opts.summary,
|
|
13472
|
+
preferredAgentId: opts.preferredAgentId,
|
|
13473
|
+
issueCreationMode: opts.issueCreationMode,
|
|
13474
|
+
planMode: opts.planMode
|
|
13475
|
+
})
|
|
13476
|
+
});
|
|
13477
|
+
const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/chats`, payload);
|
|
13478
|
+
printOutput(created, { json: ctx.json });
|
|
12575
13479
|
} catch (err) {
|
|
12576
13480
|
handleCommandError(err);
|
|
12577
13481
|
}
|
|
12578
13482
|
}),
|
|
12579
13483
|
{ includeCompany: false }
|
|
12580
13484
|
);
|
|
12581
|
-
}
|
|
12582
|
-
|
|
12583
|
-
// src/commands/client/skill.ts
|
|
12584
|
-
init_dist();
|
|
12585
|
-
function registerSkillCommands(program) {
|
|
12586
|
-
const skill = program.command("skill").description("Organization skill library operations");
|
|
12587
13485
|
addCommonClientOptions(
|
|
12588
|
-
|
|
13486
|
+
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").action(async (chatId, opts) => {
|
|
12589
13487
|
try {
|
|
12590
|
-
const ctx = resolveCommandContext(opts
|
|
12591
|
-
const
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
}
|
|
12596
|
-
|
|
12597
|
-
|
|
12598
|
-
return;
|
|
12599
|
-
}
|
|
12600
|
-
for (const row of rows) {
|
|
12601
|
-
console.log(
|
|
12602
|
-
formatInlineRecord({
|
|
12603
|
-
id: row.id,
|
|
12604
|
-
key: row.key,
|
|
12605
|
-
slug: row.slug,
|
|
12606
|
-
name: row.name,
|
|
12607
|
-
sourceBadge: row.sourceBadge,
|
|
12608
|
-
compatibility: row.compatibility,
|
|
12609
|
-
attachedAgentCount: row.attachedAgentCount
|
|
12610
|
-
})
|
|
12611
|
-
);
|
|
12612
|
-
}
|
|
13488
|
+
const ctx = resolveCommandContext(opts);
|
|
13489
|
+
const body = opts.body ?? await readStdin();
|
|
13490
|
+
const payload = addChatMessageSchema.parse({
|
|
13491
|
+
body,
|
|
13492
|
+
editUserMessageId: opts.editUserMessageId
|
|
13493
|
+
});
|
|
13494
|
+
const result = await ctx.api.post(`/api/chats/${encodeURIComponent(chatId)}/messages`, payload);
|
|
13495
|
+
printOutput(result, { json: ctx.json });
|
|
12613
13496
|
} catch (err) {
|
|
12614
13497
|
handleCommandError(err);
|
|
12615
13498
|
}
|
|
12616
|
-
})
|
|
12617
|
-
{ includeCompany: false }
|
|
13499
|
+
})
|
|
12618
13500
|
);
|
|
12619
13501
|
addCommonClientOptions(
|
|
12620
|
-
|
|
13502
|
+
chat.command("archive").description(getAgentCliCapabilityById("chat.archive").description).argument("<chatId>", "Chat conversation ID").action(async (chatId, opts) => {
|
|
13503
|
+
try {
|
|
13504
|
+
const ctx = resolveCommandContext(opts);
|
|
13505
|
+
const payload = updateChatConversationSchema.parse({ status: "archived" });
|
|
13506
|
+
const updated = await ctx.api.patch(`/api/chats/${encodeURIComponent(chatId)}`, payload);
|
|
13507
|
+
printOutput(updated, { json: ctx.json });
|
|
13508
|
+
} catch (err) {
|
|
13509
|
+
handleCommandError(err);
|
|
13510
|
+
}
|
|
13511
|
+
})
|
|
13512
|
+
);
|
|
13513
|
+
}
|
|
13514
|
+
async function listChats(ctx, opts) {
|
|
13515
|
+
const params = new URLSearchParams();
|
|
13516
|
+
if (opts.status) params.set("status", opts.status);
|
|
13517
|
+
if (opts.query) params.set("q", opts.query);
|
|
13518
|
+
const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/chats?${params.toString()}`) ?? [];
|
|
13519
|
+
return rows.slice(0, parseLimit(opts.limit, rows.length));
|
|
13520
|
+
}
|
|
13521
|
+
async function getChatMessagesPage(ctx, chatId, opts) {
|
|
13522
|
+
const params = new URLSearchParams();
|
|
13523
|
+
params.set("envelope", "true");
|
|
13524
|
+
params.set("order", "newest");
|
|
13525
|
+
params.set("limit", String(parseLimit(opts.limit, 50)));
|
|
13526
|
+
if (opts.cursor) params.set("cursor", opts.cursor);
|
|
13527
|
+
if (opts.includeTranscript) params.set("includeTranscript", "true");
|
|
13528
|
+
const page = await ctx.api.get(`/api/chats/${encodeURIComponent(chatId)}/messages?${params.toString()}`);
|
|
13529
|
+
if (!page) {
|
|
13530
|
+
throw new Error("Chat messages response was empty");
|
|
13531
|
+
}
|
|
13532
|
+
return page;
|
|
13533
|
+
}
|
|
13534
|
+
function filterChatSearchRows(rows, query, scope) {
|
|
13535
|
+
const normalized = query.toLowerCase();
|
|
13536
|
+
if (scope === "all") return rows;
|
|
13537
|
+
return rows.filter((row) => {
|
|
13538
|
+
if (scope === "title") return row.title.toLowerCase().includes(normalized);
|
|
13539
|
+
if (scope === "summary") return Boolean(row.summary?.toLowerCase().includes(normalized));
|
|
13540
|
+
if (scope === "messages") return Boolean(row.searchPreview?.toLowerCase().includes(normalized));
|
|
13541
|
+
return true;
|
|
13542
|
+
});
|
|
13543
|
+
}
|
|
13544
|
+
function formatChatConversation(row) {
|
|
13545
|
+
return {
|
|
13546
|
+
id: row.id,
|
|
13547
|
+
title: row.title,
|
|
13548
|
+
status: row.status,
|
|
13549
|
+
preferredAgentId: row.preferredAgentId ?? "-",
|
|
13550
|
+
unread: row.unreadCount,
|
|
13551
|
+
lastMessageAt: row.lastMessageAt ?? "-",
|
|
13552
|
+
preview: row.latestReplyPreview ?? row.latestUserMessagePreview ?? "-"
|
|
13553
|
+
};
|
|
13554
|
+
}
|
|
13555
|
+
function formatChatSearchResult(row, maxChars) {
|
|
13556
|
+
return {
|
|
13557
|
+
id: row.id,
|
|
13558
|
+
title: row.title,
|
|
13559
|
+
status: row.status,
|
|
13560
|
+
lastMessageAt: row.lastMessageAt ?? "-",
|
|
13561
|
+
snippet: clip(row.searchPreview ?? row.latestReplyPreview ?? row.latestUserMessagePreview ?? row.summary ?? "", maxChars)
|
|
13562
|
+
};
|
|
13563
|
+
}
|
|
13564
|
+
function formatChatMessage(row, maxOutputChars = 1200) {
|
|
13565
|
+
return {
|
|
13566
|
+
id: row.id,
|
|
13567
|
+
role: row.role,
|
|
13568
|
+
kind: row.kind,
|
|
13569
|
+
status: row.status,
|
|
13570
|
+
createdAt: row.createdAt,
|
|
13571
|
+
body: clip(row.body, 220),
|
|
13572
|
+
transcriptEntries: row.transcriptSummary?.entryCount ?? row.transcript?.length ?? 0,
|
|
13573
|
+
...row.transcript?.length ? { transcriptPreview: clip(row.transcript.map((entry) => formatTranscriptEntry(entry, maxOutputChars)).join(" "), maxOutputChars) } : {}
|
|
13574
|
+
};
|
|
13575
|
+
}
|
|
13576
|
+
function formatChatTranscriptMessage(row, maxChars) {
|
|
13577
|
+
const header = {
|
|
13578
|
+
id: row.id,
|
|
13579
|
+
role: row.role,
|
|
13580
|
+
kind: row.kind,
|
|
13581
|
+
status: row.status,
|
|
13582
|
+
createdAt: row.createdAt,
|
|
13583
|
+
body: clip(row.body, 220)
|
|
13584
|
+
};
|
|
13585
|
+
const transcriptRows = (row.transcript ?? []).map((entry, index) => ({
|
|
13586
|
+
id: `${row.id}:entry-${index + 1}`,
|
|
13587
|
+
messageId: row.id,
|
|
13588
|
+
role: row.role,
|
|
13589
|
+
entry: formatTranscriptEntry(entry, maxChars)
|
|
13590
|
+
}));
|
|
13591
|
+
return transcriptRows.length > 0 ? [header, ...transcriptRows] : [header];
|
|
13592
|
+
}
|
|
13593
|
+
function formatTranscriptEntry(entry, maxChars) {
|
|
13594
|
+
if (entry.kind === "tool_call") return `${entry.ts} tool_call ${entry.name} ${clip(JSON.stringify(entry.input), maxChars)}`;
|
|
13595
|
+
if (entry.kind === "tool_result") return `${entry.ts} tool_result ${entry.toolName ?? entry.toolUseId} ${entry.isError ? "ERROR " : ""}${clip(entry.content, maxChars)}`;
|
|
13596
|
+
if (entry.kind === "result") return `${entry.ts} result ${entry.isError ? "ERROR " : ""}${clip(entry.text || entry.errors.join("; "), maxChars)}`;
|
|
13597
|
+
if ("text" in entry) return `${entry.ts} ${entry.kind} ${clip(entry.text, maxChars)}`;
|
|
13598
|
+
return `${entry.ts} ${entry.kind}`;
|
|
13599
|
+
}
|
|
13600
|
+
function parseLimit(value, fallback) {
|
|
13601
|
+
const parsed = Number(value ?? fallback);
|
|
13602
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
13603
|
+
return Math.floor(parsed);
|
|
13604
|
+
}
|
|
13605
|
+
function includesChatTranscript(opts) {
|
|
13606
|
+
return Boolean(opts.includeTranscript || opts.includeOutput || opts.includeOutputs);
|
|
13607
|
+
}
|
|
13608
|
+
function clip(value, maxChars) {
|
|
13609
|
+
const text6 = value.replace(/\s+/g, " ").trim();
|
|
13610
|
+
if (text6.length <= maxChars) return text6;
|
|
13611
|
+
return `${text6.slice(0, Math.max(0, maxChars - 1))}\u2026`;
|
|
13612
|
+
}
|
|
13613
|
+
function parseJsonObjectOption2(value, label) {
|
|
13614
|
+
if (!value) return {};
|
|
13615
|
+
try {
|
|
13616
|
+
const parsed = JSON.parse(value);
|
|
13617
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
13618
|
+
throw new Error(`${label} must be a JSON object`);
|
|
13619
|
+
}
|
|
13620
|
+
return parsed;
|
|
13621
|
+
} catch (error) {
|
|
13622
|
+
if (error instanceof Error && error.message.includes("JSON object")) throw error;
|
|
13623
|
+
throw new Error(`${label} must be valid JSON`);
|
|
13624
|
+
}
|
|
13625
|
+
}
|
|
13626
|
+
function definedRecord2(record) {
|
|
13627
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== void 0));
|
|
13628
|
+
}
|
|
13629
|
+
async function readStdin() {
|
|
13630
|
+
const chunks = [];
|
|
13631
|
+
for await (const chunk of process.stdin) {
|
|
13632
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
13633
|
+
}
|
|
13634
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
13635
|
+
}
|
|
13636
|
+
|
|
13637
|
+
// src/commands/client/runs.ts
|
|
13638
|
+
function registerRunsCommands(program) {
|
|
13639
|
+
const runs = program.command("runs").description("Run debugging operations");
|
|
13640
|
+
addCommonClientOptions(
|
|
13641
|
+
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("--created-before <iso>", "Only runs created before this timestamp").option("--limit <n>", "Maximum rows", "200").action(async (opts) => {
|
|
12621
13642
|
try {
|
|
12622
13643
|
const ctx = resolveCommandContext(opts, { requireCompany: true });
|
|
12623
|
-
const
|
|
12624
|
-
printOutput(
|
|
13644
|
+
const rows = await ctx.api.get(`/api/run-intelligence/orgs/${ctx.orgId}/runs?${buildRunsListQuery(opts)}`) ?? [];
|
|
13645
|
+
printOutput(ctx.json ? rows : rows.map(formatRunListRow), { json: ctx.json });
|
|
12625
13646
|
} catch (err) {
|
|
12626
13647
|
handleCommandError(err);
|
|
12627
13648
|
}
|
|
@@ -12629,167 +13650,178 @@ function registerSkillCommands(program) {
|
|
|
12629
13650
|
{ includeCompany: false }
|
|
12630
13651
|
);
|
|
12631
13652
|
addCommonClientOptions(
|
|
12632
|
-
|
|
13653
|
+
runs.command("get").description(getAgentCliCapabilityById("runs.get").description).argument("<runId>", "Run ID").action(async (runId, opts) => {
|
|
12633
13654
|
try {
|
|
12634
|
-
const ctx = resolveCommandContext(opts
|
|
12635
|
-
const
|
|
12636
|
-
const row = await ctx.api.get(
|
|
12637
|
-
`/api/orgs/${ctx.orgId}/skills/${skillId}/files?${query.toString()}`
|
|
12638
|
-
);
|
|
13655
|
+
const ctx = resolveCommandContext(opts);
|
|
13656
|
+
const row = await ctx.api.get(`/api/run-intelligence/runs/${encodeURIComponent(runId)}`);
|
|
12639
13657
|
printOutput(row, { json: ctx.json });
|
|
12640
13658
|
} catch (err) {
|
|
12641
13659
|
handleCommandError(err);
|
|
12642
13660
|
}
|
|
12643
|
-
})
|
|
12644
|
-
{ includeCompany: false }
|
|
13661
|
+
})
|
|
12645
13662
|
);
|
|
12646
13663
|
addCommonClientOptions(
|
|
12647
|
-
|
|
13664
|
+
runs.command("events").description(getAgentCliCapabilityById("runs.events").description).argument("<runId>", "Run ID").action(async (runId, opts) => {
|
|
12648
13665
|
try {
|
|
12649
|
-
const ctx = resolveCommandContext(opts
|
|
12650
|
-
const
|
|
12651
|
-
|
|
12652
|
-
printOutput(result, { json: ctx.json });
|
|
13666
|
+
const ctx = resolveCommandContext(opts);
|
|
13667
|
+
const rows = await ctx.api.get(`/api/run-intelligence/runs/${encodeURIComponent(runId)}/events`) ?? [];
|
|
13668
|
+
printOutput(ctx.json ? rows : rows.map(formatRunEvent), { json: ctx.json });
|
|
12653
13669
|
} catch (err) {
|
|
12654
13670
|
handleCommandError(err);
|
|
12655
13671
|
}
|
|
12656
|
-
})
|
|
12657
|
-
{ includeCompany: false }
|
|
13672
|
+
})
|
|
12658
13673
|
);
|
|
12659
13674
|
addCommonClientOptions(
|
|
12660
|
-
|
|
13675
|
+
runs.command("log").description(getAgentCliCapabilityById("runs.log").description).argument("<runId>", "Run ID").option("--max-chars <n>", "Maximum log characters for human output", "12000").action(async (runId, opts) => {
|
|
12661
13676
|
try {
|
|
12662
|
-
const ctx = resolveCommandContext(opts
|
|
12663
|
-
const
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
);
|
|
12670
|
-
printOutput(result, { json: ctx.json });
|
|
13677
|
+
const ctx = resolveCommandContext(opts);
|
|
13678
|
+
const row = await ctx.api.get(`/api/run-intelligence/runs/${encodeURIComponent(runId)}/log`);
|
|
13679
|
+
if (ctx.json) {
|
|
13680
|
+
printOutput(row, { json: true });
|
|
13681
|
+
} else {
|
|
13682
|
+
process.stdout.write(clip2(row?.content ?? "", parseLimit2(opts.maxChars, 12e3)) + "\n");
|
|
13683
|
+
}
|
|
12671
13684
|
} catch (err) {
|
|
12672
13685
|
handleCommandError(err);
|
|
12673
13686
|
}
|
|
12674
|
-
})
|
|
12675
|
-
{ includeCompany: false }
|
|
13687
|
+
})
|
|
12676
13688
|
);
|
|
12677
13689
|
addCommonClientOptions(
|
|
12678
|
-
|
|
13690
|
+
runs.command("transcript").description(getAgentCliCapabilityById("runs.transcript").description).argument("<runId>", "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").action(async (runId, opts) => {
|
|
12679
13691
|
try {
|
|
12680
|
-
const ctx = resolveCommandContext(opts
|
|
12681
|
-
const payload =
|
|
12682
|
-
|
|
12683
|
-
workspaceIds: parseCsv5(opts.workspaceIds)
|
|
12684
|
-
});
|
|
12685
|
-
const result = await ctx.api.post(
|
|
12686
|
-
`/api/orgs/${ctx.orgId}/skills/scan-projects`,
|
|
12687
|
-
payload
|
|
13692
|
+
const ctx = resolveCommandContext(opts);
|
|
13693
|
+
const payload = await ctx.api.get(
|
|
13694
|
+
`/api/run-intelligence/runs/${encodeURIComponent(runId)}/transcript?${buildTranscriptQuery(opts, { json: ctx.json })}`
|
|
12688
13695
|
);
|
|
12689
|
-
|
|
13696
|
+
if (ctx.json) {
|
|
13697
|
+
printOutput(payload, { json: true });
|
|
13698
|
+
} else if (opts.narrative) {
|
|
13699
|
+
printOutput((payload?.rows ?? []).map(formatRunTranscriptNarrative), { json: false });
|
|
13700
|
+
} else {
|
|
13701
|
+
printOutput((payload?.rows ?? []).map(formatRunTranscriptRow), { json: false });
|
|
13702
|
+
}
|
|
12690
13703
|
} catch (err) {
|
|
12691
13704
|
handleCommandError(err);
|
|
12692
13705
|
}
|
|
12693
|
-
})
|
|
12694
|
-
{ includeCompany: false }
|
|
13706
|
+
})
|
|
12695
13707
|
);
|
|
12696
|
-
}
|
|
12697
|
-
function parseCsv5(value) {
|
|
12698
|
-
if (!value) return void 0;
|
|
12699
|
-
const rows = value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
12700
|
-
return rows.length > 0 ? rows : void 0;
|
|
12701
|
-
}
|
|
12702
|
-
|
|
12703
|
-
// src/commands/client/library.ts
|
|
12704
|
-
import { readFile as readFile6 } from "node:fs/promises";
|
|
12705
|
-
import path20 from "node:path";
|
|
12706
|
-
function registerLibraryCommands(program) {
|
|
12707
|
-
const library = program.command("library").description("Library file operations");
|
|
12708
|
-
const file = library.command("file").description("Path-based Library file operations");
|
|
12709
13708
|
addCommonClientOptions(
|
|
12710
|
-
|
|
13709
|
+
runs.command("errors").description(getAgentCliCapabilityById("runs.errors").description).argument("<runId>", "Run ID").option("--max-chars <n>", "Maximum output characters per error", "1200").action(async (runId, opts) => {
|
|
12711
13710
|
try {
|
|
12712
|
-
const ctx = resolveCommandContext(opts
|
|
12713
|
-
const
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
const result = await ctx.api.get(
|
|
12718
|
-
`/api/orgs/${ctx.orgId}/workspace/files${query ? `?${query}` : ""}`
|
|
13711
|
+
const ctx = resolveCommandContext(opts);
|
|
13712
|
+
const params = new URLSearchParams();
|
|
13713
|
+
params.set("maxChars", String(parseLimit2(opts.maxChars, 1200)));
|
|
13714
|
+
const payload = await ctx.api.get(
|
|
13715
|
+
`/api/run-intelligence/runs/${encodeURIComponent(runId)}/errors?${params.toString()}`
|
|
12719
13716
|
);
|
|
12720
|
-
printOutput(
|
|
13717
|
+
printOutput(ctx.json ? payload : (payload?.errors ?? []).map(formatRunError), { json: ctx.json });
|
|
12721
13718
|
} catch (err) {
|
|
12722
13719
|
handleCommandError(err);
|
|
12723
13720
|
}
|
|
12724
|
-
})
|
|
12725
|
-
{ includeCompany: true }
|
|
13721
|
+
})
|
|
12726
13722
|
);
|
|
12727
13723
|
addCommonClientOptions(
|
|
12728
|
-
|
|
13724
|
+
runs.command("cancel").description(getAgentCliCapabilityById("runs.cancel").description).argument("<runId>", "Run ID").action(async (runId, opts) => {
|
|
12729
13725
|
try {
|
|
12730
|
-
const ctx = resolveCommandContext(opts
|
|
12731
|
-
const
|
|
12732
|
-
|
|
12733
|
-
const result = await ctx.api.get(
|
|
12734
|
-
`/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`
|
|
12735
|
-
);
|
|
12736
|
-
printOutput(result, { json: ctx.json });
|
|
13726
|
+
const ctx = resolveCommandContext(opts);
|
|
13727
|
+
const row = await ctx.api.post(`/api/heartbeat-runs/${encodeURIComponent(runId)}/cancel`, {});
|
|
13728
|
+
printOutput(row, { json: ctx.json });
|
|
12737
13729
|
} catch (err) {
|
|
12738
13730
|
handleCommandError(err);
|
|
12739
13731
|
}
|
|
12740
|
-
})
|
|
12741
|
-
{ includeCompany: true }
|
|
13732
|
+
})
|
|
12742
13733
|
);
|
|
12743
13734
|
addCommonClientOptions(
|
|
12744
|
-
|
|
13735
|
+
runs.command("retry").description(getAgentCliCapabilityById("runs.retry").description).argument("<runId>", "Run ID").action(async (runId, opts) => {
|
|
12745
13736
|
try {
|
|
12746
|
-
const ctx = resolveCommandContext(opts
|
|
12747
|
-
const
|
|
12748
|
-
|
|
12749
|
-
search.set("path", filePath.trim());
|
|
12750
|
-
const updatePath = `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`;
|
|
12751
|
-
const updated = await ctx.api.patch(
|
|
12752
|
-
updatePath,
|
|
12753
|
-
{ content: body },
|
|
12754
|
-
{ ignoreNotFound: true }
|
|
12755
|
-
);
|
|
12756
|
-
if (updated) {
|
|
12757
|
-
printOutput(updated, { json: ctx.json });
|
|
12758
|
-
return;
|
|
12759
|
-
}
|
|
12760
|
-
const created = await ctx.api.post(
|
|
12761
|
-
`/api/orgs/${ctx.orgId}/workspace/file`,
|
|
12762
|
-
{ filePath: filePath.trim(), content: body }
|
|
12763
|
-
);
|
|
12764
|
-
printOutput(created, { json: ctx.json });
|
|
13737
|
+
const ctx = resolveCommandContext(opts);
|
|
13738
|
+
const row = await ctx.api.post(`/api/heartbeat-runs/${encodeURIComponent(runId)}/retry`, {});
|
|
13739
|
+
printOutput(row, { json: ctx.json });
|
|
12765
13740
|
} catch (err) {
|
|
12766
13741
|
handleCommandError(err);
|
|
12767
13742
|
}
|
|
12768
|
-
})
|
|
12769
|
-
{ includeCompany: true }
|
|
13743
|
+
})
|
|
12770
13744
|
);
|
|
12771
13745
|
}
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
if (
|
|
12777
|
-
|
|
12778
|
-
|
|
12779
|
-
if (
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
return readFile6(resolvedPath, "utf8").catch((err) => {
|
|
12784
|
-
throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
12785
|
-
});
|
|
13746
|
+
function buildRunsListQuery(opts) {
|
|
13747
|
+
const params = new URLSearchParams();
|
|
13748
|
+
if (opts.updatedAfter) params.set("updatedAfter", opts.updatedAfter);
|
|
13749
|
+
if (opts.runIdPrefix) params.set("runIdPrefix", opts.runIdPrefix);
|
|
13750
|
+
if (opts.agentId) params.set("agentId", opts.agentId);
|
|
13751
|
+
if (opts.status) params.set("status", opts.status);
|
|
13752
|
+
if (opts.runtime) params.set("runtime", opts.runtime);
|
|
13753
|
+
if (opts.issueId) params.set("issueId", opts.issueId);
|
|
13754
|
+
if (opts.createdBefore) params.set("createdBefore", opts.createdBefore);
|
|
13755
|
+
if (opts.limit) params.set("limit", opts.limit);
|
|
13756
|
+
return params.toString();
|
|
12786
13757
|
}
|
|
12787
|
-
|
|
12788
|
-
const
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
13758
|
+
function buildTranscriptQuery(opts, output) {
|
|
13759
|
+
const params = new URLSearchParams();
|
|
13760
|
+
if (opts.errorsOnly) params.set("errorsOnly", "true");
|
|
13761
|
+
if (opts.aroundError) params.set("aroundError", opts.aroundError);
|
|
13762
|
+
if (opts.cursor) params.set("cursor", opts.cursor);
|
|
13763
|
+
if (opts.turnLimit) params.set("turnLimit", String(parseLimit2(opts.turnLimit, 20)));
|
|
13764
|
+
params.set("contextTurns", String(parseLimit2(opts.contextTurns, 1)));
|
|
13765
|
+
params.set("order", opts.chronological || opts.narrative ? "oldest" : "newest");
|
|
13766
|
+
params.set("output", output.json ? "full" : "compact");
|
|
13767
|
+
const includeOutputs = output.json || Boolean(opts.includeOutput || opts.includeOutputs || opts.narrative);
|
|
13768
|
+
params.set("includeOutputs", includeOutputs ? "true" : "false");
|
|
13769
|
+
params.set("maxChars", String(parseLimit2(opts.maxOutputChars ?? opts.maxChars, 1200)));
|
|
13770
|
+
return params.toString();
|
|
13771
|
+
}
|
|
13772
|
+
function formatRunListRow(row) {
|
|
13773
|
+
return {
|
|
13774
|
+
id: row.run.id,
|
|
13775
|
+
status: row.run.status,
|
|
13776
|
+
agent: row.agentName ?? row.run.agentId,
|
|
13777
|
+
runtime: row.bundle.agentRuntimeType,
|
|
13778
|
+
issue: row.issue?.identifier ?? row.issue?.id ?? "-",
|
|
13779
|
+
updatedAt: row.run.updatedAt
|
|
13780
|
+
};
|
|
13781
|
+
}
|
|
13782
|
+
function formatRunEvent(row) {
|
|
13783
|
+
return {
|
|
13784
|
+
seq: row.seq,
|
|
13785
|
+
level: row.level,
|
|
13786
|
+
stream: row.stream,
|
|
13787
|
+
message: row.message,
|
|
13788
|
+
createdAt: row.createdAt
|
|
13789
|
+
};
|
|
13790
|
+
}
|
|
13791
|
+
function formatRunTranscriptRow(row) {
|
|
13792
|
+
return {
|
|
13793
|
+
id: row.id,
|
|
13794
|
+
turn: row.turnIndex ?? "-",
|
|
13795
|
+
kind: row.kind,
|
|
13796
|
+
ts: row.ts,
|
|
13797
|
+
error: row.isError ? "yes" : "no",
|
|
13798
|
+
preview: row.preview || row.detailPreview,
|
|
13799
|
+
...row.output ? { output: row.output.text } : {}
|
|
13800
|
+
};
|
|
13801
|
+
}
|
|
13802
|
+
function formatRunTranscriptNarrative(row) {
|
|
13803
|
+
const marker = row.isError ? "ERROR " : "";
|
|
13804
|
+
return `${row.id} ${row.ts} ${marker}${row.kind}: ${row.preview || row.detailPreview}${row.output ? `
|
|
13805
|
+
${row.output.text}` : ""}`;
|
|
13806
|
+
}
|
|
13807
|
+
function formatRunError(row) {
|
|
13808
|
+
return {
|
|
13809
|
+
id: row.id,
|
|
13810
|
+
type: row.type,
|
|
13811
|
+
turn: row.turnIndex ?? "-",
|
|
13812
|
+
summary: row.summary,
|
|
13813
|
+
output: row.output.text,
|
|
13814
|
+
context: row.transcriptContext?.command ?? "-"
|
|
13815
|
+
};
|
|
13816
|
+
}
|
|
13817
|
+
function parseLimit2(value, fallback) {
|
|
13818
|
+
const parsed = Number(value ?? fallback);
|
|
13819
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallback;
|
|
13820
|
+
return Math.floor(parsed);
|
|
13821
|
+
}
|
|
13822
|
+
function clip2(value, maxChars) {
|
|
13823
|
+
if (value.length <= maxChars) return value;
|
|
13824
|
+
return `${value.slice(0, Math.max(0, maxChars - 1))}\u2026`;
|
|
12793
13825
|
}
|
|
12794
13826
|
|
|
12795
13827
|
// src/config/data-dir.ts
|
|
@@ -13172,6 +14204,9 @@ function createProgram() {
|
|
|
13172
14204
|
registerDashboardCommands(program);
|
|
13173
14205
|
registerSkillCommands(program);
|
|
13174
14206
|
registerLibraryCommands(program);
|
|
14207
|
+
registerAutomationCommands(program);
|
|
14208
|
+
registerChatCommands(program);
|
|
14209
|
+
registerRunsCommands(program);
|
|
13175
14210
|
registerLazyWorktreeCommands(program);
|
|
13176
14211
|
registerPluginCommands(program);
|
|
13177
14212
|
registerLazyBenchmarkCommands(program);
|