@ai-matrx/messaging 0.3.0 → 0.4.0
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 +36 -0
- package/README.md +5 -0
- package/dist/index.cjs +16 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +44 -7
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +28 -5
- package/dist/react.d.ts +28 -5
- package/dist/react.js +44 -7
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.d.cts
CHANGED
|
@@ -828,6 +828,17 @@ interface MessageActionRenderer<TPayload = unknown> {
|
|
|
828
828
|
type ReferenceRenderer = ComponentType<{
|
|
829
829
|
reference: MatrxReference;
|
|
830
830
|
}>;
|
|
831
|
+
/**
|
|
832
|
+
* A host's renderer for a raw ```matrx fence — the body between the backticks.
|
|
833
|
+
*
|
|
834
|
+
* This package understands one fence dialect: its own. A platform's fences are
|
|
835
|
+
* its platform's business (Matrx's are `__kind` directive shells resolved
|
|
836
|
+
* through a kind registry), and only the app can draw them. Give us this and
|
|
837
|
+
* EVERY fence in a message goes to you, parsed or not.
|
|
838
|
+
*/
|
|
839
|
+
type FenceRenderer = ComponentType<{
|
|
840
|
+
body: string;
|
|
841
|
+
}>;
|
|
831
842
|
/**
|
|
832
843
|
* App chrome wrapped around ONE message bubble or ONE conversation row.
|
|
833
844
|
*
|
|
@@ -858,6 +869,7 @@ interface MessagingHost {
|
|
|
858
869
|
/** Host surfaces for action kinds whose answer is a card, not a chip. */
|
|
859
870
|
readonly actionRenderers: ReadonlyMap<string, MessageActionRenderer>;
|
|
860
871
|
readonly renderReference: ReferenceRenderer | null;
|
|
872
|
+
readonly renderFence: FenceRenderer | null;
|
|
861
873
|
readonly wrapMessage: ComponentType<MessageWrapperProps> | null;
|
|
862
874
|
readonly wrapConversationRow: ComponentType<ConversationRowWrapperProps> | null;
|
|
863
875
|
}
|
|
@@ -889,6 +901,8 @@ interface MessagingProviderProps {
|
|
|
889
901
|
onOpenReference?: ((reference: MatrxReference) => void) | undefined;
|
|
890
902
|
/** Draw references with the app's own renderer instead of the package card. */
|
|
891
903
|
renderReference?: ReferenceRenderer | undefined;
|
|
904
|
+
/** Draw ```matrx fences with the app's own renderer — every fence, parsed or not. */
|
|
905
|
+
renderFence?: FenceRenderer | undefined;
|
|
892
906
|
/** App chrome (a right-click menu, a drop target) around each message bubble. */
|
|
893
907
|
wrapMessage?: ComponentType<MessageWrapperProps> | undefined;
|
|
894
908
|
/** App chrome around each conversation row. */
|
|
@@ -1077,11 +1091,6 @@ declare function Avatar(props: {
|
|
|
1077
1091
|
declare function DeliveryTick(props: {
|
|
1078
1092
|
state: DeliveryState;
|
|
1079
1093
|
}): React.ReactElement | null;
|
|
1080
|
-
/**
|
|
1081
|
-
* A reference card. NO DEAD ENDS: when the host wired `onOpenReference` it is a
|
|
1082
|
-
* button that opens; when it did not, it renders as a labeled, non-interactive
|
|
1083
|
-
* card with a title explaining why — never a button that does nothing.
|
|
1084
|
-
*/
|
|
1085
1094
|
declare function ReferenceCard(props: {
|
|
1086
1095
|
reference: MatrxReference;
|
|
1087
1096
|
onOpen?: ((reference: MatrxReference) => void) | null;
|
|
@@ -1363,6 +1372,20 @@ type TextSegment = {
|
|
|
1363
1372
|
} | {
|
|
1364
1373
|
readonly type: "reference";
|
|
1365
1374
|
readonly reference: MatrxReference;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* A ```matrx fence this package could not resolve into references.
|
|
1378
|
+
*
|
|
1379
|
+
* It is NOT dropped. Platforms carry richer fence dialects than this
|
|
1380
|
+
* package's own array shape — Matrx's is a `__kind` directive shell whose
|
|
1381
|
+
* items are typed per noun, resolvable only by the app's kind registry — and
|
|
1382
|
+
* a fence silently deleted on render is a message that lost a paragraph
|
|
1383
|
+
* between the sender and the reader. The host draws it (`renderFence`), or
|
|
1384
|
+
* the package draws an honest inert card. Never a code block of JSON.
|
|
1385
|
+
*/
|
|
1386
|
+
| {
|
|
1387
|
+
readonly type: "fence";
|
|
1388
|
+
readonly body: string;
|
|
1366
1389
|
};
|
|
1367
1390
|
/** Every reference a message carries, from both transports, de-duplicated. */
|
|
1368
1391
|
declare function extractReferences(content: string, structured?: readonly MatrxReference[]): readonly MatrxReference[];
|
package/dist/react.d.ts
CHANGED
|
@@ -828,6 +828,17 @@ interface MessageActionRenderer<TPayload = unknown> {
|
|
|
828
828
|
type ReferenceRenderer = ComponentType<{
|
|
829
829
|
reference: MatrxReference;
|
|
830
830
|
}>;
|
|
831
|
+
/**
|
|
832
|
+
* A host's renderer for a raw ```matrx fence — the body between the backticks.
|
|
833
|
+
*
|
|
834
|
+
* This package understands one fence dialect: its own. A platform's fences are
|
|
835
|
+
* its platform's business (Matrx's are `__kind` directive shells resolved
|
|
836
|
+
* through a kind registry), and only the app can draw them. Give us this and
|
|
837
|
+
* EVERY fence in a message goes to you, parsed or not.
|
|
838
|
+
*/
|
|
839
|
+
type FenceRenderer = ComponentType<{
|
|
840
|
+
body: string;
|
|
841
|
+
}>;
|
|
831
842
|
/**
|
|
832
843
|
* App chrome wrapped around ONE message bubble or ONE conversation row.
|
|
833
844
|
*
|
|
@@ -858,6 +869,7 @@ interface MessagingHost {
|
|
|
858
869
|
/** Host surfaces for action kinds whose answer is a card, not a chip. */
|
|
859
870
|
readonly actionRenderers: ReadonlyMap<string, MessageActionRenderer>;
|
|
860
871
|
readonly renderReference: ReferenceRenderer | null;
|
|
872
|
+
readonly renderFence: FenceRenderer | null;
|
|
861
873
|
readonly wrapMessage: ComponentType<MessageWrapperProps> | null;
|
|
862
874
|
readonly wrapConversationRow: ComponentType<ConversationRowWrapperProps> | null;
|
|
863
875
|
}
|
|
@@ -889,6 +901,8 @@ interface MessagingProviderProps {
|
|
|
889
901
|
onOpenReference?: ((reference: MatrxReference) => void) | undefined;
|
|
890
902
|
/** Draw references with the app's own renderer instead of the package card. */
|
|
891
903
|
renderReference?: ReferenceRenderer | undefined;
|
|
904
|
+
/** Draw ```matrx fences with the app's own renderer — every fence, parsed or not. */
|
|
905
|
+
renderFence?: FenceRenderer | undefined;
|
|
892
906
|
/** App chrome (a right-click menu, a drop target) around each message bubble. */
|
|
893
907
|
wrapMessage?: ComponentType<MessageWrapperProps> | undefined;
|
|
894
908
|
/** App chrome around each conversation row. */
|
|
@@ -1077,11 +1091,6 @@ declare function Avatar(props: {
|
|
|
1077
1091
|
declare function DeliveryTick(props: {
|
|
1078
1092
|
state: DeliveryState;
|
|
1079
1093
|
}): React.ReactElement | null;
|
|
1080
|
-
/**
|
|
1081
|
-
* A reference card. NO DEAD ENDS: when the host wired `onOpenReference` it is a
|
|
1082
|
-
* button that opens; when it did not, it renders as a labeled, non-interactive
|
|
1083
|
-
* card with a title explaining why — never a button that does nothing.
|
|
1084
|
-
*/
|
|
1085
1094
|
declare function ReferenceCard(props: {
|
|
1086
1095
|
reference: MatrxReference;
|
|
1087
1096
|
onOpen?: ((reference: MatrxReference) => void) | null;
|
|
@@ -1363,6 +1372,20 @@ type TextSegment = {
|
|
|
1363
1372
|
} | {
|
|
1364
1373
|
readonly type: "reference";
|
|
1365
1374
|
readonly reference: MatrxReference;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* A ```matrx fence this package could not resolve into references.
|
|
1378
|
+
*
|
|
1379
|
+
* It is NOT dropped. Platforms carry richer fence dialects than this
|
|
1380
|
+
* package's own array shape — Matrx's is a `__kind` directive shell whose
|
|
1381
|
+
* items are typed per noun, resolvable only by the app's kind registry — and
|
|
1382
|
+
* a fence silently deleted on render is a message that lost a paragraph
|
|
1383
|
+
* between the sender and the reader. The host draws it (`renderFence`), or
|
|
1384
|
+
* the package draws an honest inert card. Never a code block of JSON.
|
|
1385
|
+
*/
|
|
1386
|
+
| {
|
|
1387
|
+
readonly type: "fence";
|
|
1388
|
+
readonly body: string;
|
|
1366
1389
|
};
|
|
1367
1390
|
/** Every reference a message carries, from both transports, de-duplicated. */
|
|
1368
1391
|
declare function extractReferences(content: string, structured?: readonly MatrxReference[]): readonly MatrxReference[];
|
package/dist/react.js
CHANGED
|
@@ -222,21 +222,32 @@ function splitText(content) {
|
|
|
222
222
|
if (start > cursor) {
|
|
223
223
|
segments.push({ type: "text", value: content.slice(cursor, start) });
|
|
224
224
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
const body = match[1] ?? "";
|
|
226
|
+
const references = parseFenceBody(body);
|
|
227
|
+
if (references.length === 0) {
|
|
228
|
+
segments.push({ type: "fence", body });
|
|
229
|
+
} else {
|
|
230
|
+
references.forEach((reference) => {
|
|
231
|
+
segments.push({ type: "reference", reference });
|
|
232
|
+
});
|
|
233
|
+
}
|
|
228
234
|
cursor = start + match[0].length;
|
|
229
235
|
}
|
|
230
236
|
if (cursor < content.length) {
|
|
231
237
|
segments.push({ type: "text", value: content.slice(cursor) });
|
|
232
238
|
}
|
|
233
239
|
return segments.filter(
|
|
234
|
-
(segment) => segment.type
|
|
240
|
+
(segment) => segment.type !== "text" || segment.value.trim().length > 0
|
|
235
241
|
);
|
|
236
242
|
}
|
|
237
243
|
function summarizeText(content, maxLength = 140) {
|
|
238
244
|
const parts = splitText(content).map(
|
|
239
|
-
(segment) => segment.type === "text" ? segment.value : segment.reference.label
|
|
245
|
+
(segment) => segment.type === "text" ? segment.value : segment.type === "reference" ? segment.reference.label : (
|
|
246
|
+
// A fence we cannot read still SAYS something. Collapsing it to
|
|
247
|
+
// nothing is how a reference-only message becomes an inbox row that
|
|
248
|
+
// reads "No messages yet" — a screen telling a lie.
|
|
249
|
+
"Reference"
|
|
250
|
+
)
|
|
240
251
|
);
|
|
241
252
|
const flattened = parts.join(" ").replace(/\s+/g, " ").trim();
|
|
242
253
|
if (flattened.length <= maxLength) return flattened;
|
|
@@ -1794,6 +1805,7 @@ function MessagingRuntime(props) {
|
|
|
1794
1805
|
return map;
|
|
1795
1806
|
}, [renderers]);
|
|
1796
1807
|
const renderReference = props.renderReference ?? null;
|
|
1808
|
+
const renderFence = props.renderFence ?? null;
|
|
1797
1809
|
const wrapMessage = props.wrapMessage ?? null;
|
|
1798
1810
|
const wrapConversationRow = props.wrapConversationRow ?? null;
|
|
1799
1811
|
const host = useMemo(() => {
|
|
@@ -1806,10 +1818,20 @@ function MessagingRuntime(props) {
|
|
|
1806
1818
|
openReference: referenceRef.current ?? null,
|
|
1807
1819
|
actionRenderers: rendererMap,
|
|
1808
1820
|
renderReference,
|
|
1821
|
+
renderFence,
|
|
1809
1822
|
wrapMessage,
|
|
1810
1823
|
wrapConversationRow
|
|
1811
1824
|
};
|
|
1812
|
-
}, [
|
|
1825
|
+
}, [
|
|
1826
|
+
engine,
|
|
1827
|
+
actionRegistry,
|
|
1828
|
+
ai,
|
|
1829
|
+
rendererMap,
|
|
1830
|
+
renderReference,
|
|
1831
|
+
renderFence,
|
|
1832
|
+
wrapMessage,
|
|
1833
|
+
wrapConversationRow
|
|
1834
|
+
]);
|
|
1813
1835
|
const MessagingContext = messagingContext();
|
|
1814
1836
|
return /* @__PURE__ */ jsx(MessagingContext.Provider, { value: host, children });
|
|
1815
1837
|
}
|
|
@@ -2400,6 +2422,20 @@ function DeliveryTick(props) {
|
|
|
2400
2422
|
return null;
|
|
2401
2423
|
}
|
|
2402
2424
|
}
|
|
2425
|
+
function UnreadableReference() {
|
|
2426
|
+
return /* @__PURE__ */ jsxs(
|
|
2427
|
+
"span",
|
|
2428
|
+
{
|
|
2429
|
+
className: "mx-msg__reference mx-msg__reference--inert",
|
|
2430
|
+
title: "This message names something in a reference format this app has not wired. Pass renderFence to <MessagingProvider> to render it.",
|
|
2431
|
+
children: [
|
|
2432
|
+
/* @__PURE__ */ jsx3(LinkIcon, {}),
|
|
2433
|
+
/* @__PURE__ */ jsx3("span", { className: "mx-msg__reference-type", children: "reference" }),
|
|
2434
|
+
"Reference"
|
|
2435
|
+
]
|
|
2436
|
+
}
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2403
2439
|
function ReferenceCard(props) {
|
|
2404
2440
|
const { reference, onOpen } = props;
|
|
2405
2441
|
const href = reference.href;
|
|
@@ -2764,6 +2800,7 @@ function MessageBubble(props) {
|
|
|
2764
2800
|
const { message, isMine } = props;
|
|
2765
2801
|
const host = useMessagingHost();
|
|
2766
2802
|
const HostReference = host?.renderReference ?? null;
|
|
2803
|
+
const HostFence = host?.renderFence ?? null;
|
|
2767
2804
|
const MessageChrome = host?.wrapMessage ?? null;
|
|
2768
2805
|
if (message.deletedAt !== null) {
|
|
2769
2806
|
return /* @__PURE__ */ jsx4("div", { className: "mx-msg__bubble mx-msg__bubble--deleted", children: "Message deleted" });
|
|
@@ -2778,7 +2815,7 @@ function MessageBubble(props) {
|
|
|
2778
2815
|
const bubble = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2779
2816
|
/* @__PURE__ */ jsxs2("div", { className: classes, children: [
|
|
2780
2817
|
splitText(message.content).map(
|
|
2781
|
-
(segment, index) => segment.type === "text" ? /* @__PURE__ */ jsx4("span", { children: segment.value }, index) : HostReference !== null ? /* @__PURE__ */ jsx4(
|
|
2818
|
+
(segment, index) => segment.type === "text" ? /* @__PURE__ */ jsx4("span", { children: segment.value }, index) : segment.type === "fence" ? HostFence !== null ? /* @__PURE__ */ jsx4(HostFence, { body: segment.body }, `fence:${index}`) : /* @__PURE__ */ jsx4(UnreadableReference, {}, `fence:${index}`) : HostReference !== null ? /* @__PURE__ */ jsx4(
|
|
2782
2819
|
HostReference,
|
|
2783
2820
|
{
|
|
2784
2821
|
reference: segment.reference
|