@mastra/server 1.72.0-alpha.2 → 1.72.0-alpha.4

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.
@@ -4637,7 +4637,7 @@ function splitLines(text) {
4637
4637
  return result;
4638
4638
  }
4639
4639
  //#endregion
4640
- //#region ../memory/dist/src-B-_pkR2t.js
4640
+ //#region ../memory/dist/src-BikfoIdS.js
4641
4641
  var __defProp$3 = Object.defineProperty;
4642
4642
  var __exportAll = (all, no_symbols) => {
4643
4643
  let target = {};
@@ -23223,9 +23223,224 @@ async function applyExtractorHooks(opts) {
23223
23223
  failures: mergeExtractionFailures(failures)
23224
23224
  };
23225
23225
  }
23226
+ /**
23227
+ * Retry knobs for the internal OM transport-error retry wrapper.
23228
+ * Exported as a mutable object so tests can shrink the backoff schedule
23229
+ * without changing public API.
23230
+ *
23231
+ * With the defaults the per-retry pre-jitter backoff schedule is:
23232
+ * 1s, 2s, 4s, 8s, 16s, 32s, 64s, 120s (cap)
23233
+ * giving 8 retries / 9 total attempts and ~247s (~4 minutes) of waiting
23234
+ * before the final attempt fails. Designed to ride out short provider /
23235
+ * network blips without holding the actor turn for much longer than that.
23236
+ *
23237
+ * @internal
23238
+ */
23239
+ const RETRY_CONFIG = {
23240
+ /** Maximum number of retry *attempts* (total tries = maxRetries + 1). */
23241
+ maxRetries: 8,
23242
+ /** Initial backoff delay in milliseconds. */
23243
+ initialDelayMs: 1e3,
23244
+ /** Multiplier applied to the delay after each failed attempt. */
23245
+ backoffFactor: 2,
23246
+ /** Cap on per-attempt delay (ms). */
23247
+ maxDelayMs: 12e4,
23248
+ /** Random jitter as a fraction of the computed delay (e.g. 0.2 = ±20%). */
23249
+ jitter: .2
23250
+ };
23251
+ const TRANSIENT_MESSAGE_SUBSTRINGS = [
23252
+ "terminated",
23253
+ "fetch failed",
23254
+ "econnreset",
23255
+ "econnrefused",
23256
+ "enotfound",
23257
+ "eai_again",
23258
+ "socket hang up",
23259
+ "network error",
23260
+ "request timed out",
23261
+ "request timeout",
23262
+ "connection reset",
23263
+ "connection closed"
23264
+ ];
23226
23265
  function isRecord$5(value) {
23227
23266
  return typeof value === "object" && value !== null;
23228
23267
  }
23268
+ function isAbortError$1(error) {
23269
+ if (!isRecord$5(error)) return false;
23270
+ if (error.name === "AbortError") return true;
23271
+ if (typeof error.code === "string" && error.code === "ABORT_ERR") return true;
23272
+ return false;
23273
+ }
23274
+ function hasTransientMessage(value) {
23275
+ if (!isRecord$5(value)) return false;
23276
+ const message = typeof value.message === "string" ? value.message.toLowerCase() : "";
23277
+ if (message && TRANSIENT_MESSAGE_SUBSTRINGS.some((sub) => message.includes(sub))) return true;
23278
+ if (typeof value.code === "string" && value.code.toUpperCase().startsWith("UND_ERR_")) return true;
23279
+ return false;
23280
+ }
23281
+ function isRetryableHttpStatus(status) {
23282
+ if (status === 408 || status === 425 || status === 429) return true;
23283
+ return status >= 500 && status <= 599;
23284
+ }
23285
+ function hasRetryableHttpStatus(value) {
23286
+ if (!isRecord$5(value)) return false;
23287
+ if (typeof value.statusCode === "number" && isRetryableHttpStatus(value.statusCode)) return true;
23288
+ if (typeof value.code === "number" && isRetryableHttpStatus(value.code)) return true;
23289
+ return false;
23290
+ }
23291
+ function hasIsRetryableFlag(value) {
23292
+ if (!isRecord$5(value)) return false;
23293
+ return value.isRetryable === true;
23294
+ }
23295
+ /**
23296
+ * Returns true when a user-initiated cancellation appears anywhere in the
23297
+ * error's `cause`/`error` wrapper chain, so a wrapped abort can never be
23298
+ * mistaken for a retryable or survivable provider failure.
23299
+ *
23300
+ * @internal
23301
+ */
23302
+ function hasAbortInChain(error) {
23303
+ const seen = /* @__PURE__ */ new Set();
23304
+ function visit(candidate) {
23305
+ if (isAbortError$1(candidate)) return true;
23306
+ if (!isRecord$5(candidate)) return false;
23307
+ if (seen.has(candidate)) return false;
23308
+ seen.add(candidate);
23309
+ return visit(candidate.cause) || visit(candidate.error);
23310
+ }
23311
+ return visit(error);
23312
+ }
23313
+ /**
23314
+ * Returns true when the given error looks like a transient transport-class
23315
+ * failure that's worth retrying — undici `terminated`, `fetch failed`,
23316
+ * `UND_ERR_*` codes, AI SDK `APICallError` with `isRetryable: true`, and
23317
+ * common HTTP 408/425/429/5xx statuses. Walks the `error.cause` chain so
23318
+ * wrapper errors don't hide the real failure.
23319
+ *
23320
+ * Never retries on user-initiated aborts.
23321
+ *
23322
+ * @internal
23323
+ */
23324
+ function isTransientLLMError(error) {
23325
+ if (hasAbortInChain(error)) return false;
23326
+ const visited = /* @__PURE__ */ new WeakSet();
23327
+ function visit(candidate) {
23328
+ if (isRecord$5(candidate)) {
23329
+ if (visited.has(candidate)) return false;
23330
+ visited.add(candidate);
23331
+ }
23332
+ if (hasTransientMessage(candidate)) return true;
23333
+ if (hasRetryableHttpStatus(candidate)) return true;
23334
+ if (hasIsRetryableFlag(candidate)) return true;
23335
+ if (isRecord$5(candidate)) {
23336
+ if (visit(candidate.cause)) return true;
23337
+ if (visit(candidate.error)) return true;
23338
+ }
23339
+ return false;
23340
+ }
23341
+ return visit(error);
23342
+ }
23343
+ /**
23344
+ * Compute the backoff delay (ms) for the Nth retry (0-indexed).
23345
+ *
23346
+ * Exponential growth (`initialDelayMs * backoffFactor^attempt`) capped at
23347
+ * `maxDelayMs`, then nudged by ±`jitter` (fractional). Exported for unit
23348
+ * tests that lock the schedule against drift.
23349
+ *
23350
+ * @internal
23351
+ */
23352
+ function computeDelay(attempt) {
23353
+ const base = RETRY_CONFIG.initialDelayMs * Math.pow(RETRY_CONFIG.backoffFactor, attempt);
23354
+ const capped = Math.min(base, RETRY_CONFIG.maxDelayMs);
23355
+ if (RETRY_CONFIG.jitter <= 0) return capped;
23356
+ const jitterRange = capped * RETRY_CONFIG.jitter;
23357
+ const offset = (Math.random() * 2 - 1) * jitterRange;
23358
+ return Math.max(0, Math.round(capped + offset));
23359
+ }
23360
+ function sleep(ms, abortSignal) {
23361
+ if (ms <= 0) return Promise.resolve();
23362
+ return new Promise((resolve, reject) => {
23363
+ if (abortSignal?.aborted) {
23364
+ reject(/* @__PURE__ */ new Error("The operation was aborted."));
23365
+ return;
23366
+ }
23367
+ const timer = setTimeout(() => {
23368
+ abortSignal?.removeEventListener("abort", onAbort);
23369
+ resolve();
23370
+ }, ms);
23371
+ const onAbort = () => {
23372
+ clearTimeout(timer);
23373
+ abortSignal?.removeEventListener("abort", onAbort);
23374
+ reject(/* @__PURE__ */ new Error("The operation was aborted."));
23375
+ };
23376
+ abortSignal?.addEventListener("abort", onAbort, { once: true });
23377
+ });
23378
+ }
23379
+ /**
23380
+ * Run `fn` with retries on transient transport-class errors.
23381
+ *
23382
+ * Non-transient errors (auth, validation, schema, etc.) are rethrown
23383
+ * immediately. User-initiated aborts are rethrown without delay.
23384
+ *
23385
+ * @internal
23386
+ */
23387
+ async function withRetry(fn, opts) {
23388
+ const { label, abortSignal, maxRetries = RETRY_CONFIG.maxRetries } = opts;
23389
+ let attempt = 0;
23390
+ while (true) {
23391
+ if (abortSignal?.aborted) throw new Error("The operation was aborted.");
23392
+ try {
23393
+ return await fn();
23394
+ } catch (error) {
23395
+ if (hasAbortInChain(error) || abortSignal?.aborted) throw error;
23396
+ if (attempt >= maxRetries || !isTransientLLMError(error)) {
23397
+ if (attempt > 0) omDebug(`[OM:retry:${label}] giving up after ${attempt} retry/retries: ${error instanceof Error ? error.message : String(error)}`);
23398
+ throw error;
23399
+ }
23400
+ const delay = computeDelay(attempt);
23401
+ attempt++;
23402
+ omDebug(`[OM:retry:${label}] transient error on attempt ${attempt}, retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`);
23403
+ await sleep(delay, abortSignal);
23404
+ }
23405
+ }
23406
+ }
23407
+ const AI_API_CALL_ERROR_MARKER = Symbol.for("vercel.ai.error.AI_APICallError");
23408
+ function isRecord$4(value) {
23409
+ return typeof value === "object" && value !== null;
23410
+ }
23411
+ function isOmModelExecutionFailure(error) {
23412
+ if (hasAbortInChain(error)) return false;
23413
+ if (isTransientLLMError(error)) return true;
23414
+ const visited = /* @__PURE__ */ new Set();
23415
+ let current = error;
23416
+ while (isRecord$4(current) && !visited.has(current)) {
23417
+ visited.add(current);
23418
+ if (Object.prototype.hasOwnProperty.call(current, AI_API_CALL_ERROR_MARKER)) return Reflect.get(current, AI_API_CALL_ERROR_MARKER) === true;
23419
+ current = current.cause ?? current.error;
23420
+ }
23421
+ return false;
23422
+ }
23423
+ var OmModelExecutionError = class extends Error {
23424
+ failureKind;
23425
+ constructor(failureKind, cause) {
23426
+ super(formatOmError(cause), { cause });
23427
+ this.failureKind = failureKind;
23428
+ this.name = "OmModelExecutionError";
23429
+ }
23430
+ };
23431
+ function isOmModelExecutionError(error) {
23432
+ try {
23433
+ return error instanceof OmModelExecutionError;
23434
+ } catch {
23435
+ return false;
23436
+ }
23437
+ }
23438
+ function getOmFailureMetadata(error, failurePolicy) {
23439
+ return {
23440
+ failurePolicy,
23441
+ ...isOmModelExecutionError(error) ? { failureKind: error.failureKind } : {}
23442
+ };
23443
+ }
23229
23444
  /** Keep provider diagnostics in streamed/persisted markers, not whole API request/response objects. */
23230
23445
  function formatOmError(error) {
23231
23446
  const details = /* @__PURE__ */ new Set();
@@ -23235,7 +23450,7 @@ function formatOmError(error) {
23235
23450
  };
23236
23451
  function collectErrorDetails(value, depth) {
23237
23452
  if (depth > 5) return;
23238
- if (!isRecord$5(value)) {
23453
+ if (!isRecord$4(value)) {
23239
23454
  if (value !== void 0) add(String(value));
23240
23455
  return;
23241
23456
  }
@@ -23245,10 +23460,10 @@ function formatOmError(error) {
23245
23460
  if (typeof value.statusCode === "number") add(`HTTP ${value.statusCode}`);
23246
23461
  if (typeof value.responseBody === "string") try {
23247
23462
  const body = JSON.parse(value.responseBody);
23248
- if (isRecord$5(body)) {
23463
+ if (isRecord$4(body)) {
23249
23464
  add(body.message);
23250
23465
  add(body.detail);
23251
- if (isRecord$5(body.error)) add(body.error.message);
23466
+ if (isRecord$4(body.error)) add(body.error.message);
23252
23467
  else add(body.error);
23253
23468
  }
23254
23469
  } catch {}
@@ -23261,8 +23476,8 @@ function formatOmError(error) {
23261
23476
  const message = [...details].join(": ") || "Unknown error";
23262
23477
  return message.length > 2e3 ? `${message.slice(0, 1997)}...` : message;
23263
23478
  }
23264
- function isAbortError$1(error, abortSignal) {
23265
- return abortSignal?.aborted === true || error instanceof DOMException && error.name === "AbortError" || error instanceof Error && error.name === "AbortError";
23479
+ function isAbortError$5(error, abortSignal) {
23480
+ return abortSignal?.aborted === true || hasAbortInChain(error);
23266
23481
  }
23267
23482
  function shouldRetryEmptyStructuredObject(object, extractors) {
23268
23483
  return Object.keys(object).length === 0 && extractors.some((extractor) => extractor.retryStructuredExtractionOnEmptyObject);
@@ -23288,7 +23503,12 @@ If a prior value is still applicable and carry-forward is enabled, return that p
23288
23503
  ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values\n\n${priorLines.join("\n\n")}` : ""}`;
23289
23504
  const values = {};
23290
23505
  const failures = [];
23291
- const streamWithStructuredOutput = async (jsonPromptInjection) => {
23506
+ const streamWithStructuredOutput = async (jsonPromptInjection) => withRetry(() => streamOnce(jsonPromptInjection), {
23507
+ label: `om-${opts.source}-structured-extraction`,
23508
+ abortSignal: opts.abortSignal,
23509
+ maxRetries: 1
23510
+ });
23511
+ const streamOnce = async (jsonPromptInjection) => {
23292
23512
  const object = await (await opts.agent.stream(prompt, {
23293
23513
  structuredOutput: {
23294
23514
  schema,
@@ -23308,11 +23528,21 @@ ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values
23308
23528
  object = await streamWithStructuredOutput();
23309
23529
  retryEmptyObject = shouldRetryEmptyStructuredObject(object, structuredExtractors);
23310
23530
  } catch (error) {
23311
- if (isAbortError$1(error, opts.abortSignal)) throw error;
23531
+ if (isAbortError$5(error, opts.abortSignal)) throw error;
23532
+ if (isTransientLLMError(error)) {
23533
+ const message = error instanceof Error ? error.message : String(error);
23534
+ return {
23535
+ values,
23536
+ failures: structuredExtractors.map((extractor) => ({
23537
+ slug: extractor.slug,
23538
+ error: message
23539
+ }))
23540
+ };
23541
+ }
23312
23542
  try {
23313
23543
  object = await streamWithStructuredOutput(coreFeatures.has("json-prompt-injection:inline") ? "inline" : true);
23314
23544
  } catch (fallbackError) {
23315
- if (isAbortError$1(fallbackError, opts.abortSignal)) throw fallbackError;
23545
+ if (isAbortError$5(fallbackError, opts.abortSignal)) throw fallbackError;
23316
23546
  const message = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
23317
23547
  return {
23318
23548
  values,
@@ -23326,7 +23556,7 @@ ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values
23326
23556
  if (retryEmptyObject) try {
23327
23557
  object = await streamWithStructuredOutput(coreFeatures.has("json-prompt-injection:inline") ? "inline" : true);
23328
23558
  } catch (fallbackError) {
23329
- if (isAbortError$1(fallbackError, opts.abortSignal)) throw fallbackError;
23559
+ if (isAbortError$5(fallbackError, opts.abortSignal)) throw fallbackError;
23330
23560
  const message = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
23331
23561
  return {
23332
23562
  values,
@@ -23352,15 +23582,15 @@ ${extractorInstructions}${priorLines.length > 0 ? `\n\n## Prior Extracted Values
23352
23582
  };
23353
23583
  }
23354
23584
  const LEGACY_SYSTEM_REMINDER_METADATA_KEY = "dynamicAgentsMdReminder";
23355
- function isRecord$4(value) {
23585
+ function isRecord$3(value) {
23356
23586
  return typeof value === "object" && value !== null;
23357
23587
  }
23358
23588
  function isSystemReminderMessage(message) {
23359
- if (!isRecord$4(message.content)) return false;
23589
+ if (!isRecord$3(message.content)) return false;
23360
23590
  const metadata = message.content.metadata;
23361
- if (message.role === "signal") return isRecord$4(metadata) && isRecord$4(metadata.signal) && (metadata.signal.type === "system-reminder" || metadata.signal.type === "reactive");
23591
+ if (message.role === "signal") return isRecord$3(metadata) && isRecord$3(metadata.signal) && (metadata.signal.type === "system-reminder" || metadata.signal.type === "reactive");
23362
23592
  if (message.role !== "user") return false;
23363
- if (isRecord$4(metadata) && (isRecord$4(metadata.systemReminder) || LEGACY_SYSTEM_REMINDER_METADATA_KEY in metadata)) return true;
23593
+ if (isRecord$3(metadata) && (isRecord$3(metadata.systemReminder) || LEGACY_SYSTEM_REMINDER_METADATA_KEY in metadata)) return true;
23364
23594
  const firstTextPart = message.content.parts.find((part) => part.type === "text");
23365
23595
  return typeof firstTextPart?.text === "string" && firstTextPart.text.startsWith("<system-reminder");
23366
23596
  }
@@ -23419,12 +23649,41 @@ function stripEphemeralAnchorIds(observations) {
23419
23649
  * Date/time utility functions for Observational Memory.
23420
23650
  * Pure functions for formatting relative timestamps and annotating observations.
23421
23651
  */
23422
- /**
23423
- * Format a relative time string like "5 days ago", "2 weeks ago", "today", etc.
23424
- */
23425
- function formatRelativeTime(date, currentDate) {
23426
- const diffMs = currentDate.getTime() - date.getTime();
23427
- const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
23652
+ const DAY_MS = 1440 * 60 * 1e3;
23653
+ /** Day number of the calendar date a parsed date names. Parsed dates are built from local-time fields. */
23654
+ function calendarDay(date) {
23655
+ return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) / DAY_MS;
23656
+ }
23657
+ const knownTimeZones = /* @__PURE__ */ new Map();
23658
+ /** `timeZone` when this runtime recognises it; otherwise undefined, which means the process time zone. */
23659
+ function resolveTimeZone(timeZone) {
23660
+ if (!timeZone) return void 0;
23661
+ let known = knownTimeZones.get(timeZone);
23662
+ if (known === void 0) {
23663
+ try {
23664
+ new Intl.DateTimeFormat("en-US", { timeZone });
23665
+ known = true;
23666
+ } catch {
23667
+ known = false;
23668
+ }
23669
+ knownTimeZones.set(timeZone, known);
23670
+ }
23671
+ return known ? timeZone : void 0;
23672
+ }
23673
+ /** Day number of the calendar date `instant` falls on in `timeZone` (the process time zone when unset). */
23674
+ function calendarDayIn(instant, timeZone) {
23675
+ const zone = resolveTimeZone(timeZone);
23676
+ if (!zone) return calendarDay(instant);
23677
+ const parts = new Intl.DateTimeFormat("en-US", {
23678
+ timeZone: zone,
23679
+ year: "numeric",
23680
+ month: "numeric",
23681
+ day: "numeric"
23682
+ }).formatToParts(instant);
23683
+ const part = (type) => Number(parts.find((p) => p.type === type)?.value);
23684
+ return Date.UTC(part("year"), part("month") - 1, part("day")) / DAY_MS;
23685
+ }
23686
+ function formatRelativeDays(diffDays) {
23428
23687
  if (diffDays < 0) {
23429
23688
  const futureDays = Math.abs(diffDays);
23430
23689
  if (futureDays === 1) return "tomorrow";
@@ -23450,8 +23709,7 @@ function formatRelativeTime(date, currentDate) {
23450
23709
  * Returns null for consecutive days (no gap marker needed).
23451
23710
  */
23452
23711
  function formatGapBetweenDates(prevDate, currDate) {
23453
- const diffMs = currDate.getTime() - prevDate.getTime();
23454
- const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
23712
+ const diffDays = calendarDay(currDate) - calendarDay(prevDate);
23455
23713
  if (diffDays <= 1) return null;
23456
23714
  else if (diffDays < 7) return `[${diffDays} days later]`;
23457
23715
  else if (diffDays < 14) return `[1 week later]`;
@@ -23459,45 +23717,156 @@ function formatGapBetweenDates(prevDate, currDate) {
23459
23717
  else if (diffDays < 60) return `[1 month later]`;
23460
23718
  else return `[${Math.floor(diffDays / 30)} months later]`;
23461
23719
  }
23720
+ const MONTH_INDEX = {
23721
+ jan: 0,
23722
+ feb: 1,
23723
+ mar: 2,
23724
+ apr: 3,
23725
+ may: 4,
23726
+ jun: 5,
23727
+ jul: 6,
23728
+ aug: 7,
23729
+ sep: 8,
23730
+ oct: 9,
23731
+ nov: 10,
23732
+ dec: 11
23733
+ };
23734
+ const MONTH = String.raw`(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|June?|July?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\.?`;
23735
+ const DAY = String.raw`\d{1,2}(?:st|nd|rd|th)?`;
23736
+ const YEAR = String.raw`(?:19|20|21)\d{2}(?!\d)`;
23737
+ const MERIDIEM = String.raw`(?:[AaPp]\.[Mm]\.|[AaPp][Mm]\b)`;
23738
+ const TIME = String.raw`(?:,?\s+(?:at\s+)?\d{1,2}:\d{2}(?:\s*${MERIDIEM})?|\s+at\s+\d{1,2}\s*${MERIDIEM})`;
23739
+ const QUALIFIER = String.raw`(?:(?:early|mid|late)[- ](?:to[- ](?:early|mid|late)[- ])?)`;
23740
+ const RANGE_SEP = String.raw`(?:\s*[–—]\s*|\s*-\s*|\s+(?:to|through|until)\s+)`;
23741
+ /**
23742
+ * Dates written into observation text that carry their own year, longest forms first:
23743
+ * "Mar 1 - Mar 18, 2025", "May 27-28, 2023", "January 10, 2024 at 3:00 PM",
23744
+ * "June–July 2022", "Dec 2021 – June 2023", "late April 2023".
23745
+ * Bare years, dates without a year, and ISO dates (often part of model IDs, API versions,
23746
+ * paths and branch names) are deliberately not matched.
23747
+ */
23748
+ const FREE_TEXT_DATE = new RegExp([
23749
+ String.raw`\b${MONTH}\s+${DAY}(?:,?\s+${YEAR})?${RANGE_SEP}${MONTH}\s+${DAY},?\s+${YEAR}${TIME}?`,
23750
+ String.raw`\b${MONTH}\s+${DAY}${RANGE_SEP}${DAY},?\s+${YEAR}`,
23751
+ String.raw`\b${MONTH}\s+${DAY},?\s+${YEAR}${TIME}?`,
23752
+ String.raw`\b${QUALIFIER}?${MONTH}(?:\s+${YEAR})?${RANGE_SEP}${QUALIFIER}?${MONTH}\s+${YEAR}`,
23753
+ String.raw`\b${QUALIFIER}?${MONTH}\s+${YEAR}`
23754
+ ].join("|"), "g");
23755
+ const ENDPOINT = new RegExp(String.raw`^(?:(early|mid|late)\s*)?(?:(${MONTH})\s*)?(?:(\d{1,2})(?:st|nd|rd|th)?)?,?\s*(?:(${YEAR}))?$`, "i");
23756
+ function parseEndpoint(text) {
23757
+ const match = ENDPOINT.exec(text.trim());
23758
+ if (!match || !match[0]) return null;
23759
+ const [, qualifier, month, day, year] = match;
23760
+ return {
23761
+ ...qualifier ? { qualifier: qualifier.toLowerCase() } : {},
23762
+ ...month ? { month: MONTH_INDEX[month.slice(0, 3).toLowerCase()] } : {},
23763
+ ...day ? { day: Number(day) } : {},
23764
+ ...year ? { year: Number(year) } : {}
23765
+ };
23766
+ }
23767
+ const QUALIFIER_DAY = {
23768
+ early: 7,
23769
+ mid: 15,
23770
+ late: 23
23771
+ };
23772
+ const QUALIFIER_MONTH = {
23773
+ early: [1, 15],
23774
+ mid: [6, 1],
23775
+ late: [10, 15]
23776
+ };
23777
+ /** Earliest and latest local day an endpoint can mean; null when it has no year or is not a real date. */
23778
+ function endpointBounds(date) {
23779
+ const { qualifier, month, day, year } = date;
23780
+ if (year === void 0) return null;
23781
+ if (month === void 0) {
23782
+ if (day !== void 0) return null;
23783
+ if (qualifier) {
23784
+ const [m, d] = QUALIFIER_MONTH[qualifier];
23785
+ return [new Date(year, m, d), new Date(year, m, d)];
23786
+ }
23787
+ return [new Date(year, 0, 1), new Date(year, 11, 31)];
23788
+ }
23789
+ if (day !== void 0) {
23790
+ const point = new Date(year, month, day);
23791
+ if (point.getMonth() !== month) return null;
23792
+ return [point, point];
23793
+ }
23794
+ if (qualifier) {
23795
+ const point = new Date(year, month, QUALIFIER_DAY[qualifier]);
23796
+ return [point, point];
23797
+ }
23798
+ return [new Date(year, month, 1), new Date(year, month + 1, 0)];
23799
+ }
23800
+ /** Parses one alternative: a single date or a two-ended range, filling each end's missing parts from the other. */
23801
+ function parseSpanAlternative(text) {
23802
+ const ends = text.split(new RegExp(`${RANGE_SEP}(?=\\S)`)).filter(Boolean);
23803
+ if (ends.length === 0 || ends.length > 2) return null;
23804
+ const parsed = ends.map(parseEndpoint);
23805
+ if (parsed.some((end) => end === null)) return null;
23806
+ const [first, second = first] = parsed;
23807
+ const from = { ...first };
23808
+ const to = { ...second };
23809
+ const fromYearInferred = from.year === void 0;
23810
+ const toYearInferred = to.year === void 0;
23811
+ from.year ??= to.year;
23812
+ to.year ??= from.year;
23813
+ if (from.month === void 0 && (from.day !== void 0 || from.qualifier) && to.month !== void 0) from.month = to.month;
23814
+ if (to.month === void 0 && to.day !== void 0 && from.month !== void 0) to.month = from.month;
23815
+ if (from.month !== void 0 && to.month !== void 0 && from.month > to.month && from.year === to.year) {
23816
+ if (fromYearInferred) from.year -= 1;
23817
+ else if (toYearInferred) to.year += 1;
23818
+ }
23819
+ const fromBounds = endpointBounds(from);
23820
+ const toBounds = endpointBounds(to);
23821
+ if (!fromBounds || !toBounds) return null;
23822
+ const span = {
23823
+ start: fromBounds[0],
23824
+ end: toBounds[1]
23825
+ };
23826
+ return span.start <= span.end ? span : null;
23827
+ }
23828
+ function normalizeDateText(text) {
23829
+ return text.replace(/\s+/g, " ").trim().replace(/^(?:approx(?:\.|imately)?|about|around|circa|c\.|~)\s*/i, "").replace(/^(?:by|in|until|before|after)\s+/i, "").replace(/\b(?:the\s+)?end\s+of\s+/gi, "late ").replace(/\b(?:the\s+)?(?:start|beginning)\s+of\s+/gi, "early ").replace(/\b(\d{4})-(\d{2})-(\d{2})\b/g, (whole, y, m, d) => {
23830
+ const month = Object.keys(MONTH_INDEX)[Number(m) - 1];
23831
+ return month ? `${month} ${Number(d)}, ${y}` : whole;
23832
+ }).replace(new RegExp(TIME, "g"), "").replace(/\b(early|mid|late|to)-/gi, "$1 ").replace(/ {2,}/g, " ").trim();
23833
+ }
23462
23834
  /**
23463
- * Parses a date string like "May 30, 2023", "May 27-28, 2023", "late April 2023", etc.
23464
- * Returns the parsed Date or null if unparseable.
23835
+ * Parses the whole of `text` as a date or date range. Accepts "May 30, 2023",
23836
+ * "Mar 22, 2025 at 18:08", "May 27-28, 2023", "Dec 27–31, 2021", "Mar 1 - Mar 18, 2025",
23837
+ * "Aug 1, 2024 - Feb 28, 2025", "August 2024", "June–July 2022", "late April 2023",
23838
+ * "mid-to-late May 2023", "late 2023", "2035", "2021–2026", an "approx." prefix, and
23839
+ * "A or B" alternatives (their union). Returns null when no year is known.
23465
23840
  */
23466
- function parseDateFromContent(dateContent) {
23467
- let targetDate = null;
23468
- const simpleDateMatch = dateContent.match(/([A-Z][a-z]+)\s+(\d{1,2}),?\s+(\d{4})/);
23469
- if (simpleDateMatch) {
23470
- const parsed = /* @__PURE__ */ new Date(`${simpleDateMatch[1]} ${simpleDateMatch[2]}, ${simpleDateMatch[3]}`);
23471
- if (!isNaN(parsed.getTime())) targetDate = parsed;
23472
- }
23473
- if (!targetDate) {
23474
- const rangeMatch = dateContent.match(/([A-Z][a-z]+)\s+(\d{1,2})-\d{1,2},?\s+(\d{4})/);
23475
- if (rangeMatch) {
23476
- const parsed = /* @__PURE__ */ new Date(`${rangeMatch[1]} ${rangeMatch[2]}, ${rangeMatch[3]}`);
23477
- if (!isNaN(parsed.getTime())) targetDate = parsed;
23478
- }
23479
- }
23480
- if (!targetDate) {
23481
- const vagueMatch = dateContent.match(/(late|early|mid)[- ]?(?:to[- ]?(?:late|early|mid)[- ]?)?([A-Z][a-z]+)\s+(\d{4})/i);
23482
- if (vagueMatch) {
23483
- const month = vagueMatch[2];
23484
- const year = vagueMatch[3];
23485
- const modifier = vagueMatch[1].toLowerCase();
23486
- let day = 15;
23487
- if (modifier === "early") day = 7;
23488
- if (modifier === "late") day = 23;
23489
- const parsed = /* @__PURE__ */ new Date(`${month} ${day}, ${year}`);
23490
- if (!isNaN(parsed.getTime())) targetDate = parsed;
23491
- }
23492
- }
23493
- if (!targetDate) {
23494
- const crossMonthMatch = dateContent.match(/([A-Z][a-z]+)\s+to\s+(?:early\s+)?([A-Z][a-z]+)\s+(\d{4})/i);
23495
- if (crossMonthMatch) {
23496
- const parsed = /* @__PURE__ */ new Date(`${crossMonthMatch[2]} 1, ${crossMonthMatch[3]}`);
23497
- if (!isNaN(parsed.getTime())) targetDate = parsed;
23498
- }
23499
- }
23500
- return targetDate;
23841
+ function parseDateSpan(text) {
23842
+ const alternatives = normalizeDateText(text).split(/\s+or\s+/i).map(parseSpanAlternative);
23843
+ if (alternatives.length === 0 || alternatives.some((span) => span === null)) return null;
23844
+ const spans = alternatives;
23845
+ return {
23846
+ start: new Date(Math.min(...spans.map((span) => span.start.getTime()))),
23847
+ end: new Date(Math.max(...spans.map((span) => span.end.getTime())))
23848
+ };
23849
+ }
23850
+ const QUALIFIED_YEAR = new RegExp(String.raw`\b(?:by|in|until|before|after|(?:the\s+)?(?:early|mid|late|end\s+of|start\s+of|beginning\s+of))\s+${YEAR}`, "gi");
23851
+ /**
23852
+ * Like `parseDateSpan`, but falls back to the first dated expression inside longer text,
23853
+ * then to a year on its own ("by late 2027", "$500 in 2024"). Only for text known to be a date.
23854
+ */
23855
+ function findDateSpan(text) {
23856
+ const whole = parseDateSpan(text);
23857
+ if (whole) return whole;
23858
+ for (const pattern of [FREE_TEXT_DATE, QUALIFIED_YEAR]) for (const match of text.matchAll(pattern)) {
23859
+ const span = parseDateSpan(match[0]);
23860
+ if (span) return span;
23861
+ }
23862
+ return null;
23863
+ }
23864
+ function relativeSpan(span, today) {
23865
+ const start = formatRelativeDays(today - calendarDay(span.start));
23866
+ const end = formatRelativeDays(today - calendarDay(span.end));
23867
+ if (start === end) return start;
23868
+ if (!end.startsWith("in ")) return `${start} to ${end}`;
23869
+ return start.startsWith("in ") ? `${start} to ${end.slice(3)}` : `${start} to ${end.slice(3)} from now`;
23501
23870
  }
23502
23871
  /**
23503
23872
  * Detects if an observation line indicates future intent (will do, plans to, looking forward to, etc.)
@@ -23517,40 +23886,59 @@ function isFutureIntentObservation(line) {
23517
23886
  }
23518
23887
  /**
23519
23888
  * Expand inline estimated dates with relative time.
23520
- * Matches patterns like "(estimated May 27-28, 2023)" or "(meaning May 30, 2023)"
23521
- * and expands them to "(meaning May 30, 2023 - which was 3 weeks ago)"
23889
+ * Matches patterns like "(estimated May 27-28, 2023)" or "(meaning May 30, 2023 at 3:00 PM)"
23890
+ * and expands them to "(meaning May 30, 2023 - 3 weeks ago)". Notes without a year are left alone.
23522
23891
  */
23523
- function expandInlineEstimatedDates(observations, currentDate) {
23524
- return observations.replace(/\((estimated|meaning)\s+([^)]+\d{4})\)/gi, (match, prefix, dateContent, offset) => {
23525
- const targetDate = parseDateFromContent(dateContent);
23526
- if (targetDate) {
23527
- const relative = formatRelativeTime(targetDate, currentDate);
23528
- const lineStart = observations.lastIndexOf("\n", offset) + 1;
23529
- const lineBeforeDate = observations.slice(lineStart, offset);
23530
- const isPastDate = targetDate < currentDate;
23531
- const isFutureIntent = isFutureIntentObservation(lineBeforeDate);
23532
- if (isPastDate && isFutureIntent) return `(${prefix} ${dateContent} - ${relative}, likely already happened)`;
23533
- return `(${prefix} ${dateContent} - ${relative})`;
23534
- }
23535
- return match;
23892
+ function expandInlineEstimatedDates(observations, currentDate, timeZone) {
23893
+ const inlineDateRegex = /\((estimated|meaning)\s([^()]*)\)/gi;
23894
+ const today = calendarDayIn(currentDate, timeZone);
23895
+ return observations.replace(inlineDateRegex, (match, prefix, noteText, offset) => {
23896
+ const dateContent = noteText.trimStart();
23897
+ const span = findDateSpan(dateContent);
23898
+ if (!span) return match;
23899
+ const relative = relativeSpan(span, today);
23900
+ const lineStart = observations.lastIndexOf("\n", offset) + 1;
23901
+ const lineBeforeDate = observations.slice(lineStart, offset);
23902
+ if (calendarDay(span.end) < today && isFutureIntentObservation(lineBeforeDate)) return `(${prefix} ${dateContent} - ${relative}, likely already happened)`;
23903
+ return `(${prefix} ${dateContent} - ${relative})`;
23904
+ });
23905
+ }
23906
+ /**
23907
+ * Annotates dates written into observation text, e.g. "exam on January 10, 2024" becomes
23908
+ * "exam on January 10, 2024 (5 months ago)". Only dates that state their year are annotated;
23909
+ * "Date:" headers and "(meaning/estimated …)" notes are handled separately and skipped here.
23910
+ */
23911
+ function annotateObservationTextDates(observations, currentDate, timeZone) {
23912
+ const regex = new RegExp(String.raw`^Date:.*$|\((?:[Ee]stimated|[Mm]eaning)\b[^()]*\)|${FREE_TEXT_DATE.source}`, "gm");
23913
+ const today = calendarDayIn(currentDate, timeZone);
23914
+ return observations.replace(regex, (match, offset) => {
23915
+ if (match.startsWith("Date:") || match.startsWith("(")) return match;
23916
+ const span = parseDateSpan(match);
23917
+ if (!span) return match;
23918
+ const relative = relativeSpan(span, today);
23919
+ return observations[offset + match.length] === ")" ? `${match} - ${relative}` : `${match} (${relative})`;
23536
23920
  });
23537
23921
  }
23538
23922
  /**
23539
23923
  * Add relative time annotations to observations.
23540
- * Transforms "Date: May 15, 2023" headers to "Date: May 15, 2023 (5 days ago)"
23541
- * and expands inline estimated dates with relative time context.
23924
+ * Transforms "Date: May 15, 2023" headers to "Date: May 15, 2023 (5 days ago)", range headers such as
23925
+ * "Date: Aug 1, 2024 - Feb 28, 2025" to "(7 months ago to 4 weeks ago)", and annotates inline dates.
23926
+ *
23927
+ * `timeZone` is the zone the Observer wrote its dates in (the record's `observedTimezone`). "Today" is
23928
+ * `currentDate`'s calendar date in that zone, so the result doesn't depend on the zone of the process rendering it.
23542
23929
  */
23543
- function addRelativeTimeToObservations(observations, currentDate) {
23544
- const withInlineDates = expandInlineEstimatedDates(observations, currentDate);
23545
- const dateHeaderRegex = /^(Date:\s*)([A-Z][a-z]+ \d{1,2}, \d{4})$/gm;
23930
+ function addRelativeTimeToObservations(observations, currentDate, timeZone) {
23931
+ const today = calendarDayIn(currentDate, timeZone);
23932
+ const withInlineDates = annotateObservationTextDates(expandInlineEstimatedDates(observations, currentDate, timeZone), currentDate, timeZone);
23933
+ const dateHeaderRegex = /^(Date:[ \t]*)(.*)$/gm;
23546
23934
  const dates = [];
23547
23935
  let regexMatch;
23548
23936
  while ((regexMatch = dateHeaderRegex.exec(withInlineDates)) !== null) {
23549
- const dateStr = regexMatch[2];
23550
- const parsed = new Date(dateStr);
23551
- if (!isNaN(parsed.getTime())) dates.push({
23937
+ const dateStr = regexMatch[2].trimEnd();
23938
+ const span = parseDateSpan(dateStr);
23939
+ if (span) dates.push({
23552
23940
  index: regexMatch.index,
23553
- date: parsed,
23941
+ span,
23554
23942
  match: regexMatch[0],
23555
23943
  prefix: regexMatch[1],
23556
23944
  dateStr
@@ -23564,11 +23952,10 @@ function addRelativeTimeToObservations(observations, currentDate) {
23564
23952
  const prev = i > 0 ? dates[i - 1] : null;
23565
23953
  result += withInlineDates.slice(lastIndex, curr.index);
23566
23954
  if (prev) {
23567
- const gap = formatGapBetweenDates(prev.date, curr.date);
23955
+ const gap = formatGapBetweenDates(prev.span.end, curr.span.start);
23568
23956
  if (gap) result += `\n${gap}\n\n`;
23569
23957
  }
23570
- const relative = formatRelativeTime(curr.date, currentDate);
23571
- result += `${curr.prefix}${curr.dateStr} (${relative})`;
23958
+ result += `${curr.prefix}${curr.dateStr} (${relativeSpan(curr.span, today)})`;
23572
23959
  lastIndex = curr.index + curr.match.length;
23573
23960
  }
23574
23961
  result += withInlineDates.slice(lastIndex);
@@ -24573,11 +24960,20 @@ const OBSERVER_IMAGE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
24573
24960
  "heif",
24574
24961
  "avif"
24575
24962
  ]);
24576
- function formatObserverDate(createdAt) {
24577
- return createdAt ? `${createdAt.toLocaleDateString("en-US", { month: "short" })} ${createdAt.getDate()} ${createdAt.getFullYear()}` : "";
24963
+ function formatObserverDate(createdAt, timeZone) {
24964
+ if (!createdAt) return "";
24965
+ const parts = new Intl.DateTimeFormat("en-US", {
24966
+ timeZone,
24967
+ year: "numeric",
24968
+ month: "short",
24969
+ day: "numeric"
24970
+ }).formatToParts(createdAt);
24971
+ const part = (type) => parts.find((p) => p.type === type)?.value;
24972
+ return `${part("month")} ${part("day")} ${part("year")}`;
24578
24973
  }
24579
- function formatObserverTime(createdAt) {
24974
+ function formatObserverTime(createdAt, timeZone) {
24580
24975
  return createdAt ? createdAt.toLocaleTimeString("en-US", {
24976
+ timeZone,
24581
24977
  hour: "numeric",
24582
24978
  minute: "2-digit",
24583
24979
  hour12: true
@@ -24667,11 +25063,11 @@ function formatObserverAttachmentPlaceholder(part, counter) {
24667
25063
  const label = resolveObserverAttachmentLabel(part);
24668
25064
  return label ? `[${attachmentType} #${attachmentId}: ${label}]` : `[${attachmentType} #${attachmentId}]`;
24669
25065
  }
24670
- function isRecord$3(value) {
25066
+ function isRecord$2(value) {
24671
25067
  return !!value && typeof value === "object";
24672
25068
  }
24673
25069
  function mapToolResultBlockToAttachment(block) {
24674
- if (!isRecord$3(block) || typeof block.type !== "string") return;
25070
+ if (!isRecord$2(block) || typeof block.type !== "string") return;
24675
25071
  const mediaType = typeof block.mediaType === "string" ? block.mediaType : void 0;
24676
25072
  const filename = typeof block.filename === "string" ? block.filename : void 0;
24677
25073
  switch (block.type) {
@@ -24732,7 +25128,7 @@ function mapToolResultBlockToAttachment(block) {
24732
25128
  }
24733
25129
  }
24734
25130
  function extractToolResultAttachments(result, counter, attachmentFilter) {
24735
- if (!isRecord$3(result) || result.type !== "content" || !Array.isArray(result.value)) return {
25131
+ if (!isRecord$2(result) || result.type !== "content" || !Array.isArray(result.value)) return {
24736
25132
  resultWithoutAttachments: result,
24737
25133
  attachments: []
24738
25134
  };
@@ -24746,7 +25142,7 @@ function extractToolResultAttachments(result, counter, attachmentFilter) {
24746
25142
  if (shouldIncludeObserverAttachment(attachment, attachmentFilter)) attachments.push(toObserverInputAttachmentPart(attachment));
24747
25143
  const placeholder = formatObserverAttachmentPlaceholder(attachment, counter);
24748
25144
  return {
24749
- type: isRecord$3(block) ? block.type : void 0,
25145
+ type: isRecord$2(block) ? block.type : void 0,
24750
25146
  placeholder
24751
25147
  };
24752
25148
  });
@@ -24863,6 +25259,7 @@ function formatObserverMessage(msg, counter, toolFormatting, options) {
24863
25259
  const maxLen = options?.maxPartLength;
24864
25260
  const maxToolResultTokens = options?.maxToolResultTokens ?? 5e3;
24865
25261
  const attachmentFilter = options?.attachmentFilter;
25262
+ const timeZone = resolveTimeZone(options?.timeZone);
24866
25263
  const role = getObserverMessageLabel(msg);
24867
25264
  const attachments = [];
24868
25265
  const messageCreatedAt = normalizeObserverCreatedAt(msg.createdAt);
@@ -24872,8 +25269,8 @@ function formatObserverMessage(msg, counter, toolFormatting, options) {
24872
25269
  if (!body) return;
24873
25270
  const normalizedCreatedAt = normalizeObserverCreatedAt(createdAt) ?? messageCreatedAt;
24874
25271
  lines.push({
24875
- date: formatObserverDate(normalizedCreatedAt),
24876
- time: formatObserverTime(normalizedCreatedAt),
25272
+ date: formatObserverDate(normalizedCreatedAt, timeZone),
25273
+ time: formatObserverTime(normalizedCreatedAt, timeZone),
24877
25274
  title,
24878
25275
  body
24879
25276
  });
@@ -25426,169 +25823,6 @@ function optimizeObservationsForContext(observations) {
25426
25823
  optimized = optimized.replace(/\n{3,}/g, "\n\n");
25427
25824
  return optimized.trim();
25428
25825
  }
25429
- /**
25430
- * Retry knobs for the internal OM transport-error retry wrapper.
25431
- * Exported as a mutable object so tests can shrink the backoff schedule
25432
- * without changing public API.
25433
- *
25434
- * With the defaults the per-retry pre-jitter backoff schedule is:
25435
- * 1s, 2s, 4s, 8s, 16s, 32s, 64s, 120s (cap)
25436
- * giving 8 retries / 9 total attempts and ~247s (~4 minutes) of waiting
25437
- * before the final attempt fails. Designed to ride out short provider /
25438
- * network blips without holding the actor turn for much longer than that.
25439
- *
25440
- * @internal
25441
- */
25442
- const RETRY_CONFIG = {
25443
- /** Maximum number of retry *attempts* (total tries = maxRetries + 1). */
25444
- maxRetries: 8,
25445
- /** Initial backoff delay in milliseconds. */
25446
- initialDelayMs: 1e3,
25447
- /** Multiplier applied to the delay after each failed attempt. */
25448
- backoffFactor: 2,
25449
- /** Cap on per-attempt delay (ms). */
25450
- maxDelayMs: 12e4,
25451
- /** Random jitter as a fraction of the computed delay (e.g. 0.2 = ±20%). */
25452
- jitter: .2
25453
- };
25454
- const TRANSIENT_MESSAGE_SUBSTRINGS = [
25455
- "terminated",
25456
- "fetch failed",
25457
- "econnreset",
25458
- "econnrefused",
25459
- "enotfound",
25460
- "eai_again",
25461
- "socket hang up",
25462
- "network error",
25463
- "request timed out",
25464
- "request timeout",
25465
- "connection reset",
25466
- "connection closed"
25467
- ];
25468
- function isRecord$2(value) {
25469
- return typeof value === "object" && value !== null;
25470
- }
25471
- function isAbortError$5(error) {
25472
- if (!isRecord$2(error)) return false;
25473
- if (error.name === "AbortError") return true;
25474
- if (typeof error.code === "string" && error.code === "ABORT_ERR") return true;
25475
- return false;
25476
- }
25477
- function hasTransientMessage(value) {
25478
- if (!isRecord$2(value)) return false;
25479
- const message = typeof value.message === "string" ? value.message.toLowerCase() : "";
25480
- if (message && TRANSIENT_MESSAGE_SUBSTRINGS.some((sub) => message.includes(sub))) return true;
25481
- if (typeof value.code === "string" && value.code.toUpperCase().startsWith("UND_ERR_")) return true;
25482
- return false;
25483
- }
25484
- function isRetryableHttpStatus(status) {
25485
- if (status === 408 || status === 425 || status === 429) return true;
25486
- return status >= 500 && status <= 599;
25487
- }
25488
- function hasRetryableHttpStatus(value) {
25489
- if (!isRecord$2(value)) return false;
25490
- if (typeof value.statusCode === "number" && isRetryableHttpStatus(value.statusCode)) return true;
25491
- if (typeof value.code === "number" && isRetryableHttpStatus(value.code)) return true;
25492
- return false;
25493
- }
25494
- function hasIsRetryableFlag(value) {
25495
- if (!isRecord$2(value)) return false;
25496
- return value.isRetryable === true;
25497
- }
25498
- /**
25499
- * Returns true when the given error looks like a transient transport-class
25500
- * failure that's worth retrying — undici `terminated`, `fetch failed`,
25501
- * `UND_ERR_*` codes, AI SDK `APICallError` with `isRetryable: true`, and
25502
- * common HTTP 408/425/429/5xx statuses. Walks the `error.cause` chain so
25503
- * wrapper errors don't hide the real failure.
25504
- *
25505
- * Never retries on user-initiated aborts.
25506
- *
25507
- * @internal
25508
- */
25509
- function isTransientLLMError(error) {
25510
- if (isAbortError$5(error)) return false;
25511
- const visited = /* @__PURE__ */ new WeakSet();
25512
- function visit(candidate) {
25513
- if (isRecord$2(candidate)) {
25514
- if (visited.has(candidate)) return false;
25515
- visited.add(candidate);
25516
- }
25517
- if (hasTransientMessage(candidate)) return true;
25518
- if (hasRetryableHttpStatus(candidate)) return true;
25519
- if (hasIsRetryableFlag(candidate)) return true;
25520
- if (isRecord$2(candidate)) {
25521
- if (visit(candidate.cause)) return true;
25522
- if (visit(candidate.error)) return true;
25523
- }
25524
- return false;
25525
- }
25526
- return visit(error);
25527
- }
25528
- /**
25529
- * Compute the backoff delay (ms) for the Nth retry (0-indexed).
25530
- *
25531
- * Exponential growth (`initialDelayMs * backoffFactor^attempt`) capped at
25532
- * `maxDelayMs`, then nudged by ±`jitter` (fractional). Exported for unit
25533
- * tests that lock the schedule against drift.
25534
- *
25535
- * @internal
25536
- */
25537
- function computeDelay(attempt) {
25538
- const base = RETRY_CONFIG.initialDelayMs * Math.pow(RETRY_CONFIG.backoffFactor, attempt);
25539
- const capped = Math.min(base, RETRY_CONFIG.maxDelayMs);
25540
- if (RETRY_CONFIG.jitter <= 0) return capped;
25541
- const jitterRange = capped * RETRY_CONFIG.jitter;
25542
- const offset = (Math.random() * 2 - 1) * jitterRange;
25543
- return Math.max(0, Math.round(capped + offset));
25544
- }
25545
- function sleep(ms, abortSignal) {
25546
- if (ms <= 0) return Promise.resolve();
25547
- return new Promise((resolve, reject) => {
25548
- if (abortSignal?.aborted) {
25549
- reject(/* @__PURE__ */ new Error("The operation was aborted."));
25550
- return;
25551
- }
25552
- const timer = setTimeout(() => {
25553
- abortSignal?.removeEventListener("abort", onAbort);
25554
- resolve();
25555
- }, ms);
25556
- const onAbort = () => {
25557
- clearTimeout(timer);
25558
- abortSignal?.removeEventListener("abort", onAbort);
25559
- reject(/* @__PURE__ */ new Error("The operation was aborted."));
25560
- };
25561
- abortSignal?.addEventListener("abort", onAbort, { once: true });
25562
- });
25563
- }
25564
- /**
25565
- * Run `fn` with retries on transient transport-class errors.
25566
- *
25567
- * Non-transient errors (auth, validation, schema, etc.) are rethrown
25568
- * immediately. User-initiated aborts are rethrown without delay.
25569
- *
25570
- * @internal
25571
- */
25572
- async function withRetry(fn, opts) {
25573
- const { label, abortSignal } = opts;
25574
- let attempt = 0;
25575
- while (true) {
25576
- if (abortSignal?.aborted) throw new Error("The operation was aborted.");
25577
- try {
25578
- return await fn();
25579
- } catch (error) {
25580
- if (isAbortError$5(error) || abortSignal?.aborted) throw error;
25581
- if (attempt >= RETRY_CONFIG.maxRetries || !isTransientLLMError(error)) {
25582
- if (attempt > 0) omDebug(`[OM:retry:${label}] giving up after ${attempt} retry/retries: ${error instanceof Error ? error.message : String(error)}`);
25583
- throw error;
25584
- }
25585
- const delay = computeDelay(attempt);
25586
- attempt++;
25587
- omDebug(`[OM:retry:${label}] transient error on attempt ${attempt}, retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`);
25588
- await sleep(delay, abortSignal);
25589
- }
25590
- }
25591
- }
25592
25826
  function createTemporaryOmMemoryContext(prefix) {
25593
25827
  const options = {
25594
25828
  thread: `${prefix}-${randomUUID()}`,
@@ -25723,11 +25957,27 @@ var ObserverRunner = class {
25723
25957
  this.mastra = mastra;
25724
25958
  }
25725
25959
  createAgent(model, isMultiThread = false, memory, extractors = this.observationConfig.extractors ?? []) {
25960
+ let agentModel = model;
25961
+ if (Array.isArray(agentModel)) agentModel = agentModel.map((fallback) => ({
25962
+ ...fallback,
25963
+ maxRetries: 0
25964
+ }));
25965
+ else if (typeof agentModel === "function") {
25966
+ const resolveDynamicModel = agentModel;
25967
+ agentModel = (async (args) => {
25968
+ const resolvedModel = await resolveDynamicModel(args);
25969
+ return Array.isArray(resolvedModel) ? resolvedModel.map((fallback) => ({
25970
+ ...fallback,
25971
+ maxRetries: 0
25972
+ })) : resolvedModel;
25973
+ });
25974
+ }
25726
25975
  return new Agent({
25727
25976
  id: isMultiThread ? "multi-thread-observer" : "observational-memory-observer",
25728
25977
  name: isMultiThread ? "multi-thread-observer" : "Observer",
25978
+ maxRetries: 0,
25729
25979
  instructions: buildObserverSystemPrompt(isMultiThread, this.observationConfig.instruction, this.observationConfig.threadTitle, extractors),
25730
- model,
25980
+ model: agentModel,
25731
25981
  ...memory ? { memory } : {},
25732
25982
  ...this.mastra ? { mastra: this.mastra } : {}
25733
25983
  });
@@ -25819,7 +26069,10 @@ var ObserverRunner = class {
25819
26069
  ...options,
25820
26070
  includeThreadTitle: this.observationConfig.threadTitle,
25821
26071
  extractors: activeExtractors
25822
- }, { attachmentFilter })];
26072
+ }, {
26073
+ attachmentFilter,
26074
+ timeZone: options?.timeZone
26075
+ })];
25823
26076
  const doGenerate = async () => {
25824
26077
  return withRetry(() => withOmTracingSpan({
25825
26078
  phase: "observer",
@@ -25857,12 +26110,14 @@ var ObserverRunner = class {
25857
26110
  hasRequestContext: Boolean(internalRequestContext),
25858
26111
  aborted: abortSignal?.aborted ?? false
25859
26112
  });
25860
- throw error;
26113
+ if (abortSignal?.aborted || !isOmModelExecutionFailure(error)) throw error;
26114
+ throw new OmModelExecutionError("observer-model", error);
25861
26115
  }
25862
26116
  }, abortSignal)
25863
26117
  }), {
25864
26118
  label: "observer",
25865
- abortSignal
26119
+ abortSignal,
26120
+ maxRetries: this.observationConfig.maxRetries
25866
26121
  });
25867
26122
  };
25868
26123
  let result = await doGenerate();
@@ -25930,7 +26185,7 @@ var ObserverRunner = class {
25930
26185
  /**
25931
26186
  * Call the Observer agent for multiple threads in a single batched request.
25932
26187
  */
25933
- async callMultiThread(existingObservations, allMessagesByThread, allThreadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model, hookContext) {
26188
+ async callMultiThread(existingObservations, allMessagesByThread, allThreadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model, hookContext, timeZone) {
25934
26189
  const contextFor = (threadId) => ({
25935
26190
  threadId,
25936
26191
  ...hookContext
@@ -25941,7 +26196,7 @@ var ObserverRunner = class {
25941
26196
  if (filtered.length > 0) messagesByThread.set(threadId, filtered);
25942
26197
  }
25943
26198
  const threadOrder = allThreadOrder.filter((threadId) => messagesByThread.has(threadId));
25944
- const output = await this.callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model);
26199
+ const output = await this.callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model, timeZone);
25945
26200
  for (const threadId of allThreadOrder) {
25946
26201
  const threadResult = output.results.get(threadId);
25947
26202
  if (!threadResult) {
@@ -25952,7 +26207,7 @@ var ObserverRunner = class {
25952
26207
  }
25953
26208
  return output;
25954
26209
  }
25955
- async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model) {
26210
+ async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model, timeZone) {
25956
26211
  if (threadOrder.length === 0) return { results: /* @__PURE__ */ new Map() };
25957
26212
  const inputTokens = Array.from(messagesByThread.values()).reduce((total, messages) => total + this.tokenCounter.countMessages(messages), 0);
25958
26213
  const resolvedModel = (() => {
@@ -25994,7 +26249,8 @@ var ObserverRunner = class {
25994
26249
  priorSuggestedResponse: priorMetadataByThread?.get(threadId)?.suggestedResponse,
25995
26250
  priorThreadTitle: priorMetadataByThread?.get(threadId)?.threadTitle,
25996
26251
  priorExtractedValues: priorMetadataByThread?.get(threadId)?.extracted,
25997
- model: resolvedModel.model
26252
+ model: resolvedModel.model,
26253
+ timeZone
25998
26254
  });
25999
26255
  results.set(threadId, {
26000
26256
  observations: threadResult.observations,
@@ -26011,6 +26267,7 @@ var ObserverRunner = class {
26011
26267
  totalUsage.totalTokens += threadResult.usage.totalTokens ?? 0;
26012
26268
  }
26013
26269
  }
26270
+ for (const msgs of messagesByThread.values()) for (const msg of msgs) this.observedMessageIds.add(msg.id);
26014
26271
  return {
26015
26272
  results,
26016
26273
  usage: totalUsage
@@ -26019,8 +26276,10 @@ var ObserverRunner = class {
26019
26276
  const agent = this.createAgent(resolvedModel.model, true, void 0, activeExtractors);
26020
26277
  const internalRequestContext = withOmInternalThreadId(requestContext, agent.id);
26021
26278
  const multiThreadAttachmentFilter = this.resolveAttachmentFilter(resolvedModel.model, requestContext);
26022
- const observerMessages = [buildMultiThreadObserverRequestMessage(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, void 0, this.observationConfig.threadTitle, activeExtractors, { attachmentFilter: multiThreadAttachmentFilter })];
26023
- for (const msgs of messagesByThread.values()) for (const msg of msgs) this.observedMessageIds.add(msg.id);
26279
+ const observerMessages = [buildMultiThreadObserverRequestMessage(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, void 0, this.observationConfig.threadTitle, activeExtractors, {
26280
+ attachmentFilter: multiThreadAttachmentFilter,
26281
+ timeZone
26282
+ })];
26024
26283
  const doGenerate = async () => {
26025
26284
  return withRetry(() => withOmTracingSpan({
26026
26285
  phase: "observer-multi-thread",
@@ -26058,12 +26317,14 @@ var ObserverRunner = class {
26058
26317
  hasRequestContext: Boolean(internalRequestContext),
26059
26318
  aborted: abortSignal?.aborted ?? false
26060
26319
  });
26061
- throw error;
26320
+ if (abortSignal?.aborted || !isOmModelExecutionFailure(error)) throw error;
26321
+ throw new OmModelExecutionError("observer-model", error);
26062
26322
  }
26063
26323
  }, abortSignal)
26064
26324
  }), {
26065
26325
  label: "observer-multi-thread",
26066
- abortSignal
26326
+ abortSignal,
26327
+ maxRetries: this.observationConfig.maxRetries
26067
26328
  });
26068
26329
  };
26069
26330
  let result = await doGenerate();
@@ -26119,6 +26380,7 @@ var ObserverRunner = class {
26119
26380
  });
26120
26381
  }
26121
26382
  for (const threadId of threadOrder) if (!results.has(threadId)) results.set(threadId, { observations: "" });
26383
+ for (const msgs of messagesByThread.values()) for (const msg of msgs) this.observedMessageIds.add(msg.id);
26122
26384
  const usage = result.totalUsage ?? result.usage;
26123
26385
  return {
26124
26386
  results,
@@ -27606,6 +27868,8 @@ async function summarizeConversation(opts) {
27606
27868
  const runner = new ObserverRunner({
27607
27869
  observationConfig: {
27608
27870
  model: opts.model,
27871
+ maxRetries: 8,
27872
+ failurePolicy: "abort",
27609
27873
  messageTokens: OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens,
27610
27874
  shareTokenBudget: false,
27611
27875
  modelSettings: { ...OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings },
@@ -29416,6 +29680,7 @@ function createObservationFailedMarker(params) {
29416
29680
  durationMs,
29417
29681
  tokensAttempted: params.tokensAttempted,
29418
29682
  error: formatOmError(params.error),
29683
+ ...getOmFailureMetadata(params.error, params.failurePolicy ?? "abort"),
29419
29684
  recordId: params.recordId,
29420
29685
  threadId: params.threadId
29421
29686
  }
@@ -29477,6 +29742,7 @@ function createBufferingFailedMarker(params) {
29477
29742
  durationMs,
29478
29743
  tokensAttempted: params.tokensAttempted,
29479
29744
  error: formatOmError(params.error),
29745
+ ...getOmFailureMetadata(params.error, params.failurePolicy ?? "abort"),
29480
29746
  recordId: params.recordId,
29481
29747
  threadId: params.threadId
29482
29748
  }
@@ -29531,7 +29797,10 @@ function createThreadUpdateMarker(params) {
29531
29797
  function findLastCompletedObservationBoundary(message) {
29532
29798
  const parts = message.content?.parts;
29533
29799
  if (!parts || !Array.isArray(parts)) return -1;
29534
- for (let i = parts.length - 1; i >= 0; i--) if (parts[i]?.type === "data-om-observation-end") return i;
29800
+ for (let i = parts.length - 1; i >= 0; i--) {
29801
+ const part = parts[i];
29802
+ if (part?.type === "data-om-observation-end" && part.data?.operationType !== "reflection") return i;
29803
+ }
29535
29804
  return -1;
29536
29805
  }
29537
29806
  /**
@@ -29781,6 +30050,7 @@ function scanObservationGroupTags(observations) {
29781
30050
  const incompleteOpenings = [];
29782
30051
  let cursor = 0;
29783
30052
  let closeFloor = 0;
30053
+ let nestedFloor = -1;
29784
30054
  while (cursor < observations.length) {
29785
30055
  const start = observations.indexOf(OBSERVATION_GROUP_OPEN, cursor);
29786
30056
  if (start === -1) break;
@@ -29801,8 +30071,12 @@ function scanObservationGroupTags(observations) {
29801
30071
  cursor = openEnd + 1;
29802
30072
  continue;
29803
30073
  }
29804
- const nestedStart = observations.indexOf(OBSERVATION_GROUP_OPEN, openEnd + 1);
29805
- if (nestedStart !== -1 && nestedStart < closeStart && isLineStart(observations, nestedStart)) {
30074
+ if (nestedFloor <= openEnd) {
30075
+ const lineOpen = observations.indexOf(`\n${OBSERVATION_GROUP_OPEN}`, openEnd);
30076
+ nestedFloor = lineOpen === -1 ? observations.length : lineOpen + 1;
30077
+ }
30078
+ const nestedStart = nestedFloor;
30079
+ if (nestedStart < closeStart) {
29806
30080
  incompleteOpenings.push({
29807
30081
  start,
29808
30082
  end: openEnd + 1
@@ -30185,6 +30459,7 @@ var ObservationStrategy = class ObservationStrategy {
30185
30459
  observationTokens: processed.observationTokens,
30186
30460
  threadId,
30187
30461
  writer,
30462
+ messageList: this.opts.messageList,
30188
30463
  abortSignal,
30189
30464
  mainAgent: this.opts.agent,
30190
30465
  sendSignal: this.opts.sendSignal,
@@ -30209,6 +30484,7 @@ var ObservationStrategy = class ObservationStrategy {
30209
30484
  operationType: "observation",
30210
30485
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
30211
30486
  error: formatOmError(error),
30487
+ ...getOmFailureMetadata(error, this.observationConfig.failurePolicy),
30212
30488
  recordId: record.id,
30213
30489
  threadId
30214
30490
  }
@@ -30222,6 +30498,10 @@ var ObservationStrategy = class ObservationStrategy {
30222
30498
  };
30223
30499
  }
30224
30500
  omError("[OM] Observation failed", error);
30501
+ if (this.observationConfig.failurePolicy === "continue" && isOmModelExecutionError(error) && error.failureKind === "observer-model") return {
30502
+ observed: false,
30503
+ error
30504
+ };
30225
30505
  throw error;
30226
30506
  }
30227
30507
  }
@@ -30487,7 +30767,8 @@ var SyncObservationStrategy = class extends ObservationStrategy {
30487
30767
  threadId: this.opts.threadId,
30488
30768
  resourceId: this.opts.resourceId,
30489
30769
  trigger: this.opts.trigger,
30490
- mainAgent: this.opts.agent
30770
+ mainAgent: this.opts.agent,
30771
+ timeZone: this.opts.record.observedTimezone
30491
30772
  });
30492
30773
  const hookedValues = await applyExtractorHooks({
30493
30774
  source: "observer",
@@ -30496,7 +30777,10 @@ var SyncObservationStrategy = class extends ObservationStrategy {
30496
30777
  failures: result.extractionFailures,
30497
30778
  previousValues: this.priorExtractedValues,
30498
30779
  rawObservations: result.observations,
30499
- recentMessages: formatMessagesForObserver(this.opts.messages, { maxPartLength: 500 }),
30780
+ recentMessages: formatMessagesForObserver(this.opts.messages, {
30781
+ maxPartLength: 500,
30782
+ timeZone: this.opts.record.observedTimezone
30783
+ }),
30500
30784
  threadId: this.opts.threadId,
30501
30785
  resourceId: this.opts.resourceId,
30502
30786
  mainAgent: this.opts.agent,
@@ -30627,6 +30911,7 @@ var SyncObservationStrategy = class extends ObservationStrategy {
30627
30911
  startedAt: this.startedAt,
30628
30912
  tokensAttempted: this.tokensToObserve,
30629
30913
  error,
30914
+ failurePolicy: this.observationConfig.failurePolicy,
30630
30915
  recordId: this.opts.record.id,
30631
30916
  threadId: this.opts.threadId
30632
30917
  });
@@ -30676,7 +30961,8 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
30676
30961
  threadId: this.opts.threadId,
30677
30962
  resourceId: this.opts.resourceId,
30678
30963
  trigger: this.opts.trigger,
30679
- mainAgent: this.opts.agent
30964
+ mainAgent: this.opts.agent,
30965
+ timeZone: this.opts.record.observedTimezone
30680
30966
  });
30681
30967
  const hookedValues = await applyExtractorHooks({
30682
30968
  source: "observer",
@@ -30685,7 +30971,10 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
30685
30971
  failures: result.extractionFailures,
30686
30972
  previousValues: this.priorExtractedValues,
30687
30973
  rawObservations: result.observations,
30688
- recentMessages: formatMessagesForObserver(messages, { maxPartLength: 500 }),
30974
+ recentMessages: formatMessagesForObserver(messages, {
30975
+ maxPartLength: 500,
30976
+ timeZone: this.opts.record.observedTimezone
30977
+ }),
30689
30978
  threadId: this.opts.threadId,
30690
30979
  resourceId: this.opts.resourceId,
30691
30980
  mainAgent: this.opts.agent,
@@ -30831,6 +31120,7 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
30831
31120
  startedAt: this.startedAt,
30832
31121
  tokensAttempted,
30833
31122
  error,
31123
+ failurePolicy: this.observationConfig.failurePolicy,
30834
31124
  recordId: record.id,
30835
31125
  threadId
30836
31126
  });
@@ -31005,7 +31295,7 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
31005
31295
  return this.deps.observer.callMultiThread(_existingObservations, batch.threadMap, batch.threadIds, this.opts.abortSignal, this.opts.requestContext, this.priorMetadataByThread, this.opts.observabilityContext, void 0, {
31006
31296
  resourceId: this.opts.resourceId,
31007
31297
  trigger: this.opts.trigger
31008
- });
31298
+ }, this.opts.record.observedTimezone);
31009
31299
  }));
31010
31300
  for (const batchResult of batchResults) {
31011
31301
  for (const [threadId, result] of batchResult.results) this.multiThreadResults.set(threadId, result);
@@ -31038,7 +31328,10 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
31038
31328
  failures: result.extractionFailures,
31039
31329
  previousValues,
31040
31330
  rawObservations: result.observations,
31041
- recentMessages: formatMessagesForObserver(threadMessages, { maxPartLength: 500 }),
31331
+ recentMessages: formatMessagesForObserver(threadMessages, {
31332
+ maxPartLength: 500,
31333
+ timeZone: this.opts.record.observedTimezone
31334
+ }),
31042
31335
  threadId,
31043
31336
  resourceId: this.resourceId,
31044
31337
  mainAgent: this.opts.agent,
@@ -31197,6 +31490,7 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
31197
31490
  startedAt: this.startedAt,
31198
31491
  tokensAttempted,
31199
31492
  error,
31493
+ failurePolicy: this.observationConfig.failurePolicy,
31200
31494
  recordId: this.opts.record.id,
31201
31495
  threadId
31202
31496
  });
@@ -31603,19 +31897,28 @@ var ObservationStep = class {
31603
31897
  };
31604
31898
  }
31605
31899
  }
31606
- const obsResult = await om.observe({
31607
- threadId,
31608
- resourceId,
31609
- messages: observableMessages,
31610
- messageList,
31611
- trigger: "turn-sync",
31612
- agent: this.turn.agent,
31613
- sendSignal: this.turn.sendSignal,
31614
- sendStateSignal: this.turn.sendStateSignal,
31615
- requestContext: this.turn.requestContext,
31616
- writer: this.turn.writer,
31617
- observabilityContext: this.turn.observabilityContext
31618
- });
31900
+ let obsResult;
31901
+ try {
31902
+ obsResult = await om.observe({
31903
+ threadId,
31904
+ resourceId,
31905
+ messages: observableMessages,
31906
+ messageList,
31907
+ trigger: "turn-sync",
31908
+ agent: this.turn.agent,
31909
+ sendSignal: this.turn.sendSignal,
31910
+ sendStateSignal: this.turn.sendStateSignal,
31911
+ requestContext: this.turn.requestContext,
31912
+ writer: this.turn.writer,
31913
+ observabilityContext: this.turn.observabilityContext
31914
+ });
31915
+ } catch (error) {
31916
+ if (om.config.observation.failurePolicy !== "continue" || !isOmModelExecutionError(error) || error.failureKind !== "observer-model") throw error;
31917
+ return {
31918
+ succeeded: false,
31919
+ record: freshStatus.record
31920
+ };
31921
+ }
31619
31922
  if (obsResult.observed) {
31620
31923
  const observedMessageIds = new Set(obsResult.record.observedMessageIds ?? []);
31621
31924
  const liveMessages = getObservableMessages(messageList);
@@ -32267,11 +32570,27 @@ var ReflectorRunner = class {
32267
32570
  this.mastra = mastra;
32268
32571
  }
32269
32572
  createAgent(model, memory, extractors = this.reflectionConfig.extractors) {
32573
+ let agentModel = model;
32574
+ if (Array.isArray(agentModel)) agentModel = agentModel.map((fallback) => ({
32575
+ ...fallback,
32576
+ maxRetries: 0
32577
+ }));
32578
+ else if (typeof agentModel === "function") {
32579
+ const resolveDynamicModel = agentModel;
32580
+ agentModel = (async (args) => {
32581
+ const resolvedModel = await resolveDynamicModel(args);
32582
+ return Array.isArray(resolvedModel) ? resolvedModel.map((fallback) => ({
32583
+ ...fallback,
32584
+ maxRetries: 0
32585
+ })) : resolvedModel;
32586
+ });
32587
+ }
32270
32588
  return new Agent({
32271
32589
  id: "observational-memory-reflector",
32272
32590
  name: "Reflector",
32273
32591
  instructions: buildReflectorSystemPrompt(this.reflectionConfig.instruction, extractors),
32274
- model,
32592
+ model: agentModel,
32593
+ maxRetries: 0,
32275
32594
  ...memory ? { memory } : {},
32276
32595
  ...this.mastra ? { mastra: this.mastra } : {}
32277
32596
  });
@@ -32353,36 +32672,42 @@ var ReflectorRunner = class {
32353
32672
  },
32354
32673
  callback: (childObservabilityContext) => withAbortCheck(async () => {
32355
32674
  chunkCount = 0;
32356
- return (await agent.stream(prompt, {
32357
- modelSettings: { ...this.reflectionConfig.modelSettings },
32358
- providerOptions: this.reflectionConfig.providerOptions,
32359
- ...temporaryMemory ? { memory: temporaryMemory.options } : {},
32360
- ...abortSignal ? { abortSignal } : {},
32361
- ...internalRequestContext ? { requestContext: internalRequestContext } : {},
32362
- ...childObservabilityContext,
32363
- ...attemptNumber === 1 ? {
32364
- onChunk(chunk) {
32365
- chunkCount++;
32366
- if (chunkCount === 1 || chunkCount % 50 === 0) {
32367
- const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
32368
- omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
32675
+ try {
32676
+ return await (await agent.stream(prompt, {
32677
+ modelSettings: { ...this.reflectionConfig.modelSettings },
32678
+ providerOptions: this.reflectionConfig.providerOptions,
32679
+ ...temporaryMemory ? { memory: temporaryMemory.options } : {},
32680
+ ...abortSignal ? { abortSignal } : {},
32681
+ ...internalRequestContext ? { requestContext: internalRequestContext } : {},
32682
+ ...childObservabilityContext,
32683
+ ...attemptNumber === 1 ? {
32684
+ onChunk(chunk) {
32685
+ chunkCount++;
32686
+ if (chunkCount === 1 || chunkCount % 50 === 0) {
32687
+ const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
32688
+ omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
32689
+ }
32690
+ },
32691
+ onFinish(event) {
32692
+ omDebug(`[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`);
32693
+ },
32694
+ onAbort(event) {
32695
+ omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
32696
+ },
32697
+ onError({ error }) {
32698
+ omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
32369
32699
  }
32370
- },
32371
- onFinish(event) {
32372
- omDebug(`[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`);
32373
- },
32374
- onAbort(event) {
32375
- omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
32376
- },
32377
- onError({ error }) {
32378
- omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
32379
- }
32380
- } : {}
32381
- })).getFullOutput();
32700
+ } : {}
32701
+ })).getFullOutput();
32702
+ } catch (error) {
32703
+ if (abortSignal?.aborted || !isOmModelExecutionFailure(error)) throw error;
32704
+ throw new OmModelExecutionError("reflector-model", error);
32705
+ }
32382
32706
  }, abortSignal)
32383
32707
  }), {
32384
32708
  label: "reflector",
32385
- abortSignal
32709
+ abortSignal,
32710
+ maxRetries: this.reflectionConfig.maxRetries
32386
32711
  });
32387
32712
  omDebug(`[OM:callReflector] attempt #${attemptNumber} returned: textLen=${result.text?.length}, textPreview="${result.text?.slice(0, 120)}...", inputTokens=${result.usage?.inputTokens ?? result.totalUsage?.inputTokens}, outputTokens=${result.usage?.outputTokens ?? result.totalUsage?.outputTokens}`);
32388
32713
  const usage = result.totalUsage ?? result.usage;
@@ -32506,6 +32831,7 @@ var ReflectorRunner = class {
32506
32831
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
32507
32832
  tokensAttempted: observationTokens,
32508
32833
  error,
32834
+ failurePolicy: this.reflectionConfig.failurePolicy,
32509
32835
  recordId: record.id,
32510
32836
  threadId: record.threadId ?? ""
32511
32837
  });
@@ -32918,24 +33244,43 @@ var ReflectorRunner = class {
32918
33244
  usage: reflectResult.usage
32919
33245
  });
32920
33246
  } catch (error) {
32921
- if (writer && streamContext) {
32922
- const failedMarker = createObservationFailedMarker({
32923
- cycleId: streamContext.cycleId,
32924
- operationType: "reflection",
32925
- startedAt: streamContext.startedAt,
32926
- tokensAttempted: observationTokens,
32927
- error,
32928
- recordId: record.id,
32929
- threadId
32930
- });
32931
- await writer.custom({
32932
- ...failedMarker,
32933
- transient: true
32934
- }).catch(() => {});
33247
+ reflectionError = error instanceof Error ? error : new Error(String(error));
33248
+ const failedMarker = createObservationFailedMarker({
33249
+ cycleId: streamContext?.cycleId ?? cycleId,
33250
+ operationType: "reflection",
33251
+ startedAt: streamContext?.startedAt ?? startedAt,
33252
+ tokensAttempted: observationTokens,
33253
+ error,
33254
+ failurePolicy: this.reflectionConfig.failurePolicy,
33255
+ recordId: record.id,
33256
+ threadId
33257
+ });
33258
+ if (writer) await writer.custom({
33259
+ ...failedMarker,
33260
+ transient: true
33261
+ }).catch(() => {});
33262
+ let persistedToList = false;
33263
+ try {
33264
+ persistedToList = await this.persistMarkerToMessage(failedMarker, messageList, threadId, record.resourceId ?? void 0);
33265
+ } catch {
33266
+ persistedToList = false;
33267
+ }
33268
+ if (!persistedToList) try {
32935
33269
  await this.persistMarkerToStorage(failedMarker, threadId, record.resourceId ?? void 0);
33270
+ } catch (markerError) {
33271
+ omError("[OM] Failed to persist reflection-failed marker", markerError);
32936
33272
  }
32937
- reflectionError = error instanceof Error ? error : new Error(String(error));
32938
- if (lifecycleError !== void 0 || abortSignal?.aborted) throw error;
33273
+ this.emitDebugEvent({
33274
+ type: "reflection_failed",
33275
+ timestamp: /* @__PURE__ */ new Date(),
33276
+ threadId,
33277
+ resourceId: record.resourceId ?? "",
33278
+ inputTokens: observationTokens,
33279
+ failurePolicy: this.reflectionConfig.failurePolicy,
33280
+ failureKind: failedMarker.data.failureKind,
33281
+ error: reflectionError.message
33282
+ });
33283
+ if (lifecycleError !== void 0 || abortSignal?.aborted || this.reflectionConfig.failurePolicy !== "continue" || !isOmModelExecutionError(error) || error.failureKind !== "reflector-model") throw error;
32939
33284
  this.syncReflectionSuppression.set(lockKey, observationTokens);
32940
33285
  omError("[OM] Reflection failed", error);
32941
33286
  } finally {
@@ -33569,6 +33914,8 @@ var ObservationalMemory = class ObservationalMemory {
33569
33914
  const observationActivateAfterIdlePath = config.observation?.activateAfterIdle !== void 0 ? "observation.activateAfterIdle" : "activateAfterIdle";
33570
33915
  this.observationConfig = {
33571
33916
  model: observationModel,
33917
+ maxRetries: config.observation?.maxRetries ?? RETRY_CONFIG.maxRetries,
33918
+ failurePolicy: config.observation?.failurePolicy ?? "abort",
33572
33919
  messageTokens: isSharedBudget ? {
33573
33920
  min: messageTokens,
33574
33921
  max: totalBudget
@@ -33598,6 +33945,8 @@ var ObservationalMemory = class ObservationalMemory {
33598
33945
  };
33599
33946
  this.reflectionConfig = {
33600
33947
  model: reflectionModel,
33948
+ maxRetries: config.reflection?.maxRetries ?? RETRY_CONFIG.maxRetries,
33949
+ failurePolicy: config.reflection?.failurePolicy ?? "abort",
33601
33950
  observationTokens,
33602
33951
  shareTokenBudget: isSharedBudget,
33603
33952
  modelSettings: {
@@ -33671,9 +34020,15 @@ var ObservationalMemory = class ObservationalMemory {
33671
34020
  retrieval: this.retrieval,
33672
34021
  observation: {
33673
34022
  messageTokens: this.observationConfig.messageTokens,
33674
- previousObserverTokens: this.observationConfig.previousObserverTokens
34023
+ previousObserverTokens: this.observationConfig.previousObserverTokens,
34024
+ maxRetries: this.observationConfig.maxRetries,
34025
+ failurePolicy: this.observationConfig.failurePolicy
33675
34026
  },
33676
- reflection: { observationTokens: this.reflectionConfig.observationTokens }
34027
+ reflection: {
34028
+ observationTokens: this.reflectionConfig.observationTokens,
34029
+ maxRetries: this.reflectionConfig.maxRetries,
34030
+ failurePolicy: this.reflectionConfig.failurePolicy
34031
+ }
33677
34032
  };
33678
34033
  }
33679
34034
  /**
@@ -33777,11 +34132,15 @@ var ObservationalMemory = class ObservationalMemory {
33777
34132
  messageTokens: this.observationConfig.messageTokens,
33778
34133
  model: observationResolved.model,
33779
34134
  previousObserverTokens: this.observationConfig.previousObserverTokens,
34135
+ maxRetries: this.observationConfig.maxRetries,
34136
+ failurePolicy: this.observationConfig.failurePolicy,
33780
34137
  routing: observationResolved.routing
33781
34138
  },
33782
34139
  reflection: {
33783
34140
  observationTokens: this.reflectionConfig.observationTokens,
33784
34141
  model: reflectionResolved.model,
34142
+ maxRetries: this.reflectionConfig.maxRetries,
34143
+ failurePolicy: this.reflectionConfig.failurePolicy,
33785
34144
  routing: reflectionResolved.routing
33786
34145
  }
33787
34146
  };
@@ -33798,6 +34157,7 @@ var ObservationalMemory = class ObservationalMemory {
33798
34157
  * Ensures bufferTokens is less than the threshold and bufferActivation is valid.
33799
34158
  */
33800
34159
  validateBufferConfig() {
34160
+ for (const [path, value] of [["observation.maxRetries", this.observationConfig.maxRetries], ["reflection.maxRetries", this.reflectionConfig.maxRetries]]) if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${path} must be a finite non-negative integer, got ${value}`);
33801
34161
  if ((this.observationConfig.bufferTokens !== void 0 || this.observationConfig.bufferActivation !== void 0 || this.reflectionConfig.bufferActivation !== void 0) && this.scope === "resource") throw new Error("Async buffering is not yet supported with scope: 'resource'. Use scope: 'thread', or set observation: { bufferTokens: false } to disable async buffering.");
33802
34162
  const observationThreshold = getMaxThreshold(this.observationConfig.messageTokens);
33803
34163
  if (this.observationConfig.bufferTokens !== void 0) {
@@ -33925,18 +34285,19 @@ var ObservationalMemory = class ObservationalMemory {
33925
34285
  };
33926
34286
  }
33927
34287
  /**
33928
- * Persist a data-om-* marker part on the last assistant message in messageList
33929
- * AND save the updated message to the DB so it survives page reload.
33930
- * (data-* parts are filtered out before sending to the LLM, so they don't affect model calls.)
34288
+ * Persist a data-om-* marker part on the message that owns the operation in
34289
+ * messageList and save it to the DB. Observation markers belong to the latest
34290
+ * assistant message; reflection markers belong to the current user input.
33931
34291
  * @internal Used by ReflectorRunner. Do not call directly.
33932
34292
  */
33933
34293
  async persistMarkerToMessage(marker, messageList, threadId, resourceId) {
33934
- if (!messageList) return;
33935
- const allMsgs = getObservableMessages(messageList);
34294
+ if (!messageList) return false;
34295
+ const allMsgs = messageList.get.all.db();
34296
+ const markerData = marker.data;
34297
+ const targetRole = markerData?.operationType === "reflection" ? "user" : "assistant";
33936
34298
  for (let i = allMsgs.length - 1; i >= 0; i--) {
33937
34299
  const msg = allMsgs[i];
33938
- if (msg?.role === "assistant" && msg.content?.parts && Array.isArray(msg.content.parts)) {
33939
- const markerData = marker.data;
34300
+ if (msg?.role === targetRole && msg.content?.parts && Array.isArray(msg.content.parts)) {
33940
34301
  if (!(markerData?.cycleId && msg.content.parts.some((p) => p?.type === marker.type && p?.data?.cycleId === markerData.cycleId))) msg.content.parts.push(marker);
33941
34302
  try {
33942
34303
  await this.messageHistory.persistMessages({
@@ -33946,16 +34307,19 @@ var ObservationalMemory = class ObservationalMemory {
33946
34307
  });
33947
34308
  } catch (e) {
33948
34309
  omDebug(`[OM:persistMarker] failed to save marker to DB: ${e}`);
34310
+ return false;
33949
34311
  }
33950
- return;
34312
+ return true;
33951
34313
  }
33952
34314
  }
34315
+ return false;
33953
34316
  }
33954
34317
  /**
33955
- * Persist a marker to the last assistant message in storage.
33956
- * Unlike persistMarkerToMessage, this fetches messages directly from the DB
33957
- * so it works even when no MessageList is available (e.g. async buffering ops).
33958
- * @internal Used by observation strategies. Do not call directly.
34318
+ * Persist a marker to the message that owns the operation in storage.
34319
+ * Observation markers belong to the latest assistant message. Reflection runs
34320
+ * before the current assistant reply exists, so its failure marker belongs to
34321
+ * the latest user input that triggered it.
34322
+ * @internal Used by observation strategies and the reflector. Do not call directly.
33959
34323
  */
33960
34324
  async persistMarkerToStorage(marker, threadId, resourceId) {
33961
34325
  try {
@@ -33967,8 +34331,9 @@ var ObservationalMemory = class ObservationalMemory {
33967
34331
  direction: "DESC"
33968
34332
  }
33969
34333
  }))?.messages ?? [];
33970
- for (const msg of messages) if (msg?.role === "assistant" && msg.content?.parts && Array.isArray(msg.content.parts)) {
33971
- const markerData = marker.data;
34334
+ const markerData = marker.data;
34335
+ const targetRole = markerData?.operationType === "reflection" ? "user" : "assistant";
34336
+ for (const msg of messages) if (msg?.role === targetRole && msg.content?.parts && Array.isArray(msg.content.parts)) {
33972
34337
  if (!(markerData?.cycleId && msg.content.parts.some((p) => p?.type === marker.type && p?.data?.cycleId === markerData.cycleId))) msg.content.parts.push(marker);
33973
34338
  await this.messageHistory.persistMessages({
33974
34339
  messages: [msg],
@@ -34210,9 +34575,9 @@ var ObservationalMemory = class ObservationalMemory {
34210
34575
  * In resource scope mode, filters continuity messages to only show
34211
34576
  * the message for the current thread.
34212
34577
  */
34213
- formatObservationsForContext(observations, currentTask, suggestedResponse, extractedValues, unobservedContextBlocks, currentDate, retrieval = false) {
34578
+ formatObservationsForContext(observations, currentTask, suggestedResponse, extractedValues, unobservedContextBlocks, currentDate, retrieval = false, timeZone) {
34214
34579
  let optimized = retrieval ? renderObservationGroupsForReflection(observations) ?? optimizeObservationsForContext(observations) : optimizeObservationsForContext(observations);
34215
- if (currentDate) optimized = addRelativeTimeToObservations(optimized, currentDate);
34580
+ if (currentDate) optimized = addRelativeTimeToObservations(optimized, currentDate, timeZone);
34216
34581
  const messages = [`${getObservationContextPrompt(this.scope)}\n\n${OBSERVATION_CONTEXT_INSTRUCTIONS}${retrieval ? `\n\n${getRetrievalInstructions(this.retrievalScope, this.retrievalInstructions, this.retrievalSearch)}` : ""}`];
34217
34582
  if (unobservedContextBlocks) messages.push(`The following content is from OTHER conversations different from the current conversation, they're here for reference, but they're not necessarily your focus:\nSTART_OTHER_CONVERSATIONS_BLOCK\n${unobservedContextBlocks}\nEND_OTHER_CONVERSATIONS_BLOCK`);
34218
34583
  const observationChunks = this.splitObservationContextChunks(optimized);
@@ -34312,12 +34677,15 @@ var ObservationalMemory = class ObservationalMemory {
34312
34677
  * These are injected into the Actor's context so it has awareness of activity
34313
34678
  * in other threads for the same resource.
34314
34679
  */
34315
- async formatUnobservedContextBlocks(messagesByThread, currentThreadId) {
34680
+ async formatUnobservedContextBlocks(messagesByThread, currentThreadId, timeZone) {
34316
34681
  const blocks = [];
34317
34682
  for (const [threadId, messages] of messagesByThread) {
34318
34683
  if (threadId === currentThreadId) continue;
34319
34684
  if (messages.length === 0) continue;
34320
- const formattedMessages = formatMessagesForObserver(messages, { maxPartLength: 500 });
34685
+ const formattedMessages = formatMessagesForObserver(messages, {
34686
+ maxPartLength: 500,
34687
+ timeZone
34688
+ });
34321
34689
  if (formattedMessages) {
34322
34690
  const obscuredId = await this.representThreadIDInContext(threadId);
34323
34691
  blocks.push(`<other-conversation id="${obscuredId}">
@@ -34494,7 +34862,7 @@ ${formattedMessages}
34494
34862
  transient: true
34495
34863
  }).catch(() => {});
34496
34864
  omDebug(`[OM:bufferInput] cycleId=${cycleId}, msgCount=${messagesToBuffer.length}, msgTokens=${tokensToBuffer}, ids=${messagesToBuffer.map((m) => `${m.id?.slice(0, 8)}@${m.createdAt ? new Date(m.createdAt).toISOString() : "none"}`).join(",")}`);
34497
- await this.runBufferedObservationCycle({
34865
+ if ((await this.runBufferedObservationCycle({
34498
34866
  threadId,
34499
34867
  resourceId: freshRecord.resourceId ?? void 0,
34500
34868
  trigger: "async-buffer"
@@ -34509,10 +34877,11 @@ ${formattedMessages}
34509
34877
  requestContext,
34510
34878
  observabilityContext,
34511
34879
  trigger: "async-buffer"
34512
- }).run());
34513
- const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
34514
- const cursor = new Date(maxTs.getTime() + 1);
34515
- BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
34880
+ }).run()))?.observed) {
34881
+ const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
34882
+ const cursor = new Date(maxTs.getTime() + 1);
34883
+ BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
34884
+ }
34516
34885
  }
34517
34886
  /**
34518
34887
  * Trigger async buffered observation if the token count has crossed a new interval.
@@ -34740,7 +35109,7 @@ ${formattedMessages}
34740
35109
  const currentTask = activeExtractors.some((extractor) => extractor.slug === "current-task") ? omMetadata?.currentTask : void 0;
34741
35110
  const suggestedResponse = activeExtractors.some((extractor) => extractor.slug === "suggested-response") ? omMetadata?.suggestedResponse : void 0;
34742
35111
  const currentDate = opts.currentDate ?? /* @__PURE__ */ new Date();
34743
- return this.formatObservationsForContext(record.activeObservations, currentTask, suggestedResponse, omMetadata?.extracted, unobservedContextBlocks, currentDate, this.retrieval);
35112
+ return this.formatObservationsForContext(record.activeObservations, currentTask, suggestedResponse, omMetadata?.extracted, unobservedContextBlocks, currentDate, this.retrieval, record.observedTimezone);
34744
35113
  }
34745
35114
  /**
34746
35115
  * Get unobserved messages from other threads for resource-scoped observation.
@@ -34752,7 +35121,8 @@ ${formattedMessages}
34752
35121
  async getOtherThreadsContext(resourceId, currentThreadId) {
34753
35122
  const { threads: allThreads } = await this.storage.listThreads({ filter: { resourceId } });
34754
35123
  const messagesByThread = /* @__PURE__ */ new Map();
34755
- const recordLastObservedAt = (await this.getRecord(currentThreadId, resourceId))?.lastObservedAt;
35124
+ const record = await this.getRecord(currentThreadId, resourceId);
35125
+ const recordLastObservedAt = record?.lastObservedAt;
34756
35126
  for (const thread of allThreads) {
34757
35127
  if (thread.id === currentThreadId) continue;
34758
35128
  const threadLastObservedAt = getThreadOMMetadata(thread.metadata)?.lastObservedAt ?? recordLastObservedAt;
@@ -34769,7 +35139,7 @@ ${formattedMessages}
34769
35139
  if (filtered.length > 0) messagesByThread.set(thread.id, filtered);
34770
35140
  }
34771
35141
  if (messagesByThread.size === 0) return void 0;
34772
- return await this.formatUnobservedContextBlocks(messagesByThread, currentThreadId) || void 0;
35142
+ return await this.formatUnobservedContextBlocks(messagesByThread, currentThreadId, record?.observedTimezone) || void 0;
34773
35143
  }
34774
35144
  /**
34775
35145
  * Emit debug event and stream progress for UI feedback.
@@ -35112,7 +35482,7 @@ ${formattedMessages}
35112
35482
  ...startMarker,
35113
35483
  transient: true
35114
35484
  }).catch(() => {});
35115
- await this.runBufferedObservationCycle({
35485
+ if (!(await this.runBufferedObservationCycle({
35116
35486
  threadId,
35117
35487
  resourceId: record.resourceId ?? resourceId,
35118
35488
  trigger: "async-buffer"
@@ -35131,7 +35501,10 @@ ${formattedMessages}
35131
35501
  currentModel: opts.currentModel,
35132
35502
  observabilityContext,
35133
35503
  trigger: "async-buffer"
35134
- }).run());
35504
+ }).run()))?.observed) return {
35505
+ buffered: false,
35506
+ record
35507
+ };
35135
35508
  if (isOmReproCaptureEnabled()) writeObserverExchangeReproCapture({
35136
35509
  threadId,
35137
35510
  resourceId: record.resourceId ?? void 0,
@@ -35491,6 +35864,7 @@ ${formattedMessages}
35491
35864
  observed = result.observed;
35492
35865
  observationUsage = result.usage;
35493
35866
  observationProviderMetadata = result.providerMetadata;
35867
+ observationError = result.error;
35494
35868
  });
35495
35869
  } catch (error) {
35496
35870
  lifecycleError = error;
@@ -37401,6 +37775,7 @@ ${workingMemory}`;
37401
37775
  model: omConfig.model,
37402
37776
  mastra: this._mastraInstance,
37403
37777
  onIndexObservations,
37778
+ onDebugEvent: omConfig.onDebugEvent,
37404
37779
  hooks: omConfig.hooks,
37405
37780
  observation: omConfig.observation ? {
37406
37781
  model: omConfig.observation.model,
@@ -37417,10 +37792,14 @@ ${workingMemory}`;
37417
37792
  threadTitle: omConfig.observation.threadTitle,
37418
37793
  observeAttachments: omConfig.observation.observeAttachments,
37419
37794
  continuationHints: omConfig.observation.continuationHints,
37795
+ maxRetries: omConfig.observation.maxRetries,
37796
+ failurePolicy: omConfig.observation.failurePolicy,
37420
37797
  extract: omConfig.observation.extract
37421
37798
  } : void 0,
37422
37799
  reflection: omConfig.reflection ? {
37423
37800
  model: omConfig.reflection.model,
37801
+ maxRetries: omConfig.reflection.maxRetries,
37802
+ failurePolicy: omConfig.reflection.failurePolicy,
37424
37803
  observationTokens: omConfig.reflection.observationTokens,
37425
37804
  modelSettings: omConfig.reflection.modelSettings,
37426
37805
  providerOptions: omConfig.reflection.providerOptions,
@@ -49270,4 +49649,4 @@ const agentBuilderWorkflows = {
49270
49649
  //#endregion
49271
49650
  export { agentBuilderWorkflows };
49272
49651
 
49273
- //# sourceMappingURL=dist-ABdCIqbD.js.map
49652
+ //# sourceMappingURL=dist-Bo9o3JNW.js.map