invar-tools 1.17.13__py3-none-any.whl → 1.17.14__py3-none-any.whl
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.
- invar/mcp/handlers.py +58 -2
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/METADATA +1 -1
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/RECORD +8 -8
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/WHEEL +0 -0
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/entry_points.txt +0 -0
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/licenses/LICENSE +0 -0
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/licenses/LICENSE-GPL +0 -0
- {invar_tools-1.17.13.dist-info → invar_tools-1.17.14.dist-info}/licenses/NOTICE +0 -0
invar/mcp/handlers.py
CHANGED
|
@@ -427,11 +427,24 @@ async def _execute_command(
|
|
|
427
427
|
timeout=timeout,
|
|
428
428
|
)
|
|
429
429
|
|
|
430
|
+
stdout = result.stdout.strip()
|
|
431
|
+
|
|
432
|
+
# Try to parse as JSON
|
|
430
433
|
try:
|
|
431
|
-
parsed = json.loads(
|
|
434
|
+
parsed = json.loads(stdout)
|
|
432
435
|
return ([TextContent(type="text", text=json.dumps(parsed, indent=2))], parsed)
|
|
433
436
|
except json.JSONDecodeError:
|
|
434
|
-
|
|
437
|
+
# Try to fix unescaped newlines in JSON strings
|
|
438
|
+
# Guard/map commands may output multiline JSON with literal newlines
|
|
439
|
+
fixed = _fix_json_newlines(stdout)
|
|
440
|
+
try:
|
|
441
|
+
parsed = json.loads(fixed)
|
|
442
|
+
return ([TextContent(type="text", text=json.dumps(parsed, indent=2))], parsed)
|
|
443
|
+
except json.JSONDecodeError:
|
|
444
|
+
pass
|
|
445
|
+
|
|
446
|
+
# Fall back to text output
|
|
447
|
+
output = stdout
|
|
435
448
|
if result.stderr:
|
|
436
449
|
output += f"\n\nStderr:\n{result.stderr}"
|
|
437
450
|
return [TextContent(type="text", text=output)]
|
|
@@ -440,3 +453,46 @@ async def _execute_command(
|
|
|
440
453
|
return [TextContent(type="text", text=f"Error: Command timed out ({timeout}s)")]
|
|
441
454
|
except Exception as e:
|
|
442
455
|
return [TextContent(type="text", text=f"Error: {e}")]
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
# @invar:allow shell_too_complex: Simple state machine, 6 branches is minimal
|
|
459
|
+
# @invar:allow shell_pure_logic: No I/O, but called from shell context
|
|
460
|
+
# @invar:allow shell_result: Pure transformation, returns str not Result
|
|
461
|
+
def _fix_json_newlines(text: str) -> str:
|
|
462
|
+
"""Fix unescaped newlines in JSON strings.
|
|
463
|
+
|
|
464
|
+
When subprocess outputs multiline JSON, newlines inside string values
|
|
465
|
+
are not escaped, causing json.loads() to fail. This function escapes them.
|
|
466
|
+
|
|
467
|
+
DX-33: Escape hatch for complex pure logic helper.
|
|
468
|
+
"""
|
|
469
|
+
result = []
|
|
470
|
+
i = 0
|
|
471
|
+
while i < len(text):
|
|
472
|
+
if text[i] == '"':
|
|
473
|
+
# Inside a string - collect until closing quote
|
|
474
|
+
result.append('"')
|
|
475
|
+
i += 1
|
|
476
|
+
while i < len(text):
|
|
477
|
+
c = text[i]
|
|
478
|
+
if c == "\\" and i + 1 < len(text):
|
|
479
|
+
# Escaped character - keep as is
|
|
480
|
+
result.append("\\")
|
|
481
|
+
result.append(text[i + 1])
|
|
482
|
+
i += 2
|
|
483
|
+
elif c == '"':
|
|
484
|
+
# End of string
|
|
485
|
+
result.append('"')
|
|
486
|
+
i += 1
|
|
487
|
+
break
|
|
488
|
+
elif c == "\n" or c == "\r":
|
|
489
|
+
# Unescaped newline - escape it
|
|
490
|
+
result.append("\\n")
|
|
491
|
+
i += 1
|
|
492
|
+
else:
|
|
493
|
+
result.append(c)
|
|
494
|
+
i += 1
|
|
495
|
+
else:
|
|
496
|
+
result.append(text[i])
|
|
497
|
+
i += 1
|
|
498
|
+
return "".join(result)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: invar-tools
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.14
|
|
4
4
|
Summary: AI-native software engineering tools with design-by-contract verification
|
|
5
5
|
Project-URL: Homepage, https://github.com/tefx/invar
|
|
6
6
|
Project-URL: Documentation, https://github.com/tefx/invar#readme
|
|
@@ -50,7 +50,7 @@ invar/core/patterns/registry.py,sha256=2rz0wWDRarMkuHN-qM_ZrT3qeGFDSKMABvRvPNZxQ
|
|
|
50
50
|
invar/core/patterns/types.py,sha256=ULAlWuAdmO6CFcEDjTrWBfzNTBsnomAl2d25tR11ihU,5506
|
|
51
51
|
invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
|
|
52
52
|
invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
|
|
53
|
-
invar/mcp/handlers.py,sha256=
|
|
53
|
+
invar/mcp/handlers.py,sha256=VQGpFG6voBOXML2TtBFyU_lkCTn83yF4GwmMvl2gxvI,18762
|
|
54
54
|
invar/mcp/server.py,sha256=zSpY9bCFuq4mWe7XfolTnwHffhdmoyN40aFL4L7dFrE,20407
|
|
55
55
|
invar/node_tools/.gitignore,sha256=M2kz8Iw7Kzmi44mKo1r7_HOZMh79a7dFDdRrqXyaEhI,530
|
|
56
56
|
invar/node_tools/MANIFEST,sha256=2Z2at-27MK8K7DSjOjjtR4faTbt6eCiKQuEfvP_lwH8,145
|
|
@@ -2778,10 +2778,10 @@ invar/templates/skills/invar-reflect/template.md,sha256=Rr5hvbllvmd8jSLf_0ZjyKt6
|
|
|
2778
2778
|
invar/templates/skills/investigate/SKILL.md.jinja,sha256=cp6TBEixBYh1rLeeHOR1yqEnFqv1NZYePORMnavLkQI,3231
|
|
2779
2779
|
invar/templates/skills/propose/SKILL.md.jinja,sha256=6BuKiCqO1AEu3VtzMHy1QWGqr_xqG9eJlhbsKT4jev4,3463
|
|
2780
2780
|
invar/templates/skills/review/SKILL.md.jinja,sha256=ET5mbdSe_eKgJbi2LbgFC-z1aviKcHOBw7J5Q28fr4U,14105
|
|
2781
|
-
invar_tools-1.17.
|
|
2782
|
-
invar_tools-1.17.
|
|
2783
|
-
invar_tools-1.17.
|
|
2784
|
-
invar_tools-1.17.
|
|
2785
|
-
invar_tools-1.17.
|
|
2786
|
-
invar_tools-1.17.
|
|
2787
|
-
invar_tools-1.17.
|
|
2781
|
+
invar_tools-1.17.14.dist-info/METADATA,sha256=TC_Puck2FidWoZbAcQOGw7HmWg5F9fjAqY0mY-yRX-g,28596
|
|
2782
|
+
invar_tools-1.17.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
2783
|
+
invar_tools-1.17.14.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
|
|
2784
|
+
invar_tools-1.17.14.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
|
|
2785
|
+
invar_tools-1.17.14.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
|
|
2786
|
+
invar_tools-1.17.14.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
|
|
2787
|
+
invar_tools-1.17.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|