@fitlab-ai/agent-infra 0.11.13 → 0.11.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/bin/internal-cli.js +2 -7
- package/dist/lib/agent-clients/adapter.js +0 -3
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +5 -9
- package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +1 -5
- package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +1 -5
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +1 -3
- package/dist/lib/agent-clients/adapters/codex.js +0 -2
- package/dist/lib/internal/cli-route-inventory.js +0 -1
- package/dist/lib/internal/task-finalization.js +6 -4
- package/dist/lib/internal/task-lifecycle.js +3 -1
- package/dist/lib/internal/task-operation-registry.js +1 -3
- package/dist/lib/internal/task-validate.js +14 -124
- package/dist/lib/platform/release-notes.js +2 -2
- package/dist/lib/sandbox/commands/control-status.js +0 -1
- package/dist/lib/sandbox/commands/create.js +5 -4
- package/dist/lib/sandbox/config.js +12 -0
- package/dist/lib/sandbox/control/audit.js +1 -2
- package/dist/lib/sandbox/control/client.js +12 -47
- package/dist/lib/sandbox/control/executor.js +6 -10
- package/dist/lib/sandbox/control/host-recovery.js +89 -27
- package/dist/lib/sandbox/control/lifecycle.js +20 -16
- package/dist/lib/sandbox/control/protocol.js +8 -36
- package/dist/lib/sandbox/control/server.js +2 -21
- package/dist/lib/sandbox/environment.js +7 -8
- package/dist/lib/sandbox/mounts.js +71 -59
- package/dist/lib/sandbox/recovery.js +2 -3
- package/dist/lib/sandbox/removal.js +19 -4
- package/dist/lib/sandbox/workspace-view.js +41 -4
- package/dist/lib/task/control-authority.js +39 -17
- package/dist/lib/task/control-recovery.js +1 -2
- package/dist/lib/task/finalization.js +13 -2
- package/dist/lib/task/lifecycle.js +92 -33
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapter.ts +0 -27
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +6 -12
- package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +1 -5
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -7
- package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +1 -5
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +1 -4
- package/lib/agent-clients/adapters/codex-orchestration.ts +1 -3
- package/lib/agent-clients/adapters/codex.ts +0 -2
- package/lib/internal/cli-route-inventory.ts +0 -1
- package/lib/internal/task-finalization.ts +6 -4
- package/lib/internal/task-lifecycle.ts +3 -1
- package/lib/internal/task-operation-registry.ts +1 -3
- package/lib/internal/task-validate.ts +13 -127
- package/lib/platform/release-notes.ts +2 -2
- package/lib/sandbox/commands/control-status.ts +0 -1
- package/lib/sandbox/commands/create.ts +5 -4
- package/lib/sandbox/config.ts +13 -0
- package/lib/sandbox/control/audit.ts +1 -2
- package/lib/sandbox/control/client.ts +13 -61
- package/lib/sandbox/control/executor.ts +7 -13
- package/lib/sandbox/control/host-recovery.ts +94 -21
- package/lib/sandbox/control/lifecycle.ts +18 -16
- package/lib/sandbox/control/protocol.ts +9 -45
- package/lib/sandbox/control/server.ts +2 -17
- package/lib/sandbox/environment.ts +7 -8
- package/lib/sandbox/mounts.ts +92 -75
- package/lib/sandbox/recovery.ts +2 -3
- package/lib/sandbox/removal.ts +16 -4
- package/lib/sandbox/workspace-view.ts +40 -5
- package/lib/task/control-authority.ts +40 -26
- package/lib/task/control-recovery.ts +2 -3
- package/lib/task/finalization.ts +15 -2
- package/lib/task/lifecycle.ts +103 -31
- package/package.json +1 -1
- package/templates/.agents/rules/lifecycle-orchestration.en.md +3 -4
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +3 -4
- package/templates/.agents/rules/task-short-id.en.md +18 -12
- package/templates/.agents/rules/task-short-id.zh-CN.md +12 -7
- package/templates/.agents/skills/create-release-note/SKILL.en.md +3 -1
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +3 -1
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-client.js +0 -130
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +0 -127
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-operation.js +0 -131
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-registration.js +0 -275
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.js +0 -106
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +0 -345
- package/dist/lib/sandbox/control/agent-operation.js +0 -34
- package/lib/agent-clients/adapters/codex-lifecycle/controller-client.ts +0 -158
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +0 -163
- package/lib/agent-clients/adapters/codex-lifecycle/controller-operation.ts +0 -151
- package/lib/agent-clients/adapters/codex-lifecycle/controller-registration.ts +0 -352
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.ts +0 -109
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +0 -437
- package/lib/sandbox/control/agent-operation.ts +0 -49
package/lib/task/lifecycle.ts
CHANGED
|
@@ -106,6 +106,8 @@ type LifecycleFileSystem = {
|
|
|
106
106
|
};
|
|
107
107
|
type TaskLifecycleOptions = {
|
|
108
108
|
repoRoot?: string;
|
|
109
|
+
controlRoot?: string;
|
|
110
|
+
controlProject?: string;
|
|
109
111
|
metadataProvider?: () => TaskWriteMetadata;
|
|
110
112
|
fileSystem?: Partial<LifecycleFileSystem>;
|
|
111
113
|
taskFileSystem?: Partial<TaskFileSystem>;
|
|
@@ -276,6 +278,105 @@ function transferTaskContents(sourcePath: string, targetPath: string): void {
|
|
|
276
278
|
}
|
|
277
279
|
}
|
|
278
280
|
|
|
281
|
+
function pathExists(candidate: string): boolean {
|
|
282
|
+
try { fs.lstatSync(candidate); return true; }
|
|
283
|
+
catch (error) {
|
|
284
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false;
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function assertTaskControlRootPath(controlRoot: string, taskId: string, expectedProject?: string): void {
|
|
290
|
+
if (path.basename(controlRoot) !== taskId || path.basename(path.dirname(controlRoot)) !== 'tasks'
|
|
291
|
+
|| (expectedProject !== undefined && path.basename(path.dirname(path.dirname(controlRoot))) !== expectedProject)) {
|
|
292
|
+
throw new Error('control root path does not match the task/project layout');
|
|
293
|
+
}
|
|
294
|
+
const managedBase = path.dirname(path.dirname(path.dirname(controlRoot)));
|
|
295
|
+
let current = managedBase;
|
|
296
|
+
for (const segment of path.relative(managedBase, controlRoot).split(path.sep).filter(Boolean)) {
|
|
297
|
+
const stat = fs.lstatSync(current);
|
|
298
|
+
if (stat.isSymbolicLink()) throw new Error('control root ancestor is a symbolic link');
|
|
299
|
+
current = path.join(current, segment);
|
|
300
|
+
}
|
|
301
|
+
const stat = fs.lstatSync(controlRoot);
|
|
302
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error('control root is not a real directory');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function assertTaskControlManifestIdentity(controlRoot: string, taskId: string, repoRoot: string, expectedProject?: string): void {
|
|
306
|
+
const controlManifest = path.join(controlRoot, 'manifest.json');
|
|
307
|
+
if (!fs.existsSync(controlManifest)) throw new Error('control manifest is missing');
|
|
308
|
+
const manifestStat = fs.lstatSync(controlManifest);
|
|
309
|
+
if (!manifestStat.isFile() || manifestStat.isSymbolicLink()) throw new Error('control manifest is not a real file');
|
|
310
|
+
const manifest = JSON.parse(fs.readFileSync(controlManifest, 'utf8')) as {
|
|
311
|
+
mode?: unknown; taskId?: unknown; project?: unknown; repoRoot?: unknown;
|
|
312
|
+
};
|
|
313
|
+
const project = expectedProject ?? path.basename(path.dirname(path.dirname(controlRoot)));
|
|
314
|
+
if (manifest.mode !== 'task-bound' || manifest.taskId !== taskId || manifest.project !== project
|
|
315
|
+
|| typeof manifest.repoRoot !== 'string' || fs.realpathSync.native(manifest.repoRoot) !== fs.realpathSync.native(repoRoot)) {
|
|
316
|
+
throw new Error('control manifest identity does not match the task');
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function taskBoundControlMoveSafety(
|
|
321
|
+
request: TaskLifecycleRequest,
|
|
322
|
+
controlRoot: string | undefined,
|
|
323
|
+
options: TaskLifecycleOptions,
|
|
324
|
+
taskId: string,
|
|
325
|
+
repoRoot: string,
|
|
326
|
+
validateManifestIdentity: boolean
|
|
327
|
+
): LifecycleError | null {
|
|
328
|
+
if (!controlRoot) return null;
|
|
329
|
+
const controlManifest = path.join(controlRoot, 'manifest.json');
|
|
330
|
+
const controlLease = path.join(controlRoot, 'lease.json');
|
|
331
|
+
const stateExists = pathExists(controlRoot) || pathExists(controlManifest) || pathExists(controlLease);
|
|
332
|
+
if (stateExists) {
|
|
333
|
+
try {
|
|
334
|
+
assertTaskControlRootPath(controlRoot, taskId, options.controlProject);
|
|
335
|
+
if (validateManifestIdentity) {
|
|
336
|
+
assertTaskControlManifestIdentity(controlRoot, taskId, repoRoot, options.controlProject);
|
|
337
|
+
} else {
|
|
338
|
+
const manifestStat = fs.lstatSync(controlManifest);
|
|
339
|
+
if (!manifestStat.isFile() || manifestStat.isSymbolicLink()) throw new Error('control manifest is not a real file');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task-bound sandbox control root is missing, malformed, or belongs to another task' };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (request.intent !== 'complete' && (pathExists(controlManifest) || pathExists(controlLease))) {
|
|
347
|
+
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task-bound sandbox control state exists; stop and remove the verified sandbox before moving the task directory' };
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function orchestrationMoveSafety(sourcePath: string): LifecycleError | null {
|
|
353
|
+
const orchestrationPath = path.join(sourcePath, '.runtime', 'orchestration.json');
|
|
354
|
+
if (!pathExists(orchestrationPath)) return null;
|
|
355
|
+
try {
|
|
356
|
+
const run = JSON.parse(fs.readFileSync(orchestrationPath, 'utf8')) as { status?: unknown; pendingDelegation?: unknown };
|
|
357
|
+
if (run.status === 'running' || run.pendingDelegation !== null && run.pendingDelegation !== undefined) {
|
|
358
|
+
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration has an active or pending delegation; settle it before moving the task directory' };
|
|
359
|
+
}
|
|
360
|
+
} catch {
|
|
361
|
+
return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration state is unreadable; refusing to move the task directory' };
|
|
362
|
+
}
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function runtimeMoveSafety(
|
|
367
|
+
request: TaskLifecycleRequest,
|
|
368
|
+
movingTaskDirectory: boolean,
|
|
369
|
+
options: TaskLifecycleOptions,
|
|
370
|
+
taskId: string,
|
|
371
|
+
repoRoot: string,
|
|
372
|
+
sourcePath: string,
|
|
373
|
+
validateControlManifestIdentity: boolean
|
|
374
|
+
): LifecycleError | null {
|
|
375
|
+
if (!movingTaskDirectory) return null;
|
|
376
|
+
const controlSafety = taskBoundControlMoveSafety(request, options.controlRoot, options, taskId, repoRoot, validateControlManifestIdentity);
|
|
377
|
+
return controlSafety ?? orchestrationMoveSafety(sourcePath);
|
|
378
|
+
}
|
|
379
|
+
|
|
279
380
|
function targetContainsTask(targetPath: string, taskId: string, request: TaskLifecycleRequest): boolean {
|
|
280
381
|
try {
|
|
281
382
|
const stat = fs.lstatSync(targetPath);
|
|
@@ -554,35 +655,6 @@ function applyTaskLifecycleUnlocked(requestInput: TaskLifecycleRequest, options:
|
|
|
554
655
|
const targetPath = path.join(repoRoot, '.agents', 'workspace', spec.target, taskId);
|
|
555
656
|
const requiredSteps = stepsForIntent(request.intent);
|
|
556
657
|
const movingTaskDirectory = sourcePath !== targetPath;
|
|
557
|
-
const assertRuntimeMoveSafe = (): LifecycleError | null => {
|
|
558
|
-
if (!movingTaskDirectory) return null;
|
|
559
|
-
const controlManifest = path.join(sourcePath, '.runtime', 'sandbox-control', 'manifest.json');
|
|
560
|
-
const controlLease = path.join(sourcePath, '.runtime', 'sandbox-control', 'lease.json');
|
|
561
|
-
if (request.intent !== 'complete' && (fs.existsSync(controlManifest) || fs.existsSync(controlLease))) {
|
|
562
|
-
return {
|
|
563
|
-
code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE',
|
|
564
|
-
message: 'task-bound sandbox control state exists; stop and remove the verified sandbox before moving the task directory'
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
const orchestrationPath = path.join(sourcePath, '.runtime', 'orchestration.json');
|
|
568
|
-
if (fs.existsSync(orchestrationPath)) {
|
|
569
|
-
try {
|
|
570
|
-
const run = JSON.parse(fs.readFileSync(orchestrationPath, 'utf8')) as { status?: unknown; pendingDelegation?: unknown };
|
|
571
|
-
if (run.status === 'running' || run.pendingDelegation !== null && run.pendingDelegation !== undefined) {
|
|
572
|
-
return {
|
|
573
|
-
code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE',
|
|
574
|
-
message: 'task orchestration has an active or pending delegation; settle it before moving the task directory'
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
} catch {
|
|
578
|
-
return {
|
|
579
|
-
code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE',
|
|
580
|
-
message: 'task orchestration state is unreadable; refusing to move the task directory'
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
return null;
|
|
585
|
-
};
|
|
586
658
|
const currentTaskFile = path.join(sourcePath, 'task.md');
|
|
587
659
|
const existingJournal = fs.existsSync(path.join(sourcePath, '.task-lifecycle.json'));
|
|
588
660
|
if (sourceState === spec.target && !existingJournal) {
|
|
@@ -605,7 +677,7 @@ function applyTaskLifecycleUnlocked(requestInput: TaskLifecycleRequest, options:
|
|
|
605
677
|
&& !(request.intent === 'complete' && targetContainsTask(targetPath, taskId, request))) {
|
|
606
678
|
return failed(request, { code: 'LIFECYCLE_TARGET_CONFLICT', message: `target directory already exists: ${targetPath}` }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
607
679
|
}
|
|
608
|
-
const moveSafety =
|
|
680
|
+
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, sourcePath, true);
|
|
609
681
|
if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
|
|
610
682
|
const content = io.readFileSync(currentTaskFile);
|
|
611
683
|
let frontmatter;
|
|
@@ -732,7 +804,7 @@ function applyTaskLifecycleUnlocked(requestInput: TaskLifecycleRequest, options:
|
|
|
732
804
|
}
|
|
733
805
|
if (fs.existsSync(targetPath) && !fs.existsSync(path.join(sourcePath, 'task.md'))) completed.add('directory-moved');
|
|
734
806
|
if (!completed.has('directory-moved')) {
|
|
735
|
-
const moveSafety =
|
|
807
|
+
const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, sourcePath, false);
|
|
736
808
|
if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, completedSteps: [...completed], changed: completed.size > 0, timestamp: journal.metadata.timestamp, agentInfraVersion: journal.metadata.agentInfraVersion });
|
|
737
809
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
738
810
|
if (request.intent === 'complete') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fitlab-ai/agent-infra",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.14",
|
|
4
4
|
"description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Antigravity CLI, and OpenCode",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
## Current Host
|
|
16
16
|
|
|
17
17
|
- Use native spawn, wait, and App Server results from the current host. A task-bound sandbox executes ordinary task orchestration locally in the current worktree.
|
|
18
|
-
- Codex controller `open`, `verify`, and `close` remain restricted broker operations. After `open`, complete typed `verify` with the same lease proof before accepting the task, control-generation, and controller-instance binding.
|
|
19
18
|
- Prepare validates the current task, model policy, and host preflight. Start and terminal records associate observed parent/child identity; failure must not be recorded as success.
|
|
20
19
|
- Client-specific preflight, event sources, and stop-evidence validation belong to the client adapter. The common orchestrator calls only the shared capability and contains no client-ID branches.
|
|
21
20
|
|
|
@@ -28,9 +27,9 @@
|
|
|
28
27
|
|
|
29
28
|
## Current-only Cutover and Rollback
|
|
30
29
|
|
|
31
|
-
- Enter a quiet window before cutover: let in-flight orchestration intents return
|
|
32
|
-
- Deploy or roll back the CLI, broker,
|
|
33
|
-
- On either the new or rolled-back version, first confirm the same task through `status`/`route
|
|
30
|
+
- Enter a quiet window before cutover: let in-flight orchestration intents return and preserve the worktree, task/run/orchestration state, receipts, and audit. For an unknown result, inspect local `status`/`route` before using existing recover/advance semantics; do not replay an old broker request.
|
|
31
|
+
- Deploy or roll back the CLI, broker, and protocol as one versioned unit. After stopping the old container/broker, rebuild and run `ai sandbox start --recreate <task-ref>` to resume with a new control generation; never reuse an old token or request.
|
|
32
|
+
- On either the new or rolled-back version, first confirm the same task through `status`/`route`. Keep the quiet window and evidence intact if any check fails; do not mix component versions or rewrite domain facts.
|
|
34
33
|
|
|
35
34
|
## Model Policy
|
|
36
35
|
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
## 当前宿主
|
|
16
16
|
|
|
17
17
|
- 使用当前宿主的原生 spawn、wait 与 App Server 结果;task-bound sandbox 在当前 worktree 本地执行普通任务编排。
|
|
18
|
-
- Codex controller 的 `open`、`verify`、`close` 继续通过受限 broker 执行。`open` 后必须用同一 lease proof 完成 typed `verify`,再接受 task、control generation 和 controller instance 绑定。
|
|
19
18
|
- prepare 校验当前任务、模型策略与宿主 preflight。启动和完成记录关联实际 parent/child 身份,失败不得写成成功。
|
|
20
19
|
- 客户端特有的 preflight、事件来源与停止证据校验由客户端适配器实现;公共总控只调用统一能力。不得在公共流程中新增客户端 ID 分支。
|
|
21
20
|
|
|
@@ -28,9 +27,9 @@
|
|
|
28
27
|
|
|
29
28
|
## Current-only 切换与回滚
|
|
30
29
|
|
|
31
|
-
- 切换前进入静默窗口:等待在途编排 intent
|
|
32
|
-
- CLI、broker
|
|
33
|
-
-
|
|
30
|
+
- 切换前进入静默窗口:等待在途编排 intent 返回,并保留 worktree、task/run/orchestration 状态、receipts 与 audit。结果未知时先用本地 `status`/`route` 判断 domain 是否已提交,再按现有 recover/advance 语义处理;不重放旧 broker request。
|
|
31
|
+
- CLI、broker 与协议必须作为同一版本单元部署或回退。停止旧 container/broker 后执行 rebuild 与 `ai sandbox start --recreate <task-ref>`,以新的 control generation 恢复执行;旧 token 和 request 不得复用。
|
|
32
|
+
- 新版本或回滚版本都必须先核对同一任务的 `status`/`route`。任一检查失败时继续保持静默并保留证据,不局部混用组件或改写 domain 事实。
|
|
34
33
|
|
|
35
34
|
## 模型策略
|
|
36
35
|
|
|
@@ -24,12 +24,13 @@ Task short ids let mobile-style SKILL invocations replace the full 22-char
|
|
|
24
24
|
|------------|-----------------------------------------------------------------------|---------------------------------------------------------------|
|
|
25
25
|
| alloc | `create-task`, `import-issue`, `import-codescan`, `import-dependabot` | Assigns lowest free `NN` in the registry. |
|
|
26
26
|
| resolve | Lifecycle SKILLs (`analyze-task`, `plan-task`, `code-task`, …) | Looks up `NN` → full task id. Does not allocate. |
|
|
27
|
-
| release |
|
|
27
|
+
| release | Successful sandbox cleanup; also `cancel-task`, `block-task`, `close-codescan`, and `close-dependabot` | Removes the registry entry. |
|
|
28
28
|
| re-alloc | `restore-task` | Re-allocates a (possibly new) `NN` in the registry. |
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
Completion retains the short id so a sandbox still associated with the
|
|
31
|
+
completed task can resolve it before cleanup. The id is released only after
|
|
32
|
+
managed sandbox cleanup confirms that the container was deleted successfully.
|
|
33
|
+
Other lifecycle intents release ids at the times listed in the table.
|
|
33
34
|
|
|
34
35
|
## Configuration
|
|
35
36
|
|
|
@@ -52,10 +53,13 @@ archiving all active tasks first (the registry key width depends on it).
|
|
|
52
53
|
| Entrypoint | Hit | Miss |
|
|
53
54
|
|-------------------------------------------------------------|----------------------|------------------------------------------------------|
|
|
54
55
|
| SKILL parameter resolver (lifecycle SKILLs) | resolve to full id | **strict error** — short id not found / invalid |
|
|
55
|
-
| `ai sandbox exec <N>` / `ai sandbox create <N>` | resolve to
|
|
56
|
+
| `ai sandbox exec <N>` / `ai sandbox create <N>` | resolve to an active task id, then read `branch` from task.md | **strict error** — no ls-index fallback, no literal-branch fallback; hint the user to pass a short id / `TASK-id` / branch name |
|
|
57
|
+
| `ai sandbox rm <N>` | resolve the retained mapping, then read active or completed identity by full task id | **strict error** — stop cleanup when the short id is missing |
|
|
56
58
|
|
|
57
|
-
`list --verify` is strictly read-only:
|
|
58
|
-
|
|
59
|
+
`list --verify` is strictly read-only: every active task must have a mapping;
|
|
60
|
+
registry mappings may point to a valid active task or to a
|
|
61
|
+
`completed/{taskId}/task.md` whose identity matches and whose status is
|
|
62
|
+
`completed`. Other mappings are reported as orphans; no state is modified.
|
|
59
63
|
|
|
60
64
|
## SKILL parameter resolver
|
|
61
65
|
|
|
@@ -94,11 +98,13 @@ Short ids are pure local state, persisted only in the registry
|
|
|
94
98
|
- Created on demand by the first `alloc`; an absent file is treated as an empty
|
|
95
99
|
registry.
|
|
96
100
|
- Short ids are assigned only by an explicit `alloc` (`create-task` /
|
|
97
|
-
`import-*` / `restore-task`); `resolve`
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
`import-*` / `restore-task`); `resolve` and `list` are read-only and do not
|
|
102
|
+
perform implicit cleanup.
|
|
103
|
+
- `alloc` may clean up stale entries that point neither to an active task nor
|
|
104
|
+
to valid completed task content. Completed mappings stay until managed
|
|
105
|
+
sandbox cleanup succeeds.
|
|
106
|
+
- Task operations may resolve a completed mapping and then reject it at their
|
|
107
|
+
own state gate; `ai sandbox create <N>` still accepts active tasks only.
|
|
102
108
|
|
|
103
109
|
`resolve(<N>)` workflow: ① validate arg matches `^[0-9]+$` →
|
|
104
110
|
② strip leading zeros and take the numeric value `n`; classify as reserved
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
|-----------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------|
|
|
20
20
|
| alloc | `create-task`、`import-issue`、`import-codescan`、`import-dependabot` | 分配最小可用 `NN`,写入注册表。 |
|
|
21
21
|
| resolve | 生命周期 SKILL(`analyze-task` / `plan-task` / `code-task` / `review-*` / `commit` / …) | `NN` → 完整 task id 查询,不分配。 |
|
|
22
|
-
| release | `
|
|
22
|
+
| release | sandbox cleanup 成功;以及 `cancel-task`、`block-task`、`close-codescan`、`close-dependabot` | 从注册表移除。 |
|
|
23
23
|
| re-alloc | `restore-task` | 重新分配(可能与历史不同),写入注册表。 |
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
complete 保留短号,供 completed task 与仍关联的 sandbox 在 cleanup 前继续解析。
|
|
26
|
+
受管 sandbox cleanup 确认容器已删除且清理成功后,才释放对应 completed task 的短号。
|
|
27
|
+
其他 lifecycle intent 继续按表中时机释放短号。
|
|
27
28
|
|
|
28
29
|
## 配置
|
|
29
30
|
|
|
@@ -45,9 +46,12 @@
|
|
|
45
46
|
| 入口 | 注册表命中 | 注册表未命中 |
|
|
46
47
|
|-----------------------------------------------------------|----------------------|--------------------------------------------------------|
|
|
47
48
|
| SKILL 入参解析器(生命周期 SKILL) | 解析为完整 task id | **严格报错** —— 短号不存在 / 格式错误 |
|
|
48
|
-
| `ai sandbox exec <N>` / `ai sandbox create <N>` |
|
|
49
|
+
| `ai sandbox exec <N>` / `ai sandbox create <N>` | 解析为 active task id 后查 task.md 取 `branch` | **严格报错** —— 不再回退到 ls 行号或字面分支名;提示用任务短号 / `TASK-id` / 分支名 |
|
|
50
|
+
| `ai sandbox rm <N>` | 解析保留映射,再按完整 task id 读取 active 或 completed 身份 | **严格报错** —— 短号不存在时停止清理 |
|
|
49
51
|
|
|
50
|
-
`list --verify`
|
|
52
|
+
`list --verify` 严格只读:active task 必须有映射;注册表映射可指向有效 active task
|
|
53
|
+
或 `completed/{taskId}/task.md` 中身份匹配且状态为 completed 的 task。其他映射作为 orphan
|
|
54
|
+
报告,不修改任何状态。
|
|
51
55
|
|
|
52
56
|
## SKILL 入参解析
|
|
53
57
|
|
|
@@ -78,8 +82,9 @@ fi
|
|
|
78
82
|
- key 是零填充到 `task.shortIdLength` 位的字符串,value 是完整 `TASK-…` task id
|
|
79
83
|
- 自动 git ignore(active 工作区整体 ignore;无需新增 ignore 条目)
|
|
80
84
|
- 首次 `alloc` 时按需自动创建;不存在时按空注册表处理
|
|
81
|
-
- 短号只由显式 `alloc`(`create-task` / `import-*` / `restore-task`)分配;`resolve`
|
|
82
|
-
-
|
|
85
|
+
- 短号只由显式 `alloc`(`create-task` / `import-*` / `restore-task`)分配;`resolve` 与 `list` 只读,不做隐式清理
|
|
86
|
+
- alloc 可清理既非 active、也没有有效 completed task 内容的 stale entry;completed mapping 保留至受管 sandbox cleanup 成功
|
|
87
|
+
- task 操作可按 completed mapping 解析后由各自状态门禁拒绝;`ai sandbox create <N>` 仍只接受 active task
|
|
83
88
|
|
|
84
89
|
`resolve(<N>)` 工作流:① 校验入参匹配 `^[0-9]+$` → ② 去前导零取
|
|
85
90
|
数值 `n`,按 `n` 是否 `== 0`(保留)/ `> 10^shortIdLength - 1`(超容量)/
|
|
@@ -63,6 +63,8 @@ agent-infra-internal platform-release-notes context \
|
|
|
63
63
|
|
|
64
64
|
Use `pullRequests` and `commits` from Step 3. Each commit's `authors` contains only that commit's platform authors; `pullRequestNumbers` records the platform's PR associations. The skill does not interpret raw platform fields or email rules. A PR's `closingIssues` contains its actual closing Issues; never infer a relationship from matching PR and Issue numbers.
|
|
65
65
|
|
|
66
|
+
Release notes describe changes actually delivered between the tags. For commits without an associated PR, inspect the actual diff using the `oid` from the typed context to determine whether it records a delivered change or release workflow mechanics. A commit made up only of version metadata updates, generated release artifacts, or other mechanical release preparation/publication work is outside the release's change set and contributor counts. When a commit also contains an independent product, documentation, or maintenance change, retain that change and its authors. If the diff does not establish the commit's purpose, keep it and describe the actual change. Use this same filtered commit set for the classification in Step 6 and contributor counts in Step 7.
|
|
67
|
+
|
|
66
68
|
### 5. Collect Related Issues
|
|
67
69
|
|
|
68
70
|
Use each PR's `closingIssues` from Step 3. Do not parse platform-specific reference syntax in this generic skill.
|
|
@@ -112,7 +114,7 @@ If no historical release notes exist, use the following default Markdown format:
|
|
|
112
114
|
5. **Contributor collection**:
|
|
113
115
|
- **Data sources**:
|
|
114
116
|
- PR authors from the typed context
|
|
115
|
-
- Commit co-authors from
|
|
117
|
+
- Commit co-authors from `authors` of commits retained as release changes in Step 4
|
|
116
118
|
- Issue reporters from typed `closingIssues[].author`
|
|
117
119
|
- **Contribution count**: `PR count + co-authored commit count` for the same identity, merged across both sources
|
|
118
120
|
- **`@login` mapping**: follow the identity safety boundary in `.agents/rules/release-commands.md`
|
|
@@ -63,6 +63,8 @@ agent-infra-internal platform-release-notes context \
|
|
|
63
63
|
|
|
64
64
|
使用步骤 3 返回的 `pullRequests` 与 `commits`。每个 commit 的 `authors` 只包含该 commit 的平台作者;`pullRequestNumbers` 表示平台记录的 PR 关联。技能不读取平台原始字段或邮箱规则。PR 的 `closingIssues` 是该 PR 实际关闭的 Issue,不按 PR/Issue 编号推断关联。
|
|
65
65
|
|
|
66
|
+
发布说明记录标签间实际交付的变更。对于没有关联 PR 的 commit,依据 typed context 中的 `oid` 检查实际 diff,判断它记录的是版本交付还是发布流程本身。仅包含版本元数据更新、生成发布产物或其他版本准备/发布机械操作的 commit 不属于本版本变更,也不计入贡献者;同一 commit 若还包含独立的产品、文档或维护改动,则保留这些改动及其作者。diff 无法说明提交用途时,保留该 commit,并根据实际改动描述。步骤 6 的变更分类和步骤 7 的贡献者统计使用同一筛选结果。
|
|
67
|
+
|
|
66
68
|
### 5. 收集关联 Issue
|
|
67
69
|
|
|
68
70
|
使用步骤 3 中每个 PR 的 `closingIssues`,不在通用技能中解析平台专有引用语法。
|
|
@@ -112,7 +114,7 @@ agent-infra-internal platform-release-notes context \
|
|
|
112
114
|
5. **贡献者搜集**:
|
|
113
115
|
- **数据源**:
|
|
114
116
|
- PR author:来自 `.agents/rules/release-commands.md` 中已合并 PR 查询规则
|
|
115
|
-
- Commit co-authors:来自步骤 3 typed context
|
|
117
|
+
- Commit co-authors:来自步骤 3 typed context 中按步骤 4 纳入版本变更的 commit `authors`
|
|
116
118
|
- Issue reporters:来自步骤 3 typed context 的 `closingIssues[].author`
|
|
117
119
|
- **贡献数定义**:`该人的 PR 数 + 该人作为 co-author 的 commit 数`(同一身份跨来源合并计数)
|
|
118
120
|
- **`@login` 映射**:遵循 `.agents/rules/release-commands.md` 的身份安全边界
|
|
@@ -14,7 +14,7 @@ The entry point may omit the task ref; explicit task scope accepts only `--task
|
|
|
14
14
|
The orchestrator delegates only and never executes a stage skill itself. First read `.agents/rules/no-mid-flow-questions.md`, `.agents/rules/lifecycle-orchestration.md`, and `reference/host-validation.md`.
|
|
15
15
|
|
|
16
16
|
1. Resolve the canonical task ID, current Agent Client, and optional atomic policy flags, then run `task-snapshot`. If one explicit role field is present, all four are required.
|
|
17
|
-
2. Use the current host's native child spawn, wait, and result interfaces. Task-bound sandboxes execute ordinary task orchestration locally in the current worktree
|
|
17
|
+
2. Use the current host's native child spawn, wait, and result interfaces. Task-bound sandboxes execute ordinary task orchestration locally in the current worktree. Retain task binding and checks for real external process operations.
|
|
18
18
|
3. Before each loop, run `agent-infra-internal task-lifecycle {task-id} recover-started --agent {client} --auto`. The client adapter owns recovery capability and stop-evidence validation; an unsupported adapter or a run that needs no recovery returns `no-op`. Continue only after `no-op` or `applied`. Stop on every other result; a later operator invocation retries from persisted state without routing or dispatching a child.
|
|
19
19
|
4. Run `task-orchestration {task-id} begin-or-resume --client {client}` with the complete explicit policy. With no explicit policy, core reads that client's configured policy; existing runs use persisted policy. Disk state outside the complete current structure fails closed without rewriting; finish or clear active runs before upgrading. Stop on paused/completed results.
|
|
20
20
|
5. Run `route`. On `completed`, run `agent-infra-internal task-verify {task-id} run-task.completed --format text`, present its summary per `.agents/rules/validation-output.md` while retaining necessary diagnostics, and stop. Only a `running` result with non-null `next` supplies action, role, round, artifact, requested model, and requested effort.
|
|
@@ -14,7 +14,7 @@ description: >
|
|
|
14
14
|
总控只编排,不直接执行任何阶段技能。执行前先读取 `.agents/rules/no-mid-flow-questions.md`、`.agents/rules/lifecycle-orchestration.md` 与 `reference/host-validation.md`。
|
|
15
15
|
|
|
16
16
|
1. 解析规范任务 ID、当前 Agent Client,以及可选的原子策略 `--executor-model`、`--executor-reasoning-effort`、`--reviewer-model`、`--reviewer-reasoning-effort`,并执行 `agent-infra-internal task-snapshot {task-id} --format text`。任一显式策略字段出现时四个 role 字段必须完整,不得与配置拼接;两个角色可以使用同一模型。
|
|
17
|
-
2. 使用当前宿主的原生子 Agent 启动、等待与结果接口。task-bound sandbox 在当前 worktree
|
|
17
|
+
2. 使用当前宿主的原生子 Agent 启动、等待与结果接口。task-bound sandbox 在当前 worktree 本地执行普通任务编排。保留任务绑定与真实外部进程操作检查。
|
|
18
18
|
3. 每次进入循环时先调用 `agent-infra-internal task-lifecycle {task-id} recover-started --agent {client} --auto`。客户端适配器负责恢复能力和停止证据校验;没有该能力或无需恢复时返回 `no-op`。仅在结构化结果为 `no-op` 或 `applied` 时继续,其他结果安全停止;下一次人为调用按持久化状态幂等重试,不 route、不派发 child。
|
|
19
19
|
4. 调用 `agent-infra-internal task-orchestration {task-id} begin-or-resume --client {client}` 并转发完整显式策略。完全没有显式策略时由核心读取当前 client 的 `agentClients[].orchestration`;existing run 使用持久化策略。磁盘状态不符合当前完整结构时核心失败关闭且不改写;升级前必须完成或清空 active run。仅当核心返回 `ORCHESTRATION_MODEL_POLICY_REQUIRED` 时,先用 `agent-client model-selection` 展示 complete/partial/interactive-only 来源,再一次收集完整策略;未回答则不创建 run。若为 paused/completed,按结构化结果停止。
|
|
20
20
|
5. 调用 `route` 并读取结构化结果。若返回 `completed`,立即运行 `agent-infra-internal task-verify {task-id} run-task.completed --format text` 并停止;按 `.agents/rules/validation-output.md` 展示摘要并保留必要诊断。仅当返回 `running` 且 `next` 非空时读取唯一 action、role、round、artifact、`requestedModel` 和 `requestedReasoningEffort`,不得自行推断。
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { SandboxControlClientError, requestSandboxAgentOperation } from '../../../sandbox/control/client.js';
|
|
2
|
-
function fail(code, message, accepted = true) {
|
|
3
|
-
throw new SandboxControlClientError({ code, message: `${code}: ${message}`, retryable: false }, accepted);
|
|
4
|
-
}
|
|
5
|
-
function exactKeys(value, keys) {
|
|
6
|
-
return Object.keys(value).sort().join(',') === [...keys].sort().join(',');
|
|
7
|
-
}
|
|
8
|
-
function validProcess(value) {
|
|
9
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
10
|
-
return false;
|
|
11
|
-
const process = value;
|
|
12
|
-
return exactKeys(process, ['pid', 'startTime'])
|
|
13
|
-
&& Number.isSafeInteger(process.pid) && process.pid > 0
|
|
14
|
-
&& Number.isSafeInteger(process.startTime) && process.startTime >= 0;
|
|
15
|
-
}
|
|
16
|
-
function validBuild(value) {
|
|
17
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
18
|
-
return false;
|
|
19
|
-
const build = value;
|
|
20
|
-
return exactKeys(build, ['internalExecutableBuildHash', 'lifecycleContractHash', 'packageVersion', 'protocolVersion'])
|
|
21
|
-
&& build.protocolVersion === 3
|
|
22
|
-
&& typeof build.packageVersion === 'string' && build.packageVersion.length > 0
|
|
23
|
-
&& typeof build.internalExecutableBuildHash === 'string' && /^[a-f0-9]{64}$/u.test(build.internalExecutableBuildHash)
|
|
24
|
-
&& typeof build.lifecycleContractHash === 'string' && /^[a-f0-9]{64}$/u.test(build.lifecycleContractHash);
|
|
25
|
-
}
|
|
26
|
-
function parseCodexControllerResult(response) {
|
|
27
|
-
if (response.phase !== 'completed' || response.error !== null || response.stderr !== '') {
|
|
28
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller result outer response is invalid');
|
|
29
|
-
}
|
|
30
|
-
let value;
|
|
31
|
-
try {
|
|
32
|
-
if (!response.stdout.endsWith('\n') || response.stdout.slice(0, -1).includes('\n'))
|
|
33
|
-
throw new Error('not canonical');
|
|
34
|
-
value = JSON.parse(response.stdout);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller result payload is invalid');
|
|
38
|
-
}
|
|
39
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
40
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller result payload is invalid');
|
|
41
|
-
}
|
|
42
|
-
const result = value;
|
|
43
|
-
const keys = result.status === 'verified'
|
|
44
|
-
? ['binding', 'changed', 'error', 'lease', 'status', 'version']
|
|
45
|
-
: ['changed', 'error', 'lease', 'status', 'version'];
|
|
46
|
-
if (!exactKeys(result, keys) || result.version !== 1
|
|
47
|
-
|| !['opened', 'closed', 'failed', 'verified'].includes(result.status)) {
|
|
48
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller result schema is invalid');
|
|
49
|
-
}
|
|
50
|
-
if (result.status === 'failed') {
|
|
51
|
-
const error = result.error;
|
|
52
|
-
if (response.exitCode !== 1 || result.changed !== false || result.lease !== null || !error
|
|
53
|
-
|| !exactKeys(error, ['code', 'message', 'retryable'])
|
|
54
|
-
|| typeof error.code !== 'string' || !/^[A-Z][A-Z0-9_]+$/u.test(error.code)
|
|
55
|
-
|| typeof error.message !== 'string' || error.retryable !== false) {
|
|
56
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller failure result is invalid');
|
|
57
|
-
}
|
|
58
|
-
fail(error.code, error.message);
|
|
59
|
-
}
|
|
60
|
-
if (response.exitCode !== 0 || result.error !== null) {
|
|
61
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller success result is invalid');
|
|
62
|
-
}
|
|
63
|
-
if (result.status === 'closed') {
|
|
64
|
-
if (typeof result.changed !== 'boolean' || result.lease !== null)
|
|
65
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller close result is invalid');
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
if (result.status === 'verified') {
|
|
69
|
-
const binding = result.binding;
|
|
70
|
-
if (result.changed !== false || result.lease !== null || !binding
|
|
71
|
-
|| !exactKeys(binding, ['controllerInstanceDigest', 'controlGeneration', 'taskId'])
|
|
72
|
-
|| typeof binding.taskId !== 'string' || binding.taskId.length === 0
|
|
73
|
-
|| typeof binding.controlGeneration !== 'string' || binding.controlGeneration.length === 0
|
|
74
|
-
|| typeof binding.controllerInstanceDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(binding.controllerInstanceDigest)) {
|
|
75
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller verify result is invalid');
|
|
76
|
-
}
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
const lease = result.lease;
|
|
80
|
-
if (result.changed !== true || !lease
|
|
81
|
-
|| !exactKeys(lease, ['buildIdentity', 'controlGeneration', 'controllerInstanceDigest', 'controllerProcess', 'expiresAt', 'issuedAt', 'leaseId', 'leaseSecret', 'taskId', 'version'])
|
|
82
|
-
|| lease.version !== 1 || typeof lease.leaseId !== 'string' || !/^[a-f0-9]{64}$/u.test(lease.leaseId)
|
|
83
|
-
|| typeof lease.leaseSecret !== 'string' || !/^[a-f0-9]{64}$/u.test(lease.leaseSecret)
|
|
84
|
-
|| typeof lease.taskId !== 'string' || lease.taskId.length === 0
|
|
85
|
-
|| typeof lease.controlGeneration !== 'string' || lease.controlGeneration.length === 0
|
|
86
|
-
|| typeof lease.controllerInstanceDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(lease.controllerInstanceDigest)
|
|
87
|
-
|| !validProcess(lease.controllerProcess) || !validBuild(lease.buildIdentity)
|
|
88
|
-
|| !Number.isSafeInteger(lease.issuedAt) || !Number.isSafeInteger(lease.expiresAt)
|
|
89
|
-
|| lease.expiresAt <= lease.issuedAt) {
|
|
90
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller open result is invalid');
|
|
91
|
-
}
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
function requestController(params) {
|
|
95
|
-
const result = parseCodexControllerResult(requestSandboxAgentOperation({
|
|
96
|
-
agentClient: 'codex',
|
|
97
|
-
operation: `controller.${params.command}`,
|
|
98
|
-
payload: params.command === 'open'
|
|
99
|
-
? { controllerProcess: params.controllerProcess }
|
|
100
|
-
: { proof: params.controllerProof },
|
|
101
|
-
...params
|
|
102
|
-
}));
|
|
103
|
-
if (result.status === 'opened'
|
|
104
|
-
&& (result.lease.controlGeneration !== (params.generation ?? process.env.AGENT_INFRA_CONTROL_GENERATION)
|
|
105
|
-
|| result.lease.controllerProcess.pid !== params.controllerProcess.pid
|
|
106
|
-
|| result.lease.controllerProcess.startTime !== params.controllerProcess.startTime)) {
|
|
107
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller result does not match the request');
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
function requestCodexControllerOpen(params) {
|
|
112
|
-
const result = requestController({ ...params, command: 'open', controllerProof: null });
|
|
113
|
-
if (result.status !== 'opened')
|
|
114
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller open returned the wrong result');
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
function requestCodexControllerClose(params) {
|
|
118
|
-
const result = requestController({ ...params, command: 'close' });
|
|
119
|
-
if (result.status !== 'closed')
|
|
120
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller close returned the wrong result');
|
|
121
|
-
return result;
|
|
122
|
-
}
|
|
123
|
-
function requestCodexControllerVerify(params) {
|
|
124
|
-
const result = requestController({ ...params, controllerProcess: params.controllerProof.controllerProcess, command: 'verify' });
|
|
125
|
-
if (result.status !== 'verified')
|
|
126
|
-
fail('SANDBOX_CONTROL_RESULT_INVALID', 'controller verify returned the wrong result');
|
|
127
|
-
return result;
|
|
128
|
-
}
|
|
129
|
-
export { parseCodexControllerResult, requestCodexControllerClose, requestCodexControllerOpen, requestCodexControllerVerify };
|
|
130
|
-
//# sourceMappingURL=controller-client.js.map
|