fix(e2b): address the v7 review round

- restore the parent's AGENTS.md body around this branch's e2b row (the
  replay had resurrected the pre-profile-CLI layout, deleting the api/,
  bundle/, settings/, and credentials/ groups); the fs/lsp row
  condensations stay for the word budget
- aggregate the composite rollback failure, not the original error, when
  private state cleanup also fails — a surviving remote group is no
  longer hidden by a later cleanup error (triple-failure regression)
- own the state directory before the makeDir RPC, matching the terminal
  transaction, so a cancellation racing a committed creation still
  enters cleanup
- drop the hidden pollMs parameter defaults; the schemastery default is
  the one home, and tests pass the cadence explicitly
- restore spawn/spawnTerminal graceMs validation to the seam's
  documented bound (the earlier removal cited subprocess-local as not
  validating; it does), with rejection regressions
This commit is contained in:
Tianyi Cui
2026-08-08 22:37:38 +08:00
parent 10fc9405c7
commit 450ec99325
11 changed files with 218 additions and 137 deletions
+15
View File
@@ -9,6 +9,7 @@ import { posix } from 'node:path'
import { Context } from 'cordis'
import z from 'schemastery'
import { SubprocessService } from '@deepseek-ai/dsh-subprocess'
import { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'
import type {
SubprocessHandle,
SubprocessSpawnSpec,
@@ -35,6 +36,18 @@ interface TerminalSetup {
controller: AbortController
}
/**
* Enforce the seam's documented grace bound (positive, finite, one Node timer),
* matching subprocess-local's spawn-time check; an unbounded grace would make
* the remote force-escalation deadline unreachable.
* @param graceMs - The spec's cleanup grace in milliseconds.
*/
function requireRepresentableGrace(graceMs: number): void {
if (!Number.isFinite(graceMs) || graceMs <= 0 || graceMs > MAX_TIMER_DELAY_MS) {
throw new Error(`subprocess graceMs must be a positive finite number no greater than ${MAX_TIMER_DELAY_MS}`)
}
}
/** E2B command manager registered as `ctx.subprocess`. */
export class E2BSubprocessService extends SubprocessService {
static inject = ['e2b']
@@ -130,6 +143,7 @@ export class E2BSubprocessService extends SubprocessService {
if (program === undefined || program.length === 0) {
throw new Error('invalid argv: expected a non-empty program name at argv[0]')
}
requireRepresentableGrace(spec.graceMs)
if (spec.signal?.aborted === true) {
throw new Error(`aborted before spawn: ${String(spec.signal.reason)}`)
}
@@ -153,6 +167,7 @@ export class E2BSubprocessService extends SubprocessService {
if (program === undefined || program.length === 0) {
throw new Error('subprocess-e2b: terminal argv must contain a program')
}
requireRepresentableGrace(spec.graceMs)
spec.signal?.throwIfAborted()
const stateDir = posix.join(this.ctx.e2b.runtimeRoot, 'terminals', randomUUID())
const done = Promise.withResolvers<void>()