@h-ai/runner 0.0.0-stage → 1.0.0-beta.24

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.
@@ -0,0 +1,409 @@
1
+ import { z } from 'zod';
2
+ import * as _h_ai_core from '@h-ai/core';
3
+ import { HaiResult } from '@h-ai/core';
4
+ import { Writable, Readable } from 'node:stream';
5
+
6
+ declare const resources: z.ZodObject<{
7
+ cpu: z.ZodNumber;
8
+ memoryMiB: z.ZodNumber;
9
+ pids: z.ZodNumber;
10
+ scratchMiB: z.ZodNumber;
11
+ }, z.core.$strict>;
12
+ /**
13
+ * 容器资源限制;CPU 为核心数,内存和临时盘使用 MiB。
14
+ * @example
15
+ * ```ts
16
+ * import type { RunnerResources } from '@h-ai/runner'
17
+ * const resources: RunnerResources = { cpu: 1, memoryMiB: 256, pids: 32, scratchMiB: 64 }
18
+ * ```
19
+ */
20
+ type RunnerResources = z.infer<typeof resources>;
21
+ /**
22
+ * 已登记且固定镜像的执行环境。
23
+ * @example
24
+ * ```ts
25
+ * import type { RunnerEnvironment } from '@h-ai/runner'
26
+ * function resolveImage(environment: RunnerEnvironment) { return environment.image }
27
+ * ```
28
+ */
29
+ type RunnerEnvironment = z.infer<typeof environment>;
30
+ declare const environment: z.ZodObject<{
31
+ id: z.ZodString;
32
+ image: z.ZodString;
33
+ backend: z.ZodDefault<z.ZodLiteral<"container">>;
34
+ architecture: z.ZodOptional<z.ZodEnum<{
35
+ x64: "x64";
36
+ arm64: "arm64";
37
+ }>>;
38
+ capabilities: z.ZodDefault<z.ZodArray<z.ZodString>>;
39
+ resources: z.ZodObject<{
40
+ cpu: z.ZodNumber;
41
+ memoryMiB: z.ZodNumber;
42
+ pids: z.ZodNumber;
43
+ scratchMiB: z.ZodNumber;
44
+ }, z.core.$strict>;
45
+ networkPolicy: z.ZodDefault<z.ZodEnum<{
46
+ offline: "offline";
47
+ internal: "internal";
48
+ }>>;
49
+ network: z.ZodOptional<z.ZodString>;
50
+ }, z.core.$strict>;
51
+ /**
52
+ * Runner 启动配置 Schema。执行节点 ID 在部署中保持唯一。
53
+ * @example
54
+ * ```ts
55
+ * import { RunnerConfigSchema } from '@h-ai/runner'
56
+ * const result = RunnerConfigSchema.safeParse({ nodeId: 'api', executor: false })
57
+ * ```
58
+ */
59
+ declare const RunnerConfigSchema: z.ZodObject<{
60
+ nodeId: z.ZodString;
61
+ executor: z.ZodDefault<z.ZodBoolean>;
62
+ engine: z.ZodDefault<z.ZodEnum<{
63
+ podman: "podman";
64
+ docker: "docker";
65
+ }>>;
66
+ capacity: z.ZodDefault<z.ZodObject<{
67
+ cpu: z.ZodNumber;
68
+ memoryMiB: z.ZodNumber;
69
+ pids: z.ZodNumber;
70
+ scratchMiB: z.ZodNumber;
71
+ }, z.core.$strict>>;
72
+ toolCapacity: z.ZodDefault<z.ZodObject<{
73
+ cpu: z.ZodNumber;
74
+ memoryMiB: z.ZodNumber;
75
+ pids: z.ZodNumber;
76
+ scratchMiB: z.ZodNumber;
77
+ }, z.core.$strict>>;
78
+ toolMaxRunning: z.ZodDefault<z.ZodNumber>;
79
+ leaseMs: z.ZodDefault<z.ZodNumber>;
80
+ pollMs: z.ZodDefault<z.ZodNumber>;
81
+ maxRunning: z.ZodDefault<z.ZodNumber>;
82
+ maxRunningPerScope: z.ZodDefault<z.ZodNumber>;
83
+ maxControlRunning: z.ZodDefault<z.ZodNumber>;
84
+ maxQueued: z.ZodDefault<z.ZodNumber>;
85
+ maxEvents: z.ZodDefault<z.ZodNumber>;
86
+ closeTimeoutMs: z.ZodDefault<z.ZodNumber>;
87
+ environments: z.ZodDefault<z.ZodArray<z.ZodObject<{
88
+ id: z.ZodString;
89
+ image: z.ZodString;
90
+ backend: z.ZodDefault<z.ZodLiteral<"container">>;
91
+ architecture: z.ZodOptional<z.ZodEnum<{
92
+ x64: "x64";
93
+ arm64: "arm64";
94
+ }>>;
95
+ capabilities: z.ZodDefault<z.ZodArray<z.ZodString>>;
96
+ resources: z.ZodObject<{
97
+ cpu: z.ZodNumber;
98
+ memoryMiB: z.ZodNumber;
99
+ pids: z.ZodNumber;
100
+ scratchMiB: z.ZodNumber;
101
+ }, z.core.$strict>;
102
+ networkPolicy: z.ZodDefault<z.ZodEnum<{
103
+ offline: "offline";
104
+ internal: "internal";
105
+ }>>;
106
+ network: z.ZodOptional<z.ZodString>;
107
+ }, z.core.$strict>>>;
108
+ }, z.core.$strict>;
109
+ /**
110
+ * 启动参数;默认执行角色,API 节点可单独关闭执行。
111
+ * @example
112
+ * ```ts
113
+ * import type { RunnerConfigInput } from '@h-ai/runner'
114
+ * const config: RunnerConfigInput = { nodeId: 'api-east', executor: false }
115
+ * ```
116
+ */
117
+ type RunnerConfigInput = z.input<typeof RunnerConfigSchema>;
118
+ /**
119
+ * 持久 JSON 字段的校验,包括有限数值。
120
+ * @example 模块内部上下文
121
+ * ```ts
122
+ * const value = json.safeParse({ message: 'ready' })
123
+ * ```
124
+ */
125
+ declare const json: z.ZodJSONSchema;
126
+ /**
127
+ * 持久提交及主体校验。
128
+ * @example 模块内部上下文
129
+ * ```ts
130
+ * const value = submitSchema.safeParse({ scope: { tenantId: 'work', userId: 'alice' }, kind: 'report', input: null })
131
+ * ```
132
+ */
133
+ declare const submitSchema: z.ZodObject<{
134
+ scope: z.ZodObject<{
135
+ tenantId: z.ZodString;
136
+ userId: z.ZodString;
137
+ }, z.core.$strict>;
138
+ kind: z.ZodString;
139
+ input: z.ZodJSONSchema;
140
+ idempotencyKey: z.ZodOptional<z.ZodString>;
141
+ environmentId: z.ZodOptional<z.ZodString>;
142
+ resources: z.ZodOptional<z.ZodObject<{
143
+ cpu: z.ZodOptional<z.ZodNumber>;
144
+ memoryMiB: z.ZodOptional<z.ZodNumber>;
145
+ pids: z.ZodOptional<z.ZodNumber>;
146
+ scratchMiB: z.ZodOptional<z.ZodNumber>;
147
+ }, z.core.$strict>>;
148
+ nodeId: z.ZodOptional<z.ZodString>;
149
+ parentId: z.ZodOptional<z.ZodString>;
150
+ capacityClass: z.ZodDefault<z.ZodEnum<{
151
+ default: "default";
152
+ tool: "tool";
153
+ }>>;
154
+ warmPool: z.ZodOptional<z.ZodLiteral<true>>;
155
+ concurrency: z.ZodOptional<z.ZodObject<{
156
+ key: z.ZodString;
157
+ limit: z.ZodNumber;
158
+ }, z.core.$strict>>;
159
+ reuseKey: z.ZodOptional<z.ZodString>;
160
+ queueTimeoutMs: z.ZodDefault<z.ZodNumber>;
161
+ runTimeoutMs: z.ZodDefault<z.ZodNumber>;
162
+ }, z.core.$strict>;
163
+
164
+ /**
165
+ * 持久执行错误定义。业务处理失败另记录为执行终态。
166
+ * @example
167
+ * ```ts
168
+ * import { HaiRunnerError } from '@h-ai/runner'
169
+ * const key = HaiRunnerError.CONFLICT
170
+ * ```
171
+ */
172
+ declare const HaiRunnerError: {
173
+ NOT_INITIALIZED: _h_ai_core.HaiErrorDef;
174
+ ALREADY_INITIALIZED: _h_ai_core.HaiErrorDef;
175
+ INVALID: _h_ai_core.HaiErrorDef;
176
+ NOT_FOUND: _h_ai_core.HaiErrorDef;
177
+ CONFLICT: _h_ai_core.HaiErrorDef;
178
+ UNAVAILABLE: _h_ai_core.HaiErrorDef;
179
+ CAPACITY: _h_ai_core.HaiErrorDef;
180
+ LEASE_LOST: _h_ai_core.HaiErrorDef;
181
+ CLEANUP_UNCONFIRMED: _h_ai_core.HaiErrorDef;
182
+ };
183
+ /**
184
+ * 可持久化的输入、事件和输出。
185
+ * @example
186
+ * ```ts
187
+ * import type { RunnerJson } from '@h-ai/runner'
188
+ * const event: RunnerJson = { step: 'ready', parts: [1, 2] }
189
+ * ```
190
+ */
191
+ type RunnerJson = z.infer<typeof json>;
192
+ /**
193
+ * 由可信应用确定的任务主体。
194
+ * @example
195
+ * ```ts
196
+ * import type { RunnerScope } from '@h-ai/runner'
197
+ * const scope: RunnerScope = { tenantId: 'engineering', userId: 'alice' }
198
+ * ```
199
+ */
200
+ type RunnerScope = RunnerSubmit['scope'];
201
+ /**
202
+ * 不含密钥或本机文件路径的持久提交参数。
203
+ * @example
204
+ * ```ts
205
+ * import type { RunnerSubmit } from '@h-ai/runner'
206
+ * const task: RunnerSubmit = { scope: { tenantId: 'team', userId: 'alice' }, kind: 'reports.v1', input: { page: 1 } }
207
+ * ```
208
+ */
209
+ type RunnerSubmit = z.input<typeof submitSchema>;
210
+ /**
211
+ * 当前执行者的启动代次;节点重启后代次会变化。
212
+ * @example
213
+ * ```ts
214
+ * import type { RunnerOwner } from '@h-ai/runner'
215
+ * function node(owner: RunnerOwner) { return owner.nodeId }
216
+ * ```
217
+ */
218
+ interface RunnerOwner {
219
+ nodeId: string;
220
+ generation: string;
221
+ }
222
+ /**
223
+ * 跨实例可读取的执行状态和结果。
224
+ * @example
225
+ * ```ts
226
+ * import type { RunnerExecution } from '@h-ai/runner'
227
+ * function isDone(execution: RunnerExecution) { return execution.status === 'succeeded' }
228
+ * ```
229
+ */
230
+ interface RunnerExecution {
231
+ id: string;
232
+ status: 'queued' | 'running' | 'cancelling' | 'cancelled' | 'succeeded' | 'failed' | 'unknown';
233
+ owner?: RunnerOwner;
234
+ environmentId?: string;
235
+ output?: RunnerJson;
236
+ failure?: 'queue-timeout' | 'run-timeout' | 'handler-failed' | 'owner-lost' | 'parent-ended' | 'cleanup-unconfirmed';
237
+ createdAt: number;
238
+ updatedAt: number;
239
+ /** 运维核验容器和本地暂存已清理的时间;未知业务副作用仍保留。 */
240
+ reconciledAt?: number;
241
+ }
242
+ /**
243
+ * 由可信管理入口取得的核验责任人及工单原因。
244
+ * @example
245
+ * ```ts
246
+ * import type { RunnerReconciliation } from '@h-ai/runner'
247
+ * const review: RunnerReconciliation = { operatorId: 'ops-1', reason: 'INC-47: verified engine cleanup' }
248
+ * ```
249
+ */
250
+ interface RunnerReconciliation {
251
+ operatorId: string;
252
+ reason: string;
253
+ }
254
+ /**
255
+ * 已登记离线固定工具的集群预热目标及容量边界。
256
+ * @example
257
+ * ```ts
258
+ * import type { RunnerWarmPool } from '@h-ai/runner'
259
+ * const pool: RunnerWarmPool = { key: 'docs', kind: 'docs.v1', environmentId: 'docs', minReady: 1, maxRunning: 2, maxTotal: 3 }
260
+ * ```
261
+ */
262
+ interface RunnerWarmPool {
263
+ key: string;
264
+ kind: string;
265
+ environmentId: string;
266
+ minReady: number;
267
+ maxRunning: number;
268
+ maxTotal: number;
269
+ }
270
+ /**
271
+ * 持久事件游标从 1 开始,按执行内递增。
272
+ * @example
273
+ * ```ts
274
+ * import type { RunnerEvent } from '@h-ai/runner'
275
+ * function nextCursor(event: RunnerEvent) { return event.sequence }
276
+ * ```
277
+ */
278
+ interface RunnerEvent {
279
+ sequence: number;
280
+ data: RunnerJson;
281
+ createdAt: number;
282
+ }
283
+ /**
284
+ * 仅限可信已注册处理器调用。工作目录默认 /workspace,配置文件置于 /state。
285
+ * @example
286
+ * ```ts
287
+ * import type { RunnerLaunch } from '@h-ai/runner'
288
+ * const launch: RunnerLaunch = { command: 'cat', args: ['/state/manifest.json'], files: { 'manifest.json': '{}' } }
289
+ * ```
290
+ */
291
+ interface RunnerLaunch {
292
+ command: string;
293
+ args?: string[];
294
+ env?: Record<string, string>;
295
+ files?: Record<string, string>;
296
+ /** 规范 Base64 输入文件;提供空对象时也会分配 /input 与 /output。 */
297
+ inputs?: Record<string, string>;
298
+ cwd?: string;
299
+ }
300
+ /**
301
+ * 容器标准流与经过核验的停止操作。
302
+ * @example
303
+ * ```ts
304
+ * import type { RunnerProcess } from '@h-ai/runner'
305
+ * async function stop(process: RunnerProcess) { return process.close() }
306
+ * ```
307
+ */
308
+ interface RunnerProcess {
309
+ stdin: Writable;
310
+ stdout: Readable;
311
+ stderr: Readable;
312
+ wait: () => Promise<{
313
+ code: number | null;
314
+ signal: NodeJS.Signals | null;
315
+ }>;
316
+ /** 从仍运行的工具容器读取一个受限普通文件,返回规范 Base64。 */
317
+ artifact: (name: string, maxBytes: number) => Promise<HaiResult<string>>;
318
+ close: () => Promise<HaiResult<void>>;
319
+ }
320
+ /**
321
+ * 处理器只在当前租约拥有者内执行,启动和事件都经过持久代次检查。
322
+ * @example
323
+ * ```ts
324
+ * import type { RunnerContext } from '@h-ai/runner'
325
+ * async function accepted(context: RunnerContext) { return context.emit({ id: context.id }) }
326
+ * ```
327
+ */
328
+ interface RunnerContext {
329
+ id: string;
330
+ scope: RunnerScope;
331
+ owner: RunnerOwner;
332
+ parentId?: string;
333
+ signal: AbortSignal;
334
+ emit: (data: RunnerJson) => Promise<HaiResult<void>>;
335
+ start: (launch: RunnerLaunch) => Promise<HaiResult<RunnerProcess>>;
336
+ }
337
+ /**
338
+ * 可信服务器代码注册的处理器;输入需要由业务再次校验。
339
+ * @example
340
+ * ```ts
341
+ * import type { RunnerHandler } from '@h-ai/runner'
342
+ * const handler: RunnerHandler = async (input) => ({ echoed: input })
343
+ * ```
344
+ */
345
+ type RunnerHandler = (input: RunnerJson, context: RunnerContext) => Promise<RunnerJson>;
346
+ /**
347
+ * 注入 ACP 或工具服务的受管执行对象。
348
+ * @example
349
+ * ```ts
350
+ * import type { RunnerFunctions } from '@h-ai/runner'
351
+ * async function ready(instance: RunnerFunctions) { return instance.init({ nodeId: 'east' }) }
352
+ * ```
353
+ */
354
+ interface RunnerFunctions {
355
+ /** 当前实例已启动并承担执行角色。 */
356
+ readonly isExecutor: boolean;
357
+ /** 启动前应先初始化 reldb。 */
358
+ init: (config: RunnerConfigInput) => Promise<HaiResult<void>>;
359
+ /** 停止领取,取消本节点执行并核验清理。 */
360
+ close: () => Promise<HaiResult<void>>;
361
+ /** 当前环境快照。 */
362
+ environment: (id: string) => HaiResult<RunnerEnvironment>;
363
+ /** 注册处理器并返回仅移除该处理器的回调。 */
364
+ register: (kind: string, handler: RunnerHandler) => HaiResult<() => void>;
365
+ /** 在 API 和执行节点登记同一部署快照。只在执行节点创建实例。 */
366
+ registerWarmPool: (pool: RunnerWarmPool) => HaiResult<() => void>;
367
+ /** 持久化接收,在可用节点领取。 */
368
+ submit: (request: RunnerSubmit) => Promise<HaiResult<RunnerExecution>>;
369
+ /** 按业务幂等键定位既有执行。 */
370
+ find: (scope: RunnerScope, kind: string, key: string) => Promise<HaiResult<RunnerExecution | undefined>>;
371
+ /** 根据可信主体读取任务。 */
372
+ get: (scope: RunnerScope, id: string) => Promise<HaiResult<RunnerExecution>>;
373
+ /** 持久记录取消请求。 */
374
+ cancel: (scope: RunnerScope, id: string) => Promise<HaiResult<RunnerExecution>>;
375
+ /** 原执行节点管理入口;核验环境已释放并审计,仍保留未知业务结果。 */
376
+ reconcileUnknown: (scope: RunnerScope, id: string, review: RunnerReconciliation) => Promise<HaiResult<RunnerExecution>>;
377
+ /** 分页读取保序事件。 */
378
+ events: (scope: RunnerScope, id: string, after?: number, limit?: number) => Promise<HaiResult<RunnerEvent[]>>;
379
+ }
380
+
381
+ /**
382
+ * 创建独立 runner,可在同一进程分别承接不同节点角色或用于隔离测试。
383
+ * @example
384
+ * ```ts
385
+ * import { reldb } from '@h-ai/reldb'
386
+ * import { createRunner } from '@h-ai/runner'
387
+ * const database = await reldb.init({ type: 'sqlite', database: ':memory:' })
388
+ * if (!database.success) throw new Error(database.error.message)
389
+ * const runner = createRunner()
390
+ * const initialized = await runner.init({ nodeId: 'tools' })
391
+ * if (!initialized.success) throw new Error(initialized.error.message)
392
+ * await runner.close()
393
+ * await reldb.close()
394
+ * ```
395
+ */
396
+ declare function createRunner(): RunnerFunctions;
397
+ /**
398
+ * 共享执行入口;应用负责初始化数据库、启动并在关闭前等待结果。
399
+ * @example
400
+ * ```ts
401
+ * import { runner } from '@h-ai/runner'
402
+ * const status = await runner.get({ tenantId: 'team', userId: 'alice' }, '0'.repeat(64))
403
+ * if (!status.success) throw new Error(status.error.message)
404
+ * ```
405
+ */
406
+ declare const runner: RunnerFunctions;
407
+
408
+ export { HaiRunnerError, RunnerConfigSchema, createRunner, runner };
409
+ export type { RunnerConfigInput, RunnerContext, RunnerEnvironment, RunnerEvent, RunnerExecution, RunnerFunctions, RunnerHandler, RunnerJson, RunnerLaunch, RunnerOwner, RunnerProcess, RunnerReconciliation, RunnerResources, RunnerScope, RunnerSubmit, RunnerWarmPool };