openclaw-openagent 1.0.12 → 1.0.14

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 (132) hide show
  1. package/dist/index.js +2 -0
  2. package/dist/src/config/config-schema.d.ts +9 -0
  3. package/dist/src/config/config-schema.js +6 -0
  4. package/dist/src/messaging/executor.d.ts +2 -3
  5. package/dist/src/messaging/executor.js +4 -31
  6. package/dist/src/plugin-ui/assets/openagent-override.js +124 -18
  7. package/dist/src/proxy/auth-proxy.js +5 -0
  8. package/dist/src/runtime/update-checker.d.ts +18 -0
  9. package/dist/src/runtime/update-checker.js +216 -0
  10. package/index.ts +3 -0
  11. package/package.json +1 -3
  12. package/src/app/channel-tools.ts +0 -249
  13. package/src/app/discovery-tools.ts +0 -273
  14. package/src/app/download-file-tool.ts +0 -133
  15. package/src/app/hooks.ts +0 -144
  16. package/src/app/index.ts +0 -84
  17. package/src/app/messaging-tools.ts +0 -79
  18. package/src/app/ops-tools.ts +0 -155
  19. package/src/app/remote-agent-tool.ts +0 -762
  20. package/src/app/types.ts +0 -68
  21. package/src/app/upload-file-tool.ts +0 -411
  22. package/src/app/verbose-preflight.ts +0 -190
  23. package/src/auth/config.ts +0 -266
  24. package/src/auth/credential-manager.ts +0 -146
  25. package/src/auth/index.ts +0 -24
  26. package/src/auth/verify.ts +0 -99
  27. package/src/channel.ts +0 -566
  28. package/src/compat.ts +0 -94
  29. package/src/config/config-schema.ts +0 -39
  30. package/src/messaging/aggregator.ts +0 -120
  31. package/src/messaging/collector.ts +0 -89
  32. package/src/messaging/executor.ts +0 -72
  33. package/src/messaging/inbound.ts +0 -150
  34. package/src/messaging/index.ts +0 -11
  35. package/src/messaging/mention-protocol.ts +0 -94
  36. package/src/messaging/process-c2c-request.ts +0 -564
  37. package/src/messaging/process-message.ts +0 -373
  38. package/src/messaging/scheduler.ts +0 -55
  39. package/src/messaging/types.ts +0 -38
  40. package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
  41. package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
  42. package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
  43. package/src/plugin-ui/adapters/oc-unknown.js +0 -48
  44. package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
  45. package/src/plugin-ui/assets/bg.png +0 -0
  46. package/src/plugin-ui/assets/icon.png +0 -0
  47. package/src/plugin-ui/assets/magic.svg +0 -5
  48. package/src/plugin-ui/assets/openagent-override.js +0 -11156
  49. package/src/plugin-ui/build.cjs +0 -463
  50. package/src/plugin-ui/index.ts +0 -18
  51. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
  52. package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
  53. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
  54. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
  55. package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
  56. package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -833
  57. package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
  58. package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
  59. package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
  60. package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
  61. package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
  62. package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
  63. package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -256
  64. package/src/plugin-ui/modules/loader/bootstrap.js +0 -38
  65. package/src/plugin-ui/modules/loader/shared-state.js +0 -838
  66. package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
  67. package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
  68. package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
  69. package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
  70. package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
  71. package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
  72. package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
  73. package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
  74. package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
  75. package/src/plugin-ui/modules/remote-agent/styles.js +0 -896
  76. package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
  77. package/src/plugin-ui/postinstall-deploy.cjs +0 -52
  78. package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
  79. package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
  80. package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
  81. package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
  82. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
  83. package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
  84. package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
  85. package/src/proxy/auth-proxy.ts +0 -409
  86. package/src/runtime/account.ts +0 -549
  87. package/src/runtime/index.ts +0 -7
  88. package/src/runtime/plugin-runtime.ts +0 -94
  89. package/src/runtime/registry.ts +0 -71
  90. package/src/sdk/CLASS_MAP.md +0 -143
  91. package/src/sdk/index.d.ts +0 -126
  92. package/src/sdk/index.js +0 -23990
  93. package/src/sdk/modules/cloud-search-module.js +0 -1117
  94. package/src/sdk/modules/follow-module.js +0 -1069
  95. package/src/sdk/modules/group-module.js +0 -7397
  96. package/src/sdk/modules/relationship-module.js +0 -2269
  97. package/src/sdk/modules/signaling-module.js +0 -1468
  98. package/src/sdk/modules/tim-upload-plugin.js +0 -730
  99. package/src/sdk/node-env/http-request.js +0 -90
  100. package/src/sdk/node-env/index.js +0 -57
  101. package/src/sdk/node-env/storage.js +0 -114
  102. package/src/sdk/package.json +0 -10
  103. package/src/sdk/tsconfig.json +0 -16
  104. package/src/state/pending-invocation-store.ts +0 -43
  105. package/src/state/store.ts +0 -756
  106. package/src/tim/c2c.ts +0 -451
  107. package/src/tim/channels.ts +0 -364
  108. package/src/tim/client.ts +0 -330
  109. package/src/tim/index.ts +0 -18
  110. package/src/tim/messages.ts +0 -166
  111. package/src/tim/sdk-logger-init.ts +0 -50
  112. package/src/tools.ts +0 -10
  113. package/src/transport/factory.ts +0 -95
  114. package/src/transport/oasn/index.ts +0 -17
  115. package/src/transport/oasn/oasn-agent-card.ts +0 -111
  116. package/src/transport/oasn/oasn-discovery.ts +0 -108
  117. package/src/transport/oasn/oasn-files.ts +0 -210
  118. package/src/transport/oasn/oasn-http.ts +0 -529
  119. package/src/transport/oasn/oasn-invocation.ts +0 -604
  120. package/src/transport/oasn/oasn-normalize.ts +0 -133
  121. package/src/transport/oasn/oasn-register.ts +0 -33
  122. package/src/transport/oasn/oasn-transport.ts +0 -318
  123. package/src/transport/oasn/oasn-types.ts +0 -404
  124. package/src/transport/tim/index.ts +0 -8
  125. package/src/transport/tim/tim-transport.ts +0 -515
  126. package/src/transport/types.ts +0 -538
  127. package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
  128. package/src/types/openclaw.d.ts +0 -97
  129. package/src/types/tencentcloud-chat.d.ts +0 -15
  130. package/src/util/http.ts +0 -113
  131. package/src/util/logger.ts +0 -131
  132. package/src/util/url-resolver.ts +0 -77
@@ -1,249 +0,0 @@
1
- /**
2
- * Channel Tools — 8 channel management tools
3
- *
4
- * list_channels, search_channels, join_channel, leave_channel,
5
- * create_channel, get_members, set_channel_skill, get_channel_skill
6
- *
7
- * Contract ref: §0.2 refactoring-plan.md
8
- */
9
-
10
- import { registry } from '../runtime/registry.js';
11
- import { toolResult, type ToolDescriptor, type ToolParams, type ToolResult } from './types.js';
12
-
13
- function fail(error: string): ToolResult {
14
- return toolResult(JSON.stringify({ success: false, error }));
15
- }
16
-
17
- function getRuntime() {
18
- const rt = registry.getDefault();
19
- if (!rt || !rt.isRunning) return null;
20
- return rt;
21
- }
22
-
23
- export function createListChannelsTool(): ToolDescriptor {
24
- return {
25
- name: 'openagent_list_channels',
26
- label: 'List OpenAgent Channels',
27
- description: 'List all available channels on OpenAgent agent network',
28
- parameters: { type: 'object', properties: {}, required: [] },
29
- async execute() {
30
- const rt = getRuntime();
31
- if (!rt) return fail('Not connected');
32
- try {
33
- const channels = await rt.listChannels();
34
- return toolResult(JSON.stringify({ success: true, channels }));
35
- } catch (err) {
36
- return fail((err as Error).message);
37
- }
38
- },
39
- };
40
- }
41
-
42
- export function createSearchChannelsTool(): ToolDescriptor {
43
- return {
44
- name: 'openagent_search_channels',
45
- label: 'Search OpenAgent Channels',
46
- description: 'Search channels by keyword',
47
- parameters: {
48
- type: 'object',
49
- properties: { keyword: { type: 'string', description: 'Search keyword' } },
50
- required: ['keyword'],
51
- },
52
- async execute(_id: unknown, params: ToolParams) {
53
- const rt = getRuntime();
54
- if (!rt) return fail('Not connected');
55
- try {
56
- const channels = await rt.searchChannels(String(params.keyword || ''));
57
- return toolResult(JSON.stringify({ success: true, channels }));
58
- } catch (err) {
59
- return fail((err as Error).message);
60
- }
61
- },
62
- };
63
- }
64
-
65
- /**
66
- * join_channel — supports optional `purpose?` per §0.2.
67
- * If purpose is provided, it is stored via setPurpose().
68
- */
69
- export function createJoinChannelTool(): ToolDescriptor {
70
- return {
71
- name: 'openagent_join_channel',
72
- label: 'Join OpenAgent Channel',
73
- description: 'Join a channel by ID (e.g. ch-001). Optionally set a purpose for this channel.',
74
- parameters: {
75
- type: 'object',
76
- properties: {
77
- channelId: { type: 'string', description: 'Channel ID to join' },
78
- purpose: { type: 'string', description: 'Optional: your purpose/goal for this channel' },
79
- },
80
- required: ['channelId'],
81
- },
82
- async execute(_id: unknown, params: ToolParams) {
83
- const rt = getRuntime();
84
- if (!rt) return fail('Not connected');
85
- try {
86
- const channelId = String(params.channelId);
87
- const result = await rt.joinChannel(channelId);
88
- if (result.success && rt.store) {
89
- rt.store.markJoined(channelId, channelId);
90
- if (params.purpose) {
91
- rt.store.setPurpose(channelId, String(params.purpose));
92
- }
93
- }
94
- return toolResult(JSON.stringify({
95
- success: result.success,
96
- channelId,
97
- purpose: params.purpose ? String(params.purpose) : undefined,
98
- }));
99
- } catch (err) {
100
- return fail((err as Error).message);
101
- }
102
- },
103
- };
104
- }
105
-
106
- export function createLeaveChannelTool(): ToolDescriptor {
107
- return {
108
- name: 'openagent_leave_channel',
109
- label: 'Leave OpenAgent Channel',
110
- description: 'Leave a channel by ID',
111
- parameters: {
112
- type: 'object',
113
- properties: { channelId: { type: 'string', description: 'Channel ID to leave' } },
114
- required: ['channelId'],
115
- },
116
- async execute(_id: unknown, params: ToolParams) {
117
- const rt = getRuntime();
118
- if (!rt) return fail('Not connected');
119
- try {
120
- const channelId = String(params.channelId);
121
- const result = await rt.leaveChannel(channelId);
122
- if (result.success && rt.store) {
123
- rt.store.markLeft(channelId);
124
- }
125
- return toolResult(JSON.stringify(result));
126
- } catch (err) {
127
- return fail((err as Error).message);
128
- }
129
- },
130
- };
131
- }
132
-
133
- /**
134
- * create_channel — supports optional `channelId?`, `skill?`, `desc?` per §0.2.
135
- * If channelId is not given, auto-generates one.
136
- */
137
- export function createCreateChannelTool(): ToolDescriptor {
138
- return {
139
- name: 'openagent_create_channel',
140
- label: 'Create OpenAgent Channel',
141
- description: 'Create a new channel. You become the owner and are automatically joined.',
142
- parameters: {
143
- type: 'object',
144
- properties: {
145
- name: { type: 'string', description: 'Channel display name (e.g. "AI Research Discussion")' },
146
- desc: { type: 'string', description: 'Short description of the channel topic' },
147
- skill: { type: 'string', description: 'Optional initial channel skill/rules' },
148
- },
149
- required: ['name'],
150
- },
151
- async execute(_id: unknown, params: ToolParams) {
152
- const rt = getRuntime();
153
- if (!rt) return fail('Not connected');
154
- try {
155
- // Community groups: SDK auto-generates @TGS#_ prefixed groupID
156
- const result = await rt.createChannel(
157
- String(params.name),
158
- String(params.desc || ''),
159
- params.skill ? String(params.skill) : undefined,
160
- );
161
- return toolResult(JSON.stringify(result));
162
- } catch (err) {
163
- return fail((err as Error).message);
164
- }
165
- },
166
- };
167
- }
168
-
169
- /**
170
- * get_members — returns avatar? field per §0.2.
171
- */
172
- export function createGetMembersTool(): ToolDescriptor {
173
- return {
174
- name: 'openagent_get_members',
175
- label: 'Get Channel Members',
176
- description: 'Get the member list of a channel',
177
- parameters: {
178
- type: 'object',
179
- properties: { channelId: { type: 'string', description: 'Channel ID' } },
180
- required: ['channelId'],
181
- },
182
- async execute(_id: unknown, params: ToolParams) {
183
- const rt = getRuntime();
184
- if (!rt) return fail('Not connected');
185
- try {
186
- const members = await rt.getMembers(String(params.channelId));
187
- // Preserve all fields including avatar? per contract
188
- return toolResult(JSON.stringify({ success: true, members }));
189
- } catch (err) {
190
- return fail((err as Error).message);
191
- }
192
- },
193
- };
194
- }
195
-
196
- export function createSetChannelSkillTool(): ToolDescriptor {
197
- return {
198
- name: 'openagent_set_channel_skill',
199
- label: 'Set Channel Skill',
200
- description: 'Set the skill/behavior rules for a channel',
201
- parameters: {
202
- type: 'object',
203
- properties: {
204
- channelId: { type: 'string', description: 'Channel ID' },
205
- skill: { type: 'string', description: 'Channel rules that control agent behavior' },
206
- },
207
- required: ['channelId', 'skill'],
208
- },
209
- async execute(_id: unknown, params: ToolParams) {
210
- const rt = getRuntime();
211
- if (!rt) return fail('Not connected');
212
- try {
213
- await rt.setChannelSkill(String(params.channelId), String(params.skill));
214
- return toolResult(JSON.stringify({ success: true, message: `Skill set for ${params.channelId}` }));
215
- } catch (err) {
216
- return fail((err as Error).message);
217
- }
218
- },
219
- };
220
- }
221
-
222
- export function createGetChannelSkillTool(): ToolDescriptor {
223
- return {
224
- name: 'openagent_get_channel_skill',
225
- label: 'Get Channel Skill',
226
- description: 'Get the current skill/behavior rules for a channel',
227
- parameters: {
228
- type: 'object',
229
- properties: {
230
- channelId: { type: 'string', description: 'Channel ID' },
231
- },
232
- required: ['channelId'],
233
- },
234
- async execute(_id: unknown, params: ToolParams) {
235
- const rt = getRuntime();
236
- if (!rt) return fail('Not connected');
237
- try {
238
- const skill = await rt.getChannelSkill(String(params.channelId));
239
- return toolResult(JSON.stringify({
240
- success: true,
241
- channelId: params.channelId,
242
- skill: skill || '(no skill set)',
243
- }));
244
- } catch (err) {
245
- return fail((err as Error).message);
246
- }
247
- },
248
- };
249
- }
@@ -1,273 +0,0 @@
1
- /**
2
- * Discovery Tools — Agent 搜索 / Agent 详情
3
- *
4
- * 封装 OASN DiscoveryTransport 能力为 LLM 可用工具。
5
- * 当前仅 OASN 模式可用;TIM 模式下工具返回明确错误。
6
- *
7
- * 设计依据:docs/specs/2026-06-21-oasn-agent-search-tool-wiring.md
8
- *
9
- * 工具列表:
10
- * - openagent_search_agents — 按关键词 / 分类 / 标签搜索 Agent
11
- * - openagent_get_agent_detail — 查看单个 Agent 详情
12
- *
13
- * 注:getCategories() 传输层能力保留给 Agent Book UI 使用,不暴露为 LLM 工具。
14
- */
15
-
16
- import { registry } from '../runtime/registry.js';
17
- import { logger } from '../util/logger.js';
18
- import {
19
- toolResult,
20
- type ToolDescriptor,
21
- type ToolFactory,
22
- type ToolParams,
23
- type ToolResult,
24
- } from './types.js';
25
- import type { SearchQuery, AgentCard, OasnTransport } from '../transport/types.js';
26
-
27
- // ── Helpers ──
28
-
29
- function fail(error: string): ToolResult {
30
- return toolResult(JSON.stringify({ success: false, error }));
31
- }
32
-
33
- /**
34
- * 从 AccountRuntime 获取 OASN transport 并 narrow 为 DiscoveryTransport。
35
- * 返回 { error: string } 表示不可用(未连接 / TIM 模式 / transport 未就绪)。
36
- */
37
- function getOasnDiscovery(): { error: string } | { transport: OasnTransport } {
38
- const rt = registry.getDefault();
39
- if (!rt || !rt.isRunning) return { error: 'OpenAgent runtime not running' };
40
- if (rt.transportType !== 'oasn') {
41
- return { error: 'Agent discovery is only available via OASN transport' };
42
- }
43
- const transport = rt.transport;
44
- if (!transport || transport.transportType !== 'oasn') {
45
- return { error: 'OASN transport not ready' };
46
- }
47
- // transportType check above guarantees OASN transport
48
- return { transport: transport as OasnTransport };
49
- }
50
-
51
- /**
52
- * 将 AgentCard 转换为 LLM 友好的精简视图。
53
- * 去除内部字段(agent_type / visibility),保留用户关心的信息。
54
- */
55
- function agentCardToSummary(card: AgentCard) {
56
- return {
57
- agent_id: card.agent_id,
58
- name: card.name,
59
- description: card.description,
60
- tags: card.tags?.map((t) => t.name) ?? [],
61
- category: card.category,
62
- avatar_url: card.avatar_url,
63
- };
64
- }
65
-
66
- // ═══════════════════════════════════════════════════════════════
67
- // 工具 1: openagent_search_agents
68
- // ═══════════════════════════════════════════════════════════════
69
-
70
- /**
71
- * 搜索可用 Agent。
72
- *
73
- * 三种搜索模式(互斥,按优先级):
74
- * 1. query — 自然语言搜索(POST /api/agent-cards/search/by-query)
75
- * 2. category — 分类浏览(POST /api/agent-cards/search/by-category)
76
- * 3. tags — 标签筛选(POST /api/agent-cards/search/by-tags)
77
- *
78
- * LLM 使用场景:
79
- * - 用户说"我想去旅行" → search_agents({ query: "旅行" })
80
- * - 用户说"找个机票助手" → search_agents({ query: "机票" })
81
- * - 用户说"看看有哪些旅行类 Agent" → search_agents({ category: ["travel"] })
82
- */
83
- export const createSearchAgentsTool: ToolFactory = () => ({
84
- name: 'openagent_search_agents',
85
- label: 'Search Available Agents',
86
- description: [
87
- 'Search for available service agents by natural language query, category, or tags.',
88
- 'Use this tool when the user expresses an intent that might be handled by a specialist agent.',
89
- 'Examples:',
90
- ' - "我想去旅行" → search_agents({ query: "旅行" })',
91
- ' - "帮我查航班" → search_agents({ query: "机票" })',
92
- ' - "有什么翻译助手" → search_agents({ query: "翻译" })',
93
- 'After finding agents, pick the most relevant one and call openagent_call_remote_agent with its agent_id.',
94
- 'At least one of query, category, or tags must be provided.',
95
- ].join(' '),
96
- parameters: {
97
- type: 'object',
98
- properties: {
99
- query: {
100
- type: 'string',
101
- description: 'Natural language search query, e.g. "旅行" or "机票预订"',
102
- },
103
- category: {
104
- type: 'string',
105
- description: 'Category path to browse, e.g. "travel" or ["travel", "flights"]',
106
- },
107
- tags: {
108
- type: 'string',
109
- description: 'Comma-separated tag names to filter by, e.g. "机票,酒店"',
110
- },
111
- page_size: {
112
- type: 'number',
113
- description: 'Results per page (default 10, max 50)',
114
- default: 10,
115
- },
116
- page_num: {
117
- type: 'number',
118
- description: 'Page number, 1-indexed (default 1)',
119
- default: 1,
120
- },
121
- },
122
- required: [], // 至少提供一个: query / category / tags(运行时校验)
123
- },
124
-
125
- async execute(_id: unknown, params: ToolParams): Promise<ToolResult> {
126
- logger.info(`[discovery-tools] search_agents called: ${JSON.stringify(params)}`);
127
-
128
- // ① 获取 OASN transport
129
- const discovery = getOasnDiscovery();
130
- if ('error' in discovery) {
131
- logger.warn(`[discovery-tools] search_agents unavailable: ${discovery.error}`);
132
- return fail(discovery.error);
133
- }
134
-
135
- // ② 构造 SearchQuery
136
- const searchQuery = buildSearchQuery(params);
137
- if (!searchQuery.query && !searchQuery.category?.length && !searchQuery.tags?.length) {
138
- return fail('At least one of query, category, or tags must be provided');
139
- }
140
-
141
- // ③ 调用 transport.searchAgents()
142
- try {
143
- const result = await discovery.transport.searchAgents(searchQuery);
144
- logger.info(
145
- `[discovery-tools] search_agents returned: searchId=${result.searchId} ` +
146
- `count=${result.agentCards.length} hasNext=${result.hasNext}`,
147
- );
148
-
149
- return toolResult(JSON.stringify({
150
- success: true,
151
- search_id: result.searchId,
152
- agents: result.agentCards.map(agentCardToSummary),
153
- page: {
154
- num: result.pageNum,
155
- size: result.pageSize,
156
- has_next: result.hasNext,
157
- },
158
- }, null, 2));
159
- } catch (err) {
160
- const msg = (err as Error).message;
161
- logger.error(`[discovery-tools] search_agents failed: ${msg}`);
162
- return fail(`Agent search failed: ${msg}`);
163
- }
164
- },
165
- });
166
-
167
- /**
168
- * 将工具参数转换为 SearchQuery。
169
- * 处理类型转换(string → string[])和默认值。
170
- */
171
- function buildSearchQuery(params: ToolParams): SearchQuery {
172
- const query: SearchQuery = {
173
- agentTypes: ['service'], // 只搜索 service 类型
174
- pageSize: params.page_size ? Number(params.page_size) : 10,
175
- pageNum: params.page_num ? Number(params.page_num) : 1,
176
- };
177
-
178
- // query: 自然语言搜索
179
- if (params.query && typeof params.query === 'string') {
180
- query.query = params.query.trim();
181
- }
182
-
183
- // category: 可能是 string 或 string[]
184
- if (params.category) {
185
- if (Array.isArray(params.category)) {
186
- query.category = params.category.map(String);
187
- } else if (typeof params.category === 'string') {
188
- // 支持逗号分隔或单值
189
- query.category = params.category.split(',').map((s) => s.trim()).filter(Boolean);
190
- }
191
- }
192
-
193
- // tags: 可能是 string 或 string[]
194
- if (params.tags) {
195
- if (Array.isArray(params.tags)) {
196
- query.tags = params.tags.map(String);
197
- } else if (typeof params.tags === 'string') {
198
- query.tags = params.tags.split(',').map((s) => s.trim()).filter(Boolean);
199
- }
200
- }
201
-
202
- return query;
203
- }
204
-
205
- // ═══════════════════════════════════════════════════════════════
206
- // 工具 2: openagent_get_agent_detail
207
- // ═══════════════════════════════════════════════════════════════
208
-
209
- /**
210
- * 查看单个 Agent 详情。
211
- *
212
- * 在搜索结果中选择了一个 Agent 后,可以调用此工具获取完整信息(包括 MOM)。
213
- */
214
- export const createGetAgentDetailTool: ToolFactory = () => ({
215
- name: 'openagent_get_agent_detail',
216
- label: 'Get Agent Details',
217
- description: [
218
- 'Get detailed information about a specific agent by its agent_id.',
219
- 'Use this after search_agents to see the full agent card including description and MOM (Model Operation Manual).',
220
- 'The MOM contains usage instructions for the agent.',
221
- ].join(' '),
222
- parameters: {
223
- type: 'object',
224
- properties: {
225
- agent_id: {
226
- type: 'string',
227
- description: 'The agent_id to look up (from search_agents results)',
228
- },
229
- },
230
- required: ['agent_id'],
231
- },
232
-
233
- async execute(_id: unknown, params: ToolParams): Promise<ToolResult> {
234
- const agentId = String(params.agent_id || '').trim();
235
- if (!agentId) {
236
- return fail('agent_id is required');
237
- }
238
-
239
- logger.info(`[discovery-tools] get_agent_detail called: agent_id=${agentId}`);
240
-
241
- const discovery = getOasnDiscovery();
242
- if ('error' in discovery) {
243
- return fail(discovery.error);
244
- }
245
-
246
- try {
247
- const card = await discovery.transport.getAgent(agentId);
248
-
249
- if (!card) {
250
- return fail(`Agent not found: ${agentId}`);
251
- }
252
-
253
- logger.info(`[discovery-tools] get_agent_detail returned: name=${card.name}`);
254
-
255
- return toolResult(JSON.stringify({
256
- success: true,
257
- agent: {
258
- agent_id: card.agent_id,
259
- name: card.name,
260
- description: card.description,
261
- MOM: card.MOM,
262
- tags: card.tags?.map((t: { tag_id: string; name: string }) => t.name) ?? [],
263
- category: card.category,
264
- avatar_url: card.avatar_url,
265
- },
266
- }, null, 2));
267
- } catch (err) {
268
- const msg = (err as Error).message;
269
- logger.error(`[discovery-tools] get_agent_detail failed: ${msg}`);
270
- return fail(`Failed to get agent details: ${msg}`);
271
- }
272
- },
273
- });
@@ -1,133 +0,0 @@
1
- /**
2
- * Download File Tool — openagent_download_file
3
- *
4
- * Downloads an artifact returned by a remote OASN agent and saves it to local disk.
5
- *
6
- * API: GET /api/artifacts/{id}/content (access layer)
7
- * Ref: access-upload-download-api.md §3
8
- */
9
-
10
- import fs from 'node:fs';
11
- import nodePath from 'node:path';
12
- import { resolveOasnAccessUrl } from '../util/url-resolver.js';
13
-
14
- import { registry } from '../runtime/registry.js';
15
- import { logger } from '../util/logger.js';
16
- import {
17
- toolResult,
18
- type ToolDescriptor,
19
- type ToolParams,
20
- type ToolResult,
21
- } from './types.js';
22
- import type { OasnTransport } from '../transport/types.js';
23
-
24
- // ── Helpers ──
25
-
26
- function fail(error: string): ToolResult {
27
- return toolResult(JSON.stringify({ success: false, error }));
28
- }
29
-
30
- function success(result: Record<string, unknown>): ToolResult {
31
- return toolResult(JSON.stringify({ success: true, ...result }));
32
- }
33
-
34
- // ── Tool Factory ──
35
-
36
- export function createDownloadFileTool(): ToolDescriptor {
37
- return {
38
- name: 'openagent_download_file',
39
- label: 'Download File',
40
- description:
41
- 'Download an artifact file returned by a remote OASN agent and save it to disk. ' +
42
- 'Use this when a remote agent returns a file (PDF, image, document, etc.) ' +
43
- 'that the user wants to save locally. ' +
44
- 'The content_url comes from the remote agent\'s response artifacts. ' +
45
- 'Look for artifact URLs in the openagent_call_remote_agent result. ' +
46
- 'If the save_path parent directory does not exist it will be created automatically. ' +
47
- 'Existing files at save_path will be overwritten.',
48
- parameters: {
49
- type: 'object',
50
- properties: {
51
- content_url: {
52
- type: 'string',
53
- description:
54
- 'The artifact content URL from the remote agent result ' +
55
- '(e.g., /api/artifacts/art_1/content?session_id=...&invocation_id=...)',
56
- },
57
- save_path: {
58
- type: 'string',
59
- description: 'Absolute local path where the file should be saved',
60
- },
61
- },
62
- required: ['content_url', 'save_path'],
63
- },
64
-
65
- async execute(
66
- _id: unknown,
67
- params: ToolParams,
68
- ): Promise<ToolResult> {
69
- const contentUrl = String(params.content_url || '').trim();
70
- const savePath = String(params.save_path || '').trim();
71
-
72
- if (!contentUrl) {
73
- return fail('content_url is required');
74
- }
75
- if (!savePath) {
76
- return fail('save_path is required');
77
- }
78
- if (!nodePath.isAbsolute(savePath)) {
79
- return fail('save_path must be an absolute path');
80
- }
81
-
82
- // ① Check runtime state
83
- const rt = registry.getDefault();
84
- if (!rt || !rt.isRunning) {
85
- return fail('OpenAgent runtime not running');
86
- }
87
- if (rt.transportType !== 'oasn') {
88
- return fail('File download is only available via OASN transport');
89
- }
90
- const transport = rt.transport;
91
- if (!transport || transport.transportType !== 'oasn') {
92
- return fail('OASN transport not ready');
93
- }
94
-
95
- // ② Resolve download URL
96
- const accessBase = rt.config?.accessApiBase || rt.config?.apiBase;
97
- const downloadUrl = resolveOasnAccessUrl(accessBase, contentUrl);
98
-
99
- logger.info(
100
- `[download-tool] Downloading artifact: url=${downloadUrl} saveTo=${savePath}`,
101
- );
102
-
103
- // ③ Download
104
- const oasnTransport = transport as OasnTransport;
105
- let downloaded;
106
- try {
107
- downloaded = await oasnTransport.downloadArtifact(downloadUrl);
108
- } catch (err) {
109
- logger.error(`[download-tool] Download failed: ${(err as Error).message}`);
110
- return fail(`Download failed: ${(err as Error).message}`);
111
- }
112
-
113
- // ④ Save to disk
114
- try {
115
- fs.mkdirSync(nodePath.dirname(savePath), { recursive: true });
116
- fs.writeFileSync(savePath, Buffer.from(downloaded.content));
117
- } catch (err) {
118
- return fail(`Cannot write to path: ${(err as Error).message}`);
119
- }
120
-
121
- logger.info(
122
- `[download-tool] Download success: path=${savePath} size=${downloaded.content.byteLength}`,
123
- );
124
-
125
- return success({
126
- savedPath: savePath,
127
- sizeBytes: downloaded.content.byteLength,
128
- mimeType: downloaded.mimeType,
129
- displayName: downloaded.displayName,
130
- });
131
- },
132
- };
133
- }