@kortyx/hooks 0.12.1 → 0.14.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/CHANGELOG.md +15 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +355 -160
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -298,7 +298,8 @@ var emitStructuredData = (args) => {
|
|
|
298
298
|
data: validated
|
|
299
299
|
});
|
|
300
300
|
};
|
|
301
|
-
var shouldEmitStructured = (cfg) => Boolean(cfg)
|
|
301
|
+
var shouldEmitStructured = (cfg) => Boolean(cfg);
|
|
302
|
+
var shouldStreamStructured = (cfg) => Boolean(cfg) && (cfg?.stream ?? true);
|
|
302
303
|
|
|
303
304
|
// src/reason/checkpoint.ts
|
|
304
305
|
var resolveReasonCheckpointKey = (args) => typeof args.id === "string" && args.id.length > 0 ? `__useReason:${args.id}` : `__useReason:auto:${args.autoIndex}`;
|
|
@@ -861,12 +862,12 @@ var withStructuredStreamHints = (input, args) => {
|
|
|
861
862
|
const rules = [];
|
|
862
863
|
for (const path of args.setFieldPaths ?? []) {
|
|
863
864
|
rules.push(
|
|
864
|
-
`- For the
|
|
865
|
+
`- For the field path pattern \`${path}\`, write one stable final value and do not rewrite it after it is complete.`
|
|
865
866
|
);
|
|
866
867
|
}
|
|
867
868
|
for (const path of args.appendFieldPaths ?? []) {
|
|
868
869
|
rules.push(
|
|
869
|
-
`- For the
|
|
870
|
+
`- For the array field path pattern \`${path}\`, write items in final order and finish each item before starting the next.`
|
|
870
871
|
);
|
|
871
872
|
rules.push(
|
|
872
873
|
`- Once an item in \`${path}\` is complete, do not rewrite or reorder earlier items.`
|
|
@@ -874,7 +875,7 @@ var withStructuredStreamHints = (input, args) => {
|
|
|
874
875
|
}
|
|
875
876
|
for (const path of args.textDeltaFieldPaths ?? []) {
|
|
876
877
|
rules.push(
|
|
877
|
-
`- For the
|
|
878
|
+
`- For the string field path pattern \`${path}\`, write the value progressively by appending text to the end.`
|
|
878
879
|
);
|
|
879
880
|
rules.push(
|
|
880
881
|
`- Do not rewrite or replace the earlier prefix of \`${path}\` once emitted.`
|
|
@@ -890,22 +891,12 @@ var withStructuredStreamHints = (input, args) => {
|
|
|
890
891
|
};
|
|
891
892
|
|
|
892
893
|
// src/reason/structured-stream.ts
|
|
893
|
-
var escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
894
|
-
var findTopLevelArrayStart = (text, path) => {
|
|
895
|
-
const match = new RegExp(`"${escapeRegex(path)}"\\s*:\\s*\\[`).exec(text);
|
|
896
|
-
return match ? match.index + match[0].length : -1;
|
|
897
|
-
};
|
|
898
894
|
var resolveAppendFieldPaths = (cfg) => {
|
|
899
895
|
const fields = cfg?.fields;
|
|
900
896
|
if (!fields) return [];
|
|
901
897
|
const appendPaths = Object.entries(fields).filter(([, mode]) => mode === "append").map(([path]) => path);
|
|
902
898
|
for (const path of appendPaths) {
|
|
903
899
|
assertStructuredPath(path, "useReason structured append");
|
|
904
|
-
if (path.includes(".")) {
|
|
905
|
-
throw new Error(
|
|
906
|
-
"useReason structured append streaming requires non-empty top-level array field keys."
|
|
907
|
-
);
|
|
908
|
-
}
|
|
909
900
|
}
|
|
910
901
|
return appendPaths;
|
|
911
902
|
};
|
|
@@ -915,11 +906,6 @@ var resolveSetFieldPaths = (cfg) => {
|
|
|
915
906
|
const setPaths = Object.entries(fields).filter(([, mode]) => mode === "set").map(([path]) => path);
|
|
916
907
|
for (const path of setPaths) {
|
|
917
908
|
assertStructuredPath(path, "useReason structured set");
|
|
918
|
-
if (path.includes(".")) {
|
|
919
|
-
throw new Error(
|
|
920
|
-
"useReason structured set streaming requires non-empty top-level field keys."
|
|
921
|
-
);
|
|
922
|
-
}
|
|
923
909
|
}
|
|
924
910
|
return setPaths;
|
|
925
911
|
};
|
|
@@ -929,22 +915,9 @@ var resolveTextDeltaFieldPaths = (cfg) => {
|
|
|
929
915
|
const textPaths = Object.entries(fields).filter(([, mode]) => mode === "text-delta").map(([path]) => path);
|
|
930
916
|
for (const path of textPaths) {
|
|
931
917
|
assertStructuredPath(path, "useReason structured text-delta");
|
|
932
|
-
if (path.includes(".")) {
|
|
933
|
-
throw new Error(
|
|
934
|
-
"useReason structured text-delta streaming requires non-empty top-level string field keys."
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
918
|
}
|
|
938
919
|
return textPaths;
|
|
939
920
|
};
|
|
940
|
-
var findTopLevelFieldValueStart = (text, path) => {
|
|
941
|
-
const match = new RegExp(`"${escapeRegex(path)}"\\s*:\\s*`).exec(text);
|
|
942
|
-
return match ? match.index + match[0].length : -1;
|
|
943
|
-
};
|
|
944
|
-
var findTopLevelStringStart = (text, path) => {
|
|
945
|
-
const match = new RegExp(`"${escapeRegex(path)}"\\s*:\\s*"`).exec(text);
|
|
946
|
-
return match ? match.index + match[0].length : -1;
|
|
947
|
-
};
|
|
948
921
|
var extractCompletedStringValueAt = (args) => {
|
|
949
922
|
let value = "";
|
|
950
923
|
for (let i = args.start; i < args.text.length; i += 1) {
|
|
@@ -990,12 +963,52 @@ var extractCompletedStringValueAt = (args) => {
|
|
|
990
963
|
complete: false
|
|
991
964
|
};
|
|
992
965
|
};
|
|
993
|
-
var
|
|
966
|
+
var skipWhitespace = (text, start) => {
|
|
967
|
+
let i = start;
|
|
968
|
+
while (i < text.length && /\s/.test(text[i] ?? "")) i += 1;
|
|
969
|
+
return i;
|
|
970
|
+
};
|
|
971
|
+
var pathSegmentMatches = (patternPart, actualPart) => patternPart === "*" || patternPart === actualPart;
|
|
972
|
+
var pathMatchesPattern = (actualParts, patternParts) => actualParts.length === patternParts.length && actualParts.every(
|
|
973
|
+
(part, index) => pathSegmentMatches(patternParts[index] ?? "", part)
|
|
974
|
+
);
|
|
975
|
+
var isPathPrefix = (prefix, full) => prefix.length <= full.length && prefix.every((part, index) => pathSegmentMatches(full[index] ?? "", part));
|
|
976
|
+
var parseStringToken = (text, start) => {
|
|
977
|
+
if (text[start] !== '"') return { complete: false };
|
|
978
|
+
const parsed = extractCompletedStringValueAt({ text, start: start + 1 });
|
|
979
|
+
if (!parsed.complete || parsed.value === void 0)
|
|
980
|
+
return { complete: false };
|
|
981
|
+
let inEscape = false;
|
|
982
|
+
for (let i = start + 1; i < text.length; i += 1) {
|
|
983
|
+
const ch = text[i];
|
|
984
|
+
if (ch === void 0) break;
|
|
985
|
+
if (inEscape) {
|
|
986
|
+
inEscape = false;
|
|
987
|
+
if (ch === "u") i += 4;
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
if (ch === "\\") {
|
|
991
|
+
inEscape = true;
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
if (ch === '"') {
|
|
995
|
+
return {
|
|
996
|
+
complete: true,
|
|
997
|
+
end: i + 1,
|
|
998
|
+
value: parsed.value
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
return { complete: false };
|
|
1003
|
+
};
|
|
1004
|
+
var skipNestedValue = (text, start) => {
|
|
1005
|
+
const opener = text[start];
|
|
1006
|
+
const closer = opener === "{" ? "}" : "]";
|
|
994
1007
|
let inString = false;
|
|
995
1008
|
let isEscaped = false;
|
|
996
1009
|
let nesting = 0;
|
|
997
|
-
for (let i =
|
|
998
|
-
const ch =
|
|
1010
|
+
for (let i = start; i < text.length; i += 1) {
|
|
1011
|
+
const ch = text[i];
|
|
999
1012
|
if (ch === void 0) break;
|
|
1000
1013
|
if (inString) {
|
|
1001
1014
|
if (isEscaped) {
|
|
@@ -1015,124 +1028,266 @@ var extractCompletedNestedValueAt = (args) => {
|
|
|
1015
1028
|
inString = true;
|
|
1016
1029
|
continue;
|
|
1017
1030
|
}
|
|
1018
|
-
if (ch ===
|
|
1031
|
+
if (ch === opener) {
|
|
1019
1032
|
nesting += 1;
|
|
1020
1033
|
continue;
|
|
1021
1034
|
}
|
|
1022
|
-
if (ch ===
|
|
1035
|
+
if (ch === closer) {
|
|
1023
1036
|
nesting -= 1;
|
|
1024
1037
|
if (nesting === 0) {
|
|
1025
|
-
|
|
1026
|
-
try {
|
|
1027
|
-
return {
|
|
1028
|
-
complete: true,
|
|
1029
|
-
value: JSON.parse(raw)
|
|
1030
|
-
};
|
|
1031
|
-
} catch {
|
|
1032
|
-
return {
|
|
1033
|
-
complete: false
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1038
|
+
return { complete: true, end: i + 1 };
|
|
1036
1039
|
}
|
|
1037
1040
|
}
|
|
1038
1041
|
}
|
|
1039
|
-
return {
|
|
1040
|
-
complete: false
|
|
1041
|
-
};
|
|
1042
|
+
return { complete: false };
|
|
1042
1043
|
};
|
|
1043
|
-
var
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
};
|
|
1044
|
+
var skipCompleteValue = (text, start) => {
|
|
1045
|
+
const i = skipWhitespace(text, start);
|
|
1046
|
+
const first = text[i];
|
|
1047
|
+
if (!first) return { complete: false };
|
|
1048
|
+
if (first === '"') {
|
|
1049
|
+
const parsed = parseStringToken(text, i);
|
|
1050
|
+
return parsed.complete && parsed.end !== void 0 ? { complete: true, end: parsed.end } : { complete: false };
|
|
1050
1051
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
return {
|
|
1054
|
-
found: true,
|
|
1055
|
-
complete: false
|
|
1056
|
-
};
|
|
1052
|
+
if (first === "{" || first === "[") {
|
|
1053
|
+
return skipNestedValue(text, i);
|
|
1057
1054
|
}
|
|
1055
|
+
for (let j = i; j < text.length; j += 1) {
|
|
1056
|
+
const ch = text[j];
|
|
1057
|
+
if (ch !== "," && ch !== "}" && ch !== "]") continue;
|
|
1058
|
+
const raw = text.slice(i, j).trim();
|
|
1059
|
+
if (!raw) return { complete: false };
|
|
1060
|
+
try {
|
|
1061
|
+
JSON.parse(raw);
|
|
1062
|
+
return { complete: true, end: j };
|
|
1063
|
+
} catch {
|
|
1064
|
+
return { complete: false };
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return { complete: false };
|
|
1068
|
+
};
|
|
1069
|
+
var locateValueStart = (args) => {
|
|
1070
|
+
const [first] = locateValueStarts(args);
|
|
1071
|
+
return first ? {
|
|
1072
|
+
found: true,
|
|
1073
|
+
start: first.start
|
|
1074
|
+
} : {
|
|
1075
|
+
found: false
|
|
1076
|
+
};
|
|
1077
|
+
};
|
|
1078
|
+
var locateValueStarts = (args) => {
|
|
1079
|
+
const targetParts = parseStructuredPath(
|
|
1080
|
+
args.path,
|
|
1081
|
+
"useReason structured field"
|
|
1082
|
+
);
|
|
1083
|
+
const matches = [];
|
|
1084
|
+
const visitValue = (start, currentParts) => {
|
|
1085
|
+
const valueStart = skipWhitespace(args.text, start);
|
|
1086
|
+
if (pathMatchesPattern(currentParts, targetParts)) {
|
|
1087
|
+
matches.push({
|
|
1088
|
+
path: currentParts.join("."),
|
|
1089
|
+
start: valueStart
|
|
1090
|
+
});
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
if (!isPathPrefix(currentParts, targetParts)) {
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
const first = args.text[valueStart];
|
|
1097
|
+
if (first === "{") visitObject(valueStart + 1, currentParts);
|
|
1098
|
+
if (first === "[") visitArray(valueStart + 1, currentParts);
|
|
1099
|
+
};
|
|
1100
|
+
const visitObject = (start, currentParts) => {
|
|
1101
|
+
let i = skipWhitespace(args.text, start);
|
|
1102
|
+
while (i < args.text.length) {
|
|
1103
|
+
const ch = args.text[i];
|
|
1104
|
+
if (ch === "}") return;
|
|
1105
|
+
if (ch === ",") {
|
|
1106
|
+
i = skipWhitespace(args.text, i + 1);
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
if (ch !== '"') return;
|
|
1110
|
+
const key = parseStringToken(args.text, i);
|
|
1111
|
+
if (!key.complete || key.end === void 0 || key.value === void 0) {
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
i = skipWhitespace(args.text, key.end);
|
|
1115
|
+
if (args.text[i] !== ":") return;
|
|
1116
|
+
const valueStart = skipWhitespace(args.text, i + 1);
|
|
1117
|
+
const childParts = [...currentParts, key.value];
|
|
1118
|
+
if (pathMatchesPattern(childParts, targetParts)) {
|
|
1119
|
+
matches.push({
|
|
1120
|
+
path: childParts.join("."),
|
|
1121
|
+
start: valueStart
|
|
1122
|
+
});
|
|
1123
|
+
} else if (isPathPrefix(childParts, targetParts)) {
|
|
1124
|
+
visitValue(valueStart, childParts);
|
|
1125
|
+
}
|
|
1126
|
+
const skipped = skipCompleteValue(args.text, valueStart);
|
|
1127
|
+
if (!skipped.complete || skipped.end === void 0) {
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
i = skipWhitespace(args.text, skipped.end);
|
|
1131
|
+
if (args.text[i] === ",") {
|
|
1132
|
+
i = skipWhitespace(args.text, i + 1);
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
1135
|
+
if (args.text[i] === "}") return;
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
};
|
|
1139
|
+
const visitArray = (start, currentParts) => {
|
|
1140
|
+
let i = skipWhitespace(args.text, start);
|
|
1141
|
+
let index = 0;
|
|
1142
|
+
while (i < args.text.length) {
|
|
1143
|
+
if (args.text[i] === "]") return;
|
|
1144
|
+
const childParts = [...currentParts, String(index)];
|
|
1145
|
+
if (pathMatchesPattern(childParts, targetParts)) {
|
|
1146
|
+
matches.push({
|
|
1147
|
+
path: childParts.join("."),
|
|
1148
|
+
start: i
|
|
1149
|
+
});
|
|
1150
|
+
} else if (isPathPrefix(childParts, targetParts)) {
|
|
1151
|
+
visitValue(i, childParts);
|
|
1152
|
+
}
|
|
1153
|
+
const skipped = skipCompleteValue(args.text, i);
|
|
1154
|
+
if (!skipped.complete || skipped.end === void 0) {
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
i = skipWhitespace(args.text, skipped.end);
|
|
1158
|
+
if (args.text[i] === ",") {
|
|
1159
|
+
index += 1;
|
|
1160
|
+
i = skipWhitespace(args.text, i + 1);
|
|
1161
|
+
continue;
|
|
1162
|
+
}
|
|
1163
|
+
if (args.text[i] === "]") return;
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
visitValue(0, []);
|
|
1168
|
+
return matches;
|
|
1169
|
+
};
|
|
1170
|
+
var extractCompletedValueAt = (args) => {
|
|
1171
|
+
const start = skipWhitespace(args.text, args.start);
|
|
1172
|
+
const first = args.text[start];
|
|
1173
|
+
if (!first) return { complete: false };
|
|
1058
1174
|
if (first === '"') {
|
|
1059
1175
|
const parsed = extractCompletedStringValueAt({
|
|
1060
1176
|
text: args.text,
|
|
1061
1177
|
start: start + 1
|
|
1062
1178
|
});
|
|
1063
1179
|
return parsed.complete ? {
|
|
1064
|
-
found: true,
|
|
1065
1180
|
complete: true,
|
|
1066
1181
|
value: parsed.value
|
|
1067
1182
|
} : {
|
|
1068
|
-
found: true,
|
|
1069
1183
|
complete: false
|
|
1070
1184
|
};
|
|
1071
1185
|
}
|
|
1072
1186
|
if (first === "{") {
|
|
1073
|
-
|
|
1187
|
+
return extractCompletedNestedValueAt({
|
|
1074
1188
|
text: args.text,
|
|
1075
1189
|
start,
|
|
1076
1190
|
opener: "{",
|
|
1077
1191
|
closer: "}"
|
|
1078
1192
|
});
|
|
1079
|
-
return parsed.complete ? {
|
|
1080
|
-
found: true,
|
|
1081
|
-
complete: true,
|
|
1082
|
-
value: parsed.value
|
|
1083
|
-
} : {
|
|
1084
|
-
found: true,
|
|
1085
|
-
complete: false
|
|
1086
|
-
};
|
|
1087
1193
|
}
|
|
1088
1194
|
if (first === "[") {
|
|
1089
|
-
|
|
1195
|
+
return extractCompletedNestedValueAt({
|
|
1090
1196
|
text: args.text,
|
|
1091
1197
|
start,
|
|
1092
1198
|
opener: "[",
|
|
1093
1199
|
closer: "]"
|
|
1094
1200
|
});
|
|
1095
|
-
return parsed.complete ? {
|
|
1096
|
-
found: true,
|
|
1097
|
-
complete: true,
|
|
1098
|
-
value: parsed.value
|
|
1099
|
-
} : {
|
|
1100
|
-
found: true,
|
|
1101
|
-
complete: false
|
|
1102
|
-
};
|
|
1103
1201
|
}
|
|
1104
1202
|
for (let i = start; i < args.text.length; i += 1) {
|
|
1105
1203
|
const ch = args.text[i];
|
|
1106
1204
|
if (ch === void 0) break;
|
|
1107
|
-
if (ch !== "," && ch !== "}") continue;
|
|
1205
|
+
if (ch !== "," && ch !== "}" && ch !== "]") continue;
|
|
1108
1206
|
const raw = args.text.slice(start, i).trim();
|
|
1109
|
-
if (!raw) {
|
|
1110
|
-
return {
|
|
1111
|
-
found: true,
|
|
1112
|
-
complete: false
|
|
1113
|
-
};
|
|
1114
|
-
}
|
|
1207
|
+
if (!raw) return { complete: false };
|
|
1115
1208
|
try {
|
|
1116
1209
|
return {
|
|
1117
|
-
found: true,
|
|
1118
1210
|
complete: true,
|
|
1119
1211
|
value: JSON.parse(raw)
|
|
1120
1212
|
};
|
|
1121
1213
|
} catch {
|
|
1122
|
-
return {
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1214
|
+
return { complete: false };
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return { complete: false };
|
|
1218
|
+
};
|
|
1219
|
+
var extractCompletedNestedValueAt = (args) => {
|
|
1220
|
+
let inString = false;
|
|
1221
|
+
let isEscaped = false;
|
|
1222
|
+
let nesting = 0;
|
|
1223
|
+
for (let i = args.start; i < args.text.length; i += 1) {
|
|
1224
|
+
const ch = args.text[i];
|
|
1225
|
+
if (ch === void 0) break;
|
|
1226
|
+
if (inString) {
|
|
1227
|
+
if (isEscaped) {
|
|
1228
|
+
isEscaped = false;
|
|
1229
|
+
continue;
|
|
1230
|
+
}
|
|
1231
|
+
if (ch === "\\") {
|
|
1232
|
+
isEscaped = true;
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
if (ch === '"') {
|
|
1236
|
+
inString = false;
|
|
1237
|
+
}
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1240
|
+
if (ch === '"') {
|
|
1241
|
+
inString = true;
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
if (ch === args.opener) {
|
|
1245
|
+
nesting += 1;
|
|
1246
|
+
continue;
|
|
1247
|
+
}
|
|
1248
|
+
if (ch === args.closer) {
|
|
1249
|
+
nesting -= 1;
|
|
1250
|
+
if (nesting === 0) {
|
|
1251
|
+
const raw = args.text.slice(args.start, i + 1);
|
|
1252
|
+
try {
|
|
1253
|
+
return {
|
|
1254
|
+
complete: true,
|
|
1255
|
+
value: JSON.parse(raw)
|
|
1256
|
+
};
|
|
1257
|
+
} catch {
|
|
1258
|
+
return {
|
|
1259
|
+
complete: false
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1126
1263
|
}
|
|
1127
1264
|
}
|
|
1128
1265
|
return {
|
|
1129
|
-
found: true,
|
|
1130
1266
|
complete: false
|
|
1131
1267
|
};
|
|
1132
1268
|
};
|
|
1269
|
+
var extractCompletedFieldValues = (args) => {
|
|
1270
|
+
const located = locateValueStarts(args);
|
|
1271
|
+
const values = [];
|
|
1272
|
+
for (const match of located) {
|
|
1273
|
+
const parsed = extractCompletedValueAt({
|
|
1274
|
+
text: args.text,
|
|
1275
|
+
start: match.start
|
|
1276
|
+
});
|
|
1277
|
+
if (!parsed.complete) continue;
|
|
1278
|
+
values.push({
|
|
1279
|
+
path: match.path,
|
|
1280
|
+
value: parsed.value
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
return values;
|
|
1284
|
+
};
|
|
1133
1285
|
var extractCompletedArrayItems = (args) => {
|
|
1134
|
-
const
|
|
1135
|
-
if (start
|
|
1286
|
+
const located = locateValueStart(args);
|
|
1287
|
+
if (!located.found || located.start === void 0) return [];
|
|
1288
|
+
const arrayStart = skipWhitespace(args.text, located.start);
|
|
1289
|
+
if (args.text[arrayStart] !== "[") return [];
|
|
1290
|
+
const start = arrayStart + 1;
|
|
1136
1291
|
const items = [];
|
|
1137
1292
|
let inString = false;
|
|
1138
1293
|
let isEscaped = false;
|
|
@@ -1195,17 +1350,39 @@ var extractCompletedArrayItems = (args) => {
|
|
|
1195
1350
|
}
|
|
1196
1351
|
return items;
|
|
1197
1352
|
};
|
|
1353
|
+
var extractCompletedArrayItemGroups = (args) => {
|
|
1354
|
+
return locateValueStarts(args).flatMap((match) => {
|
|
1355
|
+
const items = extractCompletedArrayItems({
|
|
1356
|
+
text: args.text,
|
|
1357
|
+
path: match.path
|
|
1358
|
+
});
|
|
1359
|
+
return items.length > 0 ? [
|
|
1360
|
+
{
|
|
1361
|
+
path: match.path,
|
|
1362
|
+
items
|
|
1363
|
+
}
|
|
1364
|
+
] : [];
|
|
1365
|
+
});
|
|
1366
|
+
};
|
|
1198
1367
|
var extractStreamingStringValue = (args) => {
|
|
1199
|
-
const
|
|
1200
|
-
if (start
|
|
1368
|
+
const located = locateValueStart(args);
|
|
1369
|
+
if (!located.found || located.start === void 0) {
|
|
1201
1370
|
return {
|
|
1202
|
-
found:
|
|
1371
|
+
found: located.found,
|
|
1372
|
+
complete: false,
|
|
1373
|
+
value: ""
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
const stringStart = skipWhitespace(args.text, located.start);
|
|
1377
|
+
if (args.text[stringStart] !== '"') {
|
|
1378
|
+
return {
|
|
1379
|
+
found: true,
|
|
1203
1380
|
complete: false,
|
|
1204
1381
|
value: ""
|
|
1205
1382
|
};
|
|
1206
1383
|
}
|
|
1207
1384
|
let value = "";
|
|
1208
|
-
for (let i =
|
|
1385
|
+
for (let i = stringStart + 1; i < args.text.length; i += 1) {
|
|
1209
1386
|
const ch = args.text[i];
|
|
1210
1387
|
if (ch === void 0) break;
|
|
1211
1388
|
if (ch === '"') {
|
|
@@ -1257,6 +1434,21 @@ var extractStreamingStringValue = (args) => {
|
|
|
1257
1434
|
value
|
|
1258
1435
|
};
|
|
1259
1436
|
};
|
|
1437
|
+
var extractStreamingStringValues = (args) => {
|
|
1438
|
+
return locateValueStarts(args).flatMap((match) => {
|
|
1439
|
+
const current = extractStreamingStringValue({
|
|
1440
|
+
text: args.text,
|
|
1441
|
+
path: match.path
|
|
1442
|
+
});
|
|
1443
|
+
return current.found ? [
|
|
1444
|
+
{
|
|
1445
|
+
path: match.path,
|
|
1446
|
+
complete: current.complete,
|
|
1447
|
+
value: current.value
|
|
1448
|
+
}
|
|
1449
|
+
] : [];
|
|
1450
|
+
});
|
|
1451
|
+
};
|
|
1260
1452
|
|
|
1261
1453
|
// src/reason/use-reason.ts
|
|
1262
1454
|
var mergeUsage = (left, right) => {
|
|
@@ -1316,7 +1508,7 @@ var emitReasonStructuredOutput = (args) => {
|
|
|
1316
1508
|
streamId: args.opId
|
|
1317
1509
|
});
|
|
1318
1510
|
};
|
|
1319
|
-
var
|
|
1511
|
+
var shouldStreamReasonStructured = (args) => (args.emit ?? true) && shouldStreamStructured(args.structured);
|
|
1320
1512
|
var resolveEffectiveReasoningIncludeThoughts = (args) => args.reasoning?.includeThoughts ?? args.model.options?.reasoning?.includeThoughts ?? false;
|
|
1321
1513
|
var resolveEffectiveResponseFormatType = (args) => args.responseFormat?.type ?? args.model.options?.responseFormat?.type;
|
|
1322
1514
|
var assertReasoningThoughtsCompatibility = (args) => {
|
|
@@ -1366,7 +1558,7 @@ async function useReason(args) {
|
|
|
1366
1558
|
const appendFieldPaths = resolveAppendFieldPaths(args.structured);
|
|
1367
1559
|
const textDeltaFieldPaths = resolveTextDeltaFieldPaths(args.structured);
|
|
1368
1560
|
const useStructuredIncrementalStreaming = Boolean(
|
|
1369
|
-
args.outputSchema && !args.interrupt && (setFieldPaths.length > 0 || appendFieldPaths.length > 0 || textDeltaFieldPaths.length > 0) && args.stream !== false &&
|
|
1561
|
+
args.outputSchema && !args.interrupt && (setFieldPaths.length > 0 || appendFieldPaths.length > 0 || textDeltaFieldPaths.length > 0) && args.stream !== false && shouldStreamReasonStructured(args)
|
|
1370
1562
|
);
|
|
1371
1563
|
let firstText = "";
|
|
1372
1564
|
let firstRaw;
|
|
@@ -1407,70 +1599,73 @@ async function useReason(args) {
|
|
|
1407
1599
|
onTextChunk: (delta) => {
|
|
1408
1600
|
firstText += delta;
|
|
1409
1601
|
finalText = firstText;
|
|
1410
|
-
for (const
|
|
1411
|
-
const
|
|
1602
|
+
for (const fieldPath of setFieldPaths) {
|
|
1603
|
+
const values = extractCompletedFieldValues({
|
|
1412
1604
|
text: firstText,
|
|
1413
|
-
path
|
|
1414
|
-
});
|
|
1415
|
-
if (!current.found || !current.complete) continue;
|
|
1416
|
-
const nextSerialized = JSON.stringify(current.value);
|
|
1417
|
-
if (emittedSetValues.get(path) === nextSerialized) continue;
|
|
1418
|
-
emittedSetValues.set(path, nextSerialized);
|
|
1419
|
-
emitStructuredData({
|
|
1420
|
-
kind: "set",
|
|
1421
|
-
path,
|
|
1422
|
-
value: current.value,
|
|
1423
|
-
dataType: args.structured?.dataType ?? "reason-output",
|
|
1424
|
-
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1425
|
-
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1426
|
-
...id ? { id } : {},
|
|
1427
|
-
streamId: opId
|
|
1605
|
+
path: fieldPath
|
|
1428
1606
|
});
|
|
1607
|
+
for (const { path, value } of values) {
|
|
1608
|
+
const nextSerialized = JSON.stringify(value);
|
|
1609
|
+
if (emittedSetValues.get(path) === nextSerialized) continue;
|
|
1610
|
+
emittedSetValues.set(path, nextSerialized);
|
|
1611
|
+
emitStructuredData({
|
|
1612
|
+
kind: "set",
|
|
1613
|
+
path,
|
|
1614
|
+
value,
|
|
1615
|
+
dataType: args.structured?.dataType ?? "reason-output",
|
|
1616
|
+
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1617
|
+
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1618
|
+
...id ? { id } : {},
|
|
1619
|
+
streamId: opId
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1429
1622
|
}
|
|
1430
|
-
for (const
|
|
1431
|
-
const
|
|
1623
|
+
for (const fieldPath of appendFieldPaths) {
|
|
1624
|
+
const groups = extractCompletedArrayItemGroups({
|
|
1432
1625
|
text: firstText,
|
|
1433
|
-
path
|
|
1434
|
-
});
|
|
1435
|
-
const emittedAppendCount = emittedAppendCounts.get(path) ?? 0;
|
|
1436
|
-
if (items.length <= emittedAppendCount) continue;
|
|
1437
|
-
const nextItems = items.slice(emittedAppendCount);
|
|
1438
|
-
emittedAppendCounts.set(path, items.length);
|
|
1439
|
-
emitStructuredData({
|
|
1440
|
-
kind: "append",
|
|
1441
|
-
path,
|
|
1442
|
-
items: nextItems,
|
|
1443
|
-
dataType: args.structured?.dataType ?? "reason-output",
|
|
1444
|
-
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1445
|
-
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1446
|
-
...id ? { id } : {},
|
|
1447
|
-
streamId: opId
|
|
1626
|
+
path: fieldPath
|
|
1448
1627
|
});
|
|
1628
|
+
for (const { path, items } of groups) {
|
|
1629
|
+
const emittedAppendCount = emittedAppendCounts.get(path) ?? 0;
|
|
1630
|
+
if (items.length <= emittedAppendCount) continue;
|
|
1631
|
+
const nextItems = items.slice(emittedAppendCount);
|
|
1632
|
+
emittedAppendCounts.set(path, items.length);
|
|
1633
|
+
emitStructuredData({
|
|
1634
|
+
kind: "append",
|
|
1635
|
+
path,
|
|
1636
|
+
items: nextItems,
|
|
1637
|
+
dataType: args.structured?.dataType ?? "reason-output",
|
|
1638
|
+
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1639
|
+
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1640
|
+
...id ? { id } : {},
|
|
1641
|
+
streamId: opId
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1449
1644
|
}
|
|
1450
|
-
for (const
|
|
1451
|
-
const
|
|
1645
|
+
for (const fieldPath of textDeltaFieldPaths) {
|
|
1646
|
+
const values = extractStreamingStringValues({
|
|
1452
1647
|
text: firstText,
|
|
1453
|
-
path
|
|
1648
|
+
path: fieldPath
|
|
1454
1649
|
});
|
|
1455
|
-
const
|
|
1456
|
-
|
|
1457
|
-
|
|
1650
|
+
for (const { path, value } of values) {
|
|
1651
|
+
const emittedTextValue = emittedTextValues.get(path) ?? "";
|
|
1652
|
+
if (value.length <= emittedTextValue.length || !value.startsWith(emittedTextValue)) {
|
|
1653
|
+
continue;
|
|
1654
|
+
}
|
|
1655
|
+
const nextDelta = value.slice(emittedTextValue.length);
|
|
1656
|
+
emittedTextValues.set(path, value);
|
|
1657
|
+
if (nextDelta.length === 0) continue;
|
|
1658
|
+
emitStructuredData({
|
|
1659
|
+
kind: "text-delta",
|
|
1660
|
+
path,
|
|
1661
|
+
delta: nextDelta,
|
|
1662
|
+
dataType: args.structured?.dataType ?? "reason-output",
|
|
1663
|
+
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1664
|
+
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1665
|
+
...id ? { id } : {},
|
|
1666
|
+
streamId: opId
|
|
1667
|
+
});
|
|
1458
1668
|
}
|
|
1459
|
-
const nextDelta = current.value.slice(
|
|
1460
|
-
emittedTextValue.length
|
|
1461
|
-
);
|
|
1462
|
-
emittedTextValues.set(path, current.value);
|
|
1463
|
-
if (nextDelta.length === 0) continue;
|
|
1464
|
-
emitStructuredData({
|
|
1465
|
-
kind: "text-delta",
|
|
1466
|
-
path,
|
|
1467
|
-
delta: nextDelta,
|
|
1468
|
-
dataType: args.structured?.dataType ?? "reason-output",
|
|
1469
|
-
...args.structured?.schemaId ? { schemaId: args.structured.schemaId } : {},
|
|
1470
|
-
...args.structured?.schemaVersion ? { schemaVersion: args.structured.schemaVersion } : {},
|
|
1471
|
-
...id ? { id } : {},
|
|
1472
|
-
streamId: opId
|
|
1473
|
-
});
|
|
1474
1669
|
}
|
|
1475
1670
|
}
|
|
1476
1671
|
} : {}
|