In-session package jobs
Observe pending execution, real recipe progress and cancellation through a host-owned job handle.
In-session package jobs
Original programmable spec §53 now has an explicit SDK host job handle. createPackageJob(package, input, options) returns immediately with an immutable ID, getSnapshot(), subscribe(listener), cancel() and a result Promise. Status advances from queued to loading (contract/input checks), running (executor pending), then completed, failed or cancelled. A final operation count never completes the job.
The default executor is runPackageAsync. An application may supply an explicit trusted execute adapter; BlockPlayground uses its existing runInWorker, preserving local worker isolation and existing capability/ComfyUI approval dialogs. The handle is created by host code, never read from a package or guest result. It accepts no polling URLs, tokens, guest functions, server IDs or automatic retry instructions. Opted-in JavaScript cooperative pending envelopes are consumed inside the sandbox; only final declared outputs reach this handle. Arbitrary pending envelopes still fail final-result validation. This is not a serialized or durable job receipt.
Source/input/state are captured separately from the clones passed to the executor. Manifest and input/state validation precede execution; final outputs and declared Step state are validated before resolving. Preserved auxiliary host metadata does not become authenticated solely by this helper. Existing source admission, policy checks, output acceptance, stored media verification and attribution remain the host's responsibility.
onProgress carries actual sequential recipe operation counts or validated cooperative continuation turns and optional declared units. Other runtimes retain their own approval/progress UI. Nothing derives provider percentage, cost or remaining time from elapsed time. The deadline defaults to 15 seconds and an explicit host override is bounded to 15 minutes. Cancellation/deadline abort the executor's signal, settle once, and suppress later outputs; they do not promise remote cancellation or reverse provider billing. Listener failures cannot turn progress into completion. Handles allow up to 64 listeners and release listeners/timers on termination.
The shared PackageJobStatus renders the real snapshot. Block previews retain terminal states, offer cancellation both during input preparation and pending execution, and clear jobs for changed inputs/reset/new runs. Existing controller/source/revision/account fences remain necessary before accepting outputs. Connected Steps and import samples also use this handle through their existing trusted executors. Parent cancellation remains available during preparation, persistence and final admission after a child job completes.
Example for a trusted host
import {createPackageJob} from './packages/block-sdk/index.js';
const job = createPackageJob(pkg, input, {
signal: controller.signal,
execute: (pkg, input, options) => approvedHostExecutor(pkg, input, options),
});
const unsubscribe = job.subscribe(() => renderJobStatus(job.getSnapshot()));
try {
const final = await job.result;
// Recheck current project/source and accept through the existing host boundary.
} finally {
unsubscribe();
}
// A user cancel action calls job.cancel().Remaining scope and verification
In-session jobs do not reconnect after reload, persist a provider queue, schedule background work or resume an arbitrary external guest job. Opted-in JavaScript can yield bounded JSON continuations within the original sandbox run; see Cooperative guest jobs. Existing hosted adapters retain their own durable request protocols. No hosted fallback or financial behavior is changed. SDK downloadable inclusion is wired in the generator; generated artifacts are separate delivery work. No tests, builds, browser QA, provider calls or migrations were performed for this implementation.