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.
- package/dist/index.js +2 -0
- package/dist/src/config/config-schema.d.ts +9 -0
- package/dist/src/config/config-schema.js +6 -0
- 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 +124 -18
- package/dist/src/proxy/auth-proxy.js +5 -0
- package/dist/src/runtime/update-checker.d.ts +18 -0
- package/dist/src/runtime/update-checker.js +216 -0
- package/index.ts +3 -0
- 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 -39
- 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 -11156
- 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 -833
- 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 -256
- package/src/plugin-ui/modules/loader/bootstrap.js +0 -38
- 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 -896
- 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 -409
- 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/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
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AgentCard,
|
|
3
|
-
AgentStatusResult,
|
|
4
|
-
CategoryNode,
|
|
5
|
-
CategoryTree,
|
|
6
|
-
SearchResult,
|
|
7
|
-
} from '../types.js';
|
|
8
|
-
import type {
|
|
9
|
-
AgentCardResponse,
|
|
10
|
-
AgentStatusResponse,
|
|
11
|
-
CategoryNodeResponse,
|
|
12
|
-
CategoryTreeResponse,
|
|
13
|
-
SearchResponse,
|
|
14
|
-
} from './oasn-types.js';
|
|
15
|
-
|
|
16
|
-
type AnyRecord = Record<string, unknown>;
|
|
17
|
-
|
|
18
|
-
function asRecord(value: unknown): AnyRecord {
|
|
19
|
-
return value && typeof value === 'object' ? value as AnyRecord : {};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function pickString(record: AnyRecord, ...keys: string[]): string {
|
|
23
|
-
for (const key of keys) {
|
|
24
|
-
const value = record[key];
|
|
25
|
-
if (typeof value === 'string') return value;
|
|
26
|
-
}
|
|
27
|
-
return '';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function pickNullableString(record: AnyRecord, ...keys: string[]): string | null {
|
|
31
|
-
for (const key of keys) {
|
|
32
|
-
const value = record[key];
|
|
33
|
-
if (typeof value === 'string') return value;
|
|
34
|
-
if (value === null) return null;
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function pickNumber(record: AnyRecord, fallback: number, ...keys: string[]): number {
|
|
40
|
-
for (const key of keys) {
|
|
41
|
-
const value = record[key];
|
|
42
|
-
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
43
|
-
}
|
|
44
|
-
return fallback;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function pickBoolean(record: AnyRecord, fallback: boolean, ...keys: string[]): boolean {
|
|
48
|
-
for (const key of keys) {
|
|
49
|
-
const value = record[key];
|
|
50
|
-
if (typeof value === 'boolean') return value;
|
|
51
|
-
}
|
|
52
|
-
return fallback;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function pickRecord(record: AnyRecord, ...keys: string[]): AnyRecord {
|
|
56
|
-
for (const key of keys) {
|
|
57
|
-
const value = record[key];
|
|
58
|
-
if (value && typeof value === 'object') return value as AnyRecord;
|
|
59
|
-
}
|
|
60
|
-
return {};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function pickArray<T>(record: AnyRecord, ...keys: string[]): T[] {
|
|
64
|
-
for (const key of keys) {
|
|
65
|
-
const value = record[key];
|
|
66
|
-
if (Array.isArray(value)) return value as T[];
|
|
67
|
-
}
|
|
68
|
-
return [];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function normalizeTag(value: unknown): { tag_id: string; name: string } {
|
|
72
|
-
if (typeof value === 'string') return { tag_id: value, name: value };
|
|
73
|
-
const record = asRecord(value);
|
|
74
|
-
return {
|
|
75
|
-
tag_id: pickString(record, 'tagId', 'tag_id', 'id'),
|
|
76
|
-
name: pickString(record, 'name'),
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function normalizeAgentCard(resp: AgentCardResponse | unknown): AgentCard {
|
|
81
|
-
const record = asRecord(resp);
|
|
82
|
-
return {
|
|
83
|
-
agent_id: pickString(record, 'agentId', 'agent_id', 'id'),
|
|
84
|
-
agent_type: (pickString(record, 'agentType', 'agent_type') || 'service') as 'client' | 'service',
|
|
85
|
-
name: pickString(record, 'name') || 'Unknown',
|
|
86
|
-
description: pickNullableString(record, 'description'),
|
|
87
|
-
MOM: pickNullableString(record, 'MOM'),
|
|
88
|
-
tags: pickArray(record, 'tags').map(normalizeTag).filter((tag) => tag.name || tag.tag_id),
|
|
89
|
-
category: pickArray<string>(record, 'category'),
|
|
90
|
-
avatar_url: pickNullableString(record, 'avatarUrl', 'avatar_url', 'avatar'),
|
|
91
|
-
...(pickString(record, 'visibility') ? { visibility: pickString(record, 'visibility') as 'public' | 'private' } : {}),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function normalizeAgentStatus(resp: AgentStatusResponse | unknown): AgentStatusResult {
|
|
96
|
-
const record = asRecord(resp);
|
|
97
|
-
return {
|
|
98
|
-
agent_id: pickString(record, 'agentId', 'agent_id'),
|
|
99
|
-
status: pickString(record, 'status') as AgentStatusResult['status'],
|
|
100
|
-
...(pickString(record, 'access_token', 'accessToken') ? {
|
|
101
|
-
access_token: pickString(record, 'access_token', 'accessToken'),
|
|
102
|
-
} : {}),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function normalizeCategoryNode(node: CategoryNodeResponse | unknown): CategoryNode {
|
|
107
|
-
const record = asRecord(node);
|
|
108
|
-
return {
|
|
109
|
-
category_id: pickString(record, 'categoryId', 'category_id', 'id'),
|
|
110
|
-
name: pickString(record, 'name'),
|
|
111
|
-
children: pickArray(record, 'children').map(normalizeCategoryNode),
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export function normalizeCategoryTree(resp: CategoryTreeResponse | unknown): CategoryTree {
|
|
116
|
-
const record = asRecord(resp);
|
|
117
|
-
return {
|
|
118
|
-
categories: pickArray(record, 'categories').map(normalizeCategoryNode),
|
|
119
|
-
updated_at: pickString(record, 'updatedAt', 'updated_at'),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function normalizeSearchResponse(resp: SearchResponse | unknown): SearchResult {
|
|
124
|
-
const record = asRecord(resp);
|
|
125
|
-
const cards = pickArray(record, 'agentCards', 'agent_cards');
|
|
126
|
-
return {
|
|
127
|
-
searchId: pickString(record, 'searchId', 'search_id'),
|
|
128
|
-
agentCards: cards.map(normalizeAgentCard),
|
|
129
|
-
pageNum: pickNumber(record, 1, 'pageNum', 'page_num'),
|
|
130
|
-
pageSize: pickNumber(record, cards.length, 'pageSize', 'page_size'),
|
|
131
|
-
hasNext: pickBoolean(record, false, 'hasNext', 'has_next'),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OASN Agent 状态查询
|
|
3
|
-
*
|
|
4
|
-
* 设计依据:
|
|
5
|
-
* - docs/specs/2026-06-16-oasn-api-module-mapping.md §2.3
|
|
6
|
-
*
|
|
7
|
-
* 注意:register 和 claim 已迁移到 CLI(openclaw-plugin-openagent-cli),
|
|
8
|
-
* 本模块仅保留 getStatus(GET /api/agents/{agent_id})。
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { logger } from '../../util/logger.js';
|
|
12
|
-
import type { AgentStatusResult } from '../types.js';
|
|
13
|
-
import type { OasnHttpClient } from './oasn-http.js';
|
|
14
|
-
import {
|
|
15
|
-
OASN_ENDPOINTS,
|
|
16
|
-
type AgentStatusResponse,
|
|
17
|
-
} from './oasn-types.js';
|
|
18
|
-
import { normalizeAgentStatus } from './oasn-normalize.js';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* OASN Agent 状态查询模块。
|
|
22
|
-
*/
|
|
23
|
-
export class OasnAgentStatus {
|
|
24
|
-
constructor(private readonly _http: OasnHttpClient) {}
|
|
25
|
-
|
|
26
|
-
async getStatus(agentId: string): Promise<AgentStatusResult> {
|
|
27
|
-
const resp = await this._http.get<AgentStatusResponse>(
|
|
28
|
-
OASN_ENDPOINTS.AGENT_STATUS(agentId),
|
|
29
|
-
{ skipRetry: true },
|
|
30
|
-
);
|
|
31
|
-
return normalizeAgentStatus(resp);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OasnTransport —— 装配 OASN 子模块为统一的 AgentTransport
|
|
3
|
-
*
|
|
4
|
-
* 设计依据:
|
|
5
|
-
* - docs/specs/2026-06-16-oasn-transport-abstraction-design.md §2.4
|
|
6
|
-
* - docs/specs/2026-06-16-oasn-api-module-mapping.md §3.1
|
|
7
|
-
*
|
|
8
|
-
* 子模块组装:
|
|
9
|
-
* - OasnHttpClient HTTP 基础(Bearer 注入 / 重试 / 401 拦截)
|
|
10
|
-
* - OasnAgentStatus agent status query (GET /api/agents/{agent_id})
|
|
11
|
-
* - OasnAgentCard get / update / getCurrentOwner
|
|
12
|
-
* - OasnDiscovery search / categories
|
|
13
|
-
* - OasnInvocation sendTask / waitForTaskResult(核心路径)
|
|
14
|
-
* - OasnFiles upload / download + LRU
|
|
15
|
-
*
|
|
16
|
-
* 与 CoreTransport 契约的映射:
|
|
17
|
-
* - id = options.accountId
|
|
18
|
-
* - transportType= 'oasn'
|
|
19
|
-
* - ready() = 用 credentials.token 设置 Bearer,调 GET /api/agent-cards/{agent_id} 探活
|
|
20
|
-
* (404 也算成功 —— 未认领的 agent 仍能用 api_key,只是公开查询返 404)
|
|
21
|
-
* - dispose() = 释放 HTTP(无长连接)+ 清空 token
|
|
22
|
-
* - isReady = ready() 成功且 token 非空
|
|
23
|
-
* - 'credential_expired' 事件 = §11.5 401 撤销路径
|
|
24
|
-
*
|
|
25
|
-
* 与 TimTransport 的差异:
|
|
26
|
-
* - 不持有 WebSocket / 长连接 → dispose 几乎是 no-op
|
|
27
|
-
* - 不实现 IMChannelTransport(onTaskReceived / sendGroupMessage 等)
|
|
28
|
-
* - register/claim/updateAgentCard/uploadFile/downloadArtifact 是 OASN-only 能力
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
import { EventEmitter } from 'node:events';
|
|
32
|
-
|
|
33
|
-
import { logger } from '../../util/logger.js';
|
|
34
|
-
import {
|
|
35
|
-
makeTransportError,
|
|
36
|
-
type AgentCard,
|
|
37
|
-
type AgentCardPatch,
|
|
38
|
-
type AgentStatusResult,
|
|
39
|
-
type CategoryTree,
|
|
40
|
-
type CoreTransportEvent,
|
|
41
|
-
type DownloadArtifactResult,
|
|
42
|
-
type OasnTransport,
|
|
43
|
-
type OwnerInfo,
|
|
44
|
-
type ProgressCallback,
|
|
45
|
-
type SearchQuery,
|
|
46
|
-
type SearchResult,
|
|
47
|
-
type TaskHandle,
|
|
48
|
-
type TaskRequest,
|
|
49
|
-
type TaskResult,
|
|
50
|
-
type TransportCredentials,
|
|
51
|
-
type TransportError,
|
|
52
|
-
type UploadFileParams,
|
|
53
|
-
type UploadFileResult,
|
|
54
|
-
} from '../types.js';
|
|
55
|
-
import { OasnAgentCard } from './oasn-agent-card.js';
|
|
56
|
-
import { OasnDiscovery } from './oasn-discovery.js';
|
|
57
|
-
import { OasnFiles } from './oasn-files.js';
|
|
58
|
-
import { OasnHttpClient } from './oasn-http.js';
|
|
59
|
-
import {
|
|
60
|
-
OasnInvocation,
|
|
61
|
-
type CreateInvocationOptions,
|
|
62
|
-
type PendingInvocationStore,
|
|
63
|
-
} from './oasn-invocation.js';
|
|
64
|
-
import { OasnAgentStatus } from './oasn-register.js';
|
|
65
|
-
|
|
66
|
-
// ───────────────────────────────────────────────────────────────
|
|
67
|
-
// 构造选项
|
|
68
|
-
// ───────────────────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
export interface OasnTransportInitOptions {
|
|
71
|
-
/** 实例 id(多账户场景区分用) */
|
|
72
|
-
accountId: string;
|
|
73
|
-
/** OASN API base URL,例 `https://api.oasn.ai` */
|
|
74
|
-
apiBase: string;
|
|
75
|
-
/** Optional Access-layer API base URL for invocation/file/artifact endpoints. */
|
|
76
|
-
accessApiBase?: string;
|
|
77
|
-
/**
|
|
78
|
-
* 当前 agent_id(用于 ready() 探活 + register 后回填)。
|
|
79
|
-
* 可在 ready() 之前为空(未注册场景),但 sendTask 之类操作会失败。
|
|
80
|
-
*/
|
|
81
|
-
agentId?: string;
|
|
82
|
-
/** §11.1 持久化钩子(接 StateStore.pending_invocations);可选 */
|
|
83
|
-
pendingStore?: PendingInvocationStore;
|
|
84
|
-
/** 单次 HTTP 超时(默认 30s) */
|
|
85
|
-
defaultTimeoutMs?: number;
|
|
86
|
-
/** retryable 错误自动重试次数(默认 3) */
|
|
87
|
-
maxRetries?: number;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ───────────────────────────────────────────────────────────────
|
|
91
|
-
// 实现类
|
|
92
|
-
// ───────────────────────────────────────────────────────────────
|
|
93
|
-
|
|
94
|
-
export class OasnTransportImpl extends EventEmitter implements OasnTransport {
|
|
95
|
-
readonly transportType = 'oasn' as const;
|
|
96
|
-
readonly id: string;
|
|
97
|
-
|
|
98
|
-
private _http: OasnHttpClient;
|
|
99
|
-
private _accessHttp: OasnHttpClient;
|
|
100
|
-
private _agentCard: OasnAgentCard;
|
|
101
|
-
private _discovery: OasnDiscovery;
|
|
102
|
-
private _agentStatus: OasnAgentStatus;
|
|
103
|
-
private _invocation: OasnInvocation;
|
|
104
|
-
private _files: OasnFiles;
|
|
105
|
-
|
|
106
|
-
private _agentId: string | undefined;
|
|
107
|
-
private _isReady = false;
|
|
108
|
-
private _claimStatus: AgentStatusResult['status'] | 'unknown' = 'unknown';
|
|
109
|
-
|
|
110
|
-
constructor(options: OasnTransportInitOptions) {
|
|
111
|
-
super();
|
|
112
|
-
this.id = options.accountId;
|
|
113
|
-
this._agentId = options.agentId;
|
|
114
|
-
|
|
115
|
-
// ── HTTP 层(含 401 撤销回调) ────────────────────────────────
|
|
116
|
-
const httpConfig = {
|
|
117
|
-
apiBase: options.apiBase,
|
|
118
|
-
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
119
|
-
maxRetries: options.maxRetries,
|
|
120
|
-
onCredentialRevoked: () => this._onCredentialRevoked(),
|
|
121
|
-
};
|
|
122
|
-
this._http = new OasnHttpClient(httpConfig);
|
|
123
|
-
this._accessHttp = new OasnHttpClient({
|
|
124
|
-
...httpConfig,
|
|
125
|
-
apiBase: options.accessApiBase || options.apiBase,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// ── 子模块(共享 HTTP 实例) ──────────────────────────────────
|
|
129
|
-
this._agentCard = new OasnAgentCard(this._http);
|
|
130
|
-
this._discovery = new OasnDiscovery(this._http);
|
|
131
|
-
this._agentStatus = new OasnAgentStatus(this._http);
|
|
132
|
-
this._invocation = new OasnInvocation(this._accessHttp, options.pendingStore);
|
|
133
|
-
this._files = new OasnFiles(this._accessHttp);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ═══════════════════════════════════════════════════════════════
|
|
137
|
-
// CoreTransport
|
|
138
|
-
// ═══════════════════════════════════════════════════════════════
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 校验 api_key 有效性 + 进入可工作状态。
|
|
142
|
-
*
|
|
143
|
-
* 验证策略:
|
|
144
|
-
* 1. 设置 Bearer = credentials.token
|
|
145
|
-
* 2. 若 agentId 已知 → 调 GET /api/agent-cards/{agent_id}
|
|
146
|
-
* - status 接口返回 claimed 才允许后续 Invocation
|
|
147
|
-
* - 401 → onCredentialRevoked 回调,抛 TransportError
|
|
148
|
-
*
|
|
149
|
-
* 注:credentials.identity 在 OASN 场景下应等于 agent_id。
|
|
150
|
-
*/
|
|
151
|
-
async ready(credentials: TransportCredentials): Promise<void> {
|
|
152
|
-
if (!credentials.token) {
|
|
153
|
-
throw makeTransportError('MISSING_CREDENTIAL', 'OASN ready: token (api_key) is required');
|
|
154
|
-
}
|
|
155
|
-
this._http.setToken(credentials.token);
|
|
156
|
-
this._accessHttp.setToken(credentials.token);
|
|
157
|
-
|
|
158
|
-
// 若构造时未传 agentId,则从 credentials.identity 读取
|
|
159
|
-
if (!this._agentId && credentials.identity) {
|
|
160
|
-
this._agentId = credentials.identity;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (this._agentId) {
|
|
164
|
-
try {
|
|
165
|
-
const status = await this._agentStatus.getStatus(this._agentId);
|
|
166
|
-
this._claimStatus = status.status;
|
|
167
|
-
logger.info(
|
|
168
|
-
`[transport/oasn] ready agent_id=${this._agentId} `
|
|
169
|
-
+ `claim_status=${status.status}`,
|
|
170
|
-
);
|
|
171
|
-
} catch (err) {
|
|
172
|
-
const te = err as TransportError;
|
|
173
|
-
// 401 已经在 HTTP 层触发了 onCredentialRevoked,再次显式抛
|
|
174
|
-
if (te.code === 'HTTP_401' || te.code === 'UNAUTHENTICATED') {
|
|
175
|
-
this._isReady = false;
|
|
176
|
-
throw te;
|
|
177
|
-
}
|
|
178
|
-
// 其他错误(网络/服务端 5xx 等):不阻止 ready,但保持 unknown,sendTask 会阻断
|
|
179
|
-
logger.warn(`[transport/oasn] ready probe failed code=${te.code} msg=${te.message}, continuing anyway`);
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
logger.info('[transport/oasn] ready called without agent_id; skipping probe (register flow expected)');
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
this._isReady = true;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async dispose(): Promise<void> {
|
|
189
|
-
// OASN 无长连接 —— 清 token 即可
|
|
190
|
-
this._http.setToken(undefined);
|
|
191
|
-
this._accessHttp.setToken(undefined);
|
|
192
|
-
this._isReady = false;
|
|
193
|
-
logger.info(`[transport/oasn] disposed account=${this.id}`);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
get isReady(): boolean {
|
|
197
|
-
return this._isReady;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// EventEmitter 已经实现 on/off,此处仅做类型对齐(接口签名要求)
|
|
201
|
-
override on(event: CoreTransportEvent, handler: (...args: any[]) => void): this {
|
|
202
|
-
return super.on(event, handler);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
override off(event: CoreTransportEvent, handler: (...args: any[]) => void): this {
|
|
206
|
-
return super.off(event, handler);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// ═══════════════════════════════════════════════════════════════
|
|
210
|
-
// TaskTransport(T2 核心路径)
|
|
211
|
-
// ═══════════════════════════════════════════════════════════════
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* 发起远程 Agent 调用 → POST /api/invocations。
|
|
215
|
-
*
|
|
216
|
-
* §11.1:若 task.requestId 视作 toolCallId 传入,OasnInvocation 会去 pendingStore
|
|
217
|
-
* 查同名记录,命中则复用 idempotency_key,避免重复创建 Invocation。
|
|
218
|
-
*/
|
|
219
|
-
async sendTask(targetAgentId: string, task: TaskRequest): Promise<TaskHandle> {
|
|
220
|
-
if (!this._isReady) {
|
|
221
|
-
throw makeTransportError('NOT_READY', 'OASN transport not ready; call ready() first');
|
|
222
|
-
}
|
|
223
|
-
if (this._claimStatus !== 'claimed') {
|
|
224
|
-
throw makeTransportError(
|
|
225
|
-
'REGISTRATION_NOT_ACTIVATED',
|
|
226
|
-
'OASN ClientAgent must be claimed before creating invocations',
|
|
227
|
-
{ retryable: false },
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// 把 task.requestId 映射为 toolCallId(若存在)
|
|
232
|
-
const opts: CreateInvocationOptions = {};
|
|
233
|
-
if (task.requestId) opts.toolCallId = task.requestId;
|
|
234
|
-
if (task.timeoutMs !== undefined) opts.timeoutMs = task.timeoutMs;
|
|
235
|
-
|
|
236
|
-
return this._invocation.sendTask(targetAgentId, task, opts);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/** 等待结果(轮询 / 未来可升级到 SSE) */
|
|
240
|
-
waitForTaskResult(
|
|
241
|
-
handle: TaskHandle,
|
|
242
|
-
options: { timeoutMs: number; signal?: AbortSignal; onProgress?: ProgressCallback },
|
|
243
|
-
): Promise<TaskResult> {
|
|
244
|
-
return this._invocation.waitForTaskResult(handle, options);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// ═══════════════════════════════════════════════════════════════
|
|
248
|
-
// DiscoveryTransport
|
|
249
|
-
// ═══════════════════════════════════════════════════════════════
|
|
250
|
-
|
|
251
|
-
searchAgents(query: SearchQuery): Promise<SearchResult> {
|
|
252
|
-
return this._discovery.search(query);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
getAgent(agentId: string): Promise<AgentCard | null> {
|
|
256
|
-
return this._agentCard.get(agentId);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
getCategories(params?: { agentType?: string }): Promise<CategoryTree> {
|
|
260
|
-
return this._discovery.getCategories(params);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// ═══════════════════════════════════════════════════════════════
|
|
264
|
-
// AgentCard / Status(OASN-only)
|
|
265
|
-
// ═══════════════════════════════════════════════════════════════
|
|
266
|
-
//
|
|
267
|
-
// registerAgent / claimAgent 已迁移到 CLI,此处仅保留状态查询。
|
|
268
|
-
|
|
269
|
-
async getAgentStatus(agentId: string): Promise<AgentStatusResult> {
|
|
270
|
-
const result = await this._agentStatus.getStatus(agentId);
|
|
271
|
-
this._claimStatus = result.status;
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
updateAgentCard(agentId: string, patch: AgentCardPatch): Promise<AgentCard> {
|
|
276
|
-
return this._agentCard.update(agentId, patch);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
getCurrentOwner(): Promise<OwnerInfo | null> {
|
|
280
|
-
return this._agentCard.getCurrentOwner();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// ═══════════════════════════════════════════════════════════════
|
|
284
|
-
// FileTransport(OASN-only)
|
|
285
|
-
// ═══════════════════════════════════════════════════════════════
|
|
286
|
-
|
|
287
|
-
uploadFile(file: UploadFileParams): Promise<UploadFileResult> {
|
|
288
|
-
// 默认走 LRU 路径,避免重复上传同一份内容
|
|
289
|
-
return this._files.ensureFileRef(file);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
downloadArtifact(artifactId: string): Promise<DownloadArtifactResult> {
|
|
293
|
-
return this._files.downloadArtifact(artifactId);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// ═══════════════════════════════════════════════════════════════
|
|
297
|
-
// §11.5 401 撤销恢复路径
|
|
298
|
-
// ═══════════════════════════════════════════════════════════════
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* HTTP 层捕获 401 时调用:
|
|
302
|
-
* 1. 清掉本地 Bearer
|
|
303
|
-
* 2. 标记 not ready
|
|
304
|
-
* 3. 发 'credential_expired' 事件,AccountRuntime 接收后清凭证 + 引导 register
|
|
305
|
-
*
|
|
306
|
-
* 注意:不直接清 OpenClaw config —— config 持久层的清理由 AccountRuntime 决定。
|
|
307
|
-
*/
|
|
308
|
-
private _onCredentialRevoked(): void {
|
|
309
|
-
if (!this._isReady) return; // 防止 ready 探活阶段重复触发
|
|
310
|
-
logger.error('[transport/oasn] api_key revoked (401 UNAUTHENTICATED) - emitting credential_expired');
|
|
311
|
-
this._http.setToken(undefined);
|
|
312
|
-
this._isReady = false;
|
|
313
|
-
this.emit('credential_expired', {
|
|
314
|
-
transportType: 'oasn',
|
|
315
|
-
accountId: this.id,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
}
|