modelfusion 0.35.0 → 0.35.2
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/model-function/generate-structure/fixJson.cjs +176 -57
- package/model-function/generate-structure/fixJson.js +176 -57
- package/model-function/generate-structure/fixJson.test.cjs +59 -3
- package/model-function/generate-structure/fixJson.test.js +59 -3
- package/model-function/generate-structure/streamStructure.d.ts +1 -2
- package/model-provider/openai/OpenAITextGenerationModel.cjs +4 -0
- package/model-provider/openai/OpenAITextGenerationModel.js +4 -0
- package/model-provider/openai/chat/OpenAIChatModel.cjs +4 -0
- package/model-provider/openai/chat/OpenAIChatModel.js +4 -0
- package/package.json +1 -1
@@ -2,71 +2,130 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.fixJson = void 0;
|
4
4
|
// Implemented as a scanner with additional fixing
|
5
|
-
// that performs a single linear time scan pass over the partial JSON
|
5
|
+
// that performs a single linear time scan pass over the partial JSON.
|
6
|
+
//
|
7
|
+
// The states should ideally match relevant states from the JSON spec:
|
8
|
+
// https://www.json.org/json-en.html
|
9
|
+
//
|
10
|
+
// Please note that invalid JSON is not considered/covered, because it
|
11
|
+
// is assumed that the resulting JSON will be processed by a standard
|
12
|
+
// JSON parser that will detect any invalid JSON.
|
6
13
|
function fixJson(input) {
|
7
|
-
const stack = ["
|
14
|
+
const stack = ["ROOT"];
|
8
15
|
let lastValidIndex = -1;
|
9
16
|
let literalStart = null;
|
17
|
+
function processValueStart(char, i, swapState) {
|
18
|
+
{
|
19
|
+
switch (char) {
|
20
|
+
case '"': {
|
21
|
+
lastValidIndex = i;
|
22
|
+
stack.pop();
|
23
|
+
stack.push(swapState);
|
24
|
+
stack.push("INSIDE_STRING");
|
25
|
+
break;
|
26
|
+
}
|
27
|
+
case "f":
|
28
|
+
case "t":
|
29
|
+
case "n": {
|
30
|
+
lastValidIndex = i;
|
31
|
+
literalStart = i;
|
32
|
+
stack.pop();
|
33
|
+
stack.push(swapState);
|
34
|
+
stack.push("INSIDE_LITERAL");
|
35
|
+
break;
|
36
|
+
}
|
37
|
+
case "-": {
|
38
|
+
stack.pop();
|
39
|
+
stack.push(swapState);
|
40
|
+
stack.push("INSIDE_NUMBER");
|
41
|
+
break;
|
42
|
+
}
|
43
|
+
case "0":
|
44
|
+
case "1":
|
45
|
+
case "2":
|
46
|
+
case "3":
|
47
|
+
case "4":
|
48
|
+
case "5":
|
49
|
+
case "6":
|
50
|
+
case "7":
|
51
|
+
case "8":
|
52
|
+
case "9": {
|
53
|
+
lastValidIndex = i;
|
54
|
+
stack.pop();
|
55
|
+
stack.push(swapState);
|
56
|
+
stack.push("INSIDE_NUMBER");
|
57
|
+
break;
|
58
|
+
}
|
59
|
+
case "{": {
|
60
|
+
lastValidIndex = i;
|
61
|
+
stack.pop();
|
62
|
+
stack.push(swapState);
|
63
|
+
stack.push("INSIDE_OBJECT_START");
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
case "[": {
|
67
|
+
lastValidIndex = i;
|
68
|
+
stack.pop();
|
69
|
+
stack.push(swapState);
|
70
|
+
stack.push("INSIDE_ARRAY_START");
|
71
|
+
break;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
function processAfterObjectValue(char, i) {
|
77
|
+
switch (char) {
|
78
|
+
case ",": {
|
79
|
+
stack.pop();
|
80
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
81
|
+
break;
|
82
|
+
}
|
83
|
+
case "}": {
|
84
|
+
lastValidIndex = i;
|
85
|
+
stack.pop();
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
}
|
90
|
+
function processAfterArrayValue(char, i) {
|
91
|
+
switch (char) {
|
92
|
+
case ",": {
|
93
|
+
stack.pop();
|
94
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
95
|
+
break;
|
96
|
+
}
|
97
|
+
case "]": {
|
98
|
+
lastValidIndex = i;
|
99
|
+
stack.pop();
|
100
|
+
break;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
10
104
|
for (let i = 0; i < input.length; i++) {
|
11
105
|
const char = input[i];
|
12
106
|
const currentState = stack[stack.length - 1];
|
13
107
|
switch (currentState) {
|
14
|
-
case "
|
108
|
+
case "ROOT":
|
109
|
+
processValueStart(char, i, "FINISH");
|
110
|
+
break;
|
111
|
+
case "INSIDE_OBJECT_START": {
|
15
112
|
switch (char) {
|
16
113
|
case '"': {
|
17
|
-
lastValidIndex = i;
|
18
|
-
stack.pop();
|
19
|
-
stack.push("INSIDE_STRING");
|
20
|
-
break;
|
21
|
-
}
|
22
|
-
case "f":
|
23
|
-
case "t":
|
24
|
-
case "n": {
|
25
|
-
lastValidIndex = i;
|
26
|
-
literalStart = i;
|
27
|
-
stack.pop();
|
28
|
-
stack.push("INSIDE_LITERAL");
|
29
|
-
break;
|
30
|
-
}
|
31
|
-
case "-": {
|
32
114
|
stack.pop();
|
33
|
-
stack.push("
|
34
|
-
break;
|
35
|
-
}
|
36
|
-
case "0":
|
37
|
-
case "1":
|
38
|
-
case "2":
|
39
|
-
case "3":
|
40
|
-
case "4":
|
41
|
-
case "5":
|
42
|
-
case "6":
|
43
|
-
case "7":
|
44
|
-
case "8":
|
45
|
-
case "9": {
|
46
|
-
lastValidIndex = i;
|
47
|
-
stack.pop();
|
48
|
-
stack.push("INSIDE_NUMBER");
|
49
|
-
break;
|
50
|
-
}
|
51
|
-
case "{": {
|
52
|
-
lastValidIndex = i;
|
53
|
-
stack.pop();
|
54
|
-
stack.push("INSIDE_OBJECT");
|
115
|
+
stack.push("INSIDE_OBJECT_KEY");
|
55
116
|
break;
|
56
117
|
}
|
57
|
-
case "
|
58
|
-
lastValidIndex = i;
|
118
|
+
case "}": {
|
59
119
|
stack.pop();
|
60
|
-
stack.push("INSIDE_ARRAY");
|
61
|
-
stack.push("BEFORE_VALUE");
|
62
120
|
break;
|
63
121
|
}
|
64
122
|
}
|
65
123
|
break;
|
66
124
|
}
|
67
|
-
case "
|
125
|
+
case "INSIDE_OBJECT_AFTER_COMMA": {
|
68
126
|
switch (char) {
|
69
127
|
case '"': {
|
128
|
+
stack.pop();
|
70
129
|
stack.push("INSIDE_OBJECT_KEY");
|
71
130
|
break;
|
72
131
|
}
|
@@ -77,22 +136,30 @@ function fixJson(input) {
|
|
77
136
|
switch (char) {
|
78
137
|
case '"': {
|
79
138
|
stack.pop();
|
80
|
-
stack.push("
|
139
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
81
140
|
break;
|
82
141
|
}
|
83
142
|
}
|
84
143
|
break;
|
85
144
|
}
|
86
|
-
case "
|
145
|
+
case "INSIDE_OBJECT_AFTER_KEY": {
|
87
146
|
switch (char) {
|
88
147
|
case ":": {
|
89
148
|
stack.pop();
|
90
|
-
stack.push("
|
149
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
91
150
|
break;
|
92
151
|
}
|
93
152
|
}
|
94
153
|
break;
|
95
154
|
}
|
155
|
+
case "INSIDE_OBJECT_BEFORE_VALUE": {
|
156
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
157
|
+
break;
|
158
|
+
}
|
159
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
160
|
+
processAfterObjectValue(char, i);
|
161
|
+
break;
|
162
|
+
}
|
96
163
|
case "INSIDE_STRING": {
|
97
164
|
switch (char) {
|
98
165
|
case '"': {
|
@@ -110,10 +177,31 @@ function fixJson(input) {
|
|
110
177
|
}
|
111
178
|
break;
|
112
179
|
}
|
113
|
-
case "
|
180
|
+
case "INSIDE_ARRAY_START": {
|
181
|
+
switch (char) {
|
182
|
+
case "]": {
|
183
|
+
lastValidIndex = i;
|
184
|
+
stack.pop();
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
default: {
|
188
|
+
lastValidIndex = i;
|
189
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
break;
|
194
|
+
}
|
195
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
114
196
|
switch (char) {
|
115
197
|
case ",": {
|
116
|
-
stack.
|
198
|
+
stack.pop();
|
199
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
200
|
+
break;
|
201
|
+
}
|
202
|
+
case "]": {
|
203
|
+
lastValidIndex = i;
|
204
|
+
stack.pop();
|
117
205
|
break;
|
118
206
|
}
|
119
207
|
default: {
|
@@ -123,6 +211,10 @@ function fixJson(input) {
|
|
123
211
|
}
|
124
212
|
break;
|
125
213
|
}
|
214
|
+
case "INSIDE_ARRAY_AFTER_COMMA": {
|
215
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
216
|
+
break;
|
217
|
+
}
|
126
218
|
case "INSIDE_STRING_ESCAPE": {
|
127
219
|
stack.pop();
|
128
220
|
lastValidIndex = i;
|
@@ -151,8 +243,25 @@ function fixJson(input) {
|
|
151
243
|
}
|
152
244
|
case ",": {
|
153
245
|
stack.pop();
|
154
|
-
if (stack[stack.length - 1] === "
|
155
|
-
|
246
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
247
|
+
processAfterArrayValue(char, i);
|
248
|
+
}
|
249
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
250
|
+
processAfterObjectValue(char, i);
|
251
|
+
}
|
252
|
+
break;
|
253
|
+
}
|
254
|
+
case "}": {
|
255
|
+
stack.pop();
|
256
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
257
|
+
processAfterObjectValue(char, i);
|
258
|
+
}
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
case "]": {
|
262
|
+
stack.pop();
|
263
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
264
|
+
processAfterArrayValue(char, i);
|
156
265
|
}
|
157
266
|
break;
|
158
267
|
}
|
@@ -164,13 +273,16 @@ function fixJson(input) {
|
|
164
273
|
break;
|
165
274
|
}
|
166
275
|
case "INSIDE_LITERAL": {
|
167
|
-
const partialLiteral = input.substring(literalStart, i);
|
276
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
168
277
|
if (!"false".startsWith(partialLiteral) &&
|
169
278
|
!"true".startsWith(partialLiteral) &&
|
170
279
|
!"null".startsWith(partialLiteral)) {
|
171
280
|
stack.pop();
|
172
|
-
if (stack[stack.length - 1] === "
|
173
|
-
|
281
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
282
|
+
processAfterObjectValue(char, i);
|
283
|
+
}
|
284
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
285
|
+
processAfterArrayValue(char, i);
|
174
286
|
}
|
175
287
|
}
|
176
288
|
else {
|
@@ -188,11 +300,18 @@ function fixJson(input) {
|
|
188
300
|
result += '"';
|
189
301
|
break;
|
190
302
|
}
|
191
|
-
case "
|
303
|
+
case "INSIDE_OBJECT_KEY":
|
304
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
305
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
306
|
+
case "INSIDE_OBJECT_START":
|
307
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
308
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
192
309
|
result += "}";
|
193
310
|
break;
|
194
311
|
}
|
195
|
-
case "
|
312
|
+
case "INSIDE_ARRAY_START":
|
313
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
314
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
196
315
|
result += "]";
|
197
316
|
break;
|
198
317
|
}
|
@@ -1,69 +1,128 @@
|
|
1
1
|
// Implemented as a scanner with additional fixing
|
2
|
-
// that performs a single linear time scan pass over the partial JSON
|
2
|
+
// that performs a single linear time scan pass over the partial JSON.
|
3
|
+
//
|
4
|
+
// The states should ideally match relevant states from the JSON spec:
|
5
|
+
// https://www.json.org/json-en.html
|
6
|
+
//
|
7
|
+
// Please note that invalid JSON is not considered/covered, because it
|
8
|
+
// is assumed that the resulting JSON will be processed by a standard
|
9
|
+
// JSON parser that will detect any invalid JSON.
|
3
10
|
export function fixJson(input) {
|
4
|
-
const stack = ["
|
11
|
+
const stack = ["ROOT"];
|
5
12
|
let lastValidIndex = -1;
|
6
13
|
let literalStart = null;
|
14
|
+
function processValueStart(char, i, swapState) {
|
15
|
+
{
|
16
|
+
switch (char) {
|
17
|
+
case '"': {
|
18
|
+
lastValidIndex = i;
|
19
|
+
stack.pop();
|
20
|
+
stack.push(swapState);
|
21
|
+
stack.push("INSIDE_STRING");
|
22
|
+
break;
|
23
|
+
}
|
24
|
+
case "f":
|
25
|
+
case "t":
|
26
|
+
case "n": {
|
27
|
+
lastValidIndex = i;
|
28
|
+
literalStart = i;
|
29
|
+
stack.pop();
|
30
|
+
stack.push(swapState);
|
31
|
+
stack.push("INSIDE_LITERAL");
|
32
|
+
break;
|
33
|
+
}
|
34
|
+
case "-": {
|
35
|
+
stack.pop();
|
36
|
+
stack.push(swapState);
|
37
|
+
stack.push("INSIDE_NUMBER");
|
38
|
+
break;
|
39
|
+
}
|
40
|
+
case "0":
|
41
|
+
case "1":
|
42
|
+
case "2":
|
43
|
+
case "3":
|
44
|
+
case "4":
|
45
|
+
case "5":
|
46
|
+
case "6":
|
47
|
+
case "7":
|
48
|
+
case "8":
|
49
|
+
case "9": {
|
50
|
+
lastValidIndex = i;
|
51
|
+
stack.pop();
|
52
|
+
stack.push(swapState);
|
53
|
+
stack.push("INSIDE_NUMBER");
|
54
|
+
break;
|
55
|
+
}
|
56
|
+
case "{": {
|
57
|
+
lastValidIndex = i;
|
58
|
+
stack.pop();
|
59
|
+
stack.push(swapState);
|
60
|
+
stack.push("INSIDE_OBJECT_START");
|
61
|
+
break;
|
62
|
+
}
|
63
|
+
case "[": {
|
64
|
+
lastValidIndex = i;
|
65
|
+
stack.pop();
|
66
|
+
stack.push(swapState);
|
67
|
+
stack.push("INSIDE_ARRAY_START");
|
68
|
+
break;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
function processAfterObjectValue(char, i) {
|
74
|
+
switch (char) {
|
75
|
+
case ",": {
|
76
|
+
stack.pop();
|
77
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
case "}": {
|
81
|
+
lastValidIndex = i;
|
82
|
+
stack.pop();
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
function processAfterArrayValue(char, i) {
|
88
|
+
switch (char) {
|
89
|
+
case ",": {
|
90
|
+
stack.pop();
|
91
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
92
|
+
break;
|
93
|
+
}
|
94
|
+
case "]": {
|
95
|
+
lastValidIndex = i;
|
96
|
+
stack.pop();
|
97
|
+
break;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
7
101
|
for (let i = 0; i < input.length; i++) {
|
8
102
|
const char = input[i];
|
9
103
|
const currentState = stack[stack.length - 1];
|
10
104
|
switch (currentState) {
|
11
|
-
case "
|
105
|
+
case "ROOT":
|
106
|
+
processValueStart(char, i, "FINISH");
|
107
|
+
break;
|
108
|
+
case "INSIDE_OBJECT_START": {
|
12
109
|
switch (char) {
|
13
110
|
case '"': {
|
14
|
-
lastValidIndex = i;
|
15
|
-
stack.pop();
|
16
|
-
stack.push("INSIDE_STRING");
|
17
|
-
break;
|
18
|
-
}
|
19
|
-
case "f":
|
20
|
-
case "t":
|
21
|
-
case "n": {
|
22
|
-
lastValidIndex = i;
|
23
|
-
literalStart = i;
|
24
|
-
stack.pop();
|
25
|
-
stack.push("INSIDE_LITERAL");
|
26
|
-
break;
|
27
|
-
}
|
28
|
-
case "-": {
|
29
111
|
stack.pop();
|
30
|
-
stack.push("
|
31
|
-
break;
|
32
|
-
}
|
33
|
-
case "0":
|
34
|
-
case "1":
|
35
|
-
case "2":
|
36
|
-
case "3":
|
37
|
-
case "4":
|
38
|
-
case "5":
|
39
|
-
case "6":
|
40
|
-
case "7":
|
41
|
-
case "8":
|
42
|
-
case "9": {
|
43
|
-
lastValidIndex = i;
|
44
|
-
stack.pop();
|
45
|
-
stack.push("INSIDE_NUMBER");
|
46
|
-
break;
|
47
|
-
}
|
48
|
-
case "{": {
|
49
|
-
lastValidIndex = i;
|
50
|
-
stack.pop();
|
51
|
-
stack.push("INSIDE_OBJECT");
|
112
|
+
stack.push("INSIDE_OBJECT_KEY");
|
52
113
|
break;
|
53
114
|
}
|
54
|
-
case "
|
55
|
-
lastValidIndex = i;
|
115
|
+
case "}": {
|
56
116
|
stack.pop();
|
57
|
-
stack.push("INSIDE_ARRAY");
|
58
|
-
stack.push("BEFORE_VALUE");
|
59
117
|
break;
|
60
118
|
}
|
61
119
|
}
|
62
120
|
break;
|
63
121
|
}
|
64
|
-
case "
|
122
|
+
case "INSIDE_OBJECT_AFTER_COMMA": {
|
65
123
|
switch (char) {
|
66
124
|
case '"': {
|
125
|
+
stack.pop();
|
67
126
|
stack.push("INSIDE_OBJECT_KEY");
|
68
127
|
break;
|
69
128
|
}
|
@@ -74,22 +133,30 @@ export function fixJson(input) {
|
|
74
133
|
switch (char) {
|
75
134
|
case '"': {
|
76
135
|
stack.pop();
|
77
|
-
stack.push("
|
136
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
78
137
|
break;
|
79
138
|
}
|
80
139
|
}
|
81
140
|
break;
|
82
141
|
}
|
83
|
-
case "
|
142
|
+
case "INSIDE_OBJECT_AFTER_KEY": {
|
84
143
|
switch (char) {
|
85
144
|
case ":": {
|
86
145
|
stack.pop();
|
87
|
-
stack.push("
|
146
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
88
147
|
break;
|
89
148
|
}
|
90
149
|
}
|
91
150
|
break;
|
92
151
|
}
|
152
|
+
case "INSIDE_OBJECT_BEFORE_VALUE": {
|
153
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
154
|
+
break;
|
155
|
+
}
|
156
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
157
|
+
processAfterObjectValue(char, i);
|
158
|
+
break;
|
159
|
+
}
|
93
160
|
case "INSIDE_STRING": {
|
94
161
|
switch (char) {
|
95
162
|
case '"': {
|
@@ -107,10 +174,31 @@ export function fixJson(input) {
|
|
107
174
|
}
|
108
175
|
break;
|
109
176
|
}
|
110
|
-
case "
|
177
|
+
case "INSIDE_ARRAY_START": {
|
178
|
+
switch (char) {
|
179
|
+
case "]": {
|
180
|
+
lastValidIndex = i;
|
181
|
+
stack.pop();
|
182
|
+
break;
|
183
|
+
}
|
184
|
+
default: {
|
185
|
+
lastValidIndex = i;
|
186
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
187
|
+
break;
|
188
|
+
}
|
189
|
+
}
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
111
193
|
switch (char) {
|
112
194
|
case ",": {
|
113
|
-
stack.
|
195
|
+
stack.pop();
|
196
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
197
|
+
break;
|
198
|
+
}
|
199
|
+
case "]": {
|
200
|
+
lastValidIndex = i;
|
201
|
+
stack.pop();
|
114
202
|
break;
|
115
203
|
}
|
116
204
|
default: {
|
@@ -120,6 +208,10 @@ export function fixJson(input) {
|
|
120
208
|
}
|
121
209
|
break;
|
122
210
|
}
|
211
|
+
case "INSIDE_ARRAY_AFTER_COMMA": {
|
212
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
213
|
+
break;
|
214
|
+
}
|
123
215
|
case "INSIDE_STRING_ESCAPE": {
|
124
216
|
stack.pop();
|
125
217
|
lastValidIndex = i;
|
@@ -148,8 +240,25 @@ export function fixJson(input) {
|
|
148
240
|
}
|
149
241
|
case ",": {
|
150
242
|
stack.pop();
|
151
|
-
if (stack[stack.length - 1] === "
|
152
|
-
|
243
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
244
|
+
processAfterArrayValue(char, i);
|
245
|
+
}
|
246
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
247
|
+
processAfterObjectValue(char, i);
|
248
|
+
}
|
249
|
+
break;
|
250
|
+
}
|
251
|
+
case "}": {
|
252
|
+
stack.pop();
|
253
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
254
|
+
processAfterObjectValue(char, i);
|
255
|
+
}
|
256
|
+
break;
|
257
|
+
}
|
258
|
+
case "]": {
|
259
|
+
stack.pop();
|
260
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
261
|
+
processAfterArrayValue(char, i);
|
153
262
|
}
|
154
263
|
break;
|
155
264
|
}
|
@@ -161,13 +270,16 @@ export function fixJson(input) {
|
|
161
270
|
break;
|
162
271
|
}
|
163
272
|
case "INSIDE_LITERAL": {
|
164
|
-
const partialLiteral = input.substring(literalStart, i);
|
273
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
165
274
|
if (!"false".startsWith(partialLiteral) &&
|
166
275
|
!"true".startsWith(partialLiteral) &&
|
167
276
|
!"null".startsWith(partialLiteral)) {
|
168
277
|
stack.pop();
|
169
|
-
if (stack[stack.length - 1] === "
|
170
|
-
|
278
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") {
|
279
|
+
processAfterObjectValue(char, i);
|
280
|
+
}
|
281
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") {
|
282
|
+
processAfterArrayValue(char, i);
|
171
283
|
}
|
172
284
|
}
|
173
285
|
else {
|
@@ -185,11 +297,18 @@ export function fixJson(input) {
|
|
185
297
|
result += '"';
|
186
298
|
break;
|
187
299
|
}
|
188
|
-
case "
|
300
|
+
case "INSIDE_OBJECT_KEY":
|
301
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
302
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
303
|
+
case "INSIDE_OBJECT_START":
|
304
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
305
|
+
case "INSIDE_OBJECT_AFTER_VALUE": {
|
189
306
|
result += "}";
|
190
307
|
break;
|
191
308
|
}
|
192
|
-
case "
|
309
|
+
case "INSIDE_ARRAY_START":
|
310
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
311
|
+
case "INSIDE_ARRAY_AFTER_VALUE": {
|
193
312
|
result += "]";
|
194
313
|
break;
|
195
314
|
}
|
@@ -66,19 +66,46 @@ const fixJson_1 = require("./fixJson");
|
|
66
66
|
(0, vitest_1.test)("should handle incomplete array", () => {
|
67
67
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[")).toBe("[]");
|
68
68
|
});
|
69
|
+
(0, vitest_1.test)("should handle closing bracket after number in array", () => {
|
70
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[1], [2")).toBe("[[1], [2]]");
|
71
|
+
});
|
72
|
+
(0, vitest_1.test)("should handle closing bracket after string in array", () => {
|
73
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)(`[["1"], ["2`)).toBe(`[["1"], ["2"]]`);
|
74
|
+
});
|
75
|
+
(0, vitest_1.test)("should handle closing bracket after literal in array", () => {
|
76
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[false], [nu")).toBe("[[false], [null]]");
|
77
|
+
});
|
78
|
+
(0, vitest_1.test)("should handle closing bracket after array in array", () => {
|
79
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[[]], [[]")).toBe("[[[]], [[]]]");
|
80
|
+
});
|
81
|
+
(0, vitest_1.test)("should handle closing bracket after object in array", () => {
|
82
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[{}], [{")).toBe("[[{}], [{}]]");
|
83
|
+
});
|
69
84
|
(0, vitest_1.test)("should handle trailing comma", () => {
|
70
85
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[1, ")).toBe("[1]");
|
71
86
|
});
|
72
87
|
(0, vitest_1.test)("should handle closing array", () => {
|
73
|
-
(0, vitest_1.expect)((0, fixJson_1.fixJson)(
|
88
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)("[[], 123")).toBe("[[], 123]");
|
74
89
|
});
|
75
90
|
});
|
76
91
|
(0, vitest_1.describe)("object", () => {
|
77
92
|
(0, vitest_1.test)("should handle keys without values", () => {
|
78
93
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"key":')).toBe("{}");
|
79
94
|
});
|
80
|
-
(0, vitest_1.test)("should handle closing brace in object", () => {
|
81
|
-
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": 1}')).toBe('{"a": {"b": 1}}');
|
95
|
+
(0, vitest_1.test)("should handle closing brace after number in object", () => {
|
96
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": 1}, "c": {"d": 2')).toBe('{"a": {"b": 1}, "c": {"d": 2}}');
|
97
|
+
});
|
98
|
+
(0, vitest_1.test)("should handle closing brace after string in object", () => {
|
99
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": "1"}, "c": {"d": 2')).toBe('{"a": {"b": "1"}, "c": {"d": 2}}');
|
100
|
+
});
|
101
|
+
(0, vitest_1.test)("should handle closing brace after literal in object", () => {
|
102
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": false}, "c": {"d": 2')).toBe('{"a": {"b": false}, "c": {"d": 2}}');
|
103
|
+
});
|
104
|
+
(0, vitest_1.test)("should handle closing brace after array in object", () => {
|
105
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": []}, "c": {"d": 2')).toBe('{"a": {"b": []}, "c": {"d": 2}}');
|
106
|
+
});
|
107
|
+
(0, vitest_1.test)("should handle closing brace after object in object", () => {
|
108
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": {"b": {}}, "c": {"d": 2')).toBe('{"a": {"b": {}}, "c": {"d": 2}}');
|
82
109
|
});
|
83
110
|
(0, vitest_1.test)("should handle partial keys (first key)", () => {
|
84
111
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"ke')).toBe("{}");
|
@@ -127,4 +154,33 @@ const fixJson_1 = require("./fixJson");
|
|
127
154
|
(0, vitest_1.expect)((0, fixJson_1.fixJson)('{"a": 1, "b": "')).toBe('{"a": 1, "b": ""}');
|
128
155
|
});
|
129
156
|
});
|
157
|
+
(0, vitest_1.describe)("regression", () => {
|
158
|
+
(0, vitest_1.test)("should handle complex nesting 1", () => {
|
159
|
+
(0, vitest_1.expect)((0, fixJson_1.fixJson)([
|
160
|
+
"{",
|
161
|
+
' "a": [',
|
162
|
+
" {",
|
163
|
+
' "a1": "v1",',
|
164
|
+
' "a2": "v2",',
|
165
|
+
` "a3": "v3"`,
|
166
|
+
" }",
|
167
|
+
" ],",
|
168
|
+
' "b": [',
|
169
|
+
" {",
|
170
|
+
' "b1": "n',
|
171
|
+
].join("\n"))).toBe([
|
172
|
+
"{",
|
173
|
+
' "a": [',
|
174
|
+
" {",
|
175
|
+
' "a1": "v1",',
|
176
|
+
' "a2": "v2",',
|
177
|
+
` "a3": "v3"`,
|
178
|
+
" }",
|
179
|
+
" ],",
|
180
|
+
' "b": [',
|
181
|
+
" {",
|
182
|
+
' "b1": "n"}]}',
|
183
|
+
].join("\n"));
|
184
|
+
});
|
185
|
+
});
|
130
186
|
});
|
@@ -64,19 +64,46 @@ describe("fixJson", () => {
|
|
64
64
|
test("should handle incomplete array", () => {
|
65
65
|
expect(fixJson("[")).toBe("[]");
|
66
66
|
});
|
67
|
+
test("should handle closing bracket after number in array", () => {
|
68
|
+
expect(fixJson("[[1], [2")).toBe("[[1], [2]]");
|
69
|
+
});
|
70
|
+
test("should handle closing bracket after string in array", () => {
|
71
|
+
expect(fixJson(`[["1"], ["2`)).toBe(`[["1"], ["2"]]`);
|
72
|
+
});
|
73
|
+
test("should handle closing bracket after literal in array", () => {
|
74
|
+
expect(fixJson("[[false], [nu")).toBe("[[false], [null]]");
|
75
|
+
});
|
76
|
+
test("should handle closing bracket after array in array", () => {
|
77
|
+
expect(fixJson("[[[]], [[]")).toBe("[[[]], [[]]]");
|
78
|
+
});
|
79
|
+
test("should handle closing bracket after object in array", () => {
|
80
|
+
expect(fixJson("[[{}], [{")).toBe("[[{}], [{}]]");
|
81
|
+
});
|
67
82
|
test("should handle trailing comma", () => {
|
68
83
|
expect(fixJson("[1, ")).toBe("[1]");
|
69
84
|
});
|
70
85
|
test("should handle closing array", () => {
|
71
|
-
expect(fixJson(
|
86
|
+
expect(fixJson("[[], 123")).toBe("[[], 123]");
|
72
87
|
});
|
73
88
|
});
|
74
89
|
describe("object", () => {
|
75
90
|
test("should handle keys without values", () => {
|
76
91
|
expect(fixJson('{"key":')).toBe("{}");
|
77
92
|
});
|
78
|
-
test("should handle closing brace in object", () => {
|
79
|
-
expect(fixJson('{"a": {"b": 1}')).toBe('{"a": {"b": 1}}');
|
93
|
+
test("should handle closing brace after number in object", () => {
|
94
|
+
expect(fixJson('{"a": {"b": 1}, "c": {"d": 2')).toBe('{"a": {"b": 1}, "c": {"d": 2}}');
|
95
|
+
});
|
96
|
+
test("should handle closing brace after string in object", () => {
|
97
|
+
expect(fixJson('{"a": {"b": "1"}, "c": {"d": 2')).toBe('{"a": {"b": "1"}, "c": {"d": 2}}');
|
98
|
+
});
|
99
|
+
test("should handle closing brace after literal in object", () => {
|
100
|
+
expect(fixJson('{"a": {"b": false}, "c": {"d": 2')).toBe('{"a": {"b": false}, "c": {"d": 2}}');
|
101
|
+
});
|
102
|
+
test("should handle closing brace after array in object", () => {
|
103
|
+
expect(fixJson('{"a": {"b": []}, "c": {"d": 2')).toBe('{"a": {"b": []}, "c": {"d": 2}}');
|
104
|
+
});
|
105
|
+
test("should handle closing brace after object in object", () => {
|
106
|
+
expect(fixJson('{"a": {"b": {}}, "c": {"d": 2')).toBe('{"a": {"b": {}}, "c": {"d": 2}}');
|
80
107
|
});
|
81
108
|
test("should handle partial keys (first key)", () => {
|
82
109
|
expect(fixJson('{"ke')).toBe("{}");
|
@@ -125,4 +152,33 @@ describe("fixJson", () => {
|
|
125
152
|
expect(fixJson('{"a": 1, "b": "')).toBe('{"a": 1, "b": ""}');
|
126
153
|
});
|
127
154
|
});
|
155
|
+
describe("regression", () => {
|
156
|
+
test("should handle complex nesting 1", () => {
|
157
|
+
expect(fixJson([
|
158
|
+
"{",
|
159
|
+
' "a": [',
|
160
|
+
" {",
|
161
|
+
' "a1": "v1",',
|
162
|
+
' "a2": "v2",',
|
163
|
+
` "a3": "v3"`,
|
164
|
+
" }",
|
165
|
+
" ],",
|
166
|
+
' "b": [',
|
167
|
+
" {",
|
168
|
+
' "b1": "n',
|
169
|
+
].join("\n"))).toBe([
|
170
|
+
"{",
|
171
|
+
' "a": [',
|
172
|
+
" {",
|
173
|
+
' "a1": "v1",',
|
174
|
+
' "a2": "v2",',
|
175
|
+
` "a3": "v3"`,
|
176
|
+
" }",
|
177
|
+
" ],",
|
178
|
+
' "b": [',
|
179
|
+
" {",
|
180
|
+
' "b1": "n"}]}',
|
181
|
+
].join("\n"));
|
182
|
+
});
|
183
|
+
});
|
128
184
|
});
|
@@ -3,7 +3,7 @@ import { AsyncIterableResultPromise } from "../AsyncIterableResultPromise.js";
|
|
3
3
|
import { DeltaEvent } from "../DeltaEvent.js";
|
4
4
|
import { ModelFunctionOptions } from "../ModelFunctionOptions.js";
|
5
5
|
import { StructureGenerationModel, StructureGenerationModelSettings } from "./StructureGenerationModel.js";
|
6
|
-
type StructureStreamPart<STRUCTURE> = {
|
6
|
+
export type StructureStreamPart<STRUCTURE> = {
|
7
7
|
isComplete: false;
|
8
8
|
value: unknown;
|
9
9
|
} | {
|
@@ -14,4 +14,3 @@ export declare function streamStructure<STRUCTURE, PROMPT, FULL_DELTA, NAME exte
|
|
14
14
|
generateStructureStreamResponse: (structureDefinition: StructureDefinition<NAME, STRUCTURE>, prompt: PROMPT, options: ModelFunctionOptions<SETTINGS>) => PromiseLike<AsyncIterable<DeltaEvent<FULL_DELTA>>>;
|
15
15
|
extractPartialStructure: (fullDelta: FULL_DELTA) => unknown | undefined;
|
16
16
|
}, structureDefinition: StructureDefinition<NAME, STRUCTURE>, prompt: PROMPT, options?: ModelFunctionOptions<SETTINGS>): AsyncIterableResultPromise<StructureStreamPart<STRUCTURE>>;
|
17
|
-
export {};
|
@@ -277,6 +277,10 @@ const openAITextGenerationResponseSchema = zod_1.default.object({
|
|
277
277
|
}),
|
278
278
|
});
|
279
279
|
async function callOpenAITextGenerationAPI({ api = new OpenAIApiConfiguration_js_1.OpenAIApiConfiguration(), abortSignal, responseFormat, model, prompt, suffix, maxTokens, temperature, topP, n, logprobs, echo, stop, presencePenalty, frequencyPenalty, bestOf, logitBias, user, }) {
|
280
|
+
// empty arrays are not allowed for stop:
|
281
|
+
if (stop != null && Array.isArray(stop) && stop.length === 0) {
|
282
|
+
stop = undefined;
|
283
|
+
}
|
280
284
|
return (0, postToApi_js_1.postJsonToApi)({
|
281
285
|
url: api.assembleUrl("/completions"),
|
282
286
|
headers: api.headers,
|
@@ -267,6 +267,10 @@ const openAITextGenerationResponseSchema = z.object({
|
|
267
267
|
}),
|
268
268
|
});
|
269
269
|
async function callOpenAITextGenerationAPI({ api = new OpenAIApiConfiguration(), abortSignal, responseFormat, model, prompt, suffix, maxTokens, temperature, topP, n, logprobs, echo, stop, presencePenalty, frequencyPenalty, bestOf, logitBias, user, }) {
|
270
|
+
// empty arrays are not allowed for stop:
|
271
|
+
if (stop != null && Array.isArray(stop) && stop.length === 0) {
|
272
|
+
stop = undefined;
|
273
|
+
}
|
270
274
|
return postJsonToApi({
|
271
275
|
url: api.assembleUrl("/completions"),
|
272
276
|
headers: api.headers,
|
@@ -365,6 +365,10 @@ const openAIChatResponseSchema = zod_1.default.object({
|
|
365
365
|
}),
|
366
366
|
});
|
367
367
|
async function callOpenAIChatCompletionAPI({ api = new OpenAIApiConfiguration_js_1.OpenAIApiConfiguration(), abortSignal, responseFormat, model, messages, functions, functionCall, temperature, topP, n, stop, maxTokens, presencePenalty, frequencyPenalty, logitBias, user, }) {
|
368
|
+
// empty arrays are not allowed for stop:
|
369
|
+
if (stop != null && Array.isArray(stop) && stop.length === 0) {
|
370
|
+
stop = undefined;
|
371
|
+
}
|
368
372
|
return (0, postToApi_js_1.postJsonToApi)({
|
369
373
|
url: api.assembleUrl("/chat/completions"),
|
370
374
|
headers: api.headers,
|
@@ -355,6 +355,10 @@ const openAIChatResponseSchema = z.object({
|
|
355
355
|
}),
|
356
356
|
});
|
357
357
|
async function callOpenAIChatCompletionAPI({ api = new OpenAIApiConfiguration(), abortSignal, responseFormat, model, messages, functions, functionCall, temperature, topP, n, stop, maxTokens, presencePenalty, frequencyPenalty, logitBias, user, }) {
|
358
|
+
// empty arrays are not allowed for stop:
|
359
|
+
if (stop != null && Array.isArray(stop) && stop.length === 0) {
|
360
|
+
stop = undefined;
|
361
|
+
}
|
358
362
|
return postJsonToApi({
|
359
363
|
url: api.assembleUrl("/chat/completions"),
|
360
364
|
headers: api.headers,
|
package/package.json
CHANGED