bohr-agent-sdk 0.1.20__py3-none-any.whl → 0.1.22__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: bohr-agent-sdk
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: SDK for scientific agents
5
5
  Home-page: https://github.com/dptech-corp/bohr-agent-sdk/
6
6
  Author: DP Technology
@@ -20,21 +20,21 @@ dp/agent/device/device/__init__.py,sha256=w7_1S16S1vWUq0RGl0GFgjq2vFkc5oNvy8cQTn
20
20
  dp/agent/device/device/device.py,sha256=9ZRIJth-4qMO-i-u_b_cO3d6a4eTbTQjPaxFsV_zEkc,9643
21
21
  dp/agent/device/device/types.py,sha256=JuxB-hjf1CjjvfBxCLwRAXVFlYS-nPEdiJpBWLFVCzo,1924
22
22
  dp/agent/server/__init__.py,sha256=rckaYd8pbYyB4ENEhgjXKeGMXjdnrgcJpdM1gu5u1Wc,508
23
- dp/agent/server/calculation_mcp_server.py,sha256=omPcrjVT3k8ek3BbB5Dc3TRjdSC_0IEqjCrK2Ka0YqE,10888
23
+ dp/agent/server/calculation_mcp_server.py,sha256=oumU2xtqrrgp8BKiuF9YsqMNevXba2JACyYsvNy4nQo,11008
24
24
  dp/agent/server/preprocessor.py,sha256=XUWu7QOwo_sIDMYS2b1OTrM33EXEVH_73vk-ju1Ok8A,1264
25
25
  dp/agent/server/utils.py,sha256=8jgYZEW4XBp86AF2Km6QkwHltBmrnS-soTpHov7ZEJw,4501
26
26
  dp/agent/server/executor/__init__.py,sha256=s95M5qKQk39Yi9qaVJZhk_nfj54quSf7EDghR3OCFUA,248
27
27
  dp/agent/server/executor/base_executor.py,sha256=EFJBsYVYAvuRbiLAbLOwLTw3h7ScjN025xnSP4uJHrQ,2052
28
28
  dp/agent/server/executor/dispatcher_executor.py,sha256=urpzmKH_tBOgblBdJEa3y8eEhXqUDrdcdWCnUdJpfZk,9420
29
- dp/agent/server/executor/local_executor.py,sha256=alNpEPicZQOQMtXc1vqGSo4El_9agXAJ5ldqi-OJGL4,3887
29
+ dp/agent/server/executor/local_executor.py,sha256=9JEtZTEbKsmHAY5nsdLZ36gH5M_rSG6En0W9IrCUwm0,5803
30
30
  dp/agent/server/storage/__init__.py,sha256=Sgsyp5hb0_hhIGugAPfQFzBHt_854rS_MuMuE3sn8Gs,389
31
31
  dp/agent/server/storage/base_storage.py,sha256=728-oNG6N8isV95gZVnyi4vTznJPJhSjxw9Gl5Y_y5o,2356
32
32
  dp/agent/server/storage/bohrium_storage.py,sha256=EsKX4dWWvZTn2TEhZv4zsvihfDK0mmPFecrln-Ytk40,10488
33
33
  dp/agent/server/storage/http_storage.py,sha256=KiySq7g9-iJr12XQCKKyJLn8wJoDnSRpQAR5_qPJ1ZU,1471
34
34
  dp/agent/server/storage/local_storage.py,sha256=t1wfjByjXew9ws3PuUxWxmZQ0-Wt1a6t4wmj3fW62GI,1352
35
35
  dp/agent/server/storage/oss_storage.py,sha256=pgjmi7Gir3Y5wkMDCvU4fvSls15fXT7Ax-h9MYHFPK0,3359
36
- bohr_agent_sdk-0.1.20.dist-info/METADATA,sha256=ZEoxrydj541JG9txn0Wr0iARoxZ_w2KA6E0aJFFGlAY,6329
37
- bohr_agent_sdk-0.1.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- bohr_agent_sdk-0.1.20.dist-info/entry_points.txt,sha256=5n5kneF5IbDQtoQ2WfF-QuBjDtsimJte9Rv9baSGgc0,86
39
- bohr_agent_sdk-0.1.20.dist-info/top_level.txt,sha256=87xLUDhu_1nQHoGLwlhJ6XlO7OsjILh6i1nX6ljFzDo,3
40
- bohr_agent_sdk-0.1.20.dist-info/RECORD,,
36
+ bohr_agent_sdk-0.1.22.dist-info/METADATA,sha256=IyYt8bph_mRJ06nyUlf1BQnAm1HBIR2jssavB4nTrwU,6329
37
+ bohr_agent_sdk-0.1.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ bohr_agent_sdk-0.1.22.dist-info/entry_points.txt,sha256=5n5kneF5IbDQtoQ2WfF-QuBjDtsimJte9Rv9baSGgc0,86
39
+ bohr_agent_sdk-0.1.22.dist-info/top_level.txt,sha256=87xLUDhu_1nQHoGLwlhJ6XlO7OsjILh6i1nX6ljFzDo,3
40
+ bohr_agent_sdk-0.1.22.dist-info/RECORD,,
@@ -29,7 +29,7 @@ def parse_uri(uri):
29
29
 
30
30
 
31
31
  def init_storage(storage_config: Optional[dict] = None):
32
- if storage_config is None:
32
+ if not storage_config:
33
33
  storage_config = {"type": "local"}
34
34
  storage_config = deepcopy(storage_config)
35
35
  storage_type = storage_config.pop("type")
@@ -38,7 +38,7 @@ def init_storage(storage_config: Optional[dict] = None):
38
38
 
39
39
 
40
40
  def init_executor(executor_config: Optional[dict] = None):
41
- if executor_config is None:
41
+ if not executor_config:
42
42
  executor_config = {"type": "local"}
43
43
  executor_config = deepcopy(executor_config)
44
44
  executor_type = executor_config.pop("type")
@@ -227,7 +227,11 @@ class CalculationMCPServer:
227
227
  exec_id = res["job_id"]
228
228
  job_id = "%s/%s" % (trace_id, exec_id)
229
229
  logger.info("Job submitted (ID: %s)" % job_id)
230
- return convert_to_content({"job_id": job_id}, job_info={
230
+ result = {
231
+ "job_id": job_id,
232
+ "extra_info": res.get("extra_info"),
233
+ }
234
+ return convert_to_content(result, job_info={
231
235
  "trace_id": trace_id,
232
236
  "executor_type": executor_type,
233
237
  "job_id": job_id,
@@ -1,19 +1,43 @@
1
1
  import asyncio
2
2
  import importlib
3
3
  import inspect
4
+ import io
4
5
  import jsonpickle
5
6
  import os
6
7
  import psutil
8
+ import re
7
9
  import sys
10
+ import time
8
11
  import uuid
9
12
  from multiprocessing import Process
10
13
  from typing import Dict, Optional
11
14
 
12
15
  from .base_executor import BaseExecutor
16
+ from ..utils import get_logger
13
17
 
18
+ DFLOW_ID_PATTERN = r"Workflow has been submitted \(ID: ([^,]*), UID: ([^)]*)\)"
19
+ DFLOW_LINK_PATTERN = r"Workflow link: (.*)"
20
+ logger = get_logger(__name__)
14
21
 
15
- def wrapped_fn(fn, kwargs):
22
+
23
+ class Tee(io.TextIOBase):
24
+ def __init__(self, file, stdout):
25
+ self.file = file
26
+ self.stdout = stdout
27
+
28
+ def write(self, text):
29
+ self.stdout.write(text)
30
+ self.file.write(text)
31
+ self.file.flush()
32
+ return len(text)
33
+
34
+
35
+ def wrapped_fn(fn, kwargs, redirect_file=None):
16
36
  pid = os.getpid()
37
+ if redirect_file:
38
+ stdout = sys.stdout
39
+ flog = open(redirect_file, "w")
40
+ sys.stdout = Tee(flog, stdout)
17
41
  try:
18
42
  if inspect.iscoroutinefunction(fn):
19
43
  result = asyncio.run(fn(**kwargs))
@@ -23,6 +47,10 @@ def wrapped_fn(fn, kwargs):
23
47
  with open("err", "w") as f:
24
48
  f.write(str(e))
25
49
  raise e
50
+ finally:
51
+ if redirect_file:
52
+ sys.stdout = stdout
53
+ flog.close()
26
54
  with open("%s.txt" % pid, "w") as f:
27
55
  f.write(jsonpickle.dumps(result))
28
56
 
@@ -47,13 +75,16 @@ def reload_dflow_config():
47
75
 
48
76
 
49
77
  class LocalExecutor(BaseExecutor):
50
- def __init__(self, env: Optional[Dict[str, str]] = None):
78
+ def __init__(self, env: Optional[Dict[str, str]] = None,
79
+ dflow: bool = False):
51
80
  """
52
81
  Execute the tool locally
53
82
  Args:
54
83
  env: The environmental variables at run time
84
+ dflow: Wait until workflow submitted in submit method
55
85
  """
56
86
  self.env = env or {}
87
+ self.dflow = dflow
57
88
 
58
89
  def set_env(self):
59
90
  old_env = {}
@@ -73,10 +104,34 @@ class LocalExecutor(BaseExecutor):
73
104
  def submit(self, fn, kwargs):
74
105
  os.environ["DP_AGENT_RUNNING_MODE"] = "1"
75
106
  old_env = self.set_env()
76
- p = Process(target=wrapped_fn, kwargs={"fn": fn, "kwargs": kwargs})
107
+ params = {"fn": fn, "kwargs": kwargs}
108
+ if self.dflow:
109
+ params["redirect_file"] = "log.txt"
110
+ p = Process(target=wrapped_fn, kwargs=params)
77
111
  p.start()
112
+ extra_info = {}
113
+ if self.dflow:
114
+ while True:
115
+ alive = p.is_alive()
116
+ if os.path.isfile("log.txt"):
117
+ with open("log.txt", "r") as f:
118
+ log = f.read()
119
+ match_id = re.search(DFLOW_ID_PATTERN, log)
120
+ match_link = re.search(DFLOW_LINK_PATTERN, log)
121
+ if match_id and match_link:
122
+ wf_id = match_id.group(1)
123
+ wf_uid = match_id.group(2)
124
+ wf_link = match_link.group(1)
125
+ extra_info["workflow_id"] = wf_id
126
+ extra_info["workflow_uid"] = wf_uid
127
+ extra_info["workflow_link"] = wf_link
128
+ break
129
+ if not alive:
130
+ break
131
+ logger.info("Waiting workflow to be submitted")
132
+ time.sleep(1)
78
133
  self.recover_env(old_env)
79
- return {"job_id": str(p.pid)}
134
+ return {"job_id": str(p.pid), "extra_info": extra_info}
80
135
 
81
136
  def query_status(self, job_id):
82
137
  try: