@workclaw/openclaw-workclaw 1.0.23 → 1.0.26

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 (210) hide show
  1. package/dist/api.d.ts +4 -3
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +379 -3
  4. package/dist/channel-DSvR6Irx.js +50017 -0
  5. package/dist/cron-tasks-handler-C-mP3VmV.js +152 -0
  6. package/dist/index.d.ts +5 -4
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +2056 -232
  9. package/dist/jiti-4i2h0FGP.js +4814 -0
  10. package/dist/setup-entry.d.ts +2 -1
  11. package/dist/setup-entry.d.ts.map +1 -0
  12. package/dist/setup-entry.js +181 -11
  13. package/dist/src/accounts.d.ts +3 -2
  14. package/dist/src/accounts.d.ts.map +1 -0
  15. package/dist/src/api/accounts-api.d.ts +2 -1
  16. package/dist/src/api/accounts-api.d.ts.map +1 -0
  17. package/dist/src/api/prompts-api.d.ts +2 -1
  18. package/dist/src/api/prompts-api.d.ts.map +1 -0
  19. package/dist/src/api/session-api.d.ts +2 -1
  20. package/dist/src/api/session-api.d.ts.map +1 -0
  21. package/dist/src/api/skills-api.d.ts +2 -1
  22. package/dist/src/api/skills-api.d.ts.map +1 -0
  23. package/dist/src/api/workspace.d.ts +2 -1
  24. package/dist/src/api/workspace.d.ts.map +1 -0
  25. package/dist/src/channel.d.ts +3 -2
  26. package/dist/src/channel.d.ts.map +1 -0
  27. package/dist/src/config-schema.d.ts +1 -6
  28. package/dist/src/config-schema.d.ts.map +1 -0
  29. package/dist/src/connection/workclaw-client.d.ts +6 -4
  30. package/dist/src/connection/workclaw-client.d.ts.map +1 -0
  31. package/dist/src/gateway/agent-handlers.d.ts +3 -2
  32. package/dist/src/gateway/agent-handlers.d.ts.map +1 -0
  33. package/dist/src/gateway/config-writer.d.ts +3 -2
  34. package/dist/src/gateway/config-writer.d.ts.map +1 -0
  35. package/dist/src/gateway/cron-tasks-handler.d.ts +1 -0
  36. package/dist/src/gateway/cron-tasks-handler.d.ts.map +1 -0
  37. package/dist/src/gateway/message-context.d.ts +2 -1
  38. package/dist/src/gateway/message-context.d.ts.map +1 -0
  39. package/dist/src/gateway/message-dispatcher.d.ts +3 -4
  40. package/dist/src/gateway/message-dispatcher.d.ts.map +1 -0
  41. package/dist/src/gateway/reconnect.d.ts +3 -5
  42. package/dist/src/gateway/reconnect.d.ts.map +1 -0
  43. package/dist/src/gateway/skills-handler.d.ts +1 -0
  44. package/dist/src/gateway/skills-handler.d.ts.map +1 -0
  45. package/dist/src/gateway/skills-list-handler.d.ts +1 -0
  46. package/dist/src/gateway/skills-list-handler.d.ts.map +1 -0
  47. package/dist/src/gateway/tools-list-handler.d.ts +1 -0
  48. package/dist/src/gateway/tools-list-handler.d.ts.map +1 -0
  49. package/dist/src/gateway/workclaw-gateway.d.ts +4 -7
  50. package/dist/src/gateway/workclaw-gateway.d.ts.map +1 -0
  51. package/dist/src/media/upload.d.ts +1 -0
  52. package/dist/src/media/upload.d.ts.map +1 -0
  53. package/dist/src/outbound/index.d.ts +9 -6
  54. package/dist/src/outbound/index.d.ts.map +1 -0
  55. package/dist/src/outbound/workclaw-sender.d.ts +6 -4
  56. package/dist/src/outbound/workclaw-sender.d.ts.map +1 -0
  57. package/dist/src/runtime.d.ts +11 -9
  58. package/dist/src/runtime.d.ts.map +1 -0
  59. package/dist/src/secret-contract-api.d.ts +1 -0
  60. package/dist/src/secret-contract-api.d.ts.map +1 -0
  61. package/dist/src/send.d.ts +2 -1
  62. package/dist/src/send.d.ts.map +1 -0
  63. package/dist/src/setup-api.d.ts +4 -3
  64. package/dist/src/setup-api.d.ts.map +1 -0
  65. package/dist/src/setup-core.d.ts +2 -1
  66. package/dist/src/setup-core.d.ts.map +1 -0
  67. package/dist/src/setup-surface.d.ts +3 -2
  68. package/dist/src/setup-surface.d.ts.map +1 -0
  69. package/dist/src/tools/openclaw-workclaw-cron/api/index.d.ts +2 -4
  70. package/dist/src/tools/openclaw-workclaw-cron/api/index.d.ts.map +1 -0
  71. package/dist/src/tools/openclaw-workclaw-cron/index.d.ts +1 -0
  72. package/dist/src/tools/openclaw-workclaw-cron/index.d.ts.map +1 -0
  73. package/dist/src/tools/openclaw-workclaw-cron/src/add/params.d.ts +2 -4
  74. package/dist/src/tools/openclaw-workclaw-cron/src/add/params.d.ts.map +1 -0
  75. package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.d.ts +2 -4
  76. package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.d.ts.map +1 -0
  77. package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.d.ts +2 -4
  78. package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.d.ts.map +1 -0
  79. package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.d.ts +2 -4
  80. package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.d.ts.map +1 -0
  81. package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.d.ts +2 -4
  82. package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.d.ts.map +1 -0
  83. package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.d.ts +2 -4
  84. package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.d.ts.map +1 -0
  85. package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.d.ts +2 -6
  86. package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.d.ts.map +1 -0
  87. package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.d.ts +2 -4
  88. package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.d.ts.map +1 -0
  89. package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.d.ts +2 -4
  90. package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.d.ts.map +1 -0
  91. package/dist/src/tools/openclaw-workclaw-cron/src/update/params.d.ts +2 -4
  92. package/dist/src/tools/openclaw-workclaw-cron/src/update/params.d.ts.map +1 -0
  93. package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.d.ts +2 -4
  94. package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.d.ts.map +1 -0
  95. package/dist/src/tools/openclaw-workclaw-cron/types/index.d.ts +1 -0
  96. package/dist/src/tools/openclaw-workclaw-cron/types/index.d.ts.map +1 -0
  97. package/dist/src/tools/openclaw-workclaw-cron/utils/index.d.ts +1 -0
  98. package/dist/src/tools/openclaw-workclaw-cron/utils/index.d.ts.map +1 -0
  99. package/dist/src/tools/openclaw-workclaw-system/index.d.ts +1 -0
  100. package/dist/src/tools/openclaw-workclaw-system/index.d.ts.map +1 -0
  101. package/dist/src/tools/openclaw-workclaw-system/src/get/index.d.ts +2 -4
  102. package/dist/src/tools/openclaw-workclaw-system/src/get/index.d.ts.map +1 -0
  103. package/dist/src/tools/openclaw-workclaw-system/src/token/index.d.ts +2 -4
  104. package/dist/src/tools/openclaw-workclaw-system/src/token/index.d.ts.map +1 -0
  105. package/dist/src/types.d.ts +7 -7
  106. package/dist/src/types.d.ts.map +1 -0
  107. package/dist/src/utils/content.d.ts +1 -0
  108. package/dist/src/utils/content.d.ts.map +1 -0
  109. package/openclaw.plugin.json +6 -0
  110. package/package.json +69 -45
  111. package/api.ts +0 -3
  112. package/dist/src/accounts.js +0 -279
  113. package/dist/src/api/accounts-api.js +0 -130
  114. package/dist/src/api/prompts-api.js +0 -103
  115. package/dist/src/api/session-api.js +0 -207
  116. package/dist/src/api/skills-api.js +0 -64
  117. package/dist/src/api/workspace.js +0 -30
  118. package/dist/src/channel.js +0 -199
  119. package/dist/src/config-schema.js +0 -56
  120. package/dist/src/connection/workclaw-client.js +0 -351
  121. package/dist/src/gateway/agent-handlers.js +0 -433
  122. package/dist/src/gateway/config-writer.js +0 -302
  123. package/dist/src/gateway/cron-tasks-handler.js +0 -188
  124. package/dist/src/gateway/message-context.js +0 -509
  125. package/dist/src/gateway/message-dispatcher.js +0 -572
  126. package/dist/src/gateway/reconnect.js +0 -210
  127. package/dist/src/gateway/skills-handler.js +0 -615
  128. package/dist/src/gateway/skills-list-handler.js +0 -233
  129. package/dist/src/gateway/tools-list-handler.js +0 -101
  130. package/dist/src/gateway/workclaw-gateway.js +0 -237
  131. package/dist/src/media/upload.js +0 -125
  132. package/dist/src/outbound/index.js +0 -123
  133. package/dist/src/outbound/workclaw-sender.js +0 -95
  134. package/dist/src/runtime.js +0 -374
  135. package/dist/src/secret-contract-api.js +0 -4
  136. package/dist/src/send.js +0 -1
  137. package/dist/src/setup-api.js +0 -3
  138. package/dist/src/setup-core.js +0 -13
  139. package/dist/src/setup-surface.js +0 -363
  140. package/dist/src/tools/openclaw-workclaw-cron/api/index.js +0 -209
  141. package/dist/src/tools/openclaw-workclaw-cron/index.js +0 -33
  142. package/dist/src/tools/openclaw-workclaw-cron/src/add/params.js +0 -152
  143. package/dist/src/tools/openclaw-workclaw-cron/src/add/sync.js +0 -162
  144. package/dist/src/tools/openclaw-workclaw-cron/src/disable/params.js +0 -80
  145. package/dist/src/tools/openclaw-workclaw-cron/src/disable/sync.js +0 -107
  146. package/dist/src/tools/openclaw-workclaw-cron/src/enable/params.js +0 -80
  147. package/dist/src/tools/openclaw-workclaw-cron/src/enable/sync.js +0 -107
  148. package/dist/src/tools/openclaw-workclaw-cron/src/notify/sync.js +0 -127
  149. package/dist/src/tools/openclaw-workclaw-cron/src/remove/params.js +0 -87
  150. package/dist/src/tools/openclaw-workclaw-cron/src/remove/sync.js +0 -107
  151. package/dist/src/tools/openclaw-workclaw-cron/src/update/params.js +0 -164
  152. package/dist/src/tools/openclaw-workclaw-cron/src/update/sync.js +0 -135
  153. package/dist/src/tools/openclaw-workclaw-cron/types/index.js +0 -4
  154. package/dist/src/tools/openclaw-workclaw-cron/utils/index.js +0 -122
  155. package/dist/src/tools/openclaw-workclaw-system/index.js +0 -15
  156. package/dist/src/tools/openclaw-workclaw-system/src/get/index.js +0 -64
  157. package/dist/src/tools/openclaw-workclaw-system/src/token/index.js +0 -78
  158. package/dist/src/types.js +0 -1
  159. package/dist/src/utils/content.js +0 -38
  160. package/index.ts +0 -325
  161. package/setup-entry.ts +0 -13
  162. package/src/accounts.ts +0 -360
  163. package/src/api/accounts-api.ts +0 -156
  164. package/src/api/prompts-api.ts +0 -122
  165. package/src/api/session-api.ts +0 -246
  166. package/src/api/skills-api.ts +0 -74
  167. package/src/api/workspace.ts +0 -45
  168. package/src/channel.ts +0 -226
  169. package/src/config-schema.ts +0 -60
  170. package/src/connection/workclaw-client.ts +0 -618
  171. package/src/gateway/agent-handlers.ts +0 -551
  172. package/src/gateway/config-writer.ts +0 -378
  173. package/src/gateway/cron-tasks-handler.ts +0 -230
  174. package/src/gateway/message-context.ts +0 -645
  175. package/src/gateway/message-dispatcher.ts +0 -688
  176. package/src/gateway/reconnect.ts +0 -260
  177. package/src/gateway/skills-handler.ts +0 -805
  178. package/src/gateway/skills-list-handler.ts +0 -332
  179. package/src/gateway/tools-list-handler.ts +0 -161
  180. package/src/gateway/workclaw-gateway.ts +0 -298
  181. package/src/media/upload.ts +0 -168
  182. package/src/outbound/index.ts +0 -191
  183. package/src/outbound/workclaw-sender.ts +0 -161
  184. package/src/runtime.ts +0 -520
  185. package/src/secret-contract-api.ts +0 -4
  186. package/src/send.ts +0 -1
  187. package/src/setup-api.ts +0 -3
  188. package/src/setup-core.ts +0 -25
  189. package/src/setup-surface.ts +0 -498
  190. package/src/tools/openclaw-workclaw-cron/api/index.ts +0 -326
  191. package/src/tools/openclaw-workclaw-cron/index.ts +0 -39
  192. package/src/tools/openclaw-workclaw-cron/src/add/params.ts +0 -177
  193. package/src/tools/openclaw-workclaw-cron/src/add/sync.ts +0 -188
  194. package/src/tools/openclaw-workclaw-cron/src/disable/params.ts +0 -100
  195. package/src/tools/openclaw-workclaw-cron/src/disable/sync.ts +0 -127
  196. package/src/tools/openclaw-workclaw-cron/src/enable/params.ts +0 -100
  197. package/src/tools/openclaw-workclaw-cron/src/enable/sync.ts +0 -127
  198. package/src/tools/openclaw-workclaw-cron/src/notify/sync.ts +0 -148
  199. package/src/tools/openclaw-workclaw-cron/src/remove/params.ts +0 -109
  200. package/src/tools/openclaw-workclaw-cron/src/remove/sync.ts +0 -127
  201. package/src/tools/openclaw-workclaw-cron/src/update/params.ts +0 -195
  202. package/src/tools/openclaw-workclaw-cron/src/update/sync.ts +0 -161
  203. package/src/tools/openclaw-workclaw-cron/types/index.ts +0 -55
  204. package/src/tools/openclaw-workclaw-cron/utils/index.ts +0 -141
  205. package/src/tools/openclaw-workclaw-system/index.ts +0 -17
  206. package/src/tools/openclaw-workclaw-system/src/get/index.ts +0 -77
  207. package/src/tools/openclaw-workclaw-system/src/token/index.ts +0 -93
  208. package/src/types.ts +0 -50
  209. package/src/utils/content.ts +0 -40
  210. package/tsconfig.json +0 -34
@@ -1,246 +0,0 @@
1
- import type { OpenClawPluginApi } from 'openclaw/plugin-sdk'
2
- import { getWorkclawRuntime } from '../runtime.js'
3
-
4
- function sendJson(res: any, statusCode: number, payload: unknown) {
5
- res.statusCode = statusCode
6
- res.setHeader('Content-Type', 'application/json')
7
- res.end(JSON.stringify(payload))
8
- }
9
-
10
- async function readRequestBody(req: any): Promise<string> {
11
- const chunks: Buffer[] = []
12
- await new Promise<void>((resolve, reject) => {
13
- req.on('data', (chunk: any) => {
14
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
15
- })
16
- req.on('end', () => resolve())
17
- req.on('error', (err: unknown) => reject(err))
18
- })
19
- return Buffer.concat(chunks).toString('utf-8')
20
- }
21
-
22
- /**
23
- * 构建会话 key
24
- * 格式: openclaw-workclaw:{accountId}:{userId}
25
- */
26
- function buildSessionKey(accountId: string, userId: string): string {
27
- return `openclaw-workclaw:${accountId}:${userId}`
28
- }
29
-
30
- /**
31
- * 解析会话 key
32
- */
33
- function parseSessionKey(sessionKey: string): {
34
- channel: string
35
- accountId: string
36
- userId: string
37
- } | null {
38
- const parts = sessionKey.split(':')
39
- if (parts.length !== 3 || parts[0] !== 'openclaw-workclaw') {
40
- return null
41
- }
42
- return {
43
- channel: parts[0],
44
- accountId: parts[1],
45
- userId: parts[2],
46
- }
47
- }
48
-
49
- /**
50
- * 重置/开启新会话
51
- * 通过发送系统事件 /new 到指定会话
52
- */
53
- async function resetSession(
54
- sessionKey: string,
55
- log?: { info?: (msg: string) => void, error?: (msg: string) => void },
56
- ): Promise<{ success: boolean, message: string }> {
57
- try {
58
- const runtime = getWorkclawRuntime()
59
-
60
- // 使用 system.enqueueSystemEvent 发送 /new 命令
61
- runtime.system.enqueueSystemEvent('/new', {
62
- sessionKey,
63
- contextKey: null,
64
- })
65
-
66
- log?.info?.(`[SessionAPI] Sent /new command to session: ${sessionKey}`)
67
-
68
- return {
69
- success: true,
70
- message: `Session reset command sent to ${sessionKey}`,
71
- }
72
- }
73
- catch (err) {
74
- const errorMsg = `Failed to reset session: ${String(err)}`
75
- log?.error?.(`[SessionAPI] ${errorMsg}`)
76
- return { success: false, message: errorMsg }
77
- }
78
- }
79
-
80
- /**
81
- * 获取会话存储路径
82
- */
83
- function getSessionStorePath(
84
- agentId?: string,
85
- log?: { info?: (msg: string) => void, error?: (msg: string) => void },
86
- ): string | null {
87
- try {
88
- const runtime = getWorkclawRuntime()
89
- const storePath = runtime.channel.session.resolveStorePath(undefined, {
90
- agentId,
91
- })
92
- return storePath
93
- }
94
- catch (err) {
95
- log?.error?.(`[SessionAPI] Failed to resolve store path: ${String(err)}`)
96
- return null
97
- }
98
- }
99
-
100
- /**
101
- * 读取会话最后更新时间
102
- */
103
- async function getSessionLastUpdated(
104
- sessionKey: string,
105
- log?: { info?: (msg: string) => void, error?: (msg: string) => void },
106
- ): Promise<number | null> {
107
- try {
108
- const runtime = getWorkclawRuntime()
109
- const storePath = runtime.channel.session.resolveStorePath()
110
- const updatedAt = runtime.channel.session.readSessionUpdatedAt({
111
- storePath,
112
- sessionKey,
113
- })
114
- return updatedAt ?? null
115
- }
116
- catch (err) {
117
- log?.error?.(`[SessionAPI] Failed to read session updated at: ${String(err)}`)
118
- return null
119
- }
120
- }
121
-
122
- export function createSessionApiHandler(api: OpenClawPluginApi) {
123
- return async (req: any, res: any) => {
124
- const method = String(req.method ?? 'GET').toUpperCase()
125
- const url = new URL(req.url ?? '', 'http://localhost')
126
- // 移除尾部斜杠并获取路径部分
127
- const fullPath = url.pathname.replace(/\/+$/, '')
128
- // 提取子路径(去掉 /openclaw-workclaw/sessions 前缀)
129
- const subPath = fullPath.replace(/^\/openclaw-workclaw\/sessions/, '').replace(/^\//, '') || '/'
130
-
131
- const log = {
132
- info: (msg: string) => api.logger?.info?.(`[SessionAPI] ${msg}`),
133
- error: (msg: string) => api.logger?.error?.(`[SessionAPI] ${msg}`),
134
- }
135
-
136
- log?.info?.(`[SessionAPI] ${method} ${fullPath} (subPath: ${subPath})`)
137
-
138
- // GET /sessions 或 /sessions/ - 列出会话信息
139
- if (method === 'GET' && (subPath === '/' || subPath === '')) {
140
- const sessionKey = url.searchParams.get('sessionKey')
141
-
142
- if (sessionKey) {
143
- // 获取特定会话信息
144
- const parsed = parseSessionKey(sessionKey)
145
- const updatedAt = await getSessionLastUpdated(sessionKey, log)
146
-
147
- sendJson(res, 200, {
148
- ok: true,
149
- session: {
150
- sessionKey,
151
- parsed,
152
- lastUpdatedAt: updatedAt,
153
- lastUpdatedAtFormatted: updatedAt
154
- ? new Date(updatedAt).toISOString()
155
- : null,
156
- },
157
- })
158
- return
159
- }
160
-
161
- // 返回 API 信息
162
- sendJson(res, 200, {
163
- ok: true,
164
- message: 'Session Management API',
165
- endpoints: {
166
- 'GET /sessions': '获取会话信息 (可选参数: sessionKey)',
167
- 'POST /sessions/reset': '重置/开启新会话 (参数: accountId + userId 或直接提供 sessionKey)',
168
- 'GET /sessions/store-path': '获取会话存储路径 (可选参数: agentId)',
169
- },
170
- })
171
- return
172
- }
173
-
174
- // POST /sessions/reset - 重置会话
175
- if (method === 'POST' && subPath === 'reset') {
176
- const raw = await readRequestBody(req)
177
- let input: any = {}
178
- try {
179
- input = raw ? JSON.parse(raw) : {}
180
- }
181
- catch {
182
- sendJson(res, 400, { ok: false, error: 'Invalid JSON' })
183
- return
184
- }
185
-
186
- const { accountId, userId, sessionKey: directSessionKey } = input
187
-
188
- let sessionKey: string
189
- if (directSessionKey) {
190
- sessionKey = directSessionKey
191
- }
192
- else if (accountId && userId) {
193
- sessionKey = buildSessionKey(accountId, userId)
194
- }
195
- else {
196
- sendJson(res, 400, {
197
- ok: false,
198
- error: 'Missing required fields: either provide \'sessionKey\' or both \'accountId\' and \'userId\'',
199
- })
200
- return
201
- }
202
-
203
- const result = await resetSession(sessionKey, log)
204
-
205
- if (result.success) {
206
- sendJson(res, 200, {
207
- ok: true,
208
- message: result.message,
209
- sessionKey,
210
- })
211
- }
212
- else {
213
- sendJson(res, 500, {
214
- ok: false,
215
- error: result.message,
216
- sessionKey,
217
- })
218
- }
219
- return
220
- }
221
-
222
- // GET /sessions/store-path - 获取会话存储路径
223
- if (method === 'GET' && subPath === 'store-path') {
224
- const agentId = url.searchParams.get('agentId') ?? undefined
225
- const storePath = getSessionStorePath(agentId, log)
226
-
227
- if (storePath) {
228
- sendJson(res, 200, {
229
- ok: true,
230
- storePath,
231
- agentId: agentId ?? 'default',
232
- })
233
- }
234
- else {
235
- sendJson(res, 500, {
236
- ok: false,
237
- error: 'Failed to resolve session store path',
238
- })
239
- }
240
- return
241
- }
242
-
243
- // 404
244
- sendJson(res, 404, { ok: false, error: 'Not Found' })
245
- }
246
- }
@@ -1,74 +0,0 @@
1
- import type { OpenClawPluginApi } from 'openclaw/plugin-sdk'
2
- import { exec } from 'node:child_process'
3
- import { promisify } from 'node:util'
4
-
5
- const execAsync = promisify(exec)
6
-
7
- function sendJson(res: any, statusCode: number, payload: unknown) {
8
- res.statusCode = statusCode
9
- res.setHeader('Content-Type', 'application/json')
10
- res.end(JSON.stringify(payload))
11
- }
12
-
13
- export function createSkillsApiHandler(api: OpenClawPluginApi) {
14
- return async (req: any, res: any) => {
15
- const method = String(req.method ?? 'GET').toUpperCase()
16
-
17
- if (method === 'GET') {
18
- try {
19
- // 调用 openclaw skills list 命令
20
- const { stdout, stderr } = await execAsync('openclaw skills list --json', {
21
- timeout: 10000, // 10秒超时
22
- })
23
-
24
- if (stderr && !stdout) {
25
- api.logger.error(`Skills list error: ${stderr}`)
26
- sendJson(res, 500, { ok: false, error: 'Failed to list skills' })
27
- return
28
- }
29
-
30
- // 尝试解析JSON输出
31
- let skillsData: any
32
- try {
33
- skillsData = JSON.parse(stdout)
34
- }
35
- catch {
36
- // 如果不支持--json输出,尝试解析文本输出
37
- const lines = stdout.split('\n')
38
- const skills = lines
39
- .filter((line: string) => line.trim() && !line.includes('Skills'))
40
- .map((line: string) => {
41
- const parts = line.split(/\s{2,}/).map((p: string) => p.trim())
42
- if (parts.length >= 3) {
43
- return {
44
- status: parts[0]?.includes('✓') ? 'ready' : 'missing',
45
- name: parts[1],
46
- description: parts[2],
47
- source: parts[3] || 'openclaw-bundled',
48
- }
49
- }
50
- return null
51
- })
52
- .filter((s: any) => s !== null)
53
-
54
- skillsData = {
55
- total: skills.length,
56
- ready: skills.filter((s: any) => s.status === 'ready').length,
57
- missing: skills.filter((s: any) => s.status === 'missing').length,
58
- skills,
59
- }
60
- }
61
-
62
- sendJson(res, 200, { ok: true, ...skillsData })
63
- return
64
- }
65
- catch (error: any) {
66
- api.logger.error(`Skills API error: ${error.message}`)
67
- sendJson(res, 500, { ok: false, error: error.message })
68
- return
69
- }
70
- }
71
-
72
- sendJson(res, 405, { ok: false, error: 'Method Not Allowed' })
73
- }
74
- }
@@ -1,45 +0,0 @@
1
- import type { OpenClawPluginApi } from 'openclaw/plugin-sdk'
2
- import os from 'node:os'
3
- import path from 'node:path'
4
- import { getWorkclawLogger } from '../runtime.js'
5
-
6
- export function resolveWorkspaceDir(api: OpenClawPluginApi): string {
7
- const agents = api.config.agents?.list ?? []
8
- const defaultAgent
9
- = agents.find(agent => agent?.default === true)
10
- ?? agents.find(agent => String(agent?.id ?? '').toLowerCase() === 'main')
11
-
12
- const workspaceRaw
13
- = (typeof defaultAgent?.workspace === 'string' && defaultAgent.workspace.trim())
14
- || (typeof api.config.agents?.defaults?.workspace === 'string'
15
- && api.config.agents.defaults.workspace.trim())
16
-
17
- getWorkclawLogger().info(`workspaceRaw: ${workspaceRaw}`)
18
-
19
- if (workspaceRaw) {
20
- return api.resolvePath(workspaceRaw)
21
- }
22
-
23
- const profile = process.env.OPENCLAW_PROFILE?.trim()
24
- const suffix
25
- = profile && profile.toLowerCase() !== 'default' ? `workspace-${profile}` : 'workspace'
26
- return path.join(os.homedir(), '.openclaw', suffix)
27
- }
28
-
29
- export function isDefaultWorkspace(api: OpenClawPluginApi): boolean {
30
- const agents = api.config.agents?.list ?? []
31
- const defaultAgent
32
- = agents.find(agent => agent?.default === true)
33
- ?? agents.find(agent => String(agent?.id ?? '').toLowerCase() === 'main')
34
-
35
- const workspaceRaw
36
- = (typeof defaultAgent?.workspace === 'string' && defaultAgent.workspace.trim())
37
- || (typeof api.config.agents?.defaults?.workspace === 'string'
38
- && api.config.agents.defaults.workspace.trim())
39
-
40
- if (workspaceRaw)
41
- return false
42
-
43
- const profile = process.env.OPENCLAW_PROFILE?.trim()
44
- return !profile || profile.toLowerCase() === 'default'
45
- }
package/src/channel.ts DELETED
@@ -1,226 +0,0 @@
1
- import type {
2
- ChannelGatewayContext,
3
- ChannelPlugin,
4
- OpenClawConfig,
5
- } from 'openclaw/plugin-sdk'
6
- import type { ResolvedWorkclawAccount, WorkclawConfig } from './types.js'
7
- import { appendFileSync } from 'node:fs'
8
- import { homedir } from 'node:os'
9
- import { join } from 'node:path'
10
- import { DEFAULT_ACCOUNT_ID } from 'openclaw/plugin-sdk/account-id'
11
- import { buildChannelConfigSchema } from 'openclaw/plugin-sdk/channel-config-schema'
12
- import { formatPairingApproveHint } from 'openclaw/plugin-sdk/core'
13
- import {
14
- isWorkclawAccountConfigured,
15
- listWorkclawAccountIds,
16
- resolveWorkclawAccount,
17
- } from './accounts.js'
18
- import { WorkclawConfigSchema } from './config-schema.js'
19
- import { startWorkclawGateway, stopWorkclawGateway } from './gateway/workclaw-gateway.js'
20
- import { sendMessageWorkclaw } from './outbound/index.js'
21
- import { getLastInboundAt, getLastOutboundAt, getWorkclawRuntime, getWorkclawWsConnection } from './runtime.js'
22
-
23
- const meta = {
24
- id: 'openclaw-workclaw',
25
- label: '智小途',
26
- selectionLabel: '智小途',
27
- docsPath: '/channels/openclaw-workclaw',
28
- docsLabel: '智小途',
29
- blurb: '智小途 OpenClaw通道',
30
- aliases: [],
31
- order: 90,
32
- }
33
-
34
- /**
35
- * 写入文件日志到磁盘
36
- * @param message 日志消息
37
- */
38
- function writeFileLog(message: string): void {
39
- const timestamp = new Date().toISOString()
40
- const logLine = `[${timestamp}] ${message}\n`
41
- const logDir = join(homedir(), '.openclaw', 'logs')
42
- const logFile = join(logDir, 'sendtext-outbound.log')
43
-
44
- try {
45
- appendFileSync(logFile, logLine)
46
- }
47
- catch (err) {
48
- console.error(`[writeFileLog] Failed to write log: ${err}`)
49
- }
50
- }
51
-
52
- export const workclawDock = {
53
- id: 'openclaw-workclaw',
54
- capabilities: {
55
- chatTypes: ['direct', 'group'],
56
- media: true,
57
- blockStreaming: true,
58
- },
59
- }
60
-
61
- export const workclawPlugin: ChannelPlugin<ResolvedWorkclawAccount> = {
62
- id: 'openclaw-workclaw',
63
- meta,
64
- capabilities: {
65
- chatTypes: ['direct', 'group'],
66
- media: true,
67
- reactions: false,
68
- threads: false,
69
- polls: false,
70
- nativeCommands: false,
71
- blockStreaming: true,
72
- },
73
- reload: { configPrefixes: ['channels.openclaw-workclaw'] },
74
- configSchema: buildChannelConfigSchema(WorkclawConfigSchema),
75
- config: {
76
- listAccountIds: cfg => listWorkclawAccountIds(cfg as OpenClawConfig),
77
- resolveAccount: (cfg, accountId) =>
78
- resolveWorkclawAccount({ cfg: cfg as OpenClawConfig, accountId }),
79
- isConfigured: account => isWorkclawAccountConfigured(account.config),
80
- describeAccount: account => ({
81
- accountId: account.accountId,
82
- name: account.name,
83
- enabled: account.enabled,
84
- configured: isWorkclawAccountConfigured(account.config),
85
- }),
86
- },
87
- outbound: {
88
- deliveryMode: 'direct',
89
- chunker: (text: string, _limit: number) => [text],
90
- textChunkLimit: 4096,
91
- sendText: async ({ to, text, accountId, cfg, replyToId }) => {
92
- writeFileLog(`outbound sendText called: replyToId=${replyToId}, accountId=${accountId}, to=${to}, text=${text.substring(0, 100)}`)
93
- const result = await sendMessageWorkclaw({
94
- accountId: accountId ?? undefined,
95
- cfg: cfg as OpenClawConfig,
96
- to,
97
- text,
98
- ...(replyToId ? { replyToMessageId: replyToId } : {}),
99
- last: false,
100
- source: 'sendText',
101
- })
102
- return {
103
- channel: 'openclaw-workclaw',
104
- ok: true,
105
- messageId: result.messageId,
106
- }
107
- },
108
- sendMedia: async ({ to, text, mediaUrl, accountId, cfg }) => {
109
- if (!mediaUrl && !text.trim()) {
110
- throw new Error('mediaUrl is required for outbound media')
111
- }
112
- const log = (getWorkclawRuntime() as any).log ?? console.log
113
- if (typeof log === 'function') {
114
- log(`outbound sendMedia called for ${to} with text ${text} and mediaUrl ${mediaUrl}`)
115
- }
116
- else if (log?.info) {
117
- log.info(`outbound sendMedia called for ${to} with text ${text} and mediaUrl ${mediaUrl}`)
118
- }
119
- const messageText = text.trim() ? text : mediaUrl ?? ''
120
- const result = await sendMessageWorkclaw({
121
- accountId: accountId ?? undefined,
122
- cfg: cfg as OpenClawConfig,
123
- to,
124
- text: messageText,
125
- mediaUrl: mediaUrl ?? undefined,
126
- last: false,
127
- source: 'sendText',
128
- })
129
- return {
130
- channel: 'openclaw-workclaw',
131
- ok: true,
132
- messageId: result.messageId,
133
- }
134
- },
135
- },
136
- security: {
137
- resolveDmPolicy: ({ cfg, accountId, account }) => {
138
- const resolvedAccountId = accountId ?? account.accountId ?? DEFAULT_ACCOUNT_ID
139
- const channelConfig = cfg.channels?.['openclaw-workclaw'] as WorkclawConfig | undefined
140
- const useAccountPath = Boolean(channelConfig?.accounts?.[resolvedAccountId])
141
- const basePath = useAccountPath
142
- ? `channels.openclaw-workclaw.accounts.${resolvedAccountId}.`
143
- : 'channels.openclaw-workclaw.'
144
- return {
145
- policy: account.config.dmPolicy ?? 'open',
146
- allowFrom: account.config.allowFrom ?? ['*'],
147
- policyPath: `${basePath}dmPolicy`,
148
- allowFromPath: `${basePath}allowFrom`,
149
- approveHint: formatPairingApproveHint('openclaw-workclaw'),
150
- normalizeEntry: raw => raw.replace(/^openclaw-workclaw:/i, ''),
151
- }
152
- },
153
- },
154
- status: {
155
- buildAccountSnapshot: async ({ account }) => {
156
- // WebSocket 用 appKey 存储
157
- const wsKey = account.config.appKey
158
- const ws = wsKey ? getWorkclawWsConnection(wsKey) : undefined
159
- const isConnected = ws && ws.readyState === 1 // WebSocket.OPEN = 1
160
- const lastInboundAt = account.accountId ? getLastInboundAt(account.accountId) : undefined
161
- const lastOutboundAt = account.accountId ? getLastOutboundAt(account.accountId) : undefined
162
-
163
- return {
164
- accountId: account.accountId,
165
- name: account.name,
166
- enabled: account.enabled,
167
- configured: account.configured,
168
- connected: isConnected,
169
- running: account.enabled && account.configured,
170
- lastInboundAt: lastInboundAt ?? null,
171
- lastOutboundAt: lastOutboundAt ?? null,
172
- }
173
- },
174
- },
175
- gateway: {
176
- startAccount: async (ctx: ChannelGatewayContext<ResolvedWorkclawAccount>) => {
177
- const { setStatus, getStatus, account, accountId, cfg, log } = ctx
178
- log?.info?.(`startAccount called for ${accountId}`)
179
-
180
- await startWorkclawGateway({
181
- accountId,
182
- account,
183
- cfg,
184
- log,
185
- })
186
-
187
- setStatus({
188
- ...getStatus(),
189
- running: true,
190
- lastStartAt: Date.now(),
191
- lastError: null,
192
- })
193
- log?.info?.(`startAccount completed for ${accountId}, keeping pending until abort`)
194
-
195
- // 保持 pending 状态直到 abortSignal 触发(防止 OpenClaw 3.8 认为启动立即退出)
196
- await new Promise<void>((resolve) => {
197
- if (ctx.abortSignal.aborted) {
198
- resolve()
199
- return
200
- }
201
- ctx.abortSignal.addEventListener('abort', () => resolve(), { once: true })
202
- })
203
-
204
- // abort 触发后,清理资源
205
- log?.info?.(`startAccount abort signal received for ${accountId}`)
206
- stopWorkclawGateway(accountId)
207
- setStatus({
208
- ...getStatus(),
209
- running: false,
210
- lastStopAt: Date.now(),
211
- })
212
- },
213
- stopAccount: async (ctx: ChannelGatewayContext<ResolvedWorkclawAccount>) => {
214
- const { setStatus, getStatus, accountId } = ctx
215
-
216
- // Stop WorkClaw gateway
217
- stopWorkclawGateway(accountId)
218
-
219
- setStatus({
220
- ...getStatus(),
221
- running: false,
222
- lastStopAt: Date.now(),
223
- })
224
- },
225
- },
226
- }
@@ -1,60 +0,0 @@
1
- import { z } from 'zod'
2
-
3
- export { z }
4
-
5
- const DmPolicySchema = z.enum(['open'])
6
-
7
- export const workclawAccountConfigSchema = z
8
- .object({
9
- enabled: z.boolean().optional(),
10
- name: z.string().optional(),
11
- agentId: z.union([z.string(), z.number()]).optional(),
12
- userId: z.union([z.string(), z.number()]).optional(),
13
- openConversationId: z.string().optional(),
14
- dmPolicy: DmPolicySchema.optional(),
15
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
16
- mediaMaxMb: z.number().positive().optional(),
17
- allowInsecureTls: z.boolean().optional(),
18
- })
19
- .strict()
20
-
21
- export const WorkclawConfigSchema = z
22
- .object({
23
- enabled: z.boolean().optional(),
24
- baseUrl: z.string().url().optional(),
25
- websocketUrl: z.string().url().optional(),
26
- appKey: z.string().optional(),
27
- appSecret: z.string().optional(),
28
- agentId: z.union([z.string(), z.number()]).optional(),
29
- localIp: z.string().optional(),
30
- userId: z.union([z.string(), z.number()]).optional(),
31
- requestTimeout: z.number().int().positive().optional(),
32
- allowInsecureTls: z.boolean().optional(),
33
- allowRawJsonPayload: z.boolean().optional(),
34
- uploadUrl: z.string().url().optional(),
35
- uploadFieldName: z.string().optional(),
36
- uploadHeaders: z.record(z.string(), z.string()).optional(),
37
- uploadFormFields: z
38
- .record(z.string(), z.union([z.string(), z.number(), z.boolean()]))
39
- .optional(),
40
- uploadResponseUrlPath: z.string().optional(),
41
- dmPolicy: DmPolicySchema.optional().default('open'),
42
- allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
43
- mediaMaxMb: z.number().positive().optional(),
44
- accounts: z.record(z.string(), workclawAccountConfigSchema.optional()).optional(),
45
- })
46
- .strict()
47
- .superRefine((value, ctx) => {
48
- const allowFrom = value.allowFrom ?? []
49
- const hasWildcard = allowFrom.some(entry => String(entry).trim() === '*')
50
- if (!hasWildcard) {
51
- ctx.addIssue({
52
- code: z.ZodIssueCode.custom,
53
- path: ['allowFrom'],
54
- message:
55
- 'channels.openclaw-workclaw.allowFrom must include "*"',
56
- })
57
- }
58
- })
59
-
60
- export const workclawConfigSchema = WorkclawConfigSchema