@ai-gui/core 0.27.0 → 0.29.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 +34 -0
- package/dist/index.cjs +77 -0
- package/dist/index.d.cts +53 -1
- package/dist/index.d.ts +53 -1
- package/dist/index.js +77 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,6 +108,39 @@ const runtime = createActionRuntime({ registry: actions, cardStore })
|
|
|
108
108
|
|
|
109
109
|
`CardStore` supports initialize-if-absent registration, immutable records, recursive object merge, replace, atomic patch batches, revision checks, subscriptions, delete/clear, and snapshot/restore. Action patch results use optimistic mutation epochs, so an older Action cannot overwrite a Card changed, deleted, recreated, or restored after that Action started.
|
|
110
110
|
|
|
111
|
+
## One stream, many channels
|
|
112
|
+
|
|
113
|
+
`Renderer` is a single-writer append-only buffer: `push` concatenates, and markdown block boundaries do not survive two sources interleaving into them. So anything arriving *alongside* the answer — progress, a background job, a tool that finished late — goes on its own channel and updates a Card by id, in any order, as many times as it likes.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { CardStore, Renderer, StreamRouter, cardChannel } from "@ai-gui/core"
|
|
117
|
+
|
|
118
|
+
const store = new CardStore({ registry })
|
|
119
|
+
const renderer = new Renderer({ plugins, onPatch })
|
|
120
|
+
|
|
121
|
+
await new StreamRouter()
|
|
122
|
+
.channel("content", renderer) // text deltas → the answer
|
|
123
|
+
.on("cards", cardChannel(store, { onError })) // card messages → the store
|
|
124
|
+
.on("usage", (u) => setTokens(u)) // anything else → your callback
|
|
125
|
+
.feed(response.body)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The wire accepts either form, mixed freely in one stream:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
{"ch":"content","delta":"Working"}
|
|
132
|
+
{"ch":"cards","data":{"op":"register","id":"job-7","type":"task","data":{"pct":0}}}
|
|
133
|
+
{"ch":"cards","data":{"op":"merge","cardId":"job-7","data":{"pct":60}}}
|
|
134
|
+
event: usage
|
|
135
|
+
data: {"in":120}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`cardChannel` accepts `register`, `merge`, `replace` and `batch`. Not `delete`: a card the reader is looking at should not vanish because a late frame said so — call `store.delete` from your own handler where you can decide.
|
|
139
|
+
|
|
140
|
+
Send `revision` on a patch when a late frame overwriting newer state would be wrong; the store rejects the stale one. Without it, last write wins.
|
|
141
|
+
|
|
142
|
+
Every failure is reported through `onError` rather than thrown, because the handler runs inside one long `feed` await — a throw there would not just drop the card, it would kill the content channel and stop the answer mid-sentence. Leave `onError` unset and failures go to `console.error`; a silently swallowed one is indistinguishable from a card the model never sent.
|
|
143
|
+
|
|
111
144
|
## Exports
|
|
112
145
|
|
|
113
146
|
- `Renderer` — `push(chunk)`, `feed(AsyncIterable | ReadableStream)`, `reset()`, `setPlugins(plugins)`; constructor `{ registry?, plugins?, sanitize?, rawHtml?, onPatch?(patches, nodes) }`.
|
|
@@ -115,6 +148,7 @@ const runtime = createActionRuntime({ registry: actions, cardStore })
|
|
|
115
148
|
- `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
149
|
- 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.
|
|
117
150
|
- `StreamRouter` — demultiplex one stream into named channels: `.channel(name, sink)`, `.on(name, cb)`, `.feed(source)`.
|
|
151
|
+
- `cardChannel(store, { onError? })` — a `StreamRouter` handler that applies `register` / `merge` / `replace` / `batch` messages to a `CardStore`, reporting failures instead of throwing into the feed.
|
|
118
152
|
- `CardRegistry` — `register(def)`, `parse(type, rawJson)`, `getRender(type)`, `toPromptSpec()`, `toJSONSchema()`.
|
|
119
153
|
- `CardStore` — `register`, `get`, `list`, `subscribe`, `apply`, `applyAll`, `delete`, `clear`, `snapshot`, and `restore` for Cards with stable IDs.
|
|
120
154
|
- `ActionRegistry`, `ActionRuntime`, `createActionRuntime`, `getActionKey`, `getIdleActionState` — validated application-owned action execution and observable lifecycle state.
|
package/dist/index.cjs
CHANGED
|
@@ -1002,6 +1002,82 @@ function safeCall(listener, ...args) {
|
|
|
1002
1002
|
} catch {}
|
|
1003
1003
|
}
|
|
1004
1004
|
|
|
1005
|
+
//#endregion
|
|
1006
|
+
//#region src/card-channel.ts
|
|
1007
|
+
const OPS = "register, merge, replace, batch";
|
|
1008
|
+
/**
|
|
1009
|
+
* Apply card messages arriving on a stream channel to a `CardStore`.
|
|
1010
|
+
*
|
|
1011
|
+
* ```ts
|
|
1012
|
+
* new StreamRouter()
|
|
1013
|
+
* .channel("content", renderer)
|
|
1014
|
+
* .on("cards", cardChannel(store))
|
|
1015
|
+
* ```
|
|
1016
|
+
*
|
|
1017
|
+
* This is the parallel half of the design. The content channel is one append-only buffer with a
|
|
1018
|
+
* single writer, because markdown block boundaries cannot survive two sources interleaving into
|
|
1019
|
+
* them. Cards are addressed by id instead, so anything on the wire — a background job, a tool that
|
|
1020
|
+
* finished late, a second model — can update one without touching the text, in any order, as many
|
|
1021
|
+
* times as it likes.
|
|
1022
|
+
*
|
|
1023
|
+
* Ordering is the store's contract, not this adapter's: a patch carrying `revision` is an
|
|
1024
|
+
* optimistic lock and a stale one is rejected through `onError`; a patch without one is
|
|
1025
|
+
* last-write-wins. Send `revision` when a late frame overwriting a newer state would be wrong.
|
|
1026
|
+
*
|
|
1027
|
+
* A card channel carries whole messages, not text deltas — one JSON object per frame.
|
|
1028
|
+
*/
|
|
1029
|
+
function cardChannel(store, options = {}) {
|
|
1030
|
+
const report = (error, message) => {
|
|
1031
|
+
if (options.onError) options.onError(error, message);
|
|
1032
|
+
else console.error("[aigui] card channel:", error);
|
|
1033
|
+
};
|
|
1034
|
+
return (value) => {
|
|
1035
|
+
let message = value;
|
|
1036
|
+
if (typeof message === "string") try {
|
|
1037
|
+
message = JSON.parse(message);
|
|
1038
|
+
} catch {
|
|
1039
|
+
report(new TypeError("Card channel received text that is not a JSON message"), value);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
if (typeof message !== "object" || message === null || Array.isArray(message)) {
|
|
1043
|
+
report(new TypeError("A card message must be a JSON object"), value);
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
const op = message.op;
|
|
1047
|
+
try {
|
|
1048
|
+
if (op === "register") {
|
|
1049
|
+
const { id, type, data } = message;
|
|
1050
|
+
if (typeof id !== "string" || typeof type !== "string") {
|
|
1051
|
+
report(new TypeError("A register message needs a string id and type"), value);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
store.register({
|
|
1055
|
+
id,
|
|
1056
|
+
type,
|
|
1057
|
+
data
|
|
1058
|
+
});
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
if (isCardPatchResult(message)) {
|
|
1062
|
+
if (message.op === "batch") store.applyAll(message.patches);
|
|
1063
|
+
else store.apply(message);
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
if (op === "merge" || op === "replace") {
|
|
1067
|
+
report(new TypeError(`A ${op} message needs a string cardId and a data field`), value);
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
if (op === "batch") {
|
|
1071
|
+
report(new TypeError("A batch message needs a patches array of merge or replace patches"), value);
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
report(new TypeError(`Card message op must be one of ${OPS}, not ${JSON.stringify(op)}`), value);
|
|
1075
|
+
} catch (error) {
|
|
1076
|
+
report(error, value);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1005
1081
|
//#endregion
|
|
1006
1082
|
//#region src/actions.ts
|
|
1007
1083
|
let nextRuntimeId = 0;
|
|
@@ -2919,6 +2995,7 @@ exports.assertPlugins = assertPlugins
|
|
|
2919
2995
|
exports.availableLocales = availableLocales
|
|
2920
2996
|
exports.baseCss = baseCss
|
|
2921
2997
|
exports.buildSystemPrompt = buildSystemPrompt
|
|
2998
|
+
exports.cardChannel = cardChannel
|
|
2922
2999
|
exports.collectNodeRenderers = collectNodeRenderers
|
|
2923
3000
|
exports.collectPluginStyles = collectPluginStyles
|
|
2924
3001
|
exports.contentDeltas = contentDeltas
|
package/dist/index.d.cts
CHANGED
|
@@ -463,6 +463,58 @@ declare class CardLimitError extends CardStoreError {}
|
|
|
463
463
|
declare class CardSnapshotError extends CardStoreError {}
|
|
464
464
|
declare function isCardPatchResult(value: unknown): value is CardPatchResult;
|
|
465
465
|
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/card-channel.d.ts
|
|
468
|
+
/**
|
|
469
|
+
* A message a stream may send on a card channel.
|
|
470
|
+
*
|
|
471
|
+
* `register` first, then any number of patches against that id. Deletion is deliberately not here:
|
|
472
|
+
* a card the reader is looking at, or has already acted on, should not vanish because a late frame
|
|
473
|
+
* said so. A host that wants it calls `store.delete` from its own handler, where it can decide.
|
|
474
|
+
*/
|
|
475
|
+
type CardMessage = {
|
|
476
|
+
op: "register";
|
|
477
|
+
id: string;
|
|
478
|
+
type: string;
|
|
479
|
+
data: unknown;
|
|
480
|
+
} | CardPatch | CardPatchBatch;
|
|
481
|
+
interface CardChannelOptions {
|
|
482
|
+
/**
|
|
483
|
+
* Where a message that could not be applied goes.
|
|
484
|
+
*
|
|
485
|
+
* This is the reason the adapter exists rather than being three lines at the call site. The
|
|
486
|
+
* handler runs inside `StreamRouter.feed`, one long await over the whole response — a throw here
|
|
487
|
+
* does not just drop the card, it kills the content channel with it and the answer stops
|
|
488
|
+
* mid-sentence. So every failure is caught, and reported here instead.
|
|
489
|
+
*
|
|
490
|
+
* Left unset, failures go to `console.error`: a swallowed one looks exactly like a card that the
|
|
491
|
+
* model never sent, which is the hardest version of this bug to find.
|
|
492
|
+
*/
|
|
493
|
+
onError?: (error: unknown, message: unknown) => void;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Apply card messages arriving on a stream channel to a `CardStore`.
|
|
497
|
+
*
|
|
498
|
+
* ```ts
|
|
499
|
+
* new StreamRouter()
|
|
500
|
+
* .channel("content", renderer)
|
|
501
|
+
* .on("cards", cardChannel(store))
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* This is the parallel half of the design. The content channel is one append-only buffer with a
|
|
505
|
+
* single writer, because markdown block boundaries cannot survive two sources interleaving into
|
|
506
|
+
* them. Cards are addressed by id instead, so anything on the wire — a background job, a tool that
|
|
507
|
+
* finished late, a second model — can update one without touching the text, in any order, as many
|
|
508
|
+
* times as it likes.
|
|
509
|
+
*
|
|
510
|
+
* Ordering is the store's contract, not this adapter's: a patch carrying `revision` is an
|
|
511
|
+
* optimistic lock and a stale one is rejected through `onError`; a patch without one is
|
|
512
|
+
* last-write-wins. Send `revision` when a late frame overwriting a newer state would be wrong.
|
|
513
|
+
*
|
|
514
|
+
* A card channel carries whole messages, not text deltas — one JSON object per frame.
|
|
515
|
+
*/
|
|
516
|
+
declare function cardChannel(store: CardStore, options?: CardChannelOptions): (value: unknown) => void;
|
|
517
|
+
|
|
466
518
|
//#endregion
|
|
467
519
|
//#region src/json-schema.d.ts
|
|
468
520
|
interface JSONSchemaValidationResult {
|
|
@@ -1000,4 +1052,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
1000
1052
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
1001
1053
|
|
|
1002
1054
|
//#endregion
|
|
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 };
|
|
1055
|
+
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, CardChannelOptions, CardDef, CardJSONError, CardLimitError, CardListener, CardMessage, 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, cardChannel, 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
|
@@ -463,6 +463,58 @@ declare class CardLimitError extends CardStoreError {}
|
|
|
463
463
|
declare class CardSnapshotError extends CardStoreError {}
|
|
464
464
|
declare function isCardPatchResult(value: unknown): value is CardPatchResult;
|
|
465
465
|
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region src/card-channel.d.ts
|
|
468
|
+
/**
|
|
469
|
+
* A message a stream may send on a card channel.
|
|
470
|
+
*
|
|
471
|
+
* `register` first, then any number of patches against that id. Deletion is deliberately not here:
|
|
472
|
+
* a card the reader is looking at, or has already acted on, should not vanish because a late frame
|
|
473
|
+
* said so. A host that wants it calls `store.delete` from its own handler, where it can decide.
|
|
474
|
+
*/
|
|
475
|
+
type CardMessage = {
|
|
476
|
+
op: "register";
|
|
477
|
+
id: string;
|
|
478
|
+
type: string;
|
|
479
|
+
data: unknown;
|
|
480
|
+
} | CardPatch | CardPatchBatch;
|
|
481
|
+
interface CardChannelOptions {
|
|
482
|
+
/**
|
|
483
|
+
* Where a message that could not be applied goes.
|
|
484
|
+
*
|
|
485
|
+
* This is the reason the adapter exists rather than being three lines at the call site. The
|
|
486
|
+
* handler runs inside `StreamRouter.feed`, one long await over the whole response — a throw here
|
|
487
|
+
* does not just drop the card, it kills the content channel with it and the answer stops
|
|
488
|
+
* mid-sentence. So every failure is caught, and reported here instead.
|
|
489
|
+
*
|
|
490
|
+
* Left unset, failures go to `console.error`: a swallowed one looks exactly like a card that the
|
|
491
|
+
* model never sent, which is the hardest version of this bug to find.
|
|
492
|
+
*/
|
|
493
|
+
onError?: (error: unknown, message: unknown) => void;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Apply card messages arriving on a stream channel to a `CardStore`.
|
|
497
|
+
*
|
|
498
|
+
* ```ts
|
|
499
|
+
* new StreamRouter()
|
|
500
|
+
* .channel("content", renderer)
|
|
501
|
+
* .on("cards", cardChannel(store))
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* This is the parallel half of the design. The content channel is one append-only buffer with a
|
|
505
|
+
* single writer, because markdown block boundaries cannot survive two sources interleaving into
|
|
506
|
+
* them. Cards are addressed by id instead, so anything on the wire — a background job, a tool that
|
|
507
|
+
* finished late, a second model — can update one without touching the text, in any order, as many
|
|
508
|
+
* times as it likes.
|
|
509
|
+
*
|
|
510
|
+
* Ordering is the store's contract, not this adapter's: a patch carrying `revision` is an
|
|
511
|
+
* optimistic lock and a stale one is rejected through `onError`; a patch without one is
|
|
512
|
+
* last-write-wins. Send `revision` when a late frame overwriting a newer state would be wrong.
|
|
513
|
+
*
|
|
514
|
+
* A card channel carries whole messages, not text deltas — one JSON object per frame.
|
|
515
|
+
*/
|
|
516
|
+
declare function cardChannel(store: CardStore, options?: CardChannelOptions): (value: unknown) => void;
|
|
517
|
+
|
|
466
518
|
//#endregion
|
|
467
519
|
//#region src/json-schema.d.ts
|
|
468
520
|
interface JSONSchemaValidationResult {
|
|
@@ -1000,4 +1052,4 @@ declare function mockModelStream(events: Iterable<ModelStreamEvent> | AsyncItera
|
|
|
1000
1052
|
declare function readableBytes(chunks: Iterable<string | Uint8Array> | AsyncIterable<string | Uint8Array>): ReadableStream<Uint8Array>;
|
|
1001
1053
|
|
|
1002
1054
|
//#endregion
|
|
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 };
|
|
1055
|
+
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, CardChannelOptions, CardDef, CardJSONError, CardLimitError, CardListener, CardMessage, 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, cardChannel, 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
|
@@ -978,6 +978,82 @@ function safeCall(listener, ...args) {
|
|
|
978
978
|
} catch {}
|
|
979
979
|
}
|
|
980
980
|
|
|
981
|
+
//#endregion
|
|
982
|
+
//#region src/card-channel.ts
|
|
983
|
+
const OPS = "register, merge, replace, batch";
|
|
984
|
+
/**
|
|
985
|
+
* Apply card messages arriving on a stream channel to a `CardStore`.
|
|
986
|
+
*
|
|
987
|
+
* ```ts
|
|
988
|
+
* new StreamRouter()
|
|
989
|
+
* .channel("content", renderer)
|
|
990
|
+
* .on("cards", cardChannel(store))
|
|
991
|
+
* ```
|
|
992
|
+
*
|
|
993
|
+
* This is the parallel half of the design. The content channel is one append-only buffer with a
|
|
994
|
+
* single writer, because markdown block boundaries cannot survive two sources interleaving into
|
|
995
|
+
* them. Cards are addressed by id instead, so anything on the wire — a background job, a tool that
|
|
996
|
+
* finished late, a second model — can update one without touching the text, in any order, as many
|
|
997
|
+
* times as it likes.
|
|
998
|
+
*
|
|
999
|
+
* Ordering is the store's contract, not this adapter's: a patch carrying `revision` is an
|
|
1000
|
+
* optimistic lock and a stale one is rejected through `onError`; a patch without one is
|
|
1001
|
+
* last-write-wins. Send `revision` when a late frame overwriting a newer state would be wrong.
|
|
1002
|
+
*
|
|
1003
|
+
* A card channel carries whole messages, not text deltas — one JSON object per frame.
|
|
1004
|
+
*/
|
|
1005
|
+
function cardChannel(store, options = {}) {
|
|
1006
|
+
const report = (error, message) => {
|
|
1007
|
+
if (options.onError) options.onError(error, message);
|
|
1008
|
+
else console.error("[aigui] card channel:", error);
|
|
1009
|
+
};
|
|
1010
|
+
return (value) => {
|
|
1011
|
+
let message = value;
|
|
1012
|
+
if (typeof message === "string") try {
|
|
1013
|
+
message = JSON.parse(message);
|
|
1014
|
+
} catch {
|
|
1015
|
+
report(new TypeError("Card channel received text that is not a JSON message"), value);
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
if (typeof message !== "object" || message === null || Array.isArray(message)) {
|
|
1019
|
+
report(new TypeError("A card message must be a JSON object"), value);
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
const op = message.op;
|
|
1023
|
+
try {
|
|
1024
|
+
if (op === "register") {
|
|
1025
|
+
const { id, type, data } = message;
|
|
1026
|
+
if (typeof id !== "string" || typeof type !== "string") {
|
|
1027
|
+
report(new TypeError("A register message needs a string id and type"), value);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
store.register({
|
|
1031
|
+
id,
|
|
1032
|
+
type,
|
|
1033
|
+
data
|
|
1034
|
+
});
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
if (isCardPatchResult(message)) {
|
|
1038
|
+
if (message.op === "batch") store.applyAll(message.patches);
|
|
1039
|
+
else store.apply(message);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
if (op === "merge" || op === "replace") {
|
|
1043
|
+
report(new TypeError(`A ${op} message needs a string cardId and a data field`), value);
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
if (op === "batch") {
|
|
1047
|
+
report(new TypeError("A batch message needs a patches array of merge or replace patches"), value);
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
report(new TypeError(`Card message op must be one of ${OPS}, not ${JSON.stringify(op)}`), value);
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
report(error, value);
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
981
1057
|
//#endregion
|
|
982
1058
|
//#region src/actions.ts
|
|
983
1059
|
let nextRuntimeId = 0;
|
|
@@ -2861,4 +2937,4 @@ function delay(ms, signal) {
|
|
|
2861
2937
|
}
|
|
2862
2938
|
|
|
2863
2939
|
//#endregion
|
|
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 };
|
|
2940
|
+
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, cardChannel, 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