@xenosystem/agent-interface-ui 0.1.7 → 0.1.8

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.
@@ -18,8 +18,9 @@ import { isWideWorkbenchTab } from './AgentWorkbenchPanel.js';
18
18
  import { PermissionDialog } from './PermissionDialog.js';
19
19
  import { runtimeEventSummary } from './runtimeEventSummary.js';
20
20
  import { latestContextPressure } from './timelineContextPressure.js';
21
+ import { createConversationRuntimeBinding, runtimeSelectionForSdk } from '../../utils/conversationRuntime.js';
21
22
  import { usePermissionStore } from '../../stores/permissionStore.js';
22
- import { useAgentChatStore, loadLocalAgentConversations, projectConversationRuntimeEvents, } from '../../stores/agentChatStore.js';
23
+ import { useAgentChatStore, loadLocalAgentConversations, projectConversationRuntimeEvents, resetAcpContinuationForWorkspaceChange, } from '../../stores/agentChatStore.js';
23
24
  import { useAgentIdeStore } from '../../stores/agentIdeStore.js';
24
25
  import { useAgentSearchStore } from '../../stores/agentSearchStore.js';
25
26
  import { useWorkspaceStore, } from '../../stores/workspaceStore.js';
@@ -1553,10 +1554,13 @@ function loadCachedRightPanelTerminals() {
1553
1554
  .map((tab) => ({
1554
1555
  id: tab.id,
1555
1556
  label: tab.label,
1557
+ kind: tab.kind === 'provider-session' ? 'provider-session' : 'shell',
1556
1558
  conversationId: tab.conversationId,
1557
1559
  terminalId: tab.terminalId,
1558
1560
  cwd: tab.cwd,
1559
1561
  allowedKey: tab.allowedKey,
1562
+ ...(typeof tab.laneId === 'string' ? { laneId: tab.laneId } : {}),
1563
+ ...(typeof tab.expectedLaneRevision === 'number' ? { expectedLaneRevision: tab.expectedLaneRevision } : {}),
1560
1564
  output: '',
1561
1565
  starting: false,
1562
1566
  exited: false,
@@ -1575,10 +1579,13 @@ function persistCachedRightPanelTerminals(tabs) {
1575
1579
  .map((tab) => ({
1576
1580
  id: tab.id,
1577
1581
  label: tab.label,
1582
+ kind: tab.kind,
1578
1583
  conversationId: tab.conversationId,
1579
1584
  terminalId: tab.terminalId,
1580
1585
  cwd: tab.cwd,
1581
1586
  allowedKey: tab.allowedKey,
1587
+ ...(tab.laneId ? { laneId: tab.laneId } : {}),
1588
+ ...(typeof tab.expectedLaneRevision === 'number' ? { expectedLaneRevision: tab.expectedLaneRevision } : {}),
1582
1589
  }));
1583
1590
  window.sessionStorage.setItem(RIGHT_PANEL_TERMINALS_STORAGE_KEY, JSON.stringify(serializable));
1584
1591
  }
@@ -1592,7 +1599,7 @@ function clampRightPanelWidth(width) {
1592
1599
  : Math.max(RIGHT_PANEL_MIN_WIDTH, Math.min(RIGHT_PANEL_MAX_WIDTH, window.innerWidth - 360));
1593
1600
  return Math.min(viewportAwareMax, Math.max(RIGHT_PANEL_MIN_WIDTH, Math.round(width)));
1594
1601
  }
1595
- function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOpenFolder, onClose, onOpenFile, activeFilePath, terminalCapabilityEnabled, terminalReady, resolvedTerminalCwd, terminalTabs, onPtyInput, onPtyResize, onCreateTerminal, onCloseTerminal, onClearTerminal, onRestartTerminal, width, onResizeStart, }) {
1602
+ function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOpenFolder, onClose, onOpenFile, activeFilePath, terminalCapabilityEnabled, terminalReady, providerSessionTuiReady, resolvedTerminalCwd, terminalTabs, onPtyInput, onPtyResize, onCreateTerminal, onCreateProviderTui, onCloseTerminal, onClearTerminal, onRestartTerminal, width, onResizeStart, }) {
1596
1603
  const [rightPanelTab, setRightPanelTab] = useState('files');
1597
1604
  const [browserTabs, setBrowserTabs] = useState(() => loadCachedRightPanelBrowserTabs());
1598
1605
  const activeBrowserTabId = rightPanelTab.startsWith('browser:') ? rightPanelTab.slice('browser:'.length) : null;
@@ -1818,7 +1825,12 @@ function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOp
1818
1825
  if (id)
1819
1826
  setRightPanelTab(`terminal:${id}`);
1820
1827
  setNewTabMenuOpen(false);
1821
- }, disabled: !terminalCapabilityEnabled || !terminalReady, className: "w-full flex items-center gap-2.5 px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-white/64", children: [_jsx(Terminal, { className: "h-3.5 w-3.5 text-white/42", strokeWidth: 1.8 }), _jsx("span", { children: "PowerShell" })] })] }))] }), _jsxs("div", { ref: panelMenuRef, className: "relative", children: [_jsx("button", { type: "button", onClick: () => setPanelMenuOpen((open) => !open), className: `h-7 w-7 inline-flex items-center justify-center rounded-[5px] transition-colors ${panelMenuOpen
1828
+ }, disabled: !terminalCapabilityEnabled || !terminalReady, className: "w-full flex items-center gap-2.5 px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-white/64", children: [_jsx(Terminal, { className: "h-3.5 w-3.5 text-white/42", strokeWidth: 1.8 }), _jsx("span", { children: "PowerShell" })] }), _jsxs("button", { type: "button", role: "menuitem", onClick: () => {
1829
+ const id = onCreateProviderTui();
1830
+ if (id)
1831
+ setRightPanelTab(`terminal:${id}`);
1832
+ setNewTabMenuOpen(false);
1833
+ }, disabled: !providerSessionTuiReady, className: "w-full flex items-center gap-2.5 px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent disabled:hover:text-white/64", children: [_jsx(Terminal, { className: "h-3.5 w-3.5 text-white/42", strokeWidth: 1.8 }), _jsx("span", { children: "Provider TUI" })] })] }))] }), _jsxs("div", { ref: panelMenuRef, className: "relative", children: [_jsx("button", { type: "button", onClick: () => setPanelMenuOpen((open) => !open), className: `h-7 w-7 inline-flex items-center justify-center rounded-[5px] transition-colors ${panelMenuOpen
1822
1834
  ? 'text-white/72 bg-white/[0.07]'
1823
1835
  : 'text-white/30 hover:text-white/65 hover:bg-white/[0.055]'}`, title: "Panel options", "aria-haspopup": "menu", "aria-expanded": panelMenuOpen, children: _jsx(MoreHorizontal, { className: "w-3.5 h-3.5", strokeWidth: 1.8 }) }), panelMenuOpen && (_jsxs("div", { role: "menu", className: "absolute right-0 top-[32px] z-50 w-52 overflow-hidden rounded-[7px] border border-white/[0.08] bg-[#111114] py-1 shadow-[0_16px_40px_rgba(0,0,0,0.45)]", children: [activeTerminal ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", role: "menuitem", onClick: () => {
1824
1836
  onClearTerminal(activeTerminal.id);
@@ -1826,7 +1838,9 @@ function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOp
1826
1838
  }, className: "w-full px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors", children: "Clear terminal" }), _jsx("button", { type: "button", role: "menuitem", onClick: () => {
1827
1839
  onRestartTerminal(activeTerminal.id);
1828
1840
  setPanelMenuOpen(false);
1829
- }, className: "w-full px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors", children: "Restart PowerShell" }), _jsx("button", { type: "button", role: "menuitem", onClick: () => {
1841
+ }, className: "w-full px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors", children: activeTerminal.kind === 'provider-session' && activeTerminal.exited
1842
+ ? 'Reconcile and return to chat'
1843
+ : `Restart ${activeTerminal.kind === 'provider-session' ? (activeTerminal.label || 'Provider TUI') : 'PowerShell'}` }), _jsx("button", { type: "button", role: "menuitem", onClick: () => {
1830
1844
  onCloseTerminal(activeTerminal.id);
1831
1845
  setPanelMenuOpen(false);
1832
1846
  }, className: "w-full px-3 py-2 text-left text-[12px] text-red-200/70 hover:bg-red-500/[0.09] hover:text-red-100 transition-colors", children: "Close terminal tab" }), _jsx("div", { className: "my-1 h-px bg-white/[0.06]" })] })) : activeBrowser ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", role: "menuitem", onClick: () => {
@@ -1850,6 +1864,11 @@ function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOp
1850
1864
  setRightPanelTab(`terminal:${id}`);
1851
1865
  setPanelMenuOpen(false);
1852
1866
  }, disabled: !terminalCapabilityEnabled || !terminalReady, className: "w-full px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent", children: "New PowerShell tab" }), _jsx("button", { type: "button", role: "menuitem", onClick: () => {
1867
+ const id = onCreateProviderTui();
1868
+ if (id)
1869
+ setRightPanelTab(`terminal:${id}`);
1870
+ setPanelMenuOpen(false);
1871
+ }, disabled: !providerSessionTuiReady, className: "w-full px-3 py-2 text-left text-[12px] text-white/64 hover:bg-white/[0.06] hover:text-white transition-colors disabled:cursor-not-allowed disabled:opacity-35 disabled:hover:bg-transparent", children: "Open Provider TUI" }), _jsx("button", { type: "button", role: "menuitem", onClick: () => {
1853
1872
  terminalTabs.forEach((tab) => onCloseTerminal(tab.id));
1854
1873
  setRightPanelTab('files');
1855
1874
  setPanelMenuOpen(false);
@@ -1861,7 +1880,7 @@ function FolderSidebar({ conversationId, rootDirectory, allowedDirectories, onOp
1861
1880
  return (_jsx("div", { className: visible
1862
1881
  ? 'absolute inset-0'
1863
1882
  : 'absolute inset-0 invisible pointer-events-none opacity-0', "aria-hidden": !visible, children: _jsx(React.Suspense, { fallback: _jsx("div", { className: "h-full bg-[#08080a] px-3 py-2 text-[12px] text-white/40", children: "Loading browser..." }), children: _jsx(AgentWorkspaceBrowserPanel, { browserId: tab.id, browserLabel: tab.label, rootDirectory: effectiveRoot || rootDirectory, allowedDirectories: effectiveAllowedDirectories, onOpenFolder: onOpenFolder }) }) }, tab.id));
1864
- }), rightPanelTab === 'files' && effectiveRoot && (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => handleToggleDirectory(effectiveRoot), className: "w-full flex items-center gap-1.5 px-2 py-1.5 text-white/68 hover:text-white hover:bg-white/[0.04] rounded-md transition-colors text-left", children: [_jsx(ChevronDownIcon, { className: `w-3 h-3 flex-shrink-0 transition-transform ${expandedPaths.has(effectiveRoot) ? '' : '-rotate-90'}` }), expandedPaths.has(effectiveRoot) ? (_jsx(FolderOpen, { className: "w-3.5 h-3.5 flex-shrink-0 text-white/55", strokeWidth: 1.8 })) : (_jsx(Folder, { className: "w-3.5 h-3.5 flex-shrink-0 text-white/45", strokeWidth: 1.8 })), _jsx("span", { className: "min-w-0 truncate text-[12px]", children: directoryLeafName(effectiveRoot) })] }), expandedPaths.has(effectiveRoot) && (_jsxs("div", { className: "mt-0.5", children: [isRootLoading && (_jsx(FolderTreeLoadingSkeleton, { depth: 1, rows: 5 })), !isRootLoading && loadErrors[effectiveRoot] && (_jsx("div", { className: "pl-7 py-1 text-[11px] text-red-300/45", children: loadErrors[effectiveRoot] })), !isRootLoading && !loadErrors[effectiveRoot] && (entriesByPath[effectiveRoot] || []).map((entry) => (_jsx(FolderTreeNode, { entry: entry, depth: 1, expandedPaths: expandedPaths, loadingPaths: loadingPaths, loadErrors: loadErrors, entriesByPath: entriesByPath, onToggleDirectory: handleToggleDirectory, onOpenFile: onOpenFile, activeFilePath: activeFilePath }, entry.path)))] }))] })), rightPanelTab === 'files' && !effectiveRoot && (_jsxs("div", { className: "mt-2 rounded-md border border-white/[0.06] bg-white/[0.02] p-3", children: [_jsx("p", { className: "text-[11px] uppercase tracking-[0.18em] text-white/28", children: "Folder Explorer" }), _jsx("p", { className: "mt-2 text-[12px] leading-relaxed text-white/42", children: "Open a folder for this conversation to browse files here and send them into the editor." }), _jsxs("div", { className: "mt-3 space-y-2", children: [_jsx(SkeletonBlock, { className: "h-3 w-[78%]" }), _jsx(SkeletonBlock, { className: "h-3 w-[66%]" }), _jsx(SkeletonBlock, { className: "h-3 w-[72%]" })] })] })), activeTerminalTabId && (_jsx(React.Suspense, { fallback: _jsx("div", { className: "h-full bg-[#050506] px-3 py-2 font-mono text-[12px] text-white/40", children: "Loading terminal..." }), children: _jsx(AgentPtyTerminalPanel, { terminalKey: activeTerminal?.id || null, terminalId: activeTerminal?.terminalId || null, output: activeTerminal?.output || '', terminalCapabilityEnabled: terminalCapabilityEnabled, terminalReady: terminalReady, onInput: (data) => activeTerminal && onPtyInput(activeTerminal.id, data), onResize: (cols, rows) => activeTerminal && onPtyResize(activeTerminal.id, cols, rows) }) }))] })] }));
1883
+ }), rightPanelTab === 'files' && effectiveRoot && (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: () => handleToggleDirectory(effectiveRoot), className: "w-full flex items-center gap-1.5 px-2 py-1.5 text-white/68 hover:text-white hover:bg-white/[0.04] rounded-md transition-colors text-left", children: [_jsx(ChevronDownIcon, { className: `w-3 h-3 flex-shrink-0 transition-transform ${expandedPaths.has(effectiveRoot) ? '' : '-rotate-90'}` }), expandedPaths.has(effectiveRoot) ? (_jsx(FolderOpen, { className: "w-3.5 h-3.5 flex-shrink-0 text-white/55", strokeWidth: 1.8 })) : (_jsx(Folder, { className: "w-3.5 h-3.5 flex-shrink-0 text-white/45", strokeWidth: 1.8 })), _jsx("span", { className: "min-w-0 truncate text-[12px]", children: directoryLeafName(effectiveRoot) })] }), expandedPaths.has(effectiveRoot) && (_jsxs("div", { className: "mt-0.5", children: [isRootLoading && (_jsx(FolderTreeLoadingSkeleton, { depth: 1, rows: 5 })), !isRootLoading && loadErrors[effectiveRoot] && (_jsx("div", { className: "pl-7 py-1 text-[11px] text-red-300/45", children: loadErrors[effectiveRoot] })), !isRootLoading && !loadErrors[effectiveRoot] && (entriesByPath[effectiveRoot] || []).map((entry) => (_jsx(FolderTreeNode, { entry: entry, depth: 1, expandedPaths: expandedPaths, loadingPaths: loadingPaths, loadErrors: loadErrors, entriesByPath: entriesByPath, onToggleDirectory: handleToggleDirectory, onOpenFile: onOpenFile, activeFilePath: activeFilePath }, entry.path)))] }))] })), rightPanelTab === 'files' && !effectiveRoot && (_jsxs("div", { className: "mt-2 rounded-md border border-white/[0.06] bg-white/[0.02] p-3", children: [_jsx("p", { className: "text-[11px] uppercase tracking-[0.18em] text-white/28", children: "Folder Explorer" }), _jsx("p", { className: "mt-2 text-[12px] leading-relaxed text-white/42", children: "Open a folder for this conversation to browse files here and send them into the editor." }), _jsxs("div", { className: "mt-3 space-y-2", children: [_jsx(SkeletonBlock, { className: "h-3 w-[78%]" }), _jsx(SkeletonBlock, { className: "h-3 w-[66%]" }), _jsx(SkeletonBlock, { className: "h-3 w-[72%]" })] })] })), activeTerminalTabId && (_jsx(React.Suspense, { fallback: _jsx("div", { className: "h-full bg-[#050506] px-3 py-2 font-mono text-[12px] text-white/40", children: "Loading terminal..." }), children: _jsx(AgentPtyTerminalPanel, { terminalKey: activeTerminal?.id || null, terminalId: activeTerminal?.terminalId || null, output: activeTerminal?.output || '', terminalCapabilityEnabled: activeTerminal?.kind === 'provider-session' ? true : terminalCapabilityEnabled, terminalReady: activeTerminal?.kind === 'provider-session' ? providerSessionTuiReady : terminalReady, onInput: (data) => activeTerminal && onPtyInput(activeTerminal.id, data), onResize: (cols, rows) => activeTerminal && onPtyResize(activeTerminal.id, cols, rows) }) }))] })] }));
1865
1884
  }
1866
1885
  function RightSidebarControls({ folderPanelOpen, onOpenFolderPanel, }) {
1867
1886
  return (_jsxs("div", { className: "absolute top-2 right-3 z-20 flex items-center gap-1.5", children: [_jsx("button", { className: "h-[34px] w-[34px] inline-flex items-center justify-center text-white/35 hover:text-white/60 transition-colors", title: "Sidebar options", "aria-label": "Sidebar options", type: "button", children: _jsx(MoreHorizontal, { className: "w-4 h-4", strokeWidth: 1.8 }) }), !folderPanelOpen && (_jsx("button", { onClick: onOpenFolderPanel, className: "h-[34px] w-[34px] inline-flex items-center justify-center transition-colors text-white/45 hover:text-white/75", title: "Open right sidebar", "aria-label": "Open right sidebar", type: "button", children: _jsx(PanelRightOpen, { className: "w-4 h-4", strokeWidth: 1.8 }) }))] }));
@@ -3249,6 +3268,15 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3249
3268
  const conversationId = existing?.id || createConversation(MAIN_ASSISTANT_ID);
3250
3269
  setViewMode('inbox');
3251
3270
  setSelectedInboxConversationId(conversationId);
3271
+ updateConversation(conversationId, {
3272
+ model: MAIN_ASSISTANT_MODEL,
3273
+ runtime: createConversationRuntimeBinding({
3274
+ selection: runtimeSelectionForSdk('user'),
3275
+ model: MAIN_ASSISTANT_MODEL,
3276
+ reasoningModel: MAIN_ASSISTANT_MODEL,
3277
+ inferenceMode: 'cloud',
3278
+ }),
3279
+ });
3252
3280
  const attach = getAgentPlatformBridge()?.agent?.attachSdkSession;
3253
3281
  if (!attach) {
3254
3282
  appendMessage(conversationId, {
@@ -3375,6 +3403,8 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3375
3403
  const activeConversationAllowedDirectories = useMemo(() => {
3376
3404
  if (!activeConversation)
3377
3405
  return [];
3406
+ if (activeConversation.workspaceMode === 'chat-only')
3407
+ return [];
3378
3408
  const granted = (activeConversation.grantedDirectories || [])
3379
3409
  .map((dir) => normalizeDirectoryPath(dir))
3380
3410
  .filter(Boolean);
@@ -3398,6 +3428,44 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3398
3428
  },
3399
3429
  });
3400
3430
  }, [activeConversationId, updateConversation]);
3431
+ useEffect(() => {
3432
+ if (!activeConversationId)
3433
+ return;
3434
+ const workspace = getAgentPlatformBridge().workspace;
3435
+ if (!workspace.conversationResume || !workspace.providerLanesList)
3436
+ return;
3437
+ let cancelled = false;
3438
+ void workspace.conversationResume({ conversationId: activeConversationId }).then(async (resumed) => {
3439
+ if (cancelled || !resumed.success || !resumed.hostStorageIdentity)
3440
+ return;
3441
+ const listed = await workspace.providerLanesList({
3442
+ conversationId: activeConversationId,
3443
+ includeHistorical: true,
3444
+ });
3445
+ if (cancelled || !listed.success)
3446
+ return;
3447
+ const conversation = useAgentChatStore.getState().getConversation(activeConversationId);
3448
+ if (!conversation)
3449
+ return;
3450
+ const lanes = listed.lanes || resumed.lanes || [];
3451
+ const activeLane = lanes.find((lane) => lane.laneId === listed.activeLaneId) || resumed.activeLane;
3452
+ updateConversation(activeConversationId, {
3453
+ sessionUi: {
3454
+ ...(conversation.sessionUi || {}),
3455
+ hostBinding: {
3456
+ schemaVersion: 1,
3457
+ conversationId: activeConversationId,
3458
+ hostStorageIdentity: resumed.hostStorageIdentity,
3459
+ },
3460
+ ...(activeLane ? { activeLane } : {}),
3461
+ lanes,
3462
+ },
3463
+ });
3464
+ });
3465
+ return () => {
3466
+ cancelled = true;
3467
+ };
3468
+ }, [activeConversationId, updateConversation]);
3401
3469
  const workbenchPanelTab = activeSessionUi.panelTab || 'trace';
3402
3470
  const selectedTraceMessageId = activeSessionUi.selectedTraceMessageId || null;
3403
3471
  const terminalHistory = activeSessionUi.terminalHistory || [];
@@ -3444,7 +3512,14 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3444
3512
  return DEFAULT_AGENT_CAPABILITIES;
3445
3513
  }, [selectedAgentId, viewMode, workspaces]);
3446
3514
  const terminalCapabilityEnabled = !!activeAgentCapabilities.terminal;
3447
- const terminalReady = terminalCapabilityEnabled && activeConversationAllowedDirectories.length > 0;
3515
+ const terminalReady = terminalCapabilityEnabled && Boolean(resolvedTerminalCwd || activeConversationId);
3516
+ const activeLane = activeSessionUi.activeLane;
3517
+ const guiOwnsActiveProviderSession = Boolean(activeRuntimeRequestId && activeRuntimeConversationId === activeConversationId);
3518
+ const providerSessionTuiReady = Boolean(activeConversationId
3519
+ && activeLane?.laneId
3520
+ && !guiOwnsActiveProviderSession
3521
+ && getAgentPlatformBridge().workspace.providerNativeAttach
3522
+ && (activeLane.status === 'new' || activeLane.status === 'clean'));
3448
3523
  const rightPanelPtyAllowedKey = useMemo(() => activeConversationAllowedDirectories.map(normalizeDirectoryPath).join('|'), [activeConversationAllowedDirectories]);
3449
3524
  useEffect(() => {
3450
3525
  rightPanelTerminalsRef.current = rightPanelTerminals;
@@ -3464,7 +3539,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3464
3539
  terminalId: null,
3465
3540
  starting: false,
3466
3541
  exited: true,
3467
- output: entry.output || '[PowerShell session is no longer available.]\r\n',
3542
+ output: entry.output || `[${entry.kind === 'provider-session' ? (entry.label || 'Provider TUI') : 'PowerShell'} session is no longer available.]\r\n`,
3468
3543
  };
3469
3544
  }
3470
3545
  return {
@@ -3485,6 +3560,24 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3485
3560
  : tab)));
3486
3561
  });
3487
3562
  getAgentPlatformBridge().workspace.onPtyExit((payload) => {
3563
+ const exitedTab = rightPanelTerminalsRef.current.find((tab) => tab.terminalId === payload.terminalId);
3564
+ if (exitedTab?.kind === 'provider-session' && exitedTab.laneId) {
3565
+ const conversation = useAgentChatStore.getState().getConversation(exitedTab.conversationId);
3566
+ const lane = conversation?.sessionUi?.activeLane;
3567
+ if (lane?.laneId === exitedTab.laneId) {
3568
+ useAgentChatStore.getState().updateConversation(exitedTab.conversationId, {
3569
+ sessionUi: {
3570
+ ...(conversation?.sessionUi || {}),
3571
+ activeLane: {
3572
+ ...lane,
3573
+ status: 'externally_advanced',
3574
+ revision: (exitedTab.expectedLaneRevision ?? lane.revision) + 1,
3575
+ invalidationReason: 'Native provider TUI exited; reconcile before continuing in chat.',
3576
+ },
3577
+ },
3578
+ });
3579
+ }
3580
+ }
3488
3581
  setRightPanelTerminals((current) => current.map((tab) => (tab.terminalId === payload.terminalId
3489
3582
  ? {
3490
3583
  ...tab,
@@ -3497,14 +3590,14 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3497
3590
  });
3498
3591
  return () => {
3499
3592
  // Do not stop PTYs here. AgentInterface can unmount when switching app tabs;
3500
- // each PowerShell tab owns its process until the tab is explicitly closed.
3593
+ // each terminal tab owns its process until the tab is explicitly closed.
3501
3594
  getAgentPlatformBridge().workspace.offPtyData();
3502
3595
  getAgentPlatformBridge().workspace.offPtyExit();
3503
3596
  };
3504
3597
  }, []);
3505
- const startRightPanelTerminal = useCallback((tabId, conversationId, cwd, allowedDirs) => {
3598
+ const startRightPanelTerminal = useCallback((tabId, conversationId, cwd, allowedDirs, profile) => {
3506
3599
  const allowedDirsForStart = allowedDirs.length > 0 ? allowedDirs : [cwd].filter(Boolean);
3507
- if (!cwd || allowedDirsForStart.length === 0) {
3600
+ if (!profile && !cwd && allowedDirsForStart.length === 0 && !conversationId) {
3508
3601
  setRightPanelTerminals((current) => current.map((tab) => (tab.id === tabId
3509
3602
  ? {
3510
3603
  ...tab,
@@ -3515,16 +3608,43 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3515
3608
  : tab)));
3516
3609
  return;
3517
3610
  }
3518
- void getAgentPlatformBridge().workspace.ptyStart({
3519
- cwd,
3520
- allowedDirs: allowedDirsForStart,
3521
- cols: 80,
3522
- rows: 24,
3523
- }).then((result) => {
3611
+ const nativeAttach = getAgentPlatformBridge().workspace.providerNativeAttach;
3612
+ const start = profile
3613
+ ? nativeAttach
3614
+ ? nativeAttach({
3615
+ conversationId,
3616
+ laneId: profile.laneId,
3617
+ expectedLaneRevision: profile.expectedLaneRevision,
3618
+ cols: 80,
3619
+ rows: 24,
3620
+ })
3621
+ : Promise.resolve({
3622
+ success: false,
3623
+ code: 'NATIVE_TUI_UNSUPPORTED',
3624
+ error: 'Native provider TUI handoff is unavailable on this host.',
3625
+ terminalId: undefined,
3626
+ })
3627
+ : getAgentPlatformBridge().workspace.ptyStart({
3628
+ conversationId,
3629
+ cwd: cwd || undefined,
3630
+ allowedDirs: allowedDirsForStart,
3631
+ cols: 80,
3632
+ rows: 24,
3633
+ });
3634
+ void start.then((result) => {
3524
3635
  const tabStillExists = rightPanelTerminalsRef.current.some((tab) => tab.id === tabId);
3525
3636
  if (!tabStillExists) {
3526
- if (result?.terminalId)
3637
+ if (result?.terminalId && profile) {
3638
+ void getAgentPlatformBridge().workspace.providerNativeStop?.({
3639
+ conversationId,
3640
+ laneId: profile.laneId,
3641
+ terminalId: result.terminalId,
3642
+ reason: 'The requesting terminal tab was closed during launch.',
3643
+ });
3644
+ }
3645
+ else if (result?.terminalId) {
3527
3646
  void getAgentPlatformBridge().workspace.ptyStop({ terminalId: result.terminalId });
3647
+ }
3528
3648
  return;
3529
3649
  }
3530
3650
  if (!result?.success || !result.terminalId) {
@@ -3533,7 +3653,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3533
3653
  ...tab,
3534
3654
  starting: false,
3535
3655
  exited: true,
3536
- output: tab.output + `${result?.error || 'Failed to preload PowerShell.'}\r\n`,
3656
+ output: tab.output + `${result?.error || `Failed to start ${profile ? 'native provider TUI' : 'PowerShell'}.`}\r\n`,
3537
3657
  }
3538
3658
  : tab)));
3539
3659
  return;
@@ -3542,11 +3662,26 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3542
3662
  ? {
3543
3663
  ...tab,
3544
3664
  terminalId: result.terminalId,
3545
- cwd: result.cwd || cwd,
3665
+ cwd: ('cwd' in result && result.cwd) || cwd,
3666
+ ...(profile && 'laneRevision' in result && typeof result.laneRevision === 'number'
3667
+ ? { expectedLaneRevision: result.laneRevision }
3668
+ : {}),
3546
3669
  starting: false,
3547
3670
  exited: false,
3548
3671
  }
3549
3672
  : tab)));
3673
+ if (profile && 'laneRevision' in result && typeof result.laneRevision === 'number') {
3674
+ const conversation = useAgentChatStore.getState().getConversation(conversationId);
3675
+ const lane = conversation?.sessionUi?.activeLane;
3676
+ if (lane?.laneId === profile.laneId) {
3677
+ useAgentChatStore.getState().updateConversation(conversationId, {
3678
+ sessionUi: {
3679
+ ...(conversation?.sessionUi || {}),
3680
+ activeLane: { ...lane, status: 'active_native', revision: result.laneRevision },
3681
+ },
3682
+ });
3683
+ }
3684
+ }
3550
3685
  });
3551
3686
  }, []);
3552
3687
  const handleCreateRightPanelTerminal = useCallback(() => {
@@ -3559,6 +3694,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3559
3694
  const tab = {
3560
3695
  id: tabId,
3561
3696
  label: existingCount === 0 ? 'PowerShell' : `PowerShell ${existingCount + 1}`,
3697
+ kind: 'shell',
3562
3698
  conversationId: activeConversationId,
3563
3699
  terminalId: null,
3564
3700
  cwd,
@@ -3579,22 +3715,66 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3579
3715
  terminalCapabilityEnabled,
3580
3716
  terminalReady,
3581
3717
  ]);
3718
+ const handleCreateProviderSessionTui = useCallback(() => {
3719
+ const lane = activeSessionUi.activeLane;
3720
+ if (!activeConversationId || !lane?.laneId || guiOwnsActiveProviderSession)
3721
+ return null;
3722
+ const existing = rightPanelTerminalsRef.current.find((tab) => (tab.conversationId === activeConversationId
3723
+ && tab.kind === 'provider-session'
3724
+ && tab.laneId === lane.laneId));
3725
+ if (existing) {
3726
+ if (existing.exited && !existing.starting) {
3727
+ const cwd = existing.cwd || resolvedTerminalCwd || activeConversationAllowedDirectories[0] || '';
3728
+ setRightPanelTerminals((current) => current.map((tab) => (tab.id === existing.id
3729
+ ? { ...tab, starting: true, exited: false, output: '' }
3730
+ : tab)));
3731
+ startRightPanelTerminal(existing.id, activeConversationId, cwd, activeConversationAllowedDirectories, { kind: 'provider-session', laneId: lane.laneId, expectedLaneRevision: lane.revision });
3732
+ }
3733
+ return existing.id;
3734
+ }
3735
+ const cwd = resolvedTerminalCwd || activeConversationAllowedDirectories[0] || '';
3736
+ const tabId = `provider-tui-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
3737
+ const tab = {
3738
+ id: tabId,
3739
+ label: lane.providerDisplayName ? `${lane.providerDisplayName} TUI` : 'Provider TUI',
3740
+ kind: 'provider-session',
3741
+ conversationId: activeConversationId,
3742
+ terminalId: null,
3743
+ cwd,
3744
+ allowedKey: `provider-session:${lane.laneId}`,
3745
+ laneId: lane.laneId,
3746
+ expectedLaneRevision: lane.revision,
3747
+ output: '',
3748
+ starting: true,
3749
+ exited: false,
3750
+ };
3751
+ setRightPanelTerminals((current) => [...current, tab]);
3752
+ startRightPanelTerminal(tabId, activeConversationId, cwd, activeConversationAllowedDirectories, { kind: 'provider-session', laneId: lane.laneId, expectedLaneRevision: lane.revision });
3753
+ return tabId;
3754
+ }, [
3755
+ activeConversationAllowedDirectories,
3756
+ activeConversationId,
3757
+ activeSessionUi.activeLane,
3758
+ guiOwnsActiveProviderSession,
3759
+ resolvedTerminalCwd,
3760
+ startRightPanelTerminal,
3761
+ ]);
3582
3762
  useEffect(() => {
3583
3763
  if (!activeConversationId)
3584
3764
  return;
3585
3765
  if (!terminalCapabilityEnabled || !terminalReady) {
3586
- const tabsForConversation = rightPanelTerminalsRef.current.filter((tab) => tab.conversationId === activeConversationId);
3766
+ const tabsForConversation = rightPanelTerminalsRef.current.filter((tab) => (tab.conversationId === activeConversationId && tab.kind === 'shell'));
3587
3767
  for (const tab of tabsForConversation) {
3588
3768
  if (tab.terminalId)
3589
3769
  void getAgentPlatformBridge().workspace.ptyStop({ terminalId: tab.terminalId });
3590
3770
  }
3591
3771
  if (tabsForConversation.length > 0) {
3592
- setRightPanelTerminals((current) => current.filter((tab) => tab.conversationId !== activeConversationId));
3772
+ setRightPanelTerminals((current) => current.filter((tab) => (tab.conversationId !== activeConversationId || tab.kind !== 'shell')));
3593
3773
  }
3594
3774
  return;
3595
3775
  }
3596
3776
  const current = rightPanelTerminalsRef.current;
3597
- const conversationTabs = current.filter((tab) => tab.conversationId === activeConversationId);
3777
+ const conversationTabs = current.filter((tab) => (tab.conversationId === activeConversationId && tab.kind === 'shell'));
3598
3778
  const validTabs = conversationTabs.filter((tab) => tab.allowedKey === rightPanelPtyAllowedKey);
3599
3779
  const staleTabs = conversationTabs.filter((tab) => tab.allowedKey !== rightPanelPtyAllowedKey);
3600
3780
  for (const tab of staleTabs) {
@@ -3603,11 +3783,13 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3603
3783
  }
3604
3784
  if (staleTabs.length > 0) {
3605
3785
  setRightPanelTerminals((latest) => latest.filter((tab) => (tab.conversationId !== activeConversationId ||
3786
+ tab.kind !== 'shell' ||
3606
3787
  tab.allowedKey === rightPanelPtyAllowedKey)));
3607
3788
  }
3608
3789
  if (validTabs.length === 0) {
3609
3790
  queueMicrotask(() => {
3610
3791
  const stillMissing = !rightPanelTerminalsRef.current.some((tab) => (tab.conversationId === activeConversationId &&
3792
+ tab.kind === 'shell' &&
3611
3793
  tab.allowedKey === rightPanelPtyAllowedKey));
3612
3794
  if (stillMissing)
3613
3795
  handleCreateRightPanelTerminal();
@@ -3620,6 +3802,29 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3620
3802
  terminalCapabilityEnabled,
3621
3803
  terminalReady,
3622
3804
  ]);
3805
+ useEffect(() => {
3806
+ if (!activeConversationId)
3807
+ return;
3808
+ const activeLaneId = activeSessionUi.activeLane?.laneId;
3809
+ const staleProviderTabs = rightPanelTerminalsRef.current.filter((tab) => (tab.conversationId === activeConversationId
3810
+ && tab.kind === 'provider-session'
3811
+ && (!activeLaneId || tab.laneId !== activeLaneId)));
3812
+ for (const tab of staleProviderTabs) {
3813
+ if (tab.terminalId && tab.laneId) {
3814
+ void getAgentPlatformBridge().workspace.providerNativeStop?.({
3815
+ conversationId: tab.conversationId,
3816
+ laneId: tab.laneId,
3817
+ terminalId: tab.terminalId,
3818
+ reason: 'The active provider lane changed.',
3819
+ });
3820
+ }
3821
+ }
3822
+ if (staleProviderTabs.length > 0) {
3823
+ setRightPanelTerminals((current) => current.filter((tab) => (tab.conversationId !== activeConversationId
3824
+ || tab.kind !== 'provider-session'
3825
+ || (!!activeLaneId && tab.laneId === activeLaneId))));
3826
+ }
3827
+ }, [activeConversationId, activeSessionUi.activeLane?.laneId]);
3623
3828
  const handleRightPanelPtyInput = useCallback((tabId, data) => {
3624
3829
  const terminalId = rightPanelTerminalsRef.current.find((tab) => tab.id === tabId)?.terminalId;
3625
3830
  if (!terminalId)
@@ -3634,8 +3839,17 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3634
3839
  }, []);
3635
3840
  const handleCloseRightPanelTerminal = useCallback((tabId) => {
3636
3841
  const tab = rightPanelTerminalsRef.current.find((entry) => entry.id === tabId);
3637
- if (tab?.terminalId)
3842
+ if (tab?.terminalId && tab.kind === 'provider-session' && tab.laneId) {
3843
+ void getAgentPlatformBridge().workspace.providerNativeStop?.({
3844
+ conversationId: tab.conversationId,
3845
+ laneId: tab.laneId,
3846
+ terminalId: tab.terminalId,
3847
+ reason: 'The provider TUI tab was closed.',
3848
+ });
3849
+ }
3850
+ else if (tab?.terminalId) {
3638
3851
  void getAgentPlatformBridge().workspace.ptyStop({ terminalId: tab.terminalId });
3852
+ }
3639
3853
  setRightPanelTerminals((current) => current.filter((entry) => entry.id !== tabId));
3640
3854
  }, []);
3641
3855
  const handleClearRightPanelTerminal = useCallback((tabId) => {
@@ -3648,17 +3862,82 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
3648
3862
  const tab = rightPanelTerminalsRef.current.find((entry) => entry.id === tabId);
3649
3863
  if (!tab || tab.conversationId !== activeConversationId)
3650
3864
  return;
3865
+ const activeLane = activeSessionUi.activeLane;
3866
+ if (tab.kind === 'provider-session' && (!activeLane?.laneId || tab.laneId !== activeLane.laneId)) {
3867
+ handleCloseRightPanelTerminal(tabId);
3868
+ return;
3869
+ }
3651
3870
  const oldTerminalId = tab.terminalId;
3652
3871
  const cwd = tab.cwd || resolvedTerminalCwd || activeConversationAllowedDirectories[0] || '';
3872
+ if (tab.kind === 'provider-session' && tab.laneId) {
3873
+ if (oldTerminalId) {
3874
+ void getAgentPlatformBridge().workspace.providerNativeStop?.({
3875
+ conversationId: tab.conversationId,
3876
+ laneId: tab.laneId,
3877
+ terminalId: oldTerminalId,
3878
+ reason: 'The user requested a native provider TUI restart.',
3879
+ });
3880
+ return;
3881
+ }
3882
+ const reconcile = getAgentPlatformBridge().workspace.providerReconcile;
3883
+ if (!reconcile || !activeLane)
3884
+ return;
3885
+ setRightPanelTerminals((current) => current.map((entry) => (entry.id === tabId
3886
+ ? { ...entry, starting: true, output: `${entry.output}\r\n[reconciling native provider session]\r\n` }
3887
+ : entry)));
3888
+ void reconcile({
3889
+ conversationId: tab.conversationId,
3890
+ laneId: tab.laneId,
3891
+ expectedLaneRevision: activeLane.revision,
3892
+ acknowledgePartialContext: true,
3893
+ }).then((result) => {
3894
+ if (!result.success || !result.lane) {
3895
+ setRightPanelTerminals((current) => current.map((entry) => (entry.id === tabId
3896
+ ? { ...entry, starting: false, exited: true, output: `${entry.output}[${result.error || 'Provider reconciliation failed.'}]\r\n` }
3897
+ : entry)));
3898
+ return;
3899
+ }
3900
+ const conversation = useAgentChatStore.getState().getConversation(tab.conversationId);
3901
+ useAgentChatStore.getState().updateConversation(tab.conversationId, {
3902
+ sessionUi: {
3903
+ ...(conversation?.sessionUi || {}),
3904
+ activeLane: result.lane,
3905
+ lanes: [
3906
+ ...((conversation?.sessionUi?.lanes || []).filter((lane) => lane.laneId !== result.lane.laneId)),
3907
+ result.lane,
3908
+ ],
3909
+ },
3910
+ });
3911
+ setRightPanelTerminals((current) => current.map((entry) => (entry.id === tabId
3912
+ ? {
3913
+ ...entry,
3914
+ expectedLaneRevision: result.lane.revision,
3915
+ starting: false,
3916
+ exited: true,
3917
+ output: `${entry.output}[reconciled; chat may resume]\r\n`,
3918
+ }
3919
+ : entry)));
3920
+ });
3921
+ return;
3922
+ }
3653
3923
  setRightPanelTerminals((current) => current.map((entry) => (entry.id === tabId
3654
3924
  ? { ...entry, terminalId: null, cwd, output: '', starting: true, exited: false }
3655
3925
  : entry)));
3656
- if (oldTerminalId)
3926
+ if (oldTerminalId) {
3657
3927
  void getAgentPlatformBridge().workspace.ptyStop({ terminalId: oldTerminalId });
3658
- startRightPanelTerminal(tabId, tab.conversationId, cwd, activeConversationAllowedDirectories);
3659
- }, [activeConversationAllowedDirectories, activeConversationId, resolvedTerminalCwd, startRightPanelTerminal]);
3928
+ }
3929
+ startRightPanelTerminal(tabId, tab.conversationId, cwd, activeConversationAllowedDirectories, undefined);
3930
+ }, [activeConversationAllowedDirectories, activeConversationId, activeSessionUi.activeLane, handleCloseRightPanelTerminal, resolvedTerminalCwd, startRightPanelTerminal]);
3660
3931
  const rightPanelTerminalsForConversation = useMemo(() => (rightPanelTerminals.filter((tab) => (tab.conversationId === activeConversationId &&
3661
- tab.allowedKey === rightPanelPtyAllowedKey))), [activeConversationId, rightPanelPtyAllowedKey, rightPanelTerminals]);
3932
+ (tab.kind === 'provider-session'
3933
+ ? (activeLane?.laneId ? tab.laneId === activeLane.laneId : false)
3934
+ : tab.allowedKey === rightPanelPtyAllowedKey)))), [activeConversationId, activeLane?.laneId, rightPanelPtyAllowedKey, rightPanelTerminals]);
3935
+ const providerSessionTuiOwnsActiveSession = rightPanelTerminalsForConversation.some((tab) => (tab.kind === 'provider-session' && !tab.exited && (tab.starting || !!tab.terminalId)));
3936
+ const providerSessionTuiInputLockReason = providerSessionTuiOwnsActiveSession
3937
+ ? 'Native provider TUI owns this session. Exit or close the TUI before sending from chat.'
3938
+ : activeLane?.status === 'externally_advanced' || activeLane?.status === 'needs_reconciliation'
3939
+ ? 'The native provider session advanced outside chat. Use “Reconcile and return to chat” before continuing.'
3940
+ : undefined;
3662
3941
  const patchActiveConversationSessionUi = useCallback((patch) => {
3663
3942
  if (!activeConversationId)
3664
3943
  return;
@@ -5614,7 +5893,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
5614
5893
  }
5615
5894
  }, [handleSubagentRefresh, policyCaller, refreshSubagentAvailability, setTransientEditorStatus]);
5616
5895
  const handleOpenFolderForConversation = useCallback(async () => {
5617
- if (!activeConversationId)
5896
+ if (!activeConversationId || providerSessionTuiInputLockReason || activeRuntimeRequestId)
5618
5897
  return;
5619
5898
  const result = await getAgentPlatformBridge()?.workspace?.pickDirectory?.();
5620
5899
  if (!result?.success || !result.path)
@@ -5628,10 +5907,21 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
5628
5907
  viewMode,
5629
5908
  });
5630
5909
  updateConversation(activeConversationId, {
5910
+ schemaVersion: 3,
5911
+ workspaceMode: 'workspace',
5631
5912
  rootDirectory: normalizedDirectory,
5632
5913
  grantedDirectories: prioritizeDirectory(activeConversation?.grantedDirectories, normalizedDirectory),
5914
+ sessionUi: resetAcpContinuationForWorkspaceChange(activeConversation?.sessionUi),
5633
5915
  });
5634
- }, [activeConversation?.grantedDirectories, activeConversationId, updateConversation, viewMode]);
5916
+ }, [
5917
+ activeConversation?.grantedDirectories,
5918
+ activeConversation?.sessionUi,
5919
+ activeConversationId,
5920
+ activeRuntimeRequestId,
5921
+ providerSessionTuiInputLockReason,
5922
+ updateConversation,
5923
+ viewMode,
5924
+ ]);
5635
5925
  const handleEditorContentChange = useCallback((path, content) => {
5636
5926
  setOpenEditorTabs((prev) => prev.map((tab) => (tab.type === 'file' && tab.file.path === path
5637
5927
  ? { ...tab, file: { ...tab.file, content, isDirty: content !== tab.file.savedContent } }
@@ -7578,7 +7868,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
7578
7868
  }, teamId: settingsPanel.teamId, teamName: teamForSettings?.name || settingsPanel.teamName, onClose: handleCloseSettings, onDelete: handleDeleteFromSettings }));
7579
7869
  }
7580
7870
  if (viewMode === 'inbox') {
7581
- return (_jsx(React.Suspense, { fallback: _jsx("div", { className: "flex h-full items-center justify-center text-[12px] text-white/35", children: "Loading chat..." }), children: _jsx(AgentView, { agentId: MAIN_ASSISTANT_ID, conversationId: selectedInboxConversationId, isMainAssistant: true, agentName: MAIN_ASSISTANT_NAME, model: MAIN_ASSISTANT_MODEL, templateName: "Main Assistant", workspaceName: "All Workspaces", teamName: "Global", systemPrompt: enrichedMainSystemPromptWithCodeContext, capabilities: { terminal: true, fileRead: true, fileWrite: true, appLaunch: true }, permissionProfile: "standard", allowedDirectories: [], approvalRules: [], allowedApps: [], teamAgents: [], onCreateWorkspace: handleMainCreateWorkspace, onCreateTeam: handleMainCreateTeam, onCreateTeamAgent: handleMainCreateTeamAgent, onGetInboxWorkspaceOptions: handleGetInboxWorkspaceOptions, onBindInboxConversationToWorkspace: handleBindInboxConversationToWorkspace, onOpenReassignedConversation: handleOpenReassignedConversation, onOpenEditorPath: handleOpenEditorPath, onOpenEditorDiff: handleOpenEditorDiff, onPeekEditorPath: handlePeekEditorPath, onPeekEditorDiff: handlePeekEditorDiff, renderWorkbenchPanel: false, onOpenConversationSettings: handleSelectSidebarSettings, onConversationCreated: activateSessionConversation }) }));
7871
+ return (_jsx(React.Suspense, { fallback: _jsx("div", { className: "flex h-full items-center justify-center text-[12px] text-white/35", children: "Loading chat..." }), children: _jsx(AgentView, { agentId: MAIN_ASSISTANT_ID, conversationId: selectedInboxConversationId, isMainAssistant: true, agentName: MAIN_ASSISTANT_NAME, model: MAIN_ASSISTANT_MODEL, templateName: "Main Assistant", workspaceName: "All Workspaces", teamName: "Global", systemPrompt: enrichedMainSystemPromptWithCodeContext, capabilities: { terminal: true, fileRead: true, fileWrite: true, appLaunch: true }, permissionProfile: "standard", allowedDirectories: [], approvalRules: [], allowedApps: [], teamAgents: [], onCreateWorkspace: handleMainCreateWorkspace, onCreateTeam: handleMainCreateTeam, onCreateTeamAgent: handleMainCreateTeamAgent, onGetInboxWorkspaceOptions: handleGetInboxWorkspaceOptions, onBindInboxConversationToWorkspace: handleBindInboxConversationToWorkspace, onOpenReassignedConversation: handleOpenReassignedConversation, onOpenEditorPath: handleOpenEditorPath, onOpenEditorDiff: handleOpenEditorDiff, onPeekEditorPath: handlePeekEditorPath, onPeekEditorDiff: handlePeekEditorDiff, renderWorkbenchPanel: false, onOpenConversationSettings: handleSelectSidebarSettings, externalInputLockReason: providerSessionTuiInputLockReason, onConversationCreated: activateSessionConversation }) }));
7582
7872
  }
7583
7873
  // If an agent is selected, show the chat view.
7584
7874
  // Conversation is created lazily on first message send.
@@ -7607,7 +7897,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
7607
7897
  sp += `\n\nInstalled XENO apps: ${runtimeContext.installedApps.join(', ')}`;
7608
7898
  }
7609
7899
  return sp || undefined;
7610
- })()), templateName: selectedAgent.templateName, workspaceName: selectedAgent.workspaceName, teamName: selectedAgent.teamName, capabilities: selectedAgent.capabilities, permissionProfile: selectedAgent.permissionProfile || 'standard', runtimeSelection: selectedAgent.runtimeSelection, allowedDirectories: selectedAgent.allowedDirectories, approvalRules: selectedAgent.approvalRules || [], onAddApprovalRule: (rule) => {
7900
+ })()), templateName: selectedAgent.templateName, workspaceName: selectedAgent.workspaceName, teamName: selectedAgent.teamName, capabilities: selectedAgent.capabilities, permissionProfile: selectedAgent.permissionProfile || 'standard', runtimeSelection: selectedAgent.runtimeSelection, externalInputLockReason: providerSessionTuiInputLockReason, allowedDirectories: selectedAgent.allowedDirectories, approvalRules: selectedAgent.approvalRules || [], onAddApprovalRule: (rule) => {
7611
7901
  addAgentApprovalRule(selectedAgentHierarchy.workspace.id, selectedAgentHierarchy.team.id, selectedAgent.id, rule);
7612
7902
  }, allowedApps: resolvedAllowedApps, teamAgents: teamAgents, onCreateAgent: handleCreateAgentFromAgent, onAskAgent: handleAskAgentFromAgent, onEnableFileWrite: enableSelectedAgentFileWrite, onOpenEditorPath: handleOpenEditorPath, onOpenEditorDiff: handleOpenEditorDiff, onPeekEditorPath: handlePeekEditorPath, onPeekEditorDiff: handlePeekEditorDiff, onOpenRuntimeSettings: () => {
7613
7903
  handleOpenSettings({
@@ -7673,7 +7963,7 @@ export default function AgentInterface({ surface = 'embedded', initialSdkSession
7673
7963
  `subagentRunId ?? conversationId`, so the conversation id
7674
7964
  IS the run id here. Passing anything else would ask the
7675
7965
  host about a run it has never heard of. */
7676
- reviewRunId: activeConversationId, traceMessages: traceMessages, selectedTraceMessage: selectedTraceMessage, outputEntries: outputEntries, problemEntries: problemEntries, onSelectTab: handleSelectWorkbenchTab, onClose: handleCloseWorkbenchPanel, onSelectTraceMessage: handleSelectWorkbenchTraceMessage, onOpenChatSettings: handleOpenActiveConversationSettings, onOpenChatAcpAgents: handleOpenActiveConversationAcpAgents, onOpenChatPlugins: handleOpenPluginManager, onOpenChatKnowledge: handleOpenActiveConversationKnowledge, onOpenEditorPath: handleOpenEditorPath, onOpenEditorDiff: handleOpenEditorDiff, terminalCapabilityEnabled: terminalCapabilityEnabled, terminalReady: terminalReady, resolvedTerminalCwd: resolvedTerminalCwd, terminalDraftCwd: terminalDraftCwd, terminalDraftInput: terminalDraftInput, onChangeTerminalCwd: setTerminalDraftCwd, onChangeTerminalInput: setTerminalDraftInput, onResetTerminalCwd: handleResetWorkbenchTerminalCwd, onClearTerminalHistory: handleClearWorkbenchTerminalHistory, onRunTerminalCommand: () => { void handleRunWorkbenchTerminalCommand(); }, terminalHistory: terminalHistory, liveTerminalRuns: liveTerminalRunsForConversation, onReuseTerminalEntry: handleReuseWorkbenchTerminalEntry, onStopTerminalRun: (terminalId) => { void handleStopWorkbenchTerminalRun(terminalId); }, codeWorkbench: codeWorkbenchState, onCodeQueryChange: setCodeWorkbenchQuery, onCodeModeChange: handleCodeModeChange, onCodeIndex: handleCodeIndex, onCodeSearch: handleCodeSearch, onCodeOpenPath: handleCodeOpenPath, onCodeToggleFile: handleCodeToggleFile, onCodeToggleSymbol: handleCodeToggleSymbol, onCodeCreateContextPack: () => { void handleCodeCreateContextPack(); }, onCodeMaterializeContextPack: (packId) => { void handleCodeMaterializeContextPack(packId); }, onCodeAttachContextPack: (packId) => { void handleCodeAttachContextPack(packId); }, onCodeRefreshContextPacks: () => { void handleCodeRefreshContextPacks(); }, onCodeRefreshChanges: () => { void handleCodeRefreshChanges(); }, onCodeRefreshActions: () => { void handleCodeRefreshActions(); }, onCodeApplyAction: (action) => { void handleCodeApplyAction(action); }, onCodeOrganizeImports: () => { void handleCodeOrganizeImports(); }, onCodeRenameSymbol: () => { void handleCodeRenameSymbol(); }, onCodeRefreshLanguageServices: () => { void handleCodeRefreshLanguageServices(); }, onCodeControlLanguageService: (serviceId, action) => { void handleCodeControlLanguageService(serviceId, action); }, onCodeRepairIndex: () => { void handleCodeRepairIndex(); }, engineeringWorkbench: engineeringWorkbenchState, onEngineeringRefresh: () => { void handleEngineeringRefresh(); }, onEngineeringTogglePath: handleEngineeringTogglePath, onEngineeringOpenPath: handleEngineeringOpenPath, onEngineeringPreviewDiff: (paths) => { void handleEngineeringPreviewDiff(paths); }, onEngineeringStage: (paths) => { void handleEngineeringStage(paths); }, onEngineeringUnstage: (paths) => { void handleEngineeringUnstage(paths); }, onEngineeringRunCheck: (checkId) => { void handleEngineeringRunCheck(checkId); }, onEngineeringStartBackgroundCheck: (checkId) => { void handleEngineeringStartBackgroundCheck(checkId); }, onEngineeringStopBackgroundRun: (runId) => { void handleEngineeringStopBackgroundRun(runId); }, onEngineeringReadBackgroundRunOutput: (runId) => { void handleEngineeringReadBackgroundRunOutput(runId); }, onEngineeringCommitMessageChange: setEngineeringCommitMessage, onEngineeringCommit: () => { void handleEngineeringCommit(); }, onEngineeringQueuePatchReview: () => { void handleEngineeringQueuePatchReview(); }, onEngineeringUpdatePatchReview: (id, status) => { void handleEngineeringUpdatePatchReview(id, status); }, onEngineeringReviewPatchSelection: (request) => { void handleEngineeringReviewPatchSelection(request); }, onEngineeringCompareCheckpoints: (fromCheckpointId, toCheckpointId) => { void handleEngineeringCompareCheckpoints(fromCheckpointId, toCheckpointId); }, onEngineeringRestoreCheckpoint: (checkpointId) => { void handleEngineeringRestoreCheckpoint(checkpointId); }, cliControlPlane: cliControlPlaneState, cliControlPlaneCaller: policyCaller, cliControlPlaneConversationId: activeConversationId, cliControlPlaneRemoteBackendId: selectedAgent?.runtimeSelection?.remoteBackendId || '', onCliControlPlaneInspect: () => { void handleCliControlPlaneInspect(); }, onCliControlPlaneInspectOperation: (operation) => { void handleCliControlPlaneInspectOperation(operation); }, onCliControlPlaneRemoteRunOperation: (action, runId) => { void handleCliControlPlaneRemoteRunOperation(action, runId); }, subagentWorkbench: subagentWorkbenchState, subagentDelegationTargets: subagentDelegationTargets, subagentDelegationSourceName: selectedAgent?.name, subagentDelegationDisabledReason: subagentDelegationDisabledReason, onSubagentRefresh: () => { void handleSubagentRefresh(); }, onSubagentRecoverRuns: () => { void handleSubagentRecoverRuns(); }, onSubagentSelectRun: handleSubagentSelectRun, onSubagentOpenConversation: handleSubagentOpenConversation, onSubagentCancelRun: (run) => { void handleSubagentCancelRun(run); }, onCreateSubagentDelegation: handleWorkbenchSubagentDelegation, policyWorkbench: policyWorkbenchState, onPolicyRefresh: () => { void handlePolicyRefresh(); } }) }) }) }))] })] }), folderPanelOpen && (_jsx(FolderSidebar, { conversationId: activeConversationId, rootDirectory: activeConversation?.rootDirectory || null, allowedDirectories: activeConversationAllowedDirectories, onOpenFolder: handleOpenFolderForConversation, onClose: () => setFolderPanelOpen(false), onOpenFile: handleOpenEditorFile, activeFilePath: activeEditorFilePath, terminalCapabilityEnabled: terminalCapabilityEnabled, terminalReady: terminalReady, resolvedTerminalCwd: resolvedTerminalCwd, terminalTabs: rightPanelTerminalsForConversation, onPtyInput: handleRightPanelPtyInput, onPtyResize: handleRightPanelPtyResize, onCreateTerminal: handleCreateRightPanelTerminal, onCloseTerminal: handleCloseRightPanelTerminal, onClearTerminal: handleClearRightPanelTerminal, onRestartTerminal: handleRestartRightPanelTerminal, width: rightPanelWidth, onResizeStart: handleRightPanelResizeStart })), rightPanelResizing && (_jsx("div", { className: "fixed inset-0 z-[9999] cursor-col-resize bg-transparent", "aria-hidden": "true" })), pendingPermission && (_jsx(PermissionDialog, { request: pendingPermission, onDecision: resolvePermission }))] }));
7966
+ reviewRunId: activeConversationId, traceMessages: traceMessages, selectedTraceMessage: selectedTraceMessage, outputEntries: outputEntries, problemEntries: problemEntries, onSelectTab: handleSelectWorkbenchTab, onClose: handleCloseWorkbenchPanel, onSelectTraceMessage: handleSelectWorkbenchTraceMessage, onOpenChatSettings: handleOpenActiveConversationSettings, onOpenChatAcpAgents: handleOpenActiveConversationAcpAgents, onOpenChatPlugins: handleOpenPluginManager, onOpenChatKnowledge: handleOpenActiveConversationKnowledge, onOpenEditorPath: handleOpenEditorPath, onOpenEditorDiff: handleOpenEditorDiff, terminalCapabilityEnabled: terminalCapabilityEnabled, terminalReady: terminalReady, resolvedTerminalCwd: resolvedTerminalCwd, terminalDraftCwd: terminalDraftCwd, terminalDraftInput: terminalDraftInput, onChangeTerminalCwd: setTerminalDraftCwd, onChangeTerminalInput: setTerminalDraftInput, onResetTerminalCwd: handleResetWorkbenchTerminalCwd, onClearTerminalHistory: handleClearWorkbenchTerminalHistory, onRunTerminalCommand: () => { void handleRunWorkbenchTerminalCommand(); }, terminalHistory: terminalHistory, liveTerminalRuns: liveTerminalRunsForConversation, onReuseTerminalEntry: handleReuseWorkbenchTerminalEntry, onStopTerminalRun: (terminalId) => { void handleStopWorkbenchTerminalRun(terminalId); }, codeWorkbench: codeWorkbenchState, onCodeQueryChange: setCodeWorkbenchQuery, onCodeModeChange: handleCodeModeChange, onCodeIndex: handleCodeIndex, onCodeSearch: handleCodeSearch, onCodeOpenPath: handleCodeOpenPath, onCodeToggleFile: handleCodeToggleFile, onCodeToggleSymbol: handleCodeToggleSymbol, onCodeCreateContextPack: () => { void handleCodeCreateContextPack(); }, onCodeMaterializeContextPack: (packId) => { void handleCodeMaterializeContextPack(packId); }, onCodeAttachContextPack: (packId) => { void handleCodeAttachContextPack(packId); }, onCodeRefreshContextPacks: () => { void handleCodeRefreshContextPacks(); }, onCodeRefreshChanges: () => { void handleCodeRefreshChanges(); }, onCodeRefreshActions: () => { void handleCodeRefreshActions(); }, onCodeApplyAction: (action) => { void handleCodeApplyAction(action); }, onCodeOrganizeImports: () => { void handleCodeOrganizeImports(); }, onCodeRenameSymbol: () => { void handleCodeRenameSymbol(); }, onCodeRefreshLanguageServices: () => { void handleCodeRefreshLanguageServices(); }, onCodeControlLanguageService: (serviceId, action) => { void handleCodeControlLanguageService(serviceId, action); }, onCodeRepairIndex: () => { void handleCodeRepairIndex(); }, engineeringWorkbench: engineeringWorkbenchState, onEngineeringRefresh: () => { void handleEngineeringRefresh(); }, onEngineeringTogglePath: handleEngineeringTogglePath, onEngineeringOpenPath: handleEngineeringOpenPath, onEngineeringPreviewDiff: (paths) => { void handleEngineeringPreviewDiff(paths); }, onEngineeringStage: (paths) => { void handleEngineeringStage(paths); }, onEngineeringUnstage: (paths) => { void handleEngineeringUnstage(paths); }, onEngineeringRunCheck: (checkId) => { void handleEngineeringRunCheck(checkId); }, onEngineeringStartBackgroundCheck: (checkId) => { void handleEngineeringStartBackgroundCheck(checkId); }, onEngineeringStopBackgroundRun: (runId) => { void handleEngineeringStopBackgroundRun(runId); }, onEngineeringReadBackgroundRunOutput: (runId) => { void handleEngineeringReadBackgroundRunOutput(runId); }, onEngineeringCommitMessageChange: setEngineeringCommitMessage, onEngineeringCommit: () => { void handleEngineeringCommit(); }, onEngineeringQueuePatchReview: () => { void handleEngineeringQueuePatchReview(); }, onEngineeringUpdatePatchReview: (id, status) => { void handleEngineeringUpdatePatchReview(id, status); }, onEngineeringReviewPatchSelection: (request) => { void handleEngineeringReviewPatchSelection(request); }, onEngineeringCompareCheckpoints: (fromCheckpointId, toCheckpointId) => { void handleEngineeringCompareCheckpoints(fromCheckpointId, toCheckpointId); }, onEngineeringRestoreCheckpoint: (checkpointId) => { void handleEngineeringRestoreCheckpoint(checkpointId); }, cliControlPlane: cliControlPlaneState, cliControlPlaneCaller: policyCaller, cliControlPlaneConversationId: activeConversationId, cliControlPlaneRemoteBackendId: selectedAgent?.runtimeSelection?.remoteBackendId || '', onCliControlPlaneInspect: () => { void handleCliControlPlaneInspect(); }, onCliControlPlaneInspectOperation: (operation) => { void handleCliControlPlaneInspectOperation(operation); }, onCliControlPlaneRemoteRunOperation: (action, runId) => { void handleCliControlPlaneRemoteRunOperation(action, runId); }, subagentWorkbench: subagentWorkbenchState, subagentDelegationTargets: subagentDelegationTargets, subagentDelegationSourceName: selectedAgent?.name, subagentDelegationDisabledReason: subagentDelegationDisabledReason, onSubagentRefresh: () => { void handleSubagentRefresh(); }, onSubagentRecoverRuns: () => { void handleSubagentRecoverRuns(); }, onSubagentSelectRun: handleSubagentSelectRun, onSubagentOpenConversation: handleSubagentOpenConversation, onSubagentCancelRun: (run) => { void handleSubagentCancelRun(run); }, onCreateSubagentDelegation: handleWorkbenchSubagentDelegation, policyWorkbench: policyWorkbenchState, onPolicyRefresh: () => { void handlePolicyRefresh(); } }) }) }) }))] })] }), folderPanelOpen && (_jsx(FolderSidebar, { conversationId: activeConversationId, rootDirectory: activeConversation?.rootDirectory || null, allowedDirectories: activeConversationAllowedDirectories, onOpenFolder: handleOpenFolderForConversation, onClose: () => setFolderPanelOpen(false), onOpenFile: handleOpenEditorFile, activeFilePath: activeEditorFilePath, terminalCapabilityEnabled: terminalCapabilityEnabled, terminalReady: terminalReady, providerSessionTuiReady: providerSessionTuiReady, resolvedTerminalCwd: resolvedTerminalCwd, terminalTabs: rightPanelTerminalsForConversation, onPtyInput: handleRightPanelPtyInput, onPtyResize: handleRightPanelPtyResize, onCreateTerminal: handleCreateRightPanelTerminal, onCreateProviderTui: handleCreateProviderSessionTui, onCloseTerminal: handleCloseRightPanelTerminal, onClearTerminal: handleClearRightPanelTerminal, onRestartTerminal: handleRestartRightPanelTerminal, width: rightPanelWidth, onResizeStart: handleRightPanelResizeStart })), rightPanelResizing && (_jsx("div", { className: "fixed inset-0 z-[9999] cursor-col-resize bg-transparent", "aria-hidden": "true" })), pendingPermission && (_jsx(PermissionDialog, { request: pendingPermission, onDecision: resolvePermission }))] }));
7677
7967
  if (surface !== 'standalone-desktop') {
7678
7968
  return (_jsxs("div", { className: "flex h-full w-full flex-col overflow-hidden", "data-xeno-agent-embedded-shell": "true", children: [_jsx("header", { className: "xeno-chrome-shell xeno-border-subtle h-10 flex-shrink-0 border-b", "data-xeno-agent-session-header": "embedded", "data-xeno-hub-header-style": "true", children: sessionTabsNode }), _jsx("div", { className: "min-h-0 min-w-0 flex-1", children: agentWorkspace })] }));
7679
7969
  }