replicas-cli 0.2.171 → 0.2.172

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 +102 -218
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8065,8 +8065,7 @@ var SANDBOX_PATHS = {
8065
8065
  REPLICAS_DIR: "/home/ubuntu/.replicas",
8066
8066
  REPLICAS_FILES_DIR: "/home/ubuntu/.replicas/files",
8067
8067
  REPLICAS_FILES_DISPLAY_DIR: "~/.replicas/files",
8068
- REPLICAS_RUNTIME_ENV_FILE: "/home/ubuntu/.replicas/runtime-env.sh",
8069
- REPLICAS_PREVIEW_PORTS_FILE: "/home/ubuntu/.replicas/preview-ports.json"
8068
+ REPLICAS_RUNTIME_ENV_FILE: "/home/ubuntu/.replicas/runtime-env.sh"
8070
8069
  };
8071
8070
 
8072
8071
  // ../shared/src/urls.ts
@@ -8174,6 +8173,7 @@ function workspaceConfigWithPrFollowups(config2, prFollowups = config2?.capabili
8174
8173
  }
8175
8174
  var WORKSPACE_FILE_UPLOAD_MAX_SIZE_BYTES = 20 * 1024 * 1024;
8176
8175
  var WORKSPACE_FILE_CONTENT_MAX_SIZE_BYTES = 1 * 1024 * 1024;
8176
+ var WORKSPACE_SIDEBAR_VIEWS = ["owned", "shared", "team", "automation", "integrations", "api"];
8177
8177
 
8178
8178
  // ../shared/src/audit-log.ts
8179
8179
  var AUDIT_LOG_ACTION = {
@@ -9211,74 +9211,8 @@ var SOURCE_CONFIG = {
9211
9211
  merged: { label: "Merged", color: "#a78bfa" }
9212
9212
  };
9213
9213
 
9214
- // ../shared/src/placeholder-names.ts
9215
- var FRUITS = [
9216
- "apple",
9217
- "banana",
9218
- "cherry",
9219
- "fig",
9220
- "grape",
9221
- "kiwi",
9222
- "lemon",
9223
- "lime",
9224
- "mango",
9225
- "melon",
9226
- "olive",
9227
- "orange",
9228
- "peach",
9229
- "pear",
9230
- "plum",
9231
- "guava",
9232
- "papaya",
9233
- "lychee",
9234
- "coconut",
9235
- "apricot",
9236
- "avocado",
9237
- "berry",
9238
- "kumquat",
9239
- "nectarine",
9240
- "tangerine",
9241
- "dragonfruit"
9242
- ];
9243
- var TTC_STATIONS = [
9244
- "kipling",
9245
- "islington",
9246
- "royal-york",
9247
- "old-mill",
9248
- "jane",
9249
- "runnymede",
9250
- "high-park",
9251
- "keele",
9252
- "dundas-west",
9253
- "lansdowne",
9254
- "dufferin",
9255
- "ossington",
9256
- "christie",
9257
- "bathurst",
9258
- "spadina",
9259
- "st-george",
9260
- "bay",
9261
- "bloor-yonge",
9262
- "sherbourne",
9263
- "castle-frank",
9264
- "broadview",
9265
- "chester",
9266
- "pape",
9267
- "donlands",
9268
- "greenwood",
9269
- "woodbine",
9270
- "warden",
9271
- "kennedy"
9272
- ];
9273
- function randomElement(arr) {
9274
- return arr[Math.floor(Math.random() * arr.length)];
9275
- }
9276
- function generatePlaceholderName() {
9277
- return `${randomElement(FRUITS)}-${randomElement(TTC_STATIONS)}`;
9278
- }
9279
-
9280
9214
  // ../shared/src/workspace-groups.ts
9281
- function buildGroups(workspaces, _workspacesData, environments, _repositorySets, mockGroupAssignments) {
9215
+ function buildGroups(workspaces, _workspacesData, environments, _repositorySets) {
9282
9216
  const groupMap = /* @__PURE__ */ new Map();
9283
9217
  for (const env of environments) {
9284
9218
  groupMap.set(env.id, {
@@ -9311,41 +9245,10 @@ function buildGroups(workspaces, _workspacesData, environments, _repositorySets,
9311
9245
  groupMap.get(workspace.environment_id).workspaces.push(workspace);
9312
9246
  continue;
9313
9247
  }
9314
- const assignedGroup = mockGroupAssignments.get(workspace.id);
9315
- if (assignedGroup && groupMap.has(assignedGroup)) {
9316
- groupMap.get(assignedGroup).workspaces.push(workspace);
9317
- continue;
9318
- }
9319
9248
  placeUngrouped(workspace);
9320
9249
  }
9321
9250
  return Array.from(groupMap.values()).sort((a, b) => a.name.localeCompare(b.name));
9322
9251
  }
9323
- function createMockWorkspaceRecord(organizationId, name, environmentId) {
9324
- const id = "mock-" + Array.from(
9325
- { length: 4 },
9326
- () => Math.random().toString(36).slice(2, 6)
9327
- ).join("-");
9328
- return {
9329
- id,
9330
- user_id: null,
9331
- organization_id: organizationId,
9332
- name: name || generatePlaceholderName(),
9333
- sandbox_id: "",
9334
- engine_url: null,
9335
- engine_secret: "",
9336
- github_installation_id: null,
9337
- last_activity_at: null,
9338
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
9339
- status: "preparing",
9340
- creation_source: "dashboard",
9341
- creator_email: null,
9342
- soft_delete: false,
9343
- lifecycle_policy: "default",
9344
- auto_stop_minutes: null,
9345
- config: {},
9346
- environment_id: environmentId ?? null
9347
- };
9348
- }
9349
9252
 
9350
9253
  // ../shared/src/object-store/types.ts
9351
9254
  var MEDIA_KIND = {
@@ -11427,7 +11330,7 @@ import { createCliRenderer } from "@opentui/core";
11427
11330
  import { createRoot } from "@opentui/react";
11428
11331
 
11429
11332
  // src/interactive/App.tsx
11430
- import { useState as useState8, useEffect as useEffect3, useMemo as useMemo6, useCallback as useCallback7, useRef as useRef5 } from "react";
11333
+ import { useState as useState8, useEffect as useEffect3, useMemo as useMemo6, useCallback as useCallback8, useRef as useRef5 } from "react";
11431
11334
  import { useKeyboard as useKeyboard5, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
11432
11335
  import { QueryClient } from "@tanstack/react-query";
11433
11336
 
@@ -11515,14 +11418,16 @@ function useRawOrgFetch() {
11515
11418
  }
11516
11419
 
11517
11420
  // ../shared/src/hooks/useWorkspaces.ts
11421
+ import { useCallback as useCallback2 } from "react";
11518
11422
  import { useQuery, useMutation } from "@tanstack/react-query";
11519
- function useWorkspaces(page = 1, limit = 100, scope = "organization") {
11423
+ function useWorkspaces(viewModes, page = 1, limit = 100) {
11520
11424
  const auth = useReplicasAuth();
11521
11425
  const orgFetch = useOrgFetch();
11522
11426
  const orgId = auth.getOrganizationId();
11427
+ const sortedKey = [...viewModes].sort().join(",");
11523
11428
  return useQuery({
11524
- queryKey: ["workspaces", orgId, scope, page, limit],
11525
- queryFn: () => orgFetch(`/v1/workspaces?scope=${scope}&page=${page}&limit=${limit}`),
11429
+ queryKey: ["workspaces", orgId, sortedKey, page, limit],
11430
+ queryFn: () => orgFetch(`/v1/workspaces?viewModes=${sortedKey}&page=${page}&limit=${limit}`),
11526
11431
  enabled: !!orgId,
11527
11432
  staleTime: 1e4
11528
11433
  }, auth.queryClient);
@@ -11531,16 +11436,55 @@ function useCreateWorkspace() {
11531
11436
  const auth = useReplicasAuth();
11532
11437
  const orgFetch = useOrgFetch();
11533
11438
  const orgId = auth.getOrganizationId();
11439
+ const waitForWorkspaceActive = useWaitForWorkspaceActive();
11534
11440
  return useMutation({
11535
11441
  mutationFn: (request) => orgFetch("/v1/workspaces", {
11536
11442
  method: "POST",
11537
11443
  body: request
11538
11444
  }),
11445
+ onSuccess: (data) => {
11446
+ const workspace = data?.workspace;
11447
+ if (!workspace) return;
11448
+ auth.queryClient.setQueriesData(
11449
+ { queryKey: ["workspaces", orgId] },
11450
+ (current) => {
11451
+ if (!current) return current;
11452
+ if (current.workspaces.some((w) => w.id === workspace.id)) return current;
11453
+ return {
11454
+ ...current,
11455
+ workspaces: [workspace, ...current.workspaces],
11456
+ total: (current.total ?? current.workspaces.length) + 1
11457
+ };
11458
+ }
11459
+ );
11460
+ void waitForWorkspaceActive(workspace.id);
11461
+ },
11539
11462
  onSettled: () => {
11540
11463
  auth.queryClient.invalidateQueries({ queryKey: ["workspaces", orgId] });
11541
11464
  }
11542
11465
  }, auth.queryClient);
11543
11466
  }
11467
+ function useWaitForWorkspaceActive() {
11468
+ const auth = useReplicasAuth();
11469
+ const orgFetch = useOrgFetch();
11470
+ const orgId = auth.getOrganizationId();
11471
+ return useCallback2(async (workspaceId) => {
11472
+ try {
11473
+ const result = await auth.queryClient.fetchQuery({
11474
+ queryKey: ["workspace-wait-active", orgId, workspaceId],
11475
+ queryFn: () => orgFetch(
11476
+ `/v1/workspaces/${workspaceId}/wait-active`,
11477
+ { method: "POST" }
11478
+ ),
11479
+ staleTime: Infinity
11480
+ });
11481
+ auth.queryClient.invalidateQueries({ queryKey: ["workspaces", orgId] });
11482
+ return result.workspace;
11483
+ } catch {
11484
+ return null;
11485
+ }
11486
+ }, [auth, orgFetch, orgId]);
11487
+ }
11544
11488
  function useDeleteWorkspace() {
11545
11489
  const auth = useReplicasAuth();
11546
11490
  const orgFetch = useOrgFetch();
@@ -11588,7 +11532,7 @@ function useGenerateWorkspaceName() {
11588
11532
  }
11589
11533
 
11590
11534
  // ../shared/src/hooks/useWorkspaceEngine.ts
11591
- import { useCallback as useCallback2, useEffect, useMemo, useState } from "react";
11535
+ import { useCallback as useCallback3, useEffect, useMemo, useState } from "react";
11592
11536
  import { useQuery as useQuery2, useMutation as useMutation2 } from "@tanstack/react-query";
11593
11537
  function upsertChat(chats, chat) {
11594
11538
  const existingIndex = chats.findIndex((item) => item.id === chat.id);
@@ -11713,7 +11657,7 @@ function useWorkspaceEvents(workspaceId, enabled = true) {
11713
11657
  const rawFetch = useRawOrgFetch();
11714
11658
  const qc = auth.queryClient;
11715
11659
  const [connected, setConnected] = useState(false);
11716
- const handleEvent = useCallback2((event) => {
11660
+ const handleEvent = useCallback3((event) => {
11717
11661
  if (!workspaceId) return;
11718
11662
  const chatsKey = ["workspace-chats", workspaceId];
11719
11663
  if (event.type === "chat.created" || event.type === "chat.updated") {
@@ -11916,7 +11860,7 @@ function StatusBar({ focusPanel, viewingDiff, hasDiffAvailable }) {
11916
11860
  }
11917
11861
 
11918
11862
  // src/interactive/components/WorkspaceSidebar.tsx
11919
- import { useState as useState2, useMemo as useMemo2, useCallback as useCallback3 } from "react";
11863
+ import { useState as useState2, useMemo as useMemo2, useCallback as useCallback4 } from "react";
11920
11864
  import { useKeyboard, useTerminalDimensions } from "@opentui/react";
11921
11865
  import { jsx as jsx2, jsxs as jsxs2 } from "@opentui/react/jsx-runtime";
11922
11866
  function flattenGroups(groups, collapsedGroups) {
@@ -11937,8 +11881,7 @@ function flattenGroups(groups, collapsedGroups) {
11937
11881
  type: "workspace",
11938
11882
  workspaceId: ws.id,
11939
11883
  name: ws.name,
11940
- status: ws.status,
11941
- isMock: ws.status === "preparing"
11884
+ status: ws.status
11942
11885
  });
11943
11886
  }
11944
11887
  if (group.id !== "__ungrouped__") {
@@ -11954,7 +11897,6 @@ function truncate3(text, maxLen) {
11954
11897
  function WorkspaceSidebar({
11955
11898
  groups,
11956
11899
  selectedWorkspaceId,
11957
- mockIds,
11958
11900
  onSelectWorkspace,
11959
11901
  onCreateWorkspace,
11960
11902
  onDeleteWorkspace,
@@ -11974,7 +11916,7 @@ function WorkspaceSidebar({
11974
11916
  setCursorIndex(clampedCursor);
11975
11917
  }
11976
11918
  const visibleHeight = Math.max(1, termHeight - 4);
11977
- const adjustScroll = useCallback3(
11919
+ const adjustScroll = useCallback4(
11978
11920
  (newCursor) => {
11979
11921
  let newOffset = scrollOffset;
11980
11922
  if (newCursor < newOffset) {
@@ -11986,7 +11928,7 @@ function WorkspaceSidebar({
11986
11928
  },
11987
11929
  [scrollOffset, visibleHeight]
11988
11930
  );
11989
- const moveCursor = useCallback3(
11931
+ const moveCursor = useCallback4(
11990
11932
  (next) => {
11991
11933
  const len = items.length;
11992
11934
  if (len === 0) return;
@@ -11996,7 +11938,7 @@ function WorkspaceSidebar({
11996
11938
  },
11997
11939
  [items.length, adjustScroll]
11998
11940
  );
11999
- const handleAction = useCallback3(
11941
+ const handleAction = useCallback4(
12000
11942
  (item) => {
12001
11943
  if (item.type === "group") {
12002
11944
  setCollapsedGroups((prev) => {
@@ -12016,10 +11958,9 @@ function WorkspaceSidebar({
12016
11958
  },
12017
11959
  [onSelectWorkspace, onCreateWorkspace]
12018
11960
  );
12019
- const handleDelete = useCallback3(() => {
11961
+ const handleDelete = useCallback4(() => {
12020
11962
  const item = items[cursorIndex];
12021
11963
  if (!item || item.type !== "workspace") return;
12022
- if (item.isMock) return;
12023
11964
  if (confirmDelete === item.workspaceId) {
12024
11965
  onDeleteWorkspace(item.workspaceId);
12025
11966
  setConfirmDelete(null);
@@ -12027,7 +11968,7 @@ function WorkspaceSidebar({
12027
11968
  setConfirmDelete(item.workspaceId);
12028
11969
  }
12029
11970
  }, [items, cursorIndex, confirmDelete, onDeleteWorkspace]);
12030
- const moveCursorAndClearConfirm = useCallback3(
11971
+ const moveCursorAndClearConfirm = useCallback4(
12031
11972
  (next) => {
12032
11973
  setConfirmDelete(null);
12033
11974
  moveCursor(next);
@@ -12095,7 +12036,7 @@ function WorkspaceSidebar({
12095
12036
  return;
12096
12037
  }
12097
12038
  });
12098
- const handleItemClick = useCallback3(
12039
+ const handleItemClick = useCallback4(
12099
12040
  (globalIndex) => {
12100
12041
  setConfirmDelete(null);
12101
12042
  setCursorIndex(globalIndex);
@@ -12104,7 +12045,7 @@ function WorkspaceSidebar({
12104
12045
  },
12105
12046
  [items, handleAction]
12106
12047
  );
12107
- const handleDeleteClick = useCallback3(
12048
+ const handleDeleteClick = useCallback4(
12108
12049
  (workspaceId, e) => {
12109
12050
  e?.preventDefault?.();
12110
12051
  if (confirmDelete === workspaceId) {
@@ -12209,7 +12150,7 @@ function WorkspaceSidebar({
12209
12150
  ] }),
12210
12151
  /* @__PURE__ */ jsx2("span", { fg: nameColor, children: truncate3(item.name, 17) })
12211
12152
  ] }),
12212
- !item.isMock && /* @__PURE__ */ jsx2("box", { onMouseDown: (e) => handleDeleteClick(item.workspaceId, e), children: /* @__PURE__ */ jsx2("text", { children: /* @__PURE__ */ jsx2("span", { fg: isCursor ? "#ff4444" : "#222222", children: "\u2717" }) }) })
12153
+ /* @__PURE__ */ jsx2("box", { onMouseDown: (e) => handleDeleteClick(item.workspaceId, e), children: /* @__PURE__ */ jsx2("text", { children: /* @__PURE__ */ jsx2("span", { fg: isCursor ? "#ff4444" : "#222222", children: "\u2717" }) }) })
12213
12154
  ]
12214
12155
  },
12215
12156
  `w-${item.workspaceId}`
@@ -12264,7 +12205,7 @@ function SpinnerLabel({ color, label }) {
12264
12205
  import { useState as useState4 } from "react";
12265
12206
 
12266
12207
  // src/interactive/components/diff-utils.tsx
12267
- import React2, { useState as useState3, useMemo as useMemo3, useCallback as useCallback4, useRef } from "react";
12208
+ import React2, { useState as useState3, useMemo as useMemo3, useCallback as useCallback5, useRef } from "react";
12268
12209
  import { SyntaxStyle } from "@opentui/core";
12269
12210
  import { useKeyboard as useKeyboard2 } from "@opentui/react";
12270
12211
  import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
@@ -12532,12 +12473,12 @@ function DiffViewer({ diff, repoName, focused }) {
12532
12473
  return result;
12533
12474
  }, [tree, collapsedFolders]);
12534
12475
  const safeCursorIndex = Math.min(cursorIndex, Math.max(0, visibleTree.length - 1));
12535
- const scrollCursorIntoView = useCallback4((treeIdx) => {
12476
+ const scrollCursorIntoView = useCallback5((treeIdx) => {
12536
12477
  const node = visibleTree[treeIdx];
12537
12478
  if (!node) return;
12538
12479
  fileTreeScrollRef.current?.scrollChildIntoView(`tree-${node.path}`);
12539
12480
  }, [visibleTree]);
12540
- const moveCursor = useCallback4((next) => {
12481
+ const moveCursor = useCallback5((next) => {
12541
12482
  const len = visibleTree.length;
12542
12483
  if (len === 0) return;
12543
12484
  const wrapped = (next % len + len) % len;
@@ -12548,7 +12489,7 @@ function DiffViewer({ diff, repoName, focused }) {
12548
12489
  setSelectedFileIndex(node.fileIndex);
12549
12490
  }
12550
12491
  }, [visibleTree, scrollCursorIntoView]);
12551
- const toggleFolder = useCallback4((folderPath) => {
12492
+ const toggleFolder = useCallback5((folderPath) => {
12552
12493
  setCollapsedFolders((prev) => {
12553
12494
  const next = new Set(prev);
12554
12495
  if (next.has(folderPath)) next.delete(folderPath);
@@ -12556,7 +12497,7 @@ function DiffViewer({ diff, repoName, focused }) {
12556
12497
  return next;
12557
12498
  });
12558
12499
  }, []);
12559
- const selectFile = useCallback4((fileIndex, treeIndex) => {
12500
+ const selectFile = useCallback5((fileIndex, treeIndex) => {
12560
12501
  setSelectedFileIndex(fileIndex);
12561
12502
  setCursorIndex(treeIndex);
12562
12503
  scrollCursorIntoView(treeIndex);
@@ -13406,7 +13347,7 @@ function ChatArea({
13406
13347
  }
13407
13348
 
13408
13349
  // src/interactive/components/WorkspaceInfo.tsx
13409
- import React6, { useState as useState6, useMemo as useMemo5, useCallback as useCallback5, useRef as useRef3 } from "react";
13350
+ import React6, { useState as useState6, useMemo as useMemo5, useCallback as useCallback6, useRef as useRef3 } from "react";
13410
13351
  import open4 from "open";
13411
13352
  import { useKeyboard as useKeyboard4 } from "@opentui/react";
13412
13353
  import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
@@ -13603,7 +13544,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
13603
13544
  const hasAnyDiff = diffItems.length > 0;
13604
13545
  const safeCursor = interactiveItems.length > 0 ? Math.min(cursorIndex, interactiveItems.length - 1) : 0;
13605
13546
  const scrollboxRef = useRef3(null);
13606
- const moveCursor = useCallback5(
13547
+ const moveCursor = useCallback6(
13607
13548
  (next) => {
13608
13549
  const len = interactiveItems.length;
13609
13550
  if (len === 0) return;
@@ -13614,7 +13555,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
13614
13555
  },
13615
13556
  [interactiveItems]
13616
13557
  );
13617
- const handleAction = useCallback5(
13558
+ const handleAction = useCallback6(
13618
13559
  (item) => {
13619
13560
  if (!item) return;
13620
13561
  switch (item.type) {
@@ -13683,7 +13624,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
13683
13624
  return;
13684
13625
  }
13685
13626
  });
13686
- const isHighlighted = useCallback5(
13627
+ const isHighlighted = useCallback6(
13687
13628
  (item) => {
13688
13629
  if (!focused) return false;
13689
13630
  const idx = interactiveItems.indexOf(item);
@@ -13691,7 +13632,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
13691
13632
  },
13692
13633
  [focused, interactiveItems, safeCursor]
13693
13634
  );
13694
- const findItem = useCallback5(
13635
+ const findItem = useCallback6(
13695
13636
  (type, key) => {
13696
13637
  return interactiveItems.find((item) => {
13697
13638
  if (item.type !== type) return false;
@@ -13980,7 +13921,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, a
13980
13921
  import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
13981
13922
 
13982
13923
  // src/interactive/toast-context.tsx
13983
- import { createContext as createContext2, useContext as useContext2, useState as useState7, useCallback as useCallback6, useRef as useRef4 } from "react";
13924
+ import { createContext as createContext2, useContext as useContext2, useState as useState7, useCallback as useCallback7, useRef as useRef4 } from "react";
13984
13925
  import { jsx as jsx9 } from "@opentui/react/jsx-runtime";
13985
13926
  var ToastContext = createContext2(null);
13986
13927
  function useToast() {
@@ -13991,7 +13932,7 @@ function useToast() {
13991
13932
  function ToastProvider({ children }) {
13992
13933
  const [current, setCurrent] = useState7(null);
13993
13934
  const timeoutRef = useRef4(null);
13994
- const show = useCallback6((options) => {
13935
+ const show = useCallback7((options) => {
13995
13936
  const { message, variant = "info", duration = 3e3 } = options;
13996
13937
  setCurrent({ message, variant });
13997
13938
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -13999,7 +13940,7 @@ function ToastProvider({ children }) {
13999
13940
  setCurrent(null);
14000
13941
  }, duration);
14001
13942
  }, []);
14002
- const error = useCallback6((err) => {
13943
+ const error = useCallback7((err) => {
14003
13944
  const message = err instanceof Error ? err.message : "An error occurred";
14004
13945
  show({ message, variant: "error", duration: 5e3 });
14005
13946
  }, [show]);
@@ -14098,29 +14039,17 @@ function AppInner() {
14098
14039
  const [selectedChatId, setSelectedChatId] = useState8(null);
14099
14040
  const [focusPanel, setFocusPanel] = useState8("sidebar");
14100
14041
  const [taskMode, setTaskMode] = useState8("build");
14101
- const [mockWorkspaces, setMockWorkspaces] = useState8([]);
14102
- const mockToRealRef = useRef5(/* @__PURE__ */ new Map());
14103
- const mockGroupRef = useRef5(/* @__PURE__ */ new Map());
14104
- const mockPollingRef = useRef5(null);
14105
- if (mockWorkspaces.length > 0 && !mockPollingRef.current) {
14106
- mockPollingRef.current = setInterval(() => {
14107
- queryClient.invalidateQueries({ queryKey: ["workspaces"] });
14108
- rendererRef.current.requestRender();
14109
- }, 5e3);
14110
- } else if (mockWorkspaces.length === 0 && mockPollingRef.current) {
14111
- clearInterval(mockPollingRef.current);
14112
- mockPollingRef.current = null;
14113
- }
14114
14042
  const [mockMessages, setMockMessages] = useState8([]);
14115
14043
  const [mockThinking, setMockThinking] = useState8(false);
14116
14044
  const pendingMessageRef = useRef5(/* @__PURE__ */ new Map());
14117
14045
  const [viewingDiff, setViewingDiff] = useState8(null);
14118
14046
  const [lastViewedDiff, setLastViewedDiff] = useState8(null);
14119
- const mockIds = useMemo6(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
14120
- const isMockSelected = selectedWorkspaceId ? mockIds.has(selectedWorkspaceId) : false;
14121
- const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(1, 100, "organization");
14047
+ const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(WORKSPACE_SIDEBAR_VIEWS);
14122
14048
  const { data: setsData } = useRepositorySets();
14123
14049
  const { data: envsData } = useEnvironments();
14050
+ const workspaces = workspacesData?.workspaces ?? [];
14051
+ const selectedWorkspace = workspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
14052
+ const isMockSelected = selectedWorkspace?.status === "preparing";
14124
14053
  const { data: statusData, isLoading: loadingStatus } = useWorkspaceStatus(
14125
14054
  isMockSelected ? null : selectedWorkspaceId,
14126
14055
  { includeDiffs: true }
@@ -14149,16 +14078,13 @@ function AppInner() {
14149
14078
  const [wakingWorkspaceId, setWakingWorkspaceId] = useState8(null);
14150
14079
  const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
14151
14080
  const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
14152
- const workspaces = workspacesData?.workspaces ?? [];
14153
14081
  const repositorySets = setsData?.repository_sets ?? [];
14154
14082
  const environments = envsData?.environments ?? [];
14155
14083
  const previews = previewsData?.previews ?? [];
14156
- const allWorkspaces = useMemo6(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
14157
14084
  const groups = useMemo6(
14158
- () => buildGroups(allWorkspaces, workspacesData, environments, repositorySets, mockGroupRef.current),
14159
- [allWorkspaces, workspacesData, environments, repositorySets]
14085
+ () => buildGroups(workspaces, workspacesData, environments, repositorySets),
14086
+ [workspaces, workspacesData, environments, repositorySets]
14160
14087
  );
14161
- const selectedWorkspace = allWorkspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
14162
14088
  const selectedChat = chats.find((c) => c.id === resolvedChatId) ?? null;
14163
14089
  const isProcessing = mockThinking || (selectedChat?.processing ?? false);
14164
14090
  const selectedAgent = selectedChat?.provider ?? "claude";
@@ -14180,33 +14106,15 @@ function AppInner() {
14180
14106
  setSelectedWorkspaceId(workspaces[0].id);
14181
14107
  }
14182
14108
  }, [workspaces, selectedWorkspaceId]);
14183
- useEffect3(() => {
14184
- if (mockWorkspaces.length === 0) return;
14185
- const realIds = new Set(workspaces.map((w) => w.id));
14186
- let changed = false;
14187
- const remaining = mockWorkspaces.filter((mock) => {
14188
- const realId = mockToRealRef.current.get(mock.id);
14189
- if (realId && realIds.has(realId)) {
14190
- if (selectedWorkspaceId === mock.id) {
14191
- setSelectedWorkspaceId(realId);
14192
- }
14193
- const pending = pendingMessageRef.current.get(mock.id);
14194
- if (pending) {
14195
- pendingMessageRef.current.delete(mock.id);
14196
- pendingMessageRef.current.set(realId, pending);
14197
- }
14198
- mockToRealRef.current.delete(mock.id);
14199
- mockGroupRef.current.delete(mock.id);
14200
- setSelectedChatId(null);
14201
- setMockMessages([]);
14202
- setMockThinking(false);
14203
- changed = true;
14204
- return false;
14205
- }
14206
- return true;
14207
- });
14208
- if (changed) setMockWorkspaces(remaining);
14209
- }, [workspaces, mockWorkspaces, selectedWorkspaceId]);
14109
+ const [prevIsMockSelected, setPrevIsMockSelected] = useState8(isMockSelected);
14110
+ if (prevIsMockSelected !== isMockSelected) {
14111
+ setPrevIsMockSelected(isMockSelected);
14112
+ if (prevIsMockSelected && !isMockSelected) {
14113
+ setSelectedChatId(null);
14114
+ setMockMessages([]);
14115
+ setMockThinking(false);
14116
+ }
14117
+ }
14210
14118
  useEffect3(() => {
14211
14119
  if (!selectedWorkspaceId || isMockSelected) return;
14212
14120
  if (!resolvedChatId || resolvedChatId.startsWith("mock-")) return;
@@ -14221,7 +14129,7 @@ function AppInner() {
14221
14129
  }
14222
14130
  sendMessageMutation.mutate({ message: pending });
14223
14131
  }, [selectedWorkspaceId, resolvedChatId, isMockSelected, statusData?.status]);
14224
- const handleSelectWorkspace = useCallback7((workspaceId) => {
14132
+ const handleSelectWorkspace = useCallback8((workspaceId) => {
14225
14133
  setSelectedWorkspaceId(workspaceId);
14226
14134
  setSelectedChatId(null);
14227
14135
  setMockMessages([]);
@@ -14230,55 +14138,32 @@ function AppInner() {
14230
14138
  setLastViewedDiff(null);
14231
14139
  setFocusPanel("chat-input");
14232
14140
  }, []);
14233
- const handleFocus = useCallback7((panel) => {
14141
+ const handleFocus = useCallback8((panel) => {
14234
14142
  if (panel === "sidebar") {
14235
14143
  queryClient.invalidateQueries({ queryKey: ["workspaces"] });
14236
14144
  }
14237
14145
  setFocusPanel(panel);
14238
14146
  }, []);
14239
- const handleCreateWorkspace = useCallback7(
14147
+ const handleCreateWorkspace = useCallback8(
14240
14148
  async (group) => {
14241
14149
  if (group.id === "__ungrouped__") {
14242
14150
  toast.error("Cannot create a workspace in the Other / Ungrouped folder");
14243
14151
  return;
14244
14152
  }
14245
- const orgId = getOrganizationId() ?? "";
14246
- const mock = createMockWorkspaceRecord(orgId);
14247
- mockGroupRef.current.set(mock.id, group.id);
14248
- setMockWorkspaces((prev) => [mock, ...prev]);
14249
- setSelectedWorkspaceId(mock.id);
14250
14153
  setViewingDiff(null);
14251
14154
  setLastViewedDiff(null);
14252
14155
  setFocusPanel("chat-input");
14253
14156
  try {
14254
- const request = {
14255
- environment_id: group.environmentId,
14256
- name: mock.name,
14257
- placeholder: true
14258
- };
14259
- const result = await createWorkspaceMutation.mutateAsync(request);
14260
- mockToRealRef.current.set(mock.id, result.workspace.id);
14157
+ const result = await createWorkspaceMutation.mutateAsync({ environment_id: group.environmentId });
14158
+ setSelectedWorkspaceId(result.workspace.id);
14261
14159
  } catch (err) {
14262
- mockGroupRef.current.delete(mock.id);
14263
- setMockWorkspaces((prev) => prev.filter((m) => m.id !== mock.id));
14264
14160
  toast.error(err);
14265
14161
  }
14266
14162
  },
14267
14163
  [createWorkspaceMutation, toast]
14268
14164
  );
14269
- const handleDeleteWorkspace = useCallback7(
14165
+ const handleDeleteWorkspace = useCallback8(
14270
14166
  async (workspaceId) => {
14271
- if (mockIds.has(workspaceId)) {
14272
- mockGroupRef.current.delete(workspaceId);
14273
- mockToRealRef.current.delete(workspaceId);
14274
- setMockWorkspaces((prev) => prev.filter((m) => m.id !== workspaceId));
14275
- if (selectedWorkspaceId === workspaceId) {
14276
- setSelectedWorkspaceId(null);
14277
- setViewingDiff(null);
14278
- setLastViewedDiff(null);
14279
- }
14280
- return;
14281
- }
14282
14167
  try {
14283
14168
  await deleteWorkspaceMutation.mutateAsync(workspaceId);
14284
14169
  if (selectedWorkspaceId === workspaceId) {
@@ -14291,9 +14176,9 @@ function AppInner() {
14291
14176
  toast.error(err);
14292
14177
  }
14293
14178
  },
14294
- [mockIds, selectedWorkspaceId, deleteWorkspaceMutation]
14179
+ [selectedWorkspaceId, deleteWorkspaceMutation]
14295
14180
  );
14296
- const handleWakeWorkspace = useCallback7(
14181
+ const handleWakeWorkspace = useCallback8(
14297
14182
  async (workspaceId) => {
14298
14183
  setWakingWorkspaceId(workspaceId);
14299
14184
  try {
@@ -14307,7 +14192,7 @@ function AppInner() {
14307
14192
  },
14308
14193
  [wakeWorkspaceMutation, toast]
14309
14194
  );
14310
- const handleSelectChat = useCallback7((chatId) => {
14195
+ const handleSelectChat = useCallback8((chatId) => {
14311
14196
  setSelectedChatId(chatId);
14312
14197
  }, []);
14313
14198
  useKeyboard5((key) => {
@@ -14365,12 +14250,12 @@ function AppInner() {
14365
14250
  }
14366
14251
  if (focusPanel === "chat-input") return;
14367
14252
  });
14368
- const handleViewDiff = useCallback7((diff, repoName) => {
14253
+ const handleViewDiff = useCallback8((diff, repoName) => {
14369
14254
  setViewingDiff({ diff, repoName });
14370
14255
  setLastViewedDiff({ diff, repoName });
14371
14256
  setFocusPanel("chat-history");
14372
14257
  }, []);
14373
- const handleSelectChatMode = useCallback7(() => {
14258
+ const handleSelectChatMode = useCallback8(() => {
14374
14259
  setViewingDiff(null);
14375
14260
  setFocusPanel("chat-history");
14376
14261
  }, []);
@@ -14384,14 +14269,14 @@ function AppInner() {
14384
14269
  }
14385
14270
  return null;
14386
14271
  }, [lastViewedDiff, statusData?.repoStatuses]);
14387
- const handleSelectDiffMode = useCallback7(() => {
14272
+ const handleSelectDiffMode = useCallback8(() => {
14388
14273
  if (firstAvailableDiff) {
14389
14274
  setViewingDiff(firstAvailableDiff);
14390
14275
  setLastViewedDiff(firstAvailableDiff);
14391
14276
  setFocusPanel("chat-history");
14392
14277
  }
14393
14278
  }, [firstAvailableDiff]);
14394
- const handleSendMessage = useCallback7(
14279
+ const handleSendMessage = useCallback8(
14395
14280
  async (message) => {
14396
14281
  if (!selectedWorkspaceId || !resolvedChatId) return;
14397
14282
  if (isMockSelected) {
@@ -14419,7 +14304,6 @@ function AppInner() {
14419
14304
  {
14420
14305
  groups,
14421
14306
  selectedWorkspaceId,
14422
- mockIds,
14423
14307
  onSelectWorkspace: handleSelectWorkspace,
14424
14308
  onCreateWorkspace: handleCreateWorkspace,
14425
14309
  onDeleteWorkspace: handleDeleteWorkspace,
@@ -14927,7 +14811,7 @@ Deleted file ${pathOrId}.
14927
14811
  }
14928
14812
 
14929
14813
  // src/index.ts
14930
- var CLI_VERSION = "0.2.171";
14814
+ var CLI_VERSION = "0.2.172";
14931
14815
  function parseBooleanOption(value) {
14932
14816
  if (value === "true") return true;
14933
14817
  if (value === "false") return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.171",
3
+ "version": "0.2.172",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.mjs",
6
6
  "bin": {