feat: enhance team provisioning prompts and improve dashboard interactivity
- Updated the provisioning prompts in TeamProvisioningService to include project name alongside team and lead information, enhancing clarity for non-interactive CLI sessions. - Refactored the RepositoryCard component in DashboardView to replace button with a div for improved accessibility and keyboard navigation, allowing users to open project paths more intuitively. - Modified ChangeReviewDialog and ContinuousScrollView components to track discard actions using a record of counters per file, improving state management during file reviews.
This commit is contained in:
parent
0d0786602f
commit
50efe267e4
4 changed files with 22 additions and 12 deletions
|
|
@ -417,8 +417,11 @@ function buildProvisioningPrompt(request: TeamCreateRequest): string {
|
||||||
const leadName =
|
const leadName =
|
||||||
request.members.find((m) => m.role?.toLowerCase().includes('lead'))?.name || 'team-lead';
|
request.members.find((m) => m.role?.toLowerCase().includes('lead'))?.name || 'team-lead';
|
||||||
const teamCtlOps = buildTeamCtlOpsInstructions(request.teamName, leadName);
|
const teamCtlOps = buildTeamCtlOpsInstructions(request.teamName, leadName);
|
||||||
|
const projectName = path.basename(request.cwd);
|
||||||
|
|
||||||
return `You are running in a non-interactive CLI session. Do not ask questions. Do everything in a single turn.
|
return `Team Start [Agent Team: "${request.teamName}" | Project: "${projectName}" | Lead: "${leadName}"]
|
||||||
|
|
||||||
|
You are running in a non-interactive CLI session. Do not ask questions. Do everything in a single turn.
|
||||||
You are "${leadName}", the team lead.
|
You are "${leadName}", the team lead.
|
||||||
|
|
||||||
Goal: Provision a Claude Code agent team with live teammates.
|
Goal: Provision a Claude Code agent team with live teammates.
|
||||||
|
|
@ -494,6 +497,7 @@ function buildLaunchPrompt(
|
||||||
|
|
||||||
const leadName = members.find((m) => m.role?.toLowerCase().includes('lead'))?.name || 'team-lead';
|
const leadName = members.find((m) => m.role?.toLowerCase().includes('lead'))?.name || 'team-lead';
|
||||||
const teamCtlOps = buildTeamCtlOpsInstructions(request.teamName, leadName);
|
const teamCtlOps = buildTeamCtlOpsInstructions(request.teamName, leadName);
|
||||||
|
const projectName = path.basename(request.cwd);
|
||||||
|
|
||||||
// Build per-member task snapshots to include in each teammate's spawn prompt
|
// Build per-member task snapshots to include in each teammate's spawn prompt
|
||||||
const memberTaskBlocks = new Map<string, string>();
|
const memberTaskBlocks = new Map<string, string>();
|
||||||
|
|
@ -522,7 +526,9 @@ function buildLaunchPrompt(
|
||||||
})
|
})
|
||||||
.join('\n\n');
|
.join('\n\n');
|
||||||
|
|
||||||
return `You are running in a non-interactive CLI session. Do not ask questions. Do everything in a single turn.
|
return `Team Start [Agent Team: "${request.teamName}" | Project: "${projectName}" | Lead: "${leadName}"]
|
||||||
|
|
||||||
|
You are running in a non-interactive CLI session. Do not ask questions. Do everything in a single turn.
|
||||||
You are "${leadName}", the team lead.
|
You are "${leadName}", the team lead.
|
||||||
|
|
||||||
Goal: Reconnect with existing team "${request.teamName}" and resume pending work.
|
Goal: Reconnect with existing team "${request.teamName}" and resume pending work.
|
||||||
|
|
|
||||||
|
|
@ -180,15 +180,19 @@ const RepositoryCard = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Project path - monospace, muted, clickable to open in file manager */}
|
{/* Project path - monospace, muted, clickable to open in file manager */}
|
||||||
<button
|
<div
|
||||||
type="button"
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
onClick={handleOpenPath}
|
onClick={handleOpenPath}
|
||||||
className="flex w-full min-w-0 items-center gap-1 truncate text-left font-mono text-[10px] text-text-muted transition-colors hover:text-text-secondary"
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') handleOpenPath(e as unknown as React.MouseEvent);
|
||||||
|
}}
|
||||||
|
className="flex w-full min-w-0 cursor-pointer items-center gap-1 truncate text-left font-mono text-[10px] text-text-muted transition-colors hover:text-text-secondary"
|
||||||
title={`Open in file manager: ${projectPath}`}
|
title={`Open in file manager: ${projectPath}`}
|
||||||
>
|
>
|
||||||
<FolderOpen className="size-3 shrink-0" />
|
<FolderOpen className="size-3 shrink-0" />
|
||||||
<span className="truncate">{formattedPath}</span>
|
<span className="truncate">{formattedPath}</span>
|
||||||
</button>
|
</div>
|
||||||
|
|
||||||
{/* Git branch / worktree info */}
|
{/* Git branch / worktree info */}
|
||||||
{mainBranch ? (
|
{mainBranch ? (
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ export const ChangeReviewDialog = ({
|
||||||
const [activeFilePath, setActiveFilePath] = useState<string | null>(null);
|
const [activeFilePath, setActiveFilePath] = useState<string | null>(null);
|
||||||
const [autoViewed, setAutoViewed] = useState(true);
|
const [autoViewed, setAutoViewed] = useState(true);
|
||||||
const [timelineOpen, setTimelineOpen] = useState(false);
|
const [timelineOpen, setTimelineOpen] = useState(false);
|
||||||
const [discardCounter, setDiscardCounter] = useState(0);
|
const [discardCounters, setDiscardCounters] = useState<Record<string, number>>({});
|
||||||
|
|
||||||
// EditorView map for all visible file editors
|
// EditorView map for all visible file editors
|
||||||
const editorViewMapRef = useRef(new Map<string, EditorView>());
|
const editorViewMapRef = useRef(new Map<string, EditorView>());
|
||||||
|
|
@ -213,7 +213,7 @@ export const ChangeReviewDialog = ({
|
||||||
const handleDiscardFile = useCallback(
|
const handleDiscardFile = useCallback(
|
||||||
(filePath: string) => {
|
(filePath: string) => {
|
||||||
discardFileEdits(filePath);
|
discardFileEdits(filePath);
|
||||||
setDiscardCounter((c) => c + 1);
|
setDiscardCounters((prev) => ({ ...prev, [filePath]: (prev[filePath] ?? 0) + 1 }));
|
||||||
},
|
},
|
||||||
[discardFileEdits]
|
[discardFileEdits]
|
||||||
);
|
);
|
||||||
|
|
@ -544,7 +544,7 @@ export const ChangeReviewDialog = ({
|
||||||
collapseUnchanged={collapseUnchanged}
|
collapseUnchanged={collapseUnchanged}
|
||||||
applying={applying}
|
applying={applying}
|
||||||
autoViewed={autoViewed}
|
autoViewed={autoViewed}
|
||||||
discardCounter={discardCounter}
|
discardCounters={discardCounters}
|
||||||
onHunkAccepted={handleHunkAccepted}
|
onHunkAccepted={handleHunkAccepted}
|
||||||
onHunkRejected={handleHunkRejected}
|
onHunkRejected={handleHunkRejected}
|
||||||
onFullyViewed={handleFullyViewed}
|
onFullyViewed={handleFullyViewed}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ interface ContinuousScrollViewProps {
|
||||||
collapseUnchanged: boolean;
|
collapseUnchanged: boolean;
|
||||||
applying: boolean;
|
applying: boolean;
|
||||||
autoViewed: boolean;
|
autoViewed: boolean;
|
||||||
discardCounter: number;
|
discardCounters: Record<string, number>;
|
||||||
onHunkAccepted: (filePath: string, hunkIndex: number) => void;
|
onHunkAccepted: (filePath: string, hunkIndex: number) => void;
|
||||||
onHunkRejected: (filePath: string, hunkIndex: number) => void;
|
onHunkRejected: (filePath: string, hunkIndex: number) => void;
|
||||||
onFullyViewed: (filePath: string) => void;
|
onFullyViewed: (filePath: string) => void;
|
||||||
|
|
@ -54,7 +54,7 @@ export const ContinuousScrollView = ({
|
||||||
collapseUnchanged,
|
collapseUnchanged,
|
||||||
applying,
|
applying,
|
||||||
autoViewed,
|
autoViewed,
|
||||||
discardCounter,
|
discardCounters,
|
||||||
onHunkAccepted,
|
onHunkAccepted,
|
||||||
onHunkRejected,
|
onHunkRejected,
|
||||||
onFullyViewed,
|
onFullyViewed,
|
||||||
|
|
@ -198,7 +198,7 @@ export const ContinuousScrollView = ({
|
||||||
onFullyViewed={onFullyViewed}
|
onFullyViewed={onFullyViewed}
|
||||||
onContentChanged={onContentChanged}
|
onContentChanged={onContentChanged}
|
||||||
onEditorViewReady={handleEditorViewReady}
|
onEditorViewReady={handleEditorViewReady}
|
||||||
discardCounter={discardCounter}
|
discardCounter={discardCounters[filePath] ?? 0}
|
||||||
autoViewed={autoViewed}
|
autoViewed={autoViewed}
|
||||||
isViewed={isViewed}
|
isViewed={isViewed}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue