@anthropic-ai/sdk
Version:
The official TypeScript library for the Anthropic API
233 lines • 12.5 kB
text/typescript
import type { Anthropic } from "../../client.mjs";
import type { BetaRunnableTool } from "../tools/BetaRunnableTool.mjs";
import type { BetaToolRunnerRequestOptions } from "../tools/BetaToolRunner.mjs";
import type { AgentToolContext, MemoryDeleteMode } from "../../tools/agent-toolset/node.mjs";
/**
* Either a fixed tool array or a factory invoked once per claimed session with
* that session's {@link AgentToolContext} — use the factory form to bind
* `betaAgentToolset20260401` (or any tool that needs the workdir / session
* id) to the right session.
*/
export type EnvironmentWorkerTools = Array<BetaRunnableTool> | ((ctx: AgentToolContext) => Array<BetaRunnableTool>);
export interface EnvironmentWorkerOptions {
client: Anthropic;
/**
* The self-hosted environment to poll for work. Required by
* {@link EnvironmentWorker.run}; not used by {@link EnvironmentWorker.handleItem}.
*/
environmentId?: string;
/**
* The environment key — the worker's standing credential: polling always
* uses it, and per-session calls fall back to it when a claimed item's
* `secret` doesn't yield a sessions token. Required by
* {@link EnvironmentWorker.run}; {@link EnvironmentWorker.handleItem} falls
* back to `ANTHROPIC_ENVIRONMENT_KEY` and needs a key only when the work
* item's `secret` yields no sessions token.
*/
environmentKey?: string;
/**
* Tools to expose to each claimed session. Defaults to
* `betaAgentToolset20260401(ctx)` (the standard `agent_toolset_20260401` set
* bound to the per-session {@link AgentToolContext}).
*
* A `run` that blocks the event loop synchronously also stalls the lease
* heartbeat, and the worker can lose the lease; keep tools non-blocking (see
* {@link BetaRunnableTool.run}).
*/
tools?: EnvironmentWorkerTools;
/** Base directory for the per-session {@link AgentToolContext}. Defaults to `process.cwd()`. */
workdir?: string;
/**
* @deprecated No longer accepted: the file tools are always confined to
* `workdir` plus `allowedRoots`, which is neither behavior this flag used to
* select, so passing either value throws. Remove it; list extra directories
* in {@link AgentToolContext.allowedRoots}. The property is removed in a
* future release.
*/
unrestrictedPaths?: boolean;
/** Forwarded to the per-session {@link AgentToolContext} (`maxFileBytes`). */
maxFileBytes?: number | null;
/** Forwarded to {@link SessionToolRunner} (`maxIdleMs`). */
maxIdleMs?: number;
/**
* How often (milliseconds) to sync the session's attached memory stores back
* while it runs — checked after each dispatched tool call, plus one final
* sync when the session ends cleanly. Defaults to
* `DEFAULT_MEMORY_SYNC_INTERVAL_MS` (15s); the constructor throws for
* values below `MIN_MEMORY_SYNC_INTERVAL_MS` (5s). Every teardown also runs
* a push-only flush of changed files; that flush and the final sync are
* each bounded by `MEMORY_FLUSH_TIMEOUT_MS`, and a warning is logged when
* either bound cuts work off. `null` disables memory download and sync
* entirely. Memory stores are only touched for work items whose `secret`
* carries a `sessions_token`; while sync is enabled, an item without one
* fails when its session has memory stores attached, because those stores
* cannot be mounted without the token. With `null` the same item runs,
* without memory, and nothing is logged — turning sync off is the
* operator's explicit choice.
*/
memorySyncIntervalMs?: number | null;
/**
* Whether local file deletions may delete on the server — see
* {@link MemoryDeleteMode}. Uploads and pulls are unaffected.
* Defaults to `"enabled"`.
*/
memorySyncDeletions?: MemoryDeleteMode;
/** Forwarded to the {@link WorkPoller}. */
workerId?: string;
/** External abort signal; aborting it ends the run. */
signal?: AbortSignal;
/**
* Extra per-request options merged into every call this worker issues — the
* work poll/ack/heartbeat/stop control-plane calls and the per-session
* SessionToolRunner's stream/list/send. Mirrors what
* `client.beta.messages.toolRunner` accepts: custom `headers` (e.g. a proxy's
* auth/routing headers) reach all of them. The worker owns the abort signals,
* so a `signal` here is ignored — use {@link EnvironmentWorkerOptions.signal}.
*/
requestOptions?: BetaToolRunnerRequestOptions;
}
/**
* Options for {@link EnvironmentWorker.handleItem}. Every field falls back to the
* matching `ANTHROPIC_*` environment variable — the ones the
* `ant worker poll --on-work` command sets for the process it spawns — when not
* passed explicitly.
*/
export interface HandleItemOptions {
/** Work item id. Falls back to `ANTHROPIC_WORK_ID`. */
workId?: string;
/** Self-hosted environment id. Falls back to `ANTHROPIC_ENVIRONMENT_ID`. */
environmentId?: string;
/** Session id. Falls back to `ANTHROPIC_SESSION_ID`. */
sessionId?: string;
/**
* The environment key. Resolution order: this option, then the worker's own
* `environmentKey`, then `ANTHROPIC_ENVIRONMENT_KEY`. Needed only when
* `workSecret` is absent or its payload yields no sessions token — with a
* token-bearing secret the item runs on that token alone.
*/
environmentKey?: string;
/**
* The work item's per-item `secret` payload from the poll response. Falls
* back to `ANTHROPIC_WORK_SECRET`. Unlike the others it is optional — when
* present, the sessions token extracted from it is preferred as the Bearer
* credential for this item's heartbeat / force-stop / skill-download /
* session calls; when absent (or undecodable) those calls use the
* environment key.
*/
workSecret?: string;
/** External abort signal; aborting it ends the run. Defaults to the constructor's signal. */
signal?: AbortSignal;
}
/**
* Extract the per-item sessions token from a work item's `secret` payload.
*
* The `secret` the poll response populates is not itself a credential: it is a
* URL-safe base64 JSON payload matching {@link BetaWorkSecret} — the
* `sessions_token` (the bearer for this item's work lifecycle and
* session-level calls) plus fields this worker does not consume. Returns the
* sessions token, or `null` (meaning: fall back to the environment key) when
* the payload is missing, doesn't decode, or carries no token. Never log the
* payload or anything extracted from it.
*/
export declare function sessionsTokenFromSecret(secret: string | null | undefined): string | null;
/**
* The self-hosted environment runner, composed from the control-plane
* {@link WorkPoller} and the per-session {@link SessionToolRunner}.
*
* For each claimed `session` work item it: builds the per-session
* {@link AgentToolContext}, downloads the session agent's skills
* (`setupSkills`), then runs a {@link SessionToolRunner} for the session
* while heartbeating the work-item lease on the same event loop; on exit it
* force-stops the work item (unless the lease was lost, in which case the item
* is left to whoever holds it now), cleans up the downloaded skills, and loops
* to the next one. The lease heartbeat reports `state === "stopping"` / a lost
* lease back into the run by aborting the session runner.
*
* The `environmentKey` is the worker's standing credential. When a claimed
* work item carries a per-item `secret` (a short-lived payload the poll
* response may populate), the sessions token extracted from it is preferred
* over the environment key for that item's heartbeat / force-stop /
* skill-download / session calls; polling itself always uses the environment
* key, and items without a usable secret fall back to it entirely.
*
* Use {@link EnvironmentWorker.handleItem} if you already hold a claimed work
* item (e.g. a `worker poll --on-work` script handed one to a fresh process) and
* just want the per-item flow without the poll loop — with no arguments it reads
* the `ANTHROPIC_*` env vars that command sets.
*
* Construct it via `client.beta.environments.work.worker({ ... })` (or
* `new EnvironmentWorker({ client, ... })` directly).
*
* @example
* ```ts
* // Long-running daemon: poll for work, serve each session, loop.
* await client.beta.environments.work
* .worker({ environmentId, environmentKey, workdir: '/workspace' })
* .run(AbortSignal.timeout(60 * 60_000));
*
* // Already-claimed item (e.g. inside `ant worker poll --on-work ...`):
* await client.beta.environments.work.worker({ workdir: '/workspace' }).handleItem();
* ```
*/
export declare class EnvironmentWorker {
#private;
readonly client: Anthropic;
readonly environmentId: string | undefined;
readonly environmentKey: string | undefined;
readonly tools: EnvironmentWorkerTools | undefined;
readonly workdir: string;
/** @deprecated Never set; see {@link EnvironmentWorkerOptions.unrestrictedPaths}. */
readonly unrestrictedPaths: boolean | undefined;
readonly maxFileBytes: number | null | undefined;
readonly maxIdleMs: number | undefined;
readonly memorySyncIntervalMs: number | null | undefined;
readonly memorySyncDeletions: MemoryDeleteMode;
readonly workerId: string | undefined;
readonly requestOptions: BetaToolRunnerRequestOptions | undefined;
constructor(opts: Omit<EnvironmentWorkerOptions, 'unrestrictedPaths'>);
/** @deprecated `unrestrictedPaths` is no longer accepted — see {@link EnvironmentWorkerOptions.unrestrictedPaths}. */
constructor(opts: Omit<EnvironmentWorkerOptions, 'unrestrictedPaths'> & {
unrestrictedPaths: boolean;
});
/**
* Poll the environment and service each claimed session until the supplied
* signal (or the one passed to the constructor) aborts. Throws if
* `environmentId` / `environmentKey` were not provided to the constructor.
*/
run(signal?: AbortSignal): Promise<void>;
/**
* Service a single, already-claimed work item without the poll loop: build the
* per-session {@link AgentToolContext} (workdir from this worker's options),
* download the session agent's skills (`setupSkills`), run a
* {@link SessionToolRunner} for the session while heartbeating the work-item
* lease, and force-stop the work item on exit (whether the runner finishes
* normally, throws, or the control plane signals shutdown). The one
* exception is a lost lease: the item then belongs to the queue or another
* worker and is left alone.
*
* Use this when something else does the claiming — e.g. a `worker poll
* --on-work` script that hands an already-claimed item to a fresh process. The
* work id / environment id / session id each fall back to `ANTHROPIC_WORK_ID` /
* `ANTHROPIC_ENVIRONMENT_ID` / `ANTHROPIC_SESSION_ID` (the env vars that
* command sets) when not passed; the environment key resolves from this
* option, then the worker's own `environmentKey`, then
* `ANTHROPIC_ENVIRONMENT_KEY`, and is needed only when the work item's
* `secret` yields no sessions token — a host that receives only the
* per-item secret runs without ever holding the key. With no arguments
* inside that command it just works. Throws a clear error naming the first
* required value still missing after resolution, and — rather than ever
* running unauthenticated — when neither a sessions token nor an
* environment key resolved. Throws `SessionMemoryError` when the
* session has memory stores attached but they cannot be mounted — the work
* item carried no sessions token (unless `memorySyncIntervalMs` turned
* memory off), or a store failed to download.
*
* `workSecret` is the work item's per-item `secret` payload from the poll
* response, falling back to `ANTHROPIC_WORK_SECRET`; unlike the others it is
* optional — when present, the sessions token extracted from it is preferred
* as the Bearer credential for this item's heartbeat / force-stop / session
* calls; when absent (or undecodable) those calls use the environment key.
*/
handleItem(opts?: HandleItemOptions): Promise<void>;
}
//# sourceMappingURL=worker.d.mts.map