@rudderhq/cli 0.2.10-canary.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js 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, 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, 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";
@@ -150,6 +150,10 @@ var init_constants = __esm({
150
150
  "url",
151
151
  "connector_object"
152
152
  ];
153
+ ORGANIZATION_RESOURCE_SOURCE_TYPES = [
154
+ "external",
155
+ "library"
156
+ ];
153
157
  PROJECT_RESOURCE_ATTACHMENT_ROLES = [
154
158
  "working_set",
155
159
  "reference",
@@ -511,7 +515,7 @@ var init_budget = __esm({
511
515
 
512
516
  // ../packages/shared/dist/validators/organization.js
513
517
  import { z as z3 } from "zod";
514
- var logoAssetIdSchema, brandColorSchema, createOrganizationSchema, updateOrganizationSchema, updateOrganizationBrandingSchema, updateOrganizationWorkspaceFileSchema;
518
+ var logoAssetIdSchema, brandColorSchema, createOrganizationSchema, updateOrganizationSchema, updateOrganizationBrandingSchema, updateOrganizationWorkspaceFileSchema, createOrganizationWorkspaceFileSchema, createOrganizationWorkspaceDirectorySchema, renameOrganizationWorkspaceEntrySchema, moveOrganizationWorkspaceEntrySchema;
515
519
  var init_organization = __esm({
516
520
  "../packages/shared/dist/validators/organization.js"() {
517
521
  "use strict";
@@ -543,6 +547,19 @@ var init_organization = __esm({
543
547
  updateOrganizationWorkspaceFileSchema = z3.object({
544
548
  content: z3.string()
545
549
  });
550
+ createOrganizationWorkspaceFileSchema = z3.object({
551
+ filePath: z3.string().trim().min(1).max(1e3),
552
+ content: z3.string().optional().default("")
553
+ });
554
+ createOrganizationWorkspaceDirectorySchema = z3.object({
555
+ directoryPath: z3.string().trim().min(1).max(1e3)
556
+ });
557
+ renameOrganizationWorkspaceEntrySchema = z3.object({
558
+ name: z3.string().trim().min(1).max(255)
559
+ });
560
+ moveOrganizationWorkspaceEntrySchema = z3.object({
561
+ destinationDirectoryPath: z3.string().trim().max(1e3).default("")
562
+ });
546
563
  }
547
564
  });
548
565
 
@@ -706,27 +723,67 @@ var init_organization_intelligence_profile = __esm({
706
723
 
707
724
  // ../packages/shared/dist/validators/resource.js
708
725
  import { z as z7 } from "zod";
709
- var organizationResourceKindSchema, projectResourceAttachmentRoleSchema, createOrganizationResourceSchema, updateOrganizationResourceSchema, projectResourceAttachmentInputSchema, updateProjectResourceAttachmentSchema, createProjectInlineResourceSchema;
726
+ function isValidLibraryProjectPath(locator, kind) {
727
+ const trimmed = locator.trim();
728
+ if (!trimmed)
729
+ return false;
730
+ if (LIBRARY_PATH_SCHEME_RE.test(trimmed))
731
+ return false;
732
+ if (trimmed.startsWith("/") || trimmed.startsWith("\\") || trimmed.startsWith("~"))
733
+ return false;
734
+ if (trimmed.includes("\\"))
735
+ return false;
736
+ const parts = trimmed.split("/");
737
+ if (!parts.every((part) => part.length > 0 && part !== "." && part !== ".."))
738
+ return false;
739
+ if (parts[0] !== "projects")
740
+ return false;
741
+ return kind === "directory" ? parts.length >= 2 : parts.length >= 3;
742
+ }
743
+ function validateLibraryResourceContract(value, ctx) {
744
+ if (value.sourceType !== "library")
745
+ return;
746
+ if (value.kind !== void 0 && value.kind !== "file" && value.kind !== "directory") {
747
+ ctx.addIssue({
748
+ code: z7.ZodIssueCode.custom,
749
+ message: "Library resources must be file or directory resources.",
750
+ path: ["kind"]
751
+ });
752
+ }
753
+ if (value.locator !== void 0 && !isValidLibraryProjectPath(value.locator, value.kind)) {
754
+ ctx.addIssue({
755
+ code: z7.ZodIssueCode.custom,
756
+ message: "Library resource locator must be a normalized project Library path.",
757
+ path: ["locator"]
758
+ });
759
+ }
760
+ }
761
+ var organizationResourceKindSchema, organizationResourceSourceTypeSchema, projectResourceAttachmentRoleSchema, LIBRARY_PATH_SCHEME_RE, createOrganizationResourceBaseSchema, createOrganizationResourceSchema, updateOrganizationResourceSchema, projectResourceAttachmentInputSchema, updateProjectResourceAttachmentSchema, createProjectInlineResourceSchema;
710
762
  var init_resource = __esm({
711
763
  "../packages/shared/dist/validators/resource.js"() {
712
764
  "use strict";
713
765
  init_constants();
714
766
  organizationResourceKindSchema = z7.enum(ORGANIZATION_RESOURCE_KINDS);
767
+ organizationResourceSourceTypeSchema = z7.enum(ORGANIZATION_RESOURCE_SOURCE_TYPES);
715
768
  projectResourceAttachmentRoleSchema = z7.enum(PROJECT_RESOURCE_ATTACHMENT_ROLES);
716
- createOrganizationResourceSchema = z7.object({
769
+ LIBRARY_PATH_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
770
+ createOrganizationResourceBaseSchema = z7.object({
717
771
  name: z7.string().min(1),
718
772
  kind: organizationResourceKindSchema,
773
+ sourceType: organizationResourceSourceTypeSchema.optional().default("external"),
719
774
  locator: z7.string().min(1),
720
775
  description: z7.string().optional().nullable(),
721
776
  metadata: z7.record(z7.unknown()).optional().nullable()
722
777
  });
778
+ createOrganizationResourceSchema = createOrganizationResourceBaseSchema.superRefine(validateLibraryResourceContract);
723
779
  updateOrganizationResourceSchema = z7.object({
724
780
  name: z7.string().min(1).optional(),
725
781
  kind: organizationResourceKindSchema.optional(),
782
+ sourceType: organizationResourceSourceTypeSchema.optional(),
726
783
  locator: z7.string().min(1).optional(),
727
784
  description: z7.string().optional().nullable(),
728
785
  metadata: z7.record(z7.unknown()).optional().nullable()
729
- }).strict();
786
+ }).strict().superRefine(validateLibraryResourceContract);
730
787
  projectResourceAttachmentInputSchema = z7.object({
731
788
  resourceId: z7.string().uuid(),
732
789
  role: projectResourceAttachmentRoleSchema.optional(),
@@ -738,11 +795,11 @@ var init_resource = __esm({
738
795
  note: z7.string().optional().nullable(),
739
796
  sortOrder: z7.number().int().nonnegative().optional()
740
797
  }).strict();
741
- createProjectInlineResourceSchema = createOrganizationResourceSchema.extend({
798
+ createProjectInlineResourceSchema = createOrganizationResourceBaseSchema.extend({
742
799
  role: projectResourceAttachmentRoleSchema.optional(),
743
800
  note: z7.string().optional().nullable(),
744
801
  sortOrder: z7.number().int().nonnegative().optional()
745
- }).strict();
802
+ }).strict().superRefine(validateLibraryResourceContract);
746
803
  }
747
804
  });
748
805
 
@@ -863,7 +920,7 @@ var init_chat = __esm({
863
920
  status: z8.enum(AUTOMATION_STATUSES).optional().default("active"),
864
921
  concurrencyPolicy: z8.enum(AUTOMATION_CONCURRENCY_POLICIES).optional().default("coalesce_if_active"),
865
922
  catchUpPolicy: z8.enum(AUTOMATION_CATCH_UP_POLICIES).optional().default("skip_missed"),
866
- outputMode: z8.enum(AUTOMATION_OUTPUT_MODES).optional().default("chat_output"),
923
+ outputMode: z8.enum(AUTOMATION_OUTPUT_MODES).optional().default("track_issue"),
867
924
  schedule: z8.object({
868
925
  cronExpression: z8.string().trim().min(1),
869
926
  timezone: z8.string().trim().min(1),
@@ -1589,7 +1646,7 @@ var init_project = __esm({
1589
1646
 
1590
1647
  // ../packages/shared/dist/validators/issue.js
1591
1648
  import { z as z14 } from "zod";
1592
- var executionWorkspaceStrategySchema2, issueExecutionWorkspaceSettingsSchema, issueAssigneeAdapterOverridesSchema, createIssueSchema, createIssueLabelSchema, updateIssueLabelSchema, updateIssueSchema, reorderIssueSchema, checkoutIssueSchema, addIssueCommentSchema, reportIssueCommitSchema, linkIssueApprovalSchema, createIssueAttachmentMetadataSchema, createIssueWorkspaceAttachmentSchema, ISSUE_DOCUMENT_FORMATS, issueDocumentFormatSchema, issueDocumentKeySchema, upsertIssueDocumentSchema;
1649
+ var executionWorkspaceStrategySchema2, issueExecutionWorkspaceSettingsSchema, issueAssigneeAdapterOverridesSchema, createIssueSchema, createIssueLabelSchema, updateIssueLabelSchema, updateIssueSchema, reorderIssueSchema, checkoutIssueSchema, addIssueCommentSchema, reportIssueCommitSchema, linkIssueApprovalSchema, createIssueAttachmentMetadataSchema, createIssueWorkspaceAttachmentSchema, ISSUE_DOCUMENT_FORMATS, issueDocumentFormatSchema, issueDocumentKeySchema, upsertIssueDocumentSchema, createLibraryDocumentSchema, updateLibraryDocumentSchema, restoreLibraryDocumentRevisionSchema;
1593
1650
  var init_issue = __esm({
1594
1651
  "../packages/shared/dist/validators/issue.js"() {
1595
1652
  "use strict";
@@ -1698,6 +1755,22 @@ var init_issue = __esm({
1698
1755
  changeSummary: z14.string().trim().max(500).nullable().optional(),
1699
1756
  baseRevisionId: z14.string().uuid().nullable().optional()
1700
1757
  });
1758
+ createLibraryDocumentSchema = z14.object({
1759
+ title: z14.string().trim().max(200).nullable().optional(),
1760
+ format: issueDocumentFormatSchema.optional().default("markdown"),
1761
+ body: z14.string().max(524288).optional().default(""),
1762
+ changeSummary: z14.string().trim().max(500).nullable().optional()
1763
+ });
1764
+ updateLibraryDocumentSchema = z14.object({
1765
+ title: z14.string().trim().max(200).nullable().optional(),
1766
+ format: issueDocumentFormatSchema.optional().default("markdown"),
1767
+ body: z14.string().max(524288),
1768
+ changeSummary: z14.string().trim().max(500).nullable().optional(),
1769
+ baseRevisionId: z14.string().uuid().nullable().optional()
1770
+ });
1771
+ restoreLibraryDocumentRevisionSchema = z14.object({
1772
+ changeSummary: z14.string().trim().max(500).nullable().optional()
1773
+ });
1701
1774
  }
1702
1775
  });
1703
1776
 
@@ -1860,7 +1933,7 @@ var init_automation = __esm({
1860
1933
  status: z20.enum(AUTOMATION_STATUSES).optional().default("active"),
1861
1934
  concurrencyPolicy: z20.enum(AUTOMATION_CONCURRENCY_POLICIES).optional().default("coalesce_if_active"),
1862
1935
  catchUpPolicy: z20.enum(AUTOMATION_CATCH_UP_POLICIES).optional().default("skip_missed"),
1863
- outputMode: z20.enum(AUTOMATION_OUTPUT_MODES).optional().default("chat_output"),
1936
+ outputMode: z20.enum(AUTOMATION_OUTPUT_MODES).optional().default("track_issue"),
1864
1937
  chatConversationId: z20.string().uuid().optional().nullable().default(null)
1865
1938
  });
1866
1939
  createAutomationSchema = automationBodySchema.superRefine((value, ctx) => {
@@ -2628,12 +2701,16 @@ var init_organization_skill_reference = __esm({
2628
2701
  });
2629
2702
 
2630
2703
  // ../packages/shared/dist/project-mentions.js
2631
- var PROJECT_COLOR_VALUES;
2704
+ var AGENT_AVATAR_UUID_RE, AGENT_ASSET_ICON_RE, AGENT_DICEBEAR_NOTIONISTS_ICON_RE, PROJECT_COLOR_VALUES, AGENT_AVATAR_BACKGROUND_VALUES;
2632
2705
  var init_project_mentions = __esm({
2633
2706
  "../packages/shared/dist/project-mentions.js"() {
2634
2707
  "use strict";
2635
2708
  init_constants();
2709
+ AGENT_AVATAR_UUID_RE = "[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
2710
+ AGENT_ASSET_ICON_RE = new RegExp(`^asset:${AGENT_AVATAR_UUID_RE}(?:\\?bg=([a-z0-9-]+))?$`, "i");
2711
+ AGENT_DICEBEAR_NOTIONISTS_ICON_RE = new RegExp(`^${AGENT_DICEBEAR_NOTIONISTS_ICON_PREFIX}${AGENT_AVATAR_UUID_RE}(?:\\?bg=([a-z0-9-]+))?$`, "i");
2636
2712
  PROJECT_COLOR_VALUES = new Set(PROJECT_COLORS);
2713
+ AGENT_AVATAR_BACKGROUND_VALUES = new Set(AGENT_AVATAR_BACKGROUND_PRESET_IDS);
2637
2714
  }
2638
2715
  });
2639
2716
 
@@ -4215,10 +4292,10 @@ var init_install = __esm({
4215
4292
  init_home();
4216
4293
  RUNTIME_NPM_PACKAGE_NAME = "@rudderhq/server";
4217
4294
  RUNTIME_METADATA_FILE = "runtime.json";
4218
- DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 5;
4295
+ DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 2;
4219
4296
  DEFAULT_RUNTIME_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
4220
4297
  DEFAULT_RUNTIME_CACHE_MAX_BYTES = 2 * 1024 * 1024 * 1024;
4221
- DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 1;
4298
+ DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 0;
4222
4299
  RUNTIME_NPM_INSTALL_FLAGS = ["--omit=dev", "--include=optional", "--no-audit", "--no-fund"];
4223
4300
  RuntimeInstallError = class extends Error {
4224
4301
  cacheDir;
@@ -6470,7 +6547,7 @@ init_install();
6470
6547
  import { spawn, spawnSync as spawnSync3 } from "node:child_process";
6471
6548
  import { createHash } from "node:crypto";
6472
6549
  import { constants as fsConstants, createWriteStream, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
6473
- import { access, chmod, copyFile, cp, mkdtemp, mkdir as mkdir2, readFile as readFile2, readdir as readdir2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
6550
+ import { access, chmod, copyFile, cp, mkdtemp, mkdir as mkdir2, readFile as readFile2, readdir as readdir2, rm as rm2, stat as stat2, utimes, writeFile as writeFile2 } from "node:fs/promises";
6474
6551
  import { homedir, tmpdir } from "node:os";
6475
6552
  import path11 from "node:path";
6476
6553
  import { Readable, Transform } from "node:stream";
@@ -6601,6 +6678,10 @@ var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
6601
6678
  var DESKTOP_CHECKSUM_ASSET_NAME = "SHASUMS256.txt";
6602
6679
  var DESKTOP_ASSET_CACHE_DIR = "desktop-assets";
6603
6680
  var GITHUB_ASSET_DOWNLOAD_ACCEPT = "application/octet-stream";
6681
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES = 2;
6682
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
6683
+ var DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES = 768 * 1024 * 1024;
6684
+ var DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS = 1;
6604
6685
  function normalizeProgressTotal(totalBytes) {
6605
6686
  return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
6606
6687
  }
@@ -7065,12 +7146,158 @@ function resolveDesktopAssetCacheDir(assetChecksum, homeDir = resolveRudderHomeD
7065
7146
  function resolveDesktopCachedAssetPath(assetName, assetChecksum, homeDir = resolveRudderHomeDir()) {
7066
7147
  return path11.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path11.basename(assetName));
7067
7148
  }
7149
+ async function pruneDesktopAssetCache(options = {}) {
7150
+ const homeDir = options.homeDir ?? resolveRudderHomeDir();
7151
+ const entries = await scanDesktopAssetCacheEntries(homeDir);
7152
+ const protectedChecksums = resolveProtectedDesktopAssetChecksums(entries, {
7153
+ protectedChecksums: options.protectedChecksums ?? [],
7154
+ keepPreviousEntries: options.keepPreviousEntries ?? DEFAULT_DESKTOP_ASSET_CACHE_KEEP_PREVIOUS
7155
+ });
7156
+ const protectedSet = new Set(protectedChecksums);
7157
+ const deletions = planDesktopAssetCacheDeletions(entries, {
7158
+ nowMs: (options.now ?? /* @__PURE__ */ new Date()).getTime(),
7159
+ protectedChecksums: protectedSet,
7160
+ maxEntries: options.maxEntries ?? DEFAULT_DESKTOP_ASSET_CACHE_MAX_ENTRIES,
7161
+ maxAgeMs: options.maxAgeMs ?? DEFAULT_DESKTOP_ASSET_CACHE_MAX_AGE_MS,
7162
+ maxTotalBytes: options.maxTotalBytes ?? DEFAULT_DESKTOP_ASSET_CACHE_MAX_BYTES
7163
+ });
7164
+ const deleted = [];
7165
+ const warnings = [];
7166
+ for (const entry of deletions) {
7167
+ try {
7168
+ await rm2(entry.cacheDir, { recursive: true, force: true });
7169
+ deleted.push({
7170
+ cacheDir: entry.cacheDir,
7171
+ checksum: entry.checksum,
7172
+ sizeBytes: entry.sizeBytes
7173
+ });
7174
+ } catch (error) {
7175
+ warnings.push(
7176
+ `Failed to remove Desktop asset cache ${entry.cacheDir}: ${error instanceof Error ? error.message : String(error)}`
7177
+ );
7178
+ }
7179
+ }
7180
+ return {
7181
+ scanned: entries.length,
7182
+ deleted,
7183
+ protectedChecksums,
7184
+ freedBytes: deleted.reduce((total, entry) => total + entry.sizeBytes, 0),
7185
+ warnings
7186
+ };
7187
+ }
7188
+ async function maybePruneDesktopAssetCache(options) {
7189
+ const result = await pruneDesktopAssetCache(options);
7190
+ return result.deleted.length > 0 || result.warnings.length > 0 ? result : null;
7191
+ }
7192
+ async function scanDesktopAssetCacheEntries(homeDir) {
7193
+ const cacheRoot = path11.join(homeDir, DESKTOP_ASSET_CACHE_DIR);
7194
+ const dirents = await readdir2(cacheRoot, { withFileTypes: true }).catch(() => null);
7195
+ if (!dirents) return [];
7196
+ const entries = [];
7197
+ for (const dirent of dirents) {
7198
+ if (!dirent.isDirectory()) continue;
7199
+ let checksum;
7200
+ try {
7201
+ checksum = normalizeDesktopAssetChecksum(dirent.name);
7202
+ } catch {
7203
+ continue;
7204
+ }
7205
+ const cacheDir = path11.join(cacheRoot, dirent.name);
7206
+ const stats = await desktopCacheDirectoryStats(cacheDir);
7207
+ entries.push({
7208
+ cacheDir,
7209
+ checksum,
7210
+ lastUsedAtMs: stats.lastUsedAtMs,
7211
+ sizeBytes: stats.sizeBytes
7212
+ });
7213
+ }
7214
+ return entries;
7215
+ }
7216
+ async function desktopCacheDirectoryStats(targetPath) {
7217
+ const fallbackStat = await stat2(targetPath).catch(() => null);
7218
+ const dirents = await readdir2(targetPath, { withFileTypes: true }).catch(() => null);
7219
+ if (!dirents) {
7220
+ return {
7221
+ sizeBytes: 0,
7222
+ lastUsedAtMs: Number(fallbackStat?.mtimeMs ?? 0)
7223
+ };
7224
+ }
7225
+ let sizeBytes = 0;
7226
+ let lastUsedAtMs = Number(fallbackStat?.mtimeMs ?? 0);
7227
+ for (const dirent of dirents) {
7228
+ if (dirent.isSymbolicLink()) continue;
7229
+ const entryPath = path11.join(targetPath, dirent.name);
7230
+ const entryStat = await stat2(entryPath).catch(() => null);
7231
+ if (!entryStat) continue;
7232
+ lastUsedAtMs = Math.max(lastUsedAtMs, Number(entryStat.mtimeMs ?? 0));
7233
+ if (dirent.isDirectory()) {
7234
+ const nested = await desktopCacheDirectoryStats(entryPath);
7235
+ sizeBytes += nested.sizeBytes;
7236
+ lastUsedAtMs = Math.max(lastUsedAtMs, nested.lastUsedAtMs);
7237
+ continue;
7238
+ }
7239
+ sizeBytes += Number(entryStat.size ?? 0);
7240
+ }
7241
+ return { sizeBytes, lastUsedAtMs };
7242
+ }
7243
+ function resolveProtectedDesktopAssetChecksums(entries, options) {
7244
+ const protectedChecksums = /* @__PURE__ */ new Set();
7245
+ for (const checksum of options.protectedChecksums) {
7246
+ try {
7247
+ protectedChecksums.add(normalizeDesktopAssetChecksum(checksum));
7248
+ } catch {
7249
+ continue;
7250
+ }
7251
+ }
7252
+ const previousEntries = [...entries].filter((entry) => !protectedChecksums.has(entry.checksum)).sort((a, b) => b.lastUsedAtMs - a.lastUsedAtMs);
7253
+ for (const entry of previousEntries.slice(0, Math.max(0, options.keepPreviousEntries))) {
7254
+ protectedChecksums.add(entry.checksum);
7255
+ }
7256
+ return [...protectedChecksums].sort();
7257
+ }
7258
+ function planDesktopAssetCacheDeletions(entries, options) {
7259
+ const deletions = /* @__PURE__ */ new Set();
7260
+ const oldestFirst = [...entries].sort((a, b) => a.lastUsedAtMs - b.lastUsedAtMs);
7261
+ const canDelete = (entry) => !options.protectedChecksums.has(entry.checksum) && !deletions.has(entry.cacheDir);
7262
+ const mark = (entry) => {
7263
+ if (canDelete(entry)) deletions.add(entry.cacheDir);
7264
+ };
7265
+ if (options.maxAgeMs >= 0) {
7266
+ for (const entry of oldestFirst) {
7267
+ if (options.nowMs - entry.lastUsedAtMs > options.maxAgeMs) mark(entry);
7268
+ }
7269
+ }
7270
+ if (options.maxEntries > 0) {
7271
+ for (const entry of oldestFirst) {
7272
+ if (entries.length - deletions.size <= options.maxEntries) break;
7273
+ mark(entry);
7274
+ }
7275
+ }
7276
+ if (options.maxTotalBytes > 0) {
7277
+ let remainingBytes = entries.reduce((total, entry) => total + entry.sizeBytes, 0) - [...deletions].reduce((total, cacheDir) => total + (entries.find((entry) => entry.cacheDir === cacheDir)?.sizeBytes ?? 0), 0);
7278
+ for (const entry of oldestFirst) {
7279
+ if (remainingBytes <= options.maxTotalBytes) break;
7280
+ if (!canDelete(entry)) continue;
7281
+ deletions.add(entry.cacheDir);
7282
+ remainingBytes -= entry.sizeBytes;
7283
+ }
7284
+ }
7285
+ return entries.filter((entry) => deletions.has(entry.cacheDir));
7286
+ }
7287
+ async function touchDesktopCachedAsset(cachePath) {
7288
+ try {
7289
+ const now = /* @__PURE__ */ new Date();
7290
+ await utimes(cachePath, now, now);
7291
+ } catch {
7292
+ }
7293
+ }
7068
7294
  async function downloadDesktopAssetWithCache(asset, expectedChecksum, options = {}) {
7069
7295
  const normalizedChecksum = normalizeDesktopAssetChecksum(expectedChecksum);
7070
7296
  const cachePath = resolveDesktopCachedAssetPath(asset.name, normalizedChecksum, options.homeDir);
7071
7297
  if (await pathExists(cachePath)) {
7072
7298
  try {
7073
7299
  const checksum = assertChecksumMatch(cachePath, normalizedChecksum);
7300
+ await touchDesktopCachedAsset(cachePath);
7074
7301
  return { path: cachePath, checksum, cacheStatus: "hit" };
7075
7302
  } catch {
7076
7303
  await rm2(cachePath, { force: true });
@@ -7677,6 +7904,17 @@ async function startCommand(opts) {
7677
7904
  );
7678
7905
  await writeInstallMetadata(installPaths, releaseTag, selectedAsset.name, checksum, selectedAssetKind);
7679
7906
  }
7907
+ const desktopAssetPrune = await maybePruneDesktopAssetCache({
7908
+ protectedChecksums: [expectedChecksum]
7909
+ });
7910
+ if (desktopAssetPrune) {
7911
+ if (desktopAssetPrune.deleted.length > 0) {
7912
+ p13.log.success(
7913
+ `Pruned ${desktopAssetPrune.deleted.length} old Desktop asset cache(s), freed ${formatBytes(desktopAssetPrune.freedBytes)}.`
7914
+ );
7915
+ }
7916
+ for (const warning of desktopAssetPrune.warnings) p13.log.warn(warning);
7917
+ }
7680
7918
  if (opts.open !== false) {
7681
7919
  await runStartPhase(
7682
7920
  "Launching Rudder Desktop...",
@@ -8148,41 +8386,41 @@ var RudderApiClient = class {
8148
8386
  this.runId = opts.runId?.trim() || void 0;
8149
8387
  this.recoverAuth = opts.recoverAuth;
8150
8388
  }
8151
- get(path22, opts) {
8152
- return this.request(path22, { method: "GET" }, opts);
8389
+ get(path23, opts) {
8390
+ return this.request(path23, { method: "GET" }, opts);
8153
8391
  }
8154
- post(path22, body, opts) {
8155
- return this.request(path22, {
8392
+ post(path23, body, opts) {
8393
+ return this.request(path23, {
8156
8394
  method: "POST",
8157
8395
  body: body === void 0 ? void 0 : JSON.stringify(body)
8158
8396
  }, opts);
8159
8397
  }
8160
- postForm(path22, form, opts) {
8161
- return this.request(path22, {
8398
+ postForm(path23, form, opts) {
8399
+ return this.request(path23, {
8162
8400
  method: "POST",
8163
8401
  body: form
8164
8402
  }, opts);
8165
8403
  }
8166
- patch(path22, body, opts) {
8167
- return this.request(path22, {
8404
+ patch(path23, body, opts) {
8405
+ return this.request(path23, {
8168
8406
  method: "PATCH",
8169
8407
  body: body === void 0 ? void 0 : JSON.stringify(body)
8170
8408
  }, opts);
8171
8409
  }
8172
- put(path22, body, opts) {
8173
- return this.request(path22, {
8410
+ put(path23, body, opts) {
8411
+ return this.request(path23, {
8174
8412
  method: "PUT",
8175
8413
  body: body === void 0 ? void 0 : JSON.stringify(body)
8176
8414
  }, opts);
8177
8415
  }
8178
- delete(path22, opts) {
8179
- return this.request(path22, { method: "DELETE" }, opts);
8416
+ delete(path23, opts) {
8417
+ return this.request(path23, { method: "DELETE" }, opts);
8180
8418
  }
8181
8419
  setApiKey(apiKey) {
8182
8420
  this.apiKey = apiKey?.trim() || void 0;
8183
8421
  }
8184
- async request(path22, init, opts, hasRetriedAuth = false) {
8185
- const url = buildUrl(this.apiBase, path22);
8422
+ async request(path23, init, opts, hasRetriedAuth = false) {
8423
+ const url = buildUrl(this.apiBase, path23);
8186
8424
  const headers = {
8187
8425
  accept: "application/json",
8188
8426
  ...toStringRecord(init.headers)
@@ -8212,13 +8450,13 @@ var RudderApiClient = class {
8212
8450
  const apiError = await toApiError(response);
8213
8451
  if (!hasRetriedAuth && this.recoverAuth) {
8214
8452
  const recoveredToken = await this.recoverAuth({
8215
- path: path22,
8453
+ path: path23,
8216
8454
  method: String(init.method ?? "GET").toUpperCase(),
8217
8455
  error: apiError
8218
8456
  });
8219
8457
  if (recoveredToken) {
8220
8458
  this.setApiKey(recoveredToken);
8221
- return this.request(path22, init, opts, true);
8459
+ return this.request(path23, init, opts, true);
8222
8460
  }
8223
8461
  }
8224
8462
  throw apiError;
@@ -8237,8 +8475,8 @@ function shouldAttachAgentContext(method) {
8237
8475
  const normalized = String(method ?? "GET").toUpperCase();
8238
8476
  return normalized !== "GET" && normalized !== "HEAD";
8239
8477
  }
8240
- function buildUrl(apiBase, path22) {
8241
- const normalizedPath = path22.startsWith("/") ? path22 : `/${path22}`;
8478
+ function buildUrl(apiBase, path23) {
8479
+ const normalizedPath = path23.startsWith("/") ? path23 : `/${path23}`;
8242
8480
  const [pathname, query] = normalizedPath.split("?");
8243
8481
  const url = new URL2(apiBase);
8244
8482
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
@@ -8782,7 +9020,7 @@ function registerContextCommands(program) {
8782
9020
  }
8783
9021
 
8784
9022
  // src/commands/client/company.ts
8785
- import { mkdir as mkdir3, readdir as readdir3, readFile as readFile3, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
9023
+ import { mkdir as mkdir3, readdir as readdir3, readFile as readFile3, stat as stat3, writeFile as writeFile3 } from "node:fs/promises";
8786
9024
  import path15 from "node:path";
8787
9025
  import * as p15 from "@clack/prompts";
8788
9026
  import pc14 from "picocolors";
@@ -9009,13 +9247,13 @@ function buildImportSelectionCatalog(preview) {
9009
9247
  files: Array.from(organizationFiles).sort((left, right) => left.localeCompare(right))
9010
9248
  },
9011
9249
  projects: preview.manifest.projects.map((project) => {
9012
- const projectPath = normalizePortablePath(project.path);
9013
- const projectDir = projectPath.includes("/") ? projectPath.slice(0, projectPath.lastIndexOf("/")) : "";
9250
+ const projectPath2 = normalizePortablePath(project.path);
9251
+ const projectDir = projectPath2.includes("/") ? projectPath2.slice(0, projectPath2.lastIndexOf("/")) : "";
9014
9252
  return {
9015
9253
  key: project.slug,
9016
9254
  label: project.name,
9017
9255
  hint: project.slug,
9018
- files: collectEntityFiles(preview.files, projectPath, {
9256
+ files: collectEntityFiles(preview.files, projectPath2, {
9019
9257
  excludePrefixes: projectDir ? [`${projectDir}/issues`] : []
9020
9258
  })
9021
9259
  };
@@ -9517,7 +9755,7 @@ function normalizeGithubImportSource(input, refOverride) {
9517
9755
  }
9518
9756
  async function pathExists2(inputPath) {
9519
9757
  try {
9520
- await stat2(path15.resolve(inputPath));
9758
+ await stat3(path15.resolve(inputPath));
9521
9759
  return true;
9522
9760
  } catch {
9523
9761
  return false;
@@ -9540,7 +9778,7 @@ async function collectPackageFiles(root, current, files) {
9540
9778
  }
9541
9779
  async function resolveInlineSourceFromPath(inputPath) {
9542
9780
  const resolved = path15.resolve(inputPath);
9543
- const resolvedStat = await stat2(resolved);
9781
+ const resolvedStat = await stat3(resolved);
9544
9782
  if (resolvedStat.isFile() && path15.extname(resolved).toLowerCase() === ".zip") {
9545
9783
  const archive = await readZipArchive(await readFile3(resolved));
9546
9784
  const filteredFiles = Object.fromEntries(
@@ -9576,7 +9814,7 @@ async function writeExportToFolder(outDir, exported) {
9576
9814
  }
9577
9815
  async function confirmOverwriteExportDirectory(outDir) {
9578
9816
  const root = path15.resolve(outDir);
9579
- const stats = await stat2(root).catch(() => null);
9817
+ const stats = await stat3(root).catch(() => null);
9580
9818
  if (!stats) return;
9581
9819
  if (!stats.isDirectory()) {
9582
9820
  throw new Error(`Export output path ${root} exists and is not a directory.`);
@@ -10003,7 +10241,7 @@ ${organizationUrl}`);
10003
10241
 
10004
10242
  // src/commands/client/issue.ts
10005
10243
  init_dist();
10006
- import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
10244
+ import { readFile as readFile4, stat as stat4 } from "node:fs/promises";
10007
10245
  import path16 from "node:path";
10008
10246
 
10009
10247
  // src/agent-v1-registry.ts
@@ -10068,6 +10306,18 @@ var AGENT_CLI_CAPABILITIES = [
10068
10306
  requiresRunId: false,
10069
10307
  attachesRunIdWhenAvailable: false
10070
10308
  },
10309
+ {
10310
+ id: "agent.update",
10311
+ command: "rudder agent update [agent-id] [--title <title>] [--description <text>]",
10312
+ category: "agent",
10313
+ description: "Update an agent's control-plane identity fields; defaults to the authenticated agent.",
10314
+ mutating: true,
10315
+ contract: "agent-v1",
10316
+ requiresOrgId: false,
10317
+ requiresAgentId: false,
10318
+ requiresRunId: false,
10319
+ attachesRunIdWhenAvailable: true
10320
+ },
10071
10321
  {
10072
10322
  id: "agent.skills.create",
10073
10323
  command: "rudder agent skills create [agent-id] --name <name> [--enable]",
@@ -10360,9 +10610,9 @@ var AGENT_CLI_CAPABILITIES = [
10360
10610
  id: "issue.documents.put",
10361
10611
  command: "rudder issue documents put <issue> <key> --body-file <path>",
10362
10612
  category: "issue",
10363
- description: "Create or update an issue document.",
10613
+ description: "Legacy create or update of a DB-backed issue document; prefer `rudder library file put` for durable project files.",
10364
10614
  mutating: true,
10365
- contract: "agent-v1",
10615
+ contract: "compat",
10366
10616
  requiresOrgId: false,
10367
10617
  requiresAgentId: false,
10368
10618
  requiresRunId: false,
@@ -10380,6 +10630,90 @@ var AGENT_CLI_CAPABILITIES = [
10380
10630
  requiresRunId: false,
10381
10631
  attachesRunIdWhenAvailable: false
10382
10632
  },
10633
+ {
10634
+ id: "project.list",
10635
+ command: "rudder project list --org-id <id>",
10636
+ category: "project",
10637
+ description: "List projects in an organization.",
10638
+ mutating: false,
10639
+ contract: "agent-v1",
10640
+ requiresOrgId: true,
10641
+ requiresAgentId: false,
10642
+ requiresRunId: false,
10643
+ attachesRunIdWhenAvailable: false
10644
+ },
10645
+ {
10646
+ id: "project.get",
10647
+ command: "rudder project get <project-id-or-shortname> [--org-id <id>]",
10648
+ category: "project",
10649
+ description: "Read one project by ID or shortname.",
10650
+ mutating: false,
10651
+ contract: "agent-v1",
10652
+ requiresOrgId: false,
10653
+ requiresAgentId: false,
10654
+ requiresRunId: false,
10655
+ attachesRunIdWhenAvailable: false
10656
+ },
10657
+ {
10658
+ id: "project.create",
10659
+ command: "rudder project create --org-id <id> --name <name>",
10660
+ category: "project",
10661
+ description: "Create a project in the organization.",
10662
+ mutating: true,
10663
+ contract: "agent-v1",
10664
+ requiresOrgId: true,
10665
+ requiresAgentId: false,
10666
+ requiresRunId: false,
10667
+ attachesRunIdWhenAvailable: true
10668
+ },
10669
+ {
10670
+ id: "project.update",
10671
+ command: "rudder project update <project-id-or-shortname> [--org-id <id>]",
10672
+ category: "project",
10673
+ description: "Update mutable project fields such as name, description, status, goals, lead agent, target date, color, or archivedAt.",
10674
+ mutating: true,
10675
+ contract: "agent-v1",
10676
+ requiresOrgId: false,
10677
+ requiresAgentId: false,
10678
+ requiresRunId: false,
10679
+ attachesRunIdWhenAvailable: true
10680
+ },
10681
+ {
10682
+ id: "library.file.list",
10683
+ command: "rudder library file list [directory]",
10684
+ category: "library",
10685
+ description: "List path-based Library files and folders.",
10686
+ mutating: false,
10687
+ contract: "agent-v1",
10688
+ requiresOrgId: true,
10689
+ requiresAgentId: false,
10690
+ requiresRunId: false,
10691
+ attachesRunIdWhenAvailable: false
10692
+ },
10693
+ {
10694
+ id: "library.file.get",
10695
+ command: "rudder library file get <path>",
10696
+ category: "library",
10697
+ description: "Read one path-based Library file.",
10698
+ mutating: false,
10699
+ contract: "agent-v1",
10700
+ requiresOrgId: true,
10701
+ requiresAgentId: false,
10702
+ requiresRunId: false,
10703
+ attachesRunIdWhenAvailable: false
10704
+ },
10705
+ {
10706
+ id: "library.file.put",
10707
+ command: "rudder library file put <path> --body-file <path>",
10708
+ category: "library",
10709
+ description: "Create or update one path-based Library file.",
10710
+ mutating: true,
10711
+ contract: "agent-v1",
10712
+ requiresOrgId: true,
10713
+ requiresAgentId: false,
10714
+ requiresRunId: false,
10715
+ attachesRunIdWhenAvailable: true
10716
+ },
10383
10717
  {
10384
10718
  id: "issue.create",
10385
10719
  command: "rudder issue create --org-id <id> ... [--label-id <id> ...] [--label <name> ...]",
@@ -10540,8 +10874,10 @@ var AGENT_CLI_CAPABILITIES = [
10540
10874
  var CATEGORY_TITLES = {
10541
10875
  agent: "Agent",
10542
10876
  issue: "Issue",
10877
+ project: "Project",
10543
10878
  approval: "Approval",
10544
- skill: "Skill"
10879
+ skill: "Skill",
10880
+ library: "Library"
10545
10881
  };
10546
10882
  function getAgentCliCapabilities() {
10547
10883
  return AGENT_CLI_CAPABILITIES.map((entry) => ({ ...entry }));
@@ -11037,7 +11373,7 @@ ${imageBlock}` : imageBlock;
11037
11373
  }
11038
11374
  async function uploadIssueCommentImage(ctx, issue, imagePath) {
11039
11375
  const resolvedPath = path16.resolve(process.cwd(), imagePath);
11040
- const stats = await stat3(resolvedPath).catch((err) => {
11376
+ const stats = await stat4(resolvedPath).catch((err) => {
11041
11377
  throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
11042
11378
  });
11043
11379
  if (!stats.isFile()) {
@@ -11161,6 +11497,96 @@ function formatIssueSearchMatch(match) {
11161
11497
  return `${match.field}${commentSuffix}: ${match.snippet}`;
11162
11498
  }
11163
11499
 
11500
+ // src/commands/client/project.ts
11501
+ init_dist();
11502
+ function registerProjectCommands(program) {
11503
+ const project = program.command("project").description("Project operations");
11504
+ addCommonClientOptions(
11505
+ project.command("list").description(getAgentCliCapabilityById("project.list").description).option("-O, --org-id <id>", "Organization ID").action(async (opts) => {
11506
+ try {
11507
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
11508
+ const rows = await ctx.api.get(`/api/orgs/${ctx.orgId}/projects`) ?? [];
11509
+ printOutput(rows, { json: ctx.json });
11510
+ } catch (err) {
11511
+ handleCommandError(err);
11512
+ }
11513
+ }),
11514
+ { includeCompany: false }
11515
+ );
11516
+ addCommonClientOptions(
11517
+ 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) => {
11518
+ try {
11519
+ const ctx = resolveCommandContext(opts);
11520
+ const row = await ctx.api.get(projectPath(projectRef, ctx.orgId));
11521
+ printOutput(row, { json: ctx.json });
11522
+ } catch (err) {
11523
+ handleCommandError(err);
11524
+ }
11525
+ }),
11526
+ { includeCompany: false }
11527
+ );
11528
+ addCommonClientOptions(
11529
+ 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) => {
11530
+ try {
11531
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
11532
+ const payload = createProjectSchema.parse({
11533
+ name: opts.name,
11534
+ description: opts.description,
11535
+ status: opts.status,
11536
+ goalId: opts.goalId,
11537
+ goalIds: parseCsv2(opts.goalIds),
11538
+ leadAgentId: opts.leadAgentId,
11539
+ targetDate: opts.targetDate,
11540
+ color: opts.color
11541
+ });
11542
+ const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/projects`, payload);
11543
+ printOutput(created, { json: ctx.json });
11544
+ } catch (err) {
11545
+ handleCommandError(err);
11546
+ }
11547
+ }),
11548
+ { includeCompany: false }
11549
+ );
11550
+ addCommonClientOptions(
11551
+ 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) => {
11552
+ try {
11553
+ const ctx = resolveCommandContext(opts);
11554
+ const payload = updateProjectSchema.parse({
11555
+ name: opts.name,
11556
+ description: opts.description,
11557
+ status: opts.status,
11558
+ goalId: opts.goalId,
11559
+ goalIds: parseCsv2(opts.goalIds),
11560
+ leadAgentId: opts.leadAgentId,
11561
+ targetDate: opts.targetDate,
11562
+ color: opts.color,
11563
+ archivedAt: parseNullableOption(opts.archivedAt)
11564
+ });
11565
+ const updated = await ctx.api.patch(projectPath(projectRef, ctx.orgId), payload);
11566
+ printOutput(updated, { json: ctx.json });
11567
+ } catch (err) {
11568
+ handleCommandError(err);
11569
+ }
11570
+ }),
11571
+ { includeCompany: false }
11572
+ );
11573
+ }
11574
+ function parseCsv2(value) {
11575
+ if (!value) return void 0;
11576
+ const items = value.split(",").map((item) => item.trim()).filter(Boolean);
11577
+ return items.length > 0 ? items : void 0;
11578
+ }
11579
+ function parseNullableOption(value) {
11580
+ if (value === void 0) return void 0;
11581
+ return value === "null" ? null : value;
11582
+ }
11583
+ function projectPath(projectRef, orgId) {
11584
+ const params = new URLSearchParams();
11585
+ if (orgId) params.set("orgId", orgId);
11586
+ const query = params.toString();
11587
+ return `/api/projects/${encodeURIComponent(projectRef)}${query ? `?${query}` : ""}`;
11588
+ }
11589
+
11164
11590
  // src/commands/client/agent.ts
11165
11591
  init_dist();
11166
11592
 
@@ -11194,12 +11620,12 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
11194
11620
  "- Personal skills live under `$AGENT_HOME/skills`.",
11195
11621
  "- Shared organization workspace root lives under `$RUDDER_ORG_WORKSPACE_ROOT`.",
11196
11622
  "- Shared organization skills live under `$RUDDER_ORG_SKILLS_DIR`.",
11197
- "- Shared organization plans live under `$RUDDER_ORG_PLANS_DIR`.",
11198
- "- Shared organization artifacts live under `$RUDDER_ORG_ARTIFACTS_DIR`.",
11199
- "- Durable generated outputs such as screenshots, images, mockups, reports, CSVs, handoff logs, and other user-visible files should be written under `$RUDDER_ORG_ARTIFACTS_DIR` when available.",
11200
- "- Use `/tmp` only for transient scratch files and temporary verification artifacts; do not put durable work product there.",
11623
+ '- Library-backed project resources use `sourceType: "library"`; their `locator` points into `library:projects/<project-name>/`.',
11624
+ "- 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.",
11625
+ "- Durable generated project work files should be written under `library:projects/<project-name>/`.",
11626
+ "- 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.",
11627
+ "- Use `/tmp` only for transient scratch files and temporary verification files; do not put durable work product there.",
11201
11628
  "- 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.",
11202
- "- Durable shared work output should prefer these managed workspace paths instead of ad-hoc top-level `projects/` folders.",
11203
11629
  "",
11204
11630
  "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.",
11205
11631
  "",
@@ -11209,9 +11635,9 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
11209
11635
  "",
11210
11636
  "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.",
11211
11637
  "",
11212
- "## Memory and Planning",
11638
+ "## Memory and Shared Work Notes",
11213
11639
  "",
11214
- "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 plans. 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/planning conventions.",
11640
+ "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.",
11215
11641
  "",
11216
11642
  "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.",
11217
11643
  "",
@@ -11610,7 +12036,7 @@ function registerAgentCommands(program) {
11610
12036
  try {
11611
12037
  const ctx = resolveCommandContext(opts);
11612
12038
  const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/sync`, {
11613
- desiredSkills: parseCsv2(opts.desiredSkills)
12039
+ desiredSkills: parseCsv3(opts.desiredSkills)
11614
12040
  });
11615
12041
  printOutput(snapshot, { json: ctx.json });
11616
12042
  } catch (err) {
@@ -11633,6 +12059,32 @@ function registerAgentCommands(program) {
11633
12059
  }
11634
12060
  })
11635
12061
  );
12062
+ addCommonClientOptions(
12063
+ 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) => {
12064
+ try {
12065
+ const ctx = resolveCommandContext(opts);
12066
+ const agentId = agentIdArg?.trim() || ctx.agentId;
12067
+ if (!agentId) {
12068
+ throw new Error("Agent ID is required. Pass [agent-id] or set RUDDER_AGENT_ID.");
12069
+ }
12070
+ const patch = await buildAgentUpdatePatch(opts);
12071
+ if (Object.keys(patch).length === 0) {
12072
+ throw new Error(
12073
+ "No agent fields to update. Pass --name, --role, --title, --capabilities, --description, or --reports-to."
12074
+ );
12075
+ }
12076
+ const query = new URLSearchParams();
12077
+ if (ctx.orgId) query.set("orgId", ctx.orgId);
12078
+ const updated = await ctx.api.patch(
12079
+ `/api/agents/${encodeURIComponent(agentId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
12080
+ patch
12081
+ );
12082
+ printOutput(updated, { json: ctx.json });
12083
+ } catch (err) {
12084
+ handleCommandError(err);
12085
+ }
12086
+ })
12087
+ );
11636
12088
  addCommonClientOptions(
11637
12089
  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) => {
11638
12090
  try {
@@ -11732,7 +12184,47 @@ function registerAgentCommands(program) {
11732
12184
  { includeCompany: false }
11733
12185
  );
11734
12186
  }
11735
- function parseCsv2(value) {
12187
+ async function buildAgentUpdatePatch(opts) {
12188
+ const rawPatch = {};
12189
+ if (opts.name !== void 0) rawPatch.name = opts.name;
12190
+ if (opts.role !== void 0) rawPatch.role = opts.role;
12191
+ if (opts.title !== void 0 && opts.clearTitle) {
12192
+ throw new Error("Pass only one of --title or --clear-title.");
12193
+ }
12194
+ if (opts.title !== void 0) rawPatch.title = opts.title;
12195
+ if (opts.clearTitle) rawPatch.title = null;
12196
+ if (opts.reportsTo !== void 0 && opts.clearReportsTo) {
12197
+ throw new Error("Pass only one of --reports-to or --clear-reports-to.");
12198
+ }
12199
+ if (opts.reportsTo !== void 0) rawPatch.reportsTo = opts.reportsTo;
12200
+ if (opts.clearReportsTo) rawPatch.reportsTo = null;
12201
+ const capabilitiesInputs = [
12202
+ opts.capabilities !== void 0 ? "--capabilities" : null,
12203
+ opts.capabilitiesFile !== void 0 ? "--capabilities-file" : null,
12204
+ opts.description !== void 0 ? "--description" : null,
12205
+ opts.descriptionFile !== void 0 ? "--description-file" : null
12206
+ ].filter(Boolean);
12207
+ const clearCapabilities = opts.clearCapabilities || opts.clearDescription;
12208
+ if (capabilitiesInputs.length > 1) {
12209
+ throw new Error(
12210
+ "Pass only one of --capabilities, --capabilities-file, --description, or --description-file."
12211
+ );
12212
+ }
12213
+ if (capabilitiesInputs.length > 0 && clearCapabilities) {
12214
+ throw new Error("Pass either capabilities/description input or a clear flag, not both.");
12215
+ }
12216
+ if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
12217
+ if (opts.description !== void 0) rawPatch.capabilities = opts.description;
12218
+ if (opts.capabilitiesFile !== void 0) {
12219
+ rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.capabilitiesFile), "utf8");
12220
+ }
12221
+ if (opts.descriptionFile !== void 0) {
12222
+ rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.descriptionFile), "utf8");
12223
+ }
12224
+ if (clearCapabilities) rawPatch.capabilities = null;
12225
+ return updateAgentSchema.parse(rawPatch);
12226
+ }
12227
+ function parseCsv3(value) {
11736
12228
  if (!value) return [];
11737
12229
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
11738
12230
  }
@@ -11818,7 +12310,7 @@ function registerApprovalCommands(program) {
11818
12310
  type: opts.type,
11819
12311
  payload: payloadJson,
11820
12312
  requestedByAgentId: opts.requestedByAgentId,
11821
- issueIds: parseCsv3(opts.issueIds)
12313
+ issueIds: parseCsv4(opts.issueIds)
11822
12314
  });
11823
12315
  const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/approvals`, payload);
11824
12316
  printOutput(created, { json: ctx.json });
@@ -11924,7 +12416,7 @@ async function readStdinText2() {
11924
12416
  }
11925
12417
  return Buffer.concat(chunks).toString("utf8");
11926
12418
  }
11927
- function parseCsv3(value) {
12419
+ function parseCsv4(value) {
11928
12420
  if (!value) return void 0;
11929
12421
  const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
11930
12422
  return rows.length > 0 ? rows : void 0;
@@ -11953,8 +12445,8 @@ function registerActivityCommands(program) {
11953
12445
  if (opts.entityType) params.set("entityType", opts.entityType);
11954
12446
  if (opts.entityId) params.set("entityId", opts.entityId);
11955
12447
  const query = params.toString();
11956
- const path22 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
11957
- const rows = await ctx.api.get(path22) ?? [];
12448
+ const path23 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
12449
+ const rows = await ctx.api.get(path23) ?? [];
11958
12450
  if (ctx.json) {
11959
12451
  printOutput(rows, { json: true });
11960
12452
  return;
@@ -12082,7 +12574,7 @@ function registerSkillCommands(program) {
12082
12574
  try {
12083
12575
  const ctx = resolveCommandContext(opts, { requireCompany: true });
12084
12576
  const payload = organizationSkillLocalScanRequestSchema.parse({
12085
- roots: parseCsv4(opts.roots)
12577
+ roots: parseCsv5(opts.roots)
12086
12578
  });
12087
12579
  const result = await ctx.api.post(
12088
12580
  `/api/orgs/${ctx.orgId}/skills/scan-local`,
@@ -12100,8 +12592,8 @@ function registerSkillCommands(program) {
12100
12592
  try {
12101
12593
  const ctx = resolveCommandContext(opts, { requireCompany: true });
12102
12594
  const payload = organizationSkillProjectScanRequestSchema.parse({
12103
- projectIds: parseCsv4(opts.projectIds),
12104
- workspaceIds: parseCsv4(opts.workspaceIds)
12595
+ projectIds: parseCsv5(opts.projectIds),
12596
+ workspaceIds: parseCsv5(opts.workspaceIds)
12105
12597
  });
12106
12598
  const result = await ctx.api.post(
12107
12599
  `/api/orgs/${ctx.orgId}/skills/scan-projects`,
@@ -12115,19 +12607,111 @@ function registerSkillCommands(program) {
12115
12607
  { includeCompany: false }
12116
12608
  );
12117
12609
  }
12118
- function parseCsv4(value) {
12610
+ function parseCsv5(value) {
12119
12611
  if (!value) return void 0;
12120
12612
  const rows = value.split(",").map((entry) => entry.trim()).filter(Boolean);
12121
12613
  return rows.length > 0 ? rows : void 0;
12122
12614
  }
12123
12615
 
12616
+ // src/commands/client/library.ts
12617
+ import { readFile as readFile6 } from "node:fs/promises";
12618
+ import path20 from "node:path";
12619
+ function registerLibraryCommands(program) {
12620
+ const library = program.command("library").description("Library file operations");
12621
+ const file = library.command("file").description("Path-based Library file operations");
12622
+ addCommonClientOptions(
12623
+ file.command("list").description(getAgentCliCapabilityById("library.file.list").description).argument("[directoryPath]", "Library directory path", "projects").action(async (directoryPath, opts) => {
12624
+ try {
12625
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12626
+ const search = new URLSearchParams();
12627
+ const normalizedPath = directoryPath.trim();
12628
+ if (normalizedPath) search.set("path", normalizedPath);
12629
+ const query = search.toString();
12630
+ const result = await ctx.api.get(
12631
+ `/api/orgs/${ctx.orgId}/workspace/files${query ? `?${query}` : ""}`
12632
+ );
12633
+ printOutput(result, { json: ctx.json });
12634
+ } catch (err) {
12635
+ handleCommandError(err);
12636
+ }
12637
+ }),
12638
+ { includeCompany: true }
12639
+ );
12640
+ addCommonClientOptions(
12641
+ file.command("get").description(getAgentCliCapabilityById("library.file.get").description).argument("<filePath>", "Library file path").action(async (filePath, opts) => {
12642
+ try {
12643
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12644
+ const search = new URLSearchParams();
12645
+ search.set("path", filePath.trim());
12646
+ const result = await ctx.api.get(
12647
+ `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`
12648
+ );
12649
+ printOutput(result, { json: ctx.json });
12650
+ } catch (err) {
12651
+ handleCommandError(err);
12652
+ }
12653
+ }),
12654
+ { includeCompany: true }
12655
+ );
12656
+ addCommonClientOptions(
12657
+ 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) => {
12658
+ try {
12659
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12660
+ const body = await resolveBodyFileInput(opts.bodyFile);
12661
+ const search = new URLSearchParams();
12662
+ search.set("path", filePath.trim());
12663
+ const updatePath = `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`;
12664
+ const updated = await ctx.api.patch(
12665
+ updatePath,
12666
+ { content: body },
12667
+ { ignoreNotFound: true }
12668
+ );
12669
+ if (updated) {
12670
+ printOutput(updated, { json: ctx.json });
12671
+ return;
12672
+ }
12673
+ const created = await ctx.api.post(
12674
+ `/api/orgs/${ctx.orgId}/workspace/file`,
12675
+ { filePath: filePath.trim(), content: body }
12676
+ );
12677
+ printOutput(created, { json: ctx.json });
12678
+ } catch (err) {
12679
+ handleCommandError(err);
12680
+ }
12681
+ }),
12682
+ { includeCompany: true }
12683
+ );
12684
+ }
12685
+ async function resolveBodyFileInput(inputPath) {
12686
+ if (process.argv.includes("--body")) {
12687
+ throw new Error("--body was removed; write the body to a file and use --body-file <path> or --body-file - for stdin");
12688
+ }
12689
+ if (inputPath === void 0) {
12690
+ throw new Error("Provide --body-file <path>; use --body-file - for stdin");
12691
+ }
12692
+ if (inputPath === "-") {
12693
+ return readStdinText3();
12694
+ }
12695
+ const resolvedPath = path20.resolve(process.cwd(), inputPath);
12696
+ return readFile6(resolvedPath, "utf8").catch((err) => {
12697
+ throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
12698
+ });
12699
+ }
12700
+ async function readStdinText3() {
12701
+ const chunks = [];
12702
+ for await (const chunk of process.stdin) {
12703
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
12704
+ }
12705
+ return Buffer.concat(chunks).toString("utf8");
12706
+ }
12707
+
12124
12708
  // src/config/data-dir.ts
12125
12709
  init_home();
12126
- import path20 from "node:path";
12710
+ import path21 from "node:path";
12127
12711
  function applyDataDirOverride(options, support = {}) {
12128
12712
  const rawDataDir = options.dataDir?.trim();
12129
12713
  if (!rawDataDir) return null;
12130
- const resolvedDataDir = path20.resolve(expandHomePrefix(rawDataDir));
12714
+ const resolvedDataDir = path21.resolve(expandHomePrefix(rawDataDir));
12131
12715
  process.env.RUDDER_HOME = resolvedDataDir;
12132
12716
  if (support.hasConfigOption) {
12133
12717
  const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
@@ -12151,16 +12735,16 @@ init_env();
12151
12735
  init_local_env();
12152
12736
 
12153
12737
  // src/commands/client/plugin.ts
12154
- import path21 from "node:path";
12738
+ import path22 from "node:path";
12155
12739
  import pc15 from "picocolors";
12156
12740
  function resolvePackageArg(packageArg, isLocal) {
12157
12741
  if (!isLocal) return packageArg;
12158
- if (path21.isAbsolute(packageArg)) return packageArg;
12742
+ if (path22.isAbsolute(packageArg)) return packageArg;
12159
12743
  if (packageArg.startsWith("~")) {
12160
12744
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
12161
- return path21.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12745
+ return path22.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12162
12746
  }
12163
- return path21.resolve(process.cwd(), packageArg);
12747
+ return path22.resolve(process.cwd(), packageArg);
12164
12748
  }
12165
12749
  function formatPlugin(p16) {
12166
12750
  const statusColor = p16.status === "ready" ? pc15.green(p16.status) : p16.status === "error" ? pc15.red(p16.status) : p16.status === "disabled" ? pc15.dim(p16.status) : pc15.yellow(p16.status);
@@ -12494,11 +13078,13 @@ function createProgram() {
12494
13078
  registerContextCommands(program);
12495
13079
  registerCompanyCommands(program);
12496
13080
  registerIssueCommands(program);
13081
+ registerProjectCommands(program);
12497
13082
  registerAgentCommands(program);
12498
13083
  registerApprovalCommands(program);
12499
13084
  registerActivityCommands(program);
12500
13085
  registerDashboardCommands(program);
12501
13086
  registerSkillCommands(program);
13087
+ registerLibraryCommands(program);
12502
13088
  registerLazyWorktreeCommands(program);
12503
13089
  registerPluginCommands(program);
12504
13090
  registerLazyBenchmarkCommands(program);