gdharness 1.0.31 → 1.0.32

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/build/cli.js CHANGED
@@ -16575,7 +16575,7 @@ var init_tool_definitions = __esm(() => {
16575
16575
  operations: {
16576
16576
  tree: { summary: "the live scene tree", requires: [] },
16577
16577
  text: {
16578
- summary: "every line of text under nodePath, the values in its fields included, in the order somebody reads the screen, leaving out what is hidden and everything under it. Every line reads as drawn: rich text without its tags, text only as far as it has been typed out, a translation rather than its key, an upper-case label in capitals and a secret field as its mask. Tab titles, menu bar titles, list items, a tree's column titles and rows, and an open menu's items read a line each",
16578
+ summary: "every line of text under nodePath, the values in its fields included, in the order somebody reads the screen, leaving out what is hidden and everything under it. Every line reads as drawn: rich text without its tags, text only as far as it has been typed out, a translation rather than its key, an upper-case label in capitals and a secret field as its mask. Tab titles, menu bar titles, list items, a tree's column titles and rows, and an open menu's items and the titles of its separators read a line each",
16579
16579
  requires: []
16580
16580
  },
16581
16581
  find: {
@@ -664,7 +664,19 @@ func choose(params: Dictionary) -> Dictionary:
664
664
  "message": "%s has no such item. It holds: %s" % [node_path, ", ".join(_items_of(menu))]
665
665
  }
666
666
  if menu.is_item_separator(index):
667
- return {"type": "error", "message": "%s item %d is a separator, not a choice" % [node_path, index]}
667
+ var heading: String = Words.item_says(menu, index).strip_edges()
668
+ return {
669
+ "type": "error",
670
+ "message":
671
+ (
672
+ "%s item %d is a separator, not a choice" % [node_path, index]
673
+ if heading.is_empty()
674
+ else (
675
+ "%s item %d, %s, is a separator heading the items below it, not a choice"
676
+ % [node_path, index, heading]
677
+ )
678
+ )
679
+ }
668
680
  if menu.is_item_disabled(index):
669
681
  return {
670
682
  "type": "error",
@@ -732,26 +744,39 @@ static func _wanted_item(menu: PopupMenu, params: Dictionary) -> int:
732
744
  var wanted: String = str(params.get("text", ""))
733
745
  if wanted.is_empty():
734
746
  return -1
747
+ # The items before the separators, because a heading can carry the same words as an item under
748
+ # it, and finding the heading first refused the choice the caller meant. A separator is still
749
+ # looked for after, so a heading asked for by name is refused as one rather than as missing.
750
+ var order: Array[int] = []
751
+ for separators: bool in [false, true]:
752
+ for index: int in menu.get_item_count():
753
+ if menu.is_item_separator(index) == separators:
754
+ order.append(index)
735
755
  var shown: Array[String] = []
736
756
  var held: Array[String] = []
737
- for index: int in menu.get_item_count():
757
+ for index: int in order:
738
758
  shown.append(Words.item_says(menu, index))
739
759
  held.append(menu.get_item_text(index))
740
760
  for words: Array[String] in [shown, held]:
741
- for index: int in words.size():
742
- if words[index] == wanted:
743
- return index
744
- for index: int in words.size():
745
- if words[index].nocasecmp_to(wanted) == 0:
746
- return index
761
+ for at: int in words.size():
762
+ if words[at] == wanted:
763
+ return order[at]
764
+ for at: int in words.size():
765
+ if words[at].nocasecmp_to(wanted) == 0:
766
+ return order[at]
747
767
  return -1
748
768
 
749
769
 
750
- ## What the menu shows, for a refusal that names the choices rather than the miss.
770
+ ## What the menu shows, for a refusal that names the choices rather than the miss: a titled
771
+ ## separator marked as the heading it is, and one with no title left out, since it shows nothing.
751
772
  static func _items_of(menu: PopupMenu) -> Array[String]:
752
773
  var said: Array[String] = []
753
774
  for index: int in menu.get_item_count():
754
- said.append("%d: %s" % [index, Words.item_says(menu, index)])
775
+ var words: String = Words.item_says(menu, index)
776
+ if not menu.is_item_separator(index):
777
+ said.append("%d: %s" % [index, words])
778
+ elif not words.strip_edges().is_empty():
779
+ said.append("%d: %s (a heading)" % [index, words])
755
780
  return said
756
781
 
757
782
 
@@ -49,10 +49,11 @@ static func lines_said_by(node: Node) -> Array[String]:
49
49
  for item: int in list.item_count:
50
50
  _keep(_as_drawn(node, list.get_item_text(item), list.get_item_auto_translate_mode(item)), lines)
51
51
  elif node is PopupMenu:
52
+ # A separator too, by its title: the popup draws a titled one as a heading over the items
53
+ # below it, and one without a title says nothing and is dropped as an empty line.
52
54
  var menu: PopupMenu = node
53
55
  for item: int in menu.item_count:
54
- if not menu.is_item_separator(item):
55
- _keep(item_says(menu, item), lines)
56
+ _keep(item_says(menu, item), lines)
56
57
  elif node is Tree:
57
58
  var tree: Tree = node
58
59
  if tree.column_titles_visible:
package/build/index.js CHANGED
@@ -30701,7 +30701,7 @@ var TOOL_SPECS = [
30701
30701
  operations: {
30702
30702
  tree: { summary: "the live scene tree", requires: [] },
30703
30703
  text: {
30704
- summary: "every line of text under nodePath, the values in its fields included, in the order somebody reads the screen, leaving out what is hidden and everything under it. Every line reads as drawn: rich text without its tags, text only as far as it has been typed out, a translation rather than its key, an upper-case label in capitals and a secret field as its mask. Tab titles, menu bar titles, list items, a tree's column titles and rows, and an open menu's items read a line each",
30704
+ summary: "every line of text under nodePath, the values in its fields included, in the order somebody reads the screen, leaving out what is hidden and everything under it. Every line reads as drawn: rich text without its tags, text only as far as it has been typed out, a translation rather than its key, an upper-case label in capitals and a secret field as its mask. Tab titles, menu bar titles, list items, a tree's column titles and rows, and an open menu's items and the titles of its separators read a line each",
30705
30705
  requires: []
30706
30706
  },
30707
30707
  find: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdharness",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
4
4
  "mcpName": "io.github.Aureliolo/gdharness",
5
5
  "description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
6
6
  "type": "module",