@dcrays/dcgchat-test 0.3.25 → 0.3.26
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 +1 -1
- package/src/channel.ts +5 -5
- package/src/cron.ts +7 -11
- package/src/request/request.ts +5 -11
- package/src/tool.ts +3 -11
- package/src/transport.ts +5 -4
- package/src/utils/params.ts +15 -11
package/package.json
CHANGED
package/src/channel.ts
CHANGED
|
@@ -5,18 +5,18 @@ import { ossUpload } from './request/oss.js'
|
|
|
5
5
|
import { addSentMediaKey, getCronMessageId, getOpenClawConfig, hasSentMediaKey } from './utils/global.js'
|
|
6
6
|
import { isWsOpen, mergeDefaultParams, mergeSessionParams, sendFinal, wsSendRaw } from './transport.js'
|
|
7
7
|
import { dcgLogger, setLogger } from './utils/log.js'
|
|
8
|
-
import {
|
|
8
|
+
import { getOutboundMsgParams } from './utils/params.js'
|
|
9
9
|
import { startDcgchatGatewaySocket } from './gateway/socket.js'
|
|
10
10
|
|
|
11
11
|
export type DcgchatMediaSendOptions = {
|
|
12
|
-
/** 与 setParamsMessage / map 一致,用于
|
|
12
|
+
/** 与 setParamsMessage / map 一致,用于 getOutboundMsgParams */
|
|
13
13
|
sessionKey: string
|
|
14
14
|
mediaUrl?: string
|
|
15
15
|
text?: string
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export async function sendDcgchatMedia(opts: DcgchatMediaSendOptions): Promise<void> {
|
|
19
|
-
const msgCtx =
|
|
19
|
+
const msgCtx = getOutboundMsgParams(opts.sessionKey ?? '')
|
|
20
20
|
if (!isWsOpen()) {
|
|
21
21
|
dcgLogger(`outbound media skipped -> ws not open: ${opts.mediaUrl ?? ''}`)
|
|
22
22
|
return
|
|
@@ -147,7 +147,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
147
147
|
const isCron = ctx.to.indexOf('dcg-cron:') >= 0
|
|
148
148
|
const to = ctx.to.replace('dcg-cron:', '')
|
|
149
149
|
dcgLogger(`channel sendText to ${ctx.to} `)
|
|
150
|
-
const outboundCtx =
|
|
150
|
+
const outboundCtx = getOutboundMsgParams(to)
|
|
151
151
|
const cronMsgId = getCronMessageId(to)
|
|
152
152
|
const messageId = !!cronMsgId ? cronMsgId : isCron ? `${Date.now()}` : outboundCtx?.messageId
|
|
153
153
|
if (isWsOpen()) {
|
|
@@ -176,7 +176,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
176
176
|
},
|
|
177
177
|
sendMedia: async (ctx) => {
|
|
178
178
|
const to = ctx.to.replace('dcg-cron:', '')
|
|
179
|
-
const msgCtx =
|
|
179
|
+
const msgCtx = getOutboundMsgParams(to)
|
|
180
180
|
const cronMsgId = getCronMessageId(to)
|
|
181
181
|
const isCron = ctx.to.indexOf('dcg-cron:') >= 0
|
|
182
182
|
const messageId = !!cronMsgId ? cronMsgId : isCron ? `${Date.now()}` : msgCtx?.messageId
|
package/src/cron.ts
CHANGED
|
@@ -2,18 +2,11 @@ import path from 'node:path'
|
|
|
2
2
|
import fs from 'node:fs'
|
|
3
3
|
import type { IMsgParams } from './types.js'
|
|
4
4
|
import { isWsOpen, mergeDefaultParams, sendEventMessage, sendFinal } from './transport.js'
|
|
5
|
-
import {
|
|
6
|
-
getCronMessageId,
|
|
7
|
-
getWorkspaceDir,
|
|
8
|
-
getWsConnection,
|
|
9
|
-
removeCronMessageId,
|
|
10
|
-
setCronMessageId,
|
|
11
|
-
setMsgStatus
|
|
12
|
-
} from './utils/global.js'
|
|
5
|
+
import { getCronMessageId, getWorkspaceDir, getWsConnection, removeCronMessageId, setCronMessageId } from './utils/global.js'
|
|
13
6
|
import { ossUpload } from './request/oss.js'
|
|
14
7
|
import { dcgLogger } from './utils/log.js'
|
|
15
8
|
import { sendMessageToGateway } from './gateway/socket.js'
|
|
16
|
-
import {
|
|
9
|
+
import { getEffectiveMsgParams } from './utils/params.js'
|
|
17
10
|
|
|
18
11
|
export function getCronJobsPath(): string {
|
|
19
12
|
const workspaceDir = getWorkspaceDir()
|
|
@@ -89,12 +82,15 @@ function flushCronUploadQueue(): void {
|
|
|
89
82
|
* 将 jobs.json 同步到 OSS 并推送事件。30s 内多次调用合并为一次上传;定时触发后清空待处理项,避免重复执行。
|
|
90
83
|
* @param msgCtx 可选;省略时使用当前会话 getEffectiveMsgParams(sessionKey) 快照
|
|
91
84
|
*/
|
|
92
|
-
export function sendDcgchatCron(): void {
|
|
93
|
-
const
|
|
85
|
+
export function sendDcgchatCron(jobId: string): void {
|
|
86
|
+
const jobPath = getCronJobsPath()
|
|
87
|
+
const { sessionKey } = readCronJob(jobPath, jobId) || {}
|
|
88
|
+
const ctx = msgParamsToCtx(getEffectiveMsgParams(sessionKey))
|
|
94
89
|
if (!ctx) {
|
|
95
90
|
dcgLogger('sendDcgchatCron: no message context (missing token / params)', 'error')
|
|
96
91
|
return
|
|
97
92
|
}
|
|
93
|
+
dcgLogger(`sessionKey: ${sessionKey}, jobId: ${jobId}`)
|
|
98
94
|
pendingCronUploadCtx = ctx
|
|
99
95
|
if (cronUploadFlushTimer !== null) {
|
|
100
96
|
clearTimeout(cronUploadFlushTimer)
|
package/src/request/request.ts
CHANGED
|
@@ -3,7 +3,7 @@ import axios from 'axios'
|
|
|
3
3
|
import md5 from 'md5'
|
|
4
4
|
import type { IResponse } from '../types.js'
|
|
5
5
|
import { getUserTokenCache } from './userInfo.js'
|
|
6
|
-
import {
|
|
6
|
+
import { getEffectiveMsgParams } from '../utils/params.js'
|
|
7
7
|
import { ENV } from '../utils/constant.js'
|
|
8
8
|
import { dcgLogger } from '../utils/log.js'
|
|
9
9
|
|
|
@@ -39,9 +39,7 @@ function toCurl(config: {
|
|
|
39
39
|
}): string {
|
|
40
40
|
const base = config.baseURL ?? ''
|
|
41
41
|
const path = config.url ?? ''
|
|
42
|
-
const url = path.startsWith('http')
|
|
43
|
-
? path
|
|
44
|
-
: `${base.replace(/\/$/, '')}/${path.replace(/^\//, '')}`
|
|
42
|
+
const url = path.startsWith('http') ? path : `${base.replace(/\/$/, '')}/${path.replace(/^\//, '')}`
|
|
45
43
|
const method = (config.method ?? 'GET').toUpperCase()
|
|
46
44
|
const headers = config.headers ?? {}
|
|
47
45
|
const parts = ['curl', '-X', method, `'${url}'`]
|
|
@@ -82,9 +80,7 @@ export function getSignature(
|
|
|
82
80
|
sortedKeys
|
|
83
81
|
.map((key) => {
|
|
84
82
|
const val = map[key as keyof typeof map]
|
|
85
|
-
return val === undefined
|
|
86
|
-
? ''
|
|
87
|
-
: `${key}${typeof val === 'object' ? JSON.stringify(val) : val}`
|
|
83
|
+
return val === undefined ? '' : `${key}${typeof val === 'object' ? JSON.stringify(val) : val}`
|
|
88
84
|
})
|
|
89
85
|
.join('') + signKey[ENV]
|
|
90
86
|
// 4. MD5 加密并转大写
|
|
@@ -130,9 +126,7 @@ axiosInstance.interceptors.request.use(
|
|
|
130
126
|
if (cachedToken) {
|
|
131
127
|
config.headers = config.headers || {}
|
|
132
128
|
config.headers.authorization = cachedToken
|
|
133
|
-
dcgLogger(
|
|
134
|
-
`[request] auto-injected userToken from cache for botToken=${botToken.slice(0, 10)}...`
|
|
135
|
-
)
|
|
129
|
+
dcgLogger(`[request] auto-injected userToken from cache for botToken=${botToken.slice(0, 10)}...`)
|
|
136
130
|
}
|
|
137
131
|
}
|
|
138
132
|
|
|
@@ -172,7 +166,7 @@ export function post<T = Record<string, unknown>, R = unknown>(
|
|
|
172
166
|
botToken?: string
|
|
173
167
|
}
|
|
174
168
|
): Promise<IResponse<R>> {
|
|
175
|
-
const params = getEffectiveMsgParams(
|
|
169
|
+
const params = getEffectiveMsgParams() || { appId: 100 }
|
|
176
170
|
const config: any = {
|
|
177
171
|
method: 'POST',
|
|
178
172
|
url,
|
package/src/tool.ts
CHANGED
|
@@ -2,12 +2,9 @@ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk'
|
|
|
2
2
|
import { getMsgStatus } from './utils/global.js'
|
|
3
3
|
import { dcgLogger } from './utils/log.js'
|
|
4
4
|
import { sendFinal, sendText, wsSendRaw } from './transport.js'
|
|
5
|
-
import {
|
|
6
|
-
import { channelInfo, ENV } from './utils/constant.js'
|
|
5
|
+
import { getEffectiveMsgParams } from './utils/params.js'
|
|
7
6
|
import { cronToolCall } from './cronToolCall.js'
|
|
8
7
|
|
|
9
|
-
let toolCallId = ''
|
|
10
|
-
let toolName = ''
|
|
11
8
|
type PluginHookName =
|
|
12
9
|
| 'before_model_resolve'
|
|
13
10
|
| 'before_prompt_build'
|
|
@@ -56,13 +53,8 @@ const eventList = [
|
|
|
56
53
|
|
|
57
54
|
function sendToolCallMessage(sk: string, text: string, toolCallId: string, isCover: number) {
|
|
58
55
|
const params = getEffectiveMsgParams(sk)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
tool_call_id: toolCallId,
|
|
62
|
-
is_cover: isCover,
|
|
63
|
-
thinking_content: text,
|
|
64
|
-
response: ''
|
|
65
|
-
})
|
|
56
|
+
const content = { is_finish: -1, tool_call_id: toolCallId, is_cover: isCover, thinking_content: text, response: '' }
|
|
57
|
+
wsSendRaw(params, content, false)
|
|
66
58
|
}
|
|
67
59
|
|
|
68
60
|
/**
|
package/src/transport.ts
CHANGED
|
@@ -150,12 +150,13 @@ export function wsSend(ctx: IMsgParams, content: Record<string, unknown>): boole
|
|
|
150
150
|
* 媒体 / channel 出站:content 保持嵌套对象(单次编码)。
|
|
151
151
|
* `ctx` 须由调用方解析(如需合并覆盖可先 mergeSessionParams)。
|
|
152
152
|
*/
|
|
153
|
-
export function wsSendRaw(ctx: IMsgParams, content: Record<string, unknown
|
|
153
|
+
export function wsSendRaw(ctx: IMsgParams, content: Record<string, unknown>, isLog = true): boolean {
|
|
154
154
|
const ws = getWsConnection()
|
|
155
155
|
if (isWsOpen()) {
|
|
156
156
|
ws?.send(JSON.stringify(buildOpenclawBotChat(ctx, content, { mergeChannelDefaults: true })))
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
if (isLog) {
|
|
158
|
+
dcgLogger('已发送:' + JSON.stringify(buildOpenclawBotChat(ctx, content, { mergeChannelDefaults: true })))
|
|
159
|
+
}
|
|
159
160
|
}
|
|
160
161
|
return true
|
|
161
162
|
}
|
|
@@ -195,7 +196,7 @@ export function sendEventMessage(url: string, sessionKey: string) {
|
|
|
195
196
|
bot_id: ctx.botId,
|
|
196
197
|
agent_id: ctx.agentId,
|
|
197
198
|
session_id: ctx.sessionId,
|
|
198
|
-
message_id:
|
|
199
|
+
message_id: Date.now().toString()
|
|
199
200
|
}
|
|
200
201
|
})
|
|
201
202
|
)
|
package/src/utils/params.ts
CHANGED
|
@@ -7,12 +7,9 @@ import type { DcgchatConfig, IMsgParams } from '../types.js'
|
|
|
7
7
|
*/
|
|
8
8
|
const paramsMessageMap = new Map<string, IMsgParams>()
|
|
9
9
|
|
|
10
|
-
/** 最近一次 setParamsMessage 的 key,供不传参的 getEffectiveMsgParams() 使用 */
|
|
11
|
-
let currentSessionKey: string | null = null
|
|
12
|
-
|
|
13
10
|
/** 从 OpenClaw 配置读取当前 channel 的基础参数(唯一来源,供 transport / resolve 等复用) */
|
|
14
11
|
export function getParamsDefaults(): IMsgParams {
|
|
15
|
-
const ch = (getOpenClawConfig()?.channels?.[
|
|
12
|
+
const ch = (getOpenClawConfig()?.channels?.['dcgchat'] as DcgchatConfig | undefined) ?? {}
|
|
16
13
|
return {
|
|
17
14
|
userId: Number(ch.userId ?? 0),
|
|
18
15
|
botToken: ch.botToken ?? '',
|
|
@@ -45,14 +42,25 @@ export function resolveParamsMessage(params: Partial<IMsgParams>): IMsgParams {
|
|
|
45
42
|
* 统一取值入口:显式 sessionKey,或回落到当前会话;再与配置缺省 merge,保证字段完整。
|
|
46
43
|
*/
|
|
47
44
|
export function getEffectiveMsgParams(sessionKey?: string): IMsgParams {
|
|
48
|
-
const
|
|
49
|
-
const stored = key ? paramsMessageMap.get(key) : undefined
|
|
45
|
+
const stored = sessionKey ? paramsMessageMap.get(sessionKey) : undefined
|
|
50
46
|
return stored ? resolveParamsMessage(stored) : getParamsDefaults()
|
|
51
47
|
}
|
|
52
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Agent `message` 工具常把 `target` 设为用户 ID(如 "150"),而 `setParamsMessage` 使用的 key 是
|
|
51
|
+
* `effectiveSessionKey`(如 `agent:main:mobook:direct:...`)。若按 preferredKey 查不到 map,
|
|
52
|
+
* 则回落到当前会话 `currentSessionKey`,避免拿到空 `messageId` / `sessionId` 导致无文件卡片、WS 上下文错误。
|
|
53
|
+
*/
|
|
54
|
+
export function getOutboundMsgParams(preferredKey: string): IMsgParams {
|
|
55
|
+
const k = preferredKey?.trim()
|
|
56
|
+
if (k && paramsMessageMap.has(k)) {
|
|
57
|
+
return getEffectiveMsgParams(k)
|
|
58
|
+
}
|
|
59
|
+
return getEffectiveMsgParams()
|
|
60
|
+
}
|
|
61
|
+
|
|
53
62
|
export function setParamsMessage(sessionKey: string, params: Partial<IMsgParams>) {
|
|
54
63
|
if (!sessionKey) return
|
|
55
|
-
currentSessionKey = sessionKey
|
|
56
64
|
const previous = paramsMessageMap.get(sessionKey)
|
|
57
65
|
const base = previous ? resolveParamsMessage(previous) : getParamsDefaults()
|
|
58
66
|
paramsMessageMap.set(sessionKey, resolveParamsMessage({ ...base, ...params, sessionKey }))
|
|
@@ -61,7 +69,3 @@ export function setParamsMessage(sessionKey: string, params: Partial<IMsgParams>
|
|
|
61
69
|
export function getParamsMessage(sessionKey: string): IMsgParams | undefined {
|
|
62
70
|
return paramsMessageMap.get(sessionKey)
|
|
63
71
|
}
|
|
64
|
-
|
|
65
|
-
export function getCurrentSessionKey(): string | null {
|
|
66
|
-
return currentSessionKey
|
|
67
|
-
}
|