@dcrays/dcgchat-test 0.2.34 → 0.3.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/index.ts CHANGED
@@ -4,6 +4,7 @@ import { dcgchatPlugin } from './src/channel.js'
4
4
  import { setDcgchatRuntime, setWorkspaceDir } from './src/utils/global.js'
5
5
  import { monitoringToolMessage } from './src/tool.js'
6
6
  import { setOpenClawConfig } from './src/utils/global.js'
7
+ import { startDcgchatGatewaySocket } from './src/gateway/socket.js'
7
8
 
8
9
  const plugin = {
9
10
  id: "dcgchat-test",
@@ -15,6 +16,7 @@ const plugin = {
15
16
 
16
17
  monitoringToolMessage(api)
17
18
  setOpenClawConfig(api.config)
19
+ startDcgchatGatewaySocket()
18
20
  api.registerChannel({ plugin: dcgchatPlugin })
19
21
  setWorkspaceDir(api.config?.agents?.defaults?.workspace)
20
22
  api.registerTool((ctx) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/dcgchat-test",
3
- "version": "0.2.34",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "OpenClaw channel plugin for 书灵墨宝 (WebSocket)",
6
6
  "main": "index.ts",
package/src/bot.ts CHANGED
@@ -7,9 +7,11 @@ import { clearSentMediaKeys, getDcgchatRuntime, getOpenClawConfig, getWorkspaceD
7
7
  import { resolveAccount, sendDcgchatMedia } from './channel.js'
8
8
  import { generateSignUrl } from './request/api.js'
9
9
  import { extractMobookFiles } from './utils/searchFile.js'
10
- import { createMsgContext, sendChunk, sendFinal, sendText as sendTextMsg, sendError, sendText } from './transport.js'
10
+ import { sendChunk, sendFinal, sendText as sendTextMsg, sendError } from './transport.js'
11
11
  import { dcgLogger } from './utils/log.js'
12
12
  import { channelInfo, systemCommand, interruptCommand, ENV } from './utils/constant.js'
13
+ import { sendMessageToGateway } from './gateway/socket.js'
14
+ import { getEffectiveMsgParams, setParamsMessage } from './utils/params.js'
13
15
 
14
16
  type MediaInfo = {
15
17
  path: string
@@ -23,16 +25,7 @@ type TFileInfo = { name: string; url: string }
23
25
  const mediaMaxBytes = 300 * 1024 * 1024
24
26
 
25
27
  /** Active LLM generation abort controllers, keyed by conversationId */
26
- const activeGenerations = new Map<string, AbortController>()
27
-
28
- /** Abort an in-progress LLM generation for a given conversationId */
29
- export function abortMobookappGeneration(conversationId: string): void {
30
- const ctrl = activeGenerations.get(conversationId)
31
- if (ctrl) {
32
- ctrl.abort()
33
- activeGenerations.delete(conversationId)
34
- }
35
- }
28
+ // const activeGenerations = new Map<string, AbortController>()
36
29
 
37
30
  /**
38
31
  * Extract agentId from conversation_id formatted as "agentId::suffix".
@@ -124,16 +117,8 @@ function resolveReplyMediaList(payload: ReplyPayload): string[] {
124
117
  * 处理一条用户消息,调用 Agent 并返回回复
125
118
  */
126
119
  export async function handleDcgchatMessage(msg: InboundMessage, accountId: string): Promise<void> {
127
- const msgCtx = createMsgContext(msg)
128
-
129
120
  let finalSent = false
130
121
 
131
- const safeSendFinal = () => {
132
- if (finalSent) return
133
- finalSent = true
134
- sendFinal(msgCtx)
135
- }
136
-
137
122
  let completeText = ''
138
123
  const config = getOpenClawConfig()
139
124
  if (!config) {
@@ -142,43 +127,64 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
142
127
  }
143
128
  const account = resolveAccount(config, accountId)
144
129
  const userId = msg._userId.toString()
130
+
131
+ const core = getDcgchatRuntime()
132
+
133
+ const conversationId = msg.content.session_id?.trim()
134
+ const agentId = msg.content.agent_id?.trim()
135
+ const real_mobook = msg.content.real_mobook?.toString().trim()
136
+
137
+ const route = core.channel.routing.resolveAgentRoute({
138
+ cfg: config,
139
+ channel: "dcgchat-test",
140
+ accountId: account.accountId,
141
+ peer: { kind: 'direct', id: conversationId }
142
+ })
143
+
144
+ const embeddedAgentId = extractAgentIdFromConversationId(conversationId)
145
+
146
+ const effectiveAgentId = embeddedAgentId ?? route.agentId
147
+ const effectiveSessionKey =
148
+ real_mobook === '1' ? route.sessionKey : `agent:main:mobook:direct:${agentId}:${conversationId}`.toLowerCase()
149
+
150
+ setParamsMessage(effectiveSessionKey, {
151
+ userId: msg._userId,
152
+ botToken: msg.content.bot_token,
153
+ sessionId: conversationId,
154
+ messageId: msg.content.message_id,
155
+ domainId: msg.content.domain_id,
156
+ appId: msg.content.app_id,
157
+ botId: msg.content.bot_id ?? '',
158
+ agentId: msg.content.agent_id ?? '',
159
+ sessionKey: effectiveSessionKey,
160
+ real_mobook
161
+ })
162
+ const outboundCtx = getEffectiveMsgParams(effectiveSessionKey)
163
+ const agentEntry =
164
+ effectiveAgentId && effectiveAgentId !== 'main' ? config.agents?.list?.find((a) => a.id === effectiveAgentId) : undefined
165
+ const agentDisplayName = agentEntry?.name ?? (effectiveAgentId && effectiveAgentId !== 'main' ? effectiveAgentId : undefined)
166
+
167
+ const safeSendFinal = () => {
168
+ if (finalSent) return
169
+ finalSent = true
170
+ sendFinal(outboundCtx)
171
+ }
172
+
145
173
  const text = msg.content.text?.trim()
146
174
 
147
175
  if (!text) {
148
- sendTextMsg(msgCtx, '你需要我帮你做什么呢?')
176
+ sendTextMsg('你需要我帮你做什么呢?', outboundCtx)
149
177
  safeSendFinal()
150
178
  return
151
179
  }
152
180
 
153
181
  try {
154
- const core = getDcgchatRuntime()
155
-
156
- const conversationId = msg.content.session_id?.trim()
157
-
158
- const route = core.channel.routing.resolveAgentRoute({
159
- cfg: config,
160
- channel: "dcgchat-test",
161
- accountId: account.accountId,
162
- peer: { kind: 'direct', id: conversationId }
163
- })
164
-
165
- // If conversation_id encodes an agentId prefix ("agentId::suffix"), override the route.
166
- const embeddedAgentId = extractAgentIdFromConversationId(conversationId)
167
- const effectiveAgentId = embeddedAgentId ?? route.agentId
168
- const effectiveSessionKey = embeddedAgentId
169
- ? `agent:${embeddedAgentId}:mobook:direct:${conversationId}`.toLowerCase()
170
- : route.sessionKey
171
-
172
- const agentEntry =
173
- effectiveAgentId && effectiveAgentId !== 'main' ? config.agents?.list?.find((a) => a.id === effectiveAgentId) : undefined
174
- const agentDisplayName = agentEntry?.name ?? (effectiveAgentId && effectiveAgentId !== 'main' ? effectiveAgentId : undefined)
175
-
176
182
  // Abort any existing generation for this conversation, then start a new one
177
- const existingCtrl = activeGenerations.get(conversationId)
178
- if (existingCtrl) existingCtrl.abort()
179
- const genCtrl = new AbortController()
180
- const genSignal = genCtrl.signal
181
- activeGenerations.set(conversationId, genCtrl)
183
+ // const existingCtrl = activeGenerations.get(conversationId)
184
+ // if (existingCtrl) existingCtrl.abort()
185
+ // const genCtrl = new AbortController()
186
+ // const genSignal = genCtrl.signal
187
+ // activeGenerations.set(conversationId, genCtrl)
182
188
 
183
189
  // 处理用户上传的文件
184
190
  const files = msg.content.files ?? []
@@ -242,7 +248,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
242
248
  const key = getMediaKey(mediaUrl)
243
249
  if (sentMediaKeys.has(key)) continue
244
250
  sentMediaKeys.add(key)
245
- await sendDcgchatMedia({ msgCtx, mediaUrl, text: '' })
251
+ await sendDcgchatMedia({ sessionKey: effectiveSessionKey, mediaUrl, text: '' })
246
252
  }
247
253
  },
248
254
  onError: (err: unknown, info: { kind: string }) => {
@@ -254,7 +260,6 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
254
260
  }
255
261
  })
256
262
 
257
- let wasAborted = false
258
263
  try {
259
264
  if (systemCommand.includes(text?.trim())) {
260
265
  dcgLogger(`dispatching /new`)
@@ -269,7 +274,12 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
269
274
  })
270
275
  } else if (interruptCommand.includes(text?.trim())) {
271
276
  dcgLogger(`interrupt command: ${text}`)
272
- abortMobookappGeneration(conversationId)
277
+ sendMessageToGateway(
278
+ JSON.stringify({
279
+ method: 'chat.abort',
280
+ params: { sessionKey: effectiveSessionKey }
281
+ })
282
+ )
273
283
  safeSendFinal()
274
284
  return
275
285
  } else {
@@ -280,7 +290,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
280
290
  dispatcher,
281
291
  replyOptions: {
282
292
  ...replyOptions,
283
- abortSignal: genSignal,
293
+ // abortSignal: genSignal,
284
294
  onModelSelected: prefixContext.onModelSelected,
285
295
  onPartialReply: async (payload: ReplyPayload) => {
286
296
  // Accumulate full text
@@ -293,7 +303,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
293
303
  ? payload.text.slice(streamedTextLen)
294
304
  : payload.text
295
305
  if (delta.trim()) {
296
- sendChunk(msgCtx, delta)
306
+ sendChunk(delta, outboundCtx)
297
307
  dcgLogger(`[stream]: chunk ${delta.length} chars to user ${msg._userId} ${delta.slice(0, 100)}`)
298
308
  }
299
309
  streamedTextLen = payload.text.length
@@ -304,26 +314,26 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
304
314
  const key = getMediaKey(mediaUrl)
305
315
  if (sentMediaKeys.has(key)) continue
306
316
  sentMediaKeys.add(key)
307
- await sendDcgchatMedia({ msgCtx, mediaUrl, text: '' })
317
+ await sendDcgchatMedia({ sessionKey: effectiveSessionKey, mediaUrl, text: '' })
308
318
  }
309
319
  }
310
320
  }
311
321
  })
312
322
  }
313
323
  } catch (err: unknown) {
314
- if (genSignal.aborted) {
315
- wasAborted = true
316
- dcgLogger(` generation aborted for conversationId=${conversationId}`)
317
- } else if (err instanceof Error && err.name === 'AbortError') {
318
- wasAborted = true
319
- dcgLogger(` generation aborted for conversationId=${conversationId}`)
320
- } else {
321
- dcgLogger(` dispatchReplyFromConfig error: ${String(err)}`, 'error')
322
- }
324
+ // if (genSignal.aborted) {
325
+ // wasAborted = true
326
+ // dcgLogger(` generation aborted for conversationId=${conversationId}`)
327
+ // } else if (err instanceof Error && err.name === 'AbortError') {
328
+ // wasAborted = true
329
+ // dcgLogger(` generation aborted for conversationId=${conversationId}`)
330
+ // } else {
331
+ // dcgLogger(` dispatchReplyFromConfig error: ${String(err)}`, 'error')
332
+ // }
323
333
  } finally {
324
- if (activeGenerations.get(conversationId) === genCtrl) {
325
- activeGenerations.delete(conversationId)
326
- }
334
+ // if (activeGenerations.get(conversationId) === genCtrl) {
335
+ // activeGenerations.delete(conversationId)
336
+ // }
327
337
  }
328
338
  try {
329
339
  markRunComplete()
@@ -345,7 +355,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
345
355
  const resolved = candidates.find((p) => fs.existsSync(p))
346
356
  if (!resolved) continue
347
357
  try {
348
- await sendDcgchatMedia({ msgCtx, mediaUrl: resolved, text: '' })
358
+ await sendDcgchatMedia({ sessionKey: effectiveSessionKey, mediaUrl: resolved, text: '' })
349
359
  } catch (err) {
350
360
  dcgLogger(` sendDcgchatMedia error: ${String(err)}`, 'error')
351
361
  }
@@ -371,7 +381,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
371
381
  })
372
382
  } catch (err) {
373
383
  dcgLogger(` handle message failed: ${String(err)}`, 'error')
374
- sendError(msgCtx, err instanceof Error ? err.message : String(err))
384
+ sendError(err instanceof Error ? err.message : String(err), outboundCtx)
375
385
  } finally {
376
386
  safeSendFinal()
377
387
  }
package/src/channel.ts CHANGED
@@ -2,36 +2,40 @@ import type { ChannelPlugin, OpenClawConfig } from 'openclaw/plugin-sdk'
2
2
  import { DEFAULT_ACCOUNT_ID } from 'openclaw/plugin-sdk'
3
3
  import type { ResolvedDcgchatAccount, DcgchatConfig } from './types.js'
4
4
  import { ossUpload } from './request/oss.js'
5
- import { addSentMediaKey, getMsgParams, hasSentMediaKey } from './utils/global.js'
6
- import { type DcgchatMsgContext, isWsOpen, sendFinal, wsSendRaw } from './transport.js'
5
+ import { addSentMediaKey, getOpenClawConfig, hasSentMediaKey } from './utils/global.js'
6
+ import { isWsOpen, mergeDefaultParams, mergeSessionParams, sendFinal, wsSendRaw } from './transport.js'
7
7
  import { dcgLogger, setLogger } from './utils/log.js'
8
+ import { getParamsDefaults, getEffectiveMsgParams, getCurrentSessionKey } from './utils/params.js'
8
9
 
9
10
  export type DcgchatMediaSendOptions = {
10
- msgCtx: DcgchatMsgContext
11
+ /** 与 setParamsMessage / map 一致,用于 getEffectiveMsgParams */
12
+ sessionKey: string
11
13
  mediaUrl?: string
12
14
  text?: string
13
15
  }
14
16
 
15
17
  export async function sendDcgchatMedia(opts: DcgchatMediaSendOptions): Promise<void> {
16
- const { msgCtx } = opts
18
+ const msgCtx = getEffectiveMsgParams(opts.sessionKey)
17
19
  if (!isWsOpen()) {
18
20
  dcgLogger(`outbound media skipped -> ws not open: ${opts.mediaUrl ?? ''}`)
19
21
  return
20
22
  }
21
23
 
22
24
  const mediaUrl = opts.mediaUrl
23
- if (mediaUrl && hasSentMediaKey(msgCtx.messageId, mediaUrl)) {
25
+ const dedupeId = msgCtx.messageId
26
+ if (mediaUrl && dedupeId && hasSentMediaKey(dedupeId, mediaUrl)) {
24
27
  dcgLogger(`dcgchat: sendMedia skipped (duplicate in session): ${mediaUrl}`)
25
28
  return
26
29
  }
27
- if (mediaUrl) {
28
- addSentMediaKey(msgCtx.messageId, mediaUrl)
30
+ if (mediaUrl && dedupeId) {
31
+ addSentMediaKey(dedupeId, mediaUrl)
29
32
  }
30
33
 
31
34
  const fileName = mediaUrl?.split(/[\\/]/).pop() || ''
32
35
 
33
36
  try {
34
- const url = opts.mediaUrl ? await ossUpload(opts.mediaUrl, msgCtx.botToken) : ''
37
+ const botToken = msgCtx.botToken ?? getOpenClawConfig()?.channels?.["dcgchat-test"]?.botToken ?? ''
38
+ const url = opts.mediaUrl ? await ossUpload(opts.mediaUrl, botToken, 1) : ''
35
39
  wsSendRaw(msgCtx, {
36
40
  response: opts.text ?? '',
37
41
  files: [{ url, name: fileName }]
@@ -61,22 +65,6 @@ export function resolveAccount(cfg: OpenClawConfig, accountId?: string | null):
61
65
  }
62
66
  }
63
67
 
64
- /** Build a DcgchatMsgContext for the outbound pipeline (uses global msgParams). */
65
- function createOutboundMsgContext(cfg: OpenClawConfig, accountId?: string | null): DcgchatMsgContext {
66
- const params = getMsgParams()
67
- const { botToken } = resolveAccount(cfg, accountId)
68
- return {
69
- userId: params.userId,
70
- botToken,
71
- domainId: params.domainId,
72
- appId: params.appId,
73
- botId: params.botId,
74
- agentId: params.agentId,
75
- sessionId: params.sessionId,
76
- messageId: params.messageId
77
- }
78
- }
79
-
80
68
  export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
81
69
  id: "dcgchat-test",
82
70
  meta: {
@@ -153,24 +141,30 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
153
141
  deliveryMode: 'direct',
154
142
  textChunkLimit: 4000,
155
143
  sendText: async (ctx) => {
156
- const msgCtx = createOutboundMsgContext(ctx.cfg, ctx.accountId)
157
144
  if (isWsOpen()) {
158
- wsSendRaw(msgCtx, { response: ctx.text })
159
- dcgLogger(`channel sendText to ${msgCtx.userId} ${ctx.text?.slice(0, 50)}`)
145
+ const merged = mergeDefaultParams({
146
+ agentId: ctx.accountId ?? '',
147
+ sessionId: ctx.to,
148
+ messageId: `${Date.now()}`
149
+ })
150
+ wsSendRaw(merged, { response: ctx.text })
151
+ sendFinal(merged)
152
+ dcgLogger(`channel sendText to ${ctx.to} ${ctx.text?.slice(0, 50)}`)
160
153
  }
161
154
  return {
162
155
  channel: "dcgchat-test",
163
156
  messageId: `dcg-${Date.now()}`,
164
- chatId: msgCtx.userId.toString()
157
+ chatId: ctx.to
165
158
  }
166
159
  },
167
160
  sendMedia: async (ctx) => {
168
- const msgCtx = createOutboundMsgContext(ctx.cfg, ctx.accountId)
169
- await sendDcgchatMedia({ msgCtx, mediaUrl: ctx.mediaUrl })
161
+ const sk = getCurrentSessionKey()
162
+ const msgCtx = getEffectiveMsgParams('sk')
163
+ await sendDcgchatMedia({ sessionKey: sk ?? '', mediaUrl: ctx.mediaUrl ?? '' })
170
164
  return {
171
165
  channel: "dcgchat-test",
172
166
  messageId: `dcg-${Date.now()}`,
173
- chatId: msgCtx.userId.toString()
167
+ chatId: msgCtx.userId?.toString()
174
168
  }
175
169
  }
176
170
  },
package/src/cron.ts ADDED
@@ -0,0 +1,138 @@
1
+ import path from 'node:path'
2
+ import fs from 'node:fs'
3
+ import crypto from 'node:crypto'
4
+ import { execFile } from 'node:child_process'
5
+ import { promisify } from 'node:util'
6
+
7
+ const execFileAsync = promisify(execFile)
8
+ import type { IMsgParams } from './types.js'
9
+ import { sendEventMessage } from './transport.js'
10
+ import { getWorkspaceDir } from './utils/global.js'
11
+ import { ossUpload } from './request/oss.js'
12
+ import { dcgLogger } from './utils/log.js'
13
+ import { sendMessageToGateway } from './gateway/socket.js'
14
+ import { channelInfo, ENV } from './utils/constant.js'
15
+ import { getCurrentSessionKey, getEffectiveMsgParams } from './utils/params.js'
16
+
17
+ export function getCronJobsPath(): string {
18
+ const workspaceDir = getWorkspaceDir()
19
+ const cronDir = workspaceDir.replace('workspace', 'cron')
20
+ return path.join(cronDir, 'jobs.json')
21
+ }
22
+
23
+ function msgParamsToCtx(p: IMsgParams): IMsgParams | null {
24
+ if (!p?.botToken) return null
25
+ return p
26
+ }
27
+
28
+ const CRON_UPLOAD_DEBOUNCE_MS = 30_000
29
+
30
+ /** 待合并的上传上下文(短时间内多次调用只保留最后一次) */
31
+ let pendingCronUploadCtx: IMsgParams | null = null
32
+ let cronUploadFlushTimer: ReturnType<typeof setTimeout> | null = null
33
+
34
+ async function runCronJobsUpload(msgCtx: IMsgParams): Promise<void> {
35
+ const jobPath = getCronJobsPath()
36
+ if (fs.existsSync(jobPath)) {
37
+ try {
38
+ const url = await ossUpload(jobPath, msgCtx.botToken ?? '', 0)
39
+ dcgLogger(`定时任务创建成功: ${url}`)
40
+ if (!msgCtx.sessionKey) {
41
+ dcgLogger('runCronJobsUpload: missing sessionKey on msgCtx', 'error')
42
+ return
43
+ }
44
+ sendEventMessage(url, msgCtx.sessionKey)
45
+ } catch (error) {
46
+ dcgLogger(`${jobPath} upload failed: ${error}`, 'error')
47
+ }
48
+ } else {
49
+ dcgLogger(`${jobPath} not found`, 'error')
50
+ }
51
+ }
52
+
53
+ function flushCronUploadQueue(): void {
54
+ cronUploadFlushTimer = null
55
+ const ctx = pendingCronUploadCtx
56
+ pendingCronUploadCtx = null
57
+ if (!ctx) return
58
+ void runCronJobsUpload(ctx)
59
+ }
60
+
61
+ /**
62
+ * 将 jobs.json 同步到 OSS 并推送事件。30s 内多次调用合并为一次上传;定时触发后清空待处理项,避免重复执行。
63
+ * @param msgCtx 可选;省略时使用当前会话 getEffectiveMsgParams(sessionKey) 快照
64
+ */
65
+ export function sendDcgchatCron(): void {
66
+ const ctx = msgParamsToCtx(getEffectiveMsgParams(getCurrentSessionKey() ?? ''))
67
+ if (!ctx) {
68
+ dcgLogger('sendDcgchatCron: no message context (missing token / params)', 'error')
69
+ return
70
+ }
71
+ pendingCronUploadCtx = ctx
72
+ if (cronUploadFlushTimer !== null) {
73
+ clearTimeout(cronUploadFlushTimer)
74
+ }
75
+ cronUploadFlushTimer = setTimeout(flushCronUploadQueue, CRON_UPLOAD_DEBOUNCE_MS)
76
+ }
77
+
78
+ /**
79
+ * 通过 OpenClaw CLI 删除定时任务(走 Gateway,与内存状态一致)。
80
+ * 文档:运行中请勿手改 jobs.json,应使用 `openclaw cron rm` 或工具 API。
81
+ */
82
+ export const onRemoveCronJob = async (jobId: string) => {
83
+ const id = jobId?.trim()
84
+ if (!id) {
85
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
86
+ return
87
+ }
88
+ sendMessageToGateway(JSON.stringify({ method: 'cron.remove', params: { id: jobId } }))
89
+ }
90
+ export const onDisabledCronJob = async (jobId: string) => {
91
+ const id = jobId?.trim()
92
+ if (!id) {
93
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
94
+ return
95
+ }
96
+ sendMessageToGateway(JSON.stringify({ method: 'cron.update', params: { id: jobId, patch: { enabled: false } } }))
97
+ }
98
+ export const onEnabledCronJob = async (jobId: string) => {
99
+ const id = jobId?.trim()
100
+ if (!id) {
101
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
102
+ return
103
+ }
104
+ sendMessageToGateway(JSON.stringify({ method: 'cron.update', params: { id: jobId, patch: { enabled: true } } }))
105
+ }
106
+ export const onRunCronJob = async (jobId: string) => {
107
+ const id = jobId?.trim()
108
+ if (!id) {
109
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
110
+ return
111
+ }
112
+ sendMessageToGateway(JSON.stringify({ method: 'cron.update', jobId }))
113
+ }
114
+ export const updateCronJobSessionKey = async (jobId: string) => {
115
+ const id = jobId?.trim()
116
+ if (!id) {
117
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
118
+ return
119
+ }
120
+ const params = getEffectiveMsgParams(getCurrentSessionKey() ?? '')
121
+ sendMessageToGateway(
122
+ JSON.stringify({
123
+ method: 'cron.update',
124
+ params: {
125
+ id: jobId,
126
+ patch: {
127
+ sessionKey: params.sessionKey,
128
+ delivery: {
129
+ channel: "dcgchat-test",
130
+ to: params.sessionId,
131
+ accountId: 14,
132
+ bestEffort: true
133
+ }
134
+ }
135
+ }
136
+ })
137
+ )
138
+ }