@probelabs/probe 0.6.0-rc126 → 0.6.0-rc128

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/README.md CHANGED
@@ -82,7 +82,7 @@ The package installs the actual probe binary, not a JavaScript wrapper, so you g
82
82
  ProbeAgent provides a high-level AI-powered interface for interacting with your codebase:
83
83
 
84
84
  ```javascript
85
- import { ProbeAgent } from '@buger/probe';
85
+ import { ProbeAgent } from '@probelabs/probe';
86
86
 
87
87
  // Create an AI agent for your project
88
88
  const agent = new ProbeAgent({
@@ -28351,7 +28351,6 @@ var init_parser2 = __esm({
28351
28351
  this.linkStyleStatement = this.RULE("linkStyleStatement", () => {
28352
28352
  this.CONSUME(LinkStyleKeyword);
28353
28353
  this.SUBRULE(this.linkStyleIndexList);
28354
- this.OPTION1(() => this.CONSUME1(Newline));
28355
28354
  this.SUBRULE(this.linkStylePairs);
28356
28355
  this.OPTION2(() => this.CONSUME2(Newline));
28357
28356
  });
@@ -28815,7 +28814,7 @@ var init_semantics = __esm({
28815
28814
  }
28816
28815
  const fnTok = ch.fn?.[0];
28817
28816
  if (!fnTok) {
28818
- this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-CALL-NAME-MISSING", message: "'click \u2026 call' requires a function name.", hint: 'Example: click A call doThing() "Tooltip"' });
28817
+ this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-CALL-NAME-MISSING", message: "'click \u2026 call' requires a function name.", hint: "Example: click A call doThing()" });
28819
28818
  }
28820
28819
  const tipTok = ch.tooltip?.[0];
28821
28820
  if (tipTok) {
@@ -28872,7 +28871,7 @@ var init_semantics = __esm({
28872
28871
  severity: "error",
28873
28872
  code: "FL-CLICK-CALL-NAME-MISSING",
28874
28873
  message: "'click \u2026 call' requires a function name.",
28875
- hint: 'Example: click A call doThing() "Tooltip"'
28874
+ hint: "Example: click A call doThing()"
28876
28875
  });
28877
28876
  }
28878
28877
  return;
@@ -28953,6 +28952,8 @@ var init_semantics = __esm({
28953
28952
  const linksHere = Array.isArray(ctx.link) ? ctx.link.length : 0;
28954
28953
  if (linksHere > 0)
28955
28954
  this.edgeCount += linksHere;
28955
+ if (ctx.link)
28956
+ ctx.link.forEach((ln) => this.visit(ln));
28956
28957
  }
28957
28958
  // Edge attribute object statements must target a known edge id
28958
28959
  // Edge attribute statements are parsed as nodeStatements with a typed attrObject and no links.
@@ -29012,7 +29013,7 @@ var init_semantics = __esm({
29012
29013
  severity: "error",
29013
29014
  code: "FL-TYPED-SHAPE-UNKNOWN",
29014
29015
  message: `Unknown shape '${v}' in '@{ shape: \u2026 }'.`,
29015
- hint: "Use one of: rect, round, stadium, subroutine, circle, cylinder, diamond, trapezoid, parallelogram, hexagon, lean-l, lean-r, icon, image"
29016
+ hint: 'Use one of: rect, rounded, stadium, subroutine, circle, cylinder, diamond, trapezoid, parallelogram, hexagon, "lean-l", "lean-r", icon, image'
29016
29017
  });
29017
29018
  } else {
29018
29019
  const supportedByCli = /* @__PURE__ */ new Set(["rect", "round", "rounded", "diamond", "circle", "cylinder", "stadium", "subroutine", "lean-l", "lean-r"]);
@@ -29214,8 +29215,8 @@ var init_semantics = __esm({
29214
29215
  column: t.startColumn ?? 1,
29215
29216
  severity: "error",
29216
29217
  code: "FL-LABEL-PARENS-UNQUOTED",
29217
- message: "Parentheses inside an unquoted label are not supported by Mermaid. Wrap the label in quotes.",
29218
- hint: 'Example: A["Calls func(arg)"]'
29218
+ message: "Parentheses inside an unquoted label are not supported by Mermaid.",
29219
+ hint: 'Wrap the label in quotes, e.g., A["Mark (X)"] \u2014 or replace ( and ) with HTML entities: ( and )'
29219
29220
  });
29220
29221
  }
29221
29222
  }
@@ -29263,6 +29264,29 @@ var init_semantics = __esm({
29263
29264
  }
29264
29265
  }
29265
29266
  }
29267
+ // Validate link specifics that Mermaid CLI enforces but our grammar may parse loosely
29268
+ link(ctx) {
29269
+ const inline = ctx.linkTextInline?.[0];
29270
+ if (inline) {
29271
+ const ch = inline.children || {};
29272
+ const parts = [].concat(ch.Identifier || []).concat(ch.Text || []).concat(ch.NumberLiteral || []).concat(ch.Pipe || []);
29273
+ if (parts.length) {
29274
+ const raw = parts.map((t) => String(t.image || "")).join("").trim();
29275
+ if (raw === "x" || raw === "o") {
29276
+ const p = parts[0];
29277
+ this.ctx.errors.push({
29278
+ line: p.startLine ?? 1,
29279
+ column: p.startColumn ?? 1,
29280
+ severity: "error",
29281
+ code: "FL-LINK-UNSUPPORTED-MARKER",
29282
+ message: `Unsupported one-sided link marker '${raw}'. Use symmetric '${raw}--${raw}' or a plain arrow with a label.`,
29283
+ hint: raw === "x" ? "Example: A x--x B (or) A --> B and label it: A --|Skipped|--> B" : "Example: A o--o B (or) A --> B",
29284
+ length: p.image?.length ?? 1
29285
+ });
29286
+ }
29287
+ }
29288
+ }
29289
+ }
29266
29290
  checkBackticksInContent(contentNodes) {
29267
29291
  if (!contentNodes)
29268
29292
  return;
@@ -29614,6 +29638,31 @@ function mapFlowchartParserError(err, text) {
29614
29638
  }
29615
29639
  }
29616
29640
  }
29641
+ if (isInRule(err, "linkStylePairs") && tokType === "Newline") {
29642
+ const nextLine = Math.min(allLines.length, line + 1);
29643
+ const nxt = allLines[nextLine - 1] || "";
29644
+ const first2 = (nxt.match(/\S/) || { index: 0 }).index || 0;
29645
+ return {
29646
+ line: nextLine,
29647
+ column: Math.max(1, first2 + 1),
29648
+ severity: "error",
29649
+ code: "FL-LINKSTYLE-MULTILINE",
29650
+ message: "'linkStyle' styles must be on the same line as the indices.",
29651
+ hint: "Example: linkStyle 0,1 stroke:#f00,stroke-width:2px",
29652
+ length: 1
29653
+ };
29654
+ }
29655
+ if ((isInRule(err, "linkStyleIndexList") || isInRule(err, "linkStyleStatement")) && tokType === "Colon") {
29656
+ return {
29657
+ line,
29658
+ column,
29659
+ severity: "error",
29660
+ code: "FL-LINKSTYLE-RANGE-NOT-SUPPORTED",
29661
+ message: "Ranges in 'linkStyle' indices are not supported. Use comma-separated indices.",
29662
+ hint: "Example: linkStyle 0,1 stroke:#f00,stroke-width:2px",
29663
+ length: len
29664
+ };
29665
+ }
29617
29666
  if (tokType === "QuotedString") {
29618
29667
  const context = err?.context;
29619
29668
  const inLinkRule = context?.ruleStack?.includes("linkTextInline") || context?.ruleStack?.includes("link") || false;
@@ -29660,6 +29709,17 @@ function mapFlowchartParserError(err, text) {
29660
29709
  }
29661
29710
  if (isInRule(err, "nodeShape") && err.name === "MismatchedTokenException") {
29662
29711
  if (expecting(err, "SquareClose")) {
29712
+ if (tokType === "RoundOpen" || tokType === "RoundClose") {
29713
+ return {
29714
+ line,
29715
+ column,
29716
+ severity: "error",
29717
+ code: "FL-LABEL-PARENS-UNQUOTED",
29718
+ message: "Parentheses inside an unquoted label are not supported by Mermaid.",
29719
+ hint: 'Wrap the label in quotes, e.g., A["Mark (X)"] \u2014 or replace ( and ) with HTML entities: ( and ).',
29720
+ length: len
29721
+ };
29722
+ }
29663
29723
  if (tokType === "QuotedString") {
29664
29724
  return {
29665
29725
  line,
@@ -30155,6 +30215,32 @@ ${br.example}`,
30155
30215
  break;
30156
30216
  }
30157
30217
  }
30218
+ if (blk.label === "box" && openIdx !== -1) {
30219
+ let endIdx = -1;
30220
+ for (let i = openIdx + 1; i < lines2.length; i++) {
30221
+ const raw = lines2[i] || "";
30222
+ const ind = raw.match(/^(\s*)/)?.[1] || "";
30223
+ if (/^\s*end\s*$/.test(raw) && ind.length <= openIndent.length) {
30224
+ endIdx = i;
30225
+ break;
30226
+ }
30227
+ }
30228
+ if (endIdx !== -1) {
30229
+ const body = lines2.slice(openIdx + 1, endIdx).map((s) => (s || "").trim());
30230
+ const hasMsgWithActivation = body.some((s) => /->/.test(s) && /[+-]/.test(s));
30231
+ if (hasMsgWithActivation) {
30232
+ return {
30233
+ line: openIdx + 1,
30234
+ column: 1,
30235
+ severity: "error",
30236
+ code: "SE-BOX-EMPTY",
30237
+ message: "Box block has no participant/actor declarations. Use 'rect' to group messages visually.",
30238
+ hint: "Replace 'box' with 'rect' if you want to group messages:\nrect rgb(240, 240, 255)\n A->>B: Message\n Note over A: Info\nend",
30239
+ length: 3
30240
+ };
30241
+ }
30242
+ }
30243
+ }
30158
30244
  let caretLine = line;
30159
30245
  if (openIdx !== -1) {
30160
30246
  caretLine = lines2.length;
@@ -31494,7 +31580,7 @@ var init_validate3 = __esm({
31494
31580
  function tokenize4(text) {
31495
31581
  return ClassLexer.tokenize(text);
31496
31582
  }
31497
- var Identifier3, NumberLiteral4, ClassDiagramKeyword, DirectionKw, Direction2, ClassKw, AsKw, NoteKw, ForKw, RelCompToAgg, RelAggToComp, RelCompBoth, RelAggBoth, LollipopLeft, LollipopRight, RelExtends, RelComposition, RelAggregation, RelDependency, RelRealization, RelAssociation, RelDependencyLeft, RelRealizationLeft, RelExtendsRight, InvalidRelArrow, LCurly, RCurly, LParen2, RParen2, Colon4, Comma3, Visibility, LTlt, GTgt, GenericAngle, QuotedString4, BacktickName, SquareOpen2, SquareClose2, Comment4, WhiteSpace4, Newline4, allTokens4, ClassLexer;
31583
+ var Identifier3, NumberLiteral4, ClassDiagramKeyword, DirectionKw, Direction2, TitleKw, NamespaceKw, ClassKw, InterfaceKw, AsKw, NoteKw, ForKw, RelCompToAgg, RelAggToComp, RelCompBoth, RelAggBoth, LollipopLeft, LollipopRight, RelExtends, RelComposition, RelAggregation, RelDependency, RelRealization, RelAssociation, RelDependencyLeft, RelRealizationLeft, RelExtendsRight, InvalidRelArrow, LCurly, RCurly, LParen2, RParen2, Colon4, Comma3, Visibility, LTlt, GTgt, GenericAngle, QuotedString4, BacktickName, SquareOpen2, SquareClose2, Comment4, WhiteSpace4, Newline4, allTokens4, ClassLexer;
31498
31584
  var init_lexer5 = __esm({
31499
31585
  "node_modules/@probelabs/maid/out/diagrams/class/lexer.js"() {
31500
31586
  init_api5();
@@ -31503,7 +31589,10 @@ var init_lexer5 = __esm({
31503
31589
  ClassDiagramKeyword = createToken({ name: "ClassDiagramKeyword", pattern: /classDiagram/, longer_alt: Identifier3 });
31504
31590
  DirectionKw = createToken({ name: "DirectionKw", pattern: /direction/, longer_alt: Identifier3 });
31505
31591
  Direction2 = createToken({ name: "Direction", pattern: /LR|RL|TB|BT|TD/, longer_alt: Identifier3 });
31592
+ TitleKw = createToken({ name: "TitleKw", pattern: /title/, longer_alt: Identifier3 });
31593
+ NamespaceKw = createToken({ name: "NamespaceKw", pattern: /namespace/, longer_alt: Identifier3 });
31506
31594
  ClassKw = createToken({ name: "ClassKw", pattern: /class/, longer_alt: Identifier3 });
31595
+ InterfaceKw = createToken({ name: "InterfaceKw", pattern: /interface\b/, longer_alt: Identifier3 });
31507
31596
  AsKw = createToken({ name: "AsKw", pattern: /as/, longer_alt: Identifier3 });
31508
31597
  NoteKw = createToken({ name: "NoteKw", pattern: /note/, longer_alt: Identifier3 });
31509
31598
  ForKw = createToken({ name: "ForKw", pattern: /for/, longer_alt: Identifier3 });
@@ -31546,6 +31635,9 @@ var init_lexer5 = __esm({
31546
31635
  // Keywords
31547
31636
  ClassDiagramKeyword,
31548
31637
  DirectionKw,
31638
+ TitleKw,
31639
+ NamespaceKw,
31640
+ InterfaceKw,
31549
31641
  ClassKw,
31550
31642
  AsKw,
31551
31643
  NoteKw,
@@ -31614,8 +31706,11 @@ var init_parser5 = __esm({
31614
31706
  });
31615
31707
  this.statement = this.RULE("statement", () => {
31616
31708
  this.OR([
31709
+ { ALT: () => this.SUBRULE(this.titleStmt) },
31617
31710
  { ALT: () => this.SUBRULE(this.directionStmt) },
31711
+ { ALT: () => this.SUBRULE(this.namespaceStmt) },
31618
31712
  { ALT: () => this.SUBRULE(this.classLine) },
31713
+ { ALT: () => this.SUBRULE(this.interfaceLine) },
31619
31714
  { ALT: () => this.SUBRULE(this.relationStmt) },
31620
31715
  { ALT: () => this.SUBRULE(this.noteStmt) },
31621
31716
  { ALT: () => this.SUBRULE(this.memberAssignStmt) },
@@ -31627,6 +31722,43 @@ var init_parser5 = __esm({
31627
31722
  this.CONSUME(Direction2);
31628
31723
  this.OPTION(() => this.CONSUME(Newline4));
31629
31724
  });
31725
+ this.titleStmt = this.RULE("titleStmt", () => {
31726
+ this.CONSUME(TitleKw);
31727
+ this.OR([
31728
+ { ALT: () => this.CONSUME(QuotedString4) },
31729
+ {
31730
+ ALT: () => {
31731
+ this.AT_LEAST_ONE(() => {
31732
+ this.OR2([
31733
+ { ALT: () => this.CONSUME(Identifier3) },
31734
+ { ALT: () => this.CONSUME(NumberLiteral4) }
31735
+ ]);
31736
+ });
31737
+ }
31738
+ }
31739
+ ]);
31740
+ this.OPTION(() => this.CONSUME(Newline4));
31741
+ });
31742
+ this.namespaceStmt = this.RULE("namespaceStmt", () => {
31743
+ this.CONSUME(NamespaceKw);
31744
+ this.OR([
31745
+ { ALT: () => this.CONSUME(QuotedString4) },
31746
+ { ALT: () => this.CONSUME(Identifier3) }
31747
+ ]);
31748
+ this.CONSUME(LCurly);
31749
+ this.MANY(() => {
31750
+ this.OR2([
31751
+ { ALT: () => this.CONSUME(Newline4) },
31752
+ { ALT: () => this.SUBRULE(this.classLine) },
31753
+ { ALT: () => this.SUBRULE(this.interfaceLine) },
31754
+ { ALT: () => this.SUBRULE(this.relationStmt) },
31755
+ { ALT: () => this.SUBRULE(this.noteStmt) },
31756
+ { ALT: () => this.SUBRULE(this.memberAssignStmt) }
31757
+ ]);
31758
+ });
31759
+ this.CONSUME(RCurly);
31760
+ this.OPTION(() => this.CONSUME2(Newline4));
31761
+ });
31630
31762
  this.classLine = this.RULE("classLine", () => {
31631
31763
  this.CONSUME(ClassKw);
31632
31764
  this.SUBRULE(this.classRef);
@@ -31665,6 +31797,44 @@ var init_parser5 = __esm({
31665
31797
  }
31666
31798
  ]);
31667
31799
  });
31800
+ this.interfaceLine = this.RULE("interfaceLine", () => {
31801
+ this.CONSUME(InterfaceKw);
31802
+ this.SUBRULE(this.classRef);
31803
+ this.OR([
31804
+ {
31805
+ ALT: () => {
31806
+ this.CONSUME(LCurly);
31807
+ this.MANY(() => {
31808
+ this.OR2([
31809
+ { ALT: () => this.CONSUME3(Newline4) },
31810
+ { ALT: () => this.SUBRULE(this.memberLineStmt) }
31811
+ ]);
31812
+ });
31813
+ this.CONSUME(RCurly);
31814
+ this.OPTION(() => this.CONSUME(Newline4));
31815
+ }
31816
+ },
31817
+ {
31818
+ ALT: () => {
31819
+ this.OPTION1(() => {
31820
+ this.CONSUME(SquareOpen2);
31821
+ this.CONSUME(QuotedString4);
31822
+ this.CONSUME(SquareClose2);
31823
+ });
31824
+ this.OPTION2(() => {
31825
+ this.CONSUME(LTlt);
31826
+ this.CONSUME2(Identifier3);
31827
+ this.CONSUME(GTgt);
31828
+ });
31829
+ this.OPTION3(() => {
31830
+ this.CONSUME(AsKw);
31831
+ this.CONSUME3(Identifier3);
31832
+ });
31833
+ this.OPTION4(() => this.CONSUME2(Newline4));
31834
+ }
31835
+ }
31836
+ ]);
31837
+ });
31668
31838
  this.memberAssignStmt = this.RULE("memberAssignStmt", () => {
31669
31839
  this.SUBRULE(this.classRef);
31670
31840
  this.CONSUME(Colon4);
@@ -31834,6 +32004,31 @@ function validateClass(text, _options = {}) {
31834
32004
  length: b.image?.length ?? 1
31835
32005
  });
31836
32006
  }
32007
+ if (a.tokenType === NamespaceKw && b.tokenType === QuotedString4) {
32008
+ errs.push({
32009
+ line: b.startLine ?? 1,
32010
+ column: b.startColumn ?? 1,
32011
+ severity: "error",
32012
+ code: "CL-NAMESPACE-NAME-QUOTED",
32013
+ message: "Quoted namespace names are not supported by mermaid.js. Use an unquoted identifier.",
32014
+ hint: 'Change: namespace "ProbeAgent Core" { ... } \u2192 namespace ProbeAgentCore { ... }',
32015
+ length: b.image?.length ?? 1
32016
+ });
32017
+ }
32018
+ if (a.tokenType === InterfaceKw) {
32019
+ const prevToken = i > 0 ? tokList[i - 1] : null;
32020
+ if (!prevToken || prevToken.tokenType !== LTlt) {
32021
+ errs.push({
32022
+ line: a.startLine ?? 1,
32023
+ column: a.startColumn ?? 1,
32024
+ severity: "error",
32025
+ code: "CL-INTERFACE-KEYWORD-UNSUPPORTED",
32026
+ message: 'The "interface" keyword is not supported by mermaid.js. Use the <<interface>> annotation instead.',
32027
+ hint: 'Auto-fix converts to "class". Then manually add: <<interface>> ClassName after the class definition',
32028
+ length: a.image?.length ?? 9
32029
+ });
32030
+ }
32031
+ }
31837
32032
  }
31838
32033
  for (const tk of tokList) {
31839
32034
  if (tk.tokenType === InvalidRelArrow) {
@@ -31890,10 +32085,13 @@ function validateClass(text, _options = {}) {
31890
32085
  const has2 = (code, line) => (prev || []).some((e) => e.code === code && e.line === line && e.severity === "error");
31891
32086
  const lines = src.split(/\r?\n/);
31892
32087
  const classDeclOpen = [];
32088
+ const namespaceDeclOpen = [];
31893
32089
  for (let i = 0; i < lines.length; i++) {
31894
32090
  const raw = lines[i] || "";
31895
32091
  if (/^\s*class\b.*\{\s*$/.test(raw))
31896
32092
  classDeclOpen.push(i + 1);
32093
+ if (/^\s*namespace\b.*\{\s*$/.test(raw))
32094
+ namespaceDeclOpen.push(i + 1);
31897
32095
  }
31898
32096
  if (classDeclOpen.length > 0) {
31899
32097
  const hasClose = lines.some((l) => /\}/.test(l));
@@ -31902,6 +32100,13 @@ function validateClass(text, _options = {}) {
31902
32100
  errors.push({ line: Math.max(1, lines.length), column: 1, severity: "error", code: "CL-BLOCK-MISSING-RBRACE", message: "Missing '}' to close class block.", hint: "Close the block: class Foo { ... }" });
31903
32101
  }
31904
32102
  }
32103
+ if (namespaceDeclOpen.length > 0) {
32104
+ const hasClose = lines.some((l) => /\}/.test(l));
32105
+ if (!hasClose && !has2("CL-NAMESPACE-MISSING-RBRACE", Math.max(1, lines.length))) {
32106
+ const last2 = namespaceDeclOpen[namespaceDeclOpen.length - 1];
32107
+ errors.push({ line: Math.max(1, lines.length), column: 1, severity: "error", code: "CL-NAMESPACE-MISSING-RBRACE", message: "Missing '}' to close namespace block.", hint: 'Close the block: namespace "Name" { ... }' });
32108
+ }
32109
+ }
31905
32110
  return errors;
31906
32111
  }
31907
32112
  });
@@ -32556,6 +32761,10 @@ function computeFixes(text, errors, level = "safe") {
32556
32761
  edits.push(replaceRange(text, at(e), e.length ?? 2, "-->"));
32557
32762
  continue;
32558
32763
  }
32764
+ if (is("FL-LINK-UNSUPPORTED-MARKER", e)) {
32765
+ edits.push(replaceRange(text, at(e), e.length ?? 1, ""));
32766
+ continue;
32767
+ }
32559
32768
  if (is("FL-EDGE-LABEL-QUOTED", e)) {
32560
32769
  const lineText = lineTextAt(text, e.line);
32561
32770
  const col = Math.max(0, e.column - 1);
@@ -32628,6 +32837,29 @@ function computeFixes(text, errors, level = "safe") {
32628
32837
  }
32629
32838
  continue;
32630
32839
  }
32840
+ if (is("CL-NAMESPACE-NAME-QUOTED", e)) {
32841
+ const lineText = lineTextAt(text, e.line);
32842
+ const nsIdx = lineText.indexOf("namespace");
32843
+ const startSearch = nsIdx >= 0 ? nsIdx + 9 : 0;
32844
+ const q1 = lineText.indexOf('"', startSearch);
32845
+ if (q1 !== -1) {
32846
+ const q2 = lineText.indexOf('"', q1 + 1);
32847
+ if (q2 > q1) {
32848
+ const namespaceName = lineText.slice(q1 + 1, q2);
32849
+ const validIdentifier = namespaceName.replace(/[^A-Za-z0-9_]/g, "");
32850
+ edits.push(replaceRange(text, { line: e.line, column: q1 + 1 }, q2 - q1 + 1, validIdentifier));
32851
+ }
32852
+ }
32853
+ continue;
32854
+ }
32855
+ if (is("CL-INTERFACE-KEYWORD-UNSUPPORTED", e)) {
32856
+ const lineText = lineTextAt(text, e.line);
32857
+ const ifIdx = lineText.indexOf("interface");
32858
+ if (ifIdx !== -1) {
32859
+ edits.push(replaceRange(text, { line: e.line, column: ifIdx + 1 }, 9, "class"));
32860
+ }
32861
+ continue;
32862
+ }
32631
32863
  if (is("FL-LABEL-ESCAPED-QUOTE", e)) {
32632
32864
  const lineText = lineTextAt(text, e.line);
32633
32865
  const caret0 = Math.max(0, e.column - 1);
@@ -32775,6 +33007,42 @@ function computeFixes(text, errors, level = "safe") {
32775
33007
  const msg = e.message || "";
32776
33008
  const lineText = lineTextAt(text, e.line);
32777
33009
  const caret0 = Math.max(0, e.column - 1);
33010
+ {
33011
+ const openIdx = lineText.indexOf("([");
33012
+ if (openIdx !== -1) {
33013
+ const badClose = lineText.indexOf("})", openIdx + 2);
33014
+ if (badClose !== -1) {
33015
+ edits.push({ start: { line: e.line, column: badClose + 1 }, end: { line: e.line, column: badClose + 2 }, newText: "]" });
33016
+ patchedLines.add(e.line);
33017
+ continue;
33018
+ }
33019
+ }
33020
+ }
33021
+ {
33022
+ const openIdx = lineText.indexOf("[(");
33023
+ if (openIdx !== -1) {
33024
+ const closePair = lineText.indexOf("))", openIdx + 2);
33025
+ if (closePair !== -1) {
33026
+ edits.push({ start: { line: e.line, column: closePair + 2 }, end: { line: e.line, column: closePair + 3 }, newText: "]" });
33027
+ patchedLines.add(e.line);
33028
+ continue;
33029
+ }
33030
+ }
33031
+ }
33032
+ {
33033
+ const openPair = lineText.indexOf("([");
33034
+ if (openPair !== -1) {
33035
+ const badClose = lineText.indexOf("})", openPair + 2);
33036
+ if (badClose !== -1) {
33037
+ edits.push({ start: { line: e.line, column: badClose + 1 }, end: { line: e.line, column: badClose + 2 }, newText: "]" });
33038
+ continue;
33039
+ }
33040
+ }
33041
+ }
33042
+ if (/\(\[/.test(lineText) && lineText.indexOf("})", Math.max(0, caret0 - 1)) !== -1) {
33043
+ edits.push(replaceRange(text, at(e), e.length ?? 1, "]"));
33044
+ continue;
33045
+ }
32778
33046
  if (msg.includes("opened '('") && msg.includes("closed with ']'")) {
32779
33047
  const openIdx = lineText.lastIndexOf("(", caret0);
32780
33048
  if (openIdx !== -1) {
@@ -32847,7 +33115,36 @@ function computeFixes(text, errors, level = "safe") {
32847
33115
  const caret0 = Math.max(0, e.column - 1);
32848
33116
  const msg = e.message || "";
32849
33117
  const bracketMatch = msg.match(/Unclosed '(.+?)'/);
32850
- const expectedOpener = bracketMatch ? bracketMatch[1] : null;
33118
+ const expectedOpener = bracketMatch ? (bracketMatch[1] || "").trim() : null;
33119
+ if (expectedOpener === "((") {
33120
+ if (level === "all") {
33121
+ const openIdx = lineText.lastIndexOf("((", caret0);
33122
+ if (openIdx !== -1) {
33123
+ const contentStart = openIdx + 2;
33124
+ const picks = [];
33125
+ const pushIdx2 = (i) => {
33126
+ if (i >= 0)
33127
+ picks.push(i);
33128
+ };
33129
+ pushIdx2(lineText.indexOf("-", contentStart));
33130
+ pushIdx2(lineText.indexOf("=", contentStart));
33131
+ pushIdx2(lineText.indexOf(".", contentStart));
33132
+ pushIdx2(lineText.indexOf("|", contentStart));
33133
+ let insertIdx = picks.length ? Math.min(...picks) : lineText.length;
33134
+ const before = lineText.slice(0, openIdx);
33135
+ const m = before.match(/([A-Za-z0-9_]+)\s*$/);
33136
+ const inferred = m ? m[1] : "";
33137
+ if (inferred) {
33138
+ edits.push({ start: { line: e.line, column: contentStart + 1 }, end: { line: e.line, column: insertIdx + 1 }, newText: inferred + "))" });
33139
+ patchedLines.add(e.line);
33140
+ continue;
33141
+ }
33142
+ patchedLines.add(e.line);
33143
+ continue;
33144
+ }
33145
+ }
33146
+ continue;
33147
+ }
32851
33148
  const bracketMap = {
32852
33149
  "[": "]",
32853
33150
  "{": "}",
@@ -32933,6 +33230,14 @@ function computeFixes(text, errors, level = "safe") {
32933
33230
  patchedLines.add(e.line);
32934
33231
  continue;
32935
33232
  }
33233
+ if (innerSeg.includes("(") || innerSeg.includes(")")) {
33234
+ const replaced = innerSeg.replace(/\(/g, "&#40;").replace(/\)/g, "&#41;");
33235
+ if (replaced !== innerSeg) {
33236
+ edits.push({ start: { line: e.line, column: opened.idx + opened.len + 1 }, end: { line: e.line, column: closerIdx + 1 }, newText: replaced });
33237
+ patchedLines.add(e.line);
33238
+ continue;
33239
+ }
33240
+ }
32936
33241
  }
32937
33242
  }
32938
33243
  if (patchedLines.has(e.line)) {
@@ -32941,9 +33246,35 @@ function computeFixes(text, errors, level = "safe") {
32941
33246
  let closer = "]";
32942
33247
  if (opened)
32943
33248
  closer = opened.close;
32944
- const avail = lineText.slice(caret0);
32945
- const replaceLen = Math.min(closer.length, Math.max(1, avail.length));
32946
- edits.push({ start: { line: e.line, column: caret0 + 1 }, end: { line: e.line, column: caret0 + 1 + replaceLen }, newText: closer });
33249
+ if (closer === "]") {
33250
+ const openIdxSq = lineText.lastIndexOf("[", caret0);
33251
+ if (openIdxSq !== -1) {
33252
+ const picks = [];
33253
+ const pushIdx2 = (i) => {
33254
+ if (i >= 0)
33255
+ picks.push(i);
33256
+ };
33257
+ pushIdx2(lineText.indexOf("-", openIdxSq + 1));
33258
+ pushIdx2(lineText.indexOf("=", openIdxSq + 1));
33259
+ pushIdx2(lineText.indexOf(".", openIdxSq + 1));
33260
+ pushIdx2(lineText.indexOf("|", openIdxSq + 1));
33261
+ let ins = picks.length ? Math.min(...picks) : lineText.length;
33262
+ let tl = ins - 1;
33263
+ while (tl >= 0 && /\s/.test(lineText[tl]))
33264
+ tl--;
33265
+ const startCol2 = tl + 1 + 1;
33266
+ const endCol2 = ins + 1;
33267
+ edits.push({ start: { line: e.line, column: startCol2 }, end: { line: e.line, column: endCol2 }, newText: closer });
33268
+ } else {
33269
+ const avail = lineText.slice(caret0);
33270
+ const replaceLen = Math.min(closer.length, Math.max(1, avail.length));
33271
+ edits.push({ start: { line: e.line, column: caret0 + 1 }, end: { line: e.line, column: caret0 + 1 + replaceLen }, newText: closer });
33272
+ }
33273
+ } else {
33274
+ const avail = lineText.slice(caret0);
33275
+ const replaceLen = Math.min(closer.length, Math.max(1, avail.length));
33276
+ edits.push({ start: { line: e.line, column: caret0 + 1 }, end: { line: e.line, column: caret0 + 1 + replaceLen }, newText: closer });
33277
+ }
32947
33278
  }
32948
33279
  continue;
32949
33280
  }
@@ -33075,9 +33406,11 @@ function computeFixes(text, errors, level = "safe") {
33075
33406
  if (core.length >= 2 && isSlashPair(left, right)) {
33076
33407
  break;
33077
33408
  }
33078
- const newInner = '"' + inner + '"';
33079
- edits.push({ start: { line: e.line, column: contentStart + 1 }, end: { line: e.line, column: closeIdx + 1 }, newText: newInner });
33080
- patchedLines.add(e.line);
33409
+ const replaced = inner.replace(/\(/g, "&#40;").replace(/\)/g, "&#41;");
33410
+ if (replaced !== inner) {
33411
+ edits.push({ start: { line: e.line, column: contentStart + 1 }, end: { line: e.line, column: closeIdx + 1 }, newText: replaced });
33412
+ patchedLines.add(e.line);
33413
+ }
33081
33414
  break;
33082
33415
  }
33083
33416
  searchStart = openIdx + 1;
@@ -33234,14 +33567,33 @@ function computeFixes(text, errors, level = "safe") {
33234
33567
  continue;
33235
33568
  }
33236
33569
  if (is("SE-BOX-EMPTY", e)) {
33237
- const lines = text.split(/\r?\n/);
33238
- const boxIdx = Math.max(0, e.line - 1);
33239
- const boxLine = lines[boxIdx] || "";
33240
- const labelMatch = /^\s*box\s+(.+)$/.exec(boxLine);
33241
- if (labelMatch) {
33242
- const indent = boxLine.match(/^\s*/)?.[0] || "";
33243
- const newLine = `${indent}rect rgb(240, 240, 255)`;
33244
- edits.push({ start: { line: e.line, column: 1 }, end: { line: e.line, column: boxLine.length + 1 }, newText: newLine });
33570
+ if (level === "all") {
33571
+ const lines = text.split(/\r?\n/);
33572
+ const boxIdx = Math.max(0, e.line - 1);
33573
+ const boxLine = lines[boxIdx] || "";
33574
+ const openIndent = (boxLine.match(/^(\s*)/)?.[1] || "").length;
33575
+ let endIdx = -1;
33576
+ for (let i = boxIdx + 1; i < lines.length; i++) {
33577
+ const raw = lines[i] || "";
33578
+ const ind = (raw.match(/^(\s*)/)?.[1] || "").length;
33579
+ if (/^\s*end\s*$/.test(raw) && ind <= openIndent) {
33580
+ endIdx = i;
33581
+ break;
33582
+ }
33583
+ }
33584
+ let hasMsgWithAct = false;
33585
+ if (endIdx !== -1) {
33586
+ const body = lines.slice(boxIdx + 1, endIdx).map((s) => (s || "").trim());
33587
+ hasMsgWithAct = body.some((s) => /->/.test(s) && /[+-]/.test(s));
33588
+ }
33589
+ if (!hasMsgWithAct) {
33590
+ const labelMatch = /^\s*box\s+(.+)$/.exec(boxLine);
33591
+ if (labelMatch) {
33592
+ const indent = boxLine.match(/^\s*/)?.[0] || "";
33593
+ const newLine = `${indent}rect rgb(240, 240, 255)`;
33594
+ edits.push({ start: { line: e.line, column: 1 }, end: { line: e.line, column: boxLine.length + 1 }, newText: newLine });
33595
+ }
33596
+ }
33245
33597
  }
33246
33598
  continue;
33247
33599
  }
@@ -33517,6 +33869,41 @@ ${indent}${tail}` });
33517
33869
  }
33518
33870
  }
33519
33871
  edits.push(insertAt(text, { line: insIdx + 1, column: 1 }, `${openIndent}}
33872
+ `));
33873
+ continue;
33874
+ }
33875
+ if (is("CL-NAMESPACE-MISSING-RBRACE", e)) {
33876
+ const lines = text.split(/\r?\n/);
33877
+ const curIdx = Math.max(0, e.line - 1);
33878
+ const openerRe = /^(\s*)namespace\b.*\{\s*$/;
33879
+ let openIdx = -1;
33880
+ let openIndent = "";
33881
+ for (let i = curIdx; i >= 0; i--) {
33882
+ const m = openerRe.exec(lines[i] || "");
33883
+ if (m) {
33884
+ openIdx = i;
33885
+ openIndent = m[1] || "";
33886
+ break;
33887
+ }
33888
+ }
33889
+ if (openIdx === -1) {
33890
+ const indent = inferIndentFromLine(lines[curIdx] || "");
33891
+ edits.push(insertAt(text, { line: curIdx + 1, column: 1 }, `${indent}}
33892
+ `));
33893
+ continue;
33894
+ }
33895
+ let insIdx = lines.length;
33896
+ for (let i = openIdx + 1; i < lines.length; i++) {
33897
+ const raw = lines[i] || "";
33898
+ if (raw.trim() === "")
33899
+ continue;
33900
+ const ind = inferIndentFromLine(raw);
33901
+ if (ind.length <= openIndent.length) {
33902
+ insIdx = i;
33903
+ break;
33904
+ }
33905
+ }
33906
+ edits.push(insertAt(text, { line: insIdx + 1, column: 1 }, `${openIndent}}
33520
33907
  `));
33521
33908
  continue;
33522
33909
  }