@dcrays/dcgchat-test 0.3.4 → 0.3.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/dcgchat-test",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "type": "module",
5
5
  "description": "OpenClaw channel plugin for 书灵墨宝 (WebSocket)",
6
6
  "main": "index.ts",
package/src/bot.ts CHANGED
@@ -182,10 +182,10 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
182
182
  effectiveAgentId && effectiveAgentId !== 'main' ? config.agents?.list?.find((a) => a.id === effectiveAgentId) : undefined
183
183
  const agentDisplayName = agentEntry?.name ?? (effectiveAgentId && effectiveAgentId !== 'main' ? effectiveAgentId : undefined)
184
184
 
185
- const safeSendFinal = () => {
185
+ const safeSendFinal = (tag: string) => {
186
186
  if (finalSent) return
187
187
  finalSent = true
188
- sendFinal(outboundCtx)
188
+ sendFinal(outboundCtx, tag)
189
189
  setMsgStatus(effectiveSessionKey, 'finished')
190
190
  }
191
191
 
@@ -193,7 +193,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
193
193
 
194
194
  if (!text) {
195
195
  sendTextMsg('你需要我帮你做什么呢?', outboundCtx)
196
- safeSendFinal()
196
+ safeSendFinal('not text')
197
197
  return
198
198
  }
199
199
 
@@ -272,20 +272,11 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
272
272
  }
273
273
  },
274
274
  onError: (err: unknown, info: { kind: string }) => {
275
- activeRunIdBySessionKey.delete(effectiveSessionKey)
276
- streamChunkIdxBySessionKey.delete(effectiveSessionKey)
277
- if (sessionStreamSuppressed.has(effectiveSessionKey)) {
278
- dcgLogger(`${info.kind} reply failed (stream suppressed): ${String(err)}`, 'error')
279
- return
280
- }
281
- safeSendFinal()
275
+ safeSendFinal('error')
282
276
  dcgLogger(`${info.kind} reply failed: ${String(err)}`, 'error')
283
277
  },
284
278
  onIdle: () => {
285
- activeRunIdBySessionKey.delete(effectiveSessionKey)
286
- streamChunkIdxBySessionKey.delete(effectiveSessionKey)
287
- if (sessionStreamSuppressed.has(effectiveSessionKey)) return
288
- safeSendFinal()
279
+ // safeSendFinal()
289
280
  }
290
281
  })
291
282
 
@@ -312,7 +303,6 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
312
303
  } else if (interruptCommand.includes(text?.trim())) {
313
304
  dcgLogger(`interrupt command: ${text}`)
314
305
  sendText('会话已终止', outboundCtx)
315
- safeSendFinal()
316
306
  sessionStreamSuppressed.add(effectiveSessionKey)
317
307
  const runId = activeRunIdBySessionKey.get(effectiveSessionKey)
318
308
  sendMessageToGateway(
@@ -325,6 +315,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
325
315
  })
326
316
  )
327
317
  if (runId) activeRunIdBySessionKey.delete(effectiveSessionKey)
318
+ safeSendFinal('stop')
328
319
  return
329
320
  } else {
330
321
  dcgLogger(`dispatching to agent (session=${route.sessionKey})`)
@@ -433,7 +424,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
433
424
  }
434
425
  }
435
426
  }
436
- safeSendFinal()
427
+ safeSendFinal('end')
437
428
  clearSentMediaKeys(msg.content.message_id)
438
429
 
439
430
  // Record session metadata
@@ -454,6 +445,6 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
454
445
  dcgLogger(` handle message failed: ${String(err)}`, 'error')
455
446
  sendError(err instanceof Error ? err.message : String(err), outboundCtx)
456
447
  } finally {
457
- safeSendFinal()
448
+ safeSendFinal('finally')
458
449
  }
459
450
  }
package/src/channel.ts CHANGED
@@ -159,7 +159,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
159
159
  const outboundCtx = getEffectiveMsgParams(ctx.to)
160
160
  const messageId = getCronMessageId(ctx.to)
161
161
  const newCtx = messageId ? { ...outboundCtx, messageId } : outboundCtx
162
- wsSendRaw(newCtx, { response: ctx.text, is_finish: -1 })
162
+ wsSendRaw(newCtx, { response: ctx.text, is_finish: -1, message_tags: { source: 'channel' } })
163
163
  dcgLogger(`channel sendText to ${ctx.to} ${ctx.text?.slice(0, 50)}`)
164
164
  }
165
165
  return {
package/src/monitor.ts CHANGED
@@ -8,6 +8,7 @@ import { installSkill, uninstallSkill } from './skill.js'
8
8
  import { dcgLogger } from './utils/log.js'
9
9
  import { onDisabledCronJob, onEnabledCronJob, onRemoveCronJob, onRunCronJob } from './cron.js'
10
10
  import { ignoreToolCommand } from './utils/constant.js'
11
+ import { isWsOpen } from './transport.js'
11
12
 
12
13
  export type MonitorDcgchatOpts = {
13
14
  config?: ClawdbotConfig
@@ -64,22 +65,24 @@ export async function monitorDcgchatProvider(opts: MonitorDcgchatOpts): Promise<
64
65
  heartbeatTimer = null
65
66
  }
66
67
  }
67
-
68
+ function onHeartbeat() {
69
+ if (isWsOpen()) {
70
+ const heartbeat = {
71
+ messageType: 'openclaw_bot_heartbeat',
72
+ _userId: Number(account.userId) || 0,
73
+ source: 'client',
74
+ content: {
75
+ bot_token: account.botToken,
76
+ status: '1'
77
+ }
78
+ }
79
+ ws?.send(JSON.stringify(heartbeat))
80
+ }
81
+ }
68
82
  const startHeartbeat = () => {
69
83
  stopHeartbeat()
70
84
  heartbeatTimer = setInterval(() => {
71
- if (ws?.readyState === WebSocket.OPEN) {
72
- const heartbeat = {
73
- messageType: 'openclaw_bot_heartbeat',
74
- _userId: Number(account.userId) || 0,
75
- source: 'client',
76
- content: {
77
- bot_token: account.botToken,
78
- status: '1'
79
- }
80
- }
81
- ws.send(JSON.stringify(heartbeat))
82
- }
85
+ onHeartbeat()
83
86
  }, HEARTBEAT_INTERVAL_MS)
84
87
  }
85
88
 
@@ -94,6 +97,7 @@ export async function monitorDcgchatProvider(opts: MonitorDcgchatOpts): Promise<
94
97
  dcgLogger(`socket connected`)
95
98
  setWsConnection(ws)
96
99
  startHeartbeat()
100
+ onHeartbeat()
97
101
  })
98
102
 
99
103
  ws.on('message', async (data) => {
@@ -109,7 +113,7 @@ export async function monitorDcgchatProvider(opts: MonitorDcgchatOpts): Promise<
109
113
  const heartbeat = isOpenclawBotHeartbeat(data, parsed)
110
114
  if (heartbeat) {
111
115
  heartbeatLogCounter += 1
112
- if (heartbeatLogCounter % 10 === 0) {
116
+ if (heartbeatLogCounter % 10 === 0 || heartbeatLogCounter === 1) {
113
117
  dcgLogger(`${parsed?.messageType}, ${payloadStr}`)
114
118
  dcgLogger(`heartbeat ack received, ${payloadStr}`)
115
119
  }
package/src/tool.ts CHANGED
@@ -109,7 +109,7 @@ export function monitoringToolMessage(api: OpenClawPluginApi) {
109
109
  if (event.lastAssistant?.errorMessage === '429-账户额度耗尽') {
110
110
  const message = '您的积分已消耗完,您可以通过充值积分来继续使用'
111
111
  sendText(message, msgCtx, { message_tags: { insufficient_balance: 1 }, is_finish: -1 })
112
- sendFinal(msgCtx)
112
+ sendFinal(msgCtx, '积分不足')
113
113
  return
114
114
  }
115
115
  }
package/src/transport.ts CHANGED
@@ -162,8 +162,8 @@ export function sendChunk(text: string, ctx: IMsgParams, chunkIdx: number): bool
162
162
  return wsSend(ctx, { response: text, state: 'chunk', chunk_idx: chunkIdx })
163
163
  }
164
164
 
165
- export function sendFinal(ctx: IMsgParams): boolean {
166
- dcgLogger(` message handling complete state: final`)
165
+ export function sendFinal(ctx: IMsgParams, tag?: string): boolean {
166
+ dcgLogger(` message handling complete state: final tag:${tag}`)
167
167
  return wsSend(ctx, { response: '', state: 'final' })
168
168
  }
169
169