@ai-matrx/chat 0.7.4 → 0.7.6

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.
@@ -1,243 +0,0 @@
1
- import { OUR_FILE_URL_MARKERS } from "@ai-matrx/media/files/engine";
2
- const Candidate = {
3
- NONE: 0,
4
- TEXT: 0,
5
- // No special block detected — plain text
6
- CODE: 1 << 0,
7
- // ``` or ~~~ fenced code block
8
- XML_SIMPLE: 1 << 1,
9
- // <thinking>, <flashcards>, etc.
10
- XML_ATTR: 1 << 2,
11
- // <decision prompt="...">, <artifact ...>
12
- TABLE: 1 << 3,
13
- // | col | col |
14
- IMAGE: 1 << 4,
15
- // ![alt](url) or [Image URL: ...]
16
- VIDEO: 1 << 5,
17
- // [Video URL: ...]
18
- DIVIDER: 1 << 7,
19
- // *** or # ===
20
- TREE: 1 << 8,
21
- // Box-drawing / ASCII tree characters
22
- BARE_JSON: 1 << 9,
23
- // { "key": ... } JSON object without code fences
24
- AUDIO: 1 << 10,
25
- // [Audio URL: ...] or a standalone …/clip.mp3 link
26
- MATRX_FILE: 1 << 11
27
- // link/URL to one of OUR files (signed S3 / CDN / public / share)
28
- };
29
- const AUDIO_EXT_RE = /\.(mp3|wav|m4a|aac|ogg|oga|opus|flac|weba|webm)(\?[^\s)]*)?$/i;
30
- function isStandaloneAudioLink(trimmed) {
31
- const link = trimmed.match(/^!?\[.*?\]\((https?:\/\/[^\s)]+)\)$/);
32
- if (link) return AUDIO_EXT_RE.test(link[1]);
33
- if (/^https?:\/\/[^\s)]+$/.test(trimmed)) return AUDIO_EXT_RE.test(trimmed);
34
- return false;
35
- }
36
- function mightBeOurFile(trimmed) {
37
- const markers = OUR_FILE_URL_MARKERS;
38
- for (let mi = 0; mi < markers.length; mi++) {
39
- if (trimmed.includes(markers[mi])) return true;
40
- }
41
- return false;
42
- }
43
- const SIMPLE_XML_TAGS = /* @__PURE__ */ new Set([
44
- "thinking",
45
- "think",
46
- "reasoning",
47
- "info",
48
- "task",
49
- "database",
50
- "private",
51
- "plan",
52
- "event",
53
- "tool",
54
- "questionnaire",
55
- "flashcards",
56
- "cooking_recipe",
57
- "timeline",
58
- "progress_tracker",
59
- "troubleshooting",
60
- "resources",
61
- "research"
62
- ]);
63
- const ATTR_XML_TAGS = /* @__PURE__ */ new Set([
64
- "decision",
65
- "artifact",
66
- // Editor pill tags — carry attributes (file, line, severity, language, …)
67
- // so they're classified as ATTR. The chat-markdown renderer parses them
68
- // back into chips on load.
69
- "editor_error",
70
- "editor_code_snippet"
71
- ]);
72
- const ALL_XML_TAGS = /* @__PURE__ */ new Set([...SIMPLE_XML_TAGS, ...ATTR_XML_TAGS]);
73
- const TREE_CHARS = /* @__PURE__ */ new Set([
74
- "\u251C",
75
- "\u2514",
76
- "\u2502",
77
- "\u250C",
78
- "\u2510",
79
- "\u2518",
80
- "\u252C",
81
- "\u2534",
82
- "\u2524",
83
- "\u253C",
84
- "\u2500"
85
- ]);
86
- function classifyLine(line, trimmed) {
87
- let flags = Candidate.NONE;
88
- const len = trimmed.length;
89
- if (len === 0) return flags;
90
- const first = trimmed[0];
91
- if (first === "`" || first === "~") {
92
- if (len >= 3 && trimmed[1] === first && trimmed[2] === first) {
93
- flags |= Candidate.CODE;
94
- }
95
- }
96
- if (first === "{") {
97
- flags |= Candidate.BARE_JSON;
98
- }
99
- if (first === "|") {
100
- if (trimmed.indexOf("|", 1) !== -1) {
101
- flags |= Candidate.TABLE;
102
- }
103
- }
104
- if (first === "!" && len >= 2 && trimmed[1] === "[") {
105
- flags |= Candidate.IMAGE;
106
- }
107
- if (first === "*" || first === "#") {
108
- if (first === "*") {
109
- if (isStarDivider(trimmed)) {
110
- flags |= Candidate.DIVIDER;
111
- }
112
- } else {
113
- if (len >= 4 && trimmed.indexOf("=") !== -1) {
114
- flags |= Candidate.DIVIDER;
115
- }
116
- }
117
- }
118
- if (TREE_CHARS.has(first)) {
119
- flags |= Candidate.TREE;
120
- }
121
- let searchFrom = 0;
122
- while (searchFrom < len) {
123
- const ltPos = trimmed.indexOf("<", searchFrom);
124
- if (ltPos === -1) break;
125
- if (ltPos + 2 < len && trimmed[ltPos + 1] === "<" && trimmed[ltPos + 2] === "<") {
126
- searchFrom = ltPos + 3;
127
- continue;
128
- }
129
- if (ltPos + 1 < len) {
130
- const next = trimmed[ltPos + 1];
131
- if (isLetter(next)) {
132
- const tagName = extractTagName(trimmed, ltPos + 1);
133
- if (tagName) {
134
- if (SIMPLE_XML_TAGS.has(tagName)) {
135
- flags |= Candidate.XML_SIMPLE;
136
- }
137
- if (ATTR_XML_TAGS.has(tagName)) {
138
- flags |= Candidate.XML_ATTR;
139
- }
140
- }
141
- }
142
- }
143
- searchFrom = ltPos + 1;
144
- }
145
- if (!(flags & Candidate.IMAGE) || !(flags & Candidate.VIDEO) || !(flags & Candidate.AUDIO)) {
146
- const bracketIdx = trimmed.indexOf("[");
147
- if (bracketIdx !== -1) {
148
- if (bracketIdx + 10 < len) {
149
- const after = trimmed[bracketIdx + 1];
150
- if (after === "I" && trimmed.substring(bracketIdx + 1, bracketIdx + 11) === "Image URL:") {
151
- flags |= Candidate.IMAGE;
152
- } else if (after === "V" && trimmed.substring(bracketIdx + 1, bracketIdx + 11) === "Video URL:") {
153
- flags |= Candidate.VIDEO;
154
- } else if (after === "A" && trimmed.substring(bracketIdx + 1, bracketIdx + 11) === "Audio URL:") {
155
- flags |= Candidate.AUDIO;
156
- }
157
- }
158
- }
159
- }
160
- if (!(flags & Candidate.AUDIO) && (first === "[" || first === "!" || first === "h") && isStandaloneAudioLink(trimmed)) {
161
- flags |= Candidate.AUDIO;
162
- }
163
- if (!(flags & Candidate.TABLE) && first !== "|") {
164
- if (trimmed.indexOf("|") !== -1) {
165
- const firstPipe = trimmed.indexOf("|");
166
- if (firstPipe !== -1 && trimmed.indexOf("|", firstPipe + 1) !== -1) {
167
- flags |= Candidate.TABLE;
168
- }
169
- }
170
- }
171
- if (!(flags & Candidate.TREE)) {
172
- for (let ci = 1; ci < len; ci++) {
173
- if (TREE_CHARS.has(trimmed[ci])) {
174
- flags |= Candidate.TREE;
175
- break;
176
- }
177
- }
178
- }
179
- if (!(flags & Candidate.TREE) && (first === " " || first === " " || first === "\u2502" || first === "|" || first === "+")) {
180
- if (looksLikeAsciiTree(trimmed)) {
181
- flags |= Candidate.TREE;
182
- }
183
- }
184
- if (!(flags & Candidate.MATRX_FILE) && mightBeOurFile(trimmed)) {
185
- flags |= Candidate.MATRX_FILE;
186
- }
187
- return flags;
188
- }
189
- function isLetter(ch) {
190
- const c = ch.charCodeAt(0);
191
- return c >= 65 && c <= 90 || c >= 97 && c <= 122;
192
- }
193
- function extractTagName(str, start) {
194
- let end = start;
195
- while (end < str.length) {
196
- const c = str.charCodeAt(end);
197
- if (c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95) {
198
- end++;
199
- } else {
200
- break;
201
- }
202
- }
203
- if (end === start) return null;
204
- return str.substring(start, end).toLowerCase();
205
- }
206
- function isStarDivider(trimmed) {
207
- let starCount = 0;
208
- for (let i = 0; i < trimmed.length; i++) {
209
- const ch = trimmed[i];
210
- if (ch === "*") {
211
- starCount++;
212
- } else if (ch !== " ") {
213
- return false;
214
- }
215
- }
216
- return starCount >= 3;
217
- }
218
- function looksLikeAsciiTree(trimmed) {
219
- let i = 0;
220
- while (i < trimmed.length) {
221
- const ch2 = trimmed[i];
222
- if (ch2 === " " || ch2 === " " || ch2 === "\u2502" || ch2 === "|") {
223
- i++;
224
- } else {
225
- break;
226
- }
227
- }
228
- if (i >= trimmed.length) return false;
229
- const ch = trimmed[i];
230
- return ch === "\u251C" || ch === "\u2514" || ch === "+";
231
- }
232
- function isPlainText(flags) {
233
- return flags === Candidate.NONE;
234
- }
235
- function hasCandidate(flags, candidate) {
236
- return (flags & candidate) !== 0;
237
- }
238
- export {
239
- Candidate,
240
- classifyLine,
241
- hasCandidate,
242
- isPlainText
243
- };