@lunora/container 1.0.0-alpha.4 → 1.0.0-alpha.41

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/index.d.mts CHANGED
@@ -1,15 +1,75 @@
1
- import { a as ContainerConfig, C as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/types.d-DAOLRiZQ.mjs";
2
- export type { B as BuildImageSource, c as ContainerInstanceType, d as ContainerReadinessCheck, e as ContainerRollout, f as CustomContainerInstanceType, g as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/types.d-DAOLRiZQ.mjs";
3
- /**
4
- * The `ctx.containers` action surface: typed handles over the `CONTAINER_*`
5
- * Durable Object namespace bindings the config layer reconciles.
6
- *
7
- * Deliberately structural (no `@cloudflare/containers` import): a Durable
8
- * Object namespace stub is all that is needed to route a request to a
9
- * container-enabled DO, so this module stays Node-safe and the test double
10
- * below can satisfy the exact same shape without a workerd runtime.
11
- */
12
- /** Options for explicitly starting an instance (mirrors `@cloudflare/containers`). */
1
+ import { D as DurableObjectJurisdiction, a as ContainerConfig, C as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-KcQu2ZT_.mjs";
2
+ export type { B as BuildImageSource, c as ContainerInstanceType, d as ContainerReadinessCheck, e as ContainerRollout, f as CustomContainerInstanceType, g as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/jurisdiction.d-KcQu2ZT_.mjs";
3
+ /**
4
+ * Per-call options for `ContainerHandle.exec`.
5
+ */
6
+ interface ContainerExecOptions {
7
+ /** Arguments passed to `command`, unshelled — the container must not concatenate them into a shell string. */
8
+ args?: ReadonlyArray<string>;
9
+ /** Working directory for the command, relative to the container's own root. */
10
+ cwd?: string;
11
+ /** Extra environment for this command only, merged over the container's env. */
12
+ env?: Readonly<Record<string, string>>;
13
+ /**
14
+ * Cap on the response body, in bytes. The whole `{code,stdout,stderr}`
15
+ * document has to be held in memory to be parsed, and a build box or job
16
+ * runner routinely writes tens of megabytes — a single unbounded `exec`
17
+ * that returns more than the isolate's memory limit kills the isolate and
18
+ * every other in-flight request sharing it, not just this call. So a
19
+ * runner that overruns the cap fails the call loudly rather than taking
20
+ * the shard down with it; raise this (or have the runner cap its own
21
+ * output) when a command legitimately produces more.
22
+ *
23
+ * Default {@link DEFAULT_EXEC_MAX_OUTPUT_BYTES} (1MB).
24
+ */
25
+ maxOutputBytes?: number;
26
+ /**
27
+ * Abort the call. Composed with {@link ContainerExecOptions.timeoutMs} when
28
+ * both are given — whichever fires first wins.
29
+ */
30
+ signal?: AbortSignal;
31
+ /**
32
+ * Give up after this many ms. Covers the whole call — the request *and*
33
+ * reading the response body, since `fetch` resolves on headers and a
34
+ * runner that answers `200` and then stalls mid-body would otherwise sit
35
+ * past the deadline. Sent to the container as well, so a well-behaved
36
+ * runner can kill the process rather than leak it when the caller walks
37
+ * away.
38
+ */
39
+ timeoutMs?: number;
40
+ }
41
+ /**
42
+ * The outcome of a `ContainerHandle.exec` call.
43
+ *
44
+ * A non-zero `code` is **not** an error: a command that ran and failed is a
45
+ * result, and the caller decides what to do with it. Only a failure to *run*
46
+ * the command — transport, a non-2xx from the runner, an unparseable body —
47
+ * throws.
48
+ */
49
+ interface ContainerExecResult {
50
+ /** Process exit code. Non-zero means the command ran and failed. */
51
+ code: number;
52
+ /** Everything the command wrote to stderr. */
53
+ stderr: string;
54
+ /** Everything the command wrote to stdout. */
55
+ stdout: string;
56
+ }
57
+ /**
58
+ * The route `ContainerHandle.exec` POSTs to. Namespaced under
59
+ * `/__lunora/` so it cannot collide with an application route the container
60
+ * already serves — the previous ad-hoc convention was a bare `/exec`, which an
61
+ * app could plausibly own for its own purposes.
62
+ *
63
+ * Exported because it is a *contract*, not an implementation detail: a
64
+ * container image has to serve exactly this route, and `@lunora/agent`'s
65
+ * human-in-the-loop gate has to recognise it. Both had it hard-coded as a
66
+ * second literal, which drifts silently — and on the gate's side, drift
67
+ * un-gates model-chosen command execution.
68
+ */
69
+ declare const CONTAINER_EXEC_PATH = "/__lunora/exec";
70
+ /**
71
+ * Options for explicitly starting an instance (mirrors `@cloudflare/containers`).
72
+ */
13
73
  interface ContainerStartOptions {
14
74
  /** Override outbound internet access for this start. */
15
75
  enableInternet?: boolean;
@@ -20,7 +80,9 @@ interface ContainerStartOptions {
20
80
  /** Metadata labels attached for metrics/observability. */
21
81
  labels?: Record<string, string>;
22
82
  }
23
- /** A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time. */
83
+ /**
84
+ * A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time.
85
+ */
24
86
  interface ContainerInstanceState {
25
87
  [key: string]: unknown;
26
88
  /** Process exit code, present once the instance has `stopped_with_code`. */
@@ -46,65 +108,82 @@ interface ContainerStubLike {
46
108
  stop?: (signal?: number | string) => Promise<void>;
47
109
  }
48
110
  /**
49
- * Cloudflare Durable Object data-residency jurisdiction. Widening union —
50
- * Cloudflare adds values over time.
51
- * @see https://developers.cloudflare.com/durable-objects/reference/data-location/
52
- */
53
- type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
54
- /** What the client needs from a Durable Object namespace binding. */
111
+ * What the client needs from a Durable Object namespace binding.
112
+ */
55
113
  interface ContainerNamespaceLike {
56
114
  get: (id: unknown) => ContainerStubLike;
57
115
  idFromName: (name: string) => unknown;
58
116
  /**
59
- * Derive a jurisdiction-restricted subnamespace. Optional because older
60
- * workers-types releases (and test doubles) may not expose it.
61
- */
117
+ * Derive a jurisdiction-restricted subnamespace. Optional because older
118
+ * workers-types releases (and test doubles) may not expose it.
119
+ */
62
120
  jurisdiction?: (jurisdiction: DurableObjectJurisdiction) => ContainerNamespaceLike;
63
121
  }
64
- /** A handle on one container instance (one Durable Object). */
122
+ /**
123
+ * A handle on one container instance (one Durable Object).
124
+ */
65
125
  interface ContainerHandle {
66
126
  /**
67
- * Send an HTTP (or WebSocket-upgrade) request to the container. A path
68
- * string (`"/transcode"`) is resolved against a synthetic origin; a full
69
- * `Request`/URL passes through unchanged.
70
- */
127
+ * Run a command inside the container and return its exit code and output.
128
+ *
129
+ * A container is an HTTP server, so there is no platform-level exec to call:
130
+ * the command is POSTed to `/__lunora/exec` and the container app
131
+ * serves that route. What this method adds over hand-rolling that fetch is
132
+ * the **contract** — a pinned path, a typed request and response, and the
133
+ * distinction between "the command failed" (a `code`) and "the command could
134
+ * not be run" (a throw). Before it existed every caller invented its own
135
+ * `/exec` convention and read the raw body back as if it were output, which
136
+ * silently turned a runner's 500 into a successful-looking result.
137
+ *
138
+ * The container side must accept `{ args, command, cwd, env, timeoutMs }`
139
+ * and answer `{ code, stdout, stderr }` as JSON.
140
+ */
141
+ exec: (command: string, options?: ContainerExecOptions) => Promise<ContainerExecResult>;
142
+ /**
143
+ * Send an HTTP (or WebSocket-upgrade) request to the container. A path
144
+ * string (`"/transcode"`) is resolved against a synthetic origin; a full
145
+ * `Request`/URL passes through unchanged.
146
+ */
71
147
  fetch: (input: Request | string, init?: RequestInit) => Promise<Response>;
72
148
  /**
73
- * Return a handle that routes every request to `targetPort` on the
74
- * container instead of the definition's `defaultPort` — for multi-port
75
- * containers (declare the ports in `requiredPorts`). Sets the
76
- * `cf-container-target-port` header the way `@cloudflare/containers`'
77
- * `switchPort` does, so it composes with `.get()`, `.any()`, and `.pool()`:
78
- * `ctx.containers.app.get("u1").port(9090).fetch("/admin")`.
79
- */
149
+ * Return a handle that routes every request to `targetPort` on the
150
+ * container instead of the definition's `defaultPort` — for multi-port
151
+ * containers (declare the ports in `requiredPorts`). Sets the
152
+ * `cf-container-target-port` header the way `@cloudflare/containers`'
153
+ * `switchPort` does, so it composes with `.get()`, `.any()`, and `.pool()`:
154
+ * `ctx.containers.app.get("u1").port(9090).fetch("/admin")`.
155
+ */
80
156
  port: (targetPort: number) => ContainerHandle;
81
157
  }
82
158
  /**
83
- * A handle on a *named* instance (from `.get(name)`) — `fetch` plus explicit
84
- * lifecycle control. The per-entity pattern (a sandbox per user, a room per
85
- * game, a job runner per id) often needs to tear down or inspect the instance
86
- * rather than wait for `sleepAfter`, so these wrap the container DO's
87
- * `start`/`stop`/`destroy`/`getState`.
88
- */
159
+ * A handle on a *named* instance (from `.get(name)`) — `fetch` plus explicit
160
+ * lifecycle control. The per-entity pattern (a sandbox per user, a room per
161
+ * game, a job runner per id) often needs to tear down or inspect the instance
162
+ * rather than wait for `sleepAfter`, so these wrap the container DO's
163
+ * `start`/`stop`/`destroy`/`getState`.
164
+ */
89
165
  interface ContainerInstanceHandle extends ContainerHandle {
90
166
  /** Stop and discard the instance (its ephemeral disk is lost). */
91
167
  destroy: () => Promise<void>;
92
168
  /**
93
- * Adjust this instance's egress allow/deny lists at runtime — the dynamic
94
- * counterpart to the static `allowedHosts`/`deniedHosts` config. Useful for
95
- * per-tenant egress policy. Requires the worker to export `ContainerProxy`
96
- * (codegen re-exports it from the generated container file whenever any
97
- * container is defined, so the runtime controls always work).
98
- */
169
+ * Adjust this instance's egress allow/deny lists at runtime — the dynamic
170
+ * counterpart to the static `allowedHosts`/`deniedHosts` config. Useful for
171
+ * per-tenant egress policy. Requires the worker to export `ContainerProxy`
172
+ * (codegen re-exports it from the generated container file whenever any
173
+ * container is defined, so the runtime controls always work).
174
+ */
99
175
  egress: ContainerEgressControls;
100
176
  /** Read the instance's current runtime state. */
101
177
  getState: () => Promise<ContainerInstanceState>;
102
178
  /**
103
- * Reset the instance's `sleepAfter` idle timer. The platform renews it on
104
- * each request automatically, but WebSocket message activity does not yet
105
- * renew it (cloudflare/containers#147) call this on inbound WS traffic to
106
- * keep a busy socket's container awake.
107
- */
179
+ * Reset the instance's `sleepAfter` idle timer. The platform renews it on
180
+ * each proxied request, and because `@lunora/container` proxies WebSocket
181
+ * frames through the Durable Object, message traffic on an open socket
182
+ * renews it too (the WebSocket-keepalive gap of cloudflare/containers#147 is
183
+ * closed in the bundled base). This manual control is the escape hatch for
184
+ * keeping a container awake during activity that is neither an HTTP request
185
+ * nor a WS message — e.g. a long out-of-band job running inside it.
186
+ */
108
187
  renewActivityTimeout: () => Promise<void>;
109
188
  /** Explicitly start the instance, optionally with per-instance env/entrypoint. */
110
189
  start: (options?: ContainerStartOptions) => Promise<void>;
@@ -112,11 +191,11 @@ interface ContainerInstanceHandle extends ContainerHandle {
112
191
  stop: (signal?: number | string) => Promise<void>;
113
192
  }
114
193
  /**
115
- * Runtime egress-firewall controls for a named instance (`handle.egress.*`).
116
- * Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
117
- * an app can tighten or relax a single instance's allowed/denied hosts after
118
- * start without redeploying.
119
- */
194
+ * Runtime egress-firewall controls for a named instance (`handle.egress.*`).
195
+ * Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
196
+ * an app can tighten or relax a single instance's allowed/denied hosts after
197
+ * start without redeploying.
198
+ */
120
199
  interface ContainerEgressControls {
121
200
  /** Add one hostname (or glob) to the allow-list. */
122
201
  allow: (hostname: string) => Promise<void>;
@@ -131,53 +210,96 @@ interface ContainerEgressControls {
131
210
  /** Replace the entire deny-list. */
132
211
  setDenied: (hosts: ReadonlyArray<string>) => Promise<void>;
133
212
  }
134
- /** The per-definition accessor exposed as `ctx.containers.&lt;exportName>`. */
213
+ /**
214
+ * The per-definition accessor exposed as `ctx.containers.<exportName>`.
215
+ */
135
216
  interface ContainerAccessor {
136
217
  /**
137
- * A random instance from a fixed pool of `count` (defaults to the
138
- * definition's `maxInstances`, else 3 — mirroring `getRandom` from
139
- * `@cloudflare/containers`). For stateless, interchangeable workloads.
140
- */
141
- any: (count?: number) => ContainerHandle;
142
- /** The instance for `name` one container per entity (user, room, job…), with lifecycle control. */
143
- get: (name: string) => ContainerInstanceHandle;
218
+ * A random instance from a fixed pool of `count` (defaults to the
219
+ * definition's `maxInstances`, else 3 — mirroring `getRandom` from
220
+ * `@cloudflare/containers`). For stateless, interchangeable workloads.
221
+ *
222
+ * Like `.get()`, a path/URL-string fetch transparently retries the
223
+ * cold-start "instance is provisioning" transients (cloudflare/containers#45,
224
+ * #139); pass {@link InstanceRetryOptions} to tune or disable it.
225
+ */
226
+ any: (count?: number, options?: InstanceRetryOptions) => ContainerHandle;
144
227
  /**
145
- * A resilient handle over the pool: each `fetch` picks a random instance and,
146
- * on a thrown error or a retryable response (5xx by default), retries on a
147
- * freshly-picked instance with exponential backoff. Until Cloudflare ships
148
- * native autoscaling + health-aware routing this is the recommended way to
149
- * call a stateless container pool it rides over a single cold/unhealthy
150
- * instance instead of failing the whole request.
151
- *
152
- * Because a retry re-issues the request, pass a **replayable** body a path
153
- * string plus an `init.body` string/`ArrayBuffer` (re-created each attempt).
154
- * A pre-built `Request` carrying a stream body can only be sent once, so it
155
- * is not retry-safe here; use `.get()`/`.any()` for those.
156
- */
228
+ * The instance for `name` one container per entity (user, room, job…),
229
+ * with lifecycle control.
230
+ *
231
+ * A path/URL-string fetch transparently retries the platform's cold-start
232
+ * transients "there is no Container instance available" / "container is
233
+ * not listening" while an instance is still provisioning
234
+ * (cloudflare/containers#45, #139) — on the *same* instance with backoff,
235
+ * since the request never reached the app. Pass {@link InstanceRetryOptions}
236
+ * to tune attempts/backoff or disable it (`{ attempts: 1 }`). A pre-built
237
+ * `Request` (possibly a one-shot stream body) is sent once, never retried.
238
+ */
239
+ get: (name: string, options?: InstanceRetryOptions) => ContainerInstanceHandle;
240
+ /**
241
+ * A resilient handle over the pool: each `fetch` picks a random instance and,
242
+ * on a thrown error or a retryable response (5xx by default), retries on a
243
+ * freshly-picked instance with exponential backoff. Until Cloudflare ships
244
+ * native autoscaling + health-aware routing this is the recommended way to
245
+ * call a stateless container pool — it rides over a single cold/unhealthy
246
+ * instance instead of failing the whole request.
247
+ *
248
+ * Because a retry re-issues the request, pass a **replayable** body — a path
249
+ * string plus an `init.body` string/`ArrayBuffer` (re-created each attempt).
250
+ * A pre-built `Request` carrying a stream body can only be sent once, so it
251
+ * is not retry-safe here; use `.get()`/`.any()` for those.
252
+ */
157
253
  pool: (options?: PoolOptions) => ContainerHandle;
158
254
  }
159
- /** Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}. */
255
+ /**
256
+ * Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}.
257
+ */
160
258
  interface PoolOptions {
161
259
  /** Total attempts before giving up (each on a freshly-picked instance). Default 3. */
162
260
  attempts?: number;
163
261
  /** Base backoff in ms between attempts; doubles each retry (0 disables the wait). Default 100. */
164
262
  backoffMs?: number;
165
263
  /**
166
- * Upper bound on a single backoff sleep, in ms. The doubling delay is clamped
167
- * to this ceiling so a large `attempts` count can't produce an unboundedly
168
- * long wait. Default {@link DEFAULT_MAX_BACKOFF_MS} (30s).
169
- */
264
+ * Upper bound on a single backoff sleep, in ms. The doubling delay is clamped
265
+ * to this ceiling so a large `attempts` count can't produce an unboundedly
266
+ * long wait. Default {@link DEFAULT_MAX_BACKOFF_MS} (30s).
267
+ */
170
268
  maxBackoffMs?: number;
171
269
  /**
172
- * Whether a *returned* response should be retried on another instance.
173
- * Defaults to retrying any `5xx`. A thrown error (network/start failure) is
174
- * always retried regardless of this predicate.
175
- */
270
+ * Whether a *returned* response should be retried on another instance.
271
+ * Defaults to retrying any `5xx`. A thrown error (network/start failure) is
272
+ * always retried regardless of this predicate.
273
+ *
274
+ * Applies to `fetch` only. `exec` retries on the cold-start transients
275
+ * alone, because its caller never chose the request and a command that
276
+ * already ran must not be re-run just because the runner failed afterwards.
277
+ */
176
278
  retryOn?: (response: Response) => boolean;
177
279
  /** Pool size to spread picks across. Defaults to the definition's `maxInstances`, else 3. */
178
280
  size?: number;
179
281
  }
180
- /** Wiring info for one definition, emitted by codegen into the generated DO. */
282
+ /**
283
+ * Tuning for the cold-start retry on a `.get()`/`.any()` handle. The retry fires
284
+ * only on the platform's provisioning transients (no-instance / not-listening /
285
+ * rate-limited — see {@link isColdStartTransient}), which is why it's safe by
286
+ * default: those responses mean the request never reached the container.
287
+ */
288
+ interface InstanceRetryOptions {
289
+ /**
290
+ * Total attempts on a cold-start transient before the last outcome is
291
+ * surfaced as-is. `1` disables the retry. Default
292
+ * {@link DEFAULT_COLD_START_ATTEMPTS}.
293
+ */
294
+ attempts?: number;
295
+ /** Base backoff in ms between attempts; doubles each retry (0 disables the wait). Default {@link DEFAULT_COLD_START_BACKOFF_MS}. */
296
+ backoffMs?: number;
297
+ /** Upper bound on a single backoff sleep, in ms. Default {@link DEFAULT_MAX_BACKOFF_MS} (30s). */
298
+ maxBackoffMs?: number;
299
+ }
300
+ /**
301
+ * Wiring info for one definition, emitted by codegen into the generated DO.
302
+ */
181
303
  interface ContainerBindingSpec {
182
304
  /** Durable Object binding name, e.g. `CONTAINER_TRANSCODER`. */
183
305
  binding: string;
@@ -187,70 +309,212 @@ interface ContainerBindingSpec {
187
309
  maxInstances?: number;
188
310
  }
189
311
  /**
190
- * Build the `ctx.containers` record from the Worker `env`. Called by the
191
- * generated ShardDO with the specs codegen derived from
192
- * `lunora/containers.ts`. A missing binding doesn't throw here — only when the
193
- * handle is actually used — so one unprovisioned container never breaks
194
- * unrelated functions.
195
- */
196
- declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction) => Record<string, ContainerAccessor>;
197
- /** A test handler: receives the request plus the targeted instance name. */
312
+ * Build the `ctx.containers` record from the Worker `env`. Called by the
313
+ * generated ShardDO with the specs codegen derived from `lunora/containers.ts`.
314
+ * A missing binding doesn't throw here — only when the handle is actually used —
315
+ * so one unprovisioned container never breaks unrelated functions.
316
+ *
317
+ * `traceparent` (the inbound RPC's W3C trace context, forwarded by the runtime
318
+ * and read off the request by the DO) is stamped onto every outbound container
319
+ * `fetch`, so the container's own spans stitch under the Worker's trace.
320
+ */
321
+ declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction, traceparent?: string) => Record<string, ContainerAccessor>;
322
+ /**
323
+ * A test handler: receives the request plus the targeted instance name.
324
+ */
198
325
  type ContainerTestHandler = (request: Request, instance: {
199
326
  name: string;
200
327
  }) => Promise<Response> | Response;
201
328
  /**
202
- * Docker-free test double for `ctx.containers`: each export name maps to a
203
- * fetch handler that plays the container. Mirrors the real shape exactly, so
204
- * action handlers under test can't tell the difference.
205
- *
206
- * ```ts
207
- * const containers = createContainerTestContext({
208
- * transcoder: (request) => new Response("ok"),
209
- * });
210
- * ```
211
- */
329
+ * Docker-free test double for `ctx.containers`: each export name maps to a
330
+ * fetch handler that plays the container. Mirrors the real shape exactly, so
331
+ * action handlers under test can't tell the difference.
332
+ *
333
+ * ```ts
334
+ * const containers = createContainerTestContext({
335
+ * transcoder: (request) => new Response("ok"),
336
+ * });
337
+ * ```
338
+ */
212
339
  declare const createContainerTestContext: (handlers: Record<string, ContainerTestHandler>) => Record<string, ContainerAccessor>;
213
340
  /**
214
- * Normalize a `ContainerImageSource` into the shape wrangler wants: a
215
- * Dockerfile path + build context for local builds, or a fully-qualified
216
- * reference for pre-built images.
217
- *
218
- * A local-path string whose basename starts with `Dockerfile` (so
219
- * `Dockerfile.dev` also counts) is used as-is with its directory as the build
220
- * context; any other path is treated as the build-context directory and the
221
- * Dockerfile is expected at `&lt;dir>/Dockerfile`.
222
- */
341
+ * Normalize a `ContainerImageSource` into the shape wrangler wants: a
342
+ * Dockerfile path + build context for local builds, or a fully-qualified
343
+ * reference for pre-built images.
344
+ *
345
+ * A local-path string whose basename starts with `Dockerfile` (so
346
+ * `Dockerfile.dev` also counts) is used as-is with its directory as the build
347
+ * context; any other path is treated as the build-context directory and the
348
+ * Dockerfile is expected at `<dir>/Dockerfile`.
349
+ */
223
350
  declare const normalizeContainerImage: (image: ContainerImageSource) => NormalizedContainerImage;
224
351
  /**
225
- * The generated Container DO class name for a `lunora/containers.ts` export:
226
- * `transcoder` → `TranscoderContainer`. wrangler's `containers[].class_name`
227
- * and the Durable Object binding's `class_name` both reference it, so codegen
228
- * and the config layer MUST derive it identically — always via this helper.
229
- */
352
+ * The generated Container DO class name for a `lunora/containers.ts` export:
353
+ * `transcoder` → `TranscoderContainer`. wrangler's `containers[].class_name`
354
+ * and the Durable Object binding's `class_name` both reference it, so codegen
355
+ * and the config layer MUST derive it identically — always via this helper.
356
+ */
230
357
  declare const containerClassName: (exportName: string) => string;
231
358
  /**
232
- * The Durable Object binding name for a container export: `transcoder` →
233
- * `CONTAINER_TRANSCODER`, `imageResizer` → `CONTAINER_IMAGE_RESIZER`. The
234
- * `CONTAINER_` prefix namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`
235
- * so a container export can never collide with the built-in bindings.
236
- */
359
+ * The Durable Object binding name for a container export: `transcoder` →
360
+ * `CONTAINER_TRANSCODER`, `imageResizer` → `CONTAINER_IMAGE_RESIZER`. The
361
+ * `CONTAINER_` prefix namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`
362
+ * so a container export can never collide with the built-in bindings.
363
+ */
237
364
  declare const containerBindingName: (exportName: string) => string;
238
365
  /**
239
- * The local image tag a Railpack `{ build }` container is built and pushed
240
- * under: `transcoder` → `lunora-transcoder:build`. The config reconciler writes
241
- * it as the wrangler `containers[].image`, and `lunora deploy` builds that tag
242
- * with Railpack and `wrangler containers push`es it before deploying — so all
243
- * three derive the tag from this one helper and can never disagree.
244
- */
366
+ * The local image tag a Railpack `{ build }` container is built and pushed
367
+ * under: `transcoder` → `lunora-transcoder:build`. The config reconciler writes
368
+ * it as the wrangler `containers[].image`, and `lunora deploy` builds that tag
369
+ * with Railpack and `wrangler containers push`es it before deploying — so all
370
+ * three derive the tag from this one helper and can never disagree.
371
+ */
245
372
  declare const containerBuildTag: (exportName: string) => string;
373
+ /**
374
+ * `defineContainer` is part of the experimental `@lunora/container` API and may change without a major version bump.
375
+ */
246
376
  declare const defineContainer: (config: ContainerConfig) => ContainerDefinition;
247
- /** True when a value is a `defineContainer` result (the runtime brand check). */
377
+ /**
378
+ * True when a value is a `defineContainer` result (the runtime brand check).
379
+ */
248
380
  declare const isContainerDefinition: (value: unknown) => value is ContainerDefinition;
249
381
  /**
250
- * The container's full environment at instance start: the static `env` block
251
- * plus every declared secret resolved from the Worker `env`. A declared secret
252
- * missing from the Worker env fails fast — starting the container without a
253
- * credential it was promised yields far worse errors downstream.
254
- */
382
+ * The container's full environment at instance start: the static `env` block
383
+ * plus every declared secret resolved from the Worker `env`. A declared secret
384
+ * missing from the Worker env fails fast — starting the container without a
385
+ * credential it was promised yields far worse errors downstream.
386
+ */
255
387
  declare const resolveContainerEnvVariables: (definition: ContainerDefinition, workerEnv: Record<string, unknown>, exportName?: string) => Record<string, string>;
256
- export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerEgressControls, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type DurableObjectJurisdiction, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
388
+ export { CONTAINER_EXEC_PATH,
389
+ /**
390
+ * `@lunora/container` — Cloudflare Containers for Lunora.
391
+ *
392
+ * This root export is Node-safe (no Cloudflare runtime imports): the
393
+ * `defineContainer` authoring surface, the naming/normalization helpers
394
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
395
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
396
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
397
+ * behind the `@lunora/container/do` subpath.
398
+ */
399
+ type ContainerAccessor,
400
+ /**
401
+ * `@lunora/container` — Cloudflare Containers for Lunora.
402
+ *
403
+ * This root export is Node-safe (no Cloudflare runtime imports): the
404
+ * `defineContainer` authoring surface, the naming/normalization helpers
405
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
406
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
407
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
408
+ * behind the `@lunora/container/do` subpath.
409
+ */
410
+ type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition,
411
+ /**
412
+ * `@lunora/container` — Cloudflare Containers for Lunora.
413
+ *
414
+ * This root export is Node-safe (no Cloudflare runtime imports): the
415
+ * `defineContainer` authoring surface, the naming/normalization helpers
416
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
417
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
418
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
419
+ * behind the `@lunora/container/do` subpath.
420
+ */
421
+ type ContainerEgressControls, type ContainerExecOptions, type ContainerExecResult,
422
+ /**
423
+ * `@lunora/container` — Cloudflare Containers for Lunora.
424
+ *
425
+ * This root export is Node-safe (no Cloudflare runtime imports): the
426
+ * `defineContainer` authoring surface, the naming/normalization helpers
427
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
428
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
429
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
430
+ * behind the `@lunora/container/do` subpath.
431
+ */
432
+ type ContainerHandle, type ContainerImageSource,
433
+ /**
434
+ * `@lunora/container` — Cloudflare Containers for Lunora.
435
+ *
436
+ * This root export is Node-safe (no Cloudflare runtime imports): the
437
+ * `defineContainer` authoring surface, the naming/normalization helpers
438
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
439
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
440
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
441
+ * behind the `@lunora/container/do` subpath.
442
+ */
443
+ type ContainerInstanceHandle,
444
+ /**
445
+ * `@lunora/container` — Cloudflare Containers for Lunora.
446
+ *
447
+ * This root export is Node-safe (no Cloudflare runtime imports): the
448
+ * `defineContainer` authoring surface, the naming/normalization helpers
449
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
450
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
451
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
452
+ * behind the `@lunora/container/do` subpath.
453
+ */
454
+ type ContainerInstanceState,
455
+ /**
456
+ * `@lunora/container` — Cloudflare Containers for Lunora.
457
+ *
458
+ * This root export is Node-safe (no Cloudflare runtime imports): the
459
+ * `defineContainer` authoring surface, the naming/normalization helpers
460
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
461
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
462
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
463
+ * behind the `@lunora/container/do` subpath.
464
+ */
465
+ type ContainerNamespaceLike,
466
+ /**
467
+ * `@lunora/container` — Cloudflare Containers for Lunora.
468
+ *
469
+ * This root export is Node-safe (no Cloudflare runtime imports): the
470
+ * `defineContainer` authoring surface, the naming/normalization helpers
471
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
472
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
473
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
474
+ * behind the `@lunora/container/do` subpath.
475
+ */
476
+ type ContainerStartOptions,
477
+ /**
478
+ * `@lunora/container` — Cloudflare Containers for Lunora.
479
+ *
480
+ * This root export is Node-safe (no Cloudflare runtime imports): the
481
+ * `defineContainer` authoring surface, the naming/normalization helpers
482
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
483
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
484
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
485
+ * behind the `@lunora/container/do` subpath.
486
+ */
487
+ type ContainerTestHandler,
488
+ /**
489
+ * `@lunora/container` — Cloudflare Containers for Lunora.
490
+ *
491
+ * This root export is Node-safe (no Cloudflare runtime imports): the
492
+ * `defineContainer` authoring surface, the naming/normalization helpers
493
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
494
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
495
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
496
+ * behind the `@lunora/container/do` subpath.
497
+ */
498
+ type DurableObjectJurisdiction,
499
+ /**
500
+ * `@lunora/container` — Cloudflare Containers for Lunora.
501
+ *
502
+ * This root export is Node-safe (no Cloudflare runtime imports): the
503
+ * `defineContainer` authoring surface, the naming/normalization helpers
504
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
505
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
506
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
507
+ * behind the `@lunora/container/do` subpath.
508
+ */
509
+ type InstanceRetryOptions, type NormalizedContainerImage,
510
+ /**
511
+ * `@lunora/container` — Cloudflare Containers for Lunora.
512
+ *
513
+ * This root export is Node-safe (no Cloudflare runtime imports): the
514
+ * `defineContainer` authoring surface, the naming/normalization helpers
515
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
516
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
517
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
518
+ * behind the `@lunora/container/do` subpath.
519
+ */
520
+ type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };