helloadhavan/github_issues huggingface dataset:
Repository: nodejs/node
Pull request: fs: fix cpSync to handle non-ASCII characters

This PR fixes the problem described in the linked issue and adds a regression test for it.

Fixes: https://github.com/nodejs/node/issues/61878

Changed files:
filename: src/node_file.cc
patch: @@ -3425,15 +3425,18 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
   THROW_IF_INSUFFICIENT_PERMISSIONS(
       env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
 
+  auto src_path = src.ToPath();
+  auto dest_path = dest.ToPath();
+
   std::error_code error;
 
-  if (!std::filesystem::remove(*dest, error)) {
+  if (!std::filesystem::remove(dest_path, error)) {
     return env->ThrowStdErrException(error, "unlink", *dest);
   }
 
   if (mode == 0) {
     // if no mode is specified use the faster std::filesystem API
-    if (!std::filesystem::copy_file(*src, *dest, error)) {
+    if (!std::filesystem::copy_file(src_path, dest_path, error)) {
       return env->ThrowStdErrException(error, "cp", *dest);
     }
   } else {
@@ -3446,7 +3449,7 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
   }
 
   if (preserve_timestamps) {
-    CopyUtimes(*src, *dest, env);
+    CopyUtimes(src_path, dest_path, env);
   }
 }
 
@@ -3489,8 +3492,11 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
   bool verbatim_symlinks = args[5]->IsTrue();
   bool preserve_timestamps = args[6]->IsTrue();
 
+  auto src_path = src.ToPath();
+  auto dest_path = dest.ToPath();
+
   std::error_code error;
-  std::filesystem::create_directories(*dest, error);
+  std::filesystem::create_directories(dest_path, error);
   if (error) {
     return env->ThrowStdErrException(error, "cp", *dest);
   }
@@ -3632,7 +3638,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
     return true;
   };
 
-  copy_dir_contents(std::filesystem::path(*src), std::filesystem::path(*dest));
+  copy_dir_contents(src_path, dest_path);
 }
 
 BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(

filename: test/parallel/test-fs-cp-sync-unicode-dest.mjs
patch: @@ -0,0 +1,23 @@
+// Regression test for https://github.com/nodejs/node/issues/61878
+// fs.cpSync should copy files when destination path has UTF characters.
+import '../common/index.mjs';
+import { cpSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
+import { join } from 'node:path';
+import assert from 'node:assert';
+import tmpdir from '../common/tmpdir.js';
+
+tmpdir.refresh();
+
+const src = join(tmpdir.path, 'src');
+mkdirSync(join(src, 'subdir'), { recursive: true });
+writeFileSync(join(src, 'file1.txt'), 'Hello World');
+writeFileSync(join(src, 'subdir', 'nested.txt'), 'Nested File');
+
+const dest = join(tmpdir.path, 'Eyjafjallajökull-Pranckevičius');
+cpSync(src, dest, { recursive: true, force: true });
+
+const destFiles = readdirSync(dest);
+assert.ok(destFiles.includes('file1.txt'));
+assert.strictEqual(readFileSync(join(dest, 'file1.txt'), 'utf8'), 'Hello World');
+assert.ok(destFiles.includes('subdir'));
+assert.strictEqual(readFileSync(join(dest, 'subdir', 'nested.txt'), 'utf8'), 'Nested File');
Repository: electron/electron
Pull request: fix: correctly track BaseWindow::IsActive() on MacOS

Backport of #49460

See that PR for details.


Notes: Fixed improper focus tracking in BaseWindow on MacOS

Changed files:
filename: shell/browser/api/electron_api_base_window.cc
patch: @@ -317,6 +317,12 @@ void BaseWindow::OnWindowSheetEnd() {
   Emit("sheet-end");
 }
 
+void BaseWindow::OnWindowIsKeyChanged(bool is_key) {
+#if BUILDFLAG(IS_MAC)
+  window()->SetActive(is_key);
+#endif
+}
+
 void BaseWindow::OnWindowEnterHtmlFullScreen() {
   Emit("enter-html-full-screen");
 }

filename: shell/browser/api/electron_api_base_window.h
patch: @@ -83,6 +83,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
   void OnWindowRotateGesture(float rotation) override;
   void OnWindowSheetBegin() override;
   void OnWindowSheetEnd() override;
+  void OnWindowIsKeyChanged(bool is_key) override;
   void OnWindowEnterFullScreen() override;
   void OnWindowLeaveFullScreen() override;
   void OnWindowEnterHtmlFullScreen() override;
Repository: ollama/ollama
Pull request: template: add yesterdayDate helper function


Changed files:
filename: template/template.go
patch: @@ -127,6 +127,9 @@ var funcs = template.FuncMap{
 		// Default format is YYYY-MM-DD
 		return time.Now().Format("2006-01-02")
 	},
+	"yesterdayDate": func(args ...string) string {
+		return time.Now().AddDate(0, 0, -1).Format("2006-01-02")
+	},
 	"toTypeScriptType": func(v any) string {
 		if param, ok := v.(api.ToolProperty); ok {
 			return param.ToTypeScriptType()

filename: template/template_test.go
patch: @@ -10,6 +10,7 @@ import (
 	"slices"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/google/go-cmp/cmp"
 
@@ -451,6 +452,72 @@ func TestExecuteWithSuffix(t *testing.T) {
 	}
 }
 
+func TestDateFunctions(t *testing.T) {
+	t.Run("currentDate", func(t *testing.T) {
+		tmpl, err := Parse("{{- range .Messages }}{{ .Content }}{{ end }} Today is {{ currentDate }}")
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		var b bytes.Buffer
+		if err := tmpl.Execute(&b, Values{Messages: []api.Message{{Role: "user", Content: "Hello"}}}); err != nil {
+			t.Fatal(err)
+		}
+
+		expected := "Hello Today is " + time.Now().Format("2006-01-02")
+		if b.String() != expected {
+			t.Errorf("got %q, want %q", b.String(), expected)
+		}
+	})
+
+	t.Run("yesterdayDate", func(t *testing.T) {
+		tmpl, err := Parse("{{- range .Messages }}{{ .Content }}{{ end }} Yesterday was {{ yesterdayDate }}")
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		var b bytes.Buffer
+		if err := tmpl.Execute(&b, Values{Messages: []api.Message{{Role: "user", Content: "Hello"}}}); err != nil {
+			t.Fatal(err)
+		}
+
+		expected := "Hello Yesterday was " + time.Now().AddDate(0, 0, -1).Format("2006-01-02")
+		if b.String() != expected {
+			t.Errorf("got %q, want %q", b.String(), expected)
+		}
+	})
+
+	t.Run("yesterdayDate format", func(t *testing.T) {
+		tmpl, err := Parse("{{- range .Messages }}{{ end }}{{ yesterdayDate }}")
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		var b bytes.Buffer
+		if err := tmpl.Execute(&b, Values{Messages: []api.Message{{Role: "user", Content: "Hello"}}}); err != nil {
+			t.Fatal(err)
+		}
+
+		// Verify the format matches YYYY-MM-DD
+		result := b.String()
+		if len(result) != 10 {
+			t.Errorf("expected date length 10, got %d: %q", len(result), result)
+		}
+
+		// Parse and verify it's a valid date
+		parsed, err := time.Parse("2006-01-02", result)
+		if err != nil {
+			t.Errorf("failed to parse date %q: %v", result, err)
+		}
+
+		// Verify it's yesterday
+		yesterday := time.Now().AddDate(0, 0, -1)
+		if parsed.Year() != yesterday.Year() || parsed.Month() != yesterday.Month() || parsed.Day() != yesterday.Day() {
+			t.Errorf("expected yesterday's date, got %v", parsed)
+		}
+	})
+}
+
 func TestCollate(t *testing.T) {
 	cases := []struct {
 		name     string
Repository: vercel/next.js
Pull request: test: scope css data-url typing to fixture

In the latest TypeScript version these imports now fail so updating the assertion to handle them

x-ref: https://github.com/vercel/next.js/actions/runs/23508766037/job/68431989897#step:35:443

Changed files:
filename: test/e2e/css-data-url-global-pages/data-url-css.d.ts
patch: @@ -0,0 +1,2 @@
+// Test-local typing for Turbopack's CSS data URL side-effect import.
+declare module 'data:text/css,*' {}
Repository: nodejs/node
Pull request: deps: update amaro to 1.1.8

This is an automated update of amaro to 1.1.8.

Changed files:
filename: deps/amaro/README.md
patch: @@ -41,11 +41,31 @@ node --import="amaro/strip" file.ts
 Enabling TypeScript feature transformation:
 
 ```bash
-node --experimental-transform-types --import="amaro/transform" file.ts
+node --enable-source-maps --import="amaro/transform" file.ts
 ```
 
-> Note that the "amaro/transform" loader should be used with `--experimental-transform-types` flag, or
-> at least with `--enable-source-maps` flag, to preserve the original source maps.
+> Note that the `amaro/transform` loader should be used with `--enable-source-maps`
+> to preserve accurate source-mapped stack traces.
+
+#### Programmatic registration with `module.register()`
+
+If you want TypeScript to "just work" in an existing codebase without passing `--import` every time, create a small bootstrap file and register Amaro once before loading your TS entrypoint.
+
+```mjs
+// bootstrap.mjs
+import { register } from "node:module";
+
+register("amaro/strip", import.meta.url);
+await import("./src/index.ts");
+```
+
+Then start your app through the bootstrap file:
+
+```bash
+node --watch ./bootstrap.mjs
+```
+
+For transform mode, swap `amaro/strip` with `amaro/transform` and run Node with `--enable-source-maps`.
 
 #### Type stripping in dependencies
 

filename: deps/amaro/dist/package.json
patch: @@ -4,7 +4,7 @@
     "강동윤 <kdy1997.dev@gmail.com>"
   ],
   "description": "wasm module for swc",
-  "version": "1.15.11",
+  "version": "1.15.18",
   "license": "Apache-2.0",
   "repository": {
     "type": "git",

filename: deps/amaro/package.json
patch: @@ -1,6 +1,6 @@
 {
 	"name": "amaro",
-	"version": "1.1.7",
+	"version": "1.1.8",
 	"description": "Node.js TypeScript wrapper",
 	"license": "MIT",
 	"type": "commonjs",

filename: src/amaro_version.h
patch: @@ -2,5 +2,5 @@
 // Refer to tools/dep_updaters/update-amaro.sh
 #ifndef SRC_AMARO_VERSION_H_
 #define SRC_AMARO_VERSION_H_
-#define AMARO_VERSION "1.1.7"
+#define AMARO_VERSION "1.1.8"
 #endif  // SRC_AMARO_VERSION_H_
Repository: facebook/react
Pull request: [DevTools] Don't attempt to draw bounding box if inspected element is not a Suspense

Basically just skips a warning until we implement splitting `inspectedElementID` into inspected  element and inspected Suspense.

Changed files:
filename: packages/react-devtools-shared/src/devtools/store.js
patch: @@ -669,6 +669,10 @@ export default class Store extends EventEmitter<{
     return element;
   }
 
+  containsSuspense(id: SuspenseNode['id']): boolean {
+    return this._idToSuspense.has(id);
+  }
+
   getSuspenseByID(id: SuspenseNode['id']): SuspenseNode | null {
     const suspense = this._idToSuspense.get(id);
     if (suspense === undefined) {

filename: packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js
patch: @@ -511,7 +511,11 @@ function SuspenseRectsContainer({
   let selectedEnvironment = null;
   if (isRootSelected) {
     selectedEnvironment = rootEnvironment;
-  } else if (inspectedElementID !== null) {
+  } else if (
+    inspectedElementID !== null &&
+    // TODO: Separate inspected element and inspected Suspense and use the inspected Suspense ID here.
+    store.containsSuspense(inspectedElementID)
+  ) {
     const selectedSuspenseNode = store.getSuspenseByID(inspectedElementID);
     if (
       selectedSuspenseNode !== null &&
Repository: facebook/react
Pull request: Remove Dead Code in WWW JS

Reviewed By: bhamodi

Differential Revision: D86593830




Changed files:
filename: packages/react-dom-bindings/src/client/ReactDOMComponentTree.js
patch: @@ -293,8 +293,9 @@ export function updateFiberProps(node: Instance, props: Props): void {
 }
 
 export function getEventListenerSet(node: EventTarget): Set<string> {
-  let elementListenerSet: Set<string> | void;
-  elementListenerSet = (node: any)[internalEventHandlersKey];
+  let elementListenerSet: Set<string> | void = (node: any)[
+    internalEventHandlersKey
+  ];
   if (elementListenerSet === undefined) {
     elementListenerSet = (node: any)[internalEventHandlersKey] = new Set();
   }
Repository: ollama/ollama
Pull request: cmd/bench: fix binary name in README

The instruction `go build -o ollama-bench bench.go` creates a binary called `ollama-bench`.

Changed files:
filename: cmd/bench/README.md
patch: @@ -15,7 +15,7 @@ A Go-based command-line tool for benchmarking Ollama models with configurable pa
 
 ```
 go build -o ollama-bench bench.go
-./bench -model gpt-oss:20b -epochs 6 -format csv
+./ollama-bench -model gpt-oss:20b -epochs 6 -format csv
 ```
 
 Using Go Run (without building)
@@ -29,26 +29,26 @@ go run bench.go -model gpt-oss:20b -epochs 3
 ### Basic Example
 
 ```
-./bench -model gemma3 -epochs 6
+./ollama-bench -model gemma3 -epochs 6
 ```
 
 ### Benchmark Multiple Models
 
 ```
-./bench -model gemma3,gemma3n -epochs 6 -max-tokens 100 -p "Write me a short story" | tee gemma.bench
+./ollama-bench -model gemma3,gemma3n -epochs 6 -max-tokens 100 -p "Write me a short story" | tee gemma.bench
 benchstat -col /name gemma.bench
 ```
 
 ### With Image Prompt
 
 ```
-./bench -model qwen3-vl -image photo.jpg -epochs 6 -max-tokens 100 -p "Describe this image"
+./ollama-bench -model qwen3-vl -image photo.jpg -epochs 6 -max-tokens 100 -p "Describe this image"
 ```
 
 ### Advanced Example
 
 ```
-./bench -model llama3 -epochs 10 -temperature 0.7 -max-tokens 500 -seed 42 -format csv -output results.csv
+./ollama-bench -model llama3 -epochs 10 -temperature 0.7 -max-tokens 500 -seed 42 -format csv -output results.csv
 ```
 
 ## Command Line Options
Repository: facebook/react
Pull request: [Fizz] Simplify createSuspenseBoundary path

Small follow up to #35068.

Since this is now a single argument we can simplify the creation branching a bit and make sure it's const.

Changed files:
filename: packages/react-server/src/ReactFizzServer.js
patch: @@ -1291,24 +1291,13 @@ function renderSuspenseBoundary(
   const defer: boolean = enableCPUSuspense && props.defer === true;
 
   const fallbackAbortSet: Set<Task> = new Set();
-  let newBoundary: SuspenseBoundary;
-  if (canHavePreamble(task.formatContext)) {
-    newBoundary = createSuspenseBoundary(
-      request,
-      task.row,
-      fallbackAbortSet,
-      createPreamble(),
-      defer,
-    );
-  } else {
-    newBoundary = createSuspenseBoundary(
-      request,
-      task.row,
-      fallbackAbortSet,
-      null,
-      defer,
-    );
-  }
+  const newBoundary = createSuspenseBoundary(
+    request,
+    task.row,
+    fallbackAbortSet,
+    canHavePreamble(task.formatContext) ? createPreamble() : null,
+    defer,
+  );
 
   const insertionIndex = parentSegment.chunks.length;
   // The children of the boundary segment is actually the fallback.
@@ -1603,24 +1592,13 @@ function replaySuspenseBoundary(
   const defer: boolean = enableCPUSuspense && props.defer === true;
 
   const fallbackAbortSet: Set<Task> = new Set();
-  let resumedBoundary: SuspenseBoundary;
-  if (canHavePreamble(task.formatContext)) {
-    resumedBoundary = createSuspenseBoundary(
-      request,
-      task.row,
-      fallbackAbortSet,
-      createPreamble(),
-      defer,
-    );
-  } else {
-    resumedBoundary = createSuspenseBoundary(
-      request,
-      task.row,
-      fallbackAbortSet,
-      null,
-      defer,
-    );
-  }
+  const resumedBoundary = createSuspenseBoundary(
+    request,
+    task.row,
+    fallbackAbortSet,
+    canHavePreamble(task.formatContext) ? createPreamble() : null,
+    defer,
+  );
   resumedBoundary.parentFlushed = true;
   // We restore the same id of this boundary as was used during prerender.
   resumedBoundary.rootSegmentID = id;
Repository: electron/electron
Pull request: fix: ensure WebContents::WasShown runs when window is shown

Backport of #49421

See that PR for details.


Notes: Fixed window freeze when failing to enter/exit fullscreen on macOS.

Changed files:
filename: shell/browser/api/electron_api_browser_window.cc
patch: @@ -276,16 +276,22 @@ v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
 }
 
 void BrowserWindow::OnWindowShow() {
+  if (!web_contents_shown_) {
+    web_contents()->WasShown();
+    web_contents_shown_ = true;
+  }
   BaseWindow::OnWindowShow();
 }
 
 void BrowserWindow::OnWindowHide() {
   web_contents()->WasOccluded();
+  web_contents_shown_ = false;
   BaseWindow::OnWindowHide();
 }
 
 void BrowserWindow::Show() {
   web_contents()->WasShown();
+  web_contents_shown_ = true;
   BaseWindow::Show();
 }
 
@@ -294,6 +300,7 @@ void BrowserWindow::ShowInactive() {
   if (IsModal())
     return;
   web_contents()->WasShown();
+  web_contents_shown_ = true;
   BaseWindow::ShowInactive();
 }
 

filename: shell/browser/api/electron_api_browser_window.h
patch: @@ -80,6 +80,7 @@ class BrowserWindow : public BaseWindow,
   // Helpers.
 
   v8::Global<v8::Value> web_contents_;
+  bool web_contents_shown_ = false;
   v8::Global<v8::Value> web_contents_view_;
   base::WeakPtr<api::WebContents> api_web_contents_;
Repository: ollama/ollama
Pull request: cmd/bench: fix options table in cmd/bench/README.md

Fix the broken markdown table in cmd/bench/README.md

Changed files:
filename: cmd/bench/README.md
patch: @@ -54,6 +54,7 @@ benchstat -col /name gemma.bench
 ## Command Line Options
 
 | Option  	| Description | Default |
+|----------|-------------|---------|
 | -model	| Comma-separated list of models to benchmark	| (required)		|
 | -epochs	| Number of iterations per model		| 1			|
 | -max-tokens	| Maximum tokens for model response		| 0 (unlimited)		|
Repository: facebook/react
Pull request: [DevTools] Special case the selected root outline

When I moved the outline to above all other rects, I thought it was clever to unify with the root so that the outline was also used for the root selection. But the root outline is not drawn like the other rects. It's outside the padding and doesn't have the 1px adjustment which leads the overlay to be slightly inside the other rect instead of above it.

This goes back to just having the selected root be drawn by the root element.

Before:

<img width="652" height="253" alt="Screenshot 2025-11-07 at 11 39 28 AM" src="https://github.com/user-attachments/assets/334237d1-f190-4995-94cc-9690ec0f7ce1" />

After:

<img width="674" height="220" alt="Screenshot 2025-11-07 at 11 44 01 AM" src="https://github.com/user-attachments/assets/afaa86d8-942a-44d8-a1a5-67c7fb642c0d" />


Changed files:
filename: packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css
patch: @@ -12,6 +12,11 @@
   background-color: color-mix(in srgb, var(--color-transition) 5%, transparent);
 }
 
+.SuspenseRectsRootOutline {
+  outline-width: 4px;
+  border-radius: 0.125rem;
+}
+
 .SuspenseRectsRoot[data-hovered='true'] {
   background-color: color-mix(in srgb, var(--color-transition) 15%, transparent);
 }
@@ -100,10 +105,6 @@
   pointer-events: none;
 }
 
-.SuspenseRectOutlineRoot {
-  outline-color: var(--color-transition);
-}
-
 .SuspenseRectsBoundary[data-selected='true'] > .SuspenseRectsRect {
    box-shadow: none;
 }

filename: packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js
patch: @@ -510,7 +510,6 @@ function SuspenseRectsContainer({
   let selectedBoundingBox = null;
   let selectedEnvironment = null;
   if (isRootSelected) {
-    selectedBoundingBox = boundingBox;
     selectedEnvironment = rootEnvironment;
   } else if (inspectedElementID !== null) {
     const selectedSuspenseNode = store.getSuspenseByID(inspectedElementID);
@@ -534,6 +533,7 @@ function SuspenseRectsContainer({
       className={
         styles.SuspenseRectsContainer +
         (hasRootSuspenders ? ' ' + styles.SuspenseRectsRoot : '') +
+        (isRootSelected ? ' ' + styles.SuspenseRectsRootOutline : '') +
         ' ' +
         getClassNameForEnvironment(rootEnvironment)
       }
@@ -551,7 +551,6 @@ function SuspenseRectsContainer({
             <ScaledRect
               className={
                 styles.SuspenseRectOutline +
-                (isRootSelected ? ' ' + styles.SuspenseRectOutlineRoot : '') +
                 ' ' +
                 getClassNameForEnvironment(selectedEnvironment)
               }
Repository: huggingface/transformers
Pull request: Fix missing BPE token conversion step in Chameleon

# What does this PR do?

Fix an issue introduced in #42564 . The refactor embedded raw image tokens instead of BPE tokens, causing the model to output gibberish. This fix adds back the image tokens to BPE tokens conversion before embedding.

Cc @hmellor @zucchini-nlp 


Changed files:
filename: src/transformers/models/chameleon/modeling_chameleon.py
patch: @@ -899,8 +899,10 @@ def get_image_features(
         pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)`):
             The tensors corresponding to the input images.
         """
+        batch_size = pixel_values.shape[0]
         vqmodel_outputs: ChameleonVQVAEModelOutput = self.vqmodel.encode(pixel_values, return_dict=True, **kwargs)
-        vqmodel_outputs.pooler_output = self.get_input_embeddings()(vqmodel_outputs.image_tokens)
+        bpe_tokens = self.vocabulary_mapping.convert_img2bpe(vqmodel_outputs.image_tokens).view(batch_size, -1)
+        vqmodel_outputs.pooler_output = self.get_input_embeddings()(bpe_tokens)
         return vqmodel_outputs
 
     def get_placeholder_mask(
Repository: ollama/ollama
Pull request: app/ui: use requestAnimationFrame to prevent bottom line cutoff in streaming thinking display

When models with thinking capability stream their reasoning in real-time, the bottomline of thinking content is cut off and not visible to users in the collapsed thinking panel.

The reason why is because the thinking component uses CSS `translateY()` transform to position content and show the bottom portion in collapsed mode. During active streaming, a race condition occurs where the transform calculation happens before the browser completes layout of newly added content, resulting in positioning based on stale dimensions.

This PR modified 2 things: 
1. Wrapped transform calculations in `requestAnimationFrame`: Ensures DOM layout is complete before calculating content dimensions and positioning (to avoid race condition)
2. Added auto-scroll for expanded mode: When the thinking panel is expanded during active streaming, automatically scrolls to show the latest content

This PR is resolving #13094 

Changed files:
filename: app/ui/app/src/components/Thinking.tsx
patch: @@ -50,21 +50,33 @@ export default function Thinking({
   // Position content to show bottom when collapsed
   useEffect(() => {
     if (isCollapsed && contentRef.current && wrapperRef.current) {
-      const contentHeight = contentRef.current.scrollHeight;
-      const wrapperHeight = wrapperRef.current.clientHeight;
-      if (contentHeight > wrapperHeight) {
-        const translateY = -(contentHeight - wrapperHeight);
-        contentRef.current.style.transform = `translateY(${translateY}px)`;
-        setHasOverflow(true);
-      } else {
-        setHasOverflow(false);
-      }
+      requestAnimationFrame(() => {
+        if (!contentRef.current || !wrapperRef.current) return;
+
+        const contentHeight = contentRef.current.scrollHeight;
+        const wrapperHeight = wrapperRef.current.clientHeight;
+        if (contentHeight > wrapperHeight) {
+          const translateY = -(contentHeight - wrapperHeight);
+          contentRef.current.style.transform = `translateY(${translateY}px)`;
+          setHasOverflow(true);
+        } else {
+          contentRef.current.style.transform = "translateY(0)";
+          setHasOverflow(false);
+        }
+      });
     } else if (contentRef.current) {
       contentRef.current.style.transform = "translateY(0)";
       setHasOverflow(false);
     }
   }, [thinking, isCollapsed]);
 
+  useEffect(() => {
+    if (activelyThinking && wrapperRef.current && !isCollapsed) {
+      // When expanded and actively thinking, scroll to bottom
+      wrapperRef.current.scrollTop = wrapperRef.current.scrollHeight;
+    }
+  }, [thinking, activelyThinking, isCollapsed]);
+
   const handleToggle = () => {
     setIsCollapsed(!isCollapsed);
     setHasUserInteracted(true);