@ai-matrx/chat 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/agents/components/chat/ChatIncognitoHeaderButton.js +1 -1
  3. package/dist/agents/components/chat/SandboxPanel.js +1 -1
  4. package/dist/agents/components/context-items/context-item-block-types.d.ts +1 -1
  5. package/dist/agents/components/context-items/context-item-block-types.js +2 -1
  6. package/dist/agents/components/context-items/registry.js +9 -0
  7. package/dist/agents/components/conversation-history/ConversationHistorySidebar.js +1 -1
  8. package/dist/agents/components/inputs/resources/SmartAgentResourceChips.js +4 -1
  9. package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.d.ts +20 -0
  10. package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.js +107 -0
  11. package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +135 -204
  12. package/dist/agents/components/inputs/smart-input/composer/already-answering.d.ts +1 -1
  13. package/dist/agents/components/inputs/smart-input/composer/already-answering.js +1 -1
  14. package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.d.ts +1 -1
  15. package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.js +1 -1
  16. package/dist/agents/components/messages-display/user/UserActionBar.js +1 -1
  17. package/dist/agents/components/run/AgentRunHeader.js +1 -1
  18. package/dist/agents/components/run/run-sidebar/SidebarHeader.js +1 -1
  19. package/dist/agents/components/run-controls/RunModelPicker.d.ts +5 -1
  20. package/dist/agents/components/run-controls/RunModelPicker.js +23 -1
  21. package/dist/agents/components/shared/AgentConversationColumn.js +3 -1
  22. package/dist/agents/components/shared/AgentHeader.js +1 -1
  23. package/dist/agents/components/shared/AgentHeaderMobile.js +1 -1
  24. package/dist/agents/components/shared/AgentNewRunButton.js +1 -1
  25. package/dist/agents/components/shared/assistant-message-layout.d.ts +21 -0
  26. package/dist/agents/components/shared/assistant-message-layout.js +7 -1
  27. package/dist/agents/components/working-document/WorkingDocumentVersionHistory.js +1 -1
  28. package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.js +14 -0
  29. package/dist/agents/types/instance.types.d.ts +18 -3
  30. package/dist/agents/utils/renderedArtifactContext.d.ts +41 -0
  31. package/dist/agents/utils/renderedArtifactContext.js +41 -0
  32. package/dist/conversation/hooks/useDomCapturePrint.js +4 -0
  33. package/dist/conversation/utils/frame-print.d.ts +11 -0
  34. package/dist/conversation/utils/frame-print.js +46 -0
  35. package/dist/conversation/utils/markdown-print.d.ts +9 -1
  36. package/dist/conversation/utils/markdown-print.js +55 -26
  37. package/dist/cx-chat/components/ChatMobileHeaderBar.js +1 -1
  38. package/dist/cx-chat/components/ChatPanelBackButton.js +1 -1
  39. package/dist/cx-chat/components/ChatSidebarClient.js +1 -1
  40. package/dist/cx-chat/components/user-input/ConversationInput.js +2 -2
  41. package/dist/cx-chat/components/user-input/InputActionButtons.js +2 -2
  42. package/dist/host/frame-print.d.ts +17 -0
  43. package/dist/host/frame-print.js +13 -0
  44. package/dist/surfaces/components/chrome/SurfaceAgentsHeaderButton.js +1 -1
  45. package/dist/voice-agent/components/VoiceAgentSurface.js +2 -2
  46. package/package.json +6 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,72 @@
1
1
  # @ai-matrx/chat
2
2
 
3
+ ## 0.5.6 — 0.5.5 threw at load
4
+
5
+ - `CONTEXT_ITEM_BLOCK_TYPES` lists `rendered_artifact`: 0.5.5 registered the def without it, so the
6
+ context-items registry's load-time drift check threw ("context-items registry and
7
+ CONTEXT_ITEM_BLOCK_TYPES disagree: rendered_artifact") and every importer of the chat runtime
8
+ failed to load.
9
+
10
+ Consumer action: adopt 0.5.6; never ship 0.5.5.
11
+
12
+ ## 0.5.5 — attach a rendered page: screenshot · code · text
13
+
14
+ - `ResourceOptions.representation` is now a per-resource-type union (`RepresentationByResourceType`:
15
+ `processed_document` → clean/raw/pdf, `rendered_artifact` → code/screenshot/text).
16
+ - New block type `rendered_artifact` (an HTML page / canvas item as its code or visible text) riding
17
+ `request.context` as a resource reference with the chosen representation — never `user_input`.
18
+ Helpers: `agents/utils/renderedArtifactContext` (`availableRenderedArtifactRepresentations`,
19
+ `renderedArtifactContextEntry`).
20
+ - `useAttachRenderedArtifact(conversationId)`: one click attaches code/text, or a screenshot whose chip
21
+ shows at once (pending) and fills when the host's capture lands (stored cloud file, or a local PNG
22
+ uploaded through the paste-image path) — an explicit image part, captured at attach time.
23
+ - Consumer action: a host with a capture engine passes it as `capture` for `screenshot`.
24
+
25
+ ## Unreleased — message prints use each block's own print adapter; live pages never print blank
26
+
27
+ - `conversation/utils/markdown-print`: every embedded block (fence or `<artifact>`) prints through
28
+ `@ai-matrx/print`'s block-printer registry (`getBlockPrinter(type).toPrintHtml`) — a quiz as its
29
+ questions, a deck as its study sheet, an HTML page as its picture — and a message with a web page
30
+ says "Web pages print as a picture inside a message…". Diagrams still draw once.
31
+ - Full Print (`useDomCapturePrint`) pre-passes every `<iframe>` into its picture before the raster
32
+ (`conversation/utils/frame-print` → `framesToPictures`), restored after; with no capture engine
33
+ the frame prints `FRAME_PRINT_STAND_IN`, never blank.
34
+ - New host port `@ai-matrx/chat/host/frame-print`: `setFramePrintCapture(fn)` /
35
+ `getFramePrintCapture()`, `FramePrintCapture`, `FRAME_PRINT_STAND_IN`.
36
+ - Needs `@ai-matrx/print` ≥ 0.12.0. Consumer action: a host with a page capture engine calls
37
+ `setFramePrintCapture`; register block printers with `registerBlockPrinter` (print 0.12).
38
+
39
+ ## Unreleased — the Chat-mode agent menu, rebuilt to the owner's layout
40
+
41
+ - The agent pill's Chat menu is `Agent: <name> ›` · `Model: <model> ›` · "Choose your chat agent"
42
+ (☆ chat agents, ☆ Custom Agent) · `Choose any agent ›`. Every deeper menu opens the same way (one
43
+ right chevron; a pushed page in the phone sheet, which this menu now uses on phones). No row carries
44
+ an explanation line.
45
+ - Custom Agent is the Matrx Chat agent (`chat.cx_default`), no longer the default-chat job; the menu no
46
+ longer writes a personal default model.
47
+ - `QuickRunModelSelect` takes `presentation="inline"` + `onChosen`.
48
+ - `conversation/utils/markdown-print` follows print 0.12 (`renderBlock` per block; diagrams drawn once).
49
+ - Needs `@ai-matrx/agents` with `ModelListDropdown presentation="inline"`. Consumer action: none.
50
+
51
+ ## Unreleased — wide figures: a rendered page may widen past the reading column
52
+
53
+ - `assistant-message-layout` exports `WIDE_FIGURE_CLASS`, `WIDE_FIGURE_SCOPE_ATTRIBUTE` and
54
+ `WIDE_FIGURE_MAX_WIDTH_PX` (1100). The transcript scroll area (a size container) carries
55
+ `data-wide-figures` only for a centered, reading-width, edge-scrolled column; inside it an element
56
+ with `WIDE_FIGURE_CLASS` widens to the transcript (1rem gutters, ≤1100px), centered on the column.
57
+ Everywhere else — `width: "fill"`, start-aligned, notes, rich-document surfaces — it does nothing.
58
+
59
+ Consumer action: put `WIDE_FIGURE_CLASS` on a figure that should use the room (matrx-frontend's
60
+ inline HTML page card does).
61
+
62
+ ## Unreleased — tap-target comes from design-system
63
+
64
+ - Imports `@ai-matrx/design-system/tap-target` (and `/tap-target/buttons`, `tap-target.css`) instead of the
65
+ retired `@ai-matrx/tap-target` (Arman, 2026-10-08: tap-target merges into design-system); the
66
+ `@ai-matrx/tap-target` dependency is dropped.
67
+
68
+ Consumer action: none.
69
+
3
70
  ## 0.5.4 — tree-shakeable, and the first screen sheds its heavy parts
4
71
 
5
72
  - `"sideEffects"` is no longer `true`: it lists the CSS and the ten files that run on import
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { GhostTapButton } from "@ai-matrx/tap-target/buttons";
3
+ import { GhostTapButton } from "@ai-matrx/design-system/tap-target/buttons";
4
4
  import { PageHeaderRightPortal } from "../../../host/chrome.js";
5
5
  import { useChatIncognito } from "./ChatIncognitoProvider.js";
6
6
  function ChatIncognitoHeaderButton() {
@@ -7,7 +7,7 @@ import {
7
7
  ExternalLinkTapButton,
8
8
  CheckTapButton,
9
9
  XTapButton
10
- } from "@ai-matrx/tap-target/buttons";
10
+ } from "@ai-matrx/design-system/tap-target/buttons";
11
11
  import { sandboxDisplayName } from "../../../compute/targets.js";
12
12
  import {
13
13
  Plus,
@@ -4,7 +4,7 @@
4
4
  * bodies. `registry.tsx` asserts at load that its defs cover exactly this
5
5
  * list, so the two can never drift; `isAttachmentMessagePart` reads it.
6
6
  */
7
- export declare const CONTEXT_ITEM_BLOCK_TYPES: readonly ["image", "image_output", "audio", "audio_output", "video", "video_output", "document", "file_output", "youtube_video", "input_notes", "input_task", "working_document", "input_document", "processed_document", "ctx_org", "ctx_scope", "ctx_project", "ctx_task", "input_webpage", "input_data", "input_table", "input_list", "input_project", "input_agent", "input_agent_app", "input_transcript", "input_transcript_session", "input_workbook", "input_context", "text", "editor_error", "editor_code_snippet", "input_remarks"];
7
+ export declare const CONTEXT_ITEM_BLOCK_TYPES: readonly ["image", "image_output", "audio", "audio_output", "video", "video_output", "document", "file_output", "youtube_video", "input_notes", "input_task", "working_document", "input_document", "processed_document", "ctx_org", "ctx_scope", "ctx_project", "ctx_task", "input_webpage", "input_data", "input_table", "input_list", "input_project", "input_agent", "input_agent_app", "input_transcript", "input_transcript_session", "input_workbook", "input_context", "text", "editor_error", "editor_code_snippet", "input_remarks", "rendered_artifact"];
8
8
  export type ContextItemBlockType = (typeof CONTEXT_ITEM_BLOCK_TYPES)[number];
9
9
  /**
10
10
  * True when a block type has a REGISTERED context-item def. This is the one
@@ -31,7 +31,8 @@ const CONTEXT_ITEM_BLOCK_TYPES = [
31
31
  "text",
32
32
  "editor_error",
33
33
  "editor_code_snippet",
34
- "input_remarks"
34
+ "input_remarks",
35
+ "rendered_artifact"
35
36
  ];
36
37
  const MEMBERS = new Set(CONTEXT_ITEM_BLOCK_TYPES);
37
38
  function hasContextItemDef(blockType) {
@@ -299,6 +299,15 @@ const CONTEXT_ITEM_TYPE_DEFS = [
299
299
  editable: false,
300
300
  Body: GenericBody
301
301
  },
302
+ {
303
+ // An HTML page / canvas item attached as its code or visible text.
304
+ blockTypes: ["rendered_artifact"],
305
+ typeLabel: "Page",
306
+ icon: Code2,
307
+ themeKey: "editor_code_snippet",
308
+ editable: false,
309
+ Body: GenericBody
310
+ },
302
311
  {
303
312
  blockTypes: ["editor_code_snippet"],
304
313
  typeLabel: "Code",
@@ -73,7 +73,7 @@ import { toast } from "../../../host/notify.js";
73
73
  import {
74
74
  LoadingTapButton,
75
75
  RefreshCwTapButton
76
- } from "@ai-matrx/tap-target/buttons";
76
+ } from "@ai-matrx/design-system/tap-target/buttons";
77
77
  import { useConversationServerSearch } from "./useConversationServerSearch.js";
78
78
  import { ConversationSearchStatus } from "./ConversationSearchStatus.js";
79
79
  import { countConversationSearchCorpus } from "../../redux/conversation-history/conversation-search.js";
@@ -25,6 +25,9 @@ import { dismissRemarkChip, remarkSourceOf } from "../../../redux/execution-syst
25
25
  import {
26
26
  AttachedDocumentChip
27
27
  } from "./AttachedDocumentChip.js";
28
+ function isDocumentRepresentation(value) {
29
+ return value === "clean" || value === "raw" || value === "pdf";
30
+ }
28
31
  function getBlockTypeDisplay(blockType) {
29
32
  const def = resolveContextItemDef(blockType);
30
33
  return { icon: def.icon, label: def.typeLabel };
@@ -180,7 +183,7 @@ function PendingDocumentResourceChip({
180
183
  title: getResourceLabel(resource),
181
184
  pending: resource.status === "pending" || resource.status === "resolving",
182
185
  fileId: pendingDocumentFileId(resource),
183
- representation: resource.options.representation,
186
+ representation: isDocumentRepresentation(resource.options.representation) ? resource.options.representation : void 0,
184
187
  resourcePolicy: resource.options.resourcePolicy,
185
188
  onOpen,
186
189
  pressed,
@@ -0,0 +1,20 @@
1
+ import type { RenderedArtifactRepresentation } from "../../../types/instance.types.js";
2
+ import { type RenderedArtifactSource } from "../../../utils/renderedArtifactContext.js";
3
+ /** What a host capture port returns: a stored cloud image, or a local PNG to upload. */
4
+ export type RenderedCaptureResult = {
5
+ kind: "stored";
6
+ fileId: string;
7
+ width: number;
8
+ height: number;
9
+ url?: string | null;
10
+ } | {
11
+ kind: "file";
12
+ file: File;
13
+ };
14
+ export interface AttachRenderedArtifactArgs {
15
+ source: RenderedArtifactSource;
16
+ representation: RenderedArtifactRepresentation;
17
+ /** Required for `screenshot`: produces the image now (at attach time). */
18
+ capture?: () => Promise<RenderedCaptureResult>;
19
+ }
20
+ export declare function useAttachRenderedArtifact(conversationId: string | null | undefined): (args: AttachRenderedArtifactArgs) => Promise<boolean>;
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ import { toast } from "../../../../host/notify.js";
3
+ import { useAppDispatch, useAppStore } from "../../../../store/hooks.js";
4
+ import {
5
+ addResource,
6
+ removeResource,
7
+ setResourcePreview,
8
+ setResourceStatus
9
+ } from "../../../redux/execution-system/instance-resources/instance-resources.slice.js";
10
+ import { generateResourceId } from "../../../redux/execution-system/utils/ids.js";
11
+ import {
12
+ RENDERED_ARTIFACT_BLOCK_TYPE
13
+ } from "../../../utils/renderedArtifactContext.js";
14
+ import { useAttachResource } from "./attach-resource.js";
15
+ import { useUploadAgentResources } from "./usePasteImageResource.js";
16
+ function screenshotName(title) {
17
+ const base = title.trim().replace(/[^\w\s.-]+/g, "").trim().slice(0, 60) || "page";
18
+ return `${base} screenshot.png`;
19
+ }
20
+ function useAttachRenderedArtifact(conversationId) {
21
+ const dispatch = useAppDispatch();
22
+ const store = useAppStore();
23
+ const attachResource = useAttachResource(conversationId ?? "");
24
+ const uploadResources = useUploadAgentResources(conversationId ?? "", {
25
+ uploadRoot: "attachments",
26
+ uploadPath: "screenshots"
27
+ });
28
+ return async ({ source, representation, capture }) => {
29
+ if (!conversationId) {
30
+ toast.error("Open a chat to attach this to.");
31
+ return false;
32
+ }
33
+ if (representation !== "screenshot") {
34
+ const resourceId = generateResourceId();
35
+ dispatch(
36
+ addResource({
37
+ conversationId,
38
+ blockType: RENDERED_ARTIFACT_BLOCK_TYPE,
39
+ resourceId,
40
+ source,
41
+ options: { representation }
42
+ })
43
+ );
44
+ dispatch(
45
+ setResourcePreview({
46
+ conversationId,
47
+ resourceId,
48
+ preview: `${source.title || "Page"} \xB7 ${representation === "code" ? "Code" : "Text"}`
49
+ })
50
+ );
51
+ return true;
52
+ }
53
+ if (!capture) {
54
+ toast.error("This item can't be captured as an image.");
55
+ return false;
56
+ }
57
+ const name = screenshotName(source.title);
58
+ const placeholderId = generateResourceId();
59
+ dispatch(
60
+ addResource({
61
+ conversationId,
62
+ blockType: "image",
63
+ resourceId: placeholderId,
64
+ source: { filename: name, mime_type: "image/png" }
65
+ })
66
+ );
67
+ try {
68
+ const result = await capture();
69
+ const stillAttached = store.getState().instanceResources.byConversationId[conversationId]?.[placeholderId] !== void 0;
70
+ if (!stillAttached) return false;
71
+ if (result.kind === "file") {
72
+ dispatch(removeResource({ conversationId, resourceId: placeholderId }));
73
+ await uploadResources([result.file]);
74
+ return true;
75
+ }
76
+ const attached = await attachResource({
77
+ type: "file",
78
+ data: {
79
+ id: result.fileId,
80
+ filename: name,
81
+ url: result.url ?? void 0,
82
+ type: "image/png",
83
+ mime_type: "image/png",
84
+ details: { filename: name }
85
+ }
86
+ });
87
+ if (!attached) throw new Error("The screenshot could not be attached");
88
+ dispatch(removeResource({ conversationId, resourceId: placeholderId }));
89
+ return true;
90
+ } catch (err) {
91
+ const reason = err instanceof Error ? err.message : "Capture failed";
92
+ dispatch(
93
+ setResourceStatus({
94
+ conversationId,
95
+ resourceId: placeholderId,
96
+ status: "error",
97
+ errorMessage: reason
98
+ })
99
+ );
100
+ toast.error(`Couldn't capture the page: ${reason}`);
101
+ return false;
102
+ }
103
+ };
104
+ }
105
+ export {
106
+ useAttachRenderedArtifact
107
+ };