openmd-cli 0.1.0__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.
Files changed (177) hide show
  1. openmd/__init__.py +3 -0
  2. openmd/__main__.py +5 -0
  3. openmd/adapters/__init__.py +1 -0
  4. openmd/adapters/base.py +95 -0
  5. openmd/adapters/bilibili/__init__.py +11 -0
  6. openmd/adapters/bilibili/adapter.py +104 -0
  7. openmd/adapters/bilibili/discovery.py +33 -0
  8. openmd/adapters/douyin/__init__.py +11 -0
  9. openmd/adapters/douyin/adapter.py +117 -0
  10. openmd/adapters/douyin/discovery.py +36 -0
  11. openmd/adapters/douyin/sidecar.py +77 -0
  12. openmd/adapters/generic_media/__init__.py +14 -0
  13. openmd/adapters/high_privacy.py +77 -0
  14. openmd/adapters/local_audio/__init__.py +14 -0
  15. openmd/adapters/local_audio/adapter.py +169 -0
  16. openmd/adapters/local_audio/asr.py +58 -0
  17. openmd/adapters/local_audio/backends/__init__.py +1 -0
  18. openmd/adapters/local_audio/backends/auto.py +177 -0
  19. openmd/adapters/local_audio/backends/faster_whisper.py +285 -0
  20. openmd/adapters/local_audio/backends/funasr_sense_voice.py +14 -0
  21. openmd/adapters/local_audio/backends/qwen3_asr.py +254 -0
  22. openmd/adapters/opencli.py +770 -0
  23. openmd/adapters/pdf/__init__.py +11 -0
  24. openmd/adapters/pdf/adapter.py +153 -0
  25. openmd/adapters/pdf/backends/__init__.py +1 -0
  26. openmd/adapters/pdf/backends/markitdown.py +165 -0
  27. openmd/adapters/pdf/parser.py +56 -0
  28. openmd/adapters/qq_group/__init__.py +11 -0
  29. openmd/adapters/qq_group/adapter.py +289 -0
  30. openmd/adapters/qq_group/parsers/__init__.py +1 -0
  31. openmd/adapters/qq_group/parsers/html.py +60 -0
  32. openmd/adapters/qq_group/parsers/json.py +71 -0
  33. openmd/adapters/registry.py +149 -0
  34. openmd/adapters/screenshot/__init__.py +11 -0
  35. openmd/adapters/screenshot/adapter.py +154 -0
  36. openmd/adapters/screenshot/backends/__init__.py +1 -0
  37. openmd/adapters/screenshot/backends/paddle.py +15 -0
  38. openmd/adapters/screenshot/backends/rapidocr.py +176 -0
  39. openmd/adapters/screenshot/backends/tesseract.py +15 -0
  40. openmd/adapters/screenshot/ocr.py +84 -0
  41. openmd/adapters/wechat_group/__init__.py +11 -0
  42. openmd/adapters/wechat_group/adapter.py +160 -0
  43. openmd/adapters/wechat_group/wx_cli.py +268 -0
  44. openmd/adapters/wechat_moments/__init__.py +11 -0
  45. openmd/adapters/wechat_moments/adapter.py +167 -0
  46. openmd/adapters/wechat_moments/wx_cli.py +265 -0
  47. openmd/adapters/weixin/__init__.py +11 -0
  48. openmd/adapters/weixin/adapter.py +148 -0
  49. openmd/adapters/weixin/discovery.py +510 -0
  50. openmd/adapters/weixin/report.py +278 -0
  51. openmd/adapters/xiaohongshu.py +158 -0
  52. openmd/backends/__init__.py +1 -0
  53. openmd/backends/base.py +204 -0
  54. openmd/backends/bilibili.py +1480 -0
  55. openmd/backends/bilibili_wbi.py +277 -0
  56. openmd/backends/discourse.py +426 -0
  57. openmd/backends/douyin.py +868 -0
  58. openmd/backends/douyin_detail.py +124 -0
  59. openmd/backends/douyin_providers.py +602 -0
  60. openmd/backends/executor.py +546 -0
  61. openmd/backends/feishu.py +861 -0
  62. openmd/backends/generic_media.py +77 -0
  63. openmd/backends/interactive.py +60 -0
  64. openmd/backends/ocr.py +41 -0
  65. openmd/backends/opencli.py +82 -0
  66. openmd/backends/pdf.py +122 -0
  67. openmd/backends/registry.py +234 -0
  68. openmd/backends/screenshot.py +79 -0
  69. openmd/backends/video_metadata.py +167 -0
  70. openmd/backends/web_article.py +363 -0
  71. openmd/backends/wechat_group.py +35 -0
  72. openmd/backends/wechat_moments.py +35 -0
  73. openmd/backends/weixin.py +767 -0
  74. openmd/backends/x.py +455 -0
  75. openmd/backends/xiaoe.py +940 -0
  76. openmd/backends/xiaohongshu.py +911 -0
  77. openmd/backends/xiaohongshu_providers.py +876 -0
  78. openmd/backends/xiaoyuzhou.py +1017 -0
  79. openmd/backends/youtube.py +280 -0
  80. openmd/backends/youtube_discovery.py +1245 -0
  81. openmd/backends/youtube_transcript.py +213 -0
  82. openmd/browser_extension/background.js +231 -0
  83. openmd/browser_extension/icons/icon-128.png +0 -0
  84. openmd/browser_extension/icons/icon-16.png +0 -0
  85. openmd/browser_extension/icons/icon-32.png +0 -0
  86. openmd/browser_extension/icons/icon-48.png +0 -0
  87. openmd/browser_extension/icons/icon-512.png +0 -0
  88. openmd/browser_extension/idle.html +6 -0
  89. openmd/browser_extension/manifest.json +43 -0
  90. openmd/browser_extension/options.html +42 -0
  91. openmd/browser_extension/options.js +117 -0
  92. openmd/browser_extension/popup.css +71 -0
  93. openmd/browser_extension/popup.html +17 -0
  94. openmd/browser_extension/popup.js +59 -0
  95. openmd/browser_extension/vendor/opencli-bridge/LICENSE +190 -0
  96. openmd/browser_extension/vendor/opencli-bridge/VENDOR.md +31 -0
  97. openmd/browser_extension/vendor/opencli-bridge/background.js +2742 -0
  98. openmd/browser_host.py +503 -0
  99. openmd/browser_setup.py +106 -0
  100. openmd/cli.py +2012 -0
  101. openmd/console.py +32 -0
  102. openmd/core/__init__.py +1 -0
  103. openmd/core/capabilities.py +162 -0
  104. openmd/core/content_validation.py +323 -0
  105. openmd/core/coverage.py +163 -0
  106. openmd/core/detector.py +247 -0
  107. openmd/core/doctor.py +104 -0
  108. openmd/core/execution_policy.py +164 -0
  109. openmd/core/filename.py +64 -0
  110. openmd/core/input_validation.py +91 -0
  111. openmd/core/local_config.py +96 -0
  112. openmd/core/manifest.py +156 -0
  113. openmd/core/models.py +168 -0
  114. openmd/core/opencli_output.py +34 -0
  115. openmd/core/operation_contract.py +60 -0
  116. openmd/core/output.py +194 -0
  117. openmd/core/package_contract.py +335 -0
  118. openmd/core/package_validator.py +489 -0
  119. openmd/core/package_writer.py +666 -0
  120. openmd/core/planner.py +345 -0
  121. openmd/core/preferences.py +61 -0
  122. openmd/core/readable.py +129 -0
  123. openmd/core/receipt.py +285 -0
  124. openmd/core/renderer.py +185 -0
  125. openmd/core/runlog.py +208 -0
  126. openmd/core/secrets.py +313 -0
  127. openmd/doctor_view.py +68 -0
  128. openmd/interactive.py +453 -0
  129. openmd/ocr/__init__.py +1 -0
  130. openmd/ocr/breakers.py +84 -0
  131. openmd/ocr/config.py +54 -0
  132. openmd/ocr/documents.py +522 -0
  133. openmd/ocr/endpoint.py +72 -0
  134. openmd/ocr/layout.py +92 -0
  135. openmd/ocr/layout_filter.py +118 -0
  136. openmd/ocr/layout_worker.py +89 -0
  137. openmd/ocr/native_math.py +220 -0
  138. openmd/ocr/office.py +305 -0
  139. openmd/ocr/ollama.py +200 -0
  140. openmd/ocr/otsl.py +51 -0
  141. openmd/ocr/ovis-prompt.txt +1 -0
  142. openmd/ocr/pipeline.py +384 -0
  143. openmd/ocr/settings.json +25 -0
  144. openmd/ocr/tiling.py +631 -0
  145. openmd/post_video.py +154 -0
  146. openmd/probe.py +397 -0
  147. openmd/routing/__init__.py +1 -0
  148. openmd/routing/cards/builtin.json +620 -0
  149. openmd/routing/cards/defuddle.json +70 -0
  150. openmd/routing/cards/x-tweet-fetcher.json +71 -0
  151. openmd/routing/cards/xyz-dl.json +60 -0
  152. openmd/routing/cards/yutto.json +68 -0
  153. openmd/routing/entry_shim.py +71 -0
  154. openmd/routing/lifecycle.py +459 -0
  155. openmd/routing/loader.py +138 -0
  156. openmd/routing/providers.py +158 -0
  157. openmd/routing/readers.py +108 -0
  158. openmd/routing/routes.json +504 -0
  159. openmd/routing/runner.py +192 -0
  160. openmd/routing/view.py +40 -0
  161. openmd/runtime/__init__.py +1 -0
  162. openmd/runtime/_windows_job.py +234 -0
  163. openmd/runtime/asr.py +217 -0
  164. openmd/runtime/asr_worker.py +119 -0
  165. openmd/runtime/gpu_lock.py +81 -0
  166. openmd/runtime/gpu_quarantine.py +85 -0
  167. openmd/runtime/interpreters.py +407 -0
  168. openmd/runtime/managed_tools.py +204 -0
  169. openmd/runtime/models.py +202 -0
  170. openmd/runtime/services.py +175 -0
  171. openmd/runtime/tempdirs.py +227 -0
  172. openmd_cli-0.1.0.dist-info/METADATA +168 -0
  173. openmd_cli-0.1.0.dist-info/RECORD +177 -0
  174. openmd_cli-0.1.0.dist-info/WHEEL +5 -0
  175. openmd_cli-0.1.0.dist-info/entry_points.txt +2 -0
  176. openmd_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  177. openmd_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,71 @@
1
+ {
2
+ "schema": "openmd.tool-card/v1",
3
+ "installation": {
4
+ "mode": "isolated_existing",
5
+ "sha256": "e00f35735b2408bd3f28bdcb933531a2a138db951d108407d1f5cb6d7a19c166",
6
+ "verification": "SHA256 of the installed entry file; dependency tree is isolated, not attested"
7
+ },
8
+ "evidence": [
9
+ {
10
+ "date": "2026-11-07",
11
+ "ledger": "docs/benchmarks/routes/trials-backup.jsonl",
12
+ "scope": "one real sample; does not establish platform-wide completeness"
13
+ }
14
+ ],
15
+ "id": "x-tweet-fetcher",
16
+ "kind": "python_entry",
17
+ "version": "3.1.0",
18
+ "license": "MIT",
19
+ "homepage": "https://github.com/ythx-101/x-tweet-fetcher",
20
+ "launcher": {
21
+ "entry": "xtf.cli:main",
22
+ "which": [
23
+ "xtf"
24
+ ]
25
+ },
26
+ "capabilities": [
27
+ {
28
+ "status_policy": "verified_if_valid_else_failed",
29
+ "requires_login": false,
30
+ "cost_class": "none",
31
+ "id": "x-tweet-fetcher.x.content",
32
+ "sources": [
33
+ "x"
34
+ ],
35
+ "capability": "content",
36
+ "url_hosts": [
37
+ "x.com",
38
+ "twitter.com",
39
+ "www.x.com",
40
+ "www.twitter.com"
41
+ ],
42
+ "url_path_pattern": "^/[^/]+/status/[0-9]+/?$",
43
+ "argv": [
44
+ "--url",
45
+ "{url}"
46
+ ],
47
+ "reader": {
48
+ "type": "json_stdout",
49
+ "title_from_first_line": true,
50
+ "fields": {
51
+ "text": [
52
+ "tweet.article.full_text",
53
+ "tweet.text"
54
+ ],
55
+ "title": "tweet.article.title",
56
+ "author": "tweet.author",
57
+ "published_at": "tweet.created_at"
58
+ }
59
+ },
60
+ "gates": [
61
+ "network"
62
+ ],
63
+ "source_level": "third_party_extractor",
64
+ "timeout_s": 90,
65
+ "validation": {
66
+ "min_chars": 1
67
+ },
68
+ "coverage_note": "Single post only; this extractor does not establish full thread coverage."
69
+ }
70
+ ]
71
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "schema": "openmd.tool-card/v1",
3
+ "installation": {
4
+ "mode": "isolated_existing",
5
+ "sha256": "d5676a016f220f4a6a7c2944ccfb77dd92cf33863500f5ac18b986f34c97aa02",
6
+ "verification": "SHA256 of the installed entry file; dependency tree is isolated, not attested"
7
+ },
8
+ "evidence": [
9
+ {
10
+ "date": "2026-11-07",
11
+ "ledger": "docs/benchmarks/routes/trials-backup.jsonl",
12
+ "scope": "one real sample; does not establish platform-wide completeness"
13
+ }
14
+ ],
15
+ "id": "xyz-dl",
16
+ "kind": "python_script",
17
+ "version": "sha256:d5676a016f220f4a6a7c2944ccfb77dd92cf33863500f5ac18b986f34c97aa02",
18
+ "license": "AGPL-3.0",
19
+ "homepage": "",
20
+ "launcher": {
21
+ "script": "main.py"
22
+ },
23
+ "capabilities": [
24
+ {
25
+ "status_policy": "verified_if_valid_else_failed",
26
+ "requires_login": false,
27
+ "cost_class": "local_compute",
28
+ "id": "xyz-dl.xiaoyuzhou.media-asr",
29
+ "sources": [
30
+ "xiaoyuzhou"
31
+ ],
32
+ "capability": "media",
33
+ "url_hosts": [
34
+ "www.xiaoyuzhoufm.com",
35
+ "xiaoyuzhoufm.com"
36
+ ],
37
+ "url_path_pattern": "^/episode/[a-f0-9]{24}/?$",
38
+ "argv": [
39
+ "{url}",
40
+ "--output",
41
+ "{workdir}",
42
+ "--no-metadata"
43
+ ],
44
+ "reader": {
45
+ "type": "media_dir"
46
+ },
47
+ "then": "asr.auto",
48
+ "gates": [
49
+ "network",
50
+ "media_download",
51
+ "asr"
52
+ ],
53
+ "source_level": "media_asr",
54
+ "timeout_s": 300,
55
+ "validation": {
56
+ "min_chars": 1
57
+ }
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "schema": "openmd.tool-card/v1",
3
+ "installation": {
4
+ "mode": "isolated_existing",
5
+ "sha256": "5ac46c79fcca8f1ad80d9fc39df1ab8720d1fa8ba6f561f93cb03a7d50bb4c17",
6
+ "verification": "SHA256 of the installed entry file; dependency tree is isolated, not attested"
7
+ },
8
+ "evidence": [
9
+ {
10
+ "date": "2026-11-07",
11
+ "ledger": "docs/benchmarks/routes/trials-backup.jsonl",
12
+ "scope": "one real sample; does not establish platform-wide completeness"
13
+ }
14
+ ],
15
+ "id": "yutto",
16
+ "kind": "python_entry",
17
+ "version": "2.3.1",
18
+ "license": "GPL-3.0",
19
+ "homepage": "https://github.com/yutto-dev/yutto",
20
+ "launcher": {
21
+ "entry": "yutto.__main__:main",
22
+ "which": [
23
+ "yutto"
24
+ ]
25
+ },
26
+ "capabilities": [
27
+ {
28
+ "status_policy": "verified_if_valid_else_failed",
29
+ "requires_login": false,
30
+ "cost_class": "local_compute",
31
+ "id": "yutto.bilibili.media-asr",
32
+ "sources": [
33
+ "bilibili"
34
+ ],
35
+ "capability": "media",
36
+ "url_hosts": [
37
+ "www.bilibili.com",
38
+ "bilibili.com"
39
+ ],
40
+ "argv": [
41
+ "{url}",
42
+ "--audio-only",
43
+ "--no-danmaku",
44
+ "--no-subtitle",
45
+ "--no-cover",
46
+ "--auth-file",
47
+ "{workdir}/no-auth.toml",
48
+ "-d",
49
+ "{workdir}"
50
+ ],
51
+ "reader": {
52
+ "type": "media_dir"
53
+ },
54
+ "then": "asr.auto",
55
+ "gates": [
56
+ "network",
57
+ "media_download",
58
+ "asr"
59
+ ],
60
+ "source_level": "media_asr",
61
+ "timeout_s": 300,
62
+ "validation": {
63
+ "min_chars": 1
64
+ },
65
+ "url_path_pattern": "^/video/BV[A-Za-z0-9]+/?$"
66
+ }
67
+ ]
68
+ }
@@ -0,0 +1,71 @@
1
+ """Execute isolated Python entry points with credential and TLS boundaries."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import importlib
7
+ import runpy
8
+ import sys
9
+ from pathlib import Path
10
+
11
+
12
+ def _require_tls_verification() -> None:
13
+ try:
14
+ import requests
15
+ except ImportError:
16
+ return
17
+ original = requests.sessions.Session.send
18
+
19
+ def verified_send(self, request, **kwargs):
20
+ # Some downloaders set Session.verify=False internally. Never inherit it.
21
+ kwargs["verify"] = True
22
+ return original(self, request, **kwargs)
23
+
24
+ requests.sessions.Session.send = verified_send
25
+
26
+
27
+ def _require_yutto_tls_verification() -> None:
28
+ """Yutto's native session is independent of requests and defaults to insecure."""
29
+ fetcher = importlib.import_module("yutto.utils.fetcher")
30
+ original = fetcher.create_client
31
+
32
+ def verified_client(*args, **kwargs):
33
+ kwargs["verify"] = True
34
+ return original(*args, **kwargs)
35
+
36
+ fetcher.create_client = verified_client
37
+ # Cover aliases imported before shim initialization as well as future imports.
38
+ for name, module in tuple(sys.modules.items()):
39
+ if name.startswith("yutto.") and getattr(module, "create_client", None) is original:
40
+ module.create_client = verified_client
41
+
42
+
43
+ def main(argv: list[str] | None = None) -> int:
44
+ parser = argparse.ArgumentParser()
45
+ parser.add_argument("--path", action="append", default=[])
46
+ parser.add_argument("--entry")
47
+ parser.add_argument("--script")
48
+ parser.add_argument("arguments", nargs=argparse.REMAINDER)
49
+ args = parser.parse_args(argv)
50
+ for path in reversed(args.path):
51
+ sys.path.insert(0, str(Path(path).resolve()))
52
+ if bool(args.entry) == bool(args.script):
53
+ raise ValueError("entry_shim_requires_one_entry")
54
+ arguments = args.arguments[1:] if args.arguments[:1] == ["--"] else args.arguments
55
+ _require_tls_verification()
56
+ if args.entry and args.entry.split(":", 1)[0].split(".", 1)[0] == "yutto":
57
+ _require_yutto_tls_verification()
58
+ if args.entry:
59
+ module, name = args.entry.split(":", 1)
60
+ sys.argv = [module, *arguments]
61
+ result = getattr(importlib.import_module(module), name)()
62
+ return result if isinstance(result, int) else 0
63
+ script = Path(args.script).resolve()
64
+ sys.path.insert(0, str(script.parent))
65
+ sys.argv = [str(script), *arguments]
66
+ runpy.run_path(str(script), run_name="__main__")
67
+ return 0
68
+
69
+
70
+ if __name__ == "__main__":
71
+ raise SystemExit(main())