@ai-gui/core 0.22.0 → 0.23.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/README.md +1 -0
- package/dist/index.cjs +29 -0
- package/dist/index.d.cts +19 -4
- package/dist/index.d.ts +19 -4
- package/dist/index.js +29 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -113,6 +113,7 @@ const runtime = createActionRuntime({ registry: actions, cardStore })
|
|
|
113
113
|
- `Renderer` — `push(chunk)`, `feed(AsyncIterable | ReadableStream)`, `reset()`, `setPlugins(plugins)`; constructor `{ registry?, plugins?, sanitize?, rawHtml?, onPatch?(patches, nodes) }`.
|
|
114
114
|
- `setPlugins` swaps the grammar and reparses the buffered source, so plugins deferred behind a dynamic import can arrive mid-answer without the host replaying what it pushed.
|
|
115
115
|
- `rawHtml: false` escapes raw HTML the model wrote instead of interpreting it — a stray `<code>` in prose otherwise swallows the rest of the line.
|
|
116
|
+
- Emphasis is parsed CJK-friendly, one deliberate deviation from CommonMark. CommonMark will not let `**` close when it follows punctuation and precedes a character that is neither whitespace nor punctuation, so `**严格单调(单射)**的函数` renders its asterisks literally. ASCII is unaffected: `a * b * c` and `snake_case_word` parse exactly as before.
|
|
116
117
|
- `StreamRouter` — demultiplex one stream into named channels: `.channel(name, sink)`, `.on(name, cb)`, `.feed(source)`.
|
|
117
118
|
- `CardRegistry` — `register(def)`, `parse(type, rawJson)`, `getRender(type)`, `toPromptSpec()`, `toJSONSchema()`.
|
|
118
119
|
- `CardStore` — `register`, `get`, `list`, `subscribe`, `apply`, `applyAll`, `delete`, `clear`, `snapshot`, and `restore` for Cards with stable IDs.
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
//#endregion
|
|
25
25
|
const dompurify = __toESM(require("dompurify"));
|
|
26
26
|
const markdown_it = __toESM(require("markdown-it"));
|
|
27
|
+
const markdown_it_cjk_friendly = __toESM(require("markdown-it-cjk-friendly"));
|
|
27
28
|
|
|
28
29
|
//#region src/partial-json.ts
|
|
29
30
|
/**
|
|
@@ -1465,8 +1466,32 @@ function samePlugins(a, b) {
|
|
|
1465
1466
|
if (!a || !b || a.length !== b.length) return false;
|
|
1466
1467
|
return a.every((plugin, index) => plugin === b[index]);
|
|
1467
1468
|
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Reject anything in the list that is not a plugin, naming what to do about it.
|
|
1471
|
+
*
|
|
1472
|
+
* Every plugin package exports a factory, so `plugins: [katex]` instead of `plugins: [katex()]` is
|
|
1473
|
+
* the easiest mistake to make — and it used to be the quietest. A function has a `name` of its
|
|
1474
|
+
* own, `"katex"`, so the renderer accepted it, found no `extendParser` and no `nodeRenderers`, and
|
|
1475
|
+
* did nothing: no error, no warning, markdown still rendering, only the maths and the diagrams
|
|
1476
|
+
* missing. A product can ship like that and nobody notices until someone asks why an equation is
|
|
1477
|
+
* plain text. Misconfiguration should be loud, so this throws.
|
|
1478
|
+
*/
|
|
1479
|
+
function assertPlugins(plugins, label = "plugins") {
|
|
1480
|
+
if (!plugins) return;
|
|
1481
|
+
plugins.forEach((plugin, index) => {
|
|
1482
|
+
const at = `${label}[${index}]`;
|
|
1483
|
+
if (typeof plugin === "function") {
|
|
1484
|
+
const called = plugin.name ? `${plugin.name}()` : "the factory";
|
|
1485
|
+
throw new TypeError(`${at} is a factory function, not a plugin. Call it: ${called}`);
|
|
1486
|
+
}
|
|
1487
|
+
if (plugin === null || typeof plugin !== "object") throw new TypeError(`${at} is ${plugin === null ? "null" : typeof plugin}, not a plugin object`);
|
|
1488
|
+
const { name } = plugin;
|
|
1489
|
+
if (typeof name !== "string" || name.length === 0) throw new TypeError(`${at} has no \`name\`. A plugin needs one: its stylesheet and its debug events are keyed by it`);
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1468
1492
|
/** Merge every plugin's `nodeRenderers` into a single map (later plugins win). */
|
|
1469
1493
|
function collectNodeRenderers(plugins = [], debugOptions = {}) {
|
|
1494
|
+
assertPlugins(plugins);
|
|
1470
1495
|
const map = {};
|
|
1471
1496
|
const target = debugOptions.debugTarget;
|
|
1472
1497
|
const debug = target ? void 0 : debugOptions.debug === true ? new DebugEmitter("renderer", debugOptions) : void 0;
|
|
@@ -1554,6 +1579,7 @@ function createParserWithMetadata(options = {}) {
|
|
|
1554
1579
|
html: options.rawHtml !== false,
|
|
1555
1580
|
linkify: true
|
|
1556
1581
|
});
|
|
1582
|
+
md.use(markdown_it_cjk_friendly.default);
|
|
1557
1583
|
options.configureMd?.(md);
|
|
1558
1584
|
for (const plugin of options.plugins ?? []) plugin.extendParser?.(md);
|
|
1559
1585
|
const hasParserExtensions = Boolean(options.configureMd || options.plugins?.some((plugin) => plugin.extendParser));
|
|
@@ -2067,6 +2093,7 @@ var Renderer = class {
|
|
|
2067
2093
|
debug;
|
|
2068
2094
|
constructor(options = {}) {
|
|
2069
2095
|
this.options = options;
|
|
2096
|
+
assertPlugins(options.plugins);
|
|
2070
2097
|
this.debug = new DebugEmitter(this.debugSource, options);
|
|
2071
2098
|
this.sanitize = options.sanitize === false ? false : typeof options.sanitize === "object" ? options.sanitize : {};
|
|
2072
2099
|
this.registerPluginCards(options.plugins);
|
|
@@ -2092,6 +2119,7 @@ var Renderer = class {
|
|
|
2092
2119
|
* Passing the same plugins again is a no-op, so a host may call this on every render.
|
|
2093
2120
|
*/
|
|
2094
2121
|
setPlugins(plugins) {
|
|
2122
|
+
assertPlugins(plugins);
|
|
2095
2123
|
if (samePlugins(this.options.plugins, plugins)) return;
|
|
2096
2124
|
this.options = {
|
|
2097
2125
|
...this.options,
|
|
@@ -2887,6 +2915,7 @@ exports.Renderer = Renderer
|
|
|
2887
2915
|
exports.StreamRouter = StreamRouter
|
|
2888
2916
|
exports.actionOutcome = actionOutcome
|
|
2889
2917
|
exports.applyPatches = applyPatches
|
|
2918
|
+
exports.assertPlugins = assertPlugins
|
|
2890
2919
|
exports.availableLocales = availableLocales
|
|
2891
2920
|
exports.baseCss = baseCss
|
|
2892
2921
|
exports.buildSystemPrompt = buildSystemPrompt
|
package/dist/index.d.cts
CHANGED
|
@@ -255,6 +255,12 @@ interface AIGuiPlugin {
|
|
|
255
255
|
/**
|
|
256
256
|
* LLM-facing guidance describing this plugin's fence syntax.
|
|
257
257
|
*
|
|
258
|
+
* A host does not read this field itself: `buildSystemPrompt({ registry, plugins, locale })`
|
|
259
|
+
* collects the card specs and every enabled plugin's spec in one call, already in the product's
|
|
260
|
+
* language. Assembling it by hand — reading each plugin's spec, joining them, writing the
|
|
261
|
+
* localized wording again — reinvents that badly, and a plugin added later is then missing from
|
|
262
|
+
* the prompt while its renderer is installed.
|
|
263
|
+
*
|
|
258
264
|
* Receives the locale asked of `buildSystemPrompt`, so the rules can be written in the language
|
|
259
265
|
* the product answers in — a Chinese persona followed by English rules reads as a contradiction
|
|
260
266
|
* to the model. Plugins that only ship English simply ignore the argument.
|
|
@@ -284,9 +290,7 @@ interface FeedOptions {
|
|
|
284
290
|
signal?: AbortSignal;
|
|
285
291
|
}
|
|
286
292
|
type FeedChunk = string | Uint8Array;
|
|
287
|
-
type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>;
|
|
288
|
-
|
|
289
|
-
//#endregion
|
|
293
|
+
type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>; //#endregion
|
|
290
294
|
//#region src/card-registry.d.ts
|
|
291
295
|
interface CardParseResult {
|
|
292
296
|
data: unknown;
|
|
@@ -684,6 +688,17 @@ declare function loadPlugins(source?: PluginSource): AIGuiPlugin[] | Promise<AIG
|
|
|
684
688
|
* What matters is the members, not the array.
|
|
685
689
|
*/
|
|
686
690
|
declare function samePlugins(a?: AIGuiPlugin[], b?: AIGuiPlugin[]): boolean;
|
|
691
|
+
/**
|
|
692
|
+
* Reject anything in the list that is not a plugin, naming what to do about it.
|
|
693
|
+
*
|
|
694
|
+
* Every plugin package exports a factory, so `plugins: [katex]` instead of `plugins: [katex()]` is
|
|
695
|
+
* the easiest mistake to make — and it used to be the quietest. A function has a `name` of its
|
|
696
|
+
* own, `"katex"`, so the renderer accepted it, found no `extendParser` and no `nodeRenderers`, and
|
|
697
|
+
* did nothing: no error, no warning, markdown still rendering, only the maths and the diagrams
|
|
698
|
+
* missing. A product can ship like that and nobody notices until someone asks why an equation is
|
|
699
|
+
* plain text. Misconfiguration should be loud, so this throws.
|
|
700
|
+
*/
|
|
701
|
+
declare function assertPlugins(plugins: readonly unknown[] | undefined, label?: string): void;
|
|
687
702
|
/** Merge every plugin's `nodeRenderers` into a single map (later plugins win). */
|
|
688
703
|
declare function collectNodeRenderers(plugins?: AIGuiPlugin[], debugOptions?: CollectNodeRendererOptions): Record<string, NodeRenderer>;
|
|
689
704
|
/** The set of node types claimed by the given plugins. */
|
|
@@ -985,4 +1000,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
985
1000
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
986
1001
|
|
|
987
1002
|
//#endregion
|
|
988
|
-
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionOutcome, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DEFAULT_LOCALE, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, ExportImageOptions, ExportedImage, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, Locale, MessageBundle, Messages, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderContext, NodeRenderer, OutcomeTone, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, PluginSource, PluginStyle, PluginsLoader, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SanitizeSetting, SourceBlock, StreamParseOptions, StreamRouter, Usage, actionOutcome, applyPatches, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
|
1003
|
+
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionOutcome, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DEFAULT_LOCALE, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, ExportImageOptions, ExportedImage, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, Locale, MessageBundle, Messages, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderContext, NodeRenderer, OutcomeTone, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, PluginSource, PluginStyle, PluginsLoader, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SanitizeSetting, SourceBlock, StreamParseOptions, StreamRouter, Usage, actionOutcome, applyPatches, assertPlugins, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -255,6 +255,12 @@ interface AIGuiPlugin {
|
|
|
255
255
|
/**
|
|
256
256
|
* LLM-facing guidance describing this plugin's fence syntax.
|
|
257
257
|
*
|
|
258
|
+
* A host does not read this field itself: `buildSystemPrompt({ registry, plugins, locale })`
|
|
259
|
+
* collects the card specs and every enabled plugin's spec in one call, already in the product's
|
|
260
|
+
* language. Assembling it by hand — reading each plugin's spec, joining them, writing the
|
|
261
|
+
* localized wording again — reinvents that badly, and a plugin added later is then missing from
|
|
262
|
+
* the prompt while its renderer is installed.
|
|
263
|
+
*
|
|
258
264
|
* Receives the locale asked of `buildSystemPrompt`, so the rules can be written in the language
|
|
259
265
|
* the product answers in — a Chinese persona followed by English rules reads as a contradiction
|
|
260
266
|
* to the model. Plugins that only ship English simply ignore the argument.
|
|
@@ -284,9 +290,7 @@ interface FeedOptions {
|
|
|
284
290
|
signal?: AbortSignal;
|
|
285
291
|
}
|
|
286
292
|
type FeedChunk = string | Uint8Array;
|
|
287
|
-
type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>;
|
|
288
|
-
|
|
289
|
-
//#endregion
|
|
293
|
+
type FeedSource = AsyncIterable<FeedChunk> | ReadableStream<FeedChunk>; //#endregion
|
|
290
294
|
//#region src/card-registry.d.ts
|
|
291
295
|
interface CardParseResult {
|
|
292
296
|
data: unknown;
|
|
@@ -684,6 +688,17 @@ declare function loadPlugins(source?: PluginSource): AIGuiPlugin[] | Promise<AIG
|
|
|
684
688
|
* What matters is the members, not the array.
|
|
685
689
|
*/
|
|
686
690
|
declare function samePlugins(a?: AIGuiPlugin[], b?: AIGuiPlugin[]): boolean;
|
|
691
|
+
/**
|
|
692
|
+
* Reject anything in the list that is not a plugin, naming what to do about it.
|
|
693
|
+
*
|
|
694
|
+
* Every plugin package exports a factory, so `plugins: [katex]` instead of `plugins: [katex()]` is
|
|
695
|
+
* the easiest mistake to make — and it used to be the quietest. A function has a `name` of its
|
|
696
|
+
* own, `"katex"`, so the renderer accepted it, found no `extendParser` and no `nodeRenderers`, and
|
|
697
|
+
* did nothing: no error, no warning, markdown still rendering, only the maths and the diagrams
|
|
698
|
+
* missing. A product can ship like that and nobody notices until someone asks why an equation is
|
|
699
|
+
* plain text. Misconfiguration should be loud, so this throws.
|
|
700
|
+
*/
|
|
701
|
+
declare function assertPlugins(plugins: readonly unknown[] | undefined, label?: string): void;
|
|
687
702
|
/** Merge every plugin's `nodeRenderers` into a single map (later plugins win). */
|
|
688
703
|
declare function collectNodeRenderers(plugins?: AIGuiPlugin[], debugOptions?: CollectNodeRendererOptions): Record<string, NodeRenderer>;
|
|
689
704
|
/** The set of node types claimed by the given plugins. */
|
|
@@ -985,4 +1000,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
985
1000
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
986
1001
|
|
|
987
1002
|
//#endregion
|
|
988
|
-
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionOutcome, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DEFAULT_LOCALE, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, ExportImageOptions, ExportedImage, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, Locale, MessageBundle, Messages, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderContext, NodeRenderer, OutcomeTone, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, PluginSource, PluginStyle, PluginsLoader, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SanitizeSetting, SourceBlock, StreamParseOptions, StreamRouter, Usage, actionOutcome, applyPatches, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
|
1003
|
+
export { AIGuiPlugin, ASTNode, ActionAbortedError, ActionAlreadyRegisteredError, ActionContext, ActionDefinition, ActionDestroyedError, ActionDispatchOptions, ActionErrorEvent, ActionEventBase, ActionExecutionError, ActionNotFoundError, ActionOutcome, ActionRegisterOptions, ActionRegistry, ActionRequest, ActionRuntime, ActionRuntimeError, ActionRuntimeOptions, ActionStartEvent, ActionState, ActionStateListener, ActionStatus, ActionSuccessEvent, ActionTimeoutError, ActionValidationError, BuildSystemPromptOptions, ByteStreamSource, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardAction, CardActionError, CardDef, CardJSONError, CardLimitError, CardListener, CardNotFoundError, CardParseResult, CardPatch, CardPatchBatch, CardPatchResult, CardRecord, CardRegistry, CardRevisionConflictError, CardSnapshot, CardSnapshotError, CardStore, CardStoreError, CardStoreListener, CardStoreOptions, CardTypeConflictError, CardValidationError, ChannelSink, Citation, CollectNodeRendererOptions, DEFAULT_LOCALE, DebugEmitter, DebugEvent, DebugEventListener, DebugEventTarget, DebugInstrumentationTarget, DebugOptions, DebugRedactContext, DebugSource, ExportImageOptions, ExportedImage, FeedChunk, FeedOptions, FeedSource, JSONSchema, JSONSchemaValidationResult, Locale, MessageBundle, Messages, ModelStreamEvent, MountCardSlotRequest, MountedCardSlot, NodeRenderContext, NodeRenderer, OutcomeTone, ParseResult, ParserOptions, PartialJSONResult, Patch, PluginCommitContext, PluginSource, PluginStyle, PluginsLoader, RenderMountContext, RenderOutput, Renderer, RendererOptions, SSEEvent, SSEOptions, SafeDebugValueOptions, SanitizeHtmlOptions, SanitizeSetting, SourceBlock, StreamParseOptions, StreamRouter, Usage, actionOutcome, applyPatches, assertPlugins, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import DOMPurify from "dompurify";
|
|
2
2
|
import MarkdownIt from "markdown-it";
|
|
3
|
+
import cjkFriendly from "markdown-it-cjk-friendly";
|
|
3
4
|
|
|
4
5
|
//#region src/partial-json.ts
|
|
5
6
|
/**
|
|
@@ -1441,8 +1442,32 @@ function samePlugins(a, b) {
|
|
|
1441
1442
|
if (!a || !b || a.length !== b.length) return false;
|
|
1442
1443
|
return a.every((plugin, index) => plugin === b[index]);
|
|
1443
1444
|
}
|
|
1445
|
+
/**
|
|
1446
|
+
* Reject anything in the list that is not a plugin, naming what to do about it.
|
|
1447
|
+
*
|
|
1448
|
+
* Every plugin package exports a factory, so `plugins: [katex]` instead of `plugins: [katex()]` is
|
|
1449
|
+
* the easiest mistake to make — and it used to be the quietest. A function has a `name` of its
|
|
1450
|
+
* own, `"katex"`, so the renderer accepted it, found no `extendParser` and no `nodeRenderers`, and
|
|
1451
|
+
* did nothing: no error, no warning, markdown still rendering, only the maths and the diagrams
|
|
1452
|
+
* missing. A product can ship like that and nobody notices until someone asks why an equation is
|
|
1453
|
+
* plain text. Misconfiguration should be loud, so this throws.
|
|
1454
|
+
*/
|
|
1455
|
+
function assertPlugins(plugins, label = "plugins") {
|
|
1456
|
+
if (!plugins) return;
|
|
1457
|
+
plugins.forEach((plugin, index) => {
|
|
1458
|
+
const at = `${label}[${index}]`;
|
|
1459
|
+
if (typeof plugin === "function") {
|
|
1460
|
+
const called = plugin.name ? `${plugin.name}()` : "the factory";
|
|
1461
|
+
throw new TypeError(`${at} is a factory function, not a plugin. Call it: ${called}`);
|
|
1462
|
+
}
|
|
1463
|
+
if (plugin === null || typeof plugin !== "object") throw new TypeError(`${at} is ${plugin === null ? "null" : typeof plugin}, not a plugin object`);
|
|
1464
|
+
const { name } = plugin;
|
|
1465
|
+
if (typeof name !== "string" || name.length === 0) throw new TypeError(`${at} has no \`name\`. A plugin needs one: its stylesheet and its debug events are keyed by it`);
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1444
1468
|
/** Merge every plugin's `nodeRenderers` into a single map (later plugins win). */
|
|
1445
1469
|
function collectNodeRenderers(plugins = [], debugOptions = {}) {
|
|
1470
|
+
assertPlugins(plugins);
|
|
1446
1471
|
const map = {};
|
|
1447
1472
|
const target = debugOptions.debugTarget;
|
|
1448
1473
|
const debug = target ? void 0 : debugOptions.debug === true ? new DebugEmitter("renderer", debugOptions) : void 0;
|
|
@@ -1530,6 +1555,7 @@ function createParserWithMetadata(options = {}) {
|
|
|
1530
1555
|
html: options.rawHtml !== false,
|
|
1531
1556
|
linkify: true
|
|
1532
1557
|
});
|
|
1558
|
+
md.use(cjkFriendly);
|
|
1533
1559
|
options.configureMd?.(md);
|
|
1534
1560
|
for (const plugin of options.plugins ?? []) plugin.extendParser?.(md);
|
|
1535
1561
|
const hasParserExtensions = Boolean(options.configureMd || options.plugins?.some((plugin) => plugin.extendParser));
|
|
@@ -2043,6 +2069,7 @@ var Renderer = class {
|
|
|
2043
2069
|
debug;
|
|
2044
2070
|
constructor(options = {}) {
|
|
2045
2071
|
this.options = options;
|
|
2072
|
+
assertPlugins(options.plugins);
|
|
2046
2073
|
this.debug = new DebugEmitter(this.debugSource, options);
|
|
2047
2074
|
this.sanitize = options.sanitize === false ? false : typeof options.sanitize === "object" ? options.sanitize : {};
|
|
2048
2075
|
this.registerPluginCards(options.plugins);
|
|
@@ -2068,6 +2095,7 @@ var Renderer = class {
|
|
|
2068
2095
|
* Passing the same plugins again is a no-op, so a host may call this on every render.
|
|
2069
2096
|
*/
|
|
2070
2097
|
setPlugins(plugins) {
|
|
2098
|
+
assertPlugins(plugins);
|
|
2071
2099
|
if (samePlugins(this.options.plugins, plugins)) return;
|
|
2072
2100
|
this.options = {
|
|
2073
2101
|
...this.options,
|
|
@@ -2833,4 +2861,4 @@ function delay(ms, signal) {
|
|
|
2833
2861
|
}
|
|
2834
2862
|
|
|
2835
2863
|
//#endregion
|
|
2836
|
-
export { ActionAbortedError, ActionAlreadyRegisteredError, ActionDestroyedError, ActionExecutionError, ActionNotFoundError, ActionRegistry, ActionRuntime, ActionRuntimeError, ActionTimeoutError, ActionValidationError, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardJSONError, CardLimitError, CardNotFoundError, CardRegistry, CardRevisionConflictError, CardSnapshotError, CardStore, CardStoreError, CardTypeConflictError, CardValidationError, DEFAULT_LOCALE, DebugEmitter, Renderer, StreamRouter, actionOutcome, applyPatches, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
|
2864
|
+
export { ActionAbortedError, ActionAlreadyRegisteredError, ActionDestroyedError, ActionExecutionError, ActionNotFoundError, ActionRegistry, ActionRuntime, ActionRuntimeError, ActionTimeoutError, ActionValidationError, CARD_ID_MAX_LENGTH, CARD_JSON_MAX_DEPTH, CARD_JSON_MAX_NODES, CARD_PATCH_BATCH_MAX_SIZE, CardJSONError, CardLimitError, CardNotFoundError, CardRegistry, CardRevisionConflictError, CardSnapshotError, CardStore, CardStoreError, CardTypeConflictError, CardValidationError, DEFAULT_LOCALE, DebugEmitter, Renderer, StreamRouter, actionOutcome, applyPatches, assertPlugins, availableLocales, baseCss, buildSystemPrompt, collectNodeRenderers, collectPluginStyles, contentDeltas, createActionRuntime, createParser, createParserWithMetadata, diffAst, downloadImage, exportRenderedImages, exportSVGToImage, getActionKey, getIdleActionState, injectPluginStyles, isCardPatchResult, jsonLines, loadPlugins, mockModelStream, ndjson, parsePartialJSON, parseSSE, pluginNodeTypes, readableBytes, repairMarkdown, resolveMessages, safeDebugValue, samePlugins, sanitizeHtml, sanitizeRenderedHtml, textLines, translate, translator, validateJSONSchema };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-gui/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Headless streaming renderer core for LLM-generated UI — markdown/JSON repair, card registry, AST diff, plugin engine, sanitizer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"dompurify": "^3.4.12",
|
|
55
|
-
"markdown-it": "^14.1.0"
|
|
55
|
+
"markdown-it": "^14.1.0",
|
|
56
|
+
"markdown-it-cjk-friendly": "^2.0.2"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
59
|
"@types/markdown-it": "^14.1.2",
|