@cartanova/qgrid-ai-sdk 2.6.9 → 2.6.10

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.
Files changed (2) hide show
  1. package/dist/index.js +259 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,3 +1,257 @@
1
+ //#region src/envelope-stream-parser.ts
2
+ const ESCAPE_MAP = {
3
+ "\"": "\"",
4
+ "\\": "\\",
5
+ "/": "/",
6
+ b: "\b",
7
+ f: "\f",
8
+ n: "\n",
9
+ r: "\r",
10
+ t: " "
11
+ };
12
+ const LITERAL_CHARS = /[0-9a-zA-Z+\-.eE]/;
13
+ function createEnvelopeStreamParser(answerKind) {
14
+ let action = null;
15
+ let discard = false;
16
+ let pending = "";
17
+ let out = "";
18
+ const emit = (text) => {
19
+ if (discard || text === "") return;
20
+ if (action === "answer") out += text;
21
+ else pending += text;
22
+ };
23
+ const resolveAction = (value) => {
24
+ if (action !== null) return;
25
+ if (value === "answer") {
26
+ action = "answer";
27
+ out += pending;
28
+ pending = "";
29
+ } else {
30
+ action = "tool_call";
31
+ discard = true;
32
+ pending = "";
33
+ }
34
+ };
35
+ const stack = [];
36
+ let mode = "value";
37
+ let currentKey = null;
38
+ let inString = false;
39
+ let stringIsKey = false;
40
+ let escape = false;
41
+ let unicode = null;
42
+ let keyBuf = "";
43
+ let actionBuf = "";
44
+ let capture = "none";
45
+ let rawActive = false;
46
+ let rawDepth = 0;
47
+ let rawInString = false;
48
+ let rawEscape = false;
49
+ let rawIsLiteral = false;
50
+ const atEnvelopeLevel = () => stack.length === 2 && stack[0].openedAtKey === null && stack[1].openedAtKey === "result";
51
+ const deliverStringChar = (ch) => {
52
+ if (stringIsKey) keyBuf += ch;
53
+ else if (capture === "action") actionBuf += ch;
54
+ else if (capture === "answer-text") emit(ch);
55
+ };
56
+ const endString = () => {
57
+ inString = false;
58
+ if (stringIsKey) {
59
+ currentKey = keyBuf;
60
+ mode = "colon";
61
+ return;
62
+ }
63
+ if (capture === "action") resolveAction(actionBuf);
64
+ capture = "none";
65
+ mode = "afterValue";
66
+ };
67
+ const endRaw = (reprocessChar) => {
68
+ rawActive = false;
69
+ mode = "afterValue";
70
+ if (reprocessChar !== void 0) step(reprocessChar);
71
+ };
72
+ const rawStep = (c) => {
73
+ if (rawIsLiteral) {
74
+ if (LITERAL_CHARS.test(c)) return;
75
+ rawIsLiteral = false;
76
+ endRaw(c);
77
+ return;
78
+ }
79
+ emit(c);
80
+ if (rawInString) {
81
+ if (rawEscape) rawEscape = false;
82
+ else if (c === "\\") rawEscape = true;
83
+ else if (c === "\"") {
84
+ rawInString = false;
85
+ if (rawDepth === 0) endRaw();
86
+ }
87
+ return;
88
+ }
89
+ if (c === "\"") rawInString = true;
90
+ else if (c === "{" || c === "[") rawDepth++;
91
+ else if (c === "}" || c === "]") {
92
+ rawDepth--;
93
+ if (rawDepth === 0) endRaw();
94
+ }
95
+ };
96
+ const startValue = (c) => {
97
+ const watchedAction = atEnvelopeLevel() && currentKey === "action";
98
+ const watchedAnswer = atEnvelopeLevel() && currentKey === "answer";
99
+ if (watchedAnswer && answerKind === "json") {
100
+ rawActive = true;
101
+ rawDepth = 0;
102
+ rawInString = false;
103
+ rawEscape = false;
104
+ rawIsLiteral = false;
105
+ if (c === "{" || c === "[") {
106
+ rawDepth = 1;
107
+ emit(c);
108
+ } else if (c === "\"") {
109
+ rawInString = true;
110
+ emit(c);
111
+ } else rawIsLiteral = true;
112
+ return;
113
+ }
114
+ if (c === "\"") {
115
+ inString = true;
116
+ stringIsKey = false;
117
+ escape = false;
118
+ unicode = null;
119
+ if (watchedAction) {
120
+ capture = "action";
121
+ actionBuf = "";
122
+ } else if (watchedAnswer && answerKind === "text") capture = "answer-text";
123
+ else capture = "none";
124
+ return;
125
+ }
126
+ if (c === "{") {
127
+ stack.push({
128
+ type: "object",
129
+ openedAtKey: currentKey
130
+ });
131
+ currentKey = null;
132
+ mode = "key";
133
+ return;
134
+ }
135
+ if (c === "[") {
136
+ stack.push({
137
+ type: "array",
138
+ openedAtKey: currentKey
139
+ });
140
+ currentKey = null;
141
+ mode = "value";
142
+ return;
143
+ }
144
+ if (c === "]" && stack[stack.length - 1]?.type === "array") {
145
+ stack.pop();
146
+ mode = "afterValue";
147
+ return;
148
+ }
149
+ if (LITERAL_CHARS.test(c)) {
150
+ mode = "literal";
151
+ return;
152
+ }
153
+ discard = true;
154
+ };
155
+ const step = (c) => {
156
+ if (discard) return;
157
+ if (rawActive) {
158
+ rawStep(c);
159
+ return;
160
+ }
161
+ if (inString) {
162
+ if (unicode !== null) {
163
+ unicode += c;
164
+ if (unicode.length === 4) {
165
+ const code = Number.parseInt(unicode, 16);
166
+ unicode = null;
167
+ if (Number.isNaN(code)) {
168
+ discard = true;
169
+ return;
170
+ }
171
+ deliverStringChar(String.fromCharCode(code));
172
+ }
173
+ return;
174
+ }
175
+ if (escape) {
176
+ escape = false;
177
+ if (c === "u") {
178
+ unicode = "";
179
+ return;
180
+ }
181
+ const mapped = ESCAPE_MAP[c];
182
+ if (mapped === void 0) {
183
+ discard = true;
184
+ return;
185
+ }
186
+ deliverStringChar(mapped);
187
+ return;
188
+ }
189
+ if (c === "\\") {
190
+ escape = true;
191
+ return;
192
+ }
193
+ if (c === "\"") {
194
+ endString();
195
+ return;
196
+ }
197
+ deliverStringChar(c);
198
+ return;
199
+ }
200
+ if (mode === "literal") {
201
+ if (LITERAL_CHARS.test(c)) return;
202
+ mode = "afterValue";
203
+ step(c);
204
+ return;
205
+ }
206
+ if (c === " " || c === " " || c === "\n" || c === "\r") return;
207
+ switch (mode) {
208
+ case "value":
209
+ startValue(c);
210
+ return;
211
+ case "key":
212
+ if (c === "\"") {
213
+ inString = true;
214
+ stringIsKey = true;
215
+ escape = false;
216
+ unicode = null;
217
+ keyBuf = "";
218
+ } else if (c === "}") {
219
+ stack.pop();
220
+ mode = "afterValue";
221
+ } else discard = true;
222
+ return;
223
+ case "colon":
224
+ if (c === ":") {
225
+ mode = "value";
226
+ stringIsKey = false;
227
+ } else discard = true;
228
+ return;
229
+ case "afterValue":
230
+ if (c === ",") {
231
+ const frame = stack[stack.length - 1];
232
+ if (!frame) {
233
+ discard = true;
234
+ return;
235
+ }
236
+ currentKey = null;
237
+ mode = frame.type === "object" ? "key" : "value";
238
+ } else if (c === "}" || c === "]") stack.pop();
239
+ else discard = true;
240
+ return;
241
+ }
242
+ };
243
+ return { push(chunk) {
244
+ if (discard) return "";
245
+ for (const c of chunk) {
246
+ step(c);
247
+ if (discard) break;
248
+ }
249
+ const emitted = out;
250
+ out = "";
251
+ return emitted;
252
+ } };
253
+ }
254
+ //#endregion
1
255
  //#region src/qgrid.constant.ts
2
256
  const QGRID_PROVIDER_NAME = "qgrid";
3
257
  const THREAD_COORD_TTL_MS = 10 * 6e4;
@@ -941,11 +1195,14 @@ function qgrid(modelId, config) {
941
1195
  const textId = `${TEXT_STREAM_ID_PREFIX}_${Math.random().toString(36).slice(2, 10)}`;
942
1196
  let textStarted = false;
943
1197
  let deltaTextEmitted = false;
1198
+ const envelopeParser = hasTools ? createEnvelopeStreamParser(jsonSchema ? "json" : "text") : void 0;
944
1199
  return { stream: new ReadableStream({ async start(controller) {
945
1200
  try {
946
1201
  let streamCompleted = false;
947
1202
  for await (const event of parseSSE(streamRes.body)) if (event.type === "delta") {
948
- if (!hasTools) {
1203
+ const raw = event.data.text;
1204
+ const text = envelopeParser ? envelopeParser.push(raw) : raw;
1205
+ if (text !== "") {
949
1206
  if (!textStarted) {
950
1207
  controller.enqueue({
951
1208
  type: "text-start",
@@ -956,7 +1213,7 @@ function qgrid(modelId, config) {
956
1213
  controller.enqueue({
957
1214
  type: "text-delta",
958
1215
  id: textId,
959
- delta: event.data.text
1216
+ delta: text
960
1217
  });
961
1218
  deltaTextEmitted = true;
962
1219
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cartanova/qgrid-ai-sdk",
3
- "version": "2.6.9",
3
+ "version": "2.6.10",
4
4
  "description": "AI SDK LanguageModelV3 provider for qgrid",
5
5
  "repository": {
6
6
  "type": "git",