@opengeni/worker-bundle 3.0.1-canary.38872461489001 → 3.1.2

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.
@@ -20,6 +20,7 @@ export declare const PROVIDER_RATE_LIMIT_BACKOFF_MS: readonly [10000, 20000, 400
20
20
  /** Positive-only spread: never shorten the provider's minimum delay. */
21
21
  export declare function providerRecoveryJitterMs(delayMs: number, sample: number): number;
22
22
  export declare const POST_COMPACTION_CONTINUATION_EMPTY_CODE = "post_compaction_continuation_empty";
23
+ export declare const RETAINED_ATTACHMENT_UNAVAILABLE_CODE = "retained_attachment_unavailable";
23
24
  export declare class PostCompactionContinuationEmptyError extends Error {
24
25
  readonly code = "post_compaction_continuation_empty";
25
26
  constructor();
@@ -69,6 +69,18 @@ export declare const MAX_RETAINED_MODEL_ATTACHMENT_BYTES: number;
69
69
  export declare class RetainedAttachmentTransportLimitError extends Error {
70
70
  constructor();
71
71
  }
72
+ /**
73
+ * A retained image the conversation already sent could not be read from
74
+ * object storage, for example while a storage replica catches up after an
75
+ * outage. Its pixels are part of the accepted prompt, so the turn waits and
76
+ * retries rather than continuing without them. Integrity mismatches are not
77
+ * this error: retrying cannot repair different bytes.
78
+ */
79
+ export declare class RetainedAttachmentUnavailableError extends Error {
80
+ readonly fileIds: readonly string[];
81
+ constructor(fileIds: readonly string[]);
82
+ }
83
+ export type ModelAttachmentReadFailure = "unavailable" | "integrity_mismatch";
72
84
  export type ModelAttachmentContent = {
73
85
  kind: "image" | "file";
74
86
  fileId: string;
@@ -87,11 +99,15 @@ export type ModelAttachmentInputPolicy = {
87
99
  };
88
100
  export declare function modelAttachmentContentForFiles(files: FileAsset[], readFileBytes: (file: FileAsset) => Promise<Uint8Array>, options?: {
89
101
  retainAll?: boolean;
102
+ /** Why a selected file produced no content; omitted files are not reported. */
103
+ onReadFailure?: (fileId: string, failure: ModelAttachmentReadFailure) => void;
90
104
  }): Promise<ModelAttachmentContent[]>;
91
105
  /**
92
106
  * Build one turn-scoped durable-attachment projector. Resolve active refs under
93
107
  * current file authority and memoize metadata/bytes for retries and compaction.
94
108
  * A turn boundary never changes an authorized attachment's representation.
109
+ * Images of a message stamped with an image bound are shown downscaled to fit
110
+ * it; unstamped (older) messages keep their full-resolution projection.
95
111
  */
96
112
  export declare function createModelHistoryAttachmentProjector(policy: ModelAttachmentInputPolicy, readFileBytes?: (file: FileAsset) => Promise<Uint8Array>, loadAuthorizedFiles?: (fileIds: readonly string[]) => Promise<readonly FileAsset[]>): ModelHistoryAttachmentProjector;
97
113
  /** Add current trigger refs only when older/local history predates durable stamping. */
@@ -22,7 +22,7 @@ import {
22
22
  withFirstPartyTools,
23
23
  workflowIdForSession,
24
24
  writeSessionUsageReceipts
25
- } from "./chunk-QCD6PEBU.js";
25
+ } from "./chunk-6SHXF4SU.js";
26
26
  import {
27
27
  agentRunAdmissionDenial,
28
28
  createSiteAuthMaintenanceActivities
@@ -6142,4 +6142,4 @@ export {
6142
6142
  createControlActivities,
6143
6143
  createControlActivitiesFromServices
6144
6144
  };
6145
- //# sourceMappingURL=activities-control-3PJDM3QQ.js.map
6145
+ //# sourceMappingURL=activities-control-ROJJNNTJ.js.map
@@ -111,7 +111,7 @@ import {
111
111
  wakeSubscriptionCoreWaitersAndDeliver,
112
112
  withFirstPartyTools,
113
113
  withModelRoutePresentation
114
- } from "./chunk-QCD6PEBU.js";
114
+ } from "./chunk-6SHXF4SU.js";
115
115
  import {
116
116
  createFreshSandboxReadinessReplacementBudget,
117
117
  establishSelfhostedTurnSession,
@@ -42524,4 +42524,4 @@ export {
42524
42524
  createTurnActivities,
42525
42525
  createTurnActivitiesFromServices
42526
42526
  };
42527
- //# sourceMappingURL=activities-turn-2ILW6PRK.js.map
42527
+ //# sourceMappingURL=activities-turn-4SWYWKI5.js.map
File without changes
File without changes
@@ -6183,6 +6183,7 @@ import {
6183
6183
  MODEL_ATTACHMENT_REFS_FIELD,
6184
6184
  MODEL_ATTACHMENT_CATALOG_MARKER,
6185
6185
  MODEL_ATTACHMENT_CATALOG_RENDERED_FIELD,
6186
+ MODEL_ATTACHMENT_IMAGE_MAX_DIMENSION_FIELD,
6186
6187
  FileResourceRef,
6187
6188
  resourceMountPath,
6188
6189
  readTurnExecutionPolicyV1 as readTurnExecutionPolicyV14,
@@ -6198,6 +6199,7 @@ import {
6198
6199
  readSubscriptionHistoryProvenance
6199
6200
  } from "@opengeni/db";
6200
6201
  import {
6202
+ createModelImageSizer,
6201
6203
  projectHistoryForProvider,
6202
6204
  projectRejectedProviderArtifactsFromSerializedRunState,
6203
6205
  projectRejectedReasoningArtifact,
@@ -6295,6 +6297,14 @@ var RetainedAttachmentTransportLimitError = class extends Error {
6295
6297
  this.name = "RetainedAttachmentTransportLimitError";
6296
6298
  }
6297
6299
  };
6300
+ var RetainedAttachmentUnavailableError = class extends Error {
6301
+ fileIds;
6302
+ constructor(fileIds) {
6303
+ super("An image attached earlier in this conversation can't be read from storage right now.");
6304
+ this.name = "RetainedAttachmentUnavailableError";
6305
+ this.fileIds = [...fileIds];
6306
+ }
6307
+ };
6298
6308
  var MODEL_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["image/gif", "image/jpeg", "image/png", "image/webp"]);
6299
6309
  var MODEL_FILE_CONTENT_TYPES = /* @__PURE__ */ new Set([
6300
6310
  "application/json",
@@ -6349,12 +6359,14 @@ async function modelAttachmentContentForFiles(files, readFileBytes, options = {}
6349
6359
  expectedSizeBytes: file.sizeBytes,
6350
6360
  actualSizeBytes: bytes.byteLength
6351
6361
  });
6362
+ options.onReadFailure?.(file.id, "integrity_mismatch");
6352
6363
  continue;
6353
6364
  }
6354
6365
  if (createHash4("sha256").update(bytes).digest("hex") !== checksum) {
6355
6366
  console.error("model attachment checksum did not match finalized metadata", {
6356
6367
  fileId: file.id
6357
6368
  });
6369
+ options.onReadFailure?.(file.id, "integrity_mismatch");
6358
6370
  continue;
6359
6371
  }
6360
6372
  attachments[index] = {
@@ -6369,6 +6381,7 @@ async function modelAttachmentContentForFiles(files, readFileBytes, options = {}
6369
6381
  fileId: file.id,
6370
6382
  errorType: safeErrorType(error)
6371
6383
  });
6384
+ options.onReadFailure?.(file.id, "unavailable");
6372
6385
  }
6373
6386
  }
6374
6387
  };
@@ -6395,12 +6408,43 @@ function attachmentReceiptText(ref) {
6395
6408
  function unavailableAttachmentReceiptText(ref) {
6396
6409
  return requesterUnavailableReceiptText(`Attachment: fileId=${ref.fileId}`, "file");
6397
6410
  }
6411
+ function attachmentImageBound(item) {
6412
+ const raw = item[MODEL_ATTACHMENT_IMAGE_MAX_DIMENSION_FIELD];
6413
+ return typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 64 && raw <= 8192 ? raw : void 0;
6414
+ }
6415
+ var boundedImageSizers = /* @__PURE__ */ new Map();
6416
+ async function boundedAttachmentImage(attachment, bound) {
6417
+ const original = { image: attachment.dataUrl, note: "" };
6418
+ const comma = attachment.dataUrl.indexOf(",");
6419
+ if (comma < 0) return original;
6420
+ const data = attachment.dataUrl.slice(comma + 1);
6421
+ let sizer = boundedImageSizers.get(bound);
6422
+ if (!sizer) {
6423
+ sizer = createModelImageSizer(bound, 10 * 1024 * 1024, { jpegQuality: 85 });
6424
+ boundedImageSizers.set(bound, sizer);
6425
+ }
6426
+ try {
6427
+ const sized = await sizer(data, attachment.contentType);
6428
+ if (sized.data === data && sized.mediaType === attachment.contentType) return original;
6429
+ return {
6430
+ image: `data:${sized.mediaType};base64,${sized.data}`,
6431
+ note: ` Shown to you downscaled to ${sized.width}x${sized.height} from ${sized.originalWidth}x${sized.originalHeight}; the file itself is full resolution.`
6432
+ };
6433
+ } catch (error) {
6434
+ console.error("model attachment image could not be resized; sending original", {
6435
+ fileId: attachment.fileId,
6436
+ errorType: safeErrorType(error)
6437
+ });
6438
+ return original;
6439
+ }
6440
+ }
6398
6441
  function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthorizedFiles) {
6399
6442
  const contentById = /* @__PURE__ */ new Map();
6400
6443
  const attemptedContentIds = /* @__PURE__ */ new Set();
6401
6444
  const fileById = /* @__PURE__ */ new Map();
6402
6445
  const resolvedFileIds = /* @__PURE__ */ new Set();
6403
6446
  const retainedByteSizes = /* @__PURE__ */ new Map();
6447
+ const boundedById = /* @__PURE__ */ new Map();
6404
6448
  return async (items, options = {}) => {
6405
6449
  for (const file of options.inlineFiles ?? []) {
6406
6450
  fileById.set(file.id, file);
@@ -6451,18 +6495,37 @@ function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthor
6451
6495
  return Boolean(descriptor && descriptor.kind === "image" && policy.supportsImageInput);
6452
6496
  });
6453
6497
  for (const file of readable) attemptedContentIds.add(file.id);
6498
+ const readFailures = /* @__PURE__ */ new Map();
6454
6499
  const content = await modelAttachmentContentForFiles(readable, readFileBytes, {
6455
- retainAll: true
6500
+ retainAll: true,
6501
+ onReadFailure: (fileId, failure) => readFailures.set(fileId, failure)
6456
6502
  });
6457
6503
  const loadedIds = new Set(content.map((entry) => entry.fileId));
6458
- for (const file of readable) {
6459
- if (file.status === "ready" && file.sizeBytes <= MAX_INLINE_MODEL_ATTACHMENT_BYTES && /^[a-f0-9]{64}$/i.test(file.sha256 ?? "") && !loadedIds.has(file.id)) {
6460
- for (const candidate of readable) attemptedContentIds.delete(candidate.id);
6461
- throw new Error(`Retained attachment bytes unavailable or invalid: ${file.id}`);
6504
+ const missing = readable.filter(
6505
+ (file) => file.status === "ready" && file.sizeBytes <= MAX_INLINE_MODEL_ATTACHMENT_BYTES && /^[a-f0-9]{64}$/i.test(file.sha256 ?? "") && !loadedIds.has(file.id)
6506
+ );
6507
+ if (missing.length > 0) {
6508
+ for (const candidate of readable) attemptedContentIds.delete(candidate.id);
6509
+ const corrupt = missing.find((file) => readFailures.get(file.id) === "integrity_mismatch");
6510
+ if (corrupt) {
6511
+ throw new Error(`Retained attachment bytes unavailable or invalid: ${corrupt.id}`);
6462
6512
  }
6513
+ throw new RetainedAttachmentUnavailableError(missing.map((file) => file.id));
6463
6514
  }
6464
6515
  for (const attachment of content) contentById.set(attachment.fileId, attachment);
6465
6516
  }
6517
+ for (const [index, refs] of refsByIndex) {
6518
+ const item = items[index];
6519
+ if (item[MODEL_ATTACHMENT_CATALOG_MARKER] === true) continue;
6520
+ const bound = attachmentImageBound(item);
6521
+ if (bound === void 0) continue;
6522
+ for (const ref of refs) {
6523
+ const attachment = fileById.has(ref.fileId) ? contentById.get(ref.fileId) : void 0;
6524
+ const key = `${bound}:${ref.fileId}`;
6525
+ if (!attachment || attachment.kind !== "image" || boundedById.has(key)) continue;
6526
+ boundedById.set(key, await boundedAttachmentImage(attachment, bound));
6527
+ }
6528
+ }
6466
6529
  const projected = [...items];
6467
6530
  for (const [index, refs] of refsByIndex) {
6468
6531
  const original = items[index];
@@ -6478,14 +6541,20 @@ function createModelHistoryAttachmentProjector(policy, readFileBytes, loadAuthor
6478
6541
  const currentFile = catalog ? void 0 : fileById.get(ref.fileId);
6479
6542
  const excluded = !catalog && loadAuthorizedFiles !== void 0 && resolvedFileIds.has(ref.fileId) && currentFile === void 0;
6480
6543
  const attachment = currentFile ? contentById.get(ref.fileId) : void 0;
6481
- const receipt = {
6482
- type: "input_text",
6483
- text: excluded ? unavailableAttachmentReceiptText(ref) : attachmentReceiptText(ref)
6484
- };
6485
6544
  if (!attachment || attachment.kind !== "image") {
6486
- return [receipt];
6545
+ return [
6546
+ {
6547
+ type: "input_text",
6548
+ text: excluded ? unavailableAttachmentReceiptText(ref) : attachmentReceiptText(ref)
6549
+ }
6550
+ ];
6487
6551
  }
6488
- return [receipt, { type: "input_image", image: attachment.dataUrl }];
6552
+ const bound = attachmentImageBound(original);
6553
+ const bounded = bound === void 0 ? void 0 : boundedById.get(`${bound}:${ref.fileId}`);
6554
+ return [
6555
+ { type: "input_text", text: attachmentReceiptText(ref) + (bounded?.note ?? "") },
6556
+ { type: "input_image", image: bounded?.image ?? attachment.dataUrl }
6557
+ ];
6489
6558
  });
6490
6559
  const clone = {
6491
6560
  ...original,
@@ -7033,6 +7102,8 @@ function providerRecoverySubject(input) {
7033
7102
  return "A required MCP server is unreachable";
7034
7103
  case "sandbox_command_start_unavailable":
7035
7104
  return "The sandbox isn't ready yet";
7105
+ case "retained_attachment_unavailable":
7106
+ return "An image from earlier in this conversation can't be read from storage";
7036
7107
  case "turn_execution_policy_definition_mismatch":
7037
7108
  return "Opengeni is applying a configuration update";
7038
7109
  default:
@@ -7059,6 +7130,18 @@ function providerRecoveryJitterMs(delayMs, sample) {
7059
7130
  return Math.floor(Math.min(5e3, delayMs * 0.2) * bounded);
7060
7131
  }
7061
7132
  var POST_COMPACTION_CONTINUATION_EMPTY_CODE = "post_compaction_continuation_empty";
7133
+ var RETAINED_ATTACHMENT_UNAVAILABLE_CODE = "retained_attachment_unavailable";
7134
+ function findRetainedAttachmentUnavailableError(error) {
7135
+ let current = error;
7136
+ const seen = /* @__PURE__ */ new Set();
7137
+ for (let depth = 0; depth < 6 && current && typeof current === "object"; depth += 1) {
7138
+ if (current instanceof RetainedAttachmentUnavailableError) return current;
7139
+ if (seen.has(current)) break;
7140
+ seen.add(current);
7141
+ current = current.cause;
7142
+ }
7143
+ return null;
7144
+ }
7062
7145
  var PostCompactionContinuationEmptyError = class extends Error {
7063
7146
  code = POST_COMPACTION_CONTINUATION_EMPTY_CODE;
7064
7147
  constructor() {
@@ -7095,7 +7178,7 @@ function providerRecoveryResult(input) {
7095
7178
  Math.max(Math.trunc(input.attemptNumber) - 1, 0),
7096
7179
  PROVIDER_RATE_LIMIT_BACKOFF_MS.length - 1
7097
7180
  )]
7098
- ) : overload || 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(
7181
+ ) : overload || input.failureCode === "provider_unavailable" || input.failureCode === "upstream_connectivity_unavailable" || input.failureCode === "sandbox_command_start_unavailable" || input.failureCode === RETAINED_ATTACHMENT_UNAVAILABLE_CODE || 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(
7099
7182
  providerDelay ?? 0,
7100
7183
  PROVIDER_CONNECTIVITY_BACKOFF_MS[Math.min(
7101
7184
  Math.max(Math.trunc(input.attemptNumber) - 1, 0),
@@ -7948,6 +8031,13 @@ function baseAgentRunFailurePayload(error, options = {}) {
7948
8031
  if (error instanceof RetainedAttachmentTransportLimitError) {
7949
8032
  return { error: error.message, code: "retained_attachment_transport_limit", retryable: false };
7950
8033
  }
8034
+ if (findRetainedAttachmentUnavailableError(error)) {
8035
+ return {
8036
+ error: "An image attached earlier in this conversation can't be read from storage right now. The same turn will retry after a short delay.",
8037
+ code: RETAINED_ATTACHMENT_UNAVAILABLE_CODE,
8038
+ retryable: true
8039
+ };
8040
+ }
7951
8041
  if (error instanceof MandatoryHistoryPersistenceError) {
7952
8042
  const databaseFailure = isSessionEventPersistenceError(error.cause) || findPostgresDriverError(error.cause) !== null || isRawDatabaseQueryError(error.cause);
7953
8043
  const underlying = databaseFailure ? agentRunFailurePayload(error.cause, options) : {
@@ -8501,4 +8591,4 @@ export {
8501
8591
  codexUsageLimitFailurePayload,
8502
8592
  classifyClaudeProviderError
8503
8593
  };
8504
- //# sourceMappingURL=chunk-QCD6PEBU.js.map
8594
+ //# sourceMappingURL=chunk-6SHXF4SU.js.map