We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Clarifications] Testing in a local environment
Dear All,
I've started working with ParlAI and Mephisto some days ago in order to define an interface for data collection. In particular, I've extend the parlai-chat-demo to meet my task-specific requirements.

I was wondering how to test the interface with users in a local network or by remotely connecting to my server. Thus, I've looked up for existing threads about the same topic: [#409](https://github.com/facebookresearch/Mephisto/issues/409) and [#303 ](https://github.com/facebookresearch/Mephisto/issues/303) as the main examples.

Since I'm no expert in this kind of stuff, I'm not completely sure what are the current networking setups that I can consider at the moment.  Therefore, I kindly ask you for a gentle summary/tutorial concerning the particular objective of testing locally/remotely with own server.

To summarize, I would like to know if there's an answer to these main questions:
Q: Is it possible to easily test the interface with other people in a local environment (same network)?
Q: How to do so?

Down below I report a list of additional questions with related comments:

1. My server has a static IP, can I test it locally on the same network? Connecting from the same network to the server brings up a 'disconnected' status in the interface.

2. Can I use the mentioned nginx reverse proxy to access to my interface? What are the steps? I've tried setting it up and then access to the server. I'm able to access to the interface but the connection status is still 'disconnected'.

3. Do I need a specific mephisto configuration for local testing? Up until now I've worked with `"mephisto/architect"="local"` and `"mephisto/provider"="mock"`.

Thanks in advance and apologies if this issue sounds just as a duplicate of some past issues.
Unfortunately, I'm not sure I've done everything right until now.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `examples/simple_static_task/static_run_with_onboarding.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 # Copyright (c) Facebook, Inc. and its affiliates.
4 # This source code is licensed under the MIT license found in the
5 # LICENSE file in the root directory of this source tree.
6 
7 import os
8 from mephisto.operations.operator import Operator
9 from mephisto.operations.utils import get_root_dir
10 from mephisto.tools.scripts import load_db_and_process_config
11 from mephisto.abstractions.blueprints.static_html_task.static_html_blueprint import (
12     BLUEPRINT_TYPE,
13 )
14 from mephisto.abstractions.blueprints.abstract.static_task.static_blueprint import (
15     SharedStaticTaskState,
16 )
17 
18 import hydra
19 from omegaconf import DictConfig
20 from dataclasses import dataclass, field
21 from typing import List, Any
22 
23 TASK_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
24 CORRECT_ANSWER = "apple"
25 
26 defaults = [
27     {"mephisto/blueprint": BLUEPRINT_TYPE},
28     {"mephisto/architect": "local"},
29     {"mephisto/provider": "mock"},
30     {"conf": "onboarding_example"},
31 ]
32 
33 from mephisto.operations.hydra_config import RunScriptConfig, register_script_config
34 
35 
36 @dataclass
37 class TestScriptConfig(RunScriptConfig):
38     defaults: List[Any] = field(default_factory=lambda: defaults)
39     task_dir: str = TASK_DIRECTORY
40     correct_answer: str = CORRECT_ANSWER
41 
42 
43 register_script_config(name="scriptconfig", module=TestScriptConfig)
44 
45 
46 @hydra.main(config_path="hydra_configs", config_name="scriptconfig")
47 def main(cfg: DictConfig) -> None:
48     correct_config_answer = cfg.correct_answer
49 
50     def onboarding_is_valid(onboarding_data):
51         inputs = onboarding_data["inputs"]
52         outputs = onboarding_data["outputs"]
53         return outputs.get("answer") == correct_config_answer
54 
55     shared_state = SharedStaticTaskState(
56         onboarding_data={"correct_answer": correct_config_answer},
57         validate_onboarding=onboarding_is_valid,
58     )
59 
60     db, cfg = load_db_and_process_config(cfg)
61     operator = Operator(db)
62 
63     operator.validate_and_run_config(cfg.mephisto, shared_state)
64     operator.wait_for_runs_then_shutdown(skip_input=True, log_rate=30)
65 
66 
67 if __name__ == "__main__":
68     main()
69
```

Path: `mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 # Copyright (c) Facebook, Inc. and its affiliates.
4 # This source code is licensed under the MIT license found in the
5 # LICENSE file in the root directory of this source tree.
6 
7 from typing import List, Dict, Optional, Any, TYPE_CHECKING
8 from mephisto.abstractions.blueprint import AgentState
9 import os
10 import json
11 import time
12 import weakref
13 
14 if TYPE_CHECKING:
15     from mephisto.data_model.agent import Agent
16     from mephisto.data_model.packet import Packet
17 
18 from mephisto.operations.logger_core import get_logger
19 
20 logger = get_logger(name=__name__)
21 
22 DATA_FILE = "agent_data.json"
23 
24 
25 class StaticAgentState(AgentState):
26     """
27     Agent state for static tasks.
28     """
29 
30     def _get_empty_state(self) -> Dict[str, Optional[Dict[str, Any]]]:
31         return {
32             "inputs": None,
33             "outputs": None,
34             "times": {"task_start": 0, "task_end": 0},
35         }
36 
37     def __init__(self, agent: "Agent"):
38         """
39         Static agent states should store
40         input dict -> output dict pairs to disc
41         """
42         self.agent = weakref.proxy(agent)
43         self.state: Dict[str, Optional[Dict[str, Any]]] = self._get_empty_state()
44         self.load_data()
45 
46     def set_init_state(self, data: Any) -> bool:
47         """Set the initial state for this agent"""
48         if self.get_init_state() is not None:
49             # Initial state is already set
50             return False
51         else:
52             self.state["inputs"] = data
53             times_dict = self.state["times"]
54             assert isinstance(times_dict, dict)
55             times_dict["task_start"] = time.time()
56             self.save_data()
57             return True
58 
59     def get_init_state(self) -> Optional[Dict[str, Any]]:
60         """
61         Return the initial state for this agent,
62         None if no such state exists
63         """
64         if self.state["inputs"] is None:
65             return None
66         return self.state["inputs"].copy()
67 
68     def load_data(self) -> None:
69         """Load data for this agent from disk"""
70         data_dir = self.agent.get_data_dir()
71         data_path = os.path.join(data_dir, DATA_FILE)
72         if os.path.exists(data_path):
73             with open(data_path, "r") as data_file:
74                 self.state = json.load(data_file)
75         else:
76             self.state = self._get_empty_state()
77 
78     def get_data(self) -> Dict[str, Any]:
79         """Return dict of this agent's state"""
80         return self.state.copy()
81 
82     def save_data(self) -> None:
83         """Save static agent data to disk"""
84         data_dir = self.agent.get_data_dir()
85         os.makedirs(data_dir, exist_ok=True)
86         out_filename = os.path.join(data_dir, DATA_FILE)
87         with open(out_filename, "w+") as data_file:
88             json.dump(self.state, data_file)
89         logger.info(f"SAVED_DATA_TO_DISC at {out_filename}")
90 
91     def update_data(self, live_data: Dict[str, Any]) -> None:
92         """
93         Process the incoming data packet, and handle
94         updating the state
95         """
96         raise Exception(
97             "Static tasks should only have final act, but updated live data"
98         )
99 
100     def update_submit(self, submission_data: Dict[str, Any]) -> None:
101         """Move the submitted output to the local dict"""
102         outputs: Dict[str, Any]
103 
104         if submission_data.get("onboarding_data") is not None:
105             outputs = submission_data["onboarding_data"]
106         else:
107             outputs = submission_data["task_data"]
108         times_dict = self.state["times"]
109         assert isinstance(times_dict, dict)
110         times_dict["task_end"] = time.time()
111         if submission_data.get("files") != None:
112             logger.info(f"Got files: {str(submission_data['files'])[:500]}")
113             outputs["files"] = [f["filename"] for f in submission_data["files"]]
114         self.state["outputs"] = outputs
115         self.save_data()
116 
117     def get_task_start(self) -> Optional[float]:
118         """
119         Extract out and return the start time recorded for this task.
120         """
121         stored_times = self.state["times"]
122         assert stored_times is not None
123         return stored_times["task_start"]
124 
125     def get_task_end(self) -> Optional[float]:
126         """
127         Extract out and return the end time recorded for this task.
128         """
129         stored_times = self.state["times"]
130         assert stored_times is not None
131         return stored_times["task_end"]
132
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/examples/simple_static_task/static_run_with_onboarding.py b/examples/simple_static_task/static_run_with_onboarding.py
--- a/examples/simple_static_task/static_run_with_onboarding.py
+++ b/examples/simple_static_task/static_run_with_onboarding.py
@@ -23,12 +23,7 @@
 TASK_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
 CORRECT_ANSWER = "apple"
 
-defaults = [
-    {"mephisto/blueprint": BLUEPRINT_TYPE},
-    {"mephisto/architect": "local"},
-    {"mephisto/provider": "mock"},
-    {"conf": "onboarding_example"},
-]
+defaults = ["_self_", {"conf": "onboarding_example"}]
 
 from mephisto.operations.hydra_config import RunScriptConfig, register_script_config
 
diff --git a/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py b/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py
--- a/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py
+++ b/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py
@@ -100,18 +100,13 @@
     def update_submit(self, submission_data: Dict[str, Any]) -> None:
         """Move the submitted output to the local dict"""
         outputs: Dict[str, Any]
-
-        if submission_data.get("onboarding_data") is not None:
-            outputs = submission_data["onboarding_data"]
-        else:
-            outputs = submission_data["task_data"]
+        output_files = submission_data.get("files")
+        if output_files is not None:
+            submission_data["files"] = [f["filename"] for f in submission_data["files"]]
+        self.state["outputs"] = submission_data
         times_dict = self.state["times"]
         assert isinstance(times_dict, dict)
         times_dict["task_end"] = time.time()
-        if submission_data.get("files") != None:
-            logger.info(f"Got files: {str(submission_data['files'])[:500]}")
-            outputs["files"] = [f["filename"] for f in submission_data["files"]]
-        self.state["outputs"] = outputs
         self.save_data()
 
     def get_task_start(self) -> Optional[float]:

{"golden_diff": "diff --git a/examples/simple_static_task/static_run_with_onboarding.py b/examples/simple_static_task/static_run_with_onboarding.py\n--- a/examples/simple_static_task/static_run_with_onboarding.py\n+++ b/examples/simple_static_task/static_run_with_onboarding.py\n@@ -23,12 +23,7 @@\n TASK_DIRECTORY = os.path.dirname(os.path.abspath(__file__))\n CORRECT_ANSWER = \"apple\"\n \n-defaults = [\n-    {\"mephisto/blueprint\": BLUEPRINT_TYPE},\n-    {\"mephisto/architect\": \"local\"},\n-    {\"mephisto/provider\": \"mock\"},\n-    {\"conf\": \"onboarding_example\"},\n-]\n+defaults = [\"_self_\", {\"conf\": \"onboarding_example\"}]\n \n from mephisto.operations.hydra_config import RunScriptConfig, register_script_config\n \ndiff --git a/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py b/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py\n--- a/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py\n+++ b/mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py\n@@ -100,18 +100,13 @@\n     def update_submit(self, submission_data: Dict[str, Any]) -> None:\n         \"\"\"Move the submitted output to the local dict\"\"\"\n         outputs: Dict[str, Any]\n-\n-        if submission_data.get(\"onboarding_data\") is not None:\n-            outputs = submission_data[\"onboarding_data\"]\n-        else:\n-            outputs = submission_data[\"task_data\"]\n+        output_files = submission_data.get(\"files\")\n+        if output_files is not None:\n+            submission_data[\"files\"] = [f[\"filename\"] for f in submission_data[\"files\"]]\n+        self.state[\"outputs\"] = submission_data\n         times_dict = self.state[\"times\"]\n         assert isinstance(times_dict, dict)\n         times_dict[\"task_end\"] = time.time()\n-        if submission_data.get(\"files\") != None:\n-            logger.info(f\"Got files: {str(submission_data['files'])[:500]}\")\n-            outputs[\"files\"] = [f[\"filename\"] for f in submission_data[\"files\"]]\n-        self.state[\"outputs\"] = outputs\n         self.save_data()\n \n     def get_task_start(self) -> Optional[float]:\n", "issue": "[Clarifications] Testing in a local environment\nDear All,\r\nI've started working with ParlAI and Mephisto some days ago in order to define an interface for data collection. In particular, I've extend the parlai-chat-demo to meet my task-specific requirements.\r\n\r\nI was wondering how to test the interface with users in a local network or by remotely connecting to my server. Thus, I've looked up for existing threads about the same topic: [#409](https://github.com/facebookresearch/Mephisto/issues/409) and [#303 ](https://github.com/facebookresearch/Mephisto/issues/303) as the main examples.\r\n\r\nSince I'm no expert in this kind of stuff, I'm not completely sure what are the current networking setups that I can consider at the moment.  Therefore, I kindly ask you for a gentle summary/tutorial concerning the particular objective of testing locally/remotely with own server.\r\n\r\nTo summarize, I would like to know if there's an answer to these main questions:\r\nQ: Is it possible to easily test the interface with other people in a local environment (same network)?\r\nQ: How to do so?\r\n\r\nDown below I report a list of additional questions with related comments:\r\n\r\n1. My server has a static IP, can I test it locally on the same network? Connecting from the same network to the server brings up a 'disconnected' status in the interface.\r\n\r\n2. Can I use the mentioned nginx reverse proxy to access to my interface? What are the steps? I've tried setting it up and then access to the server. I'm able to access to the interface but the connection status is still 'disconnected'.\r\n\r\n3. Do I need a specific mephisto configuration for local testing? Up until now I've worked with `\"mephisto/architect\"=\"local\"` and `\"mephisto/provider\"=\"mock\"`.\r\n\r\nThanks in advance and apologies if this issue sounds just as a duplicate of some past issues.\r\nUnfortunately, I'm not sure I've done everything right until now.\r\n\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nfrom mephisto.operations.operator import Operator\nfrom mephisto.operations.utils import get_root_dir\nfrom mephisto.tools.scripts import load_db_and_process_config\nfrom mephisto.abstractions.blueprints.static_html_task.static_html_blueprint import (\n    BLUEPRINT_TYPE,\n)\nfrom mephisto.abstractions.blueprints.abstract.static_task.static_blueprint import (\n    SharedStaticTaskState,\n)\n\nimport hydra\nfrom omegaconf import DictConfig\nfrom dataclasses import dataclass, field\nfrom typing import List, Any\n\nTASK_DIRECTORY = os.path.dirname(os.path.abspath(__file__))\nCORRECT_ANSWER = \"apple\"\n\ndefaults = [\n    {\"mephisto/blueprint\": BLUEPRINT_TYPE},\n    {\"mephisto/architect\": \"local\"},\n    {\"mephisto/provider\": \"mock\"},\n    {\"conf\": \"onboarding_example\"},\n]\n\nfrom mephisto.operations.hydra_config import RunScriptConfig, register_script_config\n\n\n@dataclass\nclass TestScriptConfig(RunScriptConfig):\n    defaults: List[Any] = field(default_factory=lambda: defaults)\n    task_dir: str = TASK_DIRECTORY\n    correct_answer: str = CORRECT_ANSWER\n\n\nregister_script_config(name=\"scriptconfig\", module=TestScriptConfig)\n\n\n@hydra.main(config_path=\"hydra_configs\", config_name=\"scriptconfig\")\ndef main(cfg: DictConfig) -> None:\n    correct_config_answer = cfg.correct_answer\n\n    def onboarding_is_valid(onboarding_data):\n        inputs = onboarding_data[\"inputs\"]\n        outputs = onboarding_data[\"outputs\"]\n        return outputs.get(\"answer\") == correct_config_answer\n\n    shared_state = SharedStaticTaskState(\n        onboarding_data={\"correct_answer\": correct_config_answer},\n        validate_onboarding=onboarding_is_valid,\n    )\n\n    db, cfg = load_db_and_process_config(cfg)\n    operator = Operator(db)\n\n    operator.validate_and_run_config(cfg.mephisto, shared_state)\n    operator.wait_for_runs_then_shutdown(skip_input=True, log_rate=30)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "examples/simple_static_task/static_run_with_onboarding.py"}, {"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nfrom typing import List, Dict, Optional, Any, TYPE_CHECKING\nfrom mephisto.abstractions.blueprint import AgentState\nimport os\nimport json\nimport time\nimport weakref\n\nif TYPE_CHECKING:\n    from mephisto.data_model.agent import Agent\n    from mephisto.data_model.packet import Packet\n\nfrom mephisto.operations.logger_core import get_logger\n\nlogger = get_logger(name=__name__)\n\nDATA_FILE = \"agent_data.json\"\n\n\nclass StaticAgentState(AgentState):\n    \"\"\"\n    Agent state for static tasks.\n    \"\"\"\n\n    def _get_empty_state(self) -> Dict[str, Optional[Dict[str, Any]]]:\n        return {\n            \"inputs\": None,\n            \"outputs\": None,\n            \"times\": {\"task_start\": 0, \"task_end\": 0},\n        }\n\n    def __init__(self, agent: \"Agent\"):\n        \"\"\"\n        Static agent states should store\n        input dict -> output dict pairs to disc\n        \"\"\"\n        self.agent = weakref.proxy(agent)\n        self.state: Dict[str, Optional[Dict[str, Any]]] = self._get_empty_state()\n        self.load_data()\n\n    def set_init_state(self, data: Any) -> bool:\n        \"\"\"Set the initial state for this agent\"\"\"\n        if self.get_init_state() is not None:\n            # Initial state is already set\n            return False\n        else:\n            self.state[\"inputs\"] = data\n            times_dict = self.state[\"times\"]\n            assert isinstance(times_dict, dict)\n            times_dict[\"task_start\"] = time.time()\n            self.save_data()\n            return True\n\n    def get_init_state(self) -> Optional[Dict[str, Any]]:\n        \"\"\"\n        Return the initial state for this agent,\n        None if no such state exists\n        \"\"\"\n        if self.state[\"inputs\"] is None:\n            return None\n        return self.state[\"inputs\"].copy()\n\n    def load_data(self) -> None:\n        \"\"\"Load data for this agent from disk\"\"\"\n        data_dir = self.agent.get_data_dir()\n        data_path = os.path.join(data_dir, DATA_FILE)\n        if os.path.exists(data_path):\n            with open(data_path, \"r\") as data_file:\n                self.state = json.load(data_file)\n        else:\n            self.state = self._get_empty_state()\n\n    def get_data(self) -> Dict[str, Any]:\n        \"\"\"Return dict of this agent's state\"\"\"\n        return self.state.copy()\n\n    def save_data(self) -> None:\n        \"\"\"Save static agent data to disk\"\"\"\n        data_dir = self.agent.get_data_dir()\n        os.makedirs(data_dir, exist_ok=True)\n        out_filename = os.path.join(data_dir, DATA_FILE)\n        with open(out_filename, \"w+\") as data_file:\n            json.dump(self.state, data_file)\n        logger.info(f\"SAVED_DATA_TO_DISC at {out_filename}\")\n\n    def update_data(self, live_data: Dict[str, Any]) -> None:\n        \"\"\"\n        Process the incoming data packet, and handle\n        updating the state\n        \"\"\"\n        raise Exception(\n            \"Static tasks should only have final act, but updated live data\"\n        )\n\n    def update_submit(self, submission_data: Dict[str, Any]) -> None:\n        \"\"\"Move the submitted output to the local dict\"\"\"\n        outputs: Dict[str, Any]\n\n        if submission_data.get(\"onboarding_data\") is not None:\n            outputs = submission_data[\"onboarding_data\"]\n        else:\n            outputs = submission_data[\"task_data\"]\n        times_dict = self.state[\"times\"]\n        assert isinstance(times_dict, dict)\n        times_dict[\"task_end\"] = time.time()\n        if submission_data.get(\"files\") != None:\n            logger.info(f\"Got files: {str(submission_data['files'])[:500]}\")\n            outputs[\"files\"] = [f[\"filename\"] for f in submission_data[\"files\"]]\n        self.state[\"outputs\"] = outputs\n        self.save_data()\n\n    def get_task_start(self) -> Optional[float]:\n        \"\"\"\n        Extract out and return the start time recorded for this task.\n        \"\"\"\n        stored_times = self.state[\"times\"]\n        assert stored_times is not None\n        return stored_times[\"task_start\"]\n\n    def get_task_end(self) -> Optional[float]:\n        \"\"\"\n        Extract out and return the end time recorded for this task.\n        \"\"\"\n        stored_times = self.state[\"times\"]\n        assert stored_times is not None\n        return stored_times[\"task_end\"]\n", "path": "mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nimport os\nfrom mephisto.operations.operator import Operator\nfrom mephisto.operations.utils import get_root_dir\nfrom mephisto.tools.scripts import load_db_and_process_config\nfrom mephisto.abstractions.blueprints.static_html_task.static_html_blueprint import (\n    BLUEPRINT_TYPE,\n)\nfrom mephisto.abstractions.blueprints.abstract.static_task.static_blueprint import (\n    SharedStaticTaskState,\n)\n\nimport hydra\nfrom omegaconf import DictConfig\nfrom dataclasses import dataclass, field\nfrom typing import List, Any\n\nTASK_DIRECTORY = os.path.dirname(os.path.abspath(__file__))\nCORRECT_ANSWER = \"apple\"\n\ndefaults = [\"_self_\", {\"conf\": \"onboarding_example\"}]\n\nfrom mephisto.operations.hydra_config import RunScriptConfig, register_script_config\n\n\n@dataclass\nclass TestScriptConfig(RunScriptConfig):\n    defaults: List[Any] = field(default_factory=lambda: defaults)\n    task_dir: str = TASK_DIRECTORY\n    correct_answer: str = CORRECT_ANSWER\n\n\nregister_script_config(name=\"scriptconfig\", module=TestScriptConfig)\n\n\n@hydra.main(config_path=\"hydra_configs\", config_name=\"scriptconfig\")\ndef main(cfg: DictConfig) -> None:\n    correct_config_answer = cfg.correct_answer\n\n    def onboarding_is_valid(onboarding_data):\n        inputs = onboarding_data[\"inputs\"]\n        outputs = onboarding_data[\"outputs\"]\n        return outputs.get(\"answer\") == correct_config_answer\n\n    shared_state = SharedStaticTaskState(\n        onboarding_data={\"correct_answer\": correct_config_answer},\n        validate_onboarding=onboarding_is_valid,\n    )\n\n    db, cfg = load_db_and_process_config(cfg)\n    operator = Operator(db)\n\n    operator.validate_and_run_config(cfg.mephisto, shared_state)\n    operator.wait_for_runs_then_shutdown(skip_input=True, log_rate=30)\n\n\nif __name__ == \"__main__\":\n    main()\n", "path": "examples/simple_static_task/static_run_with_onboarding.py"}, {"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nfrom typing import List, Dict, Optional, Any, TYPE_CHECKING\nfrom mephisto.abstractions.blueprint import AgentState\nimport os\nimport json\nimport time\nimport weakref\n\nif TYPE_CHECKING:\n    from mephisto.data_model.agent import Agent\n    from mephisto.data_model.packet import Packet\n\nfrom mephisto.operations.logger_core import get_logger\n\nlogger = get_logger(name=__name__)\n\nDATA_FILE = \"agent_data.json\"\n\n\nclass StaticAgentState(AgentState):\n    \"\"\"\n    Agent state for static tasks.\n    \"\"\"\n\n    def _get_empty_state(self) -> Dict[str, Optional[Dict[str, Any]]]:\n        return {\n            \"inputs\": None,\n            \"outputs\": None,\n            \"times\": {\"task_start\": 0, \"task_end\": 0},\n        }\n\n    def __init__(self, agent: \"Agent\"):\n        \"\"\"\n        Static agent states should store\n        input dict -> output dict pairs to disc\n        \"\"\"\n        self.agent = weakref.proxy(agent)\n        self.state: Dict[str, Optional[Dict[str, Any]]] = self._get_empty_state()\n        self.load_data()\n\n    def set_init_state(self, data: Any) -> bool:\n        \"\"\"Set the initial state for this agent\"\"\"\n        if self.get_init_state() is not None:\n            # Initial state is already set\n            return False\n        else:\n            self.state[\"inputs\"] = data\n            times_dict = self.state[\"times\"]\n            assert isinstance(times_dict, dict)\n            times_dict[\"task_start\"] = time.time()\n            self.save_data()\n            return True\n\n    def get_init_state(self) -> Optional[Dict[str, Any]]:\n        \"\"\"\n        Return the initial state for this agent,\n        None if no such state exists\n        \"\"\"\n        if self.state[\"inputs\"] is None:\n            return None\n        return self.state[\"inputs\"].copy()\n\n    def load_data(self) -> None:\n        \"\"\"Load data for this agent from disk\"\"\"\n        data_dir = self.agent.get_data_dir()\n        data_path = os.path.join(data_dir, DATA_FILE)\n        if os.path.exists(data_path):\n            with open(data_path, \"r\") as data_file:\n                self.state = json.load(data_file)\n        else:\n            self.state = self._get_empty_state()\n\n    def get_data(self) -> Dict[str, Any]:\n        \"\"\"Return dict of this agent's state\"\"\"\n        return self.state.copy()\n\n    def save_data(self) -> None:\n        \"\"\"Save static agent data to disk\"\"\"\n        data_dir = self.agent.get_data_dir()\n        os.makedirs(data_dir, exist_ok=True)\n        out_filename = os.path.join(data_dir, DATA_FILE)\n        with open(out_filename, \"w+\") as data_file:\n            json.dump(self.state, data_file)\n        logger.info(f\"SAVED_DATA_TO_DISC at {out_filename}\")\n\n    def update_data(self, live_data: Dict[str, Any]) -> None:\n        \"\"\"\n        Process the incoming data packet, and handle\n        updating the state\n        \"\"\"\n        raise Exception(\n            \"Static tasks should only have final act, but updated live data\"\n        )\n\n    def update_submit(self, submission_data: Dict[str, Any]) -> None:\n        \"\"\"Move the submitted output to the local dict\"\"\"\n        outputs: Dict[str, Any]\n        output_files = submission_data.get(\"files\")\n        if output_files is not None:\n            submission_data[\"files\"] = [f[\"filename\"] for f in submission_data[\"files\"]]\n        self.state[\"outputs\"] = submission_data\n        times_dict = self.state[\"times\"]\n        assert isinstance(times_dict, dict)\n        times_dict[\"task_end\"] = time.time()\n        self.save_data()\n\n    def get_task_start(self) -> Optional[float]:\n        \"\"\"\n        Extract out and return the start time recorded for this task.\n        \"\"\"\n        stored_times = self.state[\"times\"]\n        assert stored_times is not None\n        return stored_times[\"task_start\"]\n\n    def get_task_end(self) -> Optional[float]:\n        \"\"\"\n        Extract out and return the end time recorded for this task.\n        \"\"\"\n        stored_times = self.state[\"times\"]\n        assert stored_times is not None\n        return stored_times[\"task_end\"]\n", "path": "mephisto/abstractions/blueprints/abstract/static_task/static_agent_state.py"}]}