@dcrays/dcgchat-test 0.6.10 → 0.6.12

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.
Files changed (60) hide show
  1. package/README.md +167 -0
  2. package/index.ts +35 -0
  3. package/openclaw.plugin.json +12 -41
  4. package/package.json +35 -8
  5. package/src/agent.ts +568 -0
  6. package/src/bot.ts +646 -0
  7. package/src/channel/index.ts +329 -0
  8. package/src/channel/outboundMedia.ts +144 -0
  9. package/src/channel/outboundTarget.ts +62 -0
  10. package/src/channel/uploadMediaUrl.ts +76 -0
  11. package/src/cron/message.ts +114 -0
  12. package/src/cron/params.ts +164 -0
  13. package/src/cron/toolGuard.ts +466 -0
  14. package/src/cron/types.ts +15 -0
  15. package/src/gateway/index.ts +430 -0
  16. package/src/gateway/security.ts +95 -0
  17. package/src/gateway/socket.ts +256 -0
  18. package/src/libs/ali-oss-6.23.0.tgz +0 -0
  19. package/src/libs/axios-1.13.6.tgz +0 -0
  20. package/src/libs/md5-2.3.0.tgz +0 -0
  21. package/src/libs/mime-types-3.0.2.tgz +0 -0
  22. package/src/libs/unzipper-0.12.3.tgz +0 -0
  23. package/src/libs/ws-8.19.0.tgz +0 -0
  24. package/src/monitor.ts +269 -0
  25. package/src/request/api.ts +80 -0
  26. package/src/request/oss.ts +200 -0
  27. package/src/request/request.ts +191 -0
  28. package/src/request/userInfo.ts +44 -0
  29. package/src/session.ts +28 -0
  30. package/src/skill.ts +114 -0
  31. package/src/tool.ts +603 -0
  32. package/src/tools/messageTool.ts +334 -0
  33. package/src/tools/toolCallGuard.ts +327 -0
  34. package/src/transport.ts +217 -0
  35. package/src/types.ts +139 -0
  36. package/src/utils/agentErrors.ts +116 -0
  37. package/src/utils/constant.ts +60 -0
  38. package/src/utils/env-config.ts +19 -0
  39. package/src/utils/formatLlmInputEvent.ts +48 -0
  40. package/src/utils/gatewayMsgHandler.ts +147 -0
  41. package/src/utils/global.ts +309 -0
  42. package/src/utils/inboundTurnState.ts +66 -0
  43. package/src/utils/log.ts +77 -0
  44. package/src/utils/mediaAttached.ts +244 -0
  45. package/src/utils/mediaEmitter.ts +54 -0
  46. package/src/utils/outboundAssistantText.ts +117 -0
  47. package/src/utils/params.ts +104 -0
  48. package/src/utils/passTxt.ts +4 -0
  49. package/src/utils/resolveRegisterConfig.ts +33 -0
  50. package/src/utils/searchFile.ts +228 -0
  51. package/src/utils/sessionState.ts +137 -0
  52. package/src/utils/sessionTermination.ts +228 -0
  53. package/src/utils/streamMerge.ts +150 -0
  54. package/src/utils/subagentRunMap.ts +71 -0
  55. package/src/utils/undiciFetchInterceptor.ts +346 -0
  56. package/src/utils/workspaceFilePaths.ts +18 -0
  57. package/src/utils/wsMessageHandler.ts +124 -0
  58. package/src/utils/zipExtract.ts +97 -0
  59. package/src/utils/zipPath.ts +24 -0
  60. package/index.js +0 -304
@@ -0,0 +1,114 @@
1
+ import { isWsOpen, mergeDefaultParams, sendFinal, wsSendRaw } from '../transport.js'
2
+ import {
3
+ getCronMessageId,
4
+ getWsConnection,
5
+ removeCronMessageId,
6
+ setCronMessageId,
7
+ takeApartSessionKey
8
+ } from '../utils/global.js'
9
+ import { dcgLogger } from '../utils/log.js'
10
+ import { sendGatewayRpc } from '../gateway/socket.js'
11
+ import { getParamsDefaults } from '../utils/params.js'
12
+ import { getSessionKeyByJobId } from './params.js'
13
+ import { deleteCronSessionKeyMap, deleteCronSessionKeyMapsForJob } from '../channel/outboundTarget.js'
14
+
15
+ /**
16
+ * 通过 OpenClaw CLI 删除定时任务(走 Gateway,与内存状态一致)。
17
+ * 文档:运行中请勿手改 jobs.json,应使用 `openclaw cron rm` 或工具 API。
18
+ */
19
+ export const onRemoveCronJob = async (jobId: string) => {
20
+ const id = jobId?.trim()
21
+ if (!id) {
22
+ dcgLogger('onRemoveCronJob: empty jobId', 'error')
23
+ return
24
+ }
25
+ try {
26
+ await sendGatewayRpc({ method: 'cron.remove', params: { id } })
27
+ } catch (err) {
28
+ dcgLogger(`onRemoveCronJob failed: id=${id}, error=${String(err)}`, 'error')
29
+ }
30
+ }
31
+ export const onDisabledCronJob = async (jobId: string) => {
32
+ const id = jobId?.trim()
33
+ if (!id) {
34
+ dcgLogger('onDisabledCronJob: empty jobId', 'error')
35
+ return
36
+ }
37
+ sendGatewayRpc({ method: 'cron.update', params: { id: jobId, patch: { enabled: false } } })
38
+ }
39
+ export const onEnabledCronJob = async (jobId: string) => {
40
+ const id = jobId?.trim()
41
+ if (!id) {
42
+ dcgLogger('onEnabledCronJob: empty jobId', 'error')
43
+ return
44
+ }
45
+ sendGatewayRpc({ method: 'cron.update', params: { id: jobId, patch: { enabled: true } } })
46
+ }
47
+ export const onRunCronJob = async (jobId: string, messageId: string) => {
48
+ const sessionKey = await getSessionKeyByJobId(jobId)
49
+ if (!sessionKey) {
50
+ dcgLogger(`onRunCronJob: no sessionKey for job id=${jobId}`, 'error')
51
+ return
52
+ }
53
+ setCronMessageId(sessionKey, messageId)
54
+ // sendGatewayRpc({
55
+ // method: 'cron.runs',
56
+ // params: { scope: 'job', id: jobId, limit: 50, offset: 0, status: 'all', sortDir: 'desc' }
57
+ // })
58
+ sendGatewayRpc({ method: 'cron.run', params: { id: jobId, mode: 'force' } })
59
+ }
60
+ /**
61
+ * 发送定时完成摘要(纯文本)。
62
+ */
63
+ export const finishedDcgchatCron = async (jobId: string, summary?: string) => {
64
+ if (!jobId) {
65
+ dcgLogger('finishedDcgchatCron: empty jobId', 'error')
66
+ return
67
+ }
68
+ const cronData = (await sendGatewayRpc({ method: 'cron.get', params: { id: jobId } })) as Record<string, any>
69
+ const sessionKey = cronData?.sessionKey || cronData.delivery?.to?.replace('dcg-cron:', '').trim()
70
+ const name = cronData?.name
71
+ const description = cronData?.description
72
+
73
+ const messageId = getCronMessageId(sessionKey) || `${Date.now()}`
74
+ const { sessionId, agentId } = takeApartSessionKey(sessionKey)
75
+ const merged = mergeDefaultParams({
76
+ agentId: agentId,
77
+ sessionId: `${sessionId}`,
78
+ messageId: messageId || `${Date.now()}`,
79
+ real_mobook: !sessionId ? 1 : ''
80
+ })
81
+ if (summary) {
82
+ wsSendRaw(merged, { response: summary, message_tags: { source: 'cron' }, is_finish: -1 })
83
+ }
84
+ setTimeout(() => {
85
+ sendFinal(merged, 'cron send', '', { message_tags: { isFinal: 1 } })
86
+ }, 1250)
87
+ const ws = getWsConnection()
88
+ const baseContent = getParamsDefaults()
89
+ if (isWsOpen()) {
90
+ ws?.send(
91
+ JSON.stringify({
92
+ messageType: 'openclaw_bot_event',
93
+ source: 'client',
94
+ content: {
95
+ event_type: 'notify',
96
+ operation_type: 'cron',
97
+ bot_token: baseContent.botToken,
98
+ app_id: baseContent.appId,
99
+ session_id: sessionId,
100
+ agent_id: agentId,
101
+ real_mobook: !sessionId ? 1 : '',
102
+ title: name,
103
+ description: description
104
+ }
105
+ })
106
+ )
107
+ }
108
+ setTimeout(() => {
109
+ removeCronMessageId(sessionKey)
110
+ deleteCronSessionKeyMapsForJob(jobId)
111
+ deleteCronSessionKeyMap(sessionKey)
112
+ }, 1200)
113
+ dcgLogger(`finishedDcgchatCron: job=${jobId} sessionKey=${sessionKey}`)
114
+ }
@@ -0,0 +1,164 @@
1
+ import { PluginHookAfterToolCallEvent } from 'openclaw/plugin-sdk/plugin-runtime'
2
+ import { dcgLogger } from '../utils/log.js'
3
+ import { CHANNEL_ID } from '../utils/constant.js'
4
+ import { sendGatewayRpc } from '../gateway/socket.js'
5
+ import { sendEventMessage } from '../transport.js'
6
+ import { isCronCreateExecCommand } from './toolGuard.js'
7
+
8
+ // 为处理的jobId列表
9
+ const processedJobIds = new Set<string>()
10
+ // 定时任务执行时间处理
11
+ export async function cronAddHandler(jobId: string) {
12
+ const hasSessionKey = await checkCronSessionKey(jobId, true)
13
+ if (!hasSessionKey) {
14
+ processedJobIds.add(jobId)
15
+ }
16
+ }
17
+ // 删除处理的jobId
18
+ export function removeProcessedJobId(jobId: string) {
19
+ processedJobIds.delete(jobId)
20
+ }
21
+
22
+ export async function getSessionKeyByJobId(jobId: string) {
23
+ const cronData = (await sendGatewayRpc({ method: 'cron.get', params: { id: jobId } })) as Record<string, any>
24
+ return cronData?.sessionKey || cronData.delivery?.to?.replace('dcg-cron:', '').trim()
25
+ }
26
+
27
+ /**
28
+ * 检查定时任务中是否含有sessionKey或deliveryTo,数据完整直接返回true,否则返回false 两者有一个补充数据更新
29
+ * @param jobId
30
+ * @returns
31
+ */
32
+ export async function checkCronSessionKey(jobId: string, isSend?: boolean) {
33
+ const cronData = (await sendGatewayRpc({ method: 'cron.get', params: { id: jobId } })) as Record<string, any>
34
+ if (!cronData) {
35
+ dcgLogger(`getJobIdBySessionKey failed for jobId: ${jobId}`, 'error')
36
+ return
37
+ }
38
+ const sessionKey = cronData?.sessionKey
39
+ const deliveryTo = cronData.delivery?.to?.replace('dcg-cron:', '').trim()
40
+ if (!sessionKey && !deliveryTo) {
41
+ dcgLogger(`checkCronSessionKey failed for jobId: ${jobId}`, 'error')
42
+ processedJobIds.add(jobId)
43
+ return false
44
+ }
45
+ if (sessionKey && deliveryTo) {
46
+ if (isSend) {
47
+ const params = {
48
+ event_type: 'cron',
49
+ operation_type: 'install',
50
+ data: cronData
51
+ }
52
+ sendEventMessage(params)
53
+ }
54
+ return true
55
+ }
56
+ return (await supplementSessionKey(jobId)) !== null
57
+ }
58
+
59
+ // 判断after_tool_call中是否含有jobId
60
+ export function getJobIdInAfterToolCall(event: PluginHookAfterToolCallEvent) {
61
+ if (event.toolName !== 'cron') return null
62
+ if (!isCronAddAction(event.params)) return
63
+ if (event.error) return
64
+
65
+ const result = event.result as { details?: { id?: unknown } }
66
+ const jobId = result.details?.id
67
+
68
+ if (typeof jobId === 'string') {
69
+ return jobId
70
+ }
71
+ const evtStr = JSON.stringify(event)
72
+ // 便利processedJobIds,找到包含在evtStr的jobId
73
+ for (const id of processedJobIds) {
74
+ if (evtStr.includes(id)) {
75
+ return id
76
+ }
77
+ }
78
+ return null
79
+ }
80
+
81
+ // 添加jobId -> sessionKey 映射
82
+ export async function cronAfterToolCallHandler(event: PluginHookAfterToolCallEvent, sessionKey: string) {
83
+ const jobId = getJobIdInAfterToolCall(event)
84
+ if (!jobId) return dcgLogger(`getJobIdInAfterToolCall failed for event not has jobId: ${JSON.stringify(event)}`, 'error')
85
+ jobIdToSessionKeyMap.set(jobId, sessionKey)
86
+ sessionKeyToJobIdMap.set(sessionKey, jobId)
87
+ const hasCompleteSessionKey = await checkCronSessionKey(jobId)
88
+ if (hasCompleteSessionKey) {
89
+ removeProcessedJobId(jobId)
90
+ return
91
+ }
92
+ if (processedJobIds.has(jobId)) {
93
+ await supplementSessionKey(jobId)
94
+ }
95
+ }
96
+
97
+ // jobId -> sessionKey 映射
98
+ const jobIdToSessionKeyMap = new Map<string, string>()
99
+ const sessionKeyToJobIdMap = new Map<string, string>()
100
+ // 获取jobId -> sessionKey 映射
101
+ function getJobIdToSessionKeyMap(jobId: string) {
102
+ return jobIdToSessionKeyMap.get(jobId)
103
+ }
104
+ // 删除jobId -> sessionKey 映射
105
+ export function removeJobIdToSessionKeyMap(jobId: string) {
106
+ const sessionKey = jobIdToSessionKeyMap.get(jobId)
107
+ jobIdToSessionKeyMap.delete(jobId)
108
+ if (sessionKey) sessionKeyToJobIdMap.delete(sessionKey)
109
+ }
110
+ // 补充定时任务数据
111
+ export async function supplementSessionKey(jobId: string) {
112
+ const sk = getJobIdToSessionKeyMap(jobId)
113
+ if (!sk) {
114
+ dcgLogger(`getJobIdToSessionKeyMap failed for jobId: ${jobId}`, 'error')
115
+ return null
116
+ }
117
+ const cronData = (await sendGatewayRpc({ method: 'cron.get', params: { id: jobId } })) as Record<string, any>
118
+ if (!cronData) {
119
+ dcgLogger(`getJobIdToSessionKeyMap failed for jobId: ${jobId}`, 'error')
120
+ return null
121
+ }
122
+ const patch = structuredClone(cronData)
123
+ patch.sessionKey = sk
124
+ if (!patch?.delivery) {
125
+ patch.delivery = {}
126
+ }
127
+ patch.delivery.to = `dcg-cron:${sk}`
128
+ patch.delivery.channel = CHANNEL_ID
129
+ delete patch.id
130
+ delete patch.createdAtMs
131
+ delete patch.updatedAtMs
132
+ try {
133
+ await sendGatewayRpc({ method: 'cron.update', params: { id: jobId, patch } })
134
+ removeProcessedJobId(jobId)
135
+ removeJobIdToSessionKeyMap(jobId)
136
+ return true
137
+ } catch (e) {
138
+ dcgLogger(`supplementSessionKey failed for jobId: ${jobId}: ${String(e)}`, 'error')
139
+ return null
140
+ }
141
+ }
142
+
143
+ export function isCronAddAction(params: unknown): boolean {
144
+ const record = params !== null && typeof params === 'object' && !Array.isArray(params) ? (params as Record<string, unknown>) : null
145
+ const action = typeof record?.action === 'string' ? record.action.trim().toLowerCase() : ''
146
+ return action === 'add' || action === 'create'
147
+ }
148
+
149
+ export { isCronCreateExecCommand } from './toolGuard.js'
150
+
151
+ export function isCreateCronTool(event: { toolName: any; params: any; toolCallId: any }) {
152
+ const { toolName, params } = event
153
+
154
+ if (toolName === 'cron') {
155
+ return isCronAddAction(params)
156
+ }
157
+
158
+ if (toolName === 'exec') {
159
+ const record = params !== null && typeof params === 'object' && !Array.isArray(params) ? (params as Record<string, unknown>) : null
160
+ return isCronCreateExecCommand(record?.command)
161
+ }
162
+
163
+ return false
164
+ }