@oxy.so/contracts 4.9.0 → 4.9.1

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.
@@ -69,7 +69,48 @@ export function decisionInputBudget(payload) {
69
69
  export function decisionFitsGateway(payload) {
70
70
  return decisionInputBudget(payload).gateway <= 32000;
71
71
  }
72
+ /** JSON permits escaped lone UTF-16 units; Go replaces them after decoding. */
73
+ function hasUnpairedSurrogate(value) {
74
+ for (let i = 0; i < value.length; i++) {
75
+ const unit = value.charCodeAt(i);
76
+ if (unit >= 0xd800 && unit <= 0xdbff) {
77
+ const next = value.charCodeAt(i + 1);
78
+ if (!(next >= 0xdc00 && next <= 0xdfff))
79
+ return true;
80
+ i++;
81
+ }
82
+ else if (unit >= 0xdc00 && unit <= 0xdfff)
83
+ return true;
84
+ }
85
+ return false;
86
+ }
72
87
  function validateInput(payload, ctx) {
88
+ const fields = [
89
+ { value: payload.state, path: ["state"] },
90
+ { value: payload.instructions, path: ["instructions"] },
91
+ ];
92
+ for (const [index, question] of payload.questions.entries()) {
93
+ for (const field of ["id", "question", "criteria"]) {
94
+ fields.push({ value: question[field], path: ["questions", index, field] });
95
+ }
96
+ if (question.kind === "choice" || question.kind === "score") {
97
+ const field = question.kind === "choice" ? "options" : "levels";
98
+ const labels = question.kind === "choice" ? question.options : question.levels;
99
+ for (const [labelIndex, value] of labels.entries()) {
100
+ fields.push({ value, path: ["questions", index, field, labelIndex] });
101
+ }
102
+ }
103
+ }
104
+ let invalidUnicode = false;
105
+ for (const { value, path } of fields) {
106
+ if (value !== undefined && hasUnpairedSurrogate(value)) {
107
+ invalidUnicode = true;
108
+ ctx.addIssue({ code: "custom", path, message: "Decisions require paired UTF-16 surrogates." });
109
+ }
110
+ }
111
+ // Reject before measuring/reserving text that the execution runtime would change.
112
+ if (invalidUnicode)
113
+ return;
73
114
  if (new Set(payload.questions.map((q) => q.id)).size !==
74
115
  payload.questions.length)
75
116
  ctx.addIssue({