@probelabs/probe 0.6.0-rc204 → 0.6.0-rc205

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.
@@ -3146,10 +3146,13 @@ Remember: Use proper XML format with BOTH opening and closing tags:
3146
3146
 
3147
3147
  Available tools: ${validTools.join(', ')}
3148
3148
 
3149
- Or for quick completion if your previous response was already correct and complete:
3150
- <attempt_complete>
3149
+ To complete with a direct answer:
3150
+ <attempt_completion>Your final answer here</attempt_completion>
3151
+
3152
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
3153
+ <attempt_complete></attempt_complete>
3151
3154
 
3152
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
3155
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
3153
3156
  }
3154
3157
 
3155
3158
  currentMessages.push({
@@ -4062,9 +4065,9 @@ Convert your previous response content into actual JSON data that follows this s
4062
4065
  return true;
4063
4066
  }
4064
4067
 
4065
- // Empty attempt_complete reminders
4066
- if (content.includes('When using <attempt_complete>') &&
4067
- content.includes('this must be the ONLY content in your response')) {
4068
+ // Empty attempt_complete reminders (legacy and new format)
4069
+ if (content.includes('<attempt_complete></attempt_complete>') &&
4070
+ content.includes('reuses your PREVIOUS assistant message')) {
4068
4071
  return true;
4069
4072
  }
4070
4073
 
@@ -31713,6 +31713,8 @@ var init_semantics = __esm({
31713
31713
  constructor(ctx, knownIds, knownEdgeIds) {
31714
31714
  super();
31715
31715
  this.edgeCount = 0;
31716
+ this.subgraphStack = [];
31717
+ this.reportedSubgraphIdCollision = /* @__PURE__ */ new Set();
31716
31718
  this.validateVisitor();
31717
31719
  this.ctx = ctx;
31718
31720
  this.knownIds = knownIds;
@@ -31905,8 +31907,13 @@ var init_semantics = __esm({
31905
31907
  }
31906
31908
  }
31907
31909
  subgraph(ctx) {
31910
+ const idTok = ctx.subgraphIdOrFirstWord && ctx.subgraphIdOrFirstWord[0];
31911
+ if (idTok)
31912
+ this.subgraphStack.push({ id: String(idTok.image) });
31908
31913
  if (ctx.subgraphStatement)
31909
31914
  ctx.subgraphStatement.forEach((s) => this.visit(s));
31915
+ if (idTok)
31916
+ this.subgraphStack.pop();
31910
31917
  }
31911
31918
  subgraphStatement(ctx) {
31912
31919
  for (const k of Object.keys(ctx)) {
@@ -31969,6 +31976,27 @@ var init_semantics = __esm({
31969
31976
  }
31970
31977
  if (ctx.nodeShape)
31971
31978
  ctx.nodeShape.forEach((n) => this.visit(n));
31979
+ const idTok = ctx.nodeId && ctx.nodeId[0];
31980
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
31981
+ const idToken = idTok || idNumTok;
31982
+ if (idToken && this.subgraphStack.length > 0) {
31983
+ const id = String(idToken.image);
31984
+ const hasCollision = this.subgraphStack.some((sg) => sg.id === id);
31985
+ if (hasCollision) {
31986
+ const key = `${id}:${idToken.startLine ?? 1}:${idToken.startColumn ?? 1}`;
31987
+ if (!this.reportedSubgraphIdCollision.has(key)) {
31988
+ this.reportedSubgraphIdCollision.add(key);
31989
+ this.ctx.errors.push({
31990
+ line: idToken.startLine ?? 1,
31991
+ column: idToken.startColumn ?? 1,
31992
+ severity: "error",
31993
+ code: "FL-SUBGRAPH-ID-COLLISION",
31994
+ message: `Node id '${id}' conflicts with an enclosing subgraph id and creates a cycle in Mermaid.`,
31995
+ hint: "Rename the subgraph id or the node id, or use a quoted subgraph title with no explicit id."
31996
+ });
31997
+ }
31998
+ }
31999
+ }
31972
32000
  if (hasAttr) {
31973
32001
  const attr = ctx.attrObject?.[0];
31974
32002
  const pairs = attr?.children?.attrPair || [];
@@ -36009,6 +36037,7 @@ function computeFixes(text, errors, level = "safe") {
36009
36037
  const patchedLines = /* @__PURE__ */ new Set();
36010
36038
  const seen = /* @__PURE__ */ new Set();
36011
36039
  const piQuoteClosedLines = /* @__PURE__ */ new Set();
36040
+ const subgraphCollisionRename = /* @__PURE__ */ new Map();
36012
36041
  function sanitizeAllQuotedSegmentsInShapes(lineText, lineNo) {
36013
36042
  const shapes = [
36014
36043
  { open: "[[", close: "]]" },
@@ -36728,6 +36757,28 @@ function computeFixes(text, errors, level = "safe") {
36728
36757
  }
36729
36758
  continue;
36730
36759
  }
36760
+ if (is("FL-SUBGRAPH-ID-COLLISION", e)) {
36761
+ if (level === "all") {
36762
+ const lineText = lineTextAt(text, e.line);
36763
+ if (lineText.trimStart().startsWith("subgraph"))
36764
+ continue;
36765
+ const caret0 = Math.max(0, e.column - 1);
36766
+ const slice = lineText.slice(caret0);
36767
+ const m = slice.match(/^([A-Za-z_][A-Za-z0-9_]*(?:-[A-Za-z0-9_]+)*)/);
36768
+ if (m) {
36769
+ const id = m[1];
36770
+ let newId = subgraphCollisionRename.get(id);
36771
+ if (!newId) {
36772
+ newId = id.endsWith("_node") ? `${id}2` : `${id}_node`;
36773
+ subgraphCollisionRename.set(id, newId);
36774
+ }
36775
+ if (newId !== id) {
36776
+ edits.push(replaceRange(text, { line: e.line, column: caret0 + 1 }, id.length, newId));
36777
+ }
36778
+ }
36779
+ }
36780
+ continue;
36781
+ }
36731
36782
  if (is("FL-LABEL-QUOTE-IN-UNQUOTED", e)) {
36732
36783
  if (level === "safe" || level === "all") {
36733
36784
  const lineText = lineTextAt(text, e.line);
@@ -71005,10 +71056,13 @@ Remember: Use proper XML format with BOTH opening and closing tags:
71005
71056
 
71006
71057
  Available tools: ${validTools.join(", ")}
71007
71058
 
71008
- Or for quick completion if your previous response was already correct and complete:
71009
- <attempt_complete>
71059
+ To complete with a direct answer:
71060
+ <attempt_completion>Your final answer here</attempt_completion>
71061
+
71062
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
71063
+ <attempt_complete></attempt_complete>
71010
71064
 
71011
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
71065
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
71012
71066
  }
71013
71067
  currentMessages.push({
71014
71068
  role: "user",
@@ -71711,7 +71765,7 @@ Convert your previous response content into actual JSON data that follows this s
71711
71765
  if (content.includes("Your response does not match the expected JSON schema") || content.includes("Please provide a valid JSON response") || content.includes("Schema validation error:")) {
71712
71766
  return true;
71713
71767
  }
71714
- if (content.includes("When using <attempt_complete>") && content.includes("this must be the ONLY content in your response")) {
71768
+ if (content.includes("<attempt_complete></attempt_complete>") && content.includes("reuses your PREVIOUS assistant message")) {
71715
71769
  return true;
71716
71770
  }
71717
71771
  return false;
@@ -59506,6 +59506,8 @@ var init_semantics = __esm({
59506
59506
  constructor(ctx, knownIds, knownEdgeIds) {
59507
59507
  super();
59508
59508
  this.edgeCount = 0;
59509
+ this.subgraphStack = [];
59510
+ this.reportedSubgraphIdCollision = /* @__PURE__ */ new Set();
59509
59511
  this.validateVisitor();
59510
59512
  this.ctx = ctx;
59511
59513
  this.knownIds = knownIds;
@@ -59698,8 +59700,13 @@ var init_semantics = __esm({
59698
59700
  }
59699
59701
  }
59700
59702
  subgraph(ctx) {
59703
+ const idTok = ctx.subgraphIdOrFirstWord && ctx.subgraphIdOrFirstWord[0];
59704
+ if (idTok)
59705
+ this.subgraphStack.push({ id: String(idTok.image) });
59701
59706
  if (ctx.subgraphStatement)
59702
59707
  ctx.subgraphStatement.forEach((s5) => this.visit(s5));
59708
+ if (idTok)
59709
+ this.subgraphStack.pop();
59703
59710
  }
59704
59711
  subgraphStatement(ctx) {
59705
59712
  for (const k5 of Object.keys(ctx)) {
@@ -59762,6 +59769,27 @@ var init_semantics = __esm({
59762
59769
  }
59763
59770
  if (ctx.nodeShape)
59764
59771
  ctx.nodeShape.forEach((n5) => this.visit(n5));
59772
+ const idTok = ctx.nodeId && ctx.nodeId[0];
59773
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
59774
+ const idToken = idTok || idNumTok;
59775
+ if (idToken && this.subgraphStack.length > 0) {
59776
+ const id = String(idToken.image);
59777
+ const hasCollision = this.subgraphStack.some((sg) => sg.id === id);
59778
+ if (hasCollision) {
59779
+ const key = `${id}:${idToken.startLine ?? 1}:${idToken.startColumn ?? 1}`;
59780
+ if (!this.reportedSubgraphIdCollision.has(key)) {
59781
+ this.reportedSubgraphIdCollision.add(key);
59782
+ this.ctx.errors.push({
59783
+ line: idToken.startLine ?? 1,
59784
+ column: idToken.startColumn ?? 1,
59785
+ severity: "error",
59786
+ code: "FL-SUBGRAPH-ID-COLLISION",
59787
+ message: `Node id '${id}' conflicts with an enclosing subgraph id and creates a cycle in Mermaid.`,
59788
+ hint: "Rename the subgraph id or the node id, or use a quoted subgraph title with no explicit id."
59789
+ });
59790
+ }
59791
+ }
59792
+ }
59765
59793
  if (hasAttr) {
59766
59794
  const attr = ctx.attrObject?.[0];
59767
59795
  const pairs = attr?.children?.attrPair || [];
@@ -63802,6 +63830,7 @@ function computeFixes(text, errors, level = "safe") {
63802
63830
  const patchedLines = /* @__PURE__ */ new Set();
63803
63831
  const seen = /* @__PURE__ */ new Set();
63804
63832
  const piQuoteClosedLines = /* @__PURE__ */ new Set();
63833
+ const subgraphCollisionRename = /* @__PURE__ */ new Map();
63805
63834
  function sanitizeAllQuotedSegmentsInShapes(lineText, lineNo) {
63806
63835
  const shapes = [
63807
63836
  { open: "[[", close: "]]" },
@@ -64521,6 +64550,28 @@ function computeFixes(text, errors, level = "safe") {
64521
64550
  }
64522
64551
  continue;
64523
64552
  }
64553
+ if (is("FL-SUBGRAPH-ID-COLLISION", e5)) {
64554
+ if (level === "all") {
64555
+ const lineText = lineTextAt(text, e5.line);
64556
+ if (lineText.trimStart().startsWith("subgraph"))
64557
+ continue;
64558
+ const caret0 = Math.max(0, e5.column - 1);
64559
+ const slice = lineText.slice(caret0);
64560
+ const m5 = slice.match(/^([A-Za-z_][A-Za-z0-9_]*(?:-[A-Za-z0-9_]+)*)/);
64561
+ if (m5) {
64562
+ const id = m5[1];
64563
+ let newId = subgraphCollisionRename.get(id);
64564
+ if (!newId) {
64565
+ newId = id.endsWith("_node") ? `${id}2` : `${id}_node`;
64566
+ subgraphCollisionRename.set(id, newId);
64567
+ }
64568
+ if (newId !== id) {
64569
+ edits.push(replaceRange(text, { line: e5.line, column: caret0 + 1 }, id.length, newId));
64570
+ }
64571
+ }
64572
+ }
64573
+ continue;
64574
+ }
64524
64575
  if (is("FL-LABEL-QUOTE-IN-UNQUOTED", e5)) {
64525
64576
  if (level === "safe" || level === "all") {
64526
64577
  const lineText = lineTextAt(text, e5.line);
@@ -98797,10 +98848,13 @@ Remember: Use proper XML format with BOTH opening and closing tags:
98797
98848
 
98798
98849
  Available tools: ${validTools.join(", ")}
98799
98850
 
98800
- Or for quick completion if your previous response was already correct and complete:
98801
- <attempt_complete>
98851
+ To complete with a direct answer:
98852
+ <attempt_completion>Your final answer here</attempt_completion>
98853
+
98854
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
98855
+ <attempt_complete></attempt_complete>
98802
98856
 
98803
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
98857
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
98804
98858
  }
98805
98859
  currentMessages.push({
98806
98860
  role: "user",
@@ -99503,7 +99557,7 @@ Convert your previous response content into actual JSON data that follows this s
99503
99557
  if (content.includes("Your response does not match the expected JSON schema") || content.includes("Please provide a valid JSON response") || content.includes("Schema validation error:")) {
99504
99558
  return true;
99505
99559
  }
99506
- if (content.includes("When using <attempt_complete>") && content.includes("this must be the ONLY content in your response")) {
99560
+ if (content.includes("<attempt_complete></attempt_complete>") && content.includes("reuses your PREVIOUS assistant message")) {
99507
99561
  return true;
99508
99562
  }
99509
99563
  return false;
package/cjs/index.cjs CHANGED
@@ -57189,6 +57189,8 @@ var init_semantics = __esm({
57189
57189
  constructor(ctx, knownIds, knownEdgeIds) {
57190
57190
  super();
57191
57191
  this.edgeCount = 0;
57192
+ this.subgraphStack = [];
57193
+ this.reportedSubgraphIdCollision = /* @__PURE__ */ new Set();
57192
57194
  this.validateVisitor();
57193
57195
  this.ctx = ctx;
57194
57196
  this.knownIds = knownIds;
@@ -57381,8 +57383,13 @@ var init_semantics = __esm({
57381
57383
  }
57382
57384
  }
57383
57385
  subgraph(ctx) {
57386
+ const idTok = ctx.subgraphIdOrFirstWord && ctx.subgraphIdOrFirstWord[0];
57387
+ if (idTok)
57388
+ this.subgraphStack.push({ id: String(idTok.image) });
57384
57389
  if (ctx.subgraphStatement)
57385
57390
  ctx.subgraphStatement.forEach((s5) => this.visit(s5));
57391
+ if (idTok)
57392
+ this.subgraphStack.pop();
57386
57393
  }
57387
57394
  subgraphStatement(ctx) {
57388
57395
  for (const k5 of Object.keys(ctx)) {
@@ -57445,6 +57452,27 @@ var init_semantics = __esm({
57445
57452
  }
57446
57453
  if (ctx.nodeShape)
57447
57454
  ctx.nodeShape.forEach((n5) => this.visit(n5));
57455
+ const idTok = ctx.nodeId && ctx.nodeId[0];
57456
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
57457
+ const idToken = idTok || idNumTok;
57458
+ if (idToken && this.subgraphStack.length > 0) {
57459
+ const id = String(idToken.image);
57460
+ const hasCollision = this.subgraphStack.some((sg) => sg.id === id);
57461
+ if (hasCollision) {
57462
+ const key = `${id}:${idToken.startLine ?? 1}:${idToken.startColumn ?? 1}`;
57463
+ if (!this.reportedSubgraphIdCollision.has(key)) {
57464
+ this.reportedSubgraphIdCollision.add(key);
57465
+ this.ctx.errors.push({
57466
+ line: idToken.startLine ?? 1,
57467
+ column: idToken.startColumn ?? 1,
57468
+ severity: "error",
57469
+ code: "FL-SUBGRAPH-ID-COLLISION",
57470
+ message: `Node id '${id}' conflicts with an enclosing subgraph id and creates a cycle in Mermaid.`,
57471
+ hint: "Rename the subgraph id or the node id, or use a quoted subgraph title with no explicit id."
57472
+ });
57473
+ }
57474
+ }
57475
+ }
57448
57476
  if (hasAttr) {
57449
57477
  const attr = ctx.attrObject?.[0];
57450
57478
  const pairs = attr?.children?.attrPair || [];
@@ -61485,6 +61513,7 @@ function computeFixes(text, errors, level = "safe") {
61485
61513
  const patchedLines = /* @__PURE__ */ new Set();
61486
61514
  const seen = /* @__PURE__ */ new Set();
61487
61515
  const piQuoteClosedLines = /* @__PURE__ */ new Set();
61516
+ const subgraphCollisionRename = /* @__PURE__ */ new Map();
61488
61517
  function sanitizeAllQuotedSegmentsInShapes(lineText, lineNo) {
61489
61518
  const shapes = [
61490
61519
  { open: "[[", close: "]]" },
@@ -62204,6 +62233,28 @@ function computeFixes(text, errors, level = "safe") {
62204
62233
  }
62205
62234
  continue;
62206
62235
  }
62236
+ if (is("FL-SUBGRAPH-ID-COLLISION", e5)) {
62237
+ if (level === "all") {
62238
+ const lineText = lineTextAt(text, e5.line);
62239
+ if (lineText.trimStart().startsWith("subgraph"))
62240
+ continue;
62241
+ const caret0 = Math.max(0, e5.column - 1);
62242
+ const slice = lineText.slice(caret0);
62243
+ const m5 = slice.match(/^([A-Za-z_][A-Za-z0-9_]*(?:-[A-Za-z0-9_]+)*)/);
62244
+ if (m5) {
62245
+ const id = m5[1];
62246
+ let newId = subgraphCollisionRename.get(id);
62247
+ if (!newId) {
62248
+ newId = id.endsWith("_node") ? `${id}2` : `${id}_node`;
62249
+ subgraphCollisionRename.set(id, newId);
62250
+ }
62251
+ if (newId !== id) {
62252
+ edits.push(replaceRange(text, { line: e5.line, column: caret0 + 1 }, id.length, newId));
62253
+ }
62254
+ }
62255
+ }
62256
+ continue;
62257
+ }
62207
62258
  if (is("FL-LABEL-QUOTE-IN-UNQUOTED", e5)) {
62208
62259
  if (level === "safe" || level === "all") {
62209
62260
  const lineText = lineTextAt(text, e5.line);
@@ -96480,10 +96531,13 @@ Remember: Use proper XML format with BOTH opening and closing tags:
96480
96531
 
96481
96532
  Available tools: ${validTools.join(", ")}
96482
96533
 
96483
- Or for quick completion if your previous response was already correct and complete:
96484
- <attempt_complete>
96534
+ To complete with a direct answer:
96535
+ <attempt_completion>Your final answer here</attempt_completion>
96536
+
96537
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
96538
+ <attempt_complete></attempt_complete>
96485
96539
 
96486
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
96540
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
96487
96541
  }
96488
96542
  currentMessages.push({
96489
96543
  role: "user",
@@ -97186,7 +97240,7 @@ Convert your previous response content into actual JSON data that follows this s
97186
97240
  if (content.includes("Your response does not match the expected JSON schema") || content.includes("Please provide a valid JSON response") || content.includes("Schema validation error:")) {
97187
97241
  return true;
97188
97242
  }
97189
- if (content.includes("When using <attempt_complete>") && content.includes("this must be the ONLY content in your response")) {
97243
+ if (content.includes("<attempt_complete></attempt_complete>") && content.includes("reuses your PREVIOUS assistant message")) {
97190
97244
  return true;
97191
97245
  }
97192
97246
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc204",
3
+ "version": "0.6.0-rc205",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -79,7 +79,7 @@
79
79
  "@ai-sdk/openai": "^2.0.10",
80
80
  "@anthropic-ai/claude-agent-sdk": "^0.1.46",
81
81
  "@modelcontextprotocol/sdk": "^1.0.0",
82
- "@probelabs/maid": "^0.0.22",
82
+ "@probelabs/maid": "^0.0.23",
83
83
  "adm-zip": "^0.5.16",
84
84
  "ai": "^5.0.0",
85
85
  "ajv": "^8.17.1",
@@ -3146,10 +3146,13 @@ Remember: Use proper XML format with BOTH opening and closing tags:
3146
3146
 
3147
3147
  Available tools: ${validTools.join(', ')}
3148
3148
 
3149
- Or for quick completion if your previous response was already correct and complete:
3150
- <attempt_complete>
3149
+ To complete with a direct answer:
3150
+ <attempt_completion>Your final answer here</attempt_completion>
3151
+
3152
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
3153
+ <attempt_complete></attempt_complete>
3151
3154
 
3152
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
3155
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
3153
3156
  }
3154
3157
 
3155
3158
  currentMessages.push({
@@ -4062,9 +4065,9 @@ Convert your previous response content into actual JSON data that follows this s
4062
4065
  return true;
4063
4066
  }
4064
4067
 
4065
- // Empty attempt_complete reminders
4066
- if (content.includes('When using <attempt_complete>') &&
4067
- content.includes('this must be the ONLY content in your response')) {
4068
+ // Empty attempt_complete reminders (legacy and new format)
4069
+ if (content.includes('<attempt_complete></attempt_complete>') &&
4070
+ content.includes('reuses your PREVIOUS assistant message')) {
4068
4071
  return true;
4069
4072
  }
4070
4073