@ai-matrx/chat 0.5.6 → 0.5.11
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 +41 -0
- package/dist/agent-copy/RichCopySplit.d.ts +3 -2
- package/dist/agent-copy/RichCopySplit.js +6 -1
- package/dist/agents/components/context-items/registry.d.ts +1 -0
- package/dist/agents/components/context-items/registry.js +7 -3
- package/dist/agents/components/inputs/resources/attach-resource.d.ts +30 -0
- package/dist/agents/components/inputs/resources/attach-resource.js +11 -2
- package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.d.ts +6 -0
- package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.js +79 -69
- 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 +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @ai-matrx/chat
|
|
2
2
|
|
|
3
|
+
## 0.5.11
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/chat/v0.5.8..npm/chat/v0.5.11 -- 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
|
+
|
|
31
|
+
## 0.5.8 — attach from outside React
|
|
32
|
+
|
|
33
|
+
- `attachResourceToConversation(store, conversationId, resource)` — THE attach path without a hook
|
|
34
|
+
(`useAttachResource` is it bound to the app store); `attachRenderedArtifact(store, conversationId,
|
|
35
|
+
args)` — the same for a rendered page, for a canvas "Attach to chat ▸" entry or any host port.
|
|
36
|
+
- Consumer action: none required; a canvas host may wire `attachRenderedArtifact` into
|
|
37
|
+
`CanvasOutputPorts.attachOptions`.
|
|
38
|
+
|
|
39
|
+
## 0.5.7 — a registry/list disagreement no longer crashes the page
|
|
40
|
+
|
|
41
|
+
- The context-items load-time drift check logs a loud console error instead of throwing; the
|
|
42
|
+
unregistered type renders through the generic fallback body. A jest test fails on any disagreement.
|
|
43
|
+
|
|
3
44
|
## 0.5.6 — 0.5.5 threw at load
|
|
4
45
|
|
|
5
46
|
- `CONTEXT_ITEM_BLOCK_TYPES` lists `rendered_artifact`: 0.5.5 registered the def without it, so the
|
|
@@ -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)
|
|
@@ -17,6 +17,7 @@ import type { ComponentType } from "react";
|
|
|
17
17
|
import { hasContextItemDef } from "./context-item-block-types.js";
|
|
18
18
|
import type { ContextItemBodyProps, ContextItemTitleProps, ContextItemTypeDef } from "./types.js";
|
|
19
19
|
export declare const CONTEXT_ITEM_TYPE_DEFS: ContextItemTypeDef[];
|
|
20
|
+
export declare function findContextItemRegistryDrift(): string[];
|
|
20
21
|
export { hasContextItemDef };
|
|
21
22
|
/** Resolve the registered def for a block type, or a graceful fallback. */
|
|
22
23
|
export declare function resolveContextItemDef(blockType: string): ContextItemTypeDef;
|
|
@@ -339,14 +339,17 @@ const FALLBACK_DEF = {
|
|
|
339
339
|
editable: false,
|
|
340
340
|
Body: GenericBody
|
|
341
341
|
};
|
|
342
|
-
{
|
|
342
|
+
function findContextItemRegistryDrift() {
|
|
343
343
|
const listed = new Set(CONTEXT_ITEM_BLOCK_TYPES);
|
|
344
|
-
|
|
344
|
+
return [
|
|
345
345
|
...[...BY_BLOCK_TYPE.keys()].filter((t) => !listed.has(t)),
|
|
346
346
|
...CONTEXT_ITEM_BLOCK_TYPES.filter((t) => !BY_BLOCK_TYPE.has(t))
|
|
347
347
|
];
|
|
348
|
+
}
|
|
349
|
+
{
|
|
350
|
+
const drift = findContextItemRegistryDrift();
|
|
348
351
|
if (drift.length > 0) {
|
|
349
|
-
|
|
352
|
+
console.error(
|
|
350
353
|
`context-items registry and CONTEXT_ITEM_BLOCK_TYPES disagree: ${drift.join(", ")}`
|
|
351
354
|
);
|
|
352
355
|
}
|
|
@@ -371,6 +374,7 @@ function resolveContextItemTitle(blockType) {
|
|
|
371
374
|
}
|
|
372
375
|
export {
|
|
373
376
|
CONTEXT_ITEM_TYPE_DEFS,
|
|
377
|
+
findContextItemRegistryDrift,
|
|
374
378
|
hasContextItemDef,
|
|
375
379
|
resolveContextItemBody,
|
|
376
380
|
resolveContextItemDef,
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* attach-resource — the single mapping from a picked `Resource` to how it gets
|
|
3
|
+
* attached to a conversation, shared by every surface that attaches resources
|
|
4
|
+
* (SmartAgentResourcePickerButton, the RunControlsMenu Attach tab, …).
|
|
5
|
+
*
|
|
6
|
+
* TWO attach shapes, by kind:
|
|
7
|
+
* - A stored FILE → a DURABLE `platform.associations` edge to the conversation
|
|
8
|
+
* (`file → conversation`). The file ID means its complete existing family,
|
|
9
|
+
* including processed documents and Knowledge. This PERSISTS across turns and reloads; the
|
|
10
|
+
* backend reads the conversation's edges at call time and injects the context.
|
|
11
|
+
* The chip renders from the edge list (see `AttachedDocumentChips`), NOT the
|
|
12
|
+
* ephemeral `instanceResources` slice.
|
|
13
|
+
* - Before the conversation row exists, the same stored FILE identity is held
|
|
14
|
+
* as a `processed_document` instance resource and emitted in request.context.
|
|
15
|
+
* It is never downgraded to a provider-native PDF block.
|
|
16
|
+
* - Everything else (media bytes, notes, tasks, webpages, …) → the per-turn
|
|
17
|
+
* `instanceResources` block. A document with no durable file identity still
|
|
18
|
+
* rides content[] as binary media.
|
|
19
|
+
*/
|
|
20
|
+
import type { Dispatch } from "@reduxjs/toolkit";
|
|
1
21
|
import type { ChatRootState } from "../../../../store/root-state.js";
|
|
2
22
|
import type { Resource } from "../../../resources/types.js";
|
|
3
23
|
import type { ResourceBlockType } from "../../../types/instance.types.js";
|
|
@@ -24,7 +44,17 @@ export declare function findIdenticalResourceId(state: ChatRootState, conversati
|
|
|
24
44
|
* the per-turn binary/instanceResources path unchanged. Closing the hosting
|
|
25
45
|
* popover is the CALLER's job.
|
|
26
46
|
*/
|
|
47
|
+
/** The store handles a non-React caller passes to the attach functions. */
|
|
48
|
+
export interface AttachStore {
|
|
49
|
+
dispatch: Dispatch;
|
|
50
|
+
getState: () => unknown;
|
|
51
|
+
}
|
|
27
52
|
export declare function useAttachResource(conversationId: string): (resource: Resource) => Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* THE attach path, callable outside React (a canvas menu entry, a host port).
|
|
55
|
+
* `useAttachResource` is this bound to the app store.
|
|
56
|
+
*/
|
|
57
|
+
export declare function attachResourceToConversation(store: AttachStore, conversationId: string, resource: Resource): Promise<boolean>;
|
|
28
58
|
/**
|
|
29
59
|
* Inverse of `useAttachResource` for files toggled in the live picker.
|
|
30
60
|
* Owned media can have both a durable authorization edge and a per-turn media
|
|
@@ -183,7 +183,15 @@ async function attachConversationFileEdge(conversationId, sourceId, fileId, labe
|
|
|
183
183
|
function useAttachResource(conversationId) {
|
|
184
184
|
const dispatch = useAppDispatch();
|
|
185
185
|
const store = useAppStore();
|
|
186
|
-
return
|
|
186
|
+
return (resource) => attachResourceToConversation(
|
|
187
|
+
{ dispatch, getState: store.getState },
|
|
188
|
+
conversationId,
|
|
189
|
+
resource
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
async function attachResourceToConversation(store, conversationId, resource) {
|
|
193
|
+
const dispatch = store.dispatch;
|
|
194
|
+
{
|
|
187
195
|
const getState = () => store.getState();
|
|
188
196
|
const baseBlockType = resourceTypeToBlockType(resource.type);
|
|
189
197
|
const blockType = refineBlockType(baseBlockType, resource.data);
|
|
@@ -298,7 +306,7 @@ function useAttachResource(conversationId) {
|
|
|
298
306
|
resourcePreviewLabel
|
|
299
307
|
);
|
|
300
308
|
return true;
|
|
301
|
-
}
|
|
309
|
+
}
|
|
302
310
|
}
|
|
303
311
|
function useDetachResource(conversationId) {
|
|
304
312
|
const dispatch = useAppDispatch();
|
|
@@ -342,6 +350,7 @@ function useDetachResource(conversationId) {
|
|
|
342
350
|
};
|
|
343
351
|
}
|
|
344
352
|
export {
|
|
353
|
+
attachResourceToConversation,
|
|
345
354
|
findIdenticalResourceId,
|
|
346
355
|
resourceLabel,
|
|
347
356
|
resourceTypeToBlockType,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { RenderedArtifactRepresentation } from "../../../types/instance.types.js";
|
|
2
2
|
import { type RenderedArtifactSource } from "../../../utils/renderedArtifactContext.js";
|
|
3
|
+
import { type AttachStore } from "./attach-resource.js";
|
|
3
4
|
/** What a host capture port returns: a stored cloud image, or a local PNG to upload. */
|
|
4
5
|
export type RenderedCaptureResult = {
|
|
5
6
|
kind: "stored";
|
|
@@ -18,3 +19,8 @@ export interface AttachRenderedArtifactArgs {
|
|
|
18
19
|
capture?: () => Promise<RenderedCaptureResult>;
|
|
19
20
|
}
|
|
20
21
|
export declare function useAttachRenderedArtifact(conversationId: string | null | undefined): (args: AttachRenderedArtifactArgs) => Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* The same attach outside React (a canvas "Attach to chat ▸" entry). Without
|
|
24
|
+
* `uploadFiles`, a capture must answer a STORED image (the server engine).
|
|
25
|
+
*/
|
|
26
|
+
export declare function attachRenderedArtifact(store: AttachStore, conversationId: string | null | undefined, { source, representation, capture }: AttachRenderedArtifactArgs, uploadFiles?: (files: File[]) => Promise<void>): Promise<boolean>;
|
|
@@ -11,7 +11,7 @@ import { generateResourceId } from "../../../redux/execution-system/utils/ids.js
|
|
|
11
11
|
import {
|
|
12
12
|
RENDERED_ARTIFACT_BLOCK_TYPE
|
|
13
13
|
} from "../../../utils/renderedArtifactContext.js";
|
|
14
|
-
import {
|
|
14
|
+
import { attachResourceToConversation } from "./attach-resource.js";
|
|
15
15
|
import { useUploadAgentResources } from "./usePasteImageResource.js";
|
|
16
16
|
function screenshotName(title) {
|
|
17
17
|
const base = title.trim().replace(/[^\w\s.-]+/g, "").trim().slice(0, 60) || "page";
|
|
@@ -20,88 +20,98 @@ function screenshotName(title) {
|
|
|
20
20
|
function useAttachRenderedArtifact(conversationId) {
|
|
21
21
|
const dispatch = useAppDispatch();
|
|
22
22
|
const store = useAppStore();
|
|
23
|
-
const attachResource = useAttachResource(conversationId ?? "");
|
|
24
23
|
const uploadResources = useUploadAgentResources(conversationId ?? "", {
|
|
25
24
|
uploadRoot: "attachments",
|
|
26
25
|
uploadPath: "screenshots"
|
|
27
26
|
});
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
return (args) => attachRenderedArtifact(
|
|
28
|
+
{ dispatch, getState: store.getState },
|
|
29
|
+
conversationId,
|
|
30
|
+
args,
|
|
31
|
+
uploadResources
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
async function attachRenderedArtifact(store, conversationId, { source, representation, capture }, uploadFiles) {
|
|
35
|
+
const { dispatch } = store;
|
|
36
|
+
if (!conversationId) {
|
|
37
|
+
toast.error("Open a chat to attach this to.");
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (representation !== "screenshot") {
|
|
41
|
+
const resourceId = generateResourceId();
|
|
42
|
+
dispatch(
|
|
43
|
+
addResource({
|
|
44
|
+
conversationId,
|
|
45
|
+
blockType: RENDERED_ARTIFACT_BLOCK_TYPE,
|
|
46
|
+
resourceId,
|
|
47
|
+
source,
|
|
48
|
+
options: { representation }
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
dispatch(
|
|
52
|
+
setResourcePreview({
|
|
53
|
+
conversationId,
|
|
54
|
+
resourceId,
|
|
55
|
+
preview: `${source.title || "Page"} \xB7 ${representation === "code" ? "Code" : "Text"}`
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (!capture) {
|
|
61
|
+
toast.error("This item can't be captured as an image.");
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const name = screenshotName(source.title);
|
|
65
|
+
const placeholderId = generateResourceId();
|
|
66
|
+
dispatch(
|
|
67
|
+
addResource({
|
|
68
|
+
conversationId,
|
|
69
|
+
blockType: "image",
|
|
70
|
+
resourceId: placeholderId,
|
|
71
|
+
source: { filename: name, mime_type: "image/png" }
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
try {
|
|
75
|
+
const result = await capture();
|
|
76
|
+
const state = store.getState();
|
|
77
|
+
if (state.instanceResources.byConversationId[conversationId]?.[placeholderId] === void 0) {
|
|
31
78
|
return false;
|
|
32
79
|
}
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
dispatch(
|
|
36
|
-
|
|
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
|
-
);
|
|
80
|
+
if (result.kind === "file") {
|
|
81
|
+
if (!uploadFiles) throw new Error("This capture needs an upload, which is not available here");
|
|
82
|
+
dispatch(removeResource({ conversationId, resourceId: placeholderId }));
|
|
83
|
+
await uploadFiles([result.file]);
|
|
51
84
|
return true;
|
|
52
85
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
const attached = await attachResourceToConversation(store, conversationId, {
|
|
87
|
+
type: "file",
|
|
88
|
+
data: {
|
|
89
|
+
id: result.fileId,
|
|
90
|
+
filename: name,
|
|
91
|
+
url: result.url ?? void 0,
|
|
92
|
+
type: "image/png",
|
|
93
|
+
mime_type: "image/png",
|
|
94
|
+
details: { filename: name }
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
if (!attached) throw new Error("The screenshot could not be attached");
|
|
98
|
+
dispatch(removeResource({ conversationId, resourceId: placeholderId }));
|
|
99
|
+
return true;
|
|
100
|
+
} catch (err) {
|
|
101
|
+
const reason = err instanceof Error ? err.message : "Capture failed";
|
|
59
102
|
dispatch(
|
|
60
|
-
|
|
103
|
+
setResourceStatus({
|
|
61
104
|
conversationId,
|
|
62
|
-
blockType: "image",
|
|
63
105
|
resourceId: placeholderId,
|
|
64
|
-
|
|
106
|
+
status: "error",
|
|
107
|
+
errorMessage: reason
|
|
65
108
|
})
|
|
66
109
|
);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
};
|
|
110
|
+
toast.error(`Couldn't capture the page: ${reason}`);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
104
113
|
}
|
|
105
114
|
export {
|
|
115
|
+
attachRenderedArtifact,
|
|
106
116
|
useAttachRenderedArtifact
|
|
107
117
|
};
|
|
@@ -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.11",
|
|
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",
|
|
@@ -166,25 +166,25 @@
|
|
|
166
166
|
"server-only": "^0.0.1",
|
|
167
167
|
"uuid": "^14.0.2",
|
|
168
168
|
"zod": "^4.6.5",
|
|
169
|
+
"@ai-matrx/agents": "latest",
|
|
169
170
|
"@ai-matrx/alchemy": "latest",
|
|
170
171
|
"@ai-matrx/associations": "latest",
|
|
171
172
|
"@ai-matrx/browser-audio": "latest",
|
|
172
|
-
"@ai-matrx/agents": "latest",
|
|
173
173
|
"@ai-matrx/canvas": "latest",
|
|
174
174
|
"@ai-matrx/content-ir": "latest",
|
|
175
175
|
"@ai-matrx/content-ir-react": "latest",
|
|
176
176
|
"@ai-matrx/data": "latest",
|
|
177
|
+
"@ai-matrx/design-system": "latest",
|
|
177
178
|
"@ai-matrx/diff": "latest",
|
|
178
179
|
"@ai-matrx/icons": "latest",
|
|
179
180
|
"@ai-matrx/media": "latest",
|
|
181
|
+
"@ai-matrx/kit": "latest",
|
|
180
182
|
"@ai-matrx/print": "latest",
|
|
181
183
|
"@ai-matrx/realtime": "latest",
|
|
182
184
|
"@ai-matrx/records": "latest",
|
|
183
185
|
"@ai-matrx/records-ui": "latest",
|
|
184
186
|
"@ai-matrx/rich-content": "latest",
|
|
185
|
-
"@ai-matrx/rich-editor": "latest"
|
|
186
|
-
"@ai-matrx/kit": "latest",
|
|
187
|
-
"@ai-matrx/design-system": "latest"
|
|
187
|
+
"@ai-matrx/rich-editor": "latest"
|
|
188
188
|
},
|
|
189
189
|
"devDependencies": {
|
|
190
190
|
"@arethetypeswrong/cli": "^0.18.5",
|