@agentica/core 0.32.6 → 0.32.7

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/lib/index.mjs CHANGED
@@ -898,15 +898,217 @@ const ChatGptTokenUsageAggregator = {
898
898
  sumPromptTokenDetail
899
899
  };
900
900
 
901
+ const JsonUtil = {
902
+ parse
903
+ };
904
+
901
905
  function parse(str) {
902
- if (str.startsWith("{}{") === true) {
903
- str = str.substring(2);
906
+ const corrected = pipe(stripFirstBrace, correctMissingLastBrace)(str);
907
+ return JSON.parse(corrected);
908
+ }
909
+
910
+ const pipe = (...fns) => str => fns.reduce(((acc, fn) => fn(acc)), str);
911
+
912
+ function stripFirstBrace(str) {
913
+ if (RegExp("^{}.").test(str) === true) {
914
+ return str.substring(2);
904
915
  }
905
- return JSON.parse(str);
916
+ return str;
906
917
  }
907
918
 
908
- const JsonUtil = {
909
- parse
919
+ function correctMissingLastBrace(input) {
920
+ const initial = {
921
+ s: "OUT",
922
+ stack: [],
923
+ line: 1,
924
+ col: 0,
925
+ edits: []
926
+ };
927
+ const scanned = Array.from(input).reduce(((ps, ch, i) => {
928
+ const updated = ch === "\n" ? {
929
+ ...ps,
930
+ line: ps.line + 1,
931
+ col: 0
932
+ } : {
933
+ ...ps,
934
+ col: ps.col + 1
935
+ };
936
+ const tok = categorize(ch);
937
+ const trans = table[updated.s]?.[tok];
938
+ return trans ? trans(updated, ch, i) : updated;
939
+ }), initial);
940
+ if (scanned.s !== "OUT") return input;
941
+ const withTail = scanned.stack.length === 0 ? scanned : (() => {
942
+ const closers = scanned.stack.slice().reverse().map((e => closeOf[e.type])).join("");
943
+ return {
944
+ ...scanned,
945
+ edits: [ ...scanned.edits, {
946
+ op: "insert",
947
+ index: input.length,
948
+ text: closers
949
+ } ],
950
+ stack: []
951
+ };
952
+ })();
953
+ return applyEditsImmutable(input, withTail.edits);
954
+ }
955
+
956
+ function applyEditsImmutable(src, edits) {
957
+ const sorted = [ ...edits ].sort(((a, b) => a.index - b.index));
958
+ const built = sorted.reduce(((acc, e) => {
959
+ const prefix = src.slice(acc.cursor, e.index);
960
+ const acc1 = {
961
+ out: acc.out + prefix,
962
+ cursor: e.index
963
+ };
964
+ return e.op === "delete" ? {
965
+ out: acc1.out,
966
+ cursor: acc1.cursor + 1
967
+ } : e.op === "replace" ? {
968
+ out: acc1.out + e.text,
969
+ cursor: acc1.cursor + 1
970
+ } : {
971
+ out: acc1.out + e.text,
972
+ cursor: acc1.cursor
973
+ };
974
+ }), {
975
+ out: "",
976
+ cursor: 0
977
+ });
978
+ return built.out + src.slice(built.cursor);
979
+ }
980
+
981
+ const openOf = Object.freeze({
982
+ "}": "{",
983
+ "]": "["
984
+ });
985
+
986
+ const closeOf = Object.freeze({
987
+ "{": "}",
988
+ "[": "]"
989
+ });
990
+
991
+ const categorize = ch => {
992
+ switch (ch) {
993
+ case '"':
994
+ return "DQUOTE";
995
+
996
+ case "\\":
997
+ return "BSLASH";
998
+
999
+ case "{":
1000
+ return "OCB";
1001
+
1002
+ case "[":
1003
+ return "OSB";
1004
+
1005
+ case "}":
1006
+ return "CCB";
1007
+
1008
+ case "]":
1009
+ return "CSB";
1010
+
1011
+ case "\n":
1012
+ return "NEWLINE";
1013
+
1014
+ default:
1015
+ return "CHAR";
1016
+ }
1017
+ };
1018
+
1019
+ const push = (ps, type, index) => ({
1020
+ ...ps,
1021
+ stack: [ ...ps.stack, {
1022
+ type,
1023
+ index
1024
+ } ]
1025
+ });
1026
+
1027
+ const withEdit = (ps, edit) => ({
1028
+ ...ps,
1029
+ edits: [ ...ps.edits, edit ]
1030
+ });
1031
+
1032
+ const popOrFix = (ps, closer, idx) => (() => {
1033
+ if (ps.stack.length === 0) {
1034
+ return withEdit(ps, {
1035
+ op: "delete",
1036
+ index: idx
1037
+ });
1038
+ }
1039
+ const top = ps.stack[ps.stack.length - 1];
1040
+ if (top !== undefined && top.type !== openOf[closer]) {
1041
+ const expected = closeOf[top.type];
1042
+ return withEdit({
1043
+ ...ps,
1044
+ stack: ps.stack.slice(0, -1)
1045
+ }, {
1046
+ op: "replace",
1047
+ index: idx,
1048
+ text: expected
1049
+ });
1050
+ }
1051
+ return {
1052
+ ...ps,
1053
+ stack: ps.stack.slice(0, -1)
1054
+ };
1055
+ })();
1056
+
1057
+ const table = {
1058
+ OUT: {
1059
+ DQUOTE: ps => ({
1060
+ ...ps,
1061
+ s: "IN"
1062
+ }),
1063
+ OCB: (ps, _ch, i) => push(ps, "{", i),
1064
+ OSB: (ps, _ch, i) => push(ps, "[", i),
1065
+ CCB: (ps, _ch, i) => popOrFix(ps, "}", i),
1066
+ CSB: (ps, _ch, i) => popOrFix(ps, "]", i)
1067
+ },
1068
+ IN: {
1069
+ BSLASH: ps => ({
1070
+ ...ps,
1071
+ s: "ESC"
1072
+ }),
1073
+ DQUOTE: ps => ({
1074
+ ...ps,
1075
+ s: "OUT"
1076
+ })
1077
+ },
1078
+ ESC: {
1079
+ DQUOTE: ps => ({
1080
+ ...ps,
1081
+ s: "IN"
1082
+ }),
1083
+ BSLASH: ps => ({
1084
+ ...ps,
1085
+ s: "IN"
1086
+ }),
1087
+ OCB: ps => ({
1088
+ ...ps,
1089
+ s: "IN"
1090
+ }),
1091
+ OSB: ps => ({
1092
+ ...ps,
1093
+ s: "IN"
1094
+ }),
1095
+ CCB: ps => ({
1096
+ ...ps,
1097
+ s: "IN"
1098
+ }),
1099
+ CSB: ps => ({
1100
+ ...ps,
1101
+ s: "IN"
1102
+ }),
1103
+ CHAR: ps => ({
1104
+ ...ps,
1105
+ s: "IN"
1106
+ }),
1107
+ NEWLINE: ps => ({
1108
+ ...ps,
1109
+ s: "IN"
1110
+ })
1111
+ }
910
1112
  };
911
1113
 
912
1114
  function transformCompletionChunk(source) {