openclaw-openagent 1.0.1 → 1.0.3

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 (188) hide show
  1. package/dist/index.d.ts +25 -0
  2. package/dist/index.js +105 -0
  3. package/dist/src/app/channel-tools.d.ts +28 -0
  4. package/dist/src/app/channel-tools.js +251 -0
  5. package/dist/src/app/discovery-tools.d.ts +35 -0
  6. package/dist/src/app/discovery-tools.js +243 -0
  7. package/dist/src/app/download-file-tool.d.ts +10 -0
  8. package/dist/src/app/download-file-tool.js +104 -0
  9. package/dist/src/app/hooks.d.ts +14 -0
  10. package/dist/src/app/hooks.js +118 -0
  11. package/dist/src/app/index.d.ts +13 -0
  12. package/dist/src/app/index.js +44 -0
  13. package/dist/src/app/messaging-tools.d.ts +11 -0
  14. package/dist/src/app/messaging-tools.js +79 -0
  15. package/dist/src/app/ops-tools.d.ts +21 -0
  16. package/dist/src/app/ops-tools.js +158 -0
  17. package/dist/src/app/remote-agent-tool.d.ts +27 -0
  18. package/dist/src/app/remote-agent-tool.js +461 -0
  19. package/dist/src/app/types.d.ts +61 -0
  20. package/dist/src/app/types.js +11 -0
  21. package/dist/src/app/upload-file-tool.d.ts +16 -0
  22. package/dist/src/app/upload-file-tool.js +353 -0
  23. package/dist/src/app/verbose-preflight.d.ts +2 -0
  24. package/dist/src/app/verbose-preflight.js +145 -0
  25. package/dist/src/auth/config.d.ts +79 -0
  26. package/dist/src/auth/config.js +133 -0
  27. package/dist/src/auth/credential-manager.d.ts +65 -0
  28. package/dist/src/auth/credential-manager.js +122 -0
  29. package/dist/src/auth/index.d.ts +6 -0
  30. package/dist/src/auth/index.js +6 -0
  31. package/dist/src/auth/verify.d.ts +42 -0
  32. package/dist/src/auth/verify.js +60 -0
  33. package/dist/src/channel.d.ts +269 -0
  34. package/dist/src/channel.js +488 -0
  35. package/dist/src/compat.d.ts +37 -0
  36. package/dist/src/compat.js +70 -0
  37. package/dist/src/config/config-schema.d.ts +56 -0
  38. package/dist/src/config/config-schema.js +34 -0
  39. package/dist/src/messaging/aggregator.d.ts +25 -0
  40. package/dist/src/messaging/aggregator.js +90 -0
  41. package/dist/src/messaging/collector.d.ts +27 -0
  42. package/dist/src/messaging/collector.js +76 -0
  43. package/dist/src/messaging/executor.d.ts +14 -0
  44. package/dist/src/messaging/executor.js +59 -0
  45. package/dist/src/messaging/inbound.d.ts +97 -0
  46. package/dist/src/messaging/inbound.js +63 -0
  47. package/dist/src/messaging/index.d.ts +10 -0
  48. package/dist/src/messaging/index.js +9 -0
  49. package/dist/src/messaging/mention-protocol.d.ts +42 -0
  50. package/dist/src/messaging/mention-protocol.js +74 -0
  51. package/dist/src/messaging/process-c2c-request.d.ts +55 -0
  52. package/dist/src/messaging/process-c2c-request.js +445 -0
  53. package/dist/src/messaging/process-message.d.ts +62 -0
  54. package/dist/src/messaging/process-message.js +282 -0
  55. package/dist/src/messaging/scheduler.d.ts +17 -0
  56. package/dist/src/messaging/scheduler.js +47 -0
  57. package/dist/src/messaging/types.d.ts +34 -0
  58. package/dist/src/messaging/types.js +4 -0
  59. package/dist/src/plugin-ui/assets/openagent-override.js +9278 -0
  60. package/dist/src/plugin-ui/index.d.ts +13 -0
  61. package/dist/src/plugin-ui/index.js +16 -0
  62. package/dist/src/plugin-ui/ui-extension-loader/backup.d.ts +23 -0
  63. package/dist/src/plugin-ui/ui-extension-loader/backup.js +82 -0
  64. package/dist/src/plugin-ui/ui-extension-loader/index.d.ts +28 -0
  65. package/dist/src/plugin-ui/ui-extension-loader/index.js +240 -0
  66. package/dist/src/plugin-ui/ui-extension-loader/locator.d.ts +35 -0
  67. package/dist/src/plugin-ui/ui-extension-loader/locator.js +129 -0
  68. package/dist/src/plugin-ui/ui-extension-loader/manifest.d.ts +26 -0
  69. package/dist/src/plugin-ui/ui-extension-loader/manifest.js +45 -0
  70. package/dist/src/plugin-ui/ui-extension-loader/registry-regex.d.ts +9 -0
  71. package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +724 -0
  72. package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.d.ts +8 -0
  73. package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.js +58 -0
  74. package/dist/src/plugin-ui/ui-extension-loader/types.d.ts +55 -0
  75. package/dist/src/plugin-ui/ui-extension-loader/types.js +23 -0
  76. package/dist/src/proxy/auth-proxy.d.ts +20 -0
  77. package/dist/src/proxy/auth-proxy.js +337 -0
  78. package/dist/src/runtime/account.d.ts +156 -0
  79. package/dist/src/runtime/account.js +491 -0
  80. package/dist/src/runtime/index.d.ts +5 -0
  81. package/dist/src/runtime/index.js +6 -0
  82. package/dist/src/runtime/plugin-runtime.d.ts +40 -0
  83. package/dist/src/runtime/plugin-runtime.js +72 -0
  84. package/dist/src/runtime/registry.d.ts +41 -0
  85. package/dist/src/runtime/registry.js +60 -0
  86. package/dist/src/sdk/CLASS_MAP.md +143 -0
  87. package/dist/src/sdk/index.d.ts +126 -0
  88. package/dist/src/sdk/index.js +23990 -0
  89. package/dist/src/sdk/modules/cloud-search-module.js +1117 -0
  90. package/dist/src/sdk/modules/follow-module.js +1069 -0
  91. package/dist/src/sdk/modules/group-module.js +7397 -0
  92. package/dist/src/sdk/modules/relationship-module.js +2269 -0
  93. package/dist/src/sdk/modules/signaling-module.js +1468 -0
  94. package/dist/src/sdk/modules/tim-upload-plugin.js +730 -0
  95. package/dist/src/sdk/node-env/http-request.js +90 -0
  96. package/dist/src/sdk/node-env/index.js +57 -0
  97. package/dist/src/sdk/node-env/storage.js +114 -0
  98. package/dist/src/sdk/package.json +10 -0
  99. package/dist/src/sdk/sdk/CLASS_MAP.md +143 -0
  100. package/dist/src/sdk/sdk/index.d.ts +126 -0
  101. package/dist/src/sdk/sdk/index.js +23990 -0
  102. package/dist/src/sdk/sdk/modules/cloud-search-module.js +1117 -0
  103. package/dist/src/sdk/sdk/modules/follow-module.js +1069 -0
  104. package/dist/src/sdk/sdk/modules/group-module.js +7397 -0
  105. package/dist/src/sdk/sdk/modules/relationship-module.js +2269 -0
  106. package/dist/src/sdk/sdk/modules/signaling-module.js +1468 -0
  107. package/dist/src/sdk/sdk/modules/tim-upload-plugin.js +730 -0
  108. package/dist/src/sdk/sdk/node-env/http-request.js +90 -0
  109. package/dist/src/sdk/sdk/node-env/index.js +57 -0
  110. package/dist/src/sdk/sdk/node-env/storage.js +114 -0
  111. package/dist/src/sdk/sdk/package.json +10 -0
  112. package/dist/src/sdk/sdk/tsconfig.json +16 -0
  113. package/dist/src/sdk/tsconfig.json +16 -0
  114. package/dist/src/state/pending-invocation-store.d.ts +26 -0
  115. package/dist/src/state/pending-invocation-store.js +39 -0
  116. package/dist/src/state/store.d.ts +165 -0
  117. package/dist/src/state/store.js +535 -0
  118. package/dist/src/tim/c2c.d.ts +83 -0
  119. package/dist/src/tim/c2c.js +318 -0
  120. package/dist/src/tim/channels.d.ts +95 -0
  121. package/dist/src/tim/channels.js +279 -0
  122. package/dist/src/tim/client.d.ts +54 -0
  123. package/dist/src/tim/client.js +268 -0
  124. package/dist/src/tim/index.d.ts +6 -0
  125. package/dist/src/tim/index.js +6 -0
  126. package/dist/src/tim/messages.d.ts +50 -0
  127. package/dist/src/tim/messages.js +104 -0
  128. package/dist/src/tim/sdk-logger-init.d.ts +13 -0
  129. package/dist/src/tim/sdk-logger-init.js +46 -0
  130. package/dist/src/tools.d.ts +9 -0
  131. package/dist/src/tools.js +8 -0
  132. package/dist/src/transport/factory.d.ts +63 -0
  133. package/dist/src/transport/factory.js +54 -0
  134. package/dist/src/transport/oasn/index.d.ts +12 -0
  135. package/dist/src/transport/oasn/index.js +9 -0
  136. package/dist/src/transport/oasn/oasn-agent-card.d.ts +38 -0
  137. package/dist/src/transport/oasn/oasn-agent-card.js +102 -0
  138. package/dist/src/transport/oasn/oasn-discovery.d.ts +33 -0
  139. package/dist/src/transport/oasn/oasn-discovery.js +97 -0
  140. package/dist/src/transport/oasn/oasn-files.d.ts +64 -0
  141. package/dist/src/transport/oasn/oasn-files.js +174 -0
  142. package/dist/src/transport/oasn/oasn-http.d.ts +98 -0
  143. package/dist/src/transport/oasn/oasn-http.js +362 -0
  144. package/dist/src/transport/oasn/oasn-invocation.d.ts +154 -0
  145. package/dist/src/transport/oasn/oasn-invocation.js +432 -0
  146. package/dist/src/transport/oasn/oasn-normalize.d.ts +6 -0
  147. package/dist/src/transport/oasn/oasn-normalize.js +112 -0
  148. package/dist/src/transport/oasn/oasn-register.d.ts +19 -0
  149. package/dist/src/transport/oasn/oasn-register.js +24 -0
  150. package/dist/src/transport/oasn/oasn-transport.d.ts +114 -0
  151. package/dist/src/transport/oasn/oasn-transport.js +230 -0
  152. package/dist/src/transport/oasn/oasn-types.d.ts +331 -0
  153. package/dist/src/transport/oasn/oasn-types.js +44 -0
  154. package/dist/src/transport/tim/index.d.ts +7 -0
  155. package/dist/src/transport/tim/index.js +6 -0
  156. package/dist/src/transport/tim/tim-transport.d.ts +122 -0
  157. package/dist/src/transport/tim/tim-transport.js +402 -0
  158. package/dist/src/transport/types.d.ts +450 -0
  159. package/dist/src/transport/types.js +38 -0
  160. package/dist/src/util/http.d.ts +21 -0
  161. package/dist/src/util/http.js +93 -0
  162. package/dist/src/util/logger.d.ts +20 -0
  163. package/dist/src/util/logger.js +100 -0
  164. package/dist/src/util/url-resolver.d.ts +7 -0
  165. package/dist/src/util/url-resolver.js +20 -0
  166. package/index.ts +11 -0
  167. package/openclaw.plugin.json +9 -0
  168. package/package.json +7 -4
  169. package/src/app/download-file-tool.ts +133 -0
  170. package/src/app/hooks.ts +89 -5
  171. package/src/app/index.ts +6 -0
  172. package/src/app/remote-agent-tool.ts +46 -0
  173. package/src/app/types.ts +1 -0
  174. package/src/app/upload-file-tool.ts +411 -0
  175. package/src/plugin-ui/assets/openagent-override.js +15 -66
  176. package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -61
  177. package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -1
  178. package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +14 -3
  179. package/src/plugin-ui/ui-extension-loader/registry-regex.ts +102 -63
  180. package/src/runtime/account.ts +0 -23
  181. package/src/transport/oasn/oasn-files.ts +5 -5
  182. package/src/transport/oasn/oasn-invocation.ts +44 -2
  183. package/src/transport/oasn/oasn-normalize.ts +0 -26
  184. package/src/transport/oasn/oasn-register.ts +8 -81
  185. package/src/transport/oasn/oasn-transport.ts +9 -32
  186. package/src/transport/oasn/oasn-types.ts +53 -6
  187. package/src/transport/types.ts +33 -36
  188. package/src/util/url-resolver.ts +17 -0
@@ -0,0 +1,114 @@
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
+ import { EventEmitter } from 'node:events';
31
+ import { type AgentCard, type AgentCardPatch, type AgentStatusResult, type CategoryTree, type CoreTransportEvent, type DownloadArtifactResult, type OasnTransport, type OwnerInfo, type ProgressCallback, type SearchQuery, type SearchResult, type TaskHandle, type TaskRequest, type TaskResult, type TransportCredentials, type UploadFileParams, type UploadFileResult } from '../types.js';
32
+ import { type PendingInvocationStore } from './oasn-invocation.js';
33
+ export interface OasnTransportInitOptions {
34
+ /** 实例 id(多账户场景区分用) */
35
+ accountId: string;
36
+ /** OASN API base URL,例 `https://api.oasn.ai` */
37
+ apiBase: string;
38
+ /** Optional Access-layer API base URL for invocation/file/artifact endpoints. */
39
+ accessApiBase?: string;
40
+ /**
41
+ * 当前 agent_id(用于 ready() 探活 + register 后回填)。
42
+ * 可在 ready() 之前为空(未注册场景),但 sendTask 之类操作会失败。
43
+ */
44
+ agentId?: string;
45
+ /** §11.1 持久化钩子(接 StateStore.pending_invocations);可选 */
46
+ pendingStore?: PendingInvocationStore;
47
+ /** 单次 HTTP 超时(默认 30s) */
48
+ defaultTimeoutMs?: number;
49
+ /** retryable 错误自动重试次数(默认 3) */
50
+ maxRetries?: number;
51
+ }
52
+ export declare class OasnTransportImpl extends EventEmitter implements OasnTransport {
53
+ readonly transportType: "oasn";
54
+ readonly id: string;
55
+ private _http;
56
+ private _accessHttp;
57
+ private _agentCard;
58
+ private _discovery;
59
+ private _agentStatus;
60
+ private _invocation;
61
+ private _files;
62
+ private _agentId;
63
+ private _isReady;
64
+ private _claimStatus;
65
+ constructor(options: OasnTransportInitOptions);
66
+ /**
67
+ * 校验 api_key 有效性 + 进入可工作状态。
68
+ *
69
+ * 验证策略:
70
+ * 1. 设置 Bearer = credentials.token
71
+ * 2. 若 agentId 已知 → 调 GET /api/agent-cards/{agent_id}
72
+ * - status 接口返回 claimed 才允许后续 Invocation
73
+ * - 401 → onCredentialRevoked 回调,抛 TransportError
74
+ *
75
+ * 注:credentials.identity 在 OASN 场景下应等于 agent_id。
76
+ */
77
+ ready(credentials: TransportCredentials): Promise<void>;
78
+ dispose(): Promise<void>;
79
+ get isReady(): boolean;
80
+ on(event: CoreTransportEvent, handler: (...args: any[]) => void): this;
81
+ off(event: CoreTransportEvent, handler: (...args: any[]) => void): this;
82
+ /**
83
+ * 发起远程 Agent 调用 → POST /api/invocations。
84
+ *
85
+ * §11.1:若 task.requestId 视作 toolCallId 传入,OasnInvocation 会去 pendingStore
86
+ * 查同名记录,命中则复用 idempotency_key,避免重复创建 Invocation。
87
+ */
88
+ sendTask(targetAgentId: string, task: TaskRequest): Promise<TaskHandle>;
89
+ /** 等待结果(轮询 / 未来可升级到 SSE) */
90
+ waitForTaskResult(handle: TaskHandle, options: {
91
+ timeoutMs: number;
92
+ signal?: AbortSignal;
93
+ onProgress?: ProgressCallback;
94
+ }): Promise<TaskResult>;
95
+ searchAgents(query: SearchQuery): Promise<SearchResult>;
96
+ getAgent(agentId: string): Promise<AgentCard | null>;
97
+ getCategories(params?: {
98
+ agentType?: string;
99
+ }): Promise<CategoryTree>;
100
+ getAgentStatus(agentId: string): Promise<AgentStatusResult>;
101
+ updateAgentCard(agentId: string, patch: AgentCardPatch): Promise<AgentCard>;
102
+ getCurrentOwner(): Promise<OwnerInfo | null>;
103
+ uploadFile(file: UploadFileParams): Promise<UploadFileResult>;
104
+ downloadArtifact(artifactId: string): Promise<DownloadArtifactResult>;
105
+ /**
106
+ * HTTP 层捕获 401 时调用:
107
+ * 1. 清掉本地 Bearer
108
+ * 2. 标记 not ready
109
+ * 3. 发 'credential_expired' 事件,AccountRuntime 接收后清凭证 + 引导 register
110
+ *
111
+ * 注意:不直接清 OpenClaw config —— config 持久层的清理由 AccountRuntime 决定。
112
+ */
113
+ private _onCredentialRevoked;
114
+ }
@@ -0,0 +1,230 @@
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
+ import { EventEmitter } from 'node:events';
31
+ import { logger } from '../../util/logger.js';
32
+ import { makeTransportError, } from '../types.js';
33
+ import { OasnAgentCard } from './oasn-agent-card.js';
34
+ import { OasnDiscovery } from './oasn-discovery.js';
35
+ import { OasnFiles } from './oasn-files.js';
36
+ import { OasnHttpClient } from './oasn-http.js';
37
+ import { OasnInvocation, } from './oasn-invocation.js';
38
+ import { OasnAgentStatus } from './oasn-register.js';
39
+ // ───────────────────────────────────────────────────────────────
40
+ // 实现类
41
+ // ───────────────────────────────────────────────────────────────
42
+ export class OasnTransportImpl extends EventEmitter {
43
+ transportType = 'oasn';
44
+ id;
45
+ _http;
46
+ _accessHttp;
47
+ _agentCard;
48
+ _discovery;
49
+ _agentStatus;
50
+ _invocation;
51
+ _files;
52
+ _agentId;
53
+ _isReady = false;
54
+ _claimStatus = 'unknown';
55
+ constructor(options) {
56
+ super();
57
+ this.id = options.accountId;
58
+ this._agentId = options.agentId;
59
+ // ── HTTP 层(含 401 撤销回调) ────────────────────────────────
60
+ const httpConfig = {
61
+ apiBase: options.apiBase,
62
+ defaultTimeoutMs: options.defaultTimeoutMs,
63
+ maxRetries: options.maxRetries,
64
+ onCredentialRevoked: () => this._onCredentialRevoked(),
65
+ };
66
+ this._http = new OasnHttpClient(httpConfig);
67
+ this._accessHttp = new OasnHttpClient({
68
+ ...httpConfig,
69
+ apiBase: options.accessApiBase || options.apiBase,
70
+ });
71
+ // ── 子模块(共享 HTTP 实例) ──────────────────────────────────
72
+ this._agentCard = new OasnAgentCard(this._http);
73
+ this._discovery = new OasnDiscovery(this._http);
74
+ this._agentStatus = new OasnAgentStatus(this._http);
75
+ this._invocation = new OasnInvocation(this._accessHttp, options.pendingStore);
76
+ this._files = new OasnFiles(this._accessHttp);
77
+ }
78
+ // ═══════════════════════════════════════════════════════════════
79
+ // CoreTransport
80
+ // ═══════════════════════════════════════════════════════════════
81
+ /**
82
+ * 校验 api_key 有效性 + 进入可工作状态。
83
+ *
84
+ * 验证策略:
85
+ * 1. 设置 Bearer = credentials.token
86
+ * 2. 若 agentId 已知 → 调 GET /api/agent-cards/{agent_id}
87
+ * - status 接口返回 claimed 才允许后续 Invocation
88
+ * - 401 → onCredentialRevoked 回调,抛 TransportError
89
+ *
90
+ * 注:credentials.identity 在 OASN 场景下应等于 agent_id。
91
+ */
92
+ async ready(credentials) {
93
+ if (!credentials.token) {
94
+ throw makeTransportError('MISSING_CREDENTIAL', 'OASN ready: token (api_key) is required');
95
+ }
96
+ this._http.setToken(credentials.token);
97
+ this._accessHttp.setToken(credentials.token);
98
+ // 若构造时未传 agentId,则从 credentials.identity 读取
99
+ if (!this._agentId && credentials.identity) {
100
+ this._agentId = credentials.identity;
101
+ }
102
+ if (this._agentId) {
103
+ try {
104
+ const status = await this._agentStatus.getStatus(this._agentId);
105
+ this._claimStatus = status.status;
106
+ logger.info(`[transport/oasn] ready agent_id=${this._agentId} `
107
+ + `claim_status=${status.status}`);
108
+ }
109
+ catch (err) {
110
+ const te = err;
111
+ // 401 已经在 HTTP 层触发了 onCredentialRevoked,再次显式抛
112
+ if (te.code === 'HTTP_401' || te.code === 'UNAUTHENTICATED') {
113
+ this._isReady = false;
114
+ throw te;
115
+ }
116
+ // 其他错误(网络/服务端 5xx 等):不阻止 ready,但保持 unknown,sendTask 会阻断
117
+ logger.warn(`[transport/oasn] ready probe failed code=${te.code} msg=${te.message}, continuing anyway`);
118
+ }
119
+ }
120
+ else {
121
+ logger.info('[transport/oasn] ready called without agent_id; skipping probe (register flow expected)');
122
+ }
123
+ this._isReady = true;
124
+ }
125
+ async dispose() {
126
+ // OASN 无长连接 —— 清 token 即可
127
+ this._http.setToken(undefined);
128
+ this._accessHttp.setToken(undefined);
129
+ this._isReady = false;
130
+ logger.info(`[transport/oasn] disposed account=${this.id}`);
131
+ }
132
+ get isReady() {
133
+ return this._isReady;
134
+ }
135
+ // EventEmitter 已经实现 on/off,此处仅做类型对齐(接口签名要求)
136
+ on(event, handler) {
137
+ return super.on(event, handler);
138
+ }
139
+ off(event, handler) {
140
+ return super.off(event, handler);
141
+ }
142
+ // ═══════════════════════════════════════════════════════════════
143
+ // TaskTransport(T2 核心路径)
144
+ // ═══════════════════════════════════════════════════════════════
145
+ /**
146
+ * 发起远程 Agent 调用 → POST /api/invocations。
147
+ *
148
+ * §11.1:若 task.requestId 视作 toolCallId 传入,OasnInvocation 会去 pendingStore
149
+ * 查同名记录,命中则复用 idempotency_key,避免重复创建 Invocation。
150
+ */
151
+ async sendTask(targetAgentId, task) {
152
+ if (!this._isReady) {
153
+ throw makeTransportError('NOT_READY', 'OASN transport not ready; call ready() first');
154
+ }
155
+ if (this._claimStatus !== 'claimed') {
156
+ throw makeTransportError('REGISTRATION_NOT_ACTIVATED', 'OASN ClientAgent must be claimed before creating invocations', { retryable: false });
157
+ }
158
+ // 把 task.requestId 映射为 toolCallId(若存在)
159
+ const opts = {};
160
+ if (task.requestId)
161
+ opts.toolCallId = task.requestId;
162
+ if (task.timeoutMs !== undefined)
163
+ opts.timeoutMs = task.timeoutMs;
164
+ return this._invocation.sendTask(targetAgentId, task, opts);
165
+ }
166
+ /** 等待结果(轮询 / 未来可升级到 SSE) */
167
+ waitForTaskResult(handle, options) {
168
+ return this._invocation.waitForTaskResult(handle, options);
169
+ }
170
+ // ═══════════════════════════════════════════════════════════════
171
+ // DiscoveryTransport
172
+ // ═══════════════════════════════════════════════════════════════
173
+ searchAgents(query) {
174
+ return this._discovery.search(query);
175
+ }
176
+ getAgent(agentId) {
177
+ return this._agentCard.get(agentId);
178
+ }
179
+ getCategories(params) {
180
+ return this._discovery.getCategories(params);
181
+ }
182
+ // ═══════════════════════════════════════════════════════════════
183
+ // AgentCard / Status(OASN-only)
184
+ // ═══════════════════════════════════════════════════════════════
185
+ //
186
+ // registerAgent / claimAgent 已迁移到 CLI,此处仅保留状态查询。
187
+ async getAgentStatus(agentId) {
188
+ const result = await this._agentStatus.getStatus(agentId);
189
+ this._claimStatus = result.status;
190
+ return result;
191
+ }
192
+ updateAgentCard(agentId, patch) {
193
+ return this._agentCard.update(agentId, patch);
194
+ }
195
+ getCurrentOwner() {
196
+ return this._agentCard.getCurrentOwner();
197
+ }
198
+ // ═══════════════════════════════════════════════════════════════
199
+ // FileTransport(OASN-only)
200
+ // ═══════════════════════════════════════════════════════════════
201
+ uploadFile(file) {
202
+ // 默认走 LRU 路径,避免重复上传同一份内容
203
+ return this._files.ensureFileRef(file);
204
+ }
205
+ downloadArtifact(artifactId) {
206
+ return this._files.downloadArtifact(artifactId);
207
+ }
208
+ // ═══════════════════════════════════════════════════════════════
209
+ // §11.5 401 撤销恢复路径
210
+ // ═══════════════════════════════════════════════════════════════
211
+ /**
212
+ * HTTP 层捕获 401 时调用:
213
+ * 1. 清掉本地 Bearer
214
+ * 2. 标记 not ready
215
+ * 3. 发 'credential_expired' 事件,AccountRuntime 接收后清凭证 + 引导 register
216
+ *
217
+ * 注意:不直接清 OpenClaw config —— config 持久层的清理由 AccountRuntime 决定。
218
+ */
219
+ _onCredentialRevoked() {
220
+ if (!this._isReady)
221
+ return; // 防止 ready 探活阶段重复触发
222
+ logger.error('[transport/oasn] api_key revoked (401 UNAUTHENTICATED) - emitting credential_expired');
223
+ this._http.setToken(undefined);
224
+ this._isReady = false;
225
+ this.emit('credential_expired', {
226
+ transportType: 'oasn',
227
+ accountId: this.id,
228
+ });
229
+ }
230
+ }
@@ -0,0 +1,331 @@
1
+ /**
2
+ * OASN API 请求/响应类型定义
3
+ *
4
+ * 设计依据:
5
+ * - docs/specs/2026-06-16-oasn-api-module-mapping.md
6
+ * - oasn-01-onboarding/apis.md(agent / claim / auth / agent-card / discovery)
7
+ * - oasn-02-access-layer/apis.md(invocation / file / artifact)
8
+ *
9
+ * 这些类型仅在 OASN transport 内部使用,对外暴露的通用类型在 src/transport/types.ts。
10
+ * onboarding controller 的 Java record 当前使用 camelCase 请求/响应字段;
11
+ * transport 层兼容历史 snake_case 响应,并对外归一到 src/transport/types.ts 的稳定模型。
12
+ */
13
+ /**
14
+ * OASN 统一错误响应格式(所有 4xx/5xx 接口返回此结构)。
15
+ * 详见 api-module-mapping.md §五 通用错误处理。
16
+ */
17
+ export interface OasnErrorBody {
18
+ error: {
19
+ /** 错误码:UNAUTHENTICATED / FORBIDDEN / TARGET_UNAVAILABLE / ... */
20
+ code: string;
21
+ /** 人类可读消息 */
22
+ message: string;
23
+ /** 客户端是否可重试(服务端裁决) */
24
+ retryable: boolean;
25
+ /** 附加上下文(端点定义具体字段) */
26
+ details?: Record<string, unknown>;
27
+ /** 排障追踪 id */
28
+ request_id?: string;
29
+ };
30
+ }
31
+ export interface RegisterAgentRequest {
32
+ /** 当前固定为 "openclaw"(也可能是 "codex" / "claude_code" / "hermes") */
33
+ platform: string;
34
+ }
35
+ export interface RegisterAgentResponse {
36
+ agentId?: string;
37
+ agent_id?: string;
38
+ agentType?: 'client';
39
+ agent_type?: 'client';
40
+ /** 一次性明文 api_key,仅此响应返回;服务端只存 hash */
41
+ apiKey?: string;
42
+ api_key?: string;
43
+ claimUrl?: string;
44
+ claim_url?: string;
45
+ status: 'unclaimed';
46
+ agentCard?: AgentCardResponse;
47
+ agent_card?: AgentCardResponse;
48
+ }
49
+ export interface AgentStatusResponse {
50
+ agentId?: string;
51
+ agent_id?: string;
52
+ status: 'unclaimed' | 'claim_pending' | 'claimed';
53
+ access_token?: string;
54
+ accessToken?: string;
55
+ }
56
+ export interface AgentCardResponse {
57
+ agentId?: string;
58
+ agent_id?: string;
59
+ agentType?: 'client' | 'service';
60
+ agent_type?: 'client' | 'service';
61
+ agentStatus?: string;
62
+ agent_status?: string;
63
+ claimStatus?: string;
64
+ claim_status?: string;
65
+ name: string;
66
+ description: string | null;
67
+ MOM: string | null;
68
+ tags: Array<{
69
+ tagId?: string;
70
+ tag_id?: string;
71
+ name: string;
72
+ }>;
73
+ category: string[];
74
+ avatarRef?: string | null;
75
+ avatar_ref?: string | null;
76
+ avatarUrl?: string | null;
77
+ avatar_url?: string | null;
78
+ visibility?: 'public' | 'private';
79
+ publicMetadata?: Record<string, unknown> | null;
80
+ public_metadata?: Record<string, unknown> | null;
81
+ updatedAt?: string;
82
+ updated_at?: string;
83
+ }
84
+ export interface ClaimAgentRequest {
85
+ agentId?: string;
86
+ claimToken?: string;
87
+ ownerEmail: string;
88
+ }
89
+ export interface ClaimAgentResponse {
90
+ agentId?: string;
91
+ agent_id?: string;
92
+ status: 'claim_email_sent';
93
+ ownerEmailMasked?: string;
94
+ owner_email_masked?: string;
95
+ expiresAt?: string;
96
+ expires_at?: string;
97
+ }
98
+ export interface UpdateAgentCardRequest {
99
+ name?: string | null;
100
+ description?: string | null;
101
+ MOM?: string | null;
102
+ tags?: string[] | null;
103
+ category?: string[] | null;
104
+ avatarRef?: string | null;
105
+ visibility?: 'public' | 'private';
106
+ publicMetadata?: Record<string, unknown> | null;
107
+ }
108
+ export interface CategoryNodeResponse {
109
+ categoryId?: string;
110
+ category_id?: string;
111
+ name: string;
112
+ children?: CategoryNodeResponse[];
113
+ }
114
+ export interface CategoryTreeResponse {
115
+ categories: CategoryNodeResponse[];
116
+ updatedAt?: string;
117
+ updated_at?: string;
118
+ }
119
+ /** 三种搜索端点的请求结构 */
120
+ export interface SearchByQueryRequest {
121
+ query: string;
122
+ agentTypes?: string[];
123
+ sort?: string[];
124
+ pageSize?: number;
125
+ pageNum?: number;
126
+ }
127
+ export interface SearchByCategoryRequest {
128
+ category: string[];
129
+ agentTypes?: string[];
130
+ sort?: string[];
131
+ pageSize?: number;
132
+ pageNum?: number;
133
+ }
134
+ export interface SearchByTagsRequest {
135
+ tags: string[];
136
+ agentTypes?: string[];
137
+ sort?: string[];
138
+ pageSize?: number;
139
+ pageNum?: number;
140
+ }
141
+ export interface SearchResponse {
142
+ searchId?: string;
143
+ search_id?: string;
144
+ agentCards?: AgentCardResponse[];
145
+ agent_cards?: AgentCardResponse[];
146
+ pageNum?: number;
147
+ page_num?: number;
148
+ pageSize?: number;
149
+ page_size?: number;
150
+ hasNext?: boolean;
151
+ has_next?: boolean;
152
+ }
153
+ export interface CreateInvocationRequest {
154
+ /** 客户端生成的幂等 key(详见 §11.1) */
155
+ idempotency_key: string;
156
+ service_agent_id: string;
157
+ /** 显式输入意图,至少包含 task 字段 */
158
+ input: {
159
+ task: string;
160
+ } & Record<string, unknown>;
161
+ session_id?: string;
162
+ input_file_refs?: string[];
163
+ input_artifact_refs?: string[];
164
+ /** 期望超时(服务端裁决最终 effective_timeout_ms) */
165
+ timeout_ms?: number;
166
+ /** 客户端分组标识(可选) */
167
+ client_request_group_id?: string;
168
+ }
169
+ export interface CreateInvocationResponse {
170
+ invocationId?: string;
171
+ invocation_id?: string;
172
+ sessionId?: string;
173
+ session_id?: string;
174
+ status: 'accepted' | 'queued';
175
+ serviceAgentId?: string;
176
+ service_agent_id?: string;
177
+ effectiveTimeoutMs?: number;
178
+ effective_timeout_ms?: number;
179
+ nextPollAfterMs?: number;
180
+ next_poll_after_ms?: number;
181
+ /** 是否幂等重放(同一 idempotency_key 多次请求返回 true) */
182
+ idempotentReplay?: boolean;
183
+ idempotent_replay?: boolean;
184
+ createdAt?: string;
185
+ created_at?: string;
186
+ }
187
+ /** Invocation 状态枚举 */
188
+ export type InvocationStatus = 'accepted' | 'queued' | 'running' | 'succeeded' | 'failed' | 'timed_out' | 'cancelled';
189
+ /** 是否进入终态(停止轮询) */
190
+ export declare function isInvocationTerminal(status: InvocationStatus): boolean;
191
+ export interface InvocationProgress {
192
+ lifecycleState?: string;
193
+ lifecycle_state?: string;
194
+ activityCategory?: string;
195
+ activity_category?: string;
196
+ progressPercent?: number;
197
+ progress_percent?: number;
198
+ elapsedMs?: number;
199
+ elapsed_ms?: number;
200
+ /** 可对外展示的安全状态描述(已脱敏) */
201
+ safeStatusMessage?: string;
202
+ safe_status_message?: string;
203
+ }
204
+ export interface ArtifactResponse {
205
+ artifactId?: string;
206
+ artifact_id?: string;
207
+ displayName?: string;
208
+ display_name?: string;
209
+ mimeType?: string;
210
+ mime_type?: string;
211
+ sizeBytes?: number;
212
+ size_bytes?: number;
213
+ contentAvailable?: boolean;
214
+ content_available?: boolean;
215
+ contentUrl?: string;
216
+ content_url?: string;
217
+ }
218
+ /**
219
+ * OASN WebUI continuation —— 标准 run 完成后,声明了 webui 能力的 ServiceAgent
220
+ * 会在用户视图里暴露一个可继续打开 WebUI 的入口。
221
+ *
222
+ * 后端同时兼容 camelCase / snake_case,插件两侧都需要做 fallback 归一。
223
+ * launch_url 通常是相对路径(如 /webui/continuations/{continuation_id}),
224
+ * 由上层按 OASN Access base URL 解析为绝对地址。
225
+ */
226
+ export interface WebuiContinuationResponse {
227
+ continuationId?: string;
228
+ continuation_id?: string;
229
+ type?: string;
230
+ displayName?: string;
231
+ display_name?: string;
232
+ visibleState?: string;
233
+ visible_state?: string;
234
+ sessionId?: string;
235
+ session_id?: string;
236
+ launchUrl?: string;
237
+ launch_url?: string;
238
+ }
239
+ /**
240
+ * 用户视图结果 —— 后端在 sanitizeInvocationView() 后追加的结构。
241
+ * 除已声明字段外,保留 index signature 以容纳后续新增字段。
242
+ */
243
+ export interface VisibleResultResponse {
244
+ inlineResultSummary?: string;
245
+ inline_result_summary?: string;
246
+ webuiContinuation?: WebuiContinuationResponse;
247
+ webui_continuation?: WebuiContinuationResponse;
248
+ [key: string]: unknown;
249
+ }
250
+ export interface GetInvocationResponse {
251
+ invocationId?: string;
252
+ invocation_id?: string;
253
+ sessionId?: string;
254
+ session_id?: string;
255
+ status: InvocationStatus;
256
+ progress?: InvocationProgress;
257
+ inlineResult?: {
258
+ summary: string;
259
+ [key: string]: unknown;
260
+ };
261
+ inline_result?: {
262
+ summary: string;
263
+ [key: string]: unknown;
264
+ };
265
+ /** 用户视图 —— 含 inline_result_summary 与 webui_continuation(camelCase) */
266
+ visibleResult?: VisibleResultResponse;
267
+ /** 用户视图 —— 含 inline_result_summary 与 webui_continuation(snake_case) */
268
+ visible_result?: VisibleResultResponse;
269
+ artifacts?: ArtifactResponse[];
270
+ /** 终态时为 null */
271
+ nextPollAfterMs?: number | null;
272
+ next_poll_after_ms?: number | null;
273
+ warnings?: string[];
274
+ userError?: {
275
+ code: string;
276
+ message: string;
277
+ };
278
+ user_error?: {
279
+ code: string;
280
+ message: string;
281
+ };
282
+ createdAt?: string;
283
+ created_at?: string;
284
+ updatedAt?: string;
285
+ updated_at?: string;
286
+ }
287
+ export interface UploadFileResponse {
288
+ file_ref?: string;
289
+ display_name?: string;
290
+ mime_type?: string;
291
+ size_bytes?: number;
292
+ /** ISO 8601 字符串 */
293
+ expires_at?: string;
294
+ created_at?: string;
295
+ fileRef?: string;
296
+ displayName?: string;
297
+ mimeType?: string;
298
+ sizeBytes?: number;
299
+ /** ISO 8601 字符串 */
300
+ expiresAt?: string | null;
301
+ createdAt?: string;
302
+ }
303
+ export interface OwnerInfoResponse {
304
+ ownerId?: string;
305
+ owner_id?: string;
306
+ ownerType?: string;
307
+ owner_type?: string;
308
+ displayName?: string;
309
+ display_name?: string;
310
+ emailMasked?: string;
311
+ email_masked?: string;
312
+ emailVerifiedAt?: string;
313
+ email_verified_at?: string;
314
+ status: string;
315
+ }
316
+ /** OASN HTTP 端点路径(相对于 api_base) */
317
+ export declare const OASN_ENDPOINTS: {
318
+ readonly REGISTER: "/api/agents/register";
319
+ readonly CLAIM: "/api/agents/claim";
320
+ readonly AGENT_STATUS: (agentId: string) => string;
321
+ readonly AGENT_CARD: (agentId: string) => string;
322
+ readonly CATEGORIES: "/api/agent-card-categories";
323
+ readonly SEARCH_BY_QUERY: "/api/agent-cards/search/by-query";
324
+ readonly SEARCH_BY_CATEGORY: "/api/agent-cards/search/by-category";
325
+ readonly SEARCH_BY_TAGS: "/api/agent-cards/search/by-tags";
326
+ readonly INVOCATIONS: "/api/invocations";
327
+ readonly INVOCATION: (id: string) => string;
328
+ readonly FILES: "/api/files";
329
+ readonly ARTIFACT_CONTENT: (id: string) => string;
330
+ readonly USERS_ME: "/api/users/me";
331
+ };