Repository: microsoft/terminal
File: src/cascadia/QueryExtension/ExtensionPalette.cpp (C++)

Code before:

    winrt::hstring ExtensionPalette::_getCurrentLocalTimeHelper()
    {
        auto now = std::chrono::system_clock::now();
        auto time = std::chrono::system_clock::to_time_t(now);

        std::tm local_time;
        localtime_s(&local_time, &time);

        std::stringstream ss;
        ss << std::put_time(&local_time, "%H:%M");
        std::string time_str = ss.str();
        return winrt::to_hstring(time_str);
    }

    void ExtensionPalette::_splitResponseAndAddToChatHelper(const IResponse response)
    {
        const auto time = _getCurrentLocalTimeHelper();
        std::vector<IInspectable> messageParts;

        const auto chatMsg = winrt::make<ChatMessage>(winrt::to_hstring(response.Message()), false);
        chatMsg.RunCommandClicked([this](auto&&, const auto commandlines) {
            auto suggestion = winrt::to_string(commandlines);
            // the AI sometimes sends multiline code blocks
            // we don't want to run any of those commands when the chat item is clicked,
            // so we replace newlines with the appropriate delimiter
            size_t pos = 0;
            while ((pos = suggestion.find("\n", pos)) != std::string::npos)
            {
                const auto delimiter = (_ActiveCommandline == cmdExe || _ActiveCommandline == cmd) ? cmdCommandDelimiter : commandDelimiter;
                suggestion.at(pos) = delimiter;
                pos += 1; // Move past the replaced character
            }
            _InputSuggestionRequestedHandlers(*this, winrt::to_hstring(suggestion));
            _close();

            const auto lmProviderName = _lmProvider ? _lmProvider.BrandingData().Name() : winrt::hstring{};
            TraceLoggingWrite(
                g_hQueryExtensionProvider,
                "AICodeResponseInputted",
                TraceLoggingDescription("Event emitted when the user clicks on a suggestion to have it be input into their active shell"),
                TraceLoggingWideString(lmProviderName.c_str(), "LMProviderName", "The name of the connected service provider, if present"),
                TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA),
                TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
        });
        messageParts.push_back(chatMsg);

        const auto brandingData = _lmProvider ? _lmProvider.BrandingData() : nullptr;
        const auto responseAttribution = response.ResponseAttribution().empty() ? _ProfileName : response.ResponseAttribution();
        const auto badgeUriPath = brandingData ? brandingData.BadgeIconPath() : L"";
        const auto responseGroupedMessages = winrt::make<GroupedChatMessages>(time, false, winrt::single_threaded_vector(std::move(messageParts)), responseAttribution, badgeUriPath);

Review comment (suggestion):
BTW on that topic again, unrelated to this PR, and related to #18186: I still think we should better integrate this with ControlCore's other paste facilities. It knows whether the shell has enabled bracketed paste (usually true for UNIX shells) which allows for perfect multi-line pastes. For PowerShell without bracketed paste we can still use `\n` as multi-line delimiters. We can infer PowerShell from the profile source (we make similar similar assumptions that `profile_source == WSL` means it wants WSL paths). And for cmd I'd be happy to make the necessary modifications to cooked read in the 1.23 timeframe if you'd like.

Code after:

    winrt::hstring ExtensionPalette::_getCurrentLocalTimeHelper()
    {
        auto now = std::chrono::system_clock::now();
        auto time = std::chrono::system_clock::to_time_t(now);

        std::tm local_time;
        localtime_s(&local_time, &time);

        std::stringstream ss;
        ss << std::put_time(&local_time, "%H:%M");
        std::string time_str = ss.str();
        return winrt::to_hstring(time_str);
    }

    void ExtensionPalette::_splitResponseAndAddToChatHelper(const IResponse response)
    {
        const auto time = _getCurrentLocalTimeHelper();
        std::vector<IInspectable> messageParts;

        const auto chatMsg = winrt::make<ChatMessage>(response.Message(), false);
        chatMsg.RunCommandClicked([this](auto&&, const auto commandlines) {
            auto suggestion = winrt::to_string(commandlines);
            // the AI sometimes sends multiline code blocks
            // we don't want to run any of those commands when the chat item is clicked,
            // so we replace newlines with the appropriate delimiter
            size_t pos = 0;
            while ((pos = suggestion.find("\n", pos)) != std::string::npos)
            {
                const auto delimiter = (_ActiveCommandline == cmdExe || _ActiveCommandline == cmd) ? cmdCommandDelimiter : commandDelimiter;
                suggestion.at(pos) = delimiter;
                pos += 1; // Move past the replaced character
            }
            _InputSuggestionRequestedHandlers(*this, winrt::to_hstring(suggestion));
            _close();

            const auto lmProviderName = _lmProvider ? _lmProvider.BrandingData().Name() : winrt::hstring{};
            TraceLoggingWrite(
                g_hQueryExtensionProvider,
                "AICodeResponseInputted",
                TraceLoggingDescription("Event emitted when the user clicks on a suggestion to have it be input into their active shell"),
                TraceLoggingWideString(lmProviderName.c_str(), "LMProviderName", "The name of the connected service provider, if present"),
                TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA),
                TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
        });
        messageParts.push_back(chatMsg);

        const auto brandingData = _lmProvider ? _lmProvider.BrandingData() : nullptr;
        const auto responseAttribution = response.ResponseAttribution().empty() ? _ProfileName : response.ResponseAttribution();
        const auto badgeUriPath = brandingData ? brandingData.BadgeIconPath() : L"";
        const auto responseGroupedMessages = winrt::make<GroupedChatMessages>(time, false, winrt::single_threaded_vector(std::move(messageParts)), responseAttribution, badgeUriPath);