feat: add Chinese UI, Responses models, and mirrored Windows setup
Localize the web console and persist custom model and capability settings. Use OpenAI Responses exclusively and move runtime limits into environment configuration. Bootstrap uv and the virtual environment on Windows, support optional China mirrors, and package source distributions without environments, build output, or credentials. Update regression tests and repository quality checks for the new behavior.
This commit is contained in:
1 parent
371aa6df56
commit
2ddec53954
183 files changed
+3427
-11857
No files matched your search
@@ -55,9 +55,9 @@ def test_tool_declaration_mirrors_the_args_schema(tool):
|
||||
assert lc_tool.args_schema is tool.args_schema
|
||||
|
||||
# And the GenAI export agrees on names and required fields.
|
||||
genai = tool.to_genai_declaration()
|
||||
assert set(genai.parameters.properties) == set(properties)
|
||||
assert list(genai.parameters.required or []) == declaration.parameters["required"]
|
||||
genai = tool.to_tool_declaration()
|
||||
assert set(genai.parameters["properties"]) == set(properties)
|
||||
assert list(genai.parameters.get("required") or []) == declaration.parameters["required"]
|
||||
|
||||
|
||||
def test_declared_types_and_enums():
|
||||
|
||||
@@ -47,10 +47,10 @@ def test_append_note_pure_tool_subclass():
|
||||
assert append_note_pure.args_schema == AppendNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = append_note_pure.to_genai_declaration()
|
||||
declaration = append_note_pure.to_tool_declaration()
|
||||
assert declaration.name == "append_note_pure"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "content" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "content" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -51,10 +51,10 @@ def test_append_note_tool_subclass():
|
||||
assert append_note.args_schema == AppendNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = append_note.to_genai_declaration()
|
||||
declaration = append_note.to_tool_declaration()
|
||||
assert declaration.name == "append_note"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "content" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "content" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert append_note_wrapper is not None
|
||||
|
||||
@@ -436,9 +436,9 @@ def test_run_adb_command_tool_subclass():
|
||||
assert run_adb_command.args_schema == RunAdbCommandArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = run_adb_command.to_genai_declaration()
|
||||
declaration = run_adb_command.to_tool_declaration()
|
||||
assert declaration.name == "run_adb_command"
|
||||
assert "CommandLine" in declaration.parameters.properties
|
||||
assert "CommandLine" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -479,9 +479,9 @@ def test_manage_task_tool_subclass():
|
||||
assert manage_task.args_schema == ManageTaskArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = manage_task.to_genai_declaration()
|
||||
declaration = manage_task.to_tool_declaration()
|
||||
assert declaration.name == "manage_task"
|
||||
assert "Action" in declaration.parameters.properties
|
||||
assert "Action" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -541,10 +541,10 @@ def test_analyze_task_output_tool_subclass():
|
||||
assert analyze_task_output.args_schema == AnalyzeTaskOutputArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = analyze_task_output.to_genai_declaration()
|
||||
declaration = analyze_task_output.to_tool_declaration()
|
||||
assert declaration.name == "analyze_task_output"
|
||||
assert "TaskId" in declaration.parameters.properties
|
||||
assert "Query" in declaration.parameters.properties
|
||||
assert "TaskId" in declaration.parameters["properties"]
|
||||
assert "Query" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -606,9 +606,9 @@ def test_run_short_adb_command_tool_subclass():
|
||||
assert run_short_adb_command.args_schema == RunShortAdbCommandArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = run_short_adb_command.to_genai_declaration()
|
||||
declaration = run_short_adb_command.to_tool_declaration()
|
||||
assert declaration.name == "run_short_adb_command"
|
||||
assert "CommandLine" in declaration.parameters.properties
|
||||
assert "CommandLine" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -195,9 +195,9 @@ class TestCommitteeTool(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(ask_committee.args_schema, AskCommitteeArgs)
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = ask_committee.to_genai_declaration()
|
||||
declaration = ask_committee.to_tool_declaration()
|
||||
self.assertEqual(declaration.name, "ask_committee")
|
||||
self.assertIn("avatar_directive", declaration.parameters.properties)
|
||||
self.assertIn("avatar_directive", declaration.parameters["properties"])
|
||||
|
||||
# Wrapper check
|
||||
self.assertIsNotNone(ask_committee_wrapper)
|
||||
|
||||
@@ -109,10 +109,10 @@ def test_tool_contract_is_tier_agnostic():
|
||||
assert fields["context_feedback"].default == ""
|
||||
assert fields["context_feedback"].description == ASK_EXPLORER_CONTEXT_FEEDBACK_DESCRIPTION
|
||||
|
||||
declaration = ask_explorer.to_genai_declaration()
|
||||
declaration = ask_explorer.to_tool_declaration()
|
||||
assert declaration.name == "ask_explorer"
|
||||
assert set(declaration.parameters.properties) == {"query", "context_feedback"}
|
||||
assert declaration.parameters.required == ["query"]
|
||||
assert set(declaration.parameters["properties"]) == {"query", "context_feedback"}
|
||||
assert declaration.parameters.get("required") == ["query"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", [None, "flash", "pro", "ultra"])
|
||||
|
||||
@@ -88,7 +88,7 @@ def test_ask_image_processor_tool_subclass():
|
||||
assert ask_image_processor.args_schema == AskVisionCoderArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = ask_image_processor.to_genai_declaration()
|
||||
declaration = ask_image_processor.to_tool_declaration()
|
||||
assert declaration.name == "ask_image_processor"
|
||||
assert "instruction" in declaration.parameters.properties
|
||||
assert "target_image_id" in declaration.parameters.properties
|
||||
assert "instruction" in declaration.parameters["properties"]
|
||||
assert "target_image_id" in declaration.parameters["properties"]
|
||||
@@ -61,9 +61,9 @@ def test_launch_app_tool_subclass():
|
||||
assert launch_app.args_schema == LaunchAppArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = launch_app.to_genai_declaration()
|
||||
declaration = launch_app.to_tool_declaration()
|
||||
assert declaration.name == "launch_app"
|
||||
assert "app_name" in declaration.parameters.properties
|
||||
assert "app_name" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert launch_app_wrapper is not None
|
||||
|
||||
@@ -47,7 +47,7 @@ def test_list_notes_pure_tool_subclass():
|
||||
assert list_notes_pure.args_schema == ListNotesArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = list_notes_pure.to_genai_declaration()
|
||||
declaration = list_notes_pure.to_tool_declaration()
|
||||
assert declaration.name == "list_notes_pure"
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ def test_list_notes_tool_subclass():
|
||||
assert list_notes.args_schema == ListNotesArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = list_notes.to_genai_declaration()
|
||||
declaration = list_notes.to_tool_declaration()
|
||||
assert declaration.name == "list_notes"
|
||||
|
||||
# Wrapper check
|
||||
|
||||
@@ -101,9 +101,9 @@ def test_analyze_logs_tool_subclass():
|
||||
assert analyze_logs.args_schema == AnalyzeLogsArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = analyze_logs.to_genai_declaration()
|
||||
declaration = analyze_logs.to_tool_declaration()
|
||||
assert declaration.name == "analyze_logs"
|
||||
assert "specific_query" in declaration.parameters.properties
|
||||
assert "specific_query" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert analyze_logs_wrapper is not None
|
||||
|
||||
@@ -66,14 +66,14 @@ def test_object_detection_tool_subclass():
|
||||
assert operator_object_detection.args_schema == OperatorObjectDetectionArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = object_detection.to_genai_declaration()
|
||||
declaration = object_detection.to_tool_declaration()
|
||||
assert declaration.name == "object_detection"
|
||||
assert "image_path" in declaration.parameters.properties
|
||||
assert "queries" in declaration.parameters.properties
|
||||
assert "image_path" in declaration.parameters["properties"]
|
||||
assert "queries" in declaration.parameters["properties"]
|
||||
|
||||
op_declaration = operator_object_detection.to_genai_declaration()
|
||||
op_declaration = operator_object_detection.to_tool_declaration()
|
||||
assert op_declaration.name == "object_detection"
|
||||
assert "queries" in op_declaration.parameters.properties
|
||||
assert "queries" in op_declaration.parameters["properties"]
|
||||
|
||||
# Wrappers
|
||||
assert object_detection_wrapper.tool_fn_getter == get_object_detector_tool
|
||||
|
||||
@@ -77,7 +77,7 @@ def test_ocr_tool_subclass():
|
||||
assert ocr_recognition.args_schema == OcrArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = ocr_recognition.to_genai_declaration()
|
||||
declaration = ocr_recognition.to_tool_declaration()
|
||||
assert declaration.name == "ocr_recognition"
|
||||
|
||||
# Wrapper check
|
||||
|
||||
@@ -59,7 +59,7 @@ def test_get_ui_hierarchy_tool_subclass():
|
||||
assert get_ui_hierarchy.args_schema == GetUiHierarchyArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = get_ui_hierarchy.to_genai_declaration()
|
||||
declaration = get_ui_hierarchy.to_tool_declaration()
|
||||
assert declaration.name == "get_ui_hierarchy"
|
||||
|
||||
# Wrapper check
|
||||
|
||||
@@ -46,11 +46,11 @@ def test_read_logs_tool_subclass():
|
||||
assert read_logs.args_schema == ReadLogsArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = read_logs.to_genai_declaration()
|
||||
declaration = read_logs.to_tool_declaration()
|
||||
assert declaration.name == "read_logs"
|
||||
assert "lines" in declaration.parameters.properties
|
||||
assert "since_time" in declaration.parameters.properties
|
||||
assert "until_time" in declaration.parameters.properties
|
||||
assert "lines" in declaration.parameters["properties"]
|
||||
assert "since_time" in declaration.parameters["properties"]
|
||||
assert "until_time" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -47,11 +47,11 @@ def test_read_note_pure_tool_subclass():
|
||||
assert read_note_pure.args_schema == ReadNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = read_note_pure.to_genai_declaration()
|
||||
declaration = read_note_pure.to_tool_declaration()
|
||||
assert declaration.name == "read_note_pure"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "start_line" in declaration.parameters.properties
|
||||
assert "end_line" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "start_line" in declaration.parameters["properties"]
|
||||
assert "end_line" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -51,11 +51,11 @@ def test_read_note_tool_subclass():
|
||||
assert read_note.args_schema == ReadNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = read_note.to_genai_declaration()
|
||||
declaration = read_note.to_tool_declaration()
|
||||
assert declaration.name == "read_note"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "start_line" in declaration.parameters.properties
|
||||
assert "end_line" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "start_line" in declaration.parameters["properties"]
|
||||
assert "end_line" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert read_note_wrapper is not None
|
||||
|
||||
@@ -47,10 +47,10 @@ def test_save_note_pure_tool_subclass():
|
||||
assert save_note_pure.args_schema == SaveNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = save_note_pure.to_genai_declaration()
|
||||
declaration = save_note_pure.to_tool_declaration()
|
||||
assert declaration.name == "save_note_pure"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "content" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "content" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -51,10 +51,10 @@ def test_save_note_tool_subclass():
|
||||
assert save_note.args_schema == SaveNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = save_note.to_genai_declaration()
|
||||
declaration = save_note.to_tool_declaration()
|
||||
assert declaration.name == "save_note"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "content" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "content" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert save_note_wrapper is not None
|
||||
|
||||
@@ -186,14 +186,14 @@ def test_search_logs_tool_subclass():
|
||||
assert search_logs.args_schema == SearchLogsArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = search_logs.to_genai_declaration()
|
||||
declaration = search_logs.to_tool_declaration()
|
||||
assert declaration.name == "search_logs"
|
||||
assert "keyword" in declaration.parameters.properties
|
||||
assert "is_regex" in declaration.parameters.properties
|
||||
assert "lines" in declaration.parameters.properties
|
||||
assert "since_time" in declaration.parameters.properties
|
||||
assert "until_time" in declaration.parameters.properties
|
||||
assert "context_lines" in declaration.parameters.properties
|
||||
assert "keyword" in declaration.parameters["properties"]
|
||||
assert "is_regex" in declaration.parameters["properties"]
|
||||
assert "lines" in declaration.parameters["properties"]
|
||||
assert "since_time" in declaration.parameters["properties"]
|
||||
assert "until_time" in declaration.parameters["properties"]
|
||||
assert "context_lines" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -48,11 +48,11 @@ def test_update_note_pure_tool_subclass():
|
||||
assert update_note_pure.args_schema == UpdateNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = update_note_pure.to_genai_declaration()
|
||||
declaration = update_note_pure.to_tool_declaration()
|
||||
assert declaration.name == "update_note_pure"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "target" in declaration.parameters.properties
|
||||
assert "replacement" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "target" in declaration.parameters["properties"]
|
||||
assert "replacement" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -52,11 +52,11 @@ def test_update_note_tool_subclass():
|
||||
assert update_note.args_schema == UpdateNoteArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = update_note.to_genai_declaration()
|
||||
declaration = update_note.to_tool_declaration()
|
||||
assert declaration.name == "update_note"
|
||||
assert "key" in declaration.parameters.properties
|
||||
assert "target" in declaration.parameters.properties
|
||||
assert "replacement" in declaration.parameters.properties
|
||||
assert "key" in declaration.parameters["properties"]
|
||||
assert "target" in declaration.parameters["properties"]
|
||||
assert "replacement" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert update_note_wrapper is not None
|
||||
|
||||
@@ -44,10 +44,10 @@ def test_video_analyzer_pure_tool_subclass():
|
||||
assert video_analyzer_pure.args_schema == VideoAnalyzerArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = video_analyzer_pure.to_genai_declaration()
|
||||
declaration = video_analyzer_pure.to_tool_declaration()
|
||||
assert declaration.name == "video_analyzer_pure"
|
||||
assert "time_description" in declaration.parameters.properties
|
||||
assert "purpose" in declaration.parameters.properties
|
||||
assert "time_description" in declaration.parameters["properties"]
|
||||
assert "purpose" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -52,10 +52,10 @@ def test_video_analyzer_tool_subclass():
|
||||
assert video_analyzer.args_schema == VideoAnalyzerArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = video_analyzer.to_genai_declaration()
|
||||
declaration = video_analyzer.to_tool_declaration()
|
||||
assert declaration.name == "video_analyzer"
|
||||
assert "time_description" in declaration.parameters.properties
|
||||
assert "purpose" in declaration.parameters.properties
|
||||
assert "time_description" in declaration.parameters["properties"]
|
||||
assert "purpose" in declaration.parameters["properties"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -47,9 +47,9 @@ def test_wait_tool_subclass():
|
||||
assert wait.args_schema == WaitArgs
|
||||
|
||||
# GenAI FunctionDeclaration export
|
||||
declaration = wait.to_genai_declaration()
|
||||
declaration = wait.to_tool_declaration()
|
||||
assert declaration.name == "wait"
|
||||
assert "seconds" in declaration.parameters.properties
|
||||
assert "seconds" in declaration.parameters["properties"]
|
||||
|
||||
# Wrapper check
|
||||
assert wait_wrapper is not None
|
||||
|
||||
Reference in new issue
Block a user