mdify-cli 3.0.5__tar.gz → 3.0.7__tar.gz

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.
Files changed (27) hide show
  1. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/PKG-INFO +1 -1
  2. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/__init__.py +1 -1
  3. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/cli.py +59 -29
  4. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/PKG-INFO +1 -1
  5. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/pyproject.toml +1 -1
  6. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/LICENSE +0 -0
  7. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/README.md +0 -0
  8. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/assets/mdify.png +0 -0
  9. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/__main__.py +0 -0
  10. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/container.py +0 -0
  11. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/docling_client.py +0 -0
  12. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/formatting.py +0 -0
  13. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/ssh/__init__.py +0 -0
  14. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/ssh/client.py +0 -0
  15. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/ssh/models.py +0 -0
  16. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/ssh/remote_container.py +0 -0
  17. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify/ssh/transfer.py +0 -0
  18. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/SOURCES.txt +0 -0
  19. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/dependency_links.txt +0 -0
  20. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/entry_points.txt +0 -0
  21. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/requires.txt +0 -0
  22. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/mdify_cli.egg-info/top_level.txt +0 -0
  23. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/setup.cfg +0 -0
  24. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/tests/test_cli.py +0 -0
  25. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/tests/test_container.py +0 -0
  26. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/tests/test_docling_client.py +0 -0
  27. {mdify_cli-3.0.5 → mdify_cli-3.0.7}/tests/test_ssh_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdify-cli
3
- Version: 3.0.5
3
+ Version: 3.0.7
4
4
  Summary: Convert PDFs and document images into structured Markdown for LLM workflows
5
5
  Author: tiroq
6
6
  License-Expression: MIT
@@ -1,3 +1,3 @@
1
1
  """mdify - Convert documents to Markdown via Docling container."""
2
2
 
3
- __version__ = "3.0.5"
3
+ __version__ = "3.0.7"
@@ -1107,17 +1107,17 @@ def main_async_remote(args) -> int:
1107
1107
 
1108
1108
  # Connect to remote server
1109
1109
  if not args.quiet:
1110
- print(f"Connecting to {ssh_config.host}:{ssh_config.port}...", file=sys.stderr)
1110
+ print(color.cyan(f"Connecting to {ssh_config.host}:{ssh_config.port}..."), file=sys.stderr)
1111
1111
 
1112
1112
  await ssh_client.connect()
1113
1113
 
1114
1114
  if not args.quiet:
1115
- print(f"✓ Connected to {ssh_config.host}", file=sys.stderr)
1115
+ print(color.green(f"✓ Connected to {ssh_config.host}"), file=sys.stderr)
1116
1116
 
1117
1117
  # Validate remote resources if not skipped
1118
1118
  if not args.remote_skip_validation:
1119
1119
  if not args.quiet:
1120
- print("Validating remote resources...", file=sys.stderr)
1120
+ print(color.cyan("Validating remote resources..."), file=sys.stderr)
1121
1121
 
1122
1122
  validation_result = await ssh_client.validate_remote_resources()
1123
1123
 
@@ -1152,7 +1152,7 @@ def main_async_remote(args) -> int:
1152
1152
  return 130
1153
1153
 
1154
1154
  if not args.quiet:
1155
- print("✓ All remote resources validated", file=sys.stderr)
1155
+ print(color.green("✓ All remote resources validated"), file=sys.stderr)
1156
1156
 
1157
1157
  # If --remote-validate-only, exit here
1158
1158
  if args.remote_validate_only:
@@ -1178,7 +1178,7 @@ def main_async_remote(args) -> int:
1178
1178
  return 1
1179
1179
 
1180
1180
  if not args.quiet:
1181
- print(f"\nFound {len(files_to_convert)} file(s) to convert", file=sys.stderr)
1181
+ print(color.cyan(f"\nFound {len(files_to_convert)} file(s) to convert"), file=sys.stderr)
1182
1182
 
1183
1183
  # Import remote container and transfer manager
1184
1184
  from mdify.ssh.transfer import FileTransferManager
@@ -1223,12 +1223,12 @@ def main_async_remote(args) -> int:
1223
1223
 
1224
1224
  # Start remote container
1225
1225
  if not args.quiet:
1226
- print(f"\nStarting remote container ({image})...", file=sys.stderr)
1226
+ print(color.cyan(f"\nStarting remote container ({image})..."), file=sys.stderr)
1227
1227
 
1228
1228
  try:
1229
1229
  await remote_container.start()
1230
1230
  if not args.quiet:
1231
- print(f"✓ Container started: {remote_container.state.container_name}", file=sys.stderr)
1231
+ print(color.green(f"✓ Container started: {remote_container.state.container_name}"), file=sys.stderr)
1232
1232
  except Exception as e:
1233
1233
  await ssh_client.disconnect()
1234
1234
  print(f"Error: Failed to start remote container: {e}", file=sys.stderr)
@@ -1319,16 +1319,43 @@ def main_async_remote(args) -> int:
1319
1319
  convert_cmd += f"-F 'mask=true' "
1320
1320
  convert_cmd += f"http://localhost:{args.port}/v1/convert/file"
1321
1321
 
1322
- stdout, stderr, code = await ssh_client.run_command(convert_cmd, timeout=timeout)
1322
+ # Retry conversion command with exponential backoff
1323
+ conversion_attempt = 0
1324
+ conversion_success = False
1325
+ conversion_output = None
1326
+ while conversion_attempt < 3 and not conversion_success:
1327
+ try:
1328
+ if conversion_attempt > 0 and not args.quiet:
1329
+ print(f" ↻ Conversion retry {conversion_attempt}...", file=sys.stderr)
1330
+
1331
+ conversion_output, _, conv_code = await ssh_client.run_command(convert_cmd, timeout=timeout)
1332
+
1333
+ if conv_code == 0:
1334
+ conversion_success = True
1335
+ break
1336
+ else:
1337
+ conversion_attempt += 1
1338
+ except Exception as conv_exc:
1339
+ if is_connection_error(conv_exc) and conversion_attempt < 2:
1340
+ conversion_attempt += 1
1341
+ if not args.quiet:
1342
+ print(f" ↻ Connection lost during conversion. Reconnecting (attempt {conversion_attempt})...", file=sys.stderr)
1343
+ try:
1344
+ await ssh_client.disconnect()
1345
+ except Exception:
1346
+ pass
1347
+ await ssh_client.connect()
1348
+ else:
1349
+ conversion_attempt += 1
1323
1350
 
1324
- if code != 0:
1325
- print(f" ✗ Conversion failed (curl error code {code}): {stderr}", file=sys.stderr)
1351
+ if not conversion_success:
1352
+ print(f" ✗ Failed: Conversion failed after {conversion_attempt} attempt(s)", file=sys.stderr)
1326
1353
  failed += 1
1327
1354
  break
1328
1355
 
1329
1356
  # Parse JSON response to extract markdown content
1330
1357
  try:
1331
- response_data = json.loads(stdout)
1358
+ response_data = json.loads(conversion_output)
1332
1359
 
1333
1360
  # Extract content from response structure
1334
1361
  # Actual format: {"document": {"md_content": "..."}, "status": "success"}
@@ -1357,7 +1384,7 @@ def main_async_remote(args) -> int:
1357
1384
  markdown_content = str(result)
1358
1385
  else:
1359
1386
  # Ultimate fallback
1360
- markdown_content = stdout
1387
+ markdown_content = conversion_output
1361
1388
 
1362
1389
  # Write markdown content to remote file
1363
1390
  write_cmd = f"cat > {remote_output_path} << 'MDIFY_EOF'\n{markdown_content}\nMDIFY_EOF"
@@ -1368,10 +1395,10 @@ def main_async_remote(args) -> int:
1368
1395
  failed += 1
1369
1396
  break
1370
1397
 
1371
- except (json.JSONDecodeError, KeyError, IndexError) as e:
1372
- print(f" ✗ Failed to parse conversion response: {e}", file=sys.stderr)
1398
+ except (json.JSONDecodeError, KeyError, IndexError):
1399
+ print(f" ✗ Failed to parse conversion response", file=sys.stderr)
1373
1400
  if DEBUG:
1374
- print(f" Response: {stdout[:500]}", file=sys.stderr)
1401
+ print(f" Response: {conversion_output[:500]}", file=sys.stderr)
1375
1402
  failed += 1
1376
1403
  break
1377
1404
 
@@ -1380,7 +1407,7 @@ def main_async_remote(args) -> int:
1380
1407
 
1381
1408
  # Download result
1382
1409
  if not args.quiet:
1383
- print(f" Downloading result to {output_file}...", file=sys.stderr)
1410
+ print(color.cyan(f" Downloading result to {output_file}..."), file=sys.stderr)
1384
1411
 
1385
1412
  await transfer_manager.download_file(
1386
1413
  remote_path=remote_output_path,
@@ -1389,7 +1416,7 @@ def main_async_remote(args) -> int:
1389
1416
  )
1390
1417
 
1391
1418
  if not args.quiet:
1392
- print(f" ✓ Download complete: {output_file}", file=sys.stderr)
1419
+ print(color.green(f" ✓ Download complete: {output_file}"), file=sys.stderr)
1393
1420
 
1394
1421
  successful += 1
1395
1422
 
@@ -1401,7 +1428,7 @@ def main_async_remote(args) -> int:
1401
1428
  if is_connection_error(e) and attempt == 0:
1402
1429
  attempt += 1
1403
1430
  if not args.quiet:
1404
- print(" ↻ Connection lost. Reconnecting...", file=sys.stderr)
1431
+ print(color.yellow(" ↻ Connection lost. Reconnecting..."), file=sys.stderr)
1405
1432
  try:
1406
1433
  await ssh_client.disconnect()
1407
1434
  except Exception:
@@ -1419,21 +1446,21 @@ def main_async_remote(args) -> int:
1419
1446
  finally:
1420
1447
  # Stop and remove container
1421
1448
  if not args.quiet:
1422
- print(f"\nStopping remote container...", file=sys.stderr)
1449
+ print(color.cyan(f"\nStopping remote container..."), file=sys.stderr)
1423
1450
 
1424
1451
  try:
1425
1452
  await remote_container.stop(force=False)
1426
1453
  if not args.quiet:
1427
- print(f"✓ Container stopped", file=sys.stderr)
1454
+ print(color.green(f"✓ Container stopped"), file=sys.stderr)
1428
1455
  except Exception as e:
1429
1456
  if not args.quiet:
1430
- print(f"Warning: Failed to stop container: {e}", file=sys.stderr)
1457
+ print(color.yellow(f"Warning: Failed to stop container: {e}"), file=sys.stderr)
1431
1458
 
1432
1459
  # Cleanup remote work directory
1433
1460
  try:
1434
1461
  await ssh_client.run_command(f"rm -rf {work_dir}")
1435
1462
  if not args.quiet:
1436
- print(f"✓ Cleaned up remote directory", file=sys.stderr)
1463
+ print(color.green(f"✓ Cleaned up remote directory"), file=sys.stderr)
1437
1464
  except Exception as e:
1438
1465
  if not args.quiet:
1439
1466
  print(f"Warning: Failed to cleanup remote directory: {e}", file=sys.stderr)
@@ -1442,21 +1469,24 @@ def main_async_remote(args) -> int:
1442
1469
  await ssh_client.disconnect()
1443
1470
 
1444
1471
  # Print summary
1445
- print(f"\n{'='*60}", file=sys.stderr)
1446
- print(f"Remote conversion complete:", file=sys.stderr)
1447
- print(f" Successful: {successful}", file=sys.stderr)
1448
- print(f" Failed: {failed}", file=sys.stderr)
1472
+ print(color.cyan(f"\n{'='*60}"), file=sys.stderr)
1473
+ print(color.cyan(f"Remote conversion complete:"), file=sys.stderr)
1474
+ print(color.green(f" Successful: {successful}"), file=sys.stderr)
1475
+ if failed > 0:
1476
+ print(color.yellow(f" Failed: {failed}"), file=sys.stderr)
1477
+ else:
1478
+ print(f" Failed: {failed}", file=sys.stderr)
1449
1479
  print(f" Total: {len(files_to_convert)}", file=sys.stderr)
1450
- print(f"{'='*60}", file=sys.stderr)
1480
+ print(color.cyan(f"{'='*60}"), file=sys.stderr)
1451
1481
 
1452
1482
  return 0 if failed == 0 else 1
1453
1483
 
1454
1484
  except SSHAuthError as e:
1455
- print(f"Error: SSH authentication failed: {e}", file=sys.stderr)
1485
+ print(color.yellow(f"Error: SSH authentication failed: {e}"), file=sys.stderr)
1456
1486
  print(" Check your SSH key, passphrase, or username", file=sys.stderr)
1457
1487
  return 1
1458
1488
  except SSHConnectionError as e:
1459
- print(f"Error: SSH connection failed: {e}", file=sys.stderr)
1489
+ print(color.yellow(f"Error: SSH connection failed: {e}"), file=sys.stderr)
1460
1490
  if hasattr(e, 'host') and hasattr(e, 'port'):
1461
1491
  print(f" Host: {e.host}:{e.port}", file=sys.stderr)
1462
1492
  return 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdify-cli
3
- Version: 3.0.5
3
+ Version: 3.0.7
4
4
  Summary: Convert PDFs and document images into structured Markdown for LLM workflows
5
5
  Author: tiroq
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mdify-cli"
3
- version = "3.0.5"
3
+ version = "3.0.7"
4
4
  description = "Convert PDFs and document images into structured Markdown for LLM workflows"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes