@qwen-code/web-shell 0.24.3 → 0.24.4-nightly.20260923.d0cd622a68

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.
Files changed (54) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +85 -1
  3. package/dist/daemon-react-sdk.js +1 -1
  4. package/dist/index.js +49318 -47393
  5. package/dist/sw.js +1 -1
  6. package/dist/{toolNames-DQad2xSu.js → toolNames-CaonquFc.js} +5677 -5279
  7. package/dist/transcript.js +10484 -10284
  8. package/dist/types/App.d.ts +9 -1
  9. package/dist/types/adapters/types.d.ts +4 -1
  10. package/dist/types/components/ChatPane.d.ts +3 -1
  11. package/dist/types/components/ConversationSearch.d.ts +18 -0
  12. package/dist/types/components/GlobalTurnNavigation.d.ts +3 -1
  13. package/dist/types/components/MessageList.d.ts +10 -2
  14. package/dist/types/components/SplitView.d.ts +3 -1
  15. package/dist/types/components/StandaloneAuth.d.ts +2 -1
  16. package/dist/types/components/WorkspaceSessionProvider.d.ts +2 -0
  17. package/dist/types/components/artifacts/ArtifactPanel.d.ts +7 -1
  18. package/dist/types/components/artifacts/SideTaskPanel.d.ts +5 -1
  19. package/dist/types/components/artifacts/TrajectoryOverview.d.ts +39 -0
  20. package/dist/types/components/channels/channel-editor-state.d.ts +9 -3
  21. package/dist/types/components/conversation-search-i18n.d.ts +6 -0
  22. package/dist/types/components/local-control-api.d.ts +3 -1
  23. package/dist/types/components/messages/AuthMessage.d.ts +2 -1
  24. package/dist/types/components/messages/ModelManagementSection.d.ts +3 -2
  25. package/dist/types/components/messages/PlanExecutionView.d.ts +14 -66
  26. package/dist/types/components/messages/SettingsMessage.d.ts +2 -2
  27. package/dist/types/components/messages/ToolGroup.d.ts +0 -1
  28. package/dist/types/components/messages/taskExecutionIndex.d.ts +80 -0
  29. package/dist/types/components/workflow/SessionWorkflowCockpit.d.ts +8 -1
  30. package/dist/types/components/workflow/SessionWorkflowInspector.d.ts +8 -1
  31. package/dist/types/components/workflow/session-workflow-model.d.ts +9 -1
  32. package/dist/types/config/pairing.d.ts +9 -0
  33. package/dist/types/config/remote-workspace-add.d.ts +25 -0
  34. package/dist/types/customization.d.ts +6 -0
  35. package/dist/types/daemon/session/session-context.d.ts +11 -0
  36. package/dist/types/daemon/session/transcript-page-table.d.ts +1 -1
  37. package/dist/types/daemon/session/turn-navigation-store.d.ts +32 -0
  38. package/dist/types/hooks/useMessageNavigation.d.ts +12 -0
  39. package/dist/types/hooks/useQueuedPrompts.d.ts +4 -1
  40. package/dist/types/hooks/useTranscriptViewport.d.ts +3 -1
  41. package/dist/types/index.d.ts +10 -0
  42. package/dist/types/modelManagement.d.ts +16 -0
  43. package/dist/types/navigation.d.ts +37 -0
  44. package/dist/types/trajectory/buildTimeline.d.ts +48 -0
  45. package/dist/types/trajectory/timelineRange.d.ts +26 -0
  46. package/dist/types/trajectory/transcriptPageLoader.d.ts +4 -2
  47. package/dist/types/trajectory/types.d.ts +3 -3
  48. package/dist/types/trajectory/useTrajectoryWindow.d.ts +55 -17
  49. package/dist/types/utils/navigationUrl.d.ts +21 -0
  50. package/dist/types/utils/popoverRoom.d.ts +22 -0
  51. package/dist/types/utils/sessionPath.d.ts +1 -0
  52. package/dist/types/utils/unifiedDiff.d.ts +1 -0
  53. package/dist/types/utils/workspace.d.ts +3 -2
  54. package/package.json +19 -20
@@ -1,4 +1,6 @@
1
+ import { type WebShellModelManagementOptions } from './modelManagement';
1
2
  import './styles/globals.css';
3
+ import { type WebShellMessageNavigationRequest, type WebShellMessageNavigationResult } from './hooks/useMessageNavigation';
2
4
  import { type DaemonProductSessionContext, type DaemonStreamingState } from '@qwen-code/web-shell/daemon-react-sdk';
3
5
  import type { DaemonAgentTrace, DaemonSessionAgentTaskStatus, DaemonTranscriptBlock, DaemonSessionMonitorTaskStatus, DaemonSessionTaskWithWorkflowStatus, DaemonWorkspaceCapability } from '@qwen-code/sdk/daemon';
4
6
  import { type ComposerToolbarAction } from './components/ChatEditor';
@@ -64,6 +66,8 @@ export type SessionChangeEvent = {
64
66
  error?: Error;
65
67
  };
66
68
  export interface WebShellApi {
69
+ /** 按持久化记录 ID 定位当前会话消息,包含尚未渲染的历史。宿主先切换会话。 */
70
+ navigateToMessage: (request: WebShellMessageNavigationRequest) => Promise<WebShellMessageNavigationResult>;
67
71
  /** Open the in-window split view, matching the built-in sidebar button. */
68
72
  openSplitView: () => void;
69
73
  /** Open the Session Overview panel, matching the built-in sidebar button. */
@@ -94,6 +98,8 @@ export type WebShellSlashCommandHandler = (command: WebShellSlashCommand) => boo
94
98
  export interface WebShellProps {
95
99
  /** Native settings-page presentation. Does not restrict commands or daemon access. */
96
100
  settings?: WebShellSettingsOptions;
101
+ /** Model add/delete interactions across WebShell. Not a backend permission policy. */
102
+ modelManagement?: WebShellModelManagementOptions;
97
103
  /** Host-specific label for the Ask User Question free-text choice. */
98
104
  askUserFreeTextLabel?: string;
99
105
  /** Called whenever the attached daemon session or workspace changes. */
@@ -362,6 +368,8 @@ export interface WebShellProps {
362
368
  markdownTableMode?: MarkdownTableMode;
363
369
  /** Enable virtual scrolling only when rendered transcript rows exceed this threshold. Defaults to 200. */
364
370
  virtualScrollThreshold?: number;
371
+ /** 会话消息数超过此阈值时显示搜索入口,默认 10。 */
372
+ conversationSearchThreshold?: number;
365
373
  /** Custom Markdown behavior for assistant content only. */
366
374
  markdown?: WebShellMarkdownCustomization;
367
375
  /**
@@ -427,4 +435,4 @@ interface SideTaskCatalogState {
427
435
  export declare function mergeSideTaskCatalog(catalog: SideTaskCatalogState, parentSessionId: string, listedItems: SideTaskListItem[], optimisticIds: ReadonlySet<string>): SideTaskCatalogState;
428
436
  export declare function getEnvironmentAgentTasks(messages: readonly Message[], sessionTasks: readonly DaemonSessionTaskWithWorkflowStatus[]): EnvironmentAgentTask[];
429
437
  export declare function mergeAgentTrace(liveAgents: readonly EnvironmentAgentTask[], trace: DaemonAgentTrace | undefined, now?: number): EnvironmentAgentTask[];
430
- export declare function App({ askUserFreeTextLabel, onSessionIdChange, onSessionInfoChange, onSessionCreated, theme: providedTheme, onThemeChange, onThemeResolved, language: providedLanguage, onLanguageChange, onLanguageResolved, brand: providedBrand, onBrandResolved, className: externalClassName, style: externalStyle, shadowDom, onConnectionChange, onStreamingStateChange, onError, onBugReport, hiddenSlashCommands, slashCommandCategoryOrder, onSlashCommand, builtinAtProviders, atProviders, composerTagIcons, fileUploadEnabled, fileUploadDirectory, artifact, fileDropAction, renderToolHeaderExtra, renderWelcomeHeader, renderWelcomeFooter, mobileWelcomeFooterMiddle, parseUserMessageContent, renderUserMessageContent, renderComposerTag, renderComposerTagTooltip, onComposerTagClick, renderAssistantTurnFooter, assistantFeedback, getAssistantSourcesIcon, sourceReferences, renderComposerToolbarStart, renderComposerToolbarEnd, renderComposerToolbarRight, renderComposerHeader, renderComposerFooter, renderChatHeader, renderFooter, bottomStatusItems, chatMaxWidth, sidebar, settings: settingsPresentation, header, rightPanel, environmentPanel, splitSessionIds: externalSplitSessionIds, onSplitSessionIdsChange, renderPaneHeaderActions, onRightPanelOpen, onFileReviewOpen, onWorkspaceFileOpen, onInsightReportOpen, onContextUsageOpen, messageTurnOutputs, shellRef, composerToolbarActions, mainModelFilter, compactComposerOverlays, autoSubmitSlashCommands, additionalSlashCommands, contextUsageAlwaysVisible, userMessageEditing, onUserMessageEditRequest, cycleModeOnTab, sessionSourceType, composerToolbarAdditionalActions, composerPlaceholders, compactThinking, hostOwnsEditDiffPreview, collapseCompletedTurns, markdownTableMode, virtualScrollThreshold, markdown, loadingPhrases, onAgentTasksChange, onTranscriptChange, onSessionArtifactsChange, onToast, composerRef, onComposerReady, composerInput, composerInputVersion, onSessionChange, onAssistantTurnSettled, prepareSubmit, onSubmitBefore, restartSseOnPrompt, historyPageSize, initialSelectedWorkspaceCwd, lockedWorkspaceCwd, lockedWorkspaceCapability, }?: AppProps): import("react/jsx-runtime").JSX.Element;
438
+ export declare function App({ askUserFreeTextLabel, onSessionIdChange, onSessionInfoChange, onSessionCreated, theme: providedTheme, onThemeChange, onThemeResolved, language: providedLanguage, onLanguageChange, onLanguageResolved, brand: providedBrand, onBrandResolved, className: externalClassName, style: externalStyle, shadowDom, onConnectionChange, onStreamingStateChange, onError, onBugReport, hiddenSlashCommands, slashCommandCategoryOrder, onSlashCommand, builtinAtProviders, atProviders, composerTagIcons, fileUploadEnabled, fileUploadDirectory, artifact, fileDropAction, renderToolHeaderExtra, renderWelcomeHeader, renderWelcomeFooter, mobileWelcomeFooterMiddle, parseUserMessageContent, renderUserMessageContent, renderComposerTag, renderComposerTagTooltip, onComposerTagClick, renderAssistantTurnFooter, assistantFeedback, getAssistantSourcesIcon, sourceReferences, renderComposerToolbarStart, renderComposerToolbarEnd, renderComposerToolbarRight, renderComposerHeader, renderComposerFooter, renderChatHeader, renderFooter, bottomStatusItems, chatMaxWidth, sidebar, settings: settingsPresentation, modelManagement, header, rightPanel, environmentPanel, splitSessionIds: externalSplitSessionIds, onSplitSessionIdsChange, renderPaneHeaderActions, onRightPanelOpen, onFileReviewOpen, onWorkspaceFileOpen, onInsightReportOpen, onContextUsageOpen, messageTurnOutputs, shellRef, composerToolbarActions, mainModelFilter, compactComposerOverlays, autoSubmitSlashCommands, additionalSlashCommands, contextUsageAlwaysVisible, userMessageEditing, onUserMessageEditRequest, cycleModeOnTab, sessionSourceType, composerToolbarAdditionalActions, composerPlaceholders, compactThinking, hostOwnsEditDiffPreview, collapseCompletedTurns, markdownTableMode, virtualScrollThreshold, conversationSearchThreshold, markdown, loadingPhrases, onAgentTasksChange, onTranscriptChange, onSessionArtifactsChange, onToast, composerRef, onComposerReady, composerInput, composerInputVersion, onSessionChange, onAssistantTurnSettled, prepareSubmit, onSubmitBefore, restartSseOnPrompt, historyPageSize, initialSelectedWorkspaceCwd, lockedWorkspaceCwd, lockedWorkspaceCapability, }?: AppProps): import("react/jsx-runtime").JSX.Element;
@@ -61,8 +61,11 @@ export interface TurnCollapseHead {
61
61
  liveStartedAt?: number;
62
62
  }
63
63
  export interface ContentBlock {
64
- type: 'text' | 'image';
64
+ type: 'text' | 'image' | 'diff';
65
65
  text?: string;
66
+ path?: string;
67
+ oldText?: string;
68
+ newText?: string;
66
69
  source?: {
67
70
  type: string;
68
71
  media_type: string;
@@ -6,6 +6,7 @@
6
6
  import { type ReactNode } from 'react';
7
7
  import { type DaemonSessionActions } from '@qwen-code/web-shell/daemon-react-sdk';
8
8
  import { type DaemonSessionArtifact, type DaemonSessionMonitorTaskStatus, type DaemonSessionSummary, type DaemonWorkspaceCapability } from '@qwen-code/sdk/daemon';
9
+ import { type WebShellModelManagementOptions } from '../modelManagement';
9
10
  import { type RegisterContextUsageControls } from '../hooks/useContextUsageControls';
10
11
  import type { WebShellSlashCommandHandler } from '../App';
11
12
  import type { TurnOutputKind, TurnOutputOpenRequest } from './artifacts/TurnOutputs';
@@ -62,6 +63,7 @@ export interface ChatPaneProps {
62
63
  onImageIngestionNotice?: (tone: 'warning' | 'error', message: string) => void;
63
64
  /** Host slash-command callback shared with the main chat composer. */
64
65
  onSlashCommand?: WebShellSlashCommandHandler;
66
+ modelManagement?: WebShellModelManagementOptions;
65
67
  onOpenGoals?: () => void;
66
68
  onRightPanelOpen?: (request: TurnOutputOpenRequest) => void;
67
69
  onOpenMonitor?: (task: DaemonSessionMonitorTaskStatus, sessionId: string, sessionActions: DaemonSessionActions) => void;
@@ -90,4 +92,4 @@ export interface ChatPaneProps {
90
92
  * state, approvals, and composer, and the browser scopes keyboard focus to the
91
93
  * pane the user clicks into — so there is no cross-pane approval arbitration.
92
94
  */
93
- export declare function ChatPane({ title, sessionSummary, isActive, onApprovalChange, workspaceCwd, renderHeaderActions, onClose, onToggleMaximize, isMaximized, onError, onImageIngestionNotice, onSlashCommand, onOpenGoals, onRightPanelOpen, onOpenMonitor, onPaneArtifactsChange, registerContextUsageControls, onBeforeContextCompress, onOpenContextUsage, messageTurnOutputs, embedded, onFirstPromptAdmitted, reportCatalogTurnCompletion, hidden, voiceUserRevision, voiceWorkspaceRevisions, voiceWorkspaces, sessionWorkflowEnabled, planControlVisible, }: ChatPaneProps): import("react/jsx-runtime").JSX.Element;
95
+ export declare function ChatPane({ title, sessionSummary, isActive, onApprovalChange, workspaceCwd, renderHeaderActions, onClose, onToggleMaximize, isMaximized, onError, onImageIngestionNotice, onSlashCommand, modelManagement, onOpenGoals, onRightPanelOpen, onOpenMonitor, onPaneArtifactsChange, registerContextUsageControls, onBeforeContextCompress, onOpenContextUsage, messageTurnOutputs, embedded, onFirstPromptAdmitted, reportCatalogTurnCompletion, hidden, voiceUserRevision, voiceWorkspaceRevisions, voiceWorkspaces, sessionWorkflowEnabled, planControlVisible, }: ChatPaneProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type RefObject, type ReactNode } from 'react';
7
+ import type { MessageListHandle } from './MessageList';
8
+ interface ConversationSearchProps {
9
+ children?: (trigger: ReactNode) => ReactNode;
10
+ active?: boolean;
11
+ onRestoreFocus?: () => void;
12
+ threshold?: number;
13
+ className?: string;
14
+ messageListRef: RefObject<MessageListHandle | null>;
15
+ registerInteractionBlocker?: () => () => void;
16
+ }
17
+ export declare function ConversationSearch({ children, active, onRestoreFocus, threshold, className, messageListRef, registerInteractionBlocker, }: ConversationSearchProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -3,8 +3,10 @@
3
3
  * Copyright 2026 Qwen Team
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import { type ReactNode } from 'react';
6
7
  import type { DaemonTurnNavigationSnapshot, DaemonTurnNavigationStore } from '../daemon/session/turn-navigation-store';
7
- export declare function GlobalTurnNavigation({ state, store, follow, onSelect, }: {
8
+ export declare function GlobalTurnNavigation({ state, store, follow, onSelect, action, }: {
9
+ action?: ReactNode;
8
10
  state: DaemonTurnNavigationSnapshot;
9
11
  store: DaemonTurnNavigationStore;
10
12
  follow?: {
@@ -35,7 +35,8 @@ export interface MessageListProps {
35
35
  * Identity of the session whose transcript `messages` show. Block ids are
36
36
  * per-session ordinals, so changing it resets every session-scoped UI state
37
37
  * (collapse overrides, pagination keep-open, pending page snapshots, the
38
- * scroll anchor) — a direct session switch never renders empty messages.
38
+ * scroll anchor, the settled-stale-message latch) — a direct session switch
39
+ * never renders empty messages.
39
40
  */
40
41
  sessionKey?: string;
41
42
  transcriptBlockCount?: number;
@@ -52,7 +53,11 @@ export interface MessageListProps {
52
53
  transcriptReloadPaused?: boolean;
53
54
  /**
54
55
  * True while the agent is still answering. The newest turn then stays
55
- * expanded and un-collapsible so streaming output is never hidden.
56
+ * expanded and un-collapsible so streaming output is never hidden. When
57
+ * false, stale assistant/thinking/tool-group-thought streaming flags left
58
+ * by a restored replay are settled before render — and stay settled when
59
+ * the session responds again, for as long as their content is unchanged —
60
+ * which is what hosts observe through MarkdownRenderContext.isStreaming.
56
61
  */
57
62
  isResponding?: boolean;
58
63
  welcomeHeader?: ReactNode;
@@ -75,6 +80,7 @@ export interface MessageListProps {
75
80
  */
76
81
  bottomOverlayInset?: number;
77
82
  hideSessionTimeline?: boolean;
83
+ timelineAction?: ReactNode;
78
84
  hideFirstUserMessage?: boolean;
79
85
  firstTurnMetrics?: {
80
86
  durationMs?: number;
@@ -213,6 +219,8 @@ export interface MessageListHandle {
213
219
  * highlight it. Returns false when the message is not in the list.
214
220
  */
215
221
  scrollToMessage: (messageId: string, callId?: string) => boolean;
222
+ /** 定位持久化历史搜索结果;调用方可取消仍在加载的选择。 */
223
+ scrollToSearchHit?: (hit: import('../daemon/session/turn-navigation-store').ConversationSearchHit, isCurrent?: () => boolean) => Promise<boolean | 'cancelled'>;
216
224
  /** Resume bottom-follow mode and scroll to the latest output. */
217
225
  scrollToBottom: (behavior?: ScrollBehavior) => void;
218
226
  }
@@ -6,6 +6,7 @@
6
6
  import { type DaemonSessionActions } from '@qwen-code/web-shell/daemon-react-sdk';
7
7
  import type { DaemonSessionArtifact, DaemonSessionMonitorTaskStatus, DaemonWorkspaceCapability } from '@qwen-code/sdk/daemon';
8
8
  import type { WebShellSlashCommandHandler } from '../App';
9
+ import type { WebShellModelManagementOptions } from '../modelManagement';
9
10
  import type { RegisterContextUsageControls } from '../hooks/useContextUsageControls';
10
11
  import { type PaneHeaderActionsRenderer } from './ChatPane';
11
12
  import type { TurnOutputKind, TurnOutputOpenRequest } from './artifacts/TurnOutputs';
@@ -34,6 +35,7 @@ export interface SplitViewProps {
34
35
  onError?: (error: unknown, fallback: string) => void;
35
36
  onImageIngestionNotice?: (tone: 'warning' | 'error', message: string) => void;
36
37
  onSlashCommand?: WebShellSlashCommandHandler;
38
+ modelManagement?: WebShellModelManagementOptions;
37
39
  onOpenGoals?: () => void;
38
40
  onRightPanelOpen?: (request: TurnOutputOpenRequest) => void;
39
41
  onOpenMonitor?: (task: DaemonSessionMonitorTaskStatus, sessionId: string, sessionActions: DaemonSessionActions) => void;
@@ -68,4 +70,4 @@ export interface SplitViewProps {
68
70
  * naturally scopes the keyboard to the pane the user clicks into, so panes never
69
71
  * fight over which session an approval or Enter belongs to.
70
72
  */
71
- export declare function SplitView({ sessionIds, showSessionDetails, onPanesChange, onAssistantTurnSettled, onPendingPanesChange, onExit, onError, onImageIngestionNotice, onSlashCommand, onOpenGoals, onRightPanelOpen, onOpenMonitor, onPaneArtifactsChange, registerContextUsageControls, onBeforeContextCompress, onOpenContextUsage, messageTurnOutputs, renderPaneHeaderActions, includeOtherWorkspaces, workspaceCwd, restartSseOnPrompt, historyPageSize, voiceUserRevision, voiceWorkspaceRevisions, voiceWorkspaces, sessionWorkflowEnabled, planControlVisible, }: SplitViewProps): import("react/jsx-runtime").JSX.Element;
73
+ export declare function SplitView({ sessionIds, showSessionDetails, onPanesChange, onAssistantTurnSettled, onPendingPanesChange, onExit, onError, onImageIngestionNotice, onSlashCommand, modelManagement, onOpenGoals, onRightPanelOpen, onOpenMonitor, onPaneArtifactsChange, registerContextUsageControls, onBeforeContextCompress, onOpenContextUsage, messageTurnOutputs, renderPaneHeaderActions, includeOtherWorkspaces, workspaceCwd, restartSseOnPrompt, historyPageSize, voiceUserRevision, voiceWorkspaceRevisions, voiceWorkspaces, sessionWorkflowEnabled, planControlVisible, }: SplitViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import type { WebShellLanguage } from '../i18n';
3
3
  import { type WebShellTheme } from '../themeContext';
4
- export declare function StandaloneAuth({ baseUrl, initialToken, initialAddress, language, theme, invalidTarget, unconfirmedTarget, onChangeTarget, children, }: {
4
+ export declare function StandaloneAuth({ baseUrl, initialToken, initialAddress, language, theme, invalidTarget, unconfirmedTarget, pairingFailed, onChangeTarget, children, }: {
5
5
  baseUrl: string;
6
6
  initialToken?: string;
7
7
  initialAddress?: string;
@@ -12,6 +12,7 @@ export declare function StandaloneAuth({ baseUrl, initialToken, initialAddress,
12
12
  invalidTarget?: boolean;
13
13
  /** The daemon came from a link to an origin this browser has not used. */
14
14
  unconfirmedTarget?: boolean;
15
+ pairingFailed?: boolean;
15
16
  onChangeTarget?: (daemonOrigin: string, token?: string, options?: {
16
17
  continueFlow?: 'workspace' | 'connection';
17
18
  }) => boolean | void;
@@ -1,8 +1,10 @@
1
1
  import { type DaemonProductSessionContext } from '@qwen-code/web-shell/daemon-react-sdk';
2
2
  import { type WebShellProps } from '../App';
3
+ import { type WebShellUrlNavigationOptions } from '../navigation';
3
4
  import { type WebShellLanguage } from '../i18n';
4
5
  import { type WebShellTheme } from '../themeContext';
5
6
  interface WorkspaceSessionProviderProps {
7
+ urlNavigation?: WebShellUrlNavigationOptions;
6
8
  sessionId?: string;
7
9
  workspaceId?: string;
8
10
  workspaceCwd?: string;
@@ -4,6 +4,8 @@ import type { WebShellRightPanelItem } from '../../customization';
4
4
  import { type DaemonSessionOwnerSnapshot, type DaemonSessionActions } from '@qwen-code/web-shell/daemon-react-sdk';
5
5
  import { type TurnOutputFileChange, type TurnOutputOpenRequest, type TurnOutputScheduledTask } from './TurnOutputs';
6
6
  import type { EnvironmentAgentTask } from '../panels/EnvironmentPanel';
7
+ import type { WebShellModelManagementOptions } from '../../modelManagement';
8
+ import type { SessionWorkflowProjection } from '../workflow/session-workflow-model';
7
9
  import type { WebPreviewState } from '../preview/web-preview';
8
10
  import type { TrajectoryPageLoader } from '../../trajectory/useTrajectoryWindow';
9
11
  import type { ContextUsageControls } from '../../hooks/useContextUsageControls';
@@ -218,6 +220,7 @@ interface ArtifactPanelProps {
218
220
  }>;
219
221
  onSideTaskCreated?: (tabId: string, sessionId: string) => void;
220
222
  onSideTaskTitleChange?: (tabId: string, title: string, fromFirstPrompt?: boolean) => void;
223
+ onSideTaskInitialPromptRefused?: (tabId: string) => void;
221
224
  onNestedRightPanelOpen?: (request: TurnOutputOpenRequest) => void;
222
225
  onNestedArtifactsChange?: (sessionId: string, artifacts: readonly DaemonSessionArtifact[]) => void;
223
226
  onOpenNestedSubagent?: (tool: ACPToolCall, sessionId: string, workspaceCwd?: string) => void;
@@ -227,10 +230,13 @@ interface ArtifactPanelProps {
227
230
  onOpenWorkflowAgent?: (task: EnvironmentAgentTask) => void;
228
231
  onError?: (error: unknown, fallback: string) => void;
229
232
  sessionWorkflowEnabled?: boolean;
233
+ modelManagement?: WebShellModelManagementOptions;
230
234
  workflow?: {
231
235
  todos: readonly TodoItem[];
232
236
  tools: readonly ACPToolCall[];
233
237
  tasks: readonly DaemonSessionTaskStatus[];
238
+ /** Shared per-render projection; also feeds the cockpit and its graph. */
239
+ projection?: SessionWorkflowProjection;
234
240
  artifacts: readonly DaemonSessionArtifact[];
235
241
  selectedTodoId?: string;
236
242
  onSelectedTodoIdChange: (todoId: string | undefined) => void;
@@ -246,5 +252,5 @@ interface ArtifactPanelProps {
246
252
  fullscreen?: boolean;
247
253
  onToggleFullscreen?: () => void;
248
254
  }
249
- export declare function ArtifactPanel({ contextUsageControls, artifacts, tabs, activeTabId, reviewChanges, selectedReviewPath, panelWidth, workspaceCwd, loading, restoring, error, onSelectTab, onCloseTab, onOpenFilePreview, latestReviewAvailable, onOpenLatestReview, onOpenTerminal, onOpenTrajectory, trajectoryTabId, onOpenWebPreview, onWebPreviewChange, items, sideTaskAvailable, sideTasks, sideTasksLoading, onCreateSideTask, onOpenSideTask, onCreateSideTaskSession, onSideTaskCreated, onSideTaskTitleChange, onNestedRightPanelOpen, onNestedArtifactsChange, onOpenNestedSubagent, agentTasks, agentTraceLoading, agentTraceError, onOpenWorkflowAgent, onError, sessionWorkflowEnabled, workflow, onImageIngestionNotice, deferSubagentMount, onClose, variant, fullscreen, onToggleFullscreen, }: ArtifactPanelProps): import("react/jsx-runtime").JSX.Element;
255
+ export declare function ArtifactPanel({ contextUsageControls, artifacts, tabs, activeTabId, reviewChanges, selectedReviewPath, panelWidth, workspaceCwd, loading, restoring, error, onSelectTab, onCloseTab, onOpenFilePreview, latestReviewAvailable, onOpenLatestReview, onOpenTerminal, onOpenTrajectory, trajectoryTabId, onOpenWebPreview, onWebPreviewChange, items, sideTaskAvailable, sideTasks, sideTasksLoading, onCreateSideTask, onOpenSideTask, onCreateSideTaskSession, onSideTaskCreated, onSideTaskTitleChange, onSideTaskInitialPromptRefused, onNestedRightPanelOpen, onNestedArtifactsChange, onOpenNestedSubagent, agentTasks, agentTraceLoading, agentTraceError, onOpenWorkflowAgent, onError, sessionWorkflowEnabled, modelManagement, workflow, onImageIngestionNotice, deferSubagentMount, onClose, variant, fullscreen, onToggleFullscreen, }: ArtifactPanelProps): import("react/jsx-runtime").JSX.Element;
250
256
  export {};
@@ -1,5 +1,6 @@
1
1
  import type { TurnOutputOpenRequest } from './TurnOutputs';
2
2
  import type { DaemonSessionArtifact } from '@qwen-code/sdk/daemon';
3
+ import { type WebShellModelManagementOptions } from '../../modelManagement';
3
4
  interface SideTaskPanelProps {
4
5
  tabId: string;
5
6
  sessionId?: string;
@@ -18,7 +19,10 @@ interface SideTaskPanelProps {
18
19
  onArtifactsChange?: (sessionId: string, artifacts: readonly DaemonSessionArtifact[]) => void;
19
20
  onError?: (error: unknown, fallback: string) => void;
20
21
  sessionWorkflowEnabled?: boolean;
22
+ modelManagement?: WebShellModelManagementOptions;
21
23
  onImageIngestionNotice?: (tone: 'warning' | 'error', message: string) => void;
24
+ /** Policy refused the stored initial prompt; the parent drops it from the tab. */
25
+ onInitialPromptRefused?: (tabId: string) => void;
22
26
  }
23
- export declare function SideTaskPanel({ tabId, sessionId, parentSessionId, workspaceCwd, title, shouldNameFromFirstPrompt, initialPrompt, createSession, onCreated, onTitleChange, onRightPanelOpen, onArtifactsChange, onError, sessionWorkflowEnabled, onImageIngestionNotice, }: SideTaskPanelProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function SideTaskPanel({ tabId, sessionId, parentSessionId, workspaceCwd, title, shouldNameFromFirstPrompt, initialPrompt, createSession, onCreated, onTitleChange, onRightPanelOpen, onArtifactsChange, onError, sessionWorkflowEnabled, modelManagement, onImageIngestionNotice, onInitialPromptRefused, }: SideTaskPanelProps): import("react/jsx-runtime").JSX.Element;
24
28
  export {};
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { TimelineModel, TimelineSpan } from '../../trajectory/buildTimeline';
7
+ import { type TimelineRange } from '../../trajectory/timelineRange';
8
+ /**
9
+ * The strip's height, which never changes. It sits above the table as a flex
10
+ * sibling of the scrolled rows, so any change in its height would move every
11
+ * row the reader is looking at. Loading, empty and drawn states all fill the
12
+ * same box.
13
+ */
14
+ export declare const OVERVIEW_HEIGHT = 64;
15
+ /**
16
+ * How far the pointer has to travel before a press becomes a drag. Below it
17
+ * the press is a click, which selects the span under it — a hand that wobbles
18
+ * a pixel while clicking a 3px bar must not turn the click into a range.
19
+ */
20
+ export declare const DRAG_THRESHOLD_PX = 4;
21
+ export interface TrajectoryOverviewProps {
22
+ model: TimelineModel | undefined;
23
+ /** Shown inside the box when there is no model to draw. */
24
+ notice?: string;
25
+ selectedKey?: string;
26
+ onSelect: (rowKey: string) => void;
27
+ /** Hover text for one span; the table owns how a row is named. */
28
+ describe: (span: TimelineSpan) => string;
29
+ /** The committed time selection, in the model's domain. */
30
+ range?: TimelineRange;
31
+ /**
32
+ * A drag commits a range; a click on empty track, a right click, or any
33
+ * other way of clearing it reports `undefined`.
34
+ */
35
+ onRangeChange: (range: TimelineRange | undefined) => void;
36
+ }
37
+ /** Percentages as CSS lengths, rounded so tests can name them exactly. */
38
+ export declare function percent(value: number): string;
39
+ export declare function TrajectoryOverview({ model, notice, selectedKey, onSelect, describe, range, onRangeChange, }: TrajectoryOverviewProps): import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,9 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type { DaemonChannelInstanceSnapshot, DaemonChannelSecretUpdate, DaemonChannelTypeDescriptor, DaemonChannelUpsertRequest } from '@qwen-code/sdk/daemon';
7
- export type ChannelSenderPolicy = 'pairing' | 'open' | '';
7
+ export type ChannelPrivatePolicy = 'disabled' | 'allowlist' | 'pairing' | 'open' | '';
8
+ /** `groups["*"].senders`; `''` means the config leaves it unset. */
9
+ export type ChannelGroupSenders = 'open' | 'allowlist' | '';
8
10
  export interface ChannelSecretDraft {
9
11
  operation: DaemonChannelSecretUpdate['operation'];
10
12
  value?: string;
@@ -13,13 +15,17 @@ export interface ChannelEditorDraft {
13
15
  name: string;
14
16
  values: Record<string, string | boolean>;
15
17
  secrets: Record<string, ChannelSecretDraft>;
16
- senderPolicy: ChannelSenderPolicy;
18
+ privatePolicy: ChannelPrivatePolicy;
17
19
  allowedGroupIds: string;
20
+ groupSenders: ChannelGroupSenders;
21
+ groupAllowedUsers: string;
18
22
  }
19
23
  export type ChannelEditorValidationCode = 'required' | 'credential' | 'duplicate' | 'invalid' | 'invalidGroupId' | 'invalidOption' | 'number' | 'outOfRange' | 'policy';
20
24
  export type ChannelEditorValidationErrors = Record<string, ChannelEditorValidationCode>;
21
- export declare function hasDescriptorSenderPolicy(descriptor: DaemonChannelTypeDescriptor): boolean;
25
+ export declare function hasDescriptorPrivatePolicy(descriptor: DaemonChannelTypeDescriptor): boolean;
22
26
  export declare function hasDescriptorGroupPolicy(descriptor: DaemonChannelTypeDescriptor): boolean;
27
+ export declare function defaultGroupSenders(): Exclude<ChannelGroupSenders, ''>;
28
+ export declare function configuredPrivatePolicy(instance?: DaemonChannelInstanceSnapshot): string;
23
29
  export declare function createChannelEditorDraft(descriptor: DaemonChannelTypeDescriptor, instance?: DaemonChannelInstanceSnapshot): ChannelEditorDraft;
24
30
  export declare function validateChannelEditorDraft(descriptor: DaemonChannelTypeDescriptor, draft: ChannelEditorDraft, existingNames: readonly string[]): ChannelEditorValidationErrors;
25
31
  export declare function buildChannelUpsertRequest(descriptor: DaemonChannelTypeDescriptor, draft: ChannelEditorDraft, expectedRevision: string, instance?: DaemonChannelInstanceSnapshot): DaemonChannelUpsertRequest;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Qwen Team
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export declare function useConversationSearchI18n(): (key: string, vars?: Record<string, string | number>) => string;
@@ -17,6 +17,7 @@ export interface LocalControlStatus {
17
17
  */
18
18
  urlRedacted?: boolean;
19
19
  qrText?: string;
20
+ expiresInMs?: number;
20
21
  interfaceName?: string;
21
22
  address?: string;
22
23
  sleepInhibited?: boolean;
@@ -25,6 +26,7 @@ export interface LocalControlStatus {
25
26
  }
26
27
  export declare class LocalControlRequestError extends Error {
27
28
  readonly payload?: LocalControlStatus | undefined;
28
- constructor(message: string, payload?: LocalControlStatus | undefined);
29
+ readonly status?: number | undefined;
30
+ constructor(message: string, payload?: LocalControlStatus | undefined, status?: number | undefined);
29
31
  }
30
32
  export declare function requestLocalControl(baseUrl: string, token: string | undefined, method: 'GET' | 'POST', path: string, body?: object): Promise<LocalControlStatus>;
@@ -1,6 +1,7 @@
1
1
  interface AuthMessageProps {
2
+ allowAdd?: boolean;
2
3
  onMessage: (text: string, type?: 'status' | 'error') => void;
3
4
  onClose: () => void;
4
5
  }
5
- export declare function AuthMessage({ onMessage, onClose }: AuthMessageProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function AuthMessage({ onMessage, onClose, allowAdd, }: AuthMessageProps): import("react/jsx-runtime").JSX.Element;
6
7
  export {};
@@ -1,3 +1,4 @@
1
+ import type { WebShellModelManagementOptions } from '../../modelManagement';
1
2
  import type { DaemonModelConfiguration, DaemonModelConfigurationUpdateResult } from '@qwen-code/sdk/daemon';
2
3
  import type { DaemonWorkspaceProviderStatus } from '@qwen-code/web-shell/daemon-react-sdk';
3
4
  export interface ModelDeleteTarget {
@@ -6,7 +7,7 @@ export interface ModelDeleteTarget {
6
7
  modelId: string;
7
8
  baseUrl?: string;
8
9
  }
9
- export interface ModelManagementProps {
10
+ export interface ModelManagementProps extends WebShellModelManagementOptions {
10
11
  providers: DaemonWorkspaceProviderStatus[];
11
12
  configurations?: DaemonModelConfiguration[];
12
13
  onUpdateContextWindow?: (key: string, size: number | null) => Promise<DaemonModelConfigurationUpdateResult>;
@@ -20,4 +21,4 @@ export interface ModelManagementProps {
20
21
  onDeleteModel: (target: ModelDeleteTarget) => void;
21
22
  onAddModel: () => void;
22
23
  }
23
- export declare function ModelManagementSection({ providers, configurations, onUpdateContextWindow, currentModelId, loading, error, busy, onSelectModel, onDeleteModel, onAddModel, }: ModelManagementProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function ModelManagementSection({ allowAdd, allowDelete, providers, configurations, onUpdateContextWindow, currentModelId, loading, error, busy, onSelectModel, onDeleteModel, onAddModel, }: ModelManagementProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,9 @@
1
- import type { DaemonSessionAgentTaskStatus, DaemonSessionTaskStatus } from '@qwen-code/sdk/daemon';
1
+ import type { DaemonSessionTaskStatus } from '@qwen-code/sdk/daemon';
2
2
  import type { ACPToolCall, TodoItem } from '../../adapters/types';
3
- export type PlanNodeStatus = 'running' | 'paused' | 'completed' | 'blocked' | 'in_progress' | 'ready';
3
+ import { type PlanNodeStatus } from './taskExecutionIndex';
4
+ import type { SessionWorkflowProjection } from '../workflow/session-workflow-model';
5
+ export { createTaskExecutionIndex, getActiveAgents, getActiveAgentsFromIndex, getAttentionAgentStatuses, getAttentionAgentTool, getPlanNodeState, getPlanNodeStateFromIndex, nestedAgentToolsForTool, nestedTasksFromIndex, nestedTasksForTool, todoIdOf, } from './taskExecutionIndex';
6
+ export type { PlanNodeStatus, TaskExecutionIndex } from './taskExecutionIndex';
4
7
  /**
5
8
  * Status is carried by a glyph as well as a colour so the graph survives
6
9
  * colour-blindness, high-contrast mode, and a greyscale screenshot. Every
@@ -8,73 +11,18 @@ export type PlanNodeStatus = 'running' | 'paused' | 'completed' | 'blocked' | 'i
8
11
  */
9
12
  export declare const PLAN_STATUS_GLYPH: Record<PlanNodeStatus, string>;
10
13
  export declare function layerPlanTodos(todos: readonly TodoItem[]): TodoItem[][];
11
- export interface TaskExecutionIndex {
12
- rootByToolCallId: ReadonlyMap<string, DaemonSessionAgentTaskStatus>;
13
- childrenByParentId: ReadonlyMap<string, DaemonSessionAgentTaskStatus[]>;
14
- nestedByRootId: Map<string, Array<{
15
- task: DaemonSessionAgentTaskStatus;
16
- depth: number;
17
- }>>;
18
- }
19
- export declare function createTaskExecutionIndex(tasks: readonly DaemonSessionTaskStatus[]): TaskExecutionIndex;
20
- export declare function nestedTasksFromIndex(tool: ACPToolCall, taskIndex: TaskExecutionIndex): Array<{
21
- task: DaemonSessionAgentTaskStatus;
22
- depth: number;
23
- }>;
24
- export declare function nestedTasksForTool(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): Array<{
25
- task: DaemonSessionAgentTaskStatus;
26
- depth: number;
27
- }>;
28
- /**
29
- * Deliberately uncached. Keying on the tool object would be wrong the moment
30
- * a reused object gains a sub-tool — `appendSubTool` mutates `subTools` in
31
- * place — and the only thing standing between that and a stale render is
32
- * `useMessages`' prefix-reuse rule in another module. The callers' own
33
- * derivations are memoized, so the repetition this would remove is bounded to
34
- * a single derivation; a silent wrong subtree is not worth that.
35
- */
36
- export declare function nestedAgentToolsForTool(tool: ACPToolCall): Array<{
37
- tool: ACPToolCall;
38
- depth: number;
39
- }>;
40
- /**
41
- * Same agent-status walk as {@link attentionAgentStatuses}, for callers that
42
- * hold the raw task list instead of a prebuilt index (the cockpit's stats
43
- * strip, which must tally exactly what the attention queue shows).
44
- */
45
- export declare function getAttentionAgentStatuses(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): string[];
46
- /**
47
- * One entry per agent the overview strip reports as active, and the single
48
- * source the workflow inspector summary counts: the live daemon task when
49
- * one exists, otherwise a transcript-derived stand-in for an in-flight tool
50
- * call with no live task (the replay shape). The walk mirrors the node
51
- * badges (executionStatus), so the strip, the badges, and the inspector can
52
- * never contradict each other. An agent observed through BOTH a live task
53
- * and a persisted transcript tool counts once (dedup by toolUseId).
54
- */
55
- export declare function getActiveAgents(tools: readonly ACPToolCall[], tasks: readonly DaemonSessionTaskStatus[]): DaemonSessionAgentTaskStatus[];
56
- /**
57
- * {@link getActiveAgents} for callers that already hold an index. Building the
58
- * index is O(tasks); doing it per todo and per tool — as the workflow
59
- * projection used to — makes the walk O((todos + tools) x tasks) for a result
60
- * that never varies with the todo or the tool.
61
- */
62
- export declare function getActiveAgentsFromIndex(tools: readonly ACPToolCall[], taskIndex: TaskExecutionIndex): DaemonSessionAgentTaskStatus[];
63
- export declare function getPlanNodeStateFromIndex(todo: TodoItem, todosById: ReadonlyMap<string, TodoItem>, tools: readonly ACPToolCall[], taskIndex: TaskExecutionIndex): {
64
- status: PlanNodeStatus;
65
- attention: boolean;
66
- };
67
- export declare function getPlanNodeState(todo: TodoItem, todosById: ReadonlyMap<string, TodoItem>, tools: readonly ACPToolCall[], tasks: readonly DaemonSessionTaskStatus[]): {
68
- status: PlanNodeStatus;
69
- attention: boolean;
70
- };
71
- /** The plan step a tool call was issued for, when it declares one. */
72
- export declare function todoIdOf(tool: ACPToolCall): string | undefined;
73
- export declare function getAttentionAgentTool(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): ACPToolCall | undefined;
74
- export declare function PlanExecutionView({ todos, tools, tasks, onOpenSubagent, hideTitle, selection, showStepDetails, }: {
14
+ export declare function PlanExecutionView({ todos, tools, tasks, projection: sharedProjection, onOpenSubagent, hideTitle, selection, showStepDetails, }: {
75
15
  todos: readonly TodoItem[];
76
16
  tools: readonly ACPToolCall[];
77
17
  tasks: readonly DaemonSessionTaskStatus[];
18
+ /**
19
+ * A host that already derives the workflow projection (the cockpit, which
20
+ * mounts this graph beside the inspector) passes its own, so the whole
21
+ * surface shares one projection — and one task-execution index — per
22
+ * render instead of each component privately rebuilding both. Standalone
23
+ * mounts derive it from `todos` / `tools` / `tasks` here.
24
+ */
25
+ projection?: SessionWorkflowProjection;
78
26
  onOpenSubagent?: (tool: ACPToolCall) => void;
79
27
  /**
80
28
  * Drop the "Plan execution" caption when the host already titles the region.
@@ -15,7 +15,7 @@ interface SettingsMessageProps {
15
15
  chatWidthMode: ChatWidthMode;
16
16
  onChatWidthModeChange: (mode: ChatWidthMode) => void;
17
17
  /** Model list/add/delete/select, rendered inside the Model category. */
18
- modelManagement?: ModelManagementProps;
18
+ modelManagementSectionProps?: ModelManagementProps;
19
19
  /** Browser-local remote computer catalog and connection controls. */
20
20
  connections?: ReactNode;
21
21
  embedded?: boolean;
@@ -45,5 +45,5 @@ export type FlatRow = {
45
45
  localKey: 'chatWidth' | 'browserNotifications';
46
46
  };
47
47
  export declare function nextSettingIdx(rows: FlatRow[], current: number, dir: 1 | -1): number;
48
- export declare function SettingsMessage({ settingsState, presentation, onLanguageChange, onSubDialog, onThemeChange, chatWidthMode, onChatWidthModeChange, modelManagement, connections, embedded, initialCategory, }: SettingsMessageProps): import("react/jsx-runtime").JSX.Element;
48
+ export declare function SettingsMessage({ settingsState, presentation, onLanguageChange, onSubDialog, onThemeChange, chatWidthMode, onChatWidthModeChange, modelManagementSectionProps, connections, embedded, initialCategory, }: SettingsMessageProps): import("react/jsx-runtime").JSX.Element;
49
49
  export {};
@@ -25,7 +25,6 @@ interface ToolGroupProps {
25
25
  }
26
26
  export declare function extractDiff(tool: ACPToolCall): string;
27
27
  export declare function getRawFileDiff(tool: ACPToolCall): string;
28
- export declare function buildUnifiedDiff(oldText: string, newText: string): string;
29
28
  export declare function languageForPath(filePath: string): string;
30
29
  export declare function fencedCodeBlock(language: string, code: string): string;
31
30
  interface ToolLineProps {
@@ -0,0 +1,80 @@
1
+ import type { DaemonSessionAgentTaskStatus, DaemonSessionTaskStatus } from '@qwen-code/sdk/daemon';
2
+ import type { ACPToolCall, TodoItem } from '../../adapters/types';
3
+ /**
4
+ * Shared task-execution lookups for the plan surfaces. Extracted from
5
+ * `PlanExecutionView` so the workflow projection (`session-workflow-model`)
6
+ * and the graph (`PlanExecutionView`) both depend on this module instead of
7
+ * on each other, and so one build of the index can be threaded from the
8
+ * projection into every consumer in a single render.
9
+ */
10
+ export type PlanNodeStatus = 'running' | 'paused' | 'completed' | 'blocked' | 'in_progress' | 'ready';
11
+ export interface TaskExecutionIndex {
12
+ rootByToolCallId: ReadonlyMap<string, DaemonSessionAgentTaskStatus>;
13
+ childrenByParentId: ReadonlyMap<string, DaemonSessionAgentTaskStatus[]>;
14
+ nestedByRootId: Map<string, Array<{
15
+ task: DaemonSessionAgentTaskStatus;
16
+ depth: number;
17
+ }>>;
18
+ }
19
+ export declare function createTaskExecutionIndex(tasks: readonly DaemonSessionTaskStatus[]): TaskExecutionIndex;
20
+ export declare function taskForTool(tool: ACPToolCall, taskIndex: TaskExecutionIndex): DaemonSessionAgentTaskStatus | undefined;
21
+ export declare function executionStatus(tool: ACPToolCall, taskIndex: TaskExecutionIndex): string;
22
+ export declare function nestedTasksFromIndex(tool: ACPToolCall, taskIndex: TaskExecutionIndex): Array<{
23
+ task: DaemonSessionAgentTaskStatus;
24
+ depth: number;
25
+ }>;
26
+ export declare function nestedTasksForTool(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): Array<{
27
+ task: DaemonSessionAgentTaskStatus;
28
+ depth: number;
29
+ }>;
30
+ /**
31
+ * Deliberately uncached. Keying on the tool object would be wrong the moment
32
+ * a reused object gains a sub-tool — `appendSubTool` mutates `subTools` in
33
+ * place — and the only thing standing between that and a stale render is
34
+ * `useMessages`' prefix-reuse rule in another module. The callers' own
35
+ * derivations are memoized, so the repetition this would remove is bounded to
36
+ * a single derivation; a silent wrong subtree is not worth that.
37
+ */
38
+ export declare function nestedAgentToolsForTool(tool: ACPToolCall): Array<{
39
+ tool: ACPToolCall;
40
+ depth: number;
41
+ }>;
42
+ /**
43
+ * Same agent-status walk as {@link attentionAgentStatuses}, for callers that
44
+ * hold the raw task list instead of a prebuilt index (the cockpit's stats
45
+ * strip, which must tally exactly what the attention queue shows).
46
+ */
47
+ export declare function getAttentionAgentStatuses(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): string[];
48
+ /**
49
+ * One entry per agent the overview strip reports as active, and the single
50
+ * source the workflow inspector summary counts: the live daemon task when
51
+ * one exists, otherwise a transcript-derived stand-in for an in-flight tool
52
+ * call with no live task (the replay shape). The walk mirrors the node
53
+ * badges (executionStatus), so the strip, the badges, and the inspector can
54
+ * never contradict each other. An agent observed through BOTH a live task
55
+ * and a persisted transcript tool counts once (dedup by toolUseId).
56
+ */
57
+ export declare function getActiveAgents(tools: readonly ACPToolCall[], tasks: readonly DaemonSessionTaskStatus[]): DaemonSessionAgentTaskStatus[];
58
+ /**
59
+ * {@link getActiveAgents} for callers that already hold an index. Building the
60
+ * index is O(tasks); doing it per todo and per tool — as the workflow
61
+ * projection used to — makes the walk O((todos + tools) x tasks) for a result
62
+ * that never varies with the todo or the tool.
63
+ */
64
+ export declare function getActiveAgentsFromIndex(tools: readonly ACPToolCall[], taskIndex: TaskExecutionIndex): DaemonSessionAgentTaskStatus[];
65
+ export declare function getPlanNodeStateFromIndex(todo: TodoItem, todosById: ReadonlyMap<string, TodoItem>, tools: readonly ACPToolCall[], taskIndex: TaskExecutionIndex): {
66
+ status: PlanNodeStatus;
67
+ attention: boolean;
68
+ };
69
+ export declare function getPlanNodeState(todo: TodoItem, todosById: ReadonlyMap<string, TodoItem>, tools: readonly ACPToolCall[], tasks: readonly DaemonSessionTaskStatus[]): {
70
+ status: PlanNodeStatus;
71
+ attention: boolean;
72
+ };
73
+ /** The plan step a tool call was issued for, when it declares one. */
74
+ export declare function todoIdOf(tool: ACPToolCall): string | undefined;
75
+ /**
76
+ * A clickable stand-in for a live agent task that has no transcript tool
77
+ * call, so the graph's nested execution rows can still open its panel.
78
+ */
79
+ export declare function toolForNestedTask(task: DaemonSessionAgentTaskStatus): ACPToolCall | undefined;
80
+ export declare function getAttentionAgentTool(tool: ACPToolCall, tasks: readonly DaemonSessionTaskStatus[]): ACPToolCall | undefined;
@@ -1,5 +1,6 @@
1
1
  import type { DaemonSessionTaskStatus } from '@qwen-code/sdk/daemon';
2
2
  import type { ACPToolCall, TodoItem } from '../../adapters/types';
3
+ import { type SessionWorkflowProjection } from './session-workflow-model';
3
4
  interface SessionWorkflowCockpitProps {
4
5
  sessionId: string;
5
6
  connected: boolean;
@@ -8,10 +9,16 @@ interface SessionWorkflowCockpitProps {
8
9
  todos: readonly TodoItem[];
9
10
  tools: readonly ACPToolCall[];
10
11
  tasks: readonly DaemonSessionTaskStatus[];
12
+ /**
13
+ * The projection shared by every workflow surface for this render. The app
14
+ * derives it once (it also feeds the inspector beside this cockpit); when
15
+ * absent — a standalone mount, a test — it is derived from the raw props.
16
+ */
17
+ projection?: SessionWorkflowProjection;
11
18
  selectedTodoId?: string;
12
19
  onSelectedTodoIdChange: (todoId: string | undefined) => void;
13
20
  onBackToChat: () => void;
14
21
  onOpenSubagent: (tool: ACPToolCall) => void;
15
22
  }
16
- export declare function SessionWorkflowCockpit({ sessionId, connected, sessionName, workspaceCwd, todos, tools, tasks, selectedTodoId, onSelectedTodoIdChange, onBackToChat, onOpenSubagent, }: SessionWorkflowCockpitProps): import("react/jsx-runtime").JSX.Element;
23
+ export declare function SessionWorkflowCockpit({ sessionId, connected, sessionName, workspaceCwd, todos, tools, tasks, projection: sharedProjection, selectedTodoId, onSelectedTodoIdChange, onBackToChat, onOpenSubagent, }: SessionWorkflowCockpitProps): import("react/jsx-runtime").JSX.Element;
17
24
  export {};