@dcrays/dcgchat-test 0.5.0-alpha.2 → 0.5.0-alpha.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/index.js +292 -0
- package/package.json +7 -15
- package/schemas/gateway-cron-finished.payload.json +39 -0
- package/index.ts +0 -24
- package/src/agent.ts +0 -128
- package/src/bot.ts +0 -515
- package/src/channel.ts +0 -474
- package/src/cron.ts +0 -199
- package/src/cronToolCall.ts +0 -202
- package/src/gateway/cronFinishedPayload.ts +0 -118
- package/src/gateway/index.ts +0 -452
- package/src/gateway/security.ts +0 -95
- package/src/gateway/socket.ts +0 -285
- package/src/libs/ali-oss-6.23.0.tgz +0 -0
- package/src/libs/axios-1.13.6.tgz +0 -0
- package/src/libs/md5-2.3.0.tgz +0 -0
- package/src/libs/mime-types-3.0.2.tgz +0 -0
- package/src/libs/unzipper-0.12.3.tgz +0 -0
- package/src/libs/ws-8.19.0.tgz +0 -0
- package/src/monitor.ts +0 -165
- package/src/request/api.ts +0 -70
- package/src/request/oss.ts +0 -212
- package/src/request/request.ts +0 -192
- package/src/request/userInfo.ts +0 -93
- package/src/session.ts +0 -19
- package/src/sessionTermination.ts +0 -168
- package/src/skill.ts +0 -146
- package/src/tool.ts +0 -403
- package/src/tools/messageTool.ts +0 -273
- package/src/transport.ts +0 -206
- package/src/types.ts +0 -139
- package/src/utils/agentErrors.ts +0 -23
- package/src/utils/constant.ts +0 -7
- package/src/utils/gatewayMsgHanlder.ts +0 -84
- package/src/utils/global.ts +0 -161
- package/src/utils/log.ts +0 -15
- package/src/utils/params.ts +0 -88
- package/src/utils/searchFile.ts +0 -228
- package/src/utils/workspaceFilePaths.ts +0 -89
- package/src/utils/wsMessageHandler.ts +0 -64
- package/src/utils/zipExtract.ts +0 -97
- package/src/utils/zipPath.ts +0 -24
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { handleDcgchatMessage } from '../bot.js'
|
|
2
|
-
import { setMsgStatus, getSessionKey } from './global.js'
|
|
3
|
-
import type { InboundMessage } from '../types.js'
|
|
4
|
-
import { installSkill, uninstallSkill } from '../skill.js'
|
|
5
|
-
import { dcgLogger } from './log.js'
|
|
6
|
-
import { onDisabledCronJob, onEnabledCronJob, onRemoveCronJob, onRunCronJob } from '../cron.js'
|
|
7
|
-
import { ignoreToolCommand } from './constant.js'
|
|
8
|
-
import { createAgent } from '../agent.js'
|
|
9
|
-
|
|
10
|
-
export type ParsedWsPayload = {
|
|
11
|
-
messageType?: string
|
|
12
|
-
content: any
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 处理 WebSocket 已解析 JSON 且 content 已二次 parse 后的业务消息(openclaw_bot_chat / openclaw_bot_event)。
|
|
17
|
-
*/
|
|
18
|
-
export async function handleParsedWsMessage(parsed: ParsedWsPayload, rawPayload: string, accountId: string): Promise<void> {
|
|
19
|
-
if (parsed.messageType == 'openclaw_bot_chat') {
|
|
20
|
-
const msg = parsed as unknown as InboundMessage
|
|
21
|
-
// 与 monitor 原逻辑一致:工具类指令不进入 running,避免误触工具链监控
|
|
22
|
-
const effectiveSessionKey = getSessionKey(msg.content, accountId)
|
|
23
|
-
if (!ignoreToolCommand.includes(msg.content.text?.trim() ?? '')) {
|
|
24
|
-
setMsgStatus(effectiveSessionKey, 'running')
|
|
25
|
-
} else {
|
|
26
|
-
setMsgStatus(effectiveSessionKey, 'finished')
|
|
27
|
-
}
|
|
28
|
-
await handleDcgchatMessage(msg, accountId)
|
|
29
|
-
} else if (parsed.messageType == 'openclaw_bot_event') {
|
|
30
|
-
const { event_type, operation_type } = parsed.content ? parsed.content : ({} as Record<string, any>)
|
|
31
|
-
if (event_type === 'skill') {
|
|
32
|
-
const { skill_url, skill_code, skill_id, bot_token, websocket_trace_id } = parsed.content
|
|
33
|
-
const content = { event_type, operation_type, skill_url, skill_code, skill_id, bot_token, websocket_trace_id }
|
|
34
|
-
if (operation_type === 'install' || operation_type === 'enable' || operation_type === 'update') {
|
|
35
|
-
installSkill({ path: skill_url, code: skill_code }, content)
|
|
36
|
-
} else if (operation_type === 'remove' || operation_type === 'disable') {
|
|
37
|
-
uninstallSkill({ code: skill_code }, content)
|
|
38
|
-
} else {
|
|
39
|
-
dcgLogger(`openclaw_bot_event unknown event_type: ${event_type}, ${rawPayload}`)
|
|
40
|
-
}
|
|
41
|
-
} else if (event_type === 'agent') {
|
|
42
|
-
if (operation_type === 'create') {
|
|
43
|
-
await createAgent(parsed.content)
|
|
44
|
-
} else {
|
|
45
|
-
dcgLogger(`openclaw_bot_event unknown event_type: ${event_type}, ${rawPayload}`)
|
|
46
|
-
}
|
|
47
|
-
} else if (event_type === 'cron') {
|
|
48
|
-
const { job_id, message_id } = parsed.content
|
|
49
|
-
if (operation_type === 'remove') {
|
|
50
|
-
await onRemoveCronJob(job_id)
|
|
51
|
-
} else if (operation_type === 'enable') {
|
|
52
|
-
await onEnabledCronJob(job_id)
|
|
53
|
-
} else if (operation_type === 'disable') {
|
|
54
|
-
await onDisabledCronJob(job_id)
|
|
55
|
-
} else if (operation_type === 'run') {
|
|
56
|
-
await onRunCronJob(job_id, message_id)
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
dcgLogger(`openclaw_bot_event unknown operation_type: ${operation_type}, ${rawPayload}`)
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
dcgLogger(`ignoring unknown messageType: ${parsed.messageType}`, 'error')
|
|
63
|
-
}
|
|
64
|
-
}
|
package/src/utils/zipExtract.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
/** @ts-ignore */
|
|
4
|
-
import unzipper from 'unzipper'
|
|
5
|
-
import { pipeline } from 'stream/promises'
|
|
6
|
-
import { decodeZipEntryPath } from './zipPath.js'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 若且唯若所有条目都在同一顶层目录下(如 GitHub 下载的 repo-name/...),返回该目录名;否则返回 null。
|
|
10
|
-
* 不能再用「第一个多段路径的第一段」推断,否则 ZIP 条目顺序变化时会误判(例如先出现 .github/ 或 src/)。
|
|
11
|
-
*/
|
|
12
|
-
export function computeSharedZipRootPrefix(decodedPaths: string[]): string | null {
|
|
13
|
-
const normalized = decodedPaths
|
|
14
|
-
.map((p) => p.replace(/\\/g, '/').replace(/\/+$/, ''))
|
|
15
|
-
.filter((p) => p.length > 0)
|
|
16
|
-
|
|
17
|
-
if (normalized.length === 0) return null
|
|
18
|
-
|
|
19
|
-
const firstSegs = new Set<string>()
|
|
20
|
-
for (const p of normalized) {
|
|
21
|
-
const seg = p.split('/').filter(Boolean)[0]
|
|
22
|
-
if (seg) firstSegs.add(seg)
|
|
23
|
-
}
|
|
24
|
-
if (firstSegs.size !== 1) return null
|
|
25
|
-
|
|
26
|
-
const root = [...firstSegs][0]!
|
|
27
|
-
const prefix = `${root}/`
|
|
28
|
-
for (const p of normalized) {
|
|
29
|
-
if (p !== root && !p.startsWith(prefix)) return null
|
|
30
|
-
}
|
|
31
|
-
return root
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function assertSafeZipTarget(destDir: string, relativePath: string): string {
|
|
35
|
-
const resolvedPath = path.resolve(destDir, relativePath)
|
|
36
|
-
const resolvedDest = path.resolve(destDir)
|
|
37
|
-
const rel = path.relative(resolvedDest, resolvedPath)
|
|
38
|
-
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
39
|
-
throw new Error(`zip 路径越界: ${relativePath}`)
|
|
40
|
-
}
|
|
41
|
-
return resolvedPath
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
type ZipEntry = {
|
|
45
|
-
path: string
|
|
46
|
-
pathBuffer: Buffer
|
|
47
|
-
flags: number
|
|
48
|
-
type: string
|
|
49
|
-
stream: (password?: string) => NodeJS.ReadableStream
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* 将已下载的 zip 解压到 destDir;顶层单根目录(若存在)会被剥掉,与原先流式 Parse 行为一致,但根目录由全量路径计算,与条目顺序无关。
|
|
54
|
-
*/
|
|
55
|
-
export async function extractZipBufferToDirectory(buf: Buffer, destDir: string): Promise<void> {
|
|
56
|
-
const directory = await unzipper.Open.buffer(buf)
|
|
57
|
-
const files = (await directory.files) as ZipEntry[]
|
|
58
|
-
|
|
59
|
-
const decodedPaths = files.map((entry) =>
|
|
60
|
-
decodeZipEntryPath(entry.pathBuffer, entry.flags ?? 0, entry.path)
|
|
61
|
-
)
|
|
62
|
-
const rootDir = computeSharedZipRootPrefix(decodedPaths)
|
|
63
|
-
|
|
64
|
-
// 与 unzipper 默认 extract 一致:串行读各 entry,避免同一 buffer 上多路解压竞争
|
|
65
|
-
for (let i = 0; i < files.length; i++) {
|
|
66
|
-
const entry = files[i]!
|
|
67
|
-
const entryPath = decodedPaths[i]!
|
|
68
|
-
let newPath = entryPath.replace(/\\/g, '/')
|
|
69
|
-
if (rootDir) {
|
|
70
|
-
if (newPath === rootDir || newPath === `${rootDir}/`) {
|
|
71
|
-
continue
|
|
72
|
-
}
|
|
73
|
-
if (newPath.startsWith(`${rootDir}/`)) {
|
|
74
|
-
newPath = newPath.slice(rootDir.length + 1)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
newPath = newPath.replace(/\/+$/, '')
|
|
78
|
-
if (!newPath) continue
|
|
79
|
-
|
|
80
|
-
const targetPath = assertSafeZipTarget(destDir, newPath)
|
|
81
|
-
|
|
82
|
-
if (entry.type === 'Directory') {
|
|
83
|
-
fs.mkdirSync(targetPath, { recursive: true })
|
|
84
|
-
continue
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const parentDir = path.dirname(targetPath)
|
|
88
|
-
fs.mkdirSync(parentDir, { recursive: true })
|
|
89
|
-
const writeStream = fs.createWriteStream(targetPath)
|
|
90
|
-
try {
|
|
91
|
-
await pipeline(entry.stream(), writeStream)
|
|
92
|
-
} catch (err) {
|
|
93
|
-
const message = err instanceof Error ? err.message : String(err)
|
|
94
|
-
throw new Error(`解压文件失败 ${entryPath}: ${message}`)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
package/src/utils/zipPath.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ZIP 文件名编码:规范要求 UTF-8 时设置 0x800;很多工具未设标志但仍写 UTF-8 字节。
|
|
3
|
-
* 无标志时若一律按 GBK 解码,会得到「鍥句功…」类乱码。先严格 UTF-8,失败再 GBK(兼容 Windows 中文 ZIP)。
|
|
4
|
-
*/
|
|
5
|
-
export function decodeZipEntryPath(
|
|
6
|
-
pathBuffer: Buffer | Uint8Array | undefined,
|
|
7
|
-
flags: number,
|
|
8
|
-
fallbackPath: string
|
|
9
|
-
): string {
|
|
10
|
-
if ((flags & 0x800) !== 0) {
|
|
11
|
-
if (pathBuffer) {
|
|
12
|
-
return new TextDecoder('utf-8').decode(pathBuffer)
|
|
13
|
-
}
|
|
14
|
-
return fallbackPath
|
|
15
|
-
}
|
|
16
|
-
if (pathBuffer && pathBuffer.length > 0) {
|
|
17
|
-
try {
|
|
18
|
-
return new TextDecoder('utf-8', { fatal: true }).decode(pathBuffer)
|
|
19
|
-
} catch {
|
|
20
|
-
return new TextDecoder('gbk').decode(pathBuffer)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return fallbackPath
|
|
24
|
-
}
|