@workclaw/openclaw-workclaw 1.0.1 → 1.0.11
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/README.md +325 -325
- package/package.json +43 -43
- package/src/config-schema.ts +1 -1
- package/src/gateway/tools-list-handler.ts +162 -162
- package/src/media/upload.ts +12 -12
- package/src/outbound/index.ts +183 -183
- package/src/outbound/workclaw-sender.ts +2 -2
- package/src/tools/openclaw-workclaw-cron/api/index.ts +321 -321
- package/src/types.ts +2 -2
- package/src/utils/content.ts +5 -5
- package/templates/IDENTITY.md +1 -1
package/package.json
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@workclaw/openclaw-workclaw",
|
|
3
|
-
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"description": "OpenClaw WorkClaw channel plugin",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"main": "./src/index.ts",
|
|
8
|
-
"publishConfig": {
|
|
9
|
-
"access": "public"
|
|
10
|
-
},
|
|
11
|
-
"peerDependencies": {
|
|
12
|
-
"openclaw": "^2026.3.13",
|
|
13
|
-
"typescript": "^5.6.3"
|
|
14
|
-
},
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"undici": "^7.16.0",
|
|
17
|
-
"ws": "^8.19.0",
|
|
18
|
-
"zod": "^4.3.6"
|
|
19
|
-
},
|
|
20
|
-
"openclaw": {
|
|
21
|
-
"extensions": [
|
|
22
|
-
"./src/index.ts"
|
|
23
|
-
],
|
|
24
|
-
"channel": {
|
|
25
|
-
"id": "openclaw-workclaw",
|
|
26
|
-
"label": "openclaw-workclaw",
|
|
27
|
-
"selectionLabel": "智小途",
|
|
28
|
-
"docsPath": "/channels/openclaw-workclaw",
|
|
29
|
-
"docsLabel": "openclaw-workclaw",
|
|
30
|
-
"blurb": "智小途 企业通讯平台集成",
|
|
31
|
-
"aliases": [
|
|
32
|
-
"openclaw-workclaw"
|
|
33
|
-
],
|
|
34
|
-
"order": 35,
|
|
35
|
-
"quickstartAllowFrom": true
|
|
36
|
-
},
|
|
37
|
-
"install": {
|
|
38
|
-
"npmSpec": "@openclaw/openclaw-workclaw",
|
|
39
|
-
"localPath": "extensions/openclaw-workclaw",
|
|
40
|
-
"defaultChoice": "npm"
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@workclaw/openclaw-workclaw",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.11",
|
|
5
|
+
"description": "OpenClaw WorkClaw channel plugin",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./src/index.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"openclaw": "^2026.3.13",
|
|
13
|
+
"typescript": "^5.6.3"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"undici": "^7.16.0",
|
|
17
|
+
"ws": "^8.19.0",
|
|
18
|
+
"zod": "^4.3.6"
|
|
19
|
+
},
|
|
20
|
+
"openclaw": {
|
|
21
|
+
"extensions": [
|
|
22
|
+
"./src/index.ts"
|
|
23
|
+
],
|
|
24
|
+
"channel": {
|
|
25
|
+
"id": "openclaw-workclaw",
|
|
26
|
+
"label": "openclaw-workclaw",
|
|
27
|
+
"selectionLabel": "智小途",
|
|
28
|
+
"docsPath": "/channels/openclaw-workclaw",
|
|
29
|
+
"docsLabel": "openclaw-workclaw",
|
|
30
|
+
"blurb": "智小途 企业通讯平台集成",
|
|
31
|
+
"aliases": [
|
|
32
|
+
"openclaw-workclaw"
|
|
33
|
+
],
|
|
34
|
+
"order": 35,
|
|
35
|
+
"quickstartAllowFrom": true
|
|
36
|
+
},
|
|
37
|
+
"install": {
|
|
38
|
+
"npmSpec": "@openclaw/openclaw-workclaw",
|
|
39
|
+
"localPath": "extensions/openclaw-workclaw",
|
|
40
|
+
"defaultChoice": "npm"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/config-schema.ts
CHANGED
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tools List 事件处理器
|
|
3
|
-
* 处理云端下发的 TOOLS_LIST EVENT 消息
|
|
4
|
-
* 从 OpenClaw 获取 tools 列表并通过 HTTP 回调返回
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { fetch } from 'undici'
|
|
8
|
-
|
|
9
|
-
export interface ToolsListEvent {
|
|
10
|
-
agentId: string | number
|
|
11
|
-
userId: string | number
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ToolItem {
|
|
15
|
-
typeStr: string
|
|
16
|
-
name: string
|
|
17
|
-
description: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ToolsListCallbackPayload {
|
|
21
|
-
userId: number
|
|
22
|
-
agentId: number
|
|
23
|
-
dataList: ToolItem[]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 处理 TOOLS_LIST 事件
|
|
28
|
-
* @param event - 事件数据
|
|
29
|
-
* @param baseUrl - 回调基础 URL
|
|
30
|
-
* @param token - 鉴权 token
|
|
31
|
-
* @param log - 日志对象(可选)
|
|
32
|
-
*/
|
|
33
|
-
export async function handleToolsListEvent(
|
|
34
|
-
event: ToolsListEvent,
|
|
35
|
-
baseUrl: string,
|
|
36
|
-
token: string,
|
|
37
|
-
log?: {
|
|
38
|
-
info?: (msg: string) => void
|
|
39
|
-
error?: (msg: string) => void
|
|
40
|
-
},
|
|
41
|
-
): Promise<void> {
|
|
42
|
-
const agentId = Number(event.agentId)
|
|
43
|
-
const userId = Number(event.userId)
|
|
44
|
-
|
|
45
|
-
log?.info?.(`ToolsList: Handling TOOLS_LIST event for agentId: ${agentId}, userId: ${userId}`)
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
// 从 OpenClaw 获取 tools 列表
|
|
49
|
-
const tools = await fetchToolsFromOpenClaw(agentId, userId, log)
|
|
50
|
-
|
|
51
|
-
// 构建回调 payload
|
|
52
|
-
const callbackPayload: ToolsListCallbackPayload = {
|
|
53
|
-
userId,
|
|
54
|
-
agentId,
|
|
55
|
-
dataList: tools,
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// 发送回调
|
|
59
|
-
const callbackUrl = `${baseUrl.replace(/\/$/, '')}/open-apis/v1/claw/push/tools`
|
|
60
|
-
await sendToolsListCallback(callbackUrl, callbackPayload, token, log)
|
|
61
|
-
|
|
62
|
-
log?.info?.(`ToolsList: Successfully processed TOOLS_LIST event, sent ${tools.length} tools`)
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
log?.error?.(`ToolsList: Failed to handle TOOLS_LIST event: ${String(error)}`)
|
|
66
|
-
throw error
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 从 OpenClaw 获取 tools 列表
|
|
72
|
-
* 根据 agent 的 tools.allow 配置决定返回哪些工具
|
|
73
|
-
*/
|
|
74
|
-
async function fetchToolsFromOpenClaw(
|
|
75
|
-
agentId: number,
|
|
76
|
-
_userId: number,
|
|
77
|
-
log?: {
|
|
78
|
-
info?: (msg: string) => void
|
|
79
|
-
error?: (msg: string) => void
|
|
80
|
-
},
|
|
81
|
-
): Promise<ToolItem[]> {
|
|
82
|
-
log?.info?.(`ToolsList: Fetching tools from OpenClaw for agentId: ${agentId}`)
|
|
83
|
-
|
|
84
|
-
// OpenClaw 所有内置工具列表
|
|
85
|
-
const allTools: ToolItem[] = [
|
|
86
|
-
{ typeStr: 'function', name: 'web_search', description: 'Search the web for information using Brave Search API.' },
|
|
87
|
-
{ typeStr: 'function', name: 'web_fetch', description: 'Fetch and read content from a URL.' },
|
|
88
|
-
{ typeStr: 'function', name: 'sessions_list', description: 'List all active agent sessions.' },
|
|
89
|
-
{ typeStr: 'function', name: 'sessions_history', description: 'Get the history of a specific session.' },
|
|
90
|
-
{ typeStr: 'function', name: 'memory_search', description: 'Search memory for past conversations and information.' },
|
|
91
|
-
{ typeStr: 'function', name: 'memory_get', description: 'Get specific memory by ID.' },
|
|
92
|
-
{ typeStr: 'function', name: 'gateway', description: 'Gateway control operations.' },
|
|
93
|
-
{ typeStr: 'function', name: 'exec', description: 'Execute shell commands.' },
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
// 读取 OpenClaw 配置文件
|
|
98
|
-
const { readFile } = await import('node:fs/promises')
|
|
99
|
-
const { homedir } = await import('node:os')
|
|
100
|
-
const path = await import('node:path')
|
|
101
|
-
|
|
102
|
-
const configPath = path.join(homedir(), '.openclaw', 'openclaw.json')
|
|
103
|
-
const configContent = await readFile(configPath, 'utf-8')
|
|
104
|
-
const config = JSON.parse(configContent)
|
|
105
|
-
|
|
106
|
-
// 查找对应的 agent 配置
|
|
107
|
-
const agentConfig = config.agents?.list?.find((agent: any) =>
|
|
108
|
-
String(agent.id) === String(agentId)
|
|
109
|
-
|| agent.id === `openclaw-workclaw-${agentId}`,
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
// 获取 tools.allow 配置
|
|
113
|
-
const allowTools = agentConfig?.tools?.allow
|
|
114
|
-
|
|
115
|
-
// 如果没有 allow 配置,或者 allow 是 ["*"],返回所有工具
|
|
116
|
-
if (!allowTools || allowTools.length === 0 || allowTools.includes('*')) {
|
|
117
|
-
log?.info?.(`ToolsList: Agent has no allow restriction or allow=[*], returning all ${allTools.length} tools`)
|
|
118
|
-
return allTools
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 如果有具体的 allow 列表,只返回列表中的工具
|
|
122
|
-
const filteredTools = allTools.filter(tool => allowTools.includes(tool.name))
|
|
123
|
-
log?.info?.(`ToolsList: Agent allow=${JSON.stringify(allowTools)}, returning ${filteredTools.length} tools`)
|
|
124
|
-
return filteredTools
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
log?.error?.(`ToolsList: Error reading agent config: ${String(error)}, returning all tools`)
|
|
128
|
-
// 如果读取配置失败,返回所有工具
|
|
129
|
-
return allTools
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 发送 tools 列表回调
|
|
135
|
-
*/
|
|
136
|
-
async function sendToolsListCallback(
|
|
137
|
-
callbackUrl: string,
|
|
138
|
-
payload: ToolsListCallbackPayload,
|
|
139
|
-
token: string,
|
|
140
|
-
log?: {
|
|
141
|
-
info?: (msg: string) => void
|
|
142
|
-
error?: (msg: string) => void
|
|
143
|
-
},
|
|
144
|
-
): Promise<void> {
|
|
145
|
-
log?.info?.(`ToolsList: Sending callback to ${callbackUrl}`)
|
|
146
|
-
|
|
147
|
-
const response = await fetch(callbackUrl, {
|
|
148
|
-
method: 'POST',
|
|
149
|
-
headers: {
|
|
150
|
-
'Content-Type': 'application/json',
|
|
151
|
-
'Authorization': `Bearer ${token}`,
|
|
152
|
-
},
|
|
153
|
-
body: JSON.stringify(payload),
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
if (!response.ok) {
|
|
157
|
-
const errorText = await response.text()
|
|
158
|
-
throw new Error(`Callback failed: ${response.status} ${response.statusText} - ${errorText}`)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
log?.info?.(`ToolsList: Callback sent successfully: ${response.status}`)
|
|
162
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Tools List 事件处理器
|
|
3
|
+
* 处理云端下发的 TOOLS_LIST EVENT 消息
|
|
4
|
+
* 从 OpenClaw 获取 tools 列表并通过 HTTP 回调返回
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { fetch } from 'undici'
|
|
8
|
+
|
|
9
|
+
export interface ToolsListEvent {
|
|
10
|
+
agentId: string | number
|
|
11
|
+
userId: string | number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ToolItem {
|
|
15
|
+
typeStr: string
|
|
16
|
+
name: string
|
|
17
|
+
description: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ToolsListCallbackPayload {
|
|
21
|
+
userId: number
|
|
22
|
+
agentId: number
|
|
23
|
+
dataList: ToolItem[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 处理 TOOLS_LIST 事件
|
|
28
|
+
* @param event - 事件数据
|
|
29
|
+
* @param baseUrl - 回调基础 URL
|
|
30
|
+
* @param token - 鉴权 token
|
|
31
|
+
* @param log - 日志对象(可选)
|
|
32
|
+
*/
|
|
33
|
+
export async function handleToolsListEvent(
|
|
34
|
+
event: ToolsListEvent,
|
|
35
|
+
baseUrl: string,
|
|
36
|
+
token: string,
|
|
37
|
+
log?: {
|
|
38
|
+
info?: (msg: string) => void
|
|
39
|
+
error?: (msg: string) => void
|
|
40
|
+
},
|
|
41
|
+
): Promise<void> {
|
|
42
|
+
const agentId = Number(event.agentId)
|
|
43
|
+
const userId = Number(event.userId)
|
|
44
|
+
|
|
45
|
+
log?.info?.(`ToolsList: Handling TOOLS_LIST event for agentId: ${agentId}, userId: ${userId}`)
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// 从 OpenClaw 获取 tools 列表
|
|
49
|
+
const tools = await fetchToolsFromOpenClaw(agentId, userId, log)
|
|
50
|
+
|
|
51
|
+
// 构建回调 payload
|
|
52
|
+
const callbackPayload: ToolsListCallbackPayload = {
|
|
53
|
+
userId,
|
|
54
|
+
agentId,
|
|
55
|
+
dataList: tools,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 发送回调
|
|
59
|
+
const callbackUrl = `${baseUrl.replace(/\/$/, '')}/open-apis/v1/claw/push/tools`
|
|
60
|
+
await sendToolsListCallback(callbackUrl, callbackPayload, token, log)
|
|
61
|
+
|
|
62
|
+
log?.info?.(`ToolsList: Successfully processed TOOLS_LIST event, sent ${tools.length} tools`)
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
log?.error?.(`ToolsList: Failed to handle TOOLS_LIST event: ${String(error)}`)
|
|
66
|
+
throw error
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 从 OpenClaw 获取 tools 列表
|
|
72
|
+
* 根据 agent 的 tools.allow 配置决定返回哪些工具
|
|
73
|
+
*/
|
|
74
|
+
async function fetchToolsFromOpenClaw(
|
|
75
|
+
agentId: number,
|
|
76
|
+
_userId: number,
|
|
77
|
+
log?: {
|
|
78
|
+
info?: (msg: string) => void
|
|
79
|
+
error?: (msg: string) => void
|
|
80
|
+
},
|
|
81
|
+
): Promise<ToolItem[]> {
|
|
82
|
+
log?.info?.(`ToolsList: Fetching tools from OpenClaw for agentId: ${agentId}`)
|
|
83
|
+
|
|
84
|
+
// OpenClaw 所有内置工具列表
|
|
85
|
+
const allTools: ToolItem[] = [
|
|
86
|
+
{ typeStr: 'function', name: 'web_search', description: 'Search the web for information using Brave Search API.' },
|
|
87
|
+
{ typeStr: 'function', name: 'web_fetch', description: 'Fetch and read content from a URL.' },
|
|
88
|
+
{ typeStr: 'function', name: 'sessions_list', description: 'List all active agent sessions.' },
|
|
89
|
+
{ typeStr: 'function', name: 'sessions_history', description: 'Get the history of a specific session.' },
|
|
90
|
+
{ typeStr: 'function', name: 'memory_search', description: 'Search memory for past conversations and information.' },
|
|
91
|
+
{ typeStr: 'function', name: 'memory_get', description: 'Get specific memory by ID.' },
|
|
92
|
+
{ typeStr: 'function', name: 'gateway', description: 'Gateway control operations.' },
|
|
93
|
+
{ typeStr: 'function', name: 'exec', description: 'Execute shell commands.' },
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
// 读取 OpenClaw 配置文件
|
|
98
|
+
const { readFile } = await import('node:fs/promises')
|
|
99
|
+
const { homedir } = await import('node:os')
|
|
100
|
+
const path = await import('node:path')
|
|
101
|
+
|
|
102
|
+
const configPath = path.join(homedir(), '.openclaw', 'openclaw.json')
|
|
103
|
+
const configContent = await readFile(configPath, 'utf-8')
|
|
104
|
+
const config = JSON.parse(configContent)
|
|
105
|
+
|
|
106
|
+
// 查找对应的 agent 配置
|
|
107
|
+
const agentConfig = config.agents?.list?.find((agent: any) =>
|
|
108
|
+
String(agent.id) === String(agentId)
|
|
109
|
+
|| agent.id === `openclaw-workclaw-${agentId}`,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// 获取 tools.allow 配置
|
|
113
|
+
const allowTools = agentConfig?.tools?.allow
|
|
114
|
+
|
|
115
|
+
// 如果没有 allow 配置,或者 allow 是 ["*"],返回所有工具
|
|
116
|
+
if (!allowTools || allowTools.length === 0 || allowTools.includes('*')) {
|
|
117
|
+
log?.info?.(`ToolsList: Agent has no allow restriction or allow=[*], returning all ${allTools.length} tools`)
|
|
118
|
+
return allTools
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 如果有具体的 allow 列表,只返回列表中的工具
|
|
122
|
+
const filteredTools = allTools.filter(tool => allowTools.includes(tool.name))
|
|
123
|
+
log?.info?.(`ToolsList: Agent allow=${JSON.stringify(allowTools)}, returning ${filteredTools.length} tools`)
|
|
124
|
+
return filteredTools
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
log?.error?.(`ToolsList: Error reading agent config: ${String(error)}, returning all tools`)
|
|
128
|
+
// 如果读取配置失败,返回所有工具
|
|
129
|
+
return allTools
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 发送 tools 列表回调
|
|
135
|
+
*/
|
|
136
|
+
async function sendToolsListCallback(
|
|
137
|
+
callbackUrl: string,
|
|
138
|
+
payload: ToolsListCallbackPayload,
|
|
139
|
+
token: string,
|
|
140
|
+
log?: {
|
|
141
|
+
info?: (msg: string) => void
|
|
142
|
+
error?: (msg: string) => void
|
|
143
|
+
},
|
|
144
|
+
): Promise<void> {
|
|
145
|
+
log?.info?.(`ToolsList: Sending callback to ${callbackUrl}`)
|
|
146
|
+
|
|
147
|
+
const response = await fetch(callbackUrl, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: {
|
|
150
|
+
'Content-Type': 'application/json',
|
|
151
|
+
'Authorization': `Bearer ${token}`,
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify(payload),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
if (!response.ok) {
|
|
157
|
+
const errorText = await response.text()
|
|
158
|
+
throw new Error(`Callback failed: ${response.status} ${response.statusText} - ${errorText}`)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
log?.info?.(`ToolsList: Callback sent successfully: ${response.status}`)
|
|
162
|
+
}
|
package/src/media/upload.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { readFile, stat } from 'node:fs/promises'
|
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import path from 'node:path'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
export function isLocalMediaSource(value: string): boolean {
|
|
7
7
|
const trimmed = value.trim()
|
|
8
8
|
return (
|
|
@@ -28,12 +28,12 @@ function readResponseUrlPath(
|
|
|
28
28
|
data: Record<string, unknown>,
|
|
29
29
|
pathValue?: string,
|
|
30
30
|
): string | undefined {
|
|
31
|
-
if (!pathValue)
|
|
31
|
+
if (!pathValue)
|
|
32
32
|
return undefined
|
|
33
33
|
const parts = pathValue.split('.').filter(Boolean)
|
|
34
34
|
let current: unknown = data
|
|
35
35
|
for (const part of parts) {
|
|
36
|
-
if (!current || typeof current !== 'object')
|
|
36
|
+
if (!current || typeof current !== 'object')
|
|
37
37
|
return undefined
|
|
38
38
|
current = (current as Record<string, unknown>)[part]
|
|
39
39
|
}
|
|
@@ -46,22 +46,22 @@ function extractUploadedUrl(
|
|
|
46
46
|
pathValue?: string,
|
|
47
47
|
): string | undefined {
|
|
48
48
|
const fromPath = readResponseUrlPath(responseData, pathValue)
|
|
49
|
-
if (fromPath)
|
|
49
|
+
if (fromPath)
|
|
50
50
|
return fromPath
|
|
51
51
|
|
|
52
52
|
const direct
|
|
53
53
|
= (responseData.url as string | undefined)
|
|
54
54
|
?? (responseData.mediaUrl as string | undefined)
|
|
55
|
-
if (typeof direct === 'string' && direct.trim())
|
|
55
|
+
if (typeof direct === 'string' && direct.trim())
|
|
56
56
|
return direct
|
|
57
57
|
|
|
58
58
|
const dataObj = responseData.data
|
|
59
59
|
if (dataObj && typeof dataObj === 'object') {
|
|
60
60
|
const dataUrl = (dataObj as Record<string, unknown>).url
|
|
61
61
|
const dataMedia = (dataObj as Record<string, unknown>).mediaUrl
|
|
62
|
-
if (typeof dataUrl === 'string' && dataUrl.trim())
|
|
62
|
+
if (typeof dataUrl === 'string' && dataUrl.trim())
|
|
63
63
|
return dataUrl
|
|
64
|
-
if (typeof dataMedia === 'string' && dataMedia.trim())
|
|
64
|
+
if (typeof dataMedia === 'string' && dataMedia.trim())
|
|
65
65
|
return dataMedia
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,9 +69,9 @@ function extractUploadedUrl(
|
|
|
69
69
|
if (resultObj && typeof resultObj === 'object') {
|
|
70
70
|
const resultUrl = (resultObj as Record<string, unknown>).url
|
|
71
71
|
const resultMedia = (resultObj as Record<string, unknown>).mediaUrl
|
|
72
|
-
if (typeof resultUrl === 'string' && resultUrl.trim())
|
|
72
|
+
if (typeof resultUrl === 'string' && resultUrl.trim())
|
|
73
73
|
return resultUrl
|
|
74
|
-
if (typeof resultMedia === 'string' && resultMedia.trim())
|
|
74
|
+
if (typeof resultMedia === 'string' && resultMedia.trim())
|
|
75
75
|
return resultMedia
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -121,7 +121,7 @@ export async function uploadLocalMedia(params: UploadLocalMediaParams): Promise<
|
|
|
121
121
|
const { Agent, fetch: undiciFetchFn } = await import('undici')
|
|
122
122
|
dispatcher = new Agent({ connect: { rejectUnauthorized: false } })
|
|
123
123
|
doFetch = undiciFetchFn as any
|
|
124
|
-
}
|
|
124
|
+
}
|
|
125
125
|
catch (error) {
|
|
126
126
|
const message = error instanceof Error ? error.message : String(error)
|
|
127
127
|
throw new Error(`allowInsecureTls requires undici. ${message}`)
|
|
@@ -146,7 +146,7 @@ export async function uploadLocalMedia(params: UploadLocalMediaParams): Promise<
|
|
|
146
146
|
if (responseText) {
|
|
147
147
|
try {
|
|
148
148
|
data = JSON.parse(responseText) as Record<string, unknown>
|
|
149
|
-
}
|
|
149
|
+
}
|
|
150
150
|
catch {
|
|
151
151
|
data = {}
|
|
152
152
|
}
|
|
@@ -161,7 +161,7 @@ export async function uploadLocalMedia(params: UploadLocalMediaParams): Promise<
|
|
|
161
161
|
throw new Error('Upload response missing file URL')
|
|
162
162
|
}
|
|
163
163
|
return uploadedUrl
|
|
164
|
-
}
|
|
164
|
+
}
|
|
165
165
|
finally {
|
|
166
166
|
clearTimeout(timeoutId)
|
|
167
167
|
}
|