@h-ai/api-client 0.1.0-alpha.66 → 0.1.0-alpha.68

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.d.ts CHANGED
@@ -11,13 +11,22 @@ import * as zod_v4_core from 'zod/v4/core';
11
11
  import * as zod from 'zod';
12
12
 
13
13
  /**
14
- * API client 标准错误集合(遵循 `@h-ai/core` 错误码规范)。
14
+ * 客户端标准错误集合;包含稳定 code/httpStatus 与构造错误的方法,业务调用先检查 success。
15
+ * 传输失败在 procedure 代理中映射;服务端 HaiResult 的业务错误保持原契约。
15
16
  *
16
17
  * @example
17
18
  * ```ts
18
- * if (!result.success && result.error.code === HaiApiClientError.UNAUTHORIZED.code) {
19
- * redirectToLogin()
19
+ * import { apiClient, HaiApiClientError } from '@h-ai/api-client'
20
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1' })
21
+ * if (!initialized.success) throw new Error(initialized.error.message)
22
+ * try {
23
+ * const result = await apiClient.iam.auth.currentUser()
24
+ * if (!result.success && result.error.code === HaiApiClientError.UNAUTHORIZED.code) {
25
+ * // 由应用切换到登录页面;不输出 Token。
26
+ * const message = result.error.message
27
+ * }
20
28
  * }
29
+ * finally { await apiClient.close() }
21
30
  * ```
22
31
  */
23
32
  declare const HaiApiClientError: {
@@ -33,7 +42,17 @@ declare const HaiApiClientError: {
33
42
  readonly CONFIG_ERROR: _h_ai_core.HaiErrorDef;
34
43
  readonly UNKNOWN: _h_ai_core.HaiErrorDef;
35
44
  };
36
- /** Token 对(与 `@h-ai/iam` 的 TokenPair 对齐)。 */
45
+ /**
46
+ * 短期 access token、可选 refresh token 与有效期;HTTP 头使用 Bearer。
47
+ * Cookie 模式的 refresh token 由服务端管理,不能要求浏览器读取或持久化它。
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * import type { TokenPair } from '@h-ai/api-client'
52
+ * const tokens: TokenPair = { accessToken: 'test-access', expiresIn: 3600, tokenType: 'Bearer' }
53
+ * // 示例为测试凭据;生产 Token 只能来自可信服务端认证响应。
54
+ * ```
55
+ */
37
56
  interface TokenPair {
38
57
  /** 短期访问凭证,请求时作为 `Authorization: Bearer ...`。 */
39
58
  readonly accessToken: string;
@@ -45,30 +64,110 @@ interface TokenPair {
45
64
  readonly tokenType: 'Bearer';
46
65
  }
47
66
  /**
48
- * Token 存储适配器。
67
+ * 异步安全凭据存储契约;null 仅表示无可用凭据,读写故障须拒绝 Promise。
68
+ * 浏览器使用内存 access token/httpOnly refresh Cookie,原生端注入平台安全存储,禁止敏感 Token 放入 localStorage。
69
+ * 已绑定客户端的身份切换通过 client.auth,避免绕过刷新代际与串行写入;部分写入失败须执行清理并报告清理失败。
49
70
  *
50
71
  * 内置实现:
51
72
  * - `apiClient.tokenStorage.httpOnlyCookie()` — **默认**;浏览器端推荐,refresh token 由服务端管理,防 XSS。
52
73
  * - `apiClient.tokenStorage.memory()` — Node.js 测试 / SSR(需显式传入)。
53
- * - `apiClient.tokenStorage.localStorage()` — 浏览器 SPA / PWA(有 XSS 风险,生产不推荐)。
54
74
  *
55
75
  * Capacitor / 小程序场景请由对应模块提供(例如 `@h-ai/capacitor`)。
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * import { apiClient, type TokenStorage } from '@h-ai/api-client'
80
+ * const storage: TokenStorage = apiClient.tokenStorage.memory()
81
+ * await storage.setAccessToken('test-access')
82
+ * const accessToken = await storage.getAccessToken()
83
+ * await storage.clear()
84
+ * ```
56
85
  */
57
86
  interface TokenStorage {
87
+ /**
88
+ * 读取本适配器可用 access token;无凭据返回 null,存储故障拒绝。
89
+ * @returns Token 或 null;不能把读取失败当成不存在。
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { apiClient } from '@h-ai/api-client'
94
+ * const storage = apiClient.tokenStorage.memory()
95
+ * const accessToken = await storage.getAccessToken()
96
+ * ```
97
+ */
58
98
  readonly getAccessToken: () => Promise<string | null>;
99
+ /**
100
+ * 保存 access token;已绑定客户端应通过 auth.setTokens 维护代际。
101
+ * @param token - 可信服务端认证返回的 access token。
102
+ * @returns 写入完成;底层故障须拒绝。
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * import { apiClient } from '@h-ai/api-client'
107
+ * const storage = apiClient.tokenStorage.memory()
108
+ * await storage.setAccessToken('test-access')
109
+ * await storage.clear()
110
+ * ```
111
+ */
59
112
  readonly setAccessToken: (token: string) => Promise<void>;
113
+ /**
114
+ * 读取 refresh token 或 Cookie 模式内部哨兵;null 仅表示没有凭据。
115
+ * @returns Token、模式哨兵或 null,不是对 httpOnly Cookie 内容的脚本读取。
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * import { apiClient } from '@h-ai/api-client'
120
+ * const storage = apiClient.tokenStorage.memory()
121
+ * const refreshToken = await storage.getRefreshToken()
122
+ * // 内存适配器初始为空;Cookie 适配器由管理器识别模式哨兵。
123
+ * ```
124
+ */
60
125
  readonly getRefreshToken: () => Promise<string | null>;
126
+ /**
127
+ * 保存 refresh token;Cookie 实现不通过脚本修改服务端 Cookie。
128
+ * @param token - 服务端返回的刷新凭据;禁止写入 Web Storage。
129
+ * @returns 写入完成;原生安全存储故障须拒绝。
130
+ *
131
+ * @example
132
+ * ```ts
133
+ * import { apiClient } from '@h-ai/api-client'
134
+ * const storage = apiClient.tokenStorage.memory()
135
+ * await storage.setRefreshToken('test-refresh')
136
+ * await storage.clear()
137
+ * ```
138
+ */
61
139
  readonly setRefreshToken: (token: string) => Promise<void>;
140
+ /**
141
+ * 清空适配器可管理的凭据;Cookie 实现只能清内存 access token。
142
+ * @returns 清理完成;失败须拒绝,服务端 Cookie/会话另由退出接口撤销。
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * import { apiClient } from '@h-ai/api-client'
147
+ * const storage = apiClient.tokenStorage.memory()
148
+ * await storage.clear()
149
+ * const remaining = await storage.getAccessToken()
150
+ * ```
151
+ */
62
152
  readonly clear: () => Promise<void>;
63
153
  }
64
- /** Token 自动刷新配置。 */
154
+ /**
155
+ * 启用 Token 注入与自动刷新;默认 Cookie 适配器,refreshPath 相对 baseUrl。
156
+ * 网络/超时/5xx 为暂时失败,保留凭据;明确失效才清理并通知。回调不应抛出或记录 Token。
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * import { apiClient, type AuthConfig } from '@h-ai/api-client'
161
+ * const auth: AuthConfig = { storage: apiClient.tokenStorage.memory(), refreshPath: '/auth/refresh', refreshTimeoutMs: 5000, onTokenRefreshed: tokens => { const lifetime = tokens.expiresIn } }
162
+ * // Node/SSR 选择独立内存存储;浏览器通常直接配置 auth: {}。
163
+ * ```
164
+ */
65
165
  interface AuthConfig {
66
166
  /**
67
167
  * Token 存储适配器;默认 `apiClient.tokenStorage.httpOnlyCookie()`(refresh token 由服务端管理,防 XSS)。
68
168
  *
69
169
  * - SSR / Node.js 测试场景请显式传入 `apiClient.tokenStorage.memory()`。
70
- * - 浏览器 SPA 如确需持久化,可显式传 `apiClient.tokenStorage.localStorage()`,
71
- * 但请先评估 XSS 风险。
170
+ * - 浏览器刷新后通过 httpOnly Cookie 恢复会话,不将 Token 持久化到 Web Storage。
72
171
  * - Capacitor / 小程序请使用对应平台的安全存储适配器(如 `@h-ai/capacitor`)。
73
172
  */
74
173
  readonly storage?: TokenStorage;
@@ -85,7 +184,20 @@ interface AuthConfig {
85
184
  /** 刷新失败回调(如 refresh token 已失效),通常用于跳转登录页。 */
86
185
  readonly onRefreshFailed?: () => void;
87
186
  }
88
- /** API client 初始化配置。 */
187
+ /**
188
+ * 客户端初始化配置;baseUrl 包含 API 前缀,headers/fetch 用于平台适配。
189
+ * auth 缺省时不创建 TokenManager;timeout 是底层请求中断期限,不代表服务端已取消副作用。
190
+ * transport 需要已初始化 crypto,首次业务请求前协商会话;客户端不接收服务端私钥。
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * import { apiClient, type ApiClientConfig } from '@h-ai/api-client'
195
+ * const config: ApiClientConfig = { baseUrl: 'https://api.example.com/api/v1', auth: { storage: apiClient.tokenStorage.memory() }, timeout: 15000, clientName: 'orders-web', headers: () => ({ 'x-app-channel': 'web' }) }
196
+ * const initialized = await apiClient.init(config)
197
+ * if (!initialized.success) throw new Error(initialized.error.message)
198
+ * await apiClient.close()
199
+ * ```
200
+ */
89
201
  interface ApiClientConfig {
90
202
  /** API service 完整 baseUrl,通常含 `apiPrefix`,例如 `https://api.example.com/api/v1`。 */
91
203
  readonly baseUrl: string;
@@ -112,16 +224,38 @@ interface ApiClientConfig {
112
224
  * import { apiClient } from '@h-ai/api-client'
113
225
  * import { crypto } from '@h-ai/crypto'
114
226
  *
115
- * await crypto.init()
116
- * await apiClient.init({
117
- * baseUrl: 'https://api.example.com/api/v1',
118
- * transport: { crypto },
119
- * })
227
+ * const cryptography = await crypto.init()
228
+ * if (!cryptography.success) throw new Error(cryptography.error.message)
229
+ * try {
230
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', transport: { crypto } })
231
+ * if (!initialized.success) throw new Error(initialized.error.message)
232
+ * await apiClient.close()
233
+ * }
234
+ * finally { await crypto.close() }
120
235
  * ```
121
236
  */
122
237
  readonly transport?: ApiClientTransportConfig;
123
238
  }
124
- /** {@link ApiClientConfig.transport} 的配置项。 */
239
+ /**
240
+ * 可选加密会话配置;密钥协商路径相对 baseUrl,并与服务端配置匹配。
241
+ * crypto 必须先初始化;服务器版本公钥通过受保护的 TLS 握手取得,不配置服务端私钥。
242
+ * 传输防重放不能代替业务幂等性,失败后不要自动重放非幂等操作。
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * import { apiClient, type ApiClientTransportConfig } from '@h-ai/api-client'
247
+ * import { crypto } from '@h-ai/crypto'
248
+ * const cryptography = await crypto.init()
249
+ * if (!cryptography.success) throw new Error(cryptography.error.message)
250
+ * try {
251
+ * const transport: ApiClientTransportConfig = { crypto, keyExchangePath: '/_hai/key-exchange' }
252
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', transport })
253
+ * if (!initialized.success) throw new Error(initialized.error.message)
254
+ * await apiClient.close()
255
+ * }
256
+ * finally { await crypto.close() }
257
+ * ```
258
+ */
125
259
  interface ApiClientTransportConfig {
126
260
  /**
127
261
  * crypto 服务实例(通常直接传入 `@h-ai/crypto` 的 `crypto`)。
@@ -135,31 +269,141 @@ interface ApiClientTransportConfig {
135
269
  */
136
270
  readonly keyExchangePath?: string;
137
271
  }
138
- /** Token 辅助操作。 */
272
+ /**
273
+ * 当前客户端的凭据辅助操作;仅 init 启用 auth 时建立实际管理器。
274
+ * setTokens/clear 撤销旧刷新代际并等待串行存储变更;故障拒绝 Promise,调用方处理失败。
275
+ * clear 不能撤销服务端会话或删除 httpOnly Cookie,退出仍需服务端接口成功。
276
+ *
277
+ * @example
278
+ * ```ts
279
+ * import { apiClient, type ApiClientAuth } from '@h-ai/api-client'
280
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
281
+ * if (!initialized.success) throw new Error(initialized.error.message)
282
+ * try {
283
+ * const auth: ApiClientAuth = apiClient.auth
284
+ * const off = auth.onTokenRefreshed(tokens => { const lifetime = tokens.expiresIn })
285
+ * off()
286
+ * await auth.clear()
287
+ * }
288
+ * finally { await apiClient.close() }
289
+ * ```
290
+ */
139
291
  interface ApiClientAuth {
140
- /** 手动写入 Token(例如登录成功后)。 */
292
+ /**
293
+ * 替换整对凭据并同步废弃旧刷新代际;缺省 refreshToken 时清除旧值。
294
+ * @param tokens - 服务端成功认证返回的真实 TokenPair。
295
+ * @returns 写入完成;安全存储失败拒绝 Promise,调用方应清理部分凭据并报告清理失败。
296
+ *
297
+ * @example
298
+ * ```ts
299
+ * import { apiClient } from '@h-ai/api-client'
300
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
301
+ * if (!initialized.success) throw new Error(initialized.error.message)
302
+ * try {
303
+ * const form = { identifier: 'alice', password: 'test-password' }
304
+ * const login = await apiClient.iam.auth.login(form)
305
+ * if (!login.success) throw new Error(login.error.message)
306
+ * try { await apiClient.auth.setTokens(login.data.tokens) }
307
+ * catch (writeError) {
308
+ * try { await apiClient.auth.clear() }
309
+ * catch (cleanupError) { throw new AggregateError([writeError, cleanupError], 'Credential persistence and cleanup failed') }
310
+ * throw writeError
311
+ * }
312
+ * }
313
+ * finally { await apiClient.close() }
314
+ * ```
315
+ */
141
316
  readonly setTokens: (tokens: TokenPair) => Promise<void>;
142
- /** 清空存储的 Token(登出)。 */
317
+ /**
318
+ * 同步废弃旧刷新代际并等待存储清理;失败拒绝 Promise,不声称已持久删除。
319
+ * 服务端会话与 httpOnly Cookie 仍需服务端退出撤销;本操作不能替代退出接口。
320
+ * @returns 本地清理完成,不返回 HaiResult。
321
+ *
322
+ * @example
323
+ * ```ts
324
+ * import { apiClient } from '@h-ai/api-client'
325
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
326
+ * if (!initialized.success) throw new Error(initialized.error.message)
327
+ * try {
328
+ * const logout = await apiClient.iam.auth.logout({})
329
+ * await apiClient.auth.clear()
330
+ * if (!logout.success) throw new Error(logout.error.message)
331
+ * // 只有服务端退出和本地清理都成功,才能确认两侧均已处理。
332
+ * }
333
+ * finally { await apiClient.close() }
334
+ * ```
335
+ */
143
336
  readonly clear: () => Promise<void>;
144
- /** 订阅 Token 刷新成功事件,返回取消订阅函数。 */
337
+ /**
338
+ * 订阅当前管理器刷新成功事件;回调在写入后同步调用,避免抛错或输出 Token。
339
+ * @param callback - 接收 TokenPair 的同步回调。
340
+ * @returns 取消订阅函数;未启用 auth 时返回空操作。
341
+ *
342
+ * @example
343
+ * ```ts
344
+ * import { apiClient } from '@h-ai/api-client'
345
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
346
+ * if (!initialized.success) throw new Error(initialized.error.message)
347
+ * try {
348
+ * const off = apiClient.auth.onTokenRefreshed(tokens => { const expiresIn = tokens.expiresIn })
349
+ * off()
350
+ * }
351
+ * finally { await apiClient.close() }
352
+ * ```
353
+ */
145
354
  readonly onTokenRefreshed: (callback: (tokens: TokenPair) => void) => () => void;
146
355
  }
147
- /** API client 生命周期能力。 */
356
+ /**
357
+ * 客户端生命周期与认证辅助能力;init 的 HaiResult 必须先检查 success。
358
+ * 同一实例并发 init 共享在途初始化,已初始化后再 init 返回 CONFIG_ERROR;切换配置先 close。
359
+ * config 为脱敏快照;close 清理运行状态/加密会话,不等于服务端退出或凭据存储清理。
360
+ *
361
+ * @example
362
+ * ```ts
363
+ * import { apiClient, type ApiClientLifecycle } from '@h-ai/api-client'
364
+ * const client: ApiClientLifecycle = apiClient
365
+ * const initialized = await client.init({ baseUrl: 'https://api.example.com/api/v1' })
366
+ * if (!initialized.success) throw new Error(initialized.error.message)
367
+ * const active = client.isInitialized
368
+ * const snapshot = client.config
369
+ * await client.close()
370
+ * ```
371
+ */
148
372
  interface ApiClientLifecycle {
149
373
  /**
150
- * 初始化 client;必须在调用任何 procedure 前完成。
374
+ * 构造并提交客户端运行状态;初始化失败返回 CONFIG_ERROR,未提交半初始化对象。
375
+ * 并发 init 共享同一初始化;已初始化再调用会失败,切换配置先 close。
376
+ * @param config - baseUrl、认证、fetch 与可选加密配置。
377
+ * @returns HaiResult;必须先判断 success,再发起 procedure。
151
378
  *
152
379
  * @example
153
380
  * ```ts
154
- * await client.init({
155
- * baseUrl: 'https://api.example.com/api/v1',
156
- * auth: { refreshPath: '/auth/refresh' },
157
- * timeout: 15_000,
158
- * })
381
+ * import { apiClient } from '@h-ai/api-client'
382
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
383
+ * if (!initialized.success) throw new Error(initialized.error.message)
384
+ * try {
385
+ * const result = await apiClient.iam.auth.publicConfig()
386
+ * if (!result.success) throw new Error(result.error.message)
387
+ * }
388
+ * finally { await apiClient.close() }
159
389
  * ```
160
390
  */
161
391
  readonly init: (config: ApiClientConfig) => Promise<HaiResult<void>>;
162
- /** 释放资源并允许重新 `init`。 */
392
+ /**
393
+ * 销毁当前加密会话并清除运行状态,允许重新 init;不发送服务端退出、不清空外置存储。
394
+ * @returns 资源清理完成;不是 HaiResult,不应读取 success。
395
+ *
396
+ * @example
397
+ * ```ts
398
+ * import { apiClient } from '@h-ai/api-client'
399
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
400
+ * if (!initialized.success) throw new Error(initialized.error.message)
401
+ * await apiClient.close()
402
+ * const reinitialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
403
+ * if (!reinitialized.success) throw new Error(reinitialized.error.message)
404
+ * await apiClient.close()
405
+ * ```
406
+ */
163
407
  readonly close: () => Promise<void>;
164
408
  /** 当前脱敏后的运行配置快照;未初始化时为 `null`。 */
165
409
  readonly config: ApiClientConfig | null;
@@ -168,15 +412,66 @@ interface ApiClientLifecycle {
168
412
  /** Token 辅助操作。 */
169
413
  readonly auth: ApiClientAuth;
170
414
  }
171
- /** 根据 oRPC contract 推导出的 typed API client(生命周期 + procedure 调用)。 */
415
+ /**
416
+ * 由 oRPC 契约推导的 JSON typed client,与生命周期组合;procedure 的输入/输出由契约决定。
417
+ * 调用先检查初始化和业务 HaiResult;自定义契约不能覆盖 init/close/config/isInitialized/auth 顶层成员。
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * import { apiClient, type ApiClient } from '@h-ai/api-client'
422
+ * import { apiContract } from '@h-ai/api-contract'
423
+ * const contract = apiContract.create({ iam: apiContract.iam })
424
+ * const client: ApiClient<typeof contract> = apiClient.create(contract)
425
+ * const initialized = await client.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
426
+ * if (!initialized.success) throw new Error(initialized.error.message)
427
+ * try {
428
+ * const result = await client.iam.auth.currentUser()
429
+ * if (!result.success) throw new Error(result.error.message)
430
+ * const userId = result.data.id
431
+ * }
432
+ * finally { await client.close() }
433
+ * ```
434
+ */
172
435
  type ApiClient<TContract extends AnyContractRouter> = ApiClientLifecycle & JsonifiedClient<ContractRouterClient<TContract>>;
173
436
 
174
- /** 与认证场景表单对齐的登录输入。 */
437
+ /**
438
+ * 认证表单登录输入;默认 password,ldap 使用 identifier/password,email/sms 使用 identifier/code。
439
+ * method/code 为客户端表单辅助字段,按所选方式映射到标准 IAM procedure。
440
+ *
441
+ * @example
442
+ * ```ts
443
+ * import type { IamAuthLoginInput } from '@h-ai/api-client'
444
+ * const input: IamAuthLoginInput = { identifier: 'alice@example.com', password: '', method: 'email', code: '123456' }
445
+ * ```
446
+ */
175
447
  type IamAuthLoginInput = IamLoginInput & {
176
448
  method?: 'password' | 'ldap' | 'email' | 'sms';
177
449
  code?: string;
178
450
  };
179
- /** 绑定任意包含标准 iam contract 的客户端;成功时自动保存 Token。 */
451
+ /**
452
+ * 将含标准 IAM 契约的客户端绑定为认证表单动作;包用户通过 apiClient.createAuthActions 调用。
453
+ * 登录/注册成功后等待 client.auth.setTokens,失败 HaiResult 原样返回;存储失败拒绝 Promise,不能据服务端成功就显示已登录。
454
+ * 调用方必须先 init 并启用 auth;未启用 auth 时客户端 setTokens 不会建立 Token 管理器。
455
+ * @param client - 具有标准 IAM procedure 与 setTokens 能力的已初始化客户端。
456
+ * @param client.iam - 标准 IAM 契约的领域分组。
457
+ * @param client.iam.auth - 公开配置、登录、注册、验证码和密码重置 procedure。
458
+ * @param client.auth - 认证成功后的凭据写入能力(setTokens)。
459
+ * @returns publicConfig、按方式登录、注册、验证码和密码重置动作。
460
+ *
461
+ * @example
462
+ * ```ts
463
+ * import { apiClient } from '@h-ai/api-client'
464
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
465
+ * if (!initialized.success) throw new Error(initialized.error.message)
466
+ * try {
467
+ * const actions = apiClient.createAuthActions(apiClient)
468
+ * // 运行时凭据来自已验证的表单;此处只请求公开配置,不提交示例密码。
469
+ * const config = await actions.publicConfig()
470
+ * if (!config.success) throw new Error(config.error.message)
471
+ * }
472
+ * finally { await apiClient.close() }
473
+ * ```
474
+ */
180
475
  declare function createIamAuthActions(client: {
181
476
  iam: {
182
477
  auth: Pick<ApiClient<{
@@ -382,17 +677,19 @@ declare function createIamAuthActions(client: {
382
677
  /**
383
678
  * @h-ai/api-client — Token 存储与刷新管理
384
679
  *
385
- * 提供两个内置 Token 存储适配器(localStorage / 内存)和一个 Token 管理器
680
+ * 提供两个内置 Token 存储适配器(httpOnly Cookie / 内存)和一个 Token 管理器
386
681
  * (封装存储读写、自动刷新、并发去重、回调通知)。
387
682
  *
388
683
  * @example 浏览器 SPA
389
684
  * ```ts
390
685
  * import { apiClient } from '@h-ai/api-client'
391
686
  *
392
- * await apiClient.init({
687
+ * const initialized = await apiClient.init({
393
688
  * baseUrl: 'https://api.example.com/api/v1',
394
- * auth: { storage: apiClient.tokenStorage.localStorage() },
689
+ * auth: { storage: apiClient.tokenStorage.httpOnlyCookie() },
395
690
  * })
691
+ * if (!initialized.success) throw new Error(initialized.error.message)
692
+ * await apiClient.close()
396
693
  * ```
397
694
  *
398
695
  * @example Node.js 测试
@@ -400,122 +697,80 @@ declare function createIamAuthActions(client: {
400
697
  * import { apiClient } from '@h-ai/api-client'
401
698
  *
402
699
  * const storage = apiClient.tokenStorage.memory()
403
- * await storage.setAccessToken('abc')
700
+ * await storage.setAccessToken('test-access')
701
+ * await storage.clear()
404
702
  * ```
405
703
  *
406
704
  * @module api-client-auth
407
705
  */
408
706
 
409
707
  /**
410
- * 创建基于 `localStorage` 的 Token 存储(浏览器 SPA / PWA)。
411
- *
412
- * ⚠️ 安全提示(XSS 风险):
413
- * - `localStorage` 对同源脚本可读,任意 XSS 漏洞都可以偷取 Token。
414
- * - 生产环境应优先使用 httpOnly cookie + SameSite 或 BFF 主机代理。
415
- * - 本适配器仅适用于内部工具、Demo、或者已接受 XSS 风险的浏览器场景,
416
- * 并且在调用方明确选择使用。`apiClient.create` 默认不会使用本适配器,
417
- * 需调用方显式传入 `auth.storage = apiClient.tokenStorage.localStorage()`。
418
- *
419
- * @example
420
- * ```ts
421
- * await apiClient.init({
422
- * baseUrl: 'https://api.example.com/api/v1',
423
- * auth: { storage: apiClient.tokenStorage.localStorage() },
424
- * })
425
- * ```
426
- */
427
- declare function createLocalStorageTokenStorage(): TokenStorage;
428
- /**
429
- * 创建内存 Token 存储(Node.js 测试 / SSR / 短生命周期场景)。
430
- * 页面刷新后丢失。
708
+ * 创建仅属于本适配器实例的内存凭据存储,页面刷新或进程结束后丢失。
709
+ * SSR 应为每个请求创建客户端和存储实例,避免不同用户共享默认单例。
710
+ * 通过 client.auth 更新已绑定的存储,才能撤销旧代际刷新;直接存储写入不提供这种保证。
711
+ * @returns 两个初始为空的 Token 槽位及清理操作。
431
712
  *
432
713
  * @example
433
714
  * ```ts
715
+ * import { apiClient } from '@h-ai/api-client'
434
716
  * const storage = apiClient.tokenStorage.memory()
435
- * await storage.setAccessToken('abc')
717
+ * await storage.setAccessToken('test-access')
718
+ * const saved = await storage.getAccessToken()
719
+ * await storage.clear()
720
+ * // saved 为本实例的测试值;不把 Token 写入 Web Storage。
436
721
  * ```
437
722
  */
438
723
  declare function createMemoryTokenStorage(): TokenStorage;
439
724
  /**
440
- * 创建基于 httpOnly cookie 的 Token 存储(生产环境推荐方案)。
441
- *
442
- * **安全模型:**
443
- * - `accessToken` 保存在**内存**中:JS 可读写,用于注入 `Authorization: Bearer`;
444
- * 页面刷新后丢失,由 refresh 流程自动补充。
445
- * - `refreshToken` 保存在服务端设置的 **httpOnly cookie** 中:
446
- * - JS 不可读写,XSS 脚本无法直接盗取。
447
- * - 结合 `SameSite=Strict` 可阻止 CSRF 攻击。
448
- * - 浏览器在每次请求时自动携带,无需客户端显式传递。
449
- *
450
- * **服务端配套要求:**
451
- * 1. 登录端点在响应中设置:
452
- * ```
453
- * Set-Cookie: refresh_token=<token>; HttpOnly; SameSite=Strict; Secure;
454
- * Path=/api/v1/auth/refresh; Max-Age=<seconds>
455
- * ```
456
- * `Path` 限定为 refresh 端点,减少 Cookie 暴露面。
457
- * 2. Refresh 端点从 Cookie 读取 refresh token(忽略请求体中的 `refreshToken` 字段)。
458
- * 3. Logout 端点清除 Cookie:
459
- * ```
460
- * Set-Cookie: refresh_token=; HttpOnly; SameSite=Strict; Secure;
461
- * Path=/api/v1/auth/refresh; Max-Age=0
462
- * ```
463
- *
464
- * **跨域注意事项:**
465
- * 若 API 与前端不同源,服务端还需设置:
466
- * `Access-Control-Allow-Origin: <前端域名>` 和 `Access-Control-Allow-Credentials: true`。
467
- * 调用方不需要做额外配置,`apiClient.create` 会自动识别并设置 `credentials: 'include'`。
725
+ * 创建浏览器使用的内存 access token 与服务端 httpOnly refresh Cookie 适配器。
726
+ * refresh getter 返回内部哨兵,setter 不修改 Cookie;clear 只清除内存 access token。
727
+ * 刷新请求使用 credentials: include;服务端须实际设置/撤销 Cookie,配置适当的 Secure、SameSite、Path 与跨域凭据策略。
728
+ * HttpOnly 限制脚本直接读取 Cookie,不能阻止已执行的恶意脚本代用户发请求;服务端仍须授权和防护 CSRF。
729
+ * @returns 独立内存 access token 与 Cookie 模式标记;不接触 localStorage。
468
730
  *
469
731
  * @example
470
732
  * ```ts
471
- * await apiClient.init({
472
- * baseUrl: 'https://api.example.com/api/v1',
473
- * auth: { storage: apiClient.tokenStorage.httpOnlyCookie() },
474
- * })
733
+ * import { apiClient } from '@h-ai/api-client'
734
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: { storage: apiClient.tokenStorage.httpOnlyCookie() } })
735
+ * if (!initialized.success) throw new Error(initialized.error.message)
736
+ * try {
737
+ * const me = await apiClient.iam.auth.currentUser()
738
+ * if (!me.success) throw new Error(me.error.message)
739
+ * const userId = me.data.id
740
+ * }
741
+ * finally { await apiClient.close() }
475
742
  * ```
476
743
  */
477
744
  declare function createHttpOnlyCookieTokenStorage(): TokenStorage;
478
745
 
479
- /** Token 存储方案集合:内存 / 浏览器 localStorage / httpOnly Cookie。 */
746
+ /** Token 存储方案集合:内存 / httpOnly Cookie。 */
480
747
  declare const tokenStorage: {
481
748
  /** 内存存储——SSR / Node 测试或一次性会话使用。 */
482
749
  readonly memory: typeof createMemoryTokenStorage;
483
- /** 浏览器 `localStorage` 存储——单页应用便捷选项;注意 XSS 风险。 */
484
- readonly localStorage: typeof createLocalStorageTokenStorage;
485
750
  /** httpOnly Cookie 存储——浏览器场景推荐方案。 */
486
751
  readonly httpOnlyCookie: typeof createHttpOnlyCookieTokenStorage;
487
752
  };
488
753
  /**
489
- * 根据 oRPC contract 创建 typed API client。
490
- *
491
- * 返回对象同时具备:
492
- * - **生命周期能力**:`init` / `close` / `config` / `isInitialized` / `auth`
493
- * - **contract procedure**:按 contract 嵌套结构调用,例如 `client.iam.auth.login(input)`
754
+ * 按真实 oRPC 契约创建独立 typed client;公开调用入口为 apiClient.create(contract)。
755
+ * init 返回 HaiResult,成功后才调用 procedure;已初始化实例必须先 close 再换配置。
756
+ * procedure 将传输异常转换为 HaiResult;auth.setTokens/clear 的安全存储失败仍会拒绝 Promise。
757
+ * SSR 应为每个请求创建客户端和内存存储;不共享默认单例中的用户凭据。
758
+ * @param contract - 已定义的嵌套 oRPC contract;顶层命名不能与生命周期成员冲突。
759
+ * @returns 生命周期、认证辅助操作与契约推导出的 procedure 代理。
494
760
  *
495
- * @example 基础用法
761
+ * @example
496
762
  * ```ts
497
763
  * import { apiClient } from '@h-ai/api-client'
498
764
  * import { apiContract } from '@h-ai/api-contract'
499
- *
500
765
  * const client = apiClient.create(apiContract.create({ iam: apiContract.iam }))
501
- * await client.init({ baseUrl: 'https://api.example.com/api/v1' })
502
- *
503
- * const result = await client.iam.auth.login({ identifier: 'alice', password: 'secret' })
504
- * if (result.success) {
505
- * await client.auth.setTokens(result.data.tokens)
766
+ * const initialized = await client.init({ baseUrl: 'https://api.example.com/api/v1', auth: { storage: apiClient.tokenStorage.memory() }, timeout: 10000 })
767
+ * if (!initialized.success) throw new Error(initialized.error.message)
768
+ * try {
769
+ * const result = await client.iam.auth.currentUser()
770
+ * if (!result.success) throw new Error(result.error.message)
771
+ * const userId = result.data.id
506
772
  * }
507
- *
508
- * await client.close()
509
- * ```
510
- *
511
- * @example 自定义 fetch / 超时
512
- * ```ts
513
- * const client = apiClient.create(contract)
514
- * await client.init({
515
- * baseUrl: 'https://api.example.com/api/v1',
516
- * fetch: customFetch,
517
- * timeout: 10_000,
518
- * })
773
+ * finally { await client.close() }
519
774
  * ```
520
775
  */
521
776
  declare function createApiClient<const TContract extends AnyContractRouter>(contract: TContract): ApiClient<TContract>;
@@ -528,12 +783,16 @@ declare function createApiClient<const TContract extends AnyContractRouter>(cont
528
783
  * ```ts
529
784
  * import { apiClient } from '@h-ai/api-client'
530
785
  *
531
- * await apiClient.init({
786
+ * const initialized = await apiClient.init({
532
787
  * baseUrl: 'http://localhost:3000/api/v1',
533
788
  * auth: { refreshPath: '/auth/refresh' },
534
789
  * })
535
- * const result = await apiClient.iam.auth.login({ identifier: 'alice', password: 'secret' })
536
- * await apiClient.close()
790
+ * if (!initialized.success) throw new Error(initialized.error.message)
791
+ * try {
792
+ * const result = await apiClient.iam.auth.currentUser()
793
+ * if (!result.success) throw new Error(result.error.message)
794
+ * }
795
+ * finally { await apiClient.close() }
537
796
  * ```
538
797
  */
539
798
  declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
@@ -699,7 +958,6 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
699
958
  login: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
700
959
  identifier: zod.ZodString;
701
960
  password: zod.ZodString;
702
- rememberMe: zod.ZodOptional<zod.ZodBoolean>;
703
961
  }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
704
962
  success: zod.ZodLiteral<true>;
705
963
  data: zod.ZodObject<{
@@ -1466,7 +1724,7 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1466
1724
  createDownload: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
1467
1725
  key: zod.ZodString;
1468
1726
  expiresIn: zod.ZodOptional<zod.ZodNumber>;
1469
- }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1727
+ }, zod_v4_core.$strict>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1470
1728
  success: zod.ZodLiteral<true>;
1471
1729
  data: zod.ZodObject<{
1472
1730
  url: zod.ZodString;
@@ -1489,9 +1747,8 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1489
1747
  createUpload: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
1490
1748
  key: zod.ZodString;
1491
1749
  contentType: zod.ZodOptional<zod.ZodString>;
1492
- contentLength: zod.ZodOptional<zod.ZodNumber>;
1493
1750
  expiresIn: zod.ZodOptional<zod.ZodNumber>;
1494
- }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1751
+ }, zod_v4_core.$strict>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1495
1752
  success: zod.ZodLiteral<true>;
1496
1753
  data: zod.ZodObject<{
1497
1754
  url: zod.ZodString;
@@ -1593,7 +1850,19 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1593
1850
  keys: zod.ZodArray<zod.ZodString>;
1594
1851
  }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1595
1852
  success: zod.ZodLiteral<true>;
1596
- data: zod.ZodVoid;
1853
+ data: zod.ZodObject<{
1854
+ deletedKeys: zod.ZodArray<zod.ZodString>;
1855
+ failures: zod.ZodArray<zod.ZodObject<{
1856
+ key: zod.ZodString;
1857
+ code: zod.ZodString;
1858
+ retryable: zod.ZodBoolean;
1859
+ outcome: zod.ZodEnum<{
1860
+ unknown: "unknown";
1861
+ failed: "failed";
1862
+ notAttempted: "notAttempted";
1863
+ }>;
1864
+ }, zod_v4_core.$strip>>;
1865
+ }, zod_v4_core.$strip>;
1597
1866
  }, zod_v4_core.$strip>, zod.ZodObject<{
1598
1867
  success: zod.ZodLiteral<false>;
1599
1868
  error: zod.ZodObject<{
@@ -1604,7 +1873,21 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1604
1873
  module: zod.ZodOptional<zod.ZodString>;
1605
1874
  cause: zod.ZodOptional<zod.ZodUnknown>;
1606
1875
  suggestion: zod.ZodOptional<zod.ZodString>;
1607
- ext: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodUnknown>>;
1876
+ ext: zod.ZodOptional<zod.ZodObject<{
1877
+ deleteMany: zod.ZodOptional<zod.ZodObject<{
1878
+ deletedKeys: zod.ZodArray<zod.ZodString>;
1879
+ failures: zod.ZodArray<zod.ZodObject<{
1880
+ key: zod.ZodString;
1881
+ code: zod.ZodString;
1882
+ retryable: zod.ZodBoolean;
1883
+ outcome: zod.ZodEnum<{
1884
+ unknown: "unknown";
1885
+ failed: "failed";
1886
+ notAttempted: "notAttempted";
1887
+ }>;
1888
+ }, zod_v4_core.$strip>>;
1889
+ }, zod_v4_core.$strip>>;
1890
+ }, zod_v4_core.$catchall<zod.ZodUnknown>>>;
1608
1891
  }, zod_v4_core.$strip>;
1609
1892
  }, zod_v4_core.$strip>], "success">, Record<never, never>, Record<never, never>>;
1610
1893
  };
@@ -1612,18 +1895,22 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1612
1895
  readonly ai: {
1613
1896
  chats: {
1614
1897
  createCompletion: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
1898
+ objectId: zod.ZodOptional<zod.ZodString>;
1899
+ sessionId: zod.ZodOptional<zod.ZodString>;
1615
1900
  model: zod.ZodOptional<zod.ZodString>;
1616
- messages: zod.ZodArray<zod.ZodObject<{
1617
- role: zod.ZodEnum<{
1618
- system: "system";
1619
- user: "user";
1620
- assistant: "assistant";
1621
- tool: "tool";
1622
- }>;
1623
- content: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
1901
+ messages: zod.ZodArray<zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1902
+ role: zod.ZodLiteral<"system">;
1903
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
1624
1904
  type: zod.ZodLiteral<"text">;
1625
1905
  text: zod.ZodString;
1626
- }, zod_v4_core.$strip>, zod.ZodObject<{
1906
+ }, zod_v4_core.$strict>>]>;
1907
+ name: zod.ZodOptional<zod.ZodString>;
1908
+ }, zod_v4_core.$strict>, zod.ZodObject<{
1909
+ role: zod.ZodLiteral<"user">;
1910
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
1911
+ type: zod.ZodLiteral<"text">;
1912
+ text: zod.ZodString;
1913
+ }, zod_v4_core.$strict>, zod.ZodObject<{
1627
1914
  type: zod.ZodLiteral<"image_url">;
1628
1915
  image_url: zod.ZodObject<{
1629
1916
  url: zod.ZodString;
@@ -1632,8 +1919,15 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1632
1919
  low: "low";
1633
1920
  high: "high";
1634
1921
  }>>;
1635
- }, zod_v4_core.$strip>;
1636
- }, zod_v4_core.$strip>]>>]>>;
1922
+ }, zod_v4_core.$strict>;
1923
+ }, zod_v4_core.$strict>]>>]>;
1924
+ name: zod.ZodOptional<zod.ZodString>;
1925
+ }, zod_v4_core.$strict>, zod.ZodObject<{
1926
+ role: zod.ZodLiteral<"assistant">;
1927
+ content: zod.ZodOptional<zod.ZodNullable<zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
1928
+ type: zod.ZodLiteral<"text">;
1929
+ text: zod.ZodString;
1930
+ }, zod_v4_core.$strict>>]>>>;
1637
1931
  name: zod.ZodOptional<zod.ZodString>;
1638
1932
  tool_calls: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
1639
1933
  id: zod.ZodString;
@@ -1641,37 +1935,35 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1641
1935
  function: zod.ZodObject<{
1642
1936
  name: zod.ZodString;
1643
1937
  arguments: zod.ZodString;
1644
- }, zod_v4_core.$strip>;
1645
- }, zod_v4_core.$strip>>>;
1646
- tool_call_id: zod.ZodOptional<zod.ZodString>;
1647
- }, zod_v4_core.$strip>>;
1938
+ }, zod_v4_core.$strict>;
1939
+ }, zod_v4_core.$strict>>>;
1940
+ }, zod_v4_core.$strict>, zod.ZodObject<{
1941
+ role: zod.ZodLiteral<"tool">;
1942
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
1943
+ type: zod.ZodLiteral<"text">;
1944
+ text: zod.ZodString;
1945
+ }, zod_v4_core.$strict>>]>;
1946
+ tool_call_id: zod.ZodString;
1947
+ }, zod_v4_core.$strict>], "role">>;
1648
1948
  temperature: zod.ZodOptional<zod.ZodNumber>;
1649
1949
  top_p: zod.ZodOptional<zod.ZodNumber>;
1650
1950
  max_tokens: zod.ZodOptional<zod.ZodNumber>;
1651
- stream: zod.ZodOptional<zod.ZodBoolean>;
1652
1951
  tools: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
1653
1952
  type: zod.ZodLiteral<"function">;
1654
1953
  function: zod.ZodObject<{
1655
1954
  name: zod.ZodString;
1656
1955
  description: zod.ZodOptional<zod.ZodString>;
1657
- parameters: zod.ZodOptional<zod.ZodObject<{
1658
- type: zod.ZodLiteral<"object">;
1659
- properties: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodObject<{
1660
- type: zod.ZodString;
1661
- description: zod.ZodOptional<zod.ZodString>;
1662
- enum: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
1663
- }, zod_v4_core.$strip>>>;
1664
- required: zod.ZodOptional<zod.ZodArray<zod.ZodString>>;
1665
- }, zod_v4_core.$strip>>;
1666
- }, zod_v4_core.$strip>;
1667
- }, zod_v4_core.$strip>>>;
1668
- tool_choice: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<"auto">, zod.ZodLiteral<"none">, zod.ZodObject<{
1956
+ parameters: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodJSONSchema>>;
1957
+ strict: zod.ZodOptional<zod.ZodNullable<zod.ZodBoolean>>;
1958
+ }, zod_v4_core.$strict>;
1959
+ }, zod_v4_core.$strict>>>;
1960
+ tool_choice: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodLiteral<"auto">, zod.ZodLiteral<"none">, zod.ZodLiteral<"required">, zod.ZodObject<{
1669
1961
  type: zod.ZodLiteral<"function">;
1670
1962
  function: zod.ZodObject<{
1671
1963
  name: zod.ZodString;
1672
- }, zod_v4_core.$strip>;
1673
- }, zod_v4_core.$strip>]>>;
1674
- }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1964
+ }, zod_v4_core.$strict>;
1965
+ }, zod_v4_core.$strict>]>>;
1966
+ }, zod_v4_core.$strict>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1675
1967
  success: zod.ZodLiteral<true>;
1676
1968
  data: zod.ZodObject<{
1677
1969
  id: zod.ZodString;
@@ -1689,8 +1981,8 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1689
1981
  function: zod.ZodObject<{
1690
1982
  name: zod.ZodString;
1691
1983
  arguments: zod.ZodString;
1692
- }, zod_v4_core.$strip>;
1693
- }, zod_v4_core.$strip>>>;
1984
+ }, zod_v4_core.$strict>;
1985
+ }, zod_v4_core.$strict>>>;
1694
1986
  }, zod_v4_core.$strip>;
1695
1987
  finish_reason: zod.ZodEnum<{
1696
1988
  length: "length";
@@ -1719,6 +2011,8 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1719
2011
  }, zod_v4_core.$strip>;
1720
2012
  }, zod_v4_core.$strip>], "success">, Record<never, never>, Record<never, never>>;
1721
2013
  sendMessage: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
2014
+ objectId: zod.ZodOptional<zod.ZodString>;
2015
+ sessionId: zod.ZodOptional<zod.ZodString>;
1722
2016
  message: zod.ZodString;
1723
2017
  systemPrompt: zod.ZodOptional<zod.ZodString>;
1724
2018
  model: zod.ZodOptional<zod.ZodString>;
@@ -1748,7 +2042,7 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1748
2042
  }, zod_v4_core.$strip>;
1749
2043
  }, zod_v4_core.$strip>], "success">, Record<never, never>, Record<never, never>>;
1750
2044
  listHistory: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
1751
- objectId: zod.ZodString;
2045
+ objectId: zod.ZodOptional<zod.ZodString>;
1752
2046
  sessionId: zod.ZodString;
1753
2047
  limit: zod.ZodOptional<zod.ZodNumber>;
1754
2048
  order: zod.ZodOptional<zod.ZodEnum<{
@@ -1764,17 +2058,19 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1764
2058
  sessionId: zod.ZodString;
1765
2059
  request: zod.ZodObject<{
1766
2060
  model: zod.ZodString;
1767
- messages: zod.ZodArray<zod.ZodObject<{
1768
- role: zod.ZodEnum<{
1769
- system: "system";
1770
- user: "user";
1771
- assistant: "assistant";
1772
- tool: "tool";
1773
- }>;
1774
- content: zod.ZodOptional<zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
2061
+ messages: zod.ZodArray<zod.ZodDiscriminatedUnion<[zod.ZodObject<{
2062
+ role: zod.ZodLiteral<"system">;
2063
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
1775
2064
  type: zod.ZodLiteral<"text">;
1776
2065
  text: zod.ZodString;
1777
- }, zod_v4_core.$strip>, zod.ZodObject<{
2066
+ }, zod_v4_core.$strict>>]>;
2067
+ name: zod.ZodOptional<zod.ZodString>;
2068
+ }, zod_v4_core.$strict>, zod.ZodObject<{
2069
+ role: zod.ZodLiteral<"user">;
2070
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodUnion<readonly [zod.ZodObject<{
2071
+ type: zod.ZodLiteral<"text">;
2072
+ text: zod.ZodString;
2073
+ }, zod_v4_core.$strict>, zod.ZodObject<{
1778
2074
  type: zod.ZodLiteral<"image_url">;
1779
2075
  image_url: zod.ZodObject<{
1780
2076
  url: zod.ZodString;
@@ -1783,8 +2079,15 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1783
2079
  low: "low";
1784
2080
  high: "high";
1785
2081
  }>>;
1786
- }, zod_v4_core.$strip>;
1787
- }, zod_v4_core.$strip>]>>]>>;
2082
+ }, zod_v4_core.$strict>;
2083
+ }, zod_v4_core.$strict>]>>]>;
2084
+ name: zod.ZodOptional<zod.ZodString>;
2085
+ }, zod_v4_core.$strict>, zod.ZodObject<{
2086
+ role: zod.ZodLiteral<"assistant">;
2087
+ content: zod.ZodOptional<zod.ZodNullable<zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
2088
+ type: zod.ZodLiteral<"text">;
2089
+ text: zod.ZodString;
2090
+ }, zod_v4_core.$strict>>]>>>;
1788
2091
  name: zod.ZodOptional<zod.ZodString>;
1789
2092
  tool_calls: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
1790
2093
  id: zod.ZodString;
@@ -1792,10 +2095,16 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1792
2095
  function: zod.ZodObject<{
1793
2096
  name: zod.ZodString;
1794
2097
  arguments: zod.ZodString;
1795
- }, zod_v4_core.$strip>;
1796
- }, zod_v4_core.$strip>>>;
1797
- tool_call_id: zod.ZodOptional<zod.ZodString>;
1798
- }, zod_v4_core.$strip>>;
2098
+ }, zod_v4_core.$strict>;
2099
+ }, zod_v4_core.$strict>>>;
2100
+ }, zod_v4_core.$strict>, zod.ZodObject<{
2101
+ role: zod.ZodLiteral<"tool">;
2102
+ content: zod.ZodUnion<readonly [zod.ZodString, zod.ZodArray<zod.ZodObject<{
2103
+ type: zod.ZodLiteral<"text">;
2104
+ text: zod.ZodString;
2105
+ }, zod_v4_core.$strict>>]>;
2106
+ tool_call_id: zod.ZodString;
2107
+ }, zod_v4_core.$strict>], "role">>;
1799
2108
  }, zod_v4_core.$strip>;
1800
2109
  response: zod.ZodObject<{
1801
2110
  content: zod.ZodString;
@@ -1805,8 +2114,8 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1805
2114
  function: zod.ZodObject<{
1806
2115
  name: zod.ZodString;
1807
2116
  arguments: zod.ZodString;
1808
- }, zod_v4_core.$strip>;
1809
- }, zod_v4_core.$strip>>>;
2117
+ }, zod_v4_core.$strict>;
2118
+ }, zod_v4_core.$strict>>>;
1810
2119
  finishReason: zod.ZodString;
1811
2120
  usage: zod.ZodObject<{
1812
2121
  prompt_tokens: zod.ZodNumber;
@@ -1928,7 +2237,7 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1928
2237
  };
1929
2238
  sessions: {
1930
2239
  list: _orpc_contract.ContractProcedureBuilderWithInputOutput<zod.ZodObject<{
1931
- objectId: zod.ZodString;
2240
+ objectId: zod.ZodOptional<zod.ZodString>;
1932
2241
  }, zod_v4_core.$strip>, zod.ZodDiscriminatedUnion<[zod.ZodObject<{
1933
2242
  success: zod.ZodLiteral<true>;
1934
2243
  data: zod.ZodObject<{
@@ -1956,13 +2265,43 @@ declare const defaultApiContract: _h_ai_api_contract.CreatedApiContract<{
1956
2265
  };
1957
2266
  };
1958
2267
  }>;
1959
- /** `apiClient` 默认单例 + 工厂命名空间的统一对外类型。 */
2268
+ /**
2269
+ * 默认 iam/storage/ai typed client 与 create、tokenStorage、createAuthActions 命名空间的交叉类型。
2270
+ * 具体项目契约使用 apiClient.create 的返回类型,不给默认单例附加未知 procedure。
2271
+ *
2272
+ * @example
2273
+ * ```ts
2274
+ * import { apiClient, type DefaultApiClient } from '@h-ai/api-client'
2275
+ * const client: DefaultApiClient = apiClient
2276
+ * const initialized = await client.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
2277
+ * if (!initialized.success) throw new Error(initialized.error.message)
2278
+ * try { const actions = client.createAuthActions(client); const result = await actions.publicConfig(); if (!result.success) throw new Error(result.error.message) }
2279
+ * finally { await client.close() }
2280
+ * ```
2281
+ */
1960
2282
  type DefaultApiClient = ApiClient<typeof defaultApiContract> & {
1961
2283
  readonly create: typeof createApiClient;
1962
2284
  readonly tokenStorage: typeof tokenStorage;
1963
2285
  readonly createAuthActions: typeof createIamAuthActions;
1964
2286
  };
1965
- /** hai-framework API client 统一入口(默认单例 + `create` + `tokenStorage`)。 */
2287
+ /**
2288
+ * API Client 公开入口:默认 iam/storage/ai 单例,以及独立实例、安全存储和认证动作工厂。
2289
+ * 未启用 auth 时不注入或刷新 Token;浏览器 auth: {} 使用 httpOnly Cookie 方案。
2290
+ * close 释放客户端运行状态/加密会话,不能替代服务端退出或 auth.clear。
2291
+ *
2292
+ * @example
2293
+ * ```ts
2294
+ * import { apiClient } from '@h-ai/api-client'
2295
+ * const initialized = await apiClient.init({ baseUrl: 'https://api.example.com/api/v1', auth: {} })
2296
+ * if (!initialized.success) throw new Error(initialized.error.message)
2297
+ * try {
2298
+ * const result = await apiClient.iam.auth.currentUser()
2299
+ * if (!result.success) throw new Error(result.error.message)
2300
+ * const permissions = result.data.permissions
2301
+ * }
2302
+ * finally { await apiClient.close() }
2303
+ * ```
2304
+ */
1966
2305
  declare const apiClient: DefaultApiClient;
1967
2306
 
1968
2307
  export { type ApiClient, type ApiClientAuth, type ApiClientConfig, type ApiClientLifecycle, type ApiClientTransportConfig, type AuthConfig, type DefaultApiClient, HaiApiClientError, type IamAuthLoginInput, type TokenPair, type TokenStorage, apiClient };