@ai-matrx/messaging 0.10.0 → 0.10.2

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/dist/react.cjs CHANGED
@@ -73,6 +73,7 @@ __export(react_exports, {
73
73
  createOutbox: () => createOutbox,
74
74
  createReadCache: () => createReadCache,
75
75
  createWebOutboxStorage: () => createWebOutboxStorage,
76
+ effectiveActorKey: () => effectiveActorKey,
76
77
  extractReferences: () => extractReferences,
77
78
  formatConversationTime: () => formatConversationTime,
78
79
  formatDateSeparator: () => formatDateSeparator,
@@ -1909,15 +1910,27 @@ function MessagingRuntime(props) {
1909
1910
  const transport = props.transport;
1910
1911
  const agents = props.agents;
1911
1912
  const maxTranscriptMessages = props.maxTranscriptMessages;
1913
+ const sourceApp = props.sourceApp;
1914
+ const sourceFeature = props.sourceFeature;
1912
1915
  const ai = (0, import_react.useMemo)(() => {
1913
1916
  if (transport === void 0 || agents === void 0 || !ready) return null;
1914
1917
  return createMessagingAi({
1915
1918
  transport,
1916
1919
  organizationId,
1917
1920
  agents,
1918
- ...maxTranscriptMessages !== void 0 ? { maxTranscriptMessages } : {}
1921
+ ...maxTranscriptMessages !== void 0 ? { maxTranscriptMessages } : {},
1922
+ ...sourceApp !== void 0 ? { sourceApp } : {},
1923
+ ...sourceFeature !== void 0 ? { sourceFeature } : {}
1919
1924
  });
1920
- }, [transport, agents, ready, organizationId, maxTranscriptMessages]);
1925
+ }, [
1926
+ transport,
1927
+ agents,
1928
+ ready,
1929
+ organizationId,
1930
+ maxTranscriptMessages,
1931
+ sourceApp,
1932
+ sourceFeature
1933
+ ]);
1921
1934
  const renderers = props.actionRenderers;
1922
1935
  const rendererMap = (0, import_react.useMemo)(() => {
1923
1936
  const map = /* @__PURE__ */ new Map();
@@ -2036,18 +2049,20 @@ function groupMessages(messages, args = {}) {
2036
2049
  let current = null;
2037
2050
  let previousDay = null;
2038
2051
  for (const message of messages) {
2052
+ const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
2039
2053
  const day = message.createdAt.slice(0, 10);
2040
2054
  const startsNewDay = day !== previousDay;
2041
2055
  previousDay = day;
2042
2056
  const last = current?.messages.at(-1);
2043
2057
  const withinWindow = last !== void 0 && Math.abs(Date.parse(message.createdAt) - Date.parse(last.createdAt)) <= windowMs;
2044
- if (current !== null && current.senderId === message.senderId && withinWindow && !startsNewDay) {
2058
+ if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
2045
2059
  current.messages.push(message);
2046
2060
  continue;
2047
2061
  }
2048
2062
  if (current !== null) groups.push(current);
2049
2063
  current = {
2050
2064
  senderId: message.senderId,
2065
+ actorKey,
2051
2066
  messages: [message],
2052
2067
  dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
2053
2068
  };
@@ -2369,19 +2384,36 @@ var import_react5 = require("react");
2369
2384
 
2370
2385
  // src/core/actor.ts
2371
2386
  function readActorHint(metadata) {
2372
- const raw = metadata["actor"];
2373
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
2374
- const record = raw;
2375
- const agentId = record["agentId"] ?? record["agent_id"];
2376
- if (typeof agentId !== "string" || agentId.length === 0) return null;
2377
- const name = record["agentName"] ?? record["agent_name"];
2378
- const avatar = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
2387
+ const envelope = metadata;
2388
+ const raw = envelope["actor"];
2389
+ if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
2390
+ const record = raw;
2391
+ const agentId = record["agentId"] ?? record["agent_id"];
2392
+ if (typeof agentId !== "string" || agentId.length === 0) return null;
2393
+ const name2 = record["agentName"] ?? record["agent_name"];
2394
+ const avatar2 = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
2395
+ return {
2396
+ agentId,
2397
+ ...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
2398
+ ...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
2399
+ };
2400
+ }
2401
+ const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
2402
+ if (actorKind !== "agent") return null;
2403
+ const id = envelope["actor_id"] ?? envelope["actorId"];
2404
+ const name = envelope["actor_label"] ?? envelope["actorLabel"];
2405
+ const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
2379
2406
  return {
2380
- agentId,
2407
+ ...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
2381
2408
  ...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
2382
2409
  ...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
2383
2410
  };
2384
2411
  }
2412
+ function effectiveActorKey(message) {
2413
+ const hint = readActorHint(message.metadata);
2414
+ if (hint === null) return `principal:${message.senderId}`;
2415
+ return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
2416
+ }
2385
2417
  function resolveActor(message, sender) {
2386
2418
  const hint = readActorHint(message.metadata);
2387
2419
  const humanName = sender?.displayName ?? message.senderId;
@@ -2777,7 +2809,7 @@ function ConversationView(props) {
2777
2809
  );
2778
2810
  const anyOnline = others.some((participant) => online.has(participant.userId));
2779
2811
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mx-msg__thread${props.className !== void 0 ? ` ${props.className}` : ""}`, children: [
2780
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-msg__header", children: [
2812
+ props.showHeader !== false ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-msg__header", children: [
2781
2813
  props.onBack !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2782
2814
  "button",
2783
2815
  {
@@ -2812,8 +2844,8 @@ function ConversationView(props) {
2812
2844
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UsersIcon, {})
2813
2845
  }
2814
2846
  ) : null })
2815
- ] }),
2816
- ai.available.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2847
+ ] }) : null,
2848
+ props.showAi !== false && ai.available.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2817
2849
  "button",
2818
2850
  {
2819
2851
  type: "button",
@@ -2827,7 +2859,7 @@ function ConversationView(props) {
2827
2859
  },
2828
2860
  capability
2829
2861
  )) }) : null,
2830
- ai.isRunning ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-msg__ai-output", "aria-busy": "true", "aria-live": "polite", children: ai.partialText.length > 0 ? ai.partialText : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2862
+ props.showAi !== false && ai.isRunning ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-msg__ai-output", "aria-busy": "true", "aria-live": "polite", children: ai.partialText.length > 0 ? ai.partialText : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2831
2863
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-msg__ai-output-label", children: ai.activeCapability !== null ? `${AI_LABELS[ai.activeCapability]}\u2026` : "Working\u2026" }),
2832
2864
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2833
2865
  "span",
@@ -2836,7 +2868,7 @@ function ConversationView(props) {
2836
2868
  style: { display: "block", height: 11, width: "72%" }
2837
2869
  }
2838
2870
  )
2839
- ] }) }) : ai.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-msg__ai-output", style: { color: "var(--mx-msg-danger)" }, children: ai.error }) : ai.result !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-msg__ai-output", children: [
2871
+ ] }) }) : props.showAi !== false && ai.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-msg__ai-output", style: { color: "var(--mx-msg-danger)" }, children: ai.error }) : props.showAi !== false && ai.result !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-msg__ai-output", children: [
2840
2872
  ai.result.text,
2841
2873
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2842
2874
  "button",
@@ -2861,26 +2893,24 @@ function ConversationView(props) {
2861
2893
  children: "Load earlier messages"
2862
2894
  }
2863
2895
  ) : null,
2864
- groupMessages(messages).map((group) => {
2896
+ groupMessages(messages, { actorKey: effectiveActorKey }).map((group) => {
2865
2897
  const first = group.messages[0];
2866
2898
  if (first === void 0) return null;
2867
- const isMine = group.senderId === selfId;
2868
2899
  const sender = conversation.participants.find(
2869
2900
  (participant) => participant.userId === group.senderId
2870
2901
  ) ?? null;
2902
+ const actor = resolveActor(first, sender);
2903
+ const isMine = group.senderId === selfId && !actor.isAgent;
2871
2904
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
2872
2905
  group.dateSeparator !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-msg__day", children: group.dateSeparator }) : null,
2873
2906
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2874
2907
  MessageGroupView,
2875
2908
  {
2876
2909
  messages: group.messages,
2877
- sender,
2910
+ actor,
2878
2911
  isMine,
2879
2912
  onRetry: conversation.retry,
2880
2913
  onReply: composer.setReplyTo,
2881
- pendingIds: new Set(
2882
- conversation.pending.filter((entry) => entry.state === "failed").map((entry) => entry.clientMessageId)
2883
- ),
2884
2914
  failedEntryIdByClientId: new Map(
2885
2915
  conversation.pending.map((entry) => [entry.clientMessageId, entry.id])
2886
2916
  )
@@ -2893,13 +2923,20 @@ function ConversationView(props) {
2893
2923
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TypingDots, {}),
2894
2924
  typists.label
2895
2925
  ] }) : null }),
2896
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ComposerView, { composer, disabled: false })
2926
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2927
+ ComposerView,
2928
+ {
2929
+ composer,
2930
+ disabled: false,
2931
+ ...props.renderComposerInput !== void 0 ? { renderInput: props.renderComposerInput } : {}
2932
+ }
2933
+ )
2897
2934
  ] });
2898
2935
  }
2899
2936
  function MessageGroupView(props) {
2900
2937
  const first = props.messages[0];
2901
2938
  if (first === void 0) return null;
2902
- const actor = resolveActor(first, props.sender);
2939
+ const actor = props.actor;
2903
2940
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mx-msg__group${props.isMine ? " mx-msg__group--mine" : ""}`, children: [
2904
2941
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2905
2942
  Avatar,
@@ -3086,7 +3123,24 @@ function ComposerView(props) {
3086
3123
  }
3087
3124
  )
3088
3125
  ] }) : null,
3089
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__composer-row", children: [
3126
+ props.renderInput !== void 0 ? props.renderInput({
3127
+ value: composer.value,
3128
+ disabled: props.disabled,
3129
+ canSend: composer.canSend,
3130
+ placeholder: "Write a reply\u2026",
3131
+ onChange: (value) => {
3132
+ composer.setValue(value);
3133
+ composer.onKeystroke();
3134
+ },
3135
+ onKeyDown: (event) => {
3136
+ if (event.key !== "Enter" || event.shiftKey) return;
3137
+ const isTouch = typeof globalThis.matchMedia === "function" && globalThis.matchMedia("(pointer: coarse)").matches;
3138
+ if (isTouch) return;
3139
+ event.preventDefault();
3140
+ composer.send();
3141
+ },
3142
+ onSubmit: composer.send
3143
+ }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-msg__composer-row", children: [
3090
3144
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3091
3145
  "textarea",
3092
3146
  {