Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b33cc64
feat(desktop): automatically render and archive chat images
Sun-GLiang Oct 5, 2026
a48ea29
fix(ci): use Astryx image controls and update dependency notices
Sun-GLiang Oct 5, 2026
30fa271
fix(chat): recover streamed images and bound local capture
Sun-GLiang Oct 5, 2026
8dee867
fix(runtime): launch filesystem worker as explicit ESM
Sun-GLiang Oct 5, 2026
17a1aa8
fix(test): include PublishImage in the root provider tool contract
Sun-GLiang Oct 6, 2026
51de6bb
fix(chat): harden image validation and delivery retries
Sun-GLiang Oct 6, 2026
f0d5019
fix(chat): normalize image destinations and preserve preview layout
Sun-GLiang Oct 6, 2026
fc9b9f7
refactor(chat): share image parsing and archive contracts
Sun-GLiang Oct 6, 2026
7400475
fix(chat): resolve encoded local image paths without breaking literal…
Sun-GLiang Oct 6, 2026
92354a6
fix(chat): preserve inline image badge dimensions
Sun-GLiang Oct 6, 2026
b57a1e9
fix(chat): stabilize image layout and resolve encoded workspace paths
Sun-GLiang Oct 6, 2026
b0c4a19
test(ui): generate image fixture without committed screenshots
Sun-GLiang Oct 6, 2026
82f55ec
fix(ci): refresh image Tooltip surface inventory
Sun-GLiang Oct 6, 2026
35fbd3b
fix(ui): preserve image destinations through display redaction
Sun-GLiang Oct 7, 2026
08545a3
test(ui): cover signed image resolution in the CI suite
Sun-GLiang Oct 7, 2026
62996df
fix(images): require remote consent and preserve saved archives
Sun-GLiang Oct 7, 2026
1523d10
refactor(images): share validation and remove obsolete preview states
Sun-GLiang Oct 7, 2026
41180a9
fix(images): honor redaction and clarify remote consent
Sun-GLiang Oct 7, 2026
77f1a00
fix(ci): exercise production WorkHub browser click path
Sun-GLiang Oct 7, 2026
08eff17
fix(review): remove unrelated WorkHub smoke changes
Sun-GLiang Oct 7, 2026
4329f9c
fix(images): remove test-only loopback grant from downloader
Sun-GLiang Oct 7, 2026
37ac249
fix(ui): enlarge chat images directly on click
Sun-GLiang Oct 7, 2026
efe025c
fix(desktop): automatically load remote images through app networking
Sun-GLiang Oct 7, 2026
aa8e0cb
fix(images): enforce copy quotas and restore UI checks
Sun-GLiang Oct 7, 2026
a449346
fix(images): align protocol guard with rebased main
Sun-GLiang Oct 9, 2026
c6b0ec3
fix(ci): synchronize Windows image test inventory
Sun-GLiang Oct 9, 2026
e4ac12e
chore(images): integrate current main before boundary refactor
Sun-GLiang Oct 10, 2026
ef91354
refactor(images): separate capture attempts and presentation state
Sun-GLiang Oct 10, 2026
f56ceb1
fix(desktop): leave room for Linux usage timestamps
Sun-GLiang Oct 10, 2026
9ed0e5d
fix(release): tolerate Linux profile cleanup races
Sun-GLiang Oct 10, 2026
a73ab9b
fix(runtime): align image guidance with automatic loading
Sun-GLiang Oct 10, 2026
4037399
refactor(network): scope image connection policy per request
Sun-GLiang Oct 10, 2026
7833fe8
fix(ui): render reasoning images as links
Sun-GLiang Oct 10, 2026
47f24b9
fix(ui): keep execution process images as links
Sun-GLiang Oct 10, 2026
03f7ed6
refactor(ui): unify chat image rendering and service contracts
Sun-GLiang Oct 10, 2026
c19d60e
fix(ui): size markdown image previews to natural dimensions
Sun-GLiang Oct 10, 2026
1080961
Merge main into feature/chat-image-delivery and resolve conflicts
Sun-GLiang Oct 11, 2026
6b7d012
docs: refresh Astryx inventory totals after main merge
Sun-GLiang Oct 11, 2026
87b0bc8
test(images): trim redundant PR image coverage
Sun-GLiang Oct 11, 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
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,13 @@ jobs:
# The smoke only launches headless; the full Chrome build was downloaded
# and never opened. The headed consumer (perf/storybook.mjs) self-installs.
- name: Install Playwright Chromium
if: steps.plan.outputs.storybook == 'true'
if: steps.plan.outputs.storybook == 'true' || contains(steps.plan.outputs.standard_workspaces, 'packages/ui')
run: npx playwright install --with-deps --only-shell chromium

- name: Markdown image security and layout
if: steps.plan.outputs.storybook == 'true' || contains(steps.plan.outputs.standard_workspaces, 'packages/ui')
run: node --test packages/ui/scripts/markdown-images.browser.test.mjs

- name: Build Storybook
if: steps.plan.outputs.storybook == 'true'
run: npm --workspace @maka/desktop run build-storybook
Expand Down
1,129 changes: 1,100 additions & 29 deletions apps/desktop/resources/licenses/npm/THIRD_PARTY_NOTICES.txt

Large diffs are not rendered by default.

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 @@ -108,7 +114,11 @@ test('WorkHub upload references round-trip through idle answers, both queue mode
assert.equal(await services.enqueueMessage(sessionId, `message-${placement}`, 'read this', attachments, placement), 'admitted');
}
assert.deepEqual(structuredClone(sent.map(({ attachments }) => attachments)), [[uploaded], [uploaded], [uploaded]]);
assert.equal((await services.readAttachmentBytes(sessionId, 'brief.txt')).ok, true);
assert.equal((await services.readBytes(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 @@ -87,6 +88,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 @@ -861,6 +861,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
3 changes: 2 additions & 1 deletion apps/desktop/src/preload/bridge-contract.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,8 @@ export interface MakaBridge {
| { ok: true; base64: string; mimeType: string }
| { ok: false; reason: string }
>;
readBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
resolveImageDelivery: import('@maka/core/image-delivery').ResolveImageDelivery;
readBytes: import('@maka/core/image-delivery').ReadAttachmentBytes;
};
search: {
recall(
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 @@ -3382,6 +3382,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 @@ -19,12 +19,10 @@

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 { ChatImageServices } 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>;
}
export type ComposerStagingServices = ComposerAttachmentService & ChatImageServices;
const context = createServicesContext<ComposerStagingServices>('ComposerStagingServicesProvider');
export const ComposerStagingServicesProvider = context.Provider;
export const useComposerStagingServices = context.useServices;
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} />;
}
4 changes: 2 additions & 2 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 { ChatImageServices } 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 @@ -164,8 +165,7 @@ export interface WorkbarArtifactsService {
saveAs(sessionId: string, artifactId: string): Promise<ArtifactSaveResult>;
}

export interface WorkbarAttachmentsService {
readBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
export interface WorkbarAttachmentsService extends ChatImageServices {
pickFiles(): Promise<
| {
ok: true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,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
5 changes: 2 additions & 3 deletions apps/desktop/src/renderer/features/workhub/ports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import type { ArtifactBinaryReadResult } from '@maka/core/artifacts';
import type { ChatImageServices } 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 All @@ -39,7 +39,7 @@ export interface WorkHubTranscript {
loadEarlier(): Promise<void>;
close(): Promise<void>;
}
export interface WorkHubServices extends WorkHubWorkspaceServices {
export interface WorkHubServices extends WorkHubWorkspaceServices, ChatImageServices {
readonly inspector: import('../../application/contracts/session-inspector/service.js').SessionInspectorService;
readonly surface: 'main' | 'workhub';
readonly initialLocale: UiLocale;
Expand All @@ -56,7 +56,6 @@ export interface WorkHubServices extends WorkHubWorkspaceServices {
model: string;
}): Promise<void>;
readonly attachments: ComposerAttachmentService;
readAttachmentBytes(sessionId: string, artifactId: string): Promise<ArtifactBinaryReadResult>;
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 @@ -397,7 +397,7 @@ export function WorkHubRoot() {
<div ref={history} className="workHubHistory" aria-hidden={!showConversation} inert={!showConversation}>
<WorkHubConversation
workLinks={links}
onReadAttachmentBytes={services.readAttachmentBytes}
onReadAttachmentBytes={services.readBytes} 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 @@ -92,7 +92,8 @@ export function createDesktopWorkHubServices(
setDefaultModel: ({ llmConnectionSlug, model }) =>
bridge.connections.setDefaultModel({ slug: llmConnectionSlug, model }),
attachments: bridge.attachments,
readAttachmentBytes: bridge.attachments.readBytes,
readBytes: 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
2 changes: 1 addition & 1 deletion apps/desktop/stories/workhub.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function makeServices(failFirst: boolean, withHistory: boolean | 'usage', colore
listSessions: async () => coloredHistory ? [target, secondTarget] : [target], subscribeSessions: (handler) => { updateSessions = handler; return () => { updateSessions = undefined; }; }, modelChoices: async () => choices,
setDefaultModel: async () => {},
attachments: { pickFiles: async () => ({ ok: true, files: [{ approvalId: 'file-1', name: 'requirements.txt', size: 12, mimeType: 'text/plain' }] }), previewApproval: async () => ({ ok: false, reason: 'not-image' }) },
readAttachmentBytes: async () => { throw new Error('Not an image'); },
readBytes: async () => { throw new Error('Not an image'); },
prepareAttachments: async (id, items) => { writes.upload(id, items); return [{ name: 'requirements.txt', kind: 'other', mimeType: 'text/plain', bytes: 12, ref: { kind: 'session_file', sessionId: 'maka_workhub_coordination', relativePath: 'artifact-1' } }]; },
listActiveInteractions: async () => pendingForm ? [pendingForm] : questionPending ? [questionRequest] : [],
subscribeActiveInteractions: (handler) => { interactionUpdate = handler; return () => { interactionUpdate = undefined; }; },
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:** 333 files — blocker 0, reimplementation 0, polish 4, aligned 329.
**Totals:** 335 files — blocker 0, reimplementation 0, polish 4, aligned 331.

## Exclusions (explicit)

Expand Down Expand Up @@ -307,11 +307,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 @@ -277,11 +277,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