@copilotkit/learning 2.0.0-rc.2 → 2.0.0-rc.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1107,7 +1107,7 @@ const BUILT_IN = new Set(BUILT_IN_EVENT_NAMES);
1107
1107
  * collector.start({ trajectoryId: crypto.randomUUID() });
1108
1108
  */
1109
1109
  function createCollector(options) {
1110
- const { sink, routes, beforeSend, enrich } = options;
1110
+ const { sink, beforeSend, enrich } = options;
1111
1111
  const capture = {
1112
1112
  clicks: true,
1113
1113
  navigation: true,
@@ -1117,7 +1117,7 @@ function createCollector(options) {
1117
1117
  };
1118
1118
  let session = null;
1119
1119
  let seq = 0;
1120
- const getRoute = () => toRoute(location.pathname, routes);
1120
+ const getRoute = () => toRoute(location.pathname);
1121
1121
  const flush = (sendOptions) => {
1122
1122
  const current = session;
1123
1123
  if (current === null) return;
@@ -1191,12 +1191,10 @@ function createCollector(options) {
1191
1191
  }));
1192
1192
  if (capture.navigation) current.uninstalls.push(installNavigationCapture({
1193
1193
  emit: recordCurrent,
1194
- routes,
1195
1194
  redact
1196
1195
  }));
1197
1196
  if (capture.network) current.uninstalls.push(installNetworkCapture({
1198
1197
  emit: recordCurrent,
1199
- routes,
1200
1198
  ignoreUrls,
1201
1199
  redact
1202
1200
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/types.ts","../src/redact.ts","../src/clicks.ts","../src/inputs.ts","../src/navigation.ts","../src/network-body.ts","../src/network.ts","../src/routes.ts","../src/collector.ts","../src/http-sink.ts","../src/trajectory-collector.ts"],"sourcesContent":["/** Event names the collector and CopilotKit Core emit. `emit()` rejects them. */\nexport const BUILT_IN_EVENT_NAMES = [\n \"page\",\n \"navigation\",\n \"click\",\n \"input\",\n \"network\",\n \"thread.linked\",\n \"agent.run\",\n \"agent.message\",\n \"tool.call\",\n] as const;\n\nexport type BuiltInEventName = (typeof BUILT_IN_EVENT_NAMES)[number];\n\n/** Replaces values that never leave the browser, even with full capture: passwords and credentials. */\nexport const REDACTED = \"[redacted]\";\n\n/** One captured interaction, shaped as an AG-UI `CUSTOM` event. */\nexport interface LearningEvent<V = Record<string, unknown>> {\n type: \"CUSTOM\";\n name: string;\n value: V;\n timestamp: number;\n}\n\n/** What a sink receives. The Trajectory scope sits on the batch, not on each event. */\nexport interface LearningBatch {\n trajectoryId: string;\n learningContainerIds?: string[];\n events: LearningEvent[];\n /** Events lost since the previous batch (queue overflow or a failed send). */\n dropped: number;\n}\n\nexport interface SinkSendOptions {\n /** True when the page is going away; use a transport that survives unload. */\n beacon?: boolean;\n}\n\n/** Receives batches. `url`, when set, is never captured as a network event. */\nexport type LearningSink = ((\n batch: LearningBatch,\n options?: SinkSendOptions,\n) => void | Promise<void>) & { readonly url?: string };\n\nexport interface ClickTarget {\n tag: string;\n role: string | null;\n action: string | null;\n text: string;\n /**\n * Short, cleaned name of the clicked control (click events only). Comes from\n * `aria-labelledby`, `aria-label`, an input caption or `alt`, `title`, or a\n * control's own text. Omitted when no safe name exists.\n */\n label?: string;\n attributes: Record<string, string>;\n value?: string;\n checked?: boolean;\n selectedValues?: string[];\n files?: { name: string; type: string; size: number; lastModified: number }[];\n input: \"pointer\" | \"keyboard\";\n}\n\n/** Adds fields to a click event, from the element the user clicked. */\nexport type EnrichFn = (target: Element) => Record<string, unknown> | undefined;\n\nexport type Emit = (name: string, value: Record<string, unknown>) => void;\n\nexport interface CaptureOptions {\n clicks?: boolean;\n navigation?: boolean;\n network?: boolean;\n inputs?: boolean;\n}\n\nexport interface CollectorOptions {\n sink: LearningSink;\n /** @deprecated Capture retains raw URLs; route templates no longer transform events. */\n routes?: string[];\n /** URLs (prefix match on the absolute URL) or patterns that network capture skips. */\n ignoreUrls?: (string | RegExp)[];\n /** Turns capture modules on or off. All are on by default. */\n capture?: CaptureOptions;\n /** Runs last, in the browser. Return the event to send, or `null` to drop it. */\n beforeSend?: (event: LearningEvent) => LearningEvent | null;\n enrich?: EnrichFn;\n}\n\nexport interface StartOptions {\n trajectoryId: string;\n learningContainerIds?: string[];\n}\n\nexport interface Collector {\n start(options: StartOptions): void;\n stop(): void;\n /** Developer events. Built-in names warn and are ignored. */\n emit(name: string, value: Record<string, unknown>): void;\n /** @internal For @copilotkit/core only: emits built-in names. */\n ɵemit(name: BuiltInEventName, value: Record<string, unknown>): void;\n readonly trajectoryId: string | null;\n}\n","import { REDACTED } from \"./types\";\n\n// Passwords and unambiguous credentials never leave the browser, even with full\n// capture. Keys are split into lowercase words (`accessToken`, `access_token`,\n// `Access-Token` all become \"access token\"). These match anywhere in the joined words:\nconst CREDENTIAL =\n /password|passwd|passphrase|passcode|credential|api(key|token)|privatekey|subscriptionkey|(access|refresh|auth|session)token|clientsecret/;\n// These match only as whole words (`secret` but not `secretary`, `id token` but\n// not `invalid token`), as the last word (`Set-Cookie` but not `cookieConsent`),\n// or as the entire key.\nconst CREDENTIAL_WORD =\n / (secret|id ?token)s? | (authorization|cookies?|jwt|bearer ?token|[cx]srf ?token) $|^ (pwd|pass|token|otp) $/;\n// Metadata about a credential is not the credential: `passwordExpiresAt`, `credentialId`.\nconst METADATA =\n / (ids?|at|in|expires?|expiry|length|count|enabled|required|policy|hint|type) $/;\nconst PASSWORD_AUTOCOMPLETE = /(current|new)-password|one-time-code/;\n// A JSON string, possibly cut off, with the `:` that makes it a key.\nconst TOKEN = /\"((?:\\\\[\\s\\S]|[^\"\\\\])*)(\"?)(\\s*:\\s*)?/g;\n// A lone trailing backslash belongs to a cut-off string.\nconst STRING = /\"(?:\\\\[\\s\\S]?|[^\"\\\\])*\"?/y;\n// `key=value` and `key: value` outside JSON strings: forms, query strings,\n// GraphQL, YAML. A `:` needs a space or end after it, so `host:port` is no pair.\n// The key length bound keeps scanning long unbroken text linear.\n// An auth scheme (`Bearer x`) belongs to the value.\nconst PAIR =\n /([\\w$.%+[\\]-]{1,64})(\\s*(?:=|:(?=\\s|$))\\s*)((?:(?:basic|bearer|digest|token) +)?[^\\s&,;)}\\]]*)/gi;\n// `scheme://user:pass@` anywhere in text; up to the last `@` before the host.\n// The scheme length bound keeps scanning long words linear.\nconst USERINFO = /([a-z][\\w+.-]{0,31}:\\/\\/)[^\\s/?#\"]*@/gi;\n/** Text beyond this is neither redacted nor kept; snapshots keep 4 KiB of the result. */\nexport const TEXT_LIMIT = 16 * 1024;\nconst REMEMBERED_VALUES = 20;\n\nexport const isCredentialKey = (key: string) => {\n const words = ` ${key\n .replace(/%([\\da-f]{2})/gi, (_, hex: string) =>\n String.fromCharCode(parseInt(hex, 16)),\n )\n .replace(/([a-z\\d])(?=[A-Z])/g, \"$1 \")\n .toLowerCase()\n .split(/[^a-z\\d]+/)\n .filter(Boolean)\n .join(\" \")} `;\n return (\n !METADATA.test(words) &&\n (CREDENTIAL.test(words.replace(/ /g, \"\")) || CREDENTIAL_WORD.test(words))\n );\n};\n\nconst decode = (body: string) => {\n try {\n return JSON.parse(`\"${body}\"`) as string;\n } catch {\n return body;\n }\n};\n\n/** The end of the JSON value at `start`: a string, a balanced object or array, or a bare literal. */\nconst endOfValue = (text: string, start: number) => {\n let depth = 0;\n for (let i = start; i < text.length; i++) {\n const char = text[i]!;\n if (char === '\"') {\n STRING.lastIndex = i;\n STRING.test(text);\n i = STRING.lastIndex - 1;\n } else if (char === \"{\" || char === \"[\") {\n depth++;\n continue;\n } else if (char === \"}\" || char === \"]\") {\n if (--depth < 0) return i;\n } else {\n if (!depth && (char === \",\" || /\\s/.test(char))) return i;\n continue;\n }\n if (!depth) return i + 1;\n }\n return text.length;\n};\n\n/**\n * Redacts credential values in JSON (valid or cut off) and in key/value text,\n * and recurses into string values that hold JSON, forms, or URLs. Unchanged\n * parts keep their exact original text.\n */\nconst redactText = (text: string, depth = 0): string => {\n const token = new RegExp(TOKEN);\n let pending = false;\n const pairs = (part: string) => {\n const segment = part.replace(USERINFO, \"$1\");\n return segment.replace(\n PAIR,\n (pair, key: string, separator: string, value: string, offset: number) => {\n if (!isCredentialKey(key)) return pair;\n // The value may continue in a following string: `password:\"x\"`.\n if (offset + pair.length === segment.length) {\n pending = true;\n if (!value) return pair;\n }\n return key + separator + REDACTED;\n },\n );\n };\n let out = \"\";\n let last = 0;\n let match: RegExpExecArray | null;\n while ((match = token.exec(text))) {\n const [raw, body, closed, colon] = match;\n pending = false;\n out += pairs(text.slice(last, match.index));\n let end = token.lastIndex;\n let replacement = raw;\n const value = body!.includes(\"\\\\\") ? decode(body!) : body!;\n if (colon) {\n if (isCredentialKey(value)) {\n const valueEnd = endOfValue(text, end);\n // Booleans and null say whether a credential exists, not what it is.\n if (!/^(true|false|null|)$/.test(text.slice(end, valueEnd))) {\n replacement += `\"${REDACTED}\"`;\n end = valueEnd;\n }\n }\n } else if (pending) replacement = `\"${REDACTED}\"`;\n else if (depth < 4 && /[=:\"]/.test(value)) {\n const redacted = redactText(value, depth + 1);\n if (redacted !== value)\n replacement = JSON.stringify(redacted).slice(\n 0,\n closed ? undefined : -1,\n );\n }\n out += replacement;\n last = token.lastIndex = end;\n }\n return out + pairs(text.slice(last));\n};\n\n/** Per-session redaction state: password-like fields and the values typed into them. */\nexport function createRedactor() {\n const seen = new WeakSet<Element>();\n // Latest value per field, so each keystroke replaces the previous prefix.\n const remembered = new Map<Element, string>();\n let observer: MutationObserver | undefined;\n\n const toggled = (records: MutationRecord[]) => {\n for (const record of records)\n if (record.oldValue?.toLowerCase() === \"password\")\n seen.add(record.target as Element);\n };\n\n /**\n * Replaces remembered values, raw and in their JSON and URL encodings, plus\n * `normalize(value)` when given and at least 4 characters long.\n */\n const scrub = (text: string, normalize?: (value: string) => string) => {\n for (const value of [...remembered.values()].sort(\n (a, b) => b.length - a.length,\n ))\n for (const form of [\n value,\n JSON.stringify(value).slice(1, -1),\n encodeURIComponent(value),\n new URLSearchParams({ v: value }).toString().slice(2),\n ...[normalize?.(value) ?? \"\"].filter((normal) => normal.length >= 4),\n ])\n text = /^\\d+$/.test(form)\n ? // One-time codes must not match inside longer numbers.\n text.replace(RegExp(`(?<!\\\\d)${form}(?!\\\\d)`, \"g\"), REDACTED)\n : text.split(form).join(REDACTED);\n return text;\n };\n\n /** True for current, former (show-password toggles), and autocomplete password fields. */\n const isPassword = (element: Element) => {\n if (observer) toggled(observer.takeRecords());\n if (\n !(element instanceof HTMLInputElement) ||\n !(\n element.type === \"password\" ||\n seen.has(element) ||\n isCredentialKey(element.name) ||\n PASSWORD_AUTOCOMPLETE.test(element.getAttribute(\"autocomplete\") ?? \"\")\n )\n )\n return false;\n seen.add(element);\n if (element.value.length >= 4) {\n remembered.delete(element);\n remembered.set(element, element.value);\n if (remembered.size > REMEMBERED_VALUES)\n remembered.delete(remembered.keys().next().value!);\n }\n return true;\n };\n\n return {\n isPassword,\n scrub,\n /**\n * Tracks password fields for the session: existing ones, `type` toggles away\n * from \"password\", and typed values even when input capture is off.\n */\n watch() {\n // Each part is optional: a partial DOM (tests, embedded webviews, hardened\n // pages) must not stop capture from starting or break the host app.\n try {\n for (const input of document.querySelectorAll(\"input[type=password]\"))\n seen.add(input);\n } catch {\n // Fields are still caught on first sight by isPassword.\n }\n let current: MutationObserver | undefined;\n try {\n current = new MutationObserver(toggled);\n current.observe(document, {\n subtree: true,\n attributeFilter: [\"type\"],\n attributeOldValue: true,\n });\n observer = current;\n } catch {\n current = undefined;\n }\n const remember = (event: Event) => {\n try {\n const [target] = event.composedPath();\n if (target instanceof Element) isPassword(target);\n } catch {\n // Capture must never break an edit in the host app.\n }\n };\n for (const type of [\"input\", \"change\"])\n window.addEventListener(type, remember, true);\n return () => {\n current?.disconnect();\n if (current !== undefined && observer === current) observer = undefined;\n for (const type of [\"input\", \"change\"])\n window.removeEventListener(type, remember, true);\n };\n },\n field: (key: string, value: string) =>\n isCredentialKey(key) ? REDACTED : scrub(redactText(value)),\n /** Returns the redacted body text, or undefined if redaction failed. */\n body(text: string) {\n try {\n return scrub(redactText(text.slice(0, TEXT_LIMIT)));\n } catch {\n return undefined;\n }\n },\n /** Drops userinfo and redacts credential values; also applied to element attributes. */\n url(value: string) {\n try {\n return scrub(value.replace(/[^#]+/g, (part) => redactText(part)));\n } catch {\n return REDACTED;\n }\n },\n };\n}\n\nexport type Redactor = ReturnType<typeof createRedactor>;\n","import { createRedactor, isCredentialKey } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { ClickTarget, Emit, EnrichFn } from \"./types\";\n\nconst INTERACTIVE =\n 'button, a[href], input, select, textarea, label, summary, [role], [data-copilotkit-action], [contenteditable]:not([contenteditable=\"false\"])';\nconst RECOVERY_DISTANCE_PX = 5;\n// `[role]` also matches containers such as role=\"main\"; cap their text so one\n// click cannot exceed the 16 KiB event limit and be dropped.\nconst MAX_TEXT_LENGTH = 1000;\n\n/** `closest()` that continues through shadow roots to their hosts. */\nfunction closestAcrossShadow(el: Element, selector: string) {\n let current: Element | null = el;\n while (current !== null) {\n const match = current.closest(selector);\n if (match !== null) return match;\n const root = current.getRootNode();\n current = root instanceof ShadowRoot ? root.host : null;\n }\n return null;\n}\n\ninterface Described {\n element: Element;\n target: Omit<ClickTarget, \"input\">;\n}\n\ninterface PointerOrigin {\n described: Described | null;\n x: number;\n y: number;\n}\n\n/**\n * Finds the nearest interactive element and retains its text, attributes, and value.\n * The explicit `data-copilotkit-ignore` opt-out still applies.\n */\nexport function describeTarget(el: Element, redact: Redactor) {\n if (closestAcrossShadow(el, \"[data-copilotkit-ignore]\") !== null) return null;\n const element = el.closest(INTERACTIVE) ?? el;\n // React and server markup can mirror the password into the value attribute.\n const password = redact.isPassword(element);\n const described: Described = {\n element,\n target: {\n tag: element.localName,\n role: element.getAttribute(\"role\"),\n action: element.getAttribute(\"data-copilotkit-action\"),\n text: (element.textContent ?? \"\").slice(0, MAX_TEXT_LENGTH),\n attributes: Object.fromEntries(\n Array.from(element.attributes, ({ name, value }) => [\n name,\n // Credential-named attributes (`data-api-key`) are redacted whole;\n // URL-valued ones (`href`, `action`, …) can carry credentials too.\n (password && name === \"value\") ||\n isCredentialKey(name.replace(/^data-/, \"\"))\n ? REDACTED\n : redact.url(value),\n ]),\n ),\n ...readControlValue(element, redact),\n },\n };\n return described;\n}\n\nconst MAX_LABEL_LENGTH = 80;\n// The text walk stops past these bounds. For a control's own text, that means no name.\nconst MAX_WALK_NODES = 1000;\nconst MAX_WALK_CHARS = 4 * MAX_LABEL_LENGTH;\n// Controls whose name comes from their content. An explicit role overrides the\n// tag, so `<li role=\"option\">` qualifies and `<a href role=\"row\">` does not.\nconst CONTROL_ROLE =\n /^(button|link|tab|menuitem(checkbox|radio)?|option|checkbox|switch|radio|treeitem)$/;\nconst CONTENTEDITABLE = '[contenteditable]:not([contenteditable=\"false\"])';\nconst TEXT_ENTRY = `${CONTENTEDITABLE}, [role~=textbox], [role~=searchbox], [role~=combobox]`;\nconst EDITABLE = `input, textarea, select, ${TEXT_ENTRY}`;\n// Card-like structure: a control containing it gets no name from its text,\n// except for one lone paragraph, or headings inside `summary`.\nconst HEADING = \"h1, h2, h3, h4, h5, h6, [role~=heading]\";\nconst STRUCTURE = `${HEADING}, p, ul, ol, li, dl, table, article, section, blockquote`;\nconst SKIPPED = 'script, style, template, [hidden], [aria-hidden=\"true\"]';\n// Inline elements that do not separate words.\nconst PHRASING =\n /^(b|i|u|em|strong|mark|small|sub|sup|abbr|code|kbd|s|q|cite|dfn|var|time|data|bdi|bdo|wbr|span)$/;\nconst CAPTION_INPUT = /^(submit|button|reset|image)$/;\n// Input types that do not hold typed text.\nconst NON_TEXT_INPUT =\n /^(submit|button|reset|image|checkbox|radio|range|color|file|hidden)$/;\n// Includes bidi controls, zero-width characters, soft hyphens, word joiners,\n// variation selectors, and tag characters.\nconst IGNORABLE = /\\p{Default_Ignorable_Code_Point}/gu;\n// Quantifier bounds and run-start anchors keep each pattern linear. No\n// lookbehind: a regex literal with one fails to parse in older Safari.\n// A URL ends before trailing sentence punctuation.\nconst URL_LIKE =\n /(?:\\b[a-z][\\w+.-]{0,31}:\\/\\/|\\bwww\\.)[^\\s<>\"']*[^\\s<>\"'.,;:!?)]/gi;\nconst EMAIL =\n /[\\p{L}\\p{N}_.%+-]{1,64}@[\\p{L}\\p{N}-]{1,63}(?:\\.[\\p{L}\\p{N}-]{1,63})+/gu;\n// JWTs, and three dotted segments that are each long or contain a digit, but\n// not dotted names such as `settings.notifications.preferences`.\nconst JWT =\n /(^|[^\\w-])(?:eyJ[\\w-]*\\.[\\w-]*\\.[\\w-]*|[\\w-]{16,}\\.[\\w-]{16,}\\.[\\w-]{16,}|(?=[\\w-]*\\d)[\\w-]{8,}\\.(?=[\\w-]*\\d)[\\w-]{8,}\\.(?=[\\w-]*\\d)[\\w-]{8,})/g;\nconst TOKEN_RUN = /[\\w+/=-]{24,}/g;\n\nconst roleOf = (element: Element) =>\n (element.getAttribute(\"role\") ?? \"\").trim().split(/\\s+/)[0]!.toLowerCase();\n\nconst idRefs = (element: Element, name: string) =>\n (element.getAttribute(name) ?? \"\").split(/\\s+/).filter(Boolean);\n\nconst rootOf = (element: Element) => {\n const root = element.getRootNode();\n return root instanceof Document || root instanceof ShadowRoot ? root : null;\n};\n\n/** Buttons, links with `href`, `summary`, and elements with a control role. */\nconst isControl = (element: Element) => {\n const role = roleOf(element);\n return role\n ? CONTROL_ROLE.test(role)\n : element.matches(\"button, a[href], summary\");\n};\n\n/** Text-like inputs, text areas, selects, and anything inside editable content or a text-entry role. */\nconst holdsValue = (element: Element) =>\n element instanceof HTMLInputElement\n ? !NON_TEXT_INPUT.test(element.type)\n : element.matches(\"textarea, select\") ||\n element.closest(TEXT_ENTRY) !== null;\n\n/**\n * The name an image contributes: `alt` of an `img`, or `aria-label` (else a\n * plain `<title>`) of an `svg` or `role=\"img\"` element. `undefined` when the\n * element is not an image.\n */\nfunction imageName(element: Element) {\n if (element.localName === \"img\") return element.getAttribute(\"alt\");\n if (element.localName !== \"svg\" && roleOf(element) !== \"img\")\n return undefined;\n const title = Array.from(element.children).find(\n (child) => child.localName === \"title\" && child.childElementCount === 0,\n );\n return element.getAttribute(\"aria-label\") ?? title?.textContent ?? null;\n}\n\n/**\n * Rendered text. Inline formatting joins words; other elements separate them.\n * Skips hidden subtrees, uses image names, and does\n * not walk into images. Yields nothing for editable content or editable\n * descendants. In `strict` mode (a control's own text) it also yields nothing\n * past the walk bounds, for card-like structure, and for text that looks like\n * separate fields: two `div`s that directly hold text, or three sibling\n * elements that each carry text.\n */\nfunction safeText(root: Element, strict: boolean) {\n if (holdsValue(root)) return \"\";\n let text = \"\";\n let nodes = 0;\n let paragraphs = 0;\n // The first div that holds text; a second one means separate fields.\n let div: Element | undefined;\n const bearers = new Map<Node, Set<Node>>();\n const add = (part: string) => (text = (text + part).replace(/\\s+/g, \" \"));\n // Marks `start` and its ancestors below root as carrying text. False once\n // three siblings do.\n const bear = (start: Node) => {\n if (!strict) return true;\n for (\n let child = start, parent = start.parentNode;\n child !== root && parent !== null;\n child = parent, parent = parent.parentNode\n ) {\n const siblings = bearers.get(parent) ?? new Set<Node>();\n bearers.set(parent, siblings);\n if (siblings.has(child)) break;\n if (siblings.add(child).size > 2) return false;\n }\n return true;\n };\n let node: Node | null = root.firstChild;\n while (node !== null) {\n if (++nodes > MAX_WALK_NODES || text.length > MAX_WALK_CHARS) {\n if (strict) return \"\";\n break;\n }\n let descend = false;\n if (node instanceof Text) {\n const parent = node.parentNode as Element;\n // The block that holds this text, through inline elements.\n let holder = parent;\n while (holder !== root && PHRASING.test(holder.localName))\n holder = holder.parentElement!;\n if (\n /\\S/.test(node.data) &&\n (!bear(parent) ||\n (strict && holder.localName === \"div\" && (div ??= holder) !== holder))\n )\n return \"\";\n add(node.data);\n } else if (node instanceof Element) {\n if (node.matches(EDITABLE)) return \"\";\n if (\n strict &&\n node.matches(STRUCTURE) &&\n !(root.localName === \"summary\" && node.matches(HEADING)) &&\n (node.localName !== \"p\" || ++paragraphs > 1)\n )\n return \"\";\n const name = node.matches(SKIPPED) ? null : imageName(node);\n if (name) {\n if (!bear(node)) return \"\";\n add(` ${name} `);\n } else if (name === undefined) {\n if (!PHRASING.test(node.localName)) add(\" \");\n descend = true;\n }\n }\n if (descend && node.firstChild !== null) node = node.firstChild;\n else {\n while (node !== root && node.nextSibling === null) {\n node = node.parentNode!;\n if (!PHRASING.test((node as Element).localName)) add(\" \");\n }\n node = node === root ? null : node.nextSibling;\n }\n }\n return text;\n}\n\n/** An option or tree item of an autocomplete or search popup, whose text usually repeats what the user typed. */\nconst isSuggestion = (element: Element) =>\n (element.localName === \"option\" ||\n /^(option|treeitem)$/.test(roleOf(element))) &&\n inSuggestionList(element);\n\n/** Whether `element` is, or is inside, a combobox, a datalist, or the popup a combobox or autocomplete field controls or owns. */\nfunction inSuggestionList(element: Element) {\n if (element.closest(\"[role~=combobox], datalist\") !== null) return true;\n const root = rootOf(element);\n return (\n root !== null &&\n Array.from(\n root.querySelectorAll(\"[role~=combobox], [aria-autocomplete]\"),\n ).some((owner) =>\n [...idRefs(owner, \"aria-controls\"), ...idRefs(owner, \"aria-owns\")].some(\n (id) => root.getElementById(id)?.contains(element),\n ),\n )\n );\n}\n\nfunction labelledBy(element: Element) {\n const root = rootOf(element);\n return root === null\n ? null\n : idRefs(element, \"aria-labelledby\")\n .map((id) => {\n const referenced = root.getElementById(id);\n return referenced === null || inSuggestionList(referenced)\n ? \"\"\n : safeText(referenced, false);\n })\n .join(\" \");\n}\n\n/** A control's own text, unless it is longer than a label: then it is content, not a name. */\nconst normalize = (text: string) =>\n text.replace(IGNORABLE, \"\").replace(/\\s+/g, \" \").trim();\n\nfunction contentText(element: Element) {\n const text = safeText(element, true);\n return Array.from(normalize(text)).length > MAX_LABEL_LENGTH ? \"\" : text;\n}\n\n/** Removes invisible characters, credentials, emails, URLs, and tokens, then caps the length. */\nfunction cleanLabel(raw: string, redact: Redactor) {\n const chars = Array.from(\n // Scrub again after collapsing, also for remembered values that differ\n // in whitespace or invisible characters.\n redact\n .scrub(\n normalize(redact.body(raw.replace(IGNORABLE, \"\")) ?? \"\"),\n normalize,\n )\n .replace(URL_LIKE, \"[url]\")\n .replace(EMAIL, \"[email]\")\n .replace(JWT, `$1${REDACTED}`)\n .replace(TOKEN_RUN, (run) => (/\\d/.test(run) ? REDACTED : run)),\n );\n return chars.length > MAX_LABEL_LENGTH\n ? `${chars\n .slice(0, MAX_LABEL_LENGTH - 1)\n .join(\"\")\n .trimEnd()}…`\n : chars.join(\"\");\n}\n\nfunction firstLabel(sources: (() => string | null)[], redact: Redactor) {\n for (const source of sources) {\n const label = cleanLabel(source() ?? \"\", redact);\n if (label) return label;\n }\n return undefined;\n}\n\n/**\n * A short name for the clicked control, from the first source that yields one:\n * `aria-labelledby`, `aria-label`, an input caption or `alt`, `title` (controls\n * only), then the text of a control named by its content. Containers, cards,\n * and editable content never contribute their text. An autocomplete suggestion,\n * or anything inside one, gets no label from any source; `data-copilotkit-action`\n * names it instead. An icon without its own name takes the name of the control\n * around it.\n */\nfunction clickLabel(element: Element, redact: Redactor): string | undefined {\n const option = element.closest(\"option, [role~=option], [role~=treeitem]\");\n if (option !== null && isSuggestion(option)) return undefined;\n // aria-labelledby and aria-label apply to any other target.\n const named = [\n () => labelledBy(element),\n () => element.getAttribute(\"aria-label\"),\n ];\n if (\n /^(img|svg)$/.test(element.localName) ||\n /^(img|presentation|none)$/.test(roleOf(element))\n ) {\n const own = firstLabel(\n [...named, () => imageName(element) ?? null],\n redact,\n );\n if (own !== undefined) return own;\n // parentElement is null at a shadow root, so the search stays inside it.\n let control = element.parentElement;\n while (control !== null && !isControl(control))\n control = control.parentElement;\n return control === null ? undefined : clickLabel(control, redact);\n }\n const control = isControl(element) && !holdsValue(element);\n const captionInput =\n element instanceof HTMLInputElement && CAPTION_INPUT.test(element.type);\n return firstLabel(\n [\n ...named,\n // The caption of a button-like input, or the `alt` of an image input.\n () =>\n captionInput\n ? element.type === \"image\"\n ? element.getAttribute(\"alt\")\n : element.value\n : null,\n () => (control || captionInput ? element.getAttribute(\"title\") : null),\n () => (control ? contentText(element) : null),\n ],\n redact,\n );\n}\n\n/** Snapshot live control properties; HTML attributes do not reflect edited values. */\nexport function readControlValue(element: Element, redact: Redactor) {\n if (element instanceof HTMLInputElement) {\n return {\n value: redact.isPassword(element) ? REDACTED : element.value,\n ...([\"checkbox\", \"radio\"].includes(element.type)\n ? { checked: element.checked }\n : {}),\n ...(element.type === \"file\"\n ? {\n files: Array.from(element.files ?? [], (file) => ({\n name: file.name,\n type: file.type,\n size: file.size,\n lastModified: file.lastModified,\n })),\n }\n : {}),\n };\n }\n if (element instanceof HTMLSelectElement) {\n return {\n value: element.value,\n selectedValues: Array.from(\n element.selectedOptions,\n (option) => option.value,\n ),\n };\n }\n if (element instanceof HTMLTextAreaElement) return { value: element.value };\n if (element.matches(CONTENTEDITABLE)) {\n return { value: element.textContent ?? \"\" };\n }\n return {};\n}\n\nfunction eventElement(event: Event) {\n const [first] = event.composedPath();\n return first instanceof Element ? first : null;\n}\n\nfunction isRootOrDetached(el: Element) {\n return el.localName === \"body\" || el.localName === \"html\" || !el.isConnected;\n}\n\nfunction isNear(origin: PointerOrigin, event: MouseEvent) {\n return (\n Math.abs(origin.x - event.clientX) <= RECOVERY_DISTANCE_PX &&\n Math.abs(origin.y - event.clientY) <= RECOVERY_DISTANCE_PX\n );\n}\n\n/**\n * Listens for clicks in the capture phase on `window`, so handlers that stop\n * propagation do not hide them. The target is described at `pointerdown`,\n * because a re-render before `click` can move the click to `<body>`.\n */\nexport function installClickCapture(params: {\n emit: Emit;\n getRoute: () => string;\n enrich?: EnrichFn;\n // ponytail: test seam only. jsdom cannot create trusted events; the collector never passes this.\n isTrusted?: (event: Event) => boolean;\n redact?: Redactor;\n}) {\n const {\n emit,\n getRoute,\n enrich,\n isTrusted = (event) => event.isTrusted,\n redact = createRedactor(),\n } = params;\n let origin: PointerOrigin | null = null;\n\n // Input events share describeTarget; only clicks carry a label.\n const describeClick = (el: Element) => {\n const described = describeTarget(el, redact);\n if (described === null) return null;\n try {\n const label = clickLabel(described.element, redact);\n if (label !== undefined) described.target.label = label;\n } catch {\n // A failed label must not drop the click.\n }\n return described;\n };\n\n const onPointerDown = (event: PointerEvent) => {\n try {\n if (event.isPrimary === false) return;\n const el = eventElement(event);\n origin = {\n described: el === null ? null : describeClick(el),\n x: event.clientX,\n y: event.clientY,\n };\n } catch {\n origin = null;\n }\n };\n\n const onClick = (event: MouseEvent) => {\n const pointerOrigin = origin;\n origin = null;\n try {\n if (!isTrusted(event)) return;\n const el = eventElement(event);\n if (el === null) return;\n const canRecover =\n pointerOrigin !== null &&\n isRootOrDetached(el) &&\n isNear(pointerOrigin, event);\n const described = canRecover\n ? pointerOrigin.described\n : describeClick(el);\n if (described === null) return;\n const input = event.detail === 0 ? \"keyboard\" : \"pointer\";\n emit(\"click\", {\n target: { ...described.target, input },\n route: getRoute(),\n url: redact.url(location.href),\n ...enrich?.(described.element),\n });\n } catch {\n // Capture must never break the host app's click.\n }\n };\n\n window.addEventListener(\"pointerdown\", onPointerDown, {\n capture: true,\n passive: true,\n });\n window.addEventListener(\"click\", onClick, { capture: true, passive: true });\n return () => {\n window.removeEventListener(\"pointerdown\", onPointerDown, { capture: true });\n window.removeEventListener(\"click\", onClick, { capture: true });\n };\n}\n","import { describeTarget, readControlValue } from \"./clicks\";\nimport { createRedactor } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { ClickTarget, Emit } from \"./types\";\n\nconst TEXT_DEBOUNCE_MS = 300;\nconst TEXT_INPUT_TYPES = new Set([\n \"text\",\n \"search\",\n \"tel\",\n \"url\",\n \"email\",\n \"password\",\n \"number\",\n]);\ntype ControlValue = ReturnType<typeof readControlValue>;\ninterface Edit {\n state: ControlValue;\n payload: {\n eventType: string;\n target: Omit<ClickTarget, \"input\">;\n url: string;\n route: string;\n };\n timer?: ReturnType<typeof setTimeout>;\n}\n\n/** Records settled user edits without interfering with the host app's controls. */\nexport function installInputCapture(params: {\n emit: Emit;\n isTrusted?: (event: Event) => boolean;\n redact?: Redactor;\n}) {\n const {\n emit,\n isTrusted = (event: Event) => event.isTrusted,\n redact = createRedactor(),\n } = params;\n let active = true;\n const pending = new Map<Element, Edit>();\n // A native change can echo a settled input on blur. Consume that one echo;\n // every fresh trusted input is a new edit, even if its redacted value matches.\n const changeEcho = new WeakMap<Element, string>();\n const composing = new WeakMap<Element, boolean>();\n\n const cancel = (element: Element) => {\n clearTimeout(pending.get(element)?.timer);\n pending.delete(element);\n };\n const deliver = (element: Element, edit: Edit) => {\n try {\n // Recheck privacy, but retain the observed value and route even if a host\n // handler reset or removed the control before this trailing delivery.\n if (!active || describeTarget(element, redact) === null) return;\n // A host can reset the live value before making this field sensitive.\n // Drop the old snapshot: mirrored text/attributes may contain its value.\n if (redact.isPassword(element) && edit.state.value !== REDACTED) return;\n if (edit.payload.eventType === \"input\") {\n changeEcho.set(element, JSON.stringify(edit.state));\n }\n edit.payload.url = redact.url(edit.payload.url);\n edit.payload.target.text = redact.url(edit.payload.target.text);\n edit.payload.target.attributes = Object.fromEntries(\n Object.entries(edit.payload.target.attributes).map(([key, value]) => [\n key,\n redact.url(value),\n ]),\n );\n emit(\"input\", edit.payload);\n } catch {\n // Capture must never break an edit or a later action in the host app.\n }\n };\n const flush = () => {\n // Clear before callbacks: an emit can synchronously stop or restart capture.\n const edits = [...pending];\n for (const [element] of edits) cancel(element);\n for (const [element, edit] of edits) deliver(element, edit);\n };\n const observe = (element: Element, eventType: string, settle: boolean) => {\n if (pending.size > 0 && !pending.has(element)) flush();\n if (!active) return;\n const described = describeTarget(element, redact);\n if (described === null) {\n cancel(element);\n return;\n }\n const state = readControlValue(element, redact);\n if (!(\"value\" in state)) return;\n const text =\n element instanceof HTMLTextAreaElement ||\n (element instanceof HTMLInputElement &&\n TEXT_INPUT_TYPES.has(element.type)) ||\n element.matches('[contenteditable]:not([contenteditable=\"false\"])');\n if (!text) flush();\n const signature = JSON.stringify(state);\n const echo =\n eventType === \"change\" &&\n (signature === JSON.stringify(pending.get(element)?.state) ||\n signature === changeEcho.get(element));\n changeEcho.delete(element);\n if (echo) {\n flush();\n changeEcho.delete(element);\n return;\n }\n cancel(element);\n const edit: Edit = {\n state,\n payload: {\n eventType,\n target: { ...described.target, ...state },\n url: redact.url(location.href),\n route: location.pathname,\n },\n };\n if (!text) {\n deliver(element, edit);\n return;\n }\n if (settle) {\n edit.timer = setTimeout(() => {\n cancel(element);\n deliver(element, edit);\n }, TEXT_DEBOUNCE_MS);\n }\n pending.set(element, edit);\n };\n const onEdit = (event: Event) => {\n try {\n if (!active || !isTrusted(event)) return;\n const [element] = event.composedPath();\n if (!(element instanceof Element)) return;\n if (event.type === \"compositionstart\") {\n composing.set(element, true);\n clearTimeout(pending.get(element)?.timer);\n return;\n }\n if (event.type === \"compositionend\") composing.set(element, false);\n // Keep a draft during composition for explicit action/stop flushes. An\n // end event takes precedence over a late input's stale isComposing flag.\n const inComposition =\n composing.get(element) === true ||\n (composing.get(element) !== false &&\n \"isComposing\" in event &&\n event.isComposing === true);\n observe(\n element,\n event.type === \"compositionend\" ? \"input\" : event.type,\n !inComposition,\n );\n if (event.type === \"change\") flush();\n } catch {\n // Capture must never break an edit in the host app.\n }\n };\n const onAction = (event: Event) => {\n if (event.type !== \"pagehide\" && !isTrusted(event)) return;\n if (event.type === \"keydown\") {\n const [element] = event.composedPath();\n // Window capture runs before no-form send handlers can reset the control.\n // IME completion can precede its final keydown, which still reports 229.\n if (\n !(event instanceof KeyboardEvent) ||\n event.key !== \"Enter\" ||\n event.isComposing ||\n event.keyCode === 229 ||\n (element instanceof Element && composing.get(element) === true)\n )\n return;\n }\n flush();\n };\n const editTypes = [\"input\", \"change\", \"compositionstart\", \"compositionend\"];\n const actionTypes = [\"click\", \"submit\", \"focusout\", \"pagehide\", \"keydown\"];\n for (const type of editTypes)\n window.addEventListener(type, onEdit, { capture: true, passive: true });\n for (const type of actionTypes)\n window.addEventListener(type, onAction, { capture: true, passive: true });\n const uninstall = () => {\n active = false;\n for (const element of pending.keys()) cancel(element);\n for (const type of editTypes)\n window.removeEventListener(type, onEdit, true);\n for (const type of actionTypes)\n window.removeEventListener(type, onAction, true);\n };\n return Object.assign(uninstall, { flush });\n}\n","import { createRedactor } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport type { Emit } from \"./types\";\n\ntype NavigationType = \"push\" | \"replace\" | \"traverse\" | \"reload\";\ntype HistoryMethod = \"pushState\" | \"replaceState\";\n\n/** The part of the Navigation API this module uses (not in TypeScript's DOM lib yet). */\ninterface NavigationTarget {\n addEventListener(\n type: \"currententrychange\",\n listener: (event: Event) => void,\n ): void;\n removeEventListener(\n type: \"currententrychange\",\n listener: (event: Event) => void,\n ): void;\n}\n\nfunction isNavigationTarget(value: unknown): value is NavigationTarget {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"addEventListener\" in value &&\n \"removeEventListener\" in value\n );\n}\n\nfunction getNavigation() {\n const navigation: unknown = Reflect.get(window, \"navigation\");\n return isNavigationTarget(navigation) ? navigation : null;\n}\n\nfunction toNavigationType(value: unknown): NavigationType {\n switch (value) {\n case \"replace\":\n case \"traverse\":\n case \"reload\":\n return value;\n default:\n return \"push\";\n }\n}\n\n/**\n * Emits `navigation` when the full URL changes in a single-page app.\n * Uses the Navigation API when it exists. Otherwise patches `pushState` and\n * `replaceState` on the prototype and on the instance, because some routers\n * (Next.js) wrap the instance method.\n */\nexport function installNavigationCapture(params: {\n emit: Emit;\n routes?: string[];\n redact?: Redactor;\n}) {\n const { emit, redact = createRedactor() } = params;\n let current = location.href;\n\n const check = (navigationType: NavigationType) => {\n try {\n const next = location.href;\n if (next === current) return;\n emit(\"navigation\", {\n from: redact.url(current),\n to: redact.url(next),\n navigationType,\n });\n current = next;\n } catch {\n // Capture must never break navigation.\n }\n };\n\n const navigation = getNavigation();\n if (navigation !== null) {\n const onEntryChange = (event: Event) =>\n check(toNavigationType(Reflect.get(event, \"navigationType\")));\n navigation.addEventListener(\"currententrychange\", onEntryChange);\n return () =>\n navigation.removeEventListener(\"currententrychange\", onEntryChange);\n }\n\n return installHistoryFallback(check);\n}\n\nfunction installHistoryFallback(\n check: (navigationType: NavigationType) => void,\n) {\n let active = true;\n const restores: (() => void)[] = [];\n\n const patch = (target: History, method: HistoryMethod) => {\n const original = target[method];\n const wrapper: History[HistoryMethod] = function (this: History, ...args) {\n const result = original.apply(this, args);\n if (active) check(method === \"pushState\" ? \"push\" : \"replace\");\n return result;\n };\n target[method] = wrapper;\n restores.push(() => {\n // Restore only if no one wrapped it after us; otherwise our wrapper stays as a pass-through.\n if (target[method] === wrapper) target[method] = original;\n });\n };\n\n const methods: HistoryMethod[] = [\"pushState\", \"replaceState\"];\n for (const method of methods) {\n patch(History.prototype, method);\n if (Object.prototype.hasOwnProperty.call(history, method))\n patch(history, method);\n }\n\n const onPopState = () => check(\"traverse\");\n window.addEventListener(\"popstate\", onPopState);\n window.addEventListener(\"hashchange\", onPopState);\n\n return () => {\n active = false;\n window.removeEventListener(\"popstate\", onPopState);\n window.removeEventListener(\"hashchange\", onPopState);\n for (const restore of restores) restore();\n };\n}\n","import { TEXT_LIMIT } from \"./redact\";\nimport type { Redactor } from \"./redact\";\n\n/** A bounded observation of a body; never the stream returned to the app. */\nexport interface BodySnapshot {\n status:\n | \"complete\"\n | \"empty\"\n | \"truncated\"\n | \"unavailable\"\n | \"interrupted\"\n | \"timeout\";\n text?: string;\n encoding?: \"utf-8\" | \"base64\";\n truncated?: true;\n reason?: string;\n}\n\nconst BODY_BYTES = 4096;\nconst READ_TIMEOUT_MS = 1000;\nconst encoder = new TextEncoder();\nconst redactionFailed = (): BodySnapshot => ({\n status: \"unavailable\",\n reason: \"redaction-failed\",\n});\ntype RedactText = (text: string) => string | undefined;\n\n/** Redacts up to TEXT_LIMIT bytes of text first, then cuts the result to BODY_BYTES. */\nfunction snapshot(\n bytes: Uint8Array,\n status: BodySnapshot[\"status\"],\n contentType: string,\n redact: RedactText,\n reason?: string,\n): BodySnapshot {\n let text: string | undefined;\n if (!isBinary(contentType))\n try {\n // Declared text decodes lossily so it is always redacted; untyped bytes\n // that are not UTF-8 are treated as binary.\n text = new TextDecoder(\"utf-8\", { fatal: !contentType }).decode(bytes, {\n stream: status !== \"complete\",\n });\n } catch {\n /* Not UTF-8: keep the bytes as base64. */\n }\n if (text !== undefined) {\n text = redact(text);\n if (text === undefined) return redactionFailed();\n // PostgreSQL jsonb rejects NUL in strings; base64 retains the redacted bytes.\n if (text.includes(\"\\0\")) {\n bytes = encoder.encode(text);\n text = undefined;\n }\n }\n const binary = text === undefined;\n // Binary bodies are not inspected; only their first bytes are kept.\n text ??= btoa(String.fromCharCode(...bytes.subarray(0, BODY_BYTES)));\n const result: BodySnapshot = {\n status: status === \"complete\" && bytes.length === 0 ? \"empty\" : status,\n text,\n encoding: binary ? \"base64\" : \"utf-8\",\n ...(reason ? { reason } : {}),\n };\n if (encoder.encode(JSON.stringify(result)).length <= BODY_BYTES)\n return result;\n result.status = status === \"complete\" ? \"truncated\" : status;\n result.truncated = true;\n // Bound the serialized field too: quotes/control characters expand in JSON.\n let low = 0;\n let high = text.length;\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n result.text = text.slice(0, middle);\n if (encoder.encode(JSON.stringify(result)).length <= BODY_BYTES)\n low = middle;\n else high = middle - 1;\n }\n if (binary)\n low -= low % 4; // Keep complete base64 groups.\n else if (low > 0 && /[\\uD800-\\uDBFF]/.test(text[low - 1]!)) low--;\n result.text = text.slice(0, low);\n return result;\n}\n\nfunction snapshotText(\n value: string,\n redact: RedactText,\n status: BodySnapshot[\"status\"] = \"complete\",\n reason?: string,\n): BodySnapshot {\n return snapshot(\n encoder.encode(value.slice(0, TEXT_LIMIT)),\n value.length > TEXT_LIMIT && status === \"complete\" ? \"truncated\" : status,\n \"text/plain\",\n redact,\n reason,\n );\n}\n\nfunction isBinary(contentType: string) {\n return (\n contentType !== \"\" &&\n !/(^text\\/|json|xml|javascript|graphql|x-www-form-urlencoded|multipart\\/form-data)/i.test(\n contentType,\n )\n );\n}\n\n/** Cancel only cloned/synthetic bodies. Cancelling a tee may wait for the app's branch. */\nexport function createBodyCapture(redact: Redactor) {\n const cancellations = new Set<() => void>();\n let active = true;\n const read = (\n stream: ReadableStream<Uint8Array> | null,\n contentType = \"\",\n ): Promise<BodySnapshot> => {\n if (!stream) return Promise.resolve({ status: \"empty\" });\n if (!active)\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"capture-stopped\",\n });\n let reader: ReadableStreamDefaultReader<Uint8Array>;\n try {\n reader = stream.getReader();\n } catch {\n return Promise.resolve({ status: \"unavailable\", reason: \"body-locked\" });\n }\n return new Promise((resolve) => {\n const bytes = new Uint8Array(TEXT_LIMIT);\n let length = 0;\n let finished = false;\n const finish = (status: BodySnapshot[\"status\"], reason?: string) => {\n if (finished) return;\n finished = true;\n clearTimeout(timer);\n cancellations.delete(cancel);\n resolve(\n snapshot(\n bytes.subarray(0, length),\n status,\n contentType,\n redact.body,\n reason,\n ),\n );\n // Do not await cancellation: a cloned fetch stream can share a live SSE source.\n void reader.cancel().catch(() => {});\n };\n const cancel = () => finish(\"interrupted\", \"capture-stopped\");\n const timer = setTimeout(\n () => finish(\"timeout\", \"body-read-timeout\"),\n READ_TIMEOUT_MS,\n );\n cancellations.add(cancel);\n void (async () => {\n try {\n for (;;) {\n const chunk = await reader.read();\n if (finished) break;\n if (chunk.done) {\n finish(\"complete\");\n break;\n }\n const kept = chunk.value.subarray(0, TEXT_LIMIT - length);\n bytes.set(kept, length);\n length += kept.length;\n if (length === TEXT_LIMIT) {\n finish(\"truncated\");\n break;\n }\n }\n } catch {\n finish(\"interrupted\", \"body-read-failed\");\n } finally {\n try {\n reader.releaseLock();\n } catch {\n /* A cancelled read may still be settling. */\n }\n }\n })();\n });\n };\n const body = (\n value: BodyInit | null | undefined,\n contentType = \"\",\n ): Promise<BodySnapshot> => {\n try {\n if (value == null) return Promise.resolve({ status: \"empty\" });\n if (value instanceof URLSearchParams) value = value.toString();\n if (typeof value === \"string\")\n return Promise.resolve(snapshotText(value, redact.body));\n if (\n typeof ReadableStream !== \"undefined\" &&\n value instanceof ReadableStream\n ) {\n // A caller-owned init.body cannot be teed without locking/replacing it.\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"caller-owned-stream\",\n });\n }\n if (value instanceof FormData) {\n const form = new FormData();\n value.forEach((field, key) =>\n form.append(\n key,\n typeof field === \"string\" ? redact.field(key, field) : field,\n ),\n );\n value = form;\n }\n const response = new Response(value);\n return read(\n response.body,\n contentType || response.headers.get(\"content-type\") || \"\",\n );\n } catch {\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"body-not-readable\",\n });\n }\n };\n return {\n read,\n body,\n text: (value: string, status?: BodySnapshot[\"status\"], reason?: string) =>\n snapshotText(value, redact.body, status, reason),\n stop() {\n active = false;\n for (const cancel of cancellations) cancel();\n },\n };\n}\n","import { createBodyCapture } from \"./network-body\";\nimport type { BodySnapshot } from \"./network-body\";\nimport { createRedactor, isCredentialKey } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { Emit } from \"./types\";\n\ntype Outcome = \"ok\" | \"error\" | \"aborted\";\ninterface RequestParts {\n url: string;\n method: string;\n headers: Record<string, string>;\n}\ninterface ResponseParts {\n url?: string;\n headers: Record<string, string>;\n body: Promise<BodySnapshot>;\n}\nconst emptyBody = () => Promise.resolve<BodySnapshot>({ status: \"empty\" });\nconst unavailableBody = (reason: string) =>\n Promise.resolve<BodySnapshot>({ status: \"unavailable\", reason });\nconst toAbsolute = (url: string) => new URL(url, location.href).href;\n// Credentials carry no product signal and must never leave the browser, even\n// with full capture. The header name stays, so the event still shows it was sent.\n// Names the credential-key matcher misses; it covers `authorization`, `cookie`,\n// `x-api-key`, `x-csrf-token`, and similar.\nconst CREDENTIAL_HEADERS = new Set([\n \"x-amz-security-token\",\n \"private-token\",\n \"x-token\",\n]);\nconst headerValue = (name: string, value: string) =>\n CREDENTIAL_HEADERS.has(name.toLowerCase()) || isCredentialKey(name)\n ? REDACTED\n : value;\nconst headerValues = (headers: Headers) =>\n Object.fromEntries(\n Array.from(headers.entries(), ([name, value]) => [\n name,\n headerValue(name, value),\n ]),\n );\n\n// Checks the name, not instanceof: errors can come from another realm.\nfunction isAbortError(error: unknown) {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n error.name === \"AbortError\"\n );\n}\n\n/** Records browser-visible request/response data without consuming the app's bodies. */\nexport function installNetworkCapture(params: {\n emit: Emit;\n routes?: string[];\n ignoreUrls: (string | RegExp)[];\n redact?: Redactor;\n}) {\n let active = true;\n const { redact = createRedactor() } = params;\n const bodies = createBodyCapture(redact);\n const ignoreUrls = params.ignoreUrls.map((pattern) =>\n typeof pattern === \"string\"\n ? toAbsolute(pattern)\n : new RegExp(pattern.source, pattern.flags),\n );\n const isIgnored = (url: string) =>\n ignoreUrls.some((pattern) => {\n if (typeof pattern === \"string\") return url.startsWith(pattern);\n pattern.lastIndex = 0;\n return pattern.test(url);\n });\n\n const record: RecordFn = (\n transport,\n request,\n requestBody,\n startedAt,\n status,\n outcome,\n response,\n ) => {\n const durationMs = Math.round(performance.now() - startedAt);\n const completedAt = Date.now();\n void Promise.all([\n requestBody,\n response?.body ?? unavailableBody(\"no-response\"),\n ])\n .then(([sent, received]) => {\n if (!active) return;\n const href = redact.url(request.url);\n const url = new URL(href);\n params.emit(\"network\", {\n transport,\n method: request.method,\n url: href,\n origin: url.origin,\n route: url.pathname,\n status,\n durationMs,\n completedAt,\n outcome,\n request: { headers: request.headers, body: sent },\n response: {\n ...(response?.url ? { url: redact.url(response.url) } : {}),\n headers: response?.headers ?? {},\n body: received,\n },\n });\n })\n .catch(() => {\n /* Capture must never affect the host request. */\n });\n };\n\n const originalFetch = globalThis.fetch;\n const wrappedFetch: typeof fetch = (input, init) => {\n if (!active) return originalFetch.call(globalThis, input, init);\n let request: RequestParts;\n let ignored: boolean;\n try {\n const source =\n typeof Request !== \"undefined\" && input instanceof Request\n ? input\n : undefined;\n request = {\n url: toAbsolute(source ? source.url : String(input)),\n method: (init?.method ?? source?.method ?? \"GET\").toUpperCase(),\n headers: headerValues(new Headers(init?.headers ?? source?.headers)),\n };\n ignored = isIgnored(request.url);\n } catch {\n return originalFetch.call(globalThis, input, init);\n }\n if (ignored) return originalFetch.call(globalThis, input, init);\n const startedAt = performance.now();\n let requestBody: Promise<BodySnapshot>;\n try {\n requestBody =\n init?.body != null\n ? bodies.body(init.body, request.headers[\"content-type\"])\n : typeof Request !== \"undefined\" && input instanceof Request\n ? bodies.read(input.clone().body, request.headers[\"content-type\"])\n : emptyBody();\n } catch {\n requestBody = unavailableBody(\"request-clone-failed\");\n }\n const failed = (error: unknown) =>\n record(\n \"fetch\",\n request,\n requestBody,\n startedAt,\n null,\n isAbortError(error) ? \"aborted\" : \"error\",\n );\n let promise: Promise<Response>;\n try {\n promise = originalFetch.call(globalThis, input, init);\n } catch (error) {\n failed(error);\n throw error;\n }\n void promise\n .then((response) => {\n if (!active) return;\n let responseBody: Promise<BodySnapshot>;\n try {\n responseBody =\n response.type === \"opaque\" || response.type === \"opaqueredirect\"\n ? unavailableBody(\"opaque-response\")\n : bodies.read(\n response.clone().body,\n response.headers.get(\"content-type\") ?? \"\",\n );\n } catch {\n responseBody = unavailableBody(\"response-clone-failed\");\n }\n record(\n \"fetch\",\n request,\n requestBody,\n startedAt,\n response.status,\n \"ok\",\n {\n url: response.url,\n headers: headerValues(response.headers),\n body: responseBody,\n },\n );\n }, failed)\n .catch(() => {});\n // Return the identical native Promise, Response, and rejection to the caller.\n return promise;\n };\n if (typeof originalFetch === \"function\") globalThis.fetch = wrappedFetch;\n const uninstallXhr = patchXhr(isIgnored, record, bodies);\n return () => {\n active = false;\n bodies.stop();\n if (globalThis.fetch === wrappedFetch) globalThis.fetch = originalFetch;\n uninstallXhr();\n };\n}\n\ntype RecordFn = (\n transport: \"fetch\" | \"xhr\",\n request: RequestParts,\n requestBody: Promise<BodySnapshot>,\n startedAt: number,\n status: number | null,\n outcome: Outcome,\n response?: ResponseParts,\n) => void;\n\nfunction patchXhr(\n isIgnored: (url: string) => boolean,\n record: RecordFn,\n bodies: ReturnType<typeof createBodyCapture>,\n) {\n if (typeof XMLHttpRequest !== \"function\") return () => {};\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const originalSetHeader = proto.setRequestHeader;\n const requests = new WeakMap<XMLHttpRequest, RequestParts>();\n const listeners = new Set<() => void>();\n // open() on an in-flight XHR ends it without `loadend`; its listeners must not\n // report the next request with the old request's details.\n const inFlight = new WeakMap<XMLHttpRequest, () => void>();\n let active = true;\n const wrappedOpen = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ) {\n inFlight.get(this)?.();\n const result = Reflect.apply(originalOpen, this, [method, url, ...rest]);\n try {\n requests.set(this, {\n url: toAbsolute(String(url)),\n method: method.toUpperCase(),\n headers: {},\n });\n } catch {\n requests.delete(this);\n }\n return result;\n };\n const wrappedSetHeader = function (\n this: XMLHttpRequest,\n name: string,\n value: string,\n ) {\n const result = originalSetHeader.call(this, name, value);\n const request = requests.get(this);\n if (active && request) {\n try {\n const headers = new Headers(request.headers);\n headers.append(name, value);\n request.headers = headerValues(headers);\n } catch {\n /* Preserve successful native calls even if observation fails. */\n }\n }\n return result;\n };\n const wrappedSend = function (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null,\n ) {\n const request = requests.get(this);\n if (!active || !request || isIgnored(request.url))\n return originalSend.call(this, body);\n const startedAt = performance.now();\n let requestBody: Promise<BodySnapshot>;\n try {\n requestBody =\n typeof Document !== \"undefined\" && body instanceof Document\n ? Promise.resolve(\n bodies.text(new XMLSerializer().serializeToString(body)),\n )\n : bodies.body(\n body as BodyInit | null | undefined,\n request.headers[\"content-type\"],\n );\n } catch {\n requestBody = unavailableBody(\"request-body-unavailable\");\n }\n let aborted = false;\n const onAbort = () => {\n aborted = true;\n };\n const cleanup = () => {\n this.removeEventListener(\"abort\", onAbort);\n this.removeEventListener(\"loadend\", onEnd);\n listeners.delete(cleanup);\n if (inFlight.get(this) === cleanup) inFlight.delete(this);\n };\n const onEnd = () => {\n cleanup();\n if (!active) return;\n const outcome = aborted ? \"aborted\" : this.status === 0 ? \"error\" : \"ok\";\n const headers: Record<string, string> = {};\n try {\n for (const line of this.getAllResponseHeaders().split(/\\r?\\n/)) {\n const split = line.indexOf(\":\");\n if (split > 0) {\n const name = line.slice(0, split).toLowerCase();\n headers[name] = headerValue(name, line.slice(split + 1).trim());\n }\n }\n } catch {\n /* Cross-origin or failed requests can hide response headers. */\n }\n let responseBody: Promise<BodySnapshot>;\n try {\n if (this.responseType === \"\" || this.responseType === \"text\") {\n responseBody = Promise.resolve(\n bodies.text(\n this.responseText,\n outcome === \"ok\" ? \"complete\" : \"interrupted\",\n outcome === \"ok\" ? undefined : `request-${outcome}`,\n ),\n );\n } else if (this.responseType === \"json\")\n responseBody = Promise.resolve(\n bodies.text(JSON.stringify(this.response)),\n );\n else if (this.responseType === \"document\")\n responseBody = this.responseXML\n ? Promise.resolve(\n bodies.text(\n new XMLSerializer().serializeToString(this.responseXML),\n ),\n )\n : unavailableBody(\"empty-document\");\n else\n responseBody = bodies.body(\n this.response as BodyInit,\n headers[\"content-type\"] ?? \"application/octet-stream\",\n );\n } catch {\n responseBody = unavailableBody(\"response-body-unavailable\");\n }\n record(\n \"xhr\",\n request,\n requestBody,\n startedAt,\n outcome === \"ok\" ? this.status : null,\n outcome,\n {\n url: this.responseURL,\n headers,\n body: responseBody,\n },\n );\n };\n this.addEventListener(\"abort\", onAbort);\n this.addEventListener(\"loadend\", onEnd);\n listeners.add(cleanup);\n inFlight.set(this, cleanup);\n try {\n return originalSend.call(this, body);\n } catch (error) {\n cleanup();\n record(\n \"xhr\",\n request,\n requestBody,\n startedAt,\n null,\n isAbortError(error) ? \"aborted\" : \"error\",\n );\n throw error;\n }\n };\n proto.open = wrappedOpen;\n proto.send = wrappedSend;\n proto.setRequestHeader = wrappedSetHeader;\n return () => {\n active = false;\n for (const cleanup of listeners) cleanup();\n if (proto.open === wrappedOpen) proto.open = originalOpen;\n if (proto.send === wrappedSend) proto.send = originalSend;\n if (proto.setRequestHeader === wrappedSetHeader)\n proto.setRequestHeader = originalSetHeader;\n };\n}\n","/** Returns the original pathname. Capture no longer masks or categorizes routes. */\nexport function toRoute(pathname: string, _templates: string[] = []) {\n return pathname;\n}\n\n/** Resolves a URL without removing path segments, query parameters, or fragments. */\nexport function toOriginAndRoute(\n url: string,\n _templates: string[] = [],\n base: string = globalThis.location?.href ?? \"http://localhost/\",\n) {\n const parsed = new URL(url, base);\n return { url: parsed.href, origin: parsed.origin, route: parsed.pathname };\n}\n","import { installClickCapture } from \"./clicks\";\nimport { installInputCapture } from \"./inputs\";\nimport { installNavigationCapture } from \"./navigation\";\nimport { installNetworkCapture } from \"./network\";\nimport { createRedactor } from \"./redact\";\nimport { toRoute } from \"./routes\";\nimport { BUILT_IN_EVENT_NAMES } from \"./types\";\nimport type {\n BuiltInEventName,\n Collector,\n CollectorOptions,\n LearningBatch,\n LearningEvent,\n SinkSendOptions,\n StartOptions,\n} from \"./types\";\n\n// ponytail: flushing at 50 also bounds the queue at 50; add a separate cap only if sends become async-buffered.\nconst FLUSH_SIZE = 50;\nconst FLUSH_INTERVAL_MS = 2000;\nconst BUILT_IN = new Set<string>(BUILT_IN_EVENT_NAMES);\n\ninterface Session {\n trajectoryId: string;\n learningContainerIds: string[] | undefined;\n queue: LearningEvent[];\n dropped: number;\n uninstalls: (() => void)[];\n timer: ReturnType<typeof setInterval> | undefined;\n flushInputs?: () => void;\n}\n\n/**\n * Creates a collector. Nothing is installed until `start()`: no listeners,\n * no patches, no timers, no buffer. `stop()` removes all of them and sends\n * queued events once, without retries.\n *\n * @example\n * const collector = createCollector({ sink: httpSink(\"/api/learning-events\") });\n * collector.start({ trajectoryId: crypto.randomUUID() });\n */\nexport function createCollector(options: CollectorOptions) {\n const { sink, routes, beforeSend, enrich } = options;\n const capture = {\n clicks: true,\n navigation: true,\n network: true,\n inputs: true,\n ...options.capture,\n };\n let session: Session | null = null;\n let seq = 0;\n\n const getRoute = () => toRoute(location.pathname, routes);\n\n const flush = (sendOptions?: SinkSendOptions) => {\n const current = session;\n if (current === null) return;\n if (current.queue.length === 0 && current.dropped === 0) return;\n const events = current.queue.splice(0);\n const dropped = current.dropped;\n current.dropped = 0;\n const batch: LearningBatch = {\n trajectoryId: current.trajectoryId,\n learningContainerIds: current.learningContainerIds,\n events,\n dropped,\n };\n const onFailure = () => {\n // No retry: report the loss in the next batch instead.\n if (session === current) current.dropped += events.length + dropped;\n };\n try {\n Promise.resolve(sink(batch, sendOptions)).catch(onFailure);\n } catch {\n onFailure();\n }\n };\n\n const record = (name: string, value: Record<string, unknown>) => {\n const current = session;\n if (current === null) return;\n if (name !== \"input\" && name !== \"network\") current.flushInputs?.();\n if (session !== current) return;\n try {\n seq += 1;\n const event: LearningEvent = {\n type: \"CUSTOM\",\n name,\n value: { ...value, seq },\n timestamp: Date.now(),\n };\n const kept = beforeSend === undefined ? event : beforeSend(event);\n if (kept === null || session !== current) return;\n current.queue.push(kept);\n if (current.queue.length >= FLUSH_SIZE) flush();\n } catch {\n // Capture must never break the host app.\n }\n };\n\n const start = ({ trajectoryId, learningContainerIds }: StartOptions) => {\n if (session !== null) {\n if (session.trajectoryId !== trajectoryId) {\n console.warn(\n `[@copilotkit/learning] Trajectory \"${session.trajectoryId}\" is active. Stop it before you start \"${trajectoryId}\".`,\n );\n }\n return;\n }\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener !== \"function\"\n )\n return;\n const current: Session = {\n trajectoryId,\n learningContainerIds,\n queue: [],\n dropped: 0,\n uninstalls: [],\n timer: undefined,\n };\n session = current;\n const recordCurrent: typeof record = (name, value) => {\n if (session === current) record(name, value);\n };\n // One per session: fields seen and values typed are forgotten on stop().\n const redact = createRedactor();\n current.uninstalls.push(redact.watch());\n const ignoreUrls = [\n ...(options.ignoreUrls ?? []),\n ...(sink.url === undefined ? [] : [sink.url]),\n ];\n if (capture.clicks)\n current.uninstalls.push(\n installClickCapture({ emit: recordCurrent, getRoute, enrich, redact }),\n );\n if (capture.navigation)\n current.uninstalls.push(\n installNavigationCapture({ emit: recordCurrent, routes, redact }),\n );\n if (capture.network)\n current.uninstalls.push(\n installNetworkCapture({\n emit: recordCurrent,\n routes,\n ignoreUrls,\n redact,\n }),\n );\n if (capture.inputs) {\n const inputs = installInputCapture({ emit: recordCurrent, redact });\n current.flushInputs = inputs.flush;\n current.uninstalls.push(inputs);\n }\n const onPageHide = () => flush({ beacon: true });\n window.addEventListener(\"pagehide\", onPageHide);\n current.uninstalls.push(() =>\n window.removeEventListener(\"pagehide\", onPageHide),\n );\n current.timer = setInterval(() => flush(), FLUSH_INTERVAL_MS);\n record(\"page\", {\n route: getRoute(),\n url: redact.url(location.href),\n title: document.title,\n referrer: redact.url(document.referrer),\n });\n };\n\n const stop = () => {\n const current = session;\n if (current === null) return;\n current.flushInputs?.();\n if (session !== current) return;\n clearInterval(current.timer);\n for (const uninstall of current.uninstalls) uninstall();\n flush();\n session = null;\n };\n\n const emit = (name: string, value: Record<string, unknown>) => {\n if (BUILT_IN.has(name)) {\n console.warn(\n `[@copilotkit/learning] \"${name}\" is a built-in event name. Use your own name, such as \"deal.approved\".`,\n );\n return;\n }\n record(name, value);\n };\n\n const ɵemit = (name: BuiltInEventName, value: Record<string, unknown>) =>\n record(name, value);\n\n const collector: Collector = {\n start,\n stop,\n emit,\n ɵemit,\n get trajectoryId() {\n return session?.trajectoryId ?? null;\n },\n };\n return collector;\n}\n","import type { LearningBatch, LearningSink, SinkSendOptions } from \"./types\";\n\n/**\n * A sink that POSTs each batch as JSON to `url`.\n *\n * Uses `fetch` with `keepalive`. When the page is going away it uses\n * `navigator.sendBeacon`, which cannot send custom headers. There is no retry:\n * a failed send rejects, and the collector counts those events as dropped.\n *\n * @example createCollector({ sink: httpSink(\"/api/learning-events\") })\n */\nexport function httpSink(\n url: string,\n init: { headers?: Record<string, string> } = {},\n) {\n const send = async (batch: LearningBatch, options: SinkSendOptions = {}) => {\n const body = JSON.stringify(batch);\n const canBeacon =\n options.beacon === true && typeof navigator.sendBeacon === \"function\";\n if (canBeacon) {\n const queued = navigator.sendBeacon(\n url,\n new Blob([body], { type: \"application/json\" }),\n );\n if (!queued) throw new Error(\"sendBeacon refused the batch\");\n return;\n }\n const response = await fetch(url, {\n method: \"POST\",\n keepalive: true,\n headers: { \"content-type\": \"application/json\", ...init.headers },\n body,\n });\n if (!response.ok) throw new Error(`Sink responded with ${response.status}`);\n };\n const sink: LearningSink = Object.assign(send, { url });\n return sink;\n}\n","import { installClickCapture } from \"./clicks\";\nimport { installNavigationCapture } from \"./navigation\";\nimport { installInputCapture } from \"./inputs\";\nimport { installNetworkCapture } from \"./network\";\nimport { createRedactor } from \"./redact\";\nimport { toRoute } from \"./routes\";\nimport { BUILT_IN_EVENT_NAMES } from \"./types\";\nimport type {\n JsonValue,\n TrajectoryCaptureOptions,\n TrajectoryCollector,\n TrajectoryEvent,\n} from \"./trajectory-types\";\n\nexport const MAX_TRAJECTORY_EVENT_BYTES = 16 * 1024;\nconst RESERVED_NAMES = new Set<string>(BUILT_IN_EVENT_NAMES);\n\nfunction isJson(\n value: unknown,\n ancestors = new Set<object>(),\n): value is JsonValue {\n if (typeof value === \"string\") return !value.includes(\"\\0\");\n if (value === null || typeof value === \"boolean\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || ancestors.has(value)) return false;\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n )\n return false;\n ancestors.add(value);\n if (\n !Array.isArray(value) &&\n Object.keys(value).some((key) => key.includes(\"\\0\"))\n )\n return false;\n const values = Array.isArray(value) ? value : Object.values(value);\n for (const item of values) {\n if (!isJson(item, ancestors)) return false;\n }\n ancestors.delete(value);\n return true;\n}\n\n/**\n * Captures outside-chat activity as plain AG-UI events, without a send queue.\n * Core starts this collector only after authentication and channel join.\n */\nexport function createTrajectoryCollector(\n options: TrajectoryCaptureOptions & {\n send: (event: TrajectoryEvent) => void;\n },\n): TrajectoryCollector {\n let active = false;\n let generation = 0;\n let uninstalls: (() => void)[] = [];\n let flushInputs: (() => void) | undefined;\n\n const report = (code: string, message: string) => {\n try {\n options.onError?.({ code, message });\n } catch {\n // Diagnostic callbacks must not interrupt the host app.\n }\n };\n\n const getRoute = () => toRoute(location.pathname);\n\n const record = (name: string, value: JsonValue) => {\n if (!active) return;\n const current = generation;\n if (name !== \"input\" && name !== \"network\") flushInputs?.();\n if (!active || generation !== current) return;\n let payload: TrajectoryEvent;\n try {\n const event: TrajectoryEvent = {\n type: \"CUSTOM\",\n name,\n timestamp: Date.now(),\n value,\n };\n const kept =\n options.beforeSend === undefined ? event : options.beforeSend(event);\n if (kept === null || !active || generation !== current) return;\n if (\n kept.type !== \"CUSTOM\" ||\n typeof kept.name !== \"string\" ||\n !kept.name.trim() ||\n kept.name.length > 200 ||\n kept.name.includes(\"\\0\") ||\n !Number.isFinite(kept.timestamp) ||\n kept.timestamp <= 0 ||\n kept.timestamp >= 253_402_300_800_000 ||\n !isJson(kept.value)\n ) {\n report(\n \"INVALID_EVENT\",\n \"The event must contain a name, timestamp, and JSON value.\",\n );\n return;\n }\n // Keep only the contract envelope and snapshot the value before delivery.\n const serialized = JSON.stringify({\n type: kept.type,\n name: kept.name,\n timestamp: kept.timestamp,\n value: kept.value,\n });\n if (\n new TextEncoder().encode(serialized).byteLength >\n MAX_TRAJECTORY_EVENT_BYTES\n ) {\n report(\"EVENT_TOO_LARGE\", \"The serialized event exceeds 16 KiB.\");\n return;\n }\n payload = JSON.parse(serialized) as TrajectoryEvent;\n } catch {\n report(\"INVALID_EVENT\", \"The event could not be serialized as JSON.\");\n return;\n }\n try {\n options.send(payload);\n } catch {\n report(\n \"PERSISTENCE_UNKNOWN\",\n \"Event delivery failed. The event will not be retried.\",\n );\n }\n };\n\n const capture = (name: string, value: Record<string, unknown>) => {\n // Shared capture modules produce JSON; record validates and snapshots before sending.\n record(name, value as JsonValue);\n };\n\n const stop = () => {\n const current = generation;\n const flush = flushInputs;\n flushInputs = undefined;\n flush?.();\n if (generation !== current) return;\n generation++;\n active = false;\n const installed = uninstalls;\n uninstalls = [];\n for (const uninstall of installed) uninstall();\n };\n\n return {\n start() {\n if (active || typeof window === \"undefined\") return;\n active = true;\n generation++;\n // Native callers can emit developer events without browser observers.\n if (typeof window.addEventListener !== \"function\") return;\n // One per session: fields seen and values typed are forgotten on stop().\n const redact = createRedactor();\n try {\n uninstalls.push(redact.watch());\n if (options.capture?.clicks !== false) {\n uninstalls.push(\n installClickCapture({ emit: capture, getRoute, redact }),\n );\n }\n if (options.capture?.navigation !== false) {\n uninstalls.push(installNavigationCapture({ emit: capture, redact }));\n }\n if (options.capture?.inputs !== false) {\n const inputs = installInputCapture({ emit: capture, redact });\n flushInputs = inputs.flush;\n uninstalls.push(inputs);\n }\n if (options.capture?.network !== false) {\n uninstalls.push(\n installNetworkCapture({\n emit: capture,\n ignoreUrls: options.ignoreUrls ?? [],\n redact,\n }),\n );\n }\n record(\"page\", {\n route: getRoute(),\n url: redact.url(location.href),\n title: document.title,\n referrer: redact.url(document.referrer),\n });\n } catch {\n stop();\n report(\"CAPTURE_FAILED\", \"Browser capture could not start.\");\n }\n },\n stop,\n emit(name, value) {\n if (!active) return;\n if (RESERVED_NAMES.has(name)) {\n report(\n \"INVALID_EVENT\",\n \"Use a developer event name, not a reserved capture name.\",\n );\n return;\n }\n record(name, value);\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/types.ts","../src/redact.ts","../src/clicks.ts","../src/inputs.ts","../src/navigation.ts","../src/network-body.ts","../src/network.ts","../src/routes.ts","../src/collector.ts","../src/http-sink.ts","../src/trajectory-collector.ts"],"sourcesContent":["/** Event names the collector and CopilotKit Core emit. `emit()` rejects them. */\nexport const BUILT_IN_EVENT_NAMES = [\n \"page\",\n \"navigation\",\n \"click\",\n \"input\",\n \"network\",\n \"thread.linked\",\n \"agent.run\",\n \"agent.message\",\n \"tool.call\",\n] as const;\n\nexport type BuiltInEventName = (typeof BUILT_IN_EVENT_NAMES)[number];\n\n/** Replaces values that never leave the browser, even with full capture: passwords and credentials. */\nexport const REDACTED = \"[redacted]\";\n\n/** One captured interaction, shaped as an AG-UI `CUSTOM` event. */\nexport interface LearningEvent<V = Record<string, unknown>> {\n type: \"CUSTOM\";\n name: string;\n value: V;\n timestamp: number;\n}\n\n/** What a sink receives. The Trajectory scope sits on the batch, not on each event. */\nexport interface LearningBatch {\n trajectoryId: string;\n learningContainerIds?: string[];\n events: LearningEvent[];\n /** Events lost since the previous batch (queue overflow or a failed send). */\n dropped: number;\n}\n\nexport interface SinkSendOptions {\n /** True when the page is going away; use a transport that survives unload. */\n beacon?: boolean;\n}\n\n/** Receives batches. `url`, when set, is never captured as a network event. */\nexport type LearningSink = ((\n batch: LearningBatch,\n options?: SinkSendOptions,\n) => void | Promise<void>) & { readonly url?: string };\n\nexport interface ClickTarget {\n tag: string;\n role: string | null;\n action: string | null;\n text: string;\n /**\n * Short, cleaned name of the clicked control (click events only). Comes from\n * `aria-labelledby`, `aria-label`, an input caption or `alt`, `title`, or a\n * control's own text. Omitted when no safe name exists.\n */\n label?: string;\n attributes: Record<string, string>;\n value?: string;\n checked?: boolean;\n selectedValues?: string[];\n files?: { name: string; type: string; size: number; lastModified: number }[];\n input: \"pointer\" | \"keyboard\";\n}\n\n/** Adds fields to a click event, from the element the user clicked. */\nexport type EnrichFn = (target: Element) => Record<string, unknown> | undefined;\n\nexport type Emit = (name: string, value: Record<string, unknown>) => void;\n\nexport interface CaptureOptions {\n clicks?: boolean;\n navigation?: boolean;\n network?: boolean;\n inputs?: boolean;\n}\n\nexport interface CollectorOptions {\n sink: LearningSink;\n /** URLs (prefix match on the absolute URL) or patterns that network capture skips. */\n ignoreUrls?: (string | RegExp)[];\n /** Turns capture modules on or off. All are on by default. */\n capture?: CaptureOptions;\n /** Runs last, in the browser. Return the event to send, or `null` to drop it. */\n beforeSend?: (event: LearningEvent) => LearningEvent | null;\n enrich?: EnrichFn;\n}\n\nexport interface StartOptions {\n trajectoryId: string;\n learningContainerIds?: string[];\n}\n\nexport interface Collector {\n start(options: StartOptions): void;\n stop(): void;\n /** Developer events. Built-in names warn and are ignored. */\n emit(name: string, value: Record<string, unknown>): void;\n /** @internal For @copilotkit/core only: emits built-in names. */\n ɵemit(name: BuiltInEventName, value: Record<string, unknown>): void;\n readonly trajectoryId: string | null;\n}\n","import { REDACTED } from \"./types\";\n\n// Passwords and unambiguous credentials never leave the browser, even with full\n// capture. Keys are split into lowercase words (`accessToken`, `access_token`,\n// `Access-Token` all become \"access token\"). These match anywhere in the joined words:\nconst CREDENTIAL =\n /password|passwd|passphrase|passcode|credential|api(key|token)|privatekey|subscriptionkey|(access|refresh|auth|session)token|clientsecret/;\n// These match only as whole words (`secret` but not `secretary`, `id token` but\n// not `invalid token`), as the last word (`Set-Cookie` but not `cookieConsent`),\n// or as the entire key.\nconst CREDENTIAL_WORD =\n / (secret|id ?token)s? | (authorization|cookies?|jwt|bearer ?token|[cx]srf ?token) $|^ (pwd|pass|token|otp) $/;\n// Metadata about a credential is not the credential: `passwordExpiresAt`, `credentialId`.\nconst METADATA =\n / (ids?|at|in|expires?|expiry|length|count|enabled|required|policy|hint|type) $/;\nconst PASSWORD_AUTOCOMPLETE = /(current|new)-password|one-time-code/;\n// A JSON string, possibly cut off, with the `:` that makes it a key.\nconst TOKEN = /\"((?:\\\\[\\s\\S]|[^\"\\\\])*)(\"?)(\\s*:\\s*)?/g;\n// A lone trailing backslash belongs to a cut-off string.\nconst STRING = /\"(?:\\\\[\\s\\S]?|[^\"\\\\])*\"?/y;\n// `key=value` and `key: value` outside JSON strings: forms, query strings,\n// GraphQL, YAML. A `:` needs a space or end after it, so `host:port` is no pair.\n// The key length bound keeps scanning long unbroken text linear.\n// An auth scheme (`Bearer x`) belongs to the value.\nconst PAIR =\n /([\\w$.%+[\\]-]{1,64})(\\s*(?:=|:(?=\\s|$))\\s*)((?:(?:basic|bearer|digest|token) +)?[^\\s&,;)}\\]]*)/gi;\n// `scheme://user:pass@` anywhere in text; up to the last `@` before the host.\n// The scheme length bound keeps scanning long words linear.\nconst USERINFO = /([a-z][\\w+.-]{0,31}:\\/\\/)[^\\s/?#\"]*@/gi;\n/** Text beyond this is neither redacted nor kept; snapshots keep 4 KiB of the result. */\nexport const TEXT_LIMIT = 16 * 1024;\nconst REMEMBERED_VALUES = 20;\n\nexport const isCredentialKey = (key: string) => {\n const words = ` ${key\n .replace(/%([\\da-f]{2})/gi, (_, hex: string) =>\n String.fromCharCode(parseInt(hex, 16)),\n )\n .replace(/([a-z\\d])(?=[A-Z])/g, \"$1 \")\n .toLowerCase()\n .split(/[^a-z\\d]+/)\n .filter(Boolean)\n .join(\" \")} `;\n return (\n !METADATA.test(words) &&\n (CREDENTIAL.test(words.replace(/ /g, \"\")) || CREDENTIAL_WORD.test(words))\n );\n};\n\nconst decode = (body: string) => {\n try {\n return JSON.parse(`\"${body}\"`) as string;\n } catch {\n return body;\n }\n};\n\n/** The end of the JSON value at `start`: a string, a balanced object or array, or a bare literal. */\nconst endOfValue = (text: string, start: number) => {\n let depth = 0;\n for (let i = start; i < text.length; i++) {\n const char = text[i]!;\n if (char === '\"') {\n STRING.lastIndex = i;\n STRING.test(text);\n i = STRING.lastIndex - 1;\n } else if (char === \"{\" || char === \"[\") {\n depth++;\n continue;\n } else if (char === \"}\" || char === \"]\") {\n if (--depth < 0) return i;\n } else {\n if (!depth && (char === \",\" || /\\s/.test(char))) return i;\n continue;\n }\n if (!depth) return i + 1;\n }\n return text.length;\n};\n\n/**\n * Redacts credential values in JSON (valid or cut off) and in key/value text,\n * and recurses into string values that hold JSON, forms, or URLs. Unchanged\n * parts keep their exact original text.\n */\nconst redactText = (text: string, depth = 0): string => {\n const token = new RegExp(TOKEN);\n let pending = false;\n const pairs = (part: string) => {\n const segment = part.replace(USERINFO, \"$1\");\n return segment.replace(\n PAIR,\n (pair, key: string, separator: string, value: string, offset: number) => {\n if (!isCredentialKey(key)) return pair;\n // The value may continue in a following string: `password:\"x\"`.\n if (offset + pair.length === segment.length) {\n pending = true;\n if (!value) return pair;\n }\n return key + separator + REDACTED;\n },\n );\n };\n let out = \"\";\n let last = 0;\n let match: RegExpExecArray | null;\n while ((match = token.exec(text))) {\n const [raw, body, closed, colon] = match;\n pending = false;\n out += pairs(text.slice(last, match.index));\n let end = token.lastIndex;\n let replacement = raw;\n const value = body!.includes(\"\\\\\") ? decode(body!) : body!;\n if (colon) {\n if (isCredentialKey(value)) {\n const valueEnd = endOfValue(text, end);\n // Booleans and null say whether a credential exists, not what it is.\n if (!/^(true|false|null|)$/.test(text.slice(end, valueEnd))) {\n replacement += `\"${REDACTED}\"`;\n end = valueEnd;\n }\n }\n } else if (pending) replacement = `\"${REDACTED}\"`;\n else if (depth < 4 && /[=:\"]/.test(value)) {\n const redacted = redactText(value, depth + 1);\n if (redacted !== value)\n replacement = JSON.stringify(redacted).slice(\n 0,\n closed ? undefined : -1,\n );\n }\n out += replacement;\n last = token.lastIndex = end;\n }\n return out + pairs(text.slice(last));\n};\n\n/** Per-session redaction state: password-like fields and the values typed into them. */\nexport function createRedactor() {\n const seen = new WeakSet<Element>();\n // Latest value per field, so each keystroke replaces the previous prefix.\n const remembered = new Map<Element, string>();\n let observer: MutationObserver | undefined;\n\n const toggled = (records: MutationRecord[]) => {\n for (const record of records)\n if (record.oldValue?.toLowerCase() === \"password\")\n seen.add(record.target as Element);\n };\n\n /**\n * Replaces remembered values, raw and in their JSON and URL encodings, plus\n * `normalize(value)` when given and at least 4 characters long.\n */\n const scrub = (text: string, normalize?: (value: string) => string) => {\n for (const value of [...remembered.values()].sort(\n (a, b) => b.length - a.length,\n ))\n for (const form of [\n value,\n JSON.stringify(value).slice(1, -1),\n encodeURIComponent(value),\n new URLSearchParams({ v: value }).toString().slice(2),\n ...[normalize?.(value) ?? \"\"].filter((normal) => normal.length >= 4),\n ])\n text = /^\\d+$/.test(form)\n ? // One-time codes must not match inside longer numbers.\n text.replace(RegExp(`(?<!\\\\d)${form}(?!\\\\d)`, \"g\"), REDACTED)\n : text.split(form).join(REDACTED);\n return text;\n };\n\n /** True for current, former (show-password toggles), and autocomplete password fields. */\n const isPassword = (element: Element) => {\n if (observer) toggled(observer.takeRecords());\n if (\n !(element instanceof HTMLInputElement) ||\n !(\n element.type === \"password\" ||\n seen.has(element) ||\n isCredentialKey(element.name) ||\n PASSWORD_AUTOCOMPLETE.test(element.getAttribute(\"autocomplete\") ?? \"\")\n )\n )\n return false;\n seen.add(element);\n if (element.value.length >= 4) {\n remembered.delete(element);\n remembered.set(element, element.value);\n if (remembered.size > REMEMBERED_VALUES)\n remembered.delete(remembered.keys().next().value!);\n }\n return true;\n };\n\n return {\n isPassword,\n scrub,\n /**\n * Tracks password fields for the session: existing ones, `type` toggles away\n * from \"password\", and typed values even when input capture is off.\n */\n watch() {\n // Each part is optional: a partial DOM (tests, embedded webviews, hardened\n // pages) must not stop capture from starting or break the host app.\n try {\n for (const input of document.querySelectorAll(\"input[type=password]\"))\n seen.add(input);\n } catch {\n // Fields are still caught on first sight by isPassword.\n }\n let current: MutationObserver | undefined;\n try {\n current = new MutationObserver(toggled);\n current.observe(document, {\n subtree: true,\n attributeFilter: [\"type\"],\n attributeOldValue: true,\n });\n observer = current;\n } catch {\n current = undefined;\n }\n const remember = (event: Event) => {\n try {\n const [target] = event.composedPath();\n if (target instanceof Element) isPassword(target);\n } catch {\n // Capture must never break an edit in the host app.\n }\n };\n for (const type of [\"input\", \"change\"])\n window.addEventListener(type, remember, true);\n return () => {\n current?.disconnect();\n if (current !== undefined && observer === current) observer = undefined;\n for (const type of [\"input\", \"change\"])\n window.removeEventListener(type, remember, true);\n };\n },\n field: (key: string, value: string) =>\n isCredentialKey(key) ? REDACTED : scrub(redactText(value)),\n /** Returns the redacted body text, or undefined if redaction failed. */\n body(text: string) {\n try {\n return scrub(redactText(text.slice(0, TEXT_LIMIT)));\n } catch {\n return undefined;\n }\n },\n /** Drops userinfo and redacts credential values; also applied to element attributes. */\n url(value: string) {\n try {\n return scrub(value.replace(/[^#]+/g, (part) => redactText(part)));\n } catch {\n return REDACTED;\n }\n },\n };\n}\n\nexport type Redactor = ReturnType<typeof createRedactor>;\n","import { createRedactor, isCredentialKey } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { ClickTarget, Emit, EnrichFn } from \"./types\";\n\nconst INTERACTIVE =\n 'button, a[href], input, select, textarea, label, summary, [role], [data-copilotkit-action], [contenteditable]:not([contenteditable=\"false\"])';\nconst RECOVERY_DISTANCE_PX = 5;\n// `[role]` also matches containers such as role=\"main\"; cap their text so one\n// click cannot exceed the 16 KiB event limit and be dropped.\nconst MAX_TEXT_LENGTH = 1000;\n\n/** `closest()` that continues through shadow roots to their hosts. */\nfunction closestAcrossShadow(el: Element, selector: string) {\n let current: Element | null = el;\n while (current !== null) {\n const match = current.closest(selector);\n if (match !== null) return match;\n const root = current.getRootNode();\n current = root instanceof ShadowRoot ? root.host : null;\n }\n return null;\n}\n\ninterface Described {\n element: Element;\n target: Omit<ClickTarget, \"input\">;\n}\n\ninterface PointerOrigin {\n described: Described | null;\n x: number;\n y: number;\n}\n\n/**\n * Finds the nearest interactive element and retains its text, attributes, and value.\n * The explicit `data-copilotkit-ignore` opt-out still applies.\n */\nexport function describeTarget(el: Element, redact: Redactor) {\n if (closestAcrossShadow(el, \"[data-copilotkit-ignore]\") !== null) return null;\n const element = el.closest(INTERACTIVE) ?? el;\n // React and server markup can mirror the password into the value attribute.\n const password = redact.isPassword(element);\n const described: Described = {\n element,\n target: {\n tag: element.localName,\n role: element.getAttribute(\"role\"),\n action: element.getAttribute(\"data-copilotkit-action\"),\n text: (element.textContent ?? \"\").slice(0, MAX_TEXT_LENGTH),\n attributes: Object.fromEntries(\n Array.from(element.attributes, ({ name, value }) => [\n name,\n // Credential-named attributes (`data-api-key`) are redacted whole;\n // URL-valued ones (`href`, `action`, …) can carry credentials too.\n (password && name === \"value\") ||\n isCredentialKey(name.replace(/^data-/, \"\"))\n ? REDACTED\n : redact.url(value),\n ]),\n ),\n ...readControlValue(element, redact),\n },\n };\n return described;\n}\n\nconst MAX_LABEL_LENGTH = 80;\n// The text walk stops past these bounds. For a control's own text, that means no name.\nconst MAX_WALK_NODES = 1000;\nconst MAX_WALK_CHARS = 4 * MAX_LABEL_LENGTH;\n// Controls whose name comes from their content. An explicit role overrides the\n// tag, so `<li role=\"option\">` qualifies and `<a href role=\"row\">` does not.\nconst CONTROL_ROLE =\n /^(button|link|tab|menuitem(checkbox|radio)?|option|checkbox|switch|radio|treeitem)$/;\nconst CONTENTEDITABLE = '[contenteditable]:not([contenteditable=\"false\"])';\nconst TEXT_ENTRY = `${CONTENTEDITABLE}, [role~=textbox], [role~=searchbox], [role~=combobox]`;\nconst EDITABLE = `input, textarea, select, ${TEXT_ENTRY}`;\n// Card-like structure: a control containing it gets no name from its text,\n// except for one lone paragraph, or headings inside `summary`.\nconst HEADING = \"h1, h2, h3, h4, h5, h6, [role~=heading]\";\nconst STRUCTURE = `${HEADING}, p, ul, ol, li, dl, table, article, section, blockquote`;\nconst SKIPPED = 'script, style, template, [hidden], [aria-hidden=\"true\"]';\n// Inline elements that do not separate words.\nconst PHRASING =\n /^(b|i|u|em|strong|mark|small|sub|sup|abbr|code|kbd|s|q|cite|dfn|var|time|data|bdi|bdo|wbr|span)$/;\nconst CAPTION_INPUT = /^(submit|button|reset|image)$/;\n// Input types that do not hold typed text.\nconst NON_TEXT_INPUT =\n /^(submit|button|reset|image|checkbox|radio|range|color|file|hidden)$/;\n// Includes bidi controls, zero-width characters, soft hyphens, word joiners,\n// variation selectors, and tag characters.\nconst IGNORABLE = /\\p{Default_Ignorable_Code_Point}/gu;\n// Quantifier bounds and run-start anchors keep each pattern linear. No\n// lookbehind: a regex literal with one fails to parse in older Safari.\n// A URL ends before trailing sentence punctuation.\nconst URL_LIKE =\n /(?:\\b[a-z][\\w+.-]{0,31}:\\/\\/|\\bwww\\.)[^\\s<>\"']*[^\\s<>\"'.,;:!?)]/gi;\nconst EMAIL =\n /[\\p{L}\\p{N}_.%+-]{1,64}@[\\p{L}\\p{N}-]{1,63}(?:\\.[\\p{L}\\p{N}-]{1,63})+/gu;\n// JWTs, and three dotted segments that are each long or contain a digit, but\n// not dotted names such as `settings.notifications.preferences`.\nconst JWT =\n /(^|[^\\w-])(?:eyJ[\\w-]*\\.[\\w-]*\\.[\\w-]*|[\\w-]{16,}\\.[\\w-]{16,}\\.[\\w-]{16,}|(?=[\\w-]*\\d)[\\w-]{8,}\\.(?=[\\w-]*\\d)[\\w-]{8,}\\.(?=[\\w-]*\\d)[\\w-]{8,})/g;\nconst TOKEN_RUN = /[\\w+/=-]{24,}/g;\n\nconst roleOf = (element: Element) =>\n (element.getAttribute(\"role\") ?? \"\").trim().split(/\\s+/)[0]!.toLowerCase();\n\nconst idRefs = (element: Element, name: string) =>\n (element.getAttribute(name) ?? \"\").split(/\\s+/).filter(Boolean);\n\nconst rootOf = (element: Element) => {\n const root = element.getRootNode();\n return root instanceof Document || root instanceof ShadowRoot ? root : null;\n};\n\n/** Buttons, links with `href`, `summary`, and elements with a control role. */\nconst isControl = (element: Element) => {\n const role = roleOf(element);\n return role\n ? CONTROL_ROLE.test(role)\n : element.matches(\"button, a[href], summary\");\n};\n\n/** Text-like inputs, text areas, selects, and anything inside editable content or a text-entry role. */\nconst holdsValue = (element: Element) =>\n element instanceof HTMLInputElement\n ? !NON_TEXT_INPUT.test(element.type)\n : element.matches(\"textarea, select\") ||\n element.closest(TEXT_ENTRY) !== null;\n\n/**\n * The name an image contributes: `alt` of an `img`, or `aria-label` (else a\n * plain `<title>`) of an `svg` or `role=\"img\"` element. `undefined` when the\n * element is not an image.\n */\nfunction imageName(element: Element) {\n if (element.localName === \"img\") return element.getAttribute(\"alt\");\n if (element.localName !== \"svg\" && roleOf(element) !== \"img\")\n return undefined;\n const title = Array.from(element.children).find(\n (child) => child.localName === \"title\" && child.childElementCount === 0,\n );\n return element.getAttribute(\"aria-label\") ?? title?.textContent ?? null;\n}\n\n/**\n * Rendered text. Inline formatting joins words; other elements separate them.\n * Skips hidden subtrees, uses image names, and does\n * not walk into images. Yields nothing for editable content or editable\n * descendants. In `strict` mode (a control's own text) it also yields nothing\n * past the walk bounds, for card-like structure, and for text that looks like\n * separate fields: two `div`s that directly hold text, or three sibling\n * elements that each carry text.\n */\nfunction safeText(root: Element, strict: boolean) {\n if (holdsValue(root)) return \"\";\n let text = \"\";\n let nodes = 0;\n let paragraphs = 0;\n // The first div that holds text; a second one means separate fields.\n let div: Element | undefined;\n const bearers = new Map<Node, Set<Node>>();\n const add = (part: string) => (text = (text + part).replace(/\\s+/g, \" \"));\n // Marks `start` and its ancestors below root as carrying text. False once\n // three siblings do.\n const bear = (start: Node) => {\n if (!strict) return true;\n for (\n let child = start, parent = start.parentNode;\n child !== root && parent !== null;\n child = parent, parent = parent.parentNode\n ) {\n const siblings = bearers.get(parent) ?? new Set<Node>();\n bearers.set(parent, siblings);\n if (siblings.has(child)) break;\n if (siblings.add(child).size > 2) return false;\n }\n return true;\n };\n let node: Node | null = root.firstChild;\n while (node !== null) {\n if (++nodes > MAX_WALK_NODES || text.length > MAX_WALK_CHARS) {\n if (strict) return \"\";\n break;\n }\n let descend = false;\n if (node instanceof Text) {\n const parent = node.parentNode as Element;\n // The block that holds this text, through inline elements.\n let holder = parent;\n while (holder !== root && PHRASING.test(holder.localName))\n holder = holder.parentElement!;\n if (\n /\\S/.test(node.data) &&\n (!bear(parent) ||\n (strict && holder.localName === \"div\" && (div ??= holder) !== holder))\n )\n return \"\";\n add(node.data);\n } else if (node instanceof Element) {\n if (node.matches(EDITABLE)) return \"\";\n if (\n strict &&\n node.matches(STRUCTURE) &&\n !(root.localName === \"summary\" && node.matches(HEADING)) &&\n (node.localName !== \"p\" || ++paragraphs > 1)\n )\n return \"\";\n const name = node.matches(SKIPPED) ? null : imageName(node);\n if (name) {\n if (!bear(node)) return \"\";\n add(` ${name} `);\n } else if (name === undefined) {\n if (!PHRASING.test(node.localName)) add(\" \");\n descend = true;\n }\n }\n if (descend && node.firstChild !== null) node = node.firstChild;\n else {\n while (node !== root && node.nextSibling === null) {\n node = node.parentNode!;\n if (!PHRASING.test((node as Element).localName)) add(\" \");\n }\n node = node === root ? null : node.nextSibling;\n }\n }\n return text;\n}\n\n/** An option or tree item of an autocomplete or search popup, whose text usually repeats what the user typed. */\nconst isSuggestion = (element: Element) =>\n (element.localName === \"option\" ||\n /^(option|treeitem)$/.test(roleOf(element))) &&\n inSuggestionList(element);\n\n/** Whether `element` is, or is inside, a combobox, a datalist, or the popup a combobox or autocomplete field controls or owns. */\nfunction inSuggestionList(element: Element) {\n if (element.closest(\"[role~=combobox], datalist\") !== null) return true;\n const root = rootOf(element);\n return (\n root !== null &&\n Array.from(\n root.querySelectorAll(\"[role~=combobox], [aria-autocomplete]\"),\n ).some((owner) =>\n [...idRefs(owner, \"aria-controls\"), ...idRefs(owner, \"aria-owns\")].some(\n (id) => root.getElementById(id)?.contains(element),\n ),\n )\n );\n}\n\nfunction labelledBy(element: Element) {\n const root = rootOf(element);\n return root === null\n ? null\n : idRefs(element, \"aria-labelledby\")\n .map((id) => {\n const referenced = root.getElementById(id);\n return referenced === null || inSuggestionList(referenced)\n ? \"\"\n : safeText(referenced, false);\n })\n .join(\" \");\n}\n\n/** A control's own text, unless it is longer than a label: then it is content, not a name. */\nconst normalize = (text: string) =>\n text.replace(IGNORABLE, \"\").replace(/\\s+/g, \" \").trim();\n\nfunction contentText(element: Element) {\n const text = safeText(element, true);\n return Array.from(normalize(text)).length > MAX_LABEL_LENGTH ? \"\" : text;\n}\n\n/** Removes invisible characters, credentials, emails, URLs, and tokens, then caps the length. */\nfunction cleanLabel(raw: string, redact: Redactor) {\n const chars = Array.from(\n // Scrub again after collapsing, also for remembered values that differ\n // in whitespace or invisible characters.\n redact\n .scrub(\n normalize(redact.body(raw.replace(IGNORABLE, \"\")) ?? \"\"),\n normalize,\n )\n .replace(URL_LIKE, \"[url]\")\n .replace(EMAIL, \"[email]\")\n .replace(JWT, `$1${REDACTED}`)\n .replace(TOKEN_RUN, (run) => (/\\d/.test(run) ? REDACTED : run)),\n );\n return chars.length > MAX_LABEL_LENGTH\n ? `${chars\n .slice(0, MAX_LABEL_LENGTH - 1)\n .join(\"\")\n .trimEnd()}…`\n : chars.join(\"\");\n}\n\nfunction firstLabel(sources: (() => string | null)[], redact: Redactor) {\n for (const source of sources) {\n const label = cleanLabel(source() ?? \"\", redact);\n if (label) return label;\n }\n return undefined;\n}\n\n/**\n * A short name for the clicked control, from the first source that yields one:\n * `aria-labelledby`, `aria-label`, an input caption or `alt`, `title` (controls\n * only), then the text of a control named by its content. Containers, cards,\n * and editable content never contribute their text. An autocomplete suggestion,\n * or anything inside one, gets no label from any source; `data-copilotkit-action`\n * names it instead. An icon without its own name takes the name of the control\n * around it.\n */\nfunction clickLabel(element: Element, redact: Redactor): string | undefined {\n const option = element.closest(\"option, [role~=option], [role~=treeitem]\");\n if (option !== null && isSuggestion(option)) return undefined;\n // aria-labelledby and aria-label apply to any other target.\n const named = [\n () => labelledBy(element),\n () => element.getAttribute(\"aria-label\"),\n ];\n if (\n /^(img|svg)$/.test(element.localName) ||\n /^(img|presentation|none)$/.test(roleOf(element))\n ) {\n const own = firstLabel(\n [...named, () => imageName(element) ?? null],\n redact,\n );\n if (own !== undefined) return own;\n // parentElement is null at a shadow root, so the search stays inside it.\n let control = element.parentElement;\n while (control !== null && !isControl(control))\n control = control.parentElement;\n return control === null ? undefined : clickLabel(control, redact);\n }\n const control = isControl(element) && !holdsValue(element);\n const captionInput =\n element instanceof HTMLInputElement && CAPTION_INPUT.test(element.type);\n return firstLabel(\n [\n ...named,\n // The caption of a button-like input, or the `alt` of an image input.\n () =>\n captionInput\n ? element.type === \"image\"\n ? element.getAttribute(\"alt\")\n : element.value\n : null,\n () => (control || captionInput ? element.getAttribute(\"title\") : null),\n () => (control ? contentText(element) : null),\n ],\n redact,\n );\n}\n\n/** Snapshot live control properties; HTML attributes do not reflect edited values. */\nexport function readControlValue(element: Element, redact: Redactor) {\n if (element instanceof HTMLInputElement) {\n return {\n value: redact.isPassword(element) ? REDACTED : element.value,\n ...([\"checkbox\", \"radio\"].includes(element.type)\n ? { checked: element.checked }\n : {}),\n ...(element.type === \"file\"\n ? {\n files: Array.from(element.files ?? [], (file) => ({\n name: file.name,\n type: file.type,\n size: file.size,\n lastModified: file.lastModified,\n })),\n }\n : {}),\n };\n }\n if (element instanceof HTMLSelectElement) {\n return {\n value: element.value,\n selectedValues: Array.from(\n element.selectedOptions,\n (option) => option.value,\n ),\n };\n }\n if (element instanceof HTMLTextAreaElement) return { value: element.value };\n if (element.matches(CONTENTEDITABLE)) {\n return { value: element.textContent ?? \"\" };\n }\n return {};\n}\n\nfunction eventElement(event: Event) {\n const [first] = event.composedPath();\n return first instanceof Element ? first : null;\n}\n\nfunction isRootOrDetached(el: Element) {\n return el.localName === \"body\" || el.localName === \"html\" || !el.isConnected;\n}\n\nfunction isNear(origin: PointerOrigin, event: MouseEvent) {\n return (\n Math.abs(origin.x - event.clientX) <= RECOVERY_DISTANCE_PX &&\n Math.abs(origin.y - event.clientY) <= RECOVERY_DISTANCE_PX\n );\n}\n\n/**\n * Listens for clicks in the capture phase on `window`, so handlers that stop\n * propagation do not hide them. The target is described at `pointerdown`,\n * because a re-render before `click` can move the click to `<body>`.\n */\nexport function installClickCapture(params: {\n emit: Emit;\n getRoute: () => string;\n enrich?: EnrichFn;\n // ponytail: test seam only. jsdom cannot create trusted events; the collector never passes this.\n isTrusted?: (event: Event) => boolean;\n redact?: Redactor;\n}) {\n const {\n emit,\n getRoute,\n enrich,\n isTrusted = (event) => event.isTrusted,\n redact = createRedactor(),\n } = params;\n let origin: PointerOrigin | null = null;\n\n // Input events share describeTarget; only clicks carry a label.\n const describeClick = (el: Element) => {\n const described = describeTarget(el, redact);\n if (described === null) return null;\n try {\n const label = clickLabel(described.element, redact);\n if (label !== undefined) described.target.label = label;\n } catch {\n // A failed label must not drop the click.\n }\n return described;\n };\n\n const onPointerDown = (event: PointerEvent) => {\n try {\n if (event.isPrimary === false) return;\n const el = eventElement(event);\n origin = {\n described: el === null ? null : describeClick(el),\n x: event.clientX,\n y: event.clientY,\n };\n } catch {\n origin = null;\n }\n };\n\n const onClick = (event: MouseEvent) => {\n const pointerOrigin = origin;\n origin = null;\n try {\n if (!isTrusted(event)) return;\n const el = eventElement(event);\n if (el === null) return;\n const canRecover =\n pointerOrigin !== null &&\n isRootOrDetached(el) &&\n isNear(pointerOrigin, event);\n const described = canRecover\n ? pointerOrigin.described\n : describeClick(el);\n if (described === null) return;\n const input = event.detail === 0 ? \"keyboard\" : \"pointer\";\n emit(\"click\", {\n target: { ...described.target, input },\n route: getRoute(),\n url: redact.url(location.href),\n ...enrich?.(described.element),\n });\n } catch {\n // Capture must never break the host app's click.\n }\n };\n\n window.addEventListener(\"pointerdown\", onPointerDown, {\n capture: true,\n passive: true,\n });\n window.addEventListener(\"click\", onClick, { capture: true, passive: true });\n return () => {\n window.removeEventListener(\"pointerdown\", onPointerDown, { capture: true });\n window.removeEventListener(\"click\", onClick, { capture: true });\n };\n}\n","import { describeTarget, readControlValue } from \"./clicks\";\nimport { createRedactor } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { ClickTarget, Emit } from \"./types\";\n\nconst TEXT_DEBOUNCE_MS = 300;\nconst TEXT_INPUT_TYPES = new Set([\n \"text\",\n \"search\",\n \"tel\",\n \"url\",\n \"email\",\n \"password\",\n \"number\",\n]);\ntype ControlValue = ReturnType<typeof readControlValue>;\ninterface Edit {\n state: ControlValue;\n payload: {\n eventType: string;\n target: Omit<ClickTarget, \"input\">;\n url: string;\n route: string;\n };\n timer?: ReturnType<typeof setTimeout>;\n}\n\n/** Records settled user edits without interfering with the host app's controls. */\nexport function installInputCapture(params: {\n emit: Emit;\n isTrusted?: (event: Event) => boolean;\n redact?: Redactor;\n}) {\n const {\n emit,\n isTrusted = (event: Event) => event.isTrusted,\n redact = createRedactor(),\n } = params;\n let active = true;\n const pending = new Map<Element, Edit>();\n // A native change can echo a settled input on blur. Consume that one echo;\n // every fresh trusted input is a new edit, even if its redacted value matches.\n const changeEcho = new WeakMap<Element, string>();\n const composing = new WeakMap<Element, boolean>();\n\n const cancel = (element: Element) => {\n clearTimeout(pending.get(element)?.timer);\n pending.delete(element);\n };\n const deliver = (element: Element, edit: Edit) => {\n try {\n // Recheck privacy, but retain the observed value and route even if a host\n // handler reset or removed the control before this trailing delivery.\n if (!active || describeTarget(element, redact) === null) return;\n // A host can reset the live value before making this field sensitive.\n // Drop the old snapshot: mirrored text/attributes may contain its value.\n if (redact.isPassword(element) && edit.state.value !== REDACTED) return;\n if (edit.payload.eventType === \"input\") {\n changeEcho.set(element, JSON.stringify(edit.state));\n }\n edit.payload.url = redact.url(edit.payload.url);\n edit.payload.target.text = redact.url(edit.payload.target.text);\n edit.payload.target.attributes = Object.fromEntries(\n Object.entries(edit.payload.target.attributes).map(([key, value]) => [\n key,\n redact.url(value),\n ]),\n );\n emit(\"input\", edit.payload);\n } catch {\n // Capture must never break an edit or a later action in the host app.\n }\n };\n const flush = () => {\n // Clear before callbacks: an emit can synchronously stop or restart capture.\n const edits = [...pending];\n for (const [element] of edits) cancel(element);\n for (const [element, edit] of edits) deliver(element, edit);\n };\n const observe = (element: Element, eventType: string, settle: boolean) => {\n if (pending.size > 0 && !pending.has(element)) flush();\n if (!active) return;\n const described = describeTarget(element, redact);\n if (described === null) {\n cancel(element);\n return;\n }\n const state = readControlValue(element, redact);\n if (!(\"value\" in state)) return;\n const text =\n element instanceof HTMLTextAreaElement ||\n (element instanceof HTMLInputElement &&\n TEXT_INPUT_TYPES.has(element.type)) ||\n element.matches('[contenteditable]:not([contenteditable=\"false\"])');\n if (!text) flush();\n const signature = JSON.stringify(state);\n const echo =\n eventType === \"change\" &&\n (signature === JSON.stringify(pending.get(element)?.state) ||\n signature === changeEcho.get(element));\n changeEcho.delete(element);\n if (echo) {\n flush();\n changeEcho.delete(element);\n return;\n }\n cancel(element);\n const edit: Edit = {\n state,\n payload: {\n eventType,\n target: { ...described.target, ...state },\n url: redact.url(location.href),\n route: location.pathname,\n },\n };\n if (!text) {\n deliver(element, edit);\n return;\n }\n if (settle) {\n edit.timer = setTimeout(() => {\n cancel(element);\n deliver(element, edit);\n }, TEXT_DEBOUNCE_MS);\n }\n pending.set(element, edit);\n };\n const onEdit = (event: Event) => {\n try {\n if (!active || !isTrusted(event)) return;\n const [element] = event.composedPath();\n if (!(element instanceof Element)) return;\n if (event.type === \"compositionstart\") {\n composing.set(element, true);\n clearTimeout(pending.get(element)?.timer);\n return;\n }\n if (event.type === \"compositionend\") composing.set(element, false);\n // Keep a draft during composition for explicit action/stop flushes. An\n // end event takes precedence over a late input's stale isComposing flag.\n const inComposition =\n composing.get(element) === true ||\n (composing.get(element) !== false &&\n \"isComposing\" in event &&\n event.isComposing === true);\n observe(\n element,\n event.type === \"compositionend\" ? \"input\" : event.type,\n !inComposition,\n );\n if (event.type === \"change\") flush();\n } catch {\n // Capture must never break an edit in the host app.\n }\n };\n const onAction = (event: Event) => {\n if (event.type !== \"pagehide\" && !isTrusted(event)) return;\n if (event.type === \"keydown\") {\n const [element] = event.composedPath();\n // Window capture runs before no-form send handlers can reset the control.\n // IME completion can precede its final keydown, which still reports 229.\n if (\n !(event instanceof KeyboardEvent) ||\n event.key !== \"Enter\" ||\n event.isComposing ||\n event.keyCode === 229 ||\n (element instanceof Element && composing.get(element) === true)\n )\n return;\n }\n flush();\n };\n const editTypes = [\"input\", \"change\", \"compositionstart\", \"compositionend\"];\n const actionTypes = [\"click\", \"submit\", \"focusout\", \"pagehide\", \"keydown\"];\n for (const type of editTypes)\n window.addEventListener(type, onEdit, { capture: true, passive: true });\n for (const type of actionTypes)\n window.addEventListener(type, onAction, { capture: true, passive: true });\n const uninstall = () => {\n active = false;\n for (const element of pending.keys()) cancel(element);\n for (const type of editTypes)\n window.removeEventListener(type, onEdit, true);\n for (const type of actionTypes)\n window.removeEventListener(type, onAction, true);\n };\n return Object.assign(uninstall, { flush });\n}\n","import { createRedactor } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport type { Emit } from \"./types\";\n\ntype NavigationType = \"push\" | \"replace\" | \"traverse\" | \"reload\";\ntype HistoryMethod = \"pushState\" | \"replaceState\";\n\n/** The part of the Navigation API this module uses (not in TypeScript's DOM lib yet). */\ninterface NavigationTarget {\n addEventListener(\n type: \"currententrychange\",\n listener: (event: Event) => void,\n ): void;\n removeEventListener(\n type: \"currententrychange\",\n listener: (event: Event) => void,\n ): void;\n}\n\nfunction isNavigationTarget(value: unknown): value is NavigationTarget {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"addEventListener\" in value &&\n \"removeEventListener\" in value\n );\n}\n\nfunction getNavigation() {\n const navigation: unknown = Reflect.get(window, \"navigation\");\n return isNavigationTarget(navigation) ? navigation : null;\n}\n\nfunction toNavigationType(value: unknown): NavigationType {\n switch (value) {\n case \"replace\":\n case \"traverse\":\n case \"reload\":\n return value;\n default:\n return \"push\";\n }\n}\n\n/**\n * Emits `navigation` when the full URL changes in a single-page app.\n * Uses the Navigation API when it exists. Otherwise patches `pushState` and\n * `replaceState` on the prototype and on the instance, because some routers\n * (Next.js) wrap the instance method.\n */\nexport function installNavigationCapture(params: {\n emit: Emit;\n redact?: Redactor;\n}) {\n const { emit, redact = createRedactor() } = params;\n let current = location.href;\n\n const check = (navigationType: NavigationType) => {\n try {\n const next = location.href;\n if (next === current) return;\n emit(\"navigation\", {\n from: redact.url(current),\n to: redact.url(next),\n navigationType,\n });\n current = next;\n } catch {\n // Capture must never break navigation.\n }\n };\n\n const navigation = getNavigation();\n if (navigation !== null) {\n const onEntryChange = (event: Event) =>\n check(toNavigationType(Reflect.get(event, \"navigationType\")));\n navigation.addEventListener(\"currententrychange\", onEntryChange);\n return () =>\n navigation.removeEventListener(\"currententrychange\", onEntryChange);\n }\n\n return installHistoryFallback(check);\n}\n\nfunction installHistoryFallback(\n check: (navigationType: NavigationType) => void,\n) {\n let active = true;\n const restores: (() => void)[] = [];\n\n const patch = (target: History, method: HistoryMethod) => {\n const original = target[method];\n const wrapper: History[HistoryMethod] = function (this: History, ...args) {\n const result = original.apply(this, args);\n if (active) check(method === \"pushState\" ? \"push\" : \"replace\");\n return result;\n };\n target[method] = wrapper;\n restores.push(() => {\n // Restore only if no one wrapped it after us; otherwise our wrapper stays as a pass-through.\n if (target[method] === wrapper) target[method] = original;\n });\n };\n\n const methods: HistoryMethod[] = [\"pushState\", \"replaceState\"];\n for (const method of methods) {\n patch(History.prototype, method);\n if (Object.prototype.hasOwnProperty.call(history, method))\n patch(history, method);\n }\n\n const onPopState = () => check(\"traverse\");\n window.addEventListener(\"popstate\", onPopState);\n window.addEventListener(\"hashchange\", onPopState);\n\n return () => {\n active = false;\n window.removeEventListener(\"popstate\", onPopState);\n window.removeEventListener(\"hashchange\", onPopState);\n for (const restore of restores) restore();\n };\n}\n","import { TEXT_LIMIT } from \"./redact\";\nimport type { Redactor } from \"./redact\";\n\n/** A bounded observation of a body; never the stream returned to the app. */\nexport interface BodySnapshot {\n status:\n | \"complete\"\n | \"empty\"\n | \"truncated\"\n | \"unavailable\"\n | \"interrupted\"\n | \"timeout\";\n text?: string;\n encoding?: \"utf-8\" | \"base64\";\n truncated?: true;\n reason?: string;\n}\n\nconst BODY_BYTES = 4096;\nconst READ_TIMEOUT_MS = 1000;\nconst encoder = new TextEncoder();\nconst redactionFailed = (): BodySnapshot => ({\n status: \"unavailable\",\n reason: \"redaction-failed\",\n});\ntype RedactText = (text: string) => string | undefined;\n\n/** Redacts up to TEXT_LIMIT bytes of text first, then cuts the result to BODY_BYTES. */\nfunction snapshot(\n bytes: Uint8Array,\n status: BodySnapshot[\"status\"],\n contentType: string,\n redact: RedactText,\n reason?: string,\n): BodySnapshot {\n let text: string | undefined;\n if (!isBinary(contentType))\n try {\n // Declared text decodes lossily so it is always redacted; untyped bytes\n // that are not UTF-8 are treated as binary.\n text = new TextDecoder(\"utf-8\", { fatal: !contentType }).decode(bytes, {\n stream: status !== \"complete\",\n });\n } catch {\n /* Not UTF-8: keep the bytes as base64. */\n }\n if (text !== undefined) {\n text = redact(text);\n if (text === undefined) return redactionFailed();\n // PostgreSQL jsonb rejects NUL in strings; base64 retains the redacted bytes.\n if (text.includes(\"\\0\")) {\n bytes = encoder.encode(text);\n text = undefined;\n }\n }\n const binary = text === undefined;\n // Binary bodies are not inspected; only their first bytes are kept.\n text ??= btoa(String.fromCharCode(...bytes.subarray(0, BODY_BYTES)));\n const result: BodySnapshot = {\n status: status === \"complete\" && bytes.length === 0 ? \"empty\" : status,\n text,\n encoding: binary ? \"base64\" : \"utf-8\",\n ...(reason ? { reason } : {}),\n };\n if (encoder.encode(JSON.stringify(result)).length <= BODY_BYTES)\n return result;\n result.status = status === \"complete\" ? \"truncated\" : status;\n result.truncated = true;\n // Bound the serialized field too: quotes/control characters expand in JSON.\n let low = 0;\n let high = text.length;\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n result.text = text.slice(0, middle);\n if (encoder.encode(JSON.stringify(result)).length <= BODY_BYTES)\n low = middle;\n else high = middle - 1;\n }\n if (binary)\n low -= low % 4; // Keep complete base64 groups.\n else if (low > 0 && /[\\uD800-\\uDBFF]/.test(text[low - 1]!)) low--;\n result.text = text.slice(0, low);\n return result;\n}\n\nfunction snapshotText(\n value: string,\n redact: RedactText,\n status: BodySnapshot[\"status\"] = \"complete\",\n reason?: string,\n): BodySnapshot {\n return snapshot(\n encoder.encode(value.slice(0, TEXT_LIMIT)),\n value.length > TEXT_LIMIT && status === \"complete\" ? \"truncated\" : status,\n \"text/plain\",\n redact,\n reason,\n );\n}\n\nfunction isBinary(contentType: string) {\n return (\n contentType !== \"\" &&\n !/(^text\\/|json|xml|javascript|graphql|x-www-form-urlencoded|multipart\\/form-data)/i.test(\n contentType,\n )\n );\n}\n\n/** Cancel only cloned/synthetic bodies. Cancelling a tee may wait for the app's branch. */\nexport function createBodyCapture(redact: Redactor) {\n const cancellations = new Set<() => void>();\n let active = true;\n const read = (\n stream: ReadableStream<Uint8Array> | null,\n contentType = \"\",\n ): Promise<BodySnapshot> => {\n if (!stream) return Promise.resolve({ status: \"empty\" });\n if (!active)\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"capture-stopped\",\n });\n let reader: ReadableStreamDefaultReader<Uint8Array>;\n try {\n reader = stream.getReader();\n } catch {\n return Promise.resolve({ status: \"unavailable\", reason: \"body-locked\" });\n }\n return new Promise((resolve) => {\n const bytes = new Uint8Array(TEXT_LIMIT);\n let length = 0;\n let finished = false;\n const finish = (status: BodySnapshot[\"status\"], reason?: string) => {\n if (finished) return;\n finished = true;\n clearTimeout(timer);\n cancellations.delete(cancel);\n resolve(\n snapshot(\n bytes.subarray(0, length),\n status,\n contentType,\n redact.body,\n reason,\n ),\n );\n // Do not await cancellation: a cloned fetch stream can share a live SSE source.\n void reader.cancel().catch(() => {});\n };\n const cancel = () => finish(\"interrupted\", \"capture-stopped\");\n const timer = setTimeout(\n () => finish(\"timeout\", \"body-read-timeout\"),\n READ_TIMEOUT_MS,\n );\n cancellations.add(cancel);\n void (async () => {\n try {\n for (;;) {\n const chunk = await reader.read();\n if (finished) break;\n if (chunk.done) {\n finish(\"complete\");\n break;\n }\n const kept = chunk.value.subarray(0, TEXT_LIMIT - length);\n bytes.set(kept, length);\n length += kept.length;\n if (length === TEXT_LIMIT) {\n finish(\"truncated\");\n break;\n }\n }\n } catch {\n finish(\"interrupted\", \"body-read-failed\");\n } finally {\n try {\n reader.releaseLock();\n } catch {\n /* A cancelled read may still be settling. */\n }\n }\n })();\n });\n };\n const body = (\n value: BodyInit | null | undefined,\n contentType = \"\",\n ): Promise<BodySnapshot> => {\n try {\n if (value == null) return Promise.resolve({ status: \"empty\" });\n if (value instanceof URLSearchParams) value = value.toString();\n if (typeof value === \"string\")\n return Promise.resolve(snapshotText(value, redact.body));\n if (\n typeof ReadableStream !== \"undefined\" &&\n value instanceof ReadableStream\n ) {\n // A caller-owned init.body cannot be teed without locking/replacing it.\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"caller-owned-stream\",\n });\n }\n if (value instanceof FormData) {\n const form = new FormData();\n value.forEach((field, key) =>\n form.append(\n key,\n typeof field === \"string\" ? redact.field(key, field) : field,\n ),\n );\n value = form;\n }\n const response = new Response(value);\n return read(\n response.body,\n contentType || response.headers.get(\"content-type\") || \"\",\n );\n } catch {\n return Promise.resolve({\n status: \"unavailable\",\n reason: \"body-not-readable\",\n });\n }\n };\n return {\n read,\n body,\n text: (value: string, status?: BodySnapshot[\"status\"], reason?: string) =>\n snapshotText(value, redact.body, status, reason),\n stop() {\n active = false;\n for (const cancel of cancellations) cancel();\n },\n };\n}\n","import { createBodyCapture } from \"./network-body\";\nimport type { BodySnapshot } from \"./network-body\";\nimport { createRedactor, isCredentialKey } from \"./redact\";\nimport type { Redactor } from \"./redact\";\nimport { REDACTED } from \"./types\";\nimport type { Emit } from \"./types\";\n\ntype Outcome = \"ok\" | \"error\" | \"aborted\";\ninterface RequestParts {\n url: string;\n method: string;\n headers: Record<string, string>;\n}\ninterface ResponseParts {\n url?: string;\n headers: Record<string, string>;\n body: Promise<BodySnapshot>;\n}\nconst emptyBody = () => Promise.resolve<BodySnapshot>({ status: \"empty\" });\nconst unavailableBody = (reason: string) =>\n Promise.resolve<BodySnapshot>({ status: \"unavailable\", reason });\nconst toAbsolute = (url: string) => new URL(url, location.href).href;\n// Credentials carry no product signal and must never leave the browser, even\n// with full capture. The header name stays, so the event still shows it was sent.\n// Names the credential-key matcher misses; it covers `authorization`, `cookie`,\n// `x-api-key`, `x-csrf-token`, and similar.\nconst CREDENTIAL_HEADERS = new Set([\n \"x-amz-security-token\",\n \"private-token\",\n \"x-token\",\n]);\nconst headerValue = (name: string, value: string) =>\n CREDENTIAL_HEADERS.has(name.toLowerCase()) || isCredentialKey(name)\n ? REDACTED\n : value;\nconst headerValues = (headers: Headers) =>\n Object.fromEntries(\n Array.from(headers.entries(), ([name, value]) => [\n name,\n headerValue(name, value),\n ]),\n );\n\n// Checks the name, not instanceof: errors can come from another realm.\nfunction isAbortError(error: unknown) {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"name\" in error &&\n error.name === \"AbortError\"\n );\n}\n\n/** Records browser-visible request/response data without consuming the app's bodies. */\nexport function installNetworkCapture(params: {\n emit: Emit;\n ignoreUrls: (string | RegExp)[];\n redact?: Redactor;\n}) {\n let active = true;\n const { redact = createRedactor() } = params;\n const bodies = createBodyCapture(redact);\n const ignoreUrls = params.ignoreUrls.map((pattern) =>\n typeof pattern === \"string\"\n ? toAbsolute(pattern)\n : new RegExp(pattern.source, pattern.flags),\n );\n const isIgnored = (url: string) =>\n ignoreUrls.some((pattern) => {\n if (typeof pattern === \"string\") return url.startsWith(pattern);\n pattern.lastIndex = 0;\n return pattern.test(url);\n });\n\n const record: RecordFn = (\n transport,\n request,\n requestBody,\n startedAt,\n status,\n outcome,\n response,\n ) => {\n const durationMs = Math.round(performance.now() - startedAt);\n const completedAt = Date.now();\n void Promise.all([\n requestBody,\n response?.body ?? unavailableBody(\"no-response\"),\n ])\n .then(([sent, received]) => {\n if (!active) return;\n const href = redact.url(request.url);\n const url = new URL(href);\n params.emit(\"network\", {\n transport,\n method: request.method,\n url: href,\n origin: url.origin,\n route: url.pathname,\n status,\n durationMs,\n completedAt,\n outcome,\n request: { headers: request.headers, body: sent },\n response: {\n ...(response?.url ? { url: redact.url(response.url) } : {}),\n headers: response?.headers ?? {},\n body: received,\n },\n });\n })\n .catch(() => {\n /* Capture must never affect the host request. */\n });\n };\n\n const originalFetch = globalThis.fetch;\n const wrappedFetch: typeof fetch = (input, init) => {\n if (!active) return originalFetch.call(globalThis, input, init);\n let request: RequestParts;\n let ignored: boolean;\n try {\n const source =\n typeof Request !== \"undefined\" && input instanceof Request\n ? input\n : undefined;\n request = {\n url: toAbsolute(source ? source.url : String(input)),\n method: (init?.method ?? source?.method ?? \"GET\").toUpperCase(),\n headers: headerValues(new Headers(init?.headers ?? source?.headers)),\n };\n ignored = isIgnored(request.url);\n } catch {\n return originalFetch.call(globalThis, input, init);\n }\n if (ignored) return originalFetch.call(globalThis, input, init);\n const startedAt = performance.now();\n let requestBody: Promise<BodySnapshot>;\n try {\n requestBody =\n init?.body != null\n ? bodies.body(init.body, request.headers[\"content-type\"])\n : typeof Request !== \"undefined\" && input instanceof Request\n ? bodies.read(input.clone().body, request.headers[\"content-type\"])\n : emptyBody();\n } catch {\n requestBody = unavailableBody(\"request-clone-failed\");\n }\n const failed = (error: unknown) =>\n record(\n \"fetch\",\n request,\n requestBody,\n startedAt,\n null,\n isAbortError(error) ? \"aborted\" : \"error\",\n );\n let promise: Promise<Response>;\n try {\n promise = originalFetch.call(globalThis, input, init);\n } catch (error) {\n failed(error);\n throw error;\n }\n void promise\n .then((response) => {\n if (!active) return;\n let responseBody: Promise<BodySnapshot>;\n try {\n responseBody =\n response.type === \"opaque\" || response.type === \"opaqueredirect\"\n ? unavailableBody(\"opaque-response\")\n : bodies.read(\n response.clone().body,\n response.headers.get(\"content-type\") ?? \"\",\n );\n } catch {\n responseBody = unavailableBody(\"response-clone-failed\");\n }\n record(\n \"fetch\",\n request,\n requestBody,\n startedAt,\n response.status,\n \"ok\",\n {\n url: response.url,\n headers: headerValues(response.headers),\n body: responseBody,\n },\n );\n }, failed)\n .catch(() => {});\n // Return the identical native Promise, Response, and rejection to the caller.\n return promise;\n };\n if (typeof originalFetch === \"function\") globalThis.fetch = wrappedFetch;\n const uninstallXhr = patchXhr(isIgnored, record, bodies);\n return () => {\n active = false;\n bodies.stop();\n if (globalThis.fetch === wrappedFetch) globalThis.fetch = originalFetch;\n uninstallXhr();\n };\n}\n\ntype RecordFn = (\n transport: \"fetch\" | \"xhr\",\n request: RequestParts,\n requestBody: Promise<BodySnapshot>,\n startedAt: number,\n status: number | null,\n outcome: Outcome,\n response?: ResponseParts,\n) => void;\n\nfunction patchXhr(\n isIgnored: (url: string) => boolean,\n record: RecordFn,\n bodies: ReturnType<typeof createBodyCapture>,\n) {\n if (typeof XMLHttpRequest !== \"function\") return () => {};\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const originalSetHeader = proto.setRequestHeader;\n const requests = new WeakMap<XMLHttpRequest, RequestParts>();\n const listeners = new Set<() => void>();\n // open() on an in-flight XHR ends it without `loadend`; its listeners must not\n // report the next request with the old request's details.\n const inFlight = new WeakMap<XMLHttpRequest, () => void>();\n let active = true;\n const wrappedOpen = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ) {\n inFlight.get(this)?.();\n const result = Reflect.apply(originalOpen, this, [method, url, ...rest]);\n try {\n requests.set(this, {\n url: toAbsolute(String(url)),\n method: method.toUpperCase(),\n headers: {},\n });\n } catch {\n requests.delete(this);\n }\n return result;\n };\n const wrappedSetHeader = function (\n this: XMLHttpRequest,\n name: string,\n value: string,\n ) {\n const result = originalSetHeader.call(this, name, value);\n const request = requests.get(this);\n if (active && request) {\n try {\n const headers = new Headers(request.headers);\n headers.append(name, value);\n request.headers = headerValues(headers);\n } catch {\n /* Preserve successful native calls even if observation fails. */\n }\n }\n return result;\n };\n const wrappedSend = function (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null,\n ) {\n const request = requests.get(this);\n if (!active || !request || isIgnored(request.url))\n return originalSend.call(this, body);\n const startedAt = performance.now();\n let requestBody: Promise<BodySnapshot>;\n try {\n requestBody =\n typeof Document !== \"undefined\" && body instanceof Document\n ? Promise.resolve(\n bodies.text(new XMLSerializer().serializeToString(body)),\n )\n : bodies.body(\n body as BodyInit | null | undefined,\n request.headers[\"content-type\"],\n );\n } catch {\n requestBody = unavailableBody(\"request-body-unavailable\");\n }\n let aborted = false;\n const onAbort = () => {\n aborted = true;\n };\n const cleanup = () => {\n this.removeEventListener(\"abort\", onAbort);\n this.removeEventListener(\"loadend\", onEnd);\n listeners.delete(cleanup);\n if (inFlight.get(this) === cleanup) inFlight.delete(this);\n };\n const onEnd = () => {\n cleanup();\n if (!active) return;\n const outcome = aborted ? \"aborted\" : this.status === 0 ? \"error\" : \"ok\";\n const headers: Record<string, string> = {};\n try {\n for (const line of this.getAllResponseHeaders().split(/\\r?\\n/)) {\n const split = line.indexOf(\":\");\n if (split > 0) {\n const name = line.slice(0, split).toLowerCase();\n headers[name] = headerValue(name, line.slice(split + 1).trim());\n }\n }\n } catch {\n /* Cross-origin or failed requests can hide response headers. */\n }\n let responseBody: Promise<BodySnapshot>;\n try {\n if (this.responseType === \"\" || this.responseType === \"text\") {\n responseBody = Promise.resolve(\n bodies.text(\n this.responseText,\n outcome === \"ok\" ? \"complete\" : \"interrupted\",\n outcome === \"ok\" ? undefined : `request-${outcome}`,\n ),\n );\n } else if (this.responseType === \"json\")\n responseBody = Promise.resolve(\n bodies.text(JSON.stringify(this.response)),\n );\n else if (this.responseType === \"document\")\n responseBody = this.responseXML\n ? Promise.resolve(\n bodies.text(\n new XMLSerializer().serializeToString(this.responseXML),\n ),\n )\n : unavailableBody(\"empty-document\");\n else\n responseBody = bodies.body(\n this.response as BodyInit,\n headers[\"content-type\"] ?? \"application/octet-stream\",\n );\n } catch {\n responseBody = unavailableBody(\"response-body-unavailable\");\n }\n record(\n \"xhr\",\n request,\n requestBody,\n startedAt,\n outcome === \"ok\" ? this.status : null,\n outcome,\n {\n url: this.responseURL,\n headers,\n body: responseBody,\n },\n );\n };\n this.addEventListener(\"abort\", onAbort);\n this.addEventListener(\"loadend\", onEnd);\n listeners.add(cleanup);\n inFlight.set(this, cleanup);\n try {\n return originalSend.call(this, body);\n } catch (error) {\n cleanup();\n record(\n \"xhr\",\n request,\n requestBody,\n startedAt,\n null,\n isAbortError(error) ? \"aborted\" : \"error\",\n );\n throw error;\n }\n };\n proto.open = wrappedOpen;\n proto.send = wrappedSend;\n proto.setRequestHeader = wrappedSetHeader;\n return () => {\n active = false;\n for (const cleanup of listeners) cleanup();\n if (proto.open === wrappedOpen) proto.open = originalOpen;\n if (proto.send === wrappedSend) proto.send = originalSend;\n if (proto.setRequestHeader === wrappedSetHeader)\n proto.setRequestHeader = originalSetHeader;\n };\n}\n","/** Returns the original pathname. Capture no longer masks or categorizes routes. */\nexport function toRoute(pathname: string, _templates: string[] = []) {\n return pathname;\n}\n\n/** Resolves a URL without removing path segments, query parameters, or fragments. */\nexport function toOriginAndRoute(\n url: string,\n _templates: string[] = [],\n base: string = globalThis.location?.href ?? \"http://localhost/\",\n) {\n const parsed = new URL(url, base);\n return { url: parsed.href, origin: parsed.origin, route: parsed.pathname };\n}\n","import { installClickCapture } from \"./clicks\";\nimport { installInputCapture } from \"./inputs\";\nimport { installNavigationCapture } from \"./navigation\";\nimport { installNetworkCapture } from \"./network\";\nimport { createRedactor } from \"./redact\";\nimport { toRoute } from \"./routes\";\nimport { BUILT_IN_EVENT_NAMES } from \"./types\";\nimport type {\n BuiltInEventName,\n Collector,\n CollectorOptions,\n LearningBatch,\n LearningEvent,\n SinkSendOptions,\n StartOptions,\n} from \"./types\";\n\n// ponytail: flushing at 50 also bounds the queue at 50; add a separate cap only if sends become async-buffered.\nconst FLUSH_SIZE = 50;\nconst FLUSH_INTERVAL_MS = 2000;\nconst BUILT_IN = new Set<string>(BUILT_IN_EVENT_NAMES);\n\ninterface Session {\n trajectoryId: string;\n learningContainerIds: string[] | undefined;\n queue: LearningEvent[];\n dropped: number;\n uninstalls: (() => void)[];\n timer: ReturnType<typeof setInterval> | undefined;\n flushInputs?: () => void;\n}\n\n/**\n * Creates a collector. Nothing is installed until `start()`: no listeners,\n * no patches, no timers, no buffer. `stop()` removes all of them and sends\n * queued events once, without retries.\n *\n * @example\n * const collector = createCollector({ sink: httpSink(\"/api/learning-events\") });\n * collector.start({ trajectoryId: crypto.randomUUID() });\n */\nexport function createCollector(options: CollectorOptions) {\n const { sink, beforeSend, enrich } = options;\n const capture = {\n clicks: true,\n navigation: true,\n network: true,\n inputs: true,\n ...options.capture,\n };\n let session: Session | null = null;\n let seq = 0;\n\n const getRoute = () => toRoute(location.pathname);\n\n const flush = (sendOptions?: SinkSendOptions) => {\n const current = session;\n if (current === null) return;\n if (current.queue.length === 0 && current.dropped === 0) return;\n const events = current.queue.splice(0);\n const dropped = current.dropped;\n current.dropped = 0;\n const batch: LearningBatch = {\n trajectoryId: current.trajectoryId,\n learningContainerIds: current.learningContainerIds,\n events,\n dropped,\n };\n const onFailure = () => {\n // No retry: report the loss in the next batch instead.\n if (session === current) current.dropped += events.length + dropped;\n };\n try {\n Promise.resolve(sink(batch, sendOptions)).catch(onFailure);\n } catch {\n onFailure();\n }\n };\n\n const record = (name: string, value: Record<string, unknown>) => {\n const current = session;\n if (current === null) return;\n if (name !== \"input\" && name !== \"network\") current.flushInputs?.();\n if (session !== current) return;\n try {\n seq += 1;\n const event: LearningEvent = {\n type: \"CUSTOM\",\n name,\n value: { ...value, seq },\n timestamp: Date.now(),\n };\n const kept = beforeSend === undefined ? event : beforeSend(event);\n if (kept === null || session !== current) return;\n current.queue.push(kept);\n if (current.queue.length >= FLUSH_SIZE) flush();\n } catch {\n // Capture must never break the host app.\n }\n };\n\n const start = ({ trajectoryId, learningContainerIds }: StartOptions) => {\n if (session !== null) {\n if (session.trajectoryId !== trajectoryId) {\n console.warn(\n `[@copilotkit/learning] Trajectory \"${session.trajectoryId}\" is active. Stop it before you start \"${trajectoryId}\".`,\n );\n }\n return;\n }\n if (\n typeof window === \"undefined\" ||\n typeof window.addEventListener !== \"function\"\n )\n return;\n const current: Session = {\n trajectoryId,\n learningContainerIds,\n queue: [],\n dropped: 0,\n uninstalls: [],\n timer: undefined,\n };\n session = current;\n const recordCurrent: typeof record = (name, value) => {\n if (session === current) record(name, value);\n };\n // One per session: fields seen and values typed are forgotten on stop().\n const redact = createRedactor();\n current.uninstalls.push(redact.watch());\n const ignoreUrls = [\n ...(options.ignoreUrls ?? []),\n ...(sink.url === undefined ? [] : [sink.url]),\n ];\n if (capture.clicks)\n current.uninstalls.push(\n installClickCapture({ emit: recordCurrent, getRoute, enrich, redact }),\n );\n if (capture.navigation)\n current.uninstalls.push(\n installNavigationCapture({ emit: recordCurrent, redact }),\n );\n if (capture.network)\n current.uninstalls.push(\n installNetworkCapture({\n emit: recordCurrent,\n ignoreUrls,\n redact,\n }),\n );\n if (capture.inputs) {\n const inputs = installInputCapture({ emit: recordCurrent, redact });\n current.flushInputs = inputs.flush;\n current.uninstalls.push(inputs);\n }\n const onPageHide = () => flush({ beacon: true });\n window.addEventListener(\"pagehide\", onPageHide);\n current.uninstalls.push(() =>\n window.removeEventListener(\"pagehide\", onPageHide),\n );\n current.timer = setInterval(() => flush(), FLUSH_INTERVAL_MS);\n record(\"page\", {\n route: getRoute(),\n url: redact.url(location.href),\n title: document.title,\n referrer: redact.url(document.referrer),\n });\n };\n\n const stop = () => {\n const current = session;\n if (current === null) return;\n current.flushInputs?.();\n if (session !== current) return;\n clearInterval(current.timer);\n for (const uninstall of current.uninstalls) uninstall();\n flush();\n session = null;\n };\n\n const emit = (name: string, value: Record<string, unknown>) => {\n if (BUILT_IN.has(name)) {\n console.warn(\n `[@copilotkit/learning] \"${name}\" is a built-in event name. Use your own name, such as \"deal.approved\".`,\n );\n return;\n }\n record(name, value);\n };\n\n const ɵemit = (name: BuiltInEventName, value: Record<string, unknown>) =>\n record(name, value);\n\n const collector: Collector = {\n start,\n stop,\n emit,\n ɵemit,\n get trajectoryId() {\n return session?.trajectoryId ?? null;\n },\n };\n return collector;\n}\n","import type { LearningBatch, LearningSink, SinkSendOptions } from \"./types\";\n\n/**\n * A sink that POSTs each batch as JSON to `url`.\n *\n * Uses `fetch` with `keepalive`. When the page is going away it uses\n * `navigator.sendBeacon`, which cannot send custom headers. There is no retry:\n * a failed send rejects, and the collector counts those events as dropped.\n *\n * @example createCollector({ sink: httpSink(\"/api/learning-events\") })\n */\nexport function httpSink(\n url: string,\n init: { headers?: Record<string, string> } = {},\n) {\n const send = async (batch: LearningBatch, options: SinkSendOptions = {}) => {\n const body = JSON.stringify(batch);\n const canBeacon =\n options.beacon === true && typeof navigator.sendBeacon === \"function\";\n if (canBeacon) {\n const queued = navigator.sendBeacon(\n url,\n new Blob([body], { type: \"application/json\" }),\n );\n if (!queued) throw new Error(\"sendBeacon refused the batch\");\n return;\n }\n const response = await fetch(url, {\n method: \"POST\",\n keepalive: true,\n headers: { \"content-type\": \"application/json\", ...init.headers },\n body,\n });\n if (!response.ok) throw new Error(`Sink responded with ${response.status}`);\n };\n const sink: LearningSink = Object.assign(send, { url });\n return sink;\n}\n","import { installClickCapture } from \"./clicks\";\nimport { installNavigationCapture } from \"./navigation\";\nimport { installInputCapture } from \"./inputs\";\nimport { installNetworkCapture } from \"./network\";\nimport { createRedactor } from \"./redact\";\nimport { toRoute } from \"./routes\";\nimport { BUILT_IN_EVENT_NAMES } from \"./types\";\nimport type {\n JsonValue,\n TrajectoryCaptureOptions,\n TrajectoryCollector,\n TrajectoryEvent,\n} from \"./trajectory-types\";\n\nexport const MAX_TRAJECTORY_EVENT_BYTES = 16 * 1024;\nconst RESERVED_NAMES = new Set<string>(BUILT_IN_EVENT_NAMES);\n\nfunction isJson(\n value: unknown,\n ancestors = new Set<object>(),\n): value is JsonValue {\n if (typeof value === \"string\") return !value.includes(\"\\0\");\n if (value === null || typeof value === \"boolean\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || ancestors.has(value)) return false;\n if (\n !Array.isArray(value) &&\n Object.getPrototypeOf(value) !== Object.prototype &&\n Object.getPrototypeOf(value) !== null\n )\n return false;\n ancestors.add(value);\n if (\n !Array.isArray(value) &&\n Object.keys(value).some((key) => key.includes(\"\\0\"))\n )\n return false;\n const values = Array.isArray(value) ? value : Object.values(value);\n for (const item of values) {\n if (!isJson(item, ancestors)) return false;\n }\n ancestors.delete(value);\n return true;\n}\n\n/**\n * Captures outside-chat activity as plain AG-UI events, without a send queue.\n * Core starts this collector only after authentication and channel join.\n */\nexport function createTrajectoryCollector(\n options: TrajectoryCaptureOptions & {\n send: (event: TrajectoryEvent) => void;\n },\n): TrajectoryCollector {\n let active = false;\n let generation = 0;\n let uninstalls: (() => void)[] = [];\n let flushInputs: (() => void) | undefined;\n\n const report = (code: string, message: string) => {\n try {\n options.onError?.({ code, message });\n } catch {\n // Diagnostic callbacks must not interrupt the host app.\n }\n };\n\n const getRoute = () => toRoute(location.pathname);\n\n const record = (name: string, value: JsonValue) => {\n if (!active) return;\n const current = generation;\n if (name !== \"input\" && name !== \"network\") flushInputs?.();\n if (!active || generation !== current) return;\n let payload: TrajectoryEvent;\n try {\n const event: TrajectoryEvent = {\n type: \"CUSTOM\",\n name,\n timestamp: Date.now(),\n value,\n };\n const kept =\n options.beforeSend === undefined ? event : options.beforeSend(event);\n if (kept === null || !active || generation !== current) return;\n if (\n kept.type !== \"CUSTOM\" ||\n typeof kept.name !== \"string\" ||\n !kept.name.trim() ||\n kept.name.length > 200 ||\n kept.name.includes(\"\\0\") ||\n !Number.isFinite(kept.timestamp) ||\n kept.timestamp <= 0 ||\n kept.timestamp >= 253_402_300_800_000 ||\n !isJson(kept.value)\n ) {\n report(\n \"INVALID_EVENT\",\n \"The event must contain a name, timestamp, and JSON value.\",\n );\n return;\n }\n // Keep only the contract envelope and snapshot the value before delivery.\n const serialized = JSON.stringify({\n type: kept.type,\n name: kept.name,\n timestamp: kept.timestamp,\n value: kept.value,\n });\n if (\n new TextEncoder().encode(serialized).byteLength >\n MAX_TRAJECTORY_EVENT_BYTES\n ) {\n report(\"EVENT_TOO_LARGE\", \"The serialized event exceeds 16 KiB.\");\n return;\n }\n payload = JSON.parse(serialized) as TrajectoryEvent;\n } catch {\n report(\"INVALID_EVENT\", \"The event could not be serialized as JSON.\");\n return;\n }\n try {\n options.send(payload);\n } catch {\n report(\n \"PERSISTENCE_UNKNOWN\",\n \"Event delivery failed. The event will not be retried.\",\n );\n }\n };\n\n const capture = (name: string, value: Record<string, unknown>) => {\n // Shared capture modules produce JSON; record validates and snapshots before sending.\n record(name, value as JsonValue);\n };\n\n const stop = () => {\n const current = generation;\n const flush = flushInputs;\n flushInputs = undefined;\n flush?.();\n if (generation !== current) return;\n generation++;\n active = false;\n const installed = uninstalls;\n uninstalls = [];\n for (const uninstall of installed) uninstall();\n };\n\n return {\n start() {\n if (active || typeof window === \"undefined\") return;\n active = true;\n generation++;\n // Native callers can emit developer events without browser observers.\n if (typeof window.addEventListener !== \"function\") return;\n // One per session: fields seen and values typed are forgotten on stop().\n const redact = createRedactor();\n try {\n uninstalls.push(redact.watch());\n if (options.capture?.clicks !== false) {\n uninstalls.push(\n installClickCapture({ emit: capture, getRoute, redact }),\n );\n }\n if (options.capture?.navigation !== false) {\n uninstalls.push(installNavigationCapture({ emit: capture, redact }));\n }\n if (options.capture?.inputs !== false) {\n const inputs = installInputCapture({ emit: capture, redact });\n flushInputs = inputs.flush;\n uninstalls.push(inputs);\n }\n if (options.capture?.network !== false) {\n uninstalls.push(\n installNetworkCapture({\n emit: capture,\n ignoreUrls: options.ignoreUrls ?? [],\n redact,\n }),\n );\n }\n record(\"page\", {\n route: getRoute(),\n url: redact.url(location.href),\n title: document.title,\n referrer: redact.url(document.referrer),\n });\n } catch {\n stop();\n report(\"CAPTURE_FAILED\", \"Browser capture could not start.\");\n }\n },\n stop,\n emit(name, value) {\n if (!active) return;\n if (RESERVED_NAMES.has(name)) {\n report(\n \"INVALID_EVENT\",\n \"Use a developer event name, not a reserved capture name.\",\n );\n return;\n }\n record(name, value);\n },\n };\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -58,8 +58,6 @@ interface CaptureOptions {
58
58
  }
59
59
  interface CollectorOptions {
60
60
  sink: LearningSink;
61
- /** @deprecated Capture retains raw URLs; route templates no longer transform events. */
62
- routes?: string[];
63
61
  /** URLs (prefix match on the absolute URL) or patterns that network capture skips. */
64
62
  ignoreUrls?: (string | RegExp)[];
65
63
  /** Turns capture modules on or off. All are on by default. */
@@ -149,8 +147,6 @@ interface TrajectoryError {
149
147
  message: string;
150
148
  }
151
149
  interface TrajectoryCaptureOptions {
152
- /** @deprecated Capture retains raw URLs; route templates no longer transform events. */
153
- routes?: string[];
154
150
  capture?: CaptureOptions;
155
151
  /** Explicit app exclusions, plus Core transport URLs to prevent self-capture. */
156
152
  ignoreUrls?: (string | RegExp)[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/collector.ts","../src/http-sink.ts","../src/routes.ts","../src/trajectory-types.ts","../src/trajectory-collector.ts"],"mappings":";;cACa,oBAAA;AAAA,KAYD,gBAAA,WAA2B,oBAAA;;UAMtB,aAAA,KAAkB,MAAA;EACjC,IAAA;EACA,IAAA;EACA,KAAA,EAAO,CAAA;EACP,SAAA;AAAA;;UAIe,aAAA;EACf,YAAA;EACA,oBAAA;EACA,MAAA,EAAQ,aAAA;EAVR;EAYA,OAAA;AAAA;AAAA,UAGe,eAAA;EAZf;EAcA,MAAA;AAAA;AAVF;AAAA,KAcY,YAAA,KACV,KAAA,EAAO,aAAA,EACP,OAAA,GAAU,eAAA,YACA,OAAA;EAAA,SAA4B,GAAA;AAAA;AAAA,UAEvB,WAAA;EACf,GAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EAlBO;;AAGT;;;EAqBE,KAAA;EACA,UAAA,EAAY,MAAA;EACZ,KAAA;EACA,OAAA;EACA,cAAA;EACA,KAAA;IAAU,IAAA;IAAc,IAAA;IAAc,IAAA;IAAc,YAAA;EAAA;EACpD,KAAA;AAAA;;KAIU,QAAA,IAAY,MAAA,EAAQ,OAAA,KAAY,MAAA;AAAA,UAI3B,cAAA;EACf,MAAA;EACA,UAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,gBAAA;EACf,IAAA,EAAM,YAAA;EA7BN;EA+BA,MAAA;EAxBA;EA0BA,UAAA,aAAuB,MAAA;EAzBX;EA2BZ,OAAA,GAAU,cAAA;EAzBV;EA2BA,UAAA,IAAc,KAAA,EAAO,aAAA,KAAkB,aAAA;EACvC,MAAA,GAAS,QAAA;AAAA;AAAA,UAGM,YAAA;EACf,YAAA;EACA,oBAAA;AAAA;AAAA,UAGe,SAAA;EACf,KAAA,CAAM,OAAA,EAAS,YAAA;EACf,IAAA;EA/BkB;EAiClB,IAAA,CAAK,IAAA,UAAc,KAAA,EAAO,MAAA;EAjCsB;EAmChD,KAAA,CAAM,IAAA,EAAM,gBAAA,EAAkB,KAAA,EAAO,MAAA;EAAA,SAC5B,YAAA;AAAA;;;AArGX;;;;;AAYA;;;;AAZA,iBCwCgB,eAAA,CAAgB,OAAA,EAAS,gBAAA,GAAgB,SAAA;;;ADxCzD;;;;;AAYA;;;;AAZA,iBEUgB,QAAA,CACd,GAAA,UACA,IAAA;EAAQ,OAAA,GAAU,MAAA;AAAA,IAA6B,YAAA;;;;iBCZjC,OAAA,CAAQ,QAAA,UAAkB,UAAA;;iBAK1B,gBAAA,CACd,GAAA,UACA,UAAA,aACA,IAAA;;;;;;;AHRF;AAAA,KIEY,SAAA,sCAKR,SAAA;EAAA,CACG,GAAA,WAAc,SAAA;AAAA;;UAGJ,eAAA,KAAoB,SAAA;EACnC,IAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,EAAO,CAAA;AAAA;AAAA,KAGG,WAAA;EACN,MAAA;EAAmB,YAAA;AAAA;EACnB,MAAA;EAAiB,IAAA;AAAA;AAAA,UAEN,eAAA;EACf,SAAA;EACA,QAAA;IAAY,SAAA;IAAmB,KAAA;EAAA;AAAA;AAAA,UAGhB,eAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,wBAAA;EJHP;EIKR,MAAA;EACA,OAAA,GAAU,cAAA;EJJH;EIMP,UAAA,aAAuB,MAAA;EJHO;EIK9B,UAAA,IAAc,KAAA,EAAO,eAAA,KAAoB,eAAA;EJHzC;EIKA,OAAA,IAAW,KAAA,EAAO,eAAA;AAAA;AAAA,UAGH,mBAAA;EACf,KAAA;EACA,IAAA;EACA,IAAA,CAAK,IAAA,UAAc,KAAA,EAAO,SAAA;AAAA;;;cClCf,0BAAA;;;;;iBAmCG,yBAAA,CACd,OAAA,EAAS,wBAAA;EACP,IAAA,GAAO,KAAA,EAAO,eAAA;AAAA,IAEf,mBAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/collector.ts","../src/http-sink.ts","../src/routes.ts","../src/trajectory-types.ts","../src/trajectory-collector.ts"],"mappings":";;cACa,oBAAA;AAAA,KAYD,gBAAA,WAA2B,oBAAA;;UAMtB,aAAA,KAAkB,MAAA;EACjC,IAAA;EACA,IAAA;EACA,KAAA,EAAO,CAAA;EACP,SAAA;AAAA;;UAIe,aAAA;EACf,YAAA;EACA,oBAAA;EACA,MAAA,EAAQ,aAAA;EAVR;EAYA,OAAA;AAAA;AAAA,UAGe,eAAA;EAZf;EAcA,MAAA;AAAA;AAVF;AAAA,KAcY,YAAA,KACV,KAAA,EAAO,aAAA,EACP,OAAA,GAAU,eAAA,YACA,OAAA;EAAA,SAA4B,GAAA;AAAA;AAAA,UAEvB,WAAA;EACf,GAAA;EACA,IAAA;EACA,MAAA;EACA,IAAA;EAlBO;;AAGT;;;EAqBE,KAAA;EACA,UAAA,EAAY,MAAA;EACZ,KAAA;EACA,OAAA;EACA,cAAA;EACA,KAAA;IAAU,IAAA;IAAc,IAAA;IAAc,IAAA;IAAc,YAAA;EAAA;EACpD,KAAA;AAAA;;KAIU,QAAA,IAAY,MAAA,EAAQ,OAAA,KAAY,MAAA;AAAA,UAI3B,cAAA;EACf,MAAA;EACA,UAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,gBAAA;EACf,IAAA,EAAM,YAAA;EA7BN;EA+BA,UAAA,aAAuB,MAAA;EAxBvB;EA0BA,OAAA,GAAU,cAAA;EAzBE;EA2BZ,UAAA,IAAc,KAAA,EAAO,aAAA,KAAkB,aAAA;EACvC,MAAA,GAAS,QAAA;AAAA;AAAA,UAGM,YAAA;EACf,YAAA;EACA,oBAAA;AAAA;AAAA,UAGe,SAAA;EACf,KAAA,CAAM,OAAA,EAAS,YAAA;EACf,IAAA;EAjCK;EAmCL,IAAA,CAAK,IAAA,UAAc,KAAA,EAAO,MAAA;EA/BR;EAiClB,KAAA,CAAM,IAAA,EAAM,gBAAA,EAAkB,KAAA,EAAO,MAAA;EAAA,SAC5B,YAAA;AAAA;;;AAnGX;;;;;AAYA;;;;AAZA,iBCwCgB,eAAA,CAAgB,OAAA,EAAS,gBAAA,GAAgB,SAAA;;;ADxCzD;;;;;AAYA;;;;AAZA,iBEUgB,QAAA,CACd,GAAA,UACA,IAAA;EAAQ,OAAA,GAAU,MAAA;AAAA,IAA6B,YAAA;;;;iBCZjC,OAAA,CAAQ,QAAA,UAAkB,UAAA;;iBAK1B,gBAAA,CACd,GAAA,UACA,UAAA,aACA,IAAA;;;;;;;AHRF;AAAA,KIEY,SAAA,sCAKR,SAAA;EAAA,CACG,GAAA,WAAc,SAAA;AAAA;;UAGJ,eAAA,KAAoB,SAAA;EACnC,IAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,EAAO,CAAA;AAAA;AAAA,KAGG,WAAA;EACN,MAAA;EAAmB,YAAA;AAAA;EACnB,MAAA;EAAiB,IAAA;AAAA;AAAA,UAEN,eAAA;EACf,SAAA;EACA,QAAA;IAAY,SAAA;IAAmB,KAAA;EAAA;AAAA;AAAA,UAGhB,eAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,wBAAA;EACf,OAAA,GAAU,cAAA;EJFV;EIIA,UAAA,aAAuB,MAAA;EJJhB;EIMP,UAAA,IAAc,KAAA,EAAO,eAAA,KAAoB,eAAA;EJHX;EIK9B,OAAA,IAAW,KAAA,EAAO,eAAA;AAAA;AAAA,UAGH,mBAAA;EACf,KAAA;EACA,IAAA;EACA,IAAA,CAAK,IAAA,UAAc,KAAA,EAAO,SAAA;AAAA;;;cChCf,0BAAA;;;;;iBAmCG,yBAAA,CACd,OAAA,EAAS,wBAAA;EACP,IAAA,GAAO,KAAA,EAAO,eAAA;AAAA,IAEf,mBAAA"}