replicas-cli 0.2.348 → 0.2.350

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.
Files changed (2) hide show
  1. package/dist/index.mjs +316 -177
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -7335,7 +7335,7 @@ var require_dist = __commonJS({
7335
7335
  // src/index.ts
7336
7336
  import "dotenv/config";
7337
7337
  import { Command, InvalidArgumentError } from "commander";
7338
- import chalk23 from "chalk";
7338
+ import chalk24 from "chalk";
7339
7339
 
7340
7340
  // src/commands/login.ts
7341
7341
  import http from "http";
@@ -9601,7 +9601,7 @@ var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
9601
9601
  var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
9602
9602
 
9603
9603
  // ../shared/src/cli-version.ts
9604
- var CLI_VERSION = "0.2.348";
9604
+ var CLI_VERSION = "0.2.350";
9605
9605
 
9606
9606
  // ../shared/src/version.ts
9607
9607
  function compareVersions(v1, v2) {
@@ -12243,11 +12243,21 @@ function isInsideGitRepo() {
12243
12243
  }
12244
12244
 
12245
12245
  // src/lib/workspace-connection.ts
12246
- async function prepareWorkspaceConnection(workspaceName) {
12247
- const orgId = getOrganizationId();
12248
- if (!orgId) {
12246
+ async function fetchWorkspaceById(workspaceId) {
12247
+ const response = await orgAuthenticatedFetch(
12248
+ `/v1/workspaces/${encodeURIComponent(workspaceId)}`
12249
+ ).catch((error) => {
12250
+ if (error instanceof Error && error.message.includes("Workspace not found")) return null;
12251
+ throw error;
12252
+ });
12253
+ return response?.workspace ?? null;
12254
+ }
12255
+ async function resolveWorkspaceRecord(workspaceName) {
12256
+ if (!canCallOrgApi()) {
12249
12257
  throw new Error('No organization selected. Please run "replicas org switch" first.');
12250
12258
  }
12259
+ const exactWorkspace = await fetchWorkspaceById(workspaceName);
12260
+ if (exactWorkspace) return exactWorkspace;
12251
12261
  console.log(chalk4.blue(`
12252
12262
  Searching for workspace: ${workspaceName}...`));
12253
12263
  const response = await orgAuthenticatedFetch(
@@ -12275,11 +12285,19 @@ Found ${response.workspaces.length} workspaces matching "${workspaceName}":`));
12275
12285
  if (!selectResponse.workspaceId) {
12276
12286
  throw new Error("Workspace selection cancelled.");
12277
12287
  }
12278
- selectedWorkspace = response.workspaces.find((ws) => ws.id === selectResponse.workspaceId);
12288
+ const selected = response.workspaces.find((ws) => ws.id === selectResponse.workspaceId);
12289
+ if (!selected) {
12290
+ throw new Error("Selected workspace was not found.");
12291
+ }
12292
+ selectedWorkspace = selected;
12279
12293
  }
12280
12294
  console.log(chalk4.green(`
12281
12295
  \u2713 Selected workspace: ${selectedWorkspace.name}`));
12282
12296
  console.log(chalk4.gray(` Status: ${selectedWorkspace.status || "unknown"}`));
12297
+ return selectedWorkspace;
12298
+ }
12299
+ async function prepareWorkspaceConnection(workspaceName) {
12300
+ const selectedWorkspace = await resolveWorkspaceRecord(workspaceName);
12283
12301
  if (isWorkspaceSuspendedStatus(selectedWorkspace.status)) {
12284
12302
  throw new Error(
12285
12303
  `Workspace is currently ${selectedWorkspace.status}. Wake it using \`replicas interact\` (press w on a suspended workspace) or visit https://tryreplicas.com`
@@ -13236,7 +13254,7 @@ function formatDisplayMessage(message) {
13236
13254
  }
13237
13255
  }
13238
13256
  async function replicaListCommand(options) {
13239
- if (!isAuthenticated()) {
13257
+ if (!canCallOrgApi()) {
13240
13258
  console.log(chalk15.red('Not logged in. Please run "replicas login" first.'));
13241
13259
  process.exit(1);
13242
13260
  }
@@ -13565,6 +13583,9 @@ function ensureOrgApiAuthenticated() {
13565
13583
  process.exit(1);
13566
13584
  }
13567
13585
  }
13586
+ function resolveByNameOrId(input, items) {
13587
+ return items.find((item) => item.id === input || item.name === input);
13588
+ }
13568
13589
 
13569
13590
  // src/commands/repositories.ts
13570
13591
  async function repositoriesListCommand() {
@@ -13742,14 +13763,14 @@ function formatModeSummary(automation2) {
13742
13763
  return modes.length > 0 ? modes.join(", ") : "default";
13743
13764
  }
13744
13765
  function resolveSelectableEnvironmentId(envInput, selectableEnvs) {
13745
- const env = selectableEnvs.find((e) => e.name === envInput || e.id === envInput);
13746
- if (!env) {
13766
+ const resolved = resolveByNameOrId(envInput, selectableEnvs);
13767
+ if (!resolved) {
13747
13768
  console.log(chalk18.red(`Environment not found: ${envInput}`));
13748
13769
  const available = selectableEnvs.map((e) => e.name).join(", ");
13749
13770
  console.log(chalk18.gray(`Available: ${available || "(none)"}`));
13750
13771
  process.exit(1);
13751
13772
  }
13752
- return env.id;
13773
+ return resolved.id;
13753
13774
  }
13754
13775
  function printAutomation(automation2) {
13755
13776
  console.log(chalk18.white(` ${automation2.name}`));
@@ -14653,6 +14674,55 @@ async function mediaListCommand(options) {
14653
14674
  }
14654
14675
  }
14655
14676
 
14677
+ // src/commands/slack.ts
14678
+ import chalk20 from "chalk";
14679
+ function getThreadOptions(options) {
14680
+ const channelId = options.channel || process.env.SLACK_CHANNEL_ID;
14681
+ const threadTs = options.threadTs || process.env.SLACK_THREAD_TS;
14682
+ if (!channelId) {
14683
+ throw new Error("--channel is required when SLACK_CHANNEL_ID is not set");
14684
+ }
14685
+ if (!threadTs) {
14686
+ throw new Error("--thread-ts is required when SLACK_THREAD_TS is not set");
14687
+ }
14688
+ return { channelId, threadTs };
14689
+ }
14690
+ async function attachThread(request) {
14691
+ const response = await orgAuthenticatedFetch("/v1/slack/threads/attach", {
14692
+ method: "POST",
14693
+ body: request
14694
+ });
14695
+ console.log(chalk20.green("Slack thread attached."));
14696
+ console.log(chalk20.gray(` Channel: ${response.thread.channel_id}`));
14697
+ console.log(chalk20.gray(` Thread: ${response.thread.thread_ts}`));
14698
+ console.log(chalk20.gray(` Workspace: ${response.workspace.name} (${response.workspace.id})`));
14699
+ }
14700
+ async function slackThreadAttachCommand(options) {
14701
+ const agentConfig = readAgentConfig();
14702
+ if (!agentConfig?.workspace_id) {
14703
+ throw new Error("This command must run inside a Replicas workspace, or use `replicas slack thread switch <workspace>`.");
14704
+ }
14705
+ const { channelId, threadTs } = getThreadOptions(options);
14706
+ await attachThread({
14707
+ channel_id: channelId,
14708
+ thread_ts: threadTs,
14709
+ workspace_id: agentConfig.workspace_id
14710
+ });
14711
+ }
14712
+ async function slackThreadSwitchCommand(workspace, options) {
14713
+ const { channelId, threadTs } = getThreadOptions(options);
14714
+ const agentConfig = readAgentConfig();
14715
+ const workspaceId = (await resolveWorkspaceRecord(workspace)).id;
14716
+ if (agentConfig?.workspace_id && workspaceId !== agentConfig.workspace_id) {
14717
+ throw new Error("Agent-mode Slack thread switching can only target the current workspace. Run this command with user authentication to switch to another workspace.");
14718
+ }
14719
+ await attachThread({
14720
+ channel_id: channelId,
14721
+ thread_ts: threadTs,
14722
+ workspace_id: workspaceId
14723
+ });
14724
+ }
14725
+
14656
14726
  // src/commands/learnings.ts
14657
14727
  function printBlocks(learnings) {
14658
14728
  for (const learning of learnings) {
@@ -14726,21 +14796,23 @@ async function learningsDeleteCommand(id) {
14726
14796
  // src/commands/computer/index.ts
14727
14797
  import { spawn as spawn4, spawnSync as spawnSync3 } from "child_process";
14728
14798
  import { createHash as createHash2 } from "crypto";
14729
- import { closeSync, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync2, readSync, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
14730
- import { dirname as dirname2 } from "path";
14731
- import chalk20 from "chalk";
14799
+ import { closeSync, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync3, readSync, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
14800
+ import { dirname as dirname3 } from "path";
14801
+ import chalk21 from "chalk";
14732
14802
 
14733
14803
  // src/commands/computer/desktop.ts
14734
14804
  import { spawnSync } from "child_process";
14735
- import { existsSync } from "fs";
14736
- import { isAbsolute, resolve } from "path";
14805
+ import { existsSync, mkdirSync, readFileSync } from "fs";
14806
+ import { dirname, isAbsolute, resolve } from "path";
14737
14807
  var STATE_DIR = process.env.REPLICAS_DESKTOP_STATE_DIR || "/tmp/replicas-computer";
14738
14808
  var DEFAULT_DISPLAY = process.env.REPLICAS_DESKTOP_DISPLAY || ":99";
14739
14809
  var NOVNC_PORT = process.env.REPLICAS_DESKTOP_NOVNC_PORT ? parseInt(process.env.REPLICAS_DESKTOP_NOVNC_PORT, 10) : DESKTOP_NOVNC_PORT;
14740
14810
  var SERVICES_SCRIPT = "/usr/local/bin/replicas-start-desktop-services";
14811
+ var INPUT_LOCK_FILE = process.env.REPLICAS_DESKTOP_INPUT_LOCK_FILE || `${STATE_DIR}/input.lock`;
14741
14812
  var CHROME_WRAPPER = "/usr/local/bin/replicas-chrome";
14742
14813
  var INFO_WAIT_TIMEOUT_MS = 1e4;
14743
14814
  var INFO_WAIT_INTERVAL_MS = 500;
14815
+ var lastDesktopHealthAt = 0;
14744
14816
  var CHROME_DEBUG_PORT = (() => {
14745
14817
  const value = process.env.REPLICAS_DESKTOP_CHROME_DEBUG_PORT;
14746
14818
  if (!value) return 9222;
@@ -14753,16 +14825,49 @@ var CHROME_DEBUG_PORT = (() => {
14753
14825
  function fail(msg) {
14754
14826
  throw new Error(msg);
14755
14827
  }
14828
+ function getDesktopBridgeStatus() {
14829
+ const r = spawnSync("bash", [SERVICES_SCRIPT, "--status-json"], { stdio: "pipe" });
14830
+ if (r.status !== 0) return null;
14831
+ try {
14832
+ return JSON.parse(r.stdout.toString());
14833
+ } catch {
14834
+ return null;
14835
+ }
14836
+ }
14837
+ function desktopStackHealthy() {
14838
+ const pids = {};
14839
+ for (const name of ["openbox", "tint2", "x11vnc", "novnc"]) {
14840
+ try {
14841
+ const pid = Number.parseInt(readFileSync(`${STATE_DIR}/${name}.pid`, "utf8").trim(), 10);
14842
+ if (!Number.isFinite(pid)) return false;
14843
+ process.kill(pid, 0);
14844
+ pids[name] = pid;
14845
+ } catch {
14846
+ return false;
14847
+ }
14848
+ }
14849
+ if (spawnSync("xdpyinfo", [], { env: withDisplay(), stdio: "ignore" }).status !== 0) return false;
14850
+ const wm = spawnSync("xprop", ["-root", "_NET_SUPPORTING_WM_CHECK"], { env: withDisplay(), stdio: "pipe" });
14851
+ if (wm.status !== 0 || !wm.stdout?.toString().includes("window id")) return false;
14852
+ const bridge = getDesktopBridgeStatus();
14853
+ return !!bridge?.x11vnc.listenerPids?.includes(pids.x11vnc) && !!bridge.websockify.listenerPids?.includes(pids.novnc);
14854
+ }
14756
14855
  function ensureServicesRunning() {
14757
14856
  if (!existsSync(SERVICES_SCRIPT)) {
14758
14857
  fail(
14759
14858
  `Desktop services script missing at ${SERVICES_SCRIPT}. The workspace image is out of date \u2014 Xvfb / openbox / x11vnc / websockify must be installed and \`replicas-start-desktop-services\` baked in.`
14760
14859
  );
14761
14860
  }
14861
+ if (Date.now() - lastDesktopHealthAt < 1e3) return;
14862
+ if (desktopStackHealthy()) {
14863
+ lastDesktopHealthAt = Date.now();
14864
+ return;
14865
+ }
14762
14866
  const r = spawnSync("bash", [SERVICES_SCRIPT], { stdio: "pipe" });
14763
14867
  if (r.status !== 0) {
14764
14868
  fail(`Failed to start desktop services: ${r.stderr?.toString() || "unknown error"}`);
14765
14869
  }
14870
+ lastDesktopHealthAt = Date.now();
14766
14871
  }
14767
14872
  function withDisplay(env = process.env) {
14768
14873
  return { ...env, DISPLAY: DEFAULT_DISPLAY };
@@ -14775,6 +14880,17 @@ function runDisplayCmd(bin, args) {
14775
14880
  }
14776
14881
  return r.stdout?.toString() ?? "";
14777
14882
  }
14883
+ function runDesktopInputCmd(args) {
14884
+ mkdirSync(dirname(INPUT_LOCK_FILE), { recursive: true });
14885
+ return runDisplayCmd("flock", [
14886
+ "--exclusive",
14887
+ "--wait",
14888
+ process.env.REPLICAS_DESKTOP_INPUT_LOCK_WAIT_SECONDS || "60",
14889
+ INPUT_LOCK_FILE,
14890
+ "xdotool",
14891
+ ...args
14892
+ ]);
14893
+ }
14778
14894
  function tryDisplayCmd(bin, args) {
14779
14895
  ensureServicesRunning();
14780
14896
  const r = spawnSync(bin, args, { env: withDisplay(), stdio: "pipe" });
@@ -14840,8 +14956,8 @@ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
14840
14956
 
14841
14957
  // src/commands/computer/recording.ts
14842
14958
  import { spawn as spawn3 } from "child_process";
14843
- import { appendFileSync, existsSync as existsSync2, mkdirSync, readFileSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
14844
- import { dirname } from "path";
14959
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
14960
+ import { dirname as dirname2 } from "path";
14845
14961
 
14846
14962
  // src/commands/computer/recording/render.ts
14847
14963
  import { spawnSync as spawnSync2 } from "child_process";
@@ -15323,7 +15439,7 @@ var RECORD_DIMENSIONS_FILE = `${STATE_DIR}/recording-dimensions.json`;
15323
15439
  var RECORD_ACTIONS_FILE = `${STATE_DIR}/recording-actions.jsonl`;
15324
15440
  function recordingStartedAt() {
15325
15441
  if (!existsSync2(RECORD_STARTED_AT_FILE)) return null;
15326
- const startedAt = Number.parseInt(readFileSync(RECORD_STARTED_AT_FILE, "utf8").trim(), 10);
15442
+ const startedAt = Number.parseInt(readFileSync2(RECORD_STARTED_AT_FILE, "utf8").trim(), 10);
15327
15443
  return Number.isFinite(startedAt) ? startedAt : null;
15328
15444
  }
15329
15445
  function logRecordingAction(action) {
@@ -15336,7 +15452,7 @@ function logRecordingAction(action) {
15336
15452
  function readRecordingDimensions() {
15337
15453
  if (!existsSync2(RECORD_DIMENSIONS_FILE)) return configuredDesktopDimensions();
15338
15454
  try {
15339
- const dimensions = JSON.parse(readFileSync(RECORD_DIMENSIONS_FILE, "utf8"));
15455
+ const dimensions = JSON.parse(readFileSync2(RECORD_DIMENSIONS_FILE, "utf8"));
15340
15456
  const width = dimensions?.width;
15341
15457
  const height = dimensions?.height;
15342
15458
  if (typeof width === "number" && Number.isFinite(width) && width > 0 && typeof height === "number" && Number.isFinite(height) && height > 0) {
@@ -15354,7 +15470,7 @@ function isOptionalNumber(value) {
15354
15470
  }
15355
15471
  function readRecordingActions() {
15356
15472
  if (!existsSync2(RECORD_ACTIONS_FILE)) return [];
15357
- return readFileSync(RECORD_ACTIONS_FILE, "utf8").split("\n").filter(Boolean).flatMap((line) => {
15473
+ return readFileSync2(RECORD_ACTIONS_FILE, "utf8").split("\n").filter(Boolean).flatMap((line) => {
15358
15474
  try {
15359
15475
  const value = JSON.parse(line);
15360
15476
  if (typeof value !== "object" || value === null) return [];
@@ -15376,7 +15492,7 @@ function readRecordingActions() {
15376
15492
  async function computerRecordStartCommand(path6, options) {
15377
15493
  ensureServicesRunning();
15378
15494
  if (existsSync2(RECORD_PID_FILE)) {
15379
- const pid = parseInt(readFileSync(RECORD_PID_FILE, "utf8").trim(), 10);
15495
+ const pid = parseInt(readFileSync2(RECORD_PID_FILE, "utf8").trim(), 10);
15380
15496
  if (Number.isFinite(pid)) {
15381
15497
  let alive = false;
15382
15498
  try {
@@ -15388,10 +15504,10 @@ async function computerRecordStartCommand(path6, options) {
15388
15504
  }
15389
15505
  }
15390
15506
  const target = resolvePath(path6);
15391
- mkdirSync(dirname(target), { recursive: true });
15507
+ mkdirSync2(dirname2(target), { recursive: true });
15392
15508
  const fps = options.fps ? parseCoord(options.fps, "--fps") : 60;
15393
15509
  const { width, height } = configuredDesktopDimensions();
15394
- mkdirSync(STATE_DIR, { recursive: true });
15510
+ mkdirSync2(STATE_DIR, { recursive: true });
15395
15511
  const rawTarget = `${target}.raw-${Date.now()}.mp4`;
15396
15512
  rmSync2(RECORD_ACTIONS_FILE, { force: true });
15397
15513
  const child = spawn3("ffmpeg", [
@@ -15436,7 +15552,7 @@ async function computerRecordStartCommand(path6, options) {
15436
15552
  async function computerRecordStopCommand() {
15437
15553
  if (!existsSync2(RECORD_PID_FILE) && !existsSync2(RECORD_PATH_FILE)) fail("no recording in progress");
15438
15554
  if (existsSync2(RECORD_PID_FILE)) {
15439
- const pid = parseInt(readFileSync(RECORD_PID_FILE, "utf8").trim(), 10);
15555
+ const pid = parseInt(readFileSync2(RECORD_PID_FILE, "utf8").trim(), 10);
15440
15556
  if (!Number.isFinite(pid)) fail("invalid recording pidfile");
15441
15557
  try {
15442
15558
  process.kill(pid, "SIGINT");
@@ -15453,9 +15569,9 @@ async function computerRecordStopCommand() {
15453
15569
  rmSync2(RECORD_PID_FILE, { force: true });
15454
15570
  }
15455
15571
  if (existsSync2(RECORD_PATH_FILE)) {
15456
- const target = readFileSync(RECORD_PATH_FILE, "utf8").trim();
15457
- const rawPath = existsSync2(RECORD_RAW_PATH_FILE) ? readFileSync(RECORD_RAW_PATH_FILE, "utf8").trim() : target;
15458
- const fps = existsSync2(RECORD_FPS_FILE) ? parseInt(readFileSync(RECORD_FPS_FILE, "utf8").trim(), 10) : 60;
15572
+ const target = readFileSync2(RECORD_PATH_FILE, "utf8").trim();
15573
+ const rawPath = existsSync2(RECORD_RAW_PATH_FILE) ? readFileSync2(RECORD_RAW_PATH_FILE, "utf8").trim() : target;
15574
+ const fps = existsSync2(RECORD_FPS_FILE) ? parseInt(readFileSync2(RECORD_FPS_FILE, "utf8").trim(), 10) : 60;
15459
15575
  const size = readRecordingDimensions();
15460
15576
  const actions = readRecordingActions();
15461
15577
  if (rawPath !== target) {
@@ -15473,15 +15589,6 @@ async function computerRecordStopCommand() {
15473
15589
  }
15474
15590
 
15475
15591
  // src/commands/computer/index.ts
15476
- function desktopBridgeStatus() {
15477
- const r = spawnSync3("bash", [SERVICES_SCRIPT, "--status-json"], { stdio: "pipe" });
15478
- if (r.status !== 0) return null;
15479
- try {
15480
- return JSON.parse(r.stdout.toString());
15481
- } catch {
15482
- return null;
15483
- }
15484
- }
15485
15592
  function bridgeStatus(details, includeBacklog = false, rootsOnly = false) {
15486
15593
  const pids = rootsOnly ? details.rootPids ?? [] : details.listenerPids ?? [];
15487
15594
  const listenerCount = rootsOnly ? details.rootListeners ?? pids.length : details.listeners ?? pids.length;
@@ -15517,23 +15624,23 @@ async function computerInfoCommand() {
15517
15624
  );
15518
15625
  }
15519
15626
  console.log(viewerUrl);
15520
- console.error(chalk20.dim(`Share this URL with the user to let them watch the desktop live.`));
15627
+ console.error(chalk21.dim(`Share this URL with the user to let them watch the desktop live.`));
15521
15628
  }
15522
15629
  async function computerStatusCommand() {
15523
15630
  ensureServicesRunning();
15524
- const bridge = desktopBridgeStatus();
15631
+ const bridge = getDesktopBridgeStatus();
15525
15632
  const procs = ["Xvfb", "openbox", "tint2", "x11vnc", "websockify"];
15526
15633
  for (const p of procs) {
15527
15634
  const r = spawnSync3("pgrep", ["-af", p], { stdio: "pipe" });
15528
15635
  const running = r.status === 0 && !!r.stdout?.toString().trim();
15529
15636
  const suffix = p === "x11vnc" && bridge ? bridgeStatus(bridge.x11vnc, true) : p === "websockify" && bridge ? bridgeStatus(bridge.websockify, false, true) : "";
15530
- console.log(` ${running ? chalk20.green("\u25CF") : chalk20.red("\u25CB")} ${p}${suffix}`);
15637
+ console.log(` ${running ? chalk21.green("\u25CF") : chalk21.red("\u25CB")} ${p}${suffix}`);
15531
15638
  }
15532
15639
  const viewerUrl = await lookupDesktopViewerUrl();
15533
15640
  if (viewerUrl) {
15534
- console.log(` ${chalk20.cyan("preview")}: ${viewerUrl}`);
15641
+ console.log(` ${chalk21.cyan("preview")}: ${viewerUrl}`);
15535
15642
  } else {
15536
- console.log(` ${chalk20.dim("preview: not yet registered (engine registers it at startup)")}`);
15643
+ console.log(` ${chalk21.dim("preview: not yet registered (engine registers it at startup)")}`);
15537
15644
  }
15538
15645
  }
15539
15646
  var PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
@@ -15561,7 +15668,7 @@ function loadBrandSvg(canvasW, canvasH) {
15561
15668
  `Brand wallpaper SVG missing at ${path6}. The workspace image is out of date \u2014 \`desktop/brand-wallpaper.svg\` must be installed at $REPLICAS_DESKTOP_TEMPLATES.`
15562
15669
  );
15563
15670
  }
15564
- return readFileSync2(path6, "utf8").replace(/(<svg[^>]*\s)width="\d+"/, `$1width="${canvasW}"`).replace(/(<svg[^>]*\s)height="\d+"/, `$1height="${canvasH}"`);
15671
+ return readFileSync3(path6, "utf8").replace(/(<svg[^>]*\s)width="\d+"/, `$1width="${canvasW}"`).replace(/(<svg[^>]*\s)height="\d+"/, `$1height="${canvasH}"`);
15565
15672
  }
15566
15673
  var BRAND_PAD_FRACTION = 0.06;
15567
15674
  var SCREENSHOT_CORNER_FRACTION = 0.022;
@@ -15624,7 +15731,7 @@ function overlayGrid(rawPath, target, width, height, gridSize, gridPath) {
15624
15731
  }
15625
15732
  async function computerScreenshotCommand(path6, options = {}) {
15626
15733
  const target = resolvePath(path6);
15627
- mkdirSync2(dirname2(target), { recursive: true });
15734
+ mkdirSync3(dirname3(target), { recursive: true });
15628
15735
  const stamp = `${process.pid}-${Date.now()}`;
15629
15736
  const rawPath = `/tmp/replicas-screenshot-${stamp}.raw.png`;
15630
15737
  const svgPath = `/tmp/replicas-screenshot-${stamp}.brand.svg`;
@@ -15703,7 +15810,7 @@ async function computerScreenshotCommand(path6, options = {}) {
15703
15810
  console.log(target);
15704
15811
  }
15705
15812
  function hashFile(path6) {
15706
- return createHash2("sha256").update(readFileSync2(path6)).digest("hex");
15813
+ return createHash2("sha256").update(readFileSync3(path6)).digest("hex");
15707
15814
  }
15708
15815
  async function captureStableRawScreenshot(target, options) {
15709
15816
  const start = Date.now();
@@ -15754,7 +15861,7 @@ function recordingMousePosition() {
15754
15861
  }
15755
15862
  async function computerObserveCommand(path6, options = {}) {
15756
15863
  const target = resolvePath(path6);
15757
- mkdirSync2(dirname2(target), { recursive: true });
15864
+ mkdirSync3(dirname3(target), { recursive: true });
15758
15865
  const timeoutMs = options.timeout ? parseCoord(options.timeout, "--timeout") : 3e3;
15759
15866
  const stableMs = options.stableMs ? parseCoord(options.stableMs, "--stable-ms") : 600;
15760
15867
  const pollMs = options.pollMs ? parseCoord(options.pollMs, "--poll-ms") : 200;
@@ -15765,6 +15872,7 @@ async function computerObserveCommand(path6, options = {}) {
15765
15872
  const rawPath = `/tmp/replicas-observe-${stamp}.raw.png`;
15766
15873
  const gridPath = `/tmp/replicas-observe-${stamp}.grid.svg`;
15767
15874
  try {
15875
+ ensureServicesRunning();
15768
15876
  const capture = await captureStableRawScreenshot(rawPath, { timeoutMs, stableMs, pollMs });
15769
15877
  const gridSize = options.raw ? null : parseGridSize(options.grid ?? true);
15770
15878
  if (gridSize === null) {
@@ -16270,7 +16378,7 @@ async function computerClickCommand(xStr, yStr, options) {
16270
16378
  args.push("keyup", mod);
16271
16379
  }
16272
16380
  }
16273
- runDisplayCmd("xdotool", args);
16381
+ runDesktopInputCmd(args);
16274
16382
  logRecordingAction({ type: "click", x, y });
16275
16383
  console.log(`clicked ${button === "1" ? "left" : button === "2" ? "middle" : button === "3" ? "right" : `button ${button}`} at (${x},${y})${options.double ? " x2" : ""}`);
16276
16384
  }
@@ -16278,19 +16386,19 @@ async function computerMoveCommand(xStr, yStr) {
16278
16386
  const dimensions = getDisplayDimensions();
16279
16387
  const x = parseScreenCoord(xStr, "x", dimensions.width);
16280
16388
  const y = parseScreenCoord(yStr, "y", dimensions.height);
16281
- runDisplayCmd("xdotool", ["mousemove", "--sync", String(x), String(y)]);
16389
+ runDesktopInputCmd(["mousemove", "--sync", String(x), String(y)]);
16282
16390
  logRecordingAction({ type: "move", x, y });
16283
16391
  console.log(`moved to (${x},${y})`);
16284
16392
  }
16285
16393
  async function computerTypeCommand(text, options) {
16286
16394
  const delay = options.delay ? parseCoord(options.delay, "--delay") : 12;
16287
- runDisplayCmd("xdotool", ["type", "--delay", String(delay), "--", text]);
16395
+ runDesktopInputCmd(["type", "--delay", String(delay), "--", text]);
16288
16396
  const position = recordingMousePosition();
16289
16397
  logRecordingAction({ type: "type", ...position ?? {} });
16290
16398
  console.log(`typed ${text.length} char${text.length === 1 ? "" : "s"}`);
16291
16399
  }
16292
16400
  async function computerKeyCommand(combo) {
16293
- runDisplayCmd("xdotool", ["key", "--", combo]);
16401
+ runDesktopInputCmd(["key", "--", combo]);
16294
16402
  const position = recordingMousePosition();
16295
16403
  logRecordingAction({ type: "key", ...position ?? {} });
16296
16404
  console.log(`pressed ${combo}`);
@@ -16317,7 +16425,7 @@ async function computerScrollCommand(direction, options) {
16317
16425
  );
16318
16426
  }
16319
16427
  args.push("click", "--repeat", String(amount), "--delay", "30", button);
16320
- runDisplayCmd("xdotool", args);
16428
+ runDesktopInputCmd(args);
16321
16429
  const position = hoverPosition ?? recordingMousePosition();
16322
16430
  logRecordingAction({ type: "scroll", ...position ?? {} });
16323
16431
  console.log(`scrolled ${dir} x${amount}`);
@@ -16344,7 +16452,7 @@ async function computerDragCommand(fx, fy, tx, ty) {
16344
16452
  args.push("mousemove", "--sync", String(x), String(y), "sleep", "0.018");
16345
16453
  }
16346
16454
  args.push("mouseup", "1");
16347
- runDisplayCmd("xdotool", args);
16455
+ runDesktopInputCmd(args);
16348
16456
  logRecordingAction({ type: "drag", x: fromX, y: fromY, toX, toY });
16349
16457
  console.log(`dragged (${fromX},${fromY}) -> (${toX},${toY})`);
16350
16458
  }
@@ -16381,7 +16489,7 @@ async function computerLaunchCommand(app, args) {
16381
16489
  }
16382
16490
 
16383
16491
  // src/commands/interactive.ts
16384
- import chalk21 from "chalk";
16492
+ import chalk22 from "chalk";
16385
16493
 
16386
16494
  // src/interactive/index.tsx
16387
16495
  import { createCliRenderer } from "@opentui/core";
@@ -19562,13 +19670,13 @@ async function interactiveCommand() {
19562
19670
  'No organization selected. Please run "replicas org switch" to select an organization.'
19563
19671
  );
19564
19672
  }
19565
- console.log(chalk21.gray("Starting interactive mode..."));
19673
+ console.log(chalk22.gray("Starting interactive mode..."));
19566
19674
  await launchInteractive();
19567
19675
  }
19568
19676
 
19569
19677
  // src/commands/environment.ts
19570
19678
  import fs5 from "fs";
19571
- import chalk22 from "chalk";
19679
+ import chalk23 from "chalk";
19572
19680
  import prompts5 from "prompts";
19573
19681
  var UUID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
19574
19682
  function maskValue(value) {
@@ -19579,40 +19687,40 @@ async function resolveEnvironmentId(input) {
19579
19687
  if (input === "global") return "global";
19580
19688
  if (UUID_RE.test(input)) return input;
19581
19689
  const response = await orgAuthenticatedFetch("/v1/environments");
19582
- const env = response.environments.find((e) => e.name === input);
19583
- if (!env) {
19584
- console.log(chalk22.red(`Environment not found: ${input}`));
19690
+ const resolved = resolveByNameOrId(input, response.environments);
19691
+ if (!resolved) {
19692
+ console.log(chalk23.red(`Environment not found: ${input}`));
19585
19693
  const available = response.environments.map((e) => e.name).join(", ");
19586
- console.log(chalk22.gray(`Available: ${available || "(none)"}`));
19694
+ console.log(chalk23.gray(`Available: ${available || "(none)"}`));
19587
19695
  process.exit(1);
19588
19696
  }
19589
- return env.id;
19697
+ return resolved.id;
19590
19698
  }
19591
19699
  function printEnvironment(env) {
19592
- console.log(chalk22.white(` ${env.name}${env.is_global ? chalk22.gray(" (global)") : ""}`));
19593
- console.log(chalk22.gray(` ID: ${env.id}`));
19700
+ console.log(chalk23.white(` ${env.name}${env.is_global ? chalk23.gray(" (global)") : ""}`));
19701
+ console.log(chalk23.gray(` ID: ${env.id}`));
19594
19702
  if (env.description) {
19595
- console.log(chalk22.gray(` Description: ${env.description}`));
19703
+ console.log(chalk23.gray(` Description: ${env.description}`));
19596
19704
  }
19597
19705
  if (env.repository_id) {
19598
- console.log(chalk22.gray(` Repository: ${env.repository_id}`));
19706
+ console.log(chalk23.gray(` Repository: ${env.repository_id}`));
19599
19707
  } else if (env.repository_set_id) {
19600
- console.log(chalk22.gray(` Repository Set: ${env.repository_set_id}`));
19708
+ console.log(chalk23.gray(` Repository Set: ${env.repository_set_id}`));
19601
19709
  }
19602
19710
  if (env.variable_count !== void 0) {
19603
- console.log(chalk22.gray(` Variables: ${env.variable_count}, Files: ${env.file_count ?? 0}, Skills: ${env.skill_count ?? 0}, MCPs: ${env.mcp_count ?? 0}`));
19711
+ console.log(chalk23.gray(` Variables: ${env.variable_count}, Files: ${env.file_count ?? 0}, Skills: ${env.skill_count ?? 0}, MCPs: ${env.mcp_count ?? 0}`));
19604
19712
  }
19605
- console.log(chalk22.gray(` Updated: ${formatDate2(env.updated_at)}`));
19713
+ console.log(chalk23.gray(` Updated: ${formatDate2(env.updated_at)}`));
19606
19714
  console.log();
19607
19715
  }
19608
19716
  async function environmentListCommand() {
19609
19717
  ensureOrgApiAuthenticated();
19610
19718
  const response = await orgAuthenticatedFetch("/v1/environments");
19611
19719
  if (response.environments.length === 0) {
19612
- console.log(chalk22.yellow("\nNo environments found.\n"));
19720
+ console.log(chalk23.yellow("\nNo environments found.\n"));
19613
19721
  return;
19614
19722
  }
19615
- console.log(chalk22.green(`
19723
+ console.log(chalk23.green(`
19616
19724
  Environments (${response.environments.length}):
19617
19725
  `));
19618
19726
  for (const env of response.environments) {
@@ -19623,7 +19731,7 @@ async function environmentGetCommand(idOrName) {
19623
19731
  ensureOrgApiAuthenticated();
19624
19732
  const id = await resolveEnvironmentId(idOrName);
19625
19733
  const response = await orgAuthenticatedFetch(`/v1/environments/${id}`);
19626
- console.log(chalk22.green(`
19734
+ console.log(chalk23.green(`
19627
19735
  Environment: ${response.environment.name}
19628
19736
  `));
19629
19737
  printEnvironment(response.environment);
@@ -19639,7 +19747,7 @@ async function environmentCreateCommand(name, options) {
19639
19747
  validate: (v) => v.trim() ? true : "Name is required"
19640
19748
  });
19641
19749
  if (!r.name) {
19642
- console.log(chalk22.yellow("\nCancelled."));
19750
+ console.log(chalk23.yellow("\nCancelled."));
19643
19751
  return;
19644
19752
  }
19645
19753
  envName = r.name;
@@ -19652,8 +19760,8 @@ async function environmentCreateCommand(name, options) {
19652
19760
  const repos2 = await orgAuthenticatedFetch("/v1/repositories");
19653
19761
  const repo = repos2.repositories.find((r) => r.name === options.repository);
19654
19762
  if (!repo) {
19655
- console.log(chalk22.red(`Repository not found: ${options.repository}`));
19656
- console.log(chalk22.gray(`Available: ${repos2.repositories.map((r) => r.name).join(", ")}`));
19763
+ console.log(chalk23.red(`Repository not found: ${options.repository}`));
19764
+ console.log(chalk23.gray(`Available: ${repos2.repositories.map((r) => r.name).join(", ")}`));
19657
19765
  process.exit(1);
19658
19766
  }
19659
19767
  repositoryId = repo.id;
@@ -19683,9 +19791,9 @@ async function environmentCreateCommand(name, options) {
19683
19791
  method: "POST",
19684
19792
  body
19685
19793
  });
19686
- console.log(chalk22.green(`
19794
+ console.log(chalk23.green(`
19687
19795
  Created environment: ${response.environment.name}`));
19688
- console.log(chalk22.gray(` ID: ${response.environment.id}
19796
+ console.log(chalk23.gray(` ID: ${response.environment.id}
19689
19797
  `));
19690
19798
  }
19691
19799
  async function environmentEditCommand(idOrName, options) {
@@ -19704,21 +19812,21 @@ async function environmentEditCommand(idOrName, options) {
19704
19812
  const repos2 = await orgAuthenticatedFetch("/v1/repositories");
19705
19813
  const repo = repos2.repositories.find((r) => r.name === options.repository);
19706
19814
  if (!repo) {
19707
- console.log(chalk22.red(`Repository not found: ${options.repository}`));
19815
+ console.log(chalk23.red(`Repository not found: ${options.repository}`));
19708
19816
  process.exit(1);
19709
19817
  }
19710
19818
  body.repository_id = repo.id;
19711
19819
  }
19712
19820
  }
19713
19821
  if (Object.keys(body).length === 0) {
19714
- console.log(chalk22.yellow("\nNo changes specified. Pass --name, --description, --repository, or --system-prompt."));
19822
+ console.log(chalk23.yellow("\nNo changes specified. Pass --name, --description, --repository, or --system-prompt."));
19715
19823
  return;
19716
19824
  }
19717
19825
  const response = await orgAuthenticatedFetch(`/v1/environments/${id}`, {
19718
19826
  method: "PATCH",
19719
19827
  body
19720
19828
  });
19721
- console.log(chalk22.green(`
19829
+ console.log(chalk23.green(`
19722
19830
  Updated environment: ${response.environment.name}
19723
19831
  `));
19724
19832
  }
@@ -19733,20 +19841,20 @@ async function environmentDeleteCommand(idOrName, options) {
19733
19841
  initial: false
19734
19842
  });
19735
19843
  if (!r.confirm) {
19736
- console.log(chalk22.yellow("\nCancelled."));
19844
+ console.log(chalk23.yellow("\nCancelled."));
19737
19845
  return;
19738
19846
  }
19739
19847
  }
19740
19848
  await orgAuthenticatedFetch(`/v1/environments/${id}`, { method: "DELETE" });
19741
- console.log(chalk22.green(`
19849
+ console.log(chalk23.green(`
19742
19850
  Deleted environment ${idOrName}.
19743
19851
  `));
19744
19852
  }
19745
19853
  function printVariable(v, reveal) {
19746
- console.log(chalk22.white(` ${v.key}`));
19747
- console.log(chalk22.gray(` ID: ${v.id}`));
19748
- console.log(chalk22.gray(` Value: ${reveal ? v.value : maskValue(v.value)}`));
19749
- console.log(chalk22.gray(` Updated: ${formatDate2(v.updated_at)}`));
19854
+ console.log(chalk23.white(` ${v.key}`));
19855
+ console.log(chalk23.gray(` ID: ${v.id}`));
19856
+ console.log(chalk23.gray(` Value: ${reveal ? v.value : maskValue(v.value)}`));
19857
+ console.log(chalk23.gray(` Updated: ${formatDate2(v.updated_at)}`));
19750
19858
  console.log();
19751
19859
  }
19752
19860
  async function envVarsListCommand(envIdOrName, options) {
@@ -19756,14 +19864,14 @@ async function envVarsListCommand(envIdOrName, options) {
19756
19864
  `/v1/environments/${id}/variables`
19757
19865
  );
19758
19866
  if (response.environment_variables.length === 0) {
19759
- console.log(chalk22.yellow("\nNo variables.\n"));
19867
+ console.log(chalk23.yellow("\nNo variables.\n"));
19760
19868
  return;
19761
19869
  }
19762
- console.log(chalk22.green(`
19870
+ console.log(chalk23.green(`
19763
19871
  Variables (${response.environment_variables.length}):
19764
19872
  `));
19765
19873
  if (!options.reveal) {
19766
- console.log(chalk22.gray(" Values are masked. Pass --reveal to show full values.\n"));
19874
+ console.log(chalk23.gray(" Values are masked. Pass --reveal to show full values.\n"));
19767
19875
  }
19768
19876
  for (const v of response.environment_variables) printVariable(v, !!options.reveal);
19769
19877
  }
@@ -19780,7 +19888,7 @@ async function envVarsSetCommand(envIdOrName, key, value) {
19780
19888
  `/v1/environments/${id}/variables/${match.id}`,
19781
19889
  { method: "PATCH", body: body2 }
19782
19890
  );
19783
- console.log(chalk22.green(`
19891
+ console.log(chalk23.green(`
19784
19892
  Updated variable ${response2.environment_variable.key}.
19785
19893
  `));
19786
19894
  return;
@@ -19794,7 +19902,7 @@ Updated variable ${response2.environment_variable.key}.
19794
19902
  `/v1/environments/${id}/variables`,
19795
19903
  { method: "POST", body }
19796
19904
  );
19797
- console.log(chalk22.green(`
19905
+ console.log(chalk23.green(`
19798
19906
  Created variable ${response.environment_variable.key}.
19799
19907
  `));
19800
19908
  }
@@ -19808,7 +19916,7 @@ async function envVarsDeleteCommand(envIdOrName, keyOrId, options) {
19808
19916
  );
19809
19917
  const match = existing.environment_variables.find((v) => v.key === keyOrId);
19810
19918
  if (!match) {
19811
- console.log(chalk22.red(`Variable not found: ${keyOrId}`));
19919
+ console.log(chalk23.red(`Variable not found: ${keyOrId}`));
19812
19920
  process.exit(1);
19813
19921
  }
19814
19922
  variableId = match.id;
@@ -19821,23 +19929,23 @@ async function envVarsDeleteCommand(envIdOrName, keyOrId, options) {
19821
19929
  initial: false
19822
19930
  });
19823
19931
  if (!r.confirm) {
19824
- console.log(chalk22.yellow("\nCancelled."));
19932
+ console.log(chalk23.yellow("\nCancelled."));
19825
19933
  return;
19826
19934
  }
19827
19935
  }
19828
19936
  await orgAuthenticatedFetch(`/v1/environments/${id}/variables/${variableId}`, {
19829
19937
  method: "DELETE"
19830
19938
  });
19831
- console.log(chalk22.green(`
19939
+ console.log(chalk23.green(`
19832
19940
  Deleted variable ${keyOrId}.
19833
19941
  `));
19834
19942
  }
19835
19943
  function printFile(f) {
19836
- console.log(chalk22.white(` ${f.path}`));
19837
- console.log(chalk22.gray(` ID: ${f.id}`));
19838
- console.log(chalk22.gray(` Name: ${f.name}`));
19839
- console.log(chalk22.gray(` Size: ${f.content.length} bytes`));
19840
- console.log(chalk22.gray(` Updated: ${formatDate2(f.updated_at)}`));
19944
+ console.log(chalk23.white(` ${f.path}`));
19945
+ console.log(chalk23.gray(` ID: ${f.id}`));
19946
+ console.log(chalk23.gray(` Name: ${f.name}`));
19947
+ console.log(chalk23.gray(` Size: ${f.content.length} bytes`));
19948
+ console.log(chalk23.gray(` Updated: ${formatDate2(f.updated_at)}`));
19841
19949
  console.log();
19842
19950
  }
19843
19951
  async function envFilesListCommand(envIdOrName) {
@@ -19847,10 +19955,10 @@ async function envFilesListCommand(envIdOrName) {
19847
19955
  `/v1/environments/${id}/files`
19848
19956
  );
19849
19957
  if (response.environment_files.length === 0) {
19850
- console.log(chalk22.yellow("\nNo files.\n"));
19958
+ console.log(chalk23.yellow("\nNo files.\n"));
19851
19959
  return;
19852
19960
  }
19853
- console.log(chalk22.green(`
19961
+ console.log(chalk23.green(`
19854
19962
  Files (${response.environment_files.length}):
19855
19963
  `));
19856
19964
  for (const f of response.environment_files) printFile(f);
@@ -19881,7 +19989,7 @@ async function envFilesSetCommand(envIdOrName, destinationPath, options) {
19881
19989
  `/v1/environments/${id}/files/${match.id}`,
19882
19990
  { method: "PATCH", body: body2 }
19883
19991
  );
19884
- console.log(chalk22.green(`
19992
+ console.log(chalk23.green(`
19885
19993
  Updated file ${response2.environment_file.path}.
19886
19994
  `));
19887
19995
  return;
@@ -19896,7 +20004,7 @@ Updated file ${response2.environment_file.path}.
19896
20004
  `/v1/environments/${id}/files`,
19897
20005
  { method: "POST", body }
19898
20006
  );
19899
- console.log(chalk22.green(`
20007
+ console.log(chalk23.green(`
19900
20008
  Created file ${response.environment_file.path}.
19901
20009
  `));
19902
20010
  }
@@ -19910,7 +20018,7 @@ async function envFilesDeleteCommand(envIdOrName, pathOrId, options) {
19910
20018
  );
19911
20019
  const match = existing.environment_files.find((f) => f.path === pathOrId);
19912
20020
  if (!match) {
19913
- console.log(chalk22.red(`File not found: ${pathOrId}`));
20021
+ console.log(chalk23.red(`File not found: ${pathOrId}`));
19914
20022
  process.exit(1);
19915
20023
  }
19916
20024
  fileId = match.id;
@@ -19923,14 +20031,14 @@ async function envFilesDeleteCommand(envIdOrName, pathOrId, options) {
19923
20031
  initial: false
19924
20032
  });
19925
20033
  if (!r.confirm) {
19926
- console.log(chalk22.yellow("\nCancelled."));
20034
+ console.log(chalk23.yellow("\nCancelled."));
19927
20035
  return;
19928
20036
  }
19929
20037
  }
19930
20038
  await orgAuthenticatedFetch(`/v1/environments/${id}/files/${fileId}`, {
19931
20039
  method: "DELETE"
19932
20040
  });
19933
- console.log(chalk22.green(`
20041
+ console.log(chalk23.green(`
19934
20042
  Deleted file ${pathOrId}.
19935
20043
  `));
19936
20044
  }
@@ -19941,15 +20049,15 @@ async function envStartHookGetCommand(envIdOrName) {
19941
20049
  `/v1/environments/${id}/start-hooks`
19942
20050
  );
19943
20051
  if (!response.start_hook) {
19944
- console.log(chalk22.yellow("\nNo start hook configured.\n"));
20052
+ console.log(chalk23.yellow("\nNo start hook configured.\n"));
19945
20053
  return;
19946
20054
  }
19947
20055
  const hook = response.start_hook;
19948
- console.log(chalk22.green(`
20056
+ console.log(chalk23.green(`
19949
20057
  Start hook (v${hook.version}, ${hook.is_active ? "active" : "inactive"}):
19950
20058
  `));
19951
- console.log(chalk22.gray(` ID: ${hook.id}`));
19952
- console.log(chalk22.gray(` Created: ${formatDate2(hook.created_at)}
20059
+ console.log(chalk23.gray(` ID: ${hook.id}`));
20060
+ console.log(chalk23.gray(` Created: ${formatDate2(hook.created_at)}
19953
20061
  `));
19954
20062
  console.log(hook.content);
19955
20063
  console.log();
@@ -19964,10 +20072,10 @@ async function envStartHookSaveCommand(envIdOrName, options) {
19964
20072
  { method: "POST", body }
19965
20073
  );
19966
20074
  if (!response.start_hook) {
19967
- console.log(chalk22.green("\nCleared start hook.\n"));
20075
+ console.log(chalk23.green("\nCleared start hook.\n"));
19968
20076
  return;
19969
20077
  }
19970
- console.log(chalk22.green(`
20078
+ console.log(chalk23.green(`
19971
20079
  Saved start hook v${response.start_hook.version}.
19972
20080
  `));
19973
20081
  }
@@ -19984,7 +20092,7 @@ async function envStartHookTestCommand(envIdOrName, options) {
19984
20092
  body: { content },
19985
20093
  onEvent: (event) => {
19986
20094
  if (event.type === "progress" && event.message) {
19987
- console.log(chalk22.gray(event.message));
20095
+ console.log(chalk23.gray(event.message));
19988
20096
  } else if (event.type === "output" && event.output) {
19989
20097
  process.stdout.write(event.output);
19990
20098
  } else if (event.type === "complete") {
@@ -19997,21 +20105,21 @@ async function envStartHookTestCommand(envIdOrName, options) {
19997
20105
  }
19998
20106
  );
19999
20107
  if (errorMessage) {
20000
- console.log(chalk22.red(`
20108
+ console.log(chalk23.red(`
20001
20109
  ${errorMessage}
20002
20110
  `));
20003
20111
  process.exit(1);
20004
20112
  }
20005
20113
  if (timedOut) {
20006
- console.log(chalk22.yellow("\nStart hook timed out.\n"));
20114
+ console.log(chalk23.yellow("\nStart hook timed out.\n"));
20007
20115
  process.exit(1);
20008
20116
  }
20009
20117
  if (exitCode === 0) {
20010
- console.log(chalk22.green(`
20118
+ console.log(chalk23.green(`
20011
20119
  Start hook passed (exit code ${exitCode}).
20012
20120
  `));
20013
20121
  } else {
20014
- console.log(chalk22.red(`
20122
+ console.log(chalk23.red(`
20015
20123
  Start hook failed (exit code ${exitCode ?? "unknown"}).
20016
20124
  `));
20017
20125
  process.exit(1);
@@ -20024,24 +20132,24 @@ async function envStartHookRepositoryHooksCommand(envIdOrName) {
20024
20132
  `/v1/environments/${id}/start-hooks/repository-hooks`
20025
20133
  );
20026
20134
  if (response.repositories.length === 0) {
20027
- console.log(chalk22.yellow("\nNo repositories bound to this environment.\n"));
20135
+ console.log(chalk23.yellow("\nNo repositories bound to this environment.\n"));
20028
20136
  return;
20029
20137
  }
20030
- console.log(chalk22.green(`
20138
+ console.log(chalk23.green(`
20031
20139
  Repository start hooks (${response.repositories.length}):
20032
20140
  `));
20033
20141
  for (const repo of response.repositories) {
20034
- console.log(chalk22.white(` ${repo.repository_name} @${repo.default_branch}`));
20142
+ console.log(chalk23.white(` ${repo.repository_name} @${repo.default_branch}`));
20035
20143
  if (repo.error) {
20036
- console.log(chalk22.red(` Error: ${repo.error}`));
20144
+ console.log(chalk23.red(` Error: ${repo.error}`));
20037
20145
  } else if (repo.start_hook) {
20038
- console.log(chalk22.gray(` Source: ${repo.filename ?? "(unknown)"}`));
20039
- console.log(chalk22.gray(` Commands (${repo.start_hook.commands.length}):`));
20146
+ console.log(chalk23.gray(` Source: ${repo.filename ?? "(unknown)"}`));
20147
+ console.log(chalk23.gray(` Commands (${repo.start_hook.commands.length}):`));
20040
20148
  for (const cmd of repo.start_hook.commands) {
20041
- console.log(chalk22.gray(` ${cmd}`));
20149
+ console.log(chalk23.gray(` ${cmd}`));
20042
20150
  }
20043
20151
  } else {
20044
- console.log(chalk22.gray(` No startHook defined.`));
20152
+ console.log(chalk23.gray(` No startHook defined.`));
20045
20153
  }
20046
20154
  console.log();
20047
20155
  }
@@ -20055,12 +20163,41 @@ function parseBooleanOption(value) {
20055
20163
  }
20056
20164
  var program = new Command();
20057
20165
  program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
20166
+ function registerSlackCommands(parent) {
20167
+ const slack = parent.command("slack").description("Manage Slack thread routing");
20168
+ const slackThread = slack.command("thread").description("Attach or switch the Slack thread that routes to a workspace");
20169
+ slackThread.command("attach").description("Attach the current Slack thread to this workspace").option("-c, --channel <channelId>", "Slack channel ID (defaults to SLACK_CHANNEL_ID)").option("-t, --thread-ts <threadTs>", "Slack thread timestamp (defaults to SLACK_THREAD_TS)").action(async (options) => {
20170
+ try {
20171
+ await slackThreadAttachCommand(options);
20172
+ } catch (error) {
20173
+ if (error instanceof Error) {
20174
+ console.error(chalk24.red(`
20175
+ \u2717 ${error.message}
20176
+ `));
20177
+ }
20178
+ process.exit(1);
20179
+ }
20180
+ });
20181
+ slackThread.command("switch <workspace>").description("Point the current Slack thread at another workspace ID or name").option("-c, --channel <channelId>", "Slack channel ID (defaults to SLACK_CHANNEL_ID)").option("-t, --thread-ts <threadTs>", "Slack thread timestamp (defaults to SLACK_THREAD_TS)").action(async (workspace, options) => {
20182
+ try {
20183
+ await slackThreadSwitchCommand(workspace, options);
20184
+ } catch (error) {
20185
+ if (error instanceof Error) {
20186
+ console.error(chalk24.red(`
20187
+ \u2717 ${error.message}
20188
+ `));
20189
+ }
20190
+ process.exit(1);
20191
+ }
20192
+ });
20193
+ }
20194
+ registerSlackCommands(program);
20058
20195
  program.command("login").description("Authenticate with your Replicas account").action(async () => {
20059
20196
  try {
20060
20197
  await loginCommand();
20061
20198
  } catch (error) {
20062
20199
  if (error instanceof Error) {
20063
- console.error(chalk23.red(`
20200
+ console.error(chalk24.red(`
20064
20201
  \u2717 ${error.message}
20065
20202
  `));
20066
20203
  }
@@ -20072,7 +20209,7 @@ program.command("init").description("Create a replicas.json or replicas.yaml con
20072
20209
  initCommand(options);
20073
20210
  } catch (error) {
20074
20211
  if (error instanceof Error) {
20075
- console.error(chalk23.red(`
20212
+ console.error(chalk24.red(`
20076
20213
  \u2717 ${error.message}
20077
20214
  `));
20078
20215
  }
@@ -20084,7 +20221,7 @@ program.command("logout").description("Clear stored credentials").action(() => {
20084
20221
  logoutCommand();
20085
20222
  } catch (error) {
20086
20223
  if (error instanceof Error) {
20087
- console.error(chalk23.red(`
20224
+ console.error(chalk24.red(`
20088
20225
  \u2717 ${error.message}
20089
20226
  `));
20090
20227
  }
@@ -20096,7 +20233,7 @@ program.command("whoami").description("Display current authenticated user").acti
20096
20233
  await whoamiCommand();
20097
20234
  } catch (error) {
20098
20235
  if (error instanceof Error) {
20099
- console.error(chalk23.red(`
20236
+ console.error(chalk24.red(`
20100
20237
  \u2717 ${error.message}
20101
20238
  `));
20102
20239
  }
@@ -20108,7 +20245,7 @@ program.command("codex-auth").description("Authenticate Replicas with your Codex
20108
20245
  await codexAuthCommand(options);
20109
20246
  } catch (error) {
20110
20247
  if (error instanceof Error) {
20111
- console.error(chalk23.red(`
20248
+ console.error(chalk24.red(`
20112
20249
  \u2717 ${error.message}
20113
20250
  `));
20114
20251
  }
@@ -20120,7 +20257,7 @@ program.command("claude-auth").description("Authenticate Replicas with your Clau
20120
20257
  await claudeAuthCommand(options);
20121
20258
  } catch (error) {
20122
20259
  if (error instanceof Error) {
20123
- console.error(chalk23.red(`
20260
+ console.error(chalk24.red(`
20124
20261
  \u2717 ${error.message}
20125
20262
  `));
20126
20263
  }
@@ -20133,7 +20270,7 @@ org.command("switch").description("Switch to a different organization").action(a
20133
20270
  await orgSwitchCommand();
20134
20271
  } catch (error) {
20135
20272
  if (error instanceof Error) {
20136
- console.error(chalk23.red(`
20273
+ console.error(chalk24.red(`
20137
20274
  \u2717 ${error.message}
20138
20275
  `));
20139
20276
  }
@@ -20145,7 +20282,7 @@ org.action(async () => {
20145
20282
  await orgCommand();
20146
20283
  } catch (error) {
20147
20284
  if (error instanceof Error) {
20148
- console.error(chalk23.red(`
20285
+ console.error(chalk24.red(`
20149
20286
  \u2717 ${error.message}
20150
20287
  `));
20151
20288
  }
@@ -20157,7 +20294,7 @@ program.command("connect <workspace-name>").description("Connect to a workspace
20157
20294
  await connectCommand(workspaceName);
20158
20295
  } catch (error) {
20159
20296
  if (error instanceof Error) {
20160
- console.error(chalk23.red(`
20297
+ console.error(chalk24.red(`
20161
20298
  \u2717 ${error.message}
20162
20299
  `));
20163
20300
  }
@@ -20169,7 +20306,7 @@ program.command("code <workspace-name>").description("Open a workspace in VSCode
20169
20306
  await codeCommand(workspaceName);
20170
20307
  } catch (error) {
20171
20308
  if (error instanceof Error) {
20172
- console.error(chalk23.red(`
20309
+ console.error(chalk24.red(`
20173
20310
  \u2717 ${error.message}
20174
20311
  `));
20175
20312
  }
@@ -20182,7 +20319,7 @@ config.command("get <key>").description("Get a configuration value").action(asyn
20182
20319
  await configGetCommand(key);
20183
20320
  } catch (error) {
20184
20321
  if (error instanceof Error) {
20185
- console.error(chalk23.red(`
20322
+ console.error(chalk24.red(`
20186
20323
  \u2717 ${error.message}
20187
20324
  `));
20188
20325
  }
@@ -20194,7 +20331,7 @@ config.command("set <key> <value>").description("Set a configuration value").act
20194
20331
  await configSetCommand(key, value);
20195
20332
  } catch (error) {
20196
20333
  if (error instanceof Error) {
20197
- console.error(chalk23.red(`
20334
+ console.error(chalk24.red(`
20198
20335
  \u2717 ${error.message}
20199
20336
  `));
20200
20337
  }
@@ -20206,7 +20343,7 @@ config.command("list").description("List all configuration values").action(async
20206
20343
  await configListCommand();
20207
20344
  } catch (error) {
20208
20345
  if (error instanceof Error) {
20209
- console.error(chalk23.red(`
20346
+ console.error(chalk24.red(`
20210
20347
  \u2717 ${error.message}
20211
20348
  `));
20212
20349
  }
@@ -20218,7 +20355,7 @@ program.command("list").description("List all replicas").option("-p, --page <pag
20218
20355
  await replicaListCommand(options);
20219
20356
  } catch (error) {
20220
20357
  if (error instanceof Error) {
20221
- console.error(chalk23.red(`
20358
+ console.error(chalk24.red(`
20222
20359
  \u2717 ${error.message}
20223
20360
  `));
20224
20361
  }
@@ -20230,7 +20367,7 @@ program.command("get <id>").description("Get replica details by ID").action(asyn
20230
20367
  await replicaGetCommand(id);
20231
20368
  } catch (error) {
20232
20369
  if (error instanceof Error) {
20233
- console.error(chalk23.red(`
20370
+ console.error(chalk24.red(`
20234
20371
  \u2717 ${error.message}
20235
20372
  `));
20236
20373
  }
@@ -20242,7 +20379,7 @@ program.command("create [name]").description("Create a new replica").option("-m,
20242
20379
  await replicaCreateCommand(name, options);
20243
20380
  } catch (error) {
20244
20381
  if (error instanceof Error) {
20245
- console.error(chalk23.red(`
20382
+ console.error(chalk24.red(`
20246
20383
  \u2717 ${error.message}
20247
20384
  `));
20248
20385
  }
@@ -20254,7 +20391,7 @@ program.command("send <id>").description("Send a message to a replica").option("
20254
20391
  await replicaSendCommand(id, options);
20255
20392
  } catch (error) {
20256
20393
  if (error instanceof Error) {
20257
- console.error(chalk23.red(`
20394
+ console.error(chalk24.red(`
20258
20395
  \u2717 ${error.message}
20259
20396
  `));
20260
20397
  }
@@ -20266,7 +20403,7 @@ program.command("delete <id>").description("Delete a replica").option("-f, --for
20266
20403
  await replicaDeleteCommand(id, options);
20267
20404
  } catch (error) {
20268
20405
  if (error instanceof Error) {
20269
- console.error(chalk23.red(`
20406
+ console.error(chalk24.red(`
20270
20407
  \u2717 ${error.message}
20271
20408
  `));
20272
20409
  }
@@ -20278,7 +20415,7 @@ program.command("read <id>").description("Read conversation history of a replica
20278
20415
  await replicaReadCommand(id, options);
20279
20416
  } catch (error) {
20280
20417
  if (error instanceof Error) {
20281
- console.error(chalk23.red(`
20418
+ console.error(chalk24.red(`
20282
20419
  \u2717 ${error.message}
20283
20420
  `));
20284
20421
  }
@@ -20291,7 +20428,7 @@ automation.command("list").description("List all automations").option("-p, --pag
20291
20428
  await automationListCommand(options);
20292
20429
  } catch (error) {
20293
20430
  if (error instanceof Error) {
20294
- console.error(chalk23.red(`
20431
+ console.error(chalk24.red(`
20295
20432
  \u2717 ${error.message}
20296
20433
  `));
20297
20434
  }
@@ -20303,7 +20440,7 @@ automation.command("get <id>").description("Get automation details by ID").actio
20303
20440
  await automationGetCommand(id);
20304
20441
  } catch (error) {
20305
20442
  if (error instanceof Error) {
20306
- console.error(chalk23.red(`
20443
+ console.error(chalk24.red(`
20307
20444
  \u2717 ${error.message}
20308
20445
  `));
20309
20446
  }
@@ -20318,7 +20455,7 @@ automation.command("create [name]").description("Create a new automation").optio
20318
20455
  });
20319
20456
  } catch (error) {
20320
20457
  if (error instanceof Error) {
20321
- console.error(chalk23.red(`
20458
+ console.error(chalk24.red(`
20322
20459
  \u2717 ${error.message}
20323
20460
  `));
20324
20461
  }
@@ -20330,7 +20467,7 @@ automation.command("edit <id>").description("Edit an existing automation").optio
20330
20467
  await automationEditCommand(id, options);
20331
20468
  } catch (error) {
20332
20469
  if (error instanceof Error) {
20333
- console.error(chalk23.red(`
20470
+ console.error(chalk24.red(`
20334
20471
  \u2717 ${error.message}
20335
20472
  `));
20336
20473
  }
@@ -20342,7 +20479,7 @@ automation.command("run <id>").description("Manually trigger an automation (cron
20342
20479
  await automationRunCommand(id);
20343
20480
  } catch (error) {
20344
20481
  if (error instanceof Error) {
20345
- console.error(chalk23.red(`
20482
+ console.error(chalk24.red(`
20346
20483
  \u2717 ${error.message}
20347
20484
  `));
20348
20485
  }
@@ -20354,7 +20491,7 @@ automation.command("delete <id>").description("Delete an automation").option("-f
20354
20491
  await automationDeleteCommand(id, options);
20355
20492
  } catch (error) {
20356
20493
  if (error instanceof Error) {
20357
- console.error(chalk23.red(`
20494
+ console.error(chalk24.red(`
20358
20495
  \u2717 ${error.message}
20359
20496
  `));
20360
20497
  }
@@ -20366,7 +20503,7 @@ automation.action(async () => {
20366
20503
  await automationListCommand({});
20367
20504
  } catch (error) {
20368
20505
  if (error instanceof Error) {
20369
- console.error(chalk23.red(`
20506
+ console.error(chalk24.red(`
20370
20507
  \u2717 ${error.message}
20371
20508
  `));
20372
20509
  }
@@ -20379,7 +20516,7 @@ repos.command("list").description("List all repositories").action(async () => {
20379
20516
  await repositoriesListCommand();
20380
20517
  } catch (error) {
20381
20518
  if (error instanceof Error) {
20382
- console.error(chalk23.red(`
20519
+ console.error(chalk24.red(`
20383
20520
  \u2717 ${error.message}
20384
20521
  `));
20385
20522
  }
@@ -20391,7 +20528,7 @@ repos.action(async () => {
20391
20528
  await repositoriesListCommand();
20392
20529
  } catch (error) {
20393
20530
  if (error instanceof Error) {
20394
- console.error(chalk23.red(`
20531
+ console.error(chalk24.red(`
20395
20532
  \u2717 ${error.message}
20396
20533
  `));
20397
20534
  }
@@ -20404,7 +20541,7 @@ environment.command("list").description("List all environments").action(async ()
20404
20541
  await environmentListCommand();
20405
20542
  } catch (error) {
20406
20543
  if (error instanceof Error) {
20407
- console.error(chalk23.red(`
20544
+ console.error(chalk24.red(`
20408
20545
  \u2717 ${error.message}
20409
20546
  `));
20410
20547
  }
@@ -20416,7 +20553,7 @@ environment.command("get <id-or-name>").description('Get an environment by ID or
20416
20553
  await environmentGetCommand(idOrName);
20417
20554
  } catch (error) {
20418
20555
  if (error instanceof Error) {
20419
- console.error(chalk23.red(`
20556
+ console.error(chalk24.red(`
20420
20557
  \u2717 ${error.message}
20421
20558
  `));
20422
20559
  }
@@ -20428,7 +20565,7 @@ environment.command("create [name]").description("Create a new environment").opt
20428
20565
  await environmentCreateCommand(name, options);
20429
20566
  } catch (error) {
20430
20567
  if (error instanceof Error) {
20431
- console.error(chalk23.red(`
20568
+ console.error(chalk24.red(`
20432
20569
  \u2717 ${error.message}
20433
20570
  `));
20434
20571
  }
@@ -20440,7 +20577,7 @@ environment.command("edit <id-or-name>").description("Edit an environment").opti
20440
20577
  await environmentEditCommand(idOrName, options);
20441
20578
  } catch (error) {
20442
20579
  if (error instanceof Error) {
20443
- console.error(chalk23.red(`
20580
+ console.error(chalk24.red(`
20444
20581
  \u2717 ${error.message}
20445
20582
  `));
20446
20583
  }
@@ -20452,7 +20589,7 @@ environment.command("delete <id-or-name>").description("Delete an environment").
20452
20589
  await environmentDeleteCommand(idOrName, options);
20453
20590
  } catch (error) {
20454
20591
  if (error instanceof Error) {
20455
- console.error(chalk23.red(`
20592
+ console.error(chalk24.red(`
20456
20593
  \u2717 ${error.message}
20457
20594
  `));
20458
20595
  }
@@ -20465,7 +20602,7 @@ envVars.command("list <env>").description("List variables in an environment (val
20465
20602
  await envVarsListCommand(env, options);
20466
20603
  } catch (error) {
20467
20604
  if (error instanceof Error) {
20468
- console.error(chalk23.red(`
20605
+ console.error(chalk24.red(`
20469
20606
  \u2717 ${error.message}
20470
20607
  `));
20471
20608
  }
@@ -20477,7 +20614,7 @@ envVars.command("set <env> <key> <value>").description("Create or update a varia
20477
20614
  await envVarsSetCommand(env, key, value);
20478
20615
  } catch (error) {
20479
20616
  if (error instanceof Error) {
20480
- console.error(chalk23.red(`
20617
+ console.error(chalk24.red(`
20481
20618
  \u2717 ${error.message}
20482
20619
  `));
20483
20620
  }
@@ -20489,7 +20626,7 @@ envVars.command("delete <env> <key-or-id>").description("Delete a variable by ke
20489
20626
  await envVarsDeleteCommand(env, keyOrId, options);
20490
20627
  } catch (error) {
20491
20628
  if (error instanceof Error) {
20492
- console.error(chalk23.red(`
20629
+ console.error(chalk24.red(`
20493
20630
  \u2717 ${error.message}
20494
20631
  `));
20495
20632
  }
@@ -20502,7 +20639,7 @@ envFiles.command("list <env>").description("List files in an environment").actio
20502
20639
  await envFilesListCommand(env);
20503
20640
  } catch (error) {
20504
20641
  if (error instanceof Error) {
20505
- console.error(chalk23.red(`
20642
+ console.error(chalk24.red(`
20506
20643
  \u2717 ${error.message}
20507
20644
  `));
20508
20645
  }
@@ -20514,7 +20651,7 @@ envFiles.command("set <env> <destination-path>").description("Create or update a
20514
20651
  await envFilesSetCommand(env, destinationPath, options);
20515
20652
  } catch (error) {
20516
20653
  if (error instanceof Error) {
20517
- console.error(chalk23.red(`
20654
+ console.error(chalk24.red(`
20518
20655
  \u2717 ${error.message}
20519
20656
  `));
20520
20657
  }
@@ -20526,7 +20663,7 @@ envFiles.command("delete <env> <path-or-id>").description("Delete a file by dest
20526
20663
  await envFilesDeleteCommand(env, pathOrId, options);
20527
20664
  } catch (error) {
20528
20665
  if (error instanceof Error) {
20529
- console.error(chalk23.red(`
20666
+ console.error(chalk24.red(`
20530
20667
  \u2717 ${error.message}
20531
20668
  `));
20532
20669
  }
@@ -20539,7 +20676,7 @@ envStartHooks.command("get <env>").description("Show the active start hook for a
20539
20676
  await envStartHookGetCommand(env);
20540
20677
  } catch (error) {
20541
20678
  if (error instanceof Error) {
20542
- console.error(chalk23.red(`
20679
+ console.error(chalk24.red(`
20543
20680
  \u2717 ${error.message}
20544
20681
  `));
20545
20682
  }
@@ -20551,7 +20688,7 @@ envStartHooks.command("save <env>").description("Save and activate a start hook
20551
20688
  await envStartHookSaveCommand(env, options);
20552
20689
  } catch (error) {
20553
20690
  if (error instanceof Error) {
20554
- console.error(chalk23.red(`
20691
+ console.error(chalk24.red(`
20555
20692
  \u2717 ${error.message}
20556
20693
  `));
20557
20694
  }
@@ -20563,7 +20700,7 @@ envStartHooks.command("test <env>").description("Run a start hook in an isolated
20563
20700
  await envStartHookTestCommand(env, options);
20564
20701
  } catch (error) {
20565
20702
  if (error instanceof Error) {
20566
- console.error(chalk23.red(`
20703
+ console.error(chalk24.red(`
20567
20704
  \u2717 ${error.message}
20568
20705
  `));
20569
20706
  }
@@ -20575,7 +20712,7 @@ envStartHooks.command("repository-hooks <env>").description("List per-repo start
20575
20712
  await envStartHookRepositoryHooksCommand(env);
20576
20713
  } catch (error) {
20577
20714
  if (error instanceof Error) {
20578
- console.error(chalk23.red(`
20715
+ console.error(chalk24.red(`
20579
20716
  \u2717 ${error.message}
20580
20717
  `));
20581
20718
  }
@@ -20587,7 +20724,7 @@ environment.action(async () => {
20587
20724
  await environmentListCommand();
20588
20725
  } catch (error) {
20589
20726
  if (error instanceof Error) {
20590
- console.error(chalk23.red(`
20727
+ console.error(chalk24.red(`
20591
20728
  \u2717 ${error.message}
20592
20729
  `));
20593
20730
  }
@@ -20599,7 +20736,7 @@ program.command("interact").alias("i").description("Launch the interactive termi
20599
20736
  await interactiveCommand();
20600
20737
  } catch (error) {
20601
20738
  if (error instanceof Error) {
20602
- console.error(chalk23.red(`
20739
+ console.error(chalk24.red(`
20603
20740
  \u2717 ${error.message}
20604
20741
  `));
20605
20742
  }
@@ -20650,7 +20787,7 @@ if (isAgentMode()) {
20650
20787
  await previewAddCommand(workspaceId, options);
20651
20788
  } catch (error) {
20652
20789
  if (error instanceof Error) {
20653
- console.error(chalk23.red(`
20790
+ console.error(chalk24.red(`
20654
20791
  \u2717 ${error.message}
20655
20792
  `));
20656
20793
  }
@@ -20662,7 +20799,7 @@ if (isAgentMode()) {
20662
20799
  await previewListCommand(workspaceId);
20663
20800
  } catch (error) {
20664
20801
  if (error instanceof Error) {
20665
- console.error(chalk23.red(`
20802
+ console.error(chalk24.red(`
20666
20803
  \u2717 ${error.message}
20667
20804
  `));
20668
20805
  }
@@ -20674,7 +20811,7 @@ if (isAgentMode()) {
20674
20811
  await previewRemoveCommand(workspaceId, options);
20675
20812
  } catch (error) {
20676
20813
  if (error instanceof Error) {
20677
- console.error(chalk23.red(`
20814
+ console.error(chalk24.red(`
20678
20815
  \u2717 ${error.message}
20679
20816
  `));
20680
20817
  }
@@ -20689,7 +20826,7 @@ if (isAgentMode()) {
20689
20826
  await mediaUploadCommand(files, options);
20690
20827
  } catch (error) {
20691
20828
  if (error instanceof Error) {
20692
- console.error(chalk23.red(`
20829
+ console.error(chalk24.red(`
20693
20830
  \u2717 ${error.message}
20694
20831
  `));
20695
20832
  }
@@ -20701,7 +20838,7 @@ if (isAgentMode()) {
20701
20838
  await mediaListCommand(options);
20702
20839
  } catch (error) {
20703
20840
  if (error instanceof Error) {
20704
- console.error(chalk23.red(`
20841
+ console.error(chalk24.red(`
20705
20842
  \u2717 ${error.message}
20706
20843
  `));
20707
20844
  }
@@ -20714,7 +20851,7 @@ if (isAgentMode()) {
20714
20851
  await learningsReadCommand(options);
20715
20852
  } catch (error) {
20716
20853
  if (error instanceof Error) {
20717
- console.error(chalk23.red(`
20854
+ console.error(chalk24.red(`
20718
20855
  \u2717 ${error.message}
20719
20856
  `));
20720
20857
  }
@@ -20726,7 +20863,7 @@ if (isAgentMode()) {
20726
20863
  await learningsAddCommand(options);
20727
20864
  } catch (error) {
20728
20865
  if (error instanceof Error) {
20729
- console.error(chalk23.red(`
20866
+ console.error(chalk24.red(`
20730
20867
  \u2717 ${error.message}
20731
20868
  `));
20732
20869
  }
@@ -20738,7 +20875,7 @@ if (isAgentMode()) {
20738
20875
  await learningsUpdateCommand(id, options);
20739
20876
  } catch (error) {
20740
20877
  if (error instanceof Error) {
20741
- console.error(chalk23.red(`
20878
+ console.error(chalk24.red(`
20742
20879
  \u2717 ${error.message}
20743
20880
  `));
20744
20881
  }
@@ -20750,7 +20887,7 @@ if (isAgentMode()) {
20750
20887
  await learningsDeleteCommand(id);
20751
20888
  } catch (error) {
20752
20889
  if (error instanceof Error) {
20753
- console.error(chalk23.red(`
20890
+ console.error(chalk24.red(`
20754
20891
  \u2717 ${error.message}
20755
20892
  `));
20756
20893
  }
@@ -20763,7 +20900,7 @@ if (isAgentMode()) {
20763
20900
  await fn(...args);
20764
20901
  } catch (error) {
20765
20902
  if (error instanceof Error) {
20766
- console.error(chalk23.red(`
20903
+ console.error(chalk24.red(`
20767
20904
  \u2717 ${error.message}
20768
20905
  `));
20769
20906
  }
@@ -20791,9 +20928,11 @@ if (isAgentMode()) {
20791
20928
  const allowed = /* @__PURE__ */ new Set([
20792
20929
  "init",
20793
20930
  "whoami",
20931
+ "list",
20794
20932
  "connect",
20795
20933
  "preview",
20796
20934
  "media",
20935
+ "slack",
20797
20936
  "computer",
20798
20937
  "automation",
20799
20938
  "repos",