@ai-matrx/chat 0.5.8 → 0.5.12
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.
- package/CHANGELOG.md +28 -0
- package/dist/agent-copy/RichCopySplit.d.ts +3 -2
- package/dist/agent-copy/RichCopySplit.js +6 -1
- package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +3 -2
- package/dist/agents/components/inputs/smart-input/composer/ComposerMenu.d.ts +3 -1
- package/dist/agents/components/inputs/smart-input/composer/ComposerMenu.js +3 -2
- package/dist/conversation/utils/markdown-print.d.ts +5 -8
- package/dist/conversation/utils/markdown-print.js +8 -65
- package/dist/host/ui-slots.d.ts +9 -0
- package/dist/host/ui-slots.js +2 -0
- package/dist/tool-call-visualization/components/ArtifactResultBar.js +7 -1
- package/dist/tool-call-visualization/components/ToolCallVisualization.js +17 -13
- package/dist/tool-call-visualization/registry/toolArtifact.d.ts +6 -2
- package/dist/tool-call-visualization/registry/toolArtifact.js +15 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.5.12
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/chat/v0.5.11..npm/chat/v0.5.12 -- apps/shared/chat`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.5.10 — message Print is the one message print
|
|
10
|
+
|
|
11
|
+
- `conversation/utils/markdown-print` delegates to `@ai-matrx/rich-content/copy/print-message`
|
|
12
|
+
(`printMarkdownContent` now always returns a Promise). Needs rich-content ≥ 0.2.58.
|
|
13
|
+
|
|
14
|
+
Consumer action: none.
|
|
15
|
+
|
|
16
|
+
## Unreleased — lane L4b rendered-output
|
|
17
|
+
### an artifact edit shows its new version
|
|
18
|
+
|
|
19
|
+
`getToolArtifact` maps a completed `edit_artifact` call to a new `canvas_item` kind (`id` = the new
|
|
20
|
+
version's `canvas_items.id`, `version`); the tool card draws a "Page · Edited" bar and, under it, the
|
|
21
|
+
host slot **`CanvasItemCard`** (`{ canvasItemId, version? }`) — the version's own card rendered through
|
|
22
|
+
the host's block registry. Unregistered, the slot draws nothing. **Consumer action:** register
|
|
23
|
+
`CanvasItemCard` (matrx-frontend renders the item through its artifact renderer registry).
|
|
24
|
+
|
|
25
|
+
## 0.5.9
|
|
26
|
+
|
|
27
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
28
|
+
`git diff npm/chat/v0.5.5..npm/chat/v0.5.9 -- apps/shared/chat`).
|
|
29
|
+
No source changes intended and no consumer action required.
|
|
30
|
+
|
|
3
31
|
## 0.5.8 — attach from outside React
|
|
4
32
|
|
|
5
33
|
- `attachResourceToConversation(store, conversationId, resource)` — THE attach path without a hook
|
|
@@ -12,8 +12,9 @@ export type RichCopySplitProps = MatrxCopyMenuProps & {
|
|
|
12
12
|
exportTitle?: string;
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
-
* THE content action set of a markdown host (ContentActions, Arman 2026-10-08:
|
|
16
|
-
*
|
|
15
|
+
* THE content action set of a markdown host (ContentActions, Arman 2026-10-08 revised): ONE Copy icon
|
|
16
|
+
* (raw, then Copy raw / formatted / for AI — the host's `agent` envelope), Raw/Formatted, and "…" with
|
|
17
|
+
* Alchemy… (the palette below), the downloads and Print.
|
|
17
18
|
* Formerly the split Copy of a markdown host (Arman, 2026-10-04: "one click to get either the markdown
|
|
18
19
|
* version or the no-markup version"). One click copies the person's flavor (`copy.default_flavor`);
|
|
19
20
|
* the chevron offers exactly Copy markdown and Copy plain text (2026-10-07). The Alchemy palette
|
|
@@ -5,6 +5,7 @@ import { ContentActions } from "@ai-matrx/rich-content/copy/ContentActions";
|
|
|
5
5
|
import { copyRichContent } from "@ai-matrx/rich-content/copy/copy-commands";
|
|
6
6
|
import { ExportPaletteAnchor, openExportPalette, useExportPaletteKey } from "@ai-matrx/rich-content/copy/ExportPalette";
|
|
7
7
|
import { cn } from "@ai-matrx/design-system";
|
|
8
|
+
import { buildAgentPayload } from "@ai-matrx/alchemy/operate";
|
|
8
9
|
import { CopyButtons } from "../host/ui-slots.js";
|
|
9
10
|
function RichCopySplit(props) {
|
|
10
11
|
const { human, className, size } = props;
|
|
@@ -25,7 +26,11 @@ function RichCopySplit(props) {
|
|
|
25
26
|
},
|
|
26
27
|
copy,
|
|
27
28
|
size: splitSize,
|
|
28
|
-
label:
|
|
29
|
+
label: props.label ?? "content",
|
|
30
|
+
copyForAi: props.agent ? async () => {
|
|
31
|
+
const built = typeof props.agent === "function" ? await props.agent() : props.agent;
|
|
32
|
+
return typeof built === "string" ? built : buildAgentPayload(built, { url: window.location.href, capturedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
33
|
+
} : void 0,
|
|
29
34
|
title: props.exportTitle ?? props.label,
|
|
30
35
|
viewKey: props.viewKey,
|
|
31
36
|
onTransform: () => void openExportPalette(exportKey)
|
|
@@ -152,7 +152,7 @@ function ChatAgentMenu({
|
|
|
152
152
|
else onSelectAgent(info.customAgentId, { mandateKey: MANDATE_KEYS.chat__cx_default });
|
|
153
153
|
};
|
|
154
154
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
155
|
-
info.agentId ? /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: Webhook, label: `Agent: ${agentLabel}` }, panelClassName: "w-[340px] h-[420px] p-0", children: /* @__PURE__ */ jsx(ComposerAgentPeek, { agentId: info.agentId, onDone: close }) }) : null,
|
|
155
|
+
info.agentId ? /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon: Webhook, label: `Agent: ${agentLabel}` }, pageTitle: "Agent", panelClassName: "w-[340px] h-[420px] p-0", children: /* @__PURE__ */ jsx(ComposerAgentPeek, { agentId: info.agentId, onDone: close }) }) : null,
|
|
156
156
|
isManualMode ? /* @__PURE__ */ jsx(
|
|
157
157
|
ComposerMenuRow,
|
|
158
158
|
{
|
|
@@ -165,6 +165,7 @@ function ChatAgentMenu({
|
|
|
165
165
|
ComposerSubmenu,
|
|
166
166
|
{
|
|
167
167
|
row: { icon: Cpu, label: `Model: ${info.effectiveModelLabel ?? "Choose a model"}` },
|
|
168
|
+
pageTitle: "Model",
|
|
168
169
|
panelClassName: MODEL_PICKER_PANEL,
|
|
169
170
|
children: (closePanel) => /* @__PURE__ */ jsx(
|
|
170
171
|
QuickRunModelSelect,
|
|
@@ -213,7 +214,7 @@ function AnyAgentRow({
|
|
|
213
214
|
agentFilter,
|
|
214
215
|
choose
|
|
215
216
|
}) {
|
|
216
|
-
return /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon, label }, panelClassName: AGENT_PICKER_PANEL, children: /* @__PURE__ */ jsx(
|
|
217
|
+
return /* @__PURE__ */ jsx(ComposerSubmenu, { row: { icon, label }, pageTitle: "Agents", panelClassName: AGENT_PICKER_PANEL, children: /* @__PURE__ */ jsx(
|
|
217
218
|
AgentListPanel,
|
|
218
219
|
{
|
|
219
220
|
consumerId: "composer-agent-pill",
|
|
@@ -105,7 +105,7 @@ export declare function ComposerMenuLevel({ children }: {
|
|
|
105
105
|
* Popover anchored to the row, so Radix treats it as a child layer: clicking
|
|
106
106
|
* inside it never dismisses the parent menu.
|
|
107
107
|
*/
|
|
108
|
-
export declare function ComposerSubmenu({ row, children, panelClassName, open: controlledOpen, onOpenChange, drillInPlace, }: {
|
|
108
|
+
export declare function ComposerSubmenu({ row, children, panelClassName, open: controlledOpen, onOpenChange, drillInPlace, pageTitle, }: {
|
|
109
109
|
row: Omit<ComposerMenuRowProps, "onClick" | "chevron" | "active">;
|
|
110
110
|
children: ReactNode | ((close: () => void) => ReactNode);
|
|
111
111
|
/** Width/height of the cascade panel (e.g. "w-[360px] h-[440px]"). */
|
|
@@ -118,6 +118,8 @@ export declare function ComposerSubmenu({ row, children, panelClassName, open: c
|
|
|
118
118
|
* the menu. The phone sheet pushes pages either way.
|
|
119
119
|
*/
|
|
120
120
|
drillInPlace?: boolean;
|
|
121
|
+
/** The phone sheet's page title when the row's label carries a value ("Model: X" → "Model"). */
|
|
122
|
+
pageTitle?: string;
|
|
121
123
|
}): import("react").JSX.Element;
|
|
122
124
|
/**
|
|
123
125
|
* What a narrow composer folded out of its rows (Arman, 2026-10-04): its own
|
|
@@ -243,7 +243,8 @@ function ComposerSubmenu({
|
|
|
243
243
|
panelClassName,
|
|
244
244
|
open: controlledOpen,
|
|
245
245
|
onOpenChange,
|
|
246
|
-
drillInPlace
|
|
246
|
+
drillInPlace,
|
|
247
|
+
pageTitle
|
|
247
248
|
}) {
|
|
248
249
|
const id = useId();
|
|
249
250
|
const level = useContext(ComposerMenuLevelContext);
|
|
@@ -269,7 +270,7 @@ function ComposerSubmenu({
|
|
|
269
270
|
...row,
|
|
270
271
|
chevron: true,
|
|
271
272
|
onClick: () => sheetNav.push({
|
|
272
|
-
title: typeof row.label === "string" ? row.label : "",
|
|
273
|
+
title: pageTitle ?? (typeof row.label === "string" ? row.label : ""),
|
|
273
274
|
// A panel with no fixed height on desktop is content-sized on the
|
|
274
275
|
// phone too — one sizing decision, both presentations.
|
|
275
276
|
fit: panelClassName && !/(^|\s)h-\[/.test(panelClassName) ? "content" : "fill",
|
|
@@ -12,13 +12,10 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Fix conversion or styling in the package (SAME-SESSION LAW), never here.
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import type { PrintOutcome } from "@ai-matrx/print/core";
|
|
16
16
|
/**
|
|
17
|
-
* Prints a message
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* questions, a deck as its study sheet, a diagram as its drawing, an HTML page
|
|
21
|
-
* as its picture (a print window runs no author scripts; the page's own Print
|
|
22
|
-
* is the sharp one, and the person is told so).
|
|
17
|
+
* Prints a message through THE message print (`@ai-matrx/rich-content/copy/print-message`):
|
|
18
|
+
* prose plus every embedded block through its own registry adapter — the same
|
|
19
|
+
* composition the content actions' Print uses.
|
|
23
20
|
*/
|
|
24
|
-
export declare function printMarkdownContent(markdown: string, title?: string):
|
|
21
|
+
export declare function printMarkdownContent(markdown: string, title?: string): Promise<PrintOutcome>;
|
|
@@ -1,74 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getBlockPrinter } from "@ai-matrx/print/core";
|
|
1
|
+
import { printMessage } from "@ai-matrx/rich-content/copy/print-message";
|
|
3
2
|
import { notifyPrintOutcome } from "../../host/ui-slots.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const text = block.body.trim();
|
|
7
|
-
if (text.startsWith("{") || text.startsWith("[")) {
|
|
8
|
-
try {
|
|
9
|
-
return JSON.parse(text);
|
|
10
|
-
} catch {
|
|
11
|
-
return block.body;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return block.body;
|
|
15
|
-
}
|
|
16
|
-
function adapterFor(block) {
|
|
17
|
-
const printer = getBlockPrinter(block.type);
|
|
18
|
-
return printer?.toPrintHtml ? printer : null;
|
|
19
|
-
}
|
|
20
|
-
function printMarkdownContent(markdown, title = "AI Response") {
|
|
21
|
-
const blocks = listPrintBlocks(markdown, "article");
|
|
22
|
-
const hasMermaid = blocks.some((block) => block.source === "fence" && block.type === "mermaid");
|
|
23
|
-
const adapted = blocks.filter((block) => adapterFor(block) !== null);
|
|
24
|
-
if (!hasMermaid && adapted.length === 0) {
|
|
25
|
-
const outcome = printMarkdown(markdown, { skin: "article", title });
|
|
26
|
-
notifyPrintOutcome(outcome);
|
|
27
|
-
return outcome;
|
|
28
|
-
}
|
|
29
|
-
let drawing = null;
|
|
30
|
-
const drawAll = () => drawing ??= (async () => {
|
|
31
|
-
try {
|
|
32
|
-
const { drawMermaidForPrint } = await import("@ai-matrx/rich-content/mermaid/print-render");
|
|
33
|
-
const { pictures, failed } = await drawMermaidForPrint(markdown);
|
|
34
|
-
if (failed > 0) {
|
|
35
|
-
const { toast } = await import("../../host/notify.js");
|
|
36
|
-
toast.warning(
|
|
37
|
-
`${failed} diagram${failed === 1 ? "" : "s"} could not be drawn and print${failed === 1 ? "s" : ""} as source.`
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
return pictures;
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.error("[print] diagrams could not be drawn", error);
|
|
43
|
-
const { toast } = await import("../../host/notify.js");
|
|
44
|
-
toast.warning("Diagrams could not be drawn, so they print as source.");
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
})();
|
|
48
|
-
return printMarkdownWhenReady(markdown, {
|
|
3
|
+
async function printMarkdownContent(markdown, title = "AI Response") {
|
|
4
|
+
const outcome = await printMessage(markdown, {
|
|
49
5
|
skin: "article",
|
|
50
6
|
title,
|
|
51
|
-
|
|
52
|
-
if (block.source === "fence" && block.type === "mermaid") {
|
|
53
|
-
const svg = (await drawAll())?.get(block.body);
|
|
54
|
-
return svg ? { svg, alt: "Diagram" } : null;
|
|
55
|
-
}
|
|
56
|
-
const printer = adapterFor(block);
|
|
57
|
-
if (!printer?.toPrintHtml) return null;
|
|
58
|
-
return printer.toPrintHtml(blockData(block), {
|
|
59
|
-
type: block.type,
|
|
60
|
-
raw: block.body,
|
|
61
|
-
...block.title ? { title: block.title } : {}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}).then(async (outcome) => {
|
|
65
|
-
notifyPrintOutcome(outcome);
|
|
66
|
-
if (outcome === "opened" && adapted.some((block) => FRAME_BLOCK_TYPES.has(block.type))) {
|
|
7
|
+
onNotice: async (level, message) => {
|
|
67
8
|
const { toast } = await import("../../host/notify.js");
|
|
68
|
-
|
|
9
|
+
if (level === "warning") toast.warning(message);
|
|
10
|
+
else toast.info(message);
|
|
69
11
|
}
|
|
70
|
-
return outcome;
|
|
71
12
|
});
|
|
13
|
+
notifyPrintOutcome(outcome);
|
|
14
|
+
return outcome;
|
|
72
15
|
}
|
|
73
16
|
export {
|
|
74
17
|
printMarkdownContent
|
package/dist/host/ui-slots.d.ts
CHANGED
|
@@ -80,6 +80,12 @@ interface ValueChangeProps<T> {
|
|
|
80
80
|
[extra: string]: any;
|
|
81
81
|
}
|
|
82
82
|
type AnyComponent = ComponentType<any>;
|
|
83
|
+
export interface CanvasItemCardProps {
|
|
84
|
+
/** `canvas_items.id` of the version to show. */
|
|
85
|
+
canvasItemId: string;
|
|
86
|
+
/** Its chain version, when the caller knows it. */
|
|
87
|
+
version?: number;
|
|
88
|
+
}
|
|
83
89
|
/**
|
|
84
90
|
* A component slot typed by the props the PACKAGE passes. Bivariant on purpose: the host
|
|
85
91
|
* component has its own (usually richer) prop type, and a slot must accept it as long as the
|
|
@@ -105,6 +111,8 @@ export interface ChatUiSlots {
|
|
|
105
111
|
FileResourceChip: AnyComponent;
|
|
106
112
|
ConnectorMark: AnyComponent;
|
|
107
113
|
MessageFilesStrip: AnyComponent;
|
|
114
|
+
/** A canvas item rendered by id through the host's block registry (a tool's new artifact version). */
|
|
115
|
+
CanvasItemCard: SlotComponent<CanvasItemCardProps>;
|
|
108
116
|
RulebookNudge: AnyComponent;
|
|
109
117
|
NegativeVerdictFollowUp: AnyComponent;
|
|
110
118
|
SpeakerButton: AnyComponent;
|
|
@@ -468,6 +476,7 @@ export declare const TableChooser: AnyComponent;
|
|
|
468
476
|
export declare const FileResourceChip: AnyComponent;
|
|
469
477
|
export declare const ConnectorMark: AnyComponent;
|
|
470
478
|
export declare const MessageFilesStrip: AnyComponent;
|
|
479
|
+
export declare const CanvasItemCard: SlotComponent<CanvasItemCardProps>;
|
|
471
480
|
export declare const RulebookNudge: AnyComponent;
|
|
472
481
|
export declare const NegativeVerdictFollowUp: AnyComponent;
|
|
473
482
|
export declare const SpeakerButton: AnyComponent;
|
package/dist/host/ui-slots.js
CHANGED
|
@@ -232,6 +232,7 @@ const TableChooser = slotComponent("TableChooser");
|
|
|
232
232
|
const FileResourceChip = slotComponent("FileResourceChip");
|
|
233
233
|
const ConnectorMark = slotComponent("ConnectorMark");
|
|
234
234
|
const MessageFilesStrip = slotComponent("MessageFilesStrip", optionalWidget("MessageFilesStrip"));
|
|
235
|
+
const CanvasItemCard = slotComponent("CanvasItemCard", optionalWidget("CanvasItemCard"));
|
|
235
236
|
const RulebookNudge = slotComponent("RulebookNudge", optionalWidget("RulebookNudge"));
|
|
236
237
|
const NegativeVerdictFollowUp = slotComponent("NegativeVerdictFollowUp", optionalWidget("NegativeVerdictFollowUp"));
|
|
237
238
|
const SpeakerButton = slotComponent("SpeakerButton", optionalWidget("SpeakerButton"));
|
|
@@ -527,6 +528,7 @@ export {
|
|
|
527
528
|
AttachedResourcesSection,
|
|
528
529
|
AuthGateDialog,
|
|
529
530
|
BlockHoverPreview,
|
|
531
|
+
CanvasItemCard,
|
|
530
532
|
ChangeDiff,
|
|
531
533
|
CitationChip,
|
|
532
534
|
ClampedNumberInput,
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ChevronDown,
|
|
5
5
|
FileText,
|
|
6
6
|
Frame,
|
|
7
|
+
Globe,
|
|
7
8
|
PanelRightOpen,
|
|
8
9
|
Pencil,
|
|
9
10
|
StickyNote,
|
|
@@ -35,6 +36,11 @@ const KIND_META = {
|
|
|
35
36
|
Icon: StickyNote,
|
|
36
37
|
noun: "Note",
|
|
37
38
|
iconTint: "text-amber-600 dark:text-amber-400"
|
|
39
|
+
},
|
|
40
|
+
canvas_item: {
|
|
41
|
+
Icon: Globe,
|
|
42
|
+
noun: "Page",
|
|
43
|
+
iconTint: "text-emerald-600 dark:text-emerald-400"
|
|
38
44
|
}
|
|
39
45
|
};
|
|
40
46
|
function ArtifactResultBar({
|
|
@@ -134,7 +140,7 @@ function ArtifactResultBar({
|
|
|
134
140
|
/* @__PURE__ */ jsx(Frame, { className: "size-4" }),
|
|
135
141
|
"Canvas"
|
|
136
142
|
] }),
|
|
137
|
-
/* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: openEdit, className: "gap-2", children: [
|
|
143
|
+
artifact.kind !== "canvas_item" && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: openEdit, className: "gap-2", children: [
|
|
138
144
|
/* @__PURE__ */ jsx(Pencil, { className: "size-4" }),
|
|
139
145
|
"Edit"
|
|
140
146
|
] }),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React, { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import {
|
|
5
5
|
ChevronDown,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "../result-fields/ToolErrorCard.js";
|
|
42
42
|
import { guardRoutingOf } from "../result-fields/guard-routing.js";
|
|
43
43
|
import { resultAsObject } from "../renderers/_shared.js";
|
|
44
|
-
import { RecordChangeApprovalCard, useHeldWriteTableName } from "../../host/ui-slots.js";
|
|
44
|
+
import { CanvasItemCard, RecordChangeApprovalCard, useHeldWriteTableName } from "../../host/ui-slots.js";
|
|
45
45
|
import { SHOW_PARKED_ASK_EVENT } from "../../agents/runtime-reconnect/show-parked-ask.js";
|
|
46
46
|
import { ParkedOnPersonCard } from "../../action-requests/components/ParkedOnPersonCard.js";
|
|
47
47
|
import {
|
|
@@ -193,6 +193,7 @@ const ToolCallVisualizationInner = ({
|
|
|
193
193
|
const querySubtitle = phase === "error" || heldWait || parkedAsk ? null : headerSubtitle;
|
|
194
194
|
const artifactRaw = phase === "complete" && settled.length === 1 && !heldWait ? getToolArtifact(headerTool) : null;
|
|
195
195
|
const artifact = artifactRaw && (artifactRaw.kind === "working_document" ? typeof conversationId === "string" && conversationId.length > 0 : Boolean(artifactRaw.id)) ? artifactRaw : null;
|
|
196
|
+
const canvasItemCard = artifact?.kind === "canvas_item" && artifact.id ? /* @__PURE__ */ jsx("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx(CanvasItemCard, { canvasItemId: artifact.id, version: artifact.version }) }) : null;
|
|
196
197
|
if (entries.length === 0) return null;
|
|
197
198
|
const handleOpenOverlay = (tabId) => {
|
|
198
199
|
setInitialOverlayTab(tabId);
|
|
@@ -232,17 +233,20 @@ const ToolCallVisualizationInner = ({
|
|
|
232
233
|
className
|
|
233
234
|
),
|
|
234
235
|
children: [
|
|
235
|
-
artifact ? /* @__PURE__ */
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
artifact ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
237
|
+
/* @__PURE__ */ jsx(
|
|
238
|
+
ArtifactResultBar,
|
|
239
|
+
{
|
|
240
|
+
artifact,
|
|
241
|
+
conversationId,
|
|
242
|
+
peekExpanded: isExpanded,
|
|
243
|
+
onTogglePeek: toggleExpand,
|
|
244
|
+
onOpenOverlay: handleOpenOverlay,
|
|
245
|
+
onOpenWindowPanel: handleOpenWindowPanel
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
canvasItemCard
|
|
249
|
+
] }) : cardMode && headerTool && HeaderInline ? (
|
|
246
250
|
// Self-headed entity card — no fold line; the card's own header carries
|
|
247
251
|
// the name + "Open in" menu. createElement (not JSX) since the component
|
|
248
252
|
// is resolved at runtime from the registry.
|
|
@@ -14,18 +14,22 @@
|
|
|
14
14
|
* branch here + one entry in the bar's `KIND_META`.
|
|
15
15
|
*/
|
|
16
16
|
import type { ToolLifecycleEntry } from "../../agents/types/request.types.js";
|
|
17
|
-
export type ToolArtifactKind = "working_document" | "note";
|
|
17
|
+
export type ToolArtifactKind = "working_document" | "note" | "canvas_item";
|
|
18
18
|
export interface ToolArtifact {
|
|
19
19
|
kind: ToolArtifactKind;
|
|
20
20
|
/** Generic fallback label; the working-doc bar prefers the live document title. */
|
|
21
21
|
title: string;
|
|
22
22
|
/** Past-tense verb for the sub-label: "Edited" / "Rewrote" / "Saved" / "Updated". */
|
|
23
23
|
verbPast: string;
|
|
24
|
-
/** Open handle for id-based kinds (note). The working document uses the shell's conversationId. */
|
|
24
|
+
/** Open handle for id-based kinds (note, canvas_item). The working document uses the shell's conversationId. */
|
|
25
25
|
id?: string;
|
|
26
|
+
/** canvas_item: the chain version this call produced (the card shows THAT version). */
|
|
27
|
+
version?: number;
|
|
26
28
|
}
|
|
27
29
|
/** The `ctx_patch` tool and its live production alias — the canonical set of
|
|
28
30
|
* tool names that carry a working-document (or any ctx key) patch. Shared so
|
|
29
31
|
* the drawer's live-diff hook matches patch entries the same way. */
|
|
30
32
|
export declare const PATCH_TOOLS: Set<string>;
|
|
33
|
+
/** Tools whose result is a new version of a canvas item (`artifact_id` + `version`). */
|
|
34
|
+
export declare const CANVAS_ITEM_TOOLS: Set<string>;
|
|
31
35
|
export declare function getToolArtifact(entry: ToolLifecycleEntry | null | undefined): ToolArtifact | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getArg, resultAsObject } from "../renderers/_shared.js";
|
|
2
2
|
const PATCH_TOOLS = /* @__PURE__ */ new Set(["ctx_patch", "context_patch"]);
|
|
3
3
|
const NOTE_TOOLS = /* @__PURE__ */ new Set(["note", "war_room_update_note"]);
|
|
4
|
+
const CANVAS_ITEM_TOOLS = /* @__PURE__ */ new Set(["edit_artifact"]);
|
|
4
5
|
const WORKING_DOC_KEY = "working_document";
|
|
5
6
|
function pastForPatchCommand(command) {
|
|
6
7
|
switch (command) {
|
|
@@ -45,9 +46,23 @@ function getToolArtifact(entry) {
|
|
|
45
46
|
id
|
|
46
47
|
};
|
|
47
48
|
}
|
|
49
|
+
if (CANVAS_ITEM_TOOLS.has(tool)) {
|
|
50
|
+
const facts = result && typeof result.artifact_id === "string" ? result : result && typeof result.details === "object" && result.details !== null ? result.details : null;
|
|
51
|
+
const id = facts && typeof facts.artifact_id === "string" ? facts.artifact_id : void 0;
|
|
52
|
+
if (!id) return null;
|
|
53
|
+
const version = facts && typeof facts.version === "number" ? facts.version : void 0;
|
|
54
|
+
return {
|
|
55
|
+
kind: "canvas_item",
|
|
56
|
+
title: version ? `Version ${version}` : "New version",
|
|
57
|
+
verbPast: "Edited",
|
|
58
|
+
id,
|
|
59
|
+
...version ? { version } : {}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
48
62
|
return null;
|
|
49
63
|
}
|
|
50
64
|
export {
|
|
65
|
+
CANVAS_ITEM_TOOLS,
|
|
51
66
|
PATCH_TOOLS,
|
|
52
67
|
getToolArtifact
|
|
53
68
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/chat",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.12",
|
|
4
4
|
"description": "THE one AI Matrx person-to-agent chat system: the full chat (running agents, conversations, tool calls, streaming, context, surfaces, voice) as per-module subpaths @ai-matrx/chat/<domain>/<module> over a host contract (/host, /host/react) whose only required value is a db. One chat, one renderer: the old kernel entries (., /external-store, /matrx, /react, /tools, styles.css, tokens.css) are retired.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -169,21 +169,21 @@
|
|
|
169
169
|
"@ai-matrx/agents": "latest",
|
|
170
170
|
"@ai-matrx/alchemy": "latest",
|
|
171
171
|
"@ai-matrx/associations": "latest",
|
|
172
|
+
"@ai-matrx/browser-audio": "latest",
|
|
172
173
|
"@ai-matrx/canvas": "latest",
|
|
173
174
|
"@ai-matrx/content-ir": "latest",
|
|
174
|
-
"@ai-matrx/content-ir-react": "latest",
|
|
175
175
|
"@ai-matrx/data": "latest",
|
|
176
|
-
"@ai-matrx/
|
|
176
|
+
"@ai-matrx/design-system": "latest",
|
|
177
|
+
"@ai-matrx/content-ir-react": "latest",
|
|
177
178
|
"@ai-matrx/diff": "latest",
|
|
178
179
|
"@ai-matrx/icons": "latest",
|
|
179
|
-
"@ai-matrx/
|
|
180
|
-
"@ai-matrx/kit": "latest",
|
|
180
|
+
"@ai-matrx/media": "latest",
|
|
181
181
|
"@ai-matrx/print": "latest",
|
|
182
182
|
"@ai-matrx/realtime": "latest",
|
|
183
|
-
"@ai-matrx/media": "latest",
|
|
184
|
-
"@ai-matrx/records-ui": "latest",
|
|
185
183
|
"@ai-matrx/records": "latest",
|
|
184
|
+
"@ai-matrx/kit": "latest",
|
|
186
185
|
"@ai-matrx/rich-editor": "latest",
|
|
186
|
+
"@ai-matrx/records-ui": "latest",
|
|
187
187
|
"@ai-matrx/rich-content": "latest"
|
|
188
188
|
},
|
|
189
189
|
"devDependencies": {
|