@opengeni/react 3.0.2-canary.38894290271001 → 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.
Files changed (54) hide show
  1. package/dist/{browser-viewer-M7BIVFTW.js → browser-viewer-ZWR6MWJ7.js} +3 -3
  2. package/dist/{chunk-PWCBMEV2.js → chunk-2I6R3GCZ.js} +4 -4
  3. package/dist/{chunk-QTSWNANQ.js → chunk-2SFFYIH3.js} +2 -2
  4. package/dist/{chunk-S5ZT4TBR.js → chunk-ADWCLI4G.js} +2 -2
  5. package/dist/{chunk-6SNDCUPB.js → chunk-B7TC2A33.js} +2 -2
  6. package/dist/{chunk-KZENYIA2.js → chunk-BLL56F7R.js} +4 -1
  7. package/dist/chunk-BLL56F7R.js.map +1 -0
  8. package/dist/{chunk-ISN726VG.js → chunk-KZC6QRNR.js} +2 -2
  9. package/dist/chunk-MK2TQO4Y.js +24 -0
  10. package/dist/chunk-MK2TQO4Y.js.map +1 -0
  11. package/dist/{chunk-TIHSXNBC.js → chunk-NKMYZFHA.js} +2 -2
  12. package/dist/{chunk-TL7M2WWQ.js → chunk-OVB5WIG5.js} +17 -11
  13. package/dist/{chunk-TL7M2WWQ.js.map → chunk-OVB5WIG5.js.map} +1 -1
  14. package/dist/{chunk-Q26UAIXI.js → chunk-V5ZUJT2T.js} +2 -2
  15. package/dist/{chunk-5XEXTWEM.js → chunk-WIUKB3LD.js} +2 -2
  16. package/dist/{chunk-UXI7L7DL.js → chunk-X5UVUIMF.js} +4 -4
  17. package/dist/composer-messages.js +2 -2
  18. package/dist/composer.js +4 -4
  19. package/dist/connect.js +2 -2
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +30 -26
  22. package/dist/index.js.map +1 -1
  23. package/dist/interaction.js +2 -2
  24. package/dist/{latest-question-W4DNEH4Q.js → latest-question-R77KWSUP.js} +3 -3
  25. package/dist/lib/scrollbars.d.ts +11 -0
  26. package/dist/machines.js +2 -2
  27. package/dist/sandbox-files-O27IPOZW.js +1 -1
  28. package/dist/scrollbars.d.ts +1 -0
  29. package/dist/scrollbars.js +10 -0
  30. package/dist/scrollbars.js.map +1 -0
  31. package/dist/session-ui.js +13 -12
  32. package/dist/session-ui.js.map +1 -1
  33. package/dist/session.js +4 -4
  34. package/dist/timeline-model.js +2 -2
  35. package/package.json +7 -3
  36. package/src/index.ts +1 -0
  37. package/src/lib/host-theme.ts +5 -0
  38. package/src/lib/provider-recovery.ts +3 -0
  39. package/src/lib/scrollbars.ts +30 -0
  40. package/src/scrollbars.ts +3 -0
  41. package/styles/compiled.css +23 -0
  42. package/styles/index.css +31 -0
  43. package/dist/chunk-KZENYIA2.js.map +0 -1
  44. /package/dist/{browser-viewer-M7BIVFTW.js.map → browser-viewer-ZWR6MWJ7.js.map} +0 -0
  45. /package/dist/{chunk-PWCBMEV2.js.map → chunk-2I6R3GCZ.js.map} +0 -0
  46. /package/dist/{chunk-QTSWNANQ.js.map → chunk-2SFFYIH3.js.map} +0 -0
  47. /package/dist/{chunk-S5ZT4TBR.js.map → chunk-ADWCLI4G.js.map} +0 -0
  48. /package/dist/{chunk-6SNDCUPB.js.map → chunk-B7TC2A33.js.map} +0 -0
  49. /package/dist/{chunk-ISN726VG.js.map → chunk-KZC6QRNR.js.map} +0 -0
  50. /package/dist/{chunk-TIHSXNBC.js.map → chunk-NKMYZFHA.js.map} +0 -0
  51. /package/dist/{chunk-Q26UAIXI.js.map → chunk-V5ZUJT2T.js.map} +0 -0
  52. /package/dist/{chunk-5XEXTWEM.js.map → chunk-WIUKB3LD.js.map} +0 -0
  53. /package/dist/{chunk-UXI7L7DL.js.map → chunk-X5UVUIMF.js.map} +0 -0
  54. /package/dist/{latest-question-W4DNEH4Q.js.map → latest-question-R77KWSUP.js.map} +0 -0
@@ -2,18 +2,18 @@
2
2
  import {
3
3
  BrowserViewer,
4
4
  staleBrowserEndRetryDelayMs
5
- } from "./chunk-ISN726VG.js";
5
+ } from "./chunk-KZC6QRNR.js";
6
6
  import "./chunk-P4BNUO57.js";
7
7
  import "./chunk-PEHTX3V7.js";
8
8
  import "./chunk-ZUWF4NF7.js";
9
9
  import "./chunk-QHUE7E4N.js";
10
10
  import "./chunk-CM7LVUKC.js";
11
11
  import "./chunk-G76LSA76.js";
12
- import "./chunk-KZENYIA2.js";
12
+ import "./chunk-BLL56F7R.js";
13
13
  import "./chunk-TNEZNMSN.js";
14
14
  import "./chunk-TXS65BB2.js";
15
15
  export {
16
16
  BrowserViewer,
17
17
  staleBrowserEndRetryDelayMs
18
18
  };
19
- //# sourceMappingURL=browser-viewer-M7BIVFTW.js.map
19
+ //# sourceMappingURL=browser-viewer-ZWR6MWJ7.js.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  defaultChatComposerMessages
4
- } from "./chunk-6SNDCUPB.js";
4
+ } from "./chunk-B7TC2A33.js";
5
5
  import {
6
6
  COMPOSER_VOICE_INPUT_START_EVENT,
7
7
  composerVoiceEventScope
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  shouldSteerOnKey,
11
11
  shouldSubmitOnKey
12
- } from "./chunk-Q26UAIXI.js";
12
+ } from "./chunk-V5ZUJT2T.js";
13
13
  import {
14
14
  Tooltip,
15
15
  TooltipContent,
@@ -28,7 +28,7 @@ import {
28
28
  } from "./chunk-CM7LVUKC.js";
29
29
  import {
30
30
  composerSubmissionErrorMessage
31
- } from "./chunk-KZENYIA2.js";
31
+ } from "./chunk-BLL56F7R.js";
32
32
  import {
33
33
  cn
34
34
  } from "./chunk-TXS65BB2.js";
@@ -4899,4 +4899,4 @@ export {
4899
4899
  useVoiceInput,
4900
4900
  ComposerTranscriptionControl
4901
4901
  };
4902
- //# sourceMappingURL=chunk-PWCBMEV2.js.map
4902
+ //# sourceMappingURL=chunk-2I6R3GCZ.js.map
@@ -8,7 +8,7 @@ import {
8
8
  isCreditExhaustion,
9
9
  presentFailure,
10
10
  tryParseJson
11
- } from "./chunk-KZENYIA2.js";
11
+ } from "./chunk-BLL56F7R.js";
12
12
 
13
13
  // src/timeline/projection.ts
14
14
  import {
@@ -3044,4 +3044,4 @@ export {
3044
3044
  isTurnExecutionEvidence,
3045
3045
  extractSessionRef
3046
3046
  };
3047
- //# sourceMappingURL=chunk-QTSWNANQ.js.map
3047
+ //# sourceMappingURL=chunk-2SFFYIH3.js.map
@@ -10,7 +10,7 @@ import {
10
10
  formatClockTime,
11
11
  stringifyPayload,
12
12
  tryParseJson
13
- } from "./chunk-KZENYIA2.js";
13
+ } from "./chunk-BLL56F7R.js";
14
14
 
15
15
  // src/timeline/parsers.ts
16
16
  import {
@@ -2025,4 +2025,4 @@ export {
2025
2025
  timelineGroupSequences,
2026
2026
  timelineGroupIndexAtSequence
2027
2027
  };
2028
- //# sourceMappingURL=chunk-S5ZT4TBR.js.map
2028
+ //# sourceMappingURL=chunk-ADWCLI4G.js.map
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  formatBytes,
4
4
  formatRelativeTime
5
- } from "./chunk-KZENYIA2.js";
5
+ } from "./chunk-BLL56F7R.js";
6
6
 
7
7
  // src/composer-messages.ts
8
8
  var defaultChatComposerMessages = {
@@ -80,4 +80,4 @@ var defaultChatComposerMessages = {
80
80
  export {
81
81
  defaultChatComposerMessages
82
82
  };
83
- //# sourceMappingURL=chunk-6SNDCUPB.js.map
83
+ //# sourceMappingURL=chunk-B7TC2A33.js.map
@@ -19,6 +19,7 @@ var RECOVERY_CODES = /* @__PURE__ */ new Set([
19
19
  "mcp_transport_timeout",
20
20
  "mcp_transport_unavailable",
21
21
  "sandbox_command_start_unavailable",
22
+ "retained_attachment_unavailable",
22
23
  "turn_execution_policy_definition_mismatch"
23
24
  ]);
24
25
  var DEFAULT_MAX_ATTEMPTS = 5;
@@ -84,6 +85,8 @@ function providerRecoverySubject(facts) {
84
85
  return "A required MCP server is unreachable";
85
86
  case "sandbox_command_start_unavailable":
86
87
  return "The sandbox isn't ready yet";
88
+ case "retained_attachment_unavailable":
89
+ return "An image from earlier in this conversation can't be read from storage";
87
90
  case "turn_execution_policy_definition_mismatch":
88
91
  return "Opengeni is applying a configuration update";
89
92
  case "sandbox_deadline_rotation":
@@ -379,4 +382,4 @@ export {
379
382
  humanizeFailureReason,
380
383
  presentFailure
381
384
  };
382
- //# sourceMappingURL=chunk-KZENYIA2.js.map
385
+ //# sourceMappingURL=chunk-BLL56F7R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/provider-recovery.ts","../src/lib/format.ts"],"sourcesContent":["import type { SessionEvent, SessionStatus } from \"@opengeni/sdk\";\n\n/**\n * Finite same-turn provider recovery, projected for people. Presentation only:\n * the worker owns retry authority, pacing and the recovery budget. The worker\n * (`apps/worker/src/activities/agent-turn/provider-recovery-copy.ts`) writes\n * the same exhausted sentence into `turn.failed.error`; keep the two in step.\n */\nexport type ProviderRecoveryCondition =\n | \"overloaded\"\n | \"unavailable\"\n | \"unresponsive\"\n | \"rate_limited\";\n\nexport type ProviderRecoveryFacts = {\n /** Recorded worker failure code (`provider_unavailable`, `mcp_transport_timeout`, ...). */\n code: string;\n condition: ProviderRecoveryCondition | null;\n /** Display label of the affected model, when the route was recorded. */\n modelLabel: string | null;\n /** Display label of the serving provider, when the route was recorded. */\n providerLabel: string | null;\n /** Automatic retries scheduled (live) or spent (exhausted). */\n attempt: number | null;\n /** Finite automatic retry budget. */\n maxAttempts: number | null;\n /** True when the model route itself is affected, so another model may help. */\n modelRoute: boolean;\n /** True while the turn waits for its sandbox to be saved and replaced. It\n * has no retry budget: it resumes as soon as the successor box is ready. */\n sandboxWait?: boolean;\n /** Recorded lifecycle fence of a sandbox wait (`capture_in_progress`,\n * `rotation_in_progress`, `provider_recovery_in_progress`), when known. */\n sandboxTransition?: string | null;\n};\n\nconst MODEL_CODES: ReadonlySet<string> = new Set([\n \"provider_unavailable\",\n \"provider_rate_limited\",\n \"provider_unknown_finish_reason\",\n \"post_compaction_continuation_empty\",\n]);\n\n/** A recovering turn parked behind a sandbox lifecycle transition (worker\n * `failure-settlement.ts`). Before, this showed only \"Recovering\" with no\n * reason. A superseded lease\n * counts only when the worker recorded the pending transition it waits for. */\nconst SANDBOX_WAIT_CODES: ReadonlySet<string> = new Set([\n \"sandbox_deadline_rotation\",\n \"sandbox_lifecycle_transition\",\n \"sandbox_lease_superseded\",\n]);\n\nconst RECOVERY_CODES: ReadonlySet<string> = new Set([\n ...MODEL_CODES,\n ...SANDBOX_WAIT_CODES,\n \"upstream_connectivity_unavailable\",\n \"mcp_transport_timeout\",\n \"mcp_transport_unavailable\",\n \"sandbox_command_start_unavailable\",\n \"retained_attachment_unavailable\",\n \"turn_execution_policy_definition_mismatch\",\n]);\n\n/** Matches the worker's default budget for legacy events that omit it. */\nconst DEFAULT_MAX_ATTEMPTS = 5;\n\nfunction text(value: unknown, max = 120): string | null {\n if (typeof value !== \"string\") return null;\n const normalized = value.replace(/\\s+/g, \" \").trim();\n return normalized ? normalized.slice(0, max) : null;\n}\n\nfunction count(value: unknown): number | null {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value > 0 ? value : null;\n}\n\nfunction condition(\n payload: Record<string, unknown>,\n code: string,\n): ProviderRecoveryCondition | null {\n const recorded = payload.providerCondition;\n if (\n recorded === \"overloaded\" ||\n recorded === \"unavailable\" ||\n recorded === \"unresponsive\" ||\n recorded === \"rate_limited\"\n )\n return recorded;\n if (code === \"provider_rate_limited\") return \"rate_limited\";\n if (code !== \"provider_unavailable\") return null;\n // Older events predate the typed condition; their provider text still says so.\n return [payload.lastRetryableError, payload.detail, payload.error].some(\n (value) => typeof value === \"string\" && /\\boverload(?:ed)?(?:_error)?\\b/i.test(value),\n )\n ? \"overloaded\"\n : null;\n}\n\n/**\n * Read a retryable `turn.recovery.requested` payload or an exhausted\n * `turn.failed` payload. Returns null for every other recovery reason (human\n * Retry, worker shutdown, credential rotation, capacity waits, ...).\n */\nexport function parseProviderRecovery(payload: unknown): ProviderRecoveryFacts | null {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return null;\n const record = payload as Record<string, unknown>;\n const code = text(record.code) ?? text(record.reason);\n if (!code || !RECOVERY_CODES.has(code)) return null;\n const rotation = text(record.rotationReason);\n const transition = text(record.transitionReason);\n if (code === \"sandbox_lease_superseded\" && !rotation && !transition) return null;\n // A live recovery request is retryable; a spent budget is explicitly marked.\n if (record.recoveryExhausted !== true && record.retryable === false) return null;\n const attempt = count(record.providerRecoveryCount);\n return {\n code,\n condition: condition(record, code),\n modelLabel: text(record.modelLabel),\n providerLabel: text(record.providerLabel),\n attempt,\n maxAttempts: count(record.maxProviderRecoveryCount) ?? DEFAULT_MAX_ATTEMPTS,\n modelRoute: MODEL_CODES.has(code),\n ...(SANDBOX_WAIT_CODES.has(code)\n ? {\n sandboxWait: true,\n sandboxTransition: transition ?? (rotation ? \"rotation_in_progress\" : null),\n }\n : {}),\n };\n}\n\n/** One present-tense clause naming what is unavailable, without a trailing period. */\nexport function providerRecoverySubject(facts: ProviderRecoveryFacts): string {\n const model = facts.modelLabel ?? \"The model\";\n const at = facts.providerLabel ? ` at the provider (${facts.providerLabel})` : \" at the provider\";\n switch (facts.code) {\n case \"provider_rate_limited\":\n return `${model} is rate limited${at}`;\n case \"provider_unavailable\":\n return facts.condition === \"overloaded\"\n ? `${model} is overloaded${at}`\n : facts.condition === \"unresponsive\"\n ? `${model} stopped responding${at}`\n : `${model} is temporarily unavailable${at}`;\n case \"provider_unknown_finish_reason\":\n return `${model} ended its response unexpectedly`;\n case \"post_compaction_continuation_empty\":\n return `${model} stopped right after compacting the conversation`;\n case \"upstream_connectivity_unavailable\":\n return \"Opengeni can't reach an upstream service\";\n case \"mcp_transport_timeout\":\n return \"A required MCP server isn't responding\";\n case \"mcp_transport_unavailable\":\n return \"A required MCP server is unreachable\";\n case \"sandbox_command_start_unavailable\":\n return \"The sandbox isn't ready yet\";\n case \"retained_attachment_unavailable\":\n return \"An image from earlier in this conversation can't be read from storage\";\n case \"turn_execution_policy_definition_mismatch\":\n return \"Opengeni is applying a configuration update\";\n case \"sandbox_deadline_rotation\":\n return \"The sandbox reached its maximum lifetime, so Opengeni is moving the workspace to a fresh sandbox\";\n case \"sandbox_lifecycle_transition\":\n case \"sandbox_lease_superseded\":\n return facts.sandboxTransition === \"capture_in_progress\"\n ? \"Opengeni is saving the sandbox workspace\"\n : facts.sandboxTransition === \"provider_recovery_in_progress\"\n ? \"Opengeni is recovering the sandbox\"\n : facts.sandboxTransition === \"rotation_in_progress\"\n ? \"Opengeni is moving the workspace to a fresh sandbox\"\n : \"Opengeni is preparing the sandbox\";\n default:\n return \"A service this turn depends on is temporarily unavailable\";\n }\n}\n\n/** Live status while the same turn waits for its next automatic retry. */\nexport function providerRecoveryRetryingText(facts: ProviderRecoveryFacts): string {\n if (facts.sandboxWait) return `${providerRecoverySubject(facts)}…`;\n const progress =\n facts.attempt !== null && facts.maxAttempts !== null\n ? ` (attempt ${Math.min(facts.attempt, facts.maxAttempts)} of ${facts.maxAttempts})`\n : \" automatically\";\n return `${providerRecoverySubject(facts)} — retrying${progress}…`;\n}\n\n/** Terminal sentence once the automatic budget is spent. */\nexport function providerRecoveryExhaustedText(facts: ProviderRecoveryFacts): string {\n const spent = facts.attempt ?? facts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const retried = `Opengeni retried ${spent} ${spent === 1 ? \"time\" : \"times\"} without success.`;\n const remedy = facts.modelRoute\n ? \"Try again in a few minutes, or switch to another model.\"\n : \"Try again in a few minutes.\";\n return `${providerRecoverySubject(facts)}. ${retried} ${remedy}`;\n}\n\nconst BOUNDARY_TYPES: ReadonlySet<string> = new Set([\n \"turn.recovery.requested\",\n \"turn.started\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"turn.superseded\",\n]);\n\n/**\n * The active turn's current automatic provider retry, or null. Only a\n * `recovering`, unpaused session qualifies, and only the newest boundary of its\n * exact active turn counts, so merged or replayed pages never borrow another\n * turn's diagnosis.\n */\nexport function currentProviderRecovery(\n session: {\n id: string;\n status: SessionStatus | null | undefined;\n activeTurnId: string | null | undefined;\n effectiveControl?: { state: string } | null | undefined;\n },\n events: readonly SessionEvent[],\n): ProviderRecoveryFacts | null {\n if (\n session.status !== \"recovering\" ||\n (session.effectiveControl && session.effectiveControl.state !== \"active\") ||\n !session.activeTurnId\n )\n return null;\n let latest: SessionEvent | undefined;\n for (const event of events) {\n if (\n event.sessionId !== session.id ||\n event.turnId !== session.activeTurnId ||\n event.duplicateOfEventId ||\n (event.turnAssociation && event.turnAssociation !== \"current\") ||\n !BOUNDARY_TYPES.has(event.type)\n )\n continue;\n if (!latest || event.sequence > latest.sequence) latest = event;\n }\n if (latest?.type !== \"turn.recovery.requested\") return null;\n const payload = latest.payload as Record<string, unknown> | null | undefined;\n return payload?.recoveryExhausted === true ? null : parseProviderRecovery(payload);\n}\n","import { formatErrorMessage, OpenGeniApiError } from \"@opengeni/sdk\";\nimport { parseProviderRecovery, providerRecoveryExhaustedText } from \"./provider-recovery\";\n\nconst clockTimeFormatter = new Intl.DateTimeFormat(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n});\n\n/** Local finished-at stamp for message footers: \"Aug 2, 3:42 PM\" / locale-equivalent. */\nexport function formatClockTime(iso: string): string {\n const then = new Date(iso);\n if (Number.isNaN(then.getTime())) {\n return \"\";\n }\n return clockTimeFormatter.format(then);\n}\n\n/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The canonical credit-death sentence. Credit exhaustion is the one failure a\n * user can fix themselves — the copy must say what happened (empty balance),\n * what to do (add credits), and what is safe (nothing was lost). Crucially it\n * must NOT say \"send a message to revive\": a revive turn burns credits the\n * workspace no longer has.\n */\nexport const CREDIT_EXHAUSTION_MESSAGE =\n \"Out of credits — this workspace's balance is empty. Add credits to continue; the conversation is preserved.\";\n\n/** A usage ceiling refused the send; the default allowance wording, plus what is safe. */\nexport const COMPOSER_MEMBER_ALLOWANCE_MESSAGE =\n \"Usage limit reached. A workspace admin can raise this limit. Your draft is preserved.\";\nexport const COMPOSER_WORKSPACE_ALLOWANCE_MESSAGE =\n \"Workspace usage limit reached. An organization admin can raise the workspace budget. Your draft is preserved.\";\n\n/**\n * Actionable composer copy for an edge rejection before a turn is accepted.\n * Unlike an in-flight credit exhaustion, this path has not consumed the\n * actor-private draft or any finalized attachment.\n */\nexport const COMPOSER_PAYMENT_REQUIRED_MESSAGE =\n \"Your organization doesn't have enough credits to send this message. Add credits or choose a model with another payment source. Your message and attachments are saved.\";\n\n/** Trusted, composer-owned guidance; unlike remote diagnostic prose, this is UI copy. */\nexport class ComposerStateError extends Error {}\n\n/** A restored request has omitted credentials and must be reconciled, not replayed. */\nexport class ComposerReconciliationRequiredError extends ComposerStateError {\n constructor() {\n super(\n \"Opengeni cannot safely retry this uncertain request after remount; reconcile the session before sending again.\",\n );\n }\n}\n\nexport class ComposerWorkspaceControlUnavailableError extends Error {\n constructor() {\n super(\"@opengeni/react: workspace-scoped resume requires setWorkspaceInferenceState.\");\n }\n}\n\n/**\n * The send named a model that is no longer in the live catalog (retired or\n * removed). Retrying the same send cannot succeed; the person must choose\n * another model, and the typed message stays recoverable via Edit message.\n */\nexport const COMPOSER_MODEL_UNAVAILABLE_MESSAGE =\n \"This chat's model is no longer available. Choose another model to continue. Your message is saved.\";\n\n/** `details.code` the API sets on a 422 for a model missing from the live catalog. */\nexport const MODEL_UNAVAILABLE_DETAIL_CODE = \"model_unavailable\";\n\n/**\n * A fresh Send or Steer refused because the task's own usage limit is reached.\n * The draft is kept and an unchanged retry is never offered. The one current\n * recovery action (raise or remove the limit, resume a goal) belongs to the\n * composer's `SessionUsageLimitNotice`, so this line only says what happened.\n */\nexport const COMPOSER_SESSION_USAGE_LIMIT_MESSAGE =\n \"This task's usage limit is reached. Your message is saved.\";\n\n/** The earlier wording, still recognized in refusals restored from storage. */\nconst LEGACY_COMPOSER_SESSION_USAGE_LIMIT_MESSAGE =\n \"This task's usage limit is reached. Raise or remove the limit to continue. Your message is saved.\";\n\n/**\n * Is this send refusal the task's usage limit? Reads the typed SDK error code\n * (`OpenGeniSessionUsageLimitReachedError`), and also the composer's own\n * sentence so a refusal restored from storage after a reload is recognized.\n */\nexport function isSessionUsageLimitSubmissionError(error: Error): boolean {\n return (\n (error instanceof OpenGeniApiError && error.code === \"session_usage_limit_reached\") ||\n error.message === COMPOSER_SESSION_USAGE_LIMIT_MESSAGE ||\n error.message === LEGACY_COMPOSER_SESSION_USAGE_LIMIT_MESSAGE\n );\n}\n\n/**\n * Is this send refusal \"the model is no longer available\"? Reads the typed\n * `details.code`, and also the historical message so a refusal persisted\n * before a reload (only its text survives) or from an older API is recognized.\n */\nexport function isModelUnavailableSubmissionError(error: Error): boolean {\n if (error instanceof OpenGeniApiError && error.details?.code === MODEL_UNAVAILABLE_DETAIL_CODE) {\n return true;\n }\n return (\n error.message === COMPOSER_MODEL_UNAVAILABLE_MESSAGE ||\n /^(?:Opengeni|OpenGeni) API 422: model is not available: /.test(error.message)\n );\n}\n\n/**\n * What a published Site's assistant tells a viewer it refused, by the\n * refusal's `details.code`. The draft is kept in every case.\n */\nexport const COMPOSER_SITE_REFUSAL_MESSAGES: Readonly<Record<string, string>> = Object.freeze({\n not_available_for_viewer: \"This Site's assistant can't do that for you. Your message is saved.\",\n site_budget_exhausted:\n \"This Site's assistant has reached its usage limit for now. Your message is saved.\",\n site_budget_busy: \"This Site's assistant is busy. Try again in a moment. Your message is saved.\",\n site_platform_brake_engaged:\n \"This Site's assistant is paused for visitors right now. Your message is saved.\",\n});\n\n/** The Site refusal code of a send refusal, if it is one. */\nexport function siteRefusalCode(error: Error): string | null {\n if (!(error instanceof OpenGeniApiError)) return null;\n const code = error.details?.code;\n return typeof code === \"string\" && code in COMPOSER_SITE_REFUSAL_MESSAGES ? code : null;\n}\n\nexport function composerSubmissionErrorMessage(error: Error): string {\n if (error instanceof ComposerReconciliationRequiredError) {\n return \"This client cannot safely retry this uncertain request after remount; reconcile the session before sending again.\";\n }\n if (error instanceof ComposerWorkspaceControlUnavailableError) {\n return \"This client cannot resume the workspace. Ask your administrator for a control-capable client.\";\n }\n if (error instanceof ComposerStateError) return error.message;\n if (error instanceof OpenGeniApiError && error.outcomeUnknown) return formatErrorMessage(error);\n if (isModelUnavailableSubmissionError(error)) return COMPOSER_MODEL_UNAVAILABLE_MESSAGE;\n if (isSessionUsageLimitSubmissionError(error)) return COMPOSER_SESSION_USAGE_LIMIT_MESSAGE;\n const siteRefusal = siteRefusalCode(error);\n if (siteRefusal) return COMPOSER_SITE_REFUSAL_MESSAGES[siteRefusal]!;\n if (error instanceof OpenGeniApiError && error.code === \"allowance_exhausted\") {\n // OpenGeniAllowanceExhaustedError carries the scope; read it structurally\n // so this startup-path helper adds no SDK or wording imports.\n const message =\n (error as { scope?: unknown }).scope === \"workspace\"\n ? COMPOSER_WORKSPACE_ALLOWANCE_MESSAGE\n : COMPOSER_MEMBER_ALLOWANCE_MESSAGE;\n return composerErrorReference(error, message);\n }\n return isComposerCreditRefusal(error)\n ? composerErrorReference(error, COMPOSER_PAYMENT_REQUIRED_MESSAGE)\n : formatErrorMessage(error);\n}\n\nfunction composerErrorReference(error: Error, message: string): string {\n return error instanceof OpenGeniApiError && error.correlationId\n ? `${message} Reference: ${error.correlationId}.`\n : message;\n}\n\n/** These definitive refusals need a payment, allowance or model change, not an unchanged retry. */\nexport function composerSubmissionCanRetry(error: Error): boolean {\n return !(\n isComposerCreditRefusal(error) ||\n isModelUnavailableSubmissionError(error) ||\n isSessionUsageLimitSubmissionError(error) ||\n (error instanceof OpenGeniApiError && error.code === \"allowance_exhausted\") ||\n // Only a busy Site assistant is worth an unchanged retry.\n (siteRefusalCode(error) !== null && siteRefusalCode(error) !== \"site_budget_busy\")\n );\n}\n\nfunction isComposerCreditRefusal(error: Error): boolean {\n // A 402 for the task's own usage limit is not a credit or payment problem.\n if (isSessionUsageLimitSubmissionError(error)) return false;\n return (\n (error instanceof OpenGeniApiError &&\n error.status === 402 &&\n (error.code === \"payment_required\" || error.code === \"insufficient_credits\")) ||\n isCreditExhaustion(error.message)\n );\n}\n\n/**\n * Does this failure/completion payload (or raw error string) mean the\n * workspace ran out of Opengeni credits? Matches the engine's\n * \"insufficient Opengeni credits\" text (case-insensitive, substring — it\n * arrives both bare and wrapped in \"Activity task failed: …\") and the\n * budget-exhausted segment limit the engine stamps on a turn it ended early.\n */\nexport function isCreditExhaustion(\n input: { error?: string | null; detail?: string | null; segmentLimit?: string | null } | string,\n): boolean {\n if (typeof input === \"string\") {\n return input.toLowerCase().includes(\"insufficient opengeni credits\");\n }\n if (input.segmentLimit === \"budget_exhausted\") {\n return true;\n }\n for (const text of [input.error, input.detail]) {\n if (typeof text === \"string\" && text.toLowerCase().includes(\"insufficient opengeni credits\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Humanize engine/provider failure text before it reaches the timeline or a\n * failure banner. Raw provider errors leak the wrong audience's instructions —\n * \"Incorrect API key … find your API key at platform.openai.com\" tells a\n * managed-deployment USER to fix credentials only an OPERATOR controls (and is\n * flatly wrong for Azure or subscription-backed engines). Auth, quota, and\n * credit-exhaustion failures collapse to one neutral, honest sentence; every\n * other reason passes through untouched. Raw payloads stay available in the\n * debug surfaces.\n */\nexport function humanizeFailureReason(reason: string | null): string | null {\n if (!reason) {\n return reason;\n }\n if (isCreditExhaustion(reason)) {\n return CREDIT_EXHAUSTION_MESSAGE;\n }\n const normalized = reason.toLowerCase();\n const authFailure =\n normalized.includes(\"incorrect api key\") ||\n normalized.includes(\"invalid api key\") ||\n normalized.includes(\"invalid_api_key\") ||\n normalized.includes(\"platform.openai.com/account/api-keys\") ||\n (normalized.includes(\"401\") &&\n (normalized.includes(\"api key\") || normalized.includes(\"unauthorized\")));\n if (authFailure) {\n return \"The model provider rejected this deployment's engine credentials. Sending messages won't help until the deployment's engine configuration is fixed.\";\n }\n const quotaFailure =\n normalized.includes(\"insufficient_quota\") || normalized.includes(\"exceeded your current quota\");\n if (quotaFailure) {\n return \"The model provider refused the request: this deployment's provider quota is exhausted.\";\n }\n return reason;\n}\n\n/** Project failure diagnostics without changing the stored event, including legacy retry wrappers. */\nexport function presentFailure(payload: Record<string, unknown>): {\n reason: string | null;\n safetyRefusal: boolean;\n} {\n const databaseFailure =\n payload.code === \"db_deadlock\" ||\n payload.code === \"db_serialization_failure\" ||\n payload.code === \"db_failure\" ||\n (typeof payload.sqlState === \"string\" &&\n /^[0-9A-Z]{5}$/.test(payload.sqlState) &&\n payload.database !== null &&\n typeof payload.database === \"object\" &&\n !Array.isArray(payload.database));\n if (databaseFailure) {\n return { reason: \"The service encountered a database error.\", safetyRefusal: false };\n }\n const text = (key: string): string | null => {\n const value = payload[key];\n return typeof value === \"string\" && value.trim() ? value : null;\n };\n const message = text(\"error\") ?? text(\"message\");\n const detail = text(\"lastRetryableError\") ?? text(\"detail\");\n const safetyRefusal =\n payload.code === \"provider_safety_refusal\" ||\n [message, detail].some(\n (value) =>\n value !== null && /\\bthis request was blocked by our safety systems\\b/i.test(value),\n );\n if (safetyRefusal) {\n return {\n reason: `The model provider blocked this request.${detail || message ? ` ${detail ?? message}` : \"\"}`,\n safetyRefusal: true,\n };\n }\n // Spent automatic retries: name the model and the remedy instead of the\n // recorded wrapper plus raw provider text (still in the stored event).\n const recovery = parseProviderRecovery(payload);\n if (recovery && payload.recoveryExhausted === true) {\n return { reason: providerRecoveryExhaustedText(recovery), safetyRefusal: false };\n }\n return {\n reason:\n detail && detail !== message\n ? [humanizeFailureReason(message), humanizeFailureReason(detail)].filter(Boolean).join(\" \")\n : humanizeFailureReason(message),\n safetyRefusal: false,\n };\n}\n"],"mappings":"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","names":["text"]}
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-G76LSA76.js";
23
23
  import {
24
24
  formatBytes
25
- } from "./chunk-KZENYIA2.js";
25
+ } from "./chunk-BLL56F7R.js";
26
26
  import {
27
27
  STREAM_CLOSE_REASON_NORMAL,
28
28
  STREAM_KIND_BROWSER,
@@ -4720,4 +4720,4 @@ export {
4720
4720
  staleBrowserEndRetryDelayMs,
4721
4721
  BrowserViewer
4722
4722
  };
4723
- //# sourceMappingURL=chunk-ISN726VG.js.map
4723
+ //# sourceMappingURL=chunk-KZC6QRNR.js.map
@@ -0,0 +1,24 @@
1
+ "use client";
2
+
3
+ // src/lib/scrollbars.ts
4
+ var CLASSIC_SCROLLBARS_ATTRIBUTE = "data-og-scrollbars";
5
+ var marked = /* @__PURE__ */ new WeakSet();
6
+ function markClassicScrollbars(doc = globalThis.document) {
7
+ if (!doc?.documentElement || marked.has(doc)) return;
8
+ marked.add(doc);
9
+ const root = doc.documentElement;
10
+ root.removeAttribute(CLASSIC_SCROLLBARS_ATTRIBUTE);
11
+ const probe = doc.createElement("div");
12
+ probe.setAttribute("aria-hidden", "true");
13
+ probe.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden;scrollbar-width:auto;scrollbar-color:auto";
14
+ root.append(probe);
15
+ const classic = probe.offsetWidth - probe.clientWidth > 0;
16
+ probe.remove();
17
+ if (classic) root.setAttribute(CLASSIC_SCROLLBARS_ATTRIBUTE, "classic");
18
+ }
19
+
20
+ export {
21
+ CLASSIC_SCROLLBARS_ATTRIBUTE,
22
+ markClassicScrollbars
23
+ };
24
+ //# sourceMappingURL=chunk-MK2TQO4Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/scrollbars.ts"],"sourcesContent":["/**\n * Where a platform draws classic, always-visible scrollbars (Windows, and Linux\n * or macOS when set to always show them), Chromium paints arrow buttons on the\n * thin, colored scrollbars the stylesheet asks for with `scrollbar-width` and\n * `scrollbar-color`. This marks such documents with\n * `data-og-scrollbars=\"classic\"` on <html> so the stylesheet can use a slim\n * rounded thumb there instead. Overlay-scrollbar platforms keep their native\n * scrollbars.\n */\nexport const CLASSIC_SCROLLBARS_ATTRIBUTE = \"data-og-scrollbars\";\n\nconst marked = new WeakSet<Document>();\n\nexport function markClassicScrollbars(doc: Document | undefined = globalThis.document): void {\n if (!doc?.documentElement || marked.has(doc)) return;\n marked.add(doc);\n const root = doc.documentElement;\n // Probe with the platform default: the page's own scrollbar styles must not\n // decide what the platform draws.\n root.removeAttribute(CLASSIC_SCROLLBARS_ATTRIBUTE);\n const probe = doc.createElement(\"div\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n probe.style.cssText =\n \"position:absolute;top:-9999px;left:-9999px;width:100px;height:100px;\" +\n \"overflow:scroll;visibility:hidden;scrollbar-width:auto;scrollbar-color:auto\";\n root.append(probe);\n const classic = probe.offsetWidth - probe.clientWidth > 0;\n probe.remove();\n if (classic) root.setAttribute(CLASSIC_SCROLLBARS_ATTRIBUTE, \"classic\");\n}\n"],"mappings":";;;AASO,IAAM,+BAA+B;AAE5C,IAAM,SAAS,oBAAI,QAAkB;AAE9B,SAAS,sBAAsB,MAA4B,WAAW,UAAgB;AAC3F,MAAI,CAAC,KAAK,mBAAmB,OAAO,IAAI,GAAG,EAAG;AAC9C,SAAO,IAAI,GAAG;AACd,QAAM,OAAO,IAAI;AAGjB,OAAK,gBAAgB,4BAA4B;AACjD,QAAM,QAAQ,IAAI,cAAc,KAAK;AACrC,QAAM,aAAa,eAAe,MAAM;AACxC,QAAM,MAAM,UACV;AAEF,OAAK,OAAO,KAAK;AACjB,QAAM,UAAU,MAAM,cAAc,MAAM,cAAc;AACxD,QAAM,OAAO;AACb,MAAI,QAAS,MAAK,aAAa,8BAA8B,SAAS;AACxE;","names":[]}
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  formatBytes,
14
14
  formatRelativeTime
15
- } from "./chunk-KZENYIA2.js";
15
+ } from "./chunk-BLL56F7R.js";
16
16
  import {
17
17
  cn
18
18
  } from "./chunk-TXS65BB2.js";
@@ -2774,4 +2774,4 @@ export {
2774
2774
  EnrollmentDeviceFlow,
2775
2775
  EnrollmentConsent
2776
2776
  };
2777
- //# sourceMappingURL=chunk-TIHSXNBC.js.map
2777
+ //# sourceMappingURL=chunk-NKMYZFHA.js.map
@@ -11,6 +11,12 @@ import {
11
11
  import {
12
12
  TimelineAnnotationSourceRootContext
13
13
  } from "./chunk-2HVLQ26H.js";
14
+ import {
15
+ OpenGeniProvider
16
+ } from "./chunk-R5SBNG7S.js";
17
+ import {
18
+ markClassicScrollbars
19
+ } from "./chunk-MK2TQO4Y.js";
14
20
  import {
15
21
  loadPierreDiffs,
16
22
  pierreDiffsRevision,
@@ -27,7 +33,7 @@ import {
27
33
  useGoal,
28
34
  useNewConversation,
29
35
  useSessionConversation
30
- } from "./chunk-UXI7L7DL.js";
36
+ } from "./chunk-X5UVUIMF.js";
31
37
  import {
32
38
  buildTimeline,
33
39
  compactionFailureDetails,
@@ -35,10 +41,7 @@ import {
35
41
  compactionSkipTitle,
36
42
  groupTimeline,
37
43
  presentTurnFailureText
38
- } from "./chunk-QTSWNANQ.js";
39
- import {
40
- OpenGeniProvider
41
- } from "./chunk-R5SBNG7S.js";
44
+ } from "./chunk-2SFFYIH3.js";
42
45
  import {
43
46
  ActivityDisclosure,
44
47
  BodyNote,
@@ -62,7 +65,7 @@ import {
62
65
  useSecretsUi,
63
66
  useTimelineSearchNavigation,
64
67
  useTimelineSearchReveal
65
- } from "./chunk-5XEXTWEM.js";
68
+ } from "./chunk-WIUKB3LD.js";
66
69
  import {
67
70
  prefersReducedMotion
68
71
  } from "./chunk-OYQQJL3J.js";
@@ -148,7 +151,7 @@ import {
148
151
  unwrapMcpOutput,
149
152
  webSearchPresentation,
150
153
  writeStdinPresentation
151
- } from "./chunk-S5ZT4TBR.js";
154
+ } from "./chunk-ADWCLI4G.js";
152
155
  import {
153
156
  namedAgentTitle,
154
157
  workerRowTitleParts
@@ -191,13 +194,13 @@ import {
191
194
  StopButton,
192
195
  Surface,
193
196
  useChatComposerController
194
- } from "./chunk-PWCBMEV2.js";
197
+ } from "./chunk-2I6R3GCZ.js";
195
198
  import {
196
199
  ModelPolicyPicker
197
200
  } from "./chunk-XDA5QJE7.js";
198
201
  import {
199
202
  notifyObserver
200
- } from "./chunk-Q26UAIXI.js";
203
+ } from "./chunk-V5ZUJT2T.js";
201
204
  import {
202
205
  LightboxProvider,
203
206
  Tooltip,
@@ -222,7 +225,7 @@ import {
222
225
  providerRecoveryRetryingText,
223
226
  truncate,
224
227
  tryParseJson
225
- } from "./chunk-KZENYIA2.js";
228
+ } from "./chunk-BLL56F7R.js";
226
229
  import {
227
230
  cn
228
231
  } from "./chunk-TXS65BB2.js";
@@ -12465,6 +12468,9 @@ function useHostTheme(ref, options) {
12465
12468
  const preference = options.theme ?? "auto";
12466
12469
  const surface = options.surface ?? "host";
12467
12470
  const [state, setState] = useState24({ theme: preference === "auto" ? void 0 : preference, inherited: false, style: null });
12471
+ useIsomorphicLayoutEffect(() => {
12472
+ markClassicScrollbars(ref.current?.ownerDocument);
12473
+ }, [ref]);
12468
12474
  useIsomorphicLayoutEffect(() => {
12469
12475
  const element = ref.current;
12470
12476
  if (!element || typeof window === "undefined") return;
@@ -14055,4 +14061,4 @@ export {
14055
14061
  SessionCommands,
14056
14062
  StartupTimings
14057
14063
  };
14058
- //# sourceMappingURL=chunk-TL7M2WWQ.js.map
14064
+ //# sourceMappingURL=chunk-OVB5WIG5.js.map