You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by as...@apache.org on 2026/10/09 01:02:34 UTC

(maka) branch chore/astryx-upgrade-066 created (now f7772d8ae5)

This is an automated email from the ASF dual-hosted git repository.

Astro-Han pushed a change to branch chore/astryx-upgrade-066
in repository https://gitbox.apache.org/repos/asf/maka.git


      at f7772d8ae5 chore(deps): upgrade Astryx to 0.6.6

This branch includes the following new commits:

     new f7772d8ae5 chore(deps): upgrade Astryx to 0.6.6

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


(maka) 01/01: chore(deps): upgrade Astryx to 0.6.6

Posted by as...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

Astro-Han pushed a commit to branch chore/astryx-upgrade-066
in repository https://gitbox.apache.org/repos/asf/maka.git

commit f7772d8ae55d924308f2106b89b43e889a408c52
Author: AstroHan <le...@outlook.com>
AuthorDate: Fri Oct 9 11:00:28 2026 +1000

    chore(deps): upgrade Astryx to 0.6.6
    
    Rebase the existing core patch onto 0.6.6 while retaining host-owned scroll, caret, streaming, touch-trigger, spinner, and toast behavior. Remove the inline-token geometry patch now shipped upstream and preserve new menu, layer, and Markdown fixes. Regenerate the theme, surface version, and license notices. Supply DOM constructors in the existing UI test harnesses for the delegated press controller.
    
    Generated-by: Maka
---
 LICENSE                                            |   4 +-
 apps/desktop/package.json                          |   4 +-
 .../resources/licenses/npm/THIRD_PARTY_NOTICES.txt |   4 +-
 apps/desktop/src/renderer/astryx-theme/maka.css    |   2 +-
 apps/desktop/src/renderer/astryx-theme/maka.d.ts   |   4 +-
 apps/desktop/src/renderer/astryx-theme/maka.js     |   8 +-
 docs/astryx-surface-file-inventory.md              |   2 +-
 package-lock.json                                  |  52 +--
 package.json                                       |   4 +-
 packages/ui/package.json                           |   2 +-
 .../ui/src/__tests__/model-wheel-picker.test.tsx   |  10 +-
 .../session-history-move-to-project-menu.test.tsx  |   5 +-
 .../session-history-multi-select.test.tsx          |  10 +-
 .../src/__tests__/skills-panel-locations.test.tsx  |   6 +
 ...+0.6.3.patch => @astryxdesign+core+0.6.6.patch} | 401 +++++++++------------
 scripts/generate-third-party-notices.mjs           |   2 +-
 16 files changed, 240 insertions(+), 280 deletions(-)

diff --git a/LICENSE b/LICENSE
index cfff851951..1057803472 100644
--- a/LICENSE
+++ b/LICENSE
@@ -253,9 +253,9 @@ License: MIT
 
 Maka includes an ejected adaptation of Astryx ChatReasoning v0.1.9 in
 `packages/ui/src/astryx-chat-reasoning.tsx` and generated theme artifacts in
-`apps/desktop/src/renderer/astryx-theme/`, based on Astryx theme-neutral v0.6.3.
+`apps/desktop/src/renderer/astryx-theme/`, based on Astryx theme-neutral v0.6.6.
 Maka also redistributes
-`patches/@astryxdesign+core+0.6.3.patch`, which modifies the MIT-licensed Astryx
+`patches/@astryxdesign+core+0.6.6.patch`, which modifies the MIT-licensed Astryx
 core package. The following MIT License applies to that material:
 
 MIT License
diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index 4dc857e29e..3a08545f8f 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -76,8 +76,8 @@
     "zod": "^4.6.5"
   },
   "devDependencies": {
-    "@astryxdesign/core": "0.6.3",
-    "@astryxdesign/theme-neutral": "0.6.3",
+    "@astryxdesign/core": "0.6.6",
+    "@astryxdesign/theme-neutral": "0.6.6",
     "@babel/parser": "7.29.9",
     "@fontsource-variable/geist": "^5.3.0",
     "@fontsource-variable/geist-mono": "^5.3.0",
diff --git a/apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt b/apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt
index 7e62f8d604..5c4984a354 100644
--- a/apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt
+++ b/apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt
@@ -647,7 +647,7 @@ SOFTWARE.
 
 ================================================================================
 
-Package: @astryxdesign/core@0.6.3
+Package: @astryxdesign/core@0.6.6
 Declared license: MIT
 Selected license: MIT
 Repository: git+https://github.com/facebook/astryx.git#packages/core
@@ -677,7 +677,7 @@ SOFTWARE.
 
 ================================================================================
 
-Package: @astryxdesign/theme-neutral@0.6.3
+Package: @astryxdesign/theme-neutral@0.6.6
 Declared license: MIT
 Selected license: MIT
 Repository: git+https://github.com/facebook/astryx.git#packages/themes/neutral
diff --git a/apps/desktop/src/renderer/astryx-theme/maka.css b/apps/desktop/src/renderer/astryx-theme/maka.css
index 32fc2ee497..527a7595c1 100644
--- a/apps/desktop/src/renderer/astryx-theme/maka.css
+++ b/apps/desktop/src/renderer/astryx-theme/maka.css
@@ -2,7 +2,7 @@
  * @generated by `astryx theme build` — do not edit manually.
  * Source: src/renderer/astryx-theme/makaTheme.ts
  * Command: astryx theme build src/renderer/astryx-theme/makaTheme.ts --out src/renderer/astryx-theme/maka.css
- * CLI: @astryxdesign/cli@0.6.3
+ * CLI: @astryxdesign/cli@0.6.6
  * Core: @astryxdesign/core@0.1.0
  */
 
diff --git a/apps/desktop/src/renderer/astryx-theme/maka.d.ts b/apps/desktop/src/renderer/astryx-theme/maka.d.ts
index 1a3c052f78..31a9a51297 100644
--- a/apps/desktop/src/renderer/astryx-theme/maka.d.ts
+++ b/apps/desktop/src/renderer/astryx-theme/maka.d.ts
@@ -2,11 +2,11 @@
  * @generated by `astryx theme build` — do not edit manually.
  * Source: src/renderer/astryx-theme/makaTheme.ts
  * Command: astryx theme build src/renderer/astryx-theme/makaTheme.ts --out src/renderer/astryx-theme/maka.css
- * CLI: @astryxdesign/cli@0.6.3
+ * CLI: @astryxdesign/cli@0.6.6
  * Core: @astryxdesign/core@0.1.0
  */
 
 import type { DefinedTheme } from '@astryxdesign/core/theme';
 import type { IconRegistry } from '@astryxdesign/core/Icon';
-export declare const neutralIconRegistry: IconRegistry;
+export declare const themeIcons: IconRegistry;
 export declare const makaTheme: DefinedTheme;
diff --git a/apps/desktop/src/renderer/astryx-theme/maka.js b/apps/desktop/src/renderer/astryx-theme/maka.js
index 628556e286..5d6700c250 100644
--- a/apps/desktop/src/renderer/astryx-theme/maka.js
+++ b/apps/desktop/src/renderer/astryx-theme/maka.js
@@ -2,11 +2,13 @@
  * @generated by `astryx theme build` — do not edit manually.
  * Source: src/renderer/astryx-theme/makaTheme.ts
  * Command: astryx theme build src/renderer/astryx-theme/makaTheme.ts --out src/renderer/astryx-theme/maka.css
- * CLI: @astryxdesign/cli@0.6.3
+ * CLI: @astryxdesign/cli@0.6.6
  * Core: @astryxdesign/core@0.1.0
  */
 
+import { neutralTheme } from '@astryxdesign/theme-neutral';
 import { neutralIconRegistry } from '@astryxdesign/theme-neutral';
+const themeIcons = {...neutralTheme["icons"], ...neutralIconRegistry};
 /**
  * maka theme — built by `astryx theme build`
  * Import the CSS file alongside this module:
@@ -549,7 +551,7 @@ export const makaTheme = {
       "ratio": 0.75
     }
   },
-  icons: neutralIconRegistry,
+  icons: themeIcons,
 };
 
-export { neutralIconRegistry };
+export { themeIcons };
diff --git a/docs/astryx-surface-file-inventory.md b/docs/astryx-surface-file-inventory.md
index 3fa17e2570..934b2cee30 100644
--- a/docs/astryx-surface-file-inventory.md
+++ b/docs/astryx-surface-file-inventory.md
@@ -2,7 +2,7 @@
 
 Generated by `scripts/generate-astryx-surface-inventory.mjs`.
 Each row is one on-disk product surface file. Regenerated inventory must stay in sync with disk (coverage gate).
-Generated against `@astryxdesign/core@0.6.3` (195 component exports).
+Generated against `@astryxdesign/core@0.6.6` (200 component exports).
 
 Wiki bar: Design Conventions · API Use-the-System · Theming · Container Padding.
 
diff --git a/package-lock.json b/package-lock.json
index 4f9c96b1bf..9acee3dfd9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,8 +26,8 @@
       ],
       "devDependencies": {
         "@ai-sdk/provider-utils": "5.0.51",
-        "@astryxdesign/cli": "0.6.3",
-        "@astryxdesign/core": "0.6.3",
+        "@astryxdesign/cli": "0.6.6",
+        "@astryxdesign/core": "0.6.6",
         "@biomejs/biome": "2.5.14",
         "@electron/asar": "4.3.0",
         "@types/node": "^26.6.3",
@@ -65,8 +65,8 @@
         "zod": "^4.6.5"
       },
       "devDependencies": {
-        "@astryxdesign/core": "0.6.3",
-        "@astryxdesign/theme-neutral": "0.6.3",
+        "@astryxdesign/core": "0.6.6",
+        "@astryxdesign/theme-neutral": "0.6.6",
         "@babel/parser": "7.29.9",
         "@fontsource-variable/geist": "^5.3.0",
         "@fontsource-variable/geist-mono": "^5.3.0",
@@ -670,9 +670,9 @@
       }
     },
     "node_modules/@astryxdesign/cli": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/@astryxdesign/cli/-/cli-0.6.3.tgz",
-      "integrity": "sha512-3ggz5X5j0AsFnX43/mRs3bdnYDICGMuIPkVl+uCvaQUnzbPWFcu1fWR3JS27qyZ5CIg9ZVBP4mUB+dwm6R6ZXQ==",
+      "version": "0.6.6",
+      "resolved": "https://registry.npmjs.org/@astryxdesign/cli/-/cli-0.6.6.tgz",
+      "integrity": "sha512-6JOHXiAQS0/cBiGfRTBLT13Wb673U8c7+qtDfwe0w3mnog72FTpo8rYoUrMfNXFbPVELE2FTp83WdaxWHeeZ+A==",
       "dev": true,
       "hasInstallScript": true,
       "license": "MIT",
@@ -683,6 +683,7 @@
         "@babel/types": "7.29.8",
         "ast-types": "0.16.3",
         "commander": "^12.1.0",
+        "ignore": "^7.0.5",
         "jiti": "^2.7.0",
         "jscodeshift": "^17.3.0",
         "node-diff3": "3.2.1",
@@ -702,8 +703,7 @@
         "@astryxdesign/charts": "*",
         "@astryxdesign/core": "*",
         "@astryxdesign/lab": "*",
-        "@astryxdesign/theme-neutral": "*",
-        "gpt-tokenizer": "^3.4.0"
+        "@astryxdesign/theme-neutral": "*"
       },
       "peerDependenciesMeta": {
         "@astryxdesign/charts": {
@@ -747,9 +747,9 @@
       }
     },
     "node_modules/@astryxdesign/core": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/@astryxdesign/core/-/core-0.6.3.tgz",
-      "integrity": "sha512-ieaZZn0wjP8saWkfSXFgzvrA0UfXWeOBsvuvsbtJ0789LdYacTJS83UXsROcvPLONUIOO/Iy1Ar5+70xvcVpgg==",
+      "version": "0.6.6",
+      "resolved": "https://registry.npmjs.org/@astryxdesign/core/-/core-0.6.6.tgz",
+      "integrity": "sha512-a1KuL9ILvsvbSafa+gAwXEX5Cnl0tRNDOCgNRBkhuxLd7MWrorUKx+/kayVB8ymWFZJD5LbricGD22pPHNetag==",
       "hasInstallScript": true,
       "license": "MIT",
       "dependencies": {
@@ -762,16 +762,16 @@
       }
     },
     "node_modules/@astryxdesign/theme-neutral": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/@astryxdesign/theme-neutral/-/theme-neutral-0.6.3.tgz",
-      "integrity": "sha512-6l2u3qVcs5TkN4YUMUrSlMdmRmzt+/nB1pJqZopn3/nylVZcxSql+wzeD7T1VyinM+wHAokoaRD6xmCa2abNDg==",
+      "version": "0.6.6",
+      "resolved": "https://registry.npmjs.org/@astryxdesign/theme-neutral/-/theme-neutral-0.6.6.tgz",
+      "integrity": "sha512-Ox1oxcAisdiqton5zLfpmZPHoEhUSlT2Ea2RtppG9ZVpbIrH+w7D9kAaGH8LAzO+HDo7lrXXsB9XKngFQPZ5wA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "lucide-react": "^1.18.0"
       },
       "peerDependencies": {
-        "@astryxdesign/core": "0.6.3",
+        "@astryxdesign/core": "0.6.6",
         "react": ">=19"
       }
     },
@@ -10484,14 +10484,6 @@
         "url": "https://github.com/sindresorhus/got?sponsor=1"
       }
     },
-    "node_modules/gpt-tokenizer": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/gpt-tokenizer/-/gpt-tokenizer-3.4.0.tgz",
-      "integrity": "sha512-wxFLnhIXTDjYebd9A9pGl3e31ZpSypbpIJSOswbgop5jLte/AsZVDvjlbEuVFlsqZixVKqbcoNmRlFDf6pz/UQ==",
-      "dev": true,
-      "license": "MIT",
-      "peer": true
-    },
     "node_modules/graceful-fs": {
       "version": "4.2.11",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -10886,6 +10878,16 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/ignore": {
+      "version": "7.0.12",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz",
+      "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/image-dimensions": {
       "version": "2.6.0",
       "resolved": "https://registry.npmjs.org/image-dimensions/-/image-dimensions-2.6.0.tgz",
@@ -17505,7 +17507,7 @@
       "version": "0.1.0",
       "license": "Apache-2.0",
       "dependencies": {
-        "@astryxdesign/core": "0.6.3",
+        "@astryxdesign/core": "0.6.6",
         "@maka/core": "0.1.0",
         "clsx": "^2.1.1",
         "katex": "0.18.9",
diff --git a/package.json b/package.json
index 8df8aa2846..67d8efe612 100644
--- a/package.json
+++ b/package.json
@@ -116,8 +116,8 @@
   },
   "devDependencies": {
     "@ai-sdk/provider-utils": "5.0.51",
-    "@astryxdesign/cli": "0.6.3",
-    "@astryxdesign/core": "0.6.3",
+    "@astryxdesign/cli": "0.6.6",
+    "@astryxdesign/core": "0.6.6",
     "@biomejs/biome": "2.5.14",
     "@electron/asar": "4.3.0",
     "@types/node": "^26.6.3",
diff --git a/packages/ui/package.json b/packages/ui/package.json
index d94cfb3849..2d19d4b922 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -27,7 +27,7 @@
     "test:dist": "node --test \"dist/**/*.test.js\""
   },
   "dependencies": {
-    "@astryxdesign/core": "0.6.3",
+    "@astryxdesign/core": "0.6.6",
     "@maka/core": "0.1.0",
     "clsx": "^2.1.1",
     "katex": "0.18.9",
diff --git a/packages/ui/src/__tests__/model-wheel-picker.test.tsx b/packages/ui/src/__tests__/model-wheel-picker.test.tsx
index 020d472716..c044f2c8ec 100644
--- a/packages/ui/src/__tests__/model-wheel-picker.test.tsx
+++ b/packages/ui/src/__tests__/model-wheel-picker.test.tsx
@@ -27,6 +27,9 @@ import { ModelWheelPicker } from '../model-wheel-picker.js';
 test('ordinary rerenders keep the layer anchor attached', async () => {
   const original = {
     document: globalThis.document,
+    Element: globalThis.Element,
+    HTMLElement: globalThis.HTMLElement,
+    Node: globalThis.Node,
     window: globalThis.window,
     IS_REACT_ACT_ENVIRONMENT: (globalThis as typeof globalThis & {
       IS_REACT_ACT_ENVIRONMENT?: boolean;
@@ -58,7 +61,7 @@ test('ordinary rerenders keep the layer anchor attached', async () => {
       return proxy;
     },
   });
-  Object.assign(globalThis, { document, window, IS_REACT_ACT_ENVIRONMENT: true });
+  Object.assign(globalThis, { document, window, Element: window.Element, HTMLElement: window.HTMLElement, Node: window.Node, IS_REACT_ACT_ENVIRONMENT: true });
   const root = createRoot(document.querySelector('#root')!);
   const options = ['A', 'B'].map((value) => ({ value, label: value }));
   try {
@@ -80,6 +83,9 @@ test('ordinary rerenders keep the layer anchor attached', async () => {
 test('the wheel applies settled selection once and restores the saved model on failure', async () => {
   const original = {
     document: globalThis.document,
+    Element: globalThis.Element,
+    HTMLElement: globalThis.HTMLElement,
+    Node: globalThis.Node,
     window: globalThis.window,
     IS_REACT_ACT_ENVIRONMENT: (globalThis as typeof globalThis & {
       IS_REACT_ACT_ENVIRONMENT?: boolean;
@@ -88,7 +94,7 @@ test('the wheel applies settled selection once and restores the saved model on f
   const { document, window } = parseHTML('<div id="root"></div>');
   window.getComputedStyle = () => ({ direction: 'ltr', writingMode: 'horizontal-tb',
     getPropertyValue: () => '' }) as unknown as CSSStyleDeclaration;
-  Object.assign(globalThis, { document, window, IS_REACT_ACT_ENVIRONMENT: true });
+  Object.assign(globalThis, { document, window, Element: window.Element, HTMLElement: window.HTMLElement, Node: window.Node, IS_REACT_ACT_ENVIRONMENT: true });
   const root = createRoot(document.querySelector('#root')!);
   const calls: string[] = [];
   let finish: ((success: boolean) => void) | undefined;
diff --git a/packages/ui/src/__tests__/session-history-move-to-project-menu.test.tsx b/packages/ui/src/__tests__/session-history-move-to-project-menu.test.tsx
index e4ee30b71d..b61dc29b8e 100644
--- a/packages/ui/src/__tests__/session-history-move-to-project-menu.test.tsx
+++ b/packages/ui/src/__tests__/session-history-move-to-project-menu.test.tsx
@@ -88,6 +88,9 @@ async function mountRail(
 ) {
   const original = {
     document: globalThis.document,
+    Element: globalThis.Element,
+    HTMLElement: globalThis.HTMLElement,
+    Node: globalThis.Node,
     window: globalThis.window,
     requestAnimationFrame: globalThis.requestAnimationFrame,
     cancelAnimationFrame: globalThis.cancelAnimationFrame,
@@ -95,7 +98,7 @@ async function mountRail(
   };
   const { document, window } = parseHTML('<div id="root"></div>');
   installDomStubs(window);
-  Object.assign(globalThis, { document, window, IS_REACT_ACT_ENVIRONMENT: true });
+  Object.assign(globalThis, { document, window, Element: window.Element, HTMLElement: window.HTMLElement, Node: window.Node, IS_REACT_ACT_ENVIRONMENT: true });
 
   const moves: Array<{ sessionId: string; projectId: string | null }> = [];
   const data: SessionRailData = {
diff --git a/packages/ui/src/__tests__/session-history-multi-select.test.tsx b/packages/ui/src/__tests__/session-history-multi-select.test.tsx
index c3d0b000f1..ac128eb235 100644
--- a/packages/ui/src/__tests__/session-history-multi-select.test.tsx
+++ b/packages/ui/src/__tests__/session-history-multi-select.test.tsx
@@ -154,6 +154,9 @@ async function mount(
 ): Promise<Harness> {
   const original = {
     document: globalThis.document,
+    Element: globalThis.Element,
+    HTMLElement: globalThis.HTMLElement,
+    Node: globalThis.Node,
     window: globalThis.window,
     IS_REACT_ACT_ENVIRONMENT: (
       globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
@@ -161,7 +164,7 @@ async function mount(
   };
   const { document, window } = parseHTML('<div id="root"></div>');
   installDomStubs(window);
-  Object.assign(globalThis, { document, window, IS_REACT_ACT_ENVIRONMENT: true });
+  Object.assign(globalThis, { document, window, Element: window.Element, HTMLElement: window.HTMLElement, Node: window.Node, IS_REACT_ACT_ENVIRONMENT: true });
 
   const sessions = options.sessions ?? ['a', 'b', 'c', 'd'].map((id) => summary(id));
   const opened: string[] = [];
@@ -469,6 +472,9 @@ test('a rail with no selection wired up behaves exactly as before', async () =>
   // story that renders rows alone — keeps plain clicks and gains no chrome.
   const original = {
     document: globalThis.document,
+    Element: globalThis.Element,
+    HTMLElement: globalThis.HTMLElement,
+    Node: globalThis.Node,
     window: globalThis.window,
     IS_REACT_ACT_ENVIRONMENT: (
       globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
@@ -476,7 +482,7 @@ test('a rail with no selection wired up behaves exactly as before', async () =>
   };
   const { document, window } = parseHTML('<div id="root"></div>');
   installDomStubs(window);
-  Object.assign(globalThis, { document, window, IS_REACT_ACT_ENVIRONMENT: true });
+  Object.assign(globalThis, { document, window, Element: window.Element, HTMLElement: window.HTMLElement, Node: window.Node, IS_REACT_ACT_ENVIRONMENT: true });
   const sessions = ['a', 'b'].map((id) => summary(id));
   const opened: string[] = [];
   const container = document.querySelector('#root');
diff --git a/packages/ui/src/__tests__/skills-panel-locations.test.tsx b/packages/ui/src/__tests__/skills-panel-locations.test.tsx
index b157d876d3..a480f31c82 100644
--- a/packages/ui/src/__tests__/skills-panel-locations.test.tsx
+++ b/packages/ui/src/__tests__/skills-panel-locations.test.tsx
@@ -31,6 +31,9 @@ const originalGlobals = {
   cancelAnimationFrame: globalThis.cancelAnimationFrame,
   CSS: globalThis.CSS,
   document: globalThis.document,
+  Element: globalThis.Element,
+  HTMLElement: globalThis.HTMLElement,
+  Node: globalThis.Node,
   matchMedia: globalThis.matchMedia,
   requestAnimationFrame: globalThis.requestAnimationFrame,
   window: globalThis.window,
@@ -76,6 +79,9 @@ test('Skill locations under Add close the menu before opening and create only a
   Object.assign(globalThis, {
     document,
     window,
+    Element: window.Element,
+    HTMLElement: window.HTMLElement,
+    Node: window.Node,
     matchMedia: () => ({ matches: false, addEventListener() {}, removeEventListener() {} }),
     requestAnimationFrame: (callback: FrameRequestCallback) => {
       frames.set(++frameId, callback);
diff --git a/patches/@astryxdesign+core+0.6.3.patch b/patches/@astryxdesign+core+0.6.6.patch
similarity index 90%
rename from patches/@astryxdesign+core+0.6.3.patch
rename to patches/@astryxdesign+core+0.6.6.patch
index 8c8df82911..8135b4b126 100644
--- a/patches/@astryxdesign+core+0.6.3.patch
+++ b/patches/@astryxdesign+core+0.6.6.patch
@@ -1,5 +1,5 @@
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.d.ts b/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.d.ts
-index ce86b88..68b40e4 100644
+index c1dd88b65..4d683d7ca 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.d.ts
 @@ -72,6 +72,8 @@ export type ChatComposerTriggerItem = SearchableItem;
@@ -12,7 +12,7 @@ index ce86b88..68b40e4 100644
       * Search source providing items for this trigger.
       * Reuses the same SearchSource interface as Typeahead \u2014
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.js b/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.js
-index c4d7fc6..e25aed3 100644
+index 901410876..2f00fbf36 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/ChatComposerInput.js
 @@ -26,7 +26,7 @@
@@ -33,7 +33,7 @@ index c4d7fc6..e25aed3 100644
  import { ChatPastedTextToken } from "./ChatPastedTextToken.js";
  import { useChatPasteAsToken } from "./useChatPasteAsToken.js";
  import { Badge } from "../Badge/index.js";
-@@ -270,7 +270,7 @@ export function ChatComposerInput(props) {
+@@ -273,7 +273,7 @@ export function ChatComposerInput(props) {
        inputControlRef.current = null;
      };
    }, [inputControlRef, focusEditableAtEnd]);
@@ -42,7 +42,7 @@ index c4d7fc6..e25aed3 100644
      if (controlledValue === undefined || !editableRef.current) {
        return;
      }
-@@ -302,6 +302,7 @@ export function ChatComposerInput(props) {
+@@ -305,6 +305,7 @@ export function ChatComposerInput(props) {
            const range = document.createRange();
            range.selectNodeContents(editable);
            range.collapse(false);
@@ -51,10 +51,10 @@ index c4d7fc6..e25aed3 100644
            selection.addRange(range);
          }
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.d.ts b/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.d.ts
-index ff34874..28aaaab 100644
+index 38d22e5a5..f805aab0d 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.d.ts
-@@ -69,8 +69,17 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
+@@ -69,6 +69,15 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
       * @default 'balanced'
       */
      density?: Density;
@@ -68,13 +68,19 @@ index ff34874..28aaaab 100644
 +     */
 +    autoScroll?: boolean;
  }
+ /**
+  * Layout shell for a full chat interface: messages in page flow, composer
+@@ -89,7 +98,7 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
+  * </ChatLayout>
+  * ```
+  */
 -export declare function ChatLayout({ children, composer, density, emptyState, scrollButton, scrollRef: externalScrollRef, xstyle, className, style, 'data-testid': testId, ref, ...rest }: ChatLayoutProps): import("react").JSX.Element;
 +export declare function ChatLayout({ children, composer, density, emptyState, scrollButton, scrollRef: externalScrollRef, xstyle, className, style, 'data-testid': testId, autoScroll, ref, ...rest }: ChatLayoutProps): import("react").JSX.Element;
  export declare namespace ChatLayout {
      var displayName: string;
  }
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.js b/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.js
-index ff9b9fa..28afe4e 100644
+index 32d7f4719..484852957 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/ChatLayout.js
 @@ -85,7 +85,8 @@ const styles = {
@@ -107,7 +113,7 @@ index ff9b9fa..28afe4e 100644
      kX1K2I: "xr5yg4x",
      kAExgp: "xo9xo30",
      $$css: true
-@@ -195,6 +193,7 @@ export function ChatLayout({
+@@ -214,6 +212,7 @@ export function ChatLayout({
    className,
    style,
    'data-testid': testId,
@@ -115,7 +121,7 @@ index ff9b9fa..28afe4e 100644
    ref,
    ...rest
  }) {
-@@ -205,7 +204,11 @@ export function ChatLayout({
+@@ -224,7 +223,11 @@ export function ChatLayout({
  
    // --- Default scroll behavior ---
    const scroll = useChatStreamScroll({
@@ -128,34 +134,11 @@ index ff9b9fa..28afe4e 100644
    });
    const newMsgs = useChatNewMessages({
      isLocked: scroll.isLocked,
-diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatTokenizedText.js b/node_modules/@astryxdesign/core/dist/Chat/ChatTokenizedText.js
-index 5edb8f6..d80a970 100644
---- a/node_modules/@astryxdesign/core/dist/Chat/ChatTokenizedText.js
-+++ b/node_modules/@astryxdesign/core/dist/Chat/ChatTokenizedText.js
-@@ -109,8 +109,16 @@ function renderTokens(text, tokens) {
-     const token = tokenMap.get(matched);
-     if (token) {
-       parts.push(/*#__PURE__*/_jsx("span", {
--        ...{
--          className: "x3nfvp2 xxymvpz"
-+        // One line box tall with the chip centered inside it, so the chip
-+        // centers on the line rather than on the x-height midline (which leaves
-+        // a 20px chip ~1px low against CJK and mixed-case text). Must stay
-+        // equal to `insertToken`'s span in useChatComposerTokens, or a token
-+        // moves when the message is sent.
-+        style: {
-+          display: 'inline-flex',
-+          alignItems: 'center',
-+          height: '1lh',
-+          verticalAlign: 'top'
-         },
-         children: isCustomToken(token) ? token.render() : /*#__PURE__*/_jsx(Badge, {
-           label: token.label,
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/ChatToolCalls.js b/node_modules/@astryxdesign/core/dist/Chat/ChatToolCalls.js
-index 3c457d1..7d5a11a 100644
+index d2ac21fae..e4b446302 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/ChatToolCalls.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/ChatToolCalls.js
-@@ -140,6 +140,7 @@ function CallRow({
+@@ -166,6 +166,7 @@ function CallRow({
    const row = /*#__PURE__*/_jsxs("div", {
      role: hasDetail ? 'button' : undefined,
      tabIndex: hasDetail ? 0 : undefined,
@@ -163,7 +146,7 @@ index 3c457d1..7d5a11a 100644
      "aria-expanded": hasDetail ? isDetailOpen : undefined,
      "aria-controls": hasDetail && isDetailOpen ? detailId : undefined,
      onClick: toggleDetail,
-@@ -279,6 +280,10 @@ export function ChatToolCalls(props) {
+@@ -296,6 +297,10 @@ export function ChatToolCalls(props) {
    const contentId = useId();
    const isControlled = controlledExpanded !== undefined;
    const isExpanded = isControlled ? controlledExpanded : internalExpanded;
@@ -174,17 +157,17 @@ index 3c457d1..7d5a11a 100644
    const toggle = useCallback(() => {
      const next = !isExpanded;
      if (!isControlled) {
-@@ -412,7 +417,7 @@ export function ChatToolCalls(props) {
+@@ -428,7 +433,7 @@ export function ChatToolCalls(props) {
            ...{
              className: "x78zum5 xdt5ytf x7a5moj xtedp8i"
            },
 -          children: calls.map(call => /*#__PURE__*/_jsx(CallRow, {
 +          children: (isExpanded || hasExpanded) && calls.map(call => /*#__PURE__*/_jsx(CallRow, {
-             call: call
+             call: call,
+             hasClippedFocusRing: true
            }, getToolCallKey(call)))
-         })
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/chatComposerSelection.js b/node_modules/@astryxdesign/core/dist/Chat/chatComposerSelection.js
-index 97b1a3b..e50f680 100644
+index 97b1a3b97..e50f680d3 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/chatComposerSelection.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/chatComposerSelection.js
 @@ -66,6 +66,51 @@ export function restoreSelectionRange(range) {
@@ -269,7 +252,7 @@ index 97b1a3b..e50f680 100644
    selection.removeAllRanges();
    selection.addRange(range);
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/index.d.ts b/node_modules/@astryxdesign/core/dist/Chat/index.d.ts
-index ecc438e..5a8a145 100644
+index ecc438ed8..5a8a145c0 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/index.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/Chat/index.d.ts
 @@ -31,6 +31,7 @@ export { useChatPasteAsToken } from './useChatPasteAsToken';
@@ -281,7 +264,7 @@ index ecc438e..5a8a145 100644
  export { useChatLayoutContext, useChatComposerContext } from './ChatContext';
  export type { ChatComposerContextValue, ChatComposerInputControl, } from './ChatContext';
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/index.js b/node_modules/@astryxdesign/core/dist/Chat/index.js
-index 47cf976..8fb9241 100644
+index 47cf97674..8fb9241c6 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/index.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/index.js
 @@ -21,6 +21,7 @@ export { useChatStreamScroll } from "./useChatStreamScroll.js";
@@ -293,10 +276,10 @@ index 47cf976..8fb9241 100644
  export { ChatToolCalls } from "./ChatToolCalls.js";
  export { ChatLayout } from "./ChatLayout.js";
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/useChatComposerTokens.js b/node_modules/@astryxdesign/core/dist/Chat/useChatComposerTokens.js
-index bee6075..378af1e 100644
+index 73e80ca37..378af1e3f 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/useChatComposerTokens.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/useChatComposerTokens.js
-@@ -79,8 +79,14 @@ export function useChatComposerTokens({
+@@ -79,6 +79,10 @@ export function useChatComposerTokens({
      span.setAttribute('data-astryx-token-value', token.value);
      span.setAttribute('data-astryx-token-id', id);
      span.contentEditable = 'false';
@@ -305,14 +288,9 @@ index bee6075..378af1e 100644
 +    // ~1px low against CJK and mixed-case text). `vertical-align: middle` would
 +    // ignore the height; `top` puts this box on the line box itself.
      span.style.display = 'inline-flex';
--    span.style.verticalAlign = 'middle';
-+    span.style.alignItems = 'center';
-+    span.style.height = '1lh';
-+    span.style.verticalAlign = 'top';
-     range.deleteContents();
-     range.insertNode(span);
- 
-@@ -88,7 +94,11 @@ export function useChatComposerTokens({
+     span.style.alignItems = 'center';
+     span.style.height = '1lh';
+@@ -90,7 +94,11 @@ export function useChatComposerTokens({
      const space = document.createTextNode('\u00A0');
      span.after(space);
      const newRange = document.createRange();
@@ -325,7 +303,7 @@ index bee6075..378af1e 100644
      newRange.collapse(true);
      selection.removeAllRanges();
      selection.addRange(newRange);
-@@ -158,11 +168,12 @@ export function useChatComposerTokens({
+@@ -160,11 +168,12 @@ export function useChatComposerTokens({
        e.preventDefault();
        const text = e.clipboardData.getData('text/plain');
  
@@ -340,7 +318,7 @@ index bee6075..378af1e 100644
        } else {
          newRange.setStartAfter(tokenEl);
        }
-@@ -199,11 +210,12 @@ export function useChatComposerTokens({
+@@ -201,11 +210,12 @@ export function useChatComposerTokens({
      }
      span.replaceWith(textNode);
  
@@ -356,7 +334,7 @@ index bee6075..378af1e 100644
        selection.removeAllRanges();
        selection.addRange(range);
 diff --git a/node_modules/@astryxdesign/core/dist/Chat/useTriggerMenu.js b/node_modules/@astryxdesign/core/dist/Chat/useTriggerMenu.js
-index 47d4e52..d705783 100644
+index 5ace4f27d..7607bd8df 100644
 --- a/node_modules/@astryxdesign/core/dist/Chat/useTriggerMenu.js
 +++ b/node_modules/@astryxdesign/core/dist/Chat/useTriggerMenu.js
 @@ -48,6 +48,45 @@ const styles = {
@@ -503,10 +481,10 @@ index 47d4e52..d705783 100644
    }, [popover, listboxId, state, selectItem, getItemId, highlightOnHover, t]);
    return {
 diff --git a/node_modules/@astryxdesign/core/dist/CodeBlock/CodeBlock.js b/node_modules/@astryxdesign/core/dist/CodeBlock/CodeBlock.js
-index fcc2513..0f2b8f8 100644
+index 333d6ce0e..25d679e27 100644
 --- a/node_modules/@astryxdesign/core/dist/CodeBlock/CodeBlock.js
 +++ b/node_modules/@astryxdesign/core/dist/CodeBlock/CodeBlock.js
-@@ -218,15 +218,8 @@ function renderLines(lines, highlightSet, renderLineContent, lineNumbers, chunkS
+@@ -220,15 +220,8 @@ function renderLines(lines, highlightSet, renderLineContent, lineNumbers, chunkS
    for (let start = 0; start < lines.length; start += chunkSize) {
      const end = Math.min(start + chunkSize, lines.length);
      const chunkLines = lines.slice(start, end);
@@ -524,7 +502,7 @@ index fcc2513..0f2b8f8 100644
          lines: chunkLines,
          startIndex: start,
 diff --git a/node_modules/@astryxdesign/core/dist/CodeBlock/tokenizer.js b/node_modules/@astryxdesign/core/dist/CodeBlock/tokenizer.js
-index eac4c4b..1ade6f9 100644
+index eac4c4ba5..1ade6f9ec 100644
 --- a/node_modules/@astryxdesign/core/dist/CodeBlock/tokenizer.js
 +++ b/node_modules/@astryxdesign/core/dist/CodeBlock/tokenizer.js
 @@ -39,7 +39,9 @@ function buildLanguage(lang) {
@@ -539,10 +517,10 @@ index eac4c4b..1ade6f9 100644
  }
  function buildLanguageUncached(lang) {
 diff --git a/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.d.ts b/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.d.ts
-index 82ae62c..a97eff5 100644
+index f9df685d7..17f464bce 100644
 --- a/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.d.ts
-@@ -42,6 +42,12 @@ export interface DropdownMenuItemProps extends Pick<BaseProps, 'xstyle' | 'class
+@@ -62,6 +62,12 @@ export interface DropdownMenuItemProps extends Pick<BaseProps, 'xstyle' | 'class
       * @default true
       */
      hasCloseOnSelect?: boolean;
@@ -555,20 +533,20 @@ index 82ae62c..a97eff5 100644
      /**
       * Visual variant. `'destructive'` renders the label, description, and icon in
       * the error color for dangerous actions (e.g. Delete). @default 'default'
-@@ -62,7 +68,7 @@ export interface DropdownMenuItemProps extends Pick<BaseProps, 'xstyle' | 'class
+@@ -89,7 +95,7 @@ export interface DropdownMenuItemProps extends Pick<BaseProps, 'xstyle' | 'class
   * </DropdownMenu>
   * ```
   */
--export declare function DropdownMenuItem({ icon, label, description, onClick, isDisabled, endContent, hasCloseOnSelect, variant, xstyle, className, style, }: DropdownMenuItemProps): import("react").JSX.Element;
-+export declare function DropdownMenuItem({ icon, 'aria-busy': ariaBusy, label, description, onClick, isDisabled, endContent, hasCloseOnSelect, variant, xstyle, className, style, }: DropdownMenuItemProps): import("react").JSX.Element;
+-export declare function DropdownMenuItem({ icon, label, description, onClick, href, target, rel, isDisabled, endContent, hasCloseOnSelect, variant, xstyle, className, style, ref, }: DropdownMenuItemProps): import("react").JSX.Element;
++export declare function DropdownMenuItem({ icon, 'aria-busy': ariaBusy, label, description, onClick, href, target, rel, isDisabled, endContent, hasCloseOnSelect, variant, xstyle, className, style, ref, }: DropdownMenuItemProps): import("react").JSX.Element;
  export declare namespace DropdownMenuItem {
      var displayName: string;
  }
 diff --git a/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.js b/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.js
-index 1975140..bf6cb77 100644
+index bfbe690ef..4a6dc58bd 100644
 --- a/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.js
 +++ b/node_modules/@astryxdesign/core/dist/DropdownMenu/DropdownMenuItem.js
-@@ -91,6 +91,7 @@ const itemSizeStyles = {
+@@ -97,6 +97,7 @@ const itemSizeStyles = {
   */
  export function DropdownMenuItem({
    icon,
@@ -576,16 +554,16 @@ index 1975140..bf6cb77 100644
    label,
    description,
    onClick,
-@@ -117,6 +118,7 @@ export function DropdownMenuItem({
-   const isDestructive = variant === 'destructive';
-   return /*#__PURE__*/_jsx(Item, {
+@@ -166,6 +167,7 @@ export function DropdownMenuItem({
+     ,
+     as: href != null ? LinkComponent : undefined,
      role: "menuitem",
 +    'aria-busy': ariaBusy,
      tabIndex: isDisabled ? undefined : -1,
      onPointerMove: handlePointerMove,
-     startContent: icon ? renderIconSlot(icon, {
+     ...pressable,
 diff --git a/node_modules/@astryxdesign/core/dist/Layer/useTouchTrigger.js b/node_modules/@astryxdesign/core/dist/Layer/useTouchTrigger.js
-index 95e7519..3680732 100644
+index 95e7519d0..36807321d 100644
 --- a/node_modules/@astryxdesign/core/dist/Layer/useTouchTrigger.js
 +++ b/node_modules/@astryxdesign/core/dist/Layer/useTouchTrigger.js
 @@ -25,7 +25,7 @@
@@ -613,10 +591,10 @@ index 95e7519..3680732 100644
  }
 \ No newline at end of file
 diff --git a/node_modules/@astryxdesign/core/dist/List/List.js b/node_modules/@astryxdesign/core/dist/List/List.js
-index 8753b5f..43a5abe 100644
+index 7d261b4a0..e81e3bda5 100644
 --- a/node_modules/@astryxdesign/core/dist/List/List.js
 +++ b/node_modules/@astryxdesign/core/dist/List/List.js
-@@ -89,6 +89,7 @@ export function List({
+@@ -95,6 +95,7 @@ export function List({
    className,
    style,
    'data-testid': testId,
@@ -624,7 +602,7 @@ index 8753b5f..43a5abe 100644
    ref,
    ...props
  }) {
-@@ -106,7 +107,8 @@ export function List({
+@@ -113,7 +114,8 @@ export function List({
      // is part of its contract and wins on conflict.
      ,
      ...props,
@@ -635,10 +613,10 @@ index 8753b5f..43a5abe 100644
      // unconditionally would erase a label a consumer pointed at their own
      // heading.
 diff --git a/node_modules/@astryxdesign/core/dist/Markdown/Markdown.d.ts b/node_modules/@astryxdesign/core/dist/Markdown/Markdown.d.ts
-index 96babc5..881f060 100644
+index 7dbfcd892..49721f6dc 100644
 --- a/node_modules/@astryxdesign/core/dist/Markdown/Markdown.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/Markdown/Markdown.d.ts
-@@ -99,6 +99,10 @@ export interface MarkdownProps<Plugins extends ReadonlyArray<MarkdownPluginEntry
+@@ -98,6 +98,10 @@ export interface MarkdownProps<Plugins extends ReadonlyArray<MarkdownPluginEntry
       */
      headingLevelStart?: 1 | 2 | 3 | 4 | 5 | 6;
      isStreaming?: boolean;
@@ -650,19 +628,19 @@ index 96babc5..881f060 100644
      /**
       * Citation sources keyed by ID. When provided, `[id]` and `【id】` markers
 diff --git a/node_modules/@astryxdesign/core/dist/Markdown/Markdown.js b/node_modules/@astryxdesign/core/dist/Markdown/Markdown.js
-index 2a294a5..052de46 100644
+index 2326b8d0d..d2877de74 100644
 --- a/node_modules/@astryxdesign/core/dist/Markdown/Markdown.js
 +++ b/node_modules/@astryxdesign/core/dist/Markdown/Markdown.js
 @@ -8,7 +8,7 @@
   * @output Exports Markdown component, MarkdownProps, and renderer contracts
   * @position Core implementation; renders markdown as Astryx components
   */
--import { Component, Suspense, useMemo, useRef } from 'react';
-+import { Component, Suspense, useMemo, useRef, useState } from 'react';
+-import { Suspense, useMemo, useRef } from 'react';
++import { Suspense, useMemo, useRef, useState } from 'react';
  import { Fragment } from 'react';
  import * as stylex from '@stylexjs/stylex';
  import "../theme/tokens.stylex.js";
-@@ -1205,6 +1205,8 @@ export function Markdown({
+@@ -1262,6 +1262,8 @@ export function Markdown({
    density = 'default',
    headingLevelStart = 1,
    isStreaming = false,
@@ -671,7 +649,7 @@ index 2a294a5..052de46 100644
    onLinkClick,
    sources,
    citationStyle = 'label',
-@@ -1251,7 +1253,10 @@ export function Markdown({
+@@ -1309,7 +1311,10 @@ export function Markdown({
  
    // Smooth bursty streamed chunks into a steady character-by-character reveal.
    // When not streaming, the hook returns children unchanged (no-op).
@@ -683,7 +661,7 @@ index 2a294a5..052de46 100644
    const incrementalStateRef = useRef(createIncrementalState());
    // Reset incremental cache when parser-affecting component options toggle —
    // cached settled blocks were parsed with the previous setting.
-@@ -1267,21 +1272,21 @@ export function Markdown({
+@@ -1325,21 +1330,21 @@ export function Markdown({
        return [];
      }
      if (isStreaming) {
@@ -709,9 +687,9 @@ index 2a294a5..052de46 100644
 -  }, preparedPlugins, transformSource, !isStreaming, 'block').children, [parsedBlocks, preparedPlugins, transformSource, isStreaming]);
 +  }, preparedPlugins, streamingSource, !isStreaming, 'block').children, [parsedBlocks, preparedPlugins, streamingSource, isStreaming]);
  
-   // Assign each top-level heading the slug that parseOutlineFromMarkdown
-   // would derive for it, so Outline hash links built from the same source
-@@ -1308,10 +1313,10 @@ export function Markdown({
+   // Resolve one post-transform projection for Markdown and derived Outline.
+   // The default remains root-only; installed first-party modules own any
+@@ -1358,10 +1363,10 @@ export function Markdown({
        return [];
      }
      const options = hasMathRenderer ? mathParseOptions : legacyParseOptions;
@@ -725,7 +703,7 @@ index 2a294a5..052de46 100644
    const inlineNodes = useMemo(() => {
      if (display !== 'inline') {
        return [];
-@@ -1342,17 +1347,25 @@ export function Markdown({
+@@ -1392,17 +1397,25 @@ export function Markdown({
      const tickMs = tick != null ? Math.max(4, Math.round(tick / 10)) : 50;
      return Math.min(Math.ceil(duration / tickMs), 12);
    }, [token]);
@@ -762,7 +740,7 @@ index 2a294a5..052de46 100644
    const cursor = {
      offset: 0,
      boundaries,
-@@ -1380,9 +1393,6 @@ export function Markdown({
+@@ -1431,9 +1444,6 @@ export function Markdown({
        children: inlineNodes.map((node, i) => renderInline(node, i, onLinkClick, cursor, citationCtx, LinkComponent, inlinePlugins, components, preparedPlugins))
      });
  
@@ -772,8 +750,8 @@ index 2a294a5..052de46 100644
      return renderedInline;
    }
    const rendered = /*#__PURE__*/_jsx("div", {
-@@ -1399,11 +1409,6 @@ export function Markdown({
-     children: blocks.map((block, i) => renderBlock(block, i, blocks.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidth ? typeof contentWidth === 'number' ? `${contentWidth}px` : contentWidth : null, contentAlign, LinkComponent, inlinePlugins, components, preparedPlugins, t, headingIdMap))
+@@ -1451,11 +1461,6 @@ export function Markdown({
+     children: blocks.map((block, i) => renderBlock(block, i, blocks.length, density, headingLevelStart, onLinkClick, cursor, citationCtx, contentWidth ? typeof contentWidth === 'number' ? `${contentWidth}px` : contentWidth : null, contentAlign, LinkComponent, inlinePlugins, components, preparedPlugins, t, headingProjection))
    });
  
 -  // Store current blocks for next render's boundary calculation.
@@ -786,10 +764,10 @@ index 2a294a5..052de46 100644
  Markdown.displayName = 'Markdown';
 \ No newline at end of file
 diff --git a/node_modules/@astryxdesign/core/dist/Markdown/parser.js b/node_modules/@astryxdesign/core/dist/Markdown/parser.js
-index 107ef3f..5c4dede 100644
+index d24b883a6..3f41b27a0 100644
 --- a/node_modules/@astryxdesign/core/dist/Markdown/parser.js
 +++ b/node_modules/@astryxdesign/core/dist/Markdown/parser.js
-@@ -2264,6 +2264,7 @@ export function trimStreamingArtifacts(input, options) {
+@@ -3200,6 +3200,7 @@ export function trimStreamingArtifacts(input, options) {
    const lastNL = displayTrimmed.lastIndexOf('\n');
    const prefix = lastNL === -1 ? '' : displayTrimmed.slice(0, lastNL + 1);
    let tail = lastNL === -1 ? displayTrimmed : displayTrimmed.slice(lastNL + 1);
@@ -797,7 +775,7 @@ index 107ef3f..5c4dede 100644
    if (options?.math) {
      // Hold an unmatched inline opener so raw TeX syntax does not flash while
      // streaming. If another unescaped dollar is already present but fails the
-@@ -2278,6 +2279,7 @@ export function trimStreamingArtifacts(input, options) {
+@@ -3214,6 +3215,7 @@ export function trimStreamingArtifacts(input, options) {
        }
        const close = findInlineMathEnd(tail, index);
        if (close !== -1) {
@@ -805,7 +783,7 @@ index 107ef3f..5c4dede 100644
          index = close;
          continue;
        }
-@@ -2295,10 +2297,23 @@ export function trimStreamingArtifacts(input, options) {
+@@ -3231,10 +3233,23 @@ export function trimStreamingArtifacts(input, options) {
        index = laterDollar;
      }
    }
@@ -830,7 +808,7 @@ index 107ef3f..5c4dede 100644
    if (lastBracket !== -1) {
      const afterBracket = tail.slice(lastBracket);
      // A closed link/image has ](...)  somewhere after the [
-@@ -2357,8 +2372,9 @@ export function trimStreamingArtifacts(input, options) {
+@@ -3293,8 +3308,9 @@ export function trimStreamingArtifacts(input, options) {
        while (idx + markerLen < tail.length && tail[idx + markerLen] === '*') {
          markerLen++;
        }
@@ -842,7 +820,7 @@ index 107ef3f..5c4dede 100644
          searchFrom = idx + markerLen;
          continue;
        }
-@@ -2426,8 +2442,10 @@ export function trimStreamingArtifacts(input, options) {
+@@ -3366,8 +3382,10 @@ export function trimStreamingArtifacts(input, options) {
        if (idx === -1) {
          break;
        }
@@ -856,7 +834,7 @@ index 107ef3f..5c4dede 100644
      }
      if (count % 2 === 1) {
 diff --git a/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.d.ts b/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.d.ts
-index c55f046..09efbbe 100644
+index c55f04685..09efbbea5 100644
 --- a/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.d.ts
 @@ -70,6 +70,12 @@ export interface SideNavItemProps extends BaseProps<HTMLElement> {
@@ -882,10 +860,10 @@ index c55f046..09efbbe 100644
      var displayName: string;
  }
 diff --git a/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.js b/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.js
-index b56c9d5..463f665 100644
+index c406f0f86..7cb4df0dc 100644
 --- a/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.js
 +++ b/node_modules/@astryxdesign/core/dist/SideNav/SideNavItem.js
-@@ -234,6 +234,7 @@ export function SideNavItem({
+@@ -235,6 +235,7 @@ export function SideNavItem({
    href,
    onClick,
    endContent,
@@ -893,7 +871,7 @@ index b56c9d5..463f665 100644
    actions,
    children,
    collapsible: itemCollapsible,
-@@ -550,7 +551,7 @@ export function SideNavItem({
+@@ -567,7 +568,7 @@ export function SideNavItem({
    const item = /*#__PURE__*/_jsxs("div", {
      ref: itemRef,
      ...stylex.props(styles.root, xstyle),
@@ -903,7 +881,7 @@ index b56c9d5..463f665 100644
        role: "group",
        "aria-labelledby": `${id}-label`,
 diff --git a/node_modules/@astryxdesign/core/dist/Spinner/Spinner.js b/node_modules/@astryxdesign/core/dist/Spinner/Spinner.js
-index 0c81fd3..51e9632 100644
+index 0c81fd329..51e963276 100644
 --- a/node_modules/@astryxdesign/core/dist/Spinner/Spinner.js
 +++ b/node_modules/@astryxdesign/core/dist/Spinner/Spinner.js
 @@ -174,11 +174,8 @@ function pinRingsToTimelineOrigin() {
@@ -987,7 +965,7 @@ index 0c81fd3..51e9632 100644
        })]
      })
 diff --git a/node_modules/@astryxdesign/core/dist/Toast/ToastViewport.js b/node_modules/@astryxdesign/core/dist/Toast/ToastViewport.js
-index bcc42ce..1ad2ef6 100644
+index a5b46badf..e8faf72d5 100644
 --- a/node_modules/@astryxdesign/core/dist/Toast/ToastViewport.js
 +++ b/node_modules/@astryxdesign/core/dist/Toast/ToastViewport.js
 @@ -14,6 +14,7 @@
@@ -998,7 +976,7 @@ index bcc42ce..1ad2ef6 100644
  import * as stylex from '@stylexjs/stylex';
  import "../theme/tokens.stylex.js";
  import { spacingVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
-@@ -239,8 +240,9 @@ export function ToastViewport({
+@@ -245,8 +246,9 @@ export function ToastViewport({
    const toastsRef = useRef(toasts);
    toastsRef.current = toasts;
  
@@ -1009,7 +987,7 @@ index bcc42ce..1ad2ef6 100644
    // Toast ids whose exit has begun — guards onHide from double-firing (see
    // removeToast). Mirrors exitingIds state, readable synchronously.
    const exitingIdsRef = useRef(new Set());
-@@ -424,20 +426,64 @@ export function ToastViewport({
+@@ -432,20 +434,64 @@ export function ToastViewport({
      insetStyle.insetInlineEnd = inset.end;
    }
  
@@ -1086,7 +1064,7 @@ index bcc42ce..1ad2ef6 100644
  
    // F6 jumps focus into the toast viewport — the standard "go to
    // notifications" affordance. Focus the first control in the newest toast,
-@@ -479,9 +525,7 @@ export function ToastViewport({
+@@ -487,9 +533,7 @@ export function ToastViewport({
    }, [hasToasts, getFocusable]);
    const posStyle = position === 'topEnd' ? styles.topEnd : position === 'topStart' ? styles.topStart : position === 'bottomStart' ? styles.bottomStart : styles.bottomEnd;
    const isReversed = position === 'topEnd' || position === 'topStart';
@@ -1097,10 +1075,10 @@ index bcc42ce..1ad2ef6 100644
        ref: viewportRef,
        role: hasToasts ? 'region' : undefined,
        "aria-label": hasToasts ? t('@astryx.toast.viewport') : undefined,
-@@ -500,7 +544,12 @@ export function ToastViewport({
-         onExited: handleExited,
-         onDismiss: removeToast
-       }, entry.id))
+@@ -510,7 +554,12 @@ export function ToastViewport({
+           onDismiss: removeToast
+         }, entry.id))
+       })
 -    })]
 +    });
 +  return /*#__PURE__*/_jsxs(ToastContext, {
@@ -1113,10 +1091,10 @@ index bcc42ce..1ad2ef6 100644
  ToastViewport.displayName = 'ToastViewport';
 \ No newline at end of file
 diff --git a/node_modules/@astryxdesign/core/dist/astryx.css b/node_modules/@astryxdesign/core/dist/astryx.css
-index 69573c6..a32e7a4 100644
+index 3020de04d..b94965572 100644
 --- a/node_modules/@astryxdesign/core/dist/astryx.css
 +++ b/node_modules/@astryxdesign/core/dist/astryx.css
-@@ -65,6 +65,7 @@
+@@ -68,6 +68,7 @@
    @keyframes xv1hr86-B{from{opacity:0;transform:translateY(calc(-1 * var(--spacing-2))) scale(.95);}to{opacity:1;transform:translateY(0) scale(1);}}
    @keyframes x1b6yrix-B{from{opacity:0;transform:translateY(var(--spacing-2));}to{opacity:1;transform:translateY(0);}}
    @keyframes xiylxmw-B{from{opacity:0;transform:translateY(calc(-1 * var(--spacing-2)));}to{opacity:1;transform:translateY(0);}}
@@ -1124,7 +1102,7 @@ index 69573c6..a32e7a4 100644
    @keyframes x1wbvqyn-B{0%{stroke-dashoffset:0;}100%{stroke-dashoffset:calc(var(--_spinner-ring-diameter) * -3.141592653589793);}}
    @keyframes x1c2q33o-B{0%{transform:translateX(100%);}100%{transform:translateX(-250%);}}
    @keyframes xr3m334-B{0%{transform:translateX(-100%);}100%{transform:translateX(250%);}}
-@@ -577,7 +578,7 @@
+@@ -625,7 +626,7 @@
    .xk2sxw7:focus-within:not(#\#):not(#\#){border-color:var(--color-error)}
    .xyq33ac:focus-within:not(#\#):not(#\#){border-color:var(--color-success)}
    .xa1yw2k:focus-within:not(#\#):not(#\#){border-color:var(--color-warning)}
@@ -1133,7 +1111,7 @@ index 69573c6..a32e7a4 100644
    .x1dordxg:focus-within:not(#\#):not(#\#){overflow:visible}
    .xb0m1lw:has(> div > .astryx-layout-content):not(#\#):not(#\#){margin-inline:0}
    .x16s19ga:has(:focus-visible):not(#\#):not(#\#){outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color)}
-@@ -650,6 +651,7 @@
+@@ -700,6 +701,7 @@
    .x3psbcj:not(#\#):not(#\#):not(#\#){animation-name:x1ahk7ht-B}
    .x1dvww92:not(#\#):not(#\#):not(#\#){animation-name:x1b6yrix-B}
    .x97zbip:not(#\#):not(#\#):not(#\#){animation-name:x1k48ry3-B}
@@ -1141,7 +1119,7 @@ index 69573c6..a32e7a4 100644
    .x1nlxm0d:not(#\#):not(#\#):not(#\#){animation-name:x1wbvqyn-B}
    .x1gbn2au:not(#\#):not(#\#):not(#\#){animation-name:x1xhkexc-B}
    .xeuoslp:not(#\#):not(#\#):not(#\#){animation-name:xgnty7z-B}
-@@ -663,6 +665,7 @@
+@@ -713,6 +715,7 @@
    .x4hg4is:not(#\#):not(#\#):not(#\#){animation-timing-function:ease-in-out}
    .x1esw782:not(#\#):not(#\#):not(#\#){animation-timing-function:linear}
    .x193epu2:not(#\#):not(#\#):not(#\#){animation-timing-function:steps(10,end)}
@@ -1149,7 +1127,7 @@ index 69573c6..a32e7a4 100644
    .x128ha8g:not(#\#):not(#\#):not(#\#){animation-timing-function:var(--ease-standard)}
    .xjyslct:not(#\#):not(#\#):not(#\#){appearance:none}
    .x1plog1:not(#\#):not(#\#):not(#\#){aspect-ratio:1}
-@@ -1367,7 +1370,7 @@
+@@ -1440,7 +1443,7 @@
    .x1l5jwag:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:calc(0px - var(--focus-outline-width))}
    .x13aywxo:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--button-focus-offset)}
    .x1vwwbsn:focus-visible:not(#\#):not(#\#):not(#\#){outline-offset:var(--focus-outline-offset)}
@@ -1158,7 +1136,7 @@ index 69573c6..a32e7a4 100644
    .x1jhp3zv:focus-visible:not(#\#):not(#\#):not(#\#){outline-style:var(--focus-outline-style)}
    .x1vidyx5:focus-visible:not(#\#):not(#\#):not(#\#){outline-width:var(--focus-outline-width)}
    .x1n6uwha:is([dir="rtl"] *):not(#\#):not(#\#):not(#\#){padding-inline-end:max(var(--spacing-4),env(safe-area-inset-left,0px))}
-@@ -1850,8 +1853,8 @@
+@@ -1950,8 +1953,8 @@
    .x5lhr3w:not(#\#):not(#\#):not(#\#):not(#\#){width:var(--x-width)}
    .x1wp2rvj.x1wp2rvj:where(.x139im0d:last-child *):not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0}
    .x132qfvm:focus-within:not(#\#):not(#\#):not(#\#):not(#\#){height:auto}
@@ -1170,7 +1148,7 @@ index 69573c6..a32e7a4 100644
    .x10okhzq:focus-within:not(#\#):not(#\#):not(#\#):not(#\#){width:auto}
    .x5du68j:has(~ * [data-chat-name]):not(#\#):not(#\#):not(#\#):not(#\#){margin-top:var(--spacing-5)}
 diff --git a/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.d.ts b/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.d.ts
-index 7a35d1c..50ee70b 100644
+index 7a35d1c87..50ee70b2c 100644
 --- a/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.d.ts
 +++ b/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.d.ts
 @@ -11,6 +11,8 @@ export interface UseStreamingTextOptions {
@@ -1183,7 +1161,7 @@ index 7a35d1c..50ee70b 100644
  /**
   * Snap a UTF-16 code-unit offset down to the start of the grapheme cluster
 diff --git a/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.js b/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.js
-index 693d728..7d5724e 100644
+index 693d7282c..7d5724ea3 100644
 --- a/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.js
 +++ b/node_modules/@astryxdesign/core/dist/hooks/useStreamingText.js
 @@ -24,7 +24,7 @@
@@ -1339,7 +1317,7 @@ index 693d728..7d5724e 100644
  }
 \ No newline at end of file
 diff --git a/node_modules/@astryxdesign/core/src/Chat/ChatComposerInput.tsx b/node_modules/@astryxdesign/core/src/Chat/ChatComposerInput.tsx
-index e63c86f..ea489b3 100644
+index 82b9466c6..f6f65ee50 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/ChatComposerInput.tsx
 +++ b/node_modules/@astryxdesign/core/src/Chat/ChatComposerInput.tsx
 @@ -32,6 +32,7 @@ import {
@@ -1358,7 +1336,7 @@ index e63c86f..ea489b3 100644
    placeCaretAtEnd,
    getSelectionRangeInside,
    restoreSelectionRange,
-@@ -126,6 +128,8 @@ export type ChatComposerTriggerItem = SearchableItem;
+@@ -127,6 +129,8 @@ export type ChatComposerTriggerItem = SearchableItem;
  export type ChatComposerTrigger = {
    /** Character that activates this trigger menu (e.g. '@', '/') */
    character: string;
@@ -1367,7 +1345,7 @@ index e63c86f..ea489b3 100644
    /**
     * Search source providing items for this trigger.
     * Reuses the same SearchSource interface as Typeahead \u2014
-@@ -485,7 +489,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
+@@ -506,7 +510,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
      };
    }, [inputControlRef, focusEditableAtEnd]);
  
@@ -1376,7 +1354,7 @@ index e63c86f..ea489b3 100644
      if (controlledValue === undefined || !editableRef.current) {
        return;
      }
-@@ -517,6 +521,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
+@@ -538,6 +542,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
            const range = document.createRange();
            range.selectNodeContents(editable);
            range.collapse(false);
@@ -1385,7 +1363,7 @@ index e63c86f..ea489b3 100644
            selection.addRange(range);
          }
 diff --git a/node_modules/@astryxdesign/core/src/Chat/ChatLayout.tsx b/node_modules/@astryxdesign/core/src/Chat/ChatLayout.tsx
-index d45a912..7dba080 100644
+index 295825a91..f97a4657b 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/ChatLayout.tsx
 +++ b/node_modules/@astryxdesign/core/src/Chat/ChatLayout.tsx
 @@ -96,6 +96,15 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
@@ -1441,7 +1419,7 @@ index d45a912..7dba080 100644
      maskImage: 'linear-gradient(to bottom, transparent, black 48px)',
      WebkitMaskImage: 'linear-gradient(to bottom, transparent, black 48px)',
    },
-@@ -279,6 +294,7 @@ export function ChatLayout({
+@@ -298,6 +313,7 @@ export function ChatLayout({
    className,
    style,
    'data-testid': testId,
@@ -1449,7 +1427,7 @@ index d45a912..7dba080 100644
    ref,
    ...rest
  }: ChatLayoutProps) {
-@@ -289,7 +305,13 @@ export function ChatLayout({
+@@ -308,7 +324,13 @@ export function ChatLayout({
    const isSelfScrolling = !externalScrollRef;
  
    // --- Default scroll behavior ---
@@ -1464,33 +1442,11 @@ index d45a912..7dba080 100644
    const newMsgs = useChatNewMessages({
      isLocked: scroll.isLocked,
      onResize: scroll.scrollIfLocked,
-diff --git a/node_modules/@astryxdesign/core/src/Chat/ChatTokenizedText.tsx b/node_modules/@astryxdesign/core/src/Chat/ChatTokenizedText.tsx
-index 7b6bf87..c9943bf 100644
---- a/node_modules/@astryxdesign/core/src/Chat/ChatTokenizedText.tsx
-+++ b/node_modules/@astryxdesign/core/src/Chat/ChatTokenizedText.tsx
-@@ -36,8 +36,16 @@ const styles = stylex.create({
-     display: 'inline',
-   },
-   token: {
-+    // One line box tall with the chip centered inside it, so the chip centers
-+    // on the line rather than on the x-height midline (which leaves a 20px chip
-+    // ~1px low against CJK and mixed-case text). `vertical-align: middle` would
-+    // ignore the height; `top` puts this box on the line box itself. Must stay
-+    // equal to `insertToken`'s span in useChatComposerTokens, or a token moves
-+    // when the message is sent.
-     display: 'inline-flex',
--    verticalAlign: 'middle',
-+    alignItems: 'center',
-+    height: '1lh',
-+    verticalAlign: 'top',
-   },
- });
- 
 diff --git a/node_modules/@astryxdesign/core/src/Chat/ChatToolCalls.tsx b/node_modules/@astryxdesign/core/src/Chat/ChatToolCalls.tsx
-index 68a424e..d4f0c5e 100644
+index a1d0e8d0a..5a4a64c06 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/ChatToolCalls.tsx
 +++ b/node_modules/@astryxdesign/core/src/Chat/ChatToolCalls.tsx
-@@ -413,6 +413,7 @@ function CallRow({call}: {call: ChatToolCallItem}) {
+@@ -427,6 +427,7 @@ function CallRow({
      <div
        role={hasDetail ? 'button' : undefined}
        tabIndex={hasDetail ? 0 : undefined}
@@ -1498,7 +1454,7 @@ index 68a424e..d4f0c5e 100644
        aria-expanded={hasDetail ? isDetailOpen : undefined}
        aria-controls={hasDetail && isDetailOpen ? detailId : undefined}
        onClick={toggleDetail}
-@@ -547,6 +548,10 @@ export function ChatToolCalls(props: ChatToolCallsProps) {
+@@ -563,6 +564,10 @@ export function ChatToolCalls(props: ChatToolCallsProps) {
    const contentId = useId();
    const isControlled = controlledExpanded !== undefined;
    const isExpanded = isControlled ? controlledExpanded : internalExpanded;
@@ -1509,22 +1465,17 @@ index 68a424e..d4f0c5e 100644
  
    const toggle = useCallback(() => {
      const next = !isExpanded;
-@@ -674,9 +679,10 @@ export function ChatToolCalls(props: ChatToolCallsProps) {
+@@ -695,7 +700,7 @@ export function ChatToolCalls(props: ChatToolCallsProps) {
          )}>
          <div {...stylex.props(styles.groupContentInner)}>
            <div {...stylex.props(styles.list)}>
 -            {calls.map(call => (
--              <CallRow key={getToolCallKey(call)} call={call} />
--            ))}
-+            {(isExpanded || hasExpanded) &&
-+              calls.map(call => (
-+                <CallRow key={getToolCallKey(call)} call={call} />
-+              ))}
-           </div>
-         </div>
-       </div>
++            {(isExpanded || hasExpanded) && calls.map(call => (
+               <CallRow
+                 key={getToolCallKey(call)}
+                 call={call}
 diff --git a/node_modules/@astryxdesign/core/src/Chat/chatComposerSelection.ts b/node_modules/@astryxdesign/core/src/Chat/chatComposerSelection.ts
-index 0f31ca8..7fa3a89 100644
+index 0f31ca85e..7fa3a89cf 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/chatComposerSelection.ts
 +++ b/node_modules/@astryxdesign/core/src/Chat/chatComposerSelection.ts
 @@ -69,6 +69,52 @@ export function restoreSelectionRange(range: Range): void {
@@ -1610,7 +1561,7 @@ index 0f31ca8..7fa3a89 100644
    selection.removeAllRanges();
    selection.addRange(range);
 diff --git a/node_modules/@astryxdesign/core/src/Chat/index.ts b/node_modules/@astryxdesign/core/src/Chat/index.ts
-index f778b8b..4d8bcbf 100644
+index f778b8b1e..4d8bcbf19 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/index.ts
 +++ b/node_modules/@astryxdesign/core/src/Chat/index.ts
 @@ -81,6 +81,7 @@ export type {
@@ -1622,26 +1573,10 @@ index f778b8b..4d8bcbf 100644
  export {useChatLayoutContext, useChatComposerContext} from './ChatContext';
  export type {
 diff --git a/node_modules/@astryxdesign/core/src/Chat/useChatComposerTokens.ts b/node_modules/@astryxdesign/core/src/Chat/useChatComposerTokens.ts
-index 071303f..d28601a 100644
+index 70855177e..fb8f31d48 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/useChatComposerTokens.ts
 +++ b/node_modules/@astryxdesign/core/src/Chat/useChatComposerTokens.ts
-@@ -119,8 +119,14 @@ export function useChatComposerTokens({
-       span.setAttribute('data-astryx-token-value', token.value);
-       span.setAttribute('data-astryx-token-id', id);
-       span.contentEditable = 'false';
-+      // One line box tall with the chip centered inside it, so the chip centers
-+      // on the line rather than on the x-height midline (which leaves a 20px
-+      // chip ~1px low against CJK and mixed-case text). `vertical-align:
-+      // middle` would ignore the height; `top` puts this box on the line box.
-       span.style.display = 'inline-flex';
--      span.style.verticalAlign = 'middle';
-+      span.style.alignItems = 'center';
-+      span.style.height = '1lh';
-+      span.style.verticalAlign = 'top';
- 
-       range.deleteContents();
-       range.insertNode(span);
-@@ -130,7 +136,11 @@ export function useChatComposerTokens({
+@@ -132,7 +132,11 @@ export function useChatComposerTokens({
        span.after(space);
  
        const newRange = document.createRange();
@@ -1654,7 +1589,7 @@ index 071303f..d28601a 100644
        newRange.collapse(true);
        selection.removeAllRanges();
        selection.addRange(newRange);
-@@ -219,7 +229,9 @@ export function useChatComposerTokens({
+@@ -221,7 +225,9 @@ export function useChatComposerTokens({
          const space = tokenEl.nextSibling;
          const newRange = document.createRange();
          if (space && space.nodeType === Node.TEXT_NODE) {
@@ -1665,7 +1600,7 @@ index 071303f..d28601a 100644
          } else {
            newRange.setStartAfter(tokenEl);
          }
-@@ -266,7 +278,9 @@ export function useChatComposerTokens({
+@@ -268,7 +274,9 @@ export function useChatComposerTokens({
        const selection = window.getSelection();
        if (selection) {
          const range = document.createRange();
@@ -1677,10 +1612,10 @@ index 071303f..d28601a 100644
          selection.removeAllRanges();
          selection.addRange(range);
 diff --git a/node_modules/@astryxdesign/core/src/Chat/useTriggerMenu.tsx b/node_modules/@astryxdesign/core/src/Chat/useTriggerMenu.tsx
-index 764be45..10a2de9 100644
+index 30a91de6f..bd8cbdf5e 100644
 --- a/node_modules/@astryxdesign/core/src/Chat/useTriggerMenu.tsx
 +++ b/node_modules/@astryxdesign/core/src/Chat/useTriggerMenu.tsx
-@@ -168,7 +168,68 @@ const styles = stylex.create({
+@@ -169,7 +169,68 @@ const styles = stylex.create({
  // Helpers
  // =============================================================================
  
@@ -1750,7 +1685,7 @@ index 764be45..10a2de9 100644
    const selection = window.getSelection();
    if (!selection || selection.rangeCount === 0) {
      return null;
-@@ -184,7 +245,9 @@ function getTextBeforeCursor(editable: HTMLDivElement): string | null {
+@@ -185,7 +246,9 @@ function getTextBeforeCursor(editable: HTMLDivElement): string | null {
  
    const node = range.startContainer;
    if (node.nodeType === Node.TEXT_NODE) {
@@ -1761,7 +1696,7 @@ index 764be45..10a2de9 100644
    }
  
    return null;
-@@ -201,15 +264,16 @@ function findActiveTrigger(
+@@ -202,15 +265,16 @@ function findActiveTrigger(
    for (let i = textBeforeCursor.length - 1; i >= 0; i--) {
      const char = textBeforeCursor[i];
  
@@ -1781,7 +1716,7 @@ index 764be45..10a2de9 100644
            return {trigger, query, triggerStart: i};
          }
        }
-@@ -335,7 +399,12 @@ export function useTriggerMenu(
+@@ -336,7 +400,12 @@ export function useTriggerMenu(
    // Anchor the popover to the cursor position (not the entire input).
    // We append a zero-size span to document.body positioned at the cursor
    // rect — outside the contentEditable to avoid splitting text nodes.
@@ -1795,7 +1730,7 @@ index 764be45..10a2de9 100644
      const editable = editableRef.current;
      if (!editable) {
        return;
-@@ -487,23 +556,24 @@ export function useTriggerMenu(
+@@ -488,23 +557,24 @@ export function useTriggerMenu(
        return;
      }
  
@@ -1825,7 +1760,7 @@ index 764be45..10a2de9 100644
  
      if (!state.isActive || state.activeTrigger !== trigger) {
        triggerStartRef.current = triggerStart;
-@@ -514,7 +584,7 @@ export function useTriggerMenu(
+@@ -515,7 +585,7 @@ export function useTriggerMenu(
          query,
          highlightedIndex: 0,
        }));
@@ -1834,7 +1769,7 @@ index 764be45..10a2de9 100644
        searchItems(trigger, query);
        popover.show();
      } else if (state.query !== query) {
-@@ -716,6 +786,7 @@ export function useTriggerMenu(
+@@ -720,6 +790,7 @@ export function useTriggerMenu(
          alignment: 'start',
          offset: spacingVars['--spacing-1'],
          xstyle: styles.popoverSurface,
@@ -1843,10 +1778,10 @@ index 764be45..10a2de9 100644
      );
    }, [popover, listboxId, state, selectItem, getItemId, highlightOnHover, t]);
 diff --git a/node_modules/@astryxdesign/core/src/CodeBlock/CodeBlock.tsx b/node_modules/@astryxdesign/core/src/CodeBlock/CodeBlock.tsx
-index 6bb384b..683642d 100644
+index dc0a2b6e9..ccbb63dd7 100644
 --- a/node_modules/@astryxdesign/core/src/CodeBlock/CodeBlock.tsx
 +++ b/node_modules/@astryxdesign/core/src/CodeBlock/CodeBlock.tsx
-@@ -386,14 +386,9 @@ function renderLines(
+@@ -387,14 +387,9 @@ function renderLines(
    for (let start = 0; start < lines.length; start += chunkSize) {
      const end = Math.min(start + chunkSize, lines.length);
      const chunkLines = lines.slice(start, end);
@@ -1863,10 +1798,10 @@ index 6bb384b..683642d 100644
            lines={chunkLines}
            startIndex={start}
 diff --git a/node_modules/@astryxdesign/core/src/DropdownMenu/DropdownMenuItem.tsx b/node_modules/@astryxdesign/core/src/DropdownMenu/DropdownMenuItem.tsx
-index 3fad1b4..e7d1e89 100644
+index 269706dff..6aed3feb0 100644
 --- a/node_modules/@astryxdesign/core/src/DropdownMenu/DropdownMenuItem.tsx
 +++ b/node_modules/@astryxdesign/core/src/DropdownMenu/DropdownMenuItem.tsx
-@@ -113,6 +113,12 @@ export interface DropdownMenuItemProps extends Pick<
+@@ -148,6 +148,12 @@ export interface DropdownMenuItemProps extends Pick<
     * @default true
     */
    hasCloseOnSelect?: boolean;
@@ -1879,7 +1814,7 @@ index 3fad1b4..e7d1e89 100644
    /**
     * Visual variant. `'destructive'` renders the label, description, and icon in
     * the error color for dangerous actions (e.g. Delete). @default 'default'
-@@ -136,6 +142,7 @@ export interface DropdownMenuItemProps extends Pick<
+@@ -178,6 +184,7 @@ export interface DropdownMenuItemProps extends Pick<
   */
  export function DropdownMenuItem({
    icon,
@@ -1887,16 +1822,16 @@ index 3fad1b4..e7d1e89 100644
    label,
    description,
    onClick,
-@@ -170,6 +177,7 @@ export function DropdownMenuItem({
-   return (
-     <Item
+@@ -261,6 +268,7 @@ export function DropdownMenuItem({
+       // address keeps the default root.
+       as={href != null ? LinkComponent : undefined}
        role="menuitem"
 +      aria-busy={ariaBusy}
        tabIndex={isDisabled ? undefined : -1}
        onPointerMove={handlePointerMove}
-       startContent={
+       {...pressable}
 diff --git a/node_modules/@astryxdesign/core/src/Layer/useTouchTrigger.ts b/node_modules/@astryxdesign/core/src/Layer/useTouchTrigger.ts
-index cb027d3..8f0e5e6 100644
+index cb027d3ff..8f0e5e697 100644
 --- a/node_modules/@astryxdesign/core/src/Layer/useTouchTrigger.ts
 +++ b/node_modules/@astryxdesign/core/src/Layer/useTouchTrigger.ts
 @@ -26,7 +26,7 @@
@@ -1931,10 +1866,10 @@ index cb027d3..8f0e5e6 100644
 +  );
  }
 diff --git a/node_modules/@astryxdesign/core/src/List/List.tsx b/node_modules/@astryxdesign/core/src/List/List.tsx
-index 5b63cd6..76627fe 100644
+index 12b0422da..47509319e 100644
 --- a/node_modules/@astryxdesign/core/src/List/List.tsx
 +++ b/node_modules/@astryxdesign/core/src/List/List.tsx
-@@ -151,6 +151,7 @@ export function List({
+@@ -171,6 +171,7 @@ export function List({
    className,
    style,
    'data-testid': testId,
@@ -1942,7 +1877,7 @@ index 5b63cd6..76627fe 100644
    ref,
    ...props
  }: ListProps) {
-@@ -170,6 +171,7 @@ export function List({
+@@ -190,6 +191,7 @@ export function List({
        // is part of its contract and wins on conflict.
        {...props}
        data-testid={testId}
@@ -1951,19 +1886,19 @@ index 5b63cd6..76627fe 100644
        // unconditionally would erase a label a consumer pointed at their own
        // heading.
 diff --git a/node_modules/@astryxdesign/core/src/Markdown/Markdown.tsx b/node_modules/@astryxdesign/core/src/Markdown/Markdown.tsx
-index 45ec33b..be7b53f 100644
+index 6f66b4138..46d996a12 100644
 --- a/node_modules/@astryxdesign/core/src/Markdown/Markdown.tsx
 +++ b/node_modules/@astryxdesign/core/src/Markdown/Markdown.tsx
 @@ -9,7 +9,7 @@
   * @position Core implementation; renders markdown as Astryx components
   */
  
--import {Component, Suspense, useMemo, useRef} from 'react';
-+import {Component, Suspense, useMemo, useRef, useState} from 'react';
+-import {Suspense, useMemo, useRef} from 'react';
++import {Suspense, useMemo, useRef, useState} from 'react';
  import type React from 'react';
  import {Fragment} from 'react';
  import * as stylex from '@stylexjs/stylex';
-@@ -178,6 +178,10 @@ export interface MarkdownProps<
+@@ -201,6 +201,10 @@ export interface MarkdownProps<
     */
    headingLevelStart?: 1 | 2 | 3 | 4 | 5 | 6;
    isStreaming?: boolean;
@@ -1974,7 +1909,7 @@ index 45ec33b..be7b53f 100644
    onLinkClick?: (
      href: string,
      event: React.MouseEvent<HTMLAnchorElement>,
-@@ -1860,6 +1864,8 @@ export function Markdown<
+@@ -1968,6 +1972,8 @@ export function Markdown<
    density = 'default',
    headingLevelStart = 1,
    isStreaming = false,
@@ -1983,7 +1918,7 @@ index 45ec33b..be7b53f 100644
    onLinkClick,
    sources,
    citationStyle = 'label',
-@@ -1911,7 +1917,10 @@ export function Markdown<
+@@ -2020,7 +2026,10 @@ export function Markdown<
  
    // Smooth bursty streamed chunks into a steady character-by-character reveal.
    // When not streaming, the hook returns children unchanged (no-op).
@@ -1995,7 +1930,7 @@ index 45ec33b..be7b53f 100644
  
    const incrementalStateRef = useRef<IncrementalState<boolean>>(
      createIncrementalState<boolean>(),
-@@ -1934,12 +1943,12 @@ export function Markdown<
+@@ -2043,12 +2052,12 @@ export function Markdown<
        return [];
      }
      if (isStreaming) {
@@ -2010,7 +1945,7 @@ index 45ec33b..be7b53f 100644
        return (
          hasMathRenderer
            ? parseMarkdownAstIncremental(
-@@ -1956,35 +1965,34 @@ export function Markdown<
+@@ -2065,35 +2074,34 @@ export function Markdown<
      }
      return (
        hasMathRenderer
@@ -2053,8 +1988,8 @@ index 45ec33b..be7b53f 100644
 +    [parsedBlocks, preparedPlugins, streamingSource, isStreaming],
    );
  
-   // Assign each top-level heading the slug that parseOutlineFromMarkdown
-@@ -2016,15 +2024,14 @@ export function Markdown<
+   // Resolve one post-transform projection for Markdown and derived Outline.
+@@ -2115,15 +2123,14 @@ export function Markdown<
      }
      const options = hasMathRenderer ? mathParseOptions : legacyParseOptions;
      const input = isStreaming
@@ -2073,7 +2008,7 @@ index 45ec33b..be7b53f 100644
      isStreaming,
      hasMathRenderer,
      mathParseOptions,
-@@ -2033,10 +2040,10 @@ export function Markdown<
+@@ -2132,10 +2139,10 @@ export function Markdown<
  
    const inlineTransformSource = isStreaming
      ? trimStreamingArtifacts(
@@ -2086,7 +2021,7 @@ index 45ec33b..be7b53f 100644
    const inlineNodes = useMemo(() => {
      if (display !== 'inline') {
        return [];
-@@ -2077,20 +2084,41 @@ export function Markdown<
+@@ -2176,20 +2183,41 @@ export function Markdown<
      return Math.min(Math.ceil(duration / tickMs), 12);
    }, [token]);
  
@@ -2142,7 +2077,7 @@ index 45ec33b..be7b53f 100644
  
    const cursor: StreamingCursor = {
      offset: 0,
-@@ -2133,10 +2161,6 @@ export function Markdown<
+@@ -2233,10 +2261,6 @@ export function Markdown<
        </span>
      );
  
@@ -2153,7 +2088,7 @@ index 45ec33b..be7b53f 100644
      return renderedInline;
    }
  
-@@ -2181,12 +2205,6 @@ export function Markdown<
+@@ -2282,12 +2306,6 @@ export function Markdown<
      </div>
    );
  
@@ -2167,10 +2102,10 @@ index 45ec33b..be7b53f 100644
  }
  
 diff --git a/node_modules/@astryxdesign/core/src/Markdown/parser.ts b/node_modules/@astryxdesign/core/src/Markdown/parser.ts
-index 418c30b..a7f533a 100644
+index 941aa92d8..b97e75db7 100644
 --- a/node_modules/@astryxdesign/core/src/Markdown/parser.ts
 +++ b/node_modules/@astryxdesign/core/src/Markdown/parser.ts
-@@ -3013,6 +3013,7 @@ export function trimStreamingArtifacts(
+@@ -4243,6 +4243,7 @@ export function trimStreamingArtifacts(
    const prefix = lastNL === -1 ? '' : displayTrimmed.slice(0, lastNL + 1);
    let tail = lastNL === -1 ? displayTrimmed : displayTrimmed.slice(lastNL + 1);
  
@@ -2178,7 +2113,7 @@ index 418c30b..a7f533a 100644
    if (options?.math) {
      // Hold an unmatched inline opener so raw TeX syntax does not flash while
      // streaming. If another unescaped dollar is already present but fails the
-@@ -3033,6 +3034,7 @@ export function trimStreamingArtifacts(
+@@ -4263,6 +4264,7 @@ export function trimStreamingArtifacts(
        }
        const close = findInlineMathEnd(tail, index);
        if (close !== -1) {
@@ -2186,7 +2121,7 @@ index 418c30b..a7f533a 100644
          index = close;
          continue;
        }
-@@ -3050,10 +3052,23 @@ export function trimStreamingArtifacts(
+@@ -4280,10 +4282,23 @@ export function trimStreamingArtifacts(
        index = laterDollar;
      }
    }
@@ -2211,7 +2146,7 @@ index 418c30b..a7f533a 100644
    if (lastBracket !== -1) {
      const afterBracket = tail.slice(lastBracket);
      // A closed link/image has ](...)  somewhere after the [
-@@ -3115,8 +3130,9 @@ export function trimStreamingArtifacts(
+@@ -4345,8 +4360,9 @@ export function trimStreamingArtifacts(
        while (idx + markerLen < tail.length && tail[idx + markerLen] === '*') {
          markerLen++;
        }
@@ -2223,7 +2158,7 @@ index 418c30b..a7f533a 100644
          searchFrom = idx + markerLen;
          continue;
        }
-@@ -3181,8 +3197,10 @@ export function trimStreamingArtifacts(
+@@ -4418,8 +4434,10 @@ export function trimStreamingArtifacts(
        if (idx === -1) {
          break;
        }
@@ -2237,10 +2172,10 @@ index 418c30b..a7f533a 100644
      }
      if (count % 2 === 1) {
 diff --git a/node_modules/@astryxdesign/core/src/SideNav/SideNavItem.tsx b/node_modules/@astryxdesign/core/src/SideNav/SideNavItem.tsx
-index 6c581d4..d3a9857 100644
+index de841443b..7386d5616 100644
 --- a/node_modules/@astryxdesign/core/src/SideNav/SideNavItem.tsx
 +++ b/node_modules/@astryxdesign/core/src/SideNav/SideNavItem.tsx
-@@ -348,6 +348,12 @@ export interface SideNavItemProps extends BaseProps<HTMLElement> {
+@@ -349,6 +349,12 @@ export interface SideNavItemProps extends BaseProps<HTMLElement> {
     * renders inside the primary link or button.
     */
    endContent?: ReactNode;
@@ -2253,7 +2188,7 @@ index 6c581d4..d3a9857 100644
    /**
     * Row-level secondary controls (icon buttons, menus) rendered as siblings
     * of the primary element at the trailing edge of the row — after the
-@@ -434,6 +440,7 @@ export function SideNavItem({
+@@ -435,6 +441,7 @@ export function SideNavItem({
    href,
    onClick,
    endContent,
@@ -2261,7 +2196,7 @@ index 6c581d4..d3a9857 100644
    actions,
    children,
    collapsible: itemCollapsible,
-@@ -799,6 +806,7 @@ export function SideNavItem({
+@@ -816,6 +823,7 @@ export function SideNavItem({
    const item = (
      <div ref={itemRef} {...stylex.props(styles.root, xstyle)}>
        {itemElement}
@@ -2270,7 +2205,7 @@ index 6c581d4..d3a9857 100644
          <div
            id={`${id}-children`}
 diff --git a/node_modules/@astryxdesign/core/src/Spinner/Spinner.tsx b/node_modules/@astryxdesign/core/src/Spinner/Spinner.tsx
-index 7f7dedd..0a8720a 100644
+index 7f7deddc9..0a8720ae2 100644
 --- a/node_modules/@astryxdesign/core/src/Spinner/Spinner.tsx
 +++ b/node_modules/@astryxdesign/core/src/Spinner/Spinner.tsx
 @@ -168,9 +168,8 @@ function pinRingsToTimelineOrigin(): void {
@@ -2373,7 +2308,7 @@ index 7f7dedd..0a8720a 100644
      transform: 'rotate(-90deg)',
      strokeDasharray: `calc(var(${RESOLVED_DIAMETER}) * ${PI} * var(--spinner-arc-fraction)) calc(var(${RESOLVED_DIAMETER}) * ${PI} * (1 - var(--spinner-arc-fraction)))`,
 diff --git a/node_modules/@astryxdesign/core/src/Toast/ToastViewport.tsx b/node_modules/@astryxdesign/core/src/Toast/ToastViewport.tsx
-index 62dbde6..012d6de 100644
+index 0a5cc1094..5b2bc8883 100644
 --- a/node_modules/@astryxdesign/core/src/Toast/ToastViewport.tsx
 +++ b/node_modules/@astryxdesign/core/src/Toast/ToastViewport.tsx
 @@ -24,6 +24,7 @@ import {
@@ -2384,7 +2319,7 @@ index 62dbde6..012d6de 100644
  import * as stylex from '@stylexjs/stylex';
  import {spacingVars, durationVars, easeVars} from '../theme/tokens.stylex';
  import {mergeProps} from '../utils';
-@@ -314,8 +315,9 @@ export function ToastViewport({
+@@ -333,8 +334,9 @@ export function ToastViewport({
    const toastsRef = useRef(toasts);
    toastsRef.current = toasts;
  
@@ -2395,7 +2330,7 @@ index 62dbde6..012d6de 100644
    // Toast ids whose exit has begun — guards onHide from double-firing (see
    // removeToast). Mirrors exitingIds state, readable synchronously.
    const exitingIdsRef = useRef<Set<string>>(new Set());
-@@ -527,20 +529,64 @@ export function ToastViewport({
+@@ -548,20 +550,64 @@ export function ToastViewport({
      insetStyle.insetInlineEnd = inset.end;
    }
  
@@ -2472,7 +2407,7 @@ index 62dbde6..012d6de 100644
  
    // F6 jumps focus into the toast viewport — the standard "go to
    // notifications" affordance. Focus the first control in the newest toast,
-@@ -591,9 +637,7 @@ export function ToastViewport({
+@@ -612,9 +658,7 @@ export function ToastViewport({
            : styles.bottomEnd;
    const isReversed = position === 'topEnd' || position === 'topStart';
  
@@ -2483,9 +2418,9 @@ index 62dbde6..012d6de 100644
        <div
          ref={viewportRef}
          role={hasToasts ? 'region' : undefined}
-@@ -619,6 +663,12 @@ export function ToastViewport({
-           />
-         ))}
+@@ -647,6 +691,12 @@ export function ToastViewport({
+           ))}
+         </LayerContentBoundary>
        </div>
 +  );
 +  return (
@@ -2497,7 +2432,7 @@ index 62dbde6..012d6de 100644
    );
  }
 diff --git a/node_modules/@astryxdesign/core/src/hooks/useStreamingText.ts b/node_modules/@astryxdesign/core/src/hooks/useStreamingText.ts
-index 55b441e..7aa4174 100644
+index 55b441e1a..7aa4174b6 100644
 --- a/node_modules/@astryxdesign/core/src/hooks/useStreamingText.ts
 +++ b/node_modules/@astryxdesign/core/src/hooks/useStreamingText.ts
 @@ -25,7 +25,7 @@
diff --git a/scripts/generate-third-party-notices.mjs b/scripts/generate-third-party-notices.mjs
index 80682309ff..f75ca6a76c 100644
--- a/scripts/generate-third-party-notices.mjs
+++ b/scripts/generate-third-party-notices.mjs
@@ -142,7 +142,7 @@ const MIT_COPYRIGHT_OVERRIDES = new Map([
   ['@astryxdesign/core@0.5.2', 'Copyright (c) 2026 Meta Platforms, Inc.'],
   ['@astryxdesign/core@0.6.1', 'Copyright (c) 2026 Meta Platforms, Inc.'],
   ['@astryxdesign/core@0.6.2', 'Copyright (c) 2026 Meta Platforms, Inc.'],
-  ['@astryxdesign/core@0.6.3', 'Copyright (c) 2026 Meta Platforms, Inc.'],
+  ['@astryxdesign/core@0.6.6', 'Copyright (c) 2026 Meta Platforms, Inc.'],
   ['@stylexjs/stylex@0.19.0', 'Copyright (c) Meta Platforms, Inc. and affiliates.'],
   ['@wecom/aibot-node-sdk@1.0.7', 'Copyright (c) WeComTeam contributors'],
   [


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org