@dcrays/dcgchat-test 0.2.30 → 0.2.32

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.ts CHANGED
@@ -3,11 +3,10 @@ import { emptyPluginConfigSchema } from 'openclaw/plugin-sdk'
3
3
  import { dcgchatPlugin } from './src/channel.js'
4
4
  import { setDcgchatRuntime, setWorkspaceDir } from './src/utils/global.js'
5
5
  import { monitoringToolMessage } from './src/tool.js'
6
- import { channelInfo, ENV } from './src/utils/constant.js'
7
6
  import { setOpenClawConfig } from './src/utils/global.js'
8
7
 
9
8
  const plugin = {
10
- id: channelInfo[ENV],
9
+ id: "dcgchat-test",
11
10
  name: '书灵墨宝',
12
11
  description: '连接 OpenClaw 与 书灵墨宝 产品(WebSocket)',
13
12
  configSchema: emptyPluginConfigSchema(),
@@ -16,6 +15,7 @@ const plugin = {
16
15
  monitoringToolMessage(api)
17
16
  setOpenClawConfig(api.config)
18
17
  api.registerChannel({ plugin: dcgchatPlugin })
18
+ setWorkspaceDir(api.config?.agents?.defaults?.workspace)
19
19
  api.registerTool((ctx) => {
20
20
  const workspaceDir = ctx.workspaceDir
21
21
  setWorkspaceDir(workspaceDir)
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "id": "dcgchat-test",
3
- "channels": ["dcgchat-test"],
3
+ "channels": [
4
+ "dcgchat-test"
5
+ ],
4
6
  "configSchema": {
5
7
  "type": "object",
6
8
  "additionalProperties": false,
7
9
  "properties": {}
8
10
  }
9
- }
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/dcgchat-test",
3
- "version": "0.2.30",
3
+ "version": "0.2.32",
4
4
  "type": "module",
5
5
  "description": "OpenClaw channel plugin for 书灵墨宝 (WebSocket)",
6
6
  "main": "index.ts",
@@ -16,12 +16,6 @@
16
16
  "websocket",
17
17
  "ai"
18
18
  ],
19
- "scripts": {
20
- "typecheck": "tsc --noEmit",
21
- "build:production": "npx tsx scripts/build.ts production",
22
- "build:prod": "npx tsx scripts/build.ts production",
23
- "build:test": "npx tsx scripts/build.ts test"
24
- },
25
19
  "dependencies": {
26
20
  "ali-oss": "file:src/libs/ali-oss-6.23.0.tgz",
27
21
  "axios": "file:src/libs/axios-1.13.6.tgz",
@@ -37,18 +31,15 @@
37
31
  "id": "dcgchat-test",
38
32
  "label": "书灵墨宝",
39
33
  "selectionLabel": "书灵墨宝",
40
- "docsPath": "/channels/dcgchat",
34
+ "docsPath": "/channels/dcgchat-test",
41
35
  "docsLabel": "dcgchat-test",
42
36
  "blurb": "连接 OpenClaw 与 书灵墨宝 产品",
43
37
  "order": 80
44
38
  },
45
39
  "install": {
46
40
  "npmSpec": "@dcrays/dcgchat-test",
47
- "localPath": "extensions/dcgchat",
41
+ "localPath": "extensions/dcgchat-test",
48
42
  "defaultChoice": "npm"
49
43
  }
50
- },
51
- "devDependencies": {
52
- "openclaw": "^2026.3.13"
53
44
  }
54
45
  }
package/src/bot.ts CHANGED
@@ -156,7 +156,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
156
156
 
157
157
  const route = core.channel.routing.resolveAgentRoute({
158
158
  cfg: config,
159
- channel: channelInfo[ENV],
159
+ channel: "dcgchat-test",
160
160
  accountId: account.accountId,
161
161
  peer: { kind: 'direct', id: conversationId }
162
162
  })
@@ -208,13 +208,13 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
208
208
  ChatType: 'direct',
209
209
  SenderName: agentDisplayName,
210
210
  SenderId: userId,
211
- Provider: channelInfo[ENV],
212
- Surface: channelInfo[ENV],
211
+ Provider: "dcgchat-test",
212
+ Surface: "dcgchat-test",
213
213
  MessageSid: msg.content.message_id,
214
214
  Timestamp: Date.now(),
215
215
  WasMentioned: true,
216
216
  CommandAuthorized: true,
217
- OriginatingChannel: channelInfo[ENV],
217
+ OriginatingChannel: "dcgchat-test",
218
218
  OriginatingTo: `user:${userId}`,
219
219
  ...mediaPayload
220
220
  })
@@ -226,7 +226,7 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
226
226
  const prefixContext = createReplyPrefixContext({
227
227
  cfg: config,
228
228
  agentId: effectiveAgentId ?? '',
229
- channel: channelInfo[ENV],
229
+ channel: "dcgchat-test",
230
230
  accountId: account.accountId
231
231
  })
232
232
 
@@ -236,8 +236,6 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
236
236
  humanDelay: core.channel.reply.resolveHumanDelayConfig(config, route.agentId),
237
237
  onReplyStart: async () => {},
238
238
  deliver: async (payload: ReplyPayload, info) => {
239
- dcgLogger(`[deliver]: kind=${info.kind}, text=${payload.text?.length ?? 0} chars, ${payload.text?.slice(0, 50)}`)
240
- // Media from the outbound pipeline (post-streaming)
241
239
  const mediaList = resolveReplyMediaList(payload)
242
240
  for (const mediaUrl of mediaList) {
243
241
  const key = getMediaKey(mediaUrl)
@@ -249,7 +247,9 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
249
247
  onError: (err: unknown, info: { kind: string }) => {
250
248
  dcgLogger(`${info.kind} reply failed: ${String(err)}`, 'error')
251
249
  },
252
- onIdle: () => {}
250
+ onIdle: () => {
251
+ sendFinal(msgCtx)
252
+ }
253
253
  })
254
254
 
255
255
  let wasAborted = false
@@ -338,8 +338,8 @@ export async function handleDcgchatMessage(msg: InboundMessage, accountId: strin
338
338
  }
339
339
  await sendDcgchatMedia({ msgCtx, mediaUrl: resolved, text: '' })
340
340
  }
341
- sendFinal(msgCtx)
342
341
  }
342
+ sendFinal(msgCtx)
343
343
  clearSentMediaKeys(msg.content.message_id)
344
344
  setMsgStatus('finished')
345
345
 
package/src/channel.ts CHANGED
@@ -5,7 +5,6 @@ import { ossUpload } from './request/oss.js'
5
5
  import { addSentMediaKey, getMsgParams, hasSentMediaKey } from './utils/global.js'
6
6
  import { type DcgchatMsgContext, isWsOpen, sendFinal, wsSendRaw } from './transport.js'
7
7
  import { dcgLogger, setLogger } from './utils/log.js'
8
- import { channelInfo, ENV } from './utils/constant.js'
9
8
 
10
9
  export type DcgchatMediaSendOptions = {
11
10
  msgCtx: DcgchatMsgContext
@@ -15,8 +14,6 @@ export type DcgchatMediaSendOptions = {
15
14
 
16
15
  export async function sendDcgchatMedia(opts: DcgchatMediaSendOptions): Promise<void> {
17
16
  const { msgCtx } = opts
18
- console.log('🚀 ~ sendDcgchatMedia ~ msgCtx:', msgCtx)
19
-
20
17
  if (!isWsOpen()) {
21
18
  dcgLogger(`outbound media skipped -> ws not open: ${opts.mediaUrl ?? ''}`)
22
19
  return
@@ -51,7 +48,7 @@ export async function sendDcgchatMedia(opts: DcgchatMediaSendOptions): Promise<v
51
48
 
52
49
  export function resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedDcgchatAccount {
53
50
  const id = accountId ?? DEFAULT_ACCOUNT_ID
54
- const raw = (cfg.channels?.[channelInfo[ENV]] as DcgchatConfig | undefined) ?? {}
51
+ const raw = (cfg.channels?.["dcgchat-test"] as DcgchatConfig | undefined) ?? {}
55
52
  return {
56
53
  accountId: id,
57
54
  enabled: raw.enabled !== false,
@@ -81,13 +78,13 @@ function createOutboundMsgContext(cfg: OpenClawConfig, accountId?: string | null
81
78
  }
82
79
 
83
80
  export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
84
- id: channelInfo[ENV],
81
+ id: "dcgchat-test",
85
82
  meta: {
86
- id: channelInfo[ENV],
83
+ id: "dcgchat-test",
87
84
  label: '书灵墨宝',
88
85
  selectionLabel: '书灵墨宝',
89
86
  docsPath: '/channels/dcgchat',
90
- docsLabel: channelInfo[ENV],
87
+ docsLabel: "dcgchat-test",
91
88
  blurb: '连接 OpenClaw 与 书灵墨宝 产品',
92
89
  order: 80
93
90
  },
@@ -128,7 +125,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
128
125
  channels: {
129
126
  ...cfg.channels,
130
127
  dcgchat: {
131
- ...(cfg.channels?.[channelInfo[ENV]] as Record<string, unknown> | undefined),
128
+ ...(cfg.channels?.["dcgchat-test"] as Record<string, unknown> | undefined),
132
129
  enabled
133
130
  }
134
131
  }
@@ -159,11 +156,10 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
159
156
  const msgCtx = createOutboundMsgContext(ctx.cfg, ctx.accountId)
160
157
  if (isWsOpen()) {
161
158
  wsSendRaw(msgCtx, { response: ctx.text })
162
- sendFinal(msgCtx)
163
- dcgLogger(`channel sendText to ${msgCtx.userId}`)
159
+ dcgLogger(`channel sendText to ${msgCtx.userId} ${ctx.text?.slice(0, 50)}`)
164
160
  }
165
161
  return {
166
- channel: channelInfo[ENV],
162
+ channel: "dcgchat-test",
167
163
  messageId: `dcg-${Date.now()}`,
168
164
  chatId: msgCtx.userId.toString()
169
165
  }
@@ -172,7 +168,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
172
168
  const msgCtx = createOutboundMsgContext(ctx.cfg, ctx.accountId)
173
169
  await sendDcgchatMedia({ msgCtx, mediaUrl: ctx.mediaUrl })
174
170
  return {
175
- channel: channelInfo[ENV],
171
+ channel: "dcgchat-test",
176
172
  messageId: `dcg-${Date.now()}`,
177
173
  chatId: msgCtx.userId.toString()
178
174
  }
@@ -1,9 +1,5 @@
1
1
  export const ENV: 'production' | 'test' | 'develop' = 'test'
2
2
 
3
- export const channelInfo: Record<string, string> = {
4
- production: 'dcgchat',
5
- test: 'dcgchat-test'
6
- }
7
3
 
8
4
  export const systemCommand = ['/new', '/status']
9
5
  export const interruptCommand = ['/stop']
@@ -22,16 +22,21 @@ export function getOpenClawConfig(): OpenClawConfig | null {
22
22
  return config
23
23
  }
24
24
 
25
- import type { ChannelLogSink, OpenClawConfig, PluginRuntime } from 'openclaw/plugin-sdk'
25
+ import type { OpenClawConfig, PluginRuntime } from 'openclaw/plugin-sdk'
26
26
  import { dcgLogger } from './log.js'
27
27
  import { IMsgParams } from '../types.js'
28
+ import { channelInfo, ENV } from './constant.js'
28
29
 
29
30
  const path = require('path')
30
31
  const fs = require('fs')
31
32
  const os = require('os')
32
33
 
33
34
  function getWorkspacePath() {
34
- const workspacePath = path.join(os.homedir(), '.openclaw', 'workspace')
35
+ const workspacePath = path.join(
36
+ os.homedir(),
37
+ config?.channels?.["dcgchat-test"]?.appId == 110 ? '.mobook' : '.openclaw',
38
+ 'workspace'
39
+ )
35
40
  if (fs.existsSync(workspacePath)) {
36
41
  return workspacePath
37
42
  }
package/src/utils/log.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { RuntimeEnv } from 'openclaw/plugin-sdk'
2
- import { channelInfo, ENV } from './constant.js'
3
2
 
4
3
  let logger: RuntimeEnv | null = null
5
4
 
@@ -11,6 +10,6 @@ export function dcgLogger(message: string, type: 'log' | 'error' = 'log'): void
11
10
  if (logger) {
12
11
  logger[type](`书灵墨宝🚀 ~ [${new Date().toISOString()}] ${message}`)
13
12
  } else {
14
- console[type](`书灵墨宝🚀 ~ ${new Date().toISOString()} [${channelInfo[ENV]}]: ${message}`)
13
+ console[type](`书灵墨宝🚀 ~ ${new Date().toISOString()} [${"dcgchat-test"}]: ${message}`)
15
14
  }
16
15
  }
package/README.md DELETED
@@ -1,83 +0,0 @@
1
- # OpenClaw 书灵墨宝 插件
2
-
3
- 连接 OpenClaw 与 书灵墨宝 产品的通道插件。
4
-
5
- ## 架构
6
-
7
- ```
8
- ┌──────────┐ WebSocket ┌──────────────┐ WebSocket ┌─────────────────────┐
9
- │ Web 前端 │ ←───────────────→ │ 公司后端服务 │ ←───────────────→ │ OpenClaw(工作电脑) │
10
- └──────────┘ └──────────────┘ (OpenClaw 主动连) └─────────────────────┘
11
- ```
12
-
13
- - OpenClaw 插件**主动连接**后端的 WebSocket 服务(不需要公网 IP)
14
- - 后端收到用户消息后转发给 OpenClaw,OpenClaw 回复后发回后端
15
-
16
- ## 快速开始
17
-
18
- ### 1. 安装插件
19
-
20
- ```bash
21
- pnpm openclaw plugins install -l /path/to/openclaw-dcgchat
22
- ```
23
-
24
- ### 2. 配置
25
-
26
- ```bash
27
- openclaw config set channels.dcgchat.enabled true
28
- openclaw config set channels.dcgchat.wsUrl "ws://your-backend:8080/openclaw/ws"
29
- ```
30
-
31
- ### 3. 启动
32
-
33
- ```bash
34
- pnpm openclaw gateway
35
- ```
36
-
37
- ## 消息协议(MVP)
38
-
39
- ### 下行:后端 → OpenClaw(用户消息)
40
-
41
- ```json
42
- { "type": "message", "userId": "user_001", "text": "你好" }
43
- ```
44
-
45
- ### 上行:OpenClaw → 后端(Agent 回复)
46
-
47
- ```json
48
- { "type": "reply", "userId": "user_001", "text": "你好!有什么可以帮你的?" }
49
- ```
50
-
51
- ## 配置项
52
-
53
- | 配置键 | 类型 | 说明 |
54
- |--------|------|------|
55
- | `channels.dcgchat.enabled` | boolean | 是否启用 |
56
- | `channels.dcgchat.wsUrl` | string | 后端 WebSocket 地址 |
57
-
58
- ## 开发
59
-
60
- ```bash
61
- # 安装依赖
62
- pnpm install
63
-
64
- # 类型检查
65
- pnpm typecheck
66
- ```
67
-
68
- ## 文件结构
69
-
70
- - `index.ts` - 插件入口
71
- - `src/channel.ts` - ChannelPlugin 定义
72
- - `src/runtime.ts` - 插件 runtime
73
- - `src/types.ts` - 类型定义
74
- - `src/monitor.ts` - WebSocket 连接与断线重连
75
- - `src/bot.ts` - 消息处理与 Agent 调用
76
-
77
- ## 后续迭代
78
-
79
- - [ ] Token 认证
80
- - [ ] 流式输出
81
- - [ ] Typing 指示
82
- - [ ] messageId 去重
83
- - [ ] 错误消息类型