Skip to main content

Interface: IHumanGate

Defined in: internal/human-gate/types.ts:41

Pause and resume mechanics for runs.

Implemented by HumanGate; the type of IAIGatewayDeps.humanGate, so a host may pass its own in overrides.

Methods​

assertResumable()​

assertResumable(args): void

Defined in: internal/human-gate/types.ts:116

assertResumable -- the checks of resume on a run already loaded, without I/O

About​

Refuse early what resume would refuse anyway.

Throws what resume throws for a run that cannot take these decisions: 409 when the run is not paused or pauseId names another pause of it, 410 when the pause has expired, 400 when the decisions do not answer the pause — every envelope needs exactly one decision, named by the envelope's callId (a single-envelope pause takes one decision without it), with an action among that envelope's allowed. Returns nothing when the decisions may go through; matchDecisions gives the pairs.

AIGateway.resume calls it first, so a resume that is doomed pays no judge call for the answer screen (D71) and no repository reads; resume calls it again on the run it reloads, right before the atomic transition.

Pitfalls​

It does not reserve anything: another caller can still win the transition in resume.

Parameters​

args​
decisions​

IResumeDecision[]

pauseId​

string

run​

IRun

Returns​

void


cancel()​

cancel(args): Promise<void>

Defined in: internal/human-gate/types.ts:174

cancel -- closes a paused run the user gave up on

About​

PAUSED to CANCELLED, atomically; a run that is not paused is a 409.

Who needs it​

AIGateway.cancelRun, before closeRun rejects the pending tool calls.

Parameters​

args​
runId​

string

tenantId​

string

Returns​

Promise<void>


expirePaused()​

expirePaused(args): Promise<IRun[]>

Defined in: internal/human-gate/types.ts:199

expirePaused -- cancels the pauses nobody answered in time

About​

Every paused run of the tenant whose expiresAt has passed becomes CANCELLED; the cancelled runs come back, with the envelopes of their pause.

A PAUSED run without an envelope counts as due too (D80): nothing can resume it (assertResumable is a 409 without a pending envelope), so it would hold its thread for ever; the job is the only way out of that state. The envelopes of one pause share their expiresAt, so the first one speaks for all. Each run leaves PAUSED through the atomic transition (D69), so a resume racing with the job loses cleanly. The gate only moves the runs: closing their tool calls in the thread and reopening the thread is the gateway's part (AIGateway.expirePausedRuns), which needs the runs, hence the return value (D75). The transition clears pending, so each returned run carries the envelopes of its pause again: the gateway closes every call with its own rejection text (D87).

Who needs it​

AIGateway.expirePausedRuns, called by a scheduled job of the application.

Parameters​

args​
tenantId​

string

Returns​

Promise<IRun[]>


listPaused()​

listPaused(args): Promise<IRun[]>

Defined in: internal/human-gate/types.ts:158

listPaused -- the paused runs of a tenant

About​

The inbox, as the store has it.

RunStore.listPaused: the tenant's PAUSED runs, one user's when userId is given.

Who needs it​

AIGateway.listPausedRuns, which strips the reviewer's draft before the asker sees the list (D111).

Parameters​

args​
tenantId​

string

userId?​

string

Returns​

Promise<IRun[]>


matchDecisions()​

matchDecisions(args): object[]

Defined in: internal/human-gate/types.ts:138

matchDecisions -- pairs every decision of a resume with the envelope it answers

About​

Which card does this answer belong to.

The pairs in the order of the envelopes. Throws what assertResumable throws: 409 when the run is not paused or pauseId is not the pause it waits on (a decision meant for an earlier pause of the same run), 410 when the pause has expired, 400 when a decision names no envelope of the pause (callId), an envelope gets no decision or two, or an action is not among its envelope's allowed. A pause of one envelope takes a single decision without callId.

Who needs it​

assertResumable, and AIGateway.resume to read each decision next to its envelope (the answer screen, the rejection texts).

Parameters​

args​
decisions​

IResumeDecision[]

pauseId​

string

The pause the decisions are for (envelope.pauseId).

run​

IRun

Returns​

object[]


pause()​

pause(args): Promise<TPauseEnvelope[]>

Defined in: internal/human-gate/types.ts:59

pause -- stores the run as PAUSED with the cards of its pause

About​

The run stops here; these are the cards the UI shows.

Stamps every draft with the run's id, one fresh pauseId and one expiresAt (now + timeoutMs), saves the run as PAUSED with them as pending and returns them. One envelope per tool call of the step that waits for a human (D102), or the one envelope of a result review (D99). An empty list is a 500 (error 5376634521017): a pause without a card could never be answered.

Who needs it​

settleRun, when the loop stopped on tool calls that need a human; settleReviewPause, when the answer waits for a reviewer.

Parameters​

args​
envelopes​

(Omit<IToolApprovalEnvelope, "runId" | "pauseId" | "expiresAt"> | Omit<IResultReviewEnvelope, "runId" | "pauseId" | "expiresAt"> | Omit<IUserQuestionEnvelope, "runId" | "pauseId" | "expiresAt">)[]

run​

IRun

tenantId​

string

Returns​

Promise<TPauseEnvelope[]>


resume()​

resume(args): Promise<IRun>

Defined in: internal/human-gate/types.ts:88

resume -- lets the decisions through and marks the run RUNNING

About​

One pause, one answer: a decision per envelope, and the first caller wins, every other one is refused.

Validates the decisions (assertResumable), then moves the run PAUSED to RUNNING in one atomic step (D69) and returns it. The LLMClient applies the decisions (run.resume).

  • 409 when the run is not paused, when pauseId is not the pause the run waits on, or another caller resumed or cancelled it first.
  • 410 when the pause has expired.
  • 400 when a decision names no envelope, an envelope gets no decision or two, or an action is not allowed on its envelope.

Who needs it​

AIGateway.resume, after the profile, tool and answer checks, before the LLMClient continues the run.

Pitfalls​

Two resumes at once (a double click, two tabs) reach this method together; the atomic transition admits one, so a side-effect tool never runs twice for one approval.

Parameters​

args​
decisions​

IResumeDecision[]

pauseId​

string

The pause the decisions are for (envelope.pauseId).

runId​

string

tenantId​

string

Returns​

Promise<IRun>