@thanh01.pmt/curriculum-kit 1.4.51 → 1.4.52

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/dist/ai/index.cjs CHANGED
@@ -8,6 +8,7 @@ var path = require('path');
8
8
  var url = require('url');
9
9
  var ai = require('ai');
10
10
  var zod = require('zod');
11
+ var jsonrepair = require('jsonrepair');
11
12
 
12
13
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -4016,11 +4017,155 @@ async function generateExtensionFlow(input) {
4016
4017
  });
4017
4018
  return object;
4018
4019
  }
4020
+ function closeTruncatedJson(candidate) {
4021
+ let inStr = false;
4022
+ let esc = false;
4023
+ const stack = [];
4024
+ for (let i = 0; i < candidate.length; i++) {
4025
+ const ch = candidate[i];
4026
+ if (esc) {
4027
+ esc = false;
4028
+ continue;
4029
+ }
4030
+ if (inStr) {
4031
+ if (ch === "\\") esc = true;
4032
+ else if (ch === '"') inStr = false;
4033
+ continue;
4034
+ }
4035
+ if (ch === '"') inStr = true;
4036
+ else if (ch === "{" || ch === "[") stack.push(ch);
4037
+ else if (ch === "}" || ch === "]") stack.pop();
4038
+ }
4039
+ if (stack.length === 0 && !inStr) return null;
4040
+ let out = candidate;
4041
+ out = out.replace(/,\s*$/, "");
4042
+ if (inStr) {
4043
+ out = out.replace(/\\+$/, "");
4044
+ out += '"';
4045
+ }
4046
+ while (stack.length > 0) {
4047
+ out += stack.pop() === "{" ? "}" : "]";
4048
+ }
4049
+ return out;
4050
+ }
4051
+ function stripLlmJsonWrappers(rawText) {
4052
+ let cleaned = rawText.replace(/<think>[\s\S]*?<\/think>/gi, "").replace(/```json\s*/gi, "").replace(/```\s*/g, "").trim();
4053
+ const firstBrace = cleaned.indexOf("{");
4054
+ if (firstBrace > 0) {
4055
+ cleaned = cleaned.slice(firstBrace);
4056
+ }
4057
+ return cleaned.trim();
4058
+ }
4059
+ function safeParseJson(rawText) {
4060
+ if (!rawText) return null;
4061
+ const cleaned = stripLlmJsonWrappers(rawText);
4062
+ if (!cleaned) return null;
4063
+ try {
4064
+ return JSON.parse(cleaned);
4065
+ } catch {
4066
+ }
4067
+ const firstBrace = cleaned.indexOf("{");
4068
+ if (firstBrace === -1) return null;
4069
+ const buildCandidates = () => {
4070
+ const list = [];
4071
+ const closed = closeTruncatedJson(cleaned.slice(firstBrace));
4072
+ if (closed) list.push(closed);
4073
+ const lastBrace = cleaned.lastIndexOf("}");
4074
+ if (lastBrace > firstBrace) {
4075
+ list.push(cleaned.slice(firstBrace, lastBrace + 1));
4076
+ }
4077
+ return list;
4078
+ };
4079
+ for (const candidate of buildCandidates()) {
4080
+ try {
4081
+ return JSON.parse(candidate);
4082
+ } catch {
4083
+ }
4084
+ try {
4085
+ return JSON.parse(jsonrepair.jsonrepair(candidate));
4086
+ } catch {
4087
+ }
4088
+ }
4089
+ let depth = 0;
4090
+ let inStr = false;
4091
+ let esc = false;
4092
+ for (let i = firstBrace; i < cleaned.length; i++) {
4093
+ const ch = cleaned[i];
4094
+ if (esc) {
4095
+ esc = false;
4096
+ continue;
4097
+ }
4098
+ if (inStr) {
4099
+ if (ch === "\\") esc = true;
4100
+ else if (ch === '"') inStr = false;
4101
+ continue;
4102
+ }
4103
+ if (ch === '"') inStr = true;
4104
+ else if (ch === "{") depth++;
4105
+ else if (ch === "}") {
4106
+ depth--;
4107
+ if (depth === 0) {
4108
+ const candidate = cleaned.slice(firstBrace, i + 1);
4109
+ try {
4110
+ return JSON.parse(candidate);
4111
+ } catch {
4112
+ }
4113
+ try {
4114
+ return JSON.parse(jsonrepair.jsonrepair(candidate));
4115
+ } catch {
4116
+ }
4117
+ }
4118
+ }
4119
+ }
4120
+ try {
4121
+ return JSON.parse(jsonrepair.jsonrepair(cleaned));
4122
+ } catch {
4123
+ }
4124
+ return null;
4125
+ }
4019
4126
 
4020
4127
  // src/constants/pedagogy.ts
4021
4128
  var JUDGE_AUTO_APPROVE_THRESHOLD = 85;
4022
4129
 
4023
4130
  // src/ai/flows/auditCurriculumQualityFlow.ts
4131
+ var REPAIR_SUFFIX = "\n\nCRITICAL OUTPUT FORMAT FIX: your previous response could not be parsed as JSON. Output ONLY the raw JSON object \u2014 no markdown code fences, no prose before or after. Start with { and end with }.";
4132
+ function extractRawText(err) {
4133
+ const e = err;
4134
+ if (typeof e?.text === "string" && e.text) return e.text;
4135
+ const cause = e?.cause;
4136
+ if (typeof cause?.text === "string" && cause.text) return cause.text;
4137
+ const msg = typeof e?.message === "string" ? e.message : typeof cause?.message === "string" ? cause.message : "";
4138
+ const m = msg.match(/Text: ([\s\S]+)/);
4139
+ return m ? m[1] : "";
4140
+ }
4141
+ async function generateJudgeObject(opts) {
4142
+ let firstText = "";
4143
+ try {
4144
+ return (await ai.generateObject({ model: opts.model, schema: opts.schema, prompt: opts.prompt })).object;
4145
+ } catch (err) {
4146
+ firstText = extractRawText(err);
4147
+ if (firstText) {
4148
+ const salvaged = safeParseJson(firstText);
4149
+ if (salvaged) {
4150
+ const check = opts.schema.safeParse(salvaged);
4151
+ if (check.success) return check.data;
4152
+ }
4153
+ }
4154
+ try {
4155
+ return (await ai.generateObject({ model: opts.model, schema: opts.schema, prompt: opts.prompt + REPAIR_SUFFIX })).object;
4156
+ } catch (err2) {
4157
+ const secondText = extractRawText(err2);
4158
+ if (secondText && secondText !== firstText) {
4159
+ const salvaged2 = safeParseJson(secondText);
4160
+ if (salvaged2) {
4161
+ const check2 = opts.schema.safeParse(salvaged2);
4162
+ if (check2.success) return check2.data;
4163
+ }
4164
+ }
4165
+ throw err2;
4166
+ }
4167
+ }
4168
+ }
4024
4169
  async function auditCurriculumQualityFlow(input) {
4025
4170
  const model = getAIModel(input.modelOptions);
4026
4171
  const prompt = buildJudgePrompt({
@@ -4031,7 +4176,7 @@ async function auditCurriculumQualityFlow(input) {
4031
4176
  generatedContentJson: input.generatedContentJson,
4032
4177
  standardStatements: input.standardStatements
4033
4178
  });
4034
- const { object } = await ai.generateObject({
4179
+ const object = await generateJudgeObject({
4035
4180
  model,
4036
4181
  schema: CurriculumQualityReportSchema,
4037
4182
  prompt: `${prompt}
@@ -4048,7 +4193,7 @@ async function auditCurriculumPlanFlow(input) {
4048
4193
  expectedLanguage: input.expectedLanguage,
4049
4194
  linterFindings: input.linterFindings
4050
4195
  });
4051
- const { object } = await ai.generateObject({
4196
+ const object = await generateJudgeObject({
4052
4197
  model,
4053
4198
  schema: MacroPedagogyPlanAuditSchema,
4054
4199
  prompt: `${prompt}
@@ -4068,7 +4213,7 @@ async function auditProjectGraphFlow(input) {
4068
4213
  briefingContext: input.briefingContext,
4069
4214
  linterFindings: input.linterFindings
4070
4215
  });
4071
- const { object } = await ai.generateObject({
4216
+ const object = await generateJudgeObject({
4072
4217
  model,
4073
4218
  schema: ProjectGraphAuditSchema,
4074
4219
  prompt: `${prompt}