replicas-cli 0.2.113 → 0.2.114
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.
|
@@ -8213,69 +8213,51 @@ function generatePlaceholderName() {
|
|
|
8213
8213
|
}
|
|
8214
8214
|
|
|
8215
8215
|
// ../shared/src/workspace-groups.ts
|
|
8216
|
-
function
|
|
8217
|
-
if (workspaceRepoIds.length <= 1) return null;
|
|
8218
|
-
for (const set of repositorySets) {
|
|
8219
|
-
const setRepoIds = new Set(set.repositories.map((r) => r.id));
|
|
8220
|
-
if (workspaceRepoIds.every((id) => setRepoIds.has(id))) {
|
|
8221
|
-
return set;
|
|
8222
|
-
}
|
|
8223
|
-
}
|
|
8224
|
-
return null;
|
|
8225
|
-
}
|
|
8226
|
-
function buildGroups(workspaces, workspacesData, repositories, repositorySets, mockGroupAssignments) {
|
|
8216
|
+
function buildGroups(workspaces, _workspacesData, environments, _repositorySets, mockGroupAssignments) {
|
|
8227
8217
|
const groupMap = /* @__PURE__ */ new Map();
|
|
8228
|
-
for (const
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8218
|
+
for (const env of environments) {
|
|
8219
|
+
if (env.is_global) continue;
|
|
8220
|
+
if (!env.repository_id && !env.repository_set_id) continue;
|
|
8221
|
+
groupMap.set(env.id, {
|
|
8222
|
+
type: "env",
|
|
8223
|
+
id: env.id,
|
|
8224
|
+
name: env.name,
|
|
8225
|
+
environmentId: env.id,
|
|
8226
|
+
repoIdForCreate: env.repository_id,
|
|
8227
|
+
repoSetIdForCreate: env.repository_set_id,
|
|
8228
|
+
workspaces: []
|
|
8229
|
+
});
|
|
8234
8230
|
}
|
|
8235
|
-
const
|
|
8231
|
+
const placeUngrouped = (workspace) => {
|
|
8232
|
+
const key = "__ungrouped__";
|
|
8233
|
+
if (!groupMap.has(key)) {
|
|
8234
|
+
groupMap.set(key, {
|
|
8235
|
+
type: "env",
|
|
8236
|
+
id: key,
|
|
8237
|
+
name: "Other",
|
|
8238
|
+
environmentId: key,
|
|
8239
|
+
repoIdForCreate: null,
|
|
8240
|
+
repoSetIdForCreate: null,
|
|
8241
|
+
workspaces: []
|
|
8242
|
+
});
|
|
8243
|
+
}
|
|
8244
|
+
groupMap.get(key).workspaces.push(workspace);
|
|
8245
|
+
};
|
|
8236
8246
|
for (const workspace of workspaces) {
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
placedInSet = true;
|
|
8246
|
-
}
|
|
8247
|
-
}
|
|
8248
|
-
if (!placedInSet) {
|
|
8249
|
-
const primaryRepo = repos[0];
|
|
8250
|
-
const group = groupMap.get(primaryRepo.id);
|
|
8251
|
-
if (group) {
|
|
8252
|
-
group.workspaces.push(workspace);
|
|
8253
|
-
} else {
|
|
8254
|
-
groupMap.set(primaryRepo.id, {
|
|
8255
|
-
type: "repo",
|
|
8256
|
-
id: primaryRepo.id,
|
|
8257
|
-
name: primaryRepo.name,
|
|
8258
|
-
url: primaryRepo.url,
|
|
8259
|
-
workspaces: [workspace]
|
|
8260
|
-
});
|
|
8261
|
-
}
|
|
8262
|
-
}
|
|
8263
|
-
} else {
|
|
8264
|
-
const assignedGroup = mockGroupAssignments.get(workspace.id);
|
|
8265
|
-
if (assignedGroup && groupMap.has(assignedGroup)) {
|
|
8266
|
-
groupMap.get(assignedGroup).workspaces.push(workspace);
|
|
8267
|
-
} else {
|
|
8268
|
-
const key = "__ungrouped__";
|
|
8269
|
-
if (!groupMap.has(key)) {
|
|
8270
|
-
groupMap.set(key, { type: "repo", id: key, name: "Other", workspaces: [] });
|
|
8271
|
-
}
|
|
8272
|
-
groupMap.get(key).workspaces.push(workspace);
|
|
8273
|
-
}
|
|
8247
|
+
if (workspace.environment_id && groupMap.has(workspace.environment_id)) {
|
|
8248
|
+
groupMap.get(workspace.environment_id).workspaces.push(workspace);
|
|
8249
|
+
continue;
|
|
8250
|
+
}
|
|
8251
|
+
const assignedGroup = mockGroupAssignments.get(workspace.id);
|
|
8252
|
+
if (assignedGroup && groupMap.has(assignedGroup)) {
|
|
8253
|
+
groupMap.get(assignedGroup).workspaces.push(workspace);
|
|
8254
|
+
continue;
|
|
8274
8255
|
}
|
|
8256
|
+
placeUngrouped(workspace);
|
|
8275
8257
|
}
|
|
8276
8258
|
return Array.from(groupMap.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
8277
8259
|
}
|
|
8278
|
-
function createMockWorkspaceRecord(organizationId, name) {
|
|
8260
|
+
function createMockWorkspaceRecord(organizationId, name, environmentId) {
|
|
8279
8261
|
const id = "mock-" + Array.from(
|
|
8280
8262
|
{ length: 4 },
|
|
8281
8263
|
() => Math.random().toString(36).slice(2, 6)
|
|
@@ -8296,7 +8278,8 @@ function createMockWorkspaceRecord(organizationId, name) {
|
|
|
8296
8278
|
creator_email: null,
|
|
8297
8279
|
soft_delete: false,
|
|
8298
8280
|
lifecycle_policy: "default",
|
|
8299
|
-
auto_stop_minutes: null
|
|
8281
|
+
auto_stop_minutes: null,
|
|
8282
|
+
environment_id: environmentId ?? null
|
|
8300
8283
|
};
|
|
8301
8284
|
}
|
|
8302
8285
|
|
package/dist/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
setIdeCommand,
|
|
17
17
|
setOrganizationId,
|
|
18
18
|
writeConfig
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-HOO346QO.mjs";
|
|
20
20
|
|
|
21
21
|
// src/index.ts
|
|
22
22
|
import "dotenv/config";
|
|
@@ -1463,15 +1463,17 @@ async function replicaCreateCommand(name, options) {
|
|
|
1463
1463
|
process.exit(1);
|
|
1464
1464
|
}
|
|
1465
1465
|
try {
|
|
1466
|
-
const
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
|
|
1466
|
+
const envResponse = await orgAuthenticatedFetch("/v1/environments");
|
|
1467
|
+
const environments = envResponse.environments.filter(
|
|
1468
|
+
(env) => !env.is_global && (env.repository_id || env.repository_set_id)
|
|
1469
|
+
);
|
|
1470
|
+
if (environments.length === 0) {
|
|
1471
|
+
console.log(chalk14.red("No repository-bound environments found. Please add a repository or bind an environment first."));
|
|
1470
1472
|
process.exit(1);
|
|
1471
1473
|
}
|
|
1472
1474
|
let replicaName = name;
|
|
1473
1475
|
let message = options.message;
|
|
1474
|
-
let
|
|
1476
|
+
let selectedEnvironmentId = options.environment?.trim();
|
|
1475
1477
|
let codingAgent = options.agent;
|
|
1476
1478
|
if (replicaName && /\s/.test(replicaName)) {
|
|
1477
1479
|
console.log(chalk14.red("Replica name cannot contain spaces."));
|
|
@@ -1494,23 +1496,22 @@ async function replicaCreateCommand(name, options) {
|
|
|
1494
1496
|
}
|
|
1495
1497
|
replicaName = response2.name;
|
|
1496
1498
|
}
|
|
1497
|
-
if (!
|
|
1499
|
+
if (!selectedEnvironmentId) {
|
|
1498
1500
|
const response2 = await prompts3({
|
|
1499
|
-
type: "
|
|
1500
|
-
name: "
|
|
1501
|
-
message: "Select
|
|
1502
|
-
choices:
|
|
1503
|
-
title:
|
|
1504
|
-
value:
|
|
1505
|
-
description:
|
|
1506
|
-
}))
|
|
1507
|
-
min: 1
|
|
1501
|
+
type: "select",
|
|
1502
|
+
name: "environment",
|
|
1503
|
+
message: "Select environment:",
|
|
1504
|
+
choices: environments.map((env) => ({
|
|
1505
|
+
title: env.name,
|
|
1506
|
+
value: env.id,
|
|
1507
|
+
description: env.repository_set_id ? "repository set" : "repository"
|
|
1508
|
+
}))
|
|
1508
1509
|
});
|
|
1509
|
-
if (!response2.
|
|
1510
|
+
if (!response2.environment) {
|
|
1510
1511
|
console.log(chalk14.yellow("\nCancelled."));
|
|
1511
1512
|
return;
|
|
1512
1513
|
}
|
|
1513
|
-
|
|
1514
|
+
selectedEnvironmentId = response2.environment;
|
|
1514
1515
|
}
|
|
1515
1516
|
if (!message) {
|
|
1516
1517
|
const response2 = await prompts3({
|
|
@@ -1549,7 +1550,7 @@ async function replicaCreateCommand(name, options) {
|
|
|
1549
1550
|
const body = {
|
|
1550
1551
|
name: replicaName,
|
|
1551
1552
|
message,
|
|
1552
|
-
|
|
1553
|
+
environment_id: selectedEnvironmentId,
|
|
1553
1554
|
coding_agent: codingAgent
|
|
1554
1555
|
};
|
|
1555
1556
|
console.log(chalk14.gray("\nCreating replica..."));
|
|
@@ -1757,6 +1758,16 @@ function truncate2(text, maxLength) {
|
|
|
1757
1758
|
if (text.length <= maxLength) return text;
|
|
1758
1759
|
return text.substring(0, maxLength) + "...";
|
|
1759
1760
|
}
|
|
1761
|
+
function resolveSelectableEnvironmentId(envInput, selectableEnvs) {
|
|
1762
|
+
const env = selectableEnvs.find((e) => e.name === envInput || e.id === envInput);
|
|
1763
|
+
if (!env) {
|
|
1764
|
+
console.log(chalk16.red(`Environment not found: ${envInput}`));
|
|
1765
|
+
const available = selectableEnvs.map((e) => e.name).join(", ");
|
|
1766
|
+
console.log(chalk16.gray(`Available: ${available || "(none)"}`));
|
|
1767
|
+
process.exit(1);
|
|
1768
|
+
}
|
|
1769
|
+
return env.id;
|
|
1770
|
+
}
|
|
1760
1771
|
function printAutomation(automation2) {
|
|
1761
1772
|
console.log(chalk16.white(` ${automation2.name}`));
|
|
1762
1773
|
console.log(chalk16.gray(` ID: ${automation2.id}`));
|
|
@@ -1830,12 +1841,7 @@ Automation: ${automation2.name}
|
|
|
1830
1841
|
}
|
|
1831
1842
|
}
|
|
1832
1843
|
console.log(chalk16.gray(` Prompt: ${automation2.prompt}`));
|
|
1833
|
-
|
|
1834
|
-
console.log(chalk16.gray(` Repository IDs: ${automation2.repository_ids.join(", ")}`));
|
|
1835
|
-
}
|
|
1836
|
-
if (automation2.repository_set_id) {
|
|
1837
|
-
console.log(chalk16.gray(` Repository Set: ${automation2.repository_set_id}`));
|
|
1838
|
-
}
|
|
1844
|
+
console.log(chalk16.gray(` Environment: ${automation2.environment_id}`));
|
|
1839
1845
|
if (automation2.cron_expression) {
|
|
1840
1846
|
console.log(chalk16.gray(` Cron: ${automation2.cron_expression}`));
|
|
1841
1847
|
}
|
|
@@ -1934,10 +1940,6 @@ async function promptForTriggers(repositories) {
|
|
|
1934
1940
|
}
|
|
1935
1941
|
async function automationCreateCommand(name, options) {
|
|
1936
1942
|
ensureAuthenticated();
|
|
1937
|
-
if (options.repositories && options.repositorySet) {
|
|
1938
|
-
console.log(chalk16.red("Cannot use both --repositories (-r) and --repository-set (-s). Choose one."));
|
|
1939
|
-
process.exit(1);
|
|
1940
|
-
}
|
|
1941
1943
|
const validLifecycles = ["default", "delete_when_done", "delete_after_inactivity"];
|
|
1942
1944
|
if (options.lifecycle && !validLifecycles.includes(options.lifecycle)) {
|
|
1943
1945
|
console.log(chalk16.red(`Invalid lifecycle policy: ${options.lifecycle}`));
|
|
@@ -1956,12 +1958,15 @@ async function automationCreateCommand(name, options) {
|
|
|
1956
1958
|
}
|
|
1957
1959
|
}
|
|
1958
1960
|
try {
|
|
1959
|
-
const
|
|
1960
|
-
const
|
|
1961
|
-
|
|
1962
|
-
|
|
1961
|
+
const envResponse = await orgAuthenticatedFetch("/v1/environments");
|
|
1962
|
+
const allEnvs = envResponse.environments;
|
|
1963
|
+
const selectableEnvs = allEnvs.filter((env) => !env.is_global);
|
|
1964
|
+
if (selectableEnvs.length === 0) {
|
|
1965
|
+
console.log(chalk16.red("No environments found. Please create an environment first."));
|
|
1963
1966
|
process.exit(1);
|
|
1964
1967
|
}
|
|
1968
|
+
const repoResponse = await orgAuthenticatedFetch("/v1/repositories");
|
|
1969
|
+
const repositories = repoResponse.repositories;
|
|
1965
1970
|
let automationName = name;
|
|
1966
1971
|
if (!automationName) {
|
|
1967
1972
|
const response2 = await prompts4({
|
|
@@ -1990,83 +1995,25 @@ async function automationCreateCommand(name, options) {
|
|
|
1990
1995
|
}
|
|
1991
1996
|
automationPrompt = response2.prompt;
|
|
1992
1997
|
}
|
|
1993
|
-
let
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
const setsResponse = await orgAuthenticatedFetch("/v1/repository-sets");
|
|
1997
|
-
const repoSet = setsResponse.repository_sets.find((s) => s.name === options.repositorySet);
|
|
1998
|
-
if (!repoSet) {
|
|
1999
|
-
console.log(chalk16.red(`Repository set not found: ${options.repositorySet}`));
|
|
2000
|
-
const available = setsResponse.repository_sets.map((s) => s.name).join(", ");
|
|
2001
|
-
console.log(chalk16.gray(`Available: ${available || "(none)"}`));
|
|
2002
|
-
process.exit(1);
|
|
2003
|
-
}
|
|
2004
|
-
selectedRepoSetId = repoSet.id;
|
|
2005
|
-
} else if (options.repositories) {
|
|
2006
|
-
const repoNames = options.repositories.split(",").map((r) => r.trim()).filter(Boolean);
|
|
2007
|
-
for (const repoName of repoNames) {
|
|
2008
|
-
const repo = repositories.find((r) => r.name === repoName);
|
|
2009
|
-
if (!repo) {
|
|
2010
|
-
console.log(chalk16.red(`Repository not found: ${repoName}`));
|
|
2011
|
-
console.log(chalk16.gray(`Available: ${repositories.map((r) => r.name).join(", ")}`));
|
|
2012
|
-
process.exit(1);
|
|
2013
|
-
}
|
|
2014
|
-
selectedRepoIds.push(repo.id);
|
|
2015
|
-
}
|
|
1998
|
+
let selectedEnvironmentId;
|
|
1999
|
+
if (options.environment) {
|
|
2000
|
+
selectedEnvironmentId = resolveSelectableEnvironmentId(options.environment, selectableEnvs);
|
|
2016
2001
|
} else {
|
|
2017
|
-
const
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
if (!modeResponse.mode) {
|
|
2031
|
-
console.log(chalk16.yellow("\nCancelled."));
|
|
2032
|
-
return;
|
|
2033
|
-
}
|
|
2034
|
-
useRepoSet = modeResponse.mode === "set";
|
|
2035
|
-
}
|
|
2036
|
-
if (useRepoSet) {
|
|
2037
|
-
const setResponse = await prompts4({
|
|
2038
|
-
type: "select",
|
|
2039
|
-
name: "set",
|
|
2040
|
-
message: "Select repository set:",
|
|
2041
|
-
choices: repoSets.map((s) => ({
|
|
2042
|
-
title: s.name,
|
|
2043
|
-
value: s.id,
|
|
2044
|
-
description: s.description || `${s.repositories.length} repos`
|
|
2045
|
-
}))
|
|
2046
|
-
});
|
|
2047
|
-
if (!setResponse.set) {
|
|
2048
|
-
console.log(chalk16.yellow("\nCancelled."));
|
|
2049
|
-
return;
|
|
2050
|
-
}
|
|
2051
|
-
selectedRepoSetId = setResponse.set;
|
|
2052
|
-
} else {
|
|
2053
|
-
const response2 = await prompts4({
|
|
2054
|
-
type: "multiselect",
|
|
2055
|
-
name: "repositories",
|
|
2056
|
-
message: "Select repositories:",
|
|
2057
|
-
choices: repositories.map((repo) => ({
|
|
2058
|
-
title: repo.name,
|
|
2059
|
-
value: repo.id,
|
|
2060
|
-
description: repo.url
|
|
2061
|
-
})),
|
|
2062
|
-
min: 1
|
|
2063
|
-
});
|
|
2064
|
-
if (!response2.repositories || response2.repositories.length === 0) {
|
|
2065
|
-
console.log(chalk16.yellow("\nCancelled."));
|
|
2066
|
-
return;
|
|
2067
|
-
}
|
|
2068
|
-
selectedRepoIds = response2.repositories;
|
|
2002
|
+
const envResponse2 = await prompts4({
|
|
2003
|
+
type: "select",
|
|
2004
|
+
name: "env",
|
|
2005
|
+
message: "Select environment:",
|
|
2006
|
+
choices: selectableEnvs.map((env) => ({
|
|
2007
|
+
title: env.name,
|
|
2008
|
+
value: env.id,
|
|
2009
|
+
description: env.description || (env.repository_id ? "repo-bound" : env.repository_set_id ? "set-bound" : "unbound")
|
|
2010
|
+
}))
|
|
2011
|
+
});
|
|
2012
|
+
if (!envResponse2.env) {
|
|
2013
|
+
console.log(chalk16.yellow("\nCancelled."));
|
|
2014
|
+
return;
|
|
2069
2015
|
}
|
|
2016
|
+
selectedEnvironmentId = envResponse2.env;
|
|
2070
2017
|
}
|
|
2071
2018
|
let triggers = [];
|
|
2072
2019
|
if (options.triggerCron) {
|
|
@@ -2108,18 +2055,10 @@ async function automationCreateCommand(name, options) {
|
|
|
2108
2055
|
process.exit(1);
|
|
2109
2056
|
}
|
|
2110
2057
|
}
|
|
2111
|
-
const body =
|
|
2112
|
-
name: automationName,
|
|
2113
|
-
prompt: automationPrompt,
|
|
2114
|
-
repository_set_id: selectedRepoSetId,
|
|
2115
|
-
triggers,
|
|
2116
|
-
enabled: options.enabled !== false,
|
|
2117
|
-
...options.lifecycle ? { workspace_lifecycle_policy: options.lifecycle } : {},
|
|
2118
|
-
...options.autoStopMinutes ? { workspace_auto_stop_minutes: parseInt(options.autoStopMinutes, 10) } : {}
|
|
2119
|
-
} : {
|
|
2058
|
+
const body = {
|
|
2120
2059
|
name: automationName,
|
|
2121
2060
|
prompt: automationPrompt,
|
|
2122
|
-
|
|
2061
|
+
environment_id: selectedEnvironmentId,
|
|
2123
2062
|
triggers,
|
|
2124
2063
|
enabled: options.enabled !== false,
|
|
2125
2064
|
...options.lifecycle ? { workspace_lifecycle_policy: options.lifecycle } : {},
|
|
@@ -2149,10 +2088,6 @@ Created automation: ${automation2.name}`));
|
|
|
2149
2088
|
}
|
|
2150
2089
|
async function automationEditCommand(id, options) {
|
|
2151
2090
|
ensureAuthenticated();
|
|
2152
|
-
if (options.repositories && options.repositorySet) {
|
|
2153
|
-
console.log(chalk16.red("Cannot use both --repositories (-r) and --repository-set (-s). Choose one."));
|
|
2154
|
-
process.exit(1);
|
|
2155
|
-
}
|
|
2156
2091
|
const validLifecycles = ["default", "delete_when_done", "delete_after_inactivity"];
|
|
2157
2092
|
if (options.lifecycle && !validLifecycles.includes(options.lifecycle)) {
|
|
2158
2093
|
console.log(chalk16.red(`Invalid lifecycle policy: ${options.lifecycle}`));
|
|
@@ -2173,7 +2108,7 @@ async function automationEditCommand(id, options) {
|
|
|
2173
2108
|
try {
|
|
2174
2109
|
const existing = await orgAuthenticatedFetch(`/v1/automations/${id}`);
|
|
2175
2110
|
const body = {};
|
|
2176
|
-
const hasOptions = options.name || options.prompt || options.enabled !== void 0 || options.triggerCron || options.triggerGithub || options.
|
|
2111
|
+
const hasOptions = options.name || options.prompt || options.enabled !== void 0 || options.triggerCron || options.triggerGithub || options.environment || options.lifecycle || options.autoStopMinutes;
|
|
2177
2112
|
if (!hasOptions) {
|
|
2178
2113
|
const nameResponse = await prompts4({
|
|
2179
2114
|
type: "text",
|
|
@@ -2257,30 +2192,10 @@ async function automationEditCommand(id, options) {
|
|
|
2257
2192
|
}
|
|
2258
2193
|
body.triggers = triggers;
|
|
2259
2194
|
}
|
|
2260
|
-
if (options.
|
|
2261
|
-
const
|
|
2262
|
-
const
|
|
2263
|
-
|
|
2264
|
-
console.log(chalk16.red(`Repository set not found: ${options.repositorySet}`));
|
|
2265
|
-
const available = setsResponse.repository_sets.map((s) => s.name).join(", ");
|
|
2266
|
-
console.log(chalk16.gray(`Available: ${available || "(none)"}`));
|
|
2267
|
-
process.exit(1);
|
|
2268
|
-
}
|
|
2269
|
-
body.repository_set_id = repoSet.id;
|
|
2270
|
-
} else if (options.repositories) {
|
|
2271
|
-
const repoResponse = await orgAuthenticatedFetch("/v1/repositories");
|
|
2272
|
-
const repoNames = options.repositories.split(",").map((r) => r.trim()).filter(Boolean);
|
|
2273
|
-
const repoIds = [];
|
|
2274
|
-
for (const repoName of repoNames) {
|
|
2275
|
-
const repo = repoResponse.repositories.find((r) => r.name === repoName);
|
|
2276
|
-
if (!repo) {
|
|
2277
|
-
console.log(chalk16.red(`Repository not found: ${repoName}`));
|
|
2278
|
-
console.log(chalk16.gray(`Available: ${repoResponse.repositories.map((r) => r.name).join(", ")}`));
|
|
2279
|
-
process.exit(1);
|
|
2280
|
-
}
|
|
2281
|
-
repoIds.push(repo.id);
|
|
2282
|
-
}
|
|
2283
|
-
body.repository_ids = repoIds;
|
|
2195
|
+
if (options.environment) {
|
|
2196
|
+
const envResp = await orgAuthenticatedFetch("/v1/environments");
|
|
2197
|
+
const selectableEnvs = envResp.environments.filter((e) => !e.is_global);
|
|
2198
|
+
body.environment_id = resolveSelectableEnvironmentId(options.environment, selectableEnvs);
|
|
2284
2199
|
}
|
|
2285
2200
|
if (options.lifecycle) {
|
|
2286
2201
|
body.workspace_lifecycle_policy = options.lifecycle;
|
|
@@ -2505,12 +2420,12 @@ async function interactiveCommand() {
|
|
|
2505
2420
|
);
|
|
2506
2421
|
}
|
|
2507
2422
|
console.log(chalk18.gray("Starting interactive mode..."));
|
|
2508
|
-
const { launchInteractive } = await import("./interactive-
|
|
2423
|
+
const { launchInteractive } = await import("./interactive-V22J5FZI.mjs");
|
|
2509
2424
|
await launchInteractive();
|
|
2510
2425
|
}
|
|
2511
2426
|
|
|
2512
2427
|
// src/index.ts
|
|
2513
|
-
var CLI_VERSION = "0.2.
|
|
2428
|
+
var CLI_VERSION = "0.2.114";
|
|
2514
2429
|
var program = new Command();
|
|
2515
2430
|
program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
|
|
2516
2431
|
program.command("login").description("Authenticate with your Replicas account").action(async () => {
|
|
@@ -2695,7 +2610,7 @@ program.command("get <id>").description("Get replica details by ID").action(asyn
|
|
|
2695
2610
|
process.exit(1);
|
|
2696
2611
|
}
|
|
2697
2612
|
});
|
|
2698
|
-
program.command("create [name]").description("Create a new replica").option("-m, --message <message>", "Initial message for the replica").option("-
|
|
2613
|
+
program.command("create [name]").description("Create a new replica").option("-m, --message <message>", "Initial message for the replica").option("-e, --environment <environment>", "Environment ID").option("-a, --agent <agent>", "Coding agent (claude, codex)").action(async (name, options) => {
|
|
2699
2614
|
try {
|
|
2700
2615
|
await replicaCreateCommand(name, options);
|
|
2701
2616
|
} catch (error) {
|
|
@@ -2768,7 +2683,7 @@ automation.command("get <id>").description("Get automation details by ID").actio
|
|
|
2768
2683
|
process.exit(1);
|
|
2769
2684
|
}
|
|
2770
2685
|
});
|
|
2771
|
-
automation.command("create [name]").description("Create a new automation").option("-p, --prompt <prompt>", "Prompt for the automation").option("-
|
|
2686
|
+
automation.command("create [name]").description("Create a new automation").option("-p, --prompt <prompt>", "Prompt for the automation").option("-e, --environment <environment>", "Environment name or ID").option("--trigger-cron <schedule>", 'Cron schedule expression (e.g. "0 9 * * 1-5")').option("--trigger-cron-timezone <timezone>", "Timezone for cron trigger (default: UTC)").option("--trigger-github <event>", 'GitHub event (e.g. "pull_request.opened")').option("--trigger-github-repos <repos>", "Comma-separated repo names to filter GitHub trigger").option("--lifecycle <policy>", "Workspace lifecycle: delete_when_done, delete_after_inactivity, default").option("--auto-stop-minutes <minutes>", "Inactivity timeout in minutes (3-1440, requires --lifecycle delete_after_inactivity)").option("--disabled", "Create in disabled state").action(async (name, options) => {
|
|
2772
2687
|
try {
|
|
2773
2688
|
await automationCreateCommand(name, {
|
|
2774
2689
|
...options,
|
|
@@ -2783,7 +2698,7 @@ automation.command("create [name]").description("Create a new automation").optio
|
|
|
2783
2698
|
process.exit(1);
|
|
2784
2699
|
}
|
|
2785
2700
|
});
|
|
2786
|
-
automation.command("edit <id>").description("Edit an existing automation").option("-n, --name <name>", "New name").option("-p, --prompt <prompt>", "New prompt").option("-e, --enabled <enabled>", "Enable or disable (true/false)").option("--trigger-cron <schedule>", "Set cron schedule (replaces existing triggers)").option("--trigger-cron-timezone <timezone>", "Timezone for cron trigger").option("--trigger-github <event>", "Set GitHub event (replaces existing triggers)").option("--trigger-github-repos <repos>", "Comma-separated repo names to filter GitHub trigger").option("
|
|
2701
|
+
automation.command("edit <id>").description("Edit an existing automation").option("-n, --name <name>", "New name").option("-p, --prompt <prompt>", "New prompt").option("-e, --enabled <enabled>", "Enable or disable (true/false)").option("--trigger-cron <schedule>", "Set cron schedule (replaces existing triggers)").option("--trigger-cron-timezone <timezone>", "Timezone for cron trigger").option("--trigger-github <event>", "Set GitHub event (replaces existing triggers)").option("--trigger-github-repos <repos>", "Comma-separated repo names to filter GitHub trigger").option("--environment <environment>", "Environment name or ID").option("--lifecycle <policy>", "Workspace lifecycle: delete_when_done, delete_after_inactivity, default").option("--auto-stop-minutes <minutes>", "Inactivity timeout in minutes (3-1440, requires --lifecycle delete_after_inactivity)").action(async (id, options) => {
|
|
2787
2702
|
try {
|
|
2788
2703
|
await automationEditCommand(id, options);
|
|
2789
2704
|
} catch (error) {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
isAgentBackendEvent,
|
|
13
13
|
parseAgentEvents,
|
|
14
14
|
parseUserMessage
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HOO346QO.mjs";
|
|
16
16
|
|
|
17
17
|
// src/interactive/index.tsx
|
|
18
18
|
import { createCliRenderer } from "@opentui/core";
|
|
@@ -445,17 +445,6 @@ function useWorkspaceEvents(workspaceId, enabled = true) {
|
|
|
445
445
|
|
|
446
446
|
// ../shared/src/hooks/useRepositories.ts
|
|
447
447
|
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
448
|
-
function useRepositories() {
|
|
449
|
-
const auth = useReplicasAuth();
|
|
450
|
-
const orgFetch = useOrgFetch();
|
|
451
|
-
const orgId = auth.getOrganizationId();
|
|
452
|
-
return useQuery3({
|
|
453
|
-
queryKey: ["repositories", orgId],
|
|
454
|
-
queryFn: () => orgFetch("/v1/repositories"),
|
|
455
|
-
enabled: !!orgId,
|
|
456
|
-
staleTime: 2 * 60 * 1e3
|
|
457
|
-
}, auth.queryClient);
|
|
458
|
-
}
|
|
459
448
|
function useRepositorySets() {
|
|
460
449
|
const auth = useReplicasAuth();
|
|
461
450
|
const orgFetch = useOrgFetch();
|
|
@@ -469,33 +458,13 @@ function useRepositorySets() {
|
|
|
469
458
|
|
|
470
459
|
// ../shared/src/hooks/useEnvironment.ts
|
|
471
460
|
import { useQuery as useQuery4 } from "@tanstack/react-query";
|
|
472
|
-
function
|
|
461
|
+
function useEnvironments() {
|
|
473
462
|
const auth = useReplicasAuth();
|
|
474
463
|
const orgFetch = useOrgFetch();
|
|
475
464
|
const orgId = auth.getOrganizationId();
|
|
476
465
|
return useQuery4({
|
|
477
|
-
queryKey: ["
|
|
478
|
-
queryFn: () => orgFetch("/v1/
|
|
479
|
-
enabled: !!orgId
|
|
480
|
-
}, auth.queryClient);
|
|
481
|
-
}
|
|
482
|
-
function useEnvironmentVariables() {
|
|
483
|
-
const auth = useReplicasAuth();
|
|
484
|
-
const orgFetch = useOrgFetch();
|
|
485
|
-
const orgId = auth.getOrganizationId();
|
|
486
|
-
return useQuery4({
|
|
487
|
-
queryKey: ["env-variables", orgId],
|
|
488
|
-
queryFn: () => orgFetch("/v1/environment/variables"),
|
|
489
|
-
enabled: !!orgId
|
|
490
|
-
}, auth.queryClient);
|
|
491
|
-
}
|
|
492
|
-
function useEnvironmentFiles() {
|
|
493
|
-
const auth = useReplicasAuth();
|
|
494
|
-
const orgFetch = useOrgFetch();
|
|
495
|
-
const orgId = auth.getOrganizationId();
|
|
496
|
-
return useQuery4({
|
|
497
|
-
queryKey: ["env-files", orgId],
|
|
498
|
-
queryFn: () => orgFetch("/v1/environment/files"),
|
|
466
|
+
queryKey: ["environments", orgId],
|
|
467
|
+
queryFn: () => orgFetch("/v1/environments"),
|
|
499
468
|
enabled: !!orgId
|
|
500
469
|
}, auth.queryClient);
|
|
501
470
|
}
|
|
@@ -559,7 +528,13 @@ function flattenGroups(groups, collapsedGroups) {
|
|
|
559
528
|
for (const group of groups) {
|
|
560
529
|
if (group.id === "__ungrouped__" && group.workspaces.length === 0) continue;
|
|
561
530
|
const expanded = !collapsedGroups.has(group.id);
|
|
562
|
-
items.push({
|
|
531
|
+
items.push({
|
|
532
|
+
type: "group",
|
|
533
|
+
id: group.id,
|
|
534
|
+
name: group.name,
|
|
535
|
+
isSetBound: !!group.repoSetIdForCreate,
|
|
536
|
+
expanded
|
|
537
|
+
});
|
|
563
538
|
if (expanded) {
|
|
564
539
|
for (const ws of group.workspaces) {
|
|
565
540
|
items.push({
|
|
@@ -571,7 +546,7 @@ function flattenGroups(groups, collapsedGroups) {
|
|
|
571
546
|
});
|
|
572
547
|
}
|
|
573
548
|
if (group.id !== "__ungrouped__") {
|
|
574
|
-
items.push({ type: "add",
|
|
549
|
+
items.push({ type: "add", group });
|
|
575
550
|
}
|
|
576
551
|
}
|
|
577
552
|
}
|
|
@@ -640,7 +615,7 @@ function WorkspaceSidebar({
|
|
|
640
615
|
} else if (item.type === "workspace") {
|
|
641
616
|
onSelectWorkspace(item.workspaceId);
|
|
642
617
|
} else if (item.type === "add") {
|
|
643
|
-
onCreateWorkspace(item.
|
|
618
|
+
onCreateWorkspace(item.group);
|
|
644
619
|
}
|
|
645
620
|
},
|
|
646
621
|
[onSelectWorkspace, onCreateWorkspace]
|
|
@@ -712,7 +687,7 @@ function WorkspaceSidebar({
|
|
|
712
687
|
if (key.name === "a") {
|
|
713
688
|
const item = items[cursorIndex];
|
|
714
689
|
if (item?.type === "add") {
|
|
715
|
-
onCreateWorkspace(item.
|
|
690
|
+
onCreateWorkspace(item.group);
|
|
716
691
|
}
|
|
717
692
|
return;
|
|
718
693
|
}
|
|
@@ -780,7 +755,7 @@ function WorkspaceSidebar({
|
|
|
780
755
|
if (item.type === "group") {
|
|
781
756
|
const chevron = item.expanded ? "\u25BE" : "\u25B8";
|
|
782
757
|
const label = truncate(item.name, 20);
|
|
783
|
-
const suffix = item.
|
|
758
|
+
const suffix = item.isSetBound ? " Set" : "";
|
|
784
759
|
return /* @__PURE__ */ jsx2(
|
|
785
760
|
"box",
|
|
786
761
|
{
|
|
@@ -856,7 +831,7 @@ function WorkspaceSidebar({
|
|
|
856
831
|
/* @__PURE__ */ jsx2("span", { fg: isCursor ? "#888888" : "#333333", children: "New workspace" })
|
|
857
832
|
] })
|
|
858
833
|
},
|
|
859
|
-
`a-${item.
|
|
834
|
+
`a-${item.group.id}`
|
|
860
835
|
);
|
|
861
836
|
}),
|
|
862
837
|
focused && /* @__PURE__ */ jsx2("box", { height: 1, paddingX: 1, backgroundColor: "#111111", children: /* @__PURE__ */ jsxs2("text", { children: [
|
|
@@ -1562,6 +1537,11 @@ function StructuredUserMessage({ parsed }) {
|
|
|
1562
1537
|
return /* @__PURE__ */ jsx5(GitHubPRGeneralMessage, { data: parsed });
|
|
1563
1538
|
case "slack_task":
|
|
1564
1539
|
return /* @__PURE__ */ jsx5(SlackTaskMessage, { data: parsed });
|
|
1540
|
+
case "automation_triggered":
|
|
1541
|
+
case "plan_quote":
|
|
1542
|
+
return /* @__PURE__ */ jsx5("text", { fg: "#cccccc", selectable: true, children: parsed.source === "plan_quote" ? parsed.blocks.map((b) => `> ${b.quotedText}
|
|
1543
|
+
${b.replyText}`).join("\n\n") : `Automation: ${parsed.automationName} (${parsed.triggerType})
|
|
1544
|
+
${parsed.userPrompt}` });
|
|
1565
1545
|
default: {
|
|
1566
1546
|
const _exhaustive = parsed;
|
|
1567
1547
|
throw new Error(`Unhandled prompt source: ${_exhaustive.source}`);
|
|
@@ -1573,7 +1553,8 @@ function StructuredUserMessage({ parsed }) {
|
|
|
1573
1553
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
|
|
1574
1554
|
var AGENT_LABELS = {
|
|
1575
1555
|
claude: "Claude",
|
|
1576
|
-
codex: "Codex"
|
|
1556
|
+
codex: "Codex",
|
|
1557
|
+
relay: "Relay"
|
|
1577
1558
|
};
|
|
1578
1559
|
function truncate2(text, maxLen) {
|
|
1579
1560
|
return text.length > maxLen ? text.slice(0, maxLen - 1) + "\u2026" : text;
|
|
@@ -2190,7 +2171,7 @@ function ViewModeRow({
|
|
|
2190
2171
|
}
|
|
2191
2172
|
);
|
|
2192
2173
|
}
|
|
2193
|
-
function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading,
|
|
2174
|
+
function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, agentAvailability, previews, onWakeWorkspace, onViewDiff, wakingWorkspaceId, viewMode, viewingDiffRepoName, onSelectChatMode, onSelectDiffMode, onCreatePr, isPlanMode }) {
|
|
2194
2175
|
const borderColor = focused ? "#66bb6a" : "#333333";
|
|
2195
2176
|
const [cursorIndex, setCursorIndex] = useState6(0);
|
|
2196
2177
|
const interactiveItems = useMemo5(() => {
|
|
@@ -2345,9 +2326,6 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
2345
2326
|
claudeAuthMethod: agentAvailability.claude.available ? rawEnv.claudeAuthMethod : "none",
|
|
2346
2327
|
codexAuthMethod: agentAvailability.codex.available ? rawEnv.codexAuthMethod : "none"
|
|
2347
2328
|
} : rawEnv;
|
|
2348
|
-
const expectedSkills = (envConfig.skills?.environment_skills ?? []).map((s) => s.source);
|
|
2349
|
-
const expectedGlobalVars = (envConfig.variables?.environment_variables ?? []).filter((v) => v.scope_type === "global").map((v) => v.key);
|
|
2350
|
-
const expectedGlobalFiles = (envConfig.files?.environment_files ?? []).filter((f) => f.scope_type === "global").map((f) => f.path);
|
|
2351
2329
|
const dashboardItem = findItem("dashboard");
|
|
2352
2330
|
const wakeItem = findItem("wake");
|
|
2353
2331
|
const createPrItem = findItem("createPr");
|
|
@@ -2571,9 +2549,9 @@ function WorkspaceInfo({ status, workspaceName, workspaceId, focused, loading, e
|
|
|
2571
2549
|
] })
|
|
2572
2550
|
] }, i))
|
|
2573
2551
|
] }),
|
|
2574
|
-
env &&
|
|
2575
|
-
env &&
|
|
2576
|
-
env &&
|
|
2552
|
+
env && env.skillsInstalled.length > 0 && /* @__PURE__ */ jsx8(Section, { title: "Skills", children: /* @__PURE__ */ jsx8(DetailList, { expected: [], actual: env.skillsInstalled }) }),
|
|
2553
|
+
env && env.envVarsSet.length > 0 && /* @__PURE__ */ jsx8(Section, { title: "Env Vars", children: /* @__PURE__ */ jsx8(DetailList, { expected: [], actual: env.envVarsSet }) }),
|
|
2554
|
+
env && env.filesUploaded.length > 0 && /* @__PURE__ */ jsx8(Section, { title: "Files", children: /* @__PURE__ */ jsx8(DetailList, { expected: [], actual: env.filesUploaded }) })
|
|
2577
2555
|
] })
|
|
2578
2556
|
}
|
|
2579
2557
|
);
|
|
@@ -2646,8 +2624,8 @@ function Toast() {
|
|
|
2646
2624
|
import { jsx as jsx11, jsxs as jsxs9 } from "@opentui/react/jsx-runtime";
|
|
2647
2625
|
var FOCUS_ORDER = ["sidebar", "chat-tabs", "chat-history", "chat-input", "info"];
|
|
2648
2626
|
var MOCK_CHATS = [
|
|
2649
|
-
{ id: "mock-claude", provider: "claude", title: "Claude Code", createdAt: "", updatedAt: "", processing: false },
|
|
2650
|
-
{ id: "mock-codex", provider: "codex", title: "Codex", createdAt: "", updatedAt: "", processing: false }
|
|
2627
|
+
{ id: "mock-claude", provider: "claude", title: "Claude Code", createdAt: "", updatedAt: "", processing: false, parentChatId: null },
|
|
2628
|
+
{ id: "mock-codex", provider: "codex", title: "Codex", createdAt: "", updatedAt: "", processing: false, parentChatId: null }
|
|
2651
2629
|
];
|
|
2652
2630
|
var MONOLITH_URL = process.env.REPLICAS_MONOLITH_URL || "https://api.replicas.dev";
|
|
2653
2631
|
var workspacePollingStarted = false;
|
|
@@ -2722,11 +2700,8 @@ function AppInner() {
|
|
|
2722
2700
|
const mockIds = useMemo6(() => new Set(mockWorkspaces.map((m) => m.id)), [mockWorkspaces]);
|
|
2723
2701
|
const isMockSelected = selectedWorkspaceId ? mockIds.has(selectedWorkspaceId) : false;
|
|
2724
2702
|
const { data: workspacesData, isLoading: loadingWorkspaces } = useWorkspaces(1, 100, "organization");
|
|
2725
|
-
const { data: reposData } = useRepositories();
|
|
2726
2703
|
const { data: setsData } = useRepositorySets();
|
|
2727
|
-
const { data:
|
|
2728
|
-
const { data: envVariables } = useEnvironmentVariables();
|
|
2729
|
-
const { data: envFiles } = useEnvironmentFiles();
|
|
2704
|
+
const { data: envsData } = useEnvironments();
|
|
2730
2705
|
const { data: statusData, isLoading: loadingStatus } = useWorkspaceStatus(
|
|
2731
2706
|
isMockSelected ? null : selectedWorkspaceId,
|
|
2732
2707
|
{ includeDiffs: true }
|
|
@@ -2756,13 +2731,13 @@ function AppInner() {
|
|
|
2756
2731
|
const sendMessageMutation = useSendChatMessage(selectedWorkspaceId, resolvedChatId);
|
|
2757
2732
|
const interruptMutation = useInterruptChat(selectedWorkspaceId, resolvedChatId);
|
|
2758
2733
|
const workspaces = workspacesData?.workspaces ?? [];
|
|
2759
|
-
const repositories = reposData?.repositories ?? [];
|
|
2760
2734
|
const repositorySets = setsData?.repository_sets ?? [];
|
|
2735
|
+
const environments = envsData?.environments ?? [];
|
|
2761
2736
|
const previews = previewsData?.previews ?? [];
|
|
2762
2737
|
const allWorkspaces = useMemo6(() => [...mockWorkspaces, ...workspaces], [mockWorkspaces, workspaces]);
|
|
2763
2738
|
const groups = useMemo6(
|
|
2764
|
-
() => buildGroups(allWorkspaces, workspacesData,
|
|
2765
|
-
[allWorkspaces, workspacesData,
|
|
2739
|
+
() => buildGroups(allWorkspaces, workspacesData, environments, repositorySets, mockGroupRef.current),
|
|
2740
|
+
[allWorkspaces, workspacesData, environments, repositorySets]
|
|
2766
2741
|
);
|
|
2767
2742
|
const selectedWorkspace = allWorkspaces.find((ws) => ws.id === selectedWorkspaceId) ?? null;
|
|
2768
2743
|
const selectedChat = chats.find((c) => c.id === resolvedChatId) ?? null;
|
|
@@ -2843,17 +2818,25 @@ function AppInner() {
|
|
|
2843
2818
|
setFocusPanel(panel);
|
|
2844
2819
|
}, []);
|
|
2845
2820
|
const handleCreateWorkspace = useCallback7(
|
|
2846
|
-
async (
|
|
2821
|
+
async (group) => {
|
|
2822
|
+
if (group.id === "__ungrouped__") {
|
|
2823
|
+
toast.error("Cannot create a workspace in the Other / Ungrouped folder");
|
|
2824
|
+
return;
|
|
2825
|
+
}
|
|
2847
2826
|
const orgId = getOrganizationId() ?? "";
|
|
2848
2827
|
const mock = createMockWorkspaceRecord(orgId);
|
|
2849
|
-
mockGroupRef.current.set(mock.id,
|
|
2828
|
+
mockGroupRef.current.set(mock.id, group.id);
|
|
2850
2829
|
setMockWorkspaces((prev) => [mock, ...prev]);
|
|
2851
2830
|
setSelectedWorkspaceId(mock.id);
|
|
2852
2831
|
setViewingDiff(null);
|
|
2853
2832
|
setLastViewedDiff(null);
|
|
2854
2833
|
setFocusPanel("chat-input");
|
|
2855
2834
|
try {
|
|
2856
|
-
const request =
|
|
2835
|
+
const request = {
|
|
2836
|
+
environment_id: group.environmentId,
|
|
2837
|
+
name: mock.name,
|
|
2838
|
+
placeholder: true
|
|
2839
|
+
};
|
|
2857
2840
|
const result = await createWorkspaceMutation.mutateAsync(request);
|
|
2858
2841
|
mockToRealRef.current.set(mock.id, result.workspace.id);
|
|
2859
2842
|
} catch (err) {
|
|
@@ -3101,11 +3084,6 @@ function AppInner() {
|
|
|
3101
3084
|
workspaceId: selectedWorkspaceId,
|
|
3102
3085
|
focused: focusPanel === "info",
|
|
3103
3086
|
loading: loadingStatus,
|
|
3104
|
-
envConfig: {
|
|
3105
|
-
skills: envSkills ?? null,
|
|
3106
|
-
variables: envVariables ?? null,
|
|
3107
|
-
files: envFiles ?? null
|
|
3108
|
-
},
|
|
3109
3087
|
previews,
|
|
3110
3088
|
agentAvailability: agentAvailability ?? null,
|
|
3111
3089
|
onWakeWorkspace: handleWakeWorkspace,
|