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,166 +0,0 @@
1
- /**
2
- * TIM Messages — Send and fetch messages via SDK
3
- *
4
- * v3: fetchMessages uses SDK getMessageList() instead of REST API.
5
- * This fixes the v2 bug where non-admin accounts got empty results.
6
- */
7
-
8
- import { logger } from '../util/logger.js';
9
- import type { TIMClient } from './client.js';
10
-
11
- // ── Types ──
12
-
13
- export interface HistoryMessage {
14
- id: string;
15
- from: string;
16
- text: string;
17
- time: number;
18
- seq?: number;
19
- }
20
-
21
- export interface SendResult {
22
- ok: boolean;
23
- messageId: string;
24
- }
25
-
26
- // ── Functions ──
27
-
28
- /**
29
- * Send a text message to a group channel.
30
- * Includes a 10s local timeout to catch dead SDK connections.
31
- *
32
- * When atUserList is provided, uses TIM createTextAtMessage to set
33
- * protocol-level @mentions (visible to receivers' atUserList detection).
34
- * See: docs/audit/012-mention-mode-bot-to-bot-v3.4.4.md
35
- */
36
- export async function sendMessage(
37
- client: TIMClient,
38
- channelId: string,
39
- text: string,
40
- atUserList?: string[],
41
- ): Promise<SendResult> {
42
- const chat = client._chat;
43
- if (!chat || !client.isReady) {
44
- throw new Error('Not connected');
45
- }
46
-
47
- logger.info(`[tim/messages] sendMessage: ch=${channelId} len=${text.length} at=${atUserList?.join(',') ?? 'none'}`);
48
-
49
- const message = (atUserList && atUserList.length > 0)
50
- ? chat.createTextAtMessage({
51
- to: channelId,
52
- conversationType: client._types.CONV_GROUP,
53
- payload: { text, atUserList },
54
- })
55
- : chat.createTextMessage({
56
- to: channelId,
57
- conversationType: client._types.CONV_GROUP,
58
- payload: { text },
59
- });
60
-
61
- // CRITICAL: Timer MUST be cleared after race settles.
62
- // Without clearTimeout, a successful send leaves an orphan reject()
63
- // firing 10s later as an unhandled rejection → gateway crash.
64
- let timeoutHandle: ReturnType<typeof setTimeout>;
65
- const timeoutPromise = new Promise<never>((_, reject) => {
66
- timeoutHandle = setTimeout(
67
- () => reject(new Error(`sendMessage timeout (10s) for channel ${channelId}`)),
68
- 10_000,
69
- );
70
- });
71
-
72
- try {
73
- const res = await Promise.race([chat.sendMessage(message), timeoutPromise]) as {
74
- data?: { message?: { ID?: string } };
75
- };
76
-
77
- return {
78
- ok: true,
79
- messageId: res.data?.message?.ID || '',
80
- };
81
- } catch (err) {
82
- const code = (err as { code?: number })?.code;
83
- logger.error(`[tim/messages] sendMessage failed: code=${code} msg=${(err as Error).message} ch=${channelId}`);
84
- throw err;
85
- } finally {
86
- clearTimeout(timeoutHandle!);
87
- }
88
- }
89
-
90
- /**
91
- * Fetch message history for a group channel using SDK getMessageList().
92
- *
93
- * v3 change: REST API → SDK getMessageList()
94
- * - Filters non-text messages (system msgs, join/leave notifications)
95
- * - Maps to HistoryMessage interface
96
- * - seq from message.sequence (optional)
97
- * - Works with normal user credentials (fixes v2 empty array bug)
98
- */
99
- export async function fetchMessages(
100
- client: TIMClient,
101
- channelId: string,
102
- count = 20,
103
- ): Promise<HistoryMessage[]> {
104
- const chat = client._chat;
105
- if (!chat || !client.isReady) {
106
- throw new Error('Not connected');
107
- }
108
-
109
- try {
110
- logger.info(`[tim/messages] fetchMessages: ch=${channelId} count=${count}`);
111
- const conversationID = `GROUP${channelId}`;
112
- const res = await chat.getMessageList({
113
- conversationID,
114
- count,
115
- }) as {
116
- data?: {
117
- messageList?: Array<{
118
- ID?: string;
119
- from?: string;
120
- type?: string;
121
- payload?: { text?: string };
122
- time?: number;
123
- sequence?: number;
124
- }>;
125
- };
126
- };
127
-
128
- const messageList = res.data?.messageList || [];
129
-
130
- // Filter to text messages only (exclude system messages, join/leave, etc.)
131
- return messageList
132
- .filter(msg => msg.type === client._types.MSG_TEXT)
133
- .map(msg => mapToHistoryMessage(msg, channelId));
134
- } catch (err) {
135
- logger.error(`[tim/messages] fetchMessages error for ${channelId}: ${(err as Error).message}`);
136
- throw err;
137
- }
138
- }
139
-
140
- /**
141
- * Map a single SDK message to HistoryMessage interface.
142
- * Exported for contract testing.
143
- */
144
- export function mapToHistoryMessage(
145
- msg: {
146
- ID?: string;
147
- from?: string;
148
- payload?: { text?: string };
149
- time?: number;
150
- sequence?: number;
151
- },
152
- channelId: string,
153
- ): HistoryMessage {
154
- const result: HistoryMessage = {
155
- id: msg.ID || `${channelId}:${msg.sequence || Date.now()}`,
156
- from: msg.from || 'unknown',
157
- text: msg.payload?.text || '',
158
- time: (msg.time || 0) * 1000,
159
- };
160
-
161
- if (msg.sequence != null) {
162
- result.seq = msg.sequence;
163
- }
164
-
165
- return result;
166
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * TIM SDK Logger Bridge — 副作用模块
3
- *
4
- * 将腾讯云 IM SDK 的内部日志输出重定向到 OpenAgent 的 logger 组件。
5
- * SDK 内部原本直接调用 console.log/warn/error,此模块通过
6
- * globalThis.__OPENAGENT_SDK_LOGGER 注入自定义 logger 适配器,
7
- * 使 SDK 日志走文件输出而非 stdout,避免污染 Gateway JSON 通道。
8
- *
9
- * 必须在 @tencentcloud/chat 之前 import(副作用 import):
10
- * import './sdk-logger-init.js';
11
- * import TencentCloudChat from '@tencentcloud/chat';
12
- */
13
-
14
- // node-polyfill.js removed — SDK now uses native Node.js APIs directly
15
- import { logger } from '../util/logger.js';
16
-
17
- function formatArgs(...args: unknown[]): string {
18
- return args
19
- .map((a) => (typeof a === 'string' ? a : JSON.stringify(a)))
20
- .join(' ');
21
- }
22
-
23
- /**
24
- * SDK 内部 logger(变量 qe/Ye)期望的接口:
25
- * qe.log(...) — 普通日志
26
- * qe.warn(...) — 警告
27
- * qe.error(...) — 错误
28
- * qe.info(...) — 信息
29
- * qe.debug(...) — 调试
30
- */
31
- const sdkLoggerAdapter = {
32
- log(...args: unknown[]): void {
33
- logger.debug(`[tim-sdk] ${formatArgs(...args)}`);
34
- },
35
- warn(...args: unknown[]): void {
36
- logger.warn(`[tim-sdk] ${formatArgs(...args)}`);
37
- },
38
- error(...args: unknown[]): void {
39
- logger.error(`[tim-sdk] ${formatArgs(...args)}`);
40
- },
41
- info(...args: unknown[]): void {
42
- logger.info(`[tim-sdk] ${formatArgs(...args)}`);
43
- },
44
- debug(...args: unknown[]): void {
45
- logger.debug(`[tim-sdk] ${formatArgs(...args)}`);
46
- },
47
- };
48
-
49
- // 注入到 globalThis,SDK 加载时会检查此变量
50
- (globalThis as Record<string, unknown>).__OPENAGENT_SDK_LOGGER = sdkLoggerAdapter;
package/src/tools.ts DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * OpenAgent Tools — re-export from app/ module
3
- *
4
- * This file exists for backward compatibility.
5
- * The actual tool implementations live in app/channel-tools.ts,
6
- * app/messaging-tools.ts, and app/ops-tools.ts.
7
- */
8
-
9
- export { registerTools } from './app/index.js';
10
- export type { ToolDescriptor, ToolFactory } from './app/types.js';
@@ -1,95 +0,0 @@
1
- /**
2
- * Transport 工厂 —— 按配置创建 AgentTransport 实例
3
- *
4
- * 设计依据:docs/specs/2026-06-16-oasn-transport-abstraction-design.md §3.1
5
- *
6
- * 调用方(AccountRuntime)通过 transportType 字段决定走 OASN 还是 TIM 路径,
7
- * 工厂内部 lazy-import 各自的实现模块,确保「未启用的 transport 不进入运行时」。
8
- * - 选 OASN 时不加载 TIM SDK(节省启动内存 & 避免无意义的 WebSocket 探测)
9
- * - 选 TIM 时不加载 OASN HTTP 客户端(更小的攻击面)
10
- *
11
- * 注意:transport 实例创建后必须显式调用 ready(credentials) 才能使用,
12
- * 工厂只负责实例化,不负责凭证校验和连接。
13
- */
14
-
15
- import type { AgentTransport, OasnTransport, TimTransport } from './types.js';
16
- import type { PendingInvocationStore } from './oasn/index.js';
17
-
18
- /** 工厂入参 */
19
- export interface CreateTransportOptions {
20
- /** 选择的 transport 类型 */
21
- transportType: 'oasn' | 'tim';
22
- /**
23
- * OASN API base URL(仅 OASN 路径必填)。
24
- * 形如:`https://api.oasn.ai`,不含尾斜杠和 `/api/*` 前缀。
25
- */
26
- apiBase?: string;
27
- /** Optional Access-layer API base URL for invocation/file/artifact endpoints. */
28
- accessApiBase?: string;
29
- /**
30
- * Agent id(仅 OASN 路径使用,TIM 路径从 credentials.userId 拿)。
31
- * 用于实例标识 + 401 撤销时定位本地存储。
32
- */
33
- agentId?: string;
34
- /**
35
- * 多账户场景下的逻辑 id。
36
- * 默认与 agentId 相同;当一个 OpenClaw 实例跑多个 OASN/TIM 账号时由调用方传入。
37
- */
38
- accountId?: string;
39
- /**
40
- * §11.1 OASN-only:把 SQLite-backed PendingInvocationStore 注入 OasnInvocation。
41
- *
42
- * - 不传:OasnInvocation 退化为「无持久化」模式(idempotency 仍然在内存生效,但跨进程重启丢失)
43
- * - 传入:sendTask 时按 toolCallId 复用 idempotency_key,崩溃恢复时可由
44
- * StateStore.listUnsettledInvocations 续轮询
45
- *
46
- * 仅当 transportType='oasn' 时有意义;TIM 路径忽略此字段。
47
- */
48
- pendingStore?: PendingInvocationStore;
49
- }
50
-
51
- /**
52
- * 创建 transport 实例。
53
- *
54
- * 关键设计:返回类型是 union `AgentTransport`,调用方需用 `transportType` 字段 narrow:
55
- *
56
- * ```ts
57
- * const t = await createTransport({ transportType: 'oasn', apiBase, agentId });
58
- * if (t.transportType === 'oasn') {
59
- * // 这里 TypeScript 知道 t 是 OasnTransport —— 可以调 t.registerAgent()
60
- * await t.registerAgent('openclaw');
61
- * }
62
- * ```
63
- *
64
- * @throws 当 OASN 路径但缺少 apiBase 时
65
- */
66
- export async function createTransport(
67
- options: CreateTransportOptions,
68
- ): Promise<AgentTransport> {
69
- if (options.transportType === 'oasn') {
70
- if (!options.apiBase) {
71
- throw new Error('createTransport: apiBase is required for OASN transport');
72
- }
73
- // lazy import:选 OASN 时才加载 OASN 模块(OASN HTTP 客户端不依赖 TIM SDK)
74
- const { OasnTransportImpl } = await import('./oasn/oasn-transport.js');
75
- return new OasnTransportImpl({
76
- apiBase: options.apiBase,
77
- accessApiBase: options.accessApiBase,
78
- agentId: options.agentId ?? '',
79
- accountId: options.accountId ?? options.agentId ?? 'default',
80
- // §11.1 持久化挂载点:仅当上层提供 pendingStore 时启用
81
- ...(options.pendingStore ? { pendingStore: options.pendingStore } : {}),
82
- }) satisfies OasnTransport;
83
- }
84
-
85
- if (options.transportType === 'tim') {
86
- // lazy import:选 TIM 时才加载 TIM SDK(避免 OASN 路径下加载 ~2MB 的 SDK)
87
- const { TimTransportImpl } = await import('./tim/tim-transport.js');
88
- return new TimTransportImpl({
89
- accountId: options.accountId ?? 'default',
90
- }) satisfies TimTransport;
91
- }
92
-
93
- // 编译期已是 'oasn' | 'tim' 的 union,运行期还能到这里说明配置异常
94
- throw new Error(`createTransport: unknown transportType "${(options as { transportType: string }).transportType}"`);
95
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * OASN transport 子模块统一出口。
3
- *
4
- * 设计依据:docs/specs/2026-06-16-oasn-transport-abstraction-design.md §3.1
5
- *
6
- * 仅 re-export 实现类与跨模块共用类型。OASN 内部 API 类型(snake_case 协议字段)
7
- * 不导出到外层 —— 上层应面向 src/transport/types.ts 的通用类型编程。
8
- */
9
-
10
- export { OasnTransportImpl } from './oasn-transport.js';
11
- export type { OasnTransportInitOptions } from './oasn-transport.js';
12
-
13
- // §11.1 持久化钩子(StateStore 接入用)
14
- export type { PendingInvocationStore } from './oasn-invocation.js';
15
-
16
- // HTTP 错误体类型(plugin-ui 错误展示可能用得上)
17
- export type { OasnErrorBody } from './oasn-types.js';
@@ -1,111 +0,0 @@
1
- /**
2
- * OASN AgentCard CRUD + Owner 查询
3
- *
4
- * 设计依据:
5
- * - docs/specs/2026-06-16-oasn-api-module-mapping.md §2.7 / §2.8 / §2.9
6
- *
7
- * 端点:
8
- * - GET /api/agent-cards/{agent_id} 公开查询(claimed+active+public 才 200)
9
- * - PATCH /api/agent-cards/{agent_id} Owner 或 Agent 更新
10
- * - GET /api/users/me 当前 Owner(Owner access token 场景)
11
- */
12
-
13
- import { logger } from '../../util/logger.js';
14
- import type { AgentCard, AgentCardPatch, OwnerInfo } from '../types.js';
15
- import type { OasnHttpClient } from './oasn-http.js';
16
- import {
17
- OASN_ENDPOINTS,
18
- type AgentCardResponse,
19
- type OwnerInfoResponse,
20
- type UpdateAgentCardRequest,
21
- } from './oasn-types.js';
22
- import type { TransportError } from '../types.js';
23
- import { normalizeAgentCard } from './oasn-normalize.js';
24
-
25
- export class OasnAgentCard {
26
- constructor(private readonly _http: OasnHttpClient) {}
27
-
28
- /**
29
- * 查询 AgentCard 公开信息。
30
- *
31
- * 用途:
32
- * 1. `connect()` 时验证 api_key 有效性(即使返回 404 也能确认 Bearer 没被 401)
33
- * 2. UI 展示其他 Agent 的详情
34
- *
35
- * 404 时返回 null(agent 不存在、未认领、或 private)。
36
- */
37
- async get(agentId: string): Promise<AgentCard | null> {
38
- try {
39
- const resp = await this._http.get<AgentCardResponse>(
40
- OASN_ENDPOINTS.AGENT_CARD(agentId),
41
- );
42
- return this._toAgentCard(resp);
43
- } catch (err) {
44
- const te = err as TransportError;
45
- if (te.code === 'HTTP_404' || te.code === 'AGENT_CARD_NOT_FOUND') {
46
- logger.info(`[transport/oasn/agent-card] get(${agentId}) → 404 not found`);
47
- return null;
48
- }
49
- throw err;
50
- }
51
- }
52
-
53
- /**
54
- * 更新 AgentCard。
55
- * PATCH 语义:省略字段不变,显式 null 清空。
56
- */
57
- async update(agentId: string, patch: AgentCardPatch): Promise<AgentCard> {
58
- const body: UpdateAgentCardRequest = {};
59
- // 只复制存在的字段(undefined 不发,null 显式发出)
60
- if ('name' in patch) body.name = patch.name;
61
- if ('description' in patch) body.description = patch.description;
62
- if ('MOM' in patch) body.MOM = patch.MOM;
63
- if ('tags' in patch) body.tags = patch.tags;
64
- if ('category' in patch) body.category = patch.category;
65
- if ('avatar_ref' in patch) body.avatarRef = patch.avatar_ref;
66
- if ('visibility' in patch) body.visibility = patch.visibility;
67
- if ('public_metadata' in patch) body.publicMetadata = patch.public_metadata;
68
-
69
- logger.info(`[transport/oasn/agent-card] update agent=${agentId} fields=${Object.keys(body).join(',')}`);
70
-
71
- const resp = await this._http.patch<AgentCardResponse>(
72
- OASN_ENDPOINTS.AGENT_CARD(agentId),
73
- body,
74
- );
75
- return this._toAgentCard(resp);
76
- }
77
-
78
- /**
79
- * 查询当前 Owner(仅当 Bearer 是 Owner access token 时可用)。
80
- * Agent api_key 调用此接口可能返回 403。
81
- */
82
- async getCurrentOwner(): Promise<OwnerInfo | null> {
83
- try {
84
- const resp = await this._http.get<OwnerInfoResponse>(OASN_ENDPOINTS.USERS_ME);
85
- return {
86
- owner_id: resp.ownerId ?? resp.owner_id ?? '',
87
- owner_type: resp.ownerType ?? resp.owner_type ?? '',
88
- display_name: resp.displayName ?? resp.display_name ?? '',
89
- email_masked: resp.emailMasked ?? resp.email_masked ?? '',
90
- ...((resp.emailVerifiedAt ?? resp.email_verified_at)
91
- ? { email_verified_at: resp.emailVerifiedAt ?? resp.email_verified_at }
92
- : {}),
93
- status: resp.status,
94
- };
95
- } catch (err) {
96
- const te = err as TransportError;
97
- if (te.code === 'HTTP_401' || te.code === 'HTTP_403' || te.code === 'UNAUTHENTICATED') {
98
- return null;
99
- }
100
- throw err;
101
- }
102
- }
103
-
104
- // ─────────────────────────────────────────────────────────────
105
- // 工具
106
- // ─────────────────────────────────────────────────────────────
107
-
108
- private _toAgentCard(resp: AgentCardResponse): AgentCard {
109
- return normalizeAgentCard(resp);
110
- }
111
- }
@@ -1,108 +0,0 @@
1
- /**
2
- * OASN Discovery —— Agent 搜索 + Category 树
3
- *
4
- * 设计依据:docs/specs/2026-06-16-oasn-api-module-mapping.md §2.10 ~ §2.13
5
- *
6
- * 三种搜索方式,按非空字段路由到对应端点:
7
- * - query → POST /api/agent-cards/search/by-query (自然语言)
8
- * - category→ POST /api/agent-cards/search/by-category (分类浏览)
9
- * - tags → POST /api/agent-cards/search/by-tags (标签筛选)
10
- *
11
- * 当前 OASN search 仅支持 agent_types=['service'](详见设计文档 §九 风险表)。
12
- */
13
-
14
- import { logger } from '../../util/logger.js';
15
- import type { CategoryTree, SearchQuery, SearchResult } from '../types.js';
16
- import type { OasnHttpClient } from './oasn-http.js';
17
- import {
18
- OASN_ENDPOINTS,
19
- type CategoryTreeResponse,
20
- type SearchByCategoryRequest,
21
- type SearchByQueryRequest,
22
- type SearchByTagsRequest,
23
- type SearchResponse,
24
- } from './oasn-types.js';
25
- import { normalizeCategoryTree, normalizeSearchResponse } from './oasn-normalize.js';
26
-
27
- export class OasnDiscovery {
28
- constructor(private readonly _http: OasnHttpClient) {}
29
-
30
- /**
31
- * 路由到对应搜索端点。
32
- *
33
- * 优先级(互斥使用):query > category > tags。
34
- * 当多个字段都传入时,以 query 为准并 logger.warn 提示。
35
- */
36
- async search(query: SearchQuery): Promise<SearchResult> {
37
- const hasQuery = !!query.query && query.query.trim().length > 0;
38
- const hasCategory = !!query.category && query.category.length > 0;
39
- const hasTags = !!query.tags && query.tags.length > 0;
40
-
41
- if ([hasQuery, hasCategory, hasTags].filter(Boolean).length > 1) {
42
- logger.warn('[transport/oasn/discovery] multiple search criteria provided, prioritising query > category > tags');
43
- }
44
-
45
- if (hasQuery) return this._searchByQuery(query);
46
- if (hasCategory) return this._searchByCategory(query);
47
- if (hasTags) return this._searchByTags(query);
48
-
49
- // 都为空:默认走 query=""(服务端可能拒绝,但 transport 不主动推断)
50
- throw new Error('OasnDiscovery.search: at least one of query/category/tags must be provided');
51
- }
52
-
53
- private async _searchByQuery(q: SearchQuery): Promise<SearchResult> {
54
- const body: SearchByQueryRequest = {
55
- query: q.query!.trim(),
56
- agentTypes: q.agentTypes ?? ['service'],
57
- };
58
- if (q.sort) body.sort = q.sort;
59
- if (q.pageSize !== undefined) body.pageSize = q.pageSize;
60
- if (q.pageNum !== undefined) body.pageNum = q.pageNum;
61
-
62
- const resp = await this._http.post<SearchResponse>(OASN_ENDPOINTS.SEARCH_BY_QUERY, body);
63
- return this._toSearchResult(resp);
64
- }
65
-
66
- private async _searchByCategory(q: SearchQuery): Promise<SearchResult> {
67
- const body: SearchByCategoryRequest = {
68
- category: q.category!,
69
- agentTypes: q.agentTypes ?? ['service'],
70
- };
71
- if (q.sort) body.sort = q.sort;
72
- if (q.pageSize !== undefined) body.pageSize = q.pageSize;
73
- if (q.pageNum !== undefined) body.pageNum = q.pageNum;
74
-
75
- const resp = await this._http.post<SearchResponse>(OASN_ENDPOINTS.SEARCH_BY_CATEGORY, body);
76
- return this._toSearchResult(resp);
77
- }
78
-
79
- private async _searchByTags(q: SearchQuery): Promise<SearchResult> {
80
- const body: SearchByTagsRequest = {
81
- tags: q.tags!,
82
- agentTypes: q.agentTypes ?? ['service'],
83
- };
84
- if (q.sort) body.sort = q.sort;
85
- if (q.pageSize !== undefined) body.pageSize = q.pageSize;
86
- if (q.pageNum !== undefined) body.pageNum = q.pageNum;
87
-
88
- const resp = await this._http.post<SearchResponse>(OASN_ENDPOINTS.SEARCH_BY_TAGS, body);
89
- return this._toSearchResult(resp);
90
- }
91
-
92
- /** 获取 category 树(用于 Agent Book UI 的分类浏览面板) */
93
- async getCategories(params?: { agentType?: string }): Promise<CategoryTree> {
94
- const qs = params?.agentType ? `?agent_type=${encodeURIComponent(params.agentType)}` : '';
95
- const resp = await this._http.get<CategoryTreeResponse>(
96
- `${OASN_ENDPOINTS.CATEGORIES}${qs}`,
97
- );
98
- return normalizeCategoryTree(resp);
99
- }
100
-
101
- // ─────────────────────────────────────────────────────────────
102
- // 工具
103
- // ─────────────────────────────────────────────────────────────
104
-
105
- private _toSearchResult(resp: SearchResponse): SearchResult {
106
- return normalizeSearchResponse(resp);
107
- }
108
- }