@willbooster/shared-lib 10.19.2 → 10.21.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.
@@ -1,4 +1,4 @@
1
- "use strict";const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
1
+ "use strict";const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
2
2
  - Start the body with \`Close #<n>\` only when the PR resolves an existing issue.\n${t}`,r=[{heading:`Problem`,requirement:`what happens, and what should happen instead`},{heading:`Evidence`,requirement:`reproduction steps, logs, run IDs, or links`},{heading:`Impact`,requirement:`who or what is affected, and how badly`},{heading:`Proposal`,requirement:`the fix you have in mind, and the root cause if known`}],i=[{heading:`Background and goal`,requirement:`the problem being solved, for whom, and what outcome counts as success`},{heading:`Behavior`,requirement:`every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing`},{heading:`Acceptance criteria`,requirement:`checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done`},{heading:`Scope and non-goals`,requirement:`what the change covers and what it deliberately leaves out, so an implementer knows where to stop`},{heading:`Design constraints`,requirement:`the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer`},{heading:`Compatibility and migration`,requirement:`what existing data, users, callers, or configurations are affected and how the transition happens`},{heading:`Verification`,requirement:`how the change is tested or demonstrated, including what needs no test and why`},{heading:`Open questions`,requirement:`undecided points, each with its options; empty once the specification is implementable`}];function a(e){return e.map(e=>`- **${e.heading}**: ${e.requirement}`).join(`
3
3
  `)}function o(e){return e.map(e=>`## ${e.heading}\n\n<!-- ${e.requirement.charAt(0).toUpperCase()}${e.requirement.slice(1)}. -->`).join(`
4
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"githubTemplates.cjs","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (a \\`required\\` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a \\`chosen\\` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a \\`required: not recorded\\` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"aAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,y0DAMlCC,EAA0B;qFAAmCD,IAa7DE,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
1
+ {"version":3,"file":"githubTemplates.cjs","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (\\`required\\` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a \\`required: not recorded\\` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"aAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,ujDAMlCC,EAA0B;qFAAmCD,IAa7DE,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
@@ -15,9 +15,9 @@ export declare const PULL_REQUEST_SECTIONS: readonly TemplateSection[];
15
15
  * bodies render this text instead of restating it, so the writers and the reviewers that read the
16
16
  * section as the boundary a fix must keep never disagree on what a line means.
17
17
  */
18
- export declare const PULL_REQUEST_REQUIREMENTS_RULES = "- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
18
+ export declare const PULL_REQUEST_REQUIREMENTS_RULES = "- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
19
19
  /** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */
20
- export declare const PULL_REQUEST_BODY_RULES = "- Base the PR body on `.github/pull_request_template.md` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with `Close #<n>` only when the PR resolves an existing issue.\n- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
20
+ export declare const PULL_REQUEST_BODY_RULES = "- Base the PR body on `.github/pull_request_template.md` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with `Close #<n>` only when the PR resolves an existing issue.\n- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
21
21
  /**
22
22
  * How a tool that creates an issue derives it from the repository's issue templates, as markdown
23
23
  * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.
@@ -1,4 +1,4 @@
1
- const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
1
+ const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
2
2
  - Start the body with \`Close #<n>\` only when the PR resolves an existing issue.\n${t}`,r="- Follow the closest template under `.github/ISSUE_TEMPLATE/`: `bug.md` for wrong behavior, `change.md` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`, ...); when it differs from the template's `title` prefix, replace the template's type label (`t: ...`) with the one matching the type.\n- The YAML front matter between the `---` lines is metadata, not body text: pass its `labels` via `--label` and submit only the content below the closing `---` as the body.",i=[{heading:`Problem`,requirement:`what happens, and what should happen instead`},{heading:`Evidence`,requirement:`reproduction steps, logs, run IDs, or links`},{heading:`Impact`,requirement:`who or what is affected, and how badly`},{heading:`Proposal`,requirement:`the fix you have in mind, and the root cause if known`}],a=[{heading:`Background and goal`,requirement:`the problem being solved, for whom, and what outcome counts as success`},{heading:`Behavior`,requirement:`every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing`},{heading:`Acceptance criteria`,requirement:`checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done`},{heading:`Scope and non-goals`,requirement:`what the change covers and what it deliberately leaves out, so an implementer knows where to stop`},{heading:`Design constraints`,requirement:`the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer`},{heading:`Compatibility and migration`,requirement:`what existing data, users, callers, or configurations are affected and how the transition happens`},{heading:`Verification`,requirement:`how the change is tested or demonstrated, including what needs no test and why`},{heading:`Open questions`,requirement:`undecided points, each with its options; empty once the specification is implementable`}];function o(e){return e.map(e=>`- **${e.heading}**: ${e.requirement}`).join(`
3
3
  `)}function s(e){return e.map(e=>`## ${e.heading}\n\n<!-- ${e.requirement.charAt(0).toUpperCase()}${e.requirement.slice(1)}. -->`).join(`
4
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"githubTemplates.js","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","ISSUE_TEMPLATE_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (a \\`required\\` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a \\`chosen\\` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a \\`required: not recorded\\` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"AAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,y0DAMlCC,EAA0B;qFAAmCD,IAQ7DE,EAAuB,qpBAKvBC,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
1
+ {"version":3,"file":"githubTemplates.js","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","ISSUE_TEMPLATE_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (\\`required\\` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a \\`required: not recorded\\` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"AAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,ujDAMlCC,EAA0B;qFAAmCD,IAQ7DE,EAAuB,qpBAKvBC,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
@@ -1,2 +1,2 @@
1
- "use strict";function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e){if(a===`"`&&!i){r=!r;continue}if(a===`'`&&!r){i=!i;continue}if(a===` `&&!r&&!i){n&&=(t.push(n),``);continue}n+=a}return n&&t.push(n),t}exports.parseCommandLineArgs=e;
1
+ "use strict";function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e)a===`"`&&!i?r=!r:a===`'`&&!r?i=!i:a===` `&&!r&&!i?n&&=(t.push(n),``):n+=a;return n&&t.push(n),t}exports.parseCommandLineArgs=e;
2
2
  //# sourceMappingURL=parseCommandLineArgs.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.cjs","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.cjs","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EACbK,IAAS,KAAO,CAACD,EACnB,EAAgB,CAACD,EAIfE,IAAS,KAAO,CAACF,EACnB,EAAgB,CAACC,EAIfC,IAAS,KAAO,CAACF,GAAiB,CAACC,EACrC,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAKd,GAAWG,EAOb,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1,2 +1,2 @@
1
- function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e){if(a===`"`&&!i){r=!r;continue}if(a===`'`&&!r){i=!i;continue}if(a===` `&&!r&&!i){n&&=(t.push(n),``);continue}n+=a}return n&&t.push(n),t}export{e as parseCommandLineArgs};
1
+ function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e)a===`"`&&!i?r=!r:a===`'`&&!r?i=!i:a===` `&&!r&&!i?n&&=(t.push(n),``):n+=a;return n&&t.push(n),t}export{e as parseCommandLineArgs};
2
2
  //# sourceMappingURL=parseCommandLineArgs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.js","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.js","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EACbK,IAAS,KAAO,CAACD,EACnB,EAAgB,CAACD,EAIfE,IAAS,KAAO,CAACF,EACnB,EAAgB,CAACC,EAIfC,IAAS,KAAO,CAACF,GAAiB,CAACC,EACrC,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAKd,GAAWG,EAOb,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1,4 +1,4 @@
1
1
  "use strict";const e=require("./error.cjs"),t=1e6,n={'"':`"`,"'":`'`,"“":`”`,"”":`”`,"‘":`’`,"’":`’`},r={"{":`}`,"[":`]`},i={true:`true`,false:`false`,null:`null`,True:`true`,False:`false`,None:`null`}
2
2
  /*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */
3
- ;function a(e){let n={candidates:[],errors:[]};if(e.length>t)return n.errors.push({offset:t,message:`JSON recovery input exceeds one million characters`}),n;let r=o(e),i=0;for(let t of r)t.index>=i&&(i=s(e,r,t,i,n));if(c(e,i,e.length,n),n.candidates.length===32){let e={offset:n.candidates.at(-1).end,message:`JSON candidate limit reached; extraction may be incomplete`};n.errors.length===32?n.errors[31]=e:n.errors.push(e)}return n}function o(e){return[...e.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(t=>{let n=t[1],r=t.index+t[0].indexOf(n)+n.length,i=t.index+t[0].length,a=e.slice(r,i),o=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(a),s=o===null?i:r+o[0].length,c=u(e[s])||d(e,s,i)?s:i;return n[0]==="`"&&c===i&&a.includes("`")?[]:[{index:t.index,marker:n,start:c}]})}function s(e,t,n,r,i){c(e,r,n.index,i);let a=i.candidates.at(-1)?.end??r;if(a>n.index)return a;let{marker:o,start:s}=n,l=RegExp(`^ {0,3}${o[0]}{${o.length},}[ \\t]*$`,`gm`);l.lastIndex=s;let u=l.exec(e),d=u?.index??e.length;c(e,s,d,i);let f=i.candidates.at(-1)?.end??s;if(f>d){l.lastIndex=f;let n=l.exec(e);if(n!==null&&!t.some(e=>e.index>=f&&e.index<n.index))return c(e,f,n.index,i),n.index+n[0].length}return Math.max(i.candidates.at(-1)?.end??s,u===null?e.length:u.index+u[0].length)}function c(e,t,n,r,i=!1){r.candidates.length<32&&new l(e,t,n,r,i).run()}var l=class{text;start;end;result;commentFragment;index;failures=0;ambiguousScalarTail=!1;scalarBoundary=!0;uriBoundaryEnd;uriTokenEnd;uriContainerStart;constructor(e,t,n,r,i){this.text=e,this.start=t,this.end=n,this.result=r,this.commentFragment=i,this.index=t,this.uriBoundaryEnd=t,this.uriTokenEnd=t,this.uriContainerStart=t}run(){let{text:e,end:t,result:n}=this;for(;this.index<t&&/\s/.test(e[this.index]);)this.index++;let r=this.index,i=new f(e,this.index,t);this.commentFragment||i.space();let a=i.index;if(a>=t){i.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(this.index,`Incomplete leading JSON comment`);return}let o=d(e,a,t)||u(e[a]);for(o||(this.index=a);this.index<t&&n.candidates.length<32&&this.failures<32;){let a=o&&this.index===r;if(a||this.skipProse(),this.index>=t||n.candidates.length>=32)break;this.extractCandidate(a?i:new f(e,this.index,t))}}skipProse(){let{text:e,end:t}=this;for(;this.index<t&&!u(e[this.index])&&!(this.scalarBoundary&&d(e,this.index,t));)this.skipUri()||this.skipCommentLikeSpan()||(/[\r\n]/.test(e[this.index])?this.scalarBoundary=!0:/[\s,]/.test(e[this.index])||(this.scalarBoundary=!1),this.index++)}skipUri(){let{text:e,end:t,index:n}=this;if(n!==this.start&&/[\w+.-]/.test(e[n-1]))return!1;let r=p(e,n,t);if(r===void 0)return!1;if(n>=this.uriTokenEnd){let r=e.slice(n,t).search(/\s/);this.uriTokenEnd=r===-1?t:n+r,this.uriContainerStart=n}if(n>=this.uriContainerStart){let t=e.slice(n,this.uriTokenEnd).search(/[{[]/);this.uriContainerStart=t===-1?this.uriTokenEnd:n+t}return this.uriContainerStart<this.uriTokenEnd&&(this.uriBoundaryEnd=Math.max(this.uriBoundaryEnd,this.uriTokenEnd)),this.index=Math.min(r,this.uriContainerStart),this.scalarBoundary=!1,!0}skipCommentLikeSpan(){let{text:e,end:t,index:n}=this;if(this.commentFragment||e[n]!==`/`)return!1;let r=new f(e,n,t);return r.space(),r.index<=n?!1:(r.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(n,`Possibly unterminated comment-like span in prose`),c(e,n+2,r.index,this.result,!0),this.scalarBoundary||=/[\r\n]/.test(e.slice(n,r.index)),this.index=r.index,!0)}extractCandidate(t){let{text:r,end:i,index:a}=this,o=t.index,s=t;try{let e=t.value(0),c=this.parsePastRegionEnd(t,o);s=c?.parser??t;let l=c?.json??e,d=s.index;if(!u(r[o])&&!s.finishScalar(i,o)){this.scalarBoundary=!1,this.index=d;return}s.space(),this.consumeSurplusClosers(s),r[o]in n&&s.hasRepair(`trailing-scalar-content`)&&this.reportExcerpt(d,`Ambiguous quoted-scalar tail`),this.markFragmentProvenance(s),this.ambiguousScalarTail||=s.hasRepair(`trailing-scalar-content`),this.result.candidates.push({value:JSON.parse(l),json:l,start:a,end:s.index,repairs:s.repairs,requiresConfirmation:s.repairs.some(e=>e.kind!==`syntax`)})}catch(t){this.reportError(s.index,e.getErrorMessage(t)),this.failures++,this.index=o+1,this.scalarBoundary=!1;return}this.index=Math.max(a+1,s.index),this.scalarBoundary=!0}parsePastRegionEnd(e,t){let{text:n,end:r}=this;if(this.commentFragment||!u(n[t])||e.index!==r||r>=n.length)return;let i=new f(n,this.index,n.length);try{let e=i.value(0);if(i.index>r&&i.repairs.every(e=>e.reason===`unescaped-control-character`))return i.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),{parser:i,json:e}}catch{}}consumeSurplusClosers(e){if(this.commentFragment||this.failures>0)return;let t=e.index;for(;e.index<this.end&&/[}\]]/.test(this.text[e.index]);)e.repairs.push({offset:e.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),e.index++,e.space();e.index>t&&this.reportExcerpt(t,`Surplus closing brackets and possible continuation`)}markFragmentProvenance(e){let t=t=>{e.repairs.unshift({offset:this.index,kind:`ambiguous`,reason:t})};this.commentFragment&&t(`fragment-in-comment-like-prose`),this.failures>0&&t(`fragment-after-rejected-document`),this.ambiguousScalarTail&&t(`fragment-after-ambiguous-scalar`),this.index<this.uriBoundaryEnd&&t(`ambiguous-uri-boundary`)}reportExcerpt(e,t){let n=Math.min(this.end,e+256),r=JSON.stringify(this.text.slice(e,n));this.reportError(e,`${t} (${n<this.end?`truncated excerpt`:`excerpt`}): ${r}`)}reportError(e,t){this.result.errors.length<32&&this.result.errors.push({offset:e,message:t})}};function u(e){return e===`{`||e===`[`}function d(e,t,r){let a=e[t];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(t,r))?.[1];return a in n||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(i,o)||Object.keys(i).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(t+o.length,r)))}var f=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,t){let r=this.index,i=this.text.slice(t,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[t]in n||this.hasRepair(`unquoted-value`);return this.space(),a?!1:this.index>=e?!0:/[\r\n]/.test(this.text.slice(r,this.index))?(this.repair(`ambiguous`,`scalar-before-prose`,r),!0):/^\d+[.)]$/.test(i)&&/[ \t]/.test(this.text[r]??``)?!1:o||/^[\p{P}\p{S}]/u.test(this.text.slice(this.index,e))?(this.repair(`ambiguous`,`trailing-scalar-content`,r),!0):!1}value(e){if(e>128)throw Error(`JSON nesting exceeds 128 levels`);this.space();let t=this.text[this.index];if(this.index>=this.end||t===`,`||t===`}`||t===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(u(t)){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,t)}if(t!==void 0&&t in n)return this.string(e>0?`value`:`root`);let r=this.index,a=p(this.text,r,this.end);if(a!==void 0)this.index=a;else for(;this.index<this.end&&!/[\s,}\]]/.test(this.text[this.index])&&!(e===0&&/[{[]/.test(this.text[this.index]))&&!this.comment();)this.index++;if(this.index===r)throw Error(`Expected a JSON value`);let o=this.text.slice(r,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(i,o)){let e=i[o];return e!==o&&this.repair(`syntax`,`python-keyword`,r),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,r),JSON.stringify(o)}container(e,t){this.index++;let n=t===`{`,i=r[t],a=[],o=/* @__PURE__ */ new Set,s=!1,c=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===i)return this.index>=this.end?this.repair(`incomplete`,`missing-${i}`):this.index++,s&&this.repair(`syntax`,`trailing-comma`,c),t+a.join(`,`)+i;if(this.text[this.index]===`}`||this.text[this.index]===`]`)throw Error(`Mismatched closing bracket`);if(this.text[this.index]===`,`){n?this.repair(`ambiguous`,`extra-comma`):(a.push(`null`),this.repair(`incomplete`,`missing-value`)),c=this.index,s=!0,this.index++;continue}a.push(n?`${this.key(o)}:${this.value(e+1)}`:this.value(e+1)),this.space(),s=this.text[this.index]===`,`,s?(c=this.index,this.index++):this.index<this.end&&this.text[this.index]!==i&&this.repair(`syntax`,`missing-comma`)}}key(e){let t=this.index,r=this.text[t]in n?this.string():this.unquotedKey(),i=JSON.parse(r);return e.has(i)&&this.repair(`ambiguous`,`duplicate-key`,t),e.add(i),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`),r}unquotedKey(){let e=this.index;for(;this.index<this.end&&!/[\s:,{}[\]]/.test(this.text[this.index])&&!this.comment();)this.index++;if(this.index===e)throw Error(`Expected an object key`);let t=this.text.slice(e,this.index);return this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e),JSON.stringify(t)}string(e=`key`){let t=this.index,r=this.text[this.index++],i=n[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,t);let a=``,o=``,s=e=>{a+=e,o=(o+e).slice(-2)},c=!1,l=`"“”`.includes(r)?`"“”`:`'‘’`,u;for(;this.index<this.end;){let t=this.text[this.index++];if(`'‘’`.includes(r)&&`'’`.includes(t)&&/[\p{L}\p{N}]$/u.test(o)&&/^[\p{L}\p{N}]/u.test(this.text.slice(this.index,this.end))){this.repair(`ambiguous`,`literal-apostrophe`,this.index-1),s(t);continue}if(l.includes(t)){let n=this.charAfterSpace(this.index),r=n===void 0||/[,}\]:"']/.test(n);if(t!==i)r&&(u??={end:this.index,value:a,repairCount:this.repairs.length});else if(!c&&e!==`root`&&u!==void 0&&!r)return this.index=u.end,this.repairs.length=u.repairCount,this.repair(`ambiguous`,`mismatched-quote`,this.index-1),JSON.stringify(u.value);else if(c||e===`value`&&!r&&this.opensEmbeddedQuote(i))c=!c,this.repair(`ambiguous`,`unescaped-quote`,this.index-1);else return JSON.stringify(a)}t===`\\`?s(this.escapeSequence(r)):(t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t))}return this.repair(`incomplete`,`unterminated-string`,t),JSON.stringify(a)}opensEmbeddedQuote(e){let t=this.text.indexOf(e,this.index),n=this.charAfterSpace(t+1);return!/\s/.test(this.text[this.index]??``)&&t>this.index&&t<this.end&&n!==void 0&&(!/[,}:\]]/.test(n)||n===`,`&&this.continuesStringAfterComma(t+1,e))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,t))&&!this.startsKey(t)}escapeSequence(e){let t=this.index-1;if(this.index>=this.end)return this.repair(`incomplete`,`truncated-escape`,t),`\\`;let n=this.text[this.index++];if(n===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));return/^[\da-fA-F]{4}$/.test(e)?(this.index+=4,String.fromCodePoint(Number.parseInt(e,16))):(this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,t),String.raw`\u`)}return String.raw`"\/bfnrt`.includes(n)?JSON.parse(`"\\${n}"`):n===`'`&&e===`'`?`'`:(this.repair(`ambiguous`,`invalid-escape`,t),`\\${n}`)}continuesStringAfterComma(t,n){let r=new e(this.text,t-1,this.end);r.string();let i=r.index-1;if(this.text[i]!==n||r.repairs.some(e=>![`non-json-quote`,`literal-apostrophe`,`unescaped-control-character`].includes(e.reason)))return!1;let a=this.text.slice(t,i),o=this.charAfterSpace(i+1);return/^\s*,\s*[\p{L}\p{N}]/u.test(a)&&!/[\\:{}[\]]/.test(a)&&(o===void 0||/[,}\]]/.test(o))}startsKey(t){let n=new e(this.text,t,this.end);return n.string(),n.space(),this.text[n.index]===`:`}space(){for(;this.index<this.end;)if(/\s/.test(this.text[this.index]))/[ \t\r\n]/.test(this.text[this.index])||this.repair(`syntax`,`non-json-whitespace`),this.index++;else if(this.text.startsWith(`//`,this.index))for(this.repair(`syntax`,`line-comment`);this.index<this.end&&!/[\r\n]/.test(this.text[this.index]);)this.index++;else if(this.text.startsWith(`/*`,this.index)){let e=this.text.indexOf(`*/`,this.index+2);this.repair(e===-1||e>=this.end?`incomplete`:`syntax`,`block-comment`),this.index=e===-1||e>=this.end?this.end:e+2}else break}hasRepair(e){return this.repairs.some(t=>t.reason===e)}charAfterSpace(e){return this.text.slice(e,this.end).trimStart()[0]}repair(e,t,n=this.index){this.repairs.push({offset:n,kind:e,reason:t})}comment(){return this.text.startsWith(`//`,this.index)||this.text.startsWith(`/*`,this.index)}};function p(e,t,n){let r=/^[A-Za-z][A-Za-z\d+.-]*:\/\//.exec(e.slice(t,n));if(r===null)return;let i=t+r[0].length,a=0;for(;i<n&&!/[\s}]/.test(e[i])&&(e[i]!==`,`||a!==0);){if(e[i]===`[`)a++;else if(e[i]===`]`){if(a===0)break;a--}i++}return i}exports.recoverJson=a;
3
+ ;function a(e){let n={candidates:[],errors:[]};if(e.length>t)return n.errors.push({offset:t,message:`JSON recovery input exceeds one million characters`}),n;let r=o(e),i=0;for(let t of r)t.index>=i&&(i=s(e,r,t,i,n));if(c(e,i,e.length,n),n.candidates.length===32){let e={offset:n.candidates.at(-1).end,message:`JSON candidate limit reached; extraction may be incomplete`};n.errors.length===32?n.errors[31]=e:n.errors.push(e)}return n}function o(e){return[...e.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(t=>{let n=t[1],r=t.index+t[0].indexOf(n)+n.length,i=t.index+t[0].length,a=e.slice(r,i),o=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(a),s=o===null?i:r+o[0].length,c=u(e[s])||d(e,s,i)?s:i;return n[0]==="`"&&c===i&&a.includes("`")?[]:[{index:t.index,marker:n,start:c}]})}function s(e,t,n,r,i){c(e,r,n.index,i);let a=i.candidates.at(-1)?.end??r;if(a>n.index)return a;let{marker:o,start:s}=n,l=RegExp(`^ {0,3}${o[0]}{${o.length},}[ \\t]*$`,`gm`);l.lastIndex=s;let u=l.exec(e),d=u?.index??e.length;c(e,s,d,i);let f=i.candidates.at(-1)?.end??s;if(f>d){l.lastIndex=f;let n=l.exec(e);if(n!==null&&!t.some(e=>e.index>=f&&e.index<n.index))return c(e,f,n.index,i),n.index+n[0].length}return Math.max(i.candidates.at(-1)?.end??s,u===null?e.length:u.index+u[0].length)}function c(e,t,n,r,i=!1){r.candidates.length<32&&new l(e,t,n,r,i).run()}var l=class{text;start;end;result;commentFragment;index;failures=0;ambiguousScalarTail=!1;scalarBoundary=!0;uriBoundaryEnd;uriTokenEnd;uriContainerStart;constructor(e,t,n,r,i){this.text=e,this.start=t,this.end=n,this.result=r,this.commentFragment=i,this.index=t,this.uriBoundaryEnd=t,this.uriTokenEnd=t,this.uriContainerStart=t}run(){let{text:e,end:t,result:n}=this;for(;this.index<t&&/\s/.test(e[this.index]);)this.index++;let r=this.index,i=new f(e,this.index,t);this.commentFragment||i.space();let a=i.index;if(a>=t){i.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(this.index,`Incomplete leading JSON comment`);return}let o=d(e,a,t)||u(e[a]);for(o||(this.index=a);this.index<t&&n.candidates.length<32&&this.failures<32;){let a=o&&this.index===r;if(a||this.skipProse(),this.index>=t||n.candidates.length>=32)break;this.extractCandidate(a?i:new f(e,this.index,t))}}skipProse(){let{text:e,end:t}=this;for(;this.index<t&&!u(e[this.index])&&!(this.scalarBoundary&&d(e,this.index,t));)this.skipUri()||this.skipCommentLikeSpan()||(/[\r\n]/.test(e[this.index])?this.scalarBoundary=!0:/[\s,]/.test(e[this.index])||(this.scalarBoundary=!1),this.index++)}skipUri(){let{text:e,end:t,index:n}=this;if(n!==this.start&&/[\w+.-]/.test(e[n-1]))return!1;let r=p(e,n,t);if(r===void 0)return!1;if(n>=this.uriTokenEnd){let r=e.slice(n,t).search(/\s/);this.uriTokenEnd=r===-1?t:n+r,this.uriContainerStart=n}if(n>=this.uriContainerStart){let t=e.slice(n,this.uriTokenEnd).search(/[{[]/);this.uriContainerStart=t===-1?this.uriTokenEnd:n+t}return this.uriContainerStart<this.uriTokenEnd&&(this.uriBoundaryEnd=Math.max(this.uriBoundaryEnd,this.uriTokenEnd)),this.index=Math.min(r,this.uriContainerStart),this.scalarBoundary=!1,!0}skipCommentLikeSpan(){let{text:e,end:t,index:n}=this;if(this.commentFragment||e[n]!==`/`)return!1;let r=new f(e,n,t);return r.space(),r.index<=n?!1:(r.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(n,`Possibly unterminated comment-like span in prose`),c(e,n+2,r.index,this.result,!0),this.scalarBoundary||=/[\r\n]/.test(e.slice(n,r.index)),this.index=r.index,!0)}extractCandidate(t){let{text:r,end:i,index:a}=this,o=t.index,s=t;try{let e=t.value(0),c=this.parsePastRegionEnd(t,o);s=c?.parser??t;let l=c?.json??e,d=s.index;if(!u(r[o])&&!s.finishScalar(i,o)){this.scalarBoundary=!1,this.index=d;return}s.space(),this.consumeSurplusClosers(s),r[o]in n&&s.hasRepair(`trailing-scalar-content`)&&this.reportExcerpt(d,`Ambiguous quoted-scalar tail`),this.markFragmentProvenance(s),this.ambiguousScalarTail||=s.hasRepair(`trailing-scalar-content`),this.result.candidates.push({value:JSON.parse(l),json:l,start:a,end:s.index,repairs:s.repairs,requiresConfirmation:s.repairs.some(e=>e.kind!==`syntax`)})}catch(t){this.reportError(s.index,e.getErrorMessage(t)),this.failures++,this.index=o+1,this.scalarBoundary=!1;return}this.index=Math.max(a+1,s.index),this.scalarBoundary=!0}parsePastRegionEnd(e,t){let{text:n,end:r}=this;if(this.commentFragment||!u(n[t])||e.index!==r||r>=n.length)return;let i=new f(n,this.index,n.length);try{let e=i.value(0);if(i.index>r&&i.repairs.every(e=>e.reason===`unescaped-control-character`))return i.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),{parser:i,json:e}}catch{}}consumeSurplusClosers(e){if(this.commentFragment||this.failures>0)return;let t=e.index;for(;e.index<this.end&&/[}\]]/.test(this.text[e.index]);)e.repairs.push({offset:e.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),e.index++,e.space();e.index>t&&this.reportExcerpt(t,`Surplus closing brackets and possible continuation`)}markFragmentProvenance(e){let t=t=>{e.repairs.unshift({offset:this.index,kind:`ambiguous`,reason:t})};this.commentFragment&&t(`fragment-in-comment-like-prose`),this.failures>0&&t(`fragment-after-rejected-document`),this.ambiguousScalarTail&&t(`fragment-after-ambiguous-scalar`),this.index<this.uriBoundaryEnd&&t(`ambiguous-uri-boundary`)}reportExcerpt(e,t){let n=Math.min(this.end,e+256),r=JSON.stringify(this.text.slice(e,n));this.reportError(e,`${t} (${n<this.end?`truncated excerpt`:`excerpt`}): ${r}`)}reportError(e,t){this.result.errors.length<32&&this.result.errors.push({offset:e,message:t})}};function u(e){return e===`{`||e===`[`}function d(e,t,r){let a=e[t];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(t,r))?.[1];return a in n||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(i,o)||Object.keys(i).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(t+o.length,r)))}var f=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,t){let r=this.index,i=this.text.slice(t,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[t]in n||this.hasRepair(`unquoted-value`);return this.space(),a?!1:this.index>=e?!0:/[\r\n]/.test(this.text.slice(r,this.index))?(this.repair(`ambiguous`,`scalar-before-prose`,r),!0):/^\d+[.)]$/.test(i)&&/[ \t]/.test(this.text[r]??``)?!1:o||/^[\p{P}\p{S}]/u.test(this.text.slice(this.index,e))?(this.repair(`ambiguous`,`trailing-scalar-content`,r),!0):!1}value(e){if(e>128)throw Error(`JSON nesting exceeds 128 levels`);this.space();let t=this.text[this.index];if(this.index>=this.end||t===`,`||t===`}`||t===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(u(t)){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,t)}if(t!==void 0&&t in n)return this.string(e>0?`value`:`root`);let r=this.index,a=p(this.text,r,this.end);if(a!==void 0)this.index=a;else for(;this.index<this.end&&!/[\s,}\]]/.test(this.text[this.index])&&!(e===0&&/[{[]/.test(this.text[this.index]))&&!this.comment();)this.index++;if(this.index===r)throw Error(`Expected a JSON value`);let o=this.text.slice(r,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(i,o)){let e=i[o];return e!==o&&this.repair(`syntax`,`python-keyword`,r),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,r),JSON.stringify(o)}container(e,t){this.index++;let n=t===`{`,i=r[t],a=[],o=/* @__PURE__ */ new Set,s=!1,c=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===i)return this.index>=this.end?this.repair(`incomplete`,`missing-${i}`):this.index++,s&&this.repair(`syntax`,`trailing-comma`,c),t+a.join(`,`)+i;if(this.text[this.index]===`}`||this.text[this.index]===`]`)throw Error(`Mismatched closing bracket`);this.text[this.index]===`,`?(n?this.repair(`ambiguous`,`extra-comma`):(a.push(`null`),this.repair(`incomplete`,`missing-value`)),c=this.index,s=!0,this.index++):(a.push(n?`${this.key(o)}:${this.value(e+1)}`:this.value(e+1)),this.space(),s=this.text[this.index]===`,`,s?(c=this.index,this.index++):this.index<this.end&&this.text[this.index]!==i&&this.repair(`syntax`,`missing-comma`))}}key(e){let t=this.index,r=this.text[t]in n?this.string():this.unquotedKey(),i=JSON.parse(r);return e.has(i)&&this.repair(`ambiguous`,`duplicate-key`,t),e.add(i),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`),r}unquotedKey(){let e=this.index;for(;this.index<this.end&&!/[\s:,{}[\]]/.test(this.text[this.index])&&!this.comment();)this.index++;if(this.index===e)throw Error(`Expected an object key`);let t=this.text.slice(e,this.index);return this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e),JSON.stringify(t)}string(e=`key`){let t=this.index,r=this.text[this.index++],i=n[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,t);let a=``,o=``,s=e=>{a+=e,o=(o+e).slice(-2)},c=!1,l=`"“”`.includes(r)?`"“”`:`'‘’`,u;for(;this.index<this.end;){let t=this.text[this.index++];if(`'‘’`.includes(r)&&`'’`.includes(t)&&/[\p{L}\p{N}]$/u.test(o)&&/^[\p{L}\p{N}]/u.test(this.text.slice(this.index,this.end)))this.repair(`ambiguous`,`literal-apostrophe`,this.index-1),s(t);else{if(l.includes(t)){let n=this.charAfterSpace(this.index),r=n===void 0||/[,}\]:"']/.test(n);if(t!==i)r&&(u??={end:this.index,value:a,repairCount:this.repairs.length});else if(!c&&e!==`root`&&u!==void 0&&!r)return this.index=u.end,this.repairs.length=u.repairCount,this.repair(`ambiguous`,`mismatched-quote`,this.index-1),JSON.stringify(u.value);else if(c||e===`value`&&!r&&this.opensEmbeddedQuote(i))c=!c,this.repair(`ambiguous`,`unescaped-quote`,this.index-1);else return JSON.stringify(a)}t===`\\`?s(this.escapeSequence(r)):(t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t))}}return this.repair(`incomplete`,`unterminated-string`,t),JSON.stringify(a)}opensEmbeddedQuote(e){let t=this.text.indexOf(e,this.index),n=this.charAfterSpace(t+1);return!/\s/.test(this.text[this.index]??``)&&t>this.index&&t<this.end&&n!==void 0&&(!/[,}:\]]/.test(n)||n===`,`&&this.continuesStringAfterComma(t+1,e))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,t))&&!this.startsKey(t)}escapeSequence(e){let t=this.index-1;if(this.index>=this.end)return this.repair(`incomplete`,`truncated-escape`,t),`\\`;let n=this.text[this.index++];if(n===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));return/^[\da-fA-F]{4}$/.test(e)?(this.index+=4,String.fromCodePoint(Number.parseInt(e,16))):(this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,t),String.raw`\u`)}return String.raw`"\/bfnrt`.includes(n)?JSON.parse(`"\\${n}"`):n===`'`&&e===`'`?`'`:(this.repair(`ambiguous`,`invalid-escape`,t),`\\${n}`)}continuesStringAfterComma(t,n){let r=new e(this.text,t-1,this.end);r.string();let i=r.index-1;if(this.text[i]!==n||r.repairs.some(e=>![`non-json-quote`,`literal-apostrophe`,`unescaped-control-character`].includes(e.reason)))return!1;let a=this.text.slice(t,i),o=this.charAfterSpace(i+1);return/^\s*,\s*[\p{L}\p{N}]/u.test(a)&&!/[\\:{}[\]]/.test(a)&&(o===void 0||/[,}\]]/.test(o))}startsKey(t){let n=new e(this.text,t,this.end);return n.string(),n.space(),this.text[n.index]===`:`}space(){for(;this.index<this.end;)if(/\s/.test(this.text[this.index]))/[ \t\r\n]/.test(this.text[this.index])||this.repair(`syntax`,`non-json-whitespace`),this.index++;else if(this.text.startsWith(`//`,this.index))for(this.repair(`syntax`,`line-comment`);this.index<this.end&&!/[\r\n]/.test(this.text[this.index]);)this.index++;else if(this.text.startsWith(`/*`,this.index)){let e=this.text.indexOf(`*/`,this.index+2);this.repair(e===-1||e>=this.end?`incomplete`:`syntax`,`block-comment`),this.index=e===-1||e>=this.end?this.end:e+2}else break}hasRepair(e){return this.repairs.some(t=>t.reason===e)}charAfterSpace(e){return this.text.slice(e,this.end).trimStart()[0]}repair(e,t,n=this.index){this.repairs.push({offset:n,kind:e,reason:t})}comment(){return this.text.startsWith(`//`,this.index)||this.text.startsWith(`/*`,this.index)}};function p(e,t,n){let r=/^[A-Za-z][A-Za-z\d+.-]*:\/\//.exec(e.slice(t,n));if(r===null)return;let i=t+r[0].length,a=0;for(;i<n&&!/[\s}]/.test(e[i])&&(e[i]!==`,`||a!==0);){if(e[i]===`[`)a++;else if(e[i]===`]`){if(a===0)break;a--}i++}return i}exports.recoverJson=a;
4
4
  //# sourceMappingURL=recoverJson.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"recoverJson.cjs","names":["getErrorMessage","require_error","MAX_INPUT_LENGTH","QUOTES","CLOSERS","KEYWORDS","recoverJson","result","text","fences","findFences","consumed","fence","extractThroughFence","extractRegion","error","marker","markerEnd","lineEnd","info","inlinePrefix","inlineStart","start","isContainerStart","scalarStart","parsedThrough","close","match","end","extendedEnd","outerClose","next","RegionExtractor","commentFragment","firstIndex","initialParser","RecoveryParser","initialValueStart","repair","initialValue","atInitialValue","index","uriEnd","unquotedUriEnd","whitespace","container","trivia","valueStart","bounded","parser","boundedJson","extended","json","valueEnd","surplusStart","mark","excerptEnd","offset","excerpt","summary","char","first","keyword","word","atom","bullet","retainLiteral","regionEnd","depth","token","canonical","object","open","items","keys","afterComma","commaOffset","key","decoded","seen","rawKey","value","tail","append","embeddedQuote","family","alternative","after","delimited","context","nextClose","afterNext","escapeOffset","escape","hex","quote","continuation","reason","brackets"],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nimport { getErrorMessage } from './error.js';\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst CLOSERS = { '{': '}', '[': ']' } as const;\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = findFences(text);\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index >= consumed) consumed = extractThroughFence(text, fences, fence, consumed, result);\n }\n extractRegion(text, consumed, text.length, result);\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\ninterface Fence {\n index: number;\n marker: string;\n /** Where the fenced content starts: after the opening line, or within it when JSON follows the info string. */\n start: number;\n}\n\nfunction findFences(text: string): Fence[] {\n return [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n isContainerStart(text[inlineStart]) || scalarStart(text, inlineStart, lineEnd) ? inlineStart : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n}\n\n/** Extracts the prose before `fence` and then its content, returning the offset up to which the text is consumed. */\nfunction extractThroughFence(\n text: string,\n fences: Fence[],\n fence: Fence,\n consumed: number,\n result: JsonRecovery\n): number {\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) return parsedThrough;\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n return outerClose.index + outerClose[0].length;\n }\n }\n return Math.max(result.candidates.at(-1)?.end ?? start, match === null ? text.length : match.index + match[0].length);\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length < MAX_CANDIDATES) new RegionExtractor(text, start, end, result, commentFragment).run();\n}\n\nclass RegionExtractor {\n private readonly text: string;\n private readonly start: number;\n private readonly end: number;\n private readonly result: JsonRecovery;\n private readonly commentFragment: boolean;\n private index: number;\n private failures = 0;\n private ambiguousScalarTail = false;\n private scalarBoundary = true;\n private uriBoundaryEnd: number;\n private uriTokenEnd: number;\n private uriContainerStart: number;\n\n constructor(text: string, start: number, end: number, result: JsonRecovery, commentFragment: boolean) {\n this.text = text;\n this.start = start;\n this.end = end;\n this.result = result;\n this.commentFragment = commentFragment;\n this.index = start;\n this.uriBoundaryEnd = start;\n this.uriTokenEnd = start;\n this.uriContainerStart = start;\n }\n\n run(): void {\n const { text, end, result } = this;\n while (this.index < end && /\\s/.test(text[this.index]!)) this.index++;\n const firstIndex = this.index;\n const initialParser = new RecoveryParser(text, this.index, end);\n if (!this.commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(this.index, 'Incomplete leading JSON comment');\n return;\n }\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const initialValue = scalarStart(text, initialValueStart, end) || isContainerStart(text[initialValueStart]);\n if (!initialValue) this.index = initialValueStart;\n while (this.index < end && result.candidates.length < MAX_CANDIDATES && this.failures < MAX_ERRORS) {\n const atInitialValue = initialValue && this.index === firstIndex;\n if (!atInitialValue) this.skipProse();\n if (this.index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n this.extractCandidate(atInitialValue ? initialParser : new RecoveryParser(text, this.index, end));\n }\n }\n\n /** Advances to the next position where a JSON value may start. */\n private skipProse(): void {\n const { text, end } = this;\n while (this.index < end && !isContainerStart(text[this.index])) {\n if (this.scalarBoundary && scalarStart(text, this.index, end)) break;\n if (this.skipUri() || this.skipCommentLikeSpan()) continue;\n if (/[\\r\\n]/.test(text[this.index]!)) this.scalarBoundary = true;\n else if (!/[\\s,]/.test(text[this.index]!)) this.scalarBoundary = false;\n this.index++;\n }\n }\n\n private skipUri(): boolean {\n const { text, end, index } = this;\n if (index !== this.start && /[\\w+.-]/.test(text[index - 1]!)) return false;\n const uriEnd = unquotedUriEnd(text, index, end);\n if (uriEnd === undefined) return false;\n if (index >= this.uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n this.uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n this.uriContainerStart = index;\n }\n if (index >= this.uriContainerStart) {\n const container = text.slice(index, this.uriTokenEnd).search(/[{[]/);\n this.uriContainerStart = container === -1 ? this.uriTokenEnd : index + container;\n }\n if (this.uriContainerStart < this.uriTokenEnd)\n this.uriBoundaryEnd = Math.max(this.uriBoundaryEnd, this.uriTokenEnd);\n this.index = Math.min(uriEnd, this.uriContainerStart);\n this.scalarBoundary = false;\n return true;\n }\n\n private skipCommentLikeSpan(): boolean {\n const { text, end, index } = this;\n if (this.commentFragment || text[index] !== '/') return false;\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index <= index) return false;\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(index, 'Possibly unterminated comment-like span in prose');\n extractRegion(text, index + 2, trivia.index, this.result, true);\n this.scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n this.index = trivia.index;\n return true;\n }\n\n private extractCandidate(bounded: RecoveryParser): void {\n const { text, end, index } = this;\n const valueStart = bounded.index;\n let parser = bounded;\n try {\n const boundedJson = bounded.value(0);\n const extended = this.parsePastRegionEnd(bounded, valueStart);\n parser = extended?.parser ?? bounded;\n const json = extended?.json ?? boundedJson;\n const valueEnd = parser.index;\n if (!isContainerStart(text[valueStart]) && !parser.finishScalar(end, valueStart)) {\n this.scalarBoundary = false;\n this.index = valueEnd;\n return;\n }\n parser.space();\n this.consumeSurplusClosers(parser);\n if (text[valueStart]! in QUOTES && parser.hasRepair('trailing-scalar-content'))\n this.reportExcerpt(valueEnd, 'Ambiguous quoted-scalar tail');\n this.markFragmentProvenance(parser);\n this.ambiguousScalarTail ||= parser.hasRepair('trailing-scalar-content');\n this.result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n this.reportError(parser.index, getErrorMessage(error));\n this.failures++;\n this.index = valueStart + 1;\n this.scalarBoundary = false;\n return;\n }\n this.index = Math.max(index + 1, parser.index);\n this.scalarBoundary = true;\n }\n\n /**\n * Reparses a container that `bounded` ended exactly at the region end against the rest of the text,\n * as the fence that bounds the region may be literal text inside one of its strings.\n */\n private parsePastRegionEnd(\n bounded: RecoveryParser,\n valueStart: number\n ): { parser: RecoveryParser; json: string } | undefined {\n const { text, end } = this;\n if (this.commentFragment || !isContainerStart(text[valueStart]) || bounded.index !== end || end >= text.length)\n return undefined;\n const parser = new RecoveryParser(text, this.index, text.length);\n try {\n const json = parser.value(0);\n if (parser.index > end && parser.repairs.every((repair) => repair.reason === 'unescaped-control-character')) {\n parser.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n return { parser, json };\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n return undefined;\n }\n\n private consumeSurplusClosers(parser: RecoveryParser): void {\n if (this.commentFragment || this.failures > 0) return;\n const surplusStart = parser.index;\n while (parser.index < this.end && /[}\\]]/.test(this.text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (parser.index > surplusStart)\n this.reportExcerpt(surplusStart, 'Surplus closing brackets and possible continuation');\n }\n\n private markFragmentProvenance(parser: RecoveryParser): void {\n const mark = (reason: string): void => {\n parser.repairs.unshift({ offset: this.index, kind: 'ambiguous', reason });\n };\n if (this.commentFragment) mark('fragment-in-comment-like-prose');\n if (this.failures > 0) mark('fragment-after-rejected-document');\n if (this.ambiguousScalarTail) mark('fragment-after-ambiguous-scalar');\n if (this.index < this.uriBoundaryEnd) mark('ambiguous-uri-boundary');\n }\n\n private reportExcerpt(offset: number, summary: string): void {\n const excerptEnd = Math.min(this.end, offset + MAX_DIAGNOSTIC_EXCERPT);\n const excerpt = JSON.stringify(this.text.slice(offset, excerptEnd));\n this.reportError(offset, `${summary} (${excerptEnd < this.end ? 'truncated excerpt' : 'excerpt'}): ${excerpt}`);\n }\n\n private reportError(offset: number, message: string): void {\n if (this.result.errors.length < MAX_ERRORS) this.result.errors.push({ offset, message });\n }\n}\n\nfunction isContainerStart(char: string | undefined): char is keyof typeof CLOSERS {\n return char === '{' || char === '[';\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral = this.text[start]! in QUOTES || this.hasRepair('unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (isContainerStart(char)) {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char);\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, open: keyof typeof CLOSERS): string {\n this.index++;\n const object = open === '{';\n const close = CLOSERS[open];\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return open + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n items.push(object ? `${this.key(keys)}:${this.value(depth + 1)}` : this.value(depth + 1));\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n /** Parses an object key and the colon after it, returning the key as JSON. */\n private key(seen: Set<string>): string {\n const start = this.index;\n const key = this.text[start]! in QUOTES ? this.string() : this.unquotedKey();\n const decoded: string = JSON.parse(key);\n if (seen.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n seen.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n return key;\n }\n\n private unquotedKey(): string {\n const start = this.index;\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n return JSON.stringify(rawKey);\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.charAfterSpace(this.index);\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char !== close) {\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n } else if (!embeddedQuote && context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n } else if (embeddedQuote || (context === 'value' && !delimited && this.opensEmbeddedQuote(close))) {\n embeddedQuote = !embeddedQuote;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n } else return JSON.stringify(value);\n }\n if (char === '\\\\') append(this.escapeSequence(open));\n else {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n /** Whether the closing quote just consumed and the next one more plausibly enclose a phrase quoted within the string. */\n private opensEmbeddedQuote(close: string): boolean {\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.charAfterSpace(nextClose + 1);\n return (\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) || (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n );\n }\n\n /** Decodes the escape sequence whose backslash was just consumed. */\n private escapeSequence(open: string): string {\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n return '\\\\';\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n this.index += 4;\n return String.fromCodePoint(Number.parseInt(hex, 16));\n }\n this.repair(/^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous', 'invalid-unicode-escape', escapeOffset);\n return String.raw`\\u`;\n }\n if (String.raw`\"\\/bfnrt`.includes(escape)) return JSON.parse(`\"\\\\${escape}\"`) as string;\n if (escape === \"'\" && open === \"'\") return \"'\";\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n return `\\\\${escape}`;\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.charAfterSpace(end + 1);\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n hasRepair(reason: string): boolean {\n return this.repairs.some((repair) => repair.reason === reason);\n }\n\n private charAfterSpace(index: number): string | undefined {\n return this.text.slice(index, this.end).trimStart()[0];\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"recoverJson.cjs","names":["getErrorMessage","require_error","MAX_INPUT_LENGTH","QUOTES","CLOSERS","KEYWORDS","recoverJson","result","text","fences","findFences","consumed","fence","extractThroughFence","extractRegion","error","marker","markerEnd","lineEnd","info","inlinePrefix","inlineStart","start","isContainerStart","scalarStart","parsedThrough","close","match","end","extendedEnd","outerClose","next","RegionExtractor","commentFragment","firstIndex","initialParser","RecoveryParser","initialValueStart","repair","initialValue","atInitialValue","index","uriEnd","unquotedUriEnd","whitespace","container","trivia","valueStart","bounded","parser","boundedJson","extended","json","valueEnd","surplusStart","mark","excerptEnd","offset","excerpt","summary","char","first","keyword","word","atom","bullet","retainLiteral","regionEnd","depth","token","canonical","object","open","items","keys","afterComma","commaOffset","key","decoded","seen","rawKey","value","tail","append","embeddedQuote","family","alternative","after","delimited","context","nextClose","afterNext","escapeOffset","escape","hex","quote","continuation","reason","brackets"],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nimport { getErrorMessage } from './error.js';\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst CLOSERS = { '{': '}', '[': ']' } as const;\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = findFences(text);\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index >= consumed) consumed = extractThroughFence(text, fences, fence, consumed, result);\n }\n extractRegion(text, consumed, text.length, result);\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\ninterface Fence {\n index: number;\n marker: string;\n /** Where the fenced content starts: after the opening line, or within it when JSON follows the info string. */\n start: number;\n}\n\nfunction findFences(text: string): Fence[] {\n return [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n isContainerStart(text[inlineStart]) || scalarStart(text, inlineStart, lineEnd) ? inlineStart : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n}\n\n/** Extracts the prose before `fence` and then its content, returning the offset up to which the text is consumed. */\nfunction extractThroughFence(\n text: string,\n fences: Fence[],\n fence: Fence,\n consumed: number,\n result: JsonRecovery\n): number {\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) return parsedThrough;\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n return outerClose.index + outerClose[0].length;\n }\n }\n return Math.max(result.candidates.at(-1)?.end ?? start, match === null ? text.length : match.index + match[0].length);\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length < MAX_CANDIDATES) new RegionExtractor(text, start, end, result, commentFragment).run();\n}\n\nclass RegionExtractor {\n private readonly text: string;\n private readonly start: number;\n private readonly end: number;\n private readonly result: JsonRecovery;\n private readonly commentFragment: boolean;\n private index: number;\n private failures = 0;\n private ambiguousScalarTail = false;\n private scalarBoundary = true;\n private uriBoundaryEnd: number;\n private uriTokenEnd: number;\n private uriContainerStart: number;\n\n constructor(text: string, start: number, end: number, result: JsonRecovery, commentFragment: boolean) {\n this.text = text;\n this.start = start;\n this.end = end;\n this.result = result;\n this.commentFragment = commentFragment;\n this.index = start;\n this.uriBoundaryEnd = start;\n this.uriTokenEnd = start;\n this.uriContainerStart = start;\n }\n\n run(): void {\n const { text, end, result } = this;\n while (this.index < end && /\\s/.test(text[this.index]!)) this.index++;\n const firstIndex = this.index;\n const initialParser = new RecoveryParser(text, this.index, end);\n if (!this.commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(this.index, 'Incomplete leading JSON comment');\n return;\n }\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const initialValue = scalarStart(text, initialValueStart, end) || isContainerStart(text[initialValueStart]);\n if (!initialValue) this.index = initialValueStart;\n while (this.index < end && result.candidates.length < MAX_CANDIDATES && this.failures < MAX_ERRORS) {\n const atInitialValue = initialValue && this.index === firstIndex;\n if (!atInitialValue) this.skipProse();\n if (this.index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n this.extractCandidate(atInitialValue ? initialParser : new RecoveryParser(text, this.index, end));\n }\n }\n\n /** Advances to the next position where a JSON value may start. */\n private skipProse(): void {\n const { text, end } = this;\n while (this.index < end && !isContainerStart(text[this.index])) {\n if (this.scalarBoundary && scalarStart(text, this.index, end)) break;\n if (this.skipUri() || this.skipCommentLikeSpan()) continue;\n if (/[\\r\\n]/.test(text[this.index]!)) this.scalarBoundary = true;\n else if (!/[\\s,]/.test(text[this.index]!)) this.scalarBoundary = false;\n this.index++;\n }\n }\n\n private skipUri(): boolean {\n const { text, end, index } = this;\n if (index !== this.start && /[\\w+.-]/.test(text[index - 1]!)) return false;\n const uriEnd = unquotedUriEnd(text, index, end);\n if (uriEnd === undefined) return false;\n if (index >= this.uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n this.uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n this.uriContainerStart = index;\n }\n if (index >= this.uriContainerStart) {\n const container = text.slice(index, this.uriTokenEnd).search(/[{[]/);\n this.uriContainerStart = container === -1 ? this.uriTokenEnd : index + container;\n }\n if (this.uriContainerStart < this.uriTokenEnd)\n this.uriBoundaryEnd = Math.max(this.uriBoundaryEnd, this.uriTokenEnd);\n this.index = Math.min(uriEnd, this.uriContainerStart);\n this.scalarBoundary = false;\n return true;\n }\n\n private skipCommentLikeSpan(): boolean {\n const { text, end, index } = this;\n if (this.commentFragment || text[index] !== '/') return false;\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index <= index) return false;\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(index, 'Possibly unterminated comment-like span in prose');\n extractRegion(text, index + 2, trivia.index, this.result, true);\n this.scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n this.index = trivia.index;\n return true;\n }\n\n private extractCandidate(bounded: RecoveryParser): void {\n const { text, end, index } = this;\n const valueStart = bounded.index;\n let parser = bounded;\n try {\n const boundedJson = bounded.value(0);\n const extended = this.parsePastRegionEnd(bounded, valueStart);\n parser = extended?.parser ?? bounded;\n const json = extended?.json ?? boundedJson;\n const valueEnd = parser.index;\n if (!isContainerStart(text[valueStart]) && !parser.finishScalar(end, valueStart)) {\n this.scalarBoundary = false;\n this.index = valueEnd;\n return;\n }\n parser.space();\n this.consumeSurplusClosers(parser);\n if (text[valueStart]! in QUOTES && parser.hasRepair('trailing-scalar-content'))\n this.reportExcerpt(valueEnd, 'Ambiguous quoted-scalar tail');\n this.markFragmentProvenance(parser);\n this.ambiguousScalarTail ||= parser.hasRepair('trailing-scalar-content');\n this.result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n this.reportError(parser.index, getErrorMessage(error));\n this.failures++;\n this.index = valueStart + 1;\n this.scalarBoundary = false;\n return;\n }\n this.index = Math.max(index + 1, parser.index);\n this.scalarBoundary = true;\n }\n\n /**\n * Reparses a container that `bounded` ended exactly at the region end against the rest of the text,\n * as the fence that bounds the region may be literal text inside one of its strings.\n */\n private parsePastRegionEnd(\n bounded: RecoveryParser,\n valueStart: number\n ): { parser: RecoveryParser; json: string } | undefined {\n const { text, end } = this;\n if (this.commentFragment || !isContainerStart(text[valueStart]) || bounded.index !== end || end >= text.length)\n return undefined;\n const parser = new RecoveryParser(text, this.index, text.length);\n try {\n const json = parser.value(0);\n if (parser.index > end && parser.repairs.every((repair) => repair.reason === 'unescaped-control-character')) {\n parser.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n return { parser, json };\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n return undefined;\n }\n\n private consumeSurplusClosers(parser: RecoveryParser): void {\n if (this.commentFragment || this.failures > 0) return;\n const surplusStart = parser.index;\n while (parser.index < this.end && /[}\\]]/.test(this.text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (parser.index > surplusStart)\n this.reportExcerpt(surplusStart, 'Surplus closing brackets and possible continuation');\n }\n\n private markFragmentProvenance(parser: RecoveryParser): void {\n const mark = (reason: string): void => {\n parser.repairs.unshift({ offset: this.index, kind: 'ambiguous', reason });\n };\n if (this.commentFragment) mark('fragment-in-comment-like-prose');\n if (this.failures > 0) mark('fragment-after-rejected-document');\n if (this.ambiguousScalarTail) mark('fragment-after-ambiguous-scalar');\n if (this.index < this.uriBoundaryEnd) mark('ambiguous-uri-boundary');\n }\n\n private reportExcerpt(offset: number, summary: string): void {\n const excerptEnd = Math.min(this.end, offset + MAX_DIAGNOSTIC_EXCERPT);\n const excerpt = JSON.stringify(this.text.slice(offset, excerptEnd));\n this.reportError(offset, `${summary} (${excerptEnd < this.end ? 'truncated excerpt' : 'excerpt'}): ${excerpt}`);\n }\n\n private reportError(offset: number, message: string): void {\n if (this.result.errors.length < MAX_ERRORS) this.result.errors.push({ offset, message });\n }\n}\n\nfunction isContainerStart(char: string | undefined): char is keyof typeof CLOSERS {\n return char === '{' || char === '[';\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral = this.text[start]! in QUOTES || this.hasRepair('unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (isContainerStart(char)) {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char);\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, open: keyof typeof CLOSERS): string {\n this.index++;\n const object = open === '{';\n const close = CLOSERS[open];\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return open + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n items.push(object ? `${this.key(keys)}:${this.value(depth + 1)}` : this.value(depth + 1));\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n /** Parses an object key and the colon after it, returning the key as JSON. */\n private key(seen: Set<string>): string {\n const start = this.index;\n const key = this.text[start]! in QUOTES ? this.string() : this.unquotedKey();\n const decoded: string = JSON.parse(key);\n if (seen.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n seen.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n return key;\n }\n\n private unquotedKey(): string {\n const start = this.index;\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n return JSON.stringify(rawKey);\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.charAfterSpace(this.index);\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char !== close) {\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n } else if (!embeddedQuote && context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n } else if (embeddedQuote || (context === 'value' && !delimited && this.opensEmbeddedQuote(close))) {\n embeddedQuote = !embeddedQuote;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n } else return JSON.stringify(value);\n }\n if (char === '\\\\') append(this.escapeSequence(open));\n else {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n /** Whether the closing quote just consumed and the next one more plausibly enclose a phrase quoted within the string. */\n private opensEmbeddedQuote(close: string): boolean {\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.charAfterSpace(nextClose + 1);\n return (\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) || (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n );\n }\n\n /** Decodes the escape sequence whose backslash was just consumed. */\n private escapeSequence(open: string): string {\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n return '\\\\';\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n this.index += 4;\n return String.fromCodePoint(Number.parseInt(hex, 16));\n }\n this.repair(/^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous', 'invalid-unicode-escape', escapeOffset);\n return String.raw`\\u`;\n }\n if (String.raw`\"\\/bfnrt`.includes(escape)) return JSON.parse(`\"\\\\${escape}\"`) as string;\n if (escape === \"'\" && open === \"'\") return \"'\";\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n return `\\\\${escape}`;\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.charAfterSpace(end + 1);\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n hasRepair(reason: string): boolean {\n return this.repairs.some((repair) => repair.reason === reason);\n }\n\n private charAfterSpace(index: number): string | undefined {\n return this.text.slice(index, this.end).trimStart()[0];\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import{getErrorMessage as e}from"./error.js";
2
2
  /*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */
3
- const t=1e6,n={'"':`"`,"'":`'`,"“":`”`,"”":`”`,"‘":`’`,"’":`’`},r={"{":`}`,"[":`]`},i={true:`true`,false:`false`,null:`null`,True:`true`,False:`false`,None:`null`};function a(e){let n={candidates:[],errors:[]};if(e.length>t)return n.errors.push({offset:t,message:`JSON recovery input exceeds one million characters`}),n;let r=o(e),i=0;for(let t of r)t.index>=i&&(i=s(e,r,t,i,n));if(c(e,i,e.length,n),n.candidates.length===32){let e={offset:n.candidates.at(-1).end,message:`JSON candidate limit reached; extraction may be incomplete`};n.errors.length===32?n.errors[31]=e:n.errors.push(e)}return n}function o(e){return[...e.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(t=>{let n=t[1],r=t.index+t[0].indexOf(n)+n.length,i=t.index+t[0].length,a=e.slice(r,i),o=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(a),s=o===null?i:r+o[0].length,c=u(e[s])||d(e,s,i)?s:i;return n[0]==="`"&&c===i&&a.includes("`")?[]:[{index:t.index,marker:n,start:c}]})}function s(e,t,n,r,i){c(e,r,n.index,i);let a=i.candidates.at(-1)?.end??r;if(a>n.index)return a;let{marker:o,start:s}=n,l=RegExp(`^ {0,3}${o[0]}{${o.length},}[ \\t]*$`,`gm`);l.lastIndex=s;let u=l.exec(e),d=u?.index??e.length;c(e,s,d,i);let f=i.candidates.at(-1)?.end??s;if(f>d){l.lastIndex=f;let n=l.exec(e);if(n!==null&&!t.some(e=>e.index>=f&&e.index<n.index))return c(e,f,n.index,i),n.index+n[0].length}return Math.max(i.candidates.at(-1)?.end??s,u===null?e.length:u.index+u[0].length)}function c(e,t,n,r,i=!1){r.candidates.length<32&&new l(e,t,n,r,i).run()}var l=class{text;start;end;result;commentFragment;index;failures=0;ambiguousScalarTail=!1;scalarBoundary=!0;uriBoundaryEnd;uriTokenEnd;uriContainerStart;constructor(e,t,n,r,i){this.text=e,this.start=t,this.end=n,this.result=r,this.commentFragment=i,this.index=t,this.uriBoundaryEnd=t,this.uriTokenEnd=t,this.uriContainerStart=t}run(){let{text:e,end:t,result:n}=this;for(;this.index<t&&/\s/.test(e[this.index]);)this.index++;let r=this.index,i=new f(e,this.index,t);this.commentFragment||i.space();let a=i.index;if(a>=t){i.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(this.index,`Incomplete leading JSON comment`);return}let o=d(e,a,t)||u(e[a]);for(o||(this.index=a);this.index<t&&n.candidates.length<32&&this.failures<32;){let a=o&&this.index===r;if(a||this.skipProse(),this.index>=t||n.candidates.length>=32)break;this.extractCandidate(a?i:new f(e,this.index,t))}}skipProse(){let{text:e,end:t}=this;for(;this.index<t&&!u(e[this.index])&&!(this.scalarBoundary&&d(e,this.index,t));)this.skipUri()||this.skipCommentLikeSpan()||(/[\r\n]/.test(e[this.index])?this.scalarBoundary=!0:/[\s,]/.test(e[this.index])||(this.scalarBoundary=!1),this.index++)}skipUri(){let{text:e,end:t,index:n}=this;if(n!==this.start&&/[\w+.-]/.test(e[n-1]))return!1;let r=p(e,n,t);if(r===void 0)return!1;if(n>=this.uriTokenEnd){let r=e.slice(n,t).search(/\s/);this.uriTokenEnd=r===-1?t:n+r,this.uriContainerStart=n}if(n>=this.uriContainerStart){let t=e.slice(n,this.uriTokenEnd).search(/[{[]/);this.uriContainerStart=t===-1?this.uriTokenEnd:n+t}return this.uriContainerStart<this.uriTokenEnd&&(this.uriBoundaryEnd=Math.max(this.uriBoundaryEnd,this.uriTokenEnd)),this.index=Math.min(r,this.uriContainerStart),this.scalarBoundary=!1,!0}skipCommentLikeSpan(){let{text:e,end:t,index:n}=this;if(this.commentFragment||e[n]!==`/`)return!1;let r=new f(e,n,t);return r.space(),r.index<=n?!1:(r.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(n,`Possibly unterminated comment-like span in prose`),c(e,n+2,r.index,this.result,!0),this.scalarBoundary||=/[\r\n]/.test(e.slice(n,r.index)),this.index=r.index,!0)}extractCandidate(t){let{text:r,end:i,index:a}=this,o=t.index,s=t;try{let e=t.value(0),c=this.parsePastRegionEnd(t,o);s=c?.parser??t;let l=c?.json??e,d=s.index;if(!u(r[o])&&!s.finishScalar(i,o)){this.scalarBoundary=!1,this.index=d;return}s.space(),this.consumeSurplusClosers(s),r[o]in n&&s.hasRepair(`trailing-scalar-content`)&&this.reportExcerpt(d,`Ambiguous quoted-scalar tail`),this.markFragmentProvenance(s),this.ambiguousScalarTail||=s.hasRepair(`trailing-scalar-content`),this.result.candidates.push({value:JSON.parse(l),json:l,start:a,end:s.index,repairs:s.repairs,requiresConfirmation:s.repairs.some(e=>e.kind!==`syntax`)})}catch(t){this.reportError(s.index,e(t)),this.failures++,this.index=o+1,this.scalarBoundary=!1;return}this.index=Math.max(a+1,s.index),this.scalarBoundary=!0}parsePastRegionEnd(e,t){let{text:n,end:r}=this;if(this.commentFragment||!u(n[t])||e.index!==r||r>=n.length)return;let i=new f(n,this.index,n.length);try{let e=i.value(0);if(i.index>r&&i.repairs.every(e=>e.reason===`unescaped-control-character`))return i.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),{parser:i,json:e}}catch{}}consumeSurplusClosers(e){if(this.commentFragment||this.failures>0)return;let t=e.index;for(;e.index<this.end&&/[}\]]/.test(this.text[e.index]);)e.repairs.push({offset:e.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),e.index++,e.space();e.index>t&&this.reportExcerpt(t,`Surplus closing brackets and possible continuation`)}markFragmentProvenance(e){let t=t=>{e.repairs.unshift({offset:this.index,kind:`ambiguous`,reason:t})};this.commentFragment&&t(`fragment-in-comment-like-prose`),this.failures>0&&t(`fragment-after-rejected-document`),this.ambiguousScalarTail&&t(`fragment-after-ambiguous-scalar`),this.index<this.uriBoundaryEnd&&t(`ambiguous-uri-boundary`)}reportExcerpt(e,t){let n=Math.min(this.end,e+256),r=JSON.stringify(this.text.slice(e,n));this.reportError(e,`${t} (${n<this.end?`truncated excerpt`:`excerpt`}): ${r}`)}reportError(e,t){this.result.errors.length<32&&this.result.errors.push({offset:e,message:t})}};function u(e){return e===`{`||e===`[`}function d(e,t,r){let a=e[t];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(t,r))?.[1];return a in n||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(i,o)||Object.keys(i).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(t+o.length,r)))}var f=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,t){let r=this.index,i=this.text.slice(t,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[t]in n||this.hasRepair(`unquoted-value`);return this.space(),a?!1:this.index>=e?!0:/[\r\n]/.test(this.text.slice(r,this.index))?(this.repair(`ambiguous`,`scalar-before-prose`,r),!0):/^\d+[.)]$/.test(i)&&/[ \t]/.test(this.text[r]??``)?!1:o||/^[\p{P}\p{S}]/u.test(this.text.slice(this.index,e))?(this.repair(`ambiguous`,`trailing-scalar-content`,r),!0):!1}value(e){if(e>128)throw Error(`JSON nesting exceeds 128 levels`);this.space();let t=this.text[this.index];if(this.index>=this.end||t===`,`||t===`}`||t===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(u(t)){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,t)}if(t!==void 0&&t in n)return this.string(e>0?`value`:`root`);let r=this.index,a=p(this.text,r,this.end);if(a!==void 0)this.index=a;else for(;this.index<this.end&&!/[\s,}\]]/.test(this.text[this.index])&&!(e===0&&/[{[]/.test(this.text[this.index]))&&!this.comment();)this.index++;if(this.index===r)throw Error(`Expected a JSON value`);let o=this.text.slice(r,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(i,o)){let e=i[o];return e!==o&&this.repair(`syntax`,`python-keyword`,r),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,r),JSON.stringify(o)}container(e,t){this.index++;let n=t===`{`,i=r[t],a=[],o=/* @__PURE__ */ new Set,s=!1,c=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===i)return this.index>=this.end?this.repair(`incomplete`,`missing-${i}`):this.index++,s&&this.repair(`syntax`,`trailing-comma`,c),t+a.join(`,`)+i;if(this.text[this.index]===`}`||this.text[this.index]===`]`)throw Error(`Mismatched closing bracket`);if(this.text[this.index]===`,`){n?this.repair(`ambiguous`,`extra-comma`):(a.push(`null`),this.repair(`incomplete`,`missing-value`)),c=this.index,s=!0,this.index++;continue}a.push(n?`${this.key(o)}:${this.value(e+1)}`:this.value(e+1)),this.space(),s=this.text[this.index]===`,`,s?(c=this.index,this.index++):this.index<this.end&&this.text[this.index]!==i&&this.repair(`syntax`,`missing-comma`)}}key(e){let t=this.index,r=this.text[t]in n?this.string():this.unquotedKey(),i=JSON.parse(r);return e.has(i)&&this.repair(`ambiguous`,`duplicate-key`,t),e.add(i),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`),r}unquotedKey(){let e=this.index;for(;this.index<this.end&&!/[\s:,{}[\]]/.test(this.text[this.index])&&!this.comment();)this.index++;if(this.index===e)throw Error(`Expected an object key`);let t=this.text.slice(e,this.index);return this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e),JSON.stringify(t)}string(e=`key`){let t=this.index,r=this.text[this.index++],i=n[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,t);let a=``,o=``,s=e=>{a+=e,o=(o+e).slice(-2)},c=!1,l=`"“”`.includes(r)?`"“”`:`'‘’`,u;for(;this.index<this.end;){let t=this.text[this.index++];if(`'‘’`.includes(r)&&`'’`.includes(t)&&/[\p{L}\p{N}]$/u.test(o)&&/^[\p{L}\p{N}]/u.test(this.text.slice(this.index,this.end))){this.repair(`ambiguous`,`literal-apostrophe`,this.index-1),s(t);continue}if(l.includes(t)){let n=this.charAfterSpace(this.index),r=n===void 0||/[,}\]:"']/.test(n);if(t!==i)r&&(u??={end:this.index,value:a,repairCount:this.repairs.length});else if(!c&&e!==`root`&&u!==void 0&&!r)return this.index=u.end,this.repairs.length=u.repairCount,this.repair(`ambiguous`,`mismatched-quote`,this.index-1),JSON.stringify(u.value);else if(c||e===`value`&&!r&&this.opensEmbeddedQuote(i))c=!c,this.repair(`ambiguous`,`unescaped-quote`,this.index-1);else return JSON.stringify(a)}t===`\\`?s(this.escapeSequence(r)):(t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t))}return this.repair(`incomplete`,`unterminated-string`,t),JSON.stringify(a)}opensEmbeddedQuote(e){let t=this.text.indexOf(e,this.index),n=this.charAfterSpace(t+1);return!/\s/.test(this.text[this.index]??``)&&t>this.index&&t<this.end&&n!==void 0&&(!/[,}:\]]/.test(n)||n===`,`&&this.continuesStringAfterComma(t+1,e))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,t))&&!this.startsKey(t)}escapeSequence(e){let t=this.index-1;if(this.index>=this.end)return this.repair(`incomplete`,`truncated-escape`,t),`\\`;let n=this.text[this.index++];if(n===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));return/^[\da-fA-F]{4}$/.test(e)?(this.index+=4,String.fromCodePoint(Number.parseInt(e,16))):(this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,t),String.raw`\u`)}return String.raw`"\/bfnrt`.includes(n)?JSON.parse(`"\\${n}"`):n===`'`&&e===`'`?`'`:(this.repair(`ambiguous`,`invalid-escape`,t),`\\${n}`)}continuesStringAfterComma(t,n){let r=new e(this.text,t-1,this.end);r.string();let i=r.index-1;if(this.text[i]!==n||r.repairs.some(e=>![`non-json-quote`,`literal-apostrophe`,`unescaped-control-character`].includes(e.reason)))return!1;let a=this.text.slice(t,i),o=this.charAfterSpace(i+1);return/^\s*,\s*[\p{L}\p{N}]/u.test(a)&&!/[\\:{}[\]]/.test(a)&&(o===void 0||/[,}\]]/.test(o))}startsKey(t){let n=new e(this.text,t,this.end);return n.string(),n.space(),this.text[n.index]===`:`}space(){for(;this.index<this.end;)if(/\s/.test(this.text[this.index]))/[ \t\r\n]/.test(this.text[this.index])||this.repair(`syntax`,`non-json-whitespace`),this.index++;else if(this.text.startsWith(`//`,this.index))for(this.repair(`syntax`,`line-comment`);this.index<this.end&&!/[\r\n]/.test(this.text[this.index]);)this.index++;else if(this.text.startsWith(`/*`,this.index)){let e=this.text.indexOf(`*/`,this.index+2);this.repair(e===-1||e>=this.end?`incomplete`:`syntax`,`block-comment`),this.index=e===-1||e>=this.end?this.end:e+2}else break}hasRepair(e){return this.repairs.some(t=>t.reason===e)}charAfterSpace(e){return this.text.slice(e,this.end).trimStart()[0]}repair(e,t,n=this.index){this.repairs.push({offset:n,kind:e,reason:t})}comment(){return this.text.startsWith(`//`,this.index)||this.text.startsWith(`/*`,this.index)}};function p(e,t,n){let r=/^[A-Za-z][A-Za-z\d+.-]*:\/\//.exec(e.slice(t,n));if(r===null)return;let i=t+r[0].length,a=0;for(;i<n&&!/[\s}]/.test(e[i])&&(e[i]!==`,`||a!==0);){if(e[i]===`[`)a++;else if(e[i]===`]`){if(a===0)break;a--}i++}return i}export{a as recoverJson};
3
+ const t=1e6,n={'"':`"`,"'":`'`,"“":`”`,"”":`”`,"‘":`’`,"’":`’`},r={"{":`}`,"[":`]`},i={true:`true`,false:`false`,null:`null`,True:`true`,False:`false`,None:`null`};function a(e){let n={candidates:[],errors:[]};if(e.length>t)return n.errors.push({offset:t,message:`JSON recovery input exceeds one million characters`}),n;let r=o(e),i=0;for(let t of r)t.index>=i&&(i=s(e,r,t,i,n));if(c(e,i,e.length,n),n.candidates.length===32){let e={offset:n.candidates.at(-1).end,message:`JSON candidate limit reached; extraction may be incomplete`};n.errors.length===32?n.errors[31]=e:n.errors.push(e)}return n}function o(e){return[...e.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(t=>{let n=t[1],r=t.index+t[0].indexOf(n)+n.length,i=t.index+t[0].length,a=e.slice(r,i),o=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(a),s=o===null?i:r+o[0].length,c=u(e[s])||d(e,s,i)?s:i;return n[0]==="`"&&c===i&&a.includes("`")?[]:[{index:t.index,marker:n,start:c}]})}function s(e,t,n,r,i){c(e,r,n.index,i);let a=i.candidates.at(-1)?.end??r;if(a>n.index)return a;let{marker:o,start:s}=n,l=RegExp(`^ {0,3}${o[0]}{${o.length},}[ \\t]*$`,`gm`);l.lastIndex=s;let u=l.exec(e),d=u?.index??e.length;c(e,s,d,i);let f=i.candidates.at(-1)?.end??s;if(f>d){l.lastIndex=f;let n=l.exec(e);if(n!==null&&!t.some(e=>e.index>=f&&e.index<n.index))return c(e,f,n.index,i),n.index+n[0].length}return Math.max(i.candidates.at(-1)?.end??s,u===null?e.length:u.index+u[0].length)}function c(e,t,n,r,i=!1){r.candidates.length<32&&new l(e,t,n,r,i).run()}var l=class{text;start;end;result;commentFragment;index;failures=0;ambiguousScalarTail=!1;scalarBoundary=!0;uriBoundaryEnd;uriTokenEnd;uriContainerStart;constructor(e,t,n,r,i){this.text=e,this.start=t,this.end=n,this.result=r,this.commentFragment=i,this.index=t,this.uriBoundaryEnd=t,this.uriTokenEnd=t,this.uriContainerStart=t}run(){let{text:e,end:t,result:n}=this;for(;this.index<t&&/\s/.test(e[this.index]);)this.index++;let r=this.index,i=new f(e,this.index,t);this.commentFragment||i.space();let a=i.index;if(a>=t){i.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(this.index,`Incomplete leading JSON comment`);return}let o=d(e,a,t)||u(e[a]);for(o||(this.index=a);this.index<t&&n.candidates.length<32&&this.failures<32;){let a=o&&this.index===r;if(a||this.skipProse(),this.index>=t||n.candidates.length>=32)break;this.extractCandidate(a?i:new f(e,this.index,t))}}skipProse(){let{text:e,end:t}=this;for(;this.index<t&&!u(e[this.index])&&!(this.scalarBoundary&&d(e,this.index,t));)this.skipUri()||this.skipCommentLikeSpan()||(/[\r\n]/.test(e[this.index])?this.scalarBoundary=!0:/[\s,]/.test(e[this.index])||(this.scalarBoundary=!1),this.index++)}skipUri(){let{text:e,end:t,index:n}=this;if(n!==this.start&&/[\w+.-]/.test(e[n-1]))return!1;let r=p(e,n,t);if(r===void 0)return!1;if(n>=this.uriTokenEnd){let r=e.slice(n,t).search(/\s/);this.uriTokenEnd=r===-1?t:n+r,this.uriContainerStart=n}if(n>=this.uriContainerStart){let t=e.slice(n,this.uriTokenEnd).search(/[{[]/);this.uriContainerStart=t===-1?this.uriTokenEnd:n+t}return this.uriContainerStart<this.uriTokenEnd&&(this.uriBoundaryEnd=Math.max(this.uriBoundaryEnd,this.uriTokenEnd)),this.index=Math.min(r,this.uriContainerStart),this.scalarBoundary=!1,!0}skipCommentLikeSpan(){let{text:e,end:t,index:n}=this;if(this.commentFragment||e[n]!==`/`)return!1;let r=new f(e,n,t);return r.space(),r.index<=n?!1:(r.repairs.some(e=>e.kind===`incomplete`)&&this.reportError(n,`Possibly unterminated comment-like span in prose`),c(e,n+2,r.index,this.result,!0),this.scalarBoundary||=/[\r\n]/.test(e.slice(n,r.index)),this.index=r.index,!0)}extractCandidate(t){let{text:r,end:i,index:a}=this,o=t.index,s=t;try{let e=t.value(0),c=this.parsePastRegionEnd(t,o);s=c?.parser??t;let l=c?.json??e,d=s.index;if(!u(r[o])&&!s.finishScalar(i,o)){this.scalarBoundary=!1,this.index=d;return}s.space(),this.consumeSurplusClosers(s),r[o]in n&&s.hasRepair(`trailing-scalar-content`)&&this.reportExcerpt(d,`Ambiguous quoted-scalar tail`),this.markFragmentProvenance(s),this.ambiguousScalarTail||=s.hasRepair(`trailing-scalar-content`),this.result.candidates.push({value:JSON.parse(l),json:l,start:a,end:s.index,repairs:s.repairs,requiresConfirmation:s.repairs.some(e=>e.kind!==`syntax`)})}catch(t){this.reportError(s.index,e(t)),this.failures++,this.index=o+1,this.scalarBoundary=!1;return}this.index=Math.max(a+1,s.index),this.scalarBoundary=!0}parsePastRegionEnd(e,t){let{text:n,end:r}=this;if(this.commentFragment||!u(n[t])||e.index!==r||r>=n.length)return;let i=new f(n,this.index,n.length);try{let e=i.value(0);if(i.index>r&&i.repairs.every(e=>e.reason===`unescaped-control-character`))return i.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),{parser:i,json:e}}catch{}}consumeSurplusClosers(e){if(this.commentFragment||this.failures>0)return;let t=e.index;for(;e.index<this.end&&/[}\]]/.test(this.text[e.index]);)e.repairs.push({offset:e.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),e.index++,e.space();e.index>t&&this.reportExcerpt(t,`Surplus closing brackets and possible continuation`)}markFragmentProvenance(e){let t=t=>{e.repairs.unshift({offset:this.index,kind:`ambiguous`,reason:t})};this.commentFragment&&t(`fragment-in-comment-like-prose`),this.failures>0&&t(`fragment-after-rejected-document`),this.ambiguousScalarTail&&t(`fragment-after-ambiguous-scalar`),this.index<this.uriBoundaryEnd&&t(`ambiguous-uri-boundary`)}reportExcerpt(e,t){let n=Math.min(this.end,e+256),r=JSON.stringify(this.text.slice(e,n));this.reportError(e,`${t} (${n<this.end?`truncated excerpt`:`excerpt`}): ${r}`)}reportError(e,t){this.result.errors.length<32&&this.result.errors.push({offset:e,message:t})}};function u(e){return e===`{`||e===`[`}function d(e,t,r){let a=e[t];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(t,r))?.[1];return a in n||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(i,o)||Object.keys(i).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(t+o.length,r)))}var f=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,t){let r=this.index,i=this.text.slice(t,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[t]in n||this.hasRepair(`unquoted-value`);return this.space(),a?!1:this.index>=e?!0:/[\r\n]/.test(this.text.slice(r,this.index))?(this.repair(`ambiguous`,`scalar-before-prose`,r),!0):/^\d+[.)]$/.test(i)&&/[ \t]/.test(this.text[r]??``)?!1:o||/^[\p{P}\p{S}]/u.test(this.text.slice(this.index,e))?(this.repair(`ambiguous`,`trailing-scalar-content`,r),!0):!1}value(e){if(e>128)throw Error(`JSON nesting exceeds 128 levels`);this.space();let t=this.text[this.index];if(this.index>=this.end||t===`,`||t===`}`||t===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(u(t)){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,t)}if(t!==void 0&&t in n)return this.string(e>0?`value`:`root`);let r=this.index,a=p(this.text,r,this.end);if(a!==void 0)this.index=a;else for(;this.index<this.end&&!/[\s,}\]]/.test(this.text[this.index])&&!(e===0&&/[{[]/.test(this.text[this.index]))&&!this.comment();)this.index++;if(this.index===r)throw Error(`Expected a JSON value`);let o=this.text.slice(r,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(i,o)){let e=i[o];return e!==o&&this.repair(`syntax`,`python-keyword`,r),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,r),JSON.stringify(o)}container(e,t){this.index++;let n=t===`{`,i=r[t],a=[],o=/* @__PURE__ */ new Set,s=!1,c=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===i)return this.index>=this.end?this.repair(`incomplete`,`missing-${i}`):this.index++,s&&this.repair(`syntax`,`trailing-comma`,c),t+a.join(`,`)+i;if(this.text[this.index]===`}`||this.text[this.index]===`]`)throw Error(`Mismatched closing bracket`);this.text[this.index]===`,`?(n?this.repair(`ambiguous`,`extra-comma`):(a.push(`null`),this.repair(`incomplete`,`missing-value`)),c=this.index,s=!0,this.index++):(a.push(n?`${this.key(o)}:${this.value(e+1)}`:this.value(e+1)),this.space(),s=this.text[this.index]===`,`,s?(c=this.index,this.index++):this.index<this.end&&this.text[this.index]!==i&&this.repair(`syntax`,`missing-comma`))}}key(e){let t=this.index,r=this.text[t]in n?this.string():this.unquotedKey(),i=JSON.parse(r);return e.has(i)&&this.repair(`ambiguous`,`duplicate-key`,t),e.add(i),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`),r}unquotedKey(){let e=this.index;for(;this.index<this.end&&!/[\s:,{}[\]]/.test(this.text[this.index])&&!this.comment();)this.index++;if(this.index===e)throw Error(`Expected an object key`);let t=this.text.slice(e,this.index);return this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e),JSON.stringify(t)}string(e=`key`){let t=this.index,r=this.text[this.index++],i=n[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,t);let a=``,o=``,s=e=>{a+=e,o=(o+e).slice(-2)},c=!1,l=`"“”`.includes(r)?`"“”`:`'‘’`,u;for(;this.index<this.end;){let t=this.text[this.index++];if(`'‘’`.includes(r)&&`'’`.includes(t)&&/[\p{L}\p{N}]$/u.test(o)&&/^[\p{L}\p{N}]/u.test(this.text.slice(this.index,this.end)))this.repair(`ambiguous`,`literal-apostrophe`,this.index-1),s(t);else{if(l.includes(t)){let n=this.charAfterSpace(this.index),r=n===void 0||/[,}\]:"']/.test(n);if(t!==i)r&&(u??={end:this.index,value:a,repairCount:this.repairs.length});else if(!c&&e!==`root`&&u!==void 0&&!r)return this.index=u.end,this.repairs.length=u.repairCount,this.repair(`ambiguous`,`mismatched-quote`,this.index-1),JSON.stringify(u.value);else if(c||e===`value`&&!r&&this.opensEmbeddedQuote(i))c=!c,this.repair(`ambiguous`,`unescaped-quote`,this.index-1);else return JSON.stringify(a)}t===`\\`?s(this.escapeSequence(r)):(t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t))}}return this.repair(`incomplete`,`unterminated-string`,t),JSON.stringify(a)}opensEmbeddedQuote(e){let t=this.text.indexOf(e,this.index),n=this.charAfterSpace(t+1);return!/\s/.test(this.text[this.index]??``)&&t>this.index&&t<this.end&&n!==void 0&&(!/[,}:\]]/.test(n)||n===`,`&&this.continuesStringAfterComma(t+1,e))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,t))&&!this.startsKey(t)}escapeSequence(e){let t=this.index-1;if(this.index>=this.end)return this.repair(`incomplete`,`truncated-escape`,t),`\\`;let n=this.text[this.index++];if(n===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));return/^[\da-fA-F]{4}$/.test(e)?(this.index+=4,String.fromCodePoint(Number.parseInt(e,16))):(this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,t),String.raw`\u`)}return String.raw`"\/bfnrt`.includes(n)?JSON.parse(`"\\${n}"`):n===`'`&&e===`'`?`'`:(this.repair(`ambiguous`,`invalid-escape`,t),`\\${n}`)}continuesStringAfterComma(t,n){let r=new e(this.text,t-1,this.end);r.string();let i=r.index-1;if(this.text[i]!==n||r.repairs.some(e=>![`non-json-quote`,`literal-apostrophe`,`unescaped-control-character`].includes(e.reason)))return!1;let a=this.text.slice(t,i),o=this.charAfterSpace(i+1);return/^\s*,\s*[\p{L}\p{N}]/u.test(a)&&!/[\\:{}[\]]/.test(a)&&(o===void 0||/[,}\]]/.test(o))}startsKey(t){let n=new e(this.text,t,this.end);return n.string(),n.space(),this.text[n.index]===`:`}space(){for(;this.index<this.end;)if(/\s/.test(this.text[this.index]))/[ \t\r\n]/.test(this.text[this.index])||this.repair(`syntax`,`non-json-whitespace`),this.index++;else if(this.text.startsWith(`//`,this.index))for(this.repair(`syntax`,`line-comment`);this.index<this.end&&!/[\r\n]/.test(this.text[this.index]);)this.index++;else if(this.text.startsWith(`/*`,this.index)){let e=this.text.indexOf(`*/`,this.index+2);this.repair(e===-1||e>=this.end?`incomplete`:`syntax`,`block-comment`),this.index=e===-1||e>=this.end?this.end:e+2}else break}hasRepair(e){return this.repairs.some(t=>t.reason===e)}charAfterSpace(e){return this.text.slice(e,this.end).trimStart()[0]}repair(e,t,n=this.index){this.repairs.push({offset:n,kind:e,reason:t})}comment(){return this.text.startsWith(`//`,this.index)||this.text.startsWith(`/*`,this.index)}};function p(e,t,n){let r=/^[A-Za-z][A-Za-z\d+.-]*:\/\//.exec(e.slice(t,n));if(r===null)return;let i=t+r[0].length,a=0;for(;i<n&&!/[\s}]/.test(e[i])&&(e[i]!==`,`||a!==0);){if(e[i]===`[`)a++;else if(e[i]===`]`){if(a===0)break;a--}i++}return i}export{a as recoverJson};
4
4
  //# sourceMappingURL=recoverJson.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"recoverJson.js","names":["MAX_INPUT_LENGTH","QUOTES","CLOSERS","KEYWORDS","recoverJson","result","text","fences","findFences","consumed","fence","extractThroughFence","extractRegion","error","marker","markerEnd","lineEnd","info","inlinePrefix","inlineStart","start","isContainerStart","scalarStart","parsedThrough","close","match","end","extendedEnd","outerClose","next","RegionExtractor","commentFragment","firstIndex","initialParser","RecoveryParser","initialValueStart","repair","initialValue","atInitialValue","index","uriEnd","unquotedUriEnd","whitespace","container","trivia","valueStart","bounded","parser","boundedJson","extended","json","valueEnd","getErrorMessage","surplusStart","mark","excerptEnd","offset","excerpt","summary","char","first","keyword","word","atom","bullet","retainLiteral","regionEnd","depth","token","canonical","object","open","items","keys","afterComma","commaOffset","key","decoded","seen","rawKey","value","tail","append","embeddedQuote","family","alternative","after","delimited","context","nextClose","afterNext","escapeOffset","escape","hex","quote","continuation","reason","brackets"],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nimport { getErrorMessage } from './error.js';\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst CLOSERS = { '{': '}', '[': ']' } as const;\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = findFences(text);\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index >= consumed) consumed = extractThroughFence(text, fences, fence, consumed, result);\n }\n extractRegion(text, consumed, text.length, result);\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\ninterface Fence {\n index: number;\n marker: string;\n /** Where the fenced content starts: after the opening line, or within it when JSON follows the info string. */\n start: number;\n}\n\nfunction findFences(text: string): Fence[] {\n return [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n isContainerStart(text[inlineStart]) || scalarStart(text, inlineStart, lineEnd) ? inlineStart : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n}\n\n/** Extracts the prose before `fence` and then its content, returning the offset up to which the text is consumed. */\nfunction extractThroughFence(\n text: string,\n fences: Fence[],\n fence: Fence,\n consumed: number,\n result: JsonRecovery\n): number {\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) return parsedThrough;\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n return outerClose.index + outerClose[0].length;\n }\n }\n return Math.max(result.candidates.at(-1)?.end ?? start, match === null ? text.length : match.index + match[0].length);\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length < MAX_CANDIDATES) new RegionExtractor(text, start, end, result, commentFragment).run();\n}\n\nclass RegionExtractor {\n private readonly text: string;\n private readonly start: number;\n private readonly end: number;\n private readonly result: JsonRecovery;\n private readonly commentFragment: boolean;\n private index: number;\n private failures = 0;\n private ambiguousScalarTail = false;\n private scalarBoundary = true;\n private uriBoundaryEnd: number;\n private uriTokenEnd: number;\n private uriContainerStart: number;\n\n constructor(text: string, start: number, end: number, result: JsonRecovery, commentFragment: boolean) {\n this.text = text;\n this.start = start;\n this.end = end;\n this.result = result;\n this.commentFragment = commentFragment;\n this.index = start;\n this.uriBoundaryEnd = start;\n this.uriTokenEnd = start;\n this.uriContainerStart = start;\n }\n\n run(): void {\n const { text, end, result } = this;\n while (this.index < end && /\\s/.test(text[this.index]!)) this.index++;\n const firstIndex = this.index;\n const initialParser = new RecoveryParser(text, this.index, end);\n if (!this.commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(this.index, 'Incomplete leading JSON comment');\n return;\n }\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const initialValue = scalarStart(text, initialValueStart, end) || isContainerStart(text[initialValueStart]);\n if (!initialValue) this.index = initialValueStart;\n while (this.index < end && result.candidates.length < MAX_CANDIDATES && this.failures < MAX_ERRORS) {\n const atInitialValue = initialValue && this.index === firstIndex;\n if (!atInitialValue) this.skipProse();\n if (this.index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n this.extractCandidate(atInitialValue ? initialParser : new RecoveryParser(text, this.index, end));\n }\n }\n\n /** Advances to the next position where a JSON value may start. */\n private skipProse(): void {\n const { text, end } = this;\n while (this.index < end && !isContainerStart(text[this.index])) {\n if (this.scalarBoundary && scalarStart(text, this.index, end)) break;\n if (this.skipUri() || this.skipCommentLikeSpan()) continue;\n if (/[\\r\\n]/.test(text[this.index]!)) this.scalarBoundary = true;\n else if (!/[\\s,]/.test(text[this.index]!)) this.scalarBoundary = false;\n this.index++;\n }\n }\n\n private skipUri(): boolean {\n const { text, end, index } = this;\n if (index !== this.start && /[\\w+.-]/.test(text[index - 1]!)) return false;\n const uriEnd = unquotedUriEnd(text, index, end);\n if (uriEnd === undefined) return false;\n if (index >= this.uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n this.uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n this.uriContainerStart = index;\n }\n if (index >= this.uriContainerStart) {\n const container = text.slice(index, this.uriTokenEnd).search(/[{[]/);\n this.uriContainerStart = container === -1 ? this.uriTokenEnd : index + container;\n }\n if (this.uriContainerStart < this.uriTokenEnd)\n this.uriBoundaryEnd = Math.max(this.uriBoundaryEnd, this.uriTokenEnd);\n this.index = Math.min(uriEnd, this.uriContainerStart);\n this.scalarBoundary = false;\n return true;\n }\n\n private skipCommentLikeSpan(): boolean {\n const { text, end, index } = this;\n if (this.commentFragment || text[index] !== '/') return false;\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index <= index) return false;\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(index, 'Possibly unterminated comment-like span in prose');\n extractRegion(text, index + 2, trivia.index, this.result, true);\n this.scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n this.index = trivia.index;\n return true;\n }\n\n private extractCandidate(bounded: RecoveryParser): void {\n const { text, end, index } = this;\n const valueStart = bounded.index;\n let parser = bounded;\n try {\n const boundedJson = bounded.value(0);\n const extended = this.parsePastRegionEnd(bounded, valueStart);\n parser = extended?.parser ?? bounded;\n const json = extended?.json ?? boundedJson;\n const valueEnd = parser.index;\n if (!isContainerStart(text[valueStart]) && !parser.finishScalar(end, valueStart)) {\n this.scalarBoundary = false;\n this.index = valueEnd;\n return;\n }\n parser.space();\n this.consumeSurplusClosers(parser);\n if (text[valueStart]! in QUOTES && parser.hasRepair('trailing-scalar-content'))\n this.reportExcerpt(valueEnd, 'Ambiguous quoted-scalar tail');\n this.markFragmentProvenance(parser);\n this.ambiguousScalarTail ||= parser.hasRepair('trailing-scalar-content');\n this.result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n this.reportError(parser.index, getErrorMessage(error));\n this.failures++;\n this.index = valueStart + 1;\n this.scalarBoundary = false;\n return;\n }\n this.index = Math.max(index + 1, parser.index);\n this.scalarBoundary = true;\n }\n\n /**\n * Reparses a container that `bounded` ended exactly at the region end against the rest of the text,\n * as the fence that bounds the region may be literal text inside one of its strings.\n */\n private parsePastRegionEnd(\n bounded: RecoveryParser,\n valueStart: number\n ): { parser: RecoveryParser; json: string } | undefined {\n const { text, end } = this;\n if (this.commentFragment || !isContainerStart(text[valueStart]) || bounded.index !== end || end >= text.length)\n return undefined;\n const parser = new RecoveryParser(text, this.index, text.length);\n try {\n const json = parser.value(0);\n if (parser.index > end && parser.repairs.every((repair) => repair.reason === 'unescaped-control-character')) {\n parser.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n return { parser, json };\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n return undefined;\n }\n\n private consumeSurplusClosers(parser: RecoveryParser): void {\n if (this.commentFragment || this.failures > 0) return;\n const surplusStart = parser.index;\n while (parser.index < this.end && /[}\\]]/.test(this.text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (parser.index > surplusStart)\n this.reportExcerpt(surplusStart, 'Surplus closing brackets and possible continuation');\n }\n\n private markFragmentProvenance(parser: RecoveryParser): void {\n const mark = (reason: string): void => {\n parser.repairs.unshift({ offset: this.index, kind: 'ambiguous', reason });\n };\n if (this.commentFragment) mark('fragment-in-comment-like-prose');\n if (this.failures > 0) mark('fragment-after-rejected-document');\n if (this.ambiguousScalarTail) mark('fragment-after-ambiguous-scalar');\n if (this.index < this.uriBoundaryEnd) mark('ambiguous-uri-boundary');\n }\n\n private reportExcerpt(offset: number, summary: string): void {\n const excerptEnd = Math.min(this.end, offset + MAX_DIAGNOSTIC_EXCERPT);\n const excerpt = JSON.stringify(this.text.slice(offset, excerptEnd));\n this.reportError(offset, `${summary} (${excerptEnd < this.end ? 'truncated excerpt' : 'excerpt'}): ${excerpt}`);\n }\n\n private reportError(offset: number, message: string): void {\n if (this.result.errors.length < MAX_ERRORS) this.result.errors.push({ offset, message });\n }\n}\n\nfunction isContainerStart(char: string | undefined): char is keyof typeof CLOSERS {\n return char === '{' || char === '[';\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral = this.text[start]! in QUOTES || this.hasRepair('unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (isContainerStart(char)) {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char);\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, open: keyof typeof CLOSERS): string {\n this.index++;\n const object = open === '{';\n const close = CLOSERS[open];\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return open + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n items.push(object ? `${this.key(keys)}:${this.value(depth + 1)}` : this.value(depth + 1));\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n /** Parses an object key and the colon after it, returning the key as JSON. */\n private key(seen: Set<string>): string {\n const start = this.index;\n const key = this.text[start]! in QUOTES ? this.string() : this.unquotedKey();\n const decoded: string = JSON.parse(key);\n if (seen.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n seen.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n return key;\n }\n\n private unquotedKey(): string {\n const start = this.index;\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n return JSON.stringify(rawKey);\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.charAfterSpace(this.index);\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char !== close) {\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n } else if (!embeddedQuote && context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n } else if (embeddedQuote || (context === 'value' && !delimited && this.opensEmbeddedQuote(close))) {\n embeddedQuote = !embeddedQuote;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n } else return JSON.stringify(value);\n }\n if (char === '\\\\') append(this.escapeSequence(open));\n else {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n /** Whether the closing quote just consumed and the next one more plausibly enclose a phrase quoted within the string. */\n private opensEmbeddedQuote(close: string): boolean {\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.charAfterSpace(nextClose + 1);\n return (\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) || (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n );\n }\n\n /** Decodes the escape sequence whose backslash was just consumed. */\n private escapeSequence(open: string): string {\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n return '\\\\';\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n this.index += 4;\n return String.fromCodePoint(Number.parseInt(hex, 16));\n }\n this.repair(/^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous', 'invalid-unicode-escape', escapeOffset);\n return String.raw`\\u`;\n }\n if (String.raw`\"\\/bfnrt`.includes(escape)) return JSON.parse(`\"\\\\${escape}\"`) as string;\n if (escape === \"'\" && open === \"'\") return \"'\";\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n return `\\\\${escape}`;\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.charAfterSpace(end + 1);\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n hasRepair(reason: string): boolean {\n return this.repairs.some((repair) => repair.reason === reason);\n }\n\n private charAfterSpace(index: number): string | undefined {\n return this.text.slice(index, this.end).trimStart()[0];\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"recoverJson.js","names":["MAX_INPUT_LENGTH","QUOTES","CLOSERS","KEYWORDS","recoverJson","result","text","fences","findFences","consumed","fence","extractThroughFence","extractRegion","error","marker","markerEnd","lineEnd","info","inlinePrefix","inlineStart","start","isContainerStart","scalarStart","parsedThrough","close","match","end","extendedEnd","outerClose","next","RegionExtractor","commentFragment","firstIndex","initialParser","RecoveryParser","initialValueStart","repair","initialValue","atInitialValue","index","uriEnd","unquotedUriEnd","whitespace","container","trivia","valueStart","bounded","parser","boundedJson","extended","json","valueEnd","getErrorMessage","surplusStart","mark","excerptEnd","offset","excerpt","summary","char","first","keyword","word","atom","bullet","retainLiteral","regionEnd","depth","token","canonical","object","open","items","keys","afterComma","commaOffset","key","decoded","seen","rawKey","value","tail","append","embeddedQuote","family","alternative","after","delimited","context","nextClose","afterNext","escapeOffset","escape","hex","quote","continuation","reason","brackets"],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\n\nimport { getErrorMessage } from './error.js';\n\nexport interface JsonRepair {\n /** UTF-16 offset in the original response. */\n offset: number;\n kind: 'syntax' | 'incomplete' | 'ambiguous';\n reason: string;\n}\n\nexport interface RecoveredJson {\n value: unknown;\n json: string;\n start: number;\n end: number;\n repairs: JsonRepair[];\n /** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */\n requiresConfirmation: boolean;\n}\n\nexport interface JsonRecovery {\n candidates: RecoveredJson[];\n errors: { offset: number; message: string }[];\n}\n\nconst MAX_INPUT_LENGTH = 1_000_000;\nconst MAX_DEPTH = 128;\nconst MAX_CANDIDATES = 32;\nconst MAX_ERRORS = 32;\nconst MAX_DIAGNOSTIC_EXCERPT = 256;\nconst QUOTES: Record<string, string> = { '\"': '\"', \"'\": \"'\", '“': '”', '”': '”', '‘': '’', '’': '’' };\nconst CLOSERS = { '{': '}', '[': ']' } as const;\nconst KEYWORDS: Record<string, string> = {\n true: 'true',\n false: 'false',\n null: 'null',\n True: 'true',\n False: 'false',\n None: 'null',\n};\n\n/**\n * Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.\n * Offsets refer to the original string. All candidates are returned: choosing among multiple answers,\n * schema validation, and provider truncation signals belong to the caller. No schema values are coerced.\n * Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.\n * A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.\n */\nexport function recoverJson(text: string): JsonRecovery {\n const result: JsonRecovery = { candidates: [], errors: [] };\n if (text.length > MAX_INPUT_LENGTH) {\n result.errors.push({ offset: MAX_INPUT_LENGTH, message: 'JSON recovery input exceeds one million characters' });\n return result;\n }\n const fences = findFences(text);\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index >= consumed) consumed = extractThroughFence(text, fences, fence, consumed, result);\n }\n extractRegion(text, consumed, text.length, result);\n if (result.candidates.length === MAX_CANDIDATES) {\n const error = {\n offset: result.candidates.at(-1)!.end,\n message: 'JSON candidate limit reached; extraction may be incomplete',\n };\n if (result.errors.length === MAX_ERRORS) result.errors[MAX_ERRORS - 1] = error;\n else result.errors.push(error);\n }\n return result;\n}\n\ninterface Fence {\n index: number;\n marker: string;\n /** Where the fenced content starts: after the opening line, or within it when JSON follows the info string. */\n start: number;\n}\n\nfunction findFences(text: string): Fence[] {\n return [...text.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\\r\\n]*(?:\\r\\n|[\\r\\n]|$)/gm)].flatMap((fence) => {\n const marker = fence[1]!;\n const markerEnd = fence.index + fence[0].indexOf(marker) + marker.length;\n const lineEnd = fence.index + fence[0].length;\n const info = text.slice(markerEnd, lineEnd);\n const inlinePrefix = /^[ \\t]*json(?=[ \\t{[\"'“”‘’])[ \\t]*/i.exec(info);\n const inlineStart = inlinePrefix === null ? lineEnd : markerEnd + inlinePrefix[0].length;\n const start =\n isContainerStart(text[inlineStart]) || scalarStart(text, inlineStart, lineEnd) ? inlineStart : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n}\n\n/** Extracts the prose before `fence` and then its content, returning the offset up to which the text is consumed. */\nfunction extractThroughFence(\n text: string,\n fences: Fence[],\n fence: Fence,\n consumed: number,\n result: JsonRecovery\n): number {\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) return parsedThrough;\n const { marker, start } = fence;\n const close = new RegExp(`^ {0,3}${marker[0]}{${marker.length},}[ \\\\t]*$`, 'gm');\n close.lastIndex = start;\n const match = close.exec(text);\n const end = match?.index ?? text.length;\n extractRegion(text, start, end, result);\n const extendedEnd = result.candidates.at(-1)?.end ?? start;\n if (extendedEnd > end) {\n close.lastIndex = extendedEnd;\n const outerClose = close.exec(text);\n if (outerClose !== null && !fences.some((next) => next.index >= extendedEnd && next.index < outerClose.index)) {\n extractRegion(text, extendedEnd, outerClose.index, result);\n return outerClose.index + outerClose[0].length;\n }\n }\n return Math.max(result.candidates.at(-1)?.end ?? start, match === null ? text.length : match.index + match[0].length);\n}\n\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length < MAX_CANDIDATES) new RegionExtractor(text, start, end, result, commentFragment).run();\n}\n\nclass RegionExtractor {\n private readonly text: string;\n private readonly start: number;\n private readonly end: number;\n private readonly result: JsonRecovery;\n private readonly commentFragment: boolean;\n private index: number;\n private failures = 0;\n private ambiguousScalarTail = false;\n private scalarBoundary = true;\n private uriBoundaryEnd: number;\n private uriTokenEnd: number;\n private uriContainerStart: number;\n\n constructor(text: string, start: number, end: number, result: JsonRecovery, commentFragment: boolean) {\n this.text = text;\n this.start = start;\n this.end = end;\n this.result = result;\n this.commentFragment = commentFragment;\n this.index = start;\n this.uriBoundaryEnd = start;\n this.uriTokenEnd = start;\n this.uriContainerStart = start;\n }\n\n run(): void {\n const { text, end, result } = this;\n while (this.index < end && /\\s/.test(text[this.index]!)) this.index++;\n const firstIndex = this.index;\n const initialParser = new RecoveryParser(text, this.index, end);\n if (!this.commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(this.index, 'Incomplete leading JSON comment');\n return;\n }\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const initialValue = scalarStart(text, initialValueStart, end) || isContainerStart(text[initialValueStart]);\n if (!initialValue) this.index = initialValueStart;\n while (this.index < end && result.candidates.length < MAX_CANDIDATES && this.failures < MAX_ERRORS) {\n const atInitialValue = initialValue && this.index === firstIndex;\n if (!atInitialValue) this.skipProse();\n if (this.index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n this.extractCandidate(atInitialValue ? initialParser : new RecoveryParser(text, this.index, end));\n }\n }\n\n /** Advances to the next position where a JSON value may start. */\n private skipProse(): void {\n const { text, end } = this;\n while (this.index < end && !isContainerStart(text[this.index])) {\n if (this.scalarBoundary && scalarStart(text, this.index, end)) break;\n if (this.skipUri() || this.skipCommentLikeSpan()) continue;\n if (/[\\r\\n]/.test(text[this.index]!)) this.scalarBoundary = true;\n else if (!/[\\s,]/.test(text[this.index]!)) this.scalarBoundary = false;\n this.index++;\n }\n }\n\n private skipUri(): boolean {\n const { text, end, index } = this;\n if (index !== this.start && /[\\w+.-]/.test(text[index - 1]!)) return false;\n const uriEnd = unquotedUriEnd(text, index, end);\n if (uriEnd === undefined) return false;\n if (index >= this.uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n this.uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n this.uriContainerStart = index;\n }\n if (index >= this.uriContainerStart) {\n const container = text.slice(index, this.uriTokenEnd).search(/[{[]/);\n this.uriContainerStart = container === -1 ? this.uriTokenEnd : index + container;\n }\n if (this.uriContainerStart < this.uriTokenEnd)\n this.uriBoundaryEnd = Math.max(this.uriBoundaryEnd, this.uriTokenEnd);\n this.index = Math.min(uriEnd, this.uriContainerStart);\n this.scalarBoundary = false;\n return true;\n }\n\n private skipCommentLikeSpan(): boolean {\n const { text, end, index } = this;\n if (this.commentFragment || text[index] !== '/') return false;\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index <= index) return false;\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete'))\n this.reportError(index, 'Possibly unterminated comment-like span in prose');\n extractRegion(text, index + 2, trivia.index, this.result, true);\n this.scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n this.index = trivia.index;\n return true;\n }\n\n private extractCandidate(bounded: RecoveryParser): void {\n const { text, end, index } = this;\n const valueStart = bounded.index;\n let parser = bounded;\n try {\n const boundedJson = bounded.value(0);\n const extended = this.parsePastRegionEnd(bounded, valueStart);\n parser = extended?.parser ?? bounded;\n const json = extended?.json ?? boundedJson;\n const valueEnd = parser.index;\n if (!isContainerStart(text[valueStart]) && !parser.finishScalar(end, valueStart)) {\n this.scalarBoundary = false;\n this.index = valueEnd;\n return;\n }\n parser.space();\n this.consumeSurplusClosers(parser);\n if (text[valueStart]! in QUOTES && parser.hasRepair('trailing-scalar-content'))\n this.reportExcerpt(valueEnd, 'Ambiguous quoted-scalar tail');\n this.markFragmentProvenance(parser);\n this.ambiguousScalarTail ||= parser.hasRepair('trailing-scalar-content');\n this.result.candidates.push({\n value: JSON.parse(json),\n json,\n start: index,\n end: parser.index,\n repairs: parser.repairs,\n requiresConfirmation: parser.repairs.some((repair) => repair.kind !== 'syntax'),\n });\n } catch (error) {\n this.reportError(parser.index, getErrorMessage(error));\n this.failures++;\n this.index = valueStart + 1;\n this.scalarBoundary = false;\n return;\n }\n this.index = Math.max(index + 1, parser.index);\n this.scalarBoundary = true;\n }\n\n /**\n * Reparses a container that `bounded` ended exactly at the region end against the rest of the text,\n * as the fence that bounds the region may be literal text inside one of its strings.\n */\n private parsePastRegionEnd(\n bounded: RecoveryParser,\n valueStart: number\n ): { parser: RecoveryParser; json: string } | undefined {\n const { text, end } = this;\n if (this.commentFragment || !isContainerStart(text[valueStart]) || bounded.index !== end || end >= text.length)\n return undefined;\n const parser = new RecoveryParser(text, this.index, text.length);\n try {\n const json = parser.value(0);\n if (parser.index > end && parser.repairs.every((repair) => repair.reason === 'unescaped-control-character')) {\n parser.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n return { parser, json };\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n return undefined;\n }\n\n private consumeSurplusClosers(parser: RecoveryParser): void {\n if (this.commentFragment || this.failures > 0) return;\n const surplusStart = parser.index;\n while (parser.index < this.end && /[}\\]]/.test(this.text[parser.index]!)) {\n parser.repairs.push({ offset: parser.index, kind: 'ambiguous', reason: 'surplus-closing-bracket' });\n parser.index++;\n parser.space();\n }\n if (parser.index > surplusStart)\n this.reportExcerpt(surplusStart, 'Surplus closing brackets and possible continuation');\n }\n\n private markFragmentProvenance(parser: RecoveryParser): void {\n const mark = (reason: string): void => {\n parser.repairs.unshift({ offset: this.index, kind: 'ambiguous', reason });\n };\n if (this.commentFragment) mark('fragment-in-comment-like-prose');\n if (this.failures > 0) mark('fragment-after-rejected-document');\n if (this.ambiguousScalarTail) mark('fragment-after-ambiguous-scalar');\n if (this.index < this.uriBoundaryEnd) mark('ambiguous-uri-boundary');\n }\n\n private reportExcerpt(offset: number, summary: string): void {\n const excerptEnd = Math.min(this.end, offset + MAX_DIAGNOSTIC_EXCERPT);\n const excerpt = JSON.stringify(this.text.slice(offset, excerptEnd));\n this.reportError(offset, `${summary} (${excerptEnd < this.end ? 'truncated excerpt' : 'excerpt'}): ${excerpt}`);\n }\n\n private reportError(offset: number, message: string): void {\n if (this.result.errors.length < MAX_ERRORS) this.result.errors.push({ offset, message });\n }\n}\n\nfunction isContainerStart(char: string | undefined): char is keyof typeof CLOSERS {\n return char === '{' || char === '[';\n}\n\nfunction scalarStart(text: string, start: number, end: number): boolean {\n const first = text[start];\n if (first === undefined) return false;\n const keyword = /^([A-Za-z]+)/.exec(text.slice(start, end))?.[1];\n return (\n first in QUOTES ||\n /[-\\d]/.test(first) ||\n (keyword !== undefined &&\n (Object.hasOwn(KEYWORDS, keyword) ||\n (Object.keys(KEYWORDS).some((word) => word.startsWith(keyword)) &&\n /^[^\\S\\r\\n]*(?:[\\r\\n]|$)/.test(text.slice(start + keyword.length, end)))))\n );\n}\n\nclass RecoveryParser {\n readonly repairs: JsonRepair[] = [];\n readonly text: string;\n readonly end: number;\n index: number;\n\n constructor(text: string, index: number, end: number) {\n this.text = text;\n this.index = index;\n this.end = end;\n }\n\n finishScalar(regionEnd: number, start: number): boolean {\n const valueEnd = this.index;\n const atom = this.text.slice(start, valueEnd);\n const bullet = atom === '-' && /\\s/.test(this.text[valueEnd] ?? '');\n const retainLiteral = this.text[start]! in QUOTES || this.hasRepair('unquoted-value');\n this.space();\n if (bullet) return false;\n if (this.index >= regionEnd) return true;\n if (/[\\r\\n]/.test(this.text.slice(valueEnd, this.index))) {\n this.repair('ambiguous', 'scalar-before-prose', valueEnd);\n return true;\n }\n if (/^\\d+[.)]$/.test(atom) && /[ \\t]/.test(this.text[valueEnd] ?? '')) return false;\n if (retainLiteral || /^[\\p{P}\\p{S}]/u.test(this.text.slice(this.index, regionEnd))) {\n this.repair('ambiguous', 'trailing-scalar-content', valueEnd);\n return true;\n }\n return false;\n }\n\n value(depth: number): string {\n if (depth > MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n this.space();\n const char = this.text[this.index];\n if (this.index >= this.end || char === ',' || char === '}' || char === ']') {\n this.repair('incomplete', 'missing-value');\n return 'null';\n }\n if (isContainerStart(char)) {\n if (depth >= MAX_DEPTH) throw new Error('JSON nesting exceeds 128 levels');\n return this.container(depth, char);\n }\n if (char !== undefined && char in QUOTES) return this.string(depth > 0 ? 'value' : 'root');\n const start = this.index;\n const uriEnd = unquotedUriEnd(this.text, start, this.end);\n if (uriEnd !== undefined) this.index = uriEnd;\n else\n while (\n this.index < this.end &&\n !/[\\s,}\\]]/.test(this.text[this.index]!) &&\n !(depth === 0 && /[{[]/.test(this.text[this.index]!)) &&\n !this.comment()\n )\n this.index++;\n if (this.index === start) throw new Error('Expected a JSON value');\n const token = this.text.slice(start, this.index);\n if (/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(token)) return token;\n if (Object.hasOwn(KEYWORDS, token)) {\n const canonical = KEYWORDS[token]!;\n if (canonical !== token) this.repair('syntax', 'python-keyword', start);\n return canonical;\n }\n this.repair(this.index >= this.end ? 'incomplete' : 'ambiguous', 'unquoted-value', start);\n return JSON.stringify(token);\n }\n\n private container(depth: number, open: keyof typeof CLOSERS): string {\n this.index++;\n const object = open === '{';\n const close = CLOSERS[open];\n const items: string[] = [];\n const keys = new Set<string>();\n let afterComma = false;\n let commaOffset = this.index;\n for (;;) {\n this.space();\n if (this.index >= this.end || this.text[this.index] === close) {\n if (this.index >= this.end) this.repair('incomplete', `missing-${close}`);\n else this.index++;\n if (afterComma) this.repair('syntax', 'trailing-comma', commaOffset);\n return open + items.join(',') + close;\n }\n if (this.text[this.index] === '}' || this.text[this.index] === ']') throw new Error('Mismatched closing bracket');\n if (this.text[this.index] === ',') {\n if (object) this.repair('ambiguous', 'extra-comma');\n else {\n items.push('null');\n this.repair('incomplete', 'missing-value');\n }\n commaOffset = this.index;\n afterComma = true;\n this.index++;\n continue;\n }\n items.push(object ? `${this.key(keys)}:${this.value(depth + 1)}` : this.value(depth + 1));\n this.space();\n afterComma = this.text[this.index] === ',';\n if (afterComma) {\n commaOffset = this.index;\n this.index++;\n } else if (this.index < this.end && this.text[this.index] !== close) this.repair('syntax', 'missing-comma');\n }\n }\n\n /** Parses an object key and the colon after it, returning the key as JSON. */\n private key(seen: Set<string>): string {\n const start = this.index;\n const key = this.text[start]! in QUOTES ? this.string() : this.unquotedKey();\n const decoded: string = JSON.parse(key);\n if (seen.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n seen.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n return key;\n }\n\n private unquotedKey(): string {\n const start = this.index;\n while (this.index < this.end && !/[\\s:,{}[\\]]/.test(this.text[this.index]!) && !this.comment()) this.index++;\n if (this.index === start) throw new Error('Expected an object key');\n const rawKey = this.text.slice(start, this.index);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n return JSON.stringify(rawKey);\n }\n\n private string(context: 'root' | 'key' | 'value' = 'key'): string {\n const start = this.index;\n const open = this.text[this.index++]!;\n const close = QUOTES[open]!;\n if (open !== '\"') this.repair('syntax', 'non-json-quote', start);\n let value = '';\n let tail = '';\n const append = (text: string): void => {\n value += text;\n tail = (tail + text).slice(-2);\n };\n let embeddedQuote = false;\n const family = '\"“”'.includes(open) ? '\"“”' : \"'‘’\";\n let alternative: { end: number; value: string; repairCount: number } | undefined;\n while (this.index < this.end) {\n const char = this.text[this.index++]!;\n if (\n \"'‘’\".includes(open) &&\n \"'’\".includes(char) &&\n /[\\p{L}\\p{N}]$/u.test(tail) &&\n /^[\\p{L}\\p{N}]/u.test(this.text.slice(this.index, this.end))\n ) {\n this.repair('ambiguous', 'literal-apostrophe', this.index - 1);\n append(char);\n continue;\n }\n if (family.includes(char)) {\n const after = this.charAfterSpace(this.index);\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char !== close) {\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n } else if (!embeddedQuote && context !== 'root' && alternative !== undefined && !delimited) {\n this.index = alternative.end;\n this.repairs.length = alternative.repairCount;\n this.repair('ambiguous', 'mismatched-quote', this.index - 1);\n return JSON.stringify(alternative.value);\n } else if (embeddedQuote || (context === 'value' && !delimited && this.opensEmbeddedQuote(close))) {\n embeddedQuote = !embeddedQuote;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n } else return JSON.stringify(value);\n }\n if (char === '\\\\') append(this.escapeSequence(open));\n else {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\n }\n\n /** Whether the closing quote just consumed and the next one more plausibly enclose a phrase quoted within the string. */\n private opensEmbeddedQuote(close: string): boolean {\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.charAfterSpace(nextClose + 1);\n return (\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) || (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n );\n }\n\n /** Decodes the escape sequence whose backslash was just consumed. */\n private escapeSequence(open: string): string {\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n return '\\\\';\n }\n const escape = this.text[this.index++]!;\n if (escape === 'u') {\n const hex = this.text.slice(this.index, Math.min(this.index + 4, this.end));\n if (/^[\\da-fA-F]{4}$/.test(hex)) {\n this.index += 4;\n return String.fromCodePoint(Number.parseInt(hex, 16));\n }\n this.repair(/^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous', 'invalid-unicode-escape', escapeOffset);\n return String.raw`\\u`;\n }\n if (String.raw`\"\\/bfnrt`.includes(escape)) return JSON.parse(`\"\\\\${escape}\"`) as string;\n if (escape === \"'\" && open === \"'\") return \"'\";\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n return `\\\\${escape}`;\n }\n\n private continuesStringAfterComma(start: number, quote: string): boolean {\n const parser = new RecoveryParser(this.text, start - 1, this.end);\n parser.string();\n const end = parser.index - 1;\n if (\n this.text[end] !== quote ||\n parser.repairs.some(\n (repair) => !['non-json-quote', 'literal-apostrophe', 'unescaped-control-character'].includes(repair.reason)\n )\n )\n return false;\n const continuation = this.text.slice(start, end);\n const after = this.charAfterSpace(end + 1);\n return (\n /^\\s*,\\s*[\\p{L}\\p{N}]/u.test(continuation) &&\n !/[\\\\:{}[\\]]/.test(continuation) &&\n (after === undefined || /[,}\\]]/.test(after))\n );\n }\n\n private startsKey(index: number): boolean {\n const parser = new RecoveryParser(this.text, index, this.end);\n parser.string();\n parser.space();\n return this.text[parser.index] === ':';\n }\n\n space(): void {\n while (this.index < this.end) {\n if (/\\s/.test(this.text[this.index]!)) {\n if (!/[ \\t\\r\\n]/.test(this.text[this.index]!)) this.repair('syntax', 'non-json-whitespace');\n this.index++;\n } else if (this.text.startsWith('//', this.index)) {\n this.repair('syntax', 'line-comment');\n while (this.index < this.end && !/[\\r\\n]/.test(this.text[this.index]!)) this.index++;\n } else if (this.text.startsWith('/*', this.index)) {\n const end = this.text.indexOf('*/', this.index + 2);\n this.repair(end === -1 || end >= this.end ? 'incomplete' : 'syntax', 'block-comment');\n this.index = end === -1 || end >= this.end ? this.end : end + 2;\n } else break;\n }\n }\n\n hasRepair(reason: string): boolean {\n return this.repairs.some((repair) => repair.reason === reason);\n }\n\n private charAfterSpace(index: number): string | undefined {\n return this.text.slice(index, this.end).trimStart()[0];\n }\n\n private repair(kind: JsonRepair['kind'], reason: string, offset = this.index): void {\n this.repairs.push({ offset, kind, reason });\n }\n\n private comment(): boolean {\n return this.text.startsWith('//', this.index) || this.text.startsWith('/*', this.index);\n }\n}\n\nfunction unquotedUriEnd(text: string, start: number, end: number): number | undefined {\n const match = /^[A-Za-z][A-Za-z\\d+.-]*:\\/\\//.exec(text.slice(start, end));\n if (match === null) return;\n let index = start + match[0].length;\n let brackets = 0;\n while (index < end && !/[\\s}]/.test(text[index]!)) {\n if (text[index] === ',' && brackets === 0) break;\n if (text[index] === '[') brackets++;\n else if (text[index] === ']') {\n if (brackets === 0) break;\n brackets--;\n }\n index++;\n }\n return index;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/shared-lib",
3
- "version": "10.19.2",
3
+ "version": "10.21.0",
4
4
  "description": "Shared library for WillBooster projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -47,16 +47,15 @@
47
47
  "@tsconfig/node-lts": "24.0.1",
48
48
  "@tsconfig/node-ts": "23.6.4",
49
49
  "@types/bun": "1.4.2",
50
- "@types/node": "26.6.4",
50
+ "@types/node": "26.6.5",
51
51
  "@willbooster/oxfmt-config": "1.2.2",
52
52
  "@willbooster/oxlint-config": "1.4.8",
53
- "@willbooster/wb": "22.23.1",
54
- "build-ts": "21.0.20",
55
- "oxfmt": "0.71.0",
56
- "oxlint": "1.86.0",
57
- "oxlint-tsgolint": "7.0.2003",
53
+ "@willbooster/wb": "22.26.2",
54
+ "build-ts": "21.0.27",
55
+ "oxfmt": "0.72.0",
56
+ "oxlint": "1.87.0",
57
+ "oxlint-tsgolint": "7.0.2004",
58
58
  "sort-package-json": "4.0.0",
59
- "typescript": "7.0.2",
60
59
  "yaml": "2.9.1"
61
60
  },
62
61
  "publishConfig": {