@tylertech/forge-ai 0.13.4 → 0.13.5
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/custom-elements.json +66 -48
- package/dist/ai-chatbot/markdown-stream-controller.d.ts +2 -1
- package/dist/ai-chatbot/markdown-stream-controller.mjs +5 -5
- package/dist/ai-chatbot/utils.d.ts +11 -1
- package/dist/ai-chatbot/utils.mjs +3 -2
- package/dist/ai-message-thread/ai-message-thread.mjs +1 -1
- package/package.json +1 -1
package/custom-elements.json
CHANGED
|
@@ -651,156 +651,156 @@
|
|
|
651
651
|
},
|
|
652
652
|
{
|
|
653
653
|
"kind": "javascript-module",
|
|
654
|
-
"path": "src/lib/ai-
|
|
654
|
+
"path": "src/lib/ai-button/ai-button.ts",
|
|
655
655
|
"declarations": [
|
|
656
656
|
{
|
|
657
657
|
"kind": "variable",
|
|
658
|
-
"name": "
|
|
658
|
+
"name": "AiButtonComponentTagName",
|
|
659
659
|
"type": {
|
|
660
660
|
"text": "keyof HTMLElementTagNameMap"
|
|
661
661
|
},
|
|
662
|
-
"default": "'forge-ai-
|
|
662
|
+
"default": "'forge-ai-button'"
|
|
663
663
|
},
|
|
664
664
|
{
|
|
665
665
|
"kind": "class",
|
|
666
666
|
"description": "",
|
|
667
|
-
"name": "
|
|
667
|
+
"name": "AiButtonComponent",
|
|
668
|
+
"slots": [
|
|
669
|
+
{
|
|
670
|
+
"description": "Default slot for button content",
|
|
671
|
+
"name": ""
|
|
672
|
+
}
|
|
673
|
+
],
|
|
668
674
|
"members": [
|
|
669
675
|
{
|
|
670
676
|
"kind": "field",
|
|
671
|
-
"name": "
|
|
677
|
+
"name": "disabled",
|
|
672
678
|
"type": {
|
|
673
679
|
"text": "boolean"
|
|
674
680
|
},
|
|
675
681
|
"privacy": "public",
|
|
676
682
|
"default": "false",
|
|
677
|
-
"description": "Whether the
|
|
678
|
-
"attribute": "
|
|
683
|
+
"description": "Whether the button is disabled",
|
|
684
|
+
"attribute": "disabled",
|
|
679
685
|
"reflects": true
|
|
680
686
|
}
|
|
681
687
|
],
|
|
682
688
|
"attributes": [
|
|
683
689
|
{
|
|
684
|
-
"name": "
|
|
690
|
+
"name": "disabled",
|
|
685
691
|
"type": {
|
|
686
692
|
"text": "boolean"
|
|
687
693
|
},
|
|
688
694
|
"default": "false",
|
|
689
|
-
"description": "Whether the
|
|
690
|
-
"fieldName": "
|
|
695
|
+
"description": "Whether the button is disabled",
|
|
696
|
+
"fieldName": "disabled"
|
|
691
697
|
}
|
|
692
698
|
],
|
|
693
699
|
"superclass": {
|
|
694
700
|
"name": "LitElement",
|
|
695
701
|
"package": "lit"
|
|
696
702
|
},
|
|
697
|
-
"tagName": "forge-ai-
|
|
703
|
+
"tagName": "forge-ai-button",
|
|
698
704
|
"customElement": true
|
|
699
705
|
}
|
|
700
706
|
],
|
|
701
707
|
"exports": [
|
|
702
708
|
{
|
|
703
709
|
"kind": "js",
|
|
704
|
-
"name": "
|
|
710
|
+
"name": "AiButtonComponentTagName",
|
|
705
711
|
"declaration": {
|
|
706
|
-
"name": "
|
|
707
|
-
"module": "src/lib/ai-
|
|
712
|
+
"name": "AiButtonComponentTagName",
|
|
713
|
+
"module": "src/lib/ai-button/ai-button.ts"
|
|
708
714
|
}
|
|
709
715
|
},
|
|
710
716
|
{
|
|
711
717
|
"kind": "js",
|
|
712
|
-
"name": "
|
|
718
|
+
"name": "AiButtonComponent",
|
|
713
719
|
"declaration": {
|
|
714
|
-
"name": "
|
|
715
|
-
"module": "src/lib/ai-
|
|
720
|
+
"name": "AiButtonComponent",
|
|
721
|
+
"module": "src/lib/ai-button/ai-button.ts"
|
|
716
722
|
}
|
|
717
723
|
},
|
|
718
724
|
{
|
|
719
725
|
"kind": "custom-element-definition",
|
|
720
726
|
"declaration": {
|
|
721
|
-
"name": "
|
|
722
|
-
"module": "src/lib/ai-
|
|
727
|
+
"name": "AiButtonComponent",
|
|
728
|
+
"module": "src/lib/ai-button/ai-button.ts"
|
|
723
729
|
}
|
|
724
730
|
}
|
|
725
731
|
]
|
|
726
732
|
},
|
|
727
733
|
{
|
|
728
734
|
"kind": "javascript-module",
|
|
729
|
-
"path": "src/lib/ai-
|
|
735
|
+
"path": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts",
|
|
730
736
|
"declarations": [
|
|
731
737
|
{
|
|
732
738
|
"kind": "variable",
|
|
733
|
-
"name": "
|
|
739
|
+
"name": "AiChainOfThoughtComponentTagName",
|
|
734
740
|
"type": {
|
|
735
741
|
"text": "keyof HTMLElementTagNameMap"
|
|
736
742
|
},
|
|
737
|
-
"default": "'forge-ai-
|
|
743
|
+
"default": "'forge-ai-chain-of-thought'"
|
|
738
744
|
},
|
|
739
745
|
{
|
|
740
746
|
"kind": "class",
|
|
741
747
|
"description": "",
|
|
742
|
-
"name": "
|
|
743
|
-
"slots": [
|
|
744
|
-
{
|
|
745
|
-
"description": "Default slot for button content",
|
|
746
|
-
"name": ""
|
|
747
|
-
}
|
|
748
|
-
],
|
|
748
|
+
"name": "AiChainOfThoughtComponent",
|
|
749
749
|
"members": [
|
|
750
750
|
{
|
|
751
751
|
"kind": "field",
|
|
752
|
-
"name": "
|
|
752
|
+
"name": "expanded",
|
|
753
753
|
"type": {
|
|
754
754
|
"text": "boolean"
|
|
755
755
|
},
|
|
756
756
|
"privacy": "public",
|
|
757
757
|
"default": "false",
|
|
758
|
-
"description": "Whether the
|
|
759
|
-
"attribute": "
|
|
758
|
+
"description": "Whether the chain of thought is expanded",
|
|
759
|
+
"attribute": "expanded",
|
|
760
760
|
"reflects": true
|
|
761
761
|
}
|
|
762
762
|
],
|
|
763
763
|
"attributes": [
|
|
764
764
|
{
|
|
765
|
-
"name": "
|
|
765
|
+
"name": "expanded",
|
|
766
766
|
"type": {
|
|
767
767
|
"text": "boolean"
|
|
768
768
|
},
|
|
769
769
|
"default": "false",
|
|
770
|
-
"description": "Whether the
|
|
771
|
-
"fieldName": "
|
|
770
|
+
"description": "Whether the chain of thought is expanded",
|
|
771
|
+
"fieldName": "expanded"
|
|
772
772
|
}
|
|
773
773
|
],
|
|
774
774
|
"superclass": {
|
|
775
775
|
"name": "LitElement",
|
|
776
776
|
"package": "lit"
|
|
777
777
|
},
|
|
778
|
-
"tagName": "forge-ai-
|
|
778
|
+
"tagName": "forge-ai-chain-of-thought",
|
|
779
779
|
"customElement": true
|
|
780
780
|
}
|
|
781
781
|
],
|
|
782
782
|
"exports": [
|
|
783
783
|
{
|
|
784
784
|
"kind": "js",
|
|
785
|
-
"name": "
|
|
785
|
+
"name": "AiChainOfThoughtComponentTagName",
|
|
786
786
|
"declaration": {
|
|
787
|
-
"name": "
|
|
788
|
-
"module": "src/lib/ai-
|
|
787
|
+
"name": "AiChainOfThoughtComponentTagName",
|
|
788
|
+
"module": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts"
|
|
789
789
|
}
|
|
790
790
|
},
|
|
791
791
|
{
|
|
792
792
|
"kind": "js",
|
|
793
|
-
"name": "
|
|
793
|
+
"name": "AiChainOfThoughtComponent",
|
|
794
794
|
"declaration": {
|
|
795
|
-
"name": "
|
|
796
|
-
"module": "src/lib/ai-
|
|
795
|
+
"name": "AiChainOfThoughtComponent",
|
|
796
|
+
"module": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts"
|
|
797
797
|
}
|
|
798
798
|
},
|
|
799
799
|
{
|
|
800
800
|
"kind": "custom-element-definition",
|
|
801
801
|
"declaration": {
|
|
802
|
-
"name": "
|
|
803
|
-
"module": "src/lib/ai-
|
|
802
|
+
"name": "AiChainOfThoughtComponent",
|
|
803
|
+
"module": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts"
|
|
804
804
|
}
|
|
805
805
|
}
|
|
806
806
|
]
|
|
@@ -5014,6 +5014,13 @@
|
|
|
5014
5014
|
"type": {
|
|
5015
5015
|
"text": "string"
|
|
5016
5016
|
}
|
|
5017
|
+
},
|
|
5018
|
+
{
|
|
5019
|
+
"name": "options",
|
|
5020
|
+
"default": "{}",
|
|
5021
|
+
"type": {
|
|
5022
|
+
"text": "RenderMarkdownOptions"
|
|
5023
|
+
}
|
|
5017
5024
|
}
|
|
5018
5025
|
]
|
|
5019
5026
|
}
|
|
@@ -5581,6 +5588,13 @@
|
|
|
5581
5588
|
"type": {
|
|
5582
5589
|
"text": "string"
|
|
5583
5590
|
}
|
|
5591
|
+
},
|
|
5592
|
+
{
|
|
5593
|
+
"name": "{ streaming = true }",
|
|
5594
|
+
"default": "{}",
|
|
5595
|
+
"type": {
|
|
5596
|
+
"text": "RenderMarkdownOptions"
|
|
5597
|
+
}
|
|
5584
5598
|
}
|
|
5585
5599
|
],
|
|
5586
5600
|
"description": "Renders markdown content to sanitized HTML"
|
|
@@ -14290,14 +14304,14 @@
|
|
|
14290
14304
|
"path": "src/lib/ai-attachment/ai-attachment.ts",
|
|
14291
14305
|
"lineNumber": 41
|
|
14292
14306
|
},
|
|
14293
|
-
"AiChainOfThoughtComponent": {
|
|
14294
|
-
"path": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts",
|
|
14295
|
-
"lineNumber": 17
|
|
14296
|
-
},
|
|
14297
14307
|
"AiButtonComponent": {
|
|
14298
14308
|
"path": "src/lib/ai-button/ai-button.ts",
|
|
14299
14309
|
"lineNumber": 22
|
|
14300
14310
|
},
|
|
14311
|
+
"AiChainOfThoughtComponent": {
|
|
14312
|
+
"path": "src/lib/ai-chain-of-thought/ai-chain-of-thought.ts",
|
|
14313
|
+
"lineNumber": 17
|
|
14314
|
+
},
|
|
14301
14315
|
"ForgeAiChatHeaderAgentChangeEventData": {
|
|
14302
14316
|
"path": "src/lib/ai-chat-header/ai-chat-header.ts",
|
|
14303
14317
|
"lineNumber": 39
|
|
@@ -14670,6 +14684,10 @@
|
|
|
14670
14684
|
"path": "src/lib/ai-chatbot/types.ts",
|
|
14671
14685
|
"lineNumber": 320
|
|
14672
14686
|
},
|
|
14687
|
+
"RenderMarkdownOptions": {
|
|
14688
|
+
"path": "src/lib/ai-chatbot/utils.ts",
|
|
14689
|
+
"lineNumber": 6
|
|
14690
|
+
},
|
|
14673
14691
|
"LauncherViewState": {
|
|
14674
14692
|
"path": "src/lib/ai-chatbot-launcher/ai-chatbot-launcher.ts",
|
|
14675
14693
|
"lineNumber": 30
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { RenderMarkdownOptions } from './utils.js';
|
|
2
3
|
/**
|
|
3
4
|
* Reactive controller for caching parsed markdown and throttling renders.
|
|
4
5
|
* Provides HTML caching per message and RAF throttling during streaming.
|
|
@@ -8,6 +9,6 @@ export declare class MarkdownStreamController implements ReactiveController {
|
|
|
8
9
|
constructor(host: ReactiveControllerHost);
|
|
9
10
|
hostConnected(): void;
|
|
10
11
|
hostDisconnected(): void;
|
|
11
|
-
getCachedHtml(messageId: string, content: string): string;
|
|
12
|
+
getCachedHtml(messageId: string, content: string, options?: RenderMarkdownOptions): string;
|
|
12
13
|
scheduleUpdate(): void;
|
|
13
14
|
}
|
|
@@ -16,16 +16,16 @@ class MarkdownStreamController {
|
|
|
16
16
|
}
|
|
17
17
|
this.#markdownCache.clear();
|
|
18
18
|
}
|
|
19
|
-
#getCacheKey(messageId, content) {
|
|
19
|
+
#getCacheKey(messageId, content, { streaming = true }) {
|
|
20
20
|
const hash = content.length + ":" + content.slice(0, 50);
|
|
21
|
-
return `${messageId}:${hash}`;
|
|
21
|
+
return `${messageId}:${hash}:${streaming}`;
|
|
22
22
|
}
|
|
23
|
-
getCachedHtml(messageId, content) {
|
|
23
|
+
getCachedHtml(messageId, content, options = {}) {
|
|
24
24
|
const str = String(content ?? "");
|
|
25
|
-
const key = this.#getCacheKey(messageId, str);
|
|
25
|
+
const key = this.#getCacheKey(messageId, str, options);
|
|
26
26
|
let html = this.#markdownCache.get(key);
|
|
27
27
|
if (!html) {
|
|
28
|
-
html = renderMarkdown(str);
|
|
28
|
+
html = renderMarkdown(str, options);
|
|
29
29
|
this.#markdownCache.set(key, html);
|
|
30
30
|
if (this.#markdownCache.size > 100) {
|
|
31
31
|
const firstKey = this.#markdownCache.keys().next().value;
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { ChatMessage, ContextItem, FileAttachment, ToolCall } from './types.js';
|
|
2
|
+
export interface RenderMarkdownOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Whether the content is still being streamed. Streaming content (the
|
|
5
|
+
* default) is run through markdown-completion repairs that finish partial
|
|
6
|
+
* syntax as tokens arrive. Complete content (e.g. finalized user messages)
|
|
7
|
+
* should set this to `false` so those repairs don't mangle intentional text
|
|
8
|
+
* such as `[text](` into incomplete-link placeholders.
|
|
9
|
+
*/
|
|
10
|
+
streaming?: boolean;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Generates a unique ID using UUID v4
|
|
4
14
|
*/
|
|
@@ -6,7 +16,7 @@ export declare function generateId(): string;
|
|
|
6
16
|
/**
|
|
7
17
|
* Renders markdown content to sanitized HTML
|
|
8
18
|
*/
|
|
9
|
-
export declare function renderMarkdown(content: string): string;
|
|
19
|
+
export declare function renderMarkdown(content: string, { streaming }?: RenderMarkdownOptions): string;
|
|
10
20
|
/**
|
|
11
21
|
* Downloads content as a file with specified MIME type
|
|
12
22
|
*/
|
|
@@ -2,6 +2,7 @@ import { marked } from "marked";
|
|
|
2
2
|
import DOMPurify from "dompurify";
|
|
3
3
|
import remend from "remend";
|
|
4
4
|
import { v4 } from "uuid";
|
|
5
|
+
const COMPLETE_CONTENT_REMEND_OPTIONS = { links: false, images: false };
|
|
5
6
|
const DOMPURIFY_CONFIG = {
|
|
6
7
|
FORBID_TAGS: ["script", "style", "iframe", "object", "embed"],
|
|
7
8
|
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover"],
|
|
@@ -10,8 +11,8 @@ const DOMPURIFY_CONFIG = {
|
|
|
10
11
|
function generateId() {
|
|
11
12
|
return v4();
|
|
12
13
|
}
|
|
13
|
-
function renderMarkdown(content) {
|
|
14
|
-
const completedMarkdown = remend(content);
|
|
14
|
+
function renderMarkdown(content, { streaming = true } = {}) {
|
|
15
|
+
const completedMarkdown = remend(content, streaming ? void 0 : COMPLETE_CONTENT_REMEND_OPTIONS);
|
|
15
16
|
const renderer = new marked.Renderer();
|
|
16
17
|
renderer.link = function(args) {
|
|
17
18
|
const link = marked.Renderer.prototype.link.call(this, args);
|
|
@@ -263,7 +263,7 @@ messages_get = function() {
|
|
|
263
263
|
const msg = item.data;
|
|
264
264
|
const content = typeof msg.content === "string" ? msg.content : "";
|
|
265
265
|
if (msg.role === "user") {
|
|
266
|
-
const renderedHtml = __privateGet(this, _markdownController).getCachedHtml(msg.id, content);
|
|
266
|
+
const renderedHtml = __privateGet(this, _markdownController).getCachedHtml(msg.id, content, { streaming: false });
|
|
267
267
|
return html`
|
|
268
268
|
<forge-ai-user-message
|
|
269
269
|
message-id=${msg.id}
|