@ai-matrx/messaging 0.14.0 → 0.15.1
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 +47 -0
- package/dist/index.cjs +47 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +47 -6
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +104 -11
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +37 -1
- package/dist/react.d.ts +37 -1
- package/dist/react.js +104 -11
- package/dist/react.js.map +1 -1
- package/package.json +2 -1
package/dist/react.cjs
CHANGED
|
@@ -75,6 +75,7 @@ __export(react_exports, {
|
|
|
75
75
|
asOrganizationId: () => asOrganizationId,
|
|
76
76
|
asUserId: () => asUserId,
|
|
77
77
|
composeFence: () => composeFence,
|
|
78
|
+
conversationContextVariables: () => conversationContextVariables,
|
|
78
79
|
conversationTopic: () => conversationTopic,
|
|
79
80
|
createActionRegistry: () => createActionRegistry,
|
|
80
81
|
createMemoryOutboxStorage: () => createMemoryOutboxStorage,
|
|
@@ -379,6 +380,20 @@ ${JSON.stringify(references, null, 2)}
|
|
|
379
380
|
}
|
|
380
381
|
|
|
381
382
|
// src/core/ai.ts
|
|
383
|
+
function conversationContextVariables(context, loadedMessageCount) {
|
|
384
|
+
const values = {
|
|
385
|
+
total_loaded_message_count: loadedMessageCount
|
|
386
|
+
};
|
|
387
|
+
if (context === void 0) return values;
|
|
388
|
+
if (context.conversationType) values.conversation_type = context.conversationType;
|
|
389
|
+
if (context.conversationName) values.conversation_name = context.conversationName;
|
|
390
|
+
if (context.conversationCreatedAt)
|
|
391
|
+
values.conversation_created_at = context.conversationCreatedAt;
|
|
392
|
+
if (typeof context.unreadCount === "number") values.unread_count = context.unreadCount;
|
|
393
|
+
if (typeof context.isMuted === "boolean") values.is_muted = context.isMuted;
|
|
394
|
+
if (context.readerUserId) values.reader_user_id = context.readerUserId;
|
|
395
|
+
return values;
|
|
396
|
+
}
|
|
382
397
|
function unreadCutoff(messages, unreadCount) {
|
|
383
398
|
if (unreadCount <= 0) return null;
|
|
384
399
|
const index = messages.length - unreadCount - 1;
|
|
@@ -468,7 +483,8 @@ function createMessagingAi(options) {
|
|
|
468
483
|
transcript_message_count: transcript.length,
|
|
469
484
|
// Honest about the cut, so an agent can say "showing the last 200".
|
|
470
485
|
transcript_truncated: args.messages.length > transcript.length,
|
|
471
|
-
...args.since != null ? { unread_since: args.since } : {}
|
|
486
|
+
...args.since != null ? { unread_since: args.since } : {},
|
|
487
|
+
...conversationContextVariables(args.context, args.messages.length)
|
|
472
488
|
};
|
|
473
489
|
}
|
|
474
490
|
function configured(capability) {
|
|
@@ -983,6 +999,7 @@ function createMessagingStore() {
|
|
|
983
999
|
let threads = /* @__PURE__ */ new Map();
|
|
984
1000
|
let activeConversationId = null;
|
|
985
1001
|
let conversationReadFailures = /* @__PURE__ */ new Map();
|
|
1002
|
+
let conversationsLoadError = null;
|
|
986
1003
|
const listeners = /* @__PURE__ */ new Set();
|
|
987
1004
|
let cached = null;
|
|
988
1005
|
function snapshot() {
|
|
@@ -996,7 +1013,8 @@ function createMessagingStore() {
|
|
|
996
1013
|
totalUnreadConversations: conversations.filter((item) => item.unreadCount > 0).length,
|
|
997
1014
|
archiveFilter,
|
|
998
1015
|
archivedCount,
|
|
999
|
-
conversationReadFailures
|
|
1016
|
+
conversationReadFailures,
|
|
1017
|
+
conversationsLoadError
|
|
1000
1018
|
};
|
|
1001
1019
|
return cached;
|
|
1002
1020
|
}
|
|
@@ -1041,6 +1059,12 @@ function createMessagingStore() {
|
|
|
1041
1059
|
conversations = normalizeConversations(items);
|
|
1042
1060
|
hasMoreConversations = hasMore;
|
|
1043
1061
|
hasLoadedConversations = true;
|
|
1062
|
+
conversationsLoadError = null;
|
|
1063
|
+
emit();
|
|
1064
|
+
},
|
|
1065
|
+
setConversationsLoadError(message) {
|
|
1066
|
+
if (message === conversationsLoadError) return;
|
|
1067
|
+
conversationsLoadError = message;
|
|
1044
1068
|
emit();
|
|
1045
1069
|
},
|
|
1046
1070
|
setArchiveFilter(next) {
|
|
@@ -1273,10 +1297,20 @@ function createMessagingEngine(options) {
|
|
|
1273
1297
|
}
|
|
1274
1298
|
async function reloadInbox() {
|
|
1275
1299
|
if (disposed) return;
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1300
|
+
let page;
|
|
1301
|
+
try {
|
|
1302
|
+
page = await repository.listConversations({
|
|
1303
|
+
limit: conversationPageSize,
|
|
1304
|
+
archived: store.snapshot().archiveFilter
|
|
1305
|
+
});
|
|
1306
|
+
} catch (error) {
|
|
1307
|
+
if (!disposed) {
|
|
1308
|
+
store.setConversationsLoadError(
|
|
1309
|
+
error instanceof Error ? error.message : typeof error === "string" ? error : "The conversation list could not be read."
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
throw error;
|
|
1313
|
+
}
|
|
1280
1314
|
if (disposed) return;
|
|
1281
1315
|
conversationCursor = page.nextCursor;
|
|
1282
1316
|
store.setConversations(page.items, page.hasMore);
|
|
@@ -1361,6 +1395,13 @@ function createMessagingEngine(options) {
|
|
|
1361
1395
|
}
|
|
1362
1396
|
});
|
|
1363
1397
|
},
|
|
1398
|
+
async refreshInbox() {
|
|
1399
|
+
try {
|
|
1400
|
+
await reloadInbox();
|
|
1401
|
+
} catch (error) {
|
|
1402
|
+
reportError(error, "inboxRefresh");
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1364
1405
|
async setArchiveFilter(next) {
|
|
1365
1406
|
if (next === store.snapshot().archiveFilter) return;
|
|
1366
1407
|
store.setArchiveFilter(next);
|
|
@@ -2504,7 +2545,11 @@ function useConversations() {
|
|
|
2504
2545
|
hasMore: snapshot?.hasMoreConversations ?? false,
|
|
2505
2546
|
// "Not loaded yet" is a FACT from the store, never a guess. Showing
|
|
2506
2547
|
// "No conversations yet" before the first read is a screen telling a lie.
|
|
2507
|
-
isInitialLoading: snapshot === null || !snapshot.hasLoadedConversations,
|
|
2548
|
+
isInitialLoading: snapshot === null || !snapshot.hasLoadedConversations && snapshot.conversationsLoadError === null,
|
|
2549
|
+
loadError: snapshot?.conversationsLoadError ?? null,
|
|
2550
|
+
retry: () => {
|
|
2551
|
+
void host?.engine.refreshInbox();
|
|
2552
|
+
},
|
|
2508
2553
|
totalUnreadConversations: snapshot?.totalUnreadConversations ?? 0,
|
|
2509
2554
|
loadMore: () => {
|
|
2510
2555
|
void host?.engine.loadMoreConversations();
|
|
@@ -2709,6 +2754,14 @@ function useMessagingAi(conversationId) {
|
|
|
2709
2754
|
conversationId,
|
|
2710
2755
|
messages: conversation.messages,
|
|
2711
2756
|
participants: conversation.participants,
|
|
2757
|
+
context: {
|
|
2758
|
+
conversationType: conversation.summary?.conversation.type,
|
|
2759
|
+
conversationName: conversation.summary?.displayName,
|
|
2760
|
+
conversationCreatedAt: conversation.summary?.conversation.createdAt,
|
|
2761
|
+
unreadCount: conversation.summary?.unreadCount,
|
|
2762
|
+
isMuted: conversation.summary?.isMuted,
|
|
2763
|
+
readerUserId: host?.identity.userId || void 0
|
|
2764
|
+
},
|
|
2712
2765
|
signal: controller.signal,
|
|
2713
2766
|
// Live progress. Aborted runs stop painting immediately — a cancelled
|
|
2714
2767
|
// answer must not keep growing on screen.
|
|
@@ -3086,6 +3139,7 @@ function EmptyState(props) {
|
|
|
3086
3139
|
}
|
|
3087
3140
|
|
|
3088
3141
|
// src/react/components.tsx
|
|
3142
|
+
var import_design_system = require("@ai-matrx/design-system");
|
|
3089
3143
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
3090
3144
|
var AI_LABELS = {
|
|
3091
3145
|
catchUp: "Catch me up",
|
|
@@ -3103,7 +3157,9 @@ function ConversationList(props) {
|
|
|
3103
3157
|
activeConversationId,
|
|
3104
3158
|
archiveFilter,
|
|
3105
3159
|
setArchiveFilter,
|
|
3106
|
-
archivedCount
|
|
3160
|
+
archivedCount,
|
|
3161
|
+
loadError,
|
|
3162
|
+
retry
|
|
3107
3163
|
} = useConversations();
|
|
3108
3164
|
const RowChrome = useMessagingHost()?.wrapConversationRow ?? null;
|
|
3109
3165
|
const [query, setQuery] = (0, import_react5.useState)("");
|
|
@@ -3168,7 +3224,20 @@ function ConversationList(props) {
|
|
|
3168
3224
|
}
|
|
3169
3225
|
) }) : null,
|
|
3170
3226
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__scroll", children: [
|
|
3171
|
-
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationSkeleton, {}) : visible.length === 0 ?
|
|
3227
|
+
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConversationSkeleton, {}) : loadError !== null && visible.length === 0 ? (
|
|
3228
|
+
// A failed read resolves to the failure — never a skeleton forever,
|
|
3229
|
+
// never "No conversations yet" (RC-B12 round 11). ErrorBox is the
|
|
3230
|
+
// design-system error slot: the host fills it with its menu.
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3232
|
+
ReadFailureBox,
|
|
3233
|
+
{
|
|
3234
|
+
title: "Couldn't load your conversations",
|
|
3235
|
+
message: loadError,
|
|
3236
|
+
operation: "List your conversations",
|
|
3237
|
+
onRetry: retry
|
|
3238
|
+
}
|
|
3239
|
+
)
|
|
3240
|
+
) : visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3172
3241
|
EmptyState,
|
|
3173
3242
|
{
|
|
3174
3243
|
title: query.length > 0 ? "No matches" : showingArchive ? "No archived conversations" : "No conversations yet",
|
|
@@ -3345,10 +3414,11 @@ function ConversationView(props) {
|
|
|
3345
3414
|
body: "It doesn't exist, or you aren't a member of it."
|
|
3346
3415
|
}
|
|
3347
3416
|
) : conversation.error !== null && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3348
|
-
|
|
3417
|
+
ReadFailureBox,
|
|
3349
3418
|
{
|
|
3350
3419
|
title: "Couldn't load this conversation",
|
|
3351
|
-
|
|
3420
|
+
message: conversation.error.message || "Check your connection, then open it again.",
|
|
3421
|
+
operation: "Open this conversation"
|
|
3352
3422
|
}
|
|
3353
3423
|
) : messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EmptyState, { title: "No messages yet", body: "Say something to get started." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__messages", children: [
|
|
3354
3424
|
conversation.hasMoreOlder ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -3679,4 +3749,27 @@ function MessagingInbox(props) {
|
|
|
3679
3749
|
}
|
|
3680
3750
|
);
|
|
3681
3751
|
}
|
|
3752
|
+
function ReadFailureBox({
|
|
3753
|
+
title,
|
|
3754
|
+
message,
|
|
3755
|
+
operation,
|
|
3756
|
+
onRetry
|
|
3757
|
+
}) {
|
|
3758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__empty", role: "alert", children: [
|
|
3759
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3760
|
+
import_design_system.ErrorBox,
|
|
3761
|
+
{
|
|
3762
|
+
as: "div",
|
|
3763
|
+
title,
|
|
3764
|
+
message,
|
|
3765
|
+
operation,
|
|
3766
|
+
origin: "messaging",
|
|
3767
|
+
style: { color: "var(--mx-msg-danger)", fontWeight: 600 },
|
|
3768
|
+
children: title
|
|
3769
|
+
}
|
|
3770
|
+
),
|
|
3771
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: message }),
|
|
3772
|
+
onRetry ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-msg__button mx-msg__button--ghost", onClick: onRetry, children: "Try again" }) : null
|
|
3773
|
+
] });
|
|
3774
|
+
}
|
|
3682
3775
|
//# sourceMappingURL=react.cjs.map
|