@workos/oagen 0.29.3 → 0.29.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.mjs +138 -5
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{diff-DqnHHXvr.mjs → diff-B6TjXIwb.mjs} +139 -6
- package/dist/diff-B6TjXIwb.mjs.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/diff-DqnHHXvr.mjs.map +0 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -3775,6 +3775,7 @@ function extractKotlinClassMembers(classBody, source) {
|
|
|
3775
3775
|
const children = classBody.namedChildren;
|
|
3776
3776
|
for (let i = 0; i < children.length; i++) {
|
|
3777
3777
|
const child = children[i];
|
|
3778
|
+
const declIndex = i;
|
|
3778
3779
|
let memberName = null;
|
|
3779
3780
|
if (child.type === "property_declaration") memberName = child.children.find((c) => c.type === "variable_declaration")?.children.find((c) => c.type === "simple_identifier")?.text ?? null;
|
|
3780
3781
|
else if (child.type === "function_declaration") memberName = child.children.find((c) => c.type === "simple_identifier")?.text ?? null;
|
|
@@ -3789,7 +3790,7 @@ function extractKotlinClassMembers(classBody, source) {
|
|
|
3789
3790
|
} else break;
|
|
3790
3791
|
}
|
|
3791
3792
|
let startIdx = child.startIndex;
|
|
3792
|
-
for (let k =
|
|
3793
|
+
for (let k = declIndex - 1; k >= 0; k--) {
|
|
3793
3794
|
const prev = children[k];
|
|
3794
3795
|
if (prev.type === "multiline_comment") {
|
|
3795
3796
|
if (source.slice(prev.startIndex, prev.endIndex).startsWith("/**")) startIdx = prev.startIndex;
|
|
@@ -3858,6 +3859,13 @@ const kotlinMergeAdapter = {
|
|
|
3858
3859
|
isManagedMember(member) {
|
|
3859
3860
|
return KOTLIN_MANAGED_ACCESSOR_DOC.test(member.text);
|
|
3860
3861
|
},
|
|
3862
|
+
importedNames(imp) {
|
|
3863
|
+
const path = imp.text.replace(/^import\s+/, "").trim();
|
|
3864
|
+
const alias = path.match(/\s+as\s+([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
3865
|
+
if (alias) return [alias[1]];
|
|
3866
|
+
const last = path.split(".").pop();
|
|
3867
|
+
return last && last !== "*" ? [last] : [];
|
|
3868
|
+
},
|
|
3861
3869
|
shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {
|
|
3862
3870
|
const newText = newMembers.map((m) => m.text).join("\n");
|
|
3863
3871
|
for (const match of newText.matchAll(/this\.(\w+)/g)) {
|
|
@@ -4740,6 +4748,116 @@ function declarationLineStart(content, declStartIndex) {
|
|
|
4740
4748
|
return prevNewline === -1 ? 0 : prevNewline + 1;
|
|
4741
4749
|
}
|
|
4742
4750
|
/**
|
|
4751
|
+
* Widen a member's byte range so deleting it removes whole lines.
|
|
4752
|
+
*
|
|
4753
|
+
* The raw range starts at the declaration (or its docstring), which sits after
|
|
4754
|
+
* the member's indentation — splicing it out verbatim leaves that indentation
|
|
4755
|
+
* glued to the following line. Extends backwards over the indentation and
|
|
4756
|
+
* forwards over the trailing newline, then absorbs the blank line the removal
|
|
4757
|
+
* would otherwise duplicate (or strand in front of the block's closing brace).
|
|
4758
|
+
*/
|
|
4759
|
+
function expandPruneRange(source, rawStart, rawEnd) {
|
|
4760
|
+
let start = rawStart;
|
|
4761
|
+
while (start > 0 && (source[start - 1] === " " || source[start - 1] === " ")) start--;
|
|
4762
|
+
let end = rawEnd;
|
|
4763
|
+
while (end < source.length && (source[end] === " " || source[end] === " ")) end++;
|
|
4764
|
+
end = skipLineBreak(source, end);
|
|
4765
|
+
if (precededByBlankLine(source, start)) {
|
|
4766
|
+
if (startsWithLineBreak(source, end)) end = skipLineBreak(source, end);
|
|
4767
|
+
else if (/^[ \t]*\}/.test(source.slice(end, end + 40))) start = backOverLineBreak(source, start);
|
|
4768
|
+
}
|
|
4769
|
+
return {
|
|
4770
|
+
start,
|
|
4771
|
+
end
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
function startsWithLineBreak(source, idx) {
|
|
4775
|
+
return source[idx] === "\n" || source[idx] === "\r" && source[idx + 1] === "\n";
|
|
4776
|
+
}
|
|
4777
|
+
function skipLineBreak(source, idx) {
|
|
4778
|
+
let i = idx;
|
|
4779
|
+
if (source[i] === "\r") i++;
|
|
4780
|
+
return source[i] === "\n" ? i + 1 : i;
|
|
4781
|
+
}
|
|
4782
|
+
function backOverLineBreak(source, idx) {
|
|
4783
|
+
let i = idx;
|
|
4784
|
+
if (source[i - 1] === "\n") i--;
|
|
4785
|
+
if (source[i - 1] === "\r") i--;
|
|
4786
|
+
return i;
|
|
4787
|
+
}
|
|
4788
|
+
/** Whether the line ending immediately before `idx` (a line start) is empty. */
|
|
4789
|
+
function precededByBlankLine(source, idx) {
|
|
4790
|
+
if (idx === 0 || source[idx - 1] !== "\n") return false;
|
|
4791
|
+
const priorLineEnd = backOverLineBreak(source, idx);
|
|
4792
|
+
return priorLineEnd > 0 && source[priorLineEnd - 1] === "\n";
|
|
4793
|
+
}
|
|
4794
|
+
function referencesIdentifier(source, name) {
|
|
4795
|
+
return new RegExp(`\\b${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`).test(source);
|
|
4796
|
+
}
|
|
4797
|
+
/**
|
|
4798
|
+
* Blank out comments and string text, preserving offsets and line structure.
|
|
4799
|
+
*
|
|
4800
|
+
* An identifier lookup over raw source can't tell a live reference from a name
|
|
4801
|
+
* that merely survives in prose. That distinction decides whether an import
|
|
4802
|
+
* stays: keeping one whose only remaining mention is a KDoc leaves an import of
|
|
4803
|
+
* a class the generator no longer emits, which doesn't compile — the very
|
|
4804
|
+
* failure the prune exists to prevent.
|
|
4805
|
+
*
|
|
4806
|
+
* Interpolated expressions are the exception: `"${Agents.NAME}"` is code that
|
|
4807
|
+
* sits inside a string literal, and masking it would drop an import the file
|
|
4808
|
+
* genuinely uses. String extents are masked around those holes, not over them.
|
|
4809
|
+
*
|
|
4810
|
+
* Grammar node names come from the adapter's `urlFingerprintConfig`, which
|
|
4811
|
+
* already inventories exactly these three categories per language. Comments are
|
|
4812
|
+
* matched structurally instead — every grammar we support names them `*comment`.
|
|
4813
|
+
*/
|
|
4814
|
+
function maskNonCode(tree, source, config) {
|
|
4815
|
+
const stringNodeTypes = new Set(config?.stringNodeTypes ?? []);
|
|
4816
|
+
const interpolationNodeTypes = new Set(config?.interpolationNodeTypes ?? []);
|
|
4817
|
+
const spans = [];
|
|
4818
|
+
const collectStringSpans = (node) => {
|
|
4819
|
+
const holes = [];
|
|
4820
|
+
const findHoles = (n) => {
|
|
4821
|
+
if (interpolationNodeTypes.has(n.type)) {
|
|
4822
|
+
holes.push([n.startIndex, n.endIndex]);
|
|
4823
|
+
return;
|
|
4824
|
+
}
|
|
4825
|
+
for (const child of n.children) findHoles(child);
|
|
4826
|
+
};
|
|
4827
|
+
findHoles(node);
|
|
4828
|
+
let cursor = node.startIndex;
|
|
4829
|
+
for (const [holeStart, holeEnd] of holes) {
|
|
4830
|
+
if (holeStart > cursor) spans.push([cursor, holeStart]);
|
|
4831
|
+
cursor = holeEnd;
|
|
4832
|
+
}
|
|
4833
|
+
if (cursor < node.endIndex) spans.push([cursor, node.endIndex]);
|
|
4834
|
+
};
|
|
4835
|
+
const walk = (node) => {
|
|
4836
|
+
if (node.type.includes("comment")) {
|
|
4837
|
+
spans.push([node.startIndex, node.endIndex]);
|
|
4838
|
+
return;
|
|
4839
|
+
}
|
|
4840
|
+
if (stringNodeTypes.has(node.type)) {
|
|
4841
|
+
collectStringSpans(node);
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
for (const child of node.children) walk(child);
|
|
4845
|
+
};
|
|
4846
|
+
walk(tree.rootNode);
|
|
4847
|
+
if (spans.length === 0) return source;
|
|
4848
|
+
let masked = "";
|
|
4849
|
+
let cursor = 0;
|
|
4850
|
+
for (const [spanStart, spanEnd] of spans) {
|
|
4851
|
+
if (spanStart < cursor) continue;
|
|
4852
|
+
masked += source.slice(cursor, spanStart) + source.slice(spanStart, spanEnd).replace(/[^\r\n]/g, " ");
|
|
4853
|
+
cursor = spanEnd;
|
|
4854
|
+
}
|
|
4855
|
+
return masked + source.slice(cursor);
|
|
4856
|
+
}
|
|
4857
|
+
function removeLines(source, lines) {
|
|
4858
|
+
return source.split("\n").filter((line) => !lines.has(line.trim())).join("\n");
|
|
4859
|
+
}
|
|
4860
|
+
/**
|
|
4743
4861
|
* Resolve a docstring range by searching for the nearest matching text before
|
|
4744
4862
|
* the declaration start. Falls back to parser-provided offsets when search fails.
|
|
4745
4863
|
*/
|
|
@@ -4954,6 +5072,7 @@ async function mergeIntoExisting(existingContent, generatedContent, language, he
|
|
|
4954
5072
|
let deepAdded = 0;
|
|
4955
5073
|
let deepPruned = 0;
|
|
4956
5074
|
const insertions = [];
|
|
5075
|
+
const prunedTexts = [];
|
|
4957
5076
|
if (adapter.extractMembers) {
|
|
4958
5077
|
const parser = await getParser(language);
|
|
4959
5078
|
const resultTree = safeParse(parser, result);
|
|
@@ -4982,10 +5101,9 @@ async function mergeIntoExisting(existingContent, generatedContent, language, he
|
|
|
4982
5101
|
if (pruneEdits.length > 0) {
|
|
4983
5102
|
pruneEdits.sort((a, b) => b.start - a.start);
|
|
4984
5103
|
for (const edit of pruneEdits) {
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
result = result.slice(0, edit.start) + result.slice(end);
|
|
5104
|
+
const { start, end } = expandPruneRange(result, edit.start, edit.end);
|
|
5105
|
+
prunedTexts.push(result.slice(start, end));
|
|
5106
|
+
result = result.slice(0, start) + result.slice(end);
|
|
4989
5107
|
}
|
|
4990
5108
|
deepPruned = pruneEdits.length;
|
|
4991
5109
|
const reTree = safeParse(parser, result);
|
|
@@ -5050,6 +5168,21 @@ async function mergeIntoExisting(existingContent, generatedContent, language, he
|
|
|
5050
5168
|
result = lines.join("\n");
|
|
5051
5169
|
}
|
|
5052
5170
|
}
|
|
5171
|
+
if (prunedTexts.length > 0 && adapter.importedNames) {
|
|
5172
|
+
const prunedText = prunedTexts.join("\n");
|
|
5173
|
+
const codeOnly = maskNonCode(safeParse(await getParser(language), result), result, adapter.urlFingerprintConfig);
|
|
5174
|
+
const orphaned = /* @__PURE__ */ new Set();
|
|
5175
|
+
for (const imp of existingStatements.imports) {
|
|
5176
|
+
const names = adapter.importedNames(imp);
|
|
5177
|
+
if (names.length === 0) continue;
|
|
5178
|
+
if (!names.some((n) => referencesIdentifier(prunedText, n))) continue;
|
|
5179
|
+
const line = imp.text.trim();
|
|
5180
|
+
const withoutImport = removeLines(codeOnly, new Set([line]));
|
|
5181
|
+
if (names.some((n) => referencesIdentifier(withoutImport, n))) continue;
|
|
5182
|
+
orphaned.add(line);
|
|
5183
|
+
}
|
|
5184
|
+
if (orphaned.size > 0) result = removeLines(result, orphaned);
|
|
5185
|
+
}
|
|
5053
5186
|
let docstringUpdates = 0;
|
|
5054
5187
|
{
|
|
5055
5188
|
const parser = await getParser(language);
|