openclaw-openagent 1.0.13 → 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.
- package/dist/src/messaging/executor.d.ts +2 -3
- package/dist/src/messaging/executor.js +4 -31
- package/dist/src/plugin-ui/assets/openagent-override.js +4 -5
- package/dist/src/runtime/update-checker.d.ts +1 -1
- package/dist/src/runtime/update-checker.js +9 -46
- package/package.json +1 -3
- package/src/app/channel-tools.ts +0 -249
- package/src/app/discovery-tools.ts +0 -273
- package/src/app/download-file-tool.ts +0 -133
- package/src/app/hooks.ts +0 -144
- package/src/app/index.ts +0 -84
- package/src/app/messaging-tools.ts +0 -79
- package/src/app/ops-tools.ts +0 -155
- package/src/app/remote-agent-tool.ts +0 -762
- package/src/app/types.ts +0 -68
- package/src/app/upload-file-tool.ts +0 -411
- package/src/app/verbose-preflight.ts +0 -190
- package/src/auth/config.ts +0 -266
- package/src/auth/credential-manager.ts +0 -146
- package/src/auth/index.ts +0 -24
- package/src/auth/verify.ts +0 -99
- package/src/channel.ts +0 -566
- package/src/compat.ts +0 -94
- package/src/config/config-schema.ts +0 -45
- package/src/messaging/aggregator.ts +0 -120
- package/src/messaging/collector.ts +0 -89
- package/src/messaging/executor.ts +0 -72
- package/src/messaging/inbound.ts +0 -150
- package/src/messaging/index.ts +0 -11
- package/src/messaging/mention-protocol.ts +0 -94
- package/src/messaging/process-c2c-request.ts +0 -564
- package/src/messaging/process-message.ts +0 -373
- package/src/messaging/scheduler.ts +0 -55
- package/src/messaging/types.ts +0 -38
- package/src/plugin-ui/adapters/oc-2026-04.js +0 -103
- package/src/plugin-ui/adapters/oc-2026-05.js +0 -125
- package/src/plugin-ui/adapters/oc-2026-06.js +0 -125
- package/src/plugin-ui/adapters/oc-unknown.js +0 -48
- package/src/plugin-ui/assets/agentbook-icon.svg +0 -5
- package/src/plugin-ui/assets/bg.png +0 -0
- package/src/plugin-ui/assets/icon.png +0 -0
- package/src/plugin-ui/assets/magic.svg +0 -5
- package/src/plugin-ui/assets/openagent-override.js +0 -11263
- package/src/plugin-ui/build.cjs +0 -463
- package/src/plugin-ui/index.ts +0 -18
- package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -570
- package/src/plugin-ui/modules/agent-book/panel/agent-card.js +0 -170
- package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -643
- package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +0 -665
- package/src/plugin-ui/modules/agent-book/panel/mention-state.js +0 -206
- package/src/plugin-ui/modules/agent-book/panel/styles.js +0 -832
- package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +0 -86
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +0 -295
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +0 -211
- package/src/plugin-ui/modules/agent-book/scanner.js +0 -131
- package/src/plugin-ui/modules/agent-book/travelcard/travel-cards.js +0 -500
- package/src/plugin-ui/modules/agent-book/travelcard/travel-engine.js +0 -652
- package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +0 -262
- package/src/plugin-ui/modules/loader/bootstrap.js +0 -133
- package/src/plugin-ui/modules/loader/shared-state.js +0 -838
- package/src/plugin-ui/modules/loader/ws-intercept.js +0 -199
- package/src/plugin-ui/modules/remote-agent/chunk-parser.js +0 -161
- package/src/plugin-ui/modules/remote-agent/execution-card.js +0 -530
- package/src/plugin-ui/modules/remote-agent/markdown-renderer.js +0 -256
- package/src/plugin-ui/modules/remote-agent/media-links.js +0 -151
- package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +0 -134
- package/src/plugin-ui/modules/remote-agent/output-card.js +0 -342
- package/src/plugin-ui/modules/remote-agent/progress-store.js +0 -363
- package/src/plugin-ui/modules/remote-agent/render-hooks.js +0 -1700
- package/src/plugin-ui/modules/remote-agent/styles.js +0 -903
- package/src/plugin-ui/modules/remote-agent/tool-card-model.js +0 -130
- package/src/plugin-ui/postinstall-deploy.cjs +0 -52
- package/src/plugin-ui/ui-extension-loader/backup.ts +0 -92
- package/src/plugin-ui/ui-extension-loader/index.ts +0 -276
- package/src/plugin-ui/ui-extension-loader/locator.ts +0 -152
- package/src/plugin-ui/ui-extension-loader/manifest.ts +0 -57
- package/src/plugin-ui/ui-extension-loader/registry-regex.ts +0 -944
- package/src/plugin-ui/ui-extension-loader/removed-extensions.ts +0 -70
- package/src/plugin-ui/ui-extension-loader/types.ts +0 -72
- package/src/proxy/auth-proxy.ts +0 -414
- package/src/runtime/account.ts +0 -549
- package/src/runtime/index.ts +0 -7
- package/src/runtime/plugin-runtime.ts +0 -94
- package/src/runtime/registry.ts +0 -71
- package/src/runtime/update-checker.ts +0 -286
- package/src/sdk/CLASS_MAP.md +0 -143
- package/src/sdk/index.d.ts +0 -126
- package/src/sdk/index.js +0 -23990
- package/src/sdk/modules/cloud-search-module.js +0 -1117
- package/src/sdk/modules/follow-module.js +0 -1069
- package/src/sdk/modules/group-module.js +0 -7397
- package/src/sdk/modules/relationship-module.js +0 -2269
- package/src/sdk/modules/signaling-module.js +0 -1468
- package/src/sdk/modules/tim-upload-plugin.js +0 -730
- package/src/sdk/node-env/http-request.js +0 -90
- package/src/sdk/node-env/index.js +0 -57
- package/src/sdk/node-env/storage.js +0 -114
- package/src/sdk/package.json +0 -10
- package/src/sdk/tsconfig.json +0 -16
- package/src/state/pending-invocation-store.ts +0 -43
- package/src/state/store.ts +0 -756
- package/src/tim/c2c.ts +0 -451
- package/src/tim/channels.ts +0 -364
- package/src/tim/client.ts +0 -330
- package/src/tim/index.ts +0 -18
- package/src/tim/messages.ts +0 -166
- package/src/tim/sdk-logger-init.ts +0 -50
- package/src/tools.ts +0 -10
- package/src/transport/factory.ts +0 -95
- package/src/transport/oasn/index.ts +0 -17
- package/src/transport/oasn/oasn-agent-card.ts +0 -111
- package/src/transport/oasn/oasn-discovery.ts +0 -108
- package/src/transport/oasn/oasn-files.ts +0 -210
- package/src/transport/oasn/oasn-http.ts +0 -529
- package/src/transport/oasn/oasn-invocation.ts +0 -604
- package/src/transport/oasn/oasn-normalize.ts +0 -133
- package/src/transport/oasn/oasn-register.ts +0 -33
- package/src/transport/oasn/oasn-transport.ts +0 -318
- package/src/transport/oasn/oasn-types.ts +0 -404
- package/src/transport/tim/index.ts +0 -8
- package/src/transport/tim/tim-transport.ts +0 -515
- package/src/transport/types.ts +0 -538
- package/src/types/openclaw-plugin-sdk-media-store.d.ts +0 -9
- package/src/types/openclaw.d.ts +0 -97
- package/src/types/tencentcloud-chat.d.ts +0 -15
- package/src/util/http.ts +0 -113
- package/src/util/logger.ts +0 -131
- package/src/util/url-resolver.ts +0 -77
package/src/tim/messages.ts
DELETED
|
@@ -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';
|
package/src/transport/factory.ts
DELETED
|
@@ -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
|
-
}
|