def build_vscode_extension():
    """Builds the VS Code extension."""
    vsix_path = VSCODE_EXTENSION_DIR / VSIX_FILENAME

    # Check if VSCode extension build is disabled via environment variable
    if os.environ.get('SKIP_VSCODE_BUILD', '').lower() in ('1', 'true', 'yes'):
        print('--- Skipping VS Code extension build (SKIP_VSCODE_BUILD is set) ---')
        if vsix_path.exists():
            print(f'--- Using existing VS Code extension: {vsix_path} ---')
        else:
            print('--- No pre-built VS Code extension found ---')
        return

    # Check Node.js version - if insufficient, use pre-built extension as fallback
    if not check_node_version():
        print('--- Warning: Node.js version < 18 detected or Node.js not found ---')
        print('--- Skipping VS Code extension build (requires Node.js >= 18) ---')
        print('--- Using pre-built extension if available ---')

        if not vsix_path.exists():
            print('--- Warning: No pre-built VS Code extension found ---')
            print('--- VS Code extension will not be available ---')
        else:
            print(f'--- Using pre-built VS Code extension: {vsix_path} ---')
        return

    print(f'--- Building VS Code extension in {VSCODE_EXTENSION_DIR} ---')

    try:
        # Ensure npm dependencies are installed
        print('--- Running npm install for VS Code extension ---')
        subprocess.run(
            ['npm', 'install'],
            cwd=VSCODE_EXTENSION_DIR,
            check=True,
            shell=os.name == 'nt',
        )

        # Package the extension
        print(f'--- Packaging VS Code extension ({VSIX_FILENAME}) ---')
        subprocess.run(
            ['npm', 'run', 'package-vsix'],
            cwd=VSCODE_EXTENSION_DIR,
            check=True,
            shell=os.name == 'nt',
        )

        # Verify the generated .vsix file exists
        if not vsix_path.exists():
            raise FileNotFoundError(
                f'VS Code extension package not found after build: {vsix_path}'
            )

        print(f'--- VS Code extension built successfully: {vsix_path} ---')

    except subprocess.CalledProcessError as e:
        print(f'--- Warning: Failed to build VS Code extension: {e} ---')
        print('--- Continuing without building extension ---')
        if not vsix_path.exists():
            print('--- Warning: No pre-built VS Code extension found ---')
            print('--- VS Code extension will not be available ---')


def parse_args():
    parser = argparse.ArgumentParser(description="Run a task with a given configuration file.")
    parser.add_argument('--config', type=str, required=True, help='Path to the configuration file.')
    return parser.parse_args()


def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    if file and file.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')):
        filename = secure_filename(file.filename)
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(filepath)

        # Get the actual media type
        media_type = file.content_type or 'image/jpeg'  # Default to jpeg if not detected

        # Convert image to base64
        with open(filepath, "rb") as image_file:
            encoded_string = base64.b64encode(image_file.read()).decode('utf-8')

        # Clean up the file
        os.remove(filepath)

        return jsonify({
            'success': True,
            'image_data': encoded_string,
            'media_type': media_type
        })

    return jsonify({'error': 'Invalid file type'}), 400


    def decode(self, input, final=False):
        return codecs.charmap_decode(input,self.errors,decoding_table)[0]


def precompute_freqs_cis(dim: int, end: int, theta: float = 10000.0):
    freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
    t = torch.arange(end, device=freqs.device, dtype=torch.float32)
    freqs = torch.outer(t, freqs)
    freqs_cis = torch.polar(torch.ones_like(freqs), freqs)  # complex64
    return freqs_cis


    def consumer(self, partition_id, type):
        """
        Creates spider log consumer with BaseStreamConsumer interface
        :param partition_id: can be None or integer
        :param type: either 'db' or 'sw'
        :return:
        """
        group = self._sw_group if type == b'sw' else self._db_group
        c = Consumer(self._location, self._enable_ssl, self._cert_path, self._topic, group, partition_id)
        assert len(c._consumer.partitions_for_topic(self._topic)) == self._partitions
        return c


    def post_setup(cls):
        """Post setup configuration.
        This is the place where you can configure settings that require other
        settings to be loaded.
        """
        super().post_setup()

        # The SENTRY_DSN setting should be available to activate sentry for an environment
        if cls.SENTRY_DSN is not None:
            sentry_sdk.init(
                dsn=cls.SENTRY_DSN,
                environment=cls.__name__.lower(),
                release=get_release(),
                integrations=[DjangoIntegration()],
            )
            sentry_sdk.set_tag("application", "backend")

            # Ignore the logs added by the DockerflowMiddleware
            ignore_logger("request.summary")

        if (
            cls.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION
            and cls.OIDC_ALLOW_DUPLICATE_EMAILS
        ):
            raise ValueError(
                "Both OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION and "
                "OIDC_ALLOW_DUPLICATE_EMAILS cannot be set to True simultaneously. "
            )


    def remove(id: str):
        context = AgentContext._contexts.pop(id, None)
        if context and context.task:
            context.task.kill()
        return context


def test_stream():
    data_raw = {
        "kb_ids": [
           "KBf46828db208c4289a120a34f0fc96147",
           "KBc2440f13e98f4736b5ef81cfaebef3a9",
           "KBb78af28c73f74fb4ae6ad44b3c53302f",
           "KB6c2b097d83be430ab809e361fa8dcc8b",
           "KB69331d593f5b4b5bb555a0ea1b145e5b",
           "KB3cdc79f8c8d24a14bffd27e6570c33da"
        ],
        "question": "西南交通大学是211院校吗",
        "user_id": "liujx_265",
        "streaming": True,
        "rerank": True,
        "history": []
    }
    for i, chunk in enumerate(stream_requests(data_raw)):
        if chunk:
            chunkstr = chunk.decode("utf-8")[6:]
            chunkjs = json.loads(chunkstr)
            print(chunkjs)


    def want_form_data_parsed(self):
        """Returns True if the request method carries content.  As of
        Werkzeug 0.9 this will be the case if a content type is transmitted.

        .. versionadded:: 0.8
        """
        return bool(self.environ.get('CONTENT_TYPE'))


    def get_registered_model(self, name=None, workspace=None, id=None):
        """
        Retrieve an already created Registered Model. Only one of name or id can be provided.

        Parameters
        ----------
        name : str, optional
            Name of the Registered Model.
        id : str, optional
            ID of the Registered Model. This parameter cannot be provided alongside `name`.

        Returns
        -------
        :class:`~verta._registry.model.RegisteredModel`
        """
        if name is not None and id is not None:
            raise ValueError("cannot specify both `name` and `id`")

        name = self._set_from_config_if_none(name, "registered_model")
        if name is None and id is None:
            raise ValueError("must specify either `name` or `id`")
        workspace = self._set_from_config_if_none(workspace, "workspace")
        if workspace is None:
            workspace = self._get_personal_workspace()

        self._ctx = _Context(self._conn, self._conf)
        self._ctx.workspace_name = workspace

        if id is not None:
            registered_model = RegisteredModel._get_by_id(self._conn, self._conf, id)
        else:
            registered_model =  RegisteredModel._get_by_name(self._conn, self._conf, name, self._ctx.workspace_name)

        if registered_model is None:
            raise ValueError("Registered model not found")

        return registered_model


def urlopen(*args, **kwargs):
    try:
        return request_module.urlopen(*args, **kwargs)
    except HTTPException as e:
        # https://bugs.python.org/issue8823
        raise EnvironmentError(e)


def _prepare_transformer(model):
    embed_dim = model.tok_embeddings.embedding_dim
    model.tok_embeddings = nn.Identity()
    model.output = nn.Identity()
    return model, embed_dim


  def _std(self):
    return math_ops.sqrt(self.alpha) / self.beta


    def test_buildPose3graph(self):
        pose3graph = gtsam.InitializePose3.buildPose3graph(self.graph)


async def auth(request: Request):
    try:
        access_token = await oauth.google.authorize_access_token(request)
    except OAuthError:
        return RedirectResponse(url="/")
    request.session["user"] = dict(access_token)["userinfo"]
    return RedirectResponse(url="/")


    def _Length2Mask(length):
      return 0xFFFFFFFF & ~((1 << (32 - length)) - 1)


    def test_ignores_other_errors(self, mock_get, mock_sleep):
        """Test that non-429 errors are returned without retrying."""
        # Setup mock response: 500 error
        mock_500_response = Mock()
        mock_500_response.status_code = 500
        mock_500_response.text = "Internal Server Error"

        mock_get.return_value = mock_500_response

        # Call the function
        headers = {"X-API-KEY": "test-key"}
        url = "https://api.financialdatasets.ai/test"

        result = _make_api_request(url, headers)

        # Verify behavior
        assert result.status_code == 500
        assert result.text == "Internal Server Error"

        # Verify requests.get was called only once
        assert mock_get.call_count == 1

        # Verify sleep was never called
        mock_sleep.assert_not_called()


    def cmd_prev_screen(self):
        """Move to the previous screen"""
        return self.focus_screen(
            (self.screens.index(self.current_screen) - 1) % len(self.screens)
        )


    def test_repo_delete_noargs(self, shell):
        """
        Test do_repo_delete no arguments.

        :param shell:
        :return:
        """
        shell.help_repo_delete = MagicMock()
        shell.client.channel.software.removeRepo = MagicMock()
        shell.do_repo_list = MagicMock()
        mprint = MagicMock()
        logger = MagicMock()

        with patch("spacecmd.repo.print", mprint) as prn, \
                patch("spacecmd.repo.logging", logger) as lgr:
            out = spacecmd.repo.do_repo_delete(shell, "")

        assert out is 1
        assert not mprint.called
        assert not logger.error.called
        assert not shell.client.channel.software.removeRepo.called
        assert shell.help_repo_delete.called


    def test_1d_slicing5_npm(self):
        self.test_1d_slicing5(flags=Noflags)


def generate_response(prompt: str, ai_model: str) -> str:
    """
    Generate a script for a video, depending on the subject of the video.

    Args:
        video_subject (str): The subject of the video.
        ai_model (str): The AI model to use for generation.

    Returns:

        str: The response from the AI model.

    """

    if ai_model == 'g4f':
        # Newest G4F Architecture
        client = Client()
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            provider=g4f.Provider.You,
            messages=[{"role": "user", "content": prompt}],
        ).choices[0].message.content

    elif ai_model in ["gpt3.5-turbo", "gpt4"]:

        model_name = "gpt-3.5-turbo" if ai_model == "gpt3.5-turbo" else "gpt-4-1106-preview"

        response = openai.chat.completions.create(

            model=model_name,

            messages=[{"role": "user", "content": prompt}],

        ).choices[0].message.content
    elif ai_model == 'gemmini':
        model = genai.GenerativeModel('gemini-pro')
        response_model = model.generate_content(prompt)
        response = response_model.text

    else:

        raise ValueError("Invalid AI model selected.")

    return response


    def readcmd(self):
        '''Read a single command.'''

        b = self.read(4)
        app, verb, n = struct.unpack('<BBH', b)

        if n > 0:
            data = self.read(n)
        else:
            data = b''

        if len(data) != n:
            raise ValueError('Facedancer expected %d bytes but received only %d' % (n, len(data)))
        cmd = FacedancerCommand(app, verb, data)
        self.logger.verbose('Facedancer Rx command: %s' % cmd)
        return cmd


    def __init__(self, seed):
        self.seed = seed
        self.state = None


  def _define_vars(self, params):
    pass


def test_request_with_existing_query_params():
    """Test a request with existing query parameters in the URL."""
    request = RequestModel(
        name="Request with existing query params",
        method="GET",
        url="https://example.com/api/search?existing=value",
        params=[
            QueryParam(name="q", value="test query"),
            QueryParam(name="page", value="1"),
        ],
    )

    expected = (
        "curl \\\n  'https://example.com/api/search?existing=value&q=test+query&page=1'"
    )
    assert request.to_curl() == expected


def get_api():
    token = input("Write token? ").strip()
    api = HfApi(token=token)
    return api


def test_chat_non_streaming_basic(request, openai_client, model, provider, verification_config, case):
    test_name_base = get_base_test_name(request)
    if should_skip_test(verification_config, provider, model, test_name_base):
        pytest.skip(f"Skipping {test_name_base} for model {model} on provider {provider} based on config.")

    response = openai_client.chat.completions.create(
        model=model,
        messages=case["input"]["messages"],
        stream=False,
    )
    assert response.choices[0].message.role == "assistant"
    assert case["output"].lower() in response.choices[0].message.content.lower()


        def init_with_suppressed_logging(self, *args, verbosity_level=LogLevel.OFF, **kwargs):
            original_multi_step_agent_init(self, *args, verbosity_level=verbosity_level, **kwargs)


    def __init__(
        self,
        name: str,
        content: Optional[str] = None,
        parent: Optional["KnowledgeNode"] = None,
        children: Optional[List["KnowledgeNode"]] = None,
        synthesize_output: Optional[str] = None,
        need_regenerate_synthesize_output: bool = True,
    ):
        """
        Initializes a KnowledgeNode instance.

        Args:
            name (str): The name of the node.
            content (list, optional): A list of information uuid. Defaults to None.
            parent (KnowledgeNode, optional): The parent node of the current node. Defaults to None.
        """
        self.name = name
        self.content: Set[int] = set(content) if content is not None else set()
        self.children = [] if children is None else children
        self.parent = parent
        self.synthesize_output = synthesize_output
        self.need_regenerate_synthesize_output = need_regenerate_synthesize_output


    def test_best_model2_alignment_handles_fertile_words(self):
        # arrange
        sentence_pair = AlignedSent(
            ['i', 'really', ',', 'really', 'love', 'ham'],
            TestIBMModel.__TEST_SRC_SENTENCE,
        )
        # 'bien' produces 2 target words: 'really' and another 'really'
        translation_table = {
            'i': {"j'": 0.9, 'aime': 0.05, 'bien': 0.02, 'jambon': 0.03, None: 0},
            'really': {"j'": 0, 'aime': 0, 'bien': 0.9, 'jambon': 0.01, None: 0.09},
            ',': {"j'": 0, 'aime': 0, 'bien': 0.3, 'jambon': 0, None: 0.7},
            'love': {"j'": 0.05, 'aime': 0.9, 'bien': 0.01, 'jambon': 0.01, None: 0.03},
            'ham': {"j'": 0, 'aime': 0.01, 'bien': 0, 'jambon': 0.99, None: 0},
        }
        alignment_table = defaultdict(
            lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 0.2)))
        )

        ibm_model = IBMModel([])
        ibm_model.translation_table = translation_table
        ibm_model.alignment_table = alignment_table

        # act
        a_info = ibm_model.best_model2_alignment(sentence_pair)

        # assert
        self.assertEqual(a_info.alignment[1:], (1, 3, 0, 3, 2, 4))
        self.assertEqual(a_info.cepts, [[3], [1], [5], [2, 4], [6]])


def app():
    with gr.Blocks():
        with gr.Row():
            with gr.Column():
                image = gr.Image(type="pil", label="Image", visible=True)
                video = gr.Video(label="Video", visible=False)
                input_type = gr.Radio(
                    choices=["Image", "Video"],
                    value="Image",
                    label="Input Type",
                )
                model_id = gr.Dropdown(
                    label="Model",
                    choices=[
                        "yolov10n",
                        "yolov10s",
                        "yolov10m",
                        "yolov10b",
                        "yolov10l",
                        "yolov10x",
                    ],
                    value="yolov10m",
                )
                image_size = gr.Slider(
                    label="Image Size",
                    minimum=320,
                    maximum=1280,
                    step=32,
                    value=640,
                )
                conf_threshold = gr.Slider(
                    label="Confidence Threshold",
                    minimum=0.0,
                    maximum=1.0,
                    step=0.05,
                    value=0.25,
                )
                yolov10_infer = gr.Button(value="Detect Objects")

            with gr.Column():
                output_image = gr.Image(type="numpy", label="Annotated Image", visible=True)
                output_video = gr.Video(label="Annotated Video", visible=False)

        def update_visibility(input_type):
            image = gr.update(visible=True) if input_type == "Image" else gr.update(visible=False)
            video = gr.update(visible=False) if input_type == "Image" else gr.update(visible=True)
            output_image = gr.update(visible=True) if input_type == "Image" else gr.update(visible=False)
            output_video = gr.update(visible=False) if input_type == "Image" else gr.update(visible=True)

            return image, video, output_image, output_video

        input_type.change(
            fn=update_visibility,
            inputs=[input_type],
            outputs=[image, video, output_image, output_video],
        )

        def run_inference(image, video, model_id, image_size, conf_threshold, input_type):
            if input_type == "Image":
                return yolov10_inference(image, None, model_id, image_size, conf_threshold)
            else:
                return yolov10_inference(None, video, model_id, image_size, conf_threshold)

        yolov10_infer.click(
            fn=run_inference,
            inputs=[image, video, model_id, image_size, conf_threshold, input_type],
            outputs=[output_image, output_video],
        )

        gr.Examples(
            examples=[
                [
                    "ultralytics/assets/bus.jpg",
                    "yolov10s",
                    640,
                    0.25,
                ],
                [
                    "ultralytics/assets/zidane.jpg",
                    "yolov10s",
                    640,
                    0.25,
                ],
            ],
            fn=yolov10_inference_for_examples,
            inputs=[
                image,
                model_id,
                image_size,
                conf_threshold,
            ],
            outputs=[output_image],
            cache_examples='lazy',
        )


  def _prob(self, x):
    return math_ops.exp(self._log_prob(x))


def load_audio(
    adfile: Path,
    sampling_rate: int = None,
    length: int = None,
    volume_normalize: bool = False,
    segment_duration: int = None,
) -> np.ndarray:
    r"""Load audio file with target sampling rate and lsength

    Args:
        adfile (Path): path to audio file.
        sampling_rate (int, optional): target sampling rate. Defaults to None.
        length (int, optional): target audio length. Defaults to None.
        volume_normalize (bool, optional): whether perform volume normalization. Defaults to False.
        segment_duration (int): random select a segment with duration of {segment_duration}s.
                                Defualt to None which means the whole audio will be used.

    Returns:
        audio (np.ndarray): audio
    """

    audio, sr = soundfile.read(adfile)
    if len(audio.shape) > 1:
        audio = audio[:, 0]

    if sampling_rate is not None and sr != sampling_rate:
        audio = soxr.resample(audio, sr, sampling_rate, quality="VHQ")
        sr = sampling_rate

    if segment_duration is not None:
        seg_length = int(sr * segment_duration)
        audio = random_select_audio_segment(audio, seg_length)

    # Audio volume normalize
    if volume_normalize:
        audio = audio_volume_normalize(audio)
    # check the audio length
    if length is not None:
        assert abs(audio.shape[0] - length) < 1000
        if audio.shape[0] > length:
            audio = audio[:length]
        else:
            audio = np.pad(audio, (0, int(length - audio.shape[0])))
    return audio


	async def test_action_model_creation(self):
		"""Test that action models are created correctly with filters"""
		registry = Registry()

		# Define actions with different filters
		@registry.action(
			description='No filter action',
		)
		def no_filter_action():
			pass

		@registry.action(description='Domain filter action', domains=['example.com'])
		def domain_filter_action():
			pass

		@registry.action(description='Page filter action', page_filter=lambda page: 'admin' in page.url)
		def page_filter_action():
			pass

		@registry.action(description='Both filters action', domains=['example.com'], page_filter=lambda page: 'admin' in page.url)
		def both_filters_action():
			pass

		# Initial action model should only include no_filter_action
		initial_model = registry.create_action_model()
		assert 'no_filter_action' in initial_model.model_fields
		assert 'domain_filter_action' not in initial_model.model_fields
		assert 'page_filter_action' not in initial_model.model_fields
		assert 'both_filters_action' not in initial_model.model_fields

		# Action model with matching page should include all matching actions
		mock_page = MagicMock(spec=Page)
		mock_page.url = 'https://example.com/admin'

		page_model = registry.create_action_model(page=mock_page)
		assert 'no_filter_action' in page_model.model_fields
		assert 'domain_filter_action' in page_model.model_fields
		assert 'page_filter_action' in page_model.model_fields
		assert 'both_filters_action' in page_model.model_fields

		# Action model with non-matching domain should exclude domain-filtered actions
		mock_page.url = 'https://other.com/admin'
		non_matching_domain_model = registry.create_action_model(page=mock_page)
		assert 'no_filter_action' in non_matching_domain_model.model_fields
		assert 'domain_filter_action' not in non_matching_domain_model.model_fields
		assert 'page_filter_action' in non_matching_domain_model.model_fields
		assert 'both_filters_action' not in non_matching_domain_model.model_fields

		# Action model with non-matching page filter should exclude page-filtered actions
		mock_page.url = 'https://example.com/dashboard'
		non_matching_page_model = registry.create_action_model(page=mock_page)
		assert 'no_filter_action' in non_matching_page_model.model_fields
		assert 'domain_filter_action' in non_matching_page_model.model_fields
		assert 'page_filter_action' not in non_matching_page_model.model_fields
		assert 'both_filters_action' not in non_matching_page_model.model_fields


def test_simple_get_request():
    """Test a simple GET request with no parameters."""
    request = RequestModel(
        name="Simple GET", method="GET", url="https://example.com/api"
    )

    expected = "curl \\\n  'https://example.com/api'"
    assert request.to_curl() == expected


def test_validation_invalid_excluded_types():
    """Test validation function with invalid excluded types."""
    entity_types = {
        'Person': Person,
        'Organization': Organization,
    }

    # Invalid exclusions should raise ValueError
    with pytest.raises(ValueError, match='Invalid excluded entity types'):
        validate_excluded_entity_types(['InvalidType'], entity_types)

    with pytest.raises(ValueError, match='Invalid excluded entity types'):
        validate_excluded_entity_types(['Person', 'NonExistentType'], entity_types)


    def handle(self, *args, **options):
        if len(args) < 1:
            raise CommandError("Invalid number of arguments")

        name = args[0].strip()
        try:
            profile = Profile.objects.get(name=name)
        except Profile.DoesNotExist:
            raise CommandError("Invalid profile name")

        users = []
        try:
            users = [AstakosUser.objects.get(pk=int(pk)) for pk in
                     options.get('users')]
        except AstakosUser.DoesNotExist:
            raise CommandError("Invalid user id")

        groups = []
        try:
            groups = [Group.objects.get(pk=int(pk)) for pk in
                      options.get('groups')]
        except Group.DoesNotExist:
            raise CommandError("Invalid group id")

        update_profile(profile, users, groups)


    def _handle_client(self, client):
        """Handle connected client"""
        print("Client handler started")
        client.settimeout(None)  # No timeout
        buffer = b''

        try:
            while self.running:
                # Receive data
                try:
                    data = client.recv(8192)
                    if not data:
                        print("Client disconnected")
                        break

                    buffer += data
                    try:
                        # Try to parse command
                        command = json.loads(buffer.decode('utf-8'))
                        buffer = b''

                        # Execute command in Blender's main thread
                        def execute_wrapper():
                            try:
                                response = self.execute_command(command)
                                response_json = json.dumps(response)
                                try:
                                    client.sendall(response_json.encode('utf-8'))
                                except:
                                    print("Failed to send response - client disconnected")
                            except Exception as e:
                                print(f"Error executing command: {str(e)}")
                                traceback.print_exc()
                                try:
                                    error_response = {
                                        "status": "error",
                                        "message": str(e)
                                    }
                                    client.sendall(json.dumps(error_response).encode('utf-8'))
                                except:
                                    pass
                            return None

                        # Schedule execution in main thread
                        bpy.app.timers.register(execute_wrapper, first_interval=0.0)
                    except json.JSONDecodeError:
                        # Incomplete data, wait for more
                        pass
                except Exception as e:
                    print(f"Error receiving data: {str(e)}")
                    break
        except Exception as e:
            print(f"Error in client handler: {str(e)}")
        finally:
            try:
                client.close()
            except:
                pass
            print("Client handler stopped")


def predict(image, audio, pose_weight, face_weight, lip_weight, face_expand_ratio, progress=gr.Progress(track_tqdm=True)):
    """
    Create a gradio interface with the configs.
    """
    _ = progress
    config = {
        'source_image': image,
        'driving_audio': audio,
        'pose_weight': pose_weight,
        'face_weight': face_weight,
        'lip_weight': lip_weight,
        'face_expand_ratio': face_expand_ratio,
        'config': 'configs/inference/default.yaml',
        'checkpoint': None,
        'output': ".cache/output.mp4"
    }
    args = argparse.Namespace()
    for key, value in config.items():
        setattr(args, key, value)
    return inference_process(args)


    def get_prompt(self) -> str:
        """Get the prompt for generation."""
        system_prompt = self.system_template.format(system_message=self.system_message)

        if self.sep_style == SeparatorStyle.DeepSeek:
            seps = [self.sep, self.sep2]
            if system_prompt == "" or system_prompt is None:
                ret = ""
            else:
                ret = system_prompt + seps[0]
            for i, (role, message) in enumerate(self.messages):
                if message:
                    ret += role + ": " + message + seps[i % 2]
                else:
                    ret += role + ":"
            return ret
        elif self.sep_style == SeparatorStyle.LLAMA2:
            seps = [self.sep, self.sep2]
            if self.system_message:
                ret = system_prompt
            else:
                ret = "[INST] "
            for i, (role, message) in enumerate(self.messages):
                tag = self.roles[i % 2]
                if message:
                    if type(message) is tuple:  # multimodal message
                        message, _ = message
                    if i == 0:
                        ret += message + " "
                    else:
                        ret += tag + " " + message + seps[i % 2]
                else:
                    ret += tag
            return ret
        elif self.sep_style == SeparatorStyle.PLAIN:
            seps = [self.sep, self.sep2]
            ret = ""
            for i, (role, message) in enumerate(self.messages):
                if message:
                    if type(message) is tuple:
                        message, _, _ = message
                    if i % 2 == 0:
                        ret += message + seps[i % 2]
                    else:
                        ret += message + seps[i % 2]
                else:
                    ret += ""
            return ret
        elif self.sep_style == SeparatorStyle.ALIGNMENT:
            seps = [self.sep, self.sep2]
            ret = ""
            for i, (role, message) in enumerate(self.messages):
                if message:
                    if type(message) is tuple:
                        message, _, _ = message
                    if i % 2 == 0:
                        ret += "<image>\n" + seps[i % 2]
                    else:
                        ret += message + seps[i % 2]
                else:
                    ret += ""
            return ret
        else:
            raise ValueError(f"Invalid style: {self.sep_style}")


    def lcd(self, path):
        path = os.path.normpath(path)
        if not os.path.exists(path):
            raise exceptions.EnvironmentError("Path '%s' does not exist on the local system" % path)
        os.chdir(path)


    def __init__(self, env, tools, names):
        if not SCons.Util.is_List(tools):
            tools = [tools]
        if not SCons.Util.is_List(names):
            names = [names]
        self.env = env
        self.tools = tools
        self.names = names
        self.methods = {}
        for name in names:
            method = ToolInitializerMethod(name, self)
            self.methods[name] = method
            env.AddMethod(method)


    def _wrap_object(self, space, obj):
        return space.newlong_from_rarith_int(obj)


    def build(self, attribute_list, class_list, col_sampler, bin_structure):
        while len(self.alive_nodes) != 0:

            # scan each attribute list
            func = partial(self._process_one_attribute_list, attribute_list, class_list)
            pool = Pool(self.num_thread)
            rets = pool.map(func, col_sampler.col_selected)
            pool.close()

            # process the rets
            for ret in rets:
                for col, uint8_threshold, tree_node_G_H in ret:
                    for tree_node_name in tree_node_G_H.keys():
                        # get the original tree_node by tree_node_name using self.name_to_node
                        tree_node = self.name_to_node[tree_node_name]
                        G, H = tree_node_G_H[tree_node_name]
                        G_left, H_left = tree_node.get_Gleft_Hleft(col, G, H)
                        G_total, H_total = tree_node.Grad, tree_node.Hess
                        gain = self.calculate_split_gain(G_left, H_left, G_total, H_total)
                        tree_node.update_best_gain(col, uint8_threshold, bin_structure[col][uint8_threshold], gain)

            # once had scan all column, we can get the best (feature,threshold,gain) for each alive tree node
            cur_level_node_size = len(self.alive_nodes)
            new_tree_nodes = []
            treenode_leftinds = []
            for _ in range(cur_level_node_size):
                tree_node = self.alive_nodes.pop(0)
                best_feature, best_uint8_threshold, best_threshold, best_gain = tree_node.get_best_feature_threshold_gain()
                if best_gain > 0:
                    nan_direction = 0  # TODO
                    left_child = TreeNode(name=2*tree_node.name, depth=tree_node.depth+1, feature_dim=attribute_list.feature_dim)
                    right_child = TreeNode(name=2*tree_node.name+1, depth=tree_node.depth+1, feature_dim=attribute_list.feature_dim)
                    tree_node.internal_node_setter(best_feature, best_uint8_threshold, best_threshold, nan_direction, left_child, right_child)

                    # to update class_list.corresponding_tree_node one pass, we should save (tree_node,left_inds)
                    left_inds = attribute_list[best_feature]["index"][0:attribute_list.attribute_list_cutting_index[best_feature][best_uint8_threshold+1]]
                    treenode_leftinds.append((tree_node, set(left_inds)))

                    new_tree_nodes.append(left_child)
                    new_tree_nodes.append(right_child)
                    self.name_to_node[left_child.name] = left_child
                    self.name_to_node[right_child.name] = right_child

                else:
                    leaf_score = self.calculate_leaf_score(tree_node.Grad, tree_node.Hess)
                    tree_node.leaf_node_setter(leaf_score)

            # update class_list.corresponding_tree_node one pass
            class_list.update_corresponding_tree_node(treenode_leftinds)

            # update histogram(Grad,Hess,num_sample) for each alive(new) tree node
            class_list.update_histogram_for_tree_node()

            # process the new tree nodes
            # satisfy max_depth? min_child_weight? min_sample_split?
            # if yes, it is leaf node, calculate its leaf score
            # if no, put into self.alive_node
            while len(new_tree_nodes) != 0:
                tree_node = new_tree_nodes.pop()
                if tree_node.depth >= self.max_depth \
                        or tree_node.Hess < self.min_child_weight \
                        or tree_node.num_sample <= self.min_sample_split:
                    tree_node.leaf_node_setter(self.calculate_leaf_score(tree_node.Grad, tree_node.Hess))
                else:
                    self.alive_nodes.append(tree_node)


    def model_dump_json(self, indent: int = 2):
        return json.dumps(self, indent=indent)


def dataset_name(key: str, sv: SessionVariables) -> str:
    """Get dataset name."""
    return next((d for d in sv.datasets.value if d.key == key), None).name  # type: ignore


def test_parse_hparam_args__exponent():
    hparam_args = ['--foo', 'HParams(boo=10**-6)']
    assert parse_hparam_args(hparam_args) == {'foo': HParams(boo=10**-6)}


def register(self, fileobj: _FileObject, events: _EventMask, data: Any = ...) -> SelectorKey: ...


    def items(self):
        return [('spam%d' % a.num, a) for a in self.args]


def get_api():
    token = input("Write token? ").strip()
    api = HfApi(token=token)
    return api


    def digest(self):
        return sha3.sha3_512(self._data).digest()


    def __sub__(self, other):
        return self + (-other)


def run_server():
    build_dir = "build"
    if platform.system() == "Windows":
        server_path = os.path.join(build_dir, "bin", "Release", "llama-server.exe")
        if not os.path.exists(server_path):
            server_path = os.path.join(build_dir, "bin", "llama-server")
    else:
        server_path = os.path.join(build_dir, "bin", "llama-server")

    command = [
        f'{server_path}',
        '-m', args.model,
        '-c', str(args.ctx_size),
        '-t', str(args.threads),
        '-n', str(args.n_predict),
        '-ngl', '0',
        '--temp', str(args.temperature),
        '--host', args.host,
        '--port', str(args.port),
        '-cb'  # Enable continuous batching
    ]

    if args.prompt:
        command.extend(['-p', args.prompt])

    # Note: -cnv flag is removed as it's not supported by the server

    print(f"Starting server on {args.host}:{args.port}")
    run_command(command)


def distribute_bn(model, world_size, reduce=False):
    # ensure every node has the same running bn stats
    for bn_name, bn_buf in unwrap_model(model).named_buffers(recurse=True):
        if ('running_mean' in bn_name) or ('running_var' in bn_name):
            if reduce:
                # average bn stats across whole group
                torch.distributed.all_reduce(bn_buf, op=dist.ReduceOp.SUM)
                bn_buf /= float(world_size)
            else:
                # broadcast bn stats from rank 0 to whole group
                torch.distributed.broadcast(bn_buf, 0)


def secondary_server_selector(selection):
    return selection.with_server_descriptions(
        [s for s in selection.server_descriptions
         if s.server_type == SERVER_TYPE.RSSecondary])


async def is_active():
    logger.info("Is active endpoint called")
    return {"is_active": interaction.is_active}


    def __init__(self, app=None, verb=None, data=None):
        self.app = app
        self.verb = verb
        self.data = data


def parse_key_info(output: str) -> str:
    """Extract and format key information from the output"""
    key_info = []

    # Extract Args namespace
    args_match = re.search(r"Namespace\(.*?\)", output, re.DOTALL)
    if args_match:
        key_info.append(args_match.group(0))

    # Extract input/output token counts
    token_matches = re.findall(r"#(Input|Output) tokens: \d+", output)
    key_info.extend(token_matches)

    # Extract benchmark result section
    result_match = re.search(
        r"============ Serving Benchmark Result ============.*?={50,}",
        output,
        re.DOTALL,
    )
    if result_match:
        key_info.append(result_match.group(0))

    return "\n\n".join(key_info)


def register_conv_template(template: Conversation, override: bool = False):
    """Register a new conversation template."""
    if not override:
        assert (
            template.name not in conv_templates
        ), f"{template.name} has been registered."

    conv_templates[template.name] = template


    def pixmap(self):
        return self.imageLabel.pixmap()


    def system_methodSignature(self, method_name):
        """system.methodSignature('add') => [double, int, int]

        Returns a list describing the signature of the method. In the
        above example, the add method takes two integers as arguments
        and returns a double result.

        This server does NOT support system.methodSignature."""

        # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html

        return 'signatures not supported'


    def smooth_pix(img, tx, ty):
        if tx == args.divide * width - 1 or ty == args.divide * width - 1 or tx == 0 or ty == 0:
            return img
        img[tx, ty] = (img[tx, ty] + img[tx + 1, ty] + img[tx, ty + 1] + img[tx - 1, ty] + img[tx, ty - 1] + img[tx + 1, ty - 1] + img[tx - 1, ty + 1] + img[tx - 1, ty - 1] + img[tx + 1, ty + 1]) / 9
        return img


def large2small(x):
    # (d * width, d * width) -> (d * d, width, width)
    x = x.reshape(args.divide, width, args.divide, width, 3)
    x = np.transpose(x, (0, 2, 1, 3, 4))
    x = x.reshape(canvas_cnt, width, width, 3)
    return x


def update_profile(profile, users, groups):
    profile.groups.all().delete()
    profile.users.all().delete()
    profile.groups.add(*groups)
    profile.users.add(*users)


    def get_builder(self, env):
        """
        Returns the appropriate real Builder for this method name
        after having the associated ToolInitializer object apply
        the appropriate Tool module.
        """
        builder = getattr(env, self.__name__)

        self.initializer.apply_tools(env)

        builder = getattr(env, self.__name__)
        if builder is self:
            # There was no Builder added, which means no valid Tool
            # for this name was found (or possibly there's a mismatch
            # between the name we were called by and the Builder name
            # added by the Tool module).
            return None

        self.initializer.remove_methods(env)

        return builder


    def url_charset(self):
        """The charset that is assumed for URLs.  Defaults to the value
        of :attr:`charset`.

        .. versionadded:: 0.6
        """
        return self.charset


def test_gpt4_tiktoken_equality(text):
    text = unpack(text)
    tokenizer = GPT4Tokenizer()
    enc = tiktoken.get_encoding("cl100k_base")
    tiktoken_ids = enc.encode(text)
    gpt4_tokenizer_ids = tokenizer.encode(text)
    assert gpt4_tokenizer_ids == tiktoken_ids


def secondary_with_tags_server_selector(tag_sets, selection):
    """All near-enough secondaries matching the tag sets."""
    return apply_tag_sets(tag_sets, secondary_server_selector(selection))


    def __enter__(self):
        return self.enter_result


    def __init__(self, color=platform.system().lower() != "windows"):
        # https://stackoverflow.com/questions/2720319/python-figure-out-local-timezone
        self.tz = datetime.now(timezone.utc).astimezone().tzinfo
        self.color = color


def get_pipeline_options(args, config):
  """Returns pipeline options based on args and confs."""
  options = {"project": str(config.get("project"))}
  if args.cloud:
    if not args.job_name:
      raise ValueError("Job name must be specified for cloud runs.")
    if not args.job_dir:
      raise ValueError("Job dir must be specified for cloud runs.")
    options.update({
        "job_name": args.job_name,
        "max_num_workers": int(config.get("max_num_workers")),
        "setup_file": os.path.abspath(get_relative_path(
            "../setup.py")),
        "staging_location": os.path.join(args.job_dir, "staging"),
        "temp_location": os.path.join(args.job_dir, "tmp"),
        "region": config.get("region"),
    })
  pipeline_options = beam.pipeline.PipelineOptions(flags=[], **options)
  return pipeline_options


    def _validate_feature_flag(self):
        """Validates the PlatformParameter domain object that is a feature
        flag.
        """
        if self._data_type != DATA_TYPES.bool:
            raise utils.ValidationError(
                'Data type of feature flags must be bool, got \'%s\' '
                'instead.' % self._data_type)
        if self._feature_stage not in ALLOWED_FEATURE_STAGES:
            raise utils.ValidationError(
                'Invalid feature stage, got \'%s\', expected one of %s.' % (
                    self._feature_stage, ALLOWED_FEATURE_STAGES))

        enabling_rules = [
            rule for rule in self._rules if rule.value_when_matched]
        for rule in enabling_rules:
            server_mode_filters = [
                server_mode_filter for server_mode_filter in rule.filters
                if server_mode_filter.type == 'server_mode']
            for server_mode_filter in server_mode_filters:
                server_modes = [
                    value for _, value in server_mode_filter.conditions]
                if self._feature_stage == FEATURE_STAGES.dev:
                    if (
                            SERVER_MODES.test in server_modes or
                            SERVER_MODES.prod in server_modes):
                        raise utils.ValidationError(
                            'Feature in dev stage cannot be enabled in test or'
                            ' production environments.')
                elif self._feature_stage == FEATURE_STAGES.test:
                    if SERVER_MODES.prod in server_modes:
                        raise utils.ValidationError(
                            'Feature in test stage cannot be enabled in '
                            'production environment.')


def _iter_encoded(iterable, charset):
    for item in iterable:
        if isinstance(item, text_type):
            yield item.encode(charset)
        else:
            yield item


async def test_openrouter_basic_completion(monkeypatch):
    settings = Settings(
        ENABLE_OPENROUTER=True,
        OPENROUTER_API_KEY="key",
        OPENROUTER_MODEL="test-model",
        LLM_KEY="OPENROUTER",
    )
    SettingsManager.set_settings(settings)
    importlib.reload(config_registry)

    monkeypatch.setattr(app, "ARTIFACT_MANAGER", DummyArtifactManager())

    async_mock = AsyncMock(return_value=DummyResponse('{"result": "ok"}'))
    monkeypatch.setattr(api_handler_factory.litellm, "acompletion", async_mock)

    handler = api_handler_factory.LLMAPIHandlerFactory.get_llm_api_handler("OPENROUTER")
    result = await handler("hi", "test")
    assert result == {"result": "ok"}
    async_mock.assert_called_once()


    def test_cosine_scaled_reward(self):
        """Test cosine_scaled_reward with various cases."""
        # Test parameters
        test_params = {
            "min_value_wrong": -1.0,
            "max_value_wrong": -0.5,
            "min_value_correct": 0.5,
            "max_value_correct": 1.0,
            "max_len": 100,
        }

        test_cases = [
            # Correct answers with different lengths
            (
                r"\boxed{\frac{63}{400}}",
                r"\frac{63}{400}",
                20,
                0.943,
            ),  # Short correct answer
            (
                r"\boxed{\frac{63}{400}}",
                r"\frac{63}{400}",
                80,
                0.547,
            ),  # Long correct answer
            # Wrong answers with different lengths
            (
                r"\boxed{\frac{64}{400}}",
                r"\frac{63}{400}",
                20,
                -0.942,
            ),  # Short wrong answer
            (
                r"\boxed{\frac{64}{400}}",
                r"\frac{63}{400}",
                80,
                -0.547,
            ),  # Long wrong answer
        ]

        for content, solution, content_len, expected_reward in test_cases:
            # Pad content to desired length
            padded_content = content + " " * (content_len - len(content))
            completion = [[{"content": padded_content}]]

            rewards = get_cosine_scaled_reward(**test_params)(completion, [solution])
            self.assertAlmostEqual(rewards[0], expected_reward, places=2)


    def _split(self, string):
        bound = self.boundary

        # Yields (startchar, endchar) pairs for each indexable substring in
        # the given string, e.g. "WikiWord" -> (0, 4), (4, 8)

        # Whether we're splitting on transitions (case changes, letter -> num,
        # num -> letter, etc.)
        splitting = self.splitting

        # Make a list (dispos, for "dispossessed") of (startchar, endchar)
        # pairs for runs of text between "'s"
        if "'" in string:
            # Split on possessive 's
            dispos = []
            prev = 0
            for match in self.possessive.finditer(string):
                dispos.append((prev, match.start()))
                prev = match.end()
            if prev < len(string):
                dispos.append((prev, len(string)))
        else:
            # Shortcut if there's no apostrophe in the string
            dispos = ((0, len(string)),)

        # For each run between 's
        for sc, ec in dispos:
            # Split on boundary characters
            for part_match in self.between.finditer(string, sc, ec):
                part_start = part_match.start()
                part_end = part_match.end()

                if splitting:
                    # The point to start splitting at
                    prev = part_start
                    # Find transitions (e.g. "iW" or "a0")
                    for bmatch in bound.finditer(string, part_start, part_end):
                        # The point in the middle of the transition
                        pivot = bmatch.start() + 1
                        # Yield from the previous match to the transition
                        yield (prev, pivot)
                        # Make the transition the new starting point
                        prev = pivot

                    # If there's leftover text at the end, yield it too
                    if prev < part_end:
                        yield (prev, part_end)
                else:
                    # Not splitting on transitions, just yield the part
                    yield (part_start, part_end)


def get_relative_path(path):
  """Return the given path relative to this module."""
  module_dir = os.path.dirname(__file__)
  return os.path.join(module_dir, path)


    def suggest_email(self, first_name, last_name):
        """Generate a suggested email based on first and last name with the last used domain"""
        try:
            # Get the last used email domain
            domain = self.get_last_email_domain()
            if not domain:
                return None

            # Generate email prefix from first and last name (lowercase)
            email_prefix = f"{first_name.lower()}.{last_name.lower()}"

            # Combine prefix and domain
            suggested_email = f"{email_prefix}@{domain}"

            return suggested_email

        except Exception as e:
            error_msg = self.translator.get('account.suggest_email_failed', error=str(e)) if self.translator else f'Failed to suggest email: {str(e)}'
            print(f"{Fore.RED}{EMOJI['ERROR']} {error_msg}{Style.RESET_ALL}")
            return None


def register(self, fileobj: _FileObject, events: _EventMask, data: Any = ...) -> SelectorKey: ...


    def order(self, field_name):
        """Order document by field name

        By default, a query retrieves all documents that satisfy the query in ascending order by document ID.
        You can specify the sort order for your data using `order()`, and you can limit the number of documents
        retrieved using `limit()`

        Put a dash(-) in front of field name if you want to sort it in descending order. You can also combine
        filter with order

        Parameters
        ----------
        field_name : str
            Name of the field on which base order is applied

        Returns
        -------
            Self object
        """
        # Save order in cursor dict for next fetch
        if 'order' in self.cursor_dict:
            self.cursor_dict['order'] = self.cursor_dict['order'] + ',' + field_name
        else:
            self.cursor_dict['order'] = field_name

        order_direction = 'Asc'
        name = field_name

        # If this is in Desc order
        if field_name[0] == '-':
            order_direction = 'Desc'
            name = field_name[1:]  # Get the field name after dash(-) e.g -age name will be age
        f_name = self.model._meta.get_field(name).db_column_name
        self.order_by.append((f_name, order_direction))
        return self


    def clean_slug(self):
        slug = slugify(self.cleaned_data['slug'])
        i = 0
        while True:
            if i > 0:
                if i > 1:
                    slug = slug.rsplit("-", 1)[0]
                slug = "%s-%s" % (slug, i)
            match = Form.objects.filter(slug=slug)
            if self.instance:
                match = match.exclude(pk=self.instance.pk)
            if not match:
                break
            i += 1
        return slug


    def test_format_reward_correct(self):
        """Test format_reward with correct format."""
        completion = [[{"content": "<think>\nSome reasoning\n</think>\n<answer>\nThe answer\n</answer>"}]]
        rewards = format_reward(completion)
        self.assertEqual(rewards[0], 1.0)


    def __getattr__(self, attr):
        return getattr(self.terminal, attr)


def run_migrations():
    """Run all pending database migrations"""
    db_path = get_db_path()

    # logger.info(f"Using database at: {db_path}")

    # Check if database file exists
    if not os.path.exists(db_path):
        # logger.error(f"Database file not found at {db_path}")
        return False

    try:
        # Initialize migration manager
        migrations_dir = os.path.join(project_root, "lpm_kernel", "database", "migrations")
        manager = MigrationManager(db_path)

        # Apply migrations
        applied = manager.apply_migrations(migrations_dir)

        # if applied:
        #     logger.info(f"Successfully applied {len(applied)} migrations")
        # else:
        #     logger.info("No new migrations to apply")

        return True

    except Exception as e:
        logger.error(f"Error during migrations: {e}")
        return False


    def testNewsPaperPromptHint(self):
        local_pdf_path = os.path.join(os.path.dirname(__file__), "gnarly_pdfs", "newspaper.pdf")

        anchor_text = get_anchor_text(local_pdf_path, 1, pdf_engine="pdfreport")

        print(anchor_text)
        print(len(anchor_text))
        self.assertLessEqual(len(anchor_text), 4000)


def extract_glimpse_handler(converter: TensorFlowConverter, tf_op: "tf.Operation"):
    raise NotImplementedError(f"[TensorFlowConverter] {tf_op.type} is not supported yet.")


    def _write_notebook(name: str, content: dict[str, Any]) -> Path:
        notebook_path = tmp_path / name
        with notebook_path.open(mode="w", encoding="utf-8") as f:
            json.dump(content, f)
        return notebook_path


def main():
    parser = argparse.ArgumentParser(description="Gradio WebUI for Browser Agent")
    parser.add_argument("--ip", type=str, default="127.0.0.1", help="IP address to bind to")
    parser.add_argument("--port", type=int, default=7788, help="Port to listen on")
    parser.add_argument("--theme", type=str, default="Ocean", choices=theme_map.keys(), help="Theme to use for the UI")
    args = parser.parse_args()

    demo = create_ui(theme_name=args.theme)
    demo.queue().launch(server_name=args.ip, server_port=args.port)


async def test_controller_with_mcp():
    import os
    from src.controller.custom_controller import CustomController
    from browser_use.controller.registry.views import ActionModel

    mcp_server_config = {
        "mcpServers": {
            # "markitdown": {
            #     "command": "docker",
            #     "args": [
            #         "run",
            #         "--rm",
            #         "-i",
            #         "markitdown-mcp:latest"
            #     ]
            # },
            "desktop-commander": {
                "command": "npx",
                "args": [
                    "-y",
                    "@wonderwhy-er/desktop-commander"
                ]
            },
            # "filesystem": {
            #     "command": "npx",
            #     "args": [
            #         "-y",
            #         "@modelcontextprotocol/server-filesystem",
            #         "/Users/xxx/ai_workspace",
            #     ]
            # },
        }
    }

    controller = CustomController()
    await controller.setup_mcp_client(mcp_server_config)
    action_name = "mcp.desktop-commander.execute_command"
    action_info = controller.registry.registry.actions[action_name]
    param_model = action_info.param_model
    print(param_model.model_json_schema())
    params = {"command": f"python ./tmp/test.py"
              }
    validated_params = param_model(**params)
    ActionModel_ = controller.registry.create_action_model()
    # Create ActionModel instance with the validated parameters
    action_model = ActionModel_(**{action_name: validated_params})
    result = await controller.act(action_model)
    result = result.extracted_content
    print(result)
    if result and "Command is still running. Use read_output to get more output." in result and "PID" in \
            result.split("\n")[0]:
        pid = int(result.split("\n")[0].split("PID")[-1].strip())
        action_name = "mcp.desktop-commander.read_output"
        action_info = controller.registry.registry.actions[action_name]
        param_model = action_info.param_model
        print(param_model.model_json_schema())
        params = {"pid": pid}
        validated_params = param_model(**params)
        action_model = ActionModel_(**{action_name: validated_params})
        output_result = ""
        while True:
            time.sleep(1)
            result = await controller.act(action_model)
            result = result.extracted_content
            if result:
                pdb.set_trace()
                output_result = result
                break
        print(output_result)
        pdb.set_trace()
    await controller.close_mcp_client()
    pdb.set_trace()


	def setUp(self):
		"""Call before every test case."""
		super(FailmanagerComplex, self).setUp()
		self.__failManager = FailManager()
		# down logging level for all this tests, because of extremely large failure count (several GB on heavydebug)
		self.__saved_ll = failmanager.logLevel
		failmanager.logLevel = 3


async def test_deep_research_agent():
    from src.agent.deep_research.deep_research_agent import DeepResearchAgent, PLAN_FILENAME, REPORT_FILENAME
    from src.utils import llm_provider

    llm = llm_provider.get_llm_model(
        provider="openai",
        model_name="gpt-4o",
        temperature=0.5
    )

    # llm = llm_provider.get_llm_model(
    #     provider="bedrock",
    # )

    mcp_server_config = {
        "mcpServers": {
            "desktop-commander": {
                "command": "npx",
                "args": [
                    "-y",
                    "@wonderwhy-er/desktop-commander"
                ]
            },
        }
    }

    browser_config = {"headless": False, "window_width": 1280, "window_height": 1100, "use_own_browser": False}
    agent = DeepResearchAgent(llm=llm, browser_config=browser_config, mcp_server_config=mcp_server_config)
    research_topic = "Give me investment advices of nvidia and tesla."
    task_id_to_resume = ""  # Set this to resume a previous task ID

    print(f"Starting research on: {research_topic}")

    try:
        # Call run and wait for the final result dictionary
        result = await agent.run(research_topic,
                                 task_id=task_id_to_resume,
                                 save_dir="./tmp/deep_research",
                                 max_parallel_browsers=1,
                                 )

        print("\n--- Research Process Ended ---")
        print(f"Status: {result.get('status')}")
        print(f"Message: {result.get('message')}")
        print(f"Task ID: {result.get('task_id')}")

        # Check the final state for the report
        final_state = result.get('final_state', {})
        if final_state:
            print("\n--- Final State Summary ---")
            print(
                f"  Plan Steps Completed: {sum(1 for item in final_state.get('research_plan', []) if item.get('status') == 'completed')}")
            print(f"  Total Search Results Logged: {len(final_state.get('search_results', []))}")
            if final_state.get("final_report"):
                print("  Final Report: Generated (content omitted). You can find it in the output directory.")
                # print("\n--- Final Report ---") # Optionally print report
                # print(final_state["final_report"])
            else:
                print("  Final Report: Not generated.")
        else:
            print("Final state information not available.")

    except Exception as e:
        print(f"\n--- An unhandled error occurred outside the agent run ---")
        print(e)


        def set_value(self, value):
            self.__value = value
            self.changed()  # Emit signal


def greedy_move_to_gpu(model, model_gpu_memory_when_using_cpu_swap):
    mem_counter = 0
    memory_in_swap = 0
    for m in model.modules():
        if hasattr(m, "weight"):
            module_mem = memory_management.module_size(m)
            if mem_counter + module_mem < model_gpu_memory_when_using_cpu_swap:
                m.to(gpu)
                mem_counter += module_mem
            else:
                m.to(cpu)
                memory_in_swap += module_mem

    print(f"[Memory Management] Loaded to CPU Swap: {memory_in_swap / (1024 * 1024):.2f} MB")
    print(f"[Memory Management] Loaded to GPU: {mem_counter / (1024 * 1024):.2f} MB")
    return


def random_select_audio_segment(audio: np.ndarray, length: int) -> np.ndarray:
    """get an audio segment given the length

    Args:
        audio (np.ndarray):
        length (int): audio length = sampling_rate * duration
    """
    if audio.shape[0] < length:
        audio = np.pad(audio, (0, int(length - audio.shape[0])))
    start_index = random.randint(0, audio.shape[0] - length)
    end_index = int(start_index + length)

    return audio[start_index:end_index]


    def execute_trade(self, ticker: str, action: str, quantity: float, current_price: float):
        """
        Execute trades with support for both long and short positions.
        `quantity` is the number of shares the agent wants to buy/sell/short/cover.
        We will only trade integer shares to keep it simple.
        """
        if quantity <= 0:
            return 0

        quantity = int(quantity)  # force integer shares
        position = self.portfolio["positions"][ticker]

        if action == "buy":
            cost = quantity * current_price
            if cost <= self.portfolio["cash"]:
                # Weighted average cost basis for the new total
                old_shares = position["long"]
                old_cost_basis = position["long_cost_basis"]
                new_shares = quantity
                total_shares = old_shares + new_shares

                if total_shares > 0:
                    total_old_cost = old_cost_basis * old_shares
                    total_new_cost = cost
                    position["long_cost_basis"] = (total_old_cost + total_new_cost) / total_shares

                position["long"] += quantity
                self.portfolio["cash"] -= cost
                return quantity
            else:
                # Calculate maximum affordable quantity
                max_quantity = int(self.portfolio["cash"] / current_price)
                if max_quantity > 0:
                    cost = max_quantity * current_price
                    old_shares = position["long"]
                    old_cost_basis = position["long_cost_basis"]
                    total_shares = old_shares + max_quantity

                    if total_shares > 0:
                        total_old_cost = old_cost_basis * old_shares
                        total_new_cost = cost
                        position["long_cost_basis"] = (total_old_cost + total_new_cost) / total_shares

                    position["long"] += max_quantity
                    self.portfolio["cash"] -= cost
                    return max_quantity
                return 0

        elif action == "sell":
            # You can only sell as many as you own
            quantity = min(quantity, position["long"])
            if quantity > 0:
                # Realized gain/loss using average cost basis
                avg_cost_per_share = position["long_cost_basis"] if position["long"] > 0 else 0
                realized_gain = (current_price - avg_cost_per_share) * quantity
                self.portfolio["realized_gains"][ticker]["long"] += realized_gain

                position["long"] -= quantity
                self.portfolio["cash"] += quantity * current_price

                if position["long"] == 0:
                    position["long_cost_basis"] = 0.0

                return quantity

        elif action == "short":
            """
            Typical short sale flow:
              1) Receive proceeds = current_price * quantity
              2) Post margin_required = proceeds * margin_ratio
              3) Net effect on cash = +proceeds - margin_required
            """
            proceeds = current_price * quantity
            margin_required = proceeds * self.portfolio["margin_requirement"]
            if margin_required <= self.portfolio["cash"]:
                # Weighted average short cost basis
                old_short_shares = position["short"]
                old_cost_basis = position["short_cost_basis"]
                new_shares = quantity
                total_shares = old_short_shares + new_shares

                if total_shares > 0:
                    total_old_cost = old_cost_basis * old_short_shares
                    total_new_cost = current_price * new_shares
                    position["short_cost_basis"] = (total_old_cost + total_new_cost) / total_shares

                position["short"] += quantity

                # Update margin usage
                position["short_margin_used"] += margin_required
                self.portfolio["margin_used"] += margin_required

                # Increase cash by proceeds, then subtract the required margin
                self.portfolio["cash"] += proceeds
                self.portfolio["cash"] -= margin_required
                return quantity
            else:
                # Calculate maximum shortable quantity
                margin_ratio = self.portfolio["margin_requirement"]
                if margin_ratio > 0:
                    max_quantity = int(self.portfolio["cash"] / (current_price * margin_ratio))
                else:
                    max_quantity = 0

                if max_quantity > 0:
                    proceeds = current_price * max_quantity
                    margin_required = proceeds * margin_ratio

                    old_short_shares = position["short"]
                    old_cost_basis = position["short_cost_basis"]
                    total_shares = old_short_shares + max_quantity

                    if total_shares > 0:
                        total_old_cost = old_cost_basis * old_short_shares
                        total_new_cost = current_price * max_quantity
                        position["short_cost_basis"] = (total_old_cost + total_new_cost) / total_shares

                    position["short"] += max_quantity
                    position["short_margin_used"] += margin_required
                    self.portfolio["margin_used"] += margin_required

                    self.portfolio["cash"] += proceeds
                    self.portfolio["cash"] -= margin_required
                    return max_quantity
                return 0

        elif action == "cover":
            """
            When covering shares:
              1) Pay cover cost = current_price * quantity
              2) Release a proportional share of the margin
              3) Net effect on cash = -cover_cost + released_margin
            """
            quantity = min(quantity, position["short"])
            if quantity > 0:
                cover_cost = quantity * current_price
                avg_short_price = position["short_cost_basis"] if position["short"] > 0 else 0
                realized_gain = (avg_short_price - current_price) * quantity

                if position["short"] > 0:
                    portion = quantity / position["short"]
                else:
                    portion = 1.0

                margin_to_release = portion * position["short_margin_used"]

                position["short"] -= quantity
                position["short_margin_used"] -= margin_to_release
                self.portfolio["margin_used"] -= margin_to_release

                # Pay the cost to cover, but get back the released margin
                self.portfolio["cash"] += margin_to_release
                self.portfolio["cash"] -= cover_cost

                self.portfolio["realized_gains"][ticker]["short"] += realized_gain

                if position["short"] == 0:
                    position["short_cost_basis"] = 0.0
                    position["short_margin_used"] = 0.0

                return quantity

        return 0


    def __init__(self, framework):
        self.framework = framework


    def __init__(self, real, timeperiod=14):
        pass


    def stop(self):
        self.running = False

        # Close socket
        if self.socket:
            try:
                self.socket.close()
            except:
                pass
            self.socket = None

        # Wait for thread to finish
        if self.server_thread:
            try:
                if self.server_thread.is_alive():
                    self.server_thread.join(timeout=1.0)
            except:
                pass
            self.server_thread = None

        print("BlenderMCP server stopped")


	def purge(self, before):
		""" Remove all done tasks that were created before `before`. Remove
		all done tasks if `before` is None."""
		c = self.connection.cursor()
		query = """
			DELETE FROM Task
			WHERE done IS NOT NULL
		"""
		if before is not None:
			query += """
				AND created < ?
			"""
			values = (before,)
		else:
			values = ()
		c.execute(query, values)
		return c.rowcount


    def test_iterconsume(self, _iterconsume, n='test_iterconsume'):
        c = compat.Consumer(self.connection, queue=n, exchange=n)
        cs = compat.ConsumerSet(self.connection, consumers=[c])
        cs.iterconsume(limit=10, no_ack=True)
        _iterconsume.assert_called_with(c.connection, cs, True, 10)


    def map_class_id_to_class_name(self, class_id):
        return RotationMaskDataset.CLASSES[class_id]


    def test_pause_instance(self):
        self._test_compute_api('pause_instance', 'cast',
                               instance=self.fake_instance_obj)


def fetch_requirements(paths) -> List[str]:
    """
    This function reads the requirements file.

    Args:
        path (str): the path to the requirements file.

    Returns:
        The lines in the requirements file.
    """
    if not isinstance(paths, list):
        paths = [paths]
    requirements = []
    for path in paths:
        with open(path, "r") as fd:
            requirements += [r.strip() for r in fd.readlines()]
    return requirements


    def test_repo_updatessl_non_interactive(self, shell):
        """
        Test do_repo_updatessl non-interactive.

        :param shell:
        :return:
        """
        shell.help_repo_rename = MagicMock()
        shell.client.channel.software.updateRepoSsl = MagicMock()
        shell.do_repo_list = MagicMock()
        mprint = MagicMock()
        logger = MagicMock()
        prompter = MagicMock(return_value="")

        with patch("spacecmd.repo.print", mprint) as prn, \
                patch("spacecmd.repo.prompt_user", prompter) as prn, \
                patch("spacecmd.repo.logging", logger) as lgr:
            out = spacecmd.repo.do_repo_updatessl(shell, "--name name --ca ca --cert cert --key key")

        assert out is 0
        assert not mprint.called
        assert not logger.error.called
        assert shell.client.channel.software.updateRepoSsl.called

        assert_args_expect(shell.client.channel.software.updateRepoSsl.call_args_list,
                           [((shell.session, "name", "ca", "cert", "key"), {})])


  def _GetHostAddresses(self, iface):
    """Returns the IP addresses on host's interfaces, breaking out |iface|."""
    interface_list = self._EnumerateHostInterfaces()
    addresses = []
    iface_address = None
    found_iface = False
    for line in interface_list:
      if not line.startswith((' ', '\t')):
        found_iface = iface in line
      match = re.search(r'(?<=inet )\S+', line)
      if match:
        address = match.group(0)
        if '/' in address:
          address = self._IpPrefix2AddressMask(address)
        else:
          match = re.search(r'(?<=netmask )\S+', line)
          address = self._Ip2Long(address), int(match.group(0), 16)
        if found_iface:
          assert not iface_address, (
            'Found %s twice when parsing host interfaces.' % iface)
          iface_address = address
        else:
          addresses.append(address)
    return addresses, iface_address


  def testNoSlashPrefixExactMatch(self, mock_gsutil_api):
    mock_gsutil_api.ListObjects.return_value = iter([
        CloudApi.CsObjectOrPrefix('folder/',
                                  CloudApi.CsObjectOrPrefixType.PREFIX)
    ])
    (exp_url, have_existing_dst_container) = ExpandUrlToSingleBlr(
        'gs://test/folder', mock_gsutil_api, 'project_id', False,
        CreateOrGetGsutilLogger('copy_test'))

    self.assertTrue(have_existing_dst_container)
    self.assertEqual(exp_url, StorageUrlFromString('gs://test/folder'))


def collect_video_folder_paths(root_path: Path) -> list:
    """
    Collect all video folder paths from the root path.

    Args:
        root_path (Path): The root directory containing video folders.

    Returns:
        list: List of video folder paths.
    """
    return [frames_dir.resolve() for frames_dir in root_path.iterdir() if frames_dir.is_dir()]


async def test_read_write_text(computer):
    tmp_path = "test_rw_text.txt"
    content = "sample text"
    await computer.interface.write_text(tmp_path, content)
    read = await computer.interface.read_text(tmp_path)
    assert read == content, "File content should match"
    await computer.interface.delete_file(tmp_path)


async def process_query(request: QueryRequest):
    global is_generating, query_resp_history
    logger.info(f"Processing query: {request.query}")
    query_resp = QueryResponse(
        done="false",
        answer="",
        reasoning="",
        agent_name="Unknown",
        success="false",
        blocks={},
        status="Ready",
        uid=str(uuid.uuid4())
    )
    if is_generating:
        logger.warning("Another query is being processed, please wait.")
        return JSONResponse(status_code=429, content=query_resp.jsonify())

    try:
        is_generating = True
        success = await think_wrapper(interaction, request.query)
        is_generating = False

        if not success:
            query_resp.answer = interaction.last_answer
            query_resp.reasoning = interaction.last_reasoning
            return JSONResponse(status_code=400, content=query_resp.jsonify())

        if interaction.current_agent:
            blocks_json = {f'{i}': block.jsonify() for i, block in enumerate(interaction.current_agent.get_blocks_result())}
        else:
            logger.error("No current agent found")
            blocks_json = {}
            query_resp.answer = "Error: No current agent"
            return JSONResponse(status_code=400, content=query_resp.jsonify())

        logger.info(f"Answer: {interaction.last_answer}")
        logger.info(f"Blocks: {blocks_json}")
        query_resp.done = "true"
        query_resp.answer = interaction.last_answer
        query_resp.reasoning = interaction.last_reasoning
        query_resp.agent_name = interaction.current_agent.agent_name
        query_resp.success = str(interaction.last_success)
        query_resp.blocks = blocks_json

        query_resp_dict = {
            "done": query_resp.done,
            "answer": query_resp.answer,
            "agent_name": query_resp.agent_name,
            "success": query_resp.success,
            "blocks": query_resp.blocks,
            "status": query_resp.status,
            "uid": query_resp.uid
        }
        query_resp_history.append(query_resp_dict)

        logger.info("Query processed successfully")
        return JSONResponse(status_code=200, content=query_resp.jsonify())
    except Exception as e:
        logger.error(f"An error occurred: {str(e)}")
        sys.exit(1)
    finally:
        logger.info("Processing finished")
        if config.getboolean('MAIN', 'save_session'):
            interaction.save_session()


    def test_repo_setfilters_wrong_filters_syntax(self, shell):
        """
        Test do_repo_setfilters with wrong filters syntax

        :param shell:
        :return:
        """
        shell.help_repo_setfilters = MagicMock()
        shell.client.channel.software.setRepoFilters = MagicMock()
        mprint = MagicMock()
        logger = MagicMock()

        with patch("spacecmd.repo.print", mprint) as prn, \
                patch("spacecmd.repo.logging", logger) as lgr:
            out = spacecmd.repo.do_repo_setfilters(shell, "repo foo bar")

        assert out is 1
        assert not mprint.called
        assert not shell.client.channel.software.setRepoFilters.called
        assert not shell.help_repo_setfilters.called
        assert logger.error.called

        assert_expect(logger.error.call_args_list, "Each filter must start with + or -")


def unregister(self, fileobj: _FileObject) -> SelectorKey: ...


    def test_execute_tool_valid_parameters(self):
        """Test executing a registered tool with valid parameters."""
        self.tool_manager._add_tool(get_current_temperature, TemperatureParams)
        tool_call = {
            "id": "call_1",
            "function": {
                "name": "get_current_temperature",
                "arguments": {"location": "San Francisco", "unit": "Celsius"},
            },
        }
        result, result_message = self.tool_manager.execute_tool(tool_call)

        # Assuming result is returned as a list with a single dictionary
        result_dict = result[0] if isinstance(result, list) else result

        # Check that the result matches expected output
        self.assertEqual(result_dict["location"], "San Francisco")
        self.assertEqual(result_dict["unit"], "Celsius")
        self.assertEqual(result_dict["temperature"], "72")


def apply_tag_sets(tag_sets, selection):
    """All servers match a list of tag sets.

    tag_sets is a list of dicts. The empty tag set {} matches any server,
    and may be provided at the end of the list as a fallback. So
    [{'a': 'value'}, {}] expresses a preference for servers tagged
    {'a': 'value'}, but accepts any server if none matches the first
    preference.
    """
    for tag_set in tag_sets:
        with_tag_set = apply_single_tag_set(tag_set, selection)
        if with_tag_set:
            return with_tag_set

    return selection.with_server_descriptions([])


def requires_gpus(count: int = 1, min_gb: float = 0.0) -> pytest.MarkDecorator:
    """Decorator to skip a test if the required number of GPUs is not available.

    Args:
        count (int): The number of GPUs required for the test. Defaults to 1.
        min_gb: Min required GPU VRAM in GB-s. Has no effect if zero or negative.

    Returns:
        pytest.MarkDecorator: A decorator that skips the test if the required
            number of GPUs is not available.
    """

    if not torch.cuda.is_available():
        return pytest.mark.skip(reason="CUDA is not available")

    gpu_count = torch.cuda.device_count()

    error_message = ""
    if gpu_count < count:
        error_message = (
            f"Not enough GPUs to run the test: requires '{count}',"
            f" got '{torch.cuda.device_count()}'"
        )
    elif min_gb > 0.0:
        eps = 1e-2  # relative tolerance
        for device_idx in range(gpu_count):
            _, total_memory = torch.cuda.mem_get_info(device_idx)
            total_memory_gb = float(total_memory) / float(1024 * 1024 * 1024)
            if total_memory_gb < min_gb * (1 - eps):
                device_name = torch.cuda.get_device_name(device_idx)
                error_message = (
                    "Not enough GPU memory to run the test: "
                    f"requires {min_gb:.3f}GB, got {total_memory_gb:.3f}GB. "
                    f"GPU: {device_name}"
                ) + (f" ({device_idx + 1} of {gpu_count})" if gpu_count > 1 else "")

    return pytest.mark.skipif(len(error_message) > 0, reason=error_message)


    def test_1d_slicing7_npm(self):
        self.test_1d_slicing7(flags=Noflags)


def merge(ids, pair, idx):
    """
    In the list of integers (ids), replace all consecutive occurrences
    of pair with the new integer token idx
    Example: ids=[1, 2, 3, 1, 2], pair=(1, 2), idx=4 -> [4, 3, 4]
    """
    newids = []
    i = 0
    while i < len(ids):
        # if not at the very last position AND the pair matches, replace it
        if ids[i] == pair[0] and i < len(ids) - 1 and ids[i+1] == pair[1]:
            newids.append(idx)
            i += 2
        else:
            newids.append(ids[i])
            i += 1
    return newids


    def test_from_array_int_time(surv_arrays):
        event, time = surv_arrays
        time += 1
        time *= time

        expected = numpy.empty(dtype=[('event', bool), ('time', float)], shape=100)
        expected['event'] = event.astype(bool)
        expected['time'] = time.astype(int)

        y = Surv.from_arrays(event.astype(bool), time.astype(int))
        assert_array_equal(y, expected)


	def get_ResourceOwnerAccount(self):
		return self.get_query_params().get('ResourceOwnerAccount')


    def prep(self, shared):
        files_data = shared["files"]
        project_name = shared["project_name"]  # Get project name
        language = shared.get("language", "english")  # Get language
        use_cache = shared.get("use_cache", True)  # Get use_cache flag, default to True
        max_abstraction_num = shared.get("max_abstraction_num", 10)  # Get max_abstraction_num, default to 10

        # Helper to create context from files, respecting limits (basic example)
        def create_llm_context(files_data):
            context = ""
            file_info = []  # Store tuples of (index, path)
            for i, (path, content) in enumerate(files_data):
                entry = f"--- File Index {i}: {path} ---\n{content}\n\n"
                context += entry
                file_info.append((i, path))

            return context, file_info  # file_info is list of (index, path)

        context, file_info = create_llm_context(files_data)
        # Format file info for the prompt (comment is just a hint for LLM)
        file_listing_for_prompt = "\n".join(
            [f"- {idx} # {path}" for idx, path in file_info]
        )
        return (
            context,
            file_listing_for_prompt,
            len(files_data),
            project_name,
            language,
            use_cache,
            max_abstraction_num,
        )  # Return all parameters


async def test_graph_undirected_property(storage):
    """
    专门测试图存储的无向图特性:
    1. 验证插入一个方向的边后，反向查询是否能获得相同的结果
    2. 验证边的属性在正向和反向查询中是否一致
    3. 验证删除一个方向的边后，另一个方向的边是否也被删除
    4. 验证批量操作中的无向图特性
    """
    try:
        # 1. 插入测试数据
        # 插入节点1: 计算机科学
        node1_id = "计算机科学"
        node1_data = {
            "entity_id": node1_id,
            "description": "计算机科学是研究计算机及其应用的科学。",
            "keywords": "计算机,科学,技术",
            "entity_type": "学科",
        }
        print(f"插入节点1: {node1_id}")
        await storage.upsert_node(node1_id, node1_data)

        # 插入节点2: 数据结构
        node2_id = "数据结构"
        node2_data = {
            "entity_id": node2_id,
            "description": "数据结构是计算机科学中的一个基础概念，用于组织和存储数据。",
            "keywords": "数据,结构,组织",
            "entity_type": "概念",
        }
        print(f"插入节点2: {node2_id}")
        await storage.upsert_node(node2_id, node2_data)

        # 插入节点3: 算法
        node3_id = "算法"
        node3_data = {
            "entity_id": node3_id,
            "description": "算法是解决问题的步骤和方法。",
            "keywords": "算法,步骤,方法",
            "entity_type": "概念",
        }
        print(f"插入节点3: {node3_id}")
        await storage.upsert_node(node3_id, node3_data)

        # 2. 测试插入边后的无向图特性
        print("\n== 测试插入边后的无向图特性")

        # 插入边1: 计算机科学 -> 数据结构
        edge1_data = {
            "relationship": "包含",
            "weight": 1.0,
            "description": "计算机科学包含数据结构这个概念",
        }
        print(f"插入边1: {node1_id} -> {node2_id}")
        await storage.upsert_edge(node1_id, node2_id, edge1_data)

        # 验证正向查询
        forward_edge = await storage.get_edge(node1_id, node2_id)
        print(f"正向边属性: {forward_edge}")
        assert forward_edge is not None, f"未能读取正向边属性: {node1_id} -> {node2_id}"

        # 验证反向查询
        reverse_edge = await storage.get_edge(node2_id, node1_id)
        print(f"反向边属性: {reverse_edge}")
        assert reverse_edge is not None, f"未能读取反向边属性: {node2_id} -> {node1_id}"

        # 验证正向和反向边属性是否一致
        assert (
            forward_edge == reverse_edge
        ), "正向和反向边属性不一致，无向图特性验证失败"
        print("无向图特性验证成功：正向和反向边属性一致")

        # 3. 测试边的度数的无向图特性
        print("\n== 测试边的度数的无向图特性")

        # 插入边2: 计算机科学 -> 算法
        edge2_data = {
            "relationship": "包含",
            "weight": 1.0,
            "description": "计算机科学包含算法这个概念",
        }
        print(f"插入边2: {node1_id} -> {node3_id}")
        await storage.upsert_edge(node1_id, node3_id, edge2_data)

        # 验证正向和反向边的度数
        forward_degree = await storage.edge_degree(node1_id, node2_id)
        reverse_degree = await storage.edge_degree(node2_id, node1_id)
        print(f"正向边 {node1_id} -> {node2_id} 的度数: {forward_degree}")
        print(f"反向边 {node2_id} -> {node1_id} 的度数: {reverse_degree}")
        assert (
            forward_degree == reverse_degree
        ), "正向和反向边的度数不一致，无向图特性验证失败"
        print("无向图特性验证成功：正向和反向边的度数一致")

        # 4. 测试删除边的无向图特性
        print("\n== 测试删除边的无向图特性")

        # 删除正向边
        print(f"删除边: {node1_id} -> {node2_id}")
        await storage.remove_edges([(node1_id, node2_id)])

        # 验证正向边是否被删除
        forward_edge = await storage.get_edge(node1_id, node2_id)
        print(f"删除后查询正向边属性 {node1_id} -> {node2_id}: {forward_edge}")
        assert forward_edge is None, f"边 {node1_id} -> {node2_id} 应已被删除"

        # 验证反向边是否也被删除
        reverse_edge = await storage.get_edge(node2_id, node1_id)
        print(f"删除后查询反向边属性 {node2_id} -> {node1_id}: {reverse_edge}")
        assert (
            reverse_edge is None
        ), f"反向边 {node2_id} -> {node1_id} 也应被删除，无向图特性验证失败"
        print("无向图特性验证成功：删除一个方向的边后，反向边也被删除")

        # 5. 测试批量操作中的无向图特性
        print("\n== 测试批量操作中的无向图特性")

        # 重新插入边
        await storage.upsert_edge(node1_id, node2_id, edge1_data)

        # 批量获取边属性
        edge_dicts = [
            {"src": node1_id, "tgt": node2_id},
            {"src": node1_id, "tgt": node3_id},
        ]
        reverse_edge_dicts = [
            {"src": node2_id, "tgt": node1_id},
            {"src": node3_id, "tgt": node1_id},
        ]

        edges_dict = await storage.get_edges_batch(edge_dicts)
        reverse_edges_dict = await storage.get_edges_batch(reverse_edge_dicts)

        print(f"批量获取正向边属性结果: {edges_dict.keys()}")
        print(f"批量获取反向边属性结果: {reverse_edges_dict.keys()}")

        # 验证正向和反向边的属性是否一致
        for (src, tgt), props in edges_dict.items():
            assert (
                tgt,
                src,
            ) in reverse_edges_dict, f"反向边 {tgt} -> {src} 应在返回结果中"
            assert (
                props == reverse_edges_dict[(tgt, src)]
            ), f"边 {src} -> {tgt} 和反向边 {tgt} -> {src} 的属性不一致"

        print("无向图特性验证成功：批量获取的正向和反向边属性一致")

        # 6. 测试批量获取节点边的无向图特性
        print("\n== 测试批量获取节点边的无向图特性")

        nodes_edges = await storage.get_nodes_edges_batch([node1_id, node2_id])
        print(f"批量获取节点边结果: {nodes_edges.keys()}")

        # 检查节点1的边是否包含所有相关的边（无论方向）
        node1_edges = nodes_edges[node1_id]
        node2_edges = nodes_edges[node2_id]

        # 检查节点1是否有到节点2和节点3的边
        has_edge_to_node2 = any(
            (src == node1_id and tgt == node2_id) for src, tgt in node1_edges
        )
        has_edge_to_node3 = any(
            (src == node1_id and tgt == node3_id) for src, tgt in node1_edges
        )

        assert has_edge_to_node2, f"节点 {node1_id} 的边列表中应包含到 {node2_id} 的边"
        assert has_edge_to_node3, f"节点 {node1_id} 的边列表中应包含到 {node3_id} 的边"

        # 检查节点2是否有到节点1的边
        has_edge_to_node1 = any(
            (src == node2_id and tgt == node1_id)
            or (src == node1_id and tgt == node2_id)
            for src, tgt in node2_edges
        )
        assert (
            has_edge_to_node1
        ), f"节点 {node2_id} 的边列表中应包含与 {node1_id} 的连接"

        print("无向图特性验证成功：批量获取的节点边包含所有相关的边（无论方向）")

        print("\n无向图特性测试完成")
        return True

    except Exception as e:
        ASCIIColors.red(f"测试过程中发生错误: {str(e)}")
        return False


	def set_EndCreateTime(self,EndCreateTime):
		self.add_query_param('EndCreateTime',EndCreateTime)


def get_configs_dir() -> Path:
    return (Path(__file__).parent.parent / "configs").resolve()


def test_js_execution(tester: Crawl4AiTester):
    print("\n=== Testing JS Execution ===")
    request = {
        "urls": ["https://www.nbcnews.com/business"],
        "priority": 8,
        "js_code": [
            "const loadMoreButton = Array.from(document.querySelectorAll('button')).find(button => button.textContent.includes('Load More')); loadMoreButton && loadMoreButton.click();"
        ],
        "wait_for": "article.tease-card:nth-child(10)",
        "crawler_params": {"headless": True},
    }

    result = tester.submit_and_wait(request)
    print(f"JS execution result length: {len(result['result']['markdown'])}")
    assert result["result"]["success"]


    def setImage(self, image):
        """ Records the original image selected by the user, creates a color
            separation, and enables the invert image checkbox.
        """
        self.originalImage = image
        self.createImage()
        self.invertButton.setEnabled(True)


    def __init__(self, dist):
        """Create and initialize a new Command object.  Most importantly,
        invokes the 'initialize_options()' method, which is the real
        initializer and depends on the actual command being
        instantiated.
        """
        # late import because of mutual dependence between these classes
        from distutils.dist import Distribution

        if not isinstance(dist, Distribution):
            raise TypeError("dist must be a Distribution instance")
        if self.__class__ is Command:
            raise RuntimeError("Command is an abstract class")

        self.distribution = dist
        self.initialize_options()

        # Per-command versions of the global flags, so that the user can
        # customize Distutils' behaviour command-by-command and let some
        # commands fall back on the Distribution's behaviour.  None means
        # "not defined, check self.distribution's copy", while 0 or 1 mean
        # false and true (duh).  Note that this means figuring out the real
        # value of each flag is a touch complicated -- hence "self._dry_run"
        # will be handled by __getattr__, below.
        # XXX This needs to be fixed.
        self._dry_run = None

        # verbose is largely ignored, but needs to be set for
        # backwards compatibility (I think)?
        self.verbose = dist.verbose

        # Some commands define a 'self.force' option to ignore file
        # timestamps, but methods defined *here* assume that
        # 'self.force' exists for all commands.  So define it here
        # just to be safe.
        self.force = None

        # The 'help' flag is just used for command-line parsing, so
        # none of that complicated bureaucracy is needed.
        self.help = 0

        # 'finalized' records whether or not 'finalize_options()' has been
        # called.  'finalize_options()' itself should not pay attention to
        # this flag: it is the business of 'ensure_finalized()', which
        # always calls 'finalize_options()', to respect/update it.
        self.finalized = 0


  def _mean(self):
    return self.alpha / self.beta


    def show_extended_status_menu(self):
        from gui.status import get_state_choices

        m = SimpleMenu(self, skinkey = skin.get('%s.MenuSkin'%self.skinkey))

        for status in get_state_choices():
            statusname, statuslabel = status

            def onclick(item, state=statusname):
                self.change_state(state)#, change_text = self.status_state == self.GetValue())

            m.AppendItem(SimpleMenuItem([StatusMessage.icon_for(statusname), statuslabel],
                                        method = onclick))

        if m.GetCount() > 0:
            m.Display(self.cbutton)


def draw_bounding_boxes_handler(converter: TensorFlowConverter, tf_op: "tf.Operation"):
    raise NotImplementedError(f"[TensorFlowConverter] {tf_op.type} is not supported yet.")


    def test_1d_slicing6_npm(self):
        self.test_1d_slicing6(flags=Noflags)


    def __init__(self, open, high, low, close):
        pass


def test_asciidocs_examples():
    fnames = sorted(glob.glob("./tests/data/asciidoc/*.asciidoc"))

    for fname in fnames:
        print(f"reading {fname}")

        bname = os.path.basename(fname)
        gname = os.path.join("./tests/data/groundtruth/docling_v2/", bname + ".md")

        doc_backend = _get_backend(Path(fname))
        doc = doc_backend.convert()

        pred_itdoc = doc._export_to_indented_text(max_text_len=16)
        print("\n\n", pred_itdoc)

        pred_mddoc = doc.export_to_markdown()
        print("\n\n", pred_mddoc)

        if os.path.exists(gname):
            with open(gname) as fr:
                fr.read()

            # assert pred_mddoc == true_mddoc, "pred_mddoc!=true_mddoc for asciidoc"
        else:
            with open(gname, "w") as fw:
                fw.write(pred_mddoc)

            # print("\n\n", doc.export_to_markdown())

    assert True


def clear_argv(func):
    """
    Decorator: Clear sys.argv before calling the decorated function, keeping only the script name. Restore original sys.argv after calling.
    Used to prevent arguments from being parsed by Hugging Face HfArgumentParser causing ValueError.
    """

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        original_argv = sys.argv.copy()
        sys.argv = [original_argv[0]]  # Keep only script name
        try:
            return func(*args, **kwargs)
        finally:
            sys.argv = original_argv  # Restore original sys.argv

    return wrapper


def cancel():
    print(colored("[!] Received cancellation request...", "yellow"))

    global GENERATING
    GENERATING = False

    return jsonify({"status": "success", "message": "Cancelled video generation."})


  def test_get_supported_models(self):
    for case in test_cases:
      with self.subTest(f"{case.name}_short_names"):
        result = get_supported_models(case.engine_lists)
        self._verify_results(case, result)

      with self.subTest(f"{case.name}_class_names"):
        class_name_lists = expand_engine_lists(case.engine_lists)
        result = get_supported_models(class_name_lists)
        self._verify_results(case, result)


def text_processing_section():
    st.header(t("b. Translate and Generate Subtitles"))
    with st.container(border=True):
        st.markdown(f"""

        {t("This stage includes the following steps:")}

            1. {t("WhisperX word-level transcription")}

            2. {t("Sentence segmentation using NLP and LLM")}

            3. {t("Summarization and multi-step translation")}

            4. {t("Cutting and aligning long subtitles")}

            5. {t("Generating timeline and subtitles")}

            6. {t("Merging subtitles into the video")}
        """, unsafe_allow_html=True)

        if not os.path.exists(SUB_VIDEO):
            if st.button(t("Start Processing Subtitles"), key="text_processing_button"):
                process_text()
                st.rerun()
        else:
            if load_key("burn_subtitles"):
                st.video(SUB_VIDEO)
            download_subtitle_zip_button(text=t("Download All Srt Files"))

            if st.button(t("Archive to 'history'"), key="cleanup_in_text_processing"):
                cleanup()
                st.rerun()
            return True


    def has_child(self, child_node_name: str):
        """
        Check if the node has the child of given name.
        """
        return child_node_name in [child.name for child in self.children]


        def extract_index(s):
            return int(index_capture.match(s).groups()[0])


    def group_fetch(self, limit=None):
        super().set_group_collection(True)
        return self.fetch(limit)


def simulate_progress(message, duration=1.0, steps=20):
    print(f"\033[94m{message}\033[0m")
    for i in range(steps + 1):
        time.sleep(duration / steps)
        progress_bar(i, steps, prefix="Progress:", length=40)


    def kill_process(self):
        if self.task:
            self.task.kill()


    def test_inject_network_info(self):
        self._test_compute_api('inject_network_info', 'cast',
                instance=self.fake_instance_obj)


  def OverrideRoutingPolicy(self):
    """Override any routing policy that could prevent
    packets from reaching the rndis interface
    """
    policies = self._device.RunShellCommand(['ip', 'rule'], check_return=True)
    if len(policies) > 1 and not 'lookup main' in policies[1]:
      self._device.RunShellCommand(
          ['ip', 'rule', 'add', 'prio', '1', 'from', 'all', 'table', 'main'],
          check_return=True)
      self._device.RunShellCommand(
          ['ip', 'route', 'flush', 'cache'], check_return=True)


    def __radd__(self, other):
        return self + other


    def is_child_left(self, ind):
        # Check if first child exists
        return self.child_left(ind) < len(self.array)