realtimex-deeptutor 0.5.0.post6__py3-none-any.whl → 0.5.0.post7__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: realtimex-deeptutor
3
- Version: 0.5.0.post6
3
+ Version: 0.5.0.post7
4
4
  Summary: RealTimeX DeepTutor - Intelligent learning companion with multi-agent collaboration and LightRAG
5
5
  License: Apache-2.0
6
6
  Requires-Python: >=3.10
@@ -1,5 +1,5 @@
1
1
  realtimex_deeptutor/__init__.py,sha256=sSfuCLjJa6BnayszcU4azNl_sr1OzuKgLP10BAtdoh8,1567
2
- realtimex_deeptutor-0.5.0.post6.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
2
+ realtimex_deeptutor-0.5.0.post7.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
3
3
  scripts/__init__.py,sha256=mxMsCbci-Qon3qWU1JIi93-tYlHAy0NIUbDRmAPVcg0,54
4
4
  scripts/audit_prompts.py,sha256=Ltuk7tvsjpKhiobVbYq1volgVFKiVLgSTaE_Is4MGaM,5651
5
5
  scripts/check_install.py,sha256=GbApEcDLJ6r0QmYrCVHAFCOK4wolpSLwL3eBRmmD3og,13929
@@ -7,7 +7,7 @@ scripts/generate_roster.py,sha256=COsJ12bvZ5W9TI-wAvKpknKBgHr9uQTvJ_JCz2gVMVo,12
7
7
  scripts/install_all.py,sha256=u-A3eLhk1ua_KCjz8WZMkrVNJN6QdYs7NhGOcsm-Mks,23875
8
8
  scripts/migrate_kb.py,sha256=uyJgplkJag35rT2RrwSiT37__gpB4TiA0xh5uVcWIa4,19667
9
9
  scripts/start.py,sha256=EYbyjryor0DN_WcxQMSkKWCboM9UjMkv61fWhLyv63I,30300
10
- scripts/start_web.py,sha256=aZ5nqH-h2F6I_tAsY-_uy56jIS5ZJt8Fsjw0OHjEYGc,29755
10
+ scripts/start_web.py,sha256=P7YCnJgjva58hjs5F4ogtrlVS1wDLFqWoUfoHZ9vREE,32197
11
11
  scripts/sync_prompts_from_en.py,sha256=TkBSFilYSwnwo0a3cgRnJ84i02zByAIW12N3ePzBwE8,4677
12
12
  src/__init__.py,sha256=UNw3C20mbskiQF3rK3HhjglrG8snhfuiVthc5UsoHX0,1046
13
13
  src/agents/__init__.py,sha256=IPhP4RZnCH2kcUDBkdKHO_ciVdyWnuHUCG2flG5Ydcw,885
@@ -289,8 +289,8 @@ src/utils/error_utils.py,sha256=ME_9q-DlmxFl-Xvv3ETPZE_iP705x6MXiuAREgWYsjM,2262
289
289
  src/utils/json_parser.py,sha256=M_KfrsrNvQPSiFvpKHQV79Aj85_MEcLVc6hnKzvTV58,3243
290
290
  src/utils/realtimex.py,sha256=vs7fAEnJJ4zpAyyBn-7vUmGWiiQvpTWQCRgax1MLTDw,9769
291
291
  src/utils/network/circuit_breaker.py,sha256=BtjogK5R3tG8fuJniS5-PJKZMtwD5P2SkP2JFiQ9sRA,2722
292
- realtimex_deeptutor-0.5.0.post6.dist-info/METADATA,sha256=ZHgtwKQVopSxjI2xUxf27e-HiHVkrPtObk6b35e2zlk,58304
293
- realtimex_deeptutor-0.5.0.post6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
294
- realtimex_deeptutor-0.5.0.post6.dist-info/entry_points.txt,sha256=slNAzwRLUpqiMtDRZBQIkXbU2vGMHL_om6-o19gYdh8,134
295
- realtimex_deeptutor-0.5.0.post6.dist-info/top_level.txt,sha256=zUAd6V7jDYhdL7bvg2S38YCM-gVhvd36WqkjxrT-02I,32
296
- realtimex_deeptutor-0.5.0.post6.dist-info/RECORD,,
292
+ realtimex_deeptutor-0.5.0.post7.dist-info/METADATA,sha256=-pKSs_xYVcVXMMkGETtdGsa7Yabv1jvUCSk_JH1GTMU,58304
293
+ realtimex_deeptutor-0.5.0.post7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
294
+ realtimex_deeptutor-0.5.0.post7.dist-info/entry_points.txt,sha256=slNAzwRLUpqiMtDRZBQIkXbU2vGMHL_om6-o19gYdh8,134
295
+ realtimex_deeptutor-0.5.0.post7.dist-info/top_level.txt,sha256=zUAd6V7jDYhdL7bvg2S38YCM-gVhvd36WqkjxrT-02I,32
296
+ realtimex_deeptutor-0.5.0.post7.dist-info/RECORD,,
scripts/start_web.py CHANGED
@@ -20,6 +20,80 @@ if hasattr(sys.stdout, "reconfigure"):
20
20
  sys.stdout.reconfigure(line_buffering=True)
21
21
 
22
22
 
23
+ class ExecutableResolver:
24
+ """
25
+ Resolves bundled executables (uvx, uv, npx) to their actual paths.
26
+ Ported from ExecutableResolver.js
27
+ """
28
+
29
+ def __init__(self):
30
+ self._resources_root = None
31
+
32
+ def get_resources_root(self) -> Path | None:
33
+ """
34
+ Get the resources root directory (~/.realtimex.ai)
35
+ Returns path to resources root or None if not found
36
+ """
37
+ if self._resources_root:
38
+ return self._resources_root
39
+
40
+ try:
41
+ home = Path.home()
42
+ self._resources_root = home / ".realtimex.ai"
43
+ return self._resources_root
44
+ except Exception as e:
45
+ print_flush(f"⚠️ [ExecutableResolver] Failed to resolve resources directory: {e}")
46
+ return None
47
+
48
+ def resolve_from_candidates(
49
+ self, env_var: str | None, candidates: list[Path | str]
50
+ ) -> str | None:
51
+ """
52
+ Find a valid executable from a list of candidate paths
53
+ """
54
+ search_paths = []
55
+ if env_var:
56
+ search_paths.append(Path(env_var))
57
+
58
+ search_paths.extend([Path(c) for c in candidates])
59
+
60
+ for candidate in search_paths:
61
+ if not candidate:
62
+ continue
63
+ try:
64
+ if candidate.exists() and candidate.is_file():
65
+ return str(candidate)
66
+ except Exception:
67
+ pass
68
+ return None
69
+
70
+ def resolve_npx(self) -> str | None:
71
+ """
72
+ Resolve npx to bundled executable
73
+ """
74
+ resources_dir = self.get_resources_root()
75
+ if not resources_dir:
76
+ return None
77
+
78
+ node_version = os.environ.get("REALTIMEX_NPX_NODE_VERSION", "v22.16.0")
79
+ home = Path.home()
80
+
81
+ candidates = [
82
+ # User's NVM installation (most common case)
83
+ home / ".nvm" / "versions" / "node" / node_version / "bin" / "npx",
84
+ # NVM-installed node in resources dir (bundled)
85
+ resources_dir / ".nvm" / "versions" / "node" / node_version / "bin" / "npx",
86
+ # Windows NVM
87
+ Path("C:/nvm") / node_version / "npx.cmd",
88
+ # Bundled in Resources
89
+ resources_dir / "Resources" / "envs" / "Scripts" / "npx.cmd",
90
+ ]
91
+
92
+ return self.resolve_from_candidates(
93
+ env_var=os.environ.get("REALTIMEX_NPX_PATH"), candidates=candidates
94
+ )
95
+
96
+
23
97
  def print_flush(*args, **kwargs):
24
98
  """Print with flush=True by default"""
25
99
  kwargs.setdefault("flush", True)
@@ -625,7 +699,9 @@ def _start_frontend_npx(frontend_port, backend_port):
625
699
  """Start frontend using published package via npx (production mode)"""
626
700
 
627
701
  # Check if npx is available
628
- npx_path = shutil.which("npx")
702
+ resolver = ExecutableResolver()
703
+ npx_path = resolver.resolve_npx() or shutil.which("npx")
704
+
629
705
  if not npx_path:
630
706
  print_flush("❌ Error: 'npx' command not found!")
631
707
  print_flush(" Please install Node.js and npm first.")
@@ -653,7 +729,7 @@ def _start_frontend_npx(frontend_port, backend_port):
653
729
  if os.name == "nt":
654
730
  env["PYTHONLEGACYWINDOWSSTDIO"] = "0"
655
731
 
656
- npx_cmd = shutil.which("npx") or "npx"
732
+ npx_cmd = npx_path or "npx"
657
733
 
658
734
  # Process group configuration
659
735
  popen_kwargs = {