@dcrays/dcgchat-test 0.4.3 → 0.4.9
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 +18 -6
- package/src/channel.ts +4 -4
- package/src/skill.ts +2 -7
- package/src/tools/messageTool.ts +10 -1
package/package.json
CHANGED
package/src/bot.ts
CHANGED
|
@@ -173,6 +173,8 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
173
173
|
sessionKey: dcgSessionKey,
|
|
174
174
|
real_mobook
|
|
175
175
|
}
|
|
176
|
+
/** 写入本条消息参数前快照:流式/abort 的 final 须对齐「上一轮」触发的对话 messageId,而非打断指令本身 */
|
|
177
|
+
const priorOutboundCtx = getEffectiveMsgParams(dcgSessionKey)
|
|
176
178
|
setParamsMessage(dcgSessionKey, mergedParams)
|
|
177
179
|
dcgLogger(`target alias bound: aliasTarget=${userId} -> sessionKey=${dcgSessionKey}`)
|
|
178
180
|
const outboundCtx = getEffectiveMsgParams(dcgSessionKey)
|
|
@@ -189,6 +191,14 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
try {
|
|
194
|
+
if (msg.content.skills_scope.length > 0 && !msg.content?.agent_clone_code && !ignoreToolCommand.includes(text?.trim())) {
|
|
195
|
+
const workspaceDir = getWorkspaceDir()
|
|
196
|
+
const skill = msg.content.skills_scope[0]
|
|
197
|
+
const skillDir = `${workspaceDir}/skills/${skill.skill_code}`
|
|
198
|
+
const skillText = `用户选择使用此技能:"${skill.skill_code}",技能路径是:"${skillDir}",在目录下查找并`
|
|
199
|
+
text = skill.skill_code ? `${skillText} ${text}` : text
|
|
200
|
+
dcgLogger(`skill: text: ${text}`)
|
|
201
|
+
}
|
|
192
202
|
// 处理用户上传的文件
|
|
193
203
|
const files = msg.content.files ?? []
|
|
194
204
|
let mediaPayload: Record<string, unknown> = {}
|
|
@@ -235,12 +245,13 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
235
245
|
const getMediaKey = (url: string) => url.split(/[\\/]/).pop() ?? url
|
|
236
246
|
let streamedTextLen = 0
|
|
237
247
|
|
|
238
|
-
if (msg.content.skills_scope.length > 0 && !msg.content?.agent_clone_code) {
|
|
248
|
+
if (msg.content.skills_scope.length > 0 && !msg.content?.agent_clone_code && !ignoreToolCommand.includes(text?.trim())) {
|
|
239
249
|
const workspaceDir = getWorkspaceDir()
|
|
240
|
-
const
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
250
|
+
const skill = msg.content.skills_scope[0]
|
|
251
|
+
const skillDir = `${workspaceDir}/skills/${skill.skill_code}`
|
|
252
|
+
const skillText = `用户选择使用此技能:"${skill.skill_code}",技能路径是:"${skillDir}",在目录下查找并`
|
|
253
|
+
text = skill.skill_code ? `${skillText} ${text}` : text
|
|
254
|
+
dcgLogger(`skill: text: ${text}`)
|
|
244
255
|
}
|
|
245
256
|
const prefixContext = createReplyPrefixContext({
|
|
246
257
|
cfg: config,
|
|
@@ -304,7 +315,8 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
|
|
|
304
315
|
})
|
|
305
316
|
} else if (interruptCommand.includes(text?.trim())) {
|
|
306
317
|
dcgLogger(`interrupt command: ${text}`)
|
|
307
|
-
|
|
318
|
+
const ctxForAbort = priorOutboundCtx.messageId?.trim() || priorOutboundCtx.sessionId?.trim() ? priorOutboundCtx : outboundCtx
|
|
319
|
+
sendFinal(ctxForAbort.messageId?.trim() ? ctxForAbort : { ...ctxForAbort, messageId: `${Date.now()}` }, 'abort')
|
|
308
320
|
sendText('会话已终止', outboundCtx)
|
|
309
321
|
sessionStreamSuppressed.add(dcgSessionKey)
|
|
310
322
|
const abortOneSession = async (sessionKey: string) => {
|
package/src/channel.ts
CHANGED
|
@@ -224,10 +224,10 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
224
224
|
},
|
|
225
225
|
agentPrompt: {
|
|
226
226
|
messageToolHints: () => [
|
|
227
|
-
'
|
|
228
|
-
'
|
|
229
|
-
'
|
|
230
|
-
'
|
|
227
|
+
'书灵墨宝 / 内置 `message`:**优先不要传 `target`**,即回复当前会话;OpenClaw 会用工具上下文里的 `currentChannelId`(与入站 `To` / `SessionKey` / `OriginatingTo` 相同)。',
|
|
228
|
+
'仅在需要显式指定时:`target` 必须与上下文中的 **完整 SessionKey 字符串逐字一致**(形如 `agent:…:mobook:direct:…` 或以 `agent:` 开头的路由键)。**禁止**填 `From`、`SenderId`、通道配置里的 WS `userId`、会话 id 纯数字等。',
|
|
229
|
+
'生成文件后,**尽可能不要**把文件路径、地址直接告诉用户;把文件名告诉用户;须通过工具发文件,勿在正文里直接输出可访问路径。',
|
|
230
|
+
'使用 `dcgchat_message` 时同样遵守上述 SessionKey 规则(该工具通常由插件注入当前会话,一般无需自造 target)。'
|
|
231
231
|
]
|
|
232
232
|
},
|
|
233
233
|
outbound: {
|
package/src/skill.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { getWsConnection } from './utils/global.js'
|
|
|
9
9
|
import { dcgLogger } from './utils/log.js'
|
|
10
10
|
import { isWsOpen } from './transport.js'
|
|
11
11
|
import { sendMessageToGateway } from './gateway/socket.js'
|
|
12
|
+
import { decodeZipEntryPath } from './utils/zipPath.js'
|
|
12
13
|
|
|
13
14
|
type ISkillParams = {
|
|
14
15
|
path: string
|
|
@@ -69,13 +70,7 @@ export async function installSkill(params: ISkillParams, msgContent: Record<stri
|
|
|
69
70
|
}
|
|
70
71
|
try {
|
|
71
72
|
const flags = entry.props?.flags ?? 0
|
|
72
|
-
const
|
|
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
|
-
}
|
|
73
|
+
const entryPath = decodeZipEntryPath(entry.props?.pathBuffer, flags, entry.path)
|
|
79
74
|
const pathParts = entryPath.split('/')
|
|
80
75
|
|
|
81
76
|
// 检测根目录
|
package/src/tools/messageTool.ts
CHANGED
|
@@ -37,7 +37,7 @@ function isSafePath(filepath: string, workspaceDir?: string): boolean {
|
|
|
37
37
|
if (ws && isPathInsideDir(filepath, ws)) return true
|
|
38
38
|
const p = toPosixPath(filepath)
|
|
39
39
|
if (p.startsWith('/workspace/') || p === '/workspace') return true
|
|
40
|
-
if (p === '/mobook') return true
|
|
40
|
+
if (p.startsWith('/mobook/') || p === '/mobook') return true
|
|
41
41
|
return /^[A-Za-z]:\/(workspace|mobook)(\/|$)/.test(p)
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -183,6 +183,15 @@ export function createDcgchatMessageTool(pluginCtx: DcgchatMessageToolContext):
|
|
|
183
183
|
sentKeys.add(key)
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
if (args.media?.length && sentFiles.size === 0) {
|
|
187
|
+
return jsonResult({
|
|
188
|
+
success: false,
|
|
189
|
+
error:
|
|
190
|
+
'未能发送任何附件:路径须位于当前 Agent 工作区,或为 /workspace/、/mobook/ 下的真实文件(非空、扩展名在白名单内)。',
|
|
191
|
+
sentMediaCount: 0
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
|
|
186
195
|
let content = args.content ?? ''
|
|
187
196
|
for (const filepath of sentFiles) {
|
|
188
197
|
const posix = toPosixPath(filepath)
|