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
package/src/auth/config.ts
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth — Configuration resolution
|
|
3
|
-
*
|
|
4
|
-
* Resolves OpenAgent account configuration from the OpenClaw config object.
|
|
5
|
-
* Supports two configuration layouts:
|
|
6
|
-
* 1. Nested: cfg.channels.openagent.accounts.{accountId}.*
|
|
7
|
-
* 2. Fallback (F1 compat): cfg.channels.openagent.agentId / .apiKey (top-level shorthand)
|
|
8
|
-
*
|
|
9
|
-
* See §0.1 of refactoring-plan.md.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const DEFAULT_API_BASE = 'https://api.openagent.club';
|
|
13
|
-
const DEFAULT_OASN_PUBLIC_ROOT = 'https://oasn-test.haimawan.com';
|
|
14
|
-
const OASN_ENV_ID_RE = /^[A-Za-z0-9_-]+$/;
|
|
15
|
-
/**
|
|
16
|
-
* OASN 默认 API base。
|
|
17
|
-
*
|
|
18
|
-
* 未配置时故意使用不可达占位,避免把本地或生产请求误打到 REL 私有地址。
|
|
19
|
-
* 解析优先级:账号级 api_base > channel 级 api_base > 环境变量 > 该占位。
|
|
20
|
-
*/
|
|
21
|
-
export const DEFAULT_OASN_API_BASE = 'https://oasn.invalid/CONFIGURE_ME';
|
|
22
|
-
|
|
23
|
-
export function isUnconfiguredOasnApiBase(value: string | undefined): boolean {
|
|
24
|
-
return !value || value === DEFAULT_OASN_API_BASE;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function normalizeOasnApiBase(value: unknown): string {
|
|
28
|
-
const normalized = String(value || '')
|
|
29
|
-
.trim()
|
|
30
|
-
.replace(/\/+$/, '')
|
|
31
|
-
.replace(/\/api$/, '');
|
|
32
|
-
return normalized === DEFAULT_OASN_API_BASE ? '' : normalized;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function normalizeOasnEnvId(value: unknown): string {
|
|
36
|
-
const envId = String(value || '').trim();
|
|
37
|
-
if (!envId) return '';
|
|
38
|
-
return OASN_ENV_ID_RE.test(envId) ? envId : '';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function oasnPublicBaseFromEnvId(envId: string): string {
|
|
42
|
-
const normalized = normalizeOasnEnvId(envId);
|
|
43
|
-
if (!normalized) return '';
|
|
44
|
-
const root = normalizeOasnApiBase(process.env.OASN_PUBLIC_ROOT || process.env.OPENAGENT_OASN_PUBLIC_ROOT || DEFAULT_OASN_PUBLIC_ROOT);
|
|
45
|
-
return `${root}/e/${normalized}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function resolveOasnBase({
|
|
49
|
-
accountBase,
|
|
50
|
-
channelBase,
|
|
51
|
-
envBase,
|
|
52
|
-
accountEnvId,
|
|
53
|
-
channelEnvId,
|
|
54
|
-
envEnvId,
|
|
55
|
-
fallbackBase,
|
|
56
|
-
}: {
|
|
57
|
-
accountBase?: unknown;
|
|
58
|
-
channelBase?: unknown;
|
|
59
|
-
envBase?: unknown;
|
|
60
|
-
accountEnvId?: unknown;
|
|
61
|
-
channelEnvId?: unknown;
|
|
62
|
-
envEnvId?: unknown;
|
|
63
|
-
fallbackBase: string;
|
|
64
|
-
}): string {
|
|
65
|
-
const configuredBase = normalizeOasnApiBase(accountBase) || normalizeOasnApiBase(channelBase);
|
|
66
|
-
if (configuredBase) return configuredBase;
|
|
67
|
-
const configuredEnvId = normalizeOasnEnvId(accountEnvId) || normalizeOasnEnvId(channelEnvId);
|
|
68
|
-
if (configuredEnvId) return oasnPublicBaseFromEnvId(configuredEnvId);
|
|
69
|
-
const ambientBase = normalizeOasnApiBase(envBase);
|
|
70
|
-
if (ambientBase) return ambientBase;
|
|
71
|
-
const ambientEnvId = normalizeOasnEnvId(envEnvId);
|
|
72
|
-
if (ambientEnvId) return oasnPublicBaseFromEnvId(ambientEnvId);
|
|
73
|
-
return fallbackBase;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Transport 类型 —— v3.9+ 双轨抽象。
|
|
78
|
-
*
|
|
79
|
-
* 默认 'tim' 保留向后兼容(旧 openagent 配置无此字段,按 TIM 路径走)。
|
|
80
|
-
* 新 OASN 部署在配置中显式设置 transport='oasn'。
|
|
81
|
-
*/
|
|
82
|
-
export type TransportType = 'oasn' | 'tim';
|
|
83
|
-
|
|
84
|
-
export interface OpenagentAccountConfig {
|
|
85
|
-
/** Resolved account ID */
|
|
86
|
-
accountId: string;
|
|
87
|
-
/** Display name */
|
|
88
|
-
name: string;
|
|
89
|
-
/** Whether the channel is enabled */
|
|
90
|
-
enabled: boolean;
|
|
91
|
-
/** Whether required credentials (agentId + apiKey) are present */
|
|
92
|
-
configured: boolean;
|
|
93
|
-
/** Agent identity on OpenAgent network */
|
|
94
|
-
agentId: string;
|
|
95
|
-
/** API key for auth verification */
|
|
96
|
-
apiKey: string;
|
|
97
|
-
/** API base URL */
|
|
98
|
-
apiBase: string;
|
|
99
|
-
/** Optional Access-layer API base URL for invocations/files when REL splits services */
|
|
100
|
-
accessApiBase: string;
|
|
101
|
-
/** Claim URL returned by OASN onboarding */
|
|
102
|
-
claimUrl: string;
|
|
103
|
-
/** Current onboarding claim status */
|
|
104
|
-
status: 'unregistered' | 'unclaimed' | 'claim_pending' | 'claimed' | 'credential_expired' | 'unknown';
|
|
105
|
-
/** Registration timestamp stored by the plugin */
|
|
106
|
-
registeredAt: string;
|
|
107
|
-
/**
|
|
108
|
-
* Transport 选型(v3.9+)。
|
|
109
|
-
*
|
|
110
|
-
* - 'oasn': 直接走 OASN HTTP API(Bearer api_key)
|
|
111
|
-
* - 'tim': 走腾讯云 IM(默认,向后兼容)
|
|
112
|
-
*
|
|
113
|
-
* 未在 config 中显式声明时默认 'tim',确保旧版插件配置无需迁移即可工作。
|
|
114
|
-
*/
|
|
115
|
-
transport: TransportType;
|
|
116
|
-
/** Raw merged config object */
|
|
117
|
-
config: Record<string, unknown>;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Extract the OpenAgent-specific config block from the full OpenClaw config.
|
|
122
|
-
* Handles multiple config key locations that have drifted across versions.
|
|
123
|
-
*
|
|
124
|
-
* v3.9+ 兼容:同时支持 `channels.oasn` / `entries.openclaw-oasn` / `entries.openclaw-plugin-oasn`,
|
|
125
|
-
* 与原有 openagent 键名并列查找。优先 oasn → openagent,便于过渡期同时挂双配置。
|
|
126
|
-
*/
|
|
127
|
-
export function getOpenagentConfig(cfg: Record<string, unknown>): Record<string, unknown> {
|
|
128
|
-
if (!cfg) return {};
|
|
129
|
-
const channels = cfg['channels'] as Record<string, unknown> | undefined;
|
|
130
|
-
const plugins = cfg['plugins'] as Record<string, unknown> | undefined;
|
|
131
|
-
const entries = plugins?.['entries'] as Record<string, unknown> | undefined;
|
|
132
|
-
|
|
133
|
-
return (channels?.['oasn'] as Record<string, unknown>)
|
|
134
|
-
|| (channels?.['openagent'] as Record<string, unknown>)
|
|
135
|
-
|| (entries?.['openclaw-oasn'] as Record<string, unknown>)?.['config'] as Record<string, unknown>
|
|
136
|
-
|| (entries?.['openclaw-plugin-oasn'] as Record<string, unknown>)?.['config'] as Record<string, unknown>
|
|
137
|
-
|| (entries?.['openclaw-openagent'] as Record<string, unknown>)?.['config'] as Record<string, unknown>
|
|
138
|
-
|| (entries?.['openclaw-plugin-openagent'] as Record<string, unknown>)?.['config'] as Record<string, unknown>
|
|
139
|
-
|| {};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Resolve a specific account's configuration from OpenClaw config.
|
|
144
|
-
*
|
|
145
|
-
* @param cfg - Full OpenClaw configuration object
|
|
146
|
-
* @param accountId - Target account ID, or 'default' to pick the first available
|
|
147
|
-
*/
|
|
148
|
-
export function resolveOpenagentAccount(
|
|
149
|
-
cfg: Record<string, unknown>,
|
|
150
|
-
accountId?: string,
|
|
151
|
-
): OpenagentAccountConfig {
|
|
152
|
-
const clCfg = getOpenagentConfig(cfg);
|
|
153
|
-
const accounts = (clCfg['accounts'] || {}) as Record<string, Record<string, unknown>>;
|
|
154
|
-
|
|
155
|
-
// Resolve actual account ID
|
|
156
|
-
let actualAccountId = accountId || 'default';
|
|
157
|
-
const keys = Object.keys(accounts);
|
|
158
|
-
if (actualAccountId === 'default') {
|
|
159
|
-
actualAccountId = keys.length > 0 ? keys[0]! : 'default';
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const targetAcc = accounts[actualAccountId] || {};
|
|
163
|
-
|
|
164
|
-
// F1 fallback: support top-level agentId/apiKey in the openagent config block
|
|
165
|
-
const agentId = (targetAcc['agentId'] || targetAcc['agent_id']
|
|
166
|
-
|| clCfg['agentId']
|
|
167
|
-
|| (actualAccountId !== 'default' ? actualAccountId : '')) as string;
|
|
168
|
-
|
|
169
|
-
const apiKey = (targetAcc['api_key'] || targetAcc['apiKey']
|
|
170
|
-
|| clCfg['apiKey']
|
|
171
|
-
|| '') as string;
|
|
172
|
-
|
|
173
|
-
// ── transport 字段(v3.9+ 双轨抽象) ──
|
|
174
|
-
// 解析顺序:账号级 > 顶层 > 默认 'oasn'
|
|
175
|
-
// 同时支持 snake_case 与 camelCase(与项目里其它配置字段一致)。
|
|
176
|
-
const transportRaw = (targetAcc['transport']
|
|
177
|
-
|| clCfg['transport']
|
|
178
|
-
|| 'oasn') as string;
|
|
179
|
-
const transport: TransportType = transportRaw === 'tim' ? 'tim' : 'oasn';
|
|
180
|
-
|
|
181
|
-
// OASN 路径优先使用 OASN 默认 base;TIM 路径维持原 openagent.club 默认
|
|
182
|
-
const fallbackApiBase = transport === 'oasn' ? DEFAULT_OASN_API_BASE : DEFAULT_API_BASE;
|
|
183
|
-
const envApiBase = transport === 'oasn'
|
|
184
|
-
? (process.env.OASN_API_BASE || process.env.OPENAGENT_OASN_API_BASE || '')
|
|
185
|
-
: '';
|
|
186
|
-
const apiBase = transport === 'oasn'
|
|
187
|
-
? resolveOasnBase({
|
|
188
|
-
accountBase: targetAcc['api_base'] || targetAcc['apiBase'],
|
|
189
|
-
channelBase: clCfg['api_base'] || clCfg['apiBase'],
|
|
190
|
-
envBase: envApiBase,
|
|
191
|
-
accountEnvId: targetAcc['oasn_env_id'] || targetAcc['oasnEnvId'] || targetAcc['env_id'] || targetAcc['envId'],
|
|
192
|
-
channelEnvId: clCfg['oasn_env_id'] || clCfg['oasnEnvId'] || clCfg['env_id'] || clCfg['envId'],
|
|
193
|
-
envEnvId: process.env.OASN_ENV_ID || process.env.OPENAGENT_OASN_ENV_ID,
|
|
194
|
-
fallbackBase: fallbackApiBase,
|
|
195
|
-
})
|
|
196
|
-
: (targetAcc['api_base'] || targetAcc['apiBase']
|
|
197
|
-
|| clCfg['api_base']
|
|
198
|
-
|| clCfg['apiBase']
|
|
199
|
-
|| fallbackApiBase) as string;
|
|
200
|
-
const envAccessApiBase = transport === 'oasn'
|
|
201
|
-
? (process.env.OASN_ACCESS_API_BASE || process.env.OPENAGENT_OASN_ACCESS_API_BASE || '')
|
|
202
|
-
: '';
|
|
203
|
-
const accessApiBase = transport === 'oasn'
|
|
204
|
-
? resolveOasnBase({
|
|
205
|
-
accountBase: targetAcc['access_api_base'] || targetAcc['accessApiBase'],
|
|
206
|
-
channelBase: clCfg['access_api_base'] || clCfg['accessApiBase'],
|
|
207
|
-
envBase: envAccessApiBase,
|
|
208
|
-
accountEnvId: targetAcc['oasn_env_id'] || targetAcc['oasnEnvId'] || targetAcc['env_id'] || targetAcc['envId'],
|
|
209
|
-
channelEnvId: clCfg['oasn_env_id'] || clCfg['oasnEnvId'] || clCfg['env_id'] || clCfg['envId'],
|
|
210
|
-
envEnvId: process.env.OASN_ENV_ID || process.env.OPENAGENT_OASN_ENV_ID,
|
|
211
|
-
fallbackBase: apiBase,
|
|
212
|
-
})
|
|
213
|
-
: (targetAcc['access_api_base'] || targetAcc['accessApiBase']
|
|
214
|
-
|| clCfg['access_api_base']
|
|
215
|
-
|| clCfg['accessApiBase']
|
|
216
|
-
|| apiBase) as string;
|
|
217
|
-
const claimUrl = (targetAcc['claim_url'] || targetAcc['claimUrl'] || clCfg['claim_url'] || clCfg['claimUrl'] || '') as string;
|
|
218
|
-
const rawStatus = (targetAcc['status'] || targetAcc['claim_status'] || targetAcc['claimStatus'] || clCfg['status'] || '') as string;
|
|
219
|
-
const normalizedStatus = normalizeClaimStatus(rawStatus, agentId, apiKey);
|
|
220
|
-
const registeredAt = (targetAcc['registered_at'] || targetAcc['registeredAt'] || '') as string;
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
accountId: actualAccountId,
|
|
224
|
-
name: (clCfg['name'] || targetAcc['name'] || 'OpenAgent') as string,
|
|
225
|
-
enabled: clCfg['enabled'] !== false && targetAcc['enabled'] !== false,
|
|
226
|
-
configured: Boolean(agentId && apiKey),
|
|
227
|
-
agentId,
|
|
228
|
-
apiKey,
|
|
229
|
-
apiBase,
|
|
230
|
-
accessApiBase,
|
|
231
|
-
claimUrl,
|
|
232
|
-
status: normalizedStatus,
|
|
233
|
-
registeredAt,
|
|
234
|
-
transport,
|
|
235
|
-
config: { ...clCfg, ...targetAcc },
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function normalizeClaimStatus(
|
|
240
|
-
raw: string,
|
|
241
|
-
agentId: string,
|
|
242
|
-
apiKey: string,
|
|
243
|
-
): OpenagentAccountConfig['status'] {
|
|
244
|
-
switch (raw) {
|
|
245
|
-
case 'unregistered':
|
|
246
|
-
case 'unclaimed':
|
|
247
|
-
case 'claim_pending':
|
|
248
|
-
case 'claimed':
|
|
249
|
-
case 'credential_expired':
|
|
250
|
-
case 'unknown':
|
|
251
|
-
return raw;
|
|
252
|
-
case 'claim_email_sent':
|
|
253
|
-
return 'claim_pending';
|
|
254
|
-
default:
|
|
255
|
-
return agentId || apiKey ? 'unknown' : 'unregistered';
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* List available account IDs from the config.
|
|
261
|
-
*/
|
|
262
|
-
export function listAccountIds(cfg: Record<string, unknown>): string[] {
|
|
263
|
-
const clCfg = getOpenagentConfig(cfg);
|
|
264
|
-
const accounts = clCfg['accounts'] as Record<string, unknown> | undefined;
|
|
265
|
-
return accounts ? Object.keys(accounts) : [];
|
|
266
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth -- Credential lifecycle manager
|
|
3
|
-
*
|
|
4
|
-
* ⚠️ TIM-only 路径(v3.9+ 双轨抽象)
|
|
5
|
-
* ---------------------------------------------------------
|
|
6
|
-
* 仅在 transport='tim' 下被 AccountRuntime 持有。OASN 路径下 api_key 直接
|
|
7
|
-
* 作为 Bearer 透传,无 UserSig 换取过程,AccountRuntime._connectOASN()
|
|
8
|
-
* 显式跳过 CredentialManager 的创建(见 account.ts §Phase 2)。
|
|
9
|
-
*
|
|
10
|
-
* 备注:类名保留为 CredentialManager(而非 TimCredentialManager),是因为
|
|
11
|
-
* 重命名会波及 channel.ts / errors / 文档等多处,价值有限;语义上"TIM-only"
|
|
12
|
-
* 由本模块的引用方收敛。
|
|
13
|
-
*
|
|
14
|
-
* Single source of truth for TIM credentials.
|
|
15
|
-
* Handles caching, expiry detection, refresh, and cooldown.
|
|
16
|
-
*
|
|
17
|
-
* Usage: AccountRuntime holds one instance per agent.
|
|
18
|
-
* Call getCredentials() whenever you need valid TIM credentials --
|
|
19
|
-
* it returns cached ones if still valid, or fetches fresh ones from backend.
|
|
20
|
-
*
|
|
21
|
-
* See docs/repair/002-auth-lifecycle-v3.0.5.md for full design.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { verifyAgent, type TIMCredentials } from './verify.js';
|
|
25
|
-
import { logger } from '../util/logger.js';
|
|
26
|
-
|
|
27
|
-
// ── Constants ──
|
|
28
|
-
|
|
29
|
-
/** Cooldown after a failed attempt (unclaimed / network error) */
|
|
30
|
-
const COOLDOWN_MS = 30_000;
|
|
31
|
-
|
|
32
|
-
/** Refresh credentials 5 minutes before actual expiry */
|
|
33
|
-
const EXPIRE_MARGIN_MS = 5 * 60 * 1000;
|
|
34
|
-
|
|
35
|
-
// ── CredentialError ──
|
|
36
|
-
|
|
37
|
-
export type CredentialErrorReason = 'unclaimed' | 'cooldown' | 'error';
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Thrown by getCredentials() when valid credentials cannot be obtained.
|
|
41
|
-
* Callers use `reason` to decide how to respond to the user.
|
|
42
|
-
*/
|
|
43
|
-
export class CredentialError extends Error {
|
|
44
|
-
constructor(
|
|
45
|
-
public readonly reason: CredentialErrorReason,
|
|
46
|
-
message: string,
|
|
47
|
-
) {
|
|
48
|
-
super(message);
|
|
49
|
-
this.name = 'CredentialError';
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// ── CredentialManager ──
|
|
54
|
-
|
|
55
|
-
export type CredentialStatus = 'idle' | 'unclaimed' | 'valid' | 'expired' | 'error';
|
|
56
|
-
|
|
57
|
-
export class CredentialManager {
|
|
58
|
-
private _credentials: TIMCredentials | null = null;
|
|
59
|
-
private _expiresAt = 0;
|
|
60
|
-
private _cooldownUntil = 0;
|
|
61
|
-
private _status: CredentialStatus = 'idle';
|
|
62
|
-
|
|
63
|
-
constructor(
|
|
64
|
-
private readonly _agentId: string,
|
|
65
|
-
private readonly _apiKey: string,
|
|
66
|
-
) {}
|
|
67
|
-
|
|
68
|
-
// ── Public API ──
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get valid TIM credentials.
|
|
72
|
-
*
|
|
73
|
-
* - Has cached + not expired -> return immediately (zero network cost)
|
|
74
|
-
* - In cooldown -> throw CredentialError('cooldown')
|
|
75
|
-
* - No cache or expired -> call verifyAgent() to fetch fresh credentials
|
|
76
|
-
* - claimed=true -> cache + return
|
|
77
|
-
* - claimed=false -> throw CredentialError('unclaimed')
|
|
78
|
-
* - network error -> throw CredentialError('error')
|
|
79
|
-
*/
|
|
80
|
-
async getCredentials(): Promise<TIMCredentials> {
|
|
81
|
-
// Fast path: valid cache
|
|
82
|
-
if (this._credentials && Date.now() < this._expiresAt) {
|
|
83
|
-
return this._credentials;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Cooldown protection
|
|
87
|
-
const now = Date.now();
|
|
88
|
-
if (now < this._cooldownUntil) {
|
|
89
|
-
const remainSec = Math.ceil((this._cooldownUntil - now) / 1000);
|
|
90
|
-
throw new CredentialError('cooldown', `Credential refresh on cooldown (${remainSec}s remaining)`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Fetch from backend
|
|
94
|
-
try {
|
|
95
|
-
const result = await verifyAgent(this._agentId, this._apiKey);
|
|
96
|
-
|
|
97
|
-
if (!result) {
|
|
98
|
-
// unclaimed: verifyAgent returns null when agent is not claimed
|
|
99
|
-
this._status = 'unclaimed';
|
|
100
|
-
this._cooldownUntil = Date.now() + COOLDOWN_MS;
|
|
101
|
-
throw new CredentialError('unclaimed', `Agent ${this._agentId} is not claimed yet (bind email first)`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Success
|
|
105
|
-
this._credentials = result;
|
|
106
|
-
this._expiresAt = Date.now() + (result.expire * 1000) - EXPIRE_MARGIN_MS;
|
|
107
|
-
this._status = 'valid';
|
|
108
|
-
logger.info(
|
|
109
|
-
`[auth/credential] Credentials obtained for ${this._agentId}, ` +
|
|
110
|
-
`valid until ${new Date(this._expiresAt).toISOString()}`,
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
return this._credentials;
|
|
114
|
-
} catch (err) {
|
|
115
|
-
if (err instanceof CredentialError) throw err;
|
|
116
|
-
// Network / server error
|
|
117
|
-
this._status = 'error';
|
|
118
|
-
this._cooldownUntil = Date.now() + COOLDOWN_MS;
|
|
119
|
-
throw new CredentialError('error', `Credential fetch failed: ${(err as Error).message}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Current credential status (for logging/debugging) */
|
|
124
|
-
get status(): CredentialStatus {
|
|
125
|
-
return this._status;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** Whether cached credentials are still valid */
|
|
129
|
-
get isValid(): boolean {
|
|
130
|
-
return this._status === 'valid' && this._credentials !== null && Date.now() < this._expiresAt;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Force-expire cached credentials.
|
|
135
|
-
*
|
|
136
|
-
* Call this when TIM SDK reports KICKED_OUT with type='userSigExpired'.
|
|
137
|
-
* Do NOT call for network disconnects -- old credentials are still valid.
|
|
138
|
-
* Next getCredentials() call will fetch fresh ones from backend.
|
|
139
|
-
*/
|
|
140
|
-
invalidate(): void {
|
|
141
|
-
this._credentials = null;
|
|
142
|
-
this._expiresAt = 0;
|
|
143
|
-
this._status = 'expired';
|
|
144
|
-
logger.info(`[auth/credential] Credentials invalidated for ${this._agentId}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
package/src/auth/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth — Module barrel export
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
getOpenagentConfig,
|
|
7
|
-
resolveOpenagentAccount,
|
|
8
|
-
listAccountIds,
|
|
9
|
-
type OpenagentAccountConfig,
|
|
10
|
-
} from './config.js';
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
verifyAgent,
|
|
14
|
-
type VerifyResult,
|
|
15
|
-
type TIMCredentials,
|
|
16
|
-
} from './verify.js';
|
|
17
|
-
|
|
18
|
-
export {
|
|
19
|
-
CredentialManager,
|
|
20
|
-
CredentialError,
|
|
21
|
-
type CredentialErrorReason,
|
|
22
|
-
type CredentialStatus,
|
|
23
|
-
} from './credential-manager.js';
|
|
24
|
-
|
package/src/auth/verify.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Auth — Agent verification against OpenAgent auth service
|
|
3
|
-
*
|
|
4
|
-
* ⚠️ TIM-only 路径(v3.9+ 双轨抽象)
|
|
5
|
-
* ---------------------------------------------------------
|
|
6
|
-
* 本模块用 apiKey 换取 TIM SDK 凭证(sdkAppId + userSig),仅在 transport='tim'
|
|
7
|
-
* 下被 CredentialManager 调用。OASN 路径不需要此流程 —— api_key 直接作为
|
|
8
|
-
* Bearer Token,由 OasnTransport 在 ready() 中通过 GET /api/agent-cards/{agent_id}
|
|
9
|
-
* 自校验。
|
|
10
|
-
*
|
|
11
|
-
* Verifies agent identity and retrieves TIM credentials (sdkAppId + userSig).
|
|
12
|
-
* See docs/API_Auth_Proxy.md for the auth service contract.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { httpPost } from '../util/http.js';
|
|
16
|
-
import { logger } from '../util/logger.js';
|
|
17
|
-
|
|
18
|
-
// OPENAGENT_AUTH_BASE env var allows overriding the auth endpoint for local dev.
|
|
19
|
-
// Falls back to the OpenAgent API base if auth.ai-talk.live is not reachable.
|
|
20
|
-
const AUTH_BASE =
|
|
21
|
-
process.env.OPENAGENT_AUTH_BASE ||
|
|
22
|
-
'https://auth.ai-talk.live';
|
|
23
|
-
|
|
24
|
-
export interface VerifyResult {
|
|
25
|
-
/** Whether the agent credentials are valid */
|
|
26
|
-
valid: boolean;
|
|
27
|
-
/** Whether the agent has been claimed (bound to an email) */
|
|
28
|
-
claimed: boolean;
|
|
29
|
-
/** TIM SDK credentials (only present if valid && claimed) */
|
|
30
|
-
tim?: {
|
|
31
|
-
sdkAppId: number;
|
|
32
|
-
userSig: string;
|
|
33
|
-
/** UserSig validity in seconds (e.g. 604800 = 7 days) */
|
|
34
|
-
expire: number;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface TIMCredentials {
|
|
39
|
-
sdkAppId: number;
|
|
40
|
-
userSig: string;
|
|
41
|
-
userId: string;
|
|
42
|
-
/** UserSig validity in seconds (e.g. 604800 = 7 days) */
|
|
43
|
-
expire: number;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Verify agent identity and retrieve TIM credentials.
|
|
48
|
-
*
|
|
49
|
-
* @param agentId - Agent identifier on the OpenAgent network
|
|
50
|
-
* @param apiKey - API key for authentication
|
|
51
|
-
* @returns TIM credentials if agent is claimed, null if unclaimed
|
|
52
|
-
* @throws Error if credentials are invalid or server error
|
|
53
|
-
*/
|
|
54
|
-
export async function verifyAgent(
|
|
55
|
-
agentId: string,
|
|
56
|
-
apiKey: string,
|
|
57
|
-
): Promise<TIMCredentials | null> {
|
|
58
|
-
// ── Dev mode: skip real auth and return mock TIM credentials ──
|
|
59
|
-
// Set OPENAGENT_SKIP_VERIFY=1 to bypass auth.ai-talk.live when offline.
|
|
60
|
-
if (process.env.OPENAGENT_SKIP_VERIFY === '1') {
|
|
61
|
-
logger.warn(`[auth] OPENAGENT_SKIP_VERIFY=1 — using mock TIM credentials for ${agentId}`);
|
|
62
|
-
return {
|
|
63
|
-
sdkAppId: 0,
|
|
64
|
-
userSig: 'dev-mock-usersig',
|
|
65
|
-
userId: agentId,
|
|
66
|
-
expire: 604800,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
logger.info(`[auth] Verifying agent ${agentId} at ${AUTH_BASE}`);
|
|
71
|
-
|
|
72
|
-
const verifyData = await httpPost<VerifyResult>(
|
|
73
|
-
`${AUTH_BASE}/api/auth/verify`,
|
|
74
|
-
{ agent_id: agentId, api_key: apiKey },
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
if (!verifyData.valid) {
|
|
78
|
-
throw new Error('Agent verification failed (Invalid credentials)');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!verifyData.claimed) {
|
|
82
|
-
logger.info(`[auth] Agent ${agentId} is not claimed yet`);
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const tim = verifyData.tim;
|
|
87
|
-
if (!tim?.userSig || !tim?.sdkAppId) {
|
|
88
|
-
throw new Error('Missing TIM credentials in verification response');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
logger.info(`[auth] Verification successful for ${agentId}`);
|
|
92
|
-
|
|
93
|
-
return {
|
|
94
|
-
sdkAppId: tim.sdkAppId,
|
|
95
|
-
userSig: tim.userSig,
|
|
96
|
-
userId: agentId,
|
|
97
|
-
expire: tim.expire ?? 604800,
|
|
98
|
-
};
|
|
99
|
-
}
|