gitspace 0.2.0-rc.4 → 0.2.0-rc.6
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 +1 -1
- package/bun.lock +8 -0
- package/docs/SITE_DOCS_FIGMA_MAKE.md +8 -8
- package/package.json +5 -5
- package/src/commands/remove.ts +66 -50
- package/src/core/__tests__/workspace.test.ts +149 -0
- package/src/core/bundle.ts +1 -1
- package/src/core/workspace.ts +249 -0
- package/src/index.ts +7 -1
- package/src/lib/remote-session/session-handler.ts +31 -21
- package/src/tui/app.tsx +178 -25
- package/src/utils/__tests__/run-scripts.test.ts +306 -0
- package/src/utils/__tests__/run-workspace-scripts.test.ts +252 -0
- package/src/utils/run-scripts.ts +27 -3
- package/src/utils/run-workspace-scripts.ts +89 -0
- package/src/utils/sanitize.ts +64 -0
- package/src/utils/workspace-state.ts +17 -1
- package/src/version.generated.d.ts +2 -0
- package/.claude/settings.local.json +0 -25
package/src/index.ts
CHANGED
|
@@ -128,7 +128,13 @@ addCommand
|
|
|
128
128
|
.action(async (workspaceName, options) => {
|
|
129
129
|
await checkFirstTimeSetup()
|
|
130
130
|
try {
|
|
131
|
-
|
|
131
|
+
// Map commander option names to CreateWorkspaceOptions property names
|
|
132
|
+
await addWorkspace(workspaceName, {
|
|
133
|
+
branchName: options.branch,
|
|
134
|
+
fromBranch: options.from,
|
|
135
|
+
noShell: options.shell === false,
|
|
136
|
+
noSetup: options.setup === false,
|
|
137
|
+
})
|
|
132
138
|
} catch (error) {
|
|
133
139
|
handleError(error)
|
|
134
140
|
}
|
|
@@ -31,9 +31,12 @@ import {
|
|
|
31
31
|
// Import project loading
|
|
32
32
|
import { loadProjects } from "../../tui/state";
|
|
33
33
|
|
|
34
|
-
// Import workspace
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
34
|
+
// Import workspace operations
|
|
35
|
+
import { deleteWorkspaceCore } from "../../core/workspace";
|
|
36
|
+
import { readProjectConfig } from "../../core/config";
|
|
37
|
+
|
|
38
|
+
// Import script execution
|
|
39
|
+
import { runWorkspaceScripts } from "../../utils/run-workspace-scripts";
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
42
|
* Session state for a connected client
|
|
@@ -326,6 +329,24 @@ export class RemoteSessionHandler {
|
|
|
326
329
|
return;
|
|
327
330
|
}
|
|
328
331
|
|
|
332
|
+
// Run setup or select scripts for the workspace
|
|
333
|
+
const config = readProjectConfig(workspace.projectName);
|
|
334
|
+
|
|
335
|
+
console.log(`[remote-session] Running workspace scripts for: ${workspace.id}`);
|
|
336
|
+
const scriptResult = await runWorkspaceScripts({
|
|
337
|
+
projectName: workspace.projectName,
|
|
338
|
+
workspacePath: workspace.path,
|
|
339
|
+
workspaceName: workspace.id,
|
|
340
|
+
repository: config.repository,
|
|
341
|
+
interactive: false, // Remote context - scripts can't prompt for input
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
if (!scriptResult.success) {
|
|
345
|
+
console.error(`[remote-session] ${scriptResult.phase} scripts failed:`, scriptResult.error);
|
|
346
|
+
await this.sendError(session, sendResponse, "SCRIPT_FAILED", `Workspace scripts failed during ${scriptResult.phase} phase: ${scriptResult.error}`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
329
350
|
// Create session name: use provided name or auto-generate
|
|
330
351
|
let sessionName: string;
|
|
331
352
|
if (msg.sessionName) {
|
|
@@ -449,25 +470,14 @@ export class RemoteSessionHandler {
|
|
|
449
470
|
sendResponse: (data: Uint8Array) => void
|
|
450
471
|
): Promise<void> {
|
|
451
472
|
try {
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
// Get workspace info for branch name
|
|
457
|
-
const info = await getWorktreeInfo(workspacePath);
|
|
458
|
-
if (!info) {
|
|
459
|
-
await this.sendError(session, sendResponse, "NOT_FOUND", "Workspace not found");
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// Remove worktree
|
|
464
|
-
await removeWorktree(baseDir, workspacePath, true);
|
|
473
|
+
const result = await deleteWorkspaceCore(projectName, workspaceId, {
|
|
474
|
+
nonInteractive: true, // Remote context - scripts can't prompt for input
|
|
475
|
+
});
|
|
465
476
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
await
|
|
469
|
-
|
|
470
|
-
// Branch deletion is best-effort
|
|
477
|
+
if (!result.success) {
|
|
478
|
+
const errorCode = result.error?.includes("not found") ? "NOT_FOUND" : "DELETE_FAILED";
|
|
479
|
+
await this.sendError(session, sendResponse, errorCode, result.error || "Failed to delete workspace");
|
|
480
|
+
return;
|
|
471
481
|
}
|
|
472
482
|
|
|
473
483
|
await this.sendMessage(session, sendResponse, {
|
package/src/tui/app.tsx
CHANGED
|
@@ -57,15 +57,18 @@ import {
|
|
|
57
57
|
projectExists,
|
|
58
58
|
updateProjectConfig,
|
|
59
59
|
} from '../core/config.js';
|
|
60
|
-
import { removeWorkspace, removeProject } from '../commands/remove.js';
|
|
61
60
|
|
|
62
|
-
// Git and workspace
|
|
63
|
-
import { listRemoteBranches, createWorktree,
|
|
61
|
+
// Git and workspace operations
|
|
62
|
+
import { listRemoteBranches, createWorktree, getDefaultBranch } from '../core/git.js';
|
|
63
|
+
import { deleteWorkspaceCore, deleteProjectCore } from '../core/workspace.js';
|
|
64
64
|
import { fetchUnstartedIssues } from '../core/linear.js';
|
|
65
65
|
import { generateMarkdown } from '../utils/markdown.js';
|
|
66
|
-
import { sanitizeForFileSystem, generateWorkspaceName, isValidWorkspaceName, extractRepoName } from '../utils/sanitize.js';
|
|
66
|
+
import { sanitizeForFileSystem, generateWorkspaceName, isValidWorkspaceName, isValidBranchName, extractRepoName } from '../utils/sanitize.js';
|
|
67
67
|
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
68
68
|
import { join } from 'path';
|
|
69
|
+
|
|
70
|
+
// Script execution
|
|
71
|
+
import { runWorkspaceScripts } from '../utils/run-workspace-scripts.js';
|
|
69
72
|
import type { LinearIssue } from '../types/workspace.js';
|
|
70
73
|
|
|
71
74
|
// Project creation
|
|
@@ -98,7 +101,8 @@ type WorkspaceFlowState =
|
|
|
98
101
|
| { type: 'loading'; title: string; message: string }
|
|
99
102
|
| { type: 'branch-select'; branches: string[]; selectedIndex: number }
|
|
100
103
|
| { type: 'linear-select'; issues: LinearIssue[]; selectedIndex: number }
|
|
101
|
-
| { type: 'manual-input'; inputValue: string; error: string | null }
|
|
104
|
+
| { type: 'manual-name-input'; inputValue: string; error: string | null }
|
|
105
|
+
| { type: 'manual-branch-input'; workspaceName: string; inputValue: string }
|
|
102
106
|
| { type: 'creating'; workspaceName: string };
|
|
103
107
|
|
|
104
108
|
/** Project flow states - explicit state machine for project creation */
|
|
@@ -371,7 +375,33 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
371
375
|
warning: 'This will delete all workspaces in this project!',
|
|
372
376
|
onConfirm: async () => {
|
|
373
377
|
flow.showLoading({ title: 'Deleting', message: 'Removing project...' });
|
|
374
|
-
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
const result = await deleteProjectCore(project.name, {
|
|
381
|
+
nonInteractive: true, // TUI is non-interactive for scripts
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
if (!result.success && result.errors.length > 0) {
|
|
385
|
+
console.error('[tui] Project deletion errors:', result.errors);
|
|
386
|
+
flow.close();
|
|
387
|
+
flow.showMessage({
|
|
388
|
+
title: 'Delete Failed',
|
|
389
|
+
message: `Failed to delete project "${project.name}". Check logs for details.`,
|
|
390
|
+
variant: 'error',
|
|
391
|
+
});
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error('[tui] Failed to delete project:', error);
|
|
396
|
+
flow.close();
|
|
397
|
+
flow.showMessage({
|
|
398
|
+
title: 'Delete Failed',
|
|
399
|
+
message: `An unexpected error occurred while deleting project "${project.name}".`,
|
|
400
|
+
variant: 'error',
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
375
405
|
flow.close();
|
|
376
406
|
await refreshProjects();
|
|
377
407
|
},
|
|
@@ -419,7 +449,7 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
419
449
|
} else if (params.workspaceId) {
|
|
420
450
|
// Create new session
|
|
421
451
|
const workspace = state.workspaces.find(w => w.name === params.workspaceId);
|
|
422
|
-
if (workspace) {
|
|
452
|
+
if (workspace && state.currentProject) {
|
|
423
453
|
flow.showInput({
|
|
424
454
|
title: 'New Session',
|
|
425
455
|
label: 'Session name (optional):',
|
|
@@ -427,12 +457,36 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
427
457
|
onSubmit: async (name) => {
|
|
428
458
|
const sessionName = name || `${state.currentProject}:${workspace.name}:${Date.now()}`;
|
|
429
459
|
try {
|
|
460
|
+
const config = readProjectConfig(state.currentProject!);
|
|
461
|
+
|
|
462
|
+
// Run workspace scripts (pre+setup for first time, select for existing)
|
|
463
|
+
const scriptResult = await runWorkspaceScripts({
|
|
464
|
+
projectName: state.currentProject!,
|
|
465
|
+
workspacePath: workspace.path,
|
|
466
|
+
workspaceName: workspace.name,
|
|
467
|
+
repository: config.repository,
|
|
468
|
+
interactive: false, // TUI context - scripts can't prompt for input
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
if (!scriptResult.success) {
|
|
472
|
+
flow.showMessage({
|
|
473
|
+
title: 'Script Failed',
|
|
474
|
+
message: `Workspace scripts failed during ${scriptResult.phase} phase: ${scriptResult.error}`,
|
|
475
|
+
variant: 'error',
|
|
476
|
+
});
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
430
480
|
const session = await createSession(sessionName, workspace.path);
|
|
431
481
|
// Attach to newly created session
|
|
432
482
|
dispatch({ type: 'SET_ATTACHED_SESSION', session });
|
|
433
483
|
dispatch({ type: 'SET_VIEW', view: 'terminal' });
|
|
434
484
|
} catch (err) {
|
|
435
|
-
|
|
485
|
+
flow.showMessage({
|
|
486
|
+
title: 'Session Failed',
|
|
487
|
+
message: err instanceof Error ? err.message : 'Failed to create session',
|
|
488
|
+
variant: 'error',
|
|
489
|
+
});
|
|
436
490
|
}
|
|
437
491
|
},
|
|
438
492
|
});
|
|
@@ -492,7 +546,33 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
492
546
|
onConfirm: async () => {
|
|
493
547
|
if (!state.currentProject) return;
|
|
494
548
|
flow.showLoading({ title: 'Deleting', message: 'Removing workspace...' });
|
|
495
|
-
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
const result = await deleteWorkspaceCore(state.currentProject, workspace.name, {
|
|
552
|
+
nonInteractive: true, // TUI is non-interactive for scripts
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
if (!result.success) {
|
|
556
|
+
console.error('[tui] Failed to delete workspace:', result.error);
|
|
557
|
+
flow.close();
|
|
558
|
+
flow.showMessage({
|
|
559
|
+
title: 'Delete Failed',
|
|
560
|
+
message: result.error ?? `Failed to delete workspace "${workspace.name}".`,
|
|
561
|
+
variant: 'error',
|
|
562
|
+
});
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
} catch (error) {
|
|
566
|
+
console.error('[tui] Failed to delete workspace:', error);
|
|
567
|
+
flow.close();
|
|
568
|
+
flow.showMessage({
|
|
569
|
+
title: 'Delete Failed',
|
|
570
|
+
message: error instanceof Error ? error.message : `Failed to delete workspace "${workspace.name}".`,
|
|
571
|
+
variant: 'error',
|
|
572
|
+
});
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
|
|
496
576
|
flow.close();
|
|
497
577
|
await refreshWorkspaces();
|
|
498
578
|
},
|
|
@@ -556,6 +636,25 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
556
636
|
writeFileSync(join(promptDir, 'issue.md'), markdown, 'utf-8');
|
|
557
637
|
}
|
|
558
638
|
|
|
639
|
+
// Run workspace scripts (pre+setup for new workspace)
|
|
640
|
+
const scriptResult = await runWorkspaceScripts({
|
|
641
|
+
projectName: state.currentProject,
|
|
642
|
+
workspacePath,
|
|
643
|
+
workspaceName,
|
|
644
|
+
repository: config.repository,
|
|
645
|
+
interactive: false, // TUI context - scripts can't prompt for input
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
if (!scriptResult.success) {
|
|
649
|
+
setWorkspaceFlow({ type: 'closed' });
|
|
650
|
+
flow.showMessage({
|
|
651
|
+
title: 'Script Failed',
|
|
652
|
+
message: `Workspace scripts failed during ${scriptResult.phase} phase: ${scriptResult.error}`,
|
|
653
|
+
variant: 'error',
|
|
654
|
+
});
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
|
|
559
658
|
setWorkspaceFlow({ type: 'closed' });
|
|
560
659
|
await refreshWorkspaces();
|
|
561
660
|
|
|
@@ -566,7 +665,11 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
566
665
|
dispatch({ type: 'SET_VIEW', view: 'terminal' });
|
|
567
666
|
} catch (err) {
|
|
568
667
|
setWorkspaceFlow({ type: 'closed' });
|
|
569
|
-
|
|
668
|
+
flow.showMessage({
|
|
669
|
+
title: 'Workspace Failed',
|
|
670
|
+
message: err instanceof Error ? err.message : 'Failed to create workspace',
|
|
671
|
+
variant: 'error',
|
|
672
|
+
});
|
|
570
673
|
}
|
|
571
674
|
}, [state.currentProject, refreshWorkspaces]);
|
|
572
675
|
|
|
@@ -639,7 +742,7 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
639
742
|
setWorkspaceFlow({ type: 'closed' });
|
|
640
743
|
}
|
|
641
744
|
} else if (source === 'manual') {
|
|
642
|
-
setWorkspaceFlow({ type: 'manual-input', inputValue: '', error: null });
|
|
745
|
+
setWorkspaceFlow({ type: 'manual-name-input', inputValue: '', error: null });
|
|
643
746
|
}
|
|
644
747
|
}, [state.currentProject, flow]);
|
|
645
748
|
|
|
@@ -655,17 +758,29 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
655
758
|
await createWorkspaceAndOpenSession(workspaceName, workspaceName, false, issue);
|
|
656
759
|
}, [createWorkspaceAndOpenSession]);
|
|
657
760
|
|
|
658
|
-
// Handle manual name submission
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
761
|
+
// Handle manual workspace name submission (advances to branch input)
|
|
762
|
+
const handleManualNameSubmit = useCallback((name: string) => {
|
|
763
|
+
const trimmedName = name.trim();
|
|
764
|
+
if (!trimmedName) {
|
|
765
|
+
setWorkspaceFlow(prev => prev.type === 'manual-name-input' ? { ...prev, error: 'Workspace name is required' } : prev);
|
|
662
766
|
return;
|
|
663
767
|
}
|
|
664
|
-
if (!isValidWorkspaceName(
|
|
665
|
-
setWorkspaceFlow(prev => prev.type === 'manual-input' ? { ...prev, error: 'Use only letters, numbers, hyphens, underscores' } : prev);
|
|
768
|
+
if (!isValidWorkspaceName(trimmedName)) {
|
|
769
|
+
setWorkspaceFlow(prev => prev.type === 'manual-name-input' ? { ...prev, error: 'Use only letters, numbers, hyphens, underscores' } : prev);
|
|
666
770
|
return;
|
|
667
771
|
}
|
|
668
|
-
|
|
772
|
+
// Advance to branch input step, pre-fill with workspace name
|
|
773
|
+
setWorkspaceFlow({ type: 'manual-branch-input', workspaceName: trimmedName, inputValue: trimmedName });
|
|
774
|
+
}, []);
|
|
775
|
+
|
|
776
|
+
// Handle manual branch name submission (creates the workspace)
|
|
777
|
+
const handleManualBranchSubmit = useCallback(async (workspaceName: string, branchName: string) => {
|
|
778
|
+
const finalBranch = branchName.trim() || workspaceName;
|
|
779
|
+
if (!isValidBranchName(finalBranch)) {
|
|
780
|
+
setWorkspaceFlow(prev => prev.type === 'manual-branch-input' ? { ...prev, error: 'Invalid branch name (no spaces, .., or special chars like : ? * [ \\ ~)' } : prev);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
await createWorkspaceAndOpenSession(workspaceName, finalBranch, false);
|
|
669
784
|
}, [createWorkspaceAndOpenSession]);
|
|
670
785
|
|
|
671
786
|
// Main handler to start new workspace flow
|
|
@@ -1155,9 +1270,9 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
1155
1270
|
return;
|
|
1156
1271
|
}
|
|
1157
1272
|
|
|
1158
|
-
if (workspaceFlow.type === 'manual-input') {
|
|
1273
|
+
if (workspaceFlow.type === 'manual-name-input') {
|
|
1159
1274
|
if (key.name === 'return') {
|
|
1160
|
-
|
|
1275
|
+
handleManualNameSubmit(workspaceFlow.inputValue);
|
|
1161
1276
|
} else if (key.name === 'backspace') {
|
|
1162
1277
|
setWorkspaceFlow({
|
|
1163
1278
|
...workspaceFlow,
|
|
@@ -1174,6 +1289,23 @@ function App({ relayConfig, onQuit }: AppProps) {
|
|
|
1174
1289
|
return;
|
|
1175
1290
|
}
|
|
1176
1291
|
|
|
1292
|
+
if (workspaceFlow.type === 'manual-branch-input') {
|
|
1293
|
+
if (key.name === 'return') {
|
|
1294
|
+
await handleManualBranchSubmit(workspaceFlow.workspaceName, workspaceFlow.inputValue);
|
|
1295
|
+
} else if (key.name === 'backspace') {
|
|
1296
|
+
setWorkspaceFlow({
|
|
1297
|
+
...workspaceFlow,
|
|
1298
|
+
inputValue: workspaceFlow.inputValue.slice(0, -1),
|
|
1299
|
+
});
|
|
1300
|
+
} else if (key.raw && key.raw.length === 1 && !key.ctrl && !key.meta) {
|
|
1301
|
+
setWorkspaceFlow({
|
|
1302
|
+
...workspaceFlow,
|
|
1303
|
+
inputValue: workspaceFlow.inputValue + key.raw,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1177
1309
|
// For loading/creating states, just wait (escape to cancel handled above)
|
|
1178
1310
|
return;
|
|
1179
1311
|
}
|
|
@@ -1484,8 +1616,10 @@ function WorkspaceFlowModal({ flow }: { flow: WorkspaceFlowState }) {
|
|
|
1484
1616
|
// Calculate modal height based on content:
|
|
1485
1617
|
// - source-select: title + spacer + (options * 2 lines each) + (spacers between) + spacer + hint + border/padding
|
|
1486
1618
|
// - branch/linear-select: title + items (scrollable) + hint + border/padding
|
|
1487
|
-
// - manual-input: title + label + input box + error? + hint + border/padding
|
|
1488
|
-
|
|
1619
|
+
// - manual-name-input: title + label + input box + error? + hint + border/padding
|
|
1620
|
+
// - manual-branch-input: title + label + input box + workspace display + hint + border/padding
|
|
1621
|
+
const modalHeight = flow.type === 'manual-name-input' ? 10 :
|
|
1622
|
+
flow.type === 'manual-branch-input' ? 12 :
|
|
1489
1623
|
flow.type === 'loading' || flow.type === 'creating' ? 6 :
|
|
1490
1624
|
flow.type === 'source-select' ? 6 + flow.options.length * 3 :
|
|
1491
1625
|
flow.type === 'branch-select' ? Math.min(16, 6 + flow.branches.length) :
|
|
@@ -1584,10 +1718,10 @@ function WorkspaceFlowModal({ flow }: { flow: WorkspaceFlowState }) {
|
|
|
1584
1718
|
</>
|
|
1585
1719
|
)}
|
|
1586
1720
|
|
|
1587
|
-
{/* Manual input */}
|
|
1588
|
-
{flow.type === 'manual-input' && (
|
|
1721
|
+
{/* Manual workspace name input */}
|
|
1722
|
+
{flow.type === 'manual-name-input' && (
|
|
1589
1723
|
<>
|
|
1590
|
-
<text fg={COLORS.title} height={1}>New Workspace</text>
|
|
1724
|
+
<text fg={COLORS.title} height={1}>New Workspace (1/2)</text>
|
|
1591
1725
|
<text fg={COLORS.text} height={1} marginTop={1}>Enter workspace name:</text>
|
|
1592
1726
|
<box
|
|
1593
1727
|
marginTop={1}
|
|
@@ -1599,6 +1733,25 @@ function WorkspaceFlowModal({ flow }: { flow: WorkspaceFlowState }) {
|
|
|
1599
1733
|
<text fg={COLORS.text} height={1}>{flow.inputValue || ' '}_</text>
|
|
1600
1734
|
</box>
|
|
1601
1735
|
{flow.error && <text fg={COLORS.error} height={1} marginTop={1}>{flow.error}</text>}
|
|
1736
|
+
<text fg={COLORS.textDim} height={1} marginTop={1}>[Enter] Next [Esc] Cancel</text>
|
|
1737
|
+
</>
|
|
1738
|
+
)}
|
|
1739
|
+
|
|
1740
|
+
{/* Manual branch name input */}
|
|
1741
|
+
{flow.type === 'manual-branch-input' && (
|
|
1742
|
+
<>
|
|
1743
|
+
<text fg={COLORS.title} height={1}>New Workspace (2/2)</text>
|
|
1744
|
+
<text fg={COLORS.text} height={1} marginTop={1}>Enter branch name (slashes allowed):</text>
|
|
1745
|
+
<box
|
|
1746
|
+
marginTop={1}
|
|
1747
|
+
borderStyle="rounded"
|
|
1748
|
+
borderColor={COLORS.border}
|
|
1749
|
+
padding={0}
|
|
1750
|
+
width="100%"
|
|
1751
|
+
>
|
|
1752
|
+
<text fg={COLORS.text} height={1}>{flow.inputValue || ' '}_</text>
|
|
1753
|
+
</box>
|
|
1754
|
+
<text fg={COLORS.textDim} height={1} marginTop={1}>Workspace: {flow.workspaceName}</text>
|
|
1602
1755
|
<text fg={COLORS.textDim} height={1} marginTop={1}>[Enter] Create [Esc] Cancel</text>
|
|
1603
1756
|
</>
|
|
1604
1757
|
)}
|