@clawling/clawchat-plugin-openclaw 2026.7.15-1 → 2026.7.21-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.
@@ -391,6 +391,10 @@ export function createOpenclawClawlingApiClient(opts) {
391
391
  async getConversation(conversationId) {
392
392
  return await call("GET", `/v1/conversations/${encodeURIComponent(conversationId)}`);
393
393
  },
394
+ async leaveConversation(conversationId) {
395
+ assertNonBlankId(conversationId, "leaveConversation: conversationId");
396
+ return await call("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/leave`);
397
+ },
394
398
  async patchConversation(conversationId, patch) {
395
399
  assertNonBlankId(conversationId, "patchConversation: conversationId");
396
400
  const body = pickPatch(patch, ["title", "description"], "patchConversation");
@@ -284,7 +284,15 @@ export function createOpenclawClawlingReplyDispatcher(options) {
284
284
  log?.info?.(`[${account.accountId}] clawchat-plugin-openclaw outbound media skipped: baseUrl not configured`);
285
285
  return [];
286
286
  }
287
- return await uploadOutboundMedia(urls, { apiClient, runtime, log });
287
+ const fragments = await uploadOutboundMedia(urls, { apiClient, runtime, log });
288
+ if (fragments.length < urls.length) {
289
+ // uploadOutboundMedia drops a failed item with only a log line. A shortfall
290
+ // means an attachment never reached the media service; surfacing it (parity
291
+ // with the adapter path in outbound.ts and with the Hermes plugin) stops a
292
+ // text-only frame from going out and reading as a successful send.
293
+ throw new Error(`clawchat-plugin-openclaw failed to upload ${urls.length - fragments.length}/${urls.length} outbound media attachment(s); message not sent`);
294
+ }
295
+ return fragments;
288
296
  }
289
297
  // ----- Reply state ------------------------------------------------------
290
298
  let reasoningText = "";
@@ -123,6 +123,11 @@ export const ClawchatGetConversationSchema = Type.Object({
123
123
  description: "Concrete ClawChat conversation id to fetch",
124
124
  }),
125
125
  });
126
+ export const ClawchatLeaveGroupSchema = Type.Object({
127
+ conversationId: Type.String({
128
+ description: "Concrete ClawChat group conversation id to leave",
129
+ }),
130
+ });
126
131
  export const ClawchatMentionMessageSchema = Type.Object({
127
132
  chatId: Type.String({
128
133
  minLength: 1,
package/dist/src/tools.js CHANGED
@@ -12,7 +12,7 @@ import { getOpenclawClawlingClient, } from "./runtime.js";
12
12
  import { markTerminalClawChatSend } from "./terminal-send.js";
13
13
  import { editClawChatMemoryBody, readClawChatMemoryFile, resolveClawChatMemoryPath, searchClawChatMemory, writeClawChatMemoryBody, } from "./clawchat-memory.js";
14
14
  import { pullGroupMetadata, pullOwnerMetadata, pullUserMetadata, pushMetadata, updateMetadata, } from "./clawchat-metadata.js";
15
- import { ClawchatGetAccountProfileSchema, ClawchatGetConversationSchema, ClawchatGetUserProfileSchema, ClawchatAcceptFriendRequestSchema, ClawchatMemoryEditSchema, ClawchatMemoryReadSchema, ClawchatMemorySearchSchema, ClawchatMemoryWriteSchema, ClawchatMetadataSyncSchema, ClawchatMetadataUpdateSchema, ClawchatCreateMomentCommentSchema, ClawchatCreateMomentSchema, ClawchatDeleteMomentCommentSchema, ClawchatDeleteMomentSchema, ClawchatListAccountFriendsSchema, ClawchatListFriendRequestsSchema, ClawchatListMomentsSchema, ClawchatMentionMessageSchema, ClawchatReplyMomentCommentSchema, ClawchatRejectFriendRequestSchema, ClawchatRemoveFriendSchema, ClawchatSearchUsersSchema, ClawchatSendFriendRequestSchema, ClawchatToggleMomentReactionSchema, ClawchatUpdateAccountProfileSchema, ClawchatUploadAvatarImageSchema, ClawchatRegisterAppSchema, ClawchatListAppsSchema, ClawchatUnregisterAppSchema, ClawchatLivewareLoginSchema, } from "./tools-schema.js";
15
+ import { ClawchatGetAccountProfileSchema, ClawchatGetConversationSchema, ClawchatGetUserProfileSchema, ClawchatLeaveGroupSchema, ClawchatAcceptFriendRequestSchema, ClawchatMemoryEditSchema, ClawchatMemoryReadSchema, ClawchatMemorySearchSchema, ClawchatMemoryWriteSchema, ClawchatMetadataSyncSchema, ClawchatMetadataUpdateSchema, ClawchatCreateMomentCommentSchema, ClawchatCreateMomentSchema, ClawchatDeleteMomentCommentSchema, ClawchatDeleteMomentSchema, ClawchatListAccountFriendsSchema, ClawchatListFriendRequestsSchema, ClawchatListMomentsSchema, ClawchatMentionMessageSchema, ClawchatReplyMomentCommentSchema, ClawchatRejectFriendRequestSchema, ClawchatRemoveFriendSchema, ClawchatSearchUsersSchema, ClawchatSendFriendRequestSchema, ClawchatToggleMomentReactionSchema, ClawchatUpdateAccountProfileSchema, ClawchatUploadAvatarImageSchema, ClawchatRegisterAppSchema, ClawchatListAppsSchema, ClawchatUnregisterAppSchema, ClawchatLivewareLoginSchema, } from "./tools-schema.js";
16
16
  const MAX_UPLOAD_BYTES = 20 * 1024 * 1024;
17
17
  // Owner-approval gate business codes (must match the ClawChat backend's owner-approval codes).
18
18
  const CODE_PENDING_APPROVAL = 21001;
@@ -780,6 +780,34 @@ export function registerOpenclawClawlingTools(api, options = {}) {
780
780
  });
781
781
  },
782
782
  }, { name: "clawchat_get_conversation" });
783
+ api.registerTool({
784
+ name: "clawchat_leave_group",
785
+ label: "Leave ClawChat Group",
786
+ description: toolDescription("Leave a ClawChat group conversation the agent is currently a member of. " +
787
+ "TRIGGER - invoke only when the user explicitly asks the agent to leave, exit, or quit a specific ClawChat group and provides a concrete conversationId. " +
788
+ "Groups only: direct conversations are rejected by the server. " +
789
+ "If the agent is the group owner, leaving auto-transfers ownership to the earliest human member; if no human member remains, the group is dissolved. " +
790
+ "After this tool succeeds, output only <clawchat:no-reply/> and do not send a normal follow-up reply."),
791
+ parameters: ClawchatLeaveGroupSchema,
792
+ async execute(_callId, params) {
793
+ return await recordClawchatToolCall("clawchat_leave_group", params, async () => {
794
+ const p = params;
795
+ const built = buildClient();
796
+ if (!built.ok)
797
+ return built.error;
798
+ try {
799
+ const data = await built.client.leaveConversation(p.conversationId);
800
+ return jsonResponse(data);
801
+ }
802
+ catch (err) {
803
+ if (err instanceof ClawlingApiError) {
804
+ return apiError(err);
805
+ }
806
+ return genericError(err);
807
+ }
808
+ });
809
+ },
810
+ }, { name: "clawchat_leave_group" });
783
811
  api.registerTool({
784
812
  name: "clawchat_mention_message",
785
813
  label: "Send ClawChat Mention Message",
@@ -45,6 +45,7 @@
45
45
  "clawchat_search_users",
46
46
  "clawchat_mention_message",
47
47
  "clawchat_get_conversation",
48
+ "clawchat_leave_group",
48
49
  "clawchat_list_moments",
49
50
  "clawchat_create_moment",
50
51
  "clawchat_delete_moment",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawling/clawchat-plugin-openclaw",
3
- "version": "2026.7.15-1",
3
+ "version": "2026.7.21-1",
4
4
  "description": "OpenClaw ClawChat channel plugin",
5
5
  "license": "MIT",
6
6
  "author": "CLAWLING PTE. LTD.",
package/src/api-client.ts CHANGED
@@ -133,6 +133,7 @@ export interface OpenclawClawlingApiClient {
133
133
  }): Promise<{ comment: MomentComment }>;
134
134
  deleteMomentComment(params: { momentId: number; commentId: number }): Promise<{ ok: boolean }>;
135
135
  getConversation(conversationId: string): Promise<{ conversation: ConversationDetails }>;
136
+ leaveConversation(conversationId: string): Promise<{ ok: boolean }>;
136
137
  patchConversation(
137
138
  conversationId: string,
138
139
  patch: ConversationMetadataPatch,
@@ -631,6 +632,13 @@ export function createOpenclawClawlingApiClient(opts: ApiClientOptions): Opencla
631
632
  `/v1/conversations/${encodeURIComponent(conversationId)}`,
632
633
  );
633
634
  },
635
+ async leaveConversation(conversationId): Promise<{ ok: boolean }> {
636
+ assertNonBlankId(conversationId, "leaveConversation: conversationId");
637
+ return await call<{ ok: boolean }>(
638
+ "POST",
639
+ `/v1/conversations/${encodeURIComponent(conversationId)}/leave`,
640
+ );
641
+ },
634
642
  async patchConversation(
635
643
  conversationId: string,
636
644
  patch: ConversationMetadataPatch,
@@ -418,7 +418,17 @@ export function createOpenclawClawlingReplyDispatcher(options: ReplyDispatcherOp
418
418
  );
419
419
  return [];
420
420
  }
421
- return await uploadOutboundMedia(urls, { apiClient, runtime, log });
421
+ const fragments = await uploadOutboundMedia(urls, { apiClient, runtime, log });
422
+ if (fragments.length < urls.length) {
423
+ // uploadOutboundMedia drops a failed item with only a log line. A shortfall
424
+ // means an attachment never reached the media service; surfacing it (parity
425
+ // with the adapter path in outbound.ts and with the Hermes plugin) stops a
426
+ // text-only frame from going out and reading as a successful send.
427
+ throw new Error(
428
+ `clawchat-plugin-openclaw failed to upload ${urls.length - fragments.length}/${urls.length} outbound media attachment(s); message not sent`,
429
+ );
430
+ }
431
+ return fragments;
422
432
  }
423
433
 
424
434
  // ----- Reply state ------------------------------------------------------
@@ -201,6 +201,13 @@ export const ClawchatGetConversationSchema = Type.Object({
201
201
  });
202
202
  export type ClawchatGetConversationParams = Static<typeof ClawchatGetConversationSchema>;
203
203
 
204
+ export const ClawchatLeaveGroupSchema = Type.Object({
205
+ conversationId: Type.String({
206
+ description: "Concrete ClawChat group conversation id to leave",
207
+ }),
208
+ });
209
+ export type ClawchatLeaveGroupParams = Static<typeof ClawchatLeaveGroupSchema>;
210
+
204
211
  export const ClawchatMentionMessageSchema = Type.Object({
205
212
  chatId: Type.String({
206
213
  minLength: 1,
package/src/tools.ts CHANGED
@@ -41,6 +41,7 @@ import {
41
41
  ClawchatGetAccountProfileSchema,
42
42
  ClawchatGetConversationSchema,
43
43
  ClawchatGetUserProfileSchema,
44
+ ClawchatLeaveGroupSchema,
44
45
  ClawchatAcceptFriendRequestSchema,
45
46
  ClawchatMemoryEditSchema,
46
47
  ClawchatMemoryReadSchema,
@@ -81,6 +82,7 @@ import {
81
82
  type ClawchatAcceptFriendRequestParams,
82
83
  type ClawchatGetConversationParams,
83
84
  type ClawchatGetUserProfileParams,
85
+ type ClawchatLeaveGroupParams,
84
86
  type ClawchatListFriendRequestsParams,
85
87
  type ClawchatListMomentsParams,
86
88
  type ClawchatMentionMessageParams,
@@ -1010,6 +1012,38 @@ export function registerOpenclawClawlingTools(
1010
1012
  { name: "clawchat_get_conversation" },
1011
1013
  );
1012
1014
 
1015
+ api.registerTool(
1016
+ {
1017
+ name: "clawchat_leave_group",
1018
+ label: "Leave ClawChat Group",
1019
+ description: toolDescription(
1020
+ "Leave a ClawChat group conversation the agent is currently a member of. " +
1021
+ "TRIGGER - invoke only when the user explicitly asks the agent to leave, exit, or quit a specific ClawChat group and provides a concrete conversationId. " +
1022
+ "Groups only: direct conversations are rejected by the server. " +
1023
+ "If the agent is the group owner, leaving auto-transfers ownership to the earliest human member; if no human member remains, the group is dissolved. " +
1024
+ "After this tool succeeds, output only <clawchat:no-reply/> and do not send a normal follow-up reply.",
1025
+ ),
1026
+ parameters: ClawchatLeaveGroupSchema,
1027
+ async execute(_callId, params) {
1028
+ return await recordClawchatToolCall("clawchat_leave_group", params, async () => {
1029
+ const p = params as ClawchatLeaveGroupParams;
1030
+ const built = buildClient();
1031
+ if (!built.ok) return built.error;
1032
+ try {
1033
+ const data = await built.client.leaveConversation(p.conversationId);
1034
+ return jsonResponse(data);
1035
+ } catch (err) {
1036
+ if (err instanceof ClawlingApiError) {
1037
+ return apiError(err);
1038
+ }
1039
+ return genericError(err);
1040
+ }
1041
+ });
1042
+ },
1043
+ },
1044
+ { name: "clawchat_leave_group" },
1045
+ );
1046
+
1013
1047
  api.registerTool(
1014
1048
  {
1015
1049
  name: "clawchat_mention_message",