conductor-oss 0.20.2 → 0.20.3
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/README.md +17 -5
- package/package.json +5 -5
- package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/agents/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/app-update/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/boards/comments/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/context-files/open/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/executor/health/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/pick-directory/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/github/webhook/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/remote-access/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/repositories/[id]/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/interrupt/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/dom/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/screenshot/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/token/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/ttyd/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/ttyd/ws/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
- package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__53bcdbc9._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__2f682641._.js → [root-of-the-server]__6246c581._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__c405048c._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__25555995._.js → [root-of-the-server]__c8eede2d._.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__ed31820a._.js → [root-of-the-server]__ffd8c5ab._.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_532f707d._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_dd3f8405._.js → _c91b376d._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_e4fbd9e4._.js → node_modules_@clerk_nextjs_dist_esm_app-router_47572fce._.js} +2 -2
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_8b33e86b._.js +3 -0
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_features_dashboard_components_DashboardDialogs_tsx_32d3d858._.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
- package/web/.next/{static/chunks/414abf6a0538296f.js → standalone/packages/web/.next/static/chunks/05535bfd4a15736a.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/0afb9504dd37f5a5.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/198b3e8333e97319.css +4 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/4c33b5df1b80b1aa.js +1 -0
- package/web/.next/standalone/packages/web/.next/static/chunks/{b1c03c2c194b81b8.js → 8ab6375ce994ee71.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/{f6e6ac9d96cf2151.js → d49e89e2e6c97f48.js} +1 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/{54fbc02b98d56f4c.js → e366fc88feb421d9.js} +1 -1
- package/web/.next/standalone/packages/web/src/features/dashboard/components/DashboardDialogs.tsx +554 -419
- package/web/.next/standalone/packages/web/src/features/dashboard/githubRepos.test.ts +40 -0
- package/web/.next/standalone/packages/web/src/features/dashboard/githubRepos.ts +27 -0
- package/web/.next/{standalone/packages/web/.next/static/chunks/414abf6a0538296f.js → static/chunks/05535bfd4a15736a.js} +1 -1
- package/web/.next/static/chunks/0afb9504dd37f5a5.js +1 -0
- package/web/.next/static/chunks/198b3e8333e97319.css +4 -0
- package/web/.next/static/chunks/4c33b5df1b80b1aa.js +1 -0
- package/web/.next/static/chunks/{b1c03c2c194b81b8.js → 8ab6375ce994ee71.js} +1 -1
- package/web/.next/static/chunks/{f6e6ac9d96cf2151.js → d49e89e2e6c97f48.js} +1 -1
- package/web/.next/static/chunks/{54fbc02b98d56f4c.js → e366fc88feb421d9.js} +1 -1
- package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_c2a45392._.js +0 -3
- package/web/.next/standalone/packages/web/.next/static/chunks/4f912a60e3753a1f.css +0 -4
- package/web/.next/standalone/packages/web/.next/static/chunks/953e23f8cfbdc9bb.js +0 -1
- package/web/.next/standalone/packages/web/.next/static/chunks/9b1065a7ccd69a3e.js +0 -1
- package/web/.next/static/chunks/4f912a60e3753a1f.css +0 -4
- package/web/.next/static/chunks/953e23f8cfbdc9bb.js +0 -1
- package/web/.next/static/chunks/9b1065a7ccd69a3e.js +0 -1
- /package/web/.next/standalone/packages/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_buildManifest.js +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/packages/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_ssgManifest.js +0 -0
- /package/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_buildManifest.js +0 -0
- /package/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{4j_KriaHEW-_LlfrKXaOW → HfIcB-Vnu7gb6quPqshK5}/_ssgManifest.js +0 -0
package/web/.next/standalone/packages/web/src/features/dashboard/components/DashboardDialogs.tsx
CHANGED
|
@@ -45,6 +45,7 @@ import { normalizeAgentName } from "@/lib/agentUtils";
|
|
|
45
45
|
import { getKnownAgent, KNOWN_AGENT_ORDER } from "@/lib/knownAgents";
|
|
46
46
|
import { AgentTileIcon } from "@/components/AgentTileIcon";
|
|
47
47
|
import { playNotificationSound } from "@/lib/notificationSounds";
|
|
48
|
+
import { filterGitHubRepos, type GitHubRepo } from "../githubRepos";
|
|
48
49
|
import { normalizeModelAccessPreferences } from "@/lib/modelAccess";
|
|
49
50
|
import {
|
|
50
51
|
getRuntimeCatalogDefaultModelForAccess,
|
|
@@ -204,19 +205,6 @@ type LinkedBoardResponse = {
|
|
|
204
205
|
}>;
|
|
205
206
|
};
|
|
206
207
|
|
|
207
|
-
type GitHubRepo = {
|
|
208
|
-
name: string;
|
|
209
|
-
fullName: string;
|
|
210
|
-
httpsUrl: string;
|
|
211
|
-
sshUrl: string;
|
|
212
|
-
defaultBranch: string;
|
|
213
|
-
private: boolean;
|
|
214
|
-
description?: string | null;
|
|
215
|
-
updatedAt?: string | null;
|
|
216
|
-
ownerLogin?: string | null;
|
|
217
|
-
permission?: string | null;
|
|
218
|
-
};
|
|
219
|
-
|
|
220
208
|
type DirectoryEntry = {
|
|
221
209
|
name: string;
|
|
222
210
|
path: string;
|
|
@@ -1023,10 +1011,12 @@ export function NewWorkspaceDialog({
|
|
|
1023
1011
|
agentOptions: string[];
|
|
1024
1012
|
}) {
|
|
1025
1013
|
const [mode, setMode] = useState<"git" | "local">("git");
|
|
1014
|
+
const [step, setStep] = useState<"source" | "details">("source");
|
|
1026
1015
|
const [projectId, setProjectId] = useState("");
|
|
1027
1016
|
const [projectIdTouched, setProjectIdTouched] = useState(false);
|
|
1028
1017
|
const [gitUrl, setGitUrl] = useState("");
|
|
1029
|
-
const [
|
|
1018
|
+
const [localPath, setLocalPath] = useState("");
|
|
1019
|
+
const [clonePath, setClonePath] = useState("");
|
|
1030
1020
|
const [defaultBranch, setDefaultBranch] = useState("main");
|
|
1031
1021
|
const [agent, setAgent] = useState(defaultAgent);
|
|
1032
1022
|
const [useWorktree, setUseWorktree] = useState(false);
|
|
@@ -1046,10 +1036,12 @@ export function NewWorkspaceDialog({
|
|
|
1046
1036
|
useEffect(() => {
|
|
1047
1037
|
if (!open) return;
|
|
1048
1038
|
setMode("git");
|
|
1039
|
+
setStep("source");
|
|
1049
1040
|
setProjectId("");
|
|
1050
1041
|
setProjectIdTouched(false);
|
|
1051
1042
|
setGitUrl("");
|
|
1052
|
-
|
|
1043
|
+
setLocalPath("");
|
|
1044
|
+
setClonePath("");
|
|
1053
1045
|
setDefaultBranch("main");
|
|
1054
1046
|
setInitializeGit(true);
|
|
1055
1047
|
setUseWorktree(false);
|
|
@@ -1068,22 +1060,14 @@ export function NewWorkspaceDialog({
|
|
|
1068
1060
|
|
|
1069
1061
|
useEffect(() => {
|
|
1070
1062
|
if (!open) return;
|
|
1071
|
-
|
|
1072
|
-
if (
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
}, [mode, open,
|
|
1063
|
+
const sourceReady = mode === "git" ? gitUrl.trim().length > 0 : localPath.trim().length > 0;
|
|
1064
|
+
if (step === "details" && !sourceReady) {
|
|
1065
|
+
setStep("source");
|
|
1066
|
+
}
|
|
1067
|
+
}, [gitUrl, localPath, mode, open, step]);
|
|
1076
1068
|
|
|
1077
1069
|
const filteredGitHubRepos = useMemo(() => {
|
|
1078
|
-
|
|
1079
|
-
const filtered = query.length === 0 ? githubRepos : githubRepos.filter((repo) => {
|
|
1080
|
-
return repo.fullName.toLowerCase().includes(query)
|
|
1081
|
-
|| repo.name.toLowerCase().includes(query)
|
|
1082
|
-
|| (repo.ownerLogin ?? "").toLowerCase().includes(query)
|
|
1083
|
-
|| (repo.description ?? "").toLowerCase().includes(query)
|
|
1084
|
-
|| repo.defaultBranch.toLowerCase().includes(query);
|
|
1085
|
-
});
|
|
1086
|
-
return query.length === 0 ? filtered.slice(0, 10) : filtered.slice(0, 14);
|
|
1070
|
+
return filterGitHubRepos(githubRepos, githubRepoSearch);
|
|
1087
1071
|
}, [githubRepoSearch, githubRepos]);
|
|
1088
1072
|
|
|
1089
1073
|
const selectedGitHubRepoData = useMemo(() => {
|
|
@@ -1110,6 +1094,21 @@ export function NewWorkspaceDialog({
|
|
|
1110
1094
|
if (!normalizedUrl) return false;
|
|
1111
1095
|
return normalizedUrl.toLowerCase() !== gitUrl.trim().toLowerCase();
|
|
1112
1096
|
}, [gitUrl, normalizedGitHubSearchUrl, normalizedManualGitUrl]);
|
|
1097
|
+
const sourceReady = mode === "git"
|
|
1098
|
+
? gitUrl.trim().length > 0
|
|
1099
|
+
: localPath.trim().length > 0;
|
|
1100
|
+
const selectedSourceTitle = useMemo(() => {
|
|
1101
|
+
if (mode === "git") {
|
|
1102
|
+
return selectedGitHubRepoData?.fullName ?? gitUrl.trim();
|
|
1103
|
+
}
|
|
1104
|
+
return extractNameFromPath(localPath) ?? localPath.trim();
|
|
1105
|
+
}, [gitUrl, localPath, mode, selectedGitHubRepoData]);
|
|
1106
|
+
const selectedSourceSubtitle = useMemo(() => {
|
|
1107
|
+
if (mode === "git") {
|
|
1108
|
+
return selectedGitHubRepoData?.description?.trim() || gitUrl.trim();
|
|
1109
|
+
}
|
|
1110
|
+
return localPath.trim();
|
|
1111
|
+
}, [gitUrl, localPath, mode, selectedGitHubRepoData]);
|
|
1113
1112
|
|
|
1114
1113
|
const orderedAgentOptions = useMemo(() => {
|
|
1115
1114
|
const opts = [...new Set(agentOptions)];
|
|
@@ -1166,7 +1165,7 @@ export function NewWorkspaceDialog({
|
|
|
1166
1165
|
sourceOverride?: { gitUrl?: string; path?: string },
|
|
1167
1166
|
) => {
|
|
1168
1167
|
const effectiveGitUrl = sourceOverride?.gitUrl ?? (mode === "git" ? gitUrl.trim() : "");
|
|
1169
|
-
const effectivePath = sourceOverride?.path ?? (mode === "local" ?
|
|
1168
|
+
const effectivePath = sourceOverride?.path ?? (mode === "local" ? localPath.trim() : "");
|
|
1170
1169
|
|
|
1171
1170
|
if (effectiveGitUrl.length === 0 && effectivePath.length === 0) {
|
|
1172
1171
|
setBranchesError(
|
|
@@ -1231,6 +1230,7 @@ export function NewWorkspaceDialog({
|
|
|
1231
1230
|
}
|
|
1232
1231
|
|
|
1233
1232
|
await handleDetectBranches({ gitUrl: selected.httpsUrl });
|
|
1233
|
+
setStep("details");
|
|
1234
1234
|
};
|
|
1235
1235
|
|
|
1236
1236
|
const handleUseSearchValueAsRepository = async () => {
|
|
@@ -1256,6 +1256,7 @@ export function NewWorkspaceDialog({
|
|
|
1256
1256
|
}
|
|
1257
1257
|
|
|
1258
1258
|
await handleDetectBranches({ gitUrl: normalizedUrl });
|
|
1259
|
+
setStep("details");
|
|
1259
1260
|
};
|
|
1260
1261
|
|
|
1261
1262
|
const openFolderPicker = (target: "clone" | "local") => {
|
|
@@ -1263,15 +1264,25 @@ export function NewWorkspaceDialog({
|
|
|
1263
1264
|
setFolderPickerOpen(true);
|
|
1264
1265
|
};
|
|
1265
1266
|
|
|
1267
|
+
const handleModeChange = (nextMode: "git" | "local") => {
|
|
1268
|
+
setMode(nextMode);
|
|
1269
|
+
setStep("source");
|
|
1270
|
+
setBranchOptions([]);
|
|
1271
|
+
setBranchesError(null);
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
const handleContinueToDetails = () => {
|
|
1275
|
+
if (!sourceReady || creating) return;
|
|
1276
|
+
setStep("details");
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1266
1279
|
if (!open) return null;
|
|
1267
1280
|
|
|
1268
|
-
const canSubmit =
|
|
1269
|
-
? gitUrl.trim().length > 0 && defaultBranch.trim().length > 0
|
|
1270
|
-
: path.trim().length > 0 && defaultBranch.trim().length > 0;
|
|
1281
|
+
const canSubmit = sourceReady && defaultBranch.trim().length > 0;
|
|
1271
1282
|
|
|
1272
1283
|
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
|
1273
1284
|
event.preventDefault();
|
|
1274
|
-
if (!canSubmit || creating) return;
|
|
1285
|
+
if (step !== "details" || !canSubmit || creating) return;
|
|
1275
1286
|
|
|
1276
1287
|
const payload: NewWorkspacePayload =
|
|
1277
1288
|
mode === "git"
|
|
@@ -1282,7 +1293,7 @@ export function NewWorkspaceDialog({
|
|
|
1282
1293
|
defaultBranch: defaultBranch.trim(),
|
|
1283
1294
|
useWorktree,
|
|
1284
1295
|
gitUrl: gitUrl.trim(),
|
|
1285
|
-
path:
|
|
1296
|
+
path: clonePath.trim() || undefined,
|
|
1286
1297
|
}
|
|
1287
1298
|
: {
|
|
1288
1299
|
mode,
|
|
@@ -1290,7 +1301,7 @@ export function NewWorkspaceDialog({
|
|
|
1290
1301
|
agent,
|
|
1291
1302
|
defaultBranch: defaultBranch.trim(),
|
|
1292
1303
|
useWorktree,
|
|
1293
|
-
path:
|
|
1304
|
+
path: localPath.trim(),
|
|
1294
1305
|
initializeGit,
|
|
1295
1306
|
};
|
|
1296
1307
|
|
|
@@ -1300,7 +1311,7 @@ export function NewWorkspaceDialog({
|
|
|
1300
1311
|
return (
|
|
1301
1312
|
<>
|
|
1302
1313
|
<div
|
|
1303
|
-
className="fixed inset-0 z-[80] flex items-
|
|
1314
|
+
className="fixed inset-0 z-[80] flex items-end justify-center overflow-y-auto bg-black/65 px-0 py-0 sm:items-center sm:px-3 sm:py-3"
|
|
1304
1315
|
onClick={() => {
|
|
1305
1316
|
if (creating || folderPickerOpen) return;
|
|
1306
1317
|
onClose();
|
|
@@ -1310,448 +1321,569 @@ export function NewWorkspaceDialog({
|
|
|
1310
1321
|
<form
|
|
1311
1322
|
onSubmit={handleSubmit}
|
|
1312
1323
|
onClick={(event) => event.stopPropagation()}
|
|
1313
|
-
className="flex
|
|
1324
|
+
className="flex h-dvh w-full max-w-none flex-col overflow-hidden rounded-none border-x-0 border-b-0 border-t border-[var(--vk-border)] bg-[var(--vk-bg-panel)] shadow-[0_24px_80px_rgba(0,0,0,0.55)] sm:h-auto sm:max-h-[calc(100dvh-3rem)] sm:max-w-[860px] sm:rounded-[10px] sm:border"
|
|
1314
1325
|
>
|
|
1315
|
-
<header className="
|
|
1316
|
-
<div>
|
|
1317
|
-
<
|
|
1318
|
-
<p className="pt-1 text-[12px] text-[var(--vk-text-muted)]">
|
|
1319
|
-
Pick a GitHub repository or local folder, then confirm the branch.
|
|
1320
|
-
</p>
|
|
1326
|
+
<header className="border-b border-[var(--vk-border)] bg-[color:color-mix(in_srgb,var(--vk-bg-panel)_92%,transparent)] px-4 py-3 backdrop-blur">
|
|
1327
|
+
<div className="mb-3 flex justify-center sm:hidden">
|
|
1328
|
+
<span className="h-1 w-10 rounded-full bg-[color:color-mix(in_srgb,var(--vk-text-muted)_36%,transparent)]" />
|
|
1321
1329
|
</div>
|
|
1322
|
-
<
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1330
|
+
<div className="flex items-start gap-3">
|
|
1331
|
+
<div className="min-w-0 flex-1">
|
|
1332
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
1333
|
+
<h2 className="text-[18px] leading-[22px] text-[var(--vk-text-strong)]">Add Workspace</h2>
|
|
1334
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1335
|
+
{step === "source" ? "Step 1 of 2" : "Step 2 of 2"}
|
|
1336
|
+
</span>
|
|
1337
|
+
</div>
|
|
1338
|
+
<p className="pt-1 text-[12px] text-[var(--vk-text-muted)]">
|
|
1339
|
+
{step === "source"
|
|
1340
|
+
? "Start with the repository or folder you want Conductor to manage."
|
|
1341
|
+
: "Confirm the defaults Conductor should use when this workspace is created."}
|
|
1342
|
+
</p>
|
|
1343
|
+
<div className="mt-3 flex flex-wrap items-center gap-2">
|
|
1344
|
+
{[
|
|
1345
|
+
{ id: "source", label: mode === "git" ? "Repository" : "Folder" },
|
|
1346
|
+
{ id: "details", label: "Defaults" },
|
|
1347
|
+
].map((item) => {
|
|
1348
|
+
const active = step === item.id;
|
|
1349
|
+
const complete = item.id === "source" && step === "details" && sourceReady;
|
|
1350
|
+
return (
|
|
1351
|
+
<div
|
|
1352
|
+
key={item.id}
|
|
1353
|
+
className={`inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[11px] ${
|
|
1354
|
+
active
|
|
1355
|
+
? "border-[var(--vk-orange)] bg-[color:color-mix(in_srgb,var(--vk-orange)_12%,transparent)] text-[var(--vk-text-strong)]"
|
|
1356
|
+
: "border-[var(--vk-border)] text-[var(--vk-text-muted)]"
|
|
1357
|
+
}`}
|
|
1358
|
+
>
|
|
1359
|
+
<span className={`inline-flex h-4 w-4 items-center justify-center rounded-full border text-[10px] ${
|
|
1360
|
+
complete
|
|
1361
|
+
? "border-[var(--vk-orange)] bg-[var(--vk-orange)] text-black"
|
|
1362
|
+
: active
|
|
1363
|
+
? "border-[var(--vk-orange)] text-[var(--vk-text-strong)]"
|
|
1364
|
+
: "border-[var(--vk-border)]"
|
|
1365
|
+
}`}>
|
|
1366
|
+
{complete ? <Check className="h-3 w-3" /> : item.id === "source" ? "1" : "2"}
|
|
1367
|
+
</span>
|
|
1368
|
+
<span>{item.label}</span>
|
|
1369
|
+
</div>
|
|
1370
|
+
);
|
|
1371
|
+
})}
|
|
1372
|
+
</div>
|
|
1373
|
+
</div>
|
|
1346
1374
|
<button
|
|
1347
1375
|
type="button"
|
|
1348
|
-
onClick={
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
: "text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)]"
|
|
1353
|
-
}`}
|
|
1376
|
+
onClick={onClose}
|
|
1377
|
+
disabled={creating}
|
|
1378
|
+
aria-label="Close dialog"
|
|
1379
|
+
className="inline-flex h-8 w-8 items-center justify-center rounded-[4px] text-[var(--vk-text-muted)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1354
1380
|
>
|
|
1355
|
-
|
|
1381
|
+
<X className="h-4 w-4" />
|
|
1356
1382
|
</button>
|
|
1357
1383
|
</div>
|
|
1384
|
+
</header>
|
|
1358
1385
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1386
|
+
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-4 sm:px-5 sm:py-5">
|
|
1387
|
+
{step === "source" ? (
|
|
1388
|
+
<div className="space-y-4">
|
|
1389
|
+
<div className="grid gap-2 sm:grid-cols-2">
|
|
1390
|
+
<button
|
|
1391
|
+
type="button"
|
|
1392
|
+
onClick={() => handleModeChange("git")}
|
|
1393
|
+
className={`rounded-[10px] border px-4 py-4 text-left transition ${
|
|
1394
|
+
mode === "git"
|
|
1395
|
+
? "border-[var(--vk-orange)] bg-[color:color-mix(in_srgb,var(--vk-orange)_12%,transparent)]"
|
|
1396
|
+
: "border-[var(--vk-border)] bg-[var(--vk-bg-main)] hover:bg-[var(--vk-bg-hover)]"
|
|
1397
|
+
}`}
|
|
1398
|
+
>
|
|
1399
|
+
<span className="inline-flex h-10 w-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] text-[var(--vk-text-strong)]">
|
|
1364
1400
|
<MarkGithubIcon className="h-[18px] w-[18px]" />
|
|
1365
1401
|
</span>
|
|
1366
|
-
<
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
</div>
|
|
1372
|
-
<button
|
|
1373
|
-
type="button"
|
|
1374
|
-
onClick={() => {
|
|
1375
|
-
setGithubReposLoaded(false);
|
|
1376
|
-
void handleFetchGitHubRepos(true);
|
|
1377
|
-
}}
|
|
1378
|
-
disabled={githubReposLoading}
|
|
1379
|
-
className="inline-flex h-8 items-center rounded-[4px] border border-[var(--vk-border)] px-2 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1380
|
-
>
|
|
1381
|
-
{githubReposLoading ? (
|
|
1382
|
-
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
1383
|
-
) : (
|
|
1384
|
-
<>
|
|
1385
|
-
<RefreshCcw className="mr-1.5 h-3.5 w-3.5" />
|
|
1386
|
-
Refresh
|
|
1387
|
-
</>
|
|
1388
|
-
)}
|
|
1389
|
-
</button>
|
|
1390
|
-
</div>
|
|
1402
|
+
<p className="mt-3 text-[14px] font-medium text-[var(--vk-text-strong)]">GitHub repository</p>
|
|
1403
|
+
<p className="mt-1 text-[12px] leading-5 text-[var(--vk-text-muted)]">
|
|
1404
|
+
Search repos you already have access to, or paste a GitHub URL directly.
|
|
1405
|
+
</p>
|
|
1406
|
+
</button>
|
|
1391
1407
|
|
|
1392
|
-
<
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1408
|
+
<button
|
|
1409
|
+
type="button"
|
|
1410
|
+
onClick={() => handleModeChange("local")}
|
|
1411
|
+
className={`rounded-[10px] border px-4 py-4 text-left transition ${
|
|
1412
|
+
mode === "local"
|
|
1413
|
+
? "border-[var(--vk-orange)] bg-[color:color-mix(in_srgb,var(--vk-orange)_12%,transparent)]"
|
|
1414
|
+
: "border-[var(--vk-border)] bg-[var(--vk-bg-main)] hover:bg-[var(--vk-bg-hover)]"
|
|
1415
|
+
}`}
|
|
1416
|
+
>
|
|
1417
|
+
<span className="inline-flex h-10 w-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] text-[var(--vk-text-strong)]">
|
|
1418
|
+
<FolderOpen className="h-5 w-5" />
|
|
1419
|
+
</span>
|
|
1420
|
+
<p className="mt-3 text-[14px] font-medium text-[var(--vk-text-strong)]">Local folder</p>
|
|
1421
|
+
<p className="mt-1 text-[12px] leading-5 text-[var(--vk-text-muted)]">
|
|
1422
|
+
Point Conductor at a repository already on this machine.
|
|
1423
|
+
</p>
|
|
1424
|
+
</button>
|
|
1425
|
+
</div>
|
|
1407
1426
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
}}
|
|
1414
|
-
className="mt-3 inline-flex items-center gap-2 rounded-[5px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 py-2 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1415
|
-
>
|
|
1416
|
-
<RepoIcon className="h-4 w-4 text-[var(--vk-text-strong)]" />
|
|
1417
|
-
<span className="truncate">
|
|
1418
|
-
Use {normalizedGitHubSearchUrl ? "this GitHub repository" : "pasted repository URL"}
|
|
1427
|
+
{mode === "git" ? (
|
|
1428
|
+
<div className="space-y-3 rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] p-3 sm:p-4">
|
|
1429
|
+
<div className="flex items-start gap-3">
|
|
1430
|
+
<span className="inline-flex h-10 w-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] text-[var(--vk-text-strong)]">
|
|
1431
|
+
<RepoIcon className="h-4 w-4" />
|
|
1419
1432
|
</span>
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
</div>
|
|
1427
|
-
) : null}
|
|
1428
|
-
|
|
1429
|
-
{githubReposError ? (
|
|
1430
|
-
<div className="mt-3 rounded-[5px] border border-[var(--vk-red)]/40 bg-[var(--vk-bg-panel)] px-3 py-3 text-[12px] text-[var(--vk-red)]">
|
|
1431
|
-
<p>{githubReposError}</p>
|
|
1433
|
+
<div className="min-w-0 flex-1">
|
|
1434
|
+
<p className="text-[14px] font-medium text-[var(--vk-text-strong)]">Choose repository</p>
|
|
1435
|
+
<p className="pt-0.5 text-[12px] leading-5 text-[var(--vk-text-muted)]">
|
|
1436
|
+
Select a repo first. Branch, workspace name, and runtime defaults come next.
|
|
1437
|
+
</p>
|
|
1438
|
+
</div>
|
|
1432
1439
|
<button
|
|
1433
1440
|
type="button"
|
|
1434
1441
|
onClick={() => {
|
|
1435
1442
|
setGithubReposLoaded(false);
|
|
1436
1443
|
void handleFetchGitHubRepos(true);
|
|
1437
1444
|
}}
|
|
1438
|
-
|
|
1445
|
+
disabled={githubReposLoading}
|
|
1446
|
+
className="inline-flex h-9 items-center rounded-[6px] border border-[var(--vk-border)] px-3 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1439
1447
|
>
|
|
1440
|
-
|
|
1448
|
+
{githubReposLoading ? (
|
|
1449
|
+
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
1450
|
+
) : (
|
|
1451
|
+
<>
|
|
1452
|
+
<RefreshCcw className="mr-1.5 h-3.5 w-3.5" />
|
|
1453
|
+
Refresh
|
|
1454
|
+
</>
|
|
1455
|
+
)}
|
|
1441
1456
|
</button>
|
|
1442
1457
|
</div>
|
|
1443
|
-
) : null}
|
|
1444
1458
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1459
|
+
<div className="relative">
|
|
1460
|
+
<MarkGithubIcon className="pointer-events-none absolute left-3 top-1/2 h-[16px] w-[16px] -translate-y-1/2 text-[var(--vk-text-muted)]" />
|
|
1461
|
+
<input
|
|
1462
|
+
value={githubRepoSearch}
|
|
1463
|
+
onChange={(event) => setGithubRepoSearch(event.target.value)}
|
|
1464
|
+
onKeyDown={(event) => {
|
|
1465
|
+
if (event.key === "Enter" && showUseSearchValueAction) {
|
|
1466
|
+
event.preventDefault();
|
|
1467
|
+
void handleUseSearchValueAsRepository();
|
|
1468
|
+
}
|
|
1469
|
+
}}
|
|
1470
|
+
placeholder="Search GitHub repos or paste a repository URL"
|
|
1471
|
+
className="h-11 w-full rounded-[8px] border border-[var(--vk-border)] bg-transparent pl-10 pr-3 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1472
|
+
/>
|
|
1473
|
+
</div>
|
|
1474
|
+
|
|
1475
|
+
{showUseSearchValueAction ? (
|
|
1476
|
+
<button
|
|
1477
|
+
type="button"
|
|
1478
|
+
onClick={() => {
|
|
1479
|
+
void handleUseSearchValueAsRepository();
|
|
1480
|
+
}}
|
|
1481
|
+
className="inline-flex w-full items-center justify-center gap-2 rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 py-2.5 text-[13px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1482
|
+
>
|
|
1483
|
+
<RepoIcon className="h-4 w-4 text-[var(--vk-text-strong)]" />
|
|
1484
|
+
<span className="truncate">
|
|
1485
|
+
Use {normalizedGitHubSearchUrl ? "this GitHub repository" : "pasted repository URL"}
|
|
1486
|
+
</span>
|
|
1487
|
+
</button>
|
|
1488
|
+
) : null}
|
|
1489
|
+
|
|
1490
|
+
{githubReposLoading && githubRepos.length === 0 ? (
|
|
1491
|
+
<div className="rounded-[8px] border border-[var(--vk-border)] px-3 py-3 text-[12px] text-[var(--vk-text-muted)]">
|
|
1492
|
+
Loading accessible GitHub repositories...
|
|
1493
|
+
</div>
|
|
1494
|
+
) : null}
|
|
1495
|
+
|
|
1496
|
+
{githubReposError ? (
|
|
1497
|
+
<div className="rounded-[8px] border border-[var(--vk-red)]/40 bg-[var(--vk-bg-panel)] px-3 py-3 text-[12px] text-[var(--vk-red)]">
|
|
1498
|
+
<p>{githubReposError}</p>
|
|
1499
|
+
<button
|
|
1500
|
+
type="button"
|
|
1501
|
+
onClick={() => {
|
|
1502
|
+
setGithubReposLoaded(false);
|
|
1503
|
+
void handleFetchGitHubRepos(true);
|
|
1504
|
+
}}
|
|
1505
|
+
className="mt-2 inline-flex items-center rounded-[6px] border border-[var(--vk-border)] px-2 py-1 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1506
|
+
>
|
|
1507
|
+
Retry
|
|
1508
|
+
</button>
|
|
1509
|
+
</div>
|
|
1510
|
+
) : null}
|
|
1511
|
+
|
|
1512
|
+
{!githubReposError && filteredGitHubRepos.length > 0 ? (
|
|
1513
|
+
<div className="max-h-[min(42dvh,340px)] space-y-2 overflow-y-auto pr-1">
|
|
1514
|
+
{filteredGitHubRepos.map((repo) => {
|
|
1515
|
+
const repoUpdatedLabel = formatRepoUpdatedLabel(repo.updatedAt);
|
|
1516
|
+
const selected = selectedGitHubRepoData?.httpsUrl === repo.httpsUrl;
|
|
1517
|
+
return (
|
|
1518
|
+
<button
|
|
1519
|
+
key={repo.httpsUrl}
|
|
1520
|
+
type="button"
|
|
1521
|
+
onClick={() => {
|
|
1522
|
+
void handleSelectGitHubRepo(repo.httpsUrl);
|
|
1523
|
+
}}
|
|
1524
|
+
className={`flex w-full items-start gap-3 rounded-[8px] border px-3 py-3 text-left transition ${
|
|
1525
|
+
selected
|
|
1526
|
+
? "border-[var(--vk-orange)] bg-[color:color-mix(in_srgb,var(--vk-orange)_10%,transparent)]"
|
|
1527
|
+
: "border-[var(--vk-border)] bg-[var(--vk-bg-panel)] hover:bg-[var(--vk-bg-hover)]"
|
|
1528
|
+
}`}
|
|
1529
|
+
>
|
|
1530
|
+
<span className="mt-0.5 inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] text-[var(--vk-text-strong)]">
|
|
1531
|
+
<RepoIcon className="h-4 w-4" />
|
|
1532
|
+
</span>
|
|
1533
|
+
<span className="min-w-0 flex-1">
|
|
1534
|
+
<span className="flex flex-wrap items-center gap-2">
|
|
1535
|
+
<span className="truncate text-[13px] font-medium text-[var(--vk-text-strong)]">
|
|
1536
|
+
{repo.fullName}
|
|
1537
|
+
</span>
|
|
1538
|
+
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1539
|
+
{repo.private ? <LockIcon className="h-3 w-3" /> : <MarkGithubIcon className="h-3 w-3" />}
|
|
1540
|
+
{repo.private ? "Private" : "Public"}
|
|
1541
|
+
</span>
|
|
1542
|
+
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1543
|
+
<GitBranchIcon className="h-3 w-3" />
|
|
1544
|
+
{repo.defaultBranch}
|
|
1545
|
+
</span>
|
|
1474
1546
|
</span>
|
|
1475
|
-
|
|
1476
|
-
<
|
|
1477
|
-
|
|
1547
|
+
{repo.description ? (
|
|
1548
|
+
<span className="mt-1 block line-clamp-2 text-[12px] leading-[17px] text-[var(--vk-text-muted)]">
|
|
1549
|
+
{repo.description}
|
|
1550
|
+
</span>
|
|
1551
|
+
) : null}
|
|
1552
|
+
<span className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-[var(--vk-text-muted)]">
|
|
1553
|
+
{repo.ownerLogin ? <span>{repo.ownerLogin}</span> : null}
|
|
1554
|
+
{repoUpdatedLabel ? <span>{repoUpdatedLabel}</span> : null}
|
|
1555
|
+
{repo.permission ? <span>{repo.permission.toLowerCase()}</span> : null}
|
|
1478
1556
|
</span>
|
|
1479
1557
|
</span>
|
|
1480
|
-
|
|
1481
|
-
<
|
|
1482
|
-
{repo.description}
|
|
1483
|
-
</span>
|
|
1484
|
-
) : null}
|
|
1485
|
-
<span className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-[var(--vk-text-muted)]">
|
|
1486
|
-
{repo.ownerLogin ? <span>{repo.ownerLogin}</span> : null}
|
|
1487
|
-
{repoUpdatedLabel ? <span>{repoUpdatedLabel}</span> : null}
|
|
1488
|
-
{repo.permission ? <span>{repo.permission.toLowerCase()}</span> : null}
|
|
1558
|
+
<span className="ml-auto inline-flex h-4 w-4 shrink-0 items-center justify-center text-[var(--vk-text-strong)]">
|
|
1559
|
+
{selected ? <Check className="h-4 w-4" /> : null}
|
|
1489
1560
|
</span>
|
|
1490
|
-
</
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
);
|
|
1496
|
-
})}
|
|
1497
|
-
</div>
|
|
1498
|
-
) : null}
|
|
1499
|
-
|
|
1500
|
-
{!githubReposLoading && !githubReposError && filteredGitHubRepos.length === 0 ? (
|
|
1501
|
-
<p className="mt-3 text-[12px] text-[var(--vk-text-muted)]">
|
|
1502
|
-
{githubRepoSearch.trim().length > 0
|
|
1503
|
-
? "No matching repositories. Try another search or paste a repository URL."
|
|
1504
|
-
: "No accessible GitHub repositories were found for this machine yet."}
|
|
1505
|
-
</p>
|
|
1506
|
-
) : null}
|
|
1507
|
-
</div>
|
|
1561
|
+
</button>
|
|
1562
|
+
);
|
|
1563
|
+
})}
|
|
1564
|
+
</div>
|
|
1565
|
+
) : null}
|
|
1508
1566
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1567
|
+
{!githubReposLoading && !githubReposError && filteredGitHubRepos.length === 0 ? (
|
|
1568
|
+
<p className="text-[12px] text-[var(--vk-text-muted)]">
|
|
1569
|
+
{githubRepoSearch.trim().length > 0
|
|
1570
|
+
? "No matching repositories. Try another search or paste a repository URL."
|
|
1571
|
+
: "No accessible GitHub repositories were found for this machine yet."}
|
|
1572
|
+
</p>
|
|
1573
|
+
) : null}
|
|
1574
|
+
</div>
|
|
1575
|
+
) : (
|
|
1576
|
+
<div className="space-y-3 rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] p-3 sm:p-4">
|
|
1511
1577
|
<div className="flex items-start gap-3">
|
|
1512
|
-
<span className="inline-flex h-
|
|
1513
|
-
<
|
|
1578
|
+
<span className="inline-flex h-10 w-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] text-[var(--vk-text-strong)]">
|
|
1579
|
+
<FolderOpen className="h-5 w-5" />
|
|
1514
1580
|
</span>
|
|
1515
1581
|
<div className="min-w-0 flex-1">
|
|
1516
|
-
<
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1521
|
-
{selectedGitHubRepoData ? (
|
|
1522
|
-
selectedGitHubRepoData.private ? <LockIcon className="h-3 w-3" /> : <MarkGithubIcon className="h-3 w-3" />
|
|
1523
|
-
) : (
|
|
1524
|
-
<MarkGithubIcon className="h-3 w-3" />
|
|
1525
|
-
)}
|
|
1526
|
-
{selectedGitHubRepoData ? (selectedGitHubRepoData.private ? "Private" : "Public") : "Manual URL"}
|
|
1527
|
-
</span>
|
|
1528
|
-
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1529
|
-
<GitBranchIcon className="h-3 w-3" />
|
|
1530
|
-
{defaultBranch || "main"}
|
|
1531
|
-
</span>
|
|
1532
|
-
</div>
|
|
1533
|
-
{selectedGitHubRepoData?.description ? (
|
|
1534
|
-
<p className="mt-1 line-clamp-2 text-[12px] leading-[17px] text-[var(--vk-text-muted)]">
|
|
1535
|
-
{selectedGitHubRepoData.description}
|
|
1536
|
-
</p>
|
|
1537
|
-
) : (
|
|
1538
|
-
<p className="mt-1 truncate text-[12px] text-[var(--vk-text-muted)]">{gitUrl}</p>
|
|
1539
|
-
)}
|
|
1540
|
-
<div className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-[var(--vk-text-muted)]">
|
|
1541
|
-
{selectedGitHubRepoData?.ownerLogin ? <span>{selectedGitHubRepoData.ownerLogin}</span> : null}
|
|
1542
|
-
{selectedRepoUpdatedLabel ? <span>{selectedRepoUpdatedLabel}</span> : null}
|
|
1543
|
-
{selectedGitHubRepoData?.permission ? (
|
|
1544
|
-
<span>{selectedGitHubRepoData.permission.toLowerCase()}</span>
|
|
1545
|
-
) : null}
|
|
1546
|
-
</div>
|
|
1582
|
+
<p className="text-[14px] font-medium text-[var(--vk-text-strong)]">Choose folder</p>
|
|
1583
|
+
<p className="pt-0.5 text-[12px] leading-5 text-[var(--vk-text-muted)]">
|
|
1584
|
+
Pick the repository folder already on disk. You can adjust branch and runtime defaults next.
|
|
1585
|
+
</p>
|
|
1547
1586
|
</div>
|
|
1548
1587
|
</div>
|
|
1549
|
-
|
|
1550
|
-
) : null}
|
|
1551
|
-
</>
|
|
1552
|
-
) : (
|
|
1553
|
-
<>
|
|
1554
|
-
<label className="block">
|
|
1555
|
-
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Local Path</span>
|
|
1556
|
-
<div className="flex items-center gap-2">
|
|
1557
|
-
<input
|
|
1558
|
-
value={path}
|
|
1559
|
-
readOnly
|
|
1560
|
-
onClick={() => openFolderPicker("local")}
|
|
1561
|
-
placeholder="Use Browse to select a repository folder"
|
|
1562
|
-
className="h-9 w-full cursor-pointer rounded-[4px] border border-[var(--vk-border)] bg-transparent px-2 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1563
|
-
/>
|
|
1588
|
+
|
|
1564
1589
|
<button
|
|
1565
1590
|
type="button"
|
|
1566
1591
|
onClick={() => openFolderPicker("local")}
|
|
1567
|
-
className="inline-flex h-
|
|
1568
|
-
title="Browse folders"
|
|
1592
|
+
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 text-[13px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1569
1593
|
>
|
|
1570
1594
|
<FolderOpen className="h-4 w-4" />
|
|
1595
|
+
{localPath.trim().length > 0 ? "Choose another folder" : "Choose folder"}
|
|
1571
1596
|
</button>
|
|
1572
|
-
</div>
|
|
1573
|
-
</label>
|
|
1574
|
-
<label className="flex items-center gap-2 text-[13px] text-[var(--vk-text-normal)]">
|
|
1575
|
-
<input
|
|
1576
|
-
type="checkbox"
|
|
1577
|
-
checked={initializeGit}
|
|
1578
|
-
onChange={(event) => setInitializeGit(event.target.checked)}
|
|
1579
|
-
className="h-4 w-4 rounded border border-[var(--vk-border)] bg-transparent accent-[var(--vk-orange)]"
|
|
1580
|
-
/>
|
|
1581
|
-
<span>Initialize git if this folder is non-git</span>
|
|
1582
|
-
</label>
|
|
1583
|
-
</>
|
|
1584
|
-
)}
|
|
1585
1597
|
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
setProjectId(event.target.value);
|
|
1592
|
-
setProjectIdTouched(true);
|
|
1593
|
-
}}
|
|
1594
|
-
placeholder="auto-derived from the selected repository or folder"
|
|
1595
|
-
className="h-9 w-full rounded-[4px] border border-[var(--vk-border)] bg-transparent px-2 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1596
|
-
/>
|
|
1597
|
-
</label>
|
|
1598
|
-
|
|
1599
|
-
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
|
|
1600
|
-
<label className="block">
|
|
1601
|
-
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Branch</span>
|
|
1602
|
-
<div className="flex items-center gap-2">
|
|
1603
|
-
<input
|
|
1604
|
-
value={defaultBranch}
|
|
1605
|
-
onChange={(event) => setDefaultBranch(event.target.value)}
|
|
1606
|
-
placeholder="Uses the repository default branch"
|
|
1607
|
-
className="h-9 w-full rounded-[4px] border border-[var(--vk-border)] bg-transparent px-2 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1608
|
-
/>
|
|
1609
|
-
<button
|
|
1610
|
-
type="button"
|
|
1611
|
-
onClick={() => {
|
|
1612
|
-
void handleDetectBranches();
|
|
1613
|
-
}}
|
|
1614
|
-
disabled={branchesLoading}
|
|
1615
|
-
className="inline-flex h-9 items-center rounded-[4px] border border-[var(--vk-border)] px-2 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1616
|
-
title="Detect branches"
|
|
1617
|
-
>
|
|
1618
|
-
{branchesLoading ? (
|
|
1619
|
-
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
1598
|
+
{localPath.trim().length > 0 ? (
|
|
1599
|
+
<div className="rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 py-3">
|
|
1600
|
+
<p className="text-[12px] font-medium text-[var(--vk-text-strong)]">Selected folder</p>
|
|
1601
|
+
<p className="mt-1 break-all text-[12px] leading-5 text-[var(--vk-text-muted)]">{localPath}</p>
|
|
1602
|
+
</div>
|
|
1620
1603
|
) : (
|
|
1621
|
-
<
|
|
1604
|
+
<p className="text-[12px] text-[var(--vk-text-muted)]">
|
|
1605
|
+
The folder picker stays separate so you do not lose your place in this setup flow on mobile.
|
|
1606
|
+
</p>
|
|
1622
1607
|
)}
|
|
1623
|
-
</
|
|
1624
|
-
</div>
|
|
1625
|
-
{branchOptions.length > 0 && (
|
|
1626
|
-
<select
|
|
1627
|
-
value={defaultBranch}
|
|
1628
|
-
onChange={(event) => setDefaultBranch(event.target.value)}
|
|
1629
|
-
className="mt-2 h-8 w-full rounded-[4px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-2 text-[12px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1630
|
-
>
|
|
1631
|
-
{branchOptions.map((branch) => (
|
|
1632
|
-
<option key={branch} value={branch}>
|
|
1633
|
-
{branch}
|
|
1634
|
-
</option>
|
|
1635
|
-
))}
|
|
1636
|
-
</select>
|
|
1637
|
-
)}
|
|
1638
|
-
{branchesError && (
|
|
1639
|
-
<p className="mt-1 text-[11px] text-[var(--vk-red)]">{branchesError}</p>
|
|
1608
|
+
</div>
|
|
1640
1609
|
)}
|
|
1641
|
-
</label>
|
|
1642
|
-
|
|
1643
|
-
<label className="block">
|
|
1644
|
-
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Agent</span>
|
|
1645
|
-
<select
|
|
1646
|
-
value={agent}
|
|
1647
|
-
onChange={(event) => setAgent(event.target.value)}
|
|
1648
|
-
className="h-9 w-full rounded-[4px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-2 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1649
|
-
>
|
|
1650
|
-
{orderedAgentOptions.map((item) => (
|
|
1651
|
-
<option key={item} value={item} className="bg-[var(--vk-bg-panel)] text-[var(--vk-text-normal)]">
|
|
1652
|
-
{getAgentLabel(item)}
|
|
1653
|
-
</option>
|
|
1654
|
-
))}
|
|
1655
|
-
</select>
|
|
1656
|
-
</label>
|
|
1657
|
-
</div>
|
|
1658
1610
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1611
|
+
{error ? <p className="text-[12px] text-[var(--vk-red)]">{error}</p> : null}
|
|
1612
|
+
</div>
|
|
1613
|
+
) : (
|
|
1614
|
+
<div className="space-y-4">
|
|
1615
|
+
<div className="rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] p-3 sm:p-4">
|
|
1616
|
+
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
1617
|
+
<div className="min-w-0 flex-1">
|
|
1618
|
+
<p className="text-[12px] uppercase tracking-[0.08em] text-[var(--vk-text-muted)]">
|
|
1619
|
+
{mode === "git" ? "Selected repository" : "Selected folder"}
|
|
1620
|
+
</p>
|
|
1621
|
+
<p className="mt-1 break-words text-[15px] font-medium text-[var(--vk-text-strong)]">
|
|
1622
|
+
{selectedSourceTitle}
|
|
1623
|
+
</p>
|
|
1624
|
+
<p className="mt-1 break-all text-[12px] leading-5 text-[var(--vk-text-muted)]">
|
|
1625
|
+
{selectedSourceSubtitle}
|
|
1626
|
+
</p>
|
|
1627
|
+
<div className="mt-2 flex flex-wrap gap-2">
|
|
1628
|
+
{mode === "git" ? (
|
|
1629
|
+
<>
|
|
1630
|
+
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1631
|
+
{selectedGitHubRepoData?.private
|
|
1632
|
+
? <LockIcon className="h-3 w-3" />
|
|
1633
|
+
: <MarkGithubIcon className="h-3 w-3" />}
|
|
1634
|
+
{selectedGitHubRepoData
|
|
1635
|
+
? (selectedGitHubRepoData.private ? "Private" : "Public")
|
|
1636
|
+
: "Manual URL"}
|
|
1637
|
+
</span>
|
|
1638
|
+
<span className="inline-flex items-center gap-1 rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1639
|
+
<GitBranchIcon className="h-3 w-3" />
|
|
1640
|
+
{defaultBranch || "main"}
|
|
1641
|
+
</span>
|
|
1642
|
+
{selectedGitHubRepoData?.ownerLogin ? (
|
|
1643
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1644
|
+
{selectedGitHubRepoData.ownerLogin}
|
|
1645
|
+
</span>
|
|
1646
|
+
) : null}
|
|
1647
|
+
{selectedRepoUpdatedLabel ? (
|
|
1648
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1649
|
+
{selectedRepoUpdatedLabel}
|
|
1650
|
+
</span>
|
|
1651
|
+
) : null}
|
|
1652
|
+
</>
|
|
1653
|
+
) : (
|
|
1654
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5 text-[11px] text-[var(--vk-text-muted)]">
|
|
1655
|
+
Local repository
|
|
1656
|
+
</span>
|
|
1657
|
+
)}
|
|
1658
|
+
</div>
|
|
1659
|
+
</div>
|
|
1660
|
+
|
|
1661
|
+
<button
|
|
1662
|
+
type="button"
|
|
1663
|
+
onClick={() => setStep("source")}
|
|
1664
|
+
className="inline-flex h-9 items-center justify-center rounded-[6px] border border-[var(--vk-border)] px-3 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1665
|
+
>
|
|
1666
|
+
Change
|
|
1667
|
+
</button>
|
|
1668
|
+
</div>
|
|
1669
|
+
</div>
|
|
1670
|
+
|
|
1671
|
+
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
|
1668
1672
|
<label className="block">
|
|
1669
|
-
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">
|
|
1670
|
-
|
|
1671
|
-
|
|
1673
|
+
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Workspace Name (optional)</span>
|
|
1674
|
+
<input
|
|
1675
|
+
value={projectId}
|
|
1676
|
+
onChange={(event) => {
|
|
1677
|
+
setProjectId(event.target.value);
|
|
1678
|
+
setProjectIdTouched(true);
|
|
1679
|
+
}}
|
|
1680
|
+
placeholder="auto-derived from the selected repository or folder"
|
|
1681
|
+
className="h-10 w-full rounded-[8px] border border-[var(--vk-border)] bg-transparent px-3 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1682
|
+
/>
|
|
1683
|
+
</label>
|
|
1684
|
+
|
|
1685
|
+
<label className="block">
|
|
1686
|
+
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Branch</span>
|
|
1672
1687
|
<div className="flex items-center gap-2">
|
|
1673
1688
|
<input
|
|
1674
|
-
value={
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
className="h-9 w-full cursor-pointer rounded-[4px] border border-[var(--vk-border)] bg-transparent px-2 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1689
|
+
value={defaultBranch}
|
|
1690
|
+
onChange={(event) => setDefaultBranch(event.target.value)}
|
|
1691
|
+
placeholder="Uses the repository default branch"
|
|
1692
|
+
className="h-10 w-full rounded-[8px] border border-[var(--vk-border)] bg-transparent px-3 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1679
1693
|
/>
|
|
1680
1694
|
<button
|
|
1681
1695
|
type="button"
|
|
1682
|
-
onClick={() =>
|
|
1683
|
-
|
|
1684
|
-
|
|
1696
|
+
onClick={() => {
|
|
1697
|
+
void handleDetectBranches();
|
|
1698
|
+
}}
|
|
1699
|
+
disabled={branchesLoading}
|
|
1700
|
+
className="inline-flex h-10 items-center rounded-[8px] border border-[var(--vk-border)] px-3 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1701
|
+
title="Detect branches"
|
|
1685
1702
|
>
|
|
1686
|
-
|
|
1703
|
+
{branchesLoading ? (
|
|
1704
|
+
<Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
1705
|
+
) : (
|
|
1706
|
+
<RefreshCcw className="h-3.5 w-3.5" />
|
|
1707
|
+
)}
|
|
1687
1708
|
</button>
|
|
1688
1709
|
</div>
|
|
1710
|
+
{branchOptions.length > 0 ? (
|
|
1711
|
+
<select
|
|
1712
|
+
value={defaultBranch}
|
|
1713
|
+
onChange={(event) => setDefaultBranch(event.target.value)}
|
|
1714
|
+
className="mt-2 h-9 w-full rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 text-[12px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1715
|
+
>
|
|
1716
|
+
{branchOptions.map((branch) => (
|
|
1717
|
+
<option key={branch} value={branch}>
|
|
1718
|
+
{branch}
|
|
1719
|
+
</option>
|
|
1720
|
+
))}
|
|
1721
|
+
</select>
|
|
1722
|
+
) : null}
|
|
1723
|
+
{branchesError ? <p className="mt-1 text-[11px] text-[var(--vk-red)]">{branchesError}</p> : null}
|
|
1689
1724
|
</label>
|
|
1725
|
+
</div>
|
|
1690
1726
|
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
Turn this off only if you want sessions to run directly in the selected branch.
|
|
1702
|
-
</span>
|
|
1727
|
+
<div className="flex flex-wrap gap-2 text-[11px] text-[var(--vk-text-muted)]">
|
|
1728
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5">
|
|
1729
|
+
Agent: {getAgentLabel(agent)}
|
|
1730
|
+
</span>
|
|
1731
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5">
|
|
1732
|
+
{useWorktree ? "Worktree isolation on" : "Runs on selected branch"}
|
|
1733
|
+
</span>
|
|
1734
|
+
{mode === "local" ? (
|
|
1735
|
+
<span className="inline-flex rounded-full border border-[var(--vk-border)] px-2 py-0.5">
|
|
1736
|
+
{initializeGit ? "Auto-init git if needed" : "Do not init git"}
|
|
1703
1737
|
</span>
|
|
1704
|
-
|
|
1738
|
+
) : null}
|
|
1705
1739
|
</div>
|
|
1706
|
-
</details>
|
|
1707
|
-
) : (
|
|
1708
|
-
<label className="flex items-start gap-2 rounded-[4px] border border-[var(--vk-border)] px-2 py-2 text-[13px] text-[var(--vk-text-normal)]">
|
|
1709
|
-
<input
|
|
1710
|
-
type="checkbox"
|
|
1711
|
-
checked={useWorktree}
|
|
1712
|
-
onChange={(event) => setUseWorktree(event.target.checked)}
|
|
1713
|
-
className="mt-0.5 h-4 w-4 rounded border border-[var(--vk-border)] bg-transparent accent-[var(--vk-orange)]"
|
|
1714
|
-
/>
|
|
1715
|
-
<span>
|
|
1716
|
-
Keep work isolated in a new worktree
|
|
1717
|
-
<span className="block text-[11px] text-[var(--vk-text-muted)]">
|
|
1718
|
-
Turn this off only if you want sessions to run directly in the selected branch.
|
|
1719
|
-
</span>
|
|
1720
|
-
</span>
|
|
1721
|
-
</label>
|
|
1722
|
-
)}
|
|
1723
1740
|
|
|
1724
|
-
|
|
1741
|
+
<details className="rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)]">
|
|
1742
|
+
<summary className="cursor-pointer list-none px-3 py-3 text-[13px] text-[var(--vk-text-normal)] marker:hidden">
|
|
1743
|
+
<span className="inline-flex items-center gap-2">
|
|
1744
|
+
<ChevronDown className="h-3.5 w-3.5 text-[var(--vk-text-muted)]" />
|
|
1745
|
+
Runtime and repository options
|
|
1746
|
+
</span>
|
|
1747
|
+
</summary>
|
|
1748
|
+
<div className="space-y-3 border-t border-[var(--vk-border)] px-3 py-3">
|
|
1749
|
+
<label className="block">
|
|
1750
|
+
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">Agent</span>
|
|
1751
|
+
<select
|
|
1752
|
+
value={agent}
|
|
1753
|
+
onChange={(event) => setAgent(event.target.value)}
|
|
1754
|
+
className="h-10 w-full rounded-[8px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1755
|
+
>
|
|
1756
|
+
{orderedAgentOptions.map((item) => (
|
|
1757
|
+
<option key={item} value={item} className="bg-[var(--vk-bg-panel)] text-[var(--vk-text-normal)]">
|
|
1758
|
+
{getAgentLabel(item)}
|
|
1759
|
+
</option>
|
|
1760
|
+
))}
|
|
1761
|
+
</select>
|
|
1762
|
+
</label>
|
|
1763
|
+
|
|
1764
|
+
<div className="rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 py-3">
|
|
1765
|
+
<label className="flex items-start gap-3 text-[13px] text-[var(--vk-text-normal)]">
|
|
1766
|
+
<input
|
|
1767
|
+
type="checkbox"
|
|
1768
|
+
checked={useWorktree}
|
|
1769
|
+
onChange={(event) => setUseWorktree(event.target.checked)}
|
|
1770
|
+
className="mt-0.5 h-4 w-4 rounded border border-[var(--vk-border)] bg-transparent accent-[var(--vk-orange)]"
|
|
1771
|
+
/>
|
|
1772
|
+
<span>
|
|
1773
|
+
Keep work isolated in a new worktree
|
|
1774
|
+
<span className="mt-1 block text-[11px] leading-5 text-[var(--vk-text-muted)]">
|
|
1775
|
+
Recommended. Turn this off only if sessions should run directly on the selected branch.
|
|
1776
|
+
</span>
|
|
1777
|
+
</span>
|
|
1778
|
+
</label>
|
|
1779
|
+
</div>
|
|
1780
|
+
|
|
1781
|
+
{mode === "local" ? (
|
|
1782
|
+
<div className="rounded-[10px] border border-[var(--vk-border)] bg-[var(--vk-bg-panel)] px-3 py-3">
|
|
1783
|
+
<label className="flex items-start gap-3 text-[13px] text-[var(--vk-text-normal)]">
|
|
1784
|
+
<input
|
|
1785
|
+
type="checkbox"
|
|
1786
|
+
checked={initializeGit}
|
|
1787
|
+
onChange={(event) => setInitializeGit(event.target.checked)}
|
|
1788
|
+
className="mt-0.5 h-4 w-4 rounded border border-[var(--vk-border)] bg-transparent accent-[var(--vk-orange)]"
|
|
1789
|
+
/>
|
|
1790
|
+
<span>
|
|
1791
|
+
Initialize git if this folder is not already a repository
|
|
1792
|
+
<span className="mt-1 block text-[11px] leading-5 text-[var(--vk-text-muted)]">
|
|
1793
|
+
Leave this on unless you know the folder should stay non-git.
|
|
1794
|
+
</span>
|
|
1795
|
+
</span>
|
|
1796
|
+
</label>
|
|
1797
|
+
</div>
|
|
1798
|
+
) : (
|
|
1799
|
+
<label className="block">
|
|
1800
|
+
<span className="mb-1.5 block text-[12px] text-[var(--vk-text-muted)]">
|
|
1801
|
+
Clone into a specific folder
|
|
1802
|
+
</span>
|
|
1803
|
+
<div className="flex items-center gap-2">
|
|
1804
|
+
<input
|
|
1805
|
+
value={clonePath}
|
|
1806
|
+
readOnly
|
|
1807
|
+
onClick={() => openFolderPicker("clone")}
|
|
1808
|
+
placeholder="Leave empty to use Conductor's default workspace location"
|
|
1809
|
+
className="h-10 w-full cursor-pointer rounded-[8px] border border-[var(--vk-border)] bg-transparent px-3 text-[14px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
|
|
1810
|
+
/>
|
|
1811
|
+
<button
|
|
1812
|
+
type="button"
|
|
1813
|
+
onClick={() => openFolderPicker("clone")}
|
|
1814
|
+
className="inline-flex h-10 items-center rounded-[8px] border border-[var(--vk-border)] px-3 text-[12px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)]"
|
|
1815
|
+
title="Browse folders"
|
|
1816
|
+
>
|
|
1817
|
+
<FolderOpen className="h-4 w-4" />
|
|
1818
|
+
</button>
|
|
1819
|
+
</div>
|
|
1820
|
+
</label>
|
|
1821
|
+
)}
|
|
1822
|
+
</div>
|
|
1823
|
+
</details>
|
|
1824
|
+
|
|
1825
|
+
{error ? <p className="text-[12px] text-[var(--vk-red)]">{error}</p> : null}
|
|
1826
|
+
</div>
|
|
1827
|
+
)}
|
|
1725
1828
|
</div>
|
|
1726
1829
|
|
|
1727
|
-
<footer className="
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1830
|
+
<footer className="border-t border-[var(--vk-border)] bg-[color:color-mix(in_srgb,var(--vk-bg-panel)_92%,transparent)] px-4 py-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur">
|
|
1831
|
+
{step === "source" ? (
|
|
1832
|
+
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-between">
|
|
1833
|
+
<button
|
|
1834
|
+
type="button"
|
|
1835
|
+
onClick={onClose}
|
|
1836
|
+
disabled={creating}
|
|
1837
|
+
className="inline-flex h-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] px-4 text-[13px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1838
|
+
>
|
|
1839
|
+
Cancel
|
|
1840
|
+
</button>
|
|
1841
|
+
<button
|
|
1842
|
+
type="button"
|
|
1843
|
+
onClick={() => {
|
|
1844
|
+
if (mode === "local" && !sourceReady) {
|
|
1845
|
+
openFolderPicker("local");
|
|
1846
|
+
return;
|
|
1847
|
+
}
|
|
1848
|
+
handleContinueToDetails();
|
|
1849
|
+
}}
|
|
1850
|
+
disabled={(mode === "git" && !sourceReady) || creating}
|
|
1851
|
+
className="inline-flex h-10 items-center justify-center rounded-[8px] bg-[var(--vk-bg-active)] px-4 text-[13px] text-[var(--vk-text-strong)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1852
|
+
>
|
|
1853
|
+
{mode === "local" && !sourceReady ? "Choose folder" : "Continue"}
|
|
1854
|
+
</button>
|
|
1855
|
+
</div>
|
|
1856
|
+
) : (
|
|
1857
|
+
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-between">
|
|
1858
|
+
<button
|
|
1859
|
+
type="button"
|
|
1860
|
+
onClick={() => setStep("source")}
|
|
1861
|
+
disabled={creating}
|
|
1862
|
+
className="inline-flex h-10 items-center justify-center rounded-[8px] border border-[var(--vk-border)] px-4 text-[13px] text-[var(--vk-text-normal)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1863
|
+
>
|
|
1864
|
+
Back
|
|
1865
|
+
</button>
|
|
1866
|
+
<button
|
|
1867
|
+
type="submit"
|
|
1868
|
+
disabled={!canSubmit || creating}
|
|
1869
|
+
className="inline-flex h-10 items-center justify-center rounded-[8px] bg-[var(--vk-bg-active)] px-4 text-[13px] text-[var(--vk-text-strong)] hover:bg-[var(--vk-bg-hover)] disabled:opacity-50"
|
|
1870
|
+
>
|
|
1871
|
+
{creating ? (
|
|
1872
|
+
<>
|
|
1873
|
+
<Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
|
|
1874
|
+
Adding...
|
|
1875
|
+
</>
|
|
1876
|
+
) : "Add Workspace"}
|
|
1877
|
+
</button>
|
|
1878
|
+
</div>
|
|
1879
|
+
)}
|
|
1880
|
+
</footer>
|
|
1749
1881
|
</form>
|
|
1750
1882
|
</div>
|
|
1751
1883
|
|
|
1752
1884
|
<FolderPickerDialog
|
|
1753
1885
|
open={folderPickerOpen}
|
|
1754
|
-
initialPath={
|
|
1886
|
+
initialPath={folderPickerTarget === "clone" ? clonePath : localPath}
|
|
1755
1887
|
title={folderPickerTarget === "local" ? "Select Local Repository" : "Select Clone Target Folder"}
|
|
1756
1888
|
description={folderPickerTarget === "local"
|
|
1757
1889
|
? "Choose the local repository folder."
|
|
@@ -1760,16 +1892,19 @@ export function NewWorkspaceDialog({
|
|
|
1760
1892
|
onSelect={(selectedPath) => {
|
|
1761
1893
|
setFolderPickerOpen(false);
|
|
1762
1894
|
if (!selectedPath) return;
|
|
1763
|
-
|
|
1764
|
-
|
|
1895
|
+
if (folderPickerTarget === "clone") {
|
|
1896
|
+
setClonePath(selectedPath);
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1899
|
+
setLocalPath(selectedPath);
|
|
1900
|
+
if (!projectIdTouched) {
|
|
1765
1901
|
const folderName = extractNameFromPath(selectedPath);
|
|
1766
1902
|
if (folderName) {
|
|
1767
1903
|
setProjectId(suggestWorkspaceId(folderName));
|
|
1768
1904
|
}
|
|
1769
1905
|
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
}
|
|
1906
|
+
void handleDetectBranches({ path: selectedPath });
|
|
1907
|
+
setStep("details");
|
|
1773
1908
|
}}
|
|
1774
1909
|
/>
|
|
1775
1910
|
</>
|