@ai-gui/core 0.1.0 → 0.2.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.
package/dist/index.d.cts CHANGED
@@ -32,6 +32,11 @@ declare function repairMarkdown(buffer: string): string;
32
32
 
33
33
  //#endregion
34
34
  //#region src/sanitizer.d.ts
35
+ interface SanitizeHtmlOptions {
36
+ sanitizer?: (html: string) => string;
37
+ /** Bare SSR either escapes all markup (default) or fails explicitly. */
38
+ ssr?: "escape" | "throw";
39
+ }
35
40
  /**
36
41
  * Sanitize an HTML string, stripping scripts and unsafe attributes.
37
42
  *
@@ -40,7 +45,7 @@ declare function repairMarkdown(buffer: string): string;
40
45
  * fall back to escaping the HTML-significant characters. This never emits raw
41
46
  * markup and never throws.
42
47
  */
43
- declare function sanitizeHtml(html: string): string;
48
+ declare function sanitizeHtml(html: string, options?: SanitizeHtmlOptions): string;
44
49
 
45
50
  //#endregion
46
51
  //#region src/types.d.ts
@@ -53,6 +58,8 @@ interface ASTNode {
53
58
  html?: string;
54
59
  attrs?: Record<string, string>;
55
60
  children?: ASTNode[];
61
+ /** Whether a streaming block has enough source to invoke its renderer. */
62
+ complete?: boolean;
56
63
  /** card-specific payload */
57
64
  card?: {
58
65
  type: string;
@@ -70,6 +77,10 @@ type Patch = {
70
77
  op: "update";
71
78
  key: string;
72
79
  node: ASTNode;
80
+ } | {
81
+ op: "move";
82
+ key: string;
83
+ index: number;
73
84
  } | {
74
85
  op: "remove";
75
86
  key: string;
@@ -120,9 +131,16 @@ interface AIGuiPlugin {
120
131
  interface RendererOptions {
121
132
  registry?: CardRegistry;
122
133
  plugins?: AIGuiPlugin[];
123
- sanitize?: boolean;
134
+ sanitize?: boolean | SanitizeHtmlOptions;
135
+ /** Coalesce multiple pushes by scheduling one render callback. */
136
+ scheduler?: (render: () => void) => void;
124
137
  onPatch?: (patches: Patch[], nodes: ASTNode[]) => void;
125
138
  }
139
+ interface FeedOptions {
140
+ signal?: AbortSignal;
141
+ }
142
+ type FeedChunk = string | Uint8Array;
143
+ type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>;
126
144
 
127
145
  //#endregion
128
146
  //#region src/card-registry.d.ts
@@ -139,6 +157,7 @@ declare class CardRegistry {
139
157
  parse(type: string, rawJson: string): CardParseResult;
140
158
  private validate;
141
159
  toPromptSpec(): string;
160
+ get size(): number;
142
161
  toJSONSchema(): JSONSchema;
143
162
  }
144
163
 
@@ -149,8 +168,21 @@ interface ParserOptions {
149
168
  plugins?: AIGuiPlugin[];
150
169
  configureMd?: (md: MarkdownIt) => void;
151
170
  }
171
+ interface SourceBlock {
172
+ start: number;
173
+ end: number;
174
+ nodeStart: number;
175
+ nodeEnd: number;
176
+ }
177
+ interface ParseResult {
178
+ nodes: ASTNode[];
179
+ blocks: SourceBlock[];
180
+ incrementalSafe: boolean;
181
+ }
152
182
  /** Build a parser that turns markdown source into a flat list of ASTNodes. */
153
- declare function createParser(options?: ParserOptions): (src: string) => ASTNode[];
183
+ declare function createParser(options?: ParserOptions): (src: string, rawSrc?: string) => ASTNode[];
184
+ /** Build a parser that also reports the source range for each top-level block. */
185
+ declare function createParserWithMetadata(options?: ParserOptions): (src: string, rawSrc?: string, sourceOffset?: number) => ParseResult;
154
186
 
155
187
  //#endregion
156
188
  //#region src/plugins.d.ts
@@ -163,6 +195,8 @@ declare function pluginNodeTypes(plugins?: AIGuiPlugin[]): Set<string>;
163
195
  //#region src/diff.d.ts
164
196
  /** Produce a minimal set of patches turning `prev` into `next`, keyed by node key. */
165
197
  declare function diffAst(prev: ASTNode[], next: ASTNode[]): Patch[];
198
+ /** Apply patches in order, primarily for framework adapters and verification. */
199
+ declare function applyPatches(nodes: ASTNode[], patches: Patch[]): ASTNode[];
166
200
 
167
201
  //#endregion
168
202
  //#region src/renderer.d.ts
@@ -175,55 +209,47 @@ declare class Renderer {
175
209
  private buffer;
176
210
  private prevAst;
177
211
  private parse;
212
+ private parsed?;
178
213
  private options;
179
214
  private sanitize;
215
+ private generation;
216
+ private activeFeed?;
217
+ private renderScheduled;
218
+ private scheduleGeneration;
180
219
  constructor(options?: RendererOptions);
181
220
  push(chunk: string): void;
182
- feed(source: AsyncIterable<string> | ReadableStream<string>): Promise<void>;
221
+ feed(source: FeedSource, options?: FeedOptions): Promise<void>;
183
222
  reset(): void;
223
+ /** Immediately render pending buffered input, bypassing the scheduler. */
224
+ flush(): void;
225
+ private scheduleRender;
226
+ private cancelActiveFeed;
184
227
  private render;
185
228
  }
186
229
 
187
230
  //#endregion
188
231
  //#region src/stream-router.d.ts
189
- /**
190
- * A consumer of a channel's text stream. `Renderer` satisfies this shape.
191
- */
232
+ /** A consumer of a channel's text stream. `Renderer` satisfies this shape. */
192
233
  interface ChannelSink {
193
234
  push(chunk: string): void;
194
235
  }
195
236
  /** Handler for structured data values (and text deltas as raw strings). */
196
237
  type ChannelHandler = (value: unknown) => void;
197
- /**
198
- * Demultiplexes one incoming stream into multiple named channels so different
199
- * UI regions can update independently (e.g. `progress` + `content` from a single
200
- * SSE). Framing is auto-detected per line and supports:
201
- *
202
- * 1. JSON envelope: `{"ch":"<channel>","delta":"text"}` (a text delta) or
203
- * `{"ch":"<channel>","data":<any>}` (a structured value). May appear bare or
204
- * after a `data: ` prefix.
205
- * 2. SSE `event: <name>` sets the channel for the following `data:` line(s).
206
- * 3. A plain `data: <text>` line with no `ch` and no preceding `event:` is a
207
- * text delta on the default `content` channel.
208
- */
238
+ type StreamChunk = string | Uint8Array;
239
+ /** Demultiplex JSON-lines and standards-compliant SSE into named channels. */
209
240
  declare class StreamRouter {
210
241
  private readonly sinks;
211
242
  private readonly handlers;
212
- /** Bind a text-stream sink to a channel: text deltas call `sink.push(delta)`. */
243
+ /** Most recently received SSE `id` field. */
244
+ lastEventId: string;
245
+ /** Most recently received valid non-negative SSE reconnection delay. */
246
+ retry: number | undefined;
213
247
  channel(name: string, sink: ChannelSink): this;
214
- /** Bind a handler to a channel: data values (and deltas as strings) call it. */
215
248
  on(name: string, handler: ChannelHandler): this;
216
- /**
217
- * Consume a stream to completion, dispatching each parsed line to its channel.
218
- * Accepts an async iterable of strings, or a `ReadableStream` of either strings
219
- * or `Uint8Array` bytes (decoded as UTF-8).
220
- */
221
- feed(source: AsyncIterable<string> | ReadableStream<Uint8Array | string>): Promise<void>;
222
- /** Process a single raw line; returns the (possibly updated) current event. */
223
- private processLine;
224
- /** Route a text delta: to a bound sink and/or an on() handler (either/both). */
249
+ feed(source: AsyncIterable<StreamChunk> | ReadableStream<StreamChunk>): Promise<void>;
250
+ private dispatchPayload;
251
+ private dispatchEnvelope;
225
252
  private routeDelta;
226
- /** Route a structured value: to the handler, or a string value to a lone sink. */
227
253
  private routeData;
228
254
  }
229
255
 
@@ -242,4 +268,4 @@ interface BuildSystemPromptOptions {
242
268
  declare function buildSystemPrompt(options?: BuildSystemPromptOptions): string;
243
269
 
244
270
  //#endregion
245
- export { AIGuiPlugin, ASTNode, BuildSystemPromptOptions, CardDef, CardParseResult, CardRegistry, ChannelSink, JSONSchema, NodeRenderer, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, StreamRouter, buildSystemPrompt, collectNodeRenderers, createParser, diffAst, parsePartialJSON, pluginNodeTypes, repairMarkdown, sanitizeHtml };
271
+ export { AIGuiPlugin, ASTNode, BuildSystemPromptOptions, CardDef, CardParseResult, CardRegistry, ChannelSink, FeedChunk, FeedOptions, FeedSource, JSONSchema, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, SanitizeHtmlOptions, SourceBlock, StreamRouter, applyPatches, buildSystemPrompt, collectNodeRenderers, createParser, createParserWithMetadata, diffAst, parsePartialJSON, pluginNodeTypes, repairMarkdown, sanitizeHtml };
package/dist/index.d.ts CHANGED
@@ -32,6 +32,11 @@ declare function repairMarkdown(buffer: string): string;
32
32
 
33
33
  //#endregion
34
34
  //#region src/sanitizer.d.ts
35
+ interface SanitizeHtmlOptions {
36
+ sanitizer?: (html: string) => string;
37
+ /** Bare SSR either escapes all markup (default) or fails explicitly. */
38
+ ssr?: "escape" | "throw";
39
+ }
35
40
  /**
36
41
  * Sanitize an HTML string, stripping scripts and unsafe attributes.
37
42
  *
@@ -40,7 +45,7 @@ declare function repairMarkdown(buffer: string): string;
40
45
  * fall back to escaping the HTML-significant characters. This never emits raw
41
46
  * markup and never throws.
42
47
  */
43
- declare function sanitizeHtml(html: string): string;
48
+ declare function sanitizeHtml(html: string, options?: SanitizeHtmlOptions): string;
44
49
 
45
50
  //#endregion
46
51
  //#region src/types.d.ts
@@ -53,6 +58,8 @@ interface ASTNode {
53
58
  html?: string;
54
59
  attrs?: Record<string, string>;
55
60
  children?: ASTNode[];
61
+ /** Whether a streaming block has enough source to invoke its renderer. */
62
+ complete?: boolean;
56
63
  /** card-specific payload */
57
64
  card?: {
58
65
  type: string;
@@ -70,6 +77,10 @@ type Patch = {
70
77
  op: "update";
71
78
  key: string;
72
79
  node: ASTNode;
80
+ } | {
81
+ op: "move";
82
+ key: string;
83
+ index: number;
73
84
  } | {
74
85
  op: "remove";
75
86
  key: string;
@@ -120,9 +131,16 @@ interface AIGuiPlugin {
120
131
  interface RendererOptions {
121
132
  registry?: CardRegistry;
122
133
  plugins?: AIGuiPlugin[];
123
- sanitize?: boolean;
134
+ sanitize?: boolean | SanitizeHtmlOptions;
135
+ /** Coalesce multiple pushes by scheduling one render callback. */
136
+ scheduler?: (render: () => void) => void;
124
137
  onPatch?: (patches: Patch[], nodes: ASTNode[]) => void;
125
138
  }
139
+ interface FeedOptions {
140
+ signal?: AbortSignal;
141
+ }
142
+ type FeedChunk = string | Uint8Array;
143
+ type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>;
126
144
 
127
145
  //#endregion
128
146
  //#region src/card-registry.d.ts
@@ -139,6 +157,7 @@ declare class CardRegistry {
139
157
  parse(type: string, rawJson: string): CardParseResult;
140
158
  private validate;
141
159
  toPromptSpec(): string;
160
+ get size(): number;
142
161
  toJSONSchema(): JSONSchema;
143
162
  }
144
163
 
@@ -149,8 +168,21 @@ interface ParserOptions {
149
168
  plugins?: AIGuiPlugin[];
150
169
  configureMd?: (md: MarkdownIt) => void;
151
170
  }
171
+ interface SourceBlock {
172
+ start: number;
173
+ end: number;
174
+ nodeStart: number;
175
+ nodeEnd: number;
176
+ }
177
+ interface ParseResult {
178
+ nodes: ASTNode[];
179
+ blocks: SourceBlock[];
180
+ incrementalSafe: boolean;
181
+ }
152
182
  /** Build a parser that turns markdown source into a flat list of ASTNodes. */
153
- declare function createParser(options?: ParserOptions): (src: string) => ASTNode[];
183
+ declare function createParser(options?: ParserOptions): (src: string, rawSrc?: string) => ASTNode[];
184
+ /** Build a parser that also reports the source range for each top-level block. */
185
+ declare function createParserWithMetadata(options?: ParserOptions): (src: string, rawSrc?: string, sourceOffset?: number) => ParseResult;
154
186
 
155
187
  //#endregion
156
188
  //#region src/plugins.d.ts
@@ -163,6 +195,8 @@ declare function pluginNodeTypes(plugins?: AIGuiPlugin[]): Set<string>;
163
195
  //#region src/diff.d.ts
164
196
  /** Produce a minimal set of patches turning `prev` into `next`, keyed by node key. */
165
197
  declare function diffAst(prev: ASTNode[], next: ASTNode[]): Patch[];
198
+ /** Apply patches in order, primarily for framework adapters and verification. */
199
+ declare function applyPatches(nodes: ASTNode[], patches: Patch[]): ASTNode[];
166
200
 
167
201
  //#endregion
168
202
  //#region src/renderer.d.ts
@@ -175,55 +209,47 @@ declare class Renderer {
175
209
  private buffer;
176
210
  private prevAst;
177
211
  private parse;
212
+ private parsed?;
178
213
  private options;
179
214
  private sanitize;
215
+ private generation;
216
+ private activeFeed?;
217
+ private renderScheduled;
218
+ private scheduleGeneration;
180
219
  constructor(options?: RendererOptions);
181
220
  push(chunk: string): void;
182
- feed(source: AsyncIterable<string> | ReadableStream<string>): Promise<void>;
221
+ feed(source: FeedSource, options?: FeedOptions): Promise<void>;
183
222
  reset(): void;
223
+ /** Immediately render pending buffered input, bypassing the scheduler. */
224
+ flush(): void;
225
+ private scheduleRender;
226
+ private cancelActiveFeed;
184
227
  private render;
185
228
  }
186
229
 
187
230
  //#endregion
188
231
  //#region src/stream-router.d.ts
189
- /**
190
- * A consumer of a channel's text stream. `Renderer` satisfies this shape.
191
- */
232
+ /** A consumer of a channel's text stream. `Renderer` satisfies this shape. */
192
233
  interface ChannelSink {
193
234
  push(chunk: string): void;
194
235
  }
195
236
  /** Handler for structured data values (and text deltas as raw strings). */
196
237
  type ChannelHandler = (value: unknown) => void;
197
- /**
198
- * Demultiplexes one incoming stream into multiple named channels so different
199
- * UI regions can update independently (e.g. `progress` + `content` from a single
200
- * SSE). Framing is auto-detected per line and supports:
201
- *
202
- * 1. JSON envelope: `{"ch":"<channel>","delta":"text"}` (a text delta) or
203
- * `{"ch":"<channel>","data":<any>}` (a structured value). May appear bare or
204
- * after a `data: ` prefix.
205
- * 2. SSE `event: <name>` sets the channel for the following `data:` line(s).
206
- * 3. A plain `data: <text>` line with no `ch` and no preceding `event:` is a
207
- * text delta on the default `content` channel.
208
- */
238
+ type StreamChunk = string | Uint8Array;
239
+ /** Demultiplex JSON-lines and standards-compliant SSE into named channels. */
209
240
  declare class StreamRouter {
210
241
  private readonly sinks;
211
242
  private readonly handlers;
212
- /** Bind a text-stream sink to a channel: text deltas call `sink.push(delta)`. */
243
+ /** Most recently received SSE `id` field. */
244
+ lastEventId: string;
245
+ /** Most recently received valid non-negative SSE reconnection delay. */
246
+ retry: number | undefined;
213
247
  channel(name: string, sink: ChannelSink): this;
214
- /** Bind a handler to a channel: data values (and deltas as strings) call it. */
215
248
  on(name: string, handler: ChannelHandler): this;
216
- /**
217
- * Consume a stream to completion, dispatching each parsed line to its channel.
218
- * Accepts an async iterable of strings, or a `ReadableStream` of either strings
219
- * or `Uint8Array` bytes (decoded as UTF-8).
220
- */
221
- feed(source: AsyncIterable<string> | ReadableStream<Uint8Array | string>): Promise<void>;
222
- /** Process a single raw line; returns the (possibly updated) current event. */
223
- private processLine;
224
- /** Route a text delta: to a bound sink and/or an on() handler (either/both). */
249
+ feed(source: AsyncIterable<StreamChunk> | ReadableStream<StreamChunk>): Promise<void>;
250
+ private dispatchPayload;
251
+ private dispatchEnvelope;
225
252
  private routeDelta;
226
- /** Route a structured value: to the handler, or a string value to a lone sink. */
227
253
  private routeData;
228
254
  }
229
255
 
@@ -242,4 +268,4 @@ interface BuildSystemPromptOptions {
242
268
  declare function buildSystemPrompt(options?: BuildSystemPromptOptions): string;
243
269
 
244
270
  //#endregion
245
- export { AIGuiPlugin, ASTNode, BuildSystemPromptOptions, CardDef, CardParseResult, CardRegistry, ChannelSink, JSONSchema, NodeRenderer, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, StreamRouter, buildSystemPrompt, collectNodeRenderers, createParser, diffAst, parsePartialJSON, pluginNodeTypes, repairMarkdown, sanitizeHtml };
271
+ export { AIGuiPlugin, ASTNode, BuildSystemPromptOptions, CardDef, CardParseResult, CardRegistry, ChannelSink, FeedChunk, FeedOptions, FeedSource, JSONSchema, NodeRenderer, ParseResult, ParserOptions, PartialJSONResult, Patch, RenderOutput, Renderer, RendererOptions, SanitizeHtmlOptions, SourceBlock, StreamRouter, applyPatches, buildSystemPrompt, collectNodeRenderers, createParser, createParserWithMetadata, diffAst, parsePartialJSON, pluginNodeTypes, repairMarkdown, sanitizeHtml };