@opengeni/worker-bundle 2.0.1 → 2.0.3-canary.36199476632001
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/activities/agent-turn/agent-build.d.ts +2 -0
- package/dist/activities/agent-turn/code-search.d.ts +60 -0
- package/dist/activities/agent-turn/codex-capacity.d.ts +13 -0
- package/dist/activities/agent-turn/errors.d.ts +12 -1
- package/dist/activities/agent-turn/failure-settlement.d.ts +1 -1
- package/dist/activities/agent-turn/governance-model.d.ts +2 -0
- package/dist/activities/agent-turn/history.d.ts +2 -0
- package/dist/activities/agent-turn/media-artifacts.d.ts +5 -3
- package/dist/activities/agent-turn/session-title.d.ts +32 -2
- package/dist/activities/agent-turn/tool-environment.d.ts +4 -0
- package/dist/activities/context-compaction.d.ts +10 -2
- package/dist/activities/knowledge-indexing.d.ts +19 -0
- package/dist/activities/retained-screenshots.d.ts +7 -2
- package/dist/activities/sandbox-lease.d.ts +3 -4
- package/dist/{activities-control-QA6OLRQY.js → activities-control-I72CRMAE.js} +283 -35
- package/dist/activities-control-I72CRMAE.js.map +1 -0
- package/dist/{activities-turn-YVVKCGAK.js → activities-turn-CSDKK4N3.js} +531 -77
- package/dist/activities-turn-CSDKK4N3.js.map +1 -0
- package/dist/artifact-outbox-entry.js +3 -0
- package/dist/artifact-outbox-entry.js.map +1 -1
- package/dist/{chunk-M3NVMF2V.js → chunk-7M6G2SCF.js} +172 -17
- package/dist/chunk-7M6G2SCF.js.map +1 -0
- package/dist/{chunk-I7HKKMUJ.js → chunk-DSPP6CZL.js} +48 -3
- package/dist/chunk-DSPP6CZL.js.map +1 -0
- package/dist/index.js +10 -5
- package/dist/index.js.map +1 -1
- package/dist/observability-metrics.d.ts +11 -1
- package/dist/sandbox-resume.d.ts +46 -0
- package/dist/workflow-bundle.js +80 -2
- package/dist/workflows/session.d.ts +30 -0
- package/package.json +20 -19
- package/src/activities/agent-turn/agent-build.ts +4 -0
- package/src/activities/agent-turn/code-search.ts +275 -0
- package/src/activities/agent-turn/codex-capacity.ts +37 -2
- package/src/activities/agent-turn/compaction-prep.ts +52 -16
- package/src/activities/agent-turn/errors.ts +67 -4
- package/src/activities/agent-turn/failure-settlement.ts +40 -8
- package/src/activities/agent-turn/governance-model.ts +17 -1
- package/src/activities/agent-turn/history.ts +14 -1
- package/src/activities/agent-turn/media-artifacts.ts +2 -1
- package/src/activities/agent-turn/run.ts +4 -0
- package/src/activities/agent-turn/sandbox-establish.ts +12 -1
- package/src/activities/agent-turn/sandbox-runtime.ts +25 -9
- package/src/activities/agent-turn/session-title.ts +73 -3
- package/src/activities/agent-turn/stream-attempt.ts +27 -15
- package/src/activities/agent-turn/tool-environment.ts +65 -0
- package/src/activities/context-compaction.ts +49 -14
- package/src/activities/knowledge-indexing.ts +240 -15
- package/src/activities/retained-screenshots.ts +82 -11
- package/src/activities/sandbox-lease.ts +141 -21
- package/src/activities/scheduled-tasks.ts +18 -2
- package/src/activity-services.ts +16 -4
- package/src/editable-artifact-hint-broker.ts +3 -0
- package/src/index.ts +2 -2
- package/src/observability-metrics.ts +70 -1
- package/src/personal-github-git-credentials.ts +2 -0
- package/src/sandbox-resume.ts +211 -5
- package/src/workflows/activities.ts +14 -1
- package/src/workflows/session.ts +102 -6
- package/dist/activities-control-QA6OLRQY.js.map +0 -1
- package/dist/activities-turn-YVVKCGAK.js.map +0 -1
- package/dist/chunk-I7HKKMUJ.js.map +0 -1
- package/dist/chunk-M3NVMF2V.js.map +0 -1
|
@@ -130,6 +130,9 @@ async function connectEditableArtifactHintBroker(input) {
|
|
|
130
130
|
name,
|
|
131
131
|
reconnect: true,
|
|
132
132
|
maxReconnectAttempts: -1,
|
|
133
|
+
// Same policy as the event bus: a broker or auth-callout restart must not
|
|
134
|
+
// permanently close this connection after two identical auth errors.
|
|
135
|
+
ignoreAuthErrorAbort: true,
|
|
133
136
|
reconnectTimeWait: 2e3,
|
|
134
137
|
reconnectJitter: 1e3,
|
|
135
138
|
reconnectJitterTLS: 1e3,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editable-artifact-outbox-service.ts","../src/editable-artifact-outbox-dispatcher.ts","../src/editable-artifact-hint-broker.ts","../src/artifact-outbox-entry.ts"],"sourcesContent":["import {\n dbSearchPath,\n getArtifactOutboxSettings,\n resolveNatsControlPlaneAuth,\n type ArtifactOutboxSettings,\n} from \"@opengeni/config\";\nimport type { EditableArtifactOutboxDispatchSummary } from \"@opengeni/core\";\nimport { createObservability, type Observability } from \"@opengeni/observability\";\n\nimport {\n EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV,\n EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE,\n createEditableArtifactOutboxWorker,\n type EditableArtifactOutboxWorkerRuntime,\n} from \"./editable-artifact-outbox-dispatcher\";\nimport type { EditableArtifactHintNatsAuth } from \"./editable-artifact-hint-broker\";\n\nexport type EditableArtifactOutboxServiceState =\n | \"starting\"\n | \"ready\"\n | \"draining\"\n | \"stopped\"\n | \"failed\";\n\nexport interface EditableArtifactOutboxRuntimePort {\n start(): Promise<void>;\n drain(): boolean;\n stop(): Promise<void>;\n check(signal?: AbortSignal): Promise<void>;\n readonly dispatcher: Readonly<{\n dispatchOnce(): Promise<EditableArtifactOutboxDispatchSummary>;\n }>;\n}\n\nexport type EditableArtifactOutboxService = Readonly<{\n state(): EditableArtifactOutboxServiceState;\n run(): Promise<void>;\n drain(reason?: string): boolean;\n close(): Promise<void>;\n dispatchOnce(): Promise<EditableArtifactOutboxDispatchSummary>;\n fetch(request: Request): Promise<Response>;\n}>;\n\nexport type CreateEditableArtifactOutboxServiceInput = Readonly<{\n runtime: EditableArtifactOutboxRuntimePort;\n observability: Observability;\n serviceName: string;\n environment: string;\n deploymentRevision?: string;\n readinessTimeoutMs?: number;\n}>;\n\nexport type ProductionEditableArtifactOutboxServiceOptions = Readonly<{\n settings: ArtifactOutboxSettings;\n databaseUrl: string;\n declaredDatabaseRole: string;\n natsUrl: string;\n natsAuth: EditableArtifactHintNatsAuth;\n owner: string;\n databasePoolSize?: number;\n batchSize?: number;\n concurrency?: number;\n leaseDurationMs?: number;\n leaseRenewIntervalMs?: number;\n pollIntervalMs?: number;\n publishTimeoutMs?: number;\n retryBaseMs?: number;\n retryMaxMs?: number;\n}>;\n\n/** Compose the independently supervised production outbox dispatcher. */\nexport async function createProductionEditableArtifactOutboxService(\n options: ProductionEditableArtifactOutboxServiceOptions,\n): Promise<EditableArtifactOutboxService> {\n if (options.declaredDatabaseRole !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE) {\n throw new Error(\"Artifact outbox dispatcher database role declaration is invalid\");\n }\n const observability = createObservability(options.settings, {\n component: \"artifact-outbox-dispatcher\",\n });\n const databaseSearchPath = dbSearchPath(options.settings);\n const runtime = await createEditableArtifactOutboxWorker({\n dispatcherDatabaseUrl: options.databaseUrl,\n ...(databaseSearchPath ? { databaseSearchPath } : {}),\n ...(options.databasePoolSize === undefined\n ? {}\n : { databasePoolSize: options.databasePoolSize }),\n natsUrl: options.natsUrl,\n natsAuth: options.natsAuth,\n owner: options.owner,\n dispatcher: {\n ...(options.batchSize === undefined ? {} : { batchSize: options.batchSize }),\n ...(options.concurrency === undefined ? {} : { concurrency: options.concurrency }),\n ...(options.leaseDurationMs === undefined\n ? {}\n : { leaseDurationMs: options.leaseDurationMs }),\n ...(options.leaseRenewIntervalMs === undefined\n ? {}\n : { leaseRenewIntervalMs: options.leaseRenewIntervalMs }),\n ...(options.pollIntervalMs === undefined ? {} : { pollIntervalMs: options.pollIntervalMs }),\n ...(options.publishTimeoutMs === undefined\n ? {}\n : { publishTimeoutMs: options.publishTimeoutMs }),\n ...(options.retryBaseMs === undefined ? {} : { retryBaseMs: options.retryBaseMs }),\n ...(options.retryMaxMs === undefined ? {} : { retryMaxMs: options.retryMaxMs }),\n },\n metrics: {\n increment(outcome, count = 1) {\n observability.incrementCounter({\n name: \"opengeni_artifact_outbox_dispatch_total\",\n help: \"Editable artifact outbox dispatch actions by closed outcome.\",\n labels: { outcome },\n amount: count,\n });\n },\n observePublishSeconds(outcome, seconds) {\n observability.observeHistogram({\n name: \"opengeni_artifact_outbox_publish_seconds\",\n help: \"Editable artifact broker publication latency by closed outcome.\",\n labels: { outcome },\n value: seconds,\n });\n },\n },\n logger: {\n warn(message, attributes) {\n observability.warn(message, {\n errorClass: \"WorkerOperationError\",\n errorCode: \"worker_operation_failed\",\n origin: \"worker\",\n outcome: typeof attributes.code === \"string\" ? attributes.code : \"unknown\",\n });\n },\n },\n });\n return createEditableArtifactOutboxService({\n runtime,\n observability,\n serviceName: options.settings.serviceName,\n environment: options.settings.environment,\n deploymentRevision: options.settings.deploymentRevision,\n });\n}\n\nexport function createEditableArtifactOutboxService(\n input: CreateEditableArtifactOutboxServiceInput,\n): EditableArtifactOutboxService {\n let state: EditableArtifactOutboxServiceState = \"starting\";\n let runPromise: Promise<void> | null = null;\n let closePromise: Promise<void> | null = null;\n let readinessPromise: Promise<void> | null = null;\n const readinessTimeoutMs = input.readinessTimeoutMs ?? 2_000;\n\n const ready = (): Promise<void> => {\n if (readinessPromise) return readinessPromise;\n const abort = new AbortController();\n const check = withTimeout(input.runtime.check(abort.signal), readinessTimeoutMs, abort);\n readinessPromise = check;\n void check.then(\n () => {\n if (readinessPromise === check) readinessPromise = null;\n },\n () => {\n if (readinessPromise === check) readinessPromise = null;\n },\n );\n return check;\n };\n\n const run = (): Promise<void> => {\n if (runPromise) return runPromise;\n if (state !== \"starting\") {\n return Promise.reject(new Error(\"Artifact outbox dispatcher service cannot be restarted\"));\n }\n runPromise = (async () => {\n try {\n await ready();\n if ((state as EditableArtifactOutboxServiceState) === \"draining\") {\n state = \"stopped\";\n return;\n }\n const running = input.runtime.start();\n state = \"ready\";\n await running;\n const exitWasDraining = (state as EditableArtifactOutboxServiceState) === \"draining\";\n state = exitWasDraining ? \"stopped\" : \"failed\";\n if (!exitWasDraining) {\n throw new Error(\"Artifact outbox dispatcher exited without a drain request\");\n }\n } catch (error) {\n const caughtState = state as EditableArtifactOutboxServiceState;\n if (caughtState !== \"draining\" && caughtState !== \"stopped\") state = \"failed\";\n throw error;\n }\n })();\n return runPromise;\n };\n\n const drain = (_reason = \"shutdown\"): boolean => {\n if (state === \"draining\" || state === \"stopped\" || state === \"failed\") return false;\n state = \"draining\";\n input.runtime.drain();\n return true;\n };\n\n const close = (): Promise<void> => {\n if (closePromise) return closePromise;\n closePromise = (async () => {\n drain(\"close\");\n if (runPromise) await runPromise.catch(() => undefined);\n await input.runtime.stop();\n if (state !== \"failed\") state = \"stopped\";\n })();\n return closePromise;\n };\n\n const fetch = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method !== \"GET\") {\n return Response.json({ error: \"method_not_allowed\" }, { status: 405 });\n }\n if (url.pathname === \"/healthz\") {\n const ok = state !== \"failed\" && state !== \"stopped\";\n return Response.json(\n {\n service: input.serviceName,\n component: \"artifact-outbox-dispatcher\",\n environment: input.environment,\n ...(input.deploymentRevision ? { deploymentRevision: input.deploymentRevision } : {}),\n state,\n ok,\n },\n { status: ok ? 200 : 503 },\n );\n }\n if (url.pathname === \"/readyz\") {\n if (state !== \"ready\") {\n return Response.json(\n {\n ok: false,\n state,\n checks: { databaseRole: { ok: false }, nats: { ok: false } },\n },\n { status: 503 },\n );\n }\n try {\n await ready();\n return Response.json({\n ok: true,\n state,\n checks: { databaseRole: { ok: true }, nats: { ok: true } },\n });\n } catch {\n return Response.json(\n {\n ok: false,\n state,\n checks: { databaseRole: { ok: false }, nats: { ok: false } },\n },\n { status: 503 },\n );\n }\n }\n if (url.pathname === \"/metrics\") {\n return new Response(await input.observability.prometheusMetrics(), {\n status: 200,\n headers: { \"content-type\": \"text/plain; version=0.0.4; charset=utf-8\" },\n });\n }\n return Response.json({ error: \"not_found\" }, { status: 404 });\n };\n\n return Object.freeze({\n state: () => state,\n run,\n drain,\n close,\n dispatchOnce: async () => await input.runtime.dispatcher.dispatchOnce(),\n fetch,\n });\n}\n\nexport type EditableArtifactOutboxSidecarEnvironment = Readonly<{\n databaseUrl: string;\n declaredDatabaseRole: string;\n owner: string;\n httpPort: number;\n databasePoolSize: number;\n batchSize: number;\n concurrency: number;\n leaseDurationMs: number;\n leaseRenewIntervalMs: number;\n pollIntervalMs: number;\n publishTimeoutMs: number;\n retryBaseMs: number;\n retryMaxMs: number;\n}>;\n\nexport function readEditableArtifactOutboxSidecarEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n): EditableArtifactOutboxSidecarEnvironment | null {\n if (environment.OPENGENI_ARTIFACT_OUTBOX_ENABLED !== \"true\") return null;\n const declaredDatabaseRole = required(environment, \"OPENGENI_ARTIFACT_OUTBOX_DATABASE_ROLE\");\n if (declaredDatabaseRole !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_DATABASE_ROLE is invalid\");\n }\n const result = {\n databaseUrl: required(environment, EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV),\n declaredDatabaseRole,\n owner:\n environment.OPENGENI_ARTIFACT_OUTBOX_OWNER?.trim() ||\n `artifact-outbox-${process.pid}-${crypto.randomUUID()}`,\n httpPort: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_HTTP_PORT\", 9466, 1, 65_535),\n databasePoolSize: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_DB_POOL_SIZE\", 4, 1, 8),\n batchSize: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_BATCH_SIZE\", 32, 1, 1_000),\n concurrency: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_CONCURRENCY\", 8, 1, 128),\n leaseDurationMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_LEASE_MS\",\n 30_000,\n 1_000,\n 86_400_000,\n ),\n leaseRenewIntervalMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_RENEW_MS\",\n 10_000,\n 100,\n 43_199_999,\n ),\n pollIntervalMs: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_POLL_MS\", 500, 10, 60_000),\n publishTimeoutMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_PUBLISH_TIMEOUT_MS\",\n 5_000,\n 100,\n 60_000,\n ),\n retryBaseMs: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_RETRY_BASE_MS\", 500, 10, 60_000),\n retryMaxMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_RETRY_MAX_MS\",\n 60_000,\n 10,\n 86_400_000,\n ),\n } as const;\n if (result.leaseRenewIntervalMs >= result.leaseDurationMs) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_RENEW_MS must be less than lease duration\");\n }\n if (result.retryBaseMs > result.retryMaxMs) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_RETRY_BASE_MS must not exceed retry max\");\n }\n return Object.freeze(result);\n}\n\nexport async function createOutboxSidecarFromEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<Readonly<{ service: EditableArtifactOutboxService; httpPort: number }> | null> {\n const sidecar = readEditableArtifactOutboxSidecarEnvironment(environment);\n if (!sidecar) return null;\n const settings = getArtifactOutboxSettings(environment);\n const controlPlaneAuth = resolveNatsControlPlaneAuth(settings);\n const natsAuth: EditableArtifactHintNatsAuth = controlPlaneAuth\n ? {\n kind: \"user-password\",\n user: controlPlaneAuth.user,\n pass: controlPlaneAuth.password,\n }\n : { kind: \"anonymous\" };\n const service = await createProductionEditableArtifactOutboxService({\n settings,\n databaseUrl: sidecar.databaseUrl,\n declaredDatabaseRole: sidecar.declaredDatabaseRole,\n natsUrl: settings.natsUrl,\n natsAuth,\n owner: sidecar.owner,\n databasePoolSize: sidecar.databasePoolSize,\n batchSize: sidecar.batchSize,\n concurrency: sidecar.concurrency,\n leaseDurationMs: sidecar.leaseDurationMs,\n leaseRenewIntervalMs: sidecar.leaseRenewIntervalMs,\n pollIntervalMs: sidecar.pollIntervalMs,\n publishTimeoutMs: sidecar.publishTimeoutMs,\n retryBaseMs: sidecar.retryBaseMs,\n retryMaxMs: sidecar.retryMaxMs,\n });\n return Object.freeze({ service, httpPort: sidecar.httpPort });\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n milliseconds: number,\n abort: AbortController,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n abort.abort();\n reject(new Error(\"readiness check timed out\"));\n }, milliseconds);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nfunction required(environment: NodeJS.ProcessEnv, name: string): string {\n const value = environment[name]?.trim();\n if (!value) throw new Error(`${name} is required when artifact outbox dispatch is enabled`);\n return value;\n}\n\nfunction integer(\n environment: NodeJS.ProcessEnv,\n name: string,\n fallback: number,\n minimum: number,\n maximum: number,\n): number {\n const raw = environment[name];\n const value = raw === undefined ? fallback : Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${name} is outside its allowed range`);\n }\n return value;\n}\n\n// Compile-time assurance that production composition satisfies the service port.\nconst _runtimePort: EditableArtifactOutboxRuntimePort | undefined = undefined as\n | EditableArtifactOutboxWorkerRuntime\n | undefined;\nvoid _runtimePort;\n","import {\n EditableArtifactLiveOutboxDispatcher,\n MathEditableArtifactOutboxRandom,\n SystemEditableArtifactLiveClock,\n SystemEditableArtifactLiveScheduler,\n type EditableArtifactOutboxDispatcherOptions,\n type EditableArtifactOutboxLoggerPort,\n type EditableArtifactOutboxMetricsPort,\n type EditableArtifactOutboxDispatcherStorePort,\n type EditableArtifactLiveOutboxRecord,\n} from \"@opengeni/core\";\nimport {\n PostgresEditableArtifactStore,\n createDb,\n dbSql,\n type Database,\n type DbClient,\n} from \"@opengeni/db\";\n\nimport {\n connectEditableArtifactHintBroker,\n type ConfirmedNatsEditableArtifactHintBroker,\n type EditableArtifactHintNatsAuth,\n} from \"./editable-artifact-hint-broker\";\n\nexport const EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE =\n \"opengeni_artifact_outbox_dispatcher\";\nexport const EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV = \"OPENGENI_ARTIFACT_OUTBOX_DATABASE_URL\";\n\nexport type EditableArtifactOutboxWorkerOptions = Readonly<{\n /** Must authenticate as the dedicated dispatcher role, never the generic app role. */\n dispatcherDatabaseUrl: string;\n databaseSearchPath?: string;\n databasePoolSize?: number;\n natsUrl: string;\n natsAuth: EditableArtifactHintNatsAuth;\n owner?: string;\n dispatcher?: Omit<EditableArtifactOutboxDispatcherOptions, \"owner\">;\n metrics?: EditableArtifactOutboxMetricsPort;\n logger?: EditableArtifactOutboxLoggerPort;\n}>;\n\n/** Explicit lifecycle handle; hosts supervise `start()` and await `stop()` on drain. */\nexport class EditableArtifactOutboxWorkerRuntime {\n private readonly abort = new AbortController();\n private running: Promise<void> | null = null;\n private closing: Promise<void> | null = null;\n\n constructor(\n readonly dispatcher: EditableArtifactLiveOutboxDispatcher,\n private readonly broker: ConfirmedNatsEditableArtifactHintBroker,\n private readonly database: DbClient,\n ) {}\n\n start(): Promise<void> {\n if (this.closing) return Promise.reject(new Error(\"Artifact outbox worker is stopping\"));\n this.running ??= this.dispatcher.run(this.abort.signal);\n return this.running;\n }\n\n drain(): boolean {\n if (this.abort.signal.aborted) return false;\n this.abort.abort();\n return true;\n }\n\n async check(signal?: AbortSignal): Promise<void> {\n if (this.abort.signal.aborted || this.closing) {\n throw new Error(\"Artifact outbox worker is stopping\");\n }\n await Promise.all([\n assertDedicatedOutboxDispatcherDatabaseRole(this.database.db),\n this.broker.check(signal),\n ]);\n }\n\n stop(): Promise<void> {\n if (this.closing) return this.closing;\n this.closing = this.stopOnce();\n return this.closing;\n }\n\n private async stopOnce(): Promise<void> {\n this.drain();\n const running = this.running ? await Promise.allSettled([this.running]) : [];\n const cleanup = await Promise.allSettled([this.broker.close(), this.database.close()]);\n const failure = [...running, ...cleanup].find(\n (result): result is PromiseRejectedResult => result.status === \"rejected\",\n );\n if (failure) throw failure.reason;\n }\n}\n\n/**\n * Production composition. DB grants make the role a narrow capability: it can\n * execute only lease-fenced dispatcher functions and cannot read artifact rows.\n */\nexport async function createEditableArtifactOutboxWorker(\n options: EditableArtifactOutboxWorkerOptions,\n): Promise<EditableArtifactOutboxWorkerRuntime> {\n const dispatcherDatabaseUrl = dedicatedDispatcherDatabaseUrl(options.dispatcherDatabaseUrl);\n const databasePoolSize = options.databasePoolSize ?? 2;\n if (!Number.isSafeInteger(databasePoolSize) || databasePoolSize < 1 || databasePoolSize > 8) {\n throw new TypeError(\"Artifact outbox dispatcher DB pool size must be 1-8\");\n }\n const database = createDb(dispatcherDatabaseUrl, {\n max: databasePoolSize,\n ...(options.databaseSearchPath ? { searchPath: options.databaseSearchPath } : {}),\n });\n let broker: ConfirmedNatsEditableArtifactHintBroker;\n try {\n await assertDedicatedOutboxDispatcherDatabaseRole(database.db);\n broker = await connectEditableArtifactHintBroker({\n natsUrl: options.natsUrl,\n auth: options.natsAuth,\n });\n } catch (error) {\n await database.close();\n throw error;\n }\n const persistence = new PostgresEditableArtifactStore(database.db);\n const store = dispatcherStore(persistence);\n const dispatcher = new EditableArtifactLiveOutboxDispatcher(\n {\n store,\n broker,\n clock: new SystemEditableArtifactLiveClock(),\n scheduler: new SystemEditableArtifactLiveScheduler(),\n random: new MathEditableArtifactOutboxRandom(),\n ...(options.metrics ? { metrics: options.metrics } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n },\n {\n owner: options.owner ?? `artifact-outbox:${crypto.randomUUID()}`,\n ...options.dispatcher,\n },\n );\n return new EditableArtifactOutboxWorkerRuntime(dispatcher, broker, database);\n}\n\n/**\n * Verify the database identity and its negative capability at runtime. A DSN\n * username check alone is insufficient because PostgreSQL role inheritance,\n * SET ROLE, or a mis-provisioned grant could otherwise widen this worker.\n */\nexport async function assertDedicatedOutboxDispatcherDatabaseRole(db: Database): Promise<void> {\n const raw = await db.execute<{\n current_role: string;\n session_role: string;\n can_access_any_relation: boolean;\n can_access_any_sequence: boolean;\n }>(dbSql`\n select\n current_user::text as current_role,\n session_user::text as session_role,\n exists (\n select 1\n from pg_catalog.pg_class relation_row\n join pg_catalog.pg_namespace namespace_row\n on namespace_row.oid = relation_row.relnamespace\n where namespace_row.nspname = current_schema()\n and relation_row.relkind in ('r', 'p', 'v', 'm', 'f')\n and (\n has_table_privilege(current_user, relation_row.oid, 'SELECT')\n or has_table_privilege(current_user, relation_row.oid, 'INSERT')\n or has_table_privilege(current_user, relation_row.oid, 'UPDATE')\n or has_table_privilege(current_user, relation_row.oid, 'DELETE')\n or has_table_privilege(current_user, relation_row.oid, 'TRUNCATE')\n or has_table_privilege(current_user, relation_row.oid, 'REFERENCES')\n or has_table_privilege(current_user, relation_row.oid, 'TRIGGER')\n or has_any_column_privilege(current_user, relation_row.oid, 'SELECT')\n or has_any_column_privilege(current_user, relation_row.oid, 'INSERT')\n or has_any_column_privilege(current_user, relation_row.oid, 'UPDATE')\n or has_any_column_privilege(current_user, relation_row.oid, 'REFERENCES')\n )\n ) as can_access_any_relation,\n exists (\n select 1\n from pg_catalog.pg_class sequence_row\n join pg_catalog.pg_namespace namespace_row\n on namespace_row.oid = sequence_row.relnamespace\n where namespace_row.nspname = current_schema()\n and sequence_row.relkind = 'S'\n and (\n has_sequence_privilege(current_user, sequence_row.oid, 'USAGE')\n or has_sequence_privilege(current_user, sequence_row.oid, 'SELECT')\n or has_sequence_privilege(current_user, sequence_row.oid, 'UPDATE')\n )\n ) as can_access_any_sequence\n `);\n const rows = Array.isArray(raw) ? raw : ((raw as unknown as { rows?: unknown[] }).rows ?? []);\n const row = rows[0] as\n | {\n current_role?: unknown;\n session_role?: unknown;\n can_access_any_relation?: unknown;\n can_access_any_sequence?: unknown;\n }\n | undefined;\n if (\n row?.current_role !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE ||\n row.session_role !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE ||\n row.can_access_any_relation !== false ||\n row.can_access_any_sequence !== false\n ) {\n throw new Error(\"Artifact outbox dispatcher database connection has an unsafe role posture\");\n }\n}\n\nfunction dispatcherStore(\n persistence: PostgresEditableArtifactStore,\n): EditableArtifactOutboxDispatcherStorePort {\n return {\n claimLiveOutbox: async (input) =>\n (await persistence.claimLiveOutbox(\n input,\n )) as unknown as readonly EditableArtifactLiveOutboxRecord[],\n renewLiveOutbox: async (input) => await persistence.renewLiveOutbox(input),\n markLiveOutboxPublished: async (input) => await persistence.markLiveOutboxPublished(input),\n retryLiveOutbox: async (input) => await persistence.retryLiveOutbox(input),\n deadLetterLiveOutbox: async (input) => await persistence.deadLetterLiveOutbox(input),\n };\n}\n\nexport function dedicatedDispatcherDatabaseUrl(raw: string): string {\n if (typeof raw !== \"string\" || raw.length > 8_192 || raw.trim() !== raw) {\n throw new TypeError(`${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} is malformed`);\n }\n let url: URL;\n try {\n url = new URL(raw);\n } catch (cause) {\n throw new TypeError(`${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} is malformed`, { cause });\n }\n if (\n (url.protocol !== \"postgres:\" && url.protocol !== \"postgresql:\") ||\n decodeURIComponent(url.username) !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE\n ) {\n throw new TypeError(\n `${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} must authenticate as ${EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE}`,\n );\n }\n return raw;\n}\n","import {\n EDITABLE_ARTIFACT_HINT_MAX_BYTES,\n type EditableArtifactHintBrokerPort,\n} from \"@opengeni/core\";\nimport { connect, type NatsConnection } from \"@opengeni/events\";\n\nconst DEFAULT_CONNECTION_NAME = \"opengeni-editable-artifact-outbox\";\n\nexport type EditableArtifactHintNatsAuth =\n | Readonly<{ kind: \"user-password\"; user: string; pass: string }>\n | Readonly<{ kind: \"token\"; token: string }>\n | Readonly<{ kind: \"anonymous\" }>;\n\nexport type EditableArtifactHintNatsBrokerOptions = Readonly<{\n maxHintBytes?: number;\n}>;\n\nexport type EditableArtifactHintNatsConnection = Pick<\n NatsConnection,\n \"publish\" | \"flush\" | \"drain\" | \"close\" | \"closed\" | \"isClosed\" | \"isDraining\"\n>;\n\n/**\n * Core-NATS adapter for the durable outbox. A publish resolves only after a\n * server round-trip flush ACK. Reconnect buffering may create duplicates after\n * a timeout; hints are intentionally idempotent wakeups for durable gap-fill.\n */\nexport class ConfirmedNatsEditableArtifactHintBroker implements EditableArtifactHintBrokerPort {\n private readonly maxHintBytes: number;\n\n constructor(\n private readonly connection: EditableArtifactHintNatsConnection,\n options: EditableArtifactHintNatsBrokerOptions = {},\n ) {\n this.maxHintBytes = options.maxHintBytes ?? EDITABLE_ARTIFACT_HINT_MAX_BYTES;\n if (\n !Number.isSafeInteger(this.maxHintBytes) ||\n this.maxHintBytes < 1 ||\n this.maxHintBytes > EDITABLE_ARTIFACT_HINT_MAX_BYTES\n ) {\n throw new TypeError(\"Editable artifact NATS hint byte limit is invalid\");\n }\n }\n\n async publish(\n input: Readonly<{\n subject: string;\n payload: Uint8Array;\n signal: AbortSignal;\n }>,\n ): Promise<void> {\n assertSubject(input.subject);\n if (\n !(input.payload instanceof Uint8Array) ||\n input.payload.byteLength < 1 ||\n input.payload.byteLength > this.maxHintBytes\n ) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_backpressure\",\n \"Editable artifact hint exceeds the NATS envelope\",\n );\n }\n if (input.signal.aborted) throw abortedPublish();\n if (this.connection.isClosed() || this.connection.isDraining()) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS connection is closed\",\n );\n }\n try {\n this.connection.publish(input.subject, input.payload);\n await abortable(this.connection.flush(), input.signal);\n } catch (error) {\n if (input.signal.aborted) throw abortedPublish();\n if (error instanceof EditableArtifactNatsHintPublishError) throw error;\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS publish was not acknowledged\",\n { cause: error },\n );\n }\n }\n\n /**\n * A readiness probe must prove the server is reachable, not merely that the\n * client object has not observed closure yet. `flush()` is a bounded NATS\n * round trip and has the same acknowledgement semantics as publication.\n */\n async check(signal: AbortSignal = new AbortController().signal): Promise<void> {\n if (signal.aborted) throw abortedPublish();\n if (this.connection.isClosed() || this.connection.isDraining()) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS connection is unavailable\",\n );\n }\n try {\n await abortable(this.connection.flush(), signal);\n } catch (error) {\n if (error instanceof EditableArtifactNatsHintPublishError) throw error;\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS readiness round trip failed\",\n { cause: error },\n );\n }\n }\n\n async close(drainTimeoutMs = 5_000): Promise<void> {\n if (!Number.isSafeInteger(drainTimeoutMs) || drainTimeoutMs < 1 || drainTimeoutMs > 30_000) {\n throw new TypeError(\"Editable artifact NATS drain timeout is invalid\");\n }\n if (this.connection.isClosed()) return;\n if (this.connection.isDraining()) {\n await this.connection.closed();\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const drain = this.connection.drain();\n const outcome = await Promise.race([\n drain.then(\n () => \"drained\" as const,\n () => \"failed\" as const,\n ),\n new Promise<\"timed_out\">((resolve) => {\n timer = setTimeout(() => resolve(\"timed_out\"), drainTimeoutMs);\n }),\n ]);\n if (timer) clearTimeout(timer);\n if (outcome !== \"drained\" && !this.connection.isClosed()) {\n await this.connection.close();\n }\n }\n}\n\nexport class EditableArtifactNatsHintPublishError extends Error {\n constructor(\n readonly code: \"broker_unavailable\" | \"broker_backpressure\",\n message: string,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"EditableArtifactNatsHintPublishError\";\n }\n}\n\n/** Opens one resilient dispatcher identity; callers own `broker.close()`. */\nexport async function connectEditableArtifactHintBroker(\n input: Readonly<{\n natsUrl: string;\n auth: EditableArtifactHintNatsAuth;\n name?: string;\n maxHintBytes?: number;\n }>,\n): Promise<ConfirmedNatsEditableArtifactHintBroker> {\n const natsUrl = boundedText(input.natsUrl, \"NATS URL\", 2_048);\n const name = boundedText(input.name ?? DEFAULT_CONNECTION_NAME, \"NATS connection name\", 128);\n const auth = natsAuthOptions(input.auth);\n const connection = await connect({\n servers: natsUrl,\n name,\n reconnect: true,\n maxReconnectAttempts: -1,\n reconnectTimeWait: 2_000,\n reconnectJitter: 1_000,\n reconnectJitterTLS: 1_000,\n waitOnFirstConnect: true,\n pingInterval: 20_000,\n maxPingOut: 3,\n ...auth,\n });\n return new ConfirmedNatsEditableArtifactHintBroker(connection, {\n ...(input.maxHintBytes === undefined ? {} : { maxHintBytes: input.maxHintBytes }),\n });\n}\n\nfunction natsAuthOptions(auth: EditableArtifactHintNatsAuth): {\n user?: string;\n pass?: string;\n token?: string;\n} {\n if (auth.kind === \"anonymous\") return {};\n if (auth.kind === \"token\") return { token: boundedText(auth.token, \"NATS token\", 4_096) };\n return {\n user: boundedText(auth.user, \"NATS user\", 256),\n pass: boundedText(auth.pass, \"NATS password\", 4_096),\n };\n}\n\nfunction assertSubject(subject: string): void {\n const bytes = new TextEncoder().encode(subject).byteLength;\n if (\n bytes < 1 ||\n bytes > 1_024 ||\n subject.startsWith(\".\") ||\n subject.endsWith(\".\") ||\n subject.includes(\"..\") ||\n /[\\s*>]/u.test(subject)\n ) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_backpressure\",\n \"Editable artifact NATS subject is malformed\",\n );\n }\n}\n\nfunction boundedText(value: string, label: string, maxBytes: number): string {\n const bytes = new TextEncoder().encode(value).byteLength;\n if (bytes < 1 || bytes > maxBytes || value.trim() !== value) {\n throw new TypeError(`${label} is malformed`);\n }\n return value;\n}\n\nfunction abortedPublish(): EditableArtifactNatsHintPublishError {\n return new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS publish was aborted\",\n );\n}\n\nasync function abortable(operation: Promise<void>, signal: AbortSignal): Promise<void> {\n if (signal.aborted) throw abortedPublish();\n let remove: () => void = () => undefined;\n const aborted = new Promise<never>((_resolve, reject) => {\n const onAbort = () => reject(abortedPublish());\n signal.addEventListener(\"abort\", onAbort, { once: true });\n remove = () => signal.removeEventListener(\"abort\", onAbort);\n });\n try {\n await Promise.race([operation, aborted]);\n } finally {\n remove();\n }\n}\n","import { createOutboxSidecarFromEnvironment } from \"./editable-artifact-outbox-service\";\n\n/** Dedicated process: no Temporal/control worker is created or imported here. */\nexport async function runEditableArtifactOutboxSidecar(\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n const configured = await createOutboxSidecarFromEnvironment(environment);\n if (!configured) throw new Error(\"Editable artifact outbox sidecar is disabled\");\n const server = Bun.serve({\n hostname: \"0.0.0.0\",\n port: configured.httpPort,\n fetch: configured.service.fetch,\n });\n const stop = () => configured.service.drain(\"process signal\");\n process.on(\"SIGTERM\", stop);\n process.on(\"SIGINT\", stop);\n try {\n await configured.service.run();\n } finally {\n process.off(\"SIGTERM\", stop);\n process.off(\"SIGINT\", stop);\n server.stop(true);\n await configured.service.close();\n }\n}\n\nif (import.meta.main) {\n await runEditableArtifactOutboxSidecar();\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/editable-artifact-outbox-service.ts","../src/editable-artifact-outbox-dispatcher.ts","../src/editable-artifact-hint-broker.ts","../src/artifact-outbox-entry.ts"],"sourcesContent":["import {\n dbSearchPath,\n getArtifactOutboxSettings,\n resolveNatsControlPlaneAuth,\n type ArtifactOutboxSettings,\n} from \"@opengeni/config\";\nimport type { EditableArtifactOutboxDispatchSummary } from \"@opengeni/core\";\nimport { createObservability, type Observability } from \"@opengeni/observability\";\n\nimport {\n EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV,\n EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE,\n createEditableArtifactOutboxWorker,\n type EditableArtifactOutboxWorkerRuntime,\n} from \"./editable-artifact-outbox-dispatcher\";\nimport type { EditableArtifactHintNatsAuth } from \"./editable-artifact-hint-broker\";\n\nexport type EditableArtifactOutboxServiceState =\n | \"starting\"\n | \"ready\"\n | \"draining\"\n | \"stopped\"\n | \"failed\";\n\nexport interface EditableArtifactOutboxRuntimePort {\n start(): Promise<void>;\n drain(): boolean;\n stop(): Promise<void>;\n check(signal?: AbortSignal): Promise<void>;\n readonly dispatcher: Readonly<{\n dispatchOnce(): Promise<EditableArtifactOutboxDispatchSummary>;\n }>;\n}\n\nexport type EditableArtifactOutboxService = Readonly<{\n state(): EditableArtifactOutboxServiceState;\n run(): Promise<void>;\n drain(reason?: string): boolean;\n close(): Promise<void>;\n dispatchOnce(): Promise<EditableArtifactOutboxDispatchSummary>;\n fetch(request: Request): Promise<Response>;\n}>;\n\nexport type CreateEditableArtifactOutboxServiceInput = Readonly<{\n runtime: EditableArtifactOutboxRuntimePort;\n observability: Observability;\n serviceName: string;\n environment: string;\n deploymentRevision?: string;\n readinessTimeoutMs?: number;\n}>;\n\nexport type ProductionEditableArtifactOutboxServiceOptions = Readonly<{\n settings: ArtifactOutboxSettings;\n databaseUrl: string;\n declaredDatabaseRole: string;\n natsUrl: string;\n natsAuth: EditableArtifactHintNatsAuth;\n owner: string;\n databasePoolSize?: number;\n batchSize?: number;\n concurrency?: number;\n leaseDurationMs?: number;\n leaseRenewIntervalMs?: number;\n pollIntervalMs?: number;\n publishTimeoutMs?: number;\n retryBaseMs?: number;\n retryMaxMs?: number;\n}>;\n\n/** Compose the independently supervised production outbox dispatcher. */\nexport async function createProductionEditableArtifactOutboxService(\n options: ProductionEditableArtifactOutboxServiceOptions,\n): Promise<EditableArtifactOutboxService> {\n if (options.declaredDatabaseRole !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE) {\n throw new Error(\"Artifact outbox dispatcher database role declaration is invalid\");\n }\n const observability = createObservability(options.settings, {\n component: \"artifact-outbox-dispatcher\",\n });\n const databaseSearchPath = dbSearchPath(options.settings);\n const runtime = await createEditableArtifactOutboxWorker({\n dispatcherDatabaseUrl: options.databaseUrl,\n ...(databaseSearchPath ? { databaseSearchPath } : {}),\n ...(options.databasePoolSize === undefined\n ? {}\n : { databasePoolSize: options.databasePoolSize }),\n natsUrl: options.natsUrl,\n natsAuth: options.natsAuth,\n owner: options.owner,\n dispatcher: {\n ...(options.batchSize === undefined ? {} : { batchSize: options.batchSize }),\n ...(options.concurrency === undefined ? {} : { concurrency: options.concurrency }),\n ...(options.leaseDurationMs === undefined\n ? {}\n : { leaseDurationMs: options.leaseDurationMs }),\n ...(options.leaseRenewIntervalMs === undefined\n ? {}\n : { leaseRenewIntervalMs: options.leaseRenewIntervalMs }),\n ...(options.pollIntervalMs === undefined ? {} : { pollIntervalMs: options.pollIntervalMs }),\n ...(options.publishTimeoutMs === undefined\n ? {}\n : { publishTimeoutMs: options.publishTimeoutMs }),\n ...(options.retryBaseMs === undefined ? {} : { retryBaseMs: options.retryBaseMs }),\n ...(options.retryMaxMs === undefined ? {} : { retryMaxMs: options.retryMaxMs }),\n },\n metrics: {\n increment(outcome, count = 1) {\n observability.incrementCounter({\n name: \"opengeni_artifact_outbox_dispatch_total\",\n help: \"Editable artifact outbox dispatch actions by closed outcome.\",\n labels: { outcome },\n amount: count,\n });\n },\n observePublishSeconds(outcome, seconds) {\n observability.observeHistogram({\n name: \"opengeni_artifact_outbox_publish_seconds\",\n help: \"Editable artifact broker publication latency by closed outcome.\",\n labels: { outcome },\n value: seconds,\n });\n },\n },\n logger: {\n warn(message, attributes) {\n observability.warn(message, {\n errorClass: \"WorkerOperationError\",\n errorCode: \"worker_operation_failed\",\n origin: \"worker\",\n outcome: typeof attributes.code === \"string\" ? attributes.code : \"unknown\",\n });\n },\n },\n });\n return createEditableArtifactOutboxService({\n runtime,\n observability,\n serviceName: options.settings.serviceName,\n environment: options.settings.environment,\n deploymentRevision: options.settings.deploymentRevision,\n });\n}\n\nexport function createEditableArtifactOutboxService(\n input: CreateEditableArtifactOutboxServiceInput,\n): EditableArtifactOutboxService {\n let state: EditableArtifactOutboxServiceState = \"starting\";\n let runPromise: Promise<void> | null = null;\n let closePromise: Promise<void> | null = null;\n let readinessPromise: Promise<void> | null = null;\n const readinessTimeoutMs = input.readinessTimeoutMs ?? 2_000;\n\n const ready = (): Promise<void> => {\n if (readinessPromise) return readinessPromise;\n const abort = new AbortController();\n const check = withTimeout(input.runtime.check(abort.signal), readinessTimeoutMs, abort);\n readinessPromise = check;\n void check.then(\n () => {\n if (readinessPromise === check) readinessPromise = null;\n },\n () => {\n if (readinessPromise === check) readinessPromise = null;\n },\n );\n return check;\n };\n\n const run = (): Promise<void> => {\n if (runPromise) return runPromise;\n if (state !== \"starting\") {\n return Promise.reject(new Error(\"Artifact outbox dispatcher service cannot be restarted\"));\n }\n runPromise = (async () => {\n try {\n await ready();\n if ((state as EditableArtifactOutboxServiceState) === \"draining\") {\n state = \"stopped\";\n return;\n }\n const running = input.runtime.start();\n state = \"ready\";\n await running;\n const exitWasDraining = (state as EditableArtifactOutboxServiceState) === \"draining\";\n state = exitWasDraining ? \"stopped\" : \"failed\";\n if (!exitWasDraining) {\n throw new Error(\"Artifact outbox dispatcher exited without a drain request\");\n }\n } catch (error) {\n const caughtState = state as EditableArtifactOutboxServiceState;\n if (caughtState !== \"draining\" && caughtState !== \"stopped\") state = \"failed\";\n throw error;\n }\n })();\n return runPromise;\n };\n\n const drain = (_reason = \"shutdown\"): boolean => {\n if (state === \"draining\" || state === \"stopped\" || state === \"failed\") return false;\n state = \"draining\";\n input.runtime.drain();\n return true;\n };\n\n const close = (): Promise<void> => {\n if (closePromise) return closePromise;\n closePromise = (async () => {\n drain(\"close\");\n if (runPromise) await runPromise.catch(() => undefined);\n await input.runtime.stop();\n if (state !== \"failed\") state = \"stopped\";\n })();\n return closePromise;\n };\n\n const fetch = async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n if (request.method !== \"GET\") {\n return Response.json({ error: \"method_not_allowed\" }, { status: 405 });\n }\n if (url.pathname === \"/healthz\") {\n const ok = state !== \"failed\" && state !== \"stopped\";\n return Response.json(\n {\n service: input.serviceName,\n component: \"artifact-outbox-dispatcher\",\n environment: input.environment,\n ...(input.deploymentRevision ? { deploymentRevision: input.deploymentRevision } : {}),\n state,\n ok,\n },\n { status: ok ? 200 : 503 },\n );\n }\n if (url.pathname === \"/readyz\") {\n if (state !== \"ready\") {\n return Response.json(\n {\n ok: false,\n state,\n checks: { databaseRole: { ok: false }, nats: { ok: false } },\n },\n { status: 503 },\n );\n }\n try {\n await ready();\n return Response.json({\n ok: true,\n state,\n checks: { databaseRole: { ok: true }, nats: { ok: true } },\n });\n } catch {\n return Response.json(\n {\n ok: false,\n state,\n checks: { databaseRole: { ok: false }, nats: { ok: false } },\n },\n { status: 503 },\n );\n }\n }\n if (url.pathname === \"/metrics\") {\n return new Response(await input.observability.prometheusMetrics(), {\n status: 200,\n headers: { \"content-type\": \"text/plain; version=0.0.4; charset=utf-8\" },\n });\n }\n return Response.json({ error: \"not_found\" }, { status: 404 });\n };\n\n return Object.freeze({\n state: () => state,\n run,\n drain,\n close,\n dispatchOnce: async () => await input.runtime.dispatcher.dispatchOnce(),\n fetch,\n });\n}\n\nexport type EditableArtifactOutboxSidecarEnvironment = Readonly<{\n databaseUrl: string;\n declaredDatabaseRole: string;\n owner: string;\n httpPort: number;\n databasePoolSize: number;\n batchSize: number;\n concurrency: number;\n leaseDurationMs: number;\n leaseRenewIntervalMs: number;\n pollIntervalMs: number;\n publishTimeoutMs: number;\n retryBaseMs: number;\n retryMaxMs: number;\n}>;\n\nexport function readEditableArtifactOutboxSidecarEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n): EditableArtifactOutboxSidecarEnvironment | null {\n if (environment.OPENGENI_ARTIFACT_OUTBOX_ENABLED !== \"true\") return null;\n const declaredDatabaseRole = required(environment, \"OPENGENI_ARTIFACT_OUTBOX_DATABASE_ROLE\");\n if (declaredDatabaseRole !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_DATABASE_ROLE is invalid\");\n }\n const result = {\n databaseUrl: required(environment, EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV),\n declaredDatabaseRole,\n owner:\n environment.OPENGENI_ARTIFACT_OUTBOX_OWNER?.trim() ||\n `artifact-outbox-${process.pid}-${crypto.randomUUID()}`,\n httpPort: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_HTTP_PORT\", 9466, 1, 65_535),\n databasePoolSize: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_DB_POOL_SIZE\", 4, 1, 8),\n batchSize: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_BATCH_SIZE\", 32, 1, 1_000),\n concurrency: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_CONCURRENCY\", 8, 1, 128),\n leaseDurationMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_LEASE_MS\",\n 30_000,\n 1_000,\n 86_400_000,\n ),\n leaseRenewIntervalMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_RENEW_MS\",\n 10_000,\n 100,\n 43_199_999,\n ),\n pollIntervalMs: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_POLL_MS\", 500, 10, 60_000),\n publishTimeoutMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_PUBLISH_TIMEOUT_MS\",\n 5_000,\n 100,\n 60_000,\n ),\n retryBaseMs: integer(environment, \"OPENGENI_ARTIFACT_OUTBOX_RETRY_BASE_MS\", 500, 10, 60_000),\n retryMaxMs: integer(\n environment,\n \"OPENGENI_ARTIFACT_OUTBOX_RETRY_MAX_MS\",\n 60_000,\n 10,\n 86_400_000,\n ),\n } as const;\n if (result.leaseRenewIntervalMs >= result.leaseDurationMs) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_RENEW_MS must be less than lease duration\");\n }\n if (result.retryBaseMs > result.retryMaxMs) {\n throw new Error(\"OPENGENI_ARTIFACT_OUTBOX_RETRY_BASE_MS must not exceed retry max\");\n }\n return Object.freeze(result);\n}\n\nexport async function createOutboxSidecarFromEnvironment(\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<Readonly<{ service: EditableArtifactOutboxService; httpPort: number }> | null> {\n const sidecar = readEditableArtifactOutboxSidecarEnvironment(environment);\n if (!sidecar) return null;\n const settings = getArtifactOutboxSettings(environment);\n const controlPlaneAuth = resolveNatsControlPlaneAuth(settings);\n const natsAuth: EditableArtifactHintNatsAuth = controlPlaneAuth\n ? {\n kind: \"user-password\",\n user: controlPlaneAuth.user,\n pass: controlPlaneAuth.password,\n }\n : { kind: \"anonymous\" };\n const service = await createProductionEditableArtifactOutboxService({\n settings,\n databaseUrl: sidecar.databaseUrl,\n declaredDatabaseRole: sidecar.declaredDatabaseRole,\n natsUrl: settings.natsUrl,\n natsAuth,\n owner: sidecar.owner,\n databasePoolSize: sidecar.databasePoolSize,\n batchSize: sidecar.batchSize,\n concurrency: sidecar.concurrency,\n leaseDurationMs: sidecar.leaseDurationMs,\n leaseRenewIntervalMs: sidecar.leaseRenewIntervalMs,\n pollIntervalMs: sidecar.pollIntervalMs,\n publishTimeoutMs: sidecar.publishTimeoutMs,\n retryBaseMs: sidecar.retryBaseMs,\n retryMaxMs: sidecar.retryMaxMs,\n });\n return Object.freeze({ service, httpPort: sidecar.httpPort });\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n milliseconds: number,\n abort: AbortController,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(() => {\n abort.abort();\n reject(new Error(\"readiness check timed out\"));\n }, milliseconds);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\nfunction required(environment: NodeJS.ProcessEnv, name: string): string {\n const value = environment[name]?.trim();\n if (!value) throw new Error(`${name} is required when artifact outbox dispatch is enabled`);\n return value;\n}\n\nfunction integer(\n environment: NodeJS.ProcessEnv,\n name: string,\n fallback: number,\n minimum: number,\n maximum: number,\n): number {\n const raw = environment[name];\n const value = raw === undefined ? fallback : Number(raw);\n if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${name} is outside its allowed range`);\n }\n return value;\n}\n\n// Compile-time assurance that production composition satisfies the service port.\nconst _runtimePort: EditableArtifactOutboxRuntimePort | undefined = undefined as\n | EditableArtifactOutboxWorkerRuntime\n | undefined;\nvoid _runtimePort;\n","import {\n EditableArtifactLiveOutboxDispatcher,\n MathEditableArtifactOutboxRandom,\n SystemEditableArtifactLiveClock,\n SystemEditableArtifactLiveScheduler,\n type EditableArtifactOutboxDispatcherOptions,\n type EditableArtifactOutboxLoggerPort,\n type EditableArtifactOutboxMetricsPort,\n type EditableArtifactOutboxDispatcherStorePort,\n type EditableArtifactLiveOutboxRecord,\n} from \"@opengeni/core\";\nimport {\n PostgresEditableArtifactStore,\n createDb,\n dbSql,\n type Database,\n type DbClient,\n} from \"@opengeni/db\";\n\nimport {\n connectEditableArtifactHintBroker,\n type ConfirmedNatsEditableArtifactHintBroker,\n type EditableArtifactHintNatsAuth,\n} from \"./editable-artifact-hint-broker\";\n\nexport const EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE =\n \"opengeni_artifact_outbox_dispatcher\";\nexport const EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV = \"OPENGENI_ARTIFACT_OUTBOX_DATABASE_URL\";\n\nexport type EditableArtifactOutboxWorkerOptions = Readonly<{\n /** Must authenticate as the dedicated dispatcher role, never the generic app role. */\n dispatcherDatabaseUrl: string;\n databaseSearchPath?: string;\n databasePoolSize?: number;\n natsUrl: string;\n natsAuth: EditableArtifactHintNatsAuth;\n owner?: string;\n dispatcher?: Omit<EditableArtifactOutboxDispatcherOptions, \"owner\">;\n metrics?: EditableArtifactOutboxMetricsPort;\n logger?: EditableArtifactOutboxLoggerPort;\n}>;\n\n/** Explicit lifecycle handle; hosts supervise `start()` and await `stop()` on drain. */\nexport class EditableArtifactOutboxWorkerRuntime {\n private readonly abort = new AbortController();\n private running: Promise<void> | null = null;\n private closing: Promise<void> | null = null;\n\n constructor(\n readonly dispatcher: EditableArtifactLiveOutboxDispatcher,\n private readonly broker: ConfirmedNatsEditableArtifactHintBroker,\n private readonly database: DbClient,\n ) {}\n\n start(): Promise<void> {\n if (this.closing) return Promise.reject(new Error(\"Artifact outbox worker is stopping\"));\n this.running ??= this.dispatcher.run(this.abort.signal);\n return this.running;\n }\n\n drain(): boolean {\n if (this.abort.signal.aborted) return false;\n this.abort.abort();\n return true;\n }\n\n async check(signal?: AbortSignal): Promise<void> {\n if (this.abort.signal.aborted || this.closing) {\n throw new Error(\"Artifact outbox worker is stopping\");\n }\n await Promise.all([\n assertDedicatedOutboxDispatcherDatabaseRole(this.database.db),\n this.broker.check(signal),\n ]);\n }\n\n stop(): Promise<void> {\n if (this.closing) return this.closing;\n this.closing = this.stopOnce();\n return this.closing;\n }\n\n private async stopOnce(): Promise<void> {\n this.drain();\n const running = this.running ? await Promise.allSettled([this.running]) : [];\n const cleanup = await Promise.allSettled([this.broker.close(), this.database.close()]);\n const failure = [...running, ...cleanup].find(\n (result): result is PromiseRejectedResult => result.status === \"rejected\",\n );\n if (failure) throw failure.reason;\n }\n}\n\n/**\n * Production composition. DB grants make the role a narrow capability: it can\n * execute only lease-fenced dispatcher functions and cannot read artifact rows.\n */\nexport async function createEditableArtifactOutboxWorker(\n options: EditableArtifactOutboxWorkerOptions,\n): Promise<EditableArtifactOutboxWorkerRuntime> {\n const dispatcherDatabaseUrl = dedicatedDispatcherDatabaseUrl(options.dispatcherDatabaseUrl);\n const databasePoolSize = options.databasePoolSize ?? 2;\n if (!Number.isSafeInteger(databasePoolSize) || databasePoolSize < 1 || databasePoolSize > 8) {\n throw new TypeError(\"Artifact outbox dispatcher DB pool size must be 1-8\");\n }\n const database = createDb(dispatcherDatabaseUrl, {\n max: databasePoolSize,\n ...(options.databaseSearchPath ? { searchPath: options.databaseSearchPath } : {}),\n });\n let broker: ConfirmedNatsEditableArtifactHintBroker;\n try {\n await assertDedicatedOutboxDispatcherDatabaseRole(database.db);\n broker = await connectEditableArtifactHintBroker({\n natsUrl: options.natsUrl,\n auth: options.natsAuth,\n });\n } catch (error) {\n await database.close();\n throw error;\n }\n const persistence = new PostgresEditableArtifactStore(database.db);\n const store = dispatcherStore(persistence);\n const dispatcher = new EditableArtifactLiveOutboxDispatcher(\n {\n store,\n broker,\n clock: new SystemEditableArtifactLiveClock(),\n scheduler: new SystemEditableArtifactLiveScheduler(),\n random: new MathEditableArtifactOutboxRandom(),\n ...(options.metrics ? { metrics: options.metrics } : {}),\n ...(options.logger ? { logger: options.logger } : {}),\n },\n {\n owner: options.owner ?? `artifact-outbox:${crypto.randomUUID()}`,\n ...options.dispatcher,\n },\n );\n return new EditableArtifactOutboxWorkerRuntime(dispatcher, broker, database);\n}\n\n/**\n * Verify the database identity and its negative capability at runtime. A DSN\n * username check alone is insufficient because PostgreSQL role inheritance,\n * SET ROLE, or a mis-provisioned grant could otherwise widen this worker.\n */\nexport async function assertDedicatedOutboxDispatcherDatabaseRole(db: Database): Promise<void> {\n const raw = await db.execute<{\n current_role: string;\n session_role: string;\n can_access_any_relation: boolean;\n can_access_any_sequence: boolean;\n }>(dbSql`\n select\n current_user::text as current_role,\n session_user::text as session_role,\n exists (\n select 1\n from pg_catalog.pg_class relation_row\n join pg_catalog.pg_namespace namespace_row\n on namespace_row.oid = relation_row.relnamespace\n where namespace_row.nspname = current_schema()\n and relation_row.relkind in ('r', 'p', 'v', 'm', 'f')\n and (\n has_table_privilege(current_user, relation_row.oid, 'SELECT')\n or has_table_privilege(current_user, relation_row.oid, 'INSERT')\n or has_table_privilege(current_user, relation_row.oid, 'UPDATE')\n or has_table_privilege(current_user, relation_row.oid, 'DELETE')\n or has_table_privilege(current_user, relation_row.oid, 'TRUNCATE')\n or has_table_privilege(current_user, relation_row.oid, 'REFERENCES')\n or has_table_privilege(current_user, relation_row.oid, 'TRIGGER')\n or has_any_column_privilege(current_user, relation_row.oid, 'SELECT')\n or has_any_column_privilege(current_user, relation_row.oid, 'INSERT')\n or has_any_column_privilege(current_user, relation_row.oid, 'UPDATE')\n or has_any_column_privilege(current_user, relation_row.oid, 'REFERENCES')\n )\n ) as can_access_any_relation,\n exists (\n select 1\n from pg_catalog.pg_class sequence_row\n join pg_catalog.pg_namespace namespace_row\n on namespace_row.oid = sequence_row.relnamespace\n where namespace_row.nspname = current_schema()\n and sequence_row.relkind = 'S'\n and (\n has_sequence_privilege(current_user, sequence_row.oid, 'USAGE')\n or has_sequence_privilege(current_user, sequence_row.oid, 'SELECT')\n or has_sequence_privilege(current_user, sequence_row.oid, 'UPDATE')\n )\n ) as can_access_any_sequence\n `);\n const rows = Array.isArray(raw) ? raw : ((raw as unknown as { rows?: unknown[] }).rows ?? []);\n const row = rows[0] as\n | {\n current_role?: unknown;\n session_role?: unknown;\n can_access_any_relation?: unknown;\n can_access_any_sequence?: unknown;\n }\n | undefined;\n if (\n row?.current_role !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE ||\n row.session_role !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE ||\n row.can_access_any_relation !== false ||\n row.can_access_any_sequence !== false\n ) {\n throw new Error(\"Artifact outbox dispatcher database connection has an unsafe role posture\");\n }\n}\n\nfunction dispatcherStore(\n persistence: PostgresEditableArtifactStore,\n): EditableArtifactOutboxDispatcherStorePort {\n return {\n claimLiveOutbox: async (input) =>\n (await persistence.claimLiveOutbox(\n input,\n )) as unknown as readonly EditableArtifactLiveOutboxRecord[],\n renewLiveOutbox: async (input) => await persistence.renewLiveOutbox(input),\n markLiveOutboxPublished: async (input) => await persistence.markLiveOutboxPublished(input),\n retryLiveOutbox: async (input) => await persistence.retryLiveOutbox(input),\n deadLetterLiveOutbox: async (input) => await persistence.deadLetterLiveOutbox(input),\n };\n}\n\nexport function dedicatedDispatcherDatabaseUrl(raw: string): string {\n if (typeof raw !== \"string\" || raw.length > 8_192 || raw.trim() !== raw) {\n throw new TypeError(`${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} is malformed`);\n }\n let url: URL;\n try {\n url = new URL(raw);\n } catch (cause) {\n throw new TypeError(`${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} is malformed`, { cause });\n }\n if (\n (url.protocol !== \"postgres:\" && url.protocol !== \"postgresql:\") ||\n decodeURIComponent(url.username) !== EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE\n ) {\n throw new TypeError(\n `${EDITABLE_ARTIFACT_OUTBOX_DATABASE_URL_ENV} must authenticate as ${EDITABLE_ARTIFACT_OUTBOX_DISPATCHER_DATABASE_ROLE}`,\n );\n }\n return raw;\n}\n","import {\n EDITABLE_ARTIFACT_HINT_MAX_BYTES,\n type EditableArtifactHintBrokerPort,\n} from \"@opengeni/core\";\nimport { connect, type NatsConnection } from \"@opengeni/events\";\n\nconst DEFAULT_CONNECTION_NAME = \"opengeni-editable-artifact-outbox\";\n\nexport type EditableArtifactHintNatsAuth =\n | Readonly<{ kind: \"user-password\"; user: string; pass: string }>\n | Readonly<{ kind: \"token\"; token: string }>\n | Readonly<{ kind: \"anonymous\" }>;\n\nexport type EditableArtifactHintNatsBrokerOptions = Readonly<{\n maxHintBytes?: number;\n}>;\n\nexport type EditableArtifactHintNatsConnection = Pick<\n NatsConnection,\n \"publish\" | \"flush\" | \"drain\" | \"close\" | \"closed\" | \"isClosed\" | \"isDraining\"\n>;\n\n/**\n * Core-NATS adapter for the durable outbox. A publish resolves only after a\n * server round-trip flush ACK. Reconnect buffering may create duplicates after\n * a timeout; hints are intentionally idempotent wakeups for durable gap-fill.\n */\nexport class ConfirmedNatsEditableArtifactHintBroker implements EditableArtifactHintBrokerPort {\n private readonly maxHintBytes: number;\n\n constructor(\n private readonly connection: EditableArtifactHintNatsConnection,\n options: EditableArtifactHintNatsBrokerOptions = {},\n ) {\n this.maxHintBytes = options.maxHintBytes ?? EDITABLE_ARTIFACT_HINT_MAX_BYTES;\n if (\n !Number.isSafeInteger(this.maxHintBytes) ||\n this.maxHintBytes < 1 ||\n this.maxHintBytes > EDITABLE_ARTIFACT_HINT_MAX_BYTES\n ) {\n throw new TypeError(\"Editable artifact NATS hint byte limit is invalid\");\n }\n }\n\n async publish(\n input: Readonly<{\n subject: string;\n payload: Uint8Array;\n signal: AbortSignal;\n }>,\n ): Promise<void> {\n assertSubject(input.subject);\n if (\n !(input.payload instanceof Uint8Array) ||\n input.payload.byteLength < 1 ||\n input.payload.byteLength > this.maxHintBytes\n ) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_backpressure\",\n \"Editable artifact hint exceeds the NATS envelope\",\n );\n }\n if (input.signal.aborted) throw abortedPublish();\n if (this.connection.isClosed() || this.connection.isDraining()) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS connection is closed\",\n );\n }\n try {\n this.connection.publish(input.subject, input.payload);\n await abortable(this.connection.flush(), input.signal);\n } catch (error) {\n if (input.signal.aborted) throw abortedPublish();\n if (error instanceof EditableArtifactNatsHintPublishError) throw error;\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS publish was not acknowledged\",\n { cause: error },\n );\n }\n }\n\n /**\n * A readiness probe must prove the server is reachable, not merely that the\n * client object has not observed closure yet. `flush()` is a bounded NATS\n * round trip and has the same acknowledgement semantics as publication.\n */\n async check(signal: AbortSignal = new AbortController().signal): Promise<void> {\n if (signal.aborted) throw abortedPublish();\n if (this.connection.isClosed() || this.connection.isDraining()) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS connection is unavailable\",\n );\n }\n try {\n await abortable(this.connection.flush(), signal);\n } catch (error) {\n if (error instanceof EditableArtifactNatsHintPublishError) throw error;\n throw new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS readiness round trip failed\",\n { cause: error },\n );\n }\n }\n\n async close(drainTimeoutMs = 5_000): Promise<void> {\n if (!Number.isSafeInteger(drainTimeoutMs) || drainTimeoutMs < 1 || drainTimeoutMs > 30_000) {\n throw new TypeError(\"Editable artifact NATS drain timeout is invalid\");\n }\n if (this.connection.isClosed()) return;\n if (this.connection.isDraining()) {\n await this.connection.closed();\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const drain = this.connection.drain();\n const outcome = await Promise.race([\n drain.then(\n () => \"drained\" as const,\n () => \"failed\" as const,\n ),\n new Promise<\"timed_out\">((resolve) => {\n timer = setTimeout(() => resolve(\"timed_out\"), drainTimeoutMs);\n }),\n ]);\n if (timer) clearTimeout(timer);\n if (outcome !== \"drained\" && !this.connection.isClosed()) {\n await this.connection.close();\n }\n }\n}\n\nexport class EditableArtifactNatsHintPublishError extends Error {\n constructor(\n readonly code: \"broker_unavailable\" | \"broker_backpressure\",\n message: string,\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = \"EditableArtifactNatsHintPublishError\";\n }\n}\n\n/** Opens one resilient dispatcher identity; callers own `broker.close()`. */\nexport async function connectEditableArtifactHintBroker(\n input: Readonly<{\n natsUrl: string;\n auth: EditableArtifactHintNatsAuth;\n name?: string;\n maxHintBytes?: number;\n }>,\n): Promise<ConfirmedNatsEditableArtifactHintBroker> {\n const natsUrl = boundedText(input.natsUrl, \"NATS URL\", 2_048);\n const name = boundedText(input.name ?? DEFAULT_CONNECTION_NAME, \"NATS connection name\", 128);\n const auth = natsAuthOptions(input.auth);\n const connection = await connect({\n servers: natsUrl,\n name,\n reconnect: true,\n maxReconnectAttempts: -1,\n // Same policy as the event bus: a broker or auth-callout restart must not\n // permanently close this connection after two identical auth errors.\n ignoreAuthErrorAbort: true,\n reconnectTimeWait: 2_000,\n reconnectJitter: 1_000,\n reconnectJitterTLS: 1_000,\n waitOnFirstConnect: true,\n pingInterval: 20_000,\n maxPingOut: 3,\n ...auth,\n });\n return new ConfirmedNatsEditableArtifactHintBroker(connection, {\n ...(input.maxHintBytes === undefined ? {} : { maxHintBytes: input.maxHintBytes }),\n });\n}\n\nfunction natsAuthOptions(auth: EditableArtifactHintNatsAuth): {\n user?: string;\n pass?: string;\n token?: string;\n} {\n if (auth.kind === \"anonymous\") return {};\n if (auth.kind === \"token\") return { token: boundedText(auth.token, \"NATS token\", 4_096) };\n return {\n user: boundedText(auth.user, \"NATS user\", 256),\n pass: boundedText(auth.pass, \"NATS password\", 4_096),\n };\n}\n\nfunction assertSubject(subject: string): void {\n const bytes = new TextEncoder().encode(subject).byteLength;\n if (\n bytes < 1 ||\n bytes > 1_024 ||\n subject.startsWith(\".\") ||\n subject.endsWith(\".\") ||\n subject.includes(\"..\") ||\n /[\\s*>]/u.test(subject)\n ) {\n throw new EditableArtifactNatsHintPublishError(\n \"broker_backpressure\",\n \"Editable artifact NATS subject is malformed\",\n );\n }\n}\n\nfunction boundedText(value: string, label: string, maxBytes: number): string {\n const bytes = new TextEncoder().encode(value).byteLength;\n if (bytes < 1 || bytes > maxBytes || value.trim() !== value) {\n throw new TypeError(`${label} is malformed`);\n }\n return value;\n}\n\nfunction abortedPublish(): EditableArtifactNatsHintPublishError {\n return new EditableArtifactNatsHintPublishError(\n \"broker_unavailable\",\n \"Editable artifact NATS publish was aborted\",\n );\n}\n\nasync function abortable(operation: Promise<void>, signal: AbortSignal): Promise<void> {\n if (signal.aborted) throw abortedPublish();\n let remove: () => void = () => undefined;\n const aborted = new Promise<never>((_resolve, reject) => {\n const onAbort = () => reject(abortedPublish());\n signal.addEventListener(\"abort\", onAbort, { once: true });\n remove = () => signal.removeEventListener(\"abort\", onAbort);\n });\n try {\n await Promise.race([operation, aborted]);\n } finally {\n remove();\n }\n}\n","import { createOutboxSidecarFromEnvironment } from \"./editable-artifact-outbox-service\";\n\n/** Dedicated process: no Temporal/control worker is created or imported here. */\nexport async function runEditableArtifactOutboxSidecar(\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n const configured = await createOutboxSidecarFromEnvironment(environment);\n if (!configured) throw new Error(\"Editable artifact outbox sidecar is disabled\");\n const server = Bun.serve({\n hostname: \"0.0.0.0\",\n port: configured.httpPort,\n fetch: configured.service.fetch,\n });\n const stop = () => configured.service.drain(\"process signal\");\n process.on(\"SIGTERM\", stop);\n process.on(\"SIGINT\", stop);\n try {\n await configured.service.run();\n } finally {\n process.off(\"SIGTERM\", stop);\n process.off(\"SIGINT\", stop);\n server.stop(true);\n await configured.service.close();\n }\n}\n\nif (import.meta.main) {\n await runEditableArtifactOutboxSidecar();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
observabilityEventBusOptions
|
|
3
|
+
} from "./chunk-DSPP6CZL.js";
|
|
4
4
|
|
|
5
5
|
// src/activity-services.ts
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
codeSearchDeploymentPolicy,
|
|
8
|
+
dbSearchPath,
|
|
9
|
+
getSettings,
|
|
10
|
+
resolveNatsControlPlaneAuth
|
|
11
|
+
} from "@opengeni/config";
|
|
12
|
+
import {
|
|
13
|
+
configureChildLifecycleNotices,
|
|
14
|
+
configureCodeSearchDeploymentPolicy,
|
|
15
|
+
createDb
|
|
16
|
+
} from "@opengeni/db";
|
|
8
17
|
import { createNatsEventBus } from "@opengeni/events";
|
|
9
18
|
import { createObservability } from "@opengeni/observability";
|
|
10
19
|
import { resolveCatalogSettings } from "@opengeni/core";
|
|
@@ -403,6 +412,7 @@ function createSharedActivityServices(dependencies) {
|
|
|
403
412
|
const db = dependencies.db ?? dbClient.db;
|
|
404
413
|
const resolvedSettings = (await resolveCatalogSettings(db, settings)).settings;
|
|
405
414
|
configureChildLifecycleNotices({ enabled: settings.childLifecycleNoticesEnabled });
|
|
415
|
+
configureCodeSearchDeploymentPolicy(codeSearchDeploymentPolicy(settings));
|
|
406
416
|
return {
|
|
407
417
|
settings: resolvedSettings,
|
|
408
418
|
catalogSourceSettings: settings,
|
|
@@ -410,7 +420,7 @@ function createSharedActivityServices(dependencies) {
|
|
|
410
420
|
bus: dependencies.bus ?? await createNatsEventBus(
|
|
411
421
|
settings.natsUrl,
|
|
412
422
|
controlPlaneAuth ? { user: controlPlaneAuth.user, pass: controlPlaneAuth.password } : void 0,
|
|
413
|
-
|
|
423
|
+
observabilityEventBusOptions(observability)
|
|
414
424
|
),
|
|
415
425
|
objectStorage: dependencies.objectStorage ?? createObjectStorage(settings),
|
|
416
426
|
observability,
|
|
@@ -5049,7 +5059,8 @@ import {
|
|
|
5049
5059
|
import {
|
|
5050
5060
|
effectiveSandboxLifecycle,
|
|
5051
5061
|
sandboxArchiveCaptureTimeoutMs,
|
|
5052
|
-
sandboxLifecycleTransitionWaitMs
|
|
5062
|
+
sandboxLifecycleTransitionWaitMs,
|
|
5063
|
+
sandboxWarmRateMicrosPerSecond
|
|
5053
5064
|
} from "@opengeni/config";
|
|
5054
5065
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5055
5066
|
|
|
@@ -5190,6 +5201,42 @@ var SandboxSiblingWarmingTimeoutError = class extends SandboxWarmingTimeoutError
|
|
|
5190
5201
|
this.name = "SandboxSiblingWarmingTimeoutError";
|
|
5191
5202
|
}
|
|
5192
5203
|
};
|
|
5204
|
+
var disposedUnreadyFreshSandboxErrors = /* @__PURE__ */ new WeakSet();
|
|
5205
|
+
function isReplaceableFreshSandboxReadinessTimeout(error) {
|
|
5206
|
+
return error instanceof SandboxExecReadinessTimeoutError && disposedUnreadyFreshSandboxErrors.has(error);
|
|
5207
|
+
}
|
|
5208
|
+
var FRESH_SANDBOX_READINESS_REPLACEMENT_BASE_DELAY_MS = 2e3;
|
|
5209
|
+
var FRESH_SANDBOX_READINESS_REPLACEMENT_JITTER_MS = 8e3;
|
|
5210
|
+
function freshSandboxReadinessReplacementDelayMs(random = Math.random) {
|
|
5211
|
+
const sample = random();
|
|
5212
|
+
const unit = Number.isFinite(sample) ? Math.min(Math.max(sample, 0), 1 - Number.EPSILON) : 0;
|
|
5213
|
+
return FRESH_SANDBOX_READINESS_REPLACEMENT_BASE_DELAY_MS + Math.floor(unit * FRESH_SANDBOX_READINESS_REPLACEMENT_JITTER_MS);
|
|
5214
|
+
}
|
|
5215
|
+
var FRESH_SANDBOX_READINESS_REPLACEMENTS_PER_TURN_ATTEMPT = 1;
|
|
5216
|
+
function createFreshSandboxReadinessReplacementBudget() {
|
|
5217
|
+
return { remaining: FRESH_SANDBOX_READINESS_REPLACEMENTS_PER_TURN_ATTEMPT };
|
|
5218
|
+
}
|
|
5219
|
+
function recordFreshSandboxReadinessReplacement(metrics, backend, outcome) {
|
|
5220
|
+
try {
|
|
5221
|
+
metrics?.onSandboxReadinessReplacement?.({ backend, outcome });
|
|
5222
|
+
} catch {
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
async function sleepUnlessCancelled(ms, signal) {
|
|
5226
|
+
if (signal?.aborted) return false;
|
|
5227
|
+
if (ms <= 0) return true;
|
|
5228
|
+
return await new Promise((resolve) => {
|
|
5229
|
+
const onAbort = () => {
|
|
5230
|
+
clearTimeout(timer);
|
|
5231
|
+
resolve(false);
|
|
5232
|
+
};
|
|
5233
|
+
const timer = setTimeout(() => {
|
|
5234
|
+
signal?.removeEventListener("abort", onAbort);
|
|
5235
|
+
resolve(true);
|
|
5236
|
+
}, ms);
|
|
5237
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5238
|
+
});
|
|
5239
|
+
}
|
|
5193
5240
|
var SandboxLeaseInstanceLostError = class extends SandboxLeaseSupersededError {
|
|
5194
5241
|
constructor(sandboxGroupId, leaseEpoch, lostInstanceId) {
|
|
5195
5242
|
super(sandboxGroupId, leaseEpoch);
|
|
@@ -5639,6 +5686,69 @@ async function persistWarmWorkspaceSnapshot(services, ids, session, leaseEpoch,
|
|
|
5639
5686
|
}
|
|
5640
5687
|
}
|
|
5641
5688
|
async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
5689
|
+
try {
|
|
5690
|
+
return await resumeBoxForTurnOnce(services, ids, kind, holderId);
|
|
5691
|
+
} catch (error) {
|
|
5692
|
+
if (!isReplaceableFreshSandboxReadinessTimeout(error)) throw error;
|
|
5693
|
+
const readiness = error;
|
|
5694
|
+
const warn = (message, fields) => {
|
|
5695
|
+
if (services.observability) services.observability.warn(message, fields);
|
|
5696
|
+
else console.warn(message, fields);
|
|
5697
|
+
};
|
|
5698
|
+
const identity = {
|
|
5699
|
+
workspaceId: ids.workspaceId,
|
|
5700
|
+
sessionId: ids.sessionId,
|
|
5701
|
+
sandboxGroupId: ids.sandboxGroupId,
|
|
5702
|
+
backend: readiness.backend,
|
|
5703
|
+
instanceId: readiness.instanceId,
|
|
5704
|
+
readinessTimeoutMs: readiness.timeoutMs
|
|
5705
|
+
};
|
|
5706
|
+
const budget = services.freshSandboxReadinessReplacementBudget ?? createFreshSandboxReadinessReplacementBudget();
|
|
5707
|
+
if (budget.remaining <= 0) {
|
|
5708
|
+
recordFreshSandboxReadinessReplacement(
|
|
5709
|
+
services.sandboxMetrics,
|
|
5710
|
+
readiness.backend,
|
|
5711
|
+
"budget_spent"
|
|
5712
|
+
);
|
|
5713
|
+
warn(
|
|
5714
|
+
"sandbox command-readiness timed out on a fresh box; this turn attempt already used its replacement",
|
|
5715
|
+
identity
|
|
5716
|
+
);
|
|
5717
|
+
throw error;
|
|
5718
|
+
}
|
|
5719
|
+
budget.remaining -= 1;
|
|
5720
|
+
const delayMs = await (services.freshSandboxReadinessReplacementDelayMs ?? freshSandboxReadinessReplacementDelayMs)();
|
|
5721
|
+
warn("sandbox command-readiness timed out on a fresh box; replacing it once after jitter", {
|
|
5722
|
+
...identity,
|
|
5723
|
+
replacementDelayMs: delayMs
|
|
5724
|
+
});
|
|
5725
|
+
if (!await sleepUnlessCancelled(delayMs, services.cancellationSignal)) {
|
|
5726
|
+
recordFreshSandboxReadinessReplacement(
|
|
5727
|
+
services.sandboxMetrics,
|
|
5728
|
+
readiness.backend,
|
|
5729
|
+
"cancelled"
|
|
5730
|
+
);
|
|
5731
|
+
throw error;
|
|
5732
|
+
}
|
|
5733
|
+
try {
|
|
5734
|
+
const replaced = await resumeBoxForTurnOnce(services, ids, kind, holderId);
|
|
5735
|
+
recordFreshSandboxReadinessReplacement(
|
|
5736
|
+
services.sandboxMetrics,
|
|
5737
|
+
readiness.backend,
|
|
5738
|
+
"replaced"
|
|
5739
|
+
);
|
|
5740
|
+
return replaced;
|
|
5741
|
+
} catch (replacementError) {
|
|
5742
|
+
recordFreshSandboxReadinessReplacement(
|
|
5743
|
+
services.sandboxMetrics,
|
|
5744
|
+
readiness.backend,
|
|
5745
|
+
services.cancellationSignal?.aborted ? "cancelled" : replacementError instanceof SandboxExecReadinessTimeoutError ? "failed_again" : "replacement_failed"
|
|
5746
|
+
);
|
|
5747
|
+
throw replacementError;
|
|
5748
|
+
}
|
|
5749
|
+
}
|
|
5750
|
+
}
|
|
5751
|
+
async function resumeBoxForTurnOnce(services, ids, kind, holderId) {
|
|
5642
5752
|
const { db, settings } = services;
|
|
5643
5753
|
const os = ids.os ?? "linux";
|
|
5644
5754
|
const leaseTtlMs = settings.sandboxLeaseTtlMs;
|
|
@@ -5711,6 +5821,10 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5711
5821
|
holderId,
|
|
5712
5822
|
subjectId: ids.sessionId,
|
|
5713
5823
|
backend: ids.backend,
|
|
5824
|
+
warmBilling: {
|
|
5825
|
+
mode: settings.sandboxWarmBillingMode,
|
|
5826
|
+
rateMicrosPerSecond: sandboxWarmRateMicrosPerSecond(settings, ids.backend)
|
|
5827
|
+
},
|
|
5714
5828
|
os,
|
|
5715
5829
|
// IMAGE IS SHARED STATE (B3): thread the resolved image so the lease stamps it +
|
|
5716
5830
|
// conflicts on a live box already running a different image. A
|
|
@@ -5795,7 +5909,8 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
5795
5909
|
kind,
|
|
5796
5910
|
holderId,
|
|
5797
5911
|
expectedEpoch: heartbeat2.expectedEpoch,
|
|
5798
|
-
leaseTtlMs: heartbeat2.leaseTtlMs
|
|
5912
|
+
leaseTtlMs: heartbeat2.leaseTtlMs,
|
|
5913
|
+
billingMode: services.settings.sandboxWarmBillingMode
|
|
5799
5914
|
}).then(async (status) => {
|
|
5800
5915
|
if (heartbeat2 !== holderLeaseHeartbeat) return;
|
|
5801
5916
|
if (!status.holderAlive) {
|
|
@@ -6074,9 +6189,15 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
6074
6189
|
});
|
|
6075
6190
|
createdEstablished = established;
|
|
6076
6191
|
throwIfReleasedOrCancelled();
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6192
|
+
if (services.verifySpawnedSandboxReadiness) {
|
|
6193
|
+
await services.verifySpawnedSandboxReadiness(established, {
|
|
6194
|
+
sandboxGroupId: ids.sandboxGroupId
|
|
6195
|
+
});
|
|
6196
|
+
} else {
|
|
6197
|
+
await waitForSandboxExecReadiness(established, MODAL_EXEC_READINESS_TIMEOUT_MS, {
|
|
6198
|
+
sandboxGroupId: ids.sandboxGroupId
|
|
6199
|
+
});
|
|
6200
|
+
}
|
|
6080
6201
|
await maybeRenewProviderExpiration(true);
|
|
6081
6202
|
throwIfReleasedOrCancelled();
|
|
6082
6203
|
const resumeEnvelope = requirePersistableReplacementSandboxEnvelope(
|
|
@@ -6170,6 +6291,9 @@ async function resumeBoxForTurn(services, ids, kind, holderId) {
|
|
|
6170
6291
|
}
|
|
6171
6292
|
await release();
|
|
6172
6293
|
recordSandboxWarmingTimeout(services.sandboxMetrics, error);
|
|
6294
|
+
if (terminated && createdEstablished && error instanceof SandboxExecReadinessTimeoutError && error.instanceId === createdEstablished.instanceId && (createdEstablished.origin === "created" || createdEstablished.origin === "restored") && !createdEstablished.providerContinuity) {
|
|
6295
|
+
disposedUnreadyFreshSandboxErrors.add(error);
|
|
6296
|
+
}
|
|
6173
6297
|
throw sandboxProvisionStageError(rematerialization ? "archive_recovery" : "create", error);
|
|
6174
6298
|
}
|
|
6175
6299
|
}
|
|
@@ -8685,10 +8809,14 @@ import {
|
|
|
8685
8809
|
describeCompactionProviderRejection,
|
|
8686
8810
|
isMcpRequestTimeoutError,
|
|
8687
8811
|
isMcpTransportConnectivityError,
|
|
8688
|
-
|
|
8812
|
+
isModalTaskExecStartPreDispatchUnavailableError,
|
|
8813
|
+
isRoutingMutationOutcomeUnknownError,
|
|
8689
8814
|
RoutingWorkspaceRootChangedError,
|
|
8690
8815
|
SandboxMaterializationVerificationError,
|
|
8691
8816
|
materializationVerificationDiagnostic,
|
|
8817
|
+
PROVIDER_QUOTA_EXHAUSTED_CODE,
|
|
8818
|
+
classifyProviderQuotaError,
|
|
8819
|
+
providerQuotaExhaustedMessage,
|
|
8692
8820
|
SelfhostedWorkspaceRootChangedError,
|
|
8693
8821
|
UNKNOWN_MODEL_FINISH_REASON_CODE
|
|
8694
8822
|
} from "@opengeni/runtime";
|
|
@@ -9206,6 +9334,7 @@ function sandboxFilePath(resource, file) {
|
|
|
9206
9334
|
|
|
9207
9335
|
// src/activities/agent-turn/errors.ts
|
|
9208
9336
|
import {
|
|
9337
|
+
CODEX_USAGE_LIMIT_ERROR_TYPE,
|
|
9209
9338
|
CodexReloginRequired,
|
|
9210
9339
|
classifyCodexEncryptedArtifactRejection,
|
|
9211
9340
|
classifyCodexResponseTimeoutError,
|
|
@@ -9250,7 +9379,7 @@ function providerRecoveryResult(input) {
|
|
|
9250
9379
|
};
|
|
9251
9380
|
}
|
|
9252
9381
|
const providerDelay = input.retryAfterMs !== null && input.retryAfterMs !== void 0 && Number.isFinite(input.retryAfterMs) && input.retryAfterMs > 0 ? Math.ceil(input.retryAfterMs) : null;
|
|
9253
|
-
const continueDelayMs = input.failureCode === "provider_rate_limited" ? providerDelay ?? PROVIDER_BACKPRESSURE_DELAY_MS : input.failureCode === "provider_unavailable" || input.failureCode === "upstream_connectivity_unavailable" || input.failureCode === "sandbox_command_start_unavailable" || input.failureCode === "mcp_transport_timeout" || input.failureCode === "mcp_transport_unavailable" || input.failureCode === POST_COMPACTION_CONTINUATION_EMPTY_CODE ? Math.max(
|
|
9382
|
+
const continueDelayMs = input.failureCode === "provider_rate_limited" ? providerDelay ?? PROVIDER_BACKPRESSURE_DELAY_MS : input.failureCode === "provider_unavailable" || input.failureCode === "upstream_connectivity_unavailable" || input.failureCode === "sandbox_command_start_unavailable" || input.failureCode === "mcp_transport_timeout" || input.failureCode === "mcp_transport_unavailable" || input.failureCode === "turn_execution_policy_definition_mismatch" || input.failureCode === POST_COMPACTION_CONTINUATION_EMPTY_CODE ? Math.max(
|
|
9254
9383
|
providerDelay ?? 0,
|
|
9255
9384
|
PROVIDER_CONNECTIVITY_BACKOFF_MS[Math.min(
|
|
9256
9385
|
Math.max(Math.trunc(input.attemptNumber) - 1, 0),
|
|
@@ -9489,6 +9618,12 @@ function compactionFailureReasonFromError(error) {
|
|
|
9489
9618
|
`the model provider rejected the compaction request (${describeCompactionProviderRejection(rejection)}). Active history was preserved. ${COMPACTION_PROVIDER_REJECTION_GUIDANCE}`
|
|
9490
9619
|
);
|
|
9491
9620
|
}
|
|
9621
|
+
const quota = classifyProviderQuotaExhaustionError(error);
|
|
9622
|
+
if (quota) {
|
|
9623
|
+
return compactionFailureReason(
|
|
9624
|
+
`${providerQuotaExhaustedMessage(quota.scope)} Active history was preserved.`
|
|
9625
|
+
);
|
|
9626
|
+
}
|
|
9492
9627
|
if (error instanceof CompactionProviderResponseError || error instanceof EmptyCompactionSummaryError) {
|
|
9493
9628
|
return compactionFailureReason(error.message);
|
|
9494
9629
|
}
|
|
@@ -9497,13 +9632,15 @@ function compactionFailureReasonFromError(error) {
|
|
|
9497
9632
|
}
|
|
9498
9633
|
function compactionFailureTurnEventPayload(error, overrides = {}) {
|
|
9499
9634
|
const rejection = compactionProviderRejection(error);
|
|
9635
|
+
const quota = rejection ? null : classifyProviderQuotaExhaustionError(error);
|
|
9500
9636
|
return {
|
|
9501
9637
|
error: overrides.error ?? compactionFailureReasonFromError(error),
|
|
9502
9638
|
code: "context_compaction_failed",
|
|
9503
9639
|
retryable: false,
|
|
9504
9640
|
recovery: "user_message",
|
|
9505
9641
|
compacted: false,
|
|
9506
|
-
...rejection ? { providerRejection: rejection } : {}
|
|
9642
|
+
...rejection ? { providerRejection: rejection } : {},
|
|
9643
|
+
...quota ? { quotaScope: quota.scope } : {}
|
|
9507
9644
|
};
|
|
9508
9645
|
}
|
|
9509
9646
|
function isCompactionSummaryFailure(error) {
|
|
@@ -9607,6 +9744,13 @@ function isTransientProviderError(error) {
|
|
|
9607
9744
|
message
|
|
9608
9745
|
);
|
|
9609
9746
|
}
|
|
9747
|
+
function hasCodexUsageLimitType(error) {
|
|
9748
|
+
return collectErrorStrings(error).some((value) => value.includes(CODEX_USAGE_LIMIT_ERROR_TYPE));
|
|
9749
|
+
}
|
|
9750
|
+
function classifyProviderQuotaExhaustionError(error) {
|
|
9751
|
+
if (isCodexTransportError(error) || isXaiSubscriptionTransportError(error)) return null;
|
|
9752
|
+
return classifyProviderQuotaError(error);
|
|
9753
|
+
}
|
|
9610
9754
|
function classifyXaiCredentialFailure(error) {
|
|
9611
9755
|
if (isProviderSafetyRefusal(error)) return null;
|
|
9612
9756
|
let relogin = error;
|
|
@@ -9724,9 +9868,9 @@ function baseAgentRunFailurePayload(error, options = {}) {
|
|
|
9724
9868
|
retryable: true
|
|
9725
9869
|
};
|
|
9726
9870
|
}
|
|
9727
|
-
if (
|
|
9871
|
+
if (!isRoutingMutationOutcomeUnknownError(error) && isModalTaskExecStartPreDispatchUnavailableError(error)) {
|
|
9728
9872
|
return {
|
|
9729
|
-
error: "The managed sandbox command
|
|
9873
|
+
error: "The managed sandbox command router was not ready before the command was sent. The same turn will retry after a short delay.",
|
|
9730
9874
|
code: "sandbox_command_start_unavailable",
|
|
9731
9875
|
retryable: true
|
|
9732
9876
|
};
|
|
@@ -9783,7 +9927,7 @@ function baseAgentRunFailurePayload(error, options = {}) {
|
|
|
9783
9927
|
};
|
|
9784
9928
|
}
|
|
9785
9929
|
const usageLimit = classifyCodexUsageLimitError(error);
|
|
9786
|
-
if (usageLimit) {
|
|
9930
|
+
if (usageLimit && (isCodexTransportError(error) || hasCodexUsageLimitType(error))) {
|
|
9787
9931
|
return codexUsageLimitFailurePayload(usageLimit, message);
|
|
9788
9932
|
}
|
|
9789
9933
|
const codexTimeout = classifyCodexResponseTimeoutError(error, {
|
|
@@ -9828,6 +9972,16 @@ function baseAgentRunFailurePayload(error, options = {}) {
|
|
|
9828
9972
|
retryable: true
|
|
9829
9973
|
};
|
|
9830
9974
|
}
|
|
9975
|
+
const quota = classifyProviderQuotaExhaustionError(error);
|
|
9976
|
+
if (quota) {
|
|
9977
|
+
return {
|
|
9978
|
+
error: providerQuotaExhaustedMessage(quota.scope),
|
|
9979
|
+
code: PROVIDER_QUOTA_EXHAUSTED_CODE,
|
|
9980
|
+
retryable: false,
|
|
9981
|
+
quotaScope: quota.scope,
|
|
9982
|
+
...message ? { detail: message } : {}
|
|
9983
|
+
};
|
|
9984
|
+
}
|
|
9831
9985
|
if (status === 429 || code === "rate_limit_exceeded" || /(?:too many requests|rate.?limit|\b429\b)/i.test(message)) {
|
|
9832
9986
|
return {
|
|
9833
9987
|
error: "Model provider rate limit hit. Try again in a minute or lower the reasoning effort.",
|
|
@@ -9983,6 +10137,7 @@ export {
|
|
|
9983
10137
|
persistWorkspaceArchiveCandidate,
|
|
9984
10138
|
putVersion1TarArchiveOrInline,
|
|
9985
10139
|
sandboxLeaseHolderIdForAttempt,
|
|
10140
|
+
createFreshSandboxReadinessReplacementBudget,
|
|
9986
10141
|
waitForWarmSnapshot,
|
|
9987
10142
|
maybePersistWarmWorkspaceSnapshot,
|
|
9988
10143
|
resumeBoxForTurn,
|
|
@@ -10064,4 +10219,4 @@ export {
|
|
|
10064
10219
|
codexUsageLimitFailurePayload,
|
|
10065
10220
|
CODEX_USAGE_LIMIT_MAX_RESUME_MS
|
|
10066
10221
|
};
|
|
10067
|
-
//# sourceMappingURL=chunk-
|
|
10222
|
+
//# sourceMappingURL=chunk-7M6G2SCF.js.map
|