@maudecode/openclaw-cowtail 0.11.0 → 0.12.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/dist/index.js CHANGED
@@ -13746,6 +13746,16 @@ var openclawActionStateSchema = exports_external.enum(["pending", "submitted", "
13746
13746
  var openclawToolCallStatusSchema = exports_external.enum(["pending", "running", "complete", "error"]);
13747
13747
  var openclawEventTypeSchema = exports_external.enum(openclawEventTypes);
13748
13748
  var openclawSequenceSchema = exports_external.number().int().nonnegative();
13749
+ var openclawMessageTextSchema = exports_external.string();
13750
+ function hasOpenClawRenderableContent(value) {
13751
+ return value.text.trim().length > 0 || (value.links?.length ?? 0) > 0 || (value.toolCalls?.length ?? 0) > 0 || (value.actions?.length ?? 0) > 0;
13752
+ }
13753
+ function requireOpenClawRenderableContent(schema) {
13754
+ return schema.refine((value) => hasOpenClawRenderableContent(value), {
13755
+ message: "OpenClaw messages require text or renderable content",
13756
+ path: ["text"]
13757
+ });
13758
+ }
13749
13759
  var openclawLinkSchema = exports_external.object({
13750
13760
  label: nonEmptyStringSchema,
13751
13761
  url: nonEmptyStringSchema
@@ -13788,18 +13798,19 @@ var openclawThreadRecordSchema = exports_external.object({
13788
13798
  updatedAt: timestampSchema,
13789
13799
  lastMessageAt: timestampSchema.optional()
13790
13800
  });
13791
- var openclawMessageRecordSchema = exports_external.object({
13801
+ var openclawMessageRecordBaseSchema = exports_external.object({
13792
13802
  id: nonEmptyStringSchema,
13793
13803
  threadId: nonEmptyStringSchema,
13794
13804
  direction: openclawMessageDirectionSchema,
13795
13805
  authorLabel: nonEmptyStringSchema.optional(),
13796
- text: nonEmptyStringSchema,
13806
+ text: openclawMessageTextSchema,
13797
13807
  links: exports_external.array(openclawLinkSchema).default([]),
13798
13808
  toolCalls: exports_external.array(openclawToolCallRecordSchema).default([]),
13799
13809
  deliveryState: openclawDeliveryStateSchema,
13800
13810
  createdAt: timestampSchema,
13801
13811
  updatedAt: timestampSchema
13802
13812
  });
13813
+ var openclawMessageRecordSchema = requireOpenClawRenderableContent(openclawMessageRecordBaseSchema);
13803
13814
  var openclawActionRecordSchema = exports_external.object({
13804
13815
  id: nonEmptyStringSchema,
13805
13816
  threadId: nonEmptyStringSchema,
@@ -13838,28 +13849,28 @@ var openclawActionDraftSchema = exports_external.object({
13838
13849
  kind: nonEmptyStringSchema,
13839
13850
  payload: jsonObjectSchema
13840
13851
  });
13841
- var openclawPluginMessageCommandSchema = exports_external.object({
13852
+ var openclawPluginMessageCommandSchema = requireOpenClawRenderableContent(exports_external.object({
13842
13853
  type: exports_external.literal("openclaw_message"),
13843
13854
  requestId: openclawRequestIdSchema,
13844
13855
  sessionKey: nonEmptyStringSchema,
13845
13856
  title: nonEmptyStringSchema.optional(),
13846
- text: nonEmptyStringSchema,
13857
+ text: openclawMessageTextSchema,
13847
13858
  authorLabel: nonEmptyStringSchema.optional(),
13848
13859
  links: exports_external.array(openclawLinkSchema).default([]),
13849
13860
  toolCalls: exports_external.array(openclawToolCallRecordSchema).default([]),
13850
13861
  actions: exports_external.array(openclawActionDraftSchema).default([]),
13851
13862
  deliveryState: openclawDeliveryStateSchema.optional()
13852
- });
13853
- var openclawPluginMessageUpdateCommandSchema = exports_external.object({
13863
+ }));
13864
+ var openclawPluginMessageUpdateCommandSchema = requireOpenClawRenderableContent(exports_external.object({
13854
13865
  type: exports_external.literal("openclaw_message_update"),
13855
13866
  requestId: openclawRequestIdSchema,
13856
13867
  messageId: nonEmptyStringSchema,
13857
- text: nonEmptyStringSchema,
13868
+ text: openclawMessageTextSchema,
13858
13869
  links: exports_external.array(openclawLinkSchema).optional(),
13859
13870
  toolCalls: exports_external.array(openclawToolCallRecordSchema).optional(),
13860
13871
  actions: exports_external.array(openclawActionDraftSchema).optional(),
13861
13872
  deliveryState: openclawDeliveryStateSchema.optional()
13862
- });
13873
+ }));
13863
13874
  var openclawIosNewThreadCommandSchema = exports_external.object({
13864
13875
  type: exports_external.literal("ios_new_thread"),
13865
13876
  requestId: openclawRequestIdSchema,
@@ -13907,7 +13918,7 @@ var openclawActionResultCommandSchema = exports_external.object({
13907
13918
  state: exports_external.enum(["submitted", "failed", "expired"]),
13908
13919
  resultMetadata: jsonObjectSchema.optional()
13909
13920
  });
13910
- var openclawRealtimeClientMessageSchema = exports_external.discriminatedUnion("type", [
13921
+ var openclawRealtimeClientMessageSchema = exports_external.union([
13911
13922
  openclawPluginMessageCommandSchema,
13912
13923
  openclawPluginMessageUpdateCommandSchema,
13913
13924
  openclawIosNewThreadCommandSchema,
@@ -13949,9 +13960,9 @@ var openclawMessageListResponseSchema = exports_external.object({
13949
13960
  count: exports_external.number().int().nonnegative(),
13950
13961
  messages: exports_external.array(openclawMessageRecordSchema)
13951
13962
  });
13952
- var openclawMessageWithActionsRecordSchema = openclawMessageRecordSchema.extend({
13963
+ var openclawMessageWithActionsRecordSchema = requireOpenClawRenderableContent(openclawMessageRecordBaseSchema.extend({
13953
13964
  actions: exports_external.array(openclawActionRecordSchema).default([])
13954
- });
13965
+ }));
13955
13966
  var openclawMessageWithActionsListResponseSchema = exports_external.object({
13956
13967
  ok: exports_external.literal(true),
13957
13968
  count: exports_external.number().int().nonnegative(),
@@ -14591,7 +14602,7 @@ async function dispatchCowtailTextTurn(params) {
14591
14602
  body,
14592
14603
  timestamp: message.createdAt
14593
14604
  });
14594
- const streamState = { text: "", toolCalls: [] };
14605
+ const streamState = { text: "", links: [], toolCalls: [] };
14595
14606
  await recordCowtailInboundSessionAndDispatchReply({
14596
14607
  cfg: runtime.config.loadConfig(),
14597
14608
  channel: CHANNEL_ID,
@@ -14617,6 +14628,10 @@ async function dispatchCowtailTextTurn(params) {
14617
14628
  logger?.error?.(`Cowtail ${info.kind} reply failed: ${errorMessage(error48)}`);
14618
14629
  }
14619
14630
  });
14631
+ await finalizeCowtailStreamedReply({
14632
+ client,
14633
+ streamState
14634
+ });
14620
14635
  }
14621
14636
  async function dispatchCowtailActionTurn(params) {
14622
14637
  const { account, client, runtime, logger, route, thread, action, payload, timestamp } = params;
@@ -14643,7 +14658,7 @@ async function dispatchCowtailActionTurn(params) {
14643
14658
  timestamp
14644
14659
  });
14645
14660
  let dispatchFailed = false;
14646
- const streamState = { text: "", toolCalls: [] };
14661
+ const streamState = { text: "", links: [], toolCalls: [] };
14647
14662
  await recordCowtailInboundSessionAndDispatchReply({
14648
14663
  cfg: runtime.config.loadConfig(),
14649
14664
  channel: CHANNEL_ID,
@@ -14670,6 +14685,10 @@ async function dispatchCowtailActionTurn(params) {
14670
14685
  logger?.error?.(`Cowtail ${info.kind} reply failed: ${errorMessage(error48)}`);
14671
14686
  }
14672
14687
  });
14688
+ await finalizeCowtailStreamedReply({
14689
+ client,
14690
+ streamState
14691
+ });
14673
14692
  return !dispatchFailed;
14674
14693
  }
14675
14694
  async function recordCowtailInboundSessionAndDispatchReply(params) {
@@ -14700,6 +14719,7 @@ async function recordCowtailInboundSessionAndDispatchReply(params) {
14700
14719
  onError: params.onDispatchError
14701
14720
  },
14702
14721
  replyOptions: {
14722
+ disableBlockStreaming: false,
14703
14723
  onModelSelected
14704
14724
  }
14705
14725
  });
@@ -14711,14 +14731,17 @@ async function deliverCowtailReply(params) {
14711
14731
  const text = params.payload.text;
14712
14732
  const kind = params.info?.kind ?? "final";
14713
14733
  const links = resolveCowtailReplyLinks(params.payload);
14734
+ if (links.length > 0) {
14735
+ params.streamState.links = links;
14736
+ }
14714
14737
  if (kind === "tool") {
14715
- const { toolCall, summary } = buildCowtailToolCall({
14738
+ const toolCall = buildCowtailToolCall({
14716
14739
  payload: params.payload,
14717
14740
  rawPayload: params.rawPayload,
14718
14741
  streamState: params.streamState
14719
14742
  });
14720
14743
  params.streamState.toolCalls = [...params.streamState.toolCalls, toolCall];
14721
- const messageText = params.streamState.text || summary || "Tool activity";
14744
+ const messageText = params.streamState.text;
14722
14745
  if (!params.streamState.messageId) {
14723
14746
  const result = await params.client.sendOpenClawMessage({
14724
14747
  type: "openclaw_message",
@@ -14731,7 +14754,11 @@ async function deliverCowtailReply(params) {
14731
14754
  actions: [],
14732
14755
  deliveryState: "pending"
14733
14756
  });
14734
- params.streamState.messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14757
+ const messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14758
+ if (!messageId) {
14759
+ return;
14760
+ }
14761
+ params.streamState.messageId = messageId;
14735
14762
  return;
14736
14763
  }
14737
14764
  await params.client.sendOpenClawMessageUpdate({
@@ -14761,7 +14788,11 @@ async function deliverCowtailReply(params) {
14761
14788
  actions: [],
14762
14789
  deliveryState: "pending"
14763
14790
  });
14764
- params.streamState.messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14791
+ const messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14792
+ if (!messageId) {
14793
+ return;
14794
+ }
14795
+ params.streamState.messageId = messageId;
14765
14796
  return;
14766
14797
  }
14767
14798
  await params.client.sendOpenClawMessageUpdate({
@@ -14785,6 +14816,7 @@ async function deliverCowtailReply(params) {
14785
14816
  actions: [],
14786
14817
  deliveryState: "sent"
14787
14818
  });
14819
+ params.streamState.completed = true;
14788
14820
  return;
14789
14821
  }
14790
14822
  await params.client.sendOpenClawMessage({
@@ -14798,8 +14830,29 @@ async function deliverCowtailReply(params) {
14798
14830
  actions: [],
14799
14831
  deliveryState: "sent"
14800
14832
  });
14833
+ params.streamState.completed = true;
14834
+ }
14835
+ async function finalizeCowtailStreamedReply(params) {
14836
+ if (params.streamState.failed || params.streamState.completed || !params.streamState.messageId || !params.streamState.text.trim() && params.streamState.toolCalls.length === 0) {
14837
+ return;
14838
+ }
14839
+ await params.client.sendOpenClawMessageUpdate({
14840
+ type: "openclaw_message_update",
14841
+ messageId: params.streamState.messageId,
14842
+ text: params.streamState.text,
14843
+ links: params.streamState.links,
14844
+ toolCalls: params.streamState.toolCalls,
14845
+ actions: [],
14846
+ deliveryState: "sent"
14847
+ });
14848
+ params.streamState.completed = true;
14801
14849
  }
14802
14850
  function recordCreatedOpenClawMessageId(streamState, result) {
14851
+ if (result.payload?.dropped === true) {
14852
+ streamState.failed = true;
14853
+ streamState.completed = true;
14854
+ return;
14855
+ }
14803
14856
  const messageId = result.payload?.messageId;
14804
14857
  if (typeof messageId === "string" && messageId.trim()) {
14805
14858
  return messageId;
@@ -14825,9 +14878,8 @@ function normalizeCowtailReplyPayload(payload) {
14825
14878
  }
14826
14879
  function buildCowtailToolCall(params) {
14827
14880
  const rawToolCall = readRawToolCall(params.rawPayload);
14828
- const summary = resolveToolCallSummary(params.payload, rawToolCall);
14829
14881
  const index = params.streamState.toolCalls.length + 1;
14830
- const toolCall = {
14882
+ return {
14831
14883
  id: rawToolCall.id ?? `tool-${index}`,
14832
14884
  name: rawToolCall.name ?? "tool_result",
14833
14885
  ...rawToolCall.args ? { args: rawToolCall.args } : {},
@@ -14838,10 +14890,6 @@ function buildCowtailToolCall(params) {
14838
14890
  insertedAtContentLength: params.streamState.text.length,
14839
14891
  contentSnapshotAtStart: params.streamState.text
14840
14892
  };
14841
- return {
14842
- toolCall,
14843
- ...summary ? { summary } : {}
14844
- };
14845
14893
  }
14846
14894
  function readRawToolCall(payload) {
14847
14895
  if (!payload || typeof payload !== "object") {
@@ -14872,16 +14920,6 @@ function readRawToolCall(payload) {
14872
14920
  ...contentSnapshotAtStart !== undefined ? { contentSnapshotAtStart } : {}
14873
14921
  };
14874
14922
  }
14875
- function resolveToolCallSummary(payload, toolCall) {
14876
- if (typeof payload.text === "string" && payload.text.trim()) {
14877
- return payload.text.trim().split(`
14878
- `)[0];
14879
- }
14880
- if (toolCall.name) {
14881
- return toolCall.name;
14882
- }
14883
- return;
14884
- }
14885
14923
  function readString(value) {
14886
14924
  return typeof value === "string" && value.trim() ? value : undefined;
14887
14925
  }
@@ -15153,7 +15191,7 @@ function createCowtailChannelPlugin(deps = defaultDeps) {
15153
15191
  reactions: false,
15154
15192
  edit: false,
15155
15193
  unsend: false,
15156
- blockStreaming: false
15194
+ blockStreaming: true
15157
15195
  },
15158
15196
  setup: {
15159
15197
  applyAccountConfig: ({ cfg }) => cfg
@@ -13746,6 +13746,16 @@ var openclawActionStateSchema = exports_external.enum(["pending", "submitted", "
13746
13746
  var openclawToolCallStatusSchema = exports_external.enum(["pending", "running", "complete", "error"]);
13747
13747
  var openclawEventTypeSchema = exports_external.enum(openclawEventTypes);
13748
13748
  var openclawSequenceSchema = exports_external.number().int().nonnegative();
13749
+ var openclawMessageTextSchema = exports_external.string();
13750
+ function hasOpenClawRenderableContent(value) {
13751
+ return value.text.trim().length > 0 || (value.links?.length ?? 0) > 0 || (value.toolCalls?.length ?? 0) > 0 || (value.actions?.length ?? 0) > 0;
13752
+ }
13753
+ function requireOpenClawRenderableContent(schema) {
13754
+ return schema.refine((value) => hasOpenClawRenderableContent(value), {
13755
+ message: "OpenClaw messages require text or renderable content",
13756
+ path: ["text"]
13757
+ });
13758
+ }
13749
13759
  var openclawLinkSchema = exports_external.object({
13750
13760
  label: nonEmptyStringSchema,
13751
13761
  url: nonEmptyStringSchema
@@ -13788,18 +13798,19 @@ var openclawThreadRecordSchema = exports_external.object({
13788
13798
  updatedAt: timestampSchema,
13789
13799
  lastMessageAt: timestampSchema.optional()
13790
13800
  });
13791
- var openclawMessageRecordSchema = exports_external.object({
13801
+ var openclawMessageRecordBaseSchema = exports_external.object({
13792
13802
  id: nonEmptyStringSchema,
13793
13803
  threadId: nonEmptyStringSchema,
13794
13804
  direction: openclawMessageDirectionSchema,
13795
13805
  authorLabel: nonEmptyStringSchema.optional(),
13796
- text: nonEmptyStringSchema,
13806
+ text: openclawMessageTextSchema,
13797
13807
  links: exports_external.array(openclawLinkSchema).default([]),
13798
13808
  toolCalls: exports_external.array(openclawToolCallRecordSchema).default([]),
13799
13809
  deliveryState: openclawDeliveryStateSchema,
13800
13810
  createdAt: timestampSchema,
13801
13811
  updatedAt: timestampSchema
13802
13812
  });
13813
+ var openclawMessageRecordSchema = requireOpenClawRenderableContent(openclawMessageRecordBaseSchema);
13803
13814
  var openclawActionRecordSchema = exports_external.object({
13804
13815
  id: nonEmptyStringSchema,
13805
13816
  threadId: nonEmptyStringSchema,
@@ -13838,28 +13849,28 @@ var openclawActionDraftSchema = exports_external.object({
13838
13849
  kind: nonEmptyStringSchema,
13839
13850
  payload: jsonObjectSchema
13840
13851
  });
13841
- var openclawPluginMessageCommandSchema = exports_external.object({
13852
+ var openclawPluginMessageCommandSchema = requireOpenClawRenderableContent(exports_external.object({
13842
13853
  type: exports_external.literal("openclaw_message"),
13843
13854
  requestId: openclawRequestIdSchema,
13844
13855
  sessionKey: nonEmptyStringSchema,
13845
13856
  title: nonEmptyStringSchema.optional(),
13846
- text: nonEmptyStringSchema,
13857
+ text: openclawMessageTextSchema,
13847
13858
  authorLabel: nonEmptyStringSchema.optional(),
13848
13859
  links: exports_external.array(openclawLinkSchema).default([]),
13849
13860
  toolCalls: exports_external.array(openclawToolCallRecordSchema).default([]),
13850
13861
  actions: exports_external.array(openclawActionDraftSchema).default([]),
13851
13862
  deliveryState: openclawDeliveryStateSchema.optional()
13852
- });
13853
- var openclawPluginMessageUpdateCommandSchema = exports_external.object({
13863
+ }));
13864
+ var openclawPluginMessageUpdateCommandSchema = requireOpenClawRenderableContent(exports_external.object({
13854
13865
  type: exports_external.literal("openclaw_message_update"),
13855
13866
  requestId: openclawRequestIdSchema,
13856
13867
  messageId: nonEmptyStringSchema,
13857
- text: nonEmptyStringSchema,
13868
+ text: openclawMessageTextSchema,
13858
13869
  links: exports_external.array(openclawLinkSchema).optional(),
13859
13870
  toolCalls: exports_external.array(openclawToolCallRecordSchema).optional(),
13860
13871
  actions: exports_external.array(openclawActionDraftSchema).optional(),
13861
13872
  deliveryState: openclawDeliveryStateSchema.optional()
13862
- });
13873
+ }));
13863
13874
  var openclawIosNewThreadCommandSchema = exports_external.object({
13864
13875
  type: exports_external.literal("ios_new_thread"),
13865
13876
  requestId: openclawRequestIdSchema,
@@ -13907,7 +13918,7 @@ var openclawActionResultCommandSchema = exports_external.object({
13907
13918
  state: exports_external.enum(["submitted", "failed", "expired"]),
13908
13919
  resultMetadata: jsonObjectSchema.optional()
13909
13920
  });
13910
- var openclawRealtimeClientMessageSchema = exports_external.discriminatedUnion("type", [
13921
+ var openclawRealtimeClientMessageSchema = exports_external.union([
13911
13922
  openclawPluginMessageCommandSchema,
13912
13923
  openclawPluginMessageUpdateCommandSchema,
13913
13924
  openclawIosNewThreadCommandSchema,
@@ -13949,9 +13960,9 @@ var openclawMessageListResponseSchema = exports_external.object({
13949
13960
  count: exports_external.number().int().nonnegative(),
13950
13961
  messages: exports_external.array(openclawMessageRecordSchema)
13951
13962
  });
13952
- var openclawMessageWithActionsRecordSchema = openclawMessageRecordSchema.extend({
13963
+ var openclawMessageWithActionsRecordSchema = requireOpenClawRenderableContent(openclawMessageRecordBaseSchema.extend({
13953
13964
  actions: exports_external.array(openclawActionRecordSchema).default([])
13954
- });
13965
+ }));
13955
13966
  var openclawMessageWithActionsListResponseSchema = exports_external.object({
13956
13967
  ok: exports_external.literal(true),
13957
13968
  count: exports_external.number().int().nonnegative(),
@@ -14591,7 +14602,7 @@ async function dispatchCowtailTextTurn(params) {
14591
14602
  body,
14592
14603
  timestamp: message.createdAt
14593
14604
  });
14594
- const streamState = { text: "", toolCalls: [] };
14605
+ const streamState = { text: "", links: [], toolCalls: [] };
14595
14606
  await recordCowtailInboundSessionAndDispatchReply({
14596
14607
  cfg: runtime.config.loadConfig(),
14597
14608
  channel: CHANNEL_ID,
@@ -14617,6 +14628,10 @@ async function dispatchCowtailTextTurn(params) {
14617
14628
  logger?.error?.(`Cowtail ${info.kind} reply failed: ${errorMessage(error48)}`);
14618
14629
  }
14619
14630
  });
14631
+ await finalizeCowtailStreamedReply({
14632
+ client,
14633
+ streamState
14634
+ });
14620
14635
  }
14621
14636
  async function dispatchCowtailActionTurn(params) {
14622
14637
  const { account, client, runtime, logger, route, thread, action, payload, timestamp } = params;
@@ -14643,7 +14658,7 @@ async function dispatchCowtailActionTurn(params) {
14643
14658
  timestamp
14644
14659
  });
14645
14660
  let dispatchFailed = false;
14646
- const streamState = { text: "", toolCalls: [] };
14661
+ const streamState = { text: "", links: [], toolCalls: [] };
14647
14662
  await recordCowtailInboundSessionAndDispatchReply({
14648
14663
  cfg: runtime.config.loadConfig(),
14649
14664
  channel: CHANNEL_ID,
@@ -14670,6 +14685,10 @@ async function dispatchCowtailActionTurn(params) {
14670
14685
  logger?.error?.(`Cowtail ${info.kind} reply failed: ${errorMessage(error48)}`);
14671
14686
  }
14672
14687
  });
14688
+ await finalizeCowtailStreamedReply({
14689
+ client,
14690
+ streamState
14691
+ });
14673
14692
  return !dispatchFailed;
14674
14693
  }
14675
14694
  async function recordCowtailInboundSessionAndDispatchReply(params) {
@@ -14700,6 +14719,7 @@ async function recordCowtailInboundSessionAndDispatchReply(params) {
14700
14719
  onError: params.onDispatchError
14701
14720
  },
14702
14721
  replyOptions: {
14722
+ disableBlockStreaming: false,
14703
14723
  onModelSelected
14704
14724
  }
14705
14725
  });
@@ -14711,14 +14731,17 @@ async function deliverCowtailReply(params) {
14711
14731
  const text = params.payload.text;
14712
14732
  const kind = params.info?.kind ?? "final";
14713
14733
  const links = resolveCowtailReplyLinks(params.payload);
14734
+ if (links.length > 0) {
14735
+ params.streamState.links = links;
14736
+ }
14714
14737
  if (kind === "tool") {
14715
- const { toolCall, summary } = buildCowtailToolCall({
14738
+ const toolCall = buildCowtailToolCall({
14716
14739
  payload: params.payload,
14717
14740
  rawPayload: params.rawPayload,
14718
14741
  streamState: params.streamState
14719
14742
  });
14720
14743
  params.streamState.toolCalls = [...params.streamState.toolCalls, toolCall];
14721
- const messageText = params.streamState.text || summary || "Tool activity";
14744
+ const messageText = params.streamState.text;
14722
14745
  if (!params.streamState.messageId) {
14723
14746
  const result = await params.client.sendOpenClawMessage({
14724
14747
  type: "openclaw_message",
@@ -14731,7 +14754,11 @@ async function deliverCowtailReply(params) {
14731
14754
  actions: [],
14732
14755
  deliveryState: "pending"
14733
14756
  });
14734
- params.streamState.messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14757
+ const messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14758
+ if (!messageId) {
14759
+ return;
14760
+ }
14761
+ params.streamState.messageId = messageId;
14735
14762
  return;
14736
14763
  }
14737
14764
  await params.client.sendOpenClawMessageUpdate({
@@ -14761,7 +14788,11 @@ async function deliverCowtailReply(params) {
14761
14788
  actions: [],
14762
14789
  deliveryState: "pending"
14763
14790
  });
14764
- params.streamState.messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14791
+ const messageId = recordCreatedOpenClawMessageId(params.streamState, result);
14792
+ if (!messageId) {
14793
+ return;
14794
+ }
14795
+ params.streamState.messageId = messageId;
14765
14796
  return;
14766
14797
  }
14767
14798
  await params.client.sendOpenClawMessageUpdate({
@@ -14785,6 +14816,7 @@ async function deliverCowtailReply(params) {
14785
14816
  actions: [],
14786
14817
  deliveryState: "sent"
14787
14818
  });
14819
+ params.streamState.completed = true;
14788
14820
  return;
14789
14821
  }
14790
14822
  await params.client.sendOpenClawMessage({
@@ -14798,8 +14830,29 @@ async function deliverCowtailReply(params) {
14798
14830
  actions: [],
14799
14831
  deliveryState: "sent"
14800
14832
  });
14833
+ params.streamState.completed = true;
14834
+ }
14835
+ async function finalizeCowtailStreamedReply(params) {
14836
+ if (params.streamState.failed || params.streamState.completed || !params.streamState.messageId || !params.streamState.text.trim() && params.streamState.toolCalls.length === 0) {
14837
+ return;
14838
+ }
14839
+ await params.client.sendOpenClawMessageUpdate({
14840
+ type: "openclaw_message_update",
14841
+ messageId: params.streamState.messageId,
14842
+ text: params.streamState.text,
14843
+ links: params.streamState.links,
14844
+ toolCalls: params.streamState.toolCalls,
14845
+ actions: [],
14846
+ deliveryState: "sent"
14847
+ });
14848
+ params.streamState.completed = true;
14801
14849
  }
14802
14850
  function recordCreatedOpenClawMessageId(streamState, result) {
14851
+ if (result.payload?.dropped === true) {
14852
+ streamState.failed = true;
14853
+ streamState.completed = true;
14854
+ return;
14855
+ }
14803
14856
  const messageId = result.payload?.messageId;
14804
14857
  if (typeof messageId === "string" && messageId.trim()) {
14805
14858
  return messageId;
@@ -14825,9 +14878,8 @@ function normalizeCowtailReplyPayload(payload) {
14825
14878
  }
14826
14879
  function buildCowtailToolCall(params) {
14827
14880
  const rawToolCall = readRawToolCall(params.rawPayload);
14828
- const summary = resolveToolCallSummary(params.payload, rawToolCall);
14829
14881
  const index = params.streamState.toolCalls.length + 1;
14830
- const toolCall = {
14882
+ return {
14831
14883
  id: rawToolCall.id ?? `tool-${index}`,
14832
14884
  name: rawToolCall.name ?? "tool_result",
14833
14885
  ...rawToolCall.args ? { args: rawToolCall.args } : {},
@@ -14838,10 +14890,6 @@ function buildCowtailToolCall(params) {
14838
14890
  insertedAtContentLength: params.streamState.text.length,
14839
14891
  contentSnapshotAtStart: params.streamState.text
14840
14892
  };
14841
- return {
14842
- toolCall,
14843
- ...summary ? { summary } : {}
14844
- };
14845
14893
  }
14846
14894
  function readRawToolCall(payload) {
14847
14895
  if (!payload || typeof payload !== "object") {
@@ -14872,16 +14920,6 @@ function readRawToolCall(payload) {
14872
14920
  ...contentSnapshotAtStart !== undefined ? { contentSnapshotAtStart } : {}
14873
14921
  };
14874
14922
  }
14875
- function resolveToolCallSummary(payload, toolCall) {
14876
- if (typeof payload.text === "string" && payload.text.trim()) {
14877
- return payload.text.trim().split(`
14878
- `)[0];
14879
- }
14880
- if (toolCall.name) {
14881
- return toolCall.name;
14882
- }
14883
- return;
14884
- }
14885
14923
  function readString(value) {
14886
14924
  return typeof value === "string" && value.trim() ? value : undefined;
14887
14925
  }
@@ -15153,7 +15191,7 @@ function createCowtailChannelPlugin(deps = defaultDeps) {
15153
15191
  reactions: false,
15154
15192
  edit: false,
15155
15193
  unsend: false,
15156
- blockStreaming: false
15194
+ blockStreaming: true
15157
15195
  },
15158
15196
  setup: {
15159
15197
  applyAccountConfig: ({ cfg }) => cfg
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maudecode/openclaw-cowtail",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Cowtail channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "repository": {