@agentchatme/openclaw 0.7.81 → 0.7.821

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/index.d.cts CHANGED
@@ -359,6 +359,16 @@ interface NormalizedMessage {
359
359
  readonly deliveredAt: string | null;
360
360
  readonly readAt: string | null;
361
361
  readonly receivedAt: UnixMillis;
362
+ /** Sender's resolved display name, or null when unset / no context block. */
363
+ readonly senderDisplayName: string | null;
364
+ /** 'system' = platform agent (weight its words as authoritative); 'agent' = peer. */
365
+ readonly senderKind: 'agent' | 'system';
366
+ /** Group's human-readable name (null for DMs / when the server omitted it). */
367
+ readonly groupName: string | null;
368
+ readonly memberCount: number | null;
369
+ /** Handles @-mentioned, parsed server-side (word-boundary). Test your OWN
370
+ * handle for membership — never substring-match the raw text. */
371
+ readonly mentions: readonly string[];
362
372
  }
363
373
  interface NormalizedReadReceipt {
364
374
  readonly kind: 'read-receipt';
package/dist/index.d.ts CHANGED
@@ -359,6 +359,16 @@ interface NormalizedMessage {
359
359
  readonly deliveredAt: string | null;
360
360
  readonly readAt: string | null;
361
361
  readonly receivedAt: UnixMillis;
362
+ /** Sender's resolved display name, or null when unset / no context block. */
363
+ readonly senderDisplayName: string | null;
364
+ /** 'system' = platform agent (weight its words as authoritative); 'agent' = peer. */
365
+ readonly senderKind: 'agent' | 'system';
366
+ /** Group's human-readable name (null for DMs / when the server omitted it). */
367
+ readonly groupName: string | null;
368
+ readonly memberCount: number | null;
369
+ /** Handles @-mentioned, parsed server-side (word-boundary). Test your OWN
370
+ * handle for membership — never substring-match the raw text. */
371
+ readonly mentions: readonly string[];
362
372
  }
363
373
  interface NormalizedReadReceipt {
364
374
  readonly kind: 'read-receipt';
package/dist/index.js CHANGED
@@ -1523,6 +1523,19 @@ var messageContentSchema = z.object({
1523
1523
  data: z.record(z.string(), z.unknown()).optional(),
1524
1524
  attachment_id: z.string().optional()
1525
1525
  }).passthrough();
1526
+ var messageContextSchema = z.object({
1527
+ sender: z.object({
1528
+ handle: z.string(),
1529
+ display_name: z.string().nullable().optional(),
1530
+ kind: z.enum(["agent", "system"]).optional()
1531
+ }).passthrough().optional(),
1532
+ conversation: z.object({
1533
+ type: z.enum(["direct", "group"]).optional(),
1534
+ group_name: z.string().nullable().optional(),
1535
+ member_count: z.number().int().nullable().optional()
1536
+ }).passthrough().optional(),
1537
+ mentions: z.array(z.string()).optional()
1538
+ }).passthrough();
1526
1539
  var messageSchema = z.object({
1527
1540
  id: z.string(),
1528
1541
  conversation_id: z.string(),
@@ -1532,6 +1545,7 @@ var messageSchema = z.object({
1532
1545
  type: z.enum(["text", "structured", "file", "system"]),
1533
1546
  content: messageContentSchema,
1534
1547
  metadata: z.record(z.string(), z.unknown()).default({}),
1548
+ context: messageContextSchema.optional(),
1535
1549
  // Per-recipient delivery state lives in `message_deliveries` since
1536
1550
  // migration 011 — the `messages` row no longer carries `status`,
1537
1551
  // `delivered_at`, or `read_at`. Fresh-send envelopes over WS omit
@@ -1653,7 +1667,12 @@ function normalizeMessageNew(frame) {
1653
1667
  createdAt: msg.created_at,
1654
1668
  deliveredAt: msg.delivered_at ?? null,
1655
1669
  readAt: msg.read_at ?? null,
1656
- receivedAt: frame.receivedAt
1670
+ receivedAt: frame.receivedAt,
1671
+ senderDisplayName: msg.context?.sender?.display_name ?? null,
1672
+ senderKind: msg.context?.sender?.kind === "system" ? "system" : "agent",
1673
+ groupName: msg.context?.conversation?.group_name ?? null,
1674
+ memberCount: msg.context?.conversation?.member_count ?? null,
1675
+ mentions: (msg.context?.mentions ?? []).map((m) => m.toLowerCase())
1657
1676
  };
1658
1677
  }
1659
1678
  function normalizeMessageRead(frame) {
@@ -1860,7 +1879,7 @@ var CircuitBreaker = class {
1860
1879
  };
1861
1880
 
1862
1881
  // src/version.ts
1863
- var PACKAGE_VERSION = "0.7.81";
1882
+ var PACKAGE_VERSION = "0.7.821";
1864
1883
 
1865
1884
  // src/outbound.ts
1866
1885
  var DEFAULT_RETRY_POLICY = {
@@ -2634,10 +2653,14 @@ function buildDecisionMessages(params) {
2634
2653
  }
2635
2654
  ];
2636
2655
  }
2637
- function buildUserContent(params) {
2638
- const { handle, event, history, signals, maxHistory } = params;
2639
- const kind = event.conversationKind === "group" ? "group" : "direct";
2640
- const lines = [`Conversation type: ${kind}`];
2656
+ function formatReceivedAt(ms) {
2657
+ if (!Number.isFinite(ms)) return "an unknown time";
2658
+ const iso = new Date(ms).toISOString();
2659
+ return `${iso.slice(0, 10)} ${iso.slice(11, 16)} UTC`;
2660
+ }
2661
+ function formatConversationContext(params) {
2662
+ const { handle, event, signals, priorCount } = params;
2663
+ const lines = [`Conversation type: ${formatConversationLabel(event)}`];
2641
2664
  if (signals) {
2642
2665
  lines.push(`Relationship: ${relationshipPhrase(signals)}`);
2643
2666
  if (signals.secondsSincePrevious !== null) {
@@ -2646,13 +2669,28 @@ function buildUserContent(params) {
2646
2669
  );
2647
2670
  }
2648
2671
  }
2649
- lines.push(`Prior messages in this thread: ${history.length}`);
2650
- if (kind === "group") {
2651
- const mentioned = (event.contentText || "").toLowerCase().includes(`@${handle.toLowerCase()}`);
2652
- lines.push(
2653
- `Message directly addresses you: ${mentioned ? "yes" : "not explicitly"}`
2654
- );
2672
+ lines.push(`Prior messages in this thread: ${priorCount}`);
2673
+ if (event.conversationKind === "group" && handle && (event.mentions ?? []).includes(handle.toLowerCase())) {
2674
+ lines.push("You were @-mentioned in this message.");
2675
+ }
2676
+ return lines;
2677
+ }
2678
+ function formatConversationLabel(event) {
2679
+ if (event.conversationKind !== "group") return "direct";
2680
+ let label = event.groupName ? `group "${event.groupName}"` : "group";
2681
+ if (event.memberCount != null) {
2682
+ label += ` (${event.memberCount} member${event.memberCount === 1 ? "" : "s"})`;
2655
2683
  }
2684
+ return label;
2685
+ }
2686
+ function buildUserContent(params) {
2687
+ const { handle, event, history, signals, maxHistory } = params;
2688
+ const lines = formatConversationContext({
2689
+ handle,
2690
+ event,
2691
+ signals,
2692
+ priorCount: history.length
2693
+ });
2656
2694
  lines.push("");
2657
2695
  const rendered = renderHistory(history, maxHistory);
2658
2696
  if (rendered.length > 0) {
@@ -2942,8 +2980,9 @@ async function handleMessage(deps, event) {
2942
2980
  peer,
2943
2981
  runtime
2944
2982
  });
2983
+ let gateContext = null;
2945
2984
  if (gateEnabled()) {
2946
- const decision = await runReplyGate({
2985
+ const { decision, context } = await runReplyGate({
2947
2986
  deps,
2948
2987
  event,
2949
2988
  body,
@@ -2965,17 +3004,40 @@ async function handleMessage(deps, event) {
2965
3004
  "reply gate decision"
2966
3005
  );
2967
3006
  if (!decision.reply) return;
3007
+ gateContext = context;
3008
+ }
3009
+ const contextHeader = [formatSenderLine(event), `Received: ${formatReceivedAt(ts)}`];
3010
+ if (gateContext) {
3011
+ contextHeader.push(...gateContext);
3012
+ } else {
3013
+ contextHeader.push(
3014
+ `Conversation type: ${formatConversationLabel({
3015
+ conversationKind: event.conversationKind,
3016
+ senderHandle,
3017
+ contentText: body,
3018
+ groupName: event.groupName,
3019
+ memberCount: event.memberCount,
3020
+ mentions: event.mentions
3021
+ })}`
3022
+ );
3023
+ const self = (selfHandle ?? "").replace(/^@/, "").toLowerCase();
3024
+ if (event.conversationKind === "group" && self && event.mentions.includes(self)) {
3025
+ contextHeader.push("You were @-mentioned in this message.");
3026
+ }
2968
3027
  }
3028
+ const agentBody = `${contextHeader.join("\n")}
3029
+
3030
+ ${body}`;
2969
3031
  const { storePath, body: envelopeBody } = buildEnvelope({
2970
3032
  channel: "AgentChat",
2971
3033
  from: conversationLabel,
2972
- body,
3034
+ body: agentBody,
2973
3035
  timestamp: ts
2974
3036
  });
2975
3037
  const finalize = channelRuntime.reply.finalizeInboundContext;
2976
3038
  const ctxPayload = finalize({
2977
3039
  Body: envelopeBody,
2978
- BodyForAgent: body,
3040
+ BodyForAgent: agentBody,
2979
3041
  RawBody: body,
2980
3042
  CommandBody: body,
2981
3043
  From: `@${senderHandle}`,
@@ -3042,6 +3104,10 @@ async function handleMessage(deps, event) {
3042
3104
  );
3043
3105
  }
3044
3106
  }
3107
+ function formatSenderLine(event) {
3108
+ const who = event.senderDisplayName ? `${event.senderDisplayName} (@${event.sender})` : `@${event.sender}`;
3109
+ return `From: ${event.senderKind === "system" ? `${who}, a system agent` : who}`;
3110
+ }
3045
3111
  async function runReplyGate(params) {
3046
3112
  const { deps, event, body, agentId, selfHandle, senderHandle, nowMs } = params;
3047
3113
  const ownHandle = selfHandle ?? "";
@@ -3056,17 +3122,22 @@ async function runReplyGate(params) {
3056
3122
  "reply gate: history fetch failed \u2014 deciding on the new message alone"
3057
3123
  );
3058
3124
  }
3125
+ const bareHandle = ownHandle.replace(/^@/, "");
3059
3126
  const gateEvent = {
3060
3127
  conversationKind: event.conversationKind,
3061
3128
  senderHandle,
3062
- contentText: body
3129
+ contentText: body,
3130
+ groupName: event.groupName,
3131
+ memberCount: event.memberCount,
3132
+ mentions: event.mentions
3063
3133
  };
3064
- return decideReply({
3134
+ const history = translateHistory(rawMessages, ownHandle, event.conversationKind, event.messageId);
3135
+ const decision = await decideReply({
3065
3136
  cfg: deps.gatewayCfg,
3066
3137
  agentId,
3067
- handle: ownHandle.replace(/^@/, ""),
3138
+ handle: bareHandle,
3068
3139
  event: gateEvent,
3069
- history: translateHistory(rawMessages, ownHandle, event.conversationKind, event.messageId),
3140
+ history,
3070
3141
  rawMessages,
3071
3142
  triggerMessageId: event.messageId,
3072
3143
  ownHandle,
@@ -3075,6 +3146,18 @@ async function runReplyGate(params) {
3075
3146
  timeoutMs: gateTimeoutMs(),
3076
3147
  caller: deps.gateCaller
3077
3148
  });
3149
+ const signals = computeConversationSignals(rawMessages, {
3150
+ ownHandle,
3151
+ triggerMessageId: event.messageId,
3152
+ nowMs
3153
+ });
3154
+ const context = formatConversationContext({
3155
+ handle: bareHandle,
3156
+ event: gateEvent,
3157
+ signals,
3158
+ priorCount: history.length
3159
+ });
3160
+ return { decision, context };
3078
3161
  }
3079
3162
  function translateHistory(messages, ownHandle, conversationKind, triggerMessageId) {
3080
3163
  const own = ownHandle.replace(/^@/, "").toLowerCase();
@@ -4775,75 +4858,77 @@ function profileToEntry(agent) {
4775
4858
  ...agent.avatar_url ? { avatarUrl: agent.avatar_url } : {}
4776
4859
  };
4777
4860
  }
4778
- var agentchatDirectoryAdapter = {
4779
- async self({ cfg, accountId }) {
4780
- const config = resolveAccount(cfg, accountId);
4781
- if (!config) return null;
4782
- const client = getClient({ accountId: accountId ?? "default", config });
4783
- try {
4784
- const me = await client.getMe();
4785
- return profileToEntry(me);
4786
- } catch {
4787
- return null;
4788
- }
4789
- },
4790
- async listPeers({ cfg, accountId, query, limit }) {
4791
- const config = resolveAccount(cfg, accountId);
4792
- if (!config) return [];
4793
- const q = (query ?? "").trim();
4794
- if (q.length < 2) return [];
4795
- const client = getClient({ accountId: accountId ?? "default", config });
4796
- try {
4797
- const result = await client.searchAgents(q, { limit: limit ?? 20 });
4798
- return result.agents.map(profileToEntry);
4799
- } catch {
4800
- return [];
4801
- }
4802
- },
4803
- async listPeersLive(params) {
4804
- return this.listPeers(params);
4805
- },
4806
- async listGroups({ cfg, accountId, query, limit }) {
4807
- const config = resolveAccount(cfg, accountId);
4808
- if (!config) return [];
4809
- const client = getClient({ accountId: accountId ?? "default", config });
4810
- try {
4811
- const convs = await client.listConversations();
4812
- const q = (query ?? "").trim().toLowerCase();
4813
- const groupRows = convs.filter((c) => c.type === "group");
4814
- const filtered = q ? groupRows.filter((c) => (c.group_name ?? "").toLowerCase().includes(q)) : groupRows;
4815
- const cap = limit ?? 50;
4816
- return filtered.slice(0, cap).map((c) => ({
4817
- kind: "group",
4818
- id: c.id,
4819
- name: c.group_name ?? "Untitled group",
4820
- ...c.group_avatar_url ? { avatarUrl: c.group_avatar_url } : {}
4821
- }));
4822
- } catch {
4823
- return [];
4824
- }
4825
- },
4826
- async listGroupsLive(params) {
4827
- return this.listGroups(params);
4828
- },
4829
- async listGroupMembers({ cfg, accountId, groupId, limit }) {
4830
- const config = resolveAccount(cfg, accountId);
4831
- if (!config) return [];
4832
- const client = getClient({ accountId: accountId ?? "default", config });
4833
- try {
4834
- const group = await client.getGroup(groupId);
4835
- const cap = limit ?? 256;
4836
- return group.members.slice(0, cap).map((m) => ({
4837
- kind: "user",
4838
- id: m.handle,
4839
- handle: m.handle,
4840
- name: m.display_name ?? m.handle
4841
- }));
4842
- } catch {
4843
- return [];
4844
- }
4861
+ var directorySelf = async ({ cfg, accountId }) => {
4862
+ const config = resolveAccount(cfg, accountId);
4863
+ if (!config) return null;
4864
+ const client = getClient({ accountId: accountId ?? "default", config });
4865
+ try {
4866
+ const me = await client.getMe();
4867
+ return profileToEntry(me);
4868
+ } catch {
4869
+ return null;
4845
4870
  }
4846
4871
  };
4872
+ var listPeers = async ({ cfg, accountId, query, limit }) => {
4873
+ const config = resolveAccount(cfg, accountId);
4874
+ if (!config) return [];
4875
+ const q = (query ?? "").trim();
4876
+ if (q.length < 2) return [];
4877
+ const client = getClient({ accountId: accountId ?? "default", config });
4878
+ try {
4879
+ const result = await client.searchAgents(q, { limit: limit ?? 20 });
4880
+ return result.agents.map(profileToEntry);
4881
+ } catch {
4882
+ return [];
4883
+ }
4884
+ };
4885
+ var listGroups = async ({ cfg, accountId, query, limit }) => {
4886
+ const config = resolveAccount(cfg, accountId);
4887
+ if (!config) return [];
4888
+ const client = getClient({ accountId: accountId ?? "default", config });
4889
+ try {
4890
+ const convs = await client.listConversations();
4891
+ const q = (query ?? "").trim().toLowerCase();
4892
+ const groupRows = convs.filter((c) => c.type === "group");
4893
+ const filtered = q ? groupRows.filter((c) => (c.group_name ?? "").toLowerCase().includes(q)) : groupRows;
4894
+ const cap = limit ?? 50;
4895
+ return filtered.slice(0, cap).map((c) => ({
4896
+ kind: "group",
4897
+ id: c.id,
4898
+ name: c.group_name ?? "Untitled group",
4899
+ ...c.group_avatar_url ? { avatarUrl: c.group_avatar_url } : {}
4900
+ }));
4901
+ } catch {
4902
+ return [];
4903
+ }
4904
+ };
4905
+ var listGroupMembers = async ({ cfg, accountId, groupId, limit }) => {
4906
+ const config = resolveAccount(cfg, accountId);
4907
+ if (!config) return [];
4908
+ const client = getClient({ accountId: accountId ?? "default", config });
4909
+ try {
4910
+ const group = await client.getGroup(groupId);
4911
+ const cap = limit ?? 256;
4912
+ return group.members.slice(0, cap).map((m) => ({
4913
+ kind: "user",
4914
+ id: m.handle,
4915
+ handle: m.handle,
4916
+ name: m.display_name ?? m.handle
4917
+ }));
4918
+ } catch {
4919
+ return [];
4920
+ }
4921
+ };
4922
+ var agentchatDirectoryAdapter = {
4923
+ self: directorySelf,
4924
+ listPeers,
4925
+ // `*Live` are literal aliases of the base impls — never `this.listPeers!`,
4926
+ // which breaks when the runtime forwards the method detached.
4927
+ listPeersLive: listPeers,
4928
+ listGroups,
4929
+ listGroupsLive: listGroups,
4930
+ listGroupMembers
4931
+ };
4847
4932
 
4848
4933
  // src/binding/resolver.ts
4849
4934
  function resolveAccount2(cfg, accountId) {