replicas-cli 0.2.41 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -1855,12 +1855,12 @@ async function interactiveCommand() {
|
|
|
1855
1855
|
);
|
|
1856
1856
|
}
|
|
1857
1857
|
console.log(chalk17.gray("Starting interactive mode..."));
|
|
1858
|
-
const { launchInteractive } = await import("./interactive-
|
|
1858
|
+
const { launchInteractive } = await import("./interactive-M3UR4H6X.mjs");
|
|
1859
1859
|
await launchInteractive();
|
|
1860
1860
|
}
|
|
1861
1861
|
|
|
1862
1862
|
// src/index.ts
|
|
1863
|
-
var CLI_VERSION = "0.2.
|
|
1863
|
+
var CLI_VERSION = "0.2.42";
|
|
1864
1864
|
var program = new Command();
|
|
1865
1865
|
program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
|
|
1866
1866
|
program.command("login").description("Authenticate with your Replicas account").action(async () => {
|
|
@@ -16,8 +16,8 @@ import { createCliRenderer } from "@opentui/core";
|
|
|
16
16
|
import { createRoot } from "@opentui/react";
|
|
17
17
|
|
|
18
18
|
// src/interactive/App.tsx
|
|
19
|
-
import { useState as
|
|
20
|
-
import { useKeyboard as
|
|
19
|
+
import { useState as useState6, useEffect as useEffect3, useMemo as useMemo4, useCallback as useCallback6, useRef as useRef3 } from "react";
|
|
20
|
+
import { useKeyboard as useKeyboard4, useRenderer, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
|
|
21
21
|
import { QueryClient } from "@tanstack/react-query";
|
|
22
22
|
|
|
23
23
|
// ../shared/src/hooks/auth-context.ts
|
|
@@ -488,7 +488,7 @@ var KEYBINDS = {
|
|
|
488
488
|
"chat-tabs": "\u2190/\u2192 switch tabs",
|
|
489
489
|
"chat-history": "j/k scroll",
|
|
490
490
|
"chat-input": "\u21B5 send \u21E5 plan/build",
|
|
491
|
-
info: "j/k
|
|
491
|
+
info: "j/k nav \u21B5 open o dashboard w wake"
|
|
492
492
|
};
|
|
493
493
|
function StatusBar({ focusPanel }) {
|
|
494
494
|
return /* @__PURE__ */ jsxs(
|
|
@@ -1298,10 +1298,45 @@ function ChatArea({
|
|
|
1298
1298
|
}
|
|
1299
1299
|
|
|
1300
1300
|
// src/interactive/components/WorkspaceInfo.tsx
|
|
1301
|
-
import React4 from "react";
|
|
1301
|
+
import React4, { useState as useState4, useMemo as useMemo3, useCallback as useCallback4 } from "react";
|
|
1302
1302
|
import open from "open";
|
|
1303
|
+
import { useKeyboard as useKeyboard3 } from "@opentui/react";
|
|
1303
1304
|
import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
|
|
1304
1305
|
var WEB_APP_URL = process.env.REPLICAS_WEB_URL || "https://replicas.dev";
|
|
1306
|
+
function buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId) {
|
|
1307
|
+
const items = [];
|
|
1308
|
+
if (workspaceId) {
|
|
1309
|
+
items.push({ type: "dashboard", workspaceId });
|
|
1310
|
+
}
|
|
1311
|
+
if (workspaceId && status.status === "sleeping" && wakingWorkspaceId !== workspaceId) {
|
|
1312
|
+
items.push({ type: "wake", workspaceId });
|
|
1313
|
+
}
|
|
1314
|
+
for (const preview of previews) {
|
|
1315
|
+
if (preview.publicUrl) {
|
|
1316
|
+
items.push({ type: "preview", url: preview.publicUrl, port: preview.port });
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (status.repoStatuses) {
|
|
1320
|
+
for (const repo of status.repoStatuses) {
|
|
1321
|
+
if (repo.prUrl) {
|
|
1322
|
+
items.push({ type: "pr", url: repo.prUrl, repoName: repo.name });
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
return items;
|
|
1327
|
+
}
|
|
1328
|
+
function getItemLabel(item) {
|
|
1329
|
+
switch (item.type) {
|
|
1330
|
+
case "dashboard":
|
|
1331
|
+
return "\u2197 Open in Dashboard";
|
|
1332
|
+
case "wake":
|
|
1333
|
+
return "\u25B6 Wake";
|
|
1334
|
+
case "preview":
|
|
1335
|
+
return `\u2197 Preview :${item.port}`;
|
|
1336
|
+
case "pr":
|
|
1337
|
+
return `\u2197 View PR (${item.repoName})`;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1305
1340
|
var AUTH_METHOD_LABELS = {
|
|
1306
1341
|
oauth: "OAuth",
|
|
1307
1342
|
api_key: "API Key",
|
|
@@ -1352,8 +1387,108 @@ function DetailList({
|
|
|
1352
1387
|
if (rows.length === 0) return null;
|
|
1353
1388
|
return /* @__PURE__ */ jsx6(Fragment, { children: rows.map((item, i) => /* @__PURE__ */ jsx6(CardItem, { label: item, status: actualSet.has(item) }, i)) });
|
|
1354
1389
|
}
|
|
1390
|
+
function InteractiveRow({ label, highlighted, onClick }) {
|
|
1391
|
+
return /* @__PURE__ */ jsx6(
|
|
1392
|
+
"box",
|
|
1393
|
+
{
|
|
1394
|
+
paddingX: 1,
|
|
1395
|
+
backgroundColor: highlighted ? "#1a2a1a" : "#111111",
|
|
1396
|
+
onMouseDown: onClick,
|
|
1397
|
+
children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: highlighted ? "#66bb6a" : "#7dcfff", children: label }) })
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1355
1401
|
function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, envConfig, previews, onWakeWorkspace, wakingWorkspaceId }) {
|
|
1356
1402
|
const borderColor = focused ? "#66bb6a" : "#333333";
|
|
1403
|
+
const [cursorIndex, setCursorIndex] = useState4(0);
|
|
1404
|
+
const interactiveItems = useMemo3(() => {
|
|
1405
|
+
if (!status || !workspaceName) return [];
|
|
1406
|
+
return buildInteractiveItems(workspaceId, status, previews, wakingWorkspaceId);
|
|
1407
|
+
}, [workspaceId, workspaceName, status, previews, wakingWorkspaceId]);
|
|
1408
|
+
const safeCursor = interactiveItems.length > 0 ? Math.min(cursorIndex, interactiveItems.length - 1) : 0;
|
|
1409
|
+
const moveCursor = useCallback4(
|
|
1410
|
+
(next) => {
|
|
1411
|
+
const clamped = Math.max(0, Math.min(interactiveItems.length - 1, next));
|
|
1412
|
+
setCursorIndex(clamped);
|
|
1413
|
+
},
|
|
1414
|
+
[interactiveItems.length]
|
|
1415
|
+
);
|
|
1416
|
+
const handleAction = useCallback4(
|
|
1417
|
+
(item) => {
|
|
1418
|
+
if (!item) return;
|
|
1419
|
+
switch (item.type) {
|
|
1420
|
+
case "dashboard":
|
|
1421
|
+
open(`${WEB_APP_URL}/dashboard?workspaceId=${item.workspaceId}`).catch(() => {
|
|
1422
|
+
});
|
|
1423
|
+
break;
|
|
1424
|
+
case "wake":
|
|
1425
|
+
onWakeWorkspace(item.workspaceId);
|
|
1426
|
+
break;
|
|
1427
|
+
case "preview":
|
|
1428
|
+
open(item.url).catch(() => {
|
|
1429
|
+
});
|
|
1430
|
+
break;
|
|
1431
|
+
case "pr":
|
|
1432
|
+
open(item.url).catch(() => {
|
|
1433
|
+
});
|
|
1434
|
+
break;
|
|
1435
|
+
}
|
|
1436
|
+
},
|
|
1437
|
+
[onWakeWorkspace]
|
|
1438
|
+
);
|
|
1439
|
+
useKeyboard3((key) => {
|
|
1440
|
+
if (!focused) return;
|
|
1441
|
+
if (interactiveItems.length === 0) return;
|
|
1442
|
+
if (key.name === "j" || key.name === "down") {
|
|
1443
|
+
moveCursor(safeCursor + 1);
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
if (key.name === "k" || key.name === "up") {
|
|
1447
|
+
moveCursor(safeCursor - 1);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
if (key.name === "g" && !key.shift) {
|
|
1451
|
+
moveCursor(0);
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
if (key.name === "g" && key.shift) {
|
|
1455
|
+
moveCursor(interactiveItems.length - 1);
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
if (key.name === "enter" || key.name === "return") {
|
|
1459
|
+
handleAction(interactiveItems[safeCursor]);
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
if (key.name === "o") {
|
|
1463
|
+
const dashboardItem2 = interactiveItems.find((item) => item.type === "dashboard");
|
|
1464
|
+
if (dashboardItem2) handleAction(dashboardItem2);
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
if (key.name === "w") {
|
|
1468
|
+
const wakeItem2 = interactiveItems.find((item) => item.type === "wake");
|
|
1469
|
+
if (wakeItem2) handleAction(wakeItem2);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
const isHighlighted = useCallback4(
|
|
1474
|
+
(item) => {
|
|
1475
|
+
if (!focused) return false;
|
|
1476
|
+
const idx = interactiveItems.indexOf(item);
|
|
1477
|
+
return idx === safeCursor;
|
|
1478
|
+
},
|
|
1479
|
+
[focused, interactiveItems, safeCursor]
|
|
1480
|
+
);
|
|
1481
|
+
const findItem = useCallback4(
|
|
1482
|
+
(type, key) => {
|
|
1483
|
+
return interactiveItems.find((item) => {
|
|
1484
|
+
if (item.type !== type) return false;
|
|
1485
|
+
if (type === "preview" && key) return item.port === Number(key);
|
|
1486
|
+
if (type === "pr" && key) return item.repoName === key;
|
|
1487
|
+
return true;
|
|
1488
|
+
});
|
|
1489
|
+
},
|
|
1490
|
+
[interactiveItems]
|
|
1491
|
+
);
|
|
1357
1492
|
if (!workspaceName) {
|
|
1358
1493
|
return /* @__PURE__ */ jsx6(
|
|
1359
1494
|
"box",
|
|
@@ -1393,6 +1528,8 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1393
1528
|
const expectedSkills = (envConfig.skills?.environment_skills ?? []).map((s) => s.source);
|
|
1394
1529
|
const expectedGlobalVars = (envConfig.variables?.environment_variables ?? []).filter((v) => v.scope_type === "global").map((v) => v.key);
|
|
1395
1530
|
const expectedGlobalFiles = (envConfig.files?.environment_files ?? []).filter((f) => f.scope_type === "global").map((f) => f.path);
|
|
1531
|
+
const dashboardItem = findItem("dashboard");
|
|
1532
|
+
const wakeItem = findItem("wake");
|
|
1396
1533
|
return /* @__PURE__ */ jsx6(
|
|
1397
1534
|
"box",
|
|
1398
1535
|
{
|
|
@@ -1419,36 +1556,24 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1419
1556
|
" ",
|
|
1420
1557
|
env.engineVersion
|
|
1421
1558
|
] })
|
|
1422
|
-
] })
|
|
1423
|
-
workspaceId && /* @__PURE__ */ jsx6(
|
|
1424
|
-
"box",
|
|
1425
|
-
{
|
|
1426
|
-
onMouseDown: () => {
|
|
1427
|
-
open(`${WEB_APP_URL}/dashboard?workspaceId=${workspaceId}`).catch(() => {
|
|
1428
|
-
});
|
|
1429
|
-
},
|
|
1430
|
-
children: /* @__PURE__ */ jsxs6("text", { children: [
|
|
1431
|
-
/* @__PURE__ */ jsxs6("span", { fg: "#7dcfff", children: [
|
|
1432
|
-
"\u2197",
|
|
1433
|
-
" Open in Dashboard"
|
|
1434
|
-
] }),
|
|
1435
|
-
/* @__PURE__ */ jsx6("span", { fg: "#555555", children: " (o)" })
|
|
1436
|
-
] })
|
|
1437
|
-
}
|
|
1438
|
-
),
|
|
1439
|
-
workspaceId && status.status === "sleeping" && /* @__PURE__ */ jsx6(
|
|
1440
|
-
"box",
|
|
1441
|
-
{
|
|
1442
|
-
onMouseDown: () => {
|
|
1443
|
-
if (wakingWorkspaceId !== workspaceId) onWakeWorkspace(workspaceId);
|
|
1444
|
-
},
|
|
1445
|
-
children: /* @__PURE__ */ jsxs6("text", { children: [
|
|
1446
|
-
/* @__PURE__ */ jsx6("span", { fg: wakingWorkspaceId === workspaceId ? "#888888" : "#66bb6a", children: wakingWorkspaceId === workspaceId ? "\u25CC Waking..." : "\u25B6 Wake" }),
|
|
1447
|
-
/* @__PURE__ */ jsx6("span", { fg: "#555555", children: " (w)" })
|
|
1448
|
-
] })
|
|
1449
|
-
}
|
|
1450
|
-
)
|
|
1559
|
+
] })
|
|
1451
1560
|
] }) }),
|
|
1561
|
+
dashboardItem && /* @__PURE__ */ jsx6(
|
|
1562
|
+
InteractiveRow,
|
|
1563
|
+
{
|
|
1564
|
+
label: getItemLabel(dashboardItem),
|
|
1565
|
+
highlighted: isHighlighted(dashboardItem),
|
|
1566
|
+
onClick: () => handleAction(dashboardItem)
|
|
1567
|
+
}
|
|
1568
|
+
),
|
|
1569
|
+
wakeItem && /* @__PURE__ */ jsx6(
|
|
1570
|
+
InteractiveRow,
|
|
1571
|
+
{
|
|
1572
|
+
label: getItemLabel(wakeItem),
|
|
1573
|
+
highlighted: isHighlighted(wakeItem),
|
|
1574
|
+
onClick: () => handleAction(wakeItem)
|
|
1575
|
+
}
|
|
1576
|
+
),
|
|
1452
1577
|
(status.isClaudeProcessing || status.isCodexProcessing) && /* @__PURE__ */ jsxs6("box", { backgroundColor: "#1a1500", paddingX: 1, marginX: 1, marginBottom: 1, children: [
|
|
1453
1578
|
status.isClaudeProcessing && /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsxs6("span", { fg: "#ffaa00", children: [
|
|
1454
1579
|
"\u25C6",
|
|
@@ -1474,42 +1599,60 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1474
1599
|
/* @__PURE__ */ jsx6(CardItem, { label: "Slack", status: env.slackAccessConfigured }),
|
|
1475
1600
|
/* @__PURE__ */ jsx6(CardItem, { label: "Linear", status: env.linearAccessConfigured })
|
|
1476
1601
|
] }),
|
|
1477
|
-
previews.length > 0 && /* @__PURE__ */ jsx6(Section, { title: "Previews", children: previews.map((preview, i) =>
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1602
|
+
previews.length > 0 && /* @__PURE__ */ jsx6(Section, { title: "Previews", children: previews.map((preview, i) => {
|
|
1603
|
+
const previewItem = findItem("preview", String(preview.port));
|
|
1604
|
+
return /* @__PURE__ */ jsxs6(
|
|
1605
|
+
"box",
|
|
1606
|
+
{
|
|
1607
|
+
flexDirection: "row",
|
|
1608
|
+
justifyContent: "space-between",
|
|
1609
|
+
paddingX: 1,
|
|
1610
|
+
backgroundColor: previewItem && isHighlighted(previewItem) ? "#1a2a1a" : "#111111",
|
|
1611
|
+
onMouseDown: () => previewItem && handleAction(previewItem),
|
|
1612
|
+
children: [
|
|
1613
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsxs6("span", { fg: "#cccccc", children: [
|
|
1614
|
+
":",
|
|
1615
|
+
preview.port
|
|
1616
|
+
] }) }),
|
|
1617
|
+
/* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: previewItem && isHighlighted(previewItem) ? "#66bb6a" : "#7dcfff", children: "\u2197" }) })
|
|
1618
|
+
]
|
|
1619
|
+
},
|
|
1620
|
+
i
|
|
1621
|
+
);
|
|
1622
|
+
}) }),
|
|
1623
|
+
status.repoStatuses && status.repoStatuses.length > 0 && /* @__PURE__ */ jsx6(Section, { title: "Repositories", children: status.repoStatuses.map((repo, i) => {
|
|
1624
|
+
const prItem = findItem("pr", repo.name);
|
|
1625
|
+
return /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
1626
|
+
/* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, children: /* @__PURE__ */ jsx6("text", { children: /* @__PURE__ */ jsx6("span", { fg: "#ffffff", children: /* @__PURE__ */ jsx6("strong", { children: repo.name }) }) }) }),
|
|
1627
|
+
/* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: /* @__PURE__ */ jsxs6("text", { children: [
|
|
1628
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#555555", children: [
|
|
1629
|
+
"\u2514",
|
|
1630
|
+
" "
|
|
1631
|
+
] }),
|
|
1632
|
+
/* @__PURE__ */ jsx6("span", { fg: repo.currentBranch !== repo.defaultBranch ? "#ffaa00" : "#66bb6a", children: repo.currentBranch })
|
|
1633
|
+
] }) }),
|
|
1634
|
+
repo.gitDiff && (repo.gitDiff.added > 0 || repo.gitDiff.removed > 0) && /* @__PURE__ */ jsx6("box", { backgroundColor: "#111111", paddingX: 1, flexDirection: "row", children: /* @__PURE__ */ jsxs6("text", { children: [
|
|
1635
|
+
/* @__PURE__ */ jsx6("span", { fg: "#555555", children: " " }),
|
|
1636
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#66bb6a", children: [
|
|
1637
|
+
"+",
|
|
1638
|
+
repo.gitDiff.added
|
|
1639
|
+
] }),
|
|
1640
|
+
/* @__PURE__ */ jsx6("span", { fg: "#444444", children: " / " }),
|
|
1641
|
+
/* @__PURE__ */ jsxs6("span", { fg: "#ff4444", children: [
|
|
1642
|
+
"-",
|
|
1643
|
+
repo.gitDiff.removed
|
|
1644
|
+
] })
|
|
1645
|
+
] }) }),
|
|
1646
|
+
prItem && /* @__PURE__ */ jsx6(
|
|
1647
|
+
InteractiveRow,
|
|
1648
|
+
{
|
|
1649
|
+
label: ` ${getItemLabel(prItem)}`,
|
|
1650
|
+
highlighted: isHighlighted(prItem),
|
|
1651
|
+
onClick: () => handleAction(prItem)
|
|
1652
|
+
}
|
|
1653
|
+
)
|
|
1654
|
+
] }, i);
|
|
1655
|
+
}) }),
|
|
1513
1656
|
env && /* @__PURE__ */ jsxs6(Section, { title: "Hooks", children: [
|
|
1514
1657
|
/* @__PURE__ */ jsx6(CardItem, { label: "Global warm", status: env.globalWarmHookCompleted.status }),
|
|
1515
1658
|
env.repositories.map((repo, i) => /* @__PURE__ */ jsxs6(React4.Fragment, { children: [
|
|
@@ -1548,7 +1691,7 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
1548
1691
|
import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
|
|
1549
1692
|
|
|
1550
1693
|
// src/interactive/toast-context.tsx
|
|
1551
|
-
import { createContext as createContext2, useContext as useContext2, useState as
|
|
1694
|
+
import { createContext as createContext2, useContext as useContext2, useState as useState5, useCallback as useCallback5, useRef as useRef2 } from "react";
|
|
1552
1695
|
import { jsx as jsx7 } from "@opentui/react/jsx-runtime";
|
|
1553
1696
|
var ToastContext = createContext2(null);
|
|
1554
1697
|
function useToast() {
|
|
@@ -1557,9 +1700,9 @@ function useToast() {
|
|
|
1557
1700
|
return ctx;
|
|
1558
1701
|
}
|
|
1559
1702
|
function ToastProvider({ children }) {
|
|
1560
|
-
const [current, setCurrent] =
|
|
1703
|
+
const [current, setCurrent] = useState5(null);
|
|
1561
1704
|
const timeoutRef = useRef2(null);
|
|
1562
|
-
const show =
|
|
1705
|
+
const show = useCallback5((options) => {
|
|
1563
1706
|
const { message, variant = "info", duration = 3e3 } = options;
|
|
1564
1707
|
setCurrent({ message, variant });
|
|
1565
1708
|
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
@@ -1567,7 +1710,7 @@ function ToastProvider({ children }) {
|
|
|
1567
1710
|
setCurrent(null);
|
|
1568
1711
|
}, duration);
|
|
1569
1712
|
}, []);
|
|
1570
|
-
const error =
|
|
1713
|
+
const error = useCallback5((err) => {
|
|
1571
1714
|
const message = err instanceof Error ? err.message : "An error occurred";
|
|
1572
1715
|
show({ message, variant: "error", duration: 5e3 });
|
|
1573
1716
|
}, [show]);
|
|
@@ -1652,17 +1795,17 @@ function AppInner() {
|
|
|
1652
1795
|
renderer.off("selection", handler);
|
|
1653
1796
|
};
|
|
1654
1797
|
}, [renderer, toast]);
|
|
1655
|
-
const [selectedWorkspaceId, setSelectedWorkspaceId] =
|
|
1656
|
-
const [selectedChatId, setSelectedChatId] =
|
|
1657
|
-
const [focusPanel, setFocusPanel] =
|
|
1658
|
-
const [taskMode, setTaskMode] =
|
|
1659
|
-
const [mockWorkspaces, setMockWorkspaces] =
|
|
1798
|
+
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState6(null);
|
|
1799
|
+
const [selectedChatId, setSelectedChatId] = useState6(null);
|
|
1800
|
+
const [focusPanel, setFocusPanel] = useState6("sidebar");
|
|
1801
|
+
const [taskMode, setTaskMode] = useState6("build");
|
|
1802
|
+
const [mockWorkspaces, setMockWorkspaces] = useState6([]);
|
|
1660
1803
|
const mockToRealRef = useRef3(/* @__PURE__ */ new Map());
|
|
1661
1804
|
const mockGroupRef = useRef3(/* @__PURE__ */ new Map());
|
|
1662
|
-
const [mockMessages, setMockMessages] =
|
|
1663
|
-
const [mockThinking, setMockThinking] =
|
|
1805
|
+
const [mockMessages, setMockMessages] = useState6([]);
|
|
1806
|
+
const [mockThinking, setMockThinking] = useState6(false);
|
|
1664
1807
|
const pendingMessageRef = useRef3(/* @__PURE__ */ new Map());
|
|
1665
|
-
const mockIds =
|
|
1808
|
+
const mockIds = useMemo4(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
|
|
1666
1809
|
const isMockSelected = selectedWorkspaceId ? mockIds.has(selectedWorkspaceId) : false;
|
|
1667
1810
|
const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(1, 100, "organization");
|
|
1668
1811
|
const { data: reposData } = useRepositories();
|
|
@@ -1676,7 +1819,7 @@ function AppInner() {
|
|
|
1676
1819
|
);
|
|
1677
1820
|
const { data: chatsData } = useWorkspaceChats(isMockSelected ? null : selectedWorkspaceId);
|
|
1678
1821
|
const chats = isMockSelected ? MOCK_CHATS : chatsData?.chats ?? [];
|
|
1679
|
-
const resolvedChatId =
|
|
1822
|
+
const resolvedChatId = useMemo4(() => {
|
|
1680
1823
|
if (selectedChatId && chats.find((c) => c.id === selectedChatId)) {
|
|
1681
1824
|
return selectedChatId;
|
|
1682
1825
|
}
|
|
@@ -1694,22 +1837,22 @@ function AppInner() {
|
|
|
1694
1837
|
const deleteWorkspaceMutation = useDeleteWorkspace();
|
|
1695
1838
|
const wakeWorkspaceMutation = useWakeWorkspace();
|
|
1696
1839
|
const generateNameMutation = useGenerateWorkspaceName();
|
|
1697
|
-
const [wakingWorkspaceId, setWakingWorkspaceId] =
|
|
1840
|
+
const [wakingWorkspaceId, setWakingWorkspaceId] = useState6(null);
|
|
1698
1841
|
const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
|
|
1699
1842
|
const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
|
|
1700
1843
|
const workspaces = workspacesData?.workspaces ?? [];
|
|
1701
1844
|
const repositories = reposData?.repositories ?? [];
|
|
1702
1845
|
const repositorySets = setsData?.repository_sets ?? [];
|
|
1703
1846
|
const previews = previewsData?.previews ?? [];
|
|
1704
|
-
const allWorkspaces =
|
|
1705
|
-
const groups =
|
|
1847
|
+
const allWorkspaces = useMemo4(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
|
|
1848
|
+
const groups = useMemo4(
|
|
1706
1849
|
() => buildGroups(allWorkspaces, workspacesData, repositories, repositorySets, mockGroupRef.current),
|
|
1707
1850
|
[allWorkspaces, workspacesData, repositories, repositorySets]
|
|
1708
1851
|
);
|
|
1709
1852
|
const selectedWorkspace = allWorkspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
|
|
1710
1853
|
const selectedChat = chats.find((c) => c.id === resolvedChatId) ?? null;
|
|
1711
1854
|
const isProcessing = mockThinking || (selectedChat?.processing ?? false);
|
|
1712
|
-
const displayMessages =
|
|
1855
|
+
const displayMessages = useMemo4(() => {
|
|
1713
1856
|
if (isMockSelected) return mockMessages;
|
|
1714
1857
|
const rawEvents = historyData?.events ?? [];
|
|
1715
1858
|
const events = rawEvents.filter(isAgentBackendEvent);
|
|
@@ -1773,17 +1916,17 @@ function AppInner() {
|
|
|
1773
1916
|
}, 5e3);
|
|
1774
1917
|
return () => clearInterval(interval);
|
|
1775
1918
|
}, [mockWorkspaces.length]);
|
|
1776
|
-
const handleSelectWorkspace =
|
|
1919
|
+
const handleSelectWorkspace = useCallback6((workspaceId) => {
|
|
1777
1920
|
setSelectedWorkspaceId(workspaceId);
|
|
1778
1921
|
setSelectedChatId(null);
|
|
1779
1922
|
setMockMessages([]);
|
|
1780
1923
|
setMockThinking(false);
|
|
1781
1924
|
setFocusPanel("chat-input");
|
|
1782
1925
|
}, []);
|
|
1783
|
-
const handleFocus =
|
|
1926
|
+
const handleFocus = useCallback6((panel) => {
|
|
1784
1927
|
setFocusPanel(panel);
|
|
1785
1928
|
}, []);
|
|
1786
|
-
const handleCreateWorkspace =
|
|
1929
|
+
const handleCreateWorkspace = useCallback6(
|
|
1787
1930
|
async (groupId, groupType) => {
|
|
1788
1931
|
const orgId = getOrganizationId() ?? "";
|
|
1789
1932
|
const mock = createMockWorkspaceRecord(orgId);
|
|
@@ -1802,7 +1945,7 @@ function AppInner() {
|
|
|
1802
1945
|
},
|
|
1803
1946
|
[createWorkspaceMutation, toast]
|
|
1804
1947
|
);
|
|
1805
|
-
const handleDeleteWorkspace =
|
|
1948
|
+
const handleDeleteWorkspace = useCallback6(
|
|
1806
1949
|
async (workspaceId) => {
|
|
1807
1950
|
if (mockIds.has(workspaceId)) {
|
|
1808
1951
|
mockGroupRef.current.delete(workspaceId);
|
|
@@ -1821,7 +1964,7 @@ function AppInner() {
|
|
|
1821
1964
|
},
|
|
1822
1965
|
[mockIds, selectedWorkspaceId, deleteWorkspaceMutation]
|
|
1823
1966
|
);
|
|
1824
|
-
const handleWakeWorkspace =
|
|
1967
|
+
const handleWakeWorkspace = useCallback6(
|
|
1825
1968
|
async (workspaceId) => {
|
|
1826
1969
|
setWakingWorkspaceId(workspaceId);
|
|
1827
1970
|
try {
|
|
@@ -1835,10 +1978,10 @@ function AppInner() {
|
|
|
1835
1978
|
},
|
|
1836
1979
|
[wakeWorkspaceMutation, toast]
|
|
1837
1980
|
);
|
|
1838
|
-
const handleSelectChat =
|
|
1981
|
+
const handleSelectChat = useCallback6((chatId) => {
|
|
1839
1982
|
setSelectedChatId(chatId);
|
|
1840
1983
|
}, []);
|
|
1841
|
-
|
|
1984
|
+
useKeyboard4((key) => {
|
|
1842
1985
|
if (key.name === "f12") {
|
|
1843
1986
|
renderer.console.toggle();
|
|
1844
1987
|
return;
|
|
@@ -1871,13 +2014,7 @@ function AppInner() {
|
|
|
1871
2014
|
setTaskMode((m) => m === "build" ? "plan" : "build");
|
|
1872
2015
|
return;
|
|
1873
2016
|
}
|
|
1874
|
-
if (key.name === "
|
|
1875
|
-
const webUrl = process.env.REPLICAS_WEB_URL || "https://replicas.dev";
|
|
1876
|
-
import("open").then((mod) => mod.default(`${webUrl}/dashboard?workspaceId=${selectedWorkspaceId}`)).catch(() => {
|
|
1877
|
-
});
|
|
1878
|
-
return;
|
|
1879
|
-
}
|
|
1880
|
-
if (key.name === "w" && focusPanel !== "sidebar" && selectedWorkspaceId) {
|
|
2017
|
+
if (key.name === "w" && focusPanel !== "sidebar" && focusPanel !== "info" && selectedWorkspaceId) {
|
|
1881
2018
|
if (statusData?.status === "sleeping" && !wakingWorkspaceId) {
|
|
1882
2019
|
handleWakeWorkspace(selectedWorkspaceId);
|
|
1883
2020
|
}
|
|
@@ -1885,7 +2022,7 @@ function AppInner() {
|
|
|
1885
2022
|
}
|
|
1886
2023
|
if (focusPanel === "chat-input") return;
|
|
1887
2024
|
});
|
|
1888
|
-
const handleSendMessage =
|
|
2025
|
+
const handleSendMessage = useCallback6(
|
|
1889
2026
|
async (message) => {
|
|
1890
2027
|
if (!selectedWorkspaceId || !resolvedChatId) return;
|
|
1891
2028
|
if (isMockSelected) {
|