@wix/web5-core 1.63.27 → 1.63.29

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.
@@ -11,6 +11,9 @@ const ERROR_PATTERNS = [{
11
11
  }, {
12
12
  pattern: /Error: conversation-403/i,
13
13
  type: 'conversation-403'
14
+ }, {
15
+ pattern: /Error: conversation-429/i,
16
+ type: 'conversation-429'
14
17
  }, {
15
18
  pattern: /Error: conversation-500/i,
16
19
  type: 'conversation-500'
@@ -57,6 +60,11 @@ class ErrorSectionDefinition {
57
60
  expected: {
58
61
  type: 'conversation-500'
59
62
  }
63
+ }, {
64
+ markdown: 'Error: conversation-429',
65
+ expected: {
66
+ type: 'conversation-429'
67
+ }
60
68
  }]);
61
69
  }
62
70
  parse(parts) {
@@ -1 +1 @@
1
- {"version":3,"names":["_parseUtils","require","ERROR_PATTERNS","pattern","type","ErrorSectionDefinition","constructor","_defineProperty2","default","markdown","expected","parse","parts","text","bodyText","test","exports"],"sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"sourcesContent":["import { bodyText } from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport type {\n ErrorCompProps,\n ErrorSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\nimport type { ConversationErrorType } from '../../errors/conversationErrorTypes';\n\ninterface ErrorPattern {\n pattern: RegExp;\n type: ConversationErrorType;\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n { pattern: /Error: conversation-404/i, type: 'conversation-404' },\n { pattern: /Error: conversation-403/i, type: 'conversation-403' },\n { pattern: /Error: conversation-500/i, type: 'conversation-500' },\n {\n pattern: /Error: conversation-generic-network-error/i,\n type: 'conversation-generic-network-error',\n },\n { pattern: /Error: conversation-timeout/i, type: 'conversation-timeout' },\n {\n pattern: /Error: conversation-partial-load/i,\n type: 'conversation-partial-load',\n },\n {\n pattern: /Error: conversation-streaming-error/i,\n type: 'conversation-streaming-error',\n },\n {\n pattern: /Error: conversation-llm-empty-response/i,\n type: 'conversation-llm-empty-response',\n },\n { pattern: /Error: history-load-error/i, type: 'history-load-error' },\n { pattern: /^error/i, type: 'conversation-llm-error-text' },\n { pattern: /Error/i, type: 'conversation-llm-error-text' },\n];\n\nexport class ErrorSectionDefinition\n implements SectionDefinition<ErrorSectionComponent>\n{\n sectionType = 'error' as const;\n patterns = ['t'];\n maxConsumedNodes = 1;\n\n defaults: ErrorCompProps = {\n type: 'conversation-llm-error-text',\n };\n\n fixtures: SectionFixture<ErrorCompProps>[] = [\n {\n markdown: 'Error: conversation-404',\n expected: { type: 'conversation-404' },\n },\n {\n markdown: 'Error: conversation-500',\n expected: { type: 'conversation-500' },\n },\n ];\n\n parse(parts: Part[]): ErrorCompProps | null {\n const text = bodyText(parts);\n if (!text) {\n return null;\n }\n\n for (const { pattern, type } of ERROR_PATTERNS) {\n if (pattern.test(text)) {\n return { type };\n }\n }\n\n return null;\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAeA,MAAMC,cAA8B,GAAG,CACrC;EAAEC,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EACED,OAAO,EAAE,4CAA4C;EACrDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,8BAA8B;EAAEC,IAAI,EAAE;AAAuB,CAAC,EACzE;EACED,OAAO,EAAE,mCAAmC;EAC5CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,sCAAsC;EAC/CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,yCAAyC;EAClDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,4BAA4B;EAAEC,IAAI,EAAE;AAAqB,CAAC,EACrE;EAAED,OAAO,EAAE,SAAS;EAAEC,IAAI,EAAE;AAA8B,CAAC,EAC3D;EAAED,OAAO,EAAE,QAAQ;EAAEC,IAAI,EAAE;AAA8B,CAAC,CAC3D;AAEM,MAAMC,sBAAsB,CAEnC;EAAAC,YAAA;IAAA,IAAAC,gBAAA,CAAAC,OAAA,uBACgB,OAAO;IAAA,IAAAD,gBAAA,CAAAC,OAAA,oBACV,CAAC,GAAG,CAAC;IAAA,IAAAD,gBAAA,CAAAC,OAAA,4BACG,CAAC;IAAA,IAAAD,gBAAA,CAAAC,OAAA,oBAEO;MACzBJ,IAAI,EAAE;IACR,CAAC;IAAA,IAAAG,gBAAA,CAAAC,OAAA,oBAE4C,CAC3C;MACEC,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEN,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEK,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEN,IAAI,EAAE;MAAmB;IACvC,CAAC,CACF;EAAA;EAEDO,KAAKA,CAACC,KAAa,EAAyB;IAC1C,MAAMC,IAAI,GAAG,IAAAC,oBAAQ,EAACF,KAAK,CAAC;IAC5B,IAAI,CAACC,IAAI,EAAE;MACT,OAAO,IAAI;IACb;IAEA,KAAK,MAAM;MAAEV,OAAO;MAAEC;IAAK,CAAC,IAAIF,cAAc,EAAE;MAC9C,IAAIC,OAAO,CAACY,IAAI,CAACF,IAAI,CAAC,EAAE;QACtB,OAAO;UAAET;QAAK,CAAC;MACjB;IACF;IAEA,OAAO,IAAI;EACb;AACF;AAACY,OAAA,CAAAX,sBAAA,GAAAA,sBAAA","ignoreList":[]}
1
+ {"version":3,"names":["_parseUtils","require","ERROR_PATTERNS","pattern","type","ErrorSectionDefinition","constructor","_defineProperty2","default","markdown","expected","parse","parts","text","bodyText","test","exports"],"sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"sourcesContent":["import { bodyText } from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport type {\n ErrorCompProps,\n ErrorSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\nimport type { ConversationErrorType } from '../../errors/conversationErrorTypes';\n\ninterface ErrorPattern {\n pattern: RegExp;\n type: ConversationErrorType;\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n { pattern: /Error: conversation-404/i, type: 'conversation-404' },\n { pattern: /Error: conversation-403/i, type: 'conversation-403' },\n { pattern: /Error: conversation-429/i, type: 'conversation-429' },\n { pattern: /Error: conversation-500/i, type: 'conversation-500' },\n {\n pattern: /Error: conversation-generic-network-error/i,\n type: 'conversation-generic-network-error',\n },\n { pattern: /Error: conversation-timeout/i, type: 'conversation-timeout' },\n {\n pattern: /Error: conversation-partial-load/i,\n type: 'conversation-partial-load',\n },\n {\n pattern: /Error: conversation-streaming-error/i,\n type: 'conversation-streaming-error',\n },\n {\n pattern: /Error: conversation-llm-empty-response/i,\n type: 'conversation-llm-empty-response',\n },\n { pattern: /Error: history-load-error/i, type: 'history-load-error' },\n { pattern: /^error/i, type: 'conversation-llm-error-text' },\n { pattern: /Error/i, type: 'conversation-llm-error-text' },\n];\n\nexport class ErrorSectionDefinition\n implements SectionDefinition<ErrorSectionComponent>\n{\n sectionType = 'error' as const;\n patterns = ['t'];\n maxConsumedNodes = 1;\n\n defaults: ErrorCompProps = {\n type: 'conversation-llm-error-text',\n };\n\n fixtures: SectionFixture<ErrorCompProps>[] = [\n {\n markdown: 'Error: conversation-404',\n expected: { type: 'conversation-404' },\n },\n {\n markdown: 'Error: conversation-500',\n expected: { type: 'conversation-500' },\n },\n {\n markdown: 'Error: conversation-429',\n expected: { type: 'conversation-429' },\n },\n ];\n\n parse(parts: Part[]): ErrorCompProps | null {\n const text = bodyText(parts);\n if (!text) {\n return null;\n }\n\n for (const { pattern, type } of ERROR_PATTERNS) {\n if (pattern.test(text)) {\n return { type };\n }\n }\n\n return null;\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAeA,MAAMC,cAA8B,GAAG,CACrC;EAAEC,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EACED,OAAO,EAAE,4CAA4C;EACrDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,8BAA8B;EAAEC,IAAI,EAAE;AAAuB,CAAC,EACzE;EACED,OAAO,EAAE,mCAAmC;EAC5CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,sCAAsC;EAC/CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,yCAAyC;EAClDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,4BAA4B;EAAEC,IAAI,EAAE;AAAqB,CAAC,EACrE;EAAED,OAAO,EAAE,SAAS;EAAEC,IAAI,EAAE;AAA8B,CAAC,EAC3D;EAAED,OAAO,EAAE,QAAQ;EAAEC,IAAI,EAAE;AAA8B,CAAC,CAC3D;AAEM,MAAMC,sBAAsB,CAEnC;EAAAC,YAAA;IAAA,IAAAC,gBAAA,CAAAC,OAAA,uBACgB,OAAO;IAAA,IAAAD,gBAAA,CAAAC,OAAA,oBACV,CAAC,GAAG,CAAC;IAAA,IAAAD,gBAAA,CAAAC,OAAA,4BACG,CAAC;IAAA,IAAAD,gBAAA,CAAAC,OAAA,oBAEO;MACzBJ,IAAI,EAAE;IACR,CAAC;IAAA,IAAAG,gBAAA,CAAAC,OAAA,oBAE4C,CAC3C;MACEC,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEN,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEK,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEN,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEK,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEN,IAAI,EAAE;MAAmB;IACvC,CAAC,CACF;EAAA;EAEDO,KAAKA,CAACC,KAAa,EAAyB;IAC1C,MAAMC,IAAI,GAAG,IAAAC,oBAAQ,EAACF,KAAK,CAAC;IAC5B,IAAI,CAACC,IAAI,EAAE;MACT,OAAO,IAAI;IACb;IAEA,KAAK,MAAM;MAAEV,OAAO;MAAEC;IAAK,CAAC,IAAIF,cAAc,EAAE;MAC9C,IAAIC,OAAO,CAACY,IAAI,CAACF,IAAI,CAAC,EAAE;QACtB,OAAO;UAAET;QAAK,CAAC;MACjB;IACF;IAEA,OAAO,IAAI;EACb;AACF;AAACY,OAAA,CAAAX,sBAAA,GAAAA,sBAAA","ignoreList":[]}
@@ -43,6 +43,19 @@ var _jsxFileName = "/home/builduser/work/c2b6ca0b3fa984ee/packages/web5-core/dis
43
43
  */
44
44
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
45
45
  const ImageSlotContext = /*#__PURE__*/(0, _react.createContext)(null);
46
+
47
+ /**
48
+ * Module-level so `read` returns a STABLE reference for a slot nobody has
49
+ * published yet. `useImageSlot` reads this store through
50
+ * `useSyncExternalStore`, which compares snapshots with `Object.is` on every
51
+ * render — a fresh `{ status: 'pending' }` per call reads as "the store
52
+ * changed", and React re-renders until it throws "Maximum update depth
53
+ * exceeded". Every slot is pending from mount until its batch answers, so a
54
+ * literal here takes down every section that declares one.
55
+ */
56
+ const PENDING = {
57
+ status: 'pending'
58
+ };
46
59
  /**
47
60
  * Mounted once per section by the host's section wrapper, so every section in
48
61
  * every client package gets a collector without opting in.
@@ -160,9 +173,7 @@ const ImageSlotProvider = ({
160
173
  });
161
174
  }
162
175
  }, [flush]);
163
- const read = (0, _react.useCallback)(slotId => statesRef.current[slotId] ?? {
164
- status: 'pending'
165
- }, []);
176
+ const read = (0, _react.useCallback)(slotId => statesRef.current[slotId] ?? PENDING, []);
166
177
  const subscribe = (0, _react.useCallback)((slotId, onChange) => {
167
178
  let set = listenersRef.current.get(slotId);
168
179
  if (!set) {
@@ -192,7 +203,7 @@ const ImageSlotProvider = ({
192
203
  __self: void 0,
193
204
  __source: {
194
205
  fileName: _jsxFileName,
195
- lineNumber: 236,
206
+ lineNumber: 246,
196
207
  columnNumber: 5
197
208
  }
198
209
  }, children);
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_ComponentDependenciesContext","_diagnosticTypes","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ImageSlotContext","createContext","ImageSlotProvider","sectionId","children","deps","useOptionalComponentDependencies","resolve","resolveImageSet","statesRef","useRef","listenersRef","Map","pendingRef","sentRef","Set","flushScheduled","aliveRef","useEffect","current","publish","useCallback","next","changed","id","state","entries","push","_listenersRef$current","forEach","fn","markUnavailable","batch","fromEntries","map","s","status","flush","values","filter","clear","length","add","res","bySlotId","slots","slotId","req","got","imageUrl","slot","err","reportDiagnostic","DIAGNOSTIC_TYPES","IMAGE_RESOLUTION_FAILED","Error","message","String","declare","queueMicrotask","read","subscribe","onChange","_set","delete","size","api","useMemo","createElement","Provider","value","__self","__source","fileName","lineNumber","columnNumber","exports","useImageSlotCollector","useContext"],"sources":["../../../src/context/ImageSlotContext.tsx"],"sourcesContent":["/**\n * The section-scoped image slot collector.\n *\n * A section declares the holes in its layout; it never makes a request. This\n * gathers every declaration made inside one section's subtree, fires ONE\n * `ResolveImageSet` through the injected port, and hands each declaration its\n * answer back by `slotId`. Sections stay ignorant of each other — no section\n * imports another, no ordering rules, no exclusion lists threaded through\n * props — and the network still sees the joint solve that distinctness depends\n * on.\n *\n * WHY THE BOUNDARY IS THE SECTION\n * -------------------------------\n * The resolver solves a maximum-weight one-to-one assignment across everything\n * in one request, so distinctness and palette cohesion are properties of that\n * solve and stop at its edge. Drawing the boundary at the page would buy\n * cross-section distinctness at the cost of making every section's pictures\n * wait on the slowest declaration on the page; drawing it at the section keeps\n * each section independent and accepts that two sections may land on the same\n * photograph. The most visible case — four identical photos in one grid — is\n * still prevented for free, because those slots share a request.\n *\n * WHY THERE IS NO READINESS POLICY\n * --------------------------------\n * There is nothing to wait for. A section component is never constructed from\n * partial markdown: a declared-but-unstreamed section is a `PageSection` with\n * `isSkeleton: true` and `component: null`, and the real element is built only\n * once its body has finished streaming. So a section's props are final the\n * moment it exists, and the flush is simply \"after this section's first render\n * commit\" — one effect, not a scheduler.\n *\n * The same fact bounds the win honestly: because only a *mounted* section\n * declares, no section can ask for a picture before its own body has streamed,\n * including a background whose subject needed nothing from that body.\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useOptionalComponentDependencies } from './ComponentDependenciesContext';\nimport { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes';\nimport type {\n ImageSlotRequest,\n SlotState,\n} from '../image/imageSlotTypes';\n\nexport interface ImageSlotCollector {\n /** Register a slot for this batch. Idempotent per content-derived id. */\n declare: (slot: ImageSlotRequest) => void;\n /** Current state for one slot. Not reactive alone — pair with `subscribe`. */\n read: (slotId: string) => SlotState;\n /** Notify only when THIS slot changes. Returns an unsubscribe. */\n subscribe: (slotId: string, onChange: () => void) => () => void;\n}\n\nconst ImageSlotContext = createContext<ImageSlotCollector | null>(null);\n\nexport interface ImageSlotProviderProps {\n /** Identifies the section in diagnostics. */\n sectionId: string;\n children: React.ReactNode;\n}\n\n/**\n * Mounted once per section by the host's section wrapper, so every section in\n * every client package gets a collector without opting in.\n */\nexport const ImageSlotProvider: React.FC<ImageSlotProviderProps> = ({\n sectionId,\n children,\n}) => {\n // Optional on purpose: this is mounted by the host around EVERY section, so\n // it sits above trees that may have no dependencies configured at all (a\n // layout test, a story). Throwing there would make the image feature's\n // provider a global requirement for rendering any section.\n const deps = useOptionalComponentDependencies();\n const resolve = deps?.resolveImageSet;\n\n /**\n * Slot state lives in a ref, NOT in React state, and the context value never\n * changes. Holding it in state put it inside the provider's value, so every\n * resolution produced a new value and re-rendered every consumer in the\n * section — free at one slot, twelve re-renders per resolution in a\n * twelve-card grid, which is exactly the shape this boundary exists to serve.\n * Consumers now subscribe to their own id and nothing else.\n */\n const statesRef = useRef<Record<string, SlotState>>({});\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Declarations arriving during this commit. A ref, not state: collecting a\n // declaration must not itself cause a render, or every hook that declares\n // would re-render every sibling before the batch is even sent.\n const pendingRef = useRef<Map<string, ImageSlotRequest>>(new Map());\n // Ids already sent. A re-render re-declares the same content-derived id, and\n // that must be a no-op rather than a second request.\n const sentRef = useRef<Set<string>>(new Set());\n const flushScheduled = useRef(false);\n const aliveRef = useRef(true);\n\n useEffect(() => {\n aliveRef.current = true;\n return () => {\n aliveRef.current = false;\n };\n }, []);\n\n const publish = useCallback((next: Record<string, SlotState>) => {\n const changed: string[] = [];\n for (const [id, state] of Object.entries(next)) {\n if (statesRef.current[id] !== state) {\n statesRef.current[id] = state;\n changed.push(id);\n }\n }\n for (const id of changed) {\n listenersRef.current.get(id)?.forEach((fn) => fn());\n }\n }, []);\n\n const markUnavailable = useCallback(\n (batch: ImageSlotRequest[]) => {\n if (!aliveRef.current) {\n return;\n }\n publish(\n Object.fromEntries(\n batch.map((s) => [s.id, { status: 'unavailable' } as SlotState]),\n ),\n );\n },\n [publish],\n );\n\n const flush = useCallback(async () => {\n flushScheduled.current = false;\n\n const batch = [...pendingRef.current.values()].filter(\n (s) => !sentRef.current.has(s.id),\n );\n pendingRef.current.clear();\n if (batch.length === 0) {\n return;\n }\n batch.forEach((s) => sentRef.current.add(s.id));\n\n // No port means the host has not injected a resolver. Fail the batch closed\n // rather than silently leaving slots pending forever.\n if (!resolve) {\n markUnavailable(batch);\n return;\n }\n\n try {\n const res = await resolve(batch);\n if (!aliveRef.current) {\n return;\n }\n const bySlotId = new Map(res.slots.map((s) => [s.slotId, s]));\n const next: Record<string, SlotState> = {};\n for (const req of batch) {\n const got = bySlotId.get(req.id);\n // A slot the resolver could not fill comes back with a null url. That\n // is `unavailable` to a layout, not a resolved picture.\n next[req.id] =\n got && got.imageUrl\n ? { status: 'resolved', slot: got }\n : { status: 'unavailable' };\n }\n publish(next);\n } catch (err) {\n // Failure is contained to this section: one bad request costs this\n // section its pictures and nothing else on the page.\n deps?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED,\n sectionId,\n `ResolveImageSet failed for ${batch.length} slot(s): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n markUnavailable(batch);\n }\n }, [resolve, deps, sectionId, publish, markUnavailable]);\n\n const declare = useCallback(\n (slot: ImageSlotRequest) => {\n if (sentRef.current.has(slot.id)) {\n return;\n }\n pendingRef.current.set(slot.id, slot);\n // Flush on a microtask, so every declaration made during this commit —\n // the background, the cards, an inline image — lands in the same batch.\n if (!flushScheduled.current) {\n flushScheduled.current = true;\n queueMicrotask(() => {\n void flush();\n });\n }\n },\n [flush],\n );\n\n const read = useCallback(\n (slotId: string): SlotState =>\n statesRef.current[slotId] ?? { status: 'pending' },\n [],\n );\n\n const subscribe = useCallback((slotId: string, onChange: () => void) => {\n let set = listenersRef.current.get(slotId);\n if (!set) {\n set = new Set();\n listenersRef.current.set(slotId, set);\n }\n set.add(onChange);\n return () => {\n set?.delete(onChange);\n if (set && set.size === 0) {\n listenersRef.current.delete(slotId);\n }\n };\n }, []);\n\n // Stable for the provider's lifetime: every member is a `useCallback` with no\n // reactive deps, so mounting this around a section costs its consumers\n // nothing after first render.\n const api = useMemo<ImageSlotCollector>(\n () => ({ declare, read, subscribe }),\n [declare, read, subscribe],\n );\n\n return (\n <ImageSlotContext.Provider value={api}>{children}</ImageSlotContext.Provider>\n );\n};\n\n/**\n * Null when no provider is mounted above — a host that has not adopted the\n * section wrapper's collector. `useImageSlot` handles that by resolving each\n * slot on its own, so a section still gets its picture and only loses batching\n * with its siblings.\n */\nexport const useImageSlotCollector = (): ImageSlotCollector | null =>\n useContext(ImageSlotContext);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_ComponentDependenciesContext","_diagnosticTypes","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ImageSlotContext","createContext","PENDING","status","ImageSlotProvider","sectionId","children","deps","useOptionalComponentDependencies","resolve","resolveImageSet","statesRef","useRef","listenersRef","Map","pendingRef","sentRef","Set","flushScheduled","aliveRef","useEffect","current","publish","useCallback","next","changed","id","state","entries","push","_listenersRef$current","forEach","fn","markUnavailable","batch","fromEntries","map","s","flush","values","filter","clear","length","add","res","bySlotId","slots","slotId","req","got","imageUrl","slot","err","reportDiagnostic","DIAGNOSTIC_TYPES","IMAGE_RESOLUTION_FAILED","Error","message","String","declare","queueMicrotask","read","subscribe","onChange","_set","delete","size","api","useMemo","createElement","Provider","value","__self","__source","fileName","lineNumber","columnNumber","exports","useImageSlotCollector","useContext"],"sources":["../../../src/context/ImageSlotContext.tsx"],"sourcesContent":["/**\n * The section-scoped image slot collector.\n *\n * A section declares the holes in its layout; it never makes a request. This\n * gathers every declaration made inside one section's subtree, fires ONE\n * `ResolveImageSet` through the injected port, and hands each declaration its\n * answer back by `slotId`. Sections stay ignorant of each other — no section\n * imports another, no ordering rules, no exclusion lists threaded through\n * props — and the network still sees the joint solve that distinctness depends\n * on.\n *\n * WHY THE BOUNDARY IS THE SECTION\n * -------------------------------\n * The resolver solves a maximum-weight one-to-one assignment across everything\n * in one request, so distinctness and palette cohesion are properties of that\n * solve and stop at its edge. Drawing the boundary at the page would buy\n * cross-section distinctness at the cost of making every section's pictures\n * wait on the slowest declaration on the page; drawing it at the section keeps\n * each section independent and accepts that two sections may land on the same\n * photograph. The most visible case — four identical photos in one grid — is\n * still prevented for free, because those slots share a request.\n *\n * WHY THERE IS NO READINESS POLICY\n * --------------------------------\n * There is nothing to wait for. A section component is never constructed from\n * partial markdown: a declared-but-unstreamed section is a `PageSection` with\n * `isSkeleton: true` and `component: null`, and the real element is built only\n * once its body has finished streaming. So a section's props are final the\n * moment it exists, and the flush is simply \"after this section's first render\n * commit\" — one effect, not a scheduler.\n *\n * The same fact bounds the win honestly: because only a *mounted* section\n * declares, no section can ask for a picture before its own body has streamed,\n * including a background whose subject needed nothing from that body.\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useOptionalComponentDependencies } from './ComponentDependenciesContext';\nimport { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes';\nimport type {\n ImageSlotRequest,\n SlotState,\n} from '../image/imageSlotTypes';\n\nexport interface ImageSlotCollector {\n /** Register a slot for this batch. Idempotent per content-derived id. */\n declare: (slot: ImageSlotRequest) => void;\n /** Current state for one slot. Not reactive alone — pair with `subscribe`. */\n read: (slotId: string) => SlotState;\n /** Notify only when THIS slot changes. Returns an unsubscribe. */\n subscribe: (slotId: string, onChange: () => void) => () => void;\n}\n\nconst ImageSlotContext = createContext<ImageSlotCollector | null>(null);\n\n/**\n * Module-level so `read` returns a STABLE reference for a slot nobody has\n * published yet. `useImageSlot` reads this store through\n * `useSyncExternalStore`, which compares snapshots with `Object.is` on every\n * render — a fresh `{ status: 'pending' }` per call reads as \"the store\n * changed\", and React re-renders until it throws \"Maximum update depth\n * exceeded\". Every slot is pending from mount until its batch answers, so a\n * literal here takes down every section that declares one.\n */\nconst PENDING: SlotState = { status: 'pending' };\n\nexport interface ImageSlotProviderProps {\n /** Identifies the section in diagnostics. */\n sectionId: string;\n children: React.ReactNode;\n}\n\n/**\n * Mounted once per section by the host's section wrapper, so every section in\n * every client package gets a collector without opting in.\n */\nexport const ImageSlotProvider: React.FC<ImageSlotProviderProps> = ({\n sectionId,\n children,\n}) => {\n // Optional on purpose: this is mounted by the host around EVERY section, so\n // it sits above trees that may have no dependencies configured at all (a\n // layout test, a story). Throwing there would make the image feature's\n // provider a global requirement for rendering any section.\n const deps = useOptionalComponentDependencies();\n const resolve = deps?.resolveImageSet;\n\n /**\n * Slot state lives in a ref, NOT in React state, and the context value never\n * changes. Holding it in state put it inside the provider's value, so every\n * resolution produced a new value and re-rendered every consumer in the\n * section — free at one slot, twelve re-renders per resolution in a\n * twelve-card grid, which is exactly the shape this boundary exists to serve.\n * Consumers now subscribe to their own id and nothing else.\n */\n const statesRef = useRef<Record<string, SlotState>>({});\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Declarations arriving during this commit. A ref, not state: collecting a\n // declaration must not itself cause a render, or every hook that declares\n // would re-render every sibling before the batch is even sent.\n const pendingRef = useRef<Map<string, ImageSlotRequest>>(new Map());\n // Ids already sent. A re-render re-declares the same content-derived id, and\n // that must be a no-op rather than a second request.\n const sentRef = useRef<Set<string>>(new Set());\n const flushScheduled = useRef(false);\n const aliveRef = useRef(true);\n\n useEffect(() => {\n aliveRef.current = true;\n return () => {\n aliveRef.current = false;\n };\n }, []);\n\n const publish = useCallback((next: Record<string, SlotState>) => {\n const changed: string[] = [];\n for (const [id, state] of Object.entries(next)) {\n if (statesRef.current[id] !== state) {\n statesRef.current[id] = state;\n changed.push(id);\n }\n }\n for (const id of changed) {\n listenersRef.current.get(id)?.forEach((fn) => fn());\n }\n }, []);\n\n const markUnavailable = useCallback(\n (batch: ImageSlotRequest[]) => {\n if (!aliveRef.current) {\n return;\n }\n publish(\n Object.fromEntries(\n batch.map((s) => [s.id, { status: 'unavailable' } as SlotState]),\n ),\n );\n },\n [publish],\n );\n\n const flush = useCallback(async () => {\n flushScheduled.current = false;\n\n const batch = [...pendingRef.current.values()].filter(\n (s) => !sentRef.current.has(s.id),\n );\n pendingRef.current.clear();\n if (batch.length === 0) {\n return;\n }\n batch.forEach((s) => sentRef.current.add(s.id));\n\n // No port means the host has not injected a resolver. Fail the batch closed\n // rather than silently leaving slots pending forever.\n if (!resolve) {\n markUnavailable(batch);\n return;\n }\n\n try {\n const res = await resolve(batch);\n if (!aliveRef.current) {\n return;\n }\n const bySlotId = new Map(res.slots.map((s) => [s.slotId, s]));\n const next: Record<string, SlotState> = {};\n for (const req of batch) {\n const got = bySlotId.get(req.id);\n // A slot the resolver could not fill comes back with a null url. That\n // is `unavailable` to a layout, not a resolved picture.\n next[req.id] =\n got && got.imageUrl\n ? { status: 'resolved', slot: got }\n : { status: 'unavailable' };\n }\n publish(next);\n } catch (err) {\n // Failure is contained to this section: one bad request costs this\n // section its pictures and nothing else on the page.\n deps?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED,\n sectionId,\n `ResolveImageSet failed for ${batch.length} slot(s): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n markUnavailable(batch);\n }\n }, [resolve, deps, sectionId, publish, markUnavailable]);\n\n const declare = useCallback(\n (slot: ImageSlotRequest) => {\n if (sentRef.current.has(slot.id)) {\n return;\n }\n pendingRef.current.set(slot.id, slot);\n // Flush on a microtask, so every declaration made during this commit —\n // the background, the cards, an inline image — lands in the same batch.\n if (!flushScheduled.current) {\n flushScheduled.current = true;\n queueMicrotask(() => {\n void flush();\n });\n }\n },\n [flush],\n );\n\n const read = useCallback(\n (slotId: string): SlotState => statesRef.current[slotId] ?? PENDING,\n [],\n );\n\n const subscribe = useCallback((slotId: string, onChange: () => void) => {\n let set = listenersRef.current.get(slotId);\n if (!set) {\n set = new Set();\n listenersRef.current.set(slotId, set);\n }\n set.add(onChange);\n return () => {\n set?.delete(onChange);\n if (set && set.size === 0) {\n listenersRef.current.delete(slotId);\n }\n };\n }, []);\n\n // Stable for the provider's lifetime: every member is a `useCallback` with no\n // reactive deps, so mounting this around a section costs its consumers\n // nothing after first render.\n const api = useMemo<ImageSlotCollector>(\n () => ({ declare, read, subscribe }),\n [declare, read, subscribe],\n );\n\n return (\n <ImageSlotContext.Provider value={api}>{children}</ImageSlotContext.Provider>\n );\n};\n\n/**\n * Null when no provider is mounted above — a host that has not adopted the\n * section wrapper's collector. `useImageSlot` handles that by resolving each\n * slot on its own, so a section still gets its picture and only loses batching\n * with its siblings.\n */\nexport const useImageSlotCollector = (): ImageSlotCollector | null =>\n useContext(ImageSlotContext);\n"],"mappings":"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","ignoreList":[]}
@@ -17,6 +17,7 @@ exports.getErrorTypeFromStatus = exports.createErrorMarkdown = exports.STREAMING
17
17
  const ERROR_MARKDOWN = exports.ERROR_MARKDOWN = {
18
18
  'conversation-404': 'Error: conversation-404',
19
19
  'conversation-403': 'Error: conversation-403',
20
+ 'conversation-429': 'Error: conversation-429',
20
21
  'conversation-500': 'Error: conversation-500',
21
22
  'conversation-generic-network-error': 'Error: conversation-generic-network-error',
22
23
  'conversation-timeout': 'Error: conversation-timeout',
@@ -35,6 +36,9 @@ const getErrorTypeFromStatus = status => {
35
36
  if (status === 403) {
36
37
  return 'conversation-403';
37
38
  }
39
+ if (status === 429) {
40
+ return 'conversation-429';
41
+ }
38
42
  if (status >= 500) {
39
43
  return 'conversation-500';
40
44
  }
@@ -1 +1 @@
1
- {"version":3,"names":["ERROR_MARKDOWN","exports","getErrorTypeFromStatus","status","createErrorMarkdown","type","STREAMING_TIMEOUT_MS"],"sources":["../../../src/errors/conversationErrorTypes.ts"],"sourcesContent":["/**\n * Conversation Error Types\n *\n * Canonical error type definitions and utilities for the error handling pipeline.\n * Maps HTTP status codes and error conditions to typed error identifiers.\n *\n * Prefix conventions:\n * conversation- → errors during conversation streaming flow\n * history- → errors during conversation history loading\n */\n\nexport type ConversationErrorType =\n | 'conversation-llm-error-text'\n | 'conversation-llm-empty-response'\n | 'conversation-500'\n | 'conversation-generic-network-error'\n | 'conversation-timeout'\n | 'conversation-streaming-error'\n | 'conversation-404'\n | 'conversation-403'\n | 'conversation-partial-load'\n | 'history-load-error';\n\n/** Error markdown strings that ErrorSectionDefinition recognizes */\nexport const ERROR_MARKDOWN: Record<ConversationErrorType, string> = {\n 'conversation-404': 'Error: conversation-404',\n 'conversation-403': 'Error: conversation-403',\n 'conversation-500': 'Error: conversation-500',\n 'conversation-generic-network-error':\n 'Error: conversation-generic-network-error',\n 'conversation-timeout': 'Error: conversation-timeout',\n 'conversation-streaming-error': 'Error: conversation-streaming-error',\n 'conversation-partial-load': 'Error: conversation-partial-load',\n 'conversation-llm-empty-response': 'Error: conversation-llm-empty-response',\n 'conversation-llm-error-text': 'Error',\n 'history-load-error': 'Error: history-load-error',\n};\n\n/** Maps HTTP status code to error type */\nexport const getErrorTypeFromStatus = (\n status: number,\n): ConversationErrorType => {\n if (status === 404) {\n return 'conversation-404';\n }\n if (status === 403) {\n return 'conversation-403';\n }\n if (status >= 500) {\n return 'conversation-500';\n }\n if (status >= 400) {\n return 'conversation-generic-network-error';\n }\n return 'conversation-llm-error-text';\n};\n\n/** Creates error markdown string for the given error type */\nexport const createErrorMarkdown = (type: ConversationErrorType): string => {\n return ERROR_MARKDOWN[type] || ERROR_MARKDOWN['conversation-llm-error-text'];\n};\n\n/** Streaming timeout in milliseconds (60 seconds) */\nexport const STREAMING_TIMEOUT_MS = 60000;\n"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAcA;AACO,MAAMA,cAAqD,GAAAC,OAAA,CAAAD,cAAA,GAAG;EACnE,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,oCAAoC,EAClC,2CAA2C;EAC7C,sBAAsB,EAAE,6BAA6B;EACrD,8BAA8B,EAAE,qCAAqC;EACrE,2BAA2B,EAAE,kCAAkC;EAC/D,iCAAiC,EAAE,wCAAwC;EAC3E,6BAA6B,EAAE,OAAO;EACtC,oBAAoB,EAAE;AACxB,CAAC;;AAED;AACO,MAAME,sBAAsB,GACjCC,MAAc,IACY;EAC1B,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,oCAAoC;EAC7C;EACA,OAAO,6BAA6B;AACtC,CAAC;;AAED;AAAAF,OAAA,CAAAC,sBAAA,GAAAA,sBAAA;AACO,MAAME,mBAAmB,GAAIC,IAA2B,IAAa;EAC1E,OAAOL,cAAc,CAACK,IAAI,CAAC,IAAIL,cAAc,CAAC,6BAA6B,CAAC;AAC9E,CAAC;;AAED;AAAAC,OAAA,CAAAG,mBAAA,GAAAA,mBAAA;AACO,MAAME,oBAAoB,GAAAL,OAAA,CAAAK,oBAAA,GAAG,KAAK","ignoreList":[]}
1
+ {"version":3,"names":["ERROR_MARKDOWN","exports","getErrorTypeFromStatus","status","createErrorMarkdown","type","STREAMING_TIMEOUT_MS"],"sources":["../../../src/errors/conversationErrorTypes.ts"],"sourcesContent":["/**\n * Conversation Error Types\n *\n * Canonical error type definitions and utilities for the error handling pipeline.\n * Maps HTTP status codes and error conditions to typed error identifiers.\n *\n * Prefix conventions:\n * conversation- → errors during conversation streaming flow\n * history- → errors during conversation history loading\n */\n\nexport type ConversationErrorType =\n | 'conversation-llm-error-text'\n | 'conversation-llm-empty-response'\n | 'conversation-500'\n | 'conversation-generic-network-error'\n | 'conversation-timeout'\n | 'conversation-streaming-error'\n | 'conversation-404'\n | 'conversation-403'\n | 'conversation-429'\n | 'conversation-partial-load'\n | 'history-load-error';\n\n/** Error markdown strings that ErrorSectionDefinition recognizes */\nexport const ERROR_MARKDOWN: Record<ConversationErrorType, string> = {\n 'conversation-404': 'Error: conversation-404',\n 'conversation-403': 'Error: conversation-403',\n 'conversation-429': 'Error: conversation-429',\n 'conversation-500': 'Error: conversation-500',\n 'conversation-generic-network-error':\n 'Error: conversation-generic-network-error',\n 'conversation-timeout': 'Error: conversation-timeout',\n 'conversation-streaming-error': 'Error: conversation-streaming-error',\n 'conversation-partial-load': 'Error: conversation-partial-load',\n 'conversation-llm-empty-response': 'Error: conversation-llm-empty-response',\n 'conversation-llm-error-text': 'Error',\n 'history-load-error': 'Error: history-load-error',\n};\n\n/** Maps HTTP status code to error type */\nexport const getErrorTypeFromStatus = (\n status: number,\n): ConversationErrorType => {\n if (status === 404) {\n return 'conversation-404';\n }\n if (status === 403) {\n return 'conversation-403';\n }\n if (status === 429) {\n return 'conversation-429';\n }\n if (status >= 500) {\n return 'conversation-500';\n }\n if (status >= 400) {\n return 'conversation-generic-network-error';\n }\n return 'conversation-llm-error-text';\n};\n\n/** Creates error markdown string for the given error type */\nexport const createErrorMarkdown = (type: ConversationErrorType): string => {\n return ERROR_MARKDOWN[type] || ERROR_MARKDOWN['conversation-llm-error-text'];\n};\n\n/** Streaming timeout in milliseconds (60 seconds) */\nexport const STREAMING_TIMEOUT_MS = 60000;\n"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAeA;AACO,MAAMA,cAAqD,GAAAC,OAAA,CAAAD,cAAA,GAAG;EACnE,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,oCAAoC,EAClC,2CAA2C;EAC7C,sBAAsB,EAAE,6BAA6B;EACrD,8BAA8B,EAAE,qCAAqC;EACrE,2BAA2B,EAAE,kCAAkC;EAC/D,iCAAiC,EAAE,wCAAwC;EAC3E,6BAA6B,EAAE,OAAO;EACtC,oBAAoB,EAAE;AACxB,CAAC;;AAED;AACO,MAAME,sBAAsB,GACjCC,MAAc,IACY;EAC1B,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,oCAAoC;EAC7C;EACA,OAAO,6BAA6B;AACtC,CAAC;;AAED;AAAAF,OAAA,CAAAC,sBAAA,GAAAA,sBAAA;AACO,MAAME,mBAAmB,GAAIC,IAA2B,IAAa;EAC1E,OAAOL,cAAc,CAACK,IAAI,CAAC,IAAIL,cAAc,CAAC,6BAA6B,CAAC;AAC9E,CAAC;;AAED;AAAAC,OAAA,CAAAG,mBAAA,GAAAA,mBAAA;AACO,MAAME,oBAAoB,GAAAL,OAAA,CAAAK,oBAAA,GAAG,KAAK","ignoreList":[]}
@@ -55,6 +55,14 @@ const DEFAULT_ERROR_TEMPLATES = exports.DEFAULT_ERROR_TEMPLATES = {
55
55
  showChips: true,
56
56
  chipsLabel: 'Some ideas to get you started:'
57
57
  },
58
+ 'conversation-429': {
59
+ iconType: 'quota-exceeded',
60
+ title: 'This service is currently out of quota.\nPlease try again later.',
61
+ buttons: [{
62
+ text: 'Contact Us',
63
+ variant: 'link'
64
+ }]
65
+ },
58
66
  'conversation-partial-load': {
59
67
  iconType: 'partial-load',
60
68
  title: 'Some content didn\u2019t load',
@@ -1 +1 @@
1
- {"version":3,"names":["retryAndContactButtons","text","action","variant","DEFAULT_ERROR_TEMPLATES","exports","title","showChips","iconType","buttons","chipsLabel","resolveErrorTemplate","type","overrides","templates"],"sources":["../../../src/errors/errorTemplates.ts"],"sourcesContent":["import type { ConversationErrorType } from './conversationErrorTypes';\n\n/** Action identifiers for error template buttons — resolved to callbacks by the rendering component */\nexport type ErrorActionType = 'retry' | 'newConversation' | 'reload';\n\n/** Icon identifiers for error templates — resolved to SVG components by the rendering component */\nexport type ErrorIconType =\n | 'error-500'\n | 'timeout'\n | 'streaming-error'\n | 'not-found'\n | 'forbidden'\n | 'partial-load';\n\nexport interface ErrorTemplateButton {\n text: string;\n /** URL for navigation (renders as a link) */\n href?: string;\n /** Action identifier — component resolves to a callback */\n action?: ErrorActionType;\n variant: 'cta' | 'link';\n}\n\nexport interface ErrorTemplate {\n title: string;\n subtitle?: string;\n /** Icon identifier — component resolves to an SVG */\n iconType?: ErrorIconType;\n buttons?: ErrorTemplateButton[];\n showChips?: boolean;\n chipsLabel?: string;\n}\n\nexport type ErrorTemplateOverrides = Partial<\n Record<ConversationErrorType, ErrorTemplate>\n>;\n\nconst retryAndContactButtons: ErrorTemplateButton[] = [\n { text: 'Try Again', action: 'retry', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n];\n\nexport const DEFAULT_ERROR_TEMPLATES: Record<\n ConversationErrorType,\n ErrorTemplate\n> = {\n 'conversation-llm-error-text': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-llm-empty-response': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-500': {\n iconType: 'error-500',\n title: \"This page isn't available right now.\",\n buttons: retryAndContactButtons,\n },\n 'conversation-generic-network-error': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-timeout': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-streaming-error': {\n iconType: 'streaming-error',\n title: 'The connection dropped. Please try again.',\n buttons: retryAndContactButtons,\n },\n 'conversation-404': {\n iconType: 'not-found',\n title: 'Page not found.\\nIt happens! Let\\u2019s get you back on track',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-403': {\n iconType: 'forbidden',\n title:\n 'Welcome back.\\nFor privacy, we couldn\\u2019t restore previous content. Ask anything to continue.',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-partial-load': {\n iconType: 'partial-load',\n title: 'Some content didn\\u2019t load',\n buttons: retryAndContactButtons,\n },\n 'history-load-error': {\n iconType: 'streaming-error',\n title: 'We couldn\\u2019t load this conversation.',\n buttons: [\n { text: 'New Conversation', action: 'newConversation', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n ],\n },\n};\n\n/** Resolves the error template for a given type, merging client overrides on top of defaults */\nexport const resolveErrorTemplate = (\n type: string,\n overrides?: ErrorTemplateOverrides,\n): ErrorTemplate => {\n const templates = overrides\n ? { ...DEFAULT_ERROR_TEMPLATES, ...overrides }\n : DEFAULT_ERROR_TEMPLATES;\n return (\n templates[type as ConversationErrorType] ??\n templates['conversation-llm-error-text']\n );\n};\n"],"mappings":";;;;AAEA;;AAGA;;AAgCA,MAAMA,sBAA6C,GAAG,CACpD;EAAEC,IAAI,EAAE,WAAW;EAAEC,MAAM,EAAE,OAAO;EAAEC,OAAO,EAAE;AAAM,CAAC,EACtD;EAAEF,IAAI,EAAE,YAAY;EAAEE,OAAO,EAAE;AAAO,CAAC,CACxC;AAEM,MAAMC,uBAGZ,GAAAC,OAAA,CAAAD,uBAAA,GAAG;EACF,6BAA6B,EAAE;IAC7BE,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,iCAAiC,EAAE;IACjCD,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,kBAAkB,EAAE;IAClBC,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,sCAAsC;IAC7CG,OAAO,EAAET;EACX,CAAC;EACD,oCAAoC,EAAE;IACpCQ,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAET;EACX,CAAC;EACD,sBAAsB,EAAE;IACtBQ,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAET;EACX,CAAC;EACD,8BAA8B,EAAE;IAC9BQ,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,2CAA2C;IAClDG,OAAO,EAAET;EACX,CAAC;EACD,kBAAkB,EAAE;IAClBQ,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,+DAA+D;IACtEC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,WAAW;IACrBF,KAAK,EACH,kGAAkG;IACpGC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,2BAA2B,EAAE;IAC3BF,QAAQ,EAAE,cAAc;IACxBF,KAAK,EAAE,+BAA+B;IACtCG,OAAO,EAAET;EACX,CAAC;EACD,oBAAoB,EAAE;IACpBQ,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,0CAA0C;IACjDG,OAAO,EAAE,CACP;MAAER,IAAI,EAAE,kBAAkB;MAAEC,MAAM,EAAE,iBAAiB;MAAEC,OAAO,EAAE;IAAM,CAAC,EACvE;MAAEF,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EAE3C;AACF,CAAC;;AAED;AACO,MAAMQ,oBAAoB,GAAGA,CAClCC,IAAY,EACZC,SAAkC,KAChB;EAClB,MAAMC,SAAS,GAAGD,SAAS,GACvB;IAAE,GAAGT,uBAAuB;IAAE,GAAGS;EAAU,CAAC,GAC5CT,uBAAuB;EAC3B,OACEU,SAAS,CAACF,IAAI,CAA0B,IACxCE,SAAS,CAAC,6BAA6B,CAAC;AAE5C,CAAC;AAACT,OAAA,CAAAM,oBAAA,GAAAA,oBAAA","ignoreList":[]}
1
+ {"version":3,"names":["retryAndContactButtons","text","action","variant","DEFAULT_ERROR_TEMPLATES","exports","title","showChips","iconType","buttons","chipsLabel","resolveErrorTemplate","type","overrides","templates"],"sources":["../../../src/errors/errorTemplates.ts"],"sourcesContent":["import type { ConversationErrorType } from './conversationErrorTypes';\n\n/** Action identifiers for error template buttons — resolved to callbacks by the rendering component */\nexport type ErrorActionType = 'retry' | 'newConversation' | 'reload';\n\n/** Icon identifiers for error templates — resolved to SVG components by the rendering component */\nexport type ErrorIconType =\n | 'error-500'\n | 'timeout'\n | 'streaming-error'\n | 'not-found'\n | 'forbidden'\n | 'partial-load'\n | 'quota-exceeded';\n\nexport interface ErrorTemplateButton {\n text: string;\n /** URL for navigation (renders as a link) */\n href?: string;\n /** Action identifier — component resolves to a callback */\n action?: ErrorActionType;\n variant: 'cta' | 'link';\n}\n\nexport interface ErrorTemplate {\n title: string;\n subtitle?: string;\n /** Icon identifier — component resolves to an SVG */\n iconType?: ErrorIconType;\n buttons?: ErrorTemplateButton[];\n showChips?: boolean;\n chipsLabel?: string;\n}\n\nexport type ErrorTemplateOverrides = Partial<\n Record<ConversationErrorType, ErrorTemplate>\n>;\n\nconst retryAndContactButtons: ErrorTemplateButton[] = [\n { text: 'Try Again', action: 'retry', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n];\n\nexport const DEFAULT_ERROR_TEMPLATES: Record<\n ConversationErrorType,\n ErrorTemplate\n> = {\n 'conversation-llm-error-text': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-llm-empty-response': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-500': {\n iconType: 'error-500',\n title: \"This page isn't available right now.\",\n buttons: retryAndContactButtons,\n },\n 'conversation-generic-network-error': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-timeout': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-streaming-error': {\n iconType: 'streaming-error',\n title: 'The connection dropped. Please try again.',\n buttons: retryAndContactButtons,\n },\n 'conversation-404': {\n iconType: 'not-found',\n title: 'Page not found.\\nIt happens! Let\\u2019s get you back on track',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-403': {\n iconType: 'forbidden',\n title:\n 'Welcome back.\\nFor privacy, we couldn\\u2019t restore previous content. Ask anything to continue.',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-429': {\n iconType: 'quota-exceeded',\n title: 'This service is currently out of quota.\\nPlease try again later.',\n buttons: [{ text: 'Contact Us', variant: 'link' }],\n },\n 'conversation-partial-load': {\n iconType: 'partial-load',\n title: 'Some content didn\\u2019t load',\n buttons: retryAndContactButtons,\n },\n 'history-load-error': {\n iconType: 'streaming-error',\n title: 'We couldn\\u2019t load this conversation.',\n buttons: [\n { text: 'New Conversation', action: 'newConversation', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n ],\n },\n};\n\n/** Resolves the error template for a given type, merging client overrides on top of defaults */\nexport const resolveErrorTemplate = (\n type: string,\n overrides?: ErrorTemplateOverrides,\n): ErrorTemplate => {\n const templates = overrides\n ? { ...DEFAULT_ERROR_TEMPLATES, ...overrides }\n : DEFAULT_ERROR_TEMPLATES;\n return (\n templates[type as ConversationErrorType] ??\n templates['conversation-llm-error-text']\n );\n};\n"],"mappings":";;;;AAEA;;AAGA;;AAiCA,MAAMA,sBAA6C,GAAG,CACpD;EAAEC,IAAI,EAAE,WAAW;EAAEC,MAAM,EAAE,OAAO;EAAEC,OAAO,EAAE;AAAM,CAAC,EACtD;EAAEF,IAAI,EAAE,YAAY;EAAEE,OAAO,EAAE;AAAO,CAAC,CACxC;AAEM,MAAMC,uBAGZ,GAAAC,OAAA,CAAAD,uBAAA,GAAG;EACF,6BAA6B,EAAE;IAC7BE,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,iCAAiC,EAAE;IACjCD,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,kBAAkB,EAAE;IAClBC,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,sCAAsC;IAC7CG,OAAO,EAAET;EACX,CAAC;EACD,oCAAoC,EAAE;IACpCQ,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAET;EACX,CAAC;EACD,sBAAsB,EAAE;IACtBQ,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAET;EACX,CAAC;EACD,8BAA8B,EAAE;IAC9BQ,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,2CAA2C;IAClDG,OAAO,EAAET;EACX,CAAC;EACD,kBAAkB,EAAE;IAClBQ,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,+DAA+D;IACtEC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,WAAW;IACrBF,KAAK,EACH,kGAAkG;IACpGC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,gBAAgB;IAC1BF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAE,CAAC;MAAER,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EACnD,CAAC;EACD,2BAA2B,EAAE;IAC3BK,QAAQ,EAAE,cAAc;IACxBF,KAAK,EAAE,+BAA+B;IACtCG,OAAO,EAAET;EACX,CAAC;EACD,oBAAoB,EAAE;IACpBQ,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,0CAA0C;IACjDG,OAAO,EAAE,CACP;MAAER,IAAI,EAAE,kBAAkB;MAAEC,MAAM,EAAE,iBAAiB;MAAEC,OAAO,EAAE;IAAM,CAAC,EACvE;MAAEF,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EAE3C;AACF,CAAC;;AAED;AACO,MAAMQ,oBAAoB,GAAGA,CAClCC,IAAY,EACZC,SAAkC,KAChB;EAClB,MAAMC,SAAS,GAAGD,SAAS,GACvB;IAAE,GAAGT,uBAAuB;IAAE,GAAGS;EAAU,CAAC,GAC5CT,uBAAuB;EAC3B,OACEU,SAAS,CAACF,IAAI,CAA0B,IACxCE,SAAS,CAAC,6BAA6B,CAAC;AAE5C,CAAC;AAACT,OAAA,CAAAM,oBAAA,GAAAA,oBAAA","ignoreList":[]}
@@ -6,6 +6,9 @@ const ERROR_PATTERNS = [{
6
6
  }, {
7
7
  pattern: /Error: conversation-403/i,
8
8
  type: 'conversation-403'
9
+ }, {
10
+ pattern: /Error: conversation-429/i,
11
+ type: 'conversation-429'
9
12
  }, {
10
13
  pattern: /Error: conversation-500/i,
11
14
  type: 'conversation-500'
@@ -52,6 +55,11 @@ export class ErrorSectionDefinition {
52
55
  expected: {
53
56
  type: 'conversation-500'
54
57
  }
58
+ }, {
59
+ markdown: 'Error: conversation-429',
60
+ expected: {
61
+ type: 'conversation-429'
62
+ }
55
63
  }]);
56
64
  }
57
65
  parse(parts) {
@@ -1 +1 @@
1
- {"version":3,"names":["bodyText","ERROR_PATTERNS","pattern","type","ErrorSectionDefinition","constructor","_defineProperty","markdown","expected","parse","parts","text","test"],"sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"sourcesContent":["import { bodyText } from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport type {\n ErrorCompProps,\n ErrorSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\nimport type { ConversationErrorType } from '../../errors/conversationErrorTypes';\n\ninterface ErrorPattern {\n pattern: RegExp;\n type: ConversationErrorType;\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n { pattern: /Error: conversation-404/i, type: 'conversation-404' },\n { pattern: /Error: conversation-403/i, type: 'conversation-403' },\n { pattern: /Error: conversation-500/i, type: 'conversation-500' },\n {\n pattern: /Error: conversation-generic-network-error/i,\n type: 'conversation-generic-network-error',\n },\n { pattern: /Error: conversation-timeout/i, type: 'conversation-timeout' },\n {\n pattern: /Error: conversation-partial-load/i,\n type: 'conversation-partial-load',\n },\n {\n pattern: /Error: conversation-streaming-error/i,\n type: 'conversation-streaming-error',\n },\n {\n pattern: /Error: conversation-llm-empty-response/i,\n type: 'conversation-llm-empty-response',\n },\n { pattern: /Error: history-load-error/i, type: 'history-load-error' },\n { pattern: /^error/i, type: 'conversation-llm-error-text' },\n { pattern: /Error/i, type: 'conversation-llm-error-text' },\n];\n\nexport class ErrorSectionDefinition\n implements SectionDefinition<ErrorSectionComponent>\n{\n sectionType = 'error' as const;\n patterns = ['t'];\n maxConsumedNodes = 1;\n\n defaults: ErrorCompProps = {\n type: 'conversation-llm-error-text',\n };\n\n fixtures: SectionFixture<ErrorCompProps>[] = [\n {\n markdown: 'Error: conversation-404',\n expected: { type: 'conversation-404' },\n },\n {\n markdown: 'Error: conversation-500',\n expected: { type: 'conversation-500' },\n },\n ];\n\n parse(parts: Part[]): ErrorCompProps | null {\n const text = bodyText(parts);\n if (!text) {\n return null;\n }\n\n for (const { pattern, type } of ERROR_PATTERNS) {\n if (pattern.test(text)) {\n return { type };\n }\n }\n\n return null;\n }\n}\n"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,eAAe;AAexC,MAAMC,cAA8B,GAAG,CACrC;EAAEC,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EACED,OAAO,EAAE,4CAA4C;EACrDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,8BAA8B;EAAEC,IAAI,EAAE;AAAuB,CAAC,EACzE;EACED,OAAO,EAAE,mCAAmC;EAC5CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,sCAAsC;EAC/CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,yCAAyC;EAClDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,4BAA4B;EAAEC,IAAI,EAAE;AAAqB,CAAC,EACrE;EAAED,OAAO,EAAE,SAAS;EAAEC,IAAI,EAAE;AAA8B,CAAC,EAC3D;EAAED,OAAO,EAAE,QAAQ;EAAEC,IAAI,EAAE;AAA8B,CAAC,CAC3D;AAED,OAAO,MAAMC,sBAAsB,CAEnC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,OAAO;IAAAA,eAAA,mBACV,CAAC,GAAG,CAAC;IAAAA,eAAA,2BACG,CAAC;IAAAA,eAAA,mBAEO;MACzBH,IAAI,EAAE;IACR,CAAC;IAAAG,eAAA,mBAE4C,CAC3C;MACEC,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEL,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEI,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEL,IAAI,EAAE;MAAmB;IACvC,CAAC,CACF;EAAA;EAEDM,KAAKA,CAACC,KAAa,EAAyB;IAC1C,MAAMC,IAAI,GAAGX,QAAQ,CAACU,KAAK,CAAC;IAC5B,IAAI,CAACC,IAAI,EAAE;MACT,OAAO,IAAI;IACb;IAEA,KAAK,MAAM;MAAET,OAAO;MAAEC;IAAK,CAAC,IAAIF,cAAc,EAAE;MAC9C,IAAIC,OAAO,CAACU,IAAI,CAACD,IAAI,CAAC,EAAE;QACtB,OAAO;UAAER;QAAK,CAAC;MACjB;IACF;IAEA,OAAO,IAAI;EACb;AACF","ignoreList":[]}
1
+ {"version":3,"names":["bodyText","ERROR_PATTERNS","pattern","type","ErrorSectionDefinition","constructor","_defineProperty","markdown","expected","parse","parts","text","test"],"sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"sourcesContent":["import { bodyText } from './parse-utils';\nimport type { Part } from '../../parts/parts';\nimport type {\n ErrorCompProps,\n ErrorSectionComponent,\n SectionFixture,\n} from '../types';\nimport type { SectionDefinition } from '../section-definition';\nimport type { ConversationErrorType } from '../../errors/conversationErrorTypes';\n\ninterface ErrorPattern {\n pattern: RegExp;\n type: ConversationErrorType;\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n { pattern: /Error: conversation-404/i, type: 'conversation-404' },\n { pattern: /Error: conversation-403/i, type: 'conversation-403' },\n { pattern: /Error: conversation-429/i, type: 'conversation-429' },\n { pattern: /Error: conversation-500/i, type: 'conversation-500' },\n {\n pattern: /Error: conversation-generic-network-error/i,\n type: 'conversation-generic-network-error',\n },\n { pattern: /Error: conversation-timeout/i, type: 'conversation-timeout' },\n {\n pattern: /Error: conversation-partial-load/i,\n type: 'conversation-partial-load',\n },\n {\n pattern: /Error: conversation-streaming-error/i,\n type: 'conversation-streaming-error',\n },\n {\n pattern: /Error: conversation-llm-empty-response/i,\n type: 'conversation-llm-empty-response',\n },\n { pattern: /Error: history-load-error/i, type: 'history-load-error' },\n { pattern: /^error/i, type: 'conversation-llm-error-text' },\n { pattern: /Error/i, type: 'conversation-llm-error-text' },\n];\n\nexport class ErrorSectionDefinition\n implements SectionDefinition<ErrorSectionComponent>\n{\n sectionType = 'error' as const;\n patterns = ['t'];\n maxConsumedNodes = 1;\n\n defaults: ErrorCompProps = {\n type: 'conversation-llm-error-text',\n };\n\n fixtures: SectionFixture<ErrorCompProps>[] = [\n {\n markdown: 'Error: conversation-404',\n expected: { type: 'conversation-404' },\n },\n {\n markdown: 'Error: conversation-500',\n expected: { type: 'conversation-500' },\n },\n {\n markdown: 'Error: conversation-429',\n expected: { type: 'conversation-429' },\n },\n ];\n\n parse(parts: Part[]): ErrorCompProps | null {\n const text = bodyText(parts);\n if (!text) {\n return null;\n }\n\n for (const { pattern, type } of ERROR_PATTERNS) {\n if (pattern.test(text)) {\n return { type };\n }\n }\n\n return null;\n }\n}\n"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,eAAe;AAexC,MAAMC,cAA8B,GAAG,CACrC;EAAEC,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EAAED,OAAO,EAAE,0BAA0B;EAAEC,IAAI,EAAE;AAAmB,CAAC,EACjE;EACED,OAAO,EAAE,4CAA4C;EACrDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,8BAA8B;EAAEC,IAAI,EAAE;AAAuB,CAAC,EACzE;EACED,OAAO,EAAE,mCAAmC;EAC5CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,sCAAsC;EAC/CC,IAAI,EAAE;AACR,CAAC,EACD;EACED,OAAO,EAAE,yCAAyC;EAClDC,IAAI,EAAE;AACR,CAAC,EACD;EAAED,OAAO,EAAE,4BAA4B;EAAEC,IAAI,EAAE;AAAqB,CAAC,EACrE;EAAED,OAAO,EAAE,SAAS;EAAEC,IAAI,EAAE;AAA8B,CAAC,EAC3D;EAAED,OAAO,EAAE,QAAQ;EAAEC,IAAI,EAAE;AAA8B,CAAC,CAC3D;AAED,OAAO,MAAMC,sBAAsB,CAEnC;EAAAC,YAAA;IAAAC,eAAA,sBACgB,OAAO;IAAAA,eAAA,mBACV,CAAC,GAAG,CAAC;IAAAA,eAAA,2BACG,CAAC;IAAAA,eAAA,mBAEO;MACzBH,IAAI,EAAE;IACR,CAAC;IAAAG,eAAA,mBAE4C,CAC3C;MACEC,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEL,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEI,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEL,IAAI,EAAE;MAAmB;IACvC,CAAC,EACD;MACEI,QAAQ,EAAE,yBAAyB;MACnCC,QAAQ,EAAE;QAAEL,IAAI,EAAE;MAAmB;IACvC,CAAC,CACF;EAAA;EAEDM,KAAKA,CAACC,KAAa,EAAyB;IAC1C,MAAMC,IAAI,GAAGX,QAAQ,CAACU,KAAK,CAAC;IAC5B,IAAI,CAACC,IAAI,EAAE;MACT,OAAO,IAAI;IACb;IAEA,KAAK,MAAM;MAAET,OAAO;MAAEC;IAAK,CAAC,IAAIF,cAAc,EAAE;MAC9C,IAAIC,OAAO,CAACU,IAAI,CAACD,IAAI,CAAC,EAAE;QACtB,OAAO;UAAER;QAAK,CAAC;MACjB;IACF;IAEA,OAAO,IAAI;EACb;AACF","ignoreList":[]}
@@ -37,6 +37,19 @@ import React, { createContext, useCallback, useContext, useEffect, useMemo, useR
37
37
  import { useOptionalComponentDependencies } from './ComponentDependenciesContext.js';
38
38
  import { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes.js';
39
39
  const ImageSlotContext = /*#__PURE__*/createContext(null);
40
+
41
+ /**
42
+ * Module-level so `read` returns a STABLE reference for a slot nobody has
43
+ * published yet. `useImageSlot` reads this store through
44
+ * `useSyncExternalStore`, which compares snapshots with `Object.is` on every
45
+ * render — a fresh `{ status: 'pending' }` per call reads as "the store
46
+ * changed", and React re-renders until it throws "Maximum update depth
47
+ * exceeded". Every slot is pending from mount until its batch answers, so a
48
+ * literal here takes down every section that declares one.
49
+ */
50
+ const PENDING = {
51
+ status: 'pending'
52
+ };
40
53
  /**
41
54
  * Mounted once per section by the host's section wrapper, so every section in
42
55
  * every client package gets a collector without opting in.
@@ -155,9 +168,7 @@ export const ImageSlotProvider = _ref => {
155
168
  });
156
169
  }
157
170
  }, [flush]);
158
- const read = useCallback(slotId => statesRef.current[slotId] ?? {
159
- status: 'pending'
160
- }, []);
171
+ const read = useCallback(slotId => statesRef.current[slotId] ?? PENDING, []);
161
172
  const subscribe = useCallback((slotId, onChange) => {
162
173
  let set = listenersRef.current.get(slotId);
163
174
  if (!set) {
@@ -1 +1 @@
1
- {"version":3,"names":["React","createContext","useCallback","useContext","useEffect","useMemo","useRef","useOptionalComponentDependencies","DIAGNOSTIC_TYPES","ImageSlotContext","ImageSlotProvider","_ref","sectionId","children","deps","resolve","resolveImageSet","statesRef","listenersRef","Map","pendingRef","sentRef","Set","flushScheduled","aliveRef","current","publish","next","changed","id","state","Object","entries","push","_listenersRef$current","get","forEach","fn","markUnavailable","batch","fromEntries","map","s","status","flush","values","filter","has","clear","length","add","res","bySlotId","slots","slotId","req","got","imageUrl","slot","err","reportDiagnostic","IMAGE_RESOLUTION_FAILED","Error","message","String","declare","set","queueMicrotask","read","subscribe","onChange","_set","delete","size","api","createElement","Provider","value","useImageSlotCollector"],"sources":["../../../src/context/ImageSlotContext.tsx"],"sourcesContent":["/**\n * The section-scoped image slot collector.\n *\n * A section declares the holes in its layout; it never makes a request. This\n * gathers every declaration made inside one section's subtree, fires ONE\n * `ResolveImageSet` through the injected port, and hands each declaration its\n * answer back by `slotId`. Sections stay ignorant of each other — no section\n * imports another, no ordering rules, no exclusion lists threaded through\n * props — and the network still sees the joint solve that distinctness depends\n * on.\n *\n * WHY THE BOUNDARY IS THE SECTION\n * -------------------------------\n * The resolver solves a maximum-weight one-to-one assignment across everything\n * in one request, so distinctness and palette cohesion are properties of that\n * solve and stop at its edge. Drawing the boundary at the page would buy\n * cross-section distinctness at the cost of making every section's pictures\n * wait on the slowest declaration on the page; drawing it at the section keeps\n * each section independent and accepts that two sections may land on the same\n * photograph. The most visible case — four identical photos in one grid — is\n * still prevented for free, because those slots share a request.\n *\n * WHY THERE IS NO READINESS POLICY\n * --------------------------------\n * There is nothing to wait for. A section component is never constructed from\n * partial markdown: a declared-but-unstreamed section is a `PageSection` with\n * `isSkeleton: true` and `component: null`, and the real element is built only\n * once its body has finished streaming. So a section's props are final the\n * moment it exists, and the flush is simply \"after this section's first render\n * commit\" — one effect, not a scheduler.\n *\n * The same fact bounds the win honestly: because only a *mounted* section\n * declares, no section can ask for a picture before its own body has streamed,\n * including a background whose subject needed nothing from that body.\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useOptionalComponentDependencies } from './ComponentDependenciesContext';\nimport { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes';\nimport type {\n ImageSlotRequest,\n SlotState,\n} from '../image/imageSlotTypes';\n\nexport interface ImageSlotCollector {\n /** Register a slot for this batch. Idempotent per content-derived id. */\n declare: (slot: ImageSlotRequest) => void;\n /** Current state for one slot. Not reactive alone — pair with `subscribe`. */\n read: (slotId: string) => SlotState;\n /** Notify only when THIS slot changes. Returns an unsubscribe. */\n subscribe: (slotId: string, onChange: () => void) => () => void;\n}\n\nconst ImageSlotContext = createContext<ImageSlotCollector | null>(null);\n\nexport interface ImageSlotProviderProps {\n /** Identifies the section in diagnostics. */\n sectionId: string;\n children: React.ReactNode;\n}\n\n/**\n * Mounted once per section by the host's section wrapper, so every section in\n * every client package gets a collector without opting in.\n */\nexport const ImageSlotProvider: React.FC<ImageSlotProviderProps> = ({\n sectionId,\n children,\n}) => {\n // Optional on purpose: this is mounted by the host around EVERY section, so\n // it sits above trees that may have no dependencies configured at all (a\n // layout test, a story). Throwing there would make the image feature's\n // provider a global requirement for rendering any section.\n const deps = useOptionalComponentDependencies();\n const resolve = deps?.resolveImageSet;\n\n /**\n * Slot state lives in a ref, NOT in React state, and the context value never\n * changes. Holding it in state put it inside the provider's value, so every\n * resolution produced a new value and re-rendered every consumer in the\n * section — free at one slot, twelve re-renders per resolution in a\n * twelve-card grid, which is exactly the shape this boundary exists to serve.\n * Consumers now subscribe to their own id and nothing else.\n */\n const statesRef = useRef<Record<string, SlotState>>({});\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Declarations arriving during this commit. A ref, not state: collecting a\n // declaration must not itself cause a render, or every hook that declares\n // would re-render every sibling before the batch is even sent.\n const pendingRef = useRef<Map<string, ImageSlotRequest>>(new Map());\n // Ids already sent. A re-render re-declares the same content-derived id, and\n // that must be a no-op rather than a second request.\n const sentRef = useRef<Set<string>>(new Set());\n const flushScheduled = useRef(false);\n const aliveRef = useRef(true);\n\n useEffect(() => {\n aliveRef.current = true;\n return () => {\n aliveRef.current = false;\n };\n }, []);\n\n const publish = useCallback((next: Record<string, SlotState>) => {\n const changed: string[] = [];\n for (const [id, state] of Object.entries(next)) {\n if (statesRef.current[id] !== state) {\n statesRef.current[id] = state;\n changed.push(id);\n }\n }\n for (const id of changed) {\n listenersRef.current.get(id)?.forEach((fn) => fn());\n }\n }, []);\n\n const markUnavailable = useCallback(\n (batch: ImageSlotRequest[]) => {\n if (!aliveRef.current) {\n return;\n }\n publish(\n Object.fromEntries(\n batch.map((s) => [s.id, { status: 'unavailable' } as SlotState]),\n ),\n );\n },\n [publish],\n );\n\n const flush = useCallback(async () => {\n flushScheduled.current = false;\n\n const batch = [...pendingRef.current.values()].filter(\n (s) => !sentRef.current.has(s.id),\n );\n pendingRef.current.clear();\n if (batch.length === 0) {\n return;\n }\n batch.forEach((s) => sentRef.current.add(s.id));\n\n // No port means the host has not injected a resolver. Fail the batch closed\n // rather than silently leaving slots pending forever.\n if (!resolve) {\n markUnavailable(batch);\n return;\n }\n\n try {\n const res = await resolve(batch);\n if (!aliveRef.current) {\n return;\n }\n const bySlotId = new Map(res.slots.map((s) => [s.slotId, s]));\n const next: Record<string, SlotState> = {};\n for (const req of batch) {\n const got = bySlotId.get(req.id);\n // A slot the resolver could not fill comes back with a null url. That\n // is `unavailable` to a layout, not a resolved picture.\n next[req.id] =\n got && got.imageUrl\n ? { status: 'resolved', slot: got }\n : { status: 'unavailable' };\n }\n publish(next);\n } catch (err) {\n // Failure is contained to this section: one bad request costs this\n // section its pictures and nothing else on the page.\n deps?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED,\n sectionId,\n `ResolveImageSet failed for ${batch.length} slot(s): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n markUnavailable(batch);\n }\n }, [resolve, deps, sectionId, publish, markUnavailable]);\n\n const declare = useCallback(\n (slot: ImageSlotRequest) => {\n if (sentRef.current.has(slot.id)) {\n return;\n }\n pendingRef.current.set(slot.id, slot);\n // Flush on a microtask, so every declaration made during this commit —\n // the background, the cards, an inline image — lands in the same batch.\n if (!flushScheduled.current) {\n flushScheduled.current = true;\n queueMicrotask(() => {\n void flush();\n });\n }\n },\n [flush],\n );\n\n const read = useCallback(\n (slotId: string): SlotState =>\n statesRef.current[slotId] ?? { status: 'pending' },\n [],\n );\n\n const subscribe = useCallback((slotId: string, onChange: () => void) => {\n let set = listenersRef.current.get(slotId);\n if (!set) {\n set = new Set();\n listenersRef.current.set(slotId, set);\n }\n set.add(onChange);\n return () => {\n set?.delete(onChange);\n if (set && set.size === 0) {\n listenersRef.current.delete(slotId);\n }\n };\n }, []);\n\n // Stable for the provider's lifetime: every member is a `useCallback` with no\n // reactive deps, so mounting this around a section costs its consumers\n // nothing after first render.\n const api = useMemo<ImageSlotCollector>(\n () => ({ declare, read, subscribe }),\n [declare, read, subscribe],\n );\n\n return (\n <ImageSlotContext.Provider value={api}>{children}</ImageSlotContext.Provider>\n );\n};\n\n/**\n * Null when no provider is mounted above — a host that has not adopted the\n * section wrapper's collector. `useImageSlot` handles that by resolving each\n * slot on its own, so a section still gets its picture and only loses batching\n * with its siblings.\n */\nexport const useImageSlotCollector = (): ImageSlotCollector | null =>\n useContext(ImageSlotContext);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","createContext","useCallback","useContext","useEffect","useMemo","useRef","useOptionalComponentDependencies","DIAGNOSTIC_TYPES","ImageSlotContext","PENDING","status","ImageSlotProvider","_ref","sectionId","children","deps","resolve","resolveImageSet","statesRef","listenersRef","Map","pendingRef","sentRef","Set","flushScheduled","aliveRef","current","publish","next","changed","id","state","Object","entries","push","_listenersRef$current","get","forEach","fn","markUnavailable","batch","fromEntries","map","s","flush","values","filter","has","clear","length","add","res","bySlotId","slots","slotId","req","got","imageUrl","slot","err","reportDiagnostic","IMAGE_RESOLUTION_FAILED","Error","message","String","declare","set","queueMicrotask","read","subscribe","onChange","_set","delete","size","api","createElement","Provider","value","useImageSlotCollector"],"sources":["../../../src/context/ImageSlotContext.tsx"],"sourcesContent":["/**\n * The section-scoped image slot collector.\n *\n * A section declares the holes in its layout; it never makes a request. This\n * gathers every declaration made inside one section's subtree, fires ONE\n * `ResolveImageSet` through the injected port, and hands each declaration its\n * answer back by `slotId`. Sections stay ignorant of each other — no section\n * imports another, no ordering rules, no exclusion lists threaded through\n * props — and the network still sees the joint solve that distinctness depends\n * on.\n *\n * WHY THE BOUNDARY IS THE SECTION\n * -------------------------------\n * The resolver solves a maximum-weight one-to-one assignment across everything\n * in one request, so distinctness and palette cohesion are properties of that\n * solve and stop at its edge. Drawing the boundary at the page would buy\n * cross-section distinctness at the cost of making every section's pictures\n * wait on the slowest declaration on the page; drawing it at the section keeps\n * each section independent and accepts that two sections may land on the same\n * photograph. The most visible case — four identical photos in one grid — is\n * still prevented for free, because those slots share a request.\n *\n * WHY THERE IS NO READINESS POLICY\n * --------------------------------\n * There is nothing to wait for. A section component is never constructed from\n * partial markdown: a declared-but-unstreamed section is a `PageSection` with\n * `isSkeleton: true` and `component: null`, and the real element is built only\n * once its body has finished streaming. So a section's props are final the\n * moment it exists, and the flush is simply \"after this section's first render\n * commit\" — one effect, not a scheduler.\n *\n * The same fact bounds the win honestly: because only a *mounted* section\n * declares, no section can ask for a picture before its own body has streamed,\n * including a background whose subject needed nothing from that body.\n */\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { useOptionalComponentDependencies } from './ComponentDependenciesContext';\nimport { DIAGNOSTIC_TYPES } from '../component/diagnosticTypes';\nimport type {\n ImageSlotRequest,\n SlotState,\n} from '../image/imageSlotTypes';\n\nexport interface ImageSlotCollector {\n /** Register a slot for this batch. Idempotent per content-derived id. */\n declare: (slot: ImageSlotRequest) => void;\n /** Current state for one slot. Not reactive alone — pair with `subscribe`. */\n read: (slotId: string) => SlotState;\n /** Notify only when THIS slot changes. Returns an unsubscribe. */\n subscribe: (slotId: string, onChange: () => void) => () => void;\n}\n\nconst ImageSlotContext = createContext<ImageSlotCollector | null>(null);\n\n/**\n * Module-level so `read` returns a STABLE reference for a slot nobody has\n * published yet. `useImageSlot` reads this store through\n * `useSyncExternalStore`, which compares snapshots with `Object.is` on every\n * render — a fresh `{ status: 'pending' }` per call reads as \"the store\n * changed\", and React re-renders until it throws \"Maximum update depth\n * exceeded\". Every slot is pending from mount until its batch answers, so a\n * literal here takes down every section that declares one.\n */\nconst PENDING: SlotState = { status: 'pending' };\n\nexport interface ImageSlotProviderProps {\n /** Identifies the section in diagnostics. */\n sectionId: string;\n children: React.ReactNode;\n}\n\n/**\n * Mounted once per section by the host's section wrapper, so every section in\n * every client package gets a collector without opting in.\n */\nexport const ImageSlotProvider: React.FC<ImageSlotProviderProps> = ({\n sectionId,\n children,\n}) => {\n // Optional on purpose: this is mounted by the host around EVERY section, so\n // it sits above trees that may have no dependencies configured at all (a\n // layout test, a story). Throwing there would make the image feature's\n // provider a global requirement for rendering any section.\n const deps = useOptionalComponentDependencies();\n const resolve = deps?.resolveImageSet;\n\n /**\n * Slot state lives in a ref, NOT in React state, and the context value never\n * changes. Holding it in state put it inside the provider's value, so every\n * resolution produced a new value and re-rendered every consumer in the\n * section — free at one slot, twelve re-renders per resolution in a\n * twelve-card grid, which is exactly the shape this boundary exists to serve.\n * Consumers now subscribe to their own id and nothing else.\n */\n const statesRef = useRef<Record<string, SlotState>>({});\n const listenersRef = useRef<Map<string, Set<() => void>>>(new Map());\n\n // Declarations arriving during this commit. A ref, not state: collecting a\n // declaration must not itself cause a render, or every hook that declares\n // would re-render every sibling before the batch is even sent.\n const pendingRef = useRef<Map<string, ImageSlotRequest>>(new Map());\n // Ids already sent. A re-render re-declares the same content-derived id, and\n // that must be a no-op rather than a second request.\n const sentRef = useRef<Set<string>>(new Set());\n const flushScheduled = useRef(false);\n const aliveRef = useRef(true);\n\n useEffect(() => {\n aliveRef.current = true;\n return () => {\n aliveRef.current = false;\n };\n }, []);\n\n const publish = useCallback((next: Record<string, SlotState>) => {\n const changed: string[] = [];\n for (const [id, state] of Object.entries(next)) {\n if (statesRef.current[id] !== state) {\n statesRef.current[id] = state;\n changed.push(id);\n }\n }\n for (const id of changed) {\n listenersRef.current.get(id)?.forEach((fn) => fn());\n }\n }, []);\n\n const markUnavailable = useCallback(\n (batch: ImageSlotRequest[]) => {\n if (!aliveRef.current) {\n return;\n }\n publish(\n Object.fromEntries(\n batch.map((s) => [s.id, { status: 'unavailable' } as SlotState]),\n ),\n );\n },\n [publish],\n );\n\n const flush = useCallback(async () => {\n flushScheduled.current = false;\n\n const batch = [...pendingRef.current.values()].filter(\n (s) => !sentRef.current.has(s.id),\n );\n pendingRef.current.clear();\n if (batch.length === 0) {\n return;\n }\n batch.forEach((s) => sentRef.current.add(s.id));\n\n // No port means the host has not injected a resolver. Fail the batch closed\n // rather than silently leaving slots pending forever.\n if (!resolve) {\n markUnavailable(batch);\n return;\n }\n\n try {\n const res = await resolve(batch);\n if (!aliveRef.current) {\n return;\n }\n const bySlotId = new Map(res.slots.map((s) => [s.slotId, s]));\n const next: Record<string, SlotState> = {};\n for (const req of batch) {\n const got = bySlotId.get(req.id);\n // A slot the resolver could not fill comes back with a null url. That\n // is `unavailable` to a layout, not a resolved picture.\n next[req.id] =\n got && got.imageUrl\n ? { status: 'resolved', slot: got }\n : { status: 'unavailable' };\n }\n publish(next);\n } catch (err) {\n // Failure is contained to this section: one bad request costs this\n // section its pictures and nothing else on the page.\n deps?.reportDiagnostic?.(\n DIAGNOSTIC_TYPES.IMAGE_RESOLUTION_FAILED,\n sectionId,\n `ResolveImageSet failed for ${batch.length} slot(s): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n markUnavailable(batch);\n }\n }, [resolve, deps, sectionId, publish, markUnavailable]);\n\n const declare = useCallback(\n (slot: ImageSlotRequest) => {\n if (sentRef.current.has(slot.id)) {\n return;\n }\n pendingRef.current.set(slot.id, slot);\n // Flush on a microtask, so every declaration made during this commit —\n // the background, the cards, an inline image — lands in the same batch.\n if (!flushScheduled.current) {\n flushScheduled.current = true;\n queueMicrotask(() => {\n void flush();\n });\n }\n },\n [flush],\n );\n\n const read = useCallback(\n (slotId: string): SlotState => statesRef.current[slotId] ?? PENDING,\n [],\n );\n\n const subscribe = useCallback((slotId: string, onChange: () => void) => {\n let set = listenersRef.current.get(slotId);\n if (!set) {\n set = new Set();\n listenersRef.current.set(slotId, set);\n }\n set.add(onChange);\n return () => {\n set?.delete(onChange);\n if (set && set.size === 0) {\n listenersRef.current.delete(slotId);\n }\n };\n }, []);\n\n // Stable for the provider's lifetime: every member is a `useCallback` with no\n // reactive deps, so mounting this around a section costs its consumers\n // nothing after first render.\n const api = useMemo<ImageSlotCollector>(\n () => ({ declare, read, subscribe }),\n [declare, read, subscribe],\n );\n\n return (\n <ImageSlotContext.Provider value={api}>{children}</ImageSlotContext.Provider>\n );\n};\n\n/**\n * Null when no provider is mounted above — a host that has not adopted the\n * section wrapper's collector. `useImageSlot` handles that by resolving each\n * slot on its own, so a section still gets its picture and only loses batching\n * with its siblings.\n */\nexport const useImageSlotCollector = (): ImageSlotCollector | null =>\n useContext(ImageSlotContext);\n"],"mappings":"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","ignoreList":[]}
@@ -13,6 +13,7 @@
13
13
  export const ERROR_MARKDOWN = {
14
14
  'conversation-404': 'Error: conversation-404',
15
15
  'conversation-403': 'Error: conversation-403',
16
+ 'conversation-429': 'Error: conversation-429',
16
17
  'conversation-500': 'Error: conversation-500',
17
18
  'conversation-generic-network-error': 'Error: conversation-generic-network-error',
18
19
  'conversation-timeout': 'Error: conversation-timeout',
@@ -31,6 +32,9 @@ export const getErrorTypeFromStatus = status => {
31
32
  if (status === 403) {
32
33
  return 'conversation-403';
33
34
  }
35
+ if (status === 429) {
36
+ return 'conversation-429';
37
+ }
34
38
  if (status >= 500) {
35
39
  return 'conversation-500';
36
40
  }
@@ -1 +1 @@
1
- {"version":3,"names":["ERROR_MARKDOWN","getErrorTypeFromStatus","status","createErrorMarkdown","type","STREAMING_TIMEOUT_MS"],"sources":["../../../src/errors/conversationErrorTypes.ts"],"sourcesContent":["/**\n * Conversation Error Types\n *\n * Canonical error type definitions and utilities for the error handling pipeline.\n * Maps HTTP status codes and error conditions to typed error identifiers.\n *\n * Prefix conventions:\n * conversation- → errors during conversation streaming flow\n * history- → errors during conversation history loading\n */\n\nexport type ConversationErrorType =\n | 'conversation-llm-error-text'\n | 'conversation-llm-empty-response'\n | 'conversation-500'\n | 'conversation-generic-network-error'\n | 'conversation-timeout'\n | 'conversation-streaming-error'\n | 'conversation-404'\n | 'conversation-403'\n | 'conversation-partial-load'\n | 'history-load-error';\n\n/** Error markdown strings that ErrorSectionDefinition recognizes */\nexport const ERROR_MARKDOWN: Record<ConversationErrorType, string> = {\n 'conversation-404': 'Error: conversation-404',\n 'conversation-403': 'Error: conversation-403',\n 'conversation-500': 'Error: conversation-500',\n 'conversation-generic-network-error':\n 'Error: conversation-generic-network-error',\n 'conversation-timeout': 'Error: conversation-timeout',\n 'conversation-streaming-error': 'Error: conversation-streaming-error',\n 'conversation-partial-load': 'Error: conversation-partial-load',\n 'conversation-llm-empty-response': 'Error: conversation-llm-empty-response',\n 'conversation-llm-error-text': 'Error',\n 'history-load-error': 'Error: history-load-error',\n};\n\n/** Maps HTTP status code to error type */\nexport const getErrorTypeFromStatus = (\n status: number,\n): ConversationErrorType => {\n if (status === 404) {\n return 'conversation-404';\n }\n if (status === 403) {\n return 'conversation-403';\n }\n if (status >= 500) {\n return 'conversation-500';\n }\n if (status >= 400) {\n return 'conversation-generic-network-error';\n }\n return 'conversation-llm-error-text';\n};\n\n/** Creates error markdown string for the given error type */\nexport const createErrorMarkdown = (type: ConversationErrorType): string => {\n return ERROR_MARKDOWN[type] || ERROR_MARKDOWN['conversation-llm-error-text'];\n};\n\n/** Streaming timeout in milliseconds (60 seconds) */\nexport const STREAMING_TIMEOUT_MS = 60000;\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAcA;AACA,OAAO,MAAMA,cAAqD,GAAG;EACnE,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,oCAAoC,EAClC,2CAA2C;EAC7C,sBAAsB,EAAE,6BAA6B;EACrD,8BAA8B,EAAE,qCAAqC;EACrE,2BAA2B,EAAE,kCAAkC;EAC/D,iCAAiC,EAAE,wCAAwC;EAC3E,6BAA6B,EAAE,OAAO;EACtC,oBAAoB,EAAE;AACxB,CAAC;;AAED;AACA,OAAO,MAAMC,sBAAsB,GACjCC,MAAc,IACY;EAC1B,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,oCAAoC;EAC7C;EACA,OAAO,6BAA6B;AACtC,CAAC;;AAED;AACA,OAAO,MAAMC,mBAAmB,GAAIC,IAA2B,IAAa;EAC1E,OAAOJ,cAAc,CAACI,IAAI,CAAC,IAAIJ,cAAc,CAAC,6BAA6B,CAAC;AAC9E,CAAC;;AAED;AACA,OAAO,MAAMK,oBAAoB,GAAG,KAAK","ignoreList":[]}
1
+ {"version":3,"names":["ERROR_MARKDOWN","getErrorTypeFromStatus","status","createErrorMarkdown","type","STREAMING_TIMEOUT_MS"],"sources":["../../../src/errors/conversationErrorTypes.ts"],"sourcesContent":["/**\n * Conversation Error Types\n *\n * Canonical error type definitions and utilities for the error handling pipeline.\n * Maps HTTP status codes and error conditions to typed error identifiers.\n *\n * Prefix conventions:\n * conversation- → errors during conversation streaming flow\n * history- → errors during conversation history loading\n */\n\nexport type ConversationErrorType =\n | 'conversation-llm-error-text'\n | 'conversation-llm-empty-response'\n | 'conversation-500'\n | 'conversation-generic-network-error'\n | 'conversation-timeout'\n | 'conversation-streaming-error'\n | 'conversation-404'\n | 'conversation-403'\n | 'conversation-429'\n | 'conversation-partial-load'\n | 'history-load-error';\n\n/** Error markdown strings that ErrorSectionDefinition recognizes */\nexport const ERROR_MARKDOWN: Record<ConversationErrorType, string> = {\n 'conversation-404': 'Error: conversation-404',\n 'conversation-403': 'Error: conversation-403',\n 'conversation-429': 'Error: conversation-429',\n 'conversation-500': 'Error: conversation-500',\n 'conversation-generic-network-error':\n 'Error: conversation-generic-network-error',\n 'conversation-timeout': 'Error: conversation-timeout',\n 'conversation-streaming-error': 'Error: conversation-streaming-error',\n 'conversation-partial-load': 'Error: conversation-partial-load',\n 'conversation-llm-empty-response': 'Error: conversation-llm-empty-response',\n 'conversation-llm-error-text': 'Error',\n 'history-load-error': 'Error: history-load-error',\n};\n\n/** Maps HTTP status code to error type */\nexport const getErrorTypeFromStatus = (\n status: number,\n): ConversationErrorType => {\n if (status === 404) {\n return 'conversation-404';\n }\n if (status === 403) {\n return 'conversation-403';\n }\n if (status === 429) {\n return 'conversation-429';\n }\n if (status >= 500) {\n return 'conversation-500';\n }\n if (status >= 400) {\n return 'conversation-generic-network-error';\n }\n return 'conversation-llm-error-text';\n};\n\n/** Creates error markdown string for the given error type */\nexport const createErrorMarkdown = (type: ConversationErrorType): string => {\n return ERROR_MARKDOWN[type] || ERROR_MARKDOWN['conversation-llm-error-text'];\n};\n\n/** Streaming timeout in milliseconds (60 seconds) */\nexport const STREAMING_TIMEOUT_MS = 60000;\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAeA;AACA,OAAO,MAAMA,cAAqD,GAAG;EACnE,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,kBAAkB,EAAE,yBAAyB;EAC7C,oCAAoC,EAClC,2CAA2C;EAC7C,sBAAsB,EAAE,6BAA6B;EACrD,8BAA8B,EAAE,qCAAqC;EACrE,2BAA2B,EAAE,kCAAkC;EAC/D,iCAAiC,EAAE,wCAAwC;EAC3E,6BAA6B,EAAE,OAAO;EACtC,oBAAoB,EAAE;AACxB,CAAC;;AAED;AACA,OAAO,MAAMC,sBAAsB,GACjCC,MAAc,IACY;EAC1B,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,KAAK,GAAG,EAAE;IAClB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,kBAAkB;EAC3B;EACA,IAAIA,MAAM,IAAI,GAAG,EAAE;IACjB,OAAO,oCAAoC;EAC7C;EACA,OAAO,6BAA6B;AACtC,CAAC;;AAED;AACA,OAAO,MAAMC,mBAAmB,GAAIC,IAA2B,IAAa;EAC1E,OAAOJ,cAAc,CAACI,IAAI,CAAC,IAAIJ,cAAc,CAAC,6BAA6B,CAAC;AAC9E,CAAC;;AAED;AACA,OAAO,MAAMK,oBAAoB,GAAG,KAAK","ignoreList":[]}
@@ -51,6 +51,14 @@ export const DEFAULT_ERROR_TEMPLATES = {
51
51
  showChips: true,
52
52
  chipsLabel: 'Some ideas to get you started:'
53
53
  },
54
+ 'conversation-429': {
55
+ iconType: 'quota-exceeded',
56
+ title: 'This service is currently out of quota.\nPlease try again later.',
57
+ buttons: [{
58
+ text: 'Contact Us',
59
+ variant: 'link'
60
+ }]
61
+ },
54
62
  'conversation-partial-load': {
55
63
  iconType: 'partial-load',
56
64
  title: 'Some content didn\u2019t load',
@@ -1 +1 @@
1
- {"version":3,"names":["retryAndContactButtons","text","action","variant","DEFAULT_ERROR_TEMPLATES","title","showChips","iconType","buttons","chipsLabel","resolveErrorTemplate","type","overrides","templates"],"sources":["../../../src/errors/errorTemplates.ts"],"sourcesContent":["import type { ConversationErrorType } from './conversationErrorTypes';\n\n/** Action identifiers for error template buttons — resolved to callbacks by the rendering component */\nexport type ErrorActionType = 'retry' | 'newConversation' | 'reload';\n\n/** Icon identifiers for error templates — resolved to SVG components by the rendering component */\nexport type ErrorIconType =\n | 'error-500'\n | 'timeout'\n | 'streaming-error'\n | 'not-found'\n | 'forbidden'\n | 'partial-load';\n\nexport interface ErrorTemplateButton {\n text: string;\n /** URL for navigation (renders as a link) */\n href?: string;\n /** Action identifier — component resolves to a callback */\n action?: ErrorActionType;\n variant: 'cta' | 'link';\n}\n\nexport interface ErrorTemplate {\n title: string;\n subtitle?: string;\n /** Icon identifier — component resolves to an SVG */\n iconType?: ErrorIconType;\n buttons?: ErrorTemplateButton[];\n showChips?: boolean;\n chipsLabel?: string;\n}\n\nexport type ErrorTemplateOverrides = Partial<\n Record<ConversationErrorType, ErrorTemplate>\n>;\n\nconst retryAndContactButtons: ErrorTemplateButton[] = [\n { text: 'Try Again', action: 'retry', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n];\n\nexport const DEFAULT_ERROR_TEMPLATES: Record<\n ConversationErrorType,\n ErrorTemplate\n> = {\n 'conversation-llm-error-text': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-llm-empty-response': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-500': {\n iconType: 'error-500',\n title: \"This page isn't available right now.\",\n buttons: retryAndContactButtons,\n },\n 'conversation-generic-network-error': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-timeout': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-streaming-error': {\n iconType: 'streaming-error',\n title: 'The connection dropped. Please try again.',\n buttons: retryAndContactButtons,\n },\n 'conversation-404': {\n iconType: 'not-found',\n title: 'Page not found.\\nIt happens! Let\\u2019s get you back on track',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-403': {\n iconType: 'forbidden',\n title:\n 'Welcome back.\\nFor privacy, we couldn\\u2019t restore previous content. Ask anything to continue.',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-partial-load': {\n iconType: 'partial-load',\n title: 'Some content didn\\u2019t load',\n buttons: retryAndContactButtons,\n },\n 'history-load-error': {\n iconType: 'streaming-error',\n title: 'We couldn\\u2019t load this conversation.',\n buttons: [\n { text: 'New Conversation', action: 'newConversation', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n ],\n },\n};\n\n/** Resolves the error template for a given type, merging client overrides on top of defaults */\nexport const resolveErrorTemplate = (\n type: string,\n overrides?: ErrorTemplateOverrides,\n): ErrorTemplate => {\n const templates = overrides\n ? { ...DEFAULT_ERROR_TEMPLATES, ...overrides }\n : DEFAULT_ERROR_TEMPLATES;\n return (\n templates[type as ConversationErrorType] ??\n templates['conversation-llm-error-text']\n );\n};\n"],"mappings":"AAEA;;AAGA;;AAgCA,MAAMA,sBAA6C,GAAG,CACpD;EAAEC,IAAI,EAAE,WAAW;EAAEC,MAAM,EAAE,OAAO;EAAEC,OAAO,EAAE;AAAM,CAAC,EACtD;EAAEF,IAAI,EAAE,YAAY;EAAEE,OAAO,EAAE;AAAO,CAAC,CACxC;AAED,OAAO,MAAMC,uBAGZ,GAAG;EACF,6BAA6B,EAAE;IAC7BC,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,iCAAiC,EAAE;IACjCD,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,kBAAkB,EAAE;IAClBC,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,sCAAsC;IAC7CG,OAAO,EAAER;EACX,CAAC;EACD,oCAAoC,EAAE;IACpCO,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAER;EACX,CAAC;EACD,sBAAsB,EAAE;IACtBO,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAER;EACX,CAAC;EACD,8BAA8B,EAAE;IAC9BO,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,2CAA2C;IAClDG,OAAO,EAAER;EACX,CAAC;EACD,kBAAkB,EAAE;IAClBO,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,+DAA+D;IACtEC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,WAAW;IACrBF,KAAK,EACH,kGAAkG;IACpGC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,2BAA2B,EAAE;IAC3BF,QAAQ,EAAE,cAAc;IACxBF,KAAK,EAAE,+BAA+B;IACtCG,OAAO,EAAER;EACX,CAAC;EACD,oBAAoB,EAAE;IACpBO,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,0CAA0C;IACjDG,OAAO,EAAE,CACP;MAAEP,IAAI,EAAE,kBAAkB;MAAEC,MAAM,EAAE,iBAAiB;MAAEC,OAAO,EAAE;IAAM,CAAC,EACvE;MAAEF,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EAE3C;AACF,CAAC;;AAED;AACA,OAAO,MAAMO,oBAAoB,GAAGA,CAClCC,IAAY,EACZC,SAAkC,KAChB;EAClB,MAAMC,SAAS,GAAGD,SAAS,GACvB;IAAE,GAAGR,uBAAuB;IAAE,GAAGQ;EAAU,CAAC,GAC5CR,uBAAuB;EAC3B,OACES,SAAS,CAACF,IAAI,CAA0B,IACxCE,SAAS,CAAC,6BAA6B,CAAC;AAE5C,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["retryAndContactButtons","text","action","variant","DEFAULT_ERROR_TEMPLATES","title","showChips","iconType","buttons","chipsLabel","resolveErrorTemplate","type","overrides","templates"],"sources":["../../../src/errors/errorTemplates.ts"],"sourcesContent":["import type { ConversationErrorType } from './conversationErrorTypes';\n\n/** Action identifiers for error template buttons — resolved to callbacks by the rendering component */\nexport type ErrorActionType = 'retry' | 'newConversation' | 'reload';\n\n/** Icon identifiers for error templates — resolved to SVG components by the rendering component */\nexport type ErrorIconType =\n | 'error-500'\n | 'timeout'\n | 'streaming-error'\n | 'not-found'\n | 'forbidden'\n | 'partial-load'\n | 'quota-exceeded';\n\nexport interface ErrorTemplateButton {\n text: string;\n /** URL for navigation (renders as a link) */\n href?: string;\n /** Action identifier — component resolves to a callback */\n action?: ErrorActionType;\n variant: 'cta' | 'link';\n}\n\nexport interface ErrorTemplate {\n title: string;\n subtitle?: string;\n /** Icon identifier — component resolves to an SVG */\n iconType?: ErrorIconType;\n buttons?: ErrorTemplateButton[];\n showChips?: boolean;\n chipsLabel?: string;\n}\n\nexport type ErrorTemplateOverrides = Partial<\n Record<ConversationErrorType, ErrorTemplate>\n>;\n\nconst retryAndContactButtons: ErrorTemplateButton[] = [\n { text: 'Try Again', action: 'retry', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n];\n\nexport const DEFAULT_ERROR_TEMPLATES: Record<\n ConversationErrorType,\n ErrorTemplate\n> = {\n 'conversation-llm-error-text': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-llm-empty-response': {\n title:\n \"I couldn't find information about what you asked.\\nTry asking about a different topic.\",\n showChips: true,\n },\n 'conversation-500': {\n iconType: 'error-500',\n title: \"This page isn't available right now.\",\n buttons: retryAndContactButtons,\n },\n 'conversation-generic-network-error': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-timeout': {\n iconType: 'timeout',\n title: 'Something went wrong on our side.\\nPlease try again in a moment.',\n buttons: retryAndContactButtons,\n },\n 'conversation-streaming-error': {\n iconType: 'streaming-error',\n title: 'The connection dropped. Please try again.',\n buttons: retryAndContactButtons,\n },\n 'conversation-404': {\n iconType: 'not-found',\n title: 'Page not found.\\nIt happens! Let\\u2019s get you back on track',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-403': {\n iconType: 'forbidden',\n title:\n 'Welcome back.\\nFor privacy, we couldn\\u2019t restore previous content. Ask anything to continue.',\n showChips: true,\n chipsLabel: 'Some ideas to get you started:',\n },\n 'conversation-429': {\n iconType: 'quota-exceeded',\n title: 'This service is currently out of quota.\\nPlease try again later.',\n buttons: [{ text: 'Contact Us', variant: 'link' }],\n },\n 'conversation-partial-load': {\n iconType: 'partial-load',\n title: 'Some content didn\\u2019t load',\n buttons: retryAndContactButtons,\n },\n 'history-load-error': {\n iconType: 'streaming-error',\n title: 'We couldn\\u2019t load this conversation.',\n buttons: [\n { text: 'New Conversation', action: 'newConversation', variant: 'cta' },\n { text: 'Contact Us', variant: 'link' },\n ],\n },\n};\n\n/** Resolves the error template for a given type, merging client overrides on top of defaults */\nexport const resolveErrorTemplate = (\n type: string,\n overrides?: ErrorTemplateOverrides,\n): ErrorTemplate => {\n const templates = overrides\n ? { ...DEFAULT_ERROR_TEMPLATES, ...overrides }\n : DEFAULT_ERROR_TEMPLATES;\n return (\n templates[type as ConversationErrorType] ??\n templates['conversation-llm-error-text']\n );\n};\n"],"mappings":"AAEA;;AAGA;;AAiCA,MAAMA,sBAA6C,GAAG,CACpD;EAAEC,IAAI,EAAE,WAAW;EAAEC,MAAM,EAAE,OAAO;EAAEC,OAAO,EAAE;AAAM,CAAC,EACtD;EAAEF,IAAI,EAAE,YAAY;EAAEE,OAAO,EAAE;AAAO,CAAC,CACxC;AAED,OAAO,MAAMC,uBAGZ,GAAG;EACF,6BAA6B,EAAE;IAC7BC,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,iCAAiC,EAAE;IACjCD,KAAK,EACH,wFAAwF;IAC1FC,SAAS,EAAE;EACb,CAAC;EACD,kBAAkB,EAAE;IAClBC,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,sCAAsC;IAC7CG,OAAO,EAAER;EACX,CAAC;EACD,oCAAoC,EAAE;IACpCO,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAER;EACX,CAAC;EACD,sBAAsB,EAAE;IACtBO,QAAQ,EAAE,SAAS;IACnBF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAER;EACX,CAAC;EACD,8BAA8B,EAAE;IAC9BO,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,2CAA2C;IAClDG,OAAO,EAAER;EACX,CAAC;EACD,kBAAkB,EAAE;IAClBO,QAAQ,EAAE,WAAW;IACrBF,KAAK,EAAE,+DAA+D;IACtEC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,WAAW;IACrBF,KAAK,EACH,kGAAkG;IACpGC,SAAS,EAAE,IAAI;IACfG,UAAU,EAAE;EACd,CAAC;EACD,kBAAkB,EAAE;IAClBF,QAAQ,EAAE,gBAAgB;IAC1BF,KAAK,EAAE,kEAAkE;IACzEG,OAAO,EAAE,CAAC;MAAEP,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EACnD,CAAC;EACD,2BAA2B,EAAE;IAC3BI,QAAQ,EAAE,cAAc;IACxBF,KAAK,EAAE,+BAA+B;IACtCG,OAAO,EAAER;EACX,CAAC;EACD,oBAAoB,EAAE;IACpBO,QAAQ,EAAE,iBAAiB;IAC3BF,KAAK,EAAE,0CAA0C;IACjDG,OAAO,EAAE,CACP;MAAEP,IAAI,EAAE,kBAAkB;MAAEC,MAAM,EAAE,iBAAiB;MAAEC,OAAO,EAAE;IAAM,CAAC,EACvE;MAAEF,IAAI,EAAE,YAAY;MAAEE,OAAO,EAAE;IAAO,CAAC;EAE3C;AACF,CAAC;;AAED;AACA,OAAO,MAAMO,oBAAoB,GAAGA,CAClCC,IAAY,EACZC,SAAkC,KAChB;EAClB,MAAMC,SAAS,GAAGD,SAAS,GACvB;IAAE,GAAGR,uBAAuB;IAAE,GAAGQ;EAAU,CAAC,GAC5CR,uBAAuB;EAC3B,OACES,SAAS,CAACF,IAAI,CAA0B,IACxCE,SAAS,CAAC,6BAA6B,CAAC;AAE5C,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorSectionDefinition.d.ts","sourceRoot":"","sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAkC/D,qBAAa,sBACX,YAAW,iBAAiB,CAAC,qBAAqB,CAAC;IAEnD,WAAW,UAAoB;IAC/B,QAAQ,WAAS;IACjB,gBAAgB,SAAK;IAErB,QAAQ,EAAE,cAAc,CAEtB;IAEF,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,CASxC;IAEF,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc,GAAG,IAAI;CAc5C"}
1
+ {"version":3,"file":"ErrorSectionDefinition.d.ts","sourceRoot":"","sources":["../../../../src/component/componentDefinitions/ErrorSectionDefinition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAmC/D,qBAAa,sBACX,YAAW,iBAAiB,CAAC,qBAAqB,CAAC;IAEnD,WAAW,UAAoB;IAC/B,QAAQ,WAAS;IACjB,gBAAgB,SAAK;IAErB,QAAQ,EAAE,cAAc,CAEtB;IAEF,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,EAAE,CAaxC;IAEF,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc,GAAG,IAAI;CAc5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageSlotContext.d.ts","sourceRoot":"","sources":["../../../src/context/ImageSlotContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,OAAO,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC1C,8EAA8E;IAC9E,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC;IACpC,kEAAkE;IAClE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CACjE;AAID,MAAM,WAAW,sBAAsB;IACrC,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAsK9D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAO,kBAAkB,GAAG,IAChC,CAAC"}
1
+ {"version":3,"file":"ImageSlotContext.d.ts","sourceRoot":"","sources":["../../../src/context/ImageSlotContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAON,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,OAAO,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC1C,8EAA8E;IAC9E,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC;IACpC,kEAAkE;IAClE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CACjE;AAeD,MAAM,WAAW,sBAAsB;IACrC,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAqK9D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAO,kBAAkB,GAAG,IAChC,CAAC"}
@@ -8,7 +8,7 @@
8
8
  * conversation- → errors during conversation streaming flow
9
9
  * history- → errors during conversation history loading
10
10
  */
11
- export type ConversationErrorType = 'conversation-llm-error-text' | 'conversation-llm-empty-response' | 'conversation-500' | 'conversation-generic-network-error' | 'conversation-timeout' | 'conversation-streaming-error' | 'conversation-404' | 'conversation-403' | 'conversation-partial-load' | 'history-load-error';
11
+ export type ConversationErrorType = 'conversation-llm-error-text' | 'conversation-llm-empty-response' | 'conversation-500' | 'conversation-generic-network-error' | 'conversation-timeout' | 'conversation-streaming-error' | 'conversation-404' | 'conversation-403' | 'conversation-429' | 'conversation-partial-load' | 'history-load-error';
12
12
  /** Error markdown strings that ErrorSectionDefinition recognizes */
13
13
  export declare const ERROR_MARKDOWN: Record<ConversationErrorType, string>;
14
14
  /** Maps HTTP status code to error type */
@@ -1 +1 @@
1
- {"version":3,"file":"conversationErrorTypes.d.ts","sourceRoot":"","sources":["../../../src/errors/conversationErrorTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,qBAAqB,GAC7B,6BAA6B,GAC7B,iCAAiC,GACjC,kBAAkB,GAClB,oCAAoC,GACpC,sBAAsB,GACtB,8BAA8B,GAC9B,kBAAkB,GAClB,kBAAkB,GAClB,2BAA2B,GAC3B,oBAAoB,CAAC;AAEzB,oEAAoE;AACpE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAYhE,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,WACzB,MAAM,KACb,qBAcF,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,SAAU,qBAAqB,KAAG,MAEjE,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,QAAQ,CAAC"}
1
+ {"version":3,"file":"conversationErrorTypes.d.ts","sourceRoot":"","sources":["../../../src/errors/conversationErrorTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,qBAAqB,GAC7B,6BAA6B,GAC7B,iCAAiC,GACjC,kBAAkB,GAClB,oCAAoC,GACpC,sBAAsB,GACtB,8BAA8B,GAC9B,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,GAClB,2BAA2B,GAC3B,oBAAoB,CAAC;AAEzB,oEAAoE;AACpE,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAahE,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,sBAAsB,WACzB,MAAM,KACb,qBAiBF,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,SAAU,qBAAqB,KAAG,MAEjE,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,QAAQ,CAAC"}
@@ -2,7 +2,7 @@ import type { ConversationErrorType } from './conversationErrorTypes';
2
2
  /** Action identifiers for error template buttons — resolved to callbacks by the rendering component */
3
3
  export type ErrorActionType = 'retry' | 'newConversation' | 'reload';
4
4
  /** Icon identifiers for error templates — resolved to SVG components by the rendering component */
5
- export type ErrorIconType = 'error-500' | 'timeout' | 'streaming-error' | 'not-found' | 'forbidden' | 'partial-load';
5
+ export type ErrorIconType = 'error-500' | 'timeout' | 'streaming-error' | 'not-found' | 'forbidden' | 'partial-load' | 'quota-exceeded';
6
6
  export interface ErrorTemplateButton {
7
7
  text: string;
8
8
  /** URL for navigation (renders as a link) */
@@ -1 +1 @@
1
- {"version":3,"file":"errorTemplates.d.ts","sourceRoot":"","sources":["../../../src/errors/errorTemplates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,uGAAuG;AACvG,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,iBAAiB,GAAG,QAAQ,CAAC;AAErE,mGAAmG;AACnG,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,SAAS,GACT,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,cAAc,CAAC;AAEnB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,KAAK,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC1C,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAC7C,CAAC;AAOF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,qBAAqB,EACrB,aAAa,CA0Dd,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,SACzB,MAAM,cACA,sBAAsB,KACjC,aAQF,CAAC"}
1
+ {"version":3,"file":"errorTemplates.d.ts","sourceRoot":"","sources":["../../../src/errors/errorTemplates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE,uGAAuG;AACvG,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,iBAAiB,GAAG,QAAQ,CAAC;AAErE,mGAAmG;AACnG,MAAM,MAAM,aAAa,GACrB,WAAW,GACX,SAAS,GACT,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,KAAK,GAAG,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC1C,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC,CAC7C,CAAC;AAOF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,qBAAqB,EACrB,aAAa,CA+Dd,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,SACzB,MAAM,cACA,sBAAsB,KACjC,aAQF,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wix/web5-core",
3
3
  "license": "MIT",
4
- "version": "1.63.27",
4
+ "version": "1.63.29",
5
5
  "author": {
6
6
  "name": "tsachis",
7
7
  "email": "tsachis@wix.com"
@@ -100,5 +100,5 @@
100
100
  "wallaby": {
101
101
  "autoDetect": true
102
102
  },
103
- "falconPackageHash": "6004eb47afd7f3a5c4bf49c7ece8bae2ac7e89831e035392d0afc7f4"
103
+ "falconPackageHash": "836f03a5a81dadced3a2ec88f55057ba79b7f97c5142e8587682ece3"
104
104
  }