@rudderhq/cli 0.2.10-canary.3 → 0.2.10-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 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),
@@ -877,6 +934,7 @@ var init_chat = __esm({
877
934
  chatIssueProposalSchema = z8.object({
878
935
  title: z8.string().trim().min(1).max(200),
879
936
  description: z8.string().trim().min(1).max(2e4),
937
+ status: z8.enum(ISSUE_STATUSES).optional().default("todo"),
880
938
  priority: z8.enum(["critical", "high", "medium", "low"]).optional().default("medium"),
881
939
  projectId: z8.string().uuid().optional().nullable(),
882
940
  goalId: z8.string().uuid().optional().nullable(),
@@ -1588,7 +1646,7 @@ var init_project = __esm({
1588
1646
 
1589
1647
  // ../packages/shared/dist/validators/issue.js
1590
1648
  import { z as z14 } from "zod";
1591
- 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;
1592
1650
  var init_issue = __esm({
1593
1651
  "../packages/shared/dist/validators/issue.js"() {
1594
1652
  "use strict";
@@ -1697,6 +1755,22 @@ var init_issue = __esm({
1697
1755
  changeSummary: z14.string().trim().max(500).nullable().optional(),
1698
1756
  baseRevisionId: z14.string().uuid().nullable().optional()
1699
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
+ });
1700
1774
  }
1701
1775
  });
1702
1776
 
@@ -2627,12 +2701,16 @@ var init_organization_skill_reference = __esm({
2627
2701
  });
2628
2702
 
2629
2703
  // ../packages/shared/dist/project-mentions.js
2630
- 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;
2631
2705
  var init_project_mentions = __esm({
2632
2706
  "../packages/shared/dist/project-mentions.js"() {
2633
2707
  "use strict";
2634
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");
2635
2712
  PROJECT_COLOR_VALUES = new Set(PROJECT_COLORS);
2713
+ AGENT_AVATAR_BACKGROUND_VALUES = new Set(AGENT_AVATAR_BACKGROUND_PRESET_IDS);
2636
2714
  }
2637
2715
  });
2638
2716
 
@@ -4214,10 +4292,10 @@ var init_install = __esm({
4214
4292
  init_home();
4215
4293
  RUNTIME_NPM_PACKAGE_NAME = "@rudderhq/server";
4216
4294
  RUNTIME_METADATA_FILE = "runtime.json";
4217
- DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 5;
4295
+ DEFAULT_RUNTIME_CACHE_MAX_ENTRIES = 2;
4218
4296
  DEFAULT_RUNTIME_CACHE_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
4219
4297
  DEFAULT_RUNTIME_CACHE_MAX_BYTES = 2 * 1024 * 1024 * 1024;
4220
- DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 1;
4298
+ DEFAULT_RUNTIME_CACHE_KEEP_PREVIOUS = 0;
4221
4299
  RUNTIME_NPM_INSTALL_FLAGS = ["--omit=dev", "--include=optional", "--no-audit", "--no-fund"];
4222
4300
  RuntimeInstallError = class extends Error {
4223
4301
  cacheDir;
@@ -6469,7 +6547,7 @@ init_install();
6469
6547
  import { spawn, spawnSync as spawnSync3 } from "node:child_process";
6470
6548
  import { createHash } from "node:crypto";
6471
6549
  import { constants as fsConstants, createWriteStream, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
6472
- 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";
6473
6551
  import { homedir, tmpdir } from "node:os";
6474
6552
  import path11 from "node:path";
6475
6553
  import { Readable, Transform } from "node:stream";
@@ -6600,6 +6678,10 @@ var DESKTOP_METADATA_FILE = ".rudder-desktop-install.json";
6600
6678
  var DESKTOP_CHECKSUM_ASSET_NAME = "SHASUMS256.txt";
6601
6679
  var DESKTOP_ASSET_CACHE_DIR = "desktop-assets";
6602
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;
6603
6685
  function normalizeProgressTotal(totalBytes) {
6604
6686
  return typeof totalBytes === "number" && Number.isFinite(totalBytes) && totalBytes > 0 ? totalBytes : null;
6605
6687
  }
@@ -7064,12 +7146,158 @@ function resolveDesktopAssetCacheDir(assetChecksum, homeDir = resolveRudderHomeD
7064
7146
  function resolveDesktopCachedAssetPath(assetName, assetChecksum, homeDir = resolveRudderHomeDir()) {
7065
7147
  return path11.join(resolveDesktopAssetCacheDir(assetChecksum, homeDir), path11.basename(assetName));
7066
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
+ }
7067
7294
  async function downloadDesktopAssetWithCache(asset, expectedChecksum, options = {}) {
7068
7295
  const normalizedChecksum = normalizeDesktopAssetChecksum(expectedChecksum);
7069
7296
  const cachePath = resolveDesktopCachedAssetPath(asset.name, normalizedChecksum, options.homeDir);
7070
7297
  if (await pathExists(cachePath)) {
7071
7298
  try {
7072
7299
  const checksum = assertChecksumMatch(cachePath, normalizedChecksum);
7300
+ await touchDesktopCachedAsset(cachePath);
7073
7301
  return { path: cachePath, checksum, cacheStatus: "hit" };
7074
7302
  } catch {
7075
7303
  await rm2(cachePath, { force: true });
@@ -7676,6 +7904,17 @@ async function startCommand(opts) {
7676
7904
  );
7677
7905
  await writeInstallMetadata(installPaths, releaseTag, selectedAsset.name, checksum, selectedAssetKind);
7678
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
+ }
7679
7918
  if (opts.open !== false) {
7680
7919
  await runStartPhase(
7681
7920
  "Launching Rudder Desktop...",
@@ -8147,41 +8386,41 @@ var RudderApiClient = class {
8147
8386
  this.runId = opts.runId?.trim() || void 0;
8148
8387
  this.recoverAuth = opts.recoverAuth;
8149
8388
  }
8150
- get(path22, opts) {
8151
- return this.request(path22, { method: "GET" }, opts);
8389
+ get(path23, opts) {
8390
+ return this.request(path23, { method: "GET" }, opts);
8152
8391
  }
8153
- post(path22, body, opts) {
8154
- return this.request(path22, {
8392
+ post(path23, body, opts) {
8393
+ return this.request(path23, {
8155
8394
  method: "POST",
8156
8395
  body: body === void 0 ? void 0 : JSON.stringify(body)
8157
8396
  }, opts);
8158
8397
  }
8159
- postForm(path22, form, opts) {
8160
- return this.request(path22, {
8398
+ postForm(path23, form, opts) {
8399
+ return this.request(path23, {
8161
8400
  method: "POST",
8162
8401
  body: form
8163
8402
  }, opts);
8164
8403
  }
8165
- patch(path22, body, opts) {
8166
- return this.request(path22, {
8404
+ patch(path23, body, opts) {
8405
+ return this.request(path23, {
8167
8406
  method: "PATCH",
8168
8407
  body: body === void 0 ? void 0 : JSON.stringify(body)
8169
8408
  }, opts);
8170
8409
  }
8171
- put(path22, body, opts) {
8172
- return this.request(path22, {
8410
+ put(path23, body, opts) {
8411
+ return this.request(path23, {
8173
8412
  method: "PUT",
8174
8413
  body: body === void 0 ? void 0 : JSON.stringify(body)
8175
8414
  }, opts);
8176
8415
  }
8177
- delete(path22, opts) {
8178
- return this.request(path22, { method: "DELETE" }, opts);
8416
+ delete(path23, opts) {
8417
+ return this.request(path23, { method: "DELETE" }, opts);
8179
8418
  }
8180
8419
  setApiKey(apiKey) {
8181
8420
  this.apiKey = apiKey?.trim() || void 0;
8182
8421
  }
8183
- async request(path22, init, opts, hasRetriedAuth = false) {
8184
- const url = buildUrl(this.apiBase, path22);
8422
+ async request(path23, init, opts, hasRetriedAuth = false) {
8423
+ const url = buildUrl(this.apiBase, path23);
8185
8424
  const headers = {
8186
8425
  accept: "application/json",
8187
8426
  ...toStringRecord(init.headers)
@@ -8211,13 +8450,13 @@ var RudderApiClient = class {
8211
8450
  const apiError = await toApiError(response);
8212
8451
  if (!hasRetriedAuth && this.recoverAuth) {
8213
8452
  const recoveredToken = await this.recoverAuth({
8214
- path: path22,
8453
+ path: path23,
8215
8454
  method: String(init.method ?? "GET").toUpperCase(),
8216
8455
  error: apiError
8217
8456
  });
8218
8457
  if (recoveredToken) {
8219
8458
  this.setApiKey(recoveredToken);
8220
- return this.request(path22, init, opts, true);
8459
+ return this.request(path23, init, opts, true);
8221
8460
  }
8222
8461
  }
8223
8462
  throw apiError;
@@ -8236,8 +8475,8 @@ function shouldAttachAgentContext(method) {
8236
8475
  const normalized = String(method ?? "GET").toUpperCase();
8237
8476
  return normalized !== "GET" && normalized !== "HEAD";
8238
8477
  }
8239
- function buildUrl(apiBase, path22) {
8240
- const normalizedPath = path22.startsWith("/") ? path22 : `/${path22}`;
8478
+ function buildUrl(apiBase, path23) {
8479
+ const normalizedPath = path23.startsWith("/") ? path23 : `/${path23}`;
8241
8480
  const [pathname, query] = normalizedPath.split("?");
8242
8481
  const url = new URL2(apiBase);
8243
8482
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${pathname}`;
@@ -8781,7 +9020,7 @@ function registerContextCommands(program) {
8781
9020
  }
8782
9021
 
8783
9022
  // src/commands/client/company.ts
8784
- 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";
8785
9024
  import path15 from "node:path";
8786
9025
  import * as p15 from "@clack/prompts";
8787
9026
  import pc14 from "picocolors";
@@ -9008,13 +9247,13 @@ function buildImportSelectionCatalog(preview) {
9008
9247
  files: Array.from(organizationFiles).sort((left, right) => left.localeCompare(right))
9009
9248
  },
9010
9249
  projects: preview.manifest.projects.map((project) => {
9011
- const projectPath = normalizePortablePath(project.path);
9012
- 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("/")) : "";
9013
9252
  return {
9014
9253
  key: project.slug,
9015
9254
  label: project.name,
9016
9255
  hint: project.slug,
9017
- files: collectEntityFiles(preview.files, projectPath, {
9256
+ files: collectEntityFiles(preview.files, projectPath2, {
9018
9257
  excludePrefixes: projectDir ? [`${projectDir}/issues`] : []
9019
9258
  })
9020
9259
  };
@@ -9516,7 +9755,7 @@ function normalizeGithubImportSource(input, refOverride) {
9516
9755
  }
9517
9756
  async function pathExists2(inputPath) {
9518
9757
  try {
9519
- await stat2(path15.resolve(inputPath));
9758
+ await stat3(path15.resolve(inputPath));
9520
9759
  return true;
9521
9760
  } catch {
9522
9761
  return false;
@@ -9539,7 +9778,7 @@ async function collectPackageFiles(root, current, files) {
9539
9778
  }
9540
9779
  async function resolveInlineSourceFromPath(inputPath) {
9541
9780
  const resolved = path15.resolve(inputPath);
9542
- const resolvedStat = await stat2(resolved);
9781
+ const resolvedStat = await stat3(resolved);
9543
9782
  if (resolvedStat.isFile() && path15.extname(resolved).toLowerCase() === ".zip") {
9544
9783
  const archive = await readZipArchive(await readFile3(resolved));
9545
9784
  const filteredFiles = Object.fromEntries(
@@ -9575,7 +9814,7 @@ async function writeExportToFolder(outDir, exported) {
9575
9814
  }
9576
9815
  async function confirmOverwriteExportDirectory(outDir) {
9577
9816
  const root = path15.resolve(outDir);
9578
- const stats = await stat2(root).catch(() => null);
9817
+ const stats = await stat3(root).catch(() => null);
9579
9818
  if (!stats) return;
9580
9819
  if (!stats.isDirectory()) {
9581
9820
  throw new Error(`Export output path ${root} exists and is not a directory.`);
@@ -10002,7 +10241,7 @@ ${organizationUrl}`);
10002
10241
 
10003
10242
  // src/commands/client/issue.ts
10004
10243
  init_dist();
10005
- import { readFile as readFile4, stat as stat3 } from "node:fs/promises";
10244
+ import { readFile as readFile4, stat as stat4 } from "node:fs/promises";
10006
10245
  import path16 from "node:path";
10007
10246
 
10008
10247
  // src/agent-v1-registry.ts
@@ -10067,6 +10306,18 @@ var AGENT_CLI_CAPABILITIES = [
10067
10306
  requiresRunId: false,
10068
10307
  attachesRunIdWhenAvailable: false
10069
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
+ },
10070
10321
  {
10071
10322
  id: "agent.skills.create",
10072
10323
  command: "rudder agent skills create [agent-id] --name <name> [--enable]",
@@ -10359,9 +10610,9 @@ var AGENT_CLI_CAPABILITIES = [
10359
10610
  id: "issue.documents.put",
10360
10611
  command: "rudder issue documents put <issue> <key> --body-file <path>",
10361
10612
  category: "issue",
10362
- 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.",
10363
10614
  mutating: true,
10364
- contract: "agent-v1",
10615
+ contract: "compat",
10365
10616
  requiresOrgId: false,
10366
10617
  requiresAgentId: false,
10367
10618
  requiresRunId: false,
@@ -10379,6 +10630,90 @@ var AGENT_CLI_CAPABILITIES = [
10379
10630
  requiresRunId: false,
10380
10631
  attachesRunIdWhenAvailable: false
10381
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
+ },
10382
10717
  {
10383
10718
  id: "issue.create",
10384
10719
  command: "rudder issue create --org-id <id> ... [--label-id <id> ...] [--label <name> ...]",
@@ -10539,8 +10874,10 @@ var AGENT_CLI_CAPABILITIES = [
10539
10874
  var CATEGORY_TITLES = {
10540
10875
  agent: "Agent",
10541
10876
  issue: "Issue",
10877
+ project: "Project",
10542
10878
  approval: "Approval",
10543
- skill: "Skill"
10879
+ skill: "Skill",
10880
+ library: "Library"
10544
10881
  };
10545
10882
  function getAgentCliCapabilities() {
10546
10883
  return AGENT_CLI_CAPABILITIES.map((entry) => ({ ...entry }));
@@ -11036,7 +11373,7 @@ ${imageBlock}` : imageBlock;
11036
11373
  }
11037
11374
  async function uploadIssueCommentImage(ctx, issue, imagePath) {
11038
11375
  const resolvedPath = path16.resolve(process.cwd(), imagePath);
11039
- const stats = await stat3(resolvedPath).catch((err) => {
11376
+ const stats = await stat4(resolvedPath).catch((err) => {
11040
11377
  throw new Error(`Unable to read image ${imagePath}: ${err instanceof Error ? err.message : String(err)}`);
11041
11378
  });
11042
11379
  if (!stats.isFile()) {
@@ -11160,6 +11497,96 @@ function formatIssueSearchMatch(match) {
11160
11497
  return `${match.field}${commentSuffix}: ${match.snippet}`;
11161
11498
  }
11162
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
+
11163
11590
  // src/commands/client/agent.ts
11164
11591
  init_dist();
11165
11592
 
@@ -11193,12 +11620,11 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
11193
11620
  "- Personal skills live under `$AGENT_HOME/skills`.",
11194
11621
  "- Shared organization workspace root lives under `$RUDDER_ORG_WORKSPACE_ROOT`.",
11195
11622
  "- Shared organization skills live under `$RUDDER_ORG_SKILLS_DIR`.",
11196
- "- Shared organization plans live under `$RUDDER_ORG_PLANS_DIR`.",
11197
- "- Shared organization artifacts live under `$RUDDER_ORG_ARTIFACTS_DIR`.",
11198
- "- 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.",
11199
- "- 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
+ "- Use `/tmp` only for transient scratch files and temporary verification files; do not put durable work product there.",
11200
11627
  "- 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.",
11201
- "- Durable shared work output should prefer these managed workspace paths instead of ad-hoc top-level `projects/` folders.",
11202
11628
  "",
11203
11629
  "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.",
11204
11630
  "",
@@ -11208,9 +11634,9 @@ var RUDDER_AGENT_OPERATING_CONTRACT = [
11208
11634
  "",
11209
11635
  "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.",
11210
11636
  "",
11211
- "## Memory and Planning",
11637
+ "## Memory and Shared Work Notes",
11212
11638
  "",
11213
- "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.",
11639
+ "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.",
11214
11640
  "",
11215
11641
  "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.",
11216
11642
  "",
@@ -11609,7 +12035,7 @@ function registerAgentCommands(program) {
11609
12035
  try {
11610
12036
  const ctx = resolveCommandContext(opts);
11611
12037
  const snapshot = await ctx.api.post(`/api/agents/${agentId}/skills/sync`, {
11612
- desiredSkills: parseCsv2(opts.desiredSkills)
12038
+ desiredSkills: parseCsv3(opts.desiredSkills)
11613
12039
  });
11614
12040
  printOutput(snapshot, { json: ctx.json });
11615
12041
  } catch (err) {
@@ -11632,6 +12058,32 @@ function registerAgentCommands(program) {
11632
12058
  }
11633
12059
  })
11634
12060
  );
12061
+ addCommonClientOptions(
12062
+ 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) => {
12063
+ try {
12064
+ const ctx = resolveCommandContext(opts);
12065
+ const agentId = agentIdArg?.trim() || ctx.agentId;
12066
+ if (!agentId) {
12067
+ throw new Error("Agent ID is required. Pass [agent-id] or set RUDDER_AGENT_ID.");
12068
+ }
12069
+ const patch = await buildAgentUpdatePatch(opts);
12070
+ if (Object.keys(patch).length === 0) {
12071
+ throw new Error(
12072
+ "No agent fields to update. Pass --name, --role, --title, --capabilities, --description, or --reports-to."
12073
+ );
12074
+ }
12075
+ const query = new URLSearchParams();
12076
+ if (ctx.orgId) query.set("orgId", ctx.orgId);
12077
+ const updated = await ctx.api.patch(
12078
+ `/api/agents/${encodeURIComponent(agentId)}${query.size > 0 ? `?${query.toString()}` : ""}`,
12079
+ patch
12080
+ );
12081
+ printOutput(updated, { json: ctx.json });
12082
+ } catch (err) {
12083
+ handleCommandError(err);
12084
+ }
12085
+ })
12086
+ );
11635
12087
  addCommonClientOptions(
11636
12088
  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) => {
11637
12089
  try {
@@ -11731,7 +12183,47 @@ function registerAgentCommands(program) {
11731
12183
  { includeCompany: false }
11732
12184
  );
11733
12185
  }
11734
- function parseCsv2(value) {
12186
+ async function buildAgentUpdatePatch(opts) {
12187
+ const rawPatch = {};
12188
+ if (opts.name !== void 0) rawPatch.name = opts.name;
12189
+ if (opts.role !== void 0) rawPatch.role = opts.role;
12190
+ if (opts.title !== void 0 && opts.clearTitle) {
12191
+ throw new Error("Pass only one of --title or --clear-title.");
12192
+ }
12193
+ if (opts.title !== void 0) rawPatch.title = opts.title;
12194
+ if (opts.clearTitle) rawPatch.title = null;
12195
+ if (opts.reportsTo !== void 0 && opts.clearReportsTo) {
12196
+ throw new Error("Pass only one of --reports-to or --clear-reports-to.");
12197
+ }
12198
+ if (opts.reportsTo !== void 0) rawPatch.reportsTo = opts.reportsTo;
12199
+ if (opts.clearReportsTo) rawPatch.reportsTo = null;
12200
+ const capabilitiesInputs = [
12201
+ opts.capabilities !== void 0 ? "--capabilities" : null,
12202
+ opts.capabilitiesFile !== void 0 ? "--capabilities-file" : null,
12203
+ opts.description !== void 0 ? "--description" : null,
12204
+ opts.descriptionFile !== void 0 ? "--description-file" : null
12205
+ ].filter(Boolean);
12206
+ const clearCapabilities = opts.clearCapabilities || opts.clearDescription;
12207
+ if (capabilitiesInputs.length > 1) {
12208
+ throw new Error(
12209
+ "Pass only one of --capabilities, --capabilities-file, --description, or --description-file."
12210
+ );
12211
+ }
12212
+ if (capabilitiesInputs.length > 0 && clearCapabilities) {
12213
+ throw new Error("Pass either capabilities/description input or a clear flag, not both.");
12214
+ }
12215
+ if (opts.capabilities !== void 0) rawPatch.capabilities = opts.capabilities;
12216
+ if (opts.description !== void 0) rawPatch.capabilities = opts.description;
12217
+ if (opts.capabilitiesFile !== void 0) {
12218
+ rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.capabilitiesFile), "utf8");
12219
+ }
12220
+ if (opts.descriptionFile !== void 0) {
12221
+ rawPatch.capabilities = await fs14.readFile(path18.resolve(opts.descriptionFile), "utf8");
12222
+ }
12223
+ if (clearCapabilities) rawPatch.capabilities = null;
12224
+ return updateAgentSchema.parse(rawPatch);
12225
+ }
12226
+ function parseCsv3(value) {
11735
12227
  if (!value) return [];
11736
12228
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
11737
12229
  }
@@ -11817,7 +12309,7 @@ function registerApprovalCommands(program) {
11817
12309
  type: opts.type,
11818
12310
  payload: payloadJson,
11819
12311
  requestedByAgentId: opts.requestedByAgentId,
11820
- issueIds: parseCsv3(opts.issueIds)
12312
+ issueIds: parseCsv4(opts.issueIds)
11821
12313
  });
11822
12314
  const created = await ctx.api.post(`/api/orgs/${ctx.orgId}/approvals`, payload);
11823
12315
  printOutput(created, { json: ctx.json });
@@ -11923,7 +12415,7 @@ async function readStdinText2() {
11923
12415
  }
11924
12416
  return Buffer.concat(chunks).toString("utf8");
11925
12417
  }
11926
- function parseCsv3(value) {
12418
+ function parseCsv4(value) {
11927
12419
  if (!value) return void 0;
11928
12420
  const rows = value.split(",").map((v) => v.trim()).filter(Boolean);
11929
12421
  return rows.length > 0 ? rows : void 0;
@@ -11952,8 +12444,8 @@ function registerActivityCommands(program) {
11952
12444
  if (opts.entityType) params.set("entityType", opts.entityType);
11953
12445
  if (opts.entityId) params.set("entityId", opts.entityId);
11954
12446
  const query = params.toString();
11955
- const path22 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
11956
- const rows = await ctx.api.get(path22) ?? [];
12447
+ const path23 = `/api/orgs/${ctx.orgId}/activity${query ? `?${query}` : ""}`;
12448
+ const rows = await ctx.api.get(path23) ?? [];
11957
12449
  if (ctx.json) {
11958
12450
  printOutput(rows, { json: true });
11959
12451
  return;
@@ -12081,7 +12573,7 @@ function registerSkillCommands(program) {
12081
12573
  try {
12082
12574
  const ctx = resolveCommandContext(opts, { requireCompany: true });
12083
12575
  const payload = organizationSkillLocalScanRequestSchema.parse({
12084
- roots: parseCsv4(opts.roots)
12576
+ roots: parseCsv5(opts.roots)
12085
12577
  });
12086
12578
  const result = await ctx.api.post(
12087
12579
  `/api/orgs/${ctx.orgId}/skills/scan-local`,
@@ -12099,8 +12591,8 @@ function registerSkillCommands(program) {
12099
12591
  try {
12100
12592
  const ctx = resolveCommandContext(opts, { requireCompany: true });
12101
12593
  const payload = organizationSkillProjectScanRequestSchema.parse({
12102
- projectIds: parseCsv4(opts.projectIds),
12103
- workspaceIds: parseCsv4(opts.workspaceIds)
12594
+ projectIds: parseCsv5(opts.projectIds),
12595
+ workspaceIds: parseCsv5(opts.workspaceIds)
12104
12596
  });
12105
12597
  const result = await ctx.api.post(
12106
12598
  `/api/orgs/${ctx.orgId}/skills/scan-projects`,
@@ -12114,19 +12606,111 @@ function registerSkillCommands(program) {
12114
12606
  { includeCompany: false }
12115
12607
  );
12116
12608
  }
12117
- function parseCsv4(value) {
12609
+ function parseCsv5(value) {
12118
12610
  if (!value) return void 0;
12119
12611
  const rows = value.split(",").map((entry) => entry.trim()).filter(Boolean);
12120
12612
  return rows.length > 0 ? rows : void 0;
12121
12613
  }
12122
12614
 
12615
+ // src/commands/client/library.ts
12616
+ import { readFile as readFile6 } from "node:fs/promises";
12617
+ import path20 from "node:path";
12618
+ function registerLibraryCommands(program) {
12619
+ const library = program.command("library").description("Library file operations");
12620
+ const file = library.command("file").description("Path-based Library file operations");
12621
+ addCommonClientOptions(
12622
+ file.command("list").description(getAgentCliCapabilityById("library.file.list").description).argument("[directoryPath]", "Library directory path", "projects").action(async (directoryPath, opts) => {
12623
+ try {
12624
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12625
+ const search = new URLSearchParams();
12626
+ const normalizedPath = directoryPath.trim();
12627
+ if (normalizedPath) search.set("path", normalizedPath);
12628
+ const query = search.toString();
12629
+ const result = await ctx.api.get(
12630
+ `/api/orgs/${ctx.orgId}/workspace/files${query ? `?${query}` : ""}`
12631
+ );
12632
+ printOutput(result, { json: ctx.json });
12633
+ } catch (err) {
12634
+ handleCommandError(err);
12635
+ }
12636
+ }),
12637
+ { includeCompany: true }
12638
+ );
12639
+ addCommonClientOptions(
12640
+ file.command("get").description(getAgentCliCapabilityById("library.file.get").description).argument("<filePath>", "Library file path").action(async (filePath, opts) => {
12641
+ try {
12642
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12643
+ const search = new URLSearchParams();
12644
+ search.set("path", filePath.trim());
12645
+ const result = await ctx.api.get(
12646
+ `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`
12647
+ );
12648
+ printOutput(result, { json: ctx.json });
12649
+ } catch (err) {
12650
+ handleCommandError(err);
12651
+ }
12652
+ }),
12653
+ { includeCompany: true }
12654
+ );
12655
+ addCommonClientOptions(
12656
+ 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) => {
12657
+ try {
12658
+ const ctx = resolveCommandContext(opts, { requireCompany: true });
12659
+ const body = await resolveBodyFileInput(opts.bodyFile);
12660
+ const search = new URLSearchParams();
12661
+ search.set("path", filePath.trim());
12662
+ const updatePath = `/api/orgs/${ctx.orgId}/workspace/file?${search.toString()}`;
12663
+ const updated = await ctx.api.patch(
12664
+ updatePath,
12665
+ { content: body },
12666
+ { ignoreNotFound: true }
12667
+ );
12668
+ if (updated) {
12669
+ printOutput(updated, { json: ctx.json });
12670
+ return;
12671
+ }
12672
+ const created = await ctx.api.post(
12673
+ `/api/orgs/${ctx.orgId}/workspace/file`,
12674
+ { filePath: filePath.trim(), content: body }
12675
+ );
12676
+ printOutput(created, { json: ctx.json });
12677
+ } catch (err) {
12678
+ handleCommandError(err);
12679
+ }
12680
+ }),
12681
+ { includeCompany: true }
12682
+ );
12683
+ }
12684
+ async function resolveBodyFileInput(inputPath) {
12685
+ if (process.argv.includes("--body")) {
12686
+ throw new Error("--body was removed; write the body to a file and use --body-file <path> or --body-file - for stdin");
12687
+ }
12688
+ if (inputPath === void 0) {
12689
+ throw new Error("Provide --body-file <path>; use --body-file - for stdin");
12690
+ }
12691
+ if (inputPath === "-") {
12692
+ return readStdinText3();
12693
+ }
12694
+ const resolvedPath = path20.resolve(process.cwd(), inputPath);
12695
+ return readFile6(resolvedPath, "utf8").catch((err) => {
12696
+ throw new Error(`Unable to read --body-file ${inputPath}: ${err instanceof Error ? err.message : String(err)}`);
12697
+ });
12698
+ }
12699
+ async function readStdinText3() {
12700
+ const chunks = [];
12701
+ for await (const chunk of process.stdin) {
12702
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
12703
+ }
12704
+ return Buffer.concat(chunks).toString("utf8");
12705
+ }
12706
+
12123
12707
  // src/config/data-dir.ts
12124
12708
  init_home();
12125
- import path20 from "node:path";
12709
+ import path21 from "node:path";
12126
12710
  function applyDataDirOverride(options, support = {}) {
12127
12711
  const rawDataDir = options.dataDir?.trim();
12128
12712
  if (!rawDataDir) return null;
12129
- const resolvedDataDir = path20.resolve(expandHomePrefix(rawDataDir));
12713
+ const resolvedDataDir = path21.resolve(expandHomePrefix(rawDataDir));
12130
12714
  process.env.RUDDER_HOME = resolvedDataDir;
12131
12715
  if (support.hasConfigOption) {
12132
12716
  const hasConfigOverride = Boolean(options.config?.trim()) || Boolean(process.env.RUDDER_CONFIG?.trim());
@@ -12150,16 +12734,16 @@ init_env();
12150
12734
  init_local_env();
12151
12735
 
12152
12736
  // src/commands/client/plugin.ts
12153
- import path21 from "node:path";
12737
+ import path22 from "node:path";
12154
12738
  import pc15 from "picocolors";
12155
12739
  function resolvePackageArg(packageArg, isLocal) {
12156
12740
  if (!isLocal) return packageArg;
12157
- if (path21.isAbsolute(packageArg)) return packageArg;
12741
+ if (path22.isAbsolute(packageArg)) return packageArg;
12158
12742
  if (packageArg.startsWith("~")) {
12159
12743
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
12160
- return path21.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12744
+ return path22.resolve(home, packageArg.slice(1).replace(/^[\\/]/, ""));
12161
12745
  }
12162
- return path21.resolve(process.cwd(), packageArg);
12746
+ return path22.resolve(process.cwd(), packageArg);
12163
12747
  }
12164
12748
  function formatPlugin(p16) {
12165
12749
  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);
@@ -12493,11 +13077,13 @@ function createProgram() {
12493
13077
  registerContextCommands(program);
12494
13078
  registerCompanyCommands(program);
12495
13079
  registerIssueCommands(program);
13080
+ registerProjectCommands(program);
12496
13081
  registerAgentCommands(program);
12497
13082
  registerApprovalCommands(program);
12498
13083
  registerActivityCommands(program);
12499
13084
  registerDashboardCommands(program);
12500
13085
  registerSkillCommands(program);
13086
+ registerLibraryCommands(program);
12501
13087
  registerLazyWorktreeCommands(program);
12502
13088
  registerPluginCommands(program);
12503
13089
  registerLazyBenchmarkCommands(program);