@dcrays/dcgchat-test 0.4.2 → 0.4.3
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/bot.ts +1 -1
- package/src/cron.ts +8 -9
- package/src/skill.ts +79 -3
- package/src/transport.ts +1 -2
- package/src/utils/gatewayMsgHanlder.ts +4 -2
package/package.json
CHANGED
package/src/bot.ts
CHANGED
|
@@ -240,6 +240,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
240
240
|
const skillCode = msg.content.skills_scope.map((skill) => `${workspaceDir}/skills/${skill.skill_code}`).join('\n')
|
|
241
241
|
const skillText = `技能${skillCode} 在目录${skillCode}下,在目录${skillCode}下读取技能 \n`
|
|
242
242
|
text = skillText ? `${skillText} \n ${text}` : text
|
|
243
|
+
dcgLogger('skill: skillText: ${skillText}')
|
|
243
244
|
}
|
|
244
245
|
const prefixContext = createReplyPrefixContext({
|
|
245
246
|
cfg: config,
|
|
@@ -336,7 +337,6 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
336
337
|
clearSentMediaKeys(msg.content.message_id)
|
|
337
338
|
clearParamsMessage(dcgSessionKey)
|
|
338
339
|
clearParamsMessage(userId)
|
|
339
|
-
|
|
340
340
|
sendFinal(outboundCtx, 'stop')
|
|
341
341
|
return
|
|
342
342
|
} else {
|
package/src/cron.ts
CHANGED
|
@@ -40,11 +40,6 @@ export function readCronJob(jobPath: string, jobId: string): Record<string, any>
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function msgParamsToCtx(p: IMsgParams): IMsgParams | null {
|
|
44
|
-
if (!p?.botToken) return null
|
|
45
|
-
return p
|
|
46
|
-
}
|
|
47
|
-
|
|
48
43
|
const CRON_UPLOAD_DEBOUNCE_MS = 2400
|
|
49
44
|
|
|
50
45
|
let cronUploadFlushTimer: ReturnType<typeof setTimeout> | null = null
|
|
@@ -63,9 +58,10 @@ async function runCronJobsUpload(sessionKey: string): Promise<void> {
|
|
|
63
58
|
event_type: 'cron',
|
|
64
59
|
operation_type: 'install',
|
|
65
60
|
session_id: sessionId,
|
|
66
|
-
agent_id: agentId
|
|
61
|
+
agent_id: agentId,
|
|
62
|
+
oss_url: url
|
|
67
63
|
}
|
|
68
|
-
sendEventMessage(
|
|
64
|
+
sendEventMessage(params)
|
|
69
65
|
} catch (error) {
|
|
70
66
|
dcgLogger(`${jobPath} upload failed: ${error}`, 'error')
|
|
71
67
|
}
|
|
@@ -170,6 +166,7 @@ export const finishedDcgchatCron = async (jobId: string) => {
|
|
|
170
166
|
sendFinal(merged, 'cron send')
|
|
171
167
|
}
|
|
172
168
|
const ws = getWsConnection()
|
|
169
|
+
const baseContent = getParamsDefaults()
|
|
173
170
|
if (isWsOpen()) {
|
|
174
171
|
ws?.send(
|
|
175
172
|
JSON.stringify({
|
|
@@ -178,15 +175,17 @@ export const finishedDcgchatCron = async (jobId: string) => {
|
|
|
178
175
|
content: {
|
|
179
176
|
event_type: 'notify',
|
|
180
177
|
operation_type: 'cron',
|
|
178
|
+
bot_token: baseContent.botToken,
|
|
179
|
+
app_id: baseContent.appId,
|
|
181
180
|
session_id: sessionId,
|
|
182
|
-
|
|
181
|
+
agent_id: agentId,
|
|
183
182
|
real_mobook: !sessionId ? 1 : '',
|
|
184
183
|
title: name
|
|
185
184
|
}
|
|
186
185
|
})
|
|
187
186
|
)
|
|
188
|
-
dcgLogger(`定时任务执行成功: ${id}`)
|
|
189
187
|
}
|
|
188
|
+
dcgLogger(`定时任务执行成功: ${id}`)
|
|
190
189
|
removeCronMessageId(sessionKey)
|
|
191
190
|
dcgLogger(`finishedDcgchatCron: job=${id} sessionKey=${sessionKey}`)
|
|
192
191
|
}
|
package/src/skill.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import axios from 'axios'
|
|
2
|
+
/** @ts-ignore */
|
|
3
|
+
import unzipper from 'unzipper'
|
|
4
|
+
import { pipeline } from 'stream/promises'
|
|
2
5
|
import fs from 'fs'
|
|
3
6
|
import path from 'path'
|
|
4
7
|
import { getWorkspaceDir } from './utils/global.js'
|
|
@@ -6,7 +9,6 @@ import { getWsConnection } from './utils/global.js'
|
|
|
6
9
|
import { dcgLogger } from './utils/log.js'
|
|
7
10
|
import { isWsOpen } from './transport.js'
|
|
8
11
|
import { sendMessageToGateway } from './gateway/socket.js'
|
|
9
|
-
import { extractZipBufferToDirectory } from './utils/zipExtract.js'
|
|
10
12
|
|
|
11
13
|
type ISkillParams = {
|
|
12
14
|
path: string
|
|
@@ -44,13 +46,87 @@ export async function installSkill(params: ISkillParams, msgContent: Record<stri
|
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
try {
|
|
49
|
+
// 下载 zip 文件
|
|
47
50
|
const response = await axios({
|
|
48
51
|
method: 'get',
|
|
49
52
|
url: cdnUrl,
|
|
50
|
-
responseType: '
|
|
53
|
+
responseType: 'stream'
|
|
51
54
|
})
|
|
55
|
+
// 创建目标目录
|
|
52
56
|
fs.mkdirSync(skillDir, { recursive: true })
|
|
53
|
-
|
|
57
|
+
// 解压文件到目标目录,跳过顶层文件夹
|
|
58
|
+
await new Promise((resolve, reject) => {
|
|
59
|
+
const tasks: Promise<void>[] = []
|
|
60
|
+
let rootDir: string | null = null
|
|
61
|
+
let hasError = false
|
|
62
|
+
|
|
63
|
+
response.data
|
|
64
|
+
.pipe(unzipper.Parse())
|
|
65
|
+
.on('entry', (entry: any) => {
|
|
66
|
+
if (hasError) {
|
|
67
|
+
entry.autodrain()
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const flags = entry.props?.flags ?? 0
|
|
72
|
+
const isUtf8 = (flags & 0x800) !== 0
|
|
73
|
+
let entryPath: string
|
|
74
|
+
if (!isUtf8 && entry.props?.pathBuffer) {
|
|
75
|
+
entryPath = new TextDecoder('gbk').decode(entry.props.pathBuffer)
|
|
76
|
+
} else {
|
|
77
|
+
entryPath = entry.path
|
|
78
|
+
}
|
|
79
|
+
const pathParts = entryPath.split('/')
|
|
80
|
+
|
|
81
|
+
// 检测根目录
|
|
82
|
+
if (!rootDir && pathParts.length > 1) {
|
|
83
|
+
rootDir = pathParts[0]
|
|
84
|
+
}
|
|
85
|
+
let newPath = entryPath
|
|
86
|
+
// 移除顶层文件夹
|
|
87
|
+
if (rootDir && entryPath.startsWith(rootDir + '/')) {
|
|
88
|
+
newPath = entryPath.slice(rootDir.length + 1)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!newPath) {
|
|
92
|
+
entry.autodrain()
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const targetPath = path.join(skillDir, newPath)
|
|
97
|
+
|
|
98
|
+
if (entry.type === 'Directory') {
|
|
99
|
+
fs.mkdirSync(targetPath, { recursive: true })
|
|
100
|
+
entry.autodrain()
|
|
101
|
+
} else {
|
|
102
|
+
const parentDir = path.dirname(targetPath)
|
|
103
|
+
fs.mkdirSync(parentDir, { recursive: true })
|
|
104
|
+
const writeStream = fs.createWriteStream(targetPath)
|
|
105
|
+
const task = pipeline(entry, writeStream).catch((err) => {
|
|
106
|
+
hasError = true
|
|
107
|
+
throw new Error(`解压文件失败 ${entryPath}: ${err.message}`)
|
|
108
|
+
})
|
|
109
|
+
tasks.push(task)
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
hasError = true
|
|
113
|
+
entry.autodrain()
|
|
114
|
+
reject(new Error(`处理entry失败: ${err}`))
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
.on('close', async () => {
|
|
118
|
+
try {
|
|
119
|
+
await Promise.all(tasks)
|
|
120
|
+
resolve(null)
|
|
121
|
+
} catch (err) {
|
|
122
|
+
reject(err)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
.on('error', (err: { message: any }) => {
|
|
126
|
+
hasError = true
|
|
127
|
+
reject(new Error(`解压流错误: ${err.message}`))
|
|
128
|
+
})
|
|
129
|
+
})
|
|
54
130
|
sendEvent({ ...msgContent, status: 'ok' })
|
|
55
131
|
sendMessageToGateway(JSON.stringify({ method: 'skills.status', params: {} }))
|
|
56
132
|
} catch (error) {
|
package/src/transport.ts
CHANGED
|
@@ -181,7 +181,7 @@ export function sendError(errorMsg: string, ctx: IMsgParams): boolean {
|
|
|
181
181
|
return wsSend(ctx, { response: `[错误] ${errorMsg}`, state: 'final' })
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
export function sendEventMessage(
|
|
184
|
+
export function sendEventMessage(params: Record<string, string> = {}) {
|
|
185
185
|
const ctx = getParamsDefaults()
|
|
186
186
|
const ws = getWsConnection()
|
|
187
187
|
if (isWsOpen()) {
|
|
@@ -193,7 +193,6 @@ export function sendEventMessage(url: string, params: Record<string, string> = {
|
|
|
193
193
|
bot_token: ctx.botToken,
|
|
194
194
|
domain_id: ctx.domainId,
|
|
195
195
|
app_id: ctx.appId,
|
|
196
|
-
oss_url: url,
|
|
197
196
|
bot_id: ctx.botId,
|
|
198
197
|
...params
|
|
199
198
|
}
|
|
@@ -14,8 +14,10 @@ export function handleGatewayEventMessage(msg: { event?: string; payload?: Recor
|
|
|
14
14
|
const sessionKey = getSessionKeyBySubAgentRunId(pl.runId)
|
|
15
15
|
const outboundCtx = getEffectiveMsgParams(sessionKey)
|
|
16
16
|
if (pl.data?.delta) {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
if (outboundCtx.sessionId) {
|
|
18
|
+
dcgLogger(`[Gateway] 收到agent事件: ${JSON.stringify(msg).slice(0, 100)}`)
|
|
19
|
+
sendChunk(pl.data.delta as string, outboundCtx, 0)
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
if (msg.event === 'cron') {
|