Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2e955a2
feat(desktop): automatically render and archive chat images
Sun-GLiang Oct 5, 2026
640c6b3
fix(ci): use Astryx image controls and update dependency notices
Sun-GLiang Oct 5, 2026
ac93c34
fix(chat): recover streamed images and bound local capture
Sun-GLiang Oct 5, 2026
56d1e07
fix(runtime): launch filesystem worker as explicit ESM
Sun-GLiang Oct 5, 2026
3f57aea
fix(test): include PublishImage in the root provider tool contract
Sun-GLiang Oct 6, 2026
0eaf235
fix(chat): harden image validation and delivery retries
Sun-GLiang Oct 6, 2026
14393d0
fix(chat): normalize image destinations and preserve preview layout
Sun-GLiang Oct 6, 2026
a8ec6b2
refactor(chat): share image parsing and archive contracts
Sun-GLiang Oct 6, 2026
191458c
fix(chat): resolve encoded local image paths without breaking literal…
Sun-GLiang Oct 6, 2026
3ab63f0
fix(chat): preserve inline image badge dimensions
Sun-GLiang Oct 6, 2026
f705794
fix(chat): stabilize image layout and resolve encoded workspace paths
Sun-GLiang Oct 6, 2026
84dab3f
test(ui): generate image fixture without committed screenshots
Sun-GLiang Oct 6, 2026
7fe2c9b
fix(ui): preserve image destinations through display redaction
Sun-GLiang Oct 7, 2026
732e149
test(ui): cover signed image resolution in the CI suite
Sun-GLiang Oct 7, 2026
c2077d4
fix(images): require remote consent and preserve saved archives
Sun-GLiang Oct 7, 2026
d2a36a9
refactor(images): share validation and remove obsolete preview states
Sun-GLiang Oct 7, 2026
49cdee6
fix(images): honor redaction and clarify remote consent
Sun-GLiang Oct 7, 2026
85fbf75
fix(images): remove test-only loopback grant from downloader
Sun-GLiang Oct 7, 2026
5356d55
fix(ui): enlarge chat images directly on click
Sun-GLiang Oct 7, 2026
824bd08
fix(desktop): automatically load remote images through app networking
Sun-GLiang Oct 7, 2026
4385ccd
fix(images): enforce copy quotas and restore UI checks
Sun-GLiang Oct 7, 2026
7cfbf4c
fix(images): align protocol guard with rebased main
Sun-GLiang Oct 9, 2026
8be5c8b
refactor(images): separate capture attempts and presentation state
Sun-GLiang Oct 10, 2026
8b6fc35
fix(release): tolerate Linux profile cleanup races
Sun-GLiang Oct 10, 2026
fef7233
fix(runtime): align image guidance with automatic loading
Sun-GLiang Oct 10, 2026
711fa6e
refactor(network): scope image connection policy per request
Sun-GLiang Oct 10, 2026
951fdf1
fix(ui): render reasoning images as links
Sun-GLiang Oct 10, 2026
dca546b
fix(ui): keep execution process images as links
Sun-GLiang Oct 10, 2026
9298932
refactor(ui): unify chat image rendering and service contracts
Sun-GLiang Oct 10, 2026
431e493
fix(ui): size markdown image previews to natural dimensions
Sun-GLiang Oct 10, 2026
722cba0
test(images): trim redundant PR image coverage
Sun-GLiang Oct 11, 2026
021ca67
refactor(images): trim image redaction and unrelated changes
Sun-GLiang Oct 13, 2026
485074e
fix(images): align rebased Host compatibility and teardown
Sun-GLiang Oct 13, 2026
86df878
refactor(images): defer optional publication and preview features
Sun-GLiang Oct 13, 2026
f78d1c8
refactor(ui): remove unused image framing field
Sun-GLiang Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12696,6 +12696,59 @@ This software is provided by the copyright holders and contributors “as is”

================================================================================

Package: marked@18.0.11
Declared license: MIT
Selected license: MIT
Repository: git+https://github.com/markedjs/marked.git

--- LICENSE ---
# License information

## Contribution License Agreement

If you contribute code to this project, you are implicitly allowing your code
to be distributed under the MIT license. You are also implicitly verifying that
all code is your original work. `</legalese>`

## Marked

Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/)
Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

## Markdown

Copyright © 2004, John Gruber
http://daringfireball.net/
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name “Markdown” nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.

================================================================================

Package: math-intrinsics@1.1.0
Declared license: MIT
Selected license: MIT
Expand Down
8 changes: 8 additions & 0 deletions apps/desktop/scripts/check-renderer-architecture.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ function canonicalRendererEntryHtml(
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="referrer" content="no-referrer" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; ${policy}; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'"
Expand Down Expand Up @@ -1778,6 +1779,13 @@ describe('renderer architecture checker fixtures', () => {
);
});

it('rejects an HTML transform that changes the no-referrer policy', () => {
assert.throws(
() => assertRendererEntryHtml(canonicalRendererEntryHtml().replace('content="no-referrer"', 'content="unsafe-url"')),
/renderer entry HTML contract forbids transformed executable or navigation surfaces/u,
);
});

it('rejects executable HTML injected around the canonical module entry', () => {
assert.doesNotThrow(() => assertRendererEntryHtml(canonicalRendererEntryHtml()));
const emittedHtml = canonicalRendererEntryHtml().replace(
Expand Down
7 changes: 6 additions & 1 deletion apps/desktop/scripts/vite-renderer-entry-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,13 @@ export function assertRendererEntryHtml(html: string, expectedScriptSource?: str
htmlAttribute(attributes, 'http-equiv')?.toLowerCase() === 'content-security-policy' &&
htmlAttribute(attributes, 'content')?.trim().replace(/\s+/gu, ' ') === CONTENT_SECURITY_POLICY,
);
const referrerMetas = metas.filter(
(attributes) => htmlAttribute(attributes, 'name')?.toLowerCase() === 'referrer' &&
htmlAttribute(attributes, 'content') === 'no-referrer',
);
const validMetas =
metas.length === 3 &&
metas.length === 4 &&
referrerMetas.length === 1 &&
charsetMetas.length === 1 &&
viewportMetas.length === 1 &&
policyMetas.length === 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ import { test } from "node:test";
import { registerRuntimeHostArtifactsIpc } from "../runtime-host-artifacts-ipc-main.js";
import { ManagedArtifactPreview } from '../managed-artifact-preview.js';

test('image resolution validates renderer requests before forwarding them', async () => {
const handlers = new Map<string, Handler>();
const forwarded: unknown[] = [];
registerRuntimeHostArtifactsIpc({
uiLocale: () => 'en',
ipcMain: { handle: (channel, handler) => handlers.set(channel, handler as Handler) },
client: { hostEpoch: 'host', resolveImageDelivery: async (...args: unknown[]) => {
forwarded.push(args); return { status: 'requires_confirmation' };
} } as never,
mainWindowController: {} as never,
showItemInFolder() {},
});
const resolve = handlers.get('attachments:resolveImage')!;
const request = { turnId: 'turn', messageId: 'message', source: 'https://example.invalid/image.png', loadRemote: true };
await resolve({}, 'session', request);
assert.deepEqual(forwarded, [['session', request]]);
for (const invalid of [null, { ...request, sessionId: 'other' }, { ...request, loadRemote: 'yes' }, { ...request, source: 'bad\nurl' }]) {
await assert.rejects(async () => resolve({}, 'session', invalid), /Invalid image delivery request/);
}
assert.equal(forwarded.length, 1);
});

for (const launchFails of [false, true]) {
test(`HTML external open uses the managed endpoint and reports launch failure=${launchFails}`, async () => {
const service = new ManagedArtifactPreview();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ import {
DesktopRuntimeHostClientError,
} from '../runtime-host-client.js';

test('image resolution keeps the routed session even if a request carries another id', async () => {
const { client, requests } = clientWithResponses([{ status: 'requires_confirmation' }]);
await client.resolveImageDelivery('routed-session', {
sessionId: 'injected-session', turnId: 'turn', messageId: 'message',
source: 'https://example.invalid/image.png', loadRemote: true,
} as import('@maka/core/image-delivery').ImageDeliveryRequest);
assert.deepEqual(requests, [{ operation: 'artifact.image.resolve', input: {
sessionId: 'routed-session', turnId: 'turn', messageId: 'message',
source: 'https://example.invalid/image.png', loadRemote: true,
} }]);
});

test('restarts a paginated catalog read instead of mixing revisions', async () => {
const revisionOne = catalogRevision('1');
const revisionTwo = catalogRevision('2');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ test('WorkHub upload references round-trip through idle answers, both queue mode
return { ok: true, disposition: args[2] === 'current_turn' ? 'steering' : 'followup', attachments: [uploaded] };
}
if (channel === 'attachments:readBytes') return { ok: true, base64: 'aGVsbG8=' };
if (channel === 'attachments:resolveImage') {
assert.deepEqual(structuredClone(args[2]), {
turnId: 'image-turn', messageId: 'image-message', source: '/tmp/image.png',
});
return { status: 'ready', artifactId: 'image-1' };
}
throw new Error(`Unexpected channel: ${channel}`);
},
},
Expand All @@ -109,6 +115,10 @@ test('WorkHub upload references round-trip through idle answers, both queue mode
}
assert.deepEqual(structuredClone(sent.map(({ attachments }) => attachments)), [[uploaded], [uploaded], [uploaded]]);
assert.equal((await services.readAttachmentBytes(sessionId, 'brief.txt')).ok, true);
assert.ok(services.resolveImageDelivery);
assert.deepEqual(await services.resolveImageDelivery(sessionId, {
turnId: 'image-turn', messageId: 'image-message', source: '/tmp/image.png',
}), { status: 'ready', artifactId: 'image-1' });
preparationResult = { ok: false, code: 'item_too_large' };
await assert.rejects(
services.prepareAttachments(sessionId, [
Expand Down
5 changes: 5 additions & 0 deletions apps/desktop/src/main/runtime-host-artifacts-ipc-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import type { UiCatalog, UiLocale } from '@maka/core/ui-locale';
import { isImageDeliveryRequest } from '@maka/core/image-delivery';
import { randomUUID } from "node:crypto";
import { open, mkdir, rename, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
Expand Down Expand Up @@ -89,6 +90,10 @@ export function registerRuntimeHostArtifactsIpc(
return result;
},
);
deps.ipcMain.handle('attachments:resolveImage', (_event, sessionId: string, request: unknown) => {
if (!isImageDeliveryRequest(request)) throw new Error('Invalid image delivery request');
return deps.client.resolveImageDelivery(sessionId, request);
});
registerRuntimeHostAttachmentPreviewIpc(deps);
const materializePresentationArtifact = async (
sessionId: string,
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/src/main/runtime-host-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,10 @@ export class DesktopRuntimeHostClient {
return result.project;
}

resolveImageDelivery(sessionId: string, request: import('@maka/core/image-delivery').ImageDeliveryRequest): Promise<import('@maka/core/image-delivery').ImageDeliveryResult> {
return this.request('artifact.image.resolve', { ...request, sessionId });
}

async listArtifacts(sessionId: string): Promise<ArtifactProjection[]> {
for (let attempt = 0; attempt < MAX_OPTIMISTIC_ATTEMPTS; attempt += 1) {
const first = await this.request("artifact.query", {
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/preload/bridge-contract.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,7 @@ export interface MakaBridge {
| { ok: true; base64: string; mimeType: string }
| { ok: false; reason: string }
>;
resolveImageDelivery: import('@maka/core/image-delivery').ResolveImageDelivery;
readBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
};
search: {
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/preload/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3422,6 +3422,7 @@ const makaBridge = {
},
},
attachments: {
resolveImageDelivery: (sessionId, request) => invokeSessionRuntimeHost('attachments:resolveImage', sessionId, request),
pickDirectory: () => invokeWhenReady('directories:pick'),
// The renderer hands over the dropped or pasted File objects, never paths:
// only a File backed by something the user dropped or pasted has a path,
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/chat-message-surface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ interface ChatMessageSurfaceProps extends Omit<
| 'pendingQuotes'
| 'onQuoteAnnotationSubmit'
| 'onReadAttachmentBytes'
| 'onResolveImageDelivery'
> {
/**
* #1985: the live projection and the shell-run records are the only session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import { createServicesContext } from '../../application/contracts/feature-services.js';
import type { ComposerAttachmentService } from '@maka/ui/use-composer-attachments';
import type { ArtifactBinaryReadResult } from '@maka/core/artifacts';
import type { ResolveImageDelivery } from '@maka/core/image-delivery';

/** One attachment port: the Composer stages through it and the transcript reads image bytes through it. */
export interface ComposerStagingServices extends ComposerAttachmentService {
readBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
resolveImageDelivery?: ResolveImageDelivery;
}
const context = createServicesContext<ComposerStagingServices>('ComposerStagingServicesProvider');
export const ComposerStagingServicesProvider = context.Provider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import { useComposerStagingServices } from '../staging-services.js';

/** Transcript attachment reads come from the injected attachment port, never from the caller. */
export function StagedQuoteChatView(props: Omit<ComponentProps<typeof PlanChatView>,
'handleRef' | 'pendingQuotes' | 'onQuoteAnnotationSubmit' | 'onReadAttachmentBytes'>) {
'handleRef' | 'pendingQuotes' | 'onQuoteAnnotationSubmit' | 'onReadAttachmentBytes' | 'onResolveImageDelivery'>) {
const staging = useComposerStaging();
const { readBytes } = useComposerStagingServices();
return <PlanChatView {...props} {...staging.chatViewQuoteProps} onReadAttachmentBytes={readBytes} />;
const { readBytes, resolveImageDelivery } = useComposerStagingServices();
return <PlanChatView {...props} {...staging.chatViewQuoteProps} onReadAttachmentBytes={readBytes} onResolveImageDelivery={resolveImageDelivery} />;
}
2 changes: 2 additions & 0 deletions apps/desktop/src/renderer/features/workbar/ports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import type { ResolveImageDelivery } from '@maka/core/image-delivery';
import type { SessionInspectorService } from '../../application/contracts/session-inspector/service.js';
export type { SessionInspectorService, SessionTracePage, SessionUsageSummary } from '../../application/contracts/session-inspector/service.js';

Expand Down Expand Up @@ -166,6 +167,7 @@ export interface WorkbarArtifactsService {

export interface WorkbarAttachmentsService {
readBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
resolveImageDelivery?: ResolveImageDelivery;
pickFiles(): Promise<
| {
ok: true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ export function QuoteCompanionPanel(props: {
liveTurns={companion.liveTurns}
activeTurn={companion.activeTurn}
activeSession={companion.companionSession}
onReadAttachmentBytes={attachments.readBytes}
onReadAttachmentBytes={attachments.readBytes} onResolveImageDelivery={attachments.resolveImageDelivery}
deriveTurnPresentation={deriveTurnPresentation}
onEditUserMessage={(turnId) => {
const message = companion.messages.find(
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/renderer/features/workhub/ports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import type { ArtifactBinaryReadResult } from '@maka/core/artifacts';
import type { ResolveImageDelivery } from '@maka/core/image-delivery';
import type { ChatModelChoice } from '@maka/core/chat-model-choice';
import type { UiLocale } from '@maka/core/ui-locale';
import type { StoredMessage, SessionSummary } from '@maka/core/session';
Expand Down Expand Up @@ -57,6 +58,7 @@ export interface WorkHubServices extends WorkHubWorkspaceServices {
}): Promise<void>;
readonly attachments: ComposerAttachmentService;
readAttachmentBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
resolveImageDelivery?: ResolveImageDelivery;
prepareAttachments(sessionId: string, items: Array<{ approvalId: string; name: string; mimeType?: string } | { file: File }>): Promise<AttachmentRef[]>;
listActiveInteractions(sessionId: string): Promise<import('@maka/core/events').ActiveInteractionRequestEvent[]>;
subscribeActiveInteractions(handler: (event: { sessionId: string; interactions: import('@maka/core/events').ActiveInteractionRequestEvent[] }) => void): () => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ export function WorkHubRoot() {
<div ref={history} className="workHubHistory" aria-hidden={!showConversation} inert={!showConversation}>
<WorkHubConversation
workLinks={links}
onReadAttachmentBytes={services.readAttachmentBytes}
onReadAttachmentBytes={services.readAttachmentBytes} onResolveImageDelivery={services.resolveImageDelivery}
onOpenWork={(id) => call(services.presentation.openSession(id))}
scrollBehavior="auto"
onNew={() => composer.current?.focus()}
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="referrer" content="no-referrer" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export function createDesktopWorkHubServices(
bridge.connections.setDefaultModel({ slug: llmConnectionSlug, model }),
attachments: bridge.attachments,
readAttachmentBytes: bridge.attachments.readBytes,
resolveImageDelivery: bridge.attachments.resolveImageDelivery,
prepareAttachments: async (sessionId, items) => {
const result = await bridge.workHub.prepareAttachments(sessionId, items);
if (!result.ok) throw new AttachmentIngestBlockedError(result.code);
Expand Down
4 changes: 3 additions & 1 deletion docs/astryx-surface-file-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Generated against `@astryxdesign/core@0.6.3` (195 component exports).

Wiki bar: Design Conventions · API Use-the-System · Theming · Container Padding.

**Totals:** 334 files — blocker 0, reimplementation 0, polish 4, aligned 330.
**Totals:** 336 files — blocker 0, reimplementation 0, polish 4, aligned 332.

## Exclusions (explicit)

Expand Down Expand Up @@ -308,11 +308,13 @@ Wiki bar: Design Conventions · API Use-the-System · Theming · Container Paddi
| `packages/ui/src/executor-model-picker.tsx` | ui-composition | Button, Popover | aligned — uses Astryx (Button, Popover) | aligned |
| `packages/ui/src/form-interaction-prompt.tsx` | ui-composition | Button, CheckboxInput, RadioList, RadioListItem, Selector, Text, TextInput | aligned — uses Astryx (Button, CheckboxInput, RadioList, RadioListItem, Selector, Text, TextInput) | aligned |
| `packages/ui/src/icons.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/image-delivery.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/inline-reference.tsx` | ui-composition | ChatTokenizedText | aligned — uses Astryx (ChatTokenizedText) | aligned |
| `packages/ui/src/inline-rename-input.tsx` | ui-composition | TextInput | aligned — uses Astryx (TextInput) | aligned |
| `packages/ui/src/locale-context.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/maka-wordmark.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/markdown-body.tsx` | ui-composition | CodeBlock, Link, Markdown | aligned — uses Astryx (CodeBlock, Link, Markdown) | aligned |
| `packages/ui/src/markdown-image.tsx` | ui-composition | Button, IconButton, Link, Spinner, Tooltip | aligned — uses Astryx (Button, IconButton, Link, Spinner, Tooltip) | aligned |
| `packages/ui/src/markdown-math.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/markdown.tsx` | ui-composition | none | aligned — no raw controls; no Astryx JSX usage | aligned |
| `packages/ui/src/mermaid-diagram.tsx` | ui-composition | Button, CodeBlock, Collapsible, Dialog, IconButton, Toolbar | aligned — uses Astryx (Button, CodeBlock, Collapsible, Dialog, IconButton, Toolbar) | aligned |
Expand Down
2 changes: 2 additions & 0 deletions docs/astryx-surface-file-inventory.paths
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,13 @@ packages/ui/src/directory-reference-chip.tsx
packages/ui/src/executor-model-picker.tsx
packages/ui/src/form-interaction-prompt.tsx
packages/ui/src/icons.tsx
packages/ui/src/image-delivery.tsx
packages/ui/src/inline-reference.tsx
packages/ui/src/inline-rename-input.tsx
packages/ui/src/locale-context.tsx
packages/ui/src/maka-wordmark.tsx
packages/ui/src/markdown-body.tsx
packages/ui/src/markdown-image.tsx
packages/ui/src/markdown-math.tsx
packages/ui/src/markdown.tsx
packages/ui/src/mermaid-diagram.tsx
Expand Down
Loading
Loading