@nonoun/native-chat 0.2.1 → 0.3.0

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.
@@ -177,7 +177,7 @@ var r = class extends e {
177
177
  let i = document.createElement("n-body"), a = document.createElement("n-chat-content");
178
178
  i.appendChild(a);
179
179
  let o = document.createElement("n-footer");
180
- o.setAttribute("dividers", ""), o.setAttribute("padding", "none"), this.#n = o;
180
+ o.setAttribute("dividers", ""), this.#n = o;
181
181
  let s = document.createElement("n-chat-input");
182
182
  s.setAttribute("variant", "plain");
183
183
  let c = document.createElement("n-textarea");
@@ -230,7 +230,7 @@ var r = class extends e {
230
230
  }));
231
231
  };
232
232
  }, a = 40, o = class extends e {
233
- static observedAttributes = ["auto-scroll"];
233
+ static observedAttributes = ["auto-scroll", "scrollable"];
234
234
  #e;
235
235
  #t = n(!0);
236
236
  #n = n(!0);
@@ -252,7 +252,7 @@ var r = class extends e {
252
252
  t !== n && (e === "auto-scroll" && (this.#t.value = n !== null), super.attributeChangedCallback(e, t, n));
253
253
  }
254
254
  setup() {
255
- super.setup(), this.#e.role = "log", this.setAttribute("aria-live", "polite"), this.setAttribute("aria-label", "Conversation"), this.hasAttribute("auto-scroll") || (this.#t.value = !0), this.addEventListener("scroll", this.#i, { passive: !0 }), this.#r = new MutationObserver(this.#a), this.#r.observe(this, {
255
+ super.setup(), this.#e.role = "log", this.setAttribute("aria-live", "polite"), this.setAttribute("aria-label", "Conversation"), this.hasAttribute("scrollable") || this.setAttribute("scrollable", ""), this.hasAttribute("auto-scroll") || (this.#t.value = !0), this.addEventListener("scroll", this.#i, { passive: !0 }), this.#r = new MutationObserver(this.#a), this.#r.observe(this, {
256
256
  childList: !0,
257
257
  subtree: !0
258
258
  }), this.addEventListener("native:message-action", this.#o);
@@ -1 +1 @@
1
- {"version":3,"file":"chat-panel-element.d.ts","sourceRoot":"","sources":["../src/chat-panel-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,UAAW,SAAQ,aAAa;;IAC3C,MAAM,CAAC,kBAAkB,WAAiC;IAa1D,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAepF,IAAI,QAAQ,IAAI,OAAO,CAAiC;IACxD,IAAI,QAAQ,CAAC,GAAG,EAAE,OAAO,EAGxB;IAED,IAAI,WAAW,IAAI,OAAO,CAAoC;IAC9D,IAAI,WAAW,CAAC,GAAG,EAAE,OAAO,EAG3B;IAID,KAAK,IAAI,IAAI;IA6Hb,QAAQ,IAAI,IAAI;CA6CjB"}
1
+ {"version":3,"file":"chat-panel-element.d.ts","sourceRoot":"","sources":["../src/chat-panel-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,UAAW,SAAQ,aAAa;;IAC3C,MAAM,CAAC,kBAAkB,WAAiC;IAa1D,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAepF,IAAI,QAAQ,IAAI,OAAO,CAAiC;IACxD,IAAI,QAAQ,CAAC,GAAG,EAAE,OAAO,EAGxB;IAED,IAAI,WAAW,IAAI,OAAO,CAAoC;IAC9D,IAAI,WAAW,CAAC,GAAG,EAAE,OAAO,EAG3B;IAID,KAAK,IAAI,IAAI;IA4Hb,QAAQ,IAAI,IAAI;CA6CjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-feed-element.d.ts","sourceRoot":"","sources":["../../src/feed/chat-feed-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,mBAAmB,CAAC;AAI1D;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,SAAU,SAAQ,aAAa;;IAC1C,MAAM,CAAC,kBAAkB,WAAmB;;IAc5C,IAAI,QAAQ,IAAI,OAAO,CAAiC;IAExD,wCAAwC;IACxC,cAAc,CAAC,MAAM,UAAO,GAAG,IAAI;IAUnC,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAUpF,KAAK,IAAI,IAAI;IAsBb,QAAQ,IAAI,IAAI;CAuCjB"}
1
+ {"version":3,"file":"chat-feed-element.d.ts","sourceRoot":"","sources":["../../src/feed/chat-feed-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,MAAM,mBAAmB,CAAC;AAI1D;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,SAAU,SAAQ,aAAa;;IAC1C,MAAM,CAAC,kBAAkB,WAAiC;;IAc1D,IAAI,QAAQ,IAAI,OAAO,CAAiC;IAExD,wCAAwC;IACxC,cAAc,CAAC,MAAM,UAAO,GAAG,IAAI;IAUnC,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAUpF,KAAK,IAAI,IAAI;IA4Bb,QAAQ,IAAI,IAAI;CAuCjB"}
package/dist/index.d.ts CHANGED
@@ -8,4 +8,8 @@ export type { SeedOption } from './message/chat-message-seed-element.ts';
8
8
  export type { StructuredOption } from './message/chat-input-structured-element.ts';
9
9
  export type { GenUINode } from './message/chat-message-genui-element.ts';
10
10
  export { renderMarkdown, renderInline, sanitizeHtml } from './message/chat-message-text-element.ts';
11
+ export type { ChatStreamChunk, StreamFormat, ChatTransportOptions, ChatStreamEvent, ChatTransport, } from './stream/index.ts';
12
+ export { parseSSE, parseNDJSON, parseJSON, detectFormat, createChatStream, createChatTransport, } from './stream/index.ts';
13
+ export type { TelemetryCorrelation, TelemetryTiming, TelemetryRetry, TelemetryLevel, TelemetryEvent, TelemetryRedactor, } from './telemetry/index.ts';
14
+ export { CHAT_EVENTS, SAFE_FIELDS, SENSITIVE_FIELDS, scrubPII, createDefaultRedactor, TelemetryEmitter, } from './telemetry/index.ts';
11
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAGvB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACzE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AACnF,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAGvB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACzE,YAAY,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AACnF,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAGpG,YAAY,EACV,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,QAAQ,EACR,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC"}
@@ -126,10 +126,16 @@
126
126
  gap: var(--n-chat-gap);
127
127
  flex: 1 1 0%;
128
128
  min-height: 0;
129
+ min-width: 0;
130
+ padding-block: calc(var(--n-space) * 4);
131
+ }
132
+
133
+ /* WHY: Opt-in scroll container — prevents layout conflicts when scroll
134
+ ownership belongs to a parent container. */
135
+ [scrollable]:where(n-chat-feed) {
129
136
  overflow-y: auto;
130
137
  scrollbar-width: thin;
131
138
  scroll-behavior: smooth;
132
- padding-block: calc(var(--n-space) * 4);
133
139
  }
134
140
 
135
141
  /* ── Date separator ── */
@@ -156,6 +162,7 @@
156
162
  align-items: flex-start;
157
163
  gap: var(--n-chat-message-gap);
158
164
  align-self: flex-start;
165
+ min-width: 0;
159
166
  }
160
167
 
161
168
  /* User messages: right-aligned, avatar on right */
@@ -1,2 +1,323 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./chat-input-structured-element-CbDnI4zv.js";
2
- export { n as NChatAvatar, r as NChatFeed, o as NChatInput, f as NChatInputStructured, p as NChatMessage, i as NChatMessageActivity, s as NChatMessageGenUI, u as NChatMessageSeed, e as NChatMessageText, a as NChatMessages, l as NChatPanel, c as renderInline, d as renderMarkdown, t as sanitizeHtml };
1
+ import { a as e, c as t, d as n, f as r, i, l as a, m as o, n as s, o as c, p as l, r as u, s as d, t as f, u as p } from "./chat-input-structured-element-Cpar3CeA.js";
2
+ /**
3
+ * Parse a Server-Sent Events (SSE) response stream into ChatStreamChunk values.
4
+ *
5
+ * Reads `data:` lines from the response body, skips empty lines and comments,
6
+ * handles the `[DONE]` sentinel, and accumulates the full message across chunks.
7
+ */
8
+ async function* m(e) {
9
+ let t = e.body.getReader(), n = new TextDecoder("utf-8"), r = "", i = "";
10
+ try {
11
+ for (;;) {
12
+ let { done: e, value: a } = await t.read();
13
+ if (e) break;
14
+ r += n.decode(a, { stream: !0 });
15
+ let o = r.split("\n");
16
+ r = o.pop() ?? "";
17
+ for (let e of o) {
18
+ let t = e.trim();
19
+ if (t === "" || t.startsWith(":") || !t.startsWith("data:")) continue;
20
+ let n = t.slice(5).trim();
21
+ if (n === "[DONE]") {
22
+ yield {
23
+ delta: "",
24
+ fullMessage: i,
25
+ role: "assistant",
26
+ datetime: Date.now(),
27
+ done: !0
28
+ };
29
+ return;
30
+ }
31
+ let r;
32
+ try {
33
+ r = JSON.parse(n);
34
+ } catch {
35
+ continue;
36
+ }
37
+ let a = "";
38
+ if (typeof r.delta == "string") a = r.delta;
39
+ else if (Array.isArray(r.choices)) {
40
+ let e = r.choices[0];
41
+ typeof e?.delta?.content == "string" && (a = e.delta.content);
42
+ } else typeof r.content == "string" && (a = r.content);
43
+ i += a;
44
+ let o = r.done === !0 || Array.isArray(r.choices) && r.choices[0]?.finish_reason != null;
45
+ if (yield {
46
+ delta: a,
47
+ fullMessage: i,
48
+ role: "assistant",
49
+ datetime: Date.now(),
50
+ done: !!o
51
+ }, o) return;
52
+ }
53
+ }
54
+ let e = (r + n.decode()).trim();
55
+ if (e !== "" && e.startsWith("data:")) {
56
+ let t = e.slice(5).trim();
57
+ if (t !== "" && t !== "[DONE]") try {
58
+ let e = JSON.parse(t), n = "";
59
+ typeof e.delta == "string" ? n = e.delta : typeof e.content == "string" && (n = e.content), i += n, yield {
60
+ delta: n,
61
+ fullMessage: i,
62
+ role: "assistant",
63
+ datetime: Date.now(),
64
+ done: !0
65
+ };
66
+ return;
67
+ } catch {}
68
+ }
69
+ i.length > 0 && (yield {
70
+ delta: "",
71
+ fullMessage: i,
72
+ role: "assistant",
73
+ datetime: Date.now(),
74
+ done: !0
75
+ });
76
+ } finally {
77
+ t.releaseLock();
78
+ }
79
+ }
80
+ /**
81
+ * Parse a newline-delimited JSON (NDJSON) response stream into ChatStreamChunk values.
82
+ *
83
+ * Each non-empty line is parsed as a standalone JSON object.
84
+ * Accumulates the full message across chunks.
85
+ */
86
+ async function* h(e) {
87
+ let t = e.body.getReader(), n = new TextDecoder("utf-8"), r = "", i = "";
88
+ try {
89
+ for (;;) {
90
+ let { done: e, value: a } = await t.read();
91
+ if (e) break;
92
+ r += n.decode(a, { stream: !0 });
93
+ let o = r.split("\n");
94
+ r = o.pop() ?? "";
95
+ for (let e of o) {
96
+ let t = e.trim();
97
+ if (t === "") continue;
98
+ let n;
99
+ try {
100
+ n = JSON.parse(t);
101
+ } catch {
102
+ continue;
103
+ }
104
+ let r = "";
105
+ typeof n.delta == "string" ? r = n.delta : typeof n.content == "string" && (r = n.content), i += r;
106
+ let a = n.done === !0;
107
+ if (yield {
108
+ delta: r,
109
+ fullMessage: i,
110
+ role: "assistant",
111
+ datetime: Date.now(),
112
+ done: a
113
+ }, a) return;
114
+ }
115
+ }
116
+ let e = (r + n.decode()).trim();
117
+ if (e !== "") try {
118
+ let t = JSON.parse(e), n = "";
119
+ typeof t.delta == "string" ? n = t.delta : typeof t.content == "string" && (n = t.content), i += n, yield {
120
+ delta: n,
121
+ fullMessage: i,
122
+ role: "assistant",
123
+ datetime: Date.now(),
124
+ done: !0
125
+ };
126
+ return;
127
+ } catch {}
128
+ i.length > 0 && (yield {
129
+ delta: "",
130
+ fullMessage: i,
131
+ role: "assistant",
132
+ datetime: Date.now(),
133
+ done: !0
134
+ });
135
+ } finally {
136
+ t.releaseLock();
137
+ }
138
+ }
139
+ /**
140
+ * Parse a standard JSON response as a single ChatStreamChunk.
141
+ *
142
+ * Reads the entire response body, parses as JSON, and yields one chunk
143
+ * with `done: true`.
144
+ */
145
+ async function* g(e) {
146
+ let t = await e.json(), n = "";
147
+ typeof t.content == "string" ? n = t.content : typeof t.message == "string" ? n = t.message : typeof t.delta == "string" ? n = t.delta : Array.isArray(t.choices) && typeof t.choices[0]?.message?.content == "string" && (n = t.choices[0].message.content), yield {
148
+ delta: n,
149
+ fullMessage: n,
150
+ role: "assistant",
151
+ datetime: Date.now(),
152
+ done: !0
153
+ };
154
+ }
155
+ /**
156
+ * Detect the stream format from a Content-Type header value.
157
+ */
158
+ function _(e) {
159
+ let t = e.toLowerCase();
160
+ return t.includes("text/event-stream") ? "sse" : t.includes("ndjson") || t.includes("x-ndjson") ? "ndjson" : "json";
161
+ }
162
+ /**
163
+ * Create an async generator that yields ChatStreamChunk values from a
164
+ * Response, auto-detecting the format from Content-Type when not specified.
165
+ */
166
+ async function* v(e, t) {
167
+ switch (t ?? _(e.headers.get("content-type") ?? "")) {
168
+ case "sse":
169
+ yield* m(e);
170
+ break;
171
+ case "ndjson":
172
+ yield* h(e);
173
+ break;
174
+ case "json":
175
+ yield* g(e);
176
+ break;
177
+ }
178
+ }
179
+ /**
180
+ * Create a reusable chat transport that sends requests and returns a
181
+ * streaming async generator.
182
+ */
183
+ function y(e) {
184
+ return { async send(t) {
185
+ let n = {
186
+ "Content-Type": "application/json",
187
+ ...e.headers
188
+ };
189
+ e.clientId && (n["X-Client-Id"] = e.clientId);
190
+ let r = await fetch(e.baseUrl, {
191
+ method: "POST",
192
+ headers: n,
193
+ body: JSON.stringify(t),
194
+ signal: e.signal
195
+ });
196
+ if (!r.ok) throw Error(`Chat transport error: ${r.status} ${r.statusText}`);
197
+ return v(r, e.format);
198
+ } };
199
+ }
200
+ const b = {
201
+ TRANSPORT: "native:chat-transport",
202
+ GENERATION_START: "native:generation-start",
203
+ GENERATION_COMPLETE: "native:generation-complete",
204
+ GENERATION_STOP: "native:generation-stop",
205
+ GENERATION_ERROR: "native:generation-error",
206
+ WARNING: "native:chat-warning"
207
+ }, x = [
208
+ "requestId",
209
+ "sessionId",
210
+ "conversationId",
211
+ "messageId",
212
+ "mode",
213
+ "contentType",
214
+ "durationMs",
215
+ "startedAt",
216
+ "completedAt",
217
+ "attempt",
218
+ "maxAttempts",
219
+ "chunkIndex"
220
+ ], S = [
221
+ "query",
222
+ "message",
223
+ "delta",
224
+ "fullMessage",
225
+ "body",
226
+ "content",
227
+ "prompt",
228
+ "response"
229
+ ];
230
+ var C = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, w = /\b(?:\+?\d{1,3}[-.\s]?)?\(?\d{2,4}\)?[-.\s]?\d{3,4}[-.\s]?\d{3,4}\b/g, T = /\b(?:\d{4}[-\s]?){3}\d{4}\b/g;
231
+ /**
232
+ * Scrub common PII patterns from a string.
233
+ *
234
+ * Replaces email addresses, phone-like numbers, and credit-card-like
235
+ * number sequences with `[redacted]` placeholders.
236
+ */
237
+ function E(e) {
238
+ return e.replace(C, "[redacted:email]").replace(T, "[redacted:card]").replace(w, "[redacted:phone]");
239
+ }
240
+ var D = new Set(S);
241
+ /**
242
+ * Create a default redactor for the given telemetry level.
243
+ *
244
+ * - **minimal**: Sensitive fields in `detail` are replaced with
245
+ * `[redacted:Nchars]` indicating the original length.
246
+ * - **debug**: All fields pass through unmodified.
247
+ */
248
+ function O(e) {
249
+ return e === "debug" ? (e) => e : (e) => {
250
+ if (!e.detail) return e;
251
+ let t = {};
252
+ for (let [n, r] of Object.entries(e.detail)) D.has(n) && typeof r == "string" ? t[n] = `[redacted:${r.length}chars]` : t[n] = r;
253
+ return {
254
+ ...e,
255
+ detail: t
256
+ };
257
+ };
258
+ }
259
+ /**
260
+ * Dispatches telemetry events as `CustomEvent` instances on a given
261
+ * `EventTarget`, applying a configurable redactor before emission.
262
+ */
263
+ var k = class {
264
+ #e;
265
+ #t;
266
+ constructor(e, t = "minimal") {
267
+ this.#e = e, this.#t = O(t);
268
+ }
269
+ /** Change the telemetry level, replacing the redactor. */
270
+ setLevel(e) {
271
+ this.#t = O(e);
272
+ }
273
+ /** Replace the redactor with a custom implementation. */
274
+ setRedactor(e) {
275
+ this.#t = e;
276
+ }
277
+ /** Apply the redactor and dispatch the event on the target. */
278
+ emit(e) {
279
+ let t = this.#t(e);
280
+ this.#e.dispatchEvent(new CustomEvent(t.type, {
281
+ detail: t,
282
+ bubbles: !0
283
+ }));
284
+ }
285
+ emitTransport(e, t, n) {
286
+ this.emit({
287
+ type: b.TRANSPORT,
288
+ correlation: e,
289
+ detail: {
290
+ mode: t,
291
+ contentType: n
292
+ }
293
+ });
294
+ }
295
+ emitGenerationStart(e) {
296
+ this.emit({
297
+ type: b.GENERATION_START,
298
+ correlation: e,
299
+ timing: { startedAt: Date.now() }
300
+ });
301
+ }
302
+ emitGenerationComplete(e, t) {
303
+ this.emit({
304
+ type: b.GENERATION_COMPLETE,
305
+ correlation: e,
306
+ timing: {
307
+ completedAt: Date.now(),
308
+ durationMs: t
309
+ }
310
+ });
311
+ }
312
+ emitWarning(e, t, n) {
313
+ this.emit({
314
+ type: b.WARNING,
315
+ correlation: e,
316
+ detail: {
317
+ message: t,
318
+ ...n
319
+ }
320
+ });
321
+ }
322
+ };
323
+ export { b as CHAT_EVENTS, n as NChatAvatar, r as NChatFeed, o as NChatInput, f as NChatInputStructured, p as NChatMessage, i as NChatMessageActivity, s as NChatMessageGenUI, u as NChatMessageSeed, e as NChatMessageText, a as NChatMessages, l as NChatPanel, x as SAFE_FIELDS, S as SENSITIVE_FIELDS, k as TelemetryEmitter, v as createChatStream, y as createChatTransport, O as createDefaultRedactor, _ as detectFormat, g as parseJSON, h as parseNDJSON, m as parseSSE, c as renderInline, d as renderMarkdown, t as sanitizeHtml, E as scrubPII };
package/dist/register.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, d as t, f as n, i as r, l as i, m as a, n as o, p as s, r as c, t as l, u } from "./chat-input-structured-element-CbDnI4zv.js";
1
+ import { a as e, d as t, f as n, i as r, l as i, m as a, n as o, p as s, r as c, t as l, u } from "./chat-input-structured-element-Cpar3CeA.js";
2
2
  import { NButton as d, NCard as f, NDialog as p, NIcon as m, NTextarea as h, NToolbar as g, define as _, registerIcon as v } from "@nonoun/native-ui";
3
3
  _("n-chat-input", a), _("native-chat-panel", s), _("n-chat-feed", n), _("n-chat-avatar", t), _("n-chat-message", u), _("n-chat-messages", i), _("n-chat-message-text", e), _("n-chat-message-activity", r), _("n-chat-message-seed", c), _("n-chat-message-genui", o), _("n-chat-input-structured", l), _("n-textarea", h), _("n-button", d), _("n-icon", m), _("n-toolbar", g), _("n-dialog", p), _("n-card", f), v("chat-dots", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M116,128a12,12,0,1,1,12,12A12,12,0,0,1,116,128ZM84,140a12,12,0,1,0-12-12A12,12,0,0,0,84,140Zm88,0a12,12,0,1,0-12-12A12,12,0,0,0,172,140Zm60-76V192a16,16,0,0,1-16,16H83l-32.6,28.16-.09.07A15.89,15.89,0,0,1,40,240a16.13,16.13,0,0,1-6.8-1.52A15.85,15.85,0,0,1,24,224V64A16,16,0,0,1,40,48H216A16,16,0,0,1,232,64ZM40,224h0ZM216,64H40V224l34.77-30A8,8,0,0,1,80,192H216Z\"/></svg>"), v("user", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M230.92,212c-15.23-26.33-38.7-45.21-66.09-54.16a72,72,0,1,0-73.66,0C63.78,166.78,40.31,185.66,25.08,212a8,8,0,1,0,13.85,8C55.71,194.74,89.05,176,128,176s72.29,18.74,89.07,44a8,8,0,0,0,13.85-8ZM72,96a56,56,0,1,1,56,56A56.06,56.06,0,0,1,72,96Z\"/></svg>"), v("stop", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,160H56V56H200V200Z\"/></svg>"), v("arrow-counter-clockwise", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M224,128a96,96,0,0,1-94.71,96H128A95.38,95.38,0,0,1,62.1,197.8a8,8,0,0,1,11-11.63A80,80,0,1,0,71.43,71.39a3.07,3.07,0,0,1-.26.25L44.59,96H72a8,8,0,0,1,0,16H24a8,8,0,0,1-8-8V56a8,8,0,0,1,16,0V85.8L60.25,60A96,96,0,0,1,224,128Z\"/></svg>");
4
4
  export { t as NChatAvatar, n as NChatFeed, a as NChatInput, l as NChatInputStructured, u as NChatMessage, r as NChatMessageActivity, o as NChatMessageGenUI, c as NChatMessageSeed, e as NChatMessageText, i as NChatMessages, s as NChatPanel };
@@ -0,0 +1,19 @@
1
+ import type { ChatStreamChunk, StreamFormat, ChatTransportOptions } from './types.ts';
2
+ /**
3
+ * Detect the stream format from a Content-Type header value.
4
+ */
5
+ export declare function detectFormat(contentType: string): StreamFormat;
6
+ /**
7
+ * Create an async generator that yields ChatStreamChunk values from a
8
+ * Response, auto-detecting the format from Content-Type when not specified.
9
+ */
10
+ export declare function createChatStream(response: Response, format?: StreamFormat): AsyncGenerator<ChatStreamChunk>;
11
+ export interface ChatTransport {
12
+ send(body: unknown): Promise<AsyncGenerator<ChatStreamChunk>>;
13
+ }
14
+ /**
15
+ * Create a reusable chat transport that sends requests and returns a
16
+ * streaming async generator.
17
+ */
18
+ export declare function createChatTransport(options: ChatTransportOptions): ChatTransport;
19
+ //# sourceMappingURL=create-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-transport.d.ts","sourceRoot":"","sources":["../../src/stream/create-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKtF;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAK9D;AAED;;;GAGG;AACH,wBAAuB,gBAAgB,CACrC,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,YAAY,GACpB,cAAc,CAAC,eAAe,CAAC,CAejC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC;CAC/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,GAC5B,aAAa,CA2Bf"}
@@ -0,0 +1,7 @@
1
+ export type { ChatStreamChunk, StreamFormat, ChatTransportOptions, ChatStreamEvent, } from './types.ts';
2
+ export { parseSSE } from './parse-sse.ts';
3
+ export { parseNDJSON } from './parse-ndjson.ts';
4
+ export { parseJSON } from './parse-json.ts';
5
+ export type { ChatTransport } from './create-transport.ts';
6
+ export { detectFormat, createChatStream, createChatTransport, } from './create-transport.ts';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stream/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ChatStreamChunk } from './types.ts';
2
+ /**
3
+ * Parse a standard JSON response as a single ChatStreamChunk.
4
+ *
5
+ * Reads the entire response body, parses as JSON, and yields one chunk
6
+ * with `done: true`.
7
+ */
8
+ export declare function parseJSON(response: Response): AsyncGenerator<ChatStreamChunk>;
9
+ //# sourceMappingURL=parse-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-json.d.ts","sourceRoot":"","sources":["../../src/stream/parse-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;GAKG;AACH,wBAAuB,SAAS,CAC9B,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAAC,eAAe,CAAC,CA2BjC"}
@@ -0,0 +1,9 @@
1
+ import type { ChatStreamChunk } from './types.ts';
2
+ /**
3
+ * Parse a newline-delimited JSON (NDJSON) response stream into ChatStreamChunk values.
4
+ *
5
+ * Each non-empty line is parsed as a standalone JSON object.
6
+ * Accumulates the full message across chunks.
7
+ */
8
+ export declare function parseNDJSON(response: Response): AsyncGenerator<ChatStreamChunk>;
9
+ //# sourceMappingURL=parse-ndjson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-ndjson.d.ts","sourceRoot":"","sources":["../../src/stream/parse-ndjson.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;GAKG;AACH,wBAAuB,WAAW,CAChC,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAAC,eAAe,CAAC,CAyFjC"}
@@ -0,0 +1,9 @@
1
+ import type { ChatStreamChunk } from './types.ts';
2
+ /**
3
+ * Parse a Server-Sent Events (SSE) response stream into ChatStreamChunk values.
4
+ *
5
+ * Reads `data:` lines from the response body, skips empty lines and comments,
6
+ * handles the `[DONE]` sentinel, and accumulates the full message across chunks.
7
+ */
8
+ export declare function parseSSE(response: Response): AsyncGenerator<ChatStreamChunk>;
9
+ //# sourceMappingURL=parse-sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-sse.d.ts","sourceRoot":"","sources":["../../src/stream/parse-sse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;GAKG;AACH,wBAAuB,QAAQ,CAC7B,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAAC,eAAe,CAAC,CAiIjC"}
@@ -0,0 +1,23 @@
1
+ export interface ChatStreamChunk {
2
+ delta: string;
3
+ fullMessage: string;
4
+ role: 'assistant' | 'user';
5
+ datetime: number;
6
+ done: boolean;
7
+ }
8
+ export type StreamFormat = 'sse' | 'ndjson' | 'json';
9
+ export interface ChatTransportOptions {
10
+ baseUrl: string;
11
+ clientId?: string;
12
+ format?: StreamFormat;
13
+ headers?: Record<string, string>;
14
+ signal?: AbortSignal;
15
+ }
16
+ export interface ChatStreamEvent {
17
+ type: 'start' | 'chunk' | 'complete' | 'error' | 'stop';
18
+ chunk?: ChatStreamChunk;
19
+ error?: Error;
20
+ durationMs?: number;
21
+ requestId: string;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/stream/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IACxD,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,20 @@
1
+ import type { TelemetryCorrelation, TelemetryEvent, TelemetryLevel, TelemetryRedactor } from './types.ts';
2
+ /**
3
+ * Dispatches telemetry events as `CustomEvent` instances on a given
4
+ * `EventTarget`, applying a configurable redactor before emission.
5
+ */
6
+ export declare class TelemetryEmitter {
7
+ #private;
8
+ constructor(target: EventTarget, level?: TelemetryLevel);
9
+ /** Change the telemetry level, replacing the redactor. */
10
+ setLevel(level: TelemetryLevel): void;
11
+ /** Replace the redactor with a custom implementation. */
12
+ setRedactor(fn: TelemetryRedactor): void;
13
+ /** Apply the redactor and dispatch the event on the target. */
14
+ emit(event: TelemetryEvent): void;
15
+ emitTransport(correlation: TelemetryCorrelation, mode: string, contentType: string): void;
16
+ emitGenerationStart(correlation: TelemetryCorrelation): void;
17
+ emitGenerationComplete(correlation: TelemetryCorrelation, durationMs: number): void;
18
+ emitWarning(correlation: TelemetryCorrelation, message: string, detail?: Record<string, unknown>): void;
19
+ }
20
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/telemetry/emitter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAIpB;;;GAGG;AACH,qBAAa,gBAAgB;;gBAIf,MAAM,EAAE,WAAW,EAAE,KAAK,GAAE,cAA0B;IAKlE,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAIrC,yDAAyD;IACzD,WAAW,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI;IAIxC,+DAA+D;IAC/D,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IASjC,aAAa,CACX,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,IAAI;IAQP,mBAAmB,CAAC,WAAW,EAAE,oBAAoB,GAAG,IAAI;IAQ5D,sBAAsB,CACpB,WAAW,EAAE,oBAAoB,EACjC,UAAU,EAAE,MAAM,GACjB,IAAI;IAQP,WAAW,CACT,WAAW,EAAE,oBAAoB,EACjC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI;CAOR"}
@@ -0,0 +1,11 @@
1
+ export declare const CHAT_EVENTS: {
2
+ readonly TRANSPORT: "native:chat-transport";
3
+ readonly GENERATION_START: "native:generation-start";
4
+ readonly GENERATION_COMPLETE: "native:generation-complete";
5
+ readonly GENERATION_STOP: "native:generation-stop";
6
+ readonly GENERATION_ERROR: "native:generation-error";
7
+ readonly WARNING: "native:chat-warning";
8
+ };
9
+ export declare const SAFE_FIELDS: readonly ["requestId", "sessionId", "conversationId", "messageId", "mode", "contentType", "durationMs", "startedAt", "completedAt", "attempt", "maxAttempts", "chunkIndex"];
10
+ export declare const SENSITIVE_FIELDS: readonly ["query", "message", "delta", "fullMessage", "body", "content", "prompt", "response"];
11
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/telemetry/events.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;;;CAOd,CAAC;AAEX,eAAO,MAAM,WAAW,6KAad,CAAC;AAEX,eAAO,MAAM,gBAAgB,gGASnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type { TelemetryCorrelation, TelemetryTiming, TelemetryRetry, TelemetryLevel, TelemetryEvent, TelemetryRedactor, } from './types.ts';
2
+ export { CHAT_EVENTS, SAFE_FIELDS, SENSITIVE_FIELDS } from './events.ts';
3
+ export { scrubPII, createDefaultRedactor } from './redactor.ts';
4
+ export { TelemetryEmitter } from './emitter.ts';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { TelemetryLevel, TelemetryRedactor } from './types.ts';
2
+ /**
3
+ * Scrub common PII patterns from a string.
4
+ *
5
+ * Replaces email addresses, phone-like numbers, and credit-card-like
6
+ * number sequences with `[redacted]` placeholders.
7
+ */
8
+ export declare function scrubPII(text: string): string;
9
+ /**
10
+ * Create a default redactor for the given telemetry level.
11
+ *
12
+ * - **minimal**: Sensitive fields in `detail` are replaced with
13
+ * `[redacted:Nchars]` indicating the original length.
14
+ * - **debug**: All fields pass through unmodified.
15
+ */
16
+ export declare function createDefaultRedactor(level: TelemetryLevel): TelemetryRedactor;
17
+ //# sourceMappingURL=redactor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redactor.d.ts","sourceRoot":"","sources":["../../src/telemetry/redactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AASpF;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK7C;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,GAAG,iBAAiB,CAmB9E"}
@@ -0,0 +1,27 @@
1
+ export interface TelemetryCorrelation {
2
+ requestId: string;
3
+ sessionId?: string;
4
+ conversationId?: string;
5
+ messageId?: string;
6
+ parentMessageId?: string;
7
+ }
8
+ export interface TelemetryTiming {
9
+ startedAt?: number;
10
+ completedAt?: number;
11
+ durationMs?: number;
12
+ }
13
+ export interface TelemetryRetry {
14
+ attempt?: number;
15
+ maxAttempts?: number;
16
+ retryReason?: string;
17
+ }
18
+ export type TelemetryLevel = 'minimal' | 'debug';
19
+ export interface TelemetryEvent {
20
+ type: string;
21
+ correlation: TelemetryCorrelation;
22
+ timing?: TelemetryTiming;
23
+ retry?: TelemetryRetry;
24
+ detail?: Record<string, unknown>;
25
+ }
26
+ export type TelemetryRedactor = (event: TelemetryEvent) => TelemetryEvent;
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/telemetry/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,oBAAoB,CAAC;IAClC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nonoun/native-chat",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Chat input and message layout components for @nonoun/native-ui",
5
5
  "license": "MIT",
6
6
  "type": "module",