@willbooster/shared-lib 10.9.0 → 10.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +26 -0
- package/README.md +20 -0
- package/dist/githubTemplates.cjs +1 -1
- package/dist/githubTemplates.cjs.map +1 -1
- package/dist/githubTemplates.d.ts +2 -2
- package/dist/githubTemplates.js +1 -1
- package/dist/githubTemplates.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/recoverJson.cjs +4 -0
- package/dist/recoverJson.cjs.map +1 -0
- package/dist/recoverJson.d.ts +31 -0
- package/dist/recoverJson.js +3 -0
- package/dist/recoverJson.js.map +1 -0
- package/package.json +4 -3
package/NOTICE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@willbooster/shared-lib
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 WillBooster Inc. and contributors.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
JSON recovery implementation and selected test cases informed by jsonrepair:
|
|
18
|
+
https://github.com/josdejong/jsonrepair
|
|
19
|
+
|
|
20
|
+
The ISC License
|
|
21
|
+
|
|
22
|
+
Copyright (c) 2020-2026 by Jos de Jong
|
|
23
|
+
|
|
24
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
1
|
# @willbooster/shared-lib
|
|
2
|
+
|
|
3
|
+
`recoverJson(response)` extracts JSON candidates from text and Markdown without runtime dependencies. It repairs common syntax errors and recovers partial strings and containers. Each candidate includes its parsed `value`, serialized `json`, original `start`/`end` offsets, and `repairs` with original UTF-16 offsets. The range includes consumed source, such as trailing whitespace and removed comments; use `json` or `value`, not the source slice, for parsing.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { recoverJson } from '@willbooster/shared-lib';
|
|
7
|
+
|
|
8
|
+
const recovered = recoverJson(response);
|
|
9
|
+
// Show recovered candidates to an operator, including their repair annotations.
|
|
10
|
+
// Before automated action, validate your schema and check the conditions below.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`requiresConfirmation` marks incomplete or ambiguous repairs, including duplicate keys. A false value does not establish that an answer is correct or that the provider finished: callers must also check provider termination, extraction errors, multiple candidates, and their domain schema. Recovery never translates domain values or supplies missing evidence. Missing values are represented by JSON `null` with an incomplete repair annotation.
|
|
14
|
+
|
|
15
|
+
For a quoted scalar with ambiguous same-line trailing text, extraction diagnostics retain a JSON-escaped excerpt of that original tail (at most 256 UTF-16 units, with truncation indicated). This keeps context visible after a possibly premature quote closure without inventing another candidate or changing string boundaries. The excerpt may include values also recovered separately.
|
|
16
|
+
|
|
17
|
+
Unknown escape sequences and stray quotes inside unquoted keys retain their literal characters and require confirmation. Scalar starts are recognized at the region root, at physical line starts, and immediately after a consumed candidate, not at arbitrary positions within prose. Scalar extraction may omit same-line prose prefixes; a scalar retained with trailing non-comment content requires confirmation. Malformed numeric/keyword atoms such as `42.` or `true;` retain their spelling as uncertain strings, rather than guessing a number or boolean. Trailing supported comments are removed with provenance. Comment-like spans encountered within prose can instead contain operators or paths: values inside them are salvaged only as unconfirmed `fragment-in-comment-like-prose` candidates. Candidates starting inside a prose URI's whitespace-free token also require confirmation (`ambiguous-uri-boundary`), since they may be URI components, including template braces and bracketed query parameters.
|
|
18
|
+
|
|
19
|
+
Markdown boundaries delimit partial answers; ordinary fence info strings are metadata, while inline JSON after a `json` tag is also supported. A root object/array can retain literal fence lines inside its strings across those boundaries only when the extended document otherwise needs no repair except escaping raw control characters; that interpretation also requires confirmation. Bare root strings never extend across Markdown boundaries. After a structural rejection or a scalar with ambiguous same-line trailing content, subsequent values in the same region are salvaged only as unconfirmed fragments (`fragment-after-rejected-document` or `fragment-after-ambiguous-scalar`), never promoted to complete answers. They may be nested members or quoted examples. The extraction errors remain available; an explicit new Markdown region starts a fresh candidate boundary.
|
|
20
|
+
|
|
21
|
+
Inputs above one million UTF-16 code units and nesting above 128 levels produce errors. At most 32 candidates and 32 errors are returned; reaching the candidate cap adds a diagnostic that extraction may be incomplete. After 32 failed starts in one region, recovery skips its remainder but still processes later Markdown regions. JSONP, MongoDB constructors, and arbitrary JavaScript expressions are outside this API's scope. Upstream implementation and test attribution is included in `NOTICE`.
|
package/dist/githubTemplates.cjs
CHANGED
|
@@ -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, 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, which a simpler design may replace);
|
|
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.
|
|
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":[],"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, 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, which a simpler design may replace); copy the requester's instructions here as given, whether they came from an issue or a conversation, and keep the list when the body is later rewritten unless the requester's instructions changed\",\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: one line per requirement, taken from the requester's instructions as they were given (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, 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- Record rule: an existing Requirements section is a record, not a description of the diff. Keep its \\`required\\` lines as they are, rewriting them only when the requester's instructions changed (then from the updated instructions, dropping a line only when the requester removed it; with no instructions available, keep them unchanged); add a \\`chosen\\` line for a new decision, and replace or remove one when the decision it records changed. 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,MAAa,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,6cACJ,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,EAiBa,EAAkC,6/CAMlC,EAA0B;qFAAmC,IAa7D,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,EAQa,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,SAAgB,EAAuB,EAA8C,CACnF,OAAO,EAAS,IAAK,GAAY,OAAO,EAAQ,QAAQ,MAAM,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgB,EAAsB,EAA8C,CAClF,OAAO,EACJ,IACE,GACC,MAAM,EAAQ,QAAQ,WAAW,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
|
|
1
|
+
{"version":3,"file":"githubTemplates.cjs","names":[],"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,MAAa,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,EAiBa,EAAkC,y0DAMlC,EAA0B;qFAAmC,IAa7D,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,EAQa,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,SAAgB,EAAuB,EAA8C,CACnF,OAAO,EAAS,IAAK,GAAY,OAAO,EAAQ,QAAQ,MAAM,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgB,EAAsB,EAA8C,CAClF,OAAO,EACJ,IACE,GACC,MAAM,EAAQ,QAAQ,WAAW,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,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: one line per requirement, taken from the requester's instructions
|
|
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.";
|
|
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: one line per requirement, taken from the requester's instructions
|
|
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.";
|
|
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`.
|
package/dist/githubTemplates.js
CHANGED
|
@@ -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, 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, which a simpler design may replace);
|
|
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.
|
|
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":[],"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, 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, which a simpler design may replace); copy the requester's instructions here as given, whether they came from an issue or a conversation, and keep the list when the body is later rewritten unless the requester's instructions changed\",\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: one line per requirement, taken from the requester's instructions as they were given (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, 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- Record rule: an existing Requirements section is a record, not a description of the diff. Keep its \\`required\\` lines as they are, rewriting them only when the requester's instructions changed (then from the updated instructions, dropping a line only when the requester removed it; with no instructions available, keep them unchanged); add a \\`chosen\\` line for a new decision, and replace or remove one when the decision it records changed. 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,MAAa,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,6cACJ,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,EAiBa,EAAkC,6/CAMlC,EAA0B;qFAAmC,IAQ7D,EAAuB,qpBAKvB,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,EAQa,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,SAAgB,EAAuB,EAA8C,CACnF,OAAO,EAAS,IAAK,GAAY,OAAO,EAAQ,QAAQ,MAAM,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgB,EAAsB,EAA8C,CAClF,OAAO,EACJ,IACE,GACC,MAAM,EAAQ,QAAQ,WAAW,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
|
|
1
|
+
{"version":3,"file":"githubTemplates.js","names":[],"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,MAAa,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,EAiBa,EAAkC,y0DAMlC,EAA0B;qFAAmC,IAQ7D,EAAuB,qpBAKvB,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,EAQa,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,SAAgB,EAAuB,EAA8C,CACnF,OAAO,EAAS,IAAK,GAAY,OAAO,EAAQ,QAAQ,MAAM,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgB,EAAsB,EAA8C,CAClF,OAAO,EACJ,IACE,GACC,MAAM,EAAQ,QAAQ,WAAW,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./assert.cjs"),n=require("./githubTemplates.cjs"),r=require("./sleep.cjs"),i=require("./error.cjs"),a=require("./humanize.cjs"),o=require("./mail.cjs"),s=require("./markdown.cjs"),c=require("./parseCommandLineArgs.cjs"),l=require("./text.cjs"),u=require("./prompt.cjs"),d=require("./promptFormatters.cjs"),f=require("./shuffle.cjs"),p=require("./
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./appEnv.cjs"),t=require("./assert.cjs"),n=require("./githubTemplates.cjs"),r=require("./sleep.cjs"),i=require("./error.cjs"),a=require("./humanize.cjs"),o=require("./mail.cjs"),s=require("./markdown.cjs"),c=require("./parseCommandLineArgs.cjs"),l=require("./text.cjs"),u=require("./prompt.cjs"),d=require("./promptFormatters.cjs"),f=require("./shuffle.cjs"),p=require("./recoverJson.cjs"),m=require("./sqlite.cjs"),h=require("./testingRules.cjs"),g=require("./zenkaku.cjs");exports.BUG_ISSUE_SECTIONS=n.BUG_ISSUE_SECTIONS,exports.CHANGE_ISSUE_SECTIONS=n.CHANGE_ISSUE_SECTIONS,exports.ISSUE_TEMPLATE_RULES=n.ISSUE_TEMPLATE_RULES,exports.PULL_REQUEST_BODY_RULES=n.PULL_REQUEST_BODY_RULES,exports.PULL_REQUEST_REQUIREMENTS_RULES=n.PULL_REQUEST_REQUIREMENTS_RULES,exports.PULL_REQUEST_SECTIONS=n.PULL_REQUEST_SECTIONS,exports.TEST_WRITING_RULES=h.TEST_WRITING_RULES,exports.ensureTruthy=t.ensureTruthy,exports.errorify=i.errorify,exports.escapePromptTag=u.escapePromptTag,exports.escapeRegExp=l.escapeRegExp,exports.extractCodeBlocks=s.extractCodeBlocks,exports.extractIfSingleOutermostCodeBlock=s.extractIfSingleOutermostCodeBlock,exports.extractSections=s.extractSections,exports.formatFilesForPrompt=d.formatFilesForPrompt,exports.formatMessagesForPrompt=d.formatMessagesForPrompt,exports.formatPrompt=u.formatPrompt,exports.getAppEnv=e.getAppEnv,exports.getConnectionLevelSqlitePragmas=m.getConnectionLevelSqlitePragmas,exports.getPersistentSqlitePragmas=m.getPersistentSqlitePragmas,exports.humanizeNumber=a.humanizeNumber,exports.ignoreEnoent=i.ignoreEnoent,exports.ignoreEnoentAsync=i.ignoreEnoentAsync,exports.ignoreError=i.ignoreError,exports.ignoreErrorAsync=i.ignoreErrorAsync,exports.mailTemplates=o.mailTemplates,exports.parseCommandLineArgs=c.parseCommandLineArgs,exports.parseMarkdownSections=s.parseMarkdownSections,exports.quoteForShell=l.quoteForShell,exports.recoverJson=p.recoverJson,exports.renderSectionChecklist=n.renderSectionChecklist,exports.renderSectionTemplate=n.renderSectionTemplate,exports.serializeForPrompt=u.serializeForPrompt,exports.serializeForPromptInTag=u.serializeForPromptInTag,exports.shuffle=f.shuffle,exports.sleep=r.sleep,exports.toCodeBlock=l.toCodeBlock,exports.toTildeCodeBlock=l.toTildeCodeBlock,exports.truncateForPrompt=u.truncateForPrompt,exports.withRetry=i.withRetry,exports.zenkakuAlphanumericalsToHankaku=g.zenkakuAlphanumericalsToHankaku;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export { parseCommandLineArgs } from './parseCommandLineArgs.js';
|
|
|
9
9
|
export { escapePromptTag, formatPrompt, serializeForPrompt, serializeForPromptInTag, truncateForPrompt, } from './prompt.js';
|
|
10
10
|
export { formatFilesForPrompt, formatMessagesForPrompt } from './promptFormatters.js';
|
|
11
11
|
export { shuffle } from './shuffle.js';
|
|
12
|
+
export { recoverJson } from './recoverJson.js';
|
|
13
|
+
export type { JsonRepair, RecoveredJson, JsonRecovery } from './recoverJson.js';
|
|
12
14
|
export { sleep } from './sleep.js';
|
|
13
15
|
export { getConnectionLevelSqlitePragmas, getPersistentSqlitePragmas } from './sqlite.js';
|
|
14
16
|
export { escapeRegExp, quoteForShell, toCodeBlock, toTildeCodeBlock } from './text.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAppEnv as e}from"./appEnv.js";import{ensureTruthy as t}from"./assert.js";import{BUG_ISSUE_SECTIONS as n,CHANGE_ISSUE_SECTIONS as r,ISSUE_TEMPLATE_RULES as i,PULL_REQUEST_BODY_RULES as a,PULL_REQUEST_REQUIREMENTS_RULES as o,PULL_REQUEST_SECTIONS as s,renderSectionChecklist as c,renderSectionTemplate as l}from"./githubTemplates.js";import{sleep as u}from"./sleep.js";import{errorify as d,ignoreEnoent as f,ignoreEnoentAsync as p,ignoreError as m,ignoreErrorAsync as h,withRetry as g}from"./error.js";import{humanizeNumber as _}from"./humanize.js";import{mailTemplates as v}from"./mail.js";import{extractCodeBlocks as y,extractIfSingleOutermostCodeBlock as b,extractSections as x,parseMarkdownSections as S}from"./markdown.js";import{parseCommandLineArgs as C}from"./parseCommandLineArgs.js";import{escapeRegExp as w,quoteForShell as T,toCodeBlock as E,toTildeCodeBlock as D}from"./text.js";import{escapePromptTag as O,formatPrompt as k,serializeForPrompt as A,serializeForPromptInTag as j,truncateForPrompt as M}from"./prompt.js";import{formatFilesForPrompt as N,formatMessagesForPrompt as P}from"./promptFormatters.js";import{shuffle as F}from"./shuffle.js";import{getConnectionLevelSqlitePragmas as
|
|
1
|
+
import{getAppEnv as e}from"./appEnv.js";import{ensureTruthy as t}from"./assert.js";import{BUG_ISSUE_SECTIONS as n,CHANGE_ISSUE_SECTIONS as r,ISSUE_TEMPLATE_RULES as i,PULL_REQUEST_BODY_RULES as a,PULL_REQUEST_REQUIREMENTS_RULES as o,PULL_REQUEST_SECTIONS as s,renderSectionChecklist as c,renderSectionTemplate as l}from"./githubTemplates.js";import{sleep as u}from"./sleep.js";import{errorify as d,ignoreEnoent as f,ignoreEnoentAsync as p,ignoreError as m,ignoreErrorAsync as h,withRetry as g}from"./error.js";import{humanizeNumber as _}from"./humanize.js";import{mailTemplates as v}from"./mail.js";import{extractCodeBlocks as y,extractIfSingleOutermostCodeBlock as b,extractSections as x,parseMarkdownSections as S}from"./markdown.js";import{parseCommandLineArgs as C}from"./parseCommandLineArgs.js";import{escapeRegExp as w,quoteForShell as T,toCodeBlock as E,toTildeCodeBlock as D}from"./text.js";import{escapePromptTag as O,formatPrompt as k,serializeForPrompt as A,serializeForPromptInTag as j,truncateForPrompt as M}from"./prompt.js";import{formatFilesForPrompt as N,formatMessagesForPrompt as P}from"./promptFormatters.js";import{shuffle as F}from"./shuffle.js";import{recoverJson as I}from"./recoverJson.js";import{getConnectionLevelSqlitePragmas as L,getPersistentSqlitePragmas as R}from"./sqlite.js";import{TEST_WRITING_RULES as z}from"./testingRules.js";import{zenkakuAlphanumericalsToHankaku as B}from"./zenkaku.js";export{n as BUG_ISSUE_SECTIONS,r as CHANGE_ISSUE_SECTIONS,i as ISSUE_TEMPLATE_RULES,a as PULL_REQUEST_BODY_RULES,o as PULL_REQUEST_REQUIREMENTS_RULES,s as PULL_REQUEST_SECTIONS,z as TEST_WRITING_RULES,t as ensureTruthy,d as errorify,O as escapePromptTag,w as escapeRegExp,y as extractCodeBlocks,b as extractIfSingleOutermostCodeBlock,x as extractSections,N as formatFilesForPrompt,P as formatMessagesForPrompt,k as formatPrompt,e as getAppEnv,L as getConnectionLevelSqlitePragmas,R as getPersistentSqlitePragmas,_ as humanizeNumber,f as ignoreEnoent,p as ignoreEnoentAsync,m as ignoreError,h as ignoreErrorAsync,v as mailTemplates,C as parseCommandLineArgs,S as parseMarkdownSections,T as quoteForShell,I as recoverJson,c as renderSectionChecklist,l as renderSectionTemplate,A as serializeForPrompt,j as serializeForPromptInTag,F as shuffle,u as sleep,E as toCodeBlock,D as toTildeCodeBlock,M as truncateForPrompt,g as withRetry,B as zenkakuAlphanumericalsToHankaku};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */
|
|
3
|
+
const e=1e6,t={'"':`"`,"'":`'`,"“":`”`,"”":`”`,"‘":`’`,"’":`’`},n={true:`true`,false:`false`,null:`null`,True:`true`,False:`false`,None:`null`};function r(t){let n={candidates:[],errors:[]};if(t.length>e)return n.errors.push({offset:e,message:`JSON recovery input exceeds one million characters`}),n;let r=[...t.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(e=>{let n=e[1],r=e.index+e[0].indexOf(n)+n.length,i=e.index+e[0].length,o=t.slice(r,i),s=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(o),c=s===null?i:r+s[0].length,l=t[c]===`{`||t[c]===`[`||a(t,c,i)?c:i;return n[0]==="`"&&l===i&&o.includes("`")?[]:[{index:e.index,marker:n,start:l}]});if(r.length>0){let e=0;for(let a of r){if(a.index<e)continue;i(t,e,a.index,n);let o=n.candidates.at(-1)?.end??e;if(o>a.index){e=o;continue}let{marker:s,start:c}=a,l=RegExp(`^ {0,3}${s[0]}{${s.length},}[ \\t]*$`,`gm`);l.lastIndex=c;let u=l.exec(t),d=u?.index??t.length;i(t,c,d,n);let f=n.candidates.at(-1)?.end??c;if(f>d){l.lastIndex=f;let a=l.exec(t);if(a!==null&&!r.some(e=>e.index>=f&&e.index<a.index)){i(t,f,a.index,n),e=a.index+a[0].length;continue}}e=Math.max(n.candidates.at(-1)?.end??c,u===null?t.length:u.index+u[0].length)}i(t,e,t.length,n)}else i(t,0,t.length,n);if(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 i(e,n,r,c,l=!1){if(c.candidates.length>=32)return;let u=n,d=0,f=!1,p=!0,m=n,h=n,g=n;for(;u<r&&/\s/.test(e[u]);)u++;let _=u,v=new o(e,u,r);l||v.space();let y=v.index;if(y>=r){v.repairs.some(e=>e.kind===`incomplete`)&&c.errors.length<32&&c.errors.push({offset:u,message:`Incomplete leading JSON comment`});return}let b=e[y],x=a(e,y,r)||b===`{`||b===`[`;for(x||(u=y);u<r&&c.candidates.length<32&&d<32;){if(!x||u!==_)for(;u<r&&e[u]!==`{`&&e[u]!==`[`&&!(p&&a(e,u,r));){let t=u===n||!/[\w+.-]/.test(e[u-1])?s(e,u,r):void 0;if(t!==void 0){if(u>=h){let t=e.slice(u,r).search(/\s/);h=t===-1?r:u+t,g=u}if(u>=g){let t=e.slice(u,h).search(/[{[]/);g=t===-1?h:u+t}g<h&&(m=Math.max(m,h)),u=Math.min(t,g),p=!1;continue}if(!l&&e[u]===`/`){let t=new o(e,u,r);if(t.space(),t.index>u){t.repairs.some(e=>e.kind===`incomplete`)&&c.errors.length<32&&c.errors.push({offset:u,message:`Possibly unterminated comment-like span in prose`}),i(e,u+2,t.index,c,!0),p||=/[\r\n]/.test(e.slice(u,t.index)),u=t.index;continue}}/[\r\n]/.test(e[u])?p=!0:/[\s,]/.test(e[u])||(p=!1),u++}if(u>=r||c.candidates.length>=32)break;let y=x&&u===_?v:new o(e,u,r),b=y.index;try{let n=y.value(0);if(!l&&(e[b]===`{`||e[b]===`[`)&&y.index===r&&r<e.length){let t=new o(e,u,e.length);try{let e=t.value(0);t.index>r&&t.repairs.every(e=>e.reason===`unescaped-control-character`)&&(t.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),y=t,n=e)}catch{}}let i=y.index;if(e[b]!==`{`&&e[b]!==`[`&&!y.finishScalar(r,b)){p=!1,u=i;continue}if(y.space(),!l&&d===0&&y.index<r&&/[}\]]/.test(e[y.index])){let t=y.index;for(;y.index<r&&/[}\]]/.test(e[y.index]);)y.repairs.push({offset:y.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),y.index++,y.space();if(c.errors.length<32){let n=Math.min(r,t+256);c.errors.push({offset:t,message:`Surplus closing brackets and possible continuation (${n<r?`truncated excerpt`:`excerpt`}): ${JSON.stringify(e.slice(t,n))}`})}}if(e[b]in t&&y.repairs.some(e=>e.reason===`trailing-scalar-content`)&&c.errors.length<32){let t=Math.min(r,i+256);c.errors.push({offset:i,message:`Ambiguous quoted-scalar tail (${t<r?`truncated excerpt`:`excerpt`}): ${JSON.stringify(e.slice(i,t))}`})}l&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-in-comment-like-prose`}),d>0&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-after-rejected-document`}),f&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-after-ambiguous-scalar`}),u<m&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`ambiguous-uri-boundary`}),f||=y.repairs.some(e=>e.reason===`trailing-scalar-content`),c.candidates.push({value:JSON.parse(n),json:n,start:u,end:y.index,repairs:y.repairs,requiresConfirmation:y.repairs.some(e=>e.kind!==`syntax`)})}catch(e){c.errors.length<32&&c.errors.push({offset:y.index,message:e instanceof Error?e.message:String(e)}),d++,u=b+1,p=!1;continue}u=Math.max(u+1,y.index),p=!0}}function a(e,r,i){let a=e[r];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(r,i))?.[1];return a in t||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(n,o)||Object.keys(n).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(r+o.length,i)))}var o=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,n){let r=this.index,i=this.text.slice(n,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[n]in t||this.repairs.some(e=>e.reason===`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 r=this.text[this.index];if(this.index>=this.end||r===`,`||r===`}`||r===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(r===`{`||r===`[`){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,r===`{`)}if(r!==void 0&&r in t)return this.string(e>0?`value`:`root`);let i=this.index,a=s(this.text,i,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===i)throw Error(`Expected a JSON value`);let o=this.text.slice(i,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(n,o)){let e=n[o];return e!==o&&this.repair(`syntax`,`python-keyword`,i),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,i),JSON.stringify(o)}container(e,n){this.index++;let r=n?`}`:`]`,i=[],a=new Set,o=!1,s=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===r)return this.index>=this.end?this.repair(`incomplete`,`missing-${r}`):this.index++,o&&this.repair(`syntax`,`trailing-comma`,s),(n?`{`:`[`)+i.join(`,`)+r;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`):(i.push(`null`),this.repair(`incomplete`,`missing-value`)),s=this.index,o=!0,this.index++;continue}let c;if(n){let e=this.index;if(this.text[this.index]in t)c=this.string();else{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);c=JSON.stringify(t),this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e)}let n=JSON.parse(c);a.has(n)&&this.repair(`ambiguous`,`duplicate-key`,e),a.add(n),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`)}let l=this.value(e+1);i.push(c===void 0?l:`${c}:${l}`),this.space(),o=this.text[this.index]===`,`,o?(s=this.index,this.index++):this.index<this.end&&this.text[this.index]!==r&&this.repair(`syntax`,`missing-comma`)}}string(e=`key`){let n=this.index,r=this.text[this.index++],i=t[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,n);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.text.slice(this.index,this.end).trimStart()[0],r=n===void 0||/[,}\]:"']/.test(n);if(t===i){if(c){c=!1,this.repair(`ambiguous`,`unescaped-quote`,this.index-1),s(t);continue}if(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);let n=this.text.indexOf(i,this.index),o=this.text.slice(n+1,this.end).trimStart()[0];if(e===`value`&&!r&&!/\s/.test(this.text[this.index]??``)&&n>this.index&&n<this.end&&o!==void 0&&(!/[,}:\]]/.test(o)||o===`,`&&this.continuesStringAfterComma(n+1,i))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,n))&&!this.startsKey(n)){c=!0,this.repair(`ambiguous`,`unescaped-quote`,this.index-1),s(t);continue}return JSON.stringify(a)}r&&(u??={end:this.index,value:a,repairCount:this.repairs.length})}if(t!==`\\`){t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t);continue}let n=this.index-1;if(this.index>=this.end){s(`\\`),this.repair(`incomplete`,`truncated-escape`,n);break}let d=this.text[this.index++];if(d===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));/^[\da-fA-F]{4}$/.test(e)?(s(String.fromCodePoint(Number.parseInt(e,16))),this.index+=4):(s(String.raw`\u`),this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,n))}else String.raw`"\/bfnrt`.includes(d)?s(JSON.parse(`"\\${d}"`)):d===`'`&&r===`'`?s(`'`):(s(`\\${d}`),this.repair(`ambiguous`,`invalid-escape`,n))}return this.repair(`incomplete`,`unterminated-string`,n),JSON.stringify(a)}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.text.slice(i+1,this.end).trimStart()[0];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}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 s(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=r;
|
|
4
|
+
//# sourceMappingURL=recoverJson.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverJson.cjs","names":[],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\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 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 = [...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 text[inlineStart] === '{' || text[inlineStart] === '[' || scalarStart(text, inlineStart, lineEnd)\n ? inlineStart\n : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n if (fences.length > 0) {\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index < consumed) continue;\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) {\n consumed = parsedThrough;\n continue;\n }\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 consumed = outerClose.index + outerClose[0].length;\n continue;\n }\n }\n consumed = Math.max(\n result.candidates.at(-1)?.end ?? start,\n match === null ? text.length : match.index + match[0].length\n );\n }\n extractRegion(text, consumed, text.length, result);\n } else {\n extractRegion(text, 0, text.length, result);\n }\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\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length >= MAX_CANDIDATES) return;\n let index = start;\n let failures = 0;\n let ambiguousScalarTail = false;\n let scalarBoundary = true;\n let uriBoundaryEnd = start;\n let uriTokenEnd = start;\n let uriContainerStart = start;\n while (index < end && /\\s/.test(text[index]!)) index++;\n const firstIndex = index;\n const initialParser = new RecoveryParser(text, index, end);\n if (!commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Incomplete leading JSON comment' });\n return;\n }\n const first = text[initialValueStart];\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const rootValue = scalarStart(text, initialValueStart, end);\n const initialValue = rootValue || first === '{' || first === '[';\n if (!initialValue) index = initialValueStart;\n while (index < end && result.candidates.length < MAX_CANDIDATES && failures < MAX_ERRORS) {\n if (!initialValue || index !== firstIndex) {\n while (index < end && text[index] !== '{' && text[index] !== '[') {\n if (scalarBoundary && scalarStart(text, index, end)) break;\n const uriEnd =\n index === start || !/[\\w+.-]/.test(text[index - 1]!) ? unquotedUriEnd(text, index, end) : undefined;\n if (uriEnd !== undefined) {\n if (index >= uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n uriContainerStart = index;\n }\n if (index >= uriContainerStart) {\n const container = text.slice(index, uriTokenEnd).search(/[{[]/);\n uriContainerStart = container === -1 ? uriTokenEnd : index + container;\n }\n if (uriContainerStart < uriTokenEnd) uriBoundaryEnd = Math.max(uriBoundaryEnd, uriTokenEnd);\n index = Math.min(uriEnd, uriContainerStart);\n scalarBoundary = false;\n continue;\n }\n if (!commentFragment && text[index] === '/') {\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index > index) {\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Possibly unterminated comment-like span in prose' });\n extractRegion(text, index + 2, trivia.index, result, true);\n scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n index = trivia.index;\n continue;\n }\n }\n if (/[\\r\\n]/.test(text[index]!)) scalarBoundary = true;\n else if (!/[\\s,]/.test(text[index]!)) scalarBoundary = false;\n index++;\n }\n }\n if (index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n let parser = initialValue && index === firstIndex ? initialParser : new RecoveryParser(text, index, end);\n const valueStart = parser.index;\n try {\n let json = parser.value(0);\n if (\n !commentFragment &&\n (text[valueStart] === '{' || text[valueStart] === '[') &&\n parser.index === end &&\n end < text.length\n ) {\n const extended = new RecoveryParser(text, index, text.length);\n try {\n const extendedJson = extended.value(0);\n if (\n extended.index > end &&\n extended.repairs.every((repair) => repair.reason === 'unescaped-control-character')\n ) {\n extended.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n parser = extended;\n json = extendedJson;\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n }\n const valueEnd = parser.index;\n if (text[valueStart] !== '{' && text[valueStart] !== '[' && !parser.finishScalar(end, valueStart)) {\n scalarBoundary = false;\n index = valueEnd;\n continue;\n }\n parser.space();\n if (!commentFragment && failures === 0 && parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n const surplusStart = parser.index;\n while (parser.index < end && /[}\\]]/.test(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 (result.errors.length < MAX_ERRORS) {\n const excerptEnd = Math.min(end, surplusStart + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: surplusStart,\n message: `Surplus closing brackets and possible continuation (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(surplusStart, excerptEnd))}`,\n });\n }\n }\n if (\n text[valueStart]! in QUOTES &&\n parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content') &&\n result.errors.length < MAX_ERRORS\n ) {\n const excerptEnd = Math.min(end, valueEnd + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: valueEnd,\n message: `Ambiguous quoted-scalar tail (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(valueEnd, excerptEnd))}`,\n });\n }\n if (commentFragment)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-in-comment-like-prose' });\n if (failures > 0)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-rejected-document' });\n if (ambiguousScalarTail)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-ambiguous-scalar' });\n if (index < uriBoundaryEnd)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'ambiguous-uri-boundary' });\n ambiguousScalarTail ||= parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content');\n 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 if (result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: parser.index, message: error instanceof Error ? error.message : String(error) });\n failures++;\n index = valueStart + 1;\n scalarBoundary = false;\n continue;\n }\n index = Math.max(index + 1, parser.index);\n scalarBoundary = true;\n }\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 =\n this.text[start]! in QUOTES || this.repairs.some((repair) => repair.reason === '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 (char === '{' || 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, object: boolean): string {\n this.index++;\n const close = object ? '}' : ']';\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 (object ? '{' : '[') + 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 let key: string | undefined;\n if (object) {\n const start = this.index;\n if (this.text[this.index]! in QUOTES) key = this.string();\n else {\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 key = JSON.stringify(rawKey);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n }\n const decoded: string = JSON.parse(key);\n if (keys.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n keys.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n }\n const value = this.value(depth + 1);\n items.push(key === undefined ? value : `${key}:${value}`);\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 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.text.slice(this.index, this.end).trimStart()[0];\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char === close) {\n if (embeddedQuote) {\n embeddedQuote = false;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n if (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 }\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.text.slice(nextClose + 1, this.end).trimStart()[0];\n if (\n context === 'value' &&\n !delimited &&\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) ||\n (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n ) {\n embeddedQuote = true;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n return JSON.stringify(value);\n }\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n }\n if (char !== '\\\\') {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n continue;\n }\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n append('\\\\');\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n break;\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 append(String.fromCodePoint(Number.parseInt(hex, 16)));\n this.index += 4;\n } else {\n append(String.raw`\\u`);\n this.repair(\n /^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous',\n 'invalid-unicode-escape',\n escapeOffset\n );\n }\n } else if (String.raw`\"\\/bfnrt`.includes(escape)) {\n append(JSON.parse(`\"\\\\${escape}\"`) as string);\n } else if (escape === \"'\" && open === \"'\") append(\"'\");\n else {\n append(`\\\\${escape}`);\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\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.text.slice(end + 1, this.end).trimStart()[0];\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 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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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */
|
|
2
|
+
export interface JsonRepair {
|
|
3
|
+
/** UTF-16 offset in the original response. */
|
|
4
|
+
offset: number;
|
|
5
|
+
kind: 'syntax' | 'incomplete' | 'ambiguous';
|
|
6
|
+
reason: string;
|
|
7
|
+
}
|
|
8
|
+
export interface RecoveredJson {
|
|
9
|
+
value: unknown;
|
|
10
|
+
json: string;
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
repairs: JsonRepair[];
|
|
14
|
+
/** Missing content or an ambiguous interpretation requires confirmation before acting on this value. */
|
|
15
|
+
requiresConfirmation: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface JsonRecovery {
|
|
18
|
+
candidates: RecoveredJson[];
|
|
19
|
+
errors: {
|
|
20
|
+
offset: number;
|
|
21
|
+
message: string;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Extracts JSON values from a response, repairing common LLM syntax and retaining repair provenance.
|
|
26
|
+
* Offsets refer to the original string. All candidates are returned: choosing among multiple answers,
|
|
27
|
+
* schema validation, and provider truncation signals belong to the caller. No schema values are coerced.
|
|
28
|
+
* Bounded to one million UTF-16 code units, 128 nesting levels, and 32 candidates/errors each.
|
|
29
|
+
* A region is abandoned after 32 failed starts; later Markdown regions can still yield candidates.
|
|
30
|
+
*/
|
|
31
|
+
export declare function recoverJson(text: string): JsonRecovery;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */
|
|
2
|
+
const e=1e6,t={'"':`"`,"'":`'`,"“":`”`,"”":`”`,"‘":`’`,"’":`’`},n={true:`true`,false:`false`,null:`null`,True:`true`,False:`false`,None:`null`};function r(t){let n={candidates:[],errors:[]};if(t.length>e)return n.errors.push({offset:e,message:`JSON recovery input exceeds one million characters`}),n;let r=[...t.matchAll(/^(?: {0,3})(`{3,}|~{3,})[^\r\n]*(?:\r\n|[\r\n]|$)/gm)].flatMap(e=>{let n=e[1],r=e.index+e[0].indexOf(n)+n.length,i=e.index+e[0].length,o=t.slice(r,i),s=/^[ \t]*json(?=[ \t{["'“”‘’])[ \t]*/i.exec(o),c=s===null?i:r+s[0].length,l=t[c]===`{`||t[c]===`[`||a(t,c,i)?c:i;return n[0]==="`"&&l===i&&o.includes("`")?[]:[{index:e.index,marker:n,start:l}]});if(r.length>0){let e=0;for(let a of r){if(a.index<e)continue;i(t,e,a.index,n);let o=n.candidates.at(-1)?.end??e;if(o>a.index){e=o;continue}let{marker:s,start:c}=a,l=RegExp(`^ {0,3}${s[0]}{${s.length},}[ \\t]*$`,`gm`);l.lastIndex=c;let u=l.exec(t),d=u?.index??t.length;i(t,c,d,n);let f=n.candidates.at(-1)?.end??c;if(f>d){l.lastIndex=f;let a=l.exec(t);if(a!==null&&!r.some(e=>e.index>=f&&e.index<a.index)){i(t,f,a.index,n),e=a.index+a[0].length;continue}}e=Math.max(n.candidates.at(-1)?.end??c,u===null?t.length:u.index+u[0].length)}i(t,e,t.length,n)}else i(t,0,t.length,n);if(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 i(e,n,r,c,l=!1){if(c.candidates.length>=32)return;let u=n,d=0,f=!1,p=!0,m=n,h=n,g=n;for(;u<r&&/\s/.test(e[u]);)u++;let _=u,v=new o(e,u,r);l||v.space();let y=v.index;if(y>=r){v.repairs.some(e=>e.kind===`incomplete`)&&c.errors.length<32&&c.errors.push({offset:u,message:`Incomplete leading JSON comment`});return}let b=e[y],x=a(e,y,r)||b===`{`||b===`[`;for(x||(u=y);u<r&&c.candidates.length<32&&d<32;){if(!x||u!==_)for(;u<r&&e[u]!==`{`&&e[u]!==`[`&&!(p&&a(e,u,r));){let t=u===n||!/[\w+.-]/.test(e[u-1])?s(e,u,r):void 0;if(t!==void 0){if(u>=h){let t=e.slice(u,r).search(/\s/);h=t===-1?r:u+t,g=u}if(u>=g){let t=e.slice(u,h).search(/[{[]/);g=t===-1?h:u+t}g<h&&(m=Math.max(m,h)),u=Math.min(t,g),p=!1;continue}if(!l&&e[u]===`/`){let t=new o(e,u,r);if(t.space(),t.index>u){t.repairs.some(e=>e.kind===`incomplete`)&&c.errors.length<32&&c.errors.push({offset:u,message:`Possibly unterminated comment-like span in prose`}),i(e,u+2,t.index,c,!0),p||=/[\r\n]/.test(e.slice(u,t.index)),u=t.index;continue}}/[\r\n]/.test(e[u])?p=!0:/[\s,]/.test(e[u])||(p=!1),u++}if(u>=r||c.candidates.length>=32)break;let y=x&&u===_?v:new o(e,u,r),b=y.index;try{let n=y.value(0);if(!l&&(e[b]===`{`||e[b]===`[`)&&y.index===r&&r<e.length){let t=new o(e,u,e.length);try{let e=t.value(0);t.index>r&&t.repairs.every(e=>e.reason===`unescaped-control-character`)&&(t.repairs.push({offset:r,kind:`ambiguous`,reason:`literal-fence-in-string`}),y=t,n=e)}catch{}}let i=y.index;if(e[b]!==`{`&&e[b]!==`[`&&!y.finishScalar(r,b)){p=!1,u=i;continue}if(y.space(),!l&&d===0&&y.index<r&&/[}\]]/.test(e[y.index])){let t=y.index;for(;y.index<r&&/[}\]]/.test(e[y.index]);)y.repairs.push({offset:y.index,kind:`ambiguous`,reason:`surplus-closing-bracket`}),y.index++,y.space();if(c.errors.length<32){let n=Math.min(r,t+256);c.errors.push({offset:t,message:`Surplus closing brackets and possible continuation (${n<r?`truncated excerpt`:`excerpt`}): ${JSON.stringify(e.slice(t,n))}`})}}if(e[b]in t&&y.repairs.some(e=>e.reason===`trailing-scalar-content`)&&c.errors.length<32){let t=Math.min(r,i+256);c.errors.push({offset:i,message:`Ambiguous quoted-scalar tail (${t<r?`truncated excerpt`:`excerpt`}): ${JSON.stringify(e.slice(i,t))}`})}l&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-in-comment-like-prose`}),d>0&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-after-rejected-document`}),f&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`fragment-after-ambiguous-scalar`}),u<m&&y.repairs.unshift({offset:u,kind:`ambiguous`,reason:`ambiguous-uri-boundary`}),f||=y.repairs.some(e=>e.reason===`trailing-scalar-content`),c.candidates.push({value:JSON.parse(n),json:n,start:u,end:y.index,repairs:y.repairs,requiresConfirmation:y.repairs.some(e=>e.kind!==`syntax`)})}catch(e){c.errors.length<32&&c.errors.push({offset:y.index,message:e instanceof Error?e.message:String(e)}),d++,u=b+1,p=!1;continue}u=Math.max(u+1,y.index),p=!0}}function a(e,r,i){let a=e[r];if(a===void 0)return!1;let o=/^([A-Za-z]+)/.exec(e.slice(r,i))?.[1];return a in t||/[-\d]/.test(a)||o!==void 0&&(Object.hasOwn(n,o)||Object.keys(n).some(e=>e.startsWith(o))&&/^[^\S\r\n]*(?:[\r\n]|$)/.test(e.slice(r+o.length,i)))}var o=class e{repairs=[];text;end;index;constructor(e,t,n){this.text=e,this.index=t,this.end=n}finishScalar(e,n){let r=this.index,i=this.text.slice(n,r),a=i===`-`&&/\s/.test(this.text[r]??``),o=this.text[n]in t||this.repairs.some(e=>e.reason===`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 r=this.text[this.index];if(this.index>=this.end||r===`,`||r===`}`||r===`]`)return this.repair(`incomplete`,`missing-value`),`null`;if(r===`{`||r===`[`){if(e>=128)throw Error(`JSON nesting exceeds 128 levels`);return this.container(e,r===`{`)}if(r!==void 0&&r in t)return this.string(e>0?`value`:`root`);let i=this.index,a=s(this.text,i,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===i)throw Error(`Expected a JSON value`);let o=this.text.slice(i,this.index);if(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(o))return o;if(Object.hasOwn(n,o)){let e=n[o];return e!==o&&this.repair(`syntax`,`python-keyword`,i),e}return this.repair(this.index>=this.end?`incomplete`:`ambiguous`,`unquoted-value`,i),JSON.stringify(o)}container(e,n){this.index++;let r=n?`}`:`]`,i=[],a=new Set,o=!1,s=this.index;for(;;){if(this.space(),this.index>=this.end||this.text[this.index]===r)return this.index>=this.end?this.repair(`incomplete`,`missing-${r}`):this.index++,o&&this.repair(`syntax`,`trailing-comma`,s),(n?`{`:`[`)+i.join(`,`)+r;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`):(i.push(`null`),this.repair(`incomplete`,`missing-value`)),s=this.index,o=!0,this.index++;continue}let c;if(n){let e=this.index;if(this.text[this.index]in t)c=this.string();else{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);c=JSON.stringify(t),this.repair(/["'“”‘’]/.test(t)?`ambiguous`:`syntax`,`unquoted-key`,e)}let n=JSON.parse(c);a.has(n)&&this.repair(`ambiguous`,`duplicate-key`,e),a.add(n),this.space(),this.text[this.index]===`:`?this.index++:this.repair(`ambiguous`,`missing-colon`)}let l=this.value(e+1);i.push(c===void 0?l:`${c}:${l}`),this.space(),o=this.text[this.index]===`,`,o?(s=this.index,this.index++):this.index<this.end&&this.text[this.index]!==r&&this.repair(`syntax`,`missing-comma`)}}string(e=`key`){let n=this.index,r=this.text[this.index++],i=t[r];r!==`"`&&this.repair(`syntax`,`non-json-quote`,n);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.text.slice(this.index,this.end).trimStart()[0],r=n===void 0||/[,}\]:"']/.test(n);if(t===i){if(c){c=!1,this.repair(`ambiguous`,`unescaped-quote`,this.index-1),s(t);continue}if(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);let n=this.text.indexOf(i,this.index),o=this.text.slice(n+1,this.end).trimStart()[0];if(e===`value`&&!r&&!/\s/.test(this.text[this.index]??``)&&n>this.index&&n<this.end&&o!==void 0&&(!/[,}:\]]/.test(o)||o===`,`&&this.continuesStringAfterComma(n+1,i))&&!/[\\*:,{}[\]\r\n]|\/\//.test(this.text.slice(this.index,n))&&!this.startsKey(n)){c=!0,this.repair(`ambiguous`,`unescaped-quote`,this.index-1),s(t);continue}return JSON.stringify(a)}r&&(u??={end:this.index,value:a,repairCount:this.repairs.length})}if(t!==`\\`){t.codePointAt(0)<32&&this.repair(`syntax`,`unescaped-control-character`,this.index-1),s(t);continue}let n=this.index-1;if(this.index>=this.end){s(`\\`),this.repair(`incomplete`,`truncated-escape`,n);break}let d=this.text[this.index++];if(d===`u`){let e=this.text.slice(this.index,Math.min(this.index+4,this.end));/^[\da-fA-F]{4}$/.test(e)?(s(String.fromCodePoint(Number.parseInt(e,16))),this.index+=4):(s(String.raw`\u`),this.repair(/^[\da-fA-F]{0,3}$/.test(e)?`incomplete`:`ambiguous`,`invalid-unicode-escape`,n))}else String.raw`"\/bfnrt`.includes(d)?s(JSON.parse(`"\\${d}"`)):d===`'`&&r===`'`?s(`'`):(s(`\\${d}`),this.repair(`ambiguous`,`invalid-escape`,n))}return this.repair(`incomplete`,`unterminated-string`,n),JSON.stringify(a)}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.text.slice(i+1,this.end).trimStart()[0];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}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 s(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{r as recoverJson};
|
|
3
|
+
//# sourceMappingURL=recoverJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoverJson.js","names":[],"sources":["../src/recoverJson.ts"],"sourcesContent":["/*! JSON recovery informed by jsonrepair, Copyright (c) 2020-2026 Jos de Jong (ISC). See NOTICE. */\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 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 = [...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 text[inlineStart] === '{' || text[inlineStart] === '[' || scalarStart(text, inlineStart, lineEnd)\n ? inlineStart\n : lineEnd;\n return marker[0] === '`' && start === lineEnd && info.includes('`') ? [] : [{ index: fence.index, marker, start }];\n });\n if (fences.length > 0) {\n let consumed = 0;\n for (const fence of fences) {\n if (fence.index < consumed) continue;\n extractRegion(text, consumed, fence.index, result);\n const parsedThrough = result.candidates.at(-1)?.end ?? consumed;\n if (parsedThrough > fence.index) {\n consumed = parsedThrough;\n continue;\n }\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 consumed = outerClose.index + outerClose[0].length;\n continue;\n }\n }\n consumed = Math.max(\n result.candidates.at(-1)?.end ?? start,\n match === null ? text.length : match.index + match[0].length\n );\n }\n extractRegion(text, consumed, text.length, result);\n } else {\n extractRegion(text, 0, text.length, result);\n }\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\nfunction extractRegion(text: string, start: number, end: number, result: JsonRecovery, commentFragment = false): void {\n if (result.candidates.length >= MAX_CANDIDATES) return;\n let index = start;\n let failures = 0;\n let ambiguousScalarTail = false;\n let scalarBoundary = true;\n let uriBoundaryEnd = start;\n let uriTokenEnd = start;\n let uriContainerStart = start;\n while (index < end && /\\s/.test(text[index]!)) index++;\n const firstIndex = index;\n const initialParser = new RecoveryParser(text, index, end);\n if (!commentFragment) initialParser.space();\n const initialValueStart = initialParser.index;\n if (initialValueStart >= end) {\n if (initialParser.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Incomplete leading JSON comment' });\n return;\n }\n const first = text[initialValueStart];\n // Within prose, scalar starts need a line boundary; containers may appear inline.\n const rootValue = scalarStart(text, initialValueStart, end);\n const initialValue = rootValue || first === '{' || first === '[';\n if (!initialValue) index = initialValueStart;\n while (index < end && result.candidates.length < MAX_CANDIDATES && failures < MAX_ERRORS) {\n if (!initialValue || index !== firstIndex) {\n while (index < end && text[index] !== '{' && text[index] !== '[') {\n if (scalarBoundary && scalarStart(text, index, end)) break;\n const uriEnd =\n index === start || !/[\\w+.-]/.test(text[index - 1]!) ? unquotedUriEnd(text, index, end) : undefined;\n if (uriEnd !== undefined) {\n if (index >= uriTokenEnd) {\n const whitespace = text.slice(index, end).search(/\\s/);\n uriTokenEnd = whitespace === -1 ? end : index + whitespace;\n uriContainerStart = index;\n }\n if (index >= uriContainerStart) {\n const container = text.slice(index, uriTokenEnd).search(/[{[]/);\n uriContainerStart = container === -1 ? uriTokenEnd : index + container;\n }\n if (uriContainerStart < uriTokenEnd) uriBoundaryEnd = Math.max(uriBoundaryEnd, uriTokenEnd);\n index = Math.min(uriEnd, uriContainerStart);\n scalarBoundary = false;\n continue;\n }\n if (!commentFragment && text[index] === '/') {\n const trivia = new RecoveryParser(text, index, end);\n trivia.space();\n if (trivia.index > index) {\n if (trivia.repairs.some((repair) => repair.kind === 'incomplete') && result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: index, message: 'Possibly unterminated comment-like span in prose' });\n extractRegion(text, index + 2, trivia.index, result, true);\n scalarBoundary ||= /[\\r\\n]/.test(text.slice(index, trivia.index));\n index = trivia.index;\n continue;\n }\n }\n if (/[\\r\\n]/.test(text[index]!)) scalarBoundary = true;\n else if (!/[\\s,]/.test(text[index]!)) scalarBoundary = false;\n index++;\n }\n }\n if (index >= end || result.candidates.length >= MAX_CANDIDATES) break;\n let parser = initialValue && index === firstIndex ? initialParser : new RecoveryParser(text, index, end);\n const valueStart = parser.index;\n try {\n let json = parser.value(0);\n if (\n !commentFragment &&\n (text[valueStart] === '{' || text[valueStart] === '[') &&\n parser.index === end &&\n end < text.length\n ) {\n const extended = new RecoveryParser(text, index, text.length);\n try {\n const extendedJson = extended.value(0);\n if (\n extended.index > end &&\n extended.repairs.every((repair) => repair.reason === 'unescaped-control-character')\n ) {\n extended.repairs.push({ offset: end, kind: 'ambiguous', reason: 'literal-fence-in-string' });\n parser = extended;\n json = extendedJson;\n }\n } catch {\n // Keep the bounded interpretation when extending it is not a complete JSON document.\n }\n }\n const valueEnd = parser.index;\n if (text[valueStart] !== '{' && text[valueStart] !== '[' && !parser.finishScalar(end, valueStart)) {\n scalarBoundary = false;\n index = valueEnd;\n continue;\n }\n parser.space();\n if (!commentFragment && failures === 0 && parser.index < end && /[}\\]]/.test(text[parser.index]!)) {\n const surplusStart = parser.index;\n while (parser.index < end && /[}\\]]/.test(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 (result.errors.length < MAX_ERRORS) {\n const excerptEnd = Math.min(end, surplusStart + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: surplusStart,\n message: `Surplus closing brackets and possible continuation (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(surplusStart, excerptEnd))}`,\n });\n }\n }\n if (\n text[valueStart]! in QUOTES &&\n parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content') &&\n result.errors.length < MAX_ERRORS\n ) {\n const excerptEnd = Math.min(end, valueEnd + MAX_DIAGNOSTIC_EXCERPT);\n result.errors.push({\n offset: valueEnd,\n message: `Ambiguous quoted-scalar tail (${excerptEnd < end ? 'truncated excerpt' : 'excerpt'}): ${JSON.stringify(text.slice(valueEnd, excerptEnd))}`,\n });\n }\n if (commentFragment)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-in-comment-like-prose' });\n if (failures > 0)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-rejected-document' });\n if (ambiguousScalarTail)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'fragment-after-ambiguous-scalar' });\n if (index < uriBoundaryEnd)\n parser.repairs.unshift({ offset: index, kind: 'ambiguous', reason: 'ambiguous-uri-boundary' });\n ambiguousScalarTail ||= parser.repairs.some((repair) => repair.reason === 'trailing-scalar-content');\n 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 if (result.errors.length < MAX_ERRORS)\n result.errors.push({ offset: parser.index, message: error instanceof Error ? error.message : String(error) });\n failures++;\n index = valueStart + 1;\n scalarBoundary = false;\n continue;\n }\n index = Math.max(index + 1, parser.index);\n scalarBoundary = true;\n }\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 =\n this.text[start]! in QUOTES || this.repairs.some((repair) => repair.reason === '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 (char === '{' || 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, object: boolean): string {\n this.index++;\n const close = object ? '}' : ']';\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 (object ? '{' : '[') + 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 let key: string | undefined;\n if (object) {\n const start = this.index;\n if (this.text[this.index]! in QUOTES) key = this.string();\n else {\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 key = JSON.stringify(rawKey);\n this.repair(/[\"'“”‘’]/.test(rawKey) ? 'ambiguous' : 'syntax', 'unquoted-key', start);\n }\n const decoded: string = JSON.parse(key);\n if (keys.has(decoded)) this.repair('ambiguous', 'duplicate-key', start);\n keys.add(decoded);\n this.space();\n if (this.text[this.index] === ':') this.index++;\n else this.repair('ambiguous', 'missing-colon');\n }\n const value = this.value(depth + 1);\n items.push(key === undefined ? value : `${key}:${value}`);\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 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.text.slice(this.index, this.end).trimStart()[0];\n const delimited = after === undefined || /[,}\\]:\"']/.test(after);\n if (char === close) {\n if (embeddedQuote) {\n embeddedQuote = false;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n if (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 }\n const nextClose = this.text.indexOf(close, this.index);\n const afterNext = this.text.slice(nextClose + 1, this.end).trimStart()[0];\n if (\n context === 'value' &&\n !delimited &&\n !/\\s/.test(this.text[this.index] ?? '') &&\n nextClose > this.index &&\n nextClose < this.end &&\n afterNext !== undefined &&\n (!/[,}:\\]]/.test(afterNext) ||\n (afterNext === ',' && this.continuesStringAfterComma(nextClose + 1, close))) &&\n !/[\\\\*:,{}[\\]\\r\\n]|\\/\\//.test(this.text.slice(this.index, nextClose)) &&\n !this.startsKey(nextClose)\n ) {\n embeddedQuote = true;\n this.repair('ambiguous', 'unescaped-quote', this.index - 1);\n append(char);\n continue;\n }\n return JSON.stringify(value);\n }\n if (delimited) alternative ??= { end: this.index, value, repairCount: this.repairs.length };\n }\n if (char !== '\\\\') {\n if (char.codePointAt(0)! < 32) this.repair('syntax', 'unescaped-control-character', this.index - 1);\n append(char);\n continue;\n }\n const escapeOffset = this.index - 1;\n if (this.index >= this.end) {\n append('\\\\');\n this.repair('incomplete', 'truncated-escape', escapeOffset);\n break;\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 append(String.fromCodePoint(Number.parseInt(hex, 16)));\n this.index += 4;\n } else {\n append(String.raw`\\u`);\n this.repair(\n /^[\\da-fA-F]{0,3}$/.test(hex) ? 'incomplete' : 'ambiguous',\n 'invalid-unicode-escape',\n escapeOffset\n );\n }\n } else if (String.raw`\"\\/bfnrt`.includes(escape)) {\n append(JSON.parse(`\"\\\\${escape}\"`) as string);\n } else if (escape === \"'\" && open === \"'\") append(\"'\");\n else {\n append(`\\\\${escape}`);\n this.repair('ambiguous', 'invalid-escape', escapeOffset);\n }\n }\n this.repair('incomplete', 'unterminated-string', start);\n return JSON.stringify(value);\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.text.slice(end + 1, this.end).trimStart()[0];\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 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.
|
|
3
|
+
"version": "10.10.0",
|
|
4
4
|
"description": "Shared library for WillBooster projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"module": "dist/index.js",
|
|
28
28
|
"types": "dist/index.d.ts",
|
|
29
29
|
"files": [
|
|
30
|
+
"NOTICE",
|
|
30
31
|
"bin/",
|
|
31
32
|
"dist/"
|
|
32
33
|
],
|
|
@@ -49,8 +50,8 @@
|
|
|
49
50
|
"@types/node": "26.5.1",
|
|
50
51
|
"@willbooster/oxfmt-config": "1.2.2",
|
|
51
52
|
"@willbooster/oxlint-config": "1.4.8",
|
|
52
|
-
"@willbooster/wb": "22.
|
|
53
|
-
"build-ts": "21.0.
|
|
53
|
+
"@willbooster/wb": "22.6.0",
|
|
54
|
+
"build-ts": "21.0.16",
|
|
54
55
|
"oxfmt": "0.67.0",
|
|
55
56
|
"oxlint": "1.82.0",
|
|
56
57
|
"oxlint-tsgolint": "7.0.2001",
|