Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/AgentPaneContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ namespace winrt::TerminalApp::implementation
// Update the cached pane-position. Fires StateChanged so the
// bottom bar can refresh its toggle-icon orientation.
void SetAgentPanePosition(const winrt::hstring& position);
void SetDurableSessionId(const winrt::hstring& sessionId) noexcept { _durableSessionId = sessionId; }
winrt::hstring DurableSessionId() const noexcept { return _durableSessionId; }
// --- Cross-window drag rename plumbing ---
// When a tab is dragged into this window, the source side has stashed
// the originating tab's StableId keyed by ContentId. The target
Expand Down Expand Up @@ -148,6 +150,9 @@ namespace winrt::TerminalApp::implementation
winrt::hstring _agentModel{};
winrt::hstring _agentState{};
winrt::hstring _agentBackend{};
// Empty for a pre-warmed session that has not processed a prompt.
// WTA only projects an ID after a real turn starts or a session is loaded.
winrt::hstring _durableSessionId{};

// When true, the bar replaces "<agent> <version>" with "Agent sessions"
// and hides the agent logo. Driven by TerminalPage::OnAgentStateChanged
Expand Down
7 changes: 5 additions & 2 deletions src/cascadia/TerminalApp/Pane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1355,10 +1355,13 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
// - splitType: How the pane should be attached
// Return Value:
// - the new reference to the child created from the current pane.
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
{
// Splice the new pane into the tree
const auto [first, _] = _Split(splitType, .5, pane);
const auto requestedSize = splitType == SplitDirection::Left || splitType == SplitDirection::Up ?
1.0f - splitSize :
splitSize;
const auto [first, _] = _Split(splitType, requestedSize, pane);

// If the new pane has a child that was the focus, re-focus it
// to steal focus from the currently focused pane.
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalApp/Pane.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ class Pane : public std::enable_shared_from_this<Pane>
void Close();

std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
float splitSize = 0.5f);
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);

bool RepositionAgentPane(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitDirection);
Expand Down
19 changes: 17 additions & 2 deletions src/cascadia/TerminalApp/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,8 @@ namespace winrt::TerminalApp::implementation
// Return Value:
// - a pair of (the Pane wrapping the original tree, the new Pane)
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Tab::SplitPaneAtRoot(SplitDirection splitType,
std::shared_ptr<Pane> pane)
std::shared_ptr<Pane> pane,
const float splitSize)
{
ASSERT_UI_THREAD();

Expand Down Expand Up @@ -803,7 +804,7 @@ namespace winrt::TerminalApp::implementation
// _firstChild and the new pane becomes _secondChild. Because _rootPane
// is modified in-place, Content() (which points to _rootPane->GetRootElement())
// remains valid without any re-parenting.
auto originalTree = _rootPane->AttachPane(pane, splitType);
auto originalTree = _rootPane->AttachPane(pane, splitType, splitSize);

// The split created a new wrapper pane for the original tree. Attach
// Tab event handlers so that focus changes are tracked correctly —
Expand Down Expand Up @@ -2521,6 +2522,20 @@ namespace winrt::TerminalApp::implementation
return nullptr;
}

float Tab::AgentPaneSize() const noexcept
{
if (const auto agentPane = FindAgentPane())
{
if (const auto parent = _rootPane->_FindParentOfPane(agentPane))
{
return parent->_firstChild == agentPane ?
parent->_desiredSplitPosition :
1.0f - parent->_desiredSplitPosition;
}
}
return 0.5f;
}

// Hide the agent pane without destroying it. The pane stays in the tab
// tree (so its TermControl + conpty + wta-helper child remain alive),
// but its parent split is rewritten so the sibling occupies the full
Expand Down
4 changes: 3 additions & 1 deletion src/cascadia/TerminalApp/Tab.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr<Pane> newPane);

std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> SplitPaneAtRoot(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
std::shared_ptr<Pane> newPane);
std::shared_ptr<Pane> newPane,
float splitSize = 0.5f);

void ToggleSplitOrientation();
void UpdateIcon(const winrt::hstring& iconPath, const winrt::Microsoft::Terminal::Settings::Model::IconStyle iconStyle);
Expand Down Expand Up @@ -109,6 +110,7 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::AgentPaneContent FindAgentPaneContent() const;
// Returns the Pane node hosting the AgentPaneContent, or nullptr.
std::shared_ptr<Pane> FindAgentPane() const;
float AgentPaneSize() const noexcept;

// Hide the agent pane without detaching it from the tree. The pane
// stays alive (so TermControl + conpty + wta-helper survive), but
Expand Down
80 changes: 79 additions & 1 deletion src/cascadia/TerminalApp/TabManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,30 @@ namespace winrt::TerminalApp::implementation

// This call to _MakePane won't return nullptr, we already checked that
// case above with the _maybeElevate call.
_CreateNewTabFromPane(_MakePane(newContentArgs, nullptr), -1, openInBackground);
const auto newTab = _CreateNewTabFromPane(_MakePane(newContentArgs, nullptr), -1, openInBackground);
if (_settings.GlobalSettings().FirstWindowPreference() == FirstWindowPreference::PersistedLayoutAndContent)
{
if (const auto newTerminalArgs = newContentArgs.try_as<NewTerminalArgs>();
newTerminalArgs && !newTerminalArgs.AgentPaneAgent().empty())
{
if (const auto tabImpl = _GetTabImpl(newTab))
{
const auto paneSize = newTerminalArgs.AgentPaneSize();
_pendingDurableAgentPaneRestores.insert_or_assign(
tabImpl->StableId(),
_PendingDurableAgentPaneRestore{
_currentStartupActionBatchId,
winrt::to_string(newTerminalArgs.AgentPaneSessionId()),
newTerminalArgs.AgentPaneAgent(),
newTerminalArgs.AgentPaneCustomCommand(),
winrt::to_string(newTerminalArgs.StartingDirectory()),
newTerminalArgs.AgentPaneView() == L"sessions",
newTerminalArgs.AgentPaneOpen(),
newTerminalArgs.AgentPanePosition(),
paneSize > 0.0f && paneSize < 1.0f ? paneSize : 0.5f });
}
}
}
return S_OK;
}
CATCH_RETURN();
Expand Down Expand Up @@ -369,6 +392,13 @@ namespace winrt::TerminalApp::implementation
// unrelated new-tab pre-warm).
if (agentLeavesSeen == 0)
{
if (self->_pendingDurableAgentPaneRestores.contains(newTabId))
{
_agentPaneLog(
std::string{ "_InitializeTab(deferred): durable agent pane restore pending on tab " } +
winrt::to_string(newTabId));
return;
}
_agentPaneLog(
std::string{ "_InitializeTab(deferred): pre-warming stashed agent pane on tab " } +
winrt::to_string(newTabId));
Expand Down Expand Up @@ -592,6 +622,54 @@ namespace winrt::TerminalApp::implementation
_previouslyClosedPanesAndTabs.emplace_back(args);
}

void TerminalPage::_AddDurableSessionMetadata(Tab* const tab, std::vector<ActionAndArgs>& actions)
{
for (const auto& action : actions)
{
INewContentArgs contentArgs{ nullptr };
if (const auto args = action.Args().try_as<NewTabArgs>())
{
contentArgs = args.ContentArgs();
}
else if (const auto args = action.Args().try_as<SplitPaneArgs>())
{
contentArgs = args.ContentArgs();
}

if (const auto terminalArgs = contentArgs.try_as<NewTerminalArgs>())
{
if (const auto binding = _paneAgentSessions.find(terminalArgs.SessionId());
binding != _paneAgentSessions.end())
{
terminalArgs.AgentSessionId(binding->second.sessionId);
terminalArgs.AgentSessionAgent(binding->second.agent);
}
}
}

if (const auto agentContent = tab->FindAgentPaneContent())
{
for (const auto& action : actions)
{
if (const auto newTabArgs = action.Args().try_as<NewTabArgs>())
{
if (const auto terminalArgs = newTabArgs.ContentArgs().try_as<NewTerminalArgs>())
{
const auto content = winrt::get_self<implementation::AgentPaneContent>(agentContent);
terminalArgs.AgentPaneSessionId(content->DurableSessionId());
terminalArgs.AgentPaneAgent(_GetDurableAgentIdentity(tab));
terminalArgs.AgentPaneCustomCommand(_GetDurableAgentCustomCommand(tab));
terminalArgs.AgentPaneView(agentContent.IsSessionsView() ? L"sessions" : L"chat");
terminalArgs.AgentPaneOpen(!tab->HasStashedAgentPane());
terminalArgs.AgentPanePosition(content->GetAgentPanePosition());
terminalArgs.AgentPaneSize(tab->AgentPaneSize());
break;
}
}
}
}
}

// Method Description:
// - If this window has a name, persist its current workspace layout to
// ApplicationState. Intended to be called from the close-pane / close-tab
Expand Down
Loading
Loading