Skip to content

Commit 4f15f24

Browse files
committed
fix(ai-native): simplify initial task loading state
1 parent ff1eef9 commit 4f15f24

4 files changed

Lines changed: 4 additions & 58 deletions

File tree

packages/ai-native/__test__/browser/acp-queued-turns.test.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ function renderQueue(
6666
onImmediateSend?: jest.Mock;
6767
onEditorReady?: jest.Mock;
6868
onOpenCapacitySettings?: jest.Mock;
69-
onCancelInitialStart?: jest.Mock;
7069
} = {},
7170
) {
7271
const snapshot = { ...baseSnapshot, ...overrides };
@@ -101,34 +100,21 @@ function renderQueue(
101100
onImmediateSend={handlers.onImmediateSend}
102101
onEditorReady={handlers.onEditorReady}
103102
onOpenCapacitySettings={overrides.onOpenCapacitySettings}
104-
onCancelInitialStart={overrides.onCancelInitialStart}
105103
/>,
106104
);
107105
});
108106
return handlers;
109107
}
110108

111-
it('shows cancellable first-launch progress at the 300ms and 8s thresholds', () => {
112-
jest.useFakeTimers();
113-
const onCancelInitialStart = jest.fn();
109+
it('shows a loading status while the first Task is launching', () => {
114110
renderQueue({
115111
activeSessionId: undefined,
116112
entries: [],
117113
initialStartPending: true,
118-
onCancelInitialStart,
119114
});
120115

121-
expect(query('[data-testid="acp-task-launch-status"]')?.textContent).toContain('Preparing task');
122-
expect(query('[data-testid="acp-task-launch-status"]')?.textContent).not.toContain('Starting task');
123-
click('[data-testid="acp-task-launch-cancel"]');
124-
expect(onCancelInitialStart).toHaveBeenCalledTimes(1);
125-
126-
act(() => jest.advanceTimersByTime(300));
127116
expect(query('[data-testid="acp-task-launch-status"]')?.textContent).toContain('Starting task');
128-
129-
act(() => jest.advanceTimersByTime(7700));
130-
expect(query('[data-testid="acp-task-launch-status"]')?.textContent).toContain('taking longer than usual');
131-
jest.useRealTimers();
117+
expect(query('[data-testid="acp-task-launch-status"] button')).toBeNull();
132118
});
133119

134120
it('renders paused state and resumes', () => {

packages/ai-native/docs/adr/0002-maintain-bounded-acp-standby-capacity.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Foreground Task Launch remains cancellable while the Agent is being prepared. Ca
88

99
A Task Launch commits only when ACP has accepted the first Prompt and established its request stream. Session creation before that point is temporary: failure or cancellation releases it and preserves the Draft, while errors after acceptance belong to the now-durable Agent Task. This prevents failed retries from creating orphan Sessions, duplicate Tasks, or duplicate first Prompts.
1010

11-
While launch is in progress, Agentic Layout freezes the submitted Draft configuration and Prompt, presents a single user-facing task-starting state, and offers cancellation as the only foreground action. It avoids exposing warmup or process-initialization phases; cancellation restores the editable Draft and input focus, while a slow launch may add non-technical explanatory text without changing the committed submission snapshot.
11+
While launch is in progress, Agentic Layout freezes the submitted Draft configuration and Prompt and presents a single user-facing task-starting state without foreground actions. It avoids exposing warmup or process-initialization phases; internal cancellation still cleans up an abandoned launch without changing the committed submission snapshot.
1212

1313
Project Addition alone does not change the standby target or start an ACP process. Task Draft Agent or Workspace changes are debounced and replace one target rather than accumulating warm processes; foreground submission flushes that debounce and immediately uses the latest Draft configuration.
1414

packages/ai-native/src/browser/chat/AcpQueuedTurns.tsx

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export interface AcpQueuedTurnsProps {
3131
onImmediateSend(id: string): void;
3232
onEditorReady(handle: ChatInputHandle | null): void;
3333
onOpenCapacitySettings?(): void;
34-
onCancelInitialStart?(): void;
3534
}
3635

3736
export function getAcpQueuedTurnPreview(message: string): string {
@@ -80,41 +79,11 @@ export const AcpQueuedTurns = ({
8079
onImmediateSend,
8180
onEditorReady,
8281
onOpenCapacitySettings,
83-
onCancelInitialStart,
8482
}: AcpQueuedTurnsProps) => {
85-
const [initialStartStage, setInitialStartStage] = React.useState<0 | 1 | 2>(0);
86-
87-
React.useEffect(() => {
88-
if (!snapshot.initialStartPending) {
89-
setInitialStartStage(0);
90-
return undefined;
91-
}
92-
const startingTimer = setTimeout(() => setInitialStartStage(1), 300);
93-
const slowTimer = setTimeout(() => setInitialStartStage(2), 8000);
94-
return () => {
95-
clearTimeout(startingTimer);
96-
clearTimeout(slowTimer);
97-
};
98-
}, [snapshot.initialStartPending]);
99-
10083
if (snapshot.initialStartPending) {
10184
return (
10285
<div className={styles.queued_turns_status} data-testid='acp-task-launch-status' role='status'>
103-
<span>
104-
{initialStartStage === 0
105-
? localize('aiNative.chat.acp.preparingTask', 'Preparing task…')
106-
: initialStartStage === 1
107-
? localize('aiNative.chat.acp.startingTask', 'Starting task…')
108-
: localize(
109-
'aiNative.chat.acp.slowTaskStart',
110-
'Task startup is taking longer than usual. You can continue waiting or cancel.',
111-
)}
112-
</span>
113-
{onCancelInitialStart && (
114-
<button data-testid='acp-task-launch-cancel' onClick={onCancelInitialStart} type='button'>
115-
{localize('aiNative.chat.acp.cancelTaskStart', 'Cancel')}
116-
</button>
117-
)}
86+
<span>{localize('aiNative.chat.acp.startingTask', 'Starting task…')}</span>
11887
</div>
11988
);
12089
}

packages/ai-native/src/browser/chat/chat.view.acp.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,14 +1465,6 @@ export const AIChatViewACPContent = () => {
14651465
void queuedTurns.resume();
14661466
}, [aiChatService, queuedTurns]);
14671467

1468-
const handleCancelInitialStart = React.useCallback(() => {
1469-
void queuedTurns.cancelInitialStart().then((result) => {
1470-
if (result.accepted) {
1471-
mainInputHandleRef.current?.focus?.();
1472-
}
1473-
});
1474-
}, [queuedTurns]);
1475-
14761468
const handleCloseChatView = React.useCallback(() => {
14771469
const draft = chatInputRegistry.preserveActiveDraft() || aiChatService.getInputDraft();
14781470
aiChatService.updateInputDraft(draft);
@@ -1933,7 +1925,6 @@ export const AIChatViewACPContent = () => {
19331925
AINativeSettingSectionsId.AcpThreadPoolSize,
19341926
)
19351927
}
1936-
onCancelInitialStart={handleCancelInitialStart}
19371928
/>
19381929
<div className={styles.header_operate}>
19391930
{/* 定制需求。不需要透出shortcut*/}

0 commit comments

Comments
 (0)