unique_orchestrator 2026.40.0.dev3__tar.gz → 2026.40.0.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/PKG-INFO +2 -2
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/pyproject.toml +2 -2
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/loop_iteration_runner.py +10 -2
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/config.py +4 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_build_loop_iteration_runner.py +71 -3
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_config_services_validators.py +12 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/README.md +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/__init__.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/__init__.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/history_manager.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/inject_tool_reminders.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/open_file_setup.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/_builders/skill_setup.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/prompts/generic_reference_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/prompts/system_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/prompts/user_message_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/settings.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_agent_config_rjsf_ui_schema.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_qwen_max_loop_iterations.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_register_code_interpreter_postprocessors.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_async_modify.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_execution_timing.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_get_filtered_user_metadata.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_log_tool_calls.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_loop_debug_params.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_persist_tool_calls.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_plan_or_execute_include.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_reference_order.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_render_system_prompt_user_instructions.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_unique_ai_token_usage.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/tests/test_utils_resolve_other_options.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/unique_ai.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/unique_ai_builder.py +0 -0
- {unique_orchestrator-2026.40.0.dev3 → unique_orchestrator-2026.40.0.dev5}/unique_orchestrator/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-orchestrator
|
|
3
|
-
Version: 2026.40.0.
|
|
3
|
+
Version: 2026.40.0.dev5
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Andreas Hauri
|
|
6
6
|
Author-email: Andreas Hauri <andreas.hauri@unique.ai>
|
|
@@ -9,7 +9,7 @@ Requires-Dist: pydantic>=2.8.2,<3
|
|
|
9
9
|
Requires-Dist: pydantic-settings>=2.10.1,<3
|
|
10
10
|
Requires-Dist: typing-extensions>=4.9.0,<5
|
|
11
11
|
Requires-Dist: jinja2>=3.1.0,<4
|
|
12
|
-
Requires-Dist: unique-toolkit>=2026.40.0.
|
|
12
|
+
Requires-Dist: unique-toolkit>=2026.40.0.dev12,<2026.40.0rc0
|
|
13
13
|
Requires-Dist: unique-stock-ticker>=2026.40.0.dev0,<2026.40.0rc0
|
|
14
14
|
Requires-Dist: unique-follow-up-questions>=2026.40.0.dev0,<2026.40.0rc0
|
|
15
15
|
Requires-Dist: unique-internal-search>=2026.40.0.dev0,<2026.40.0rc0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "unique_orchestrator"
|
|
3
|
-
version = "2026.40.0.
|
|
3
|
+
version = "2026.40.0.dev5"
|
|
4
4
|
description = ""
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "Proprietary" }
|
|
@@ -13,7 +13,7 @@ dependencies = [
|
|
|
13
13
|
"pydantic-settings>=2.10.1,<3",
|
|
14
14
|
"typing-extensions>=4.9.0,<5",
|
|
15
15
|
"jinja2>=3.1.0,<4",
|
|
16
|
-
"unique-toolkit>=2026.40.0.
|
|
16
|
+
"unique-toolkit>=2026.40.0.dev12,<2026.40.0rc0",
|
|
17
17
|
"unique-stock-ticker>=2026.40.0.dev0,<2026.40.0rc0",
|
|
18
18
|
"unique-follow-up-questions>=2026.40.0.dev0,<2026.40.0rc0",
|
|
19
19
|
"unique-internal-search>=2026.40.0.dev0,<2026.40.0rc0",
|
|
@@ -9,6 +9,7 @@ from unique_toolkit.agentic.loop_runner import (
|
|
|
9
9
|
LoopIterationRunner,
|
|
10
10
|
MistralLoopIterationRunner,
|
|
11
11
|
PlanningMiddleware,
|
|
12
|
+
PromptForcedToolLoopIterationRunner,
|
|
12
13
|
QwenLoopIterationRunner,
|
|
13
14
|
ResponsesBasicLoopIterationRunner,
|
|
14
15
|
ResponsesLoopIterationRunner,
|
|
@@ -52,9 +53,16 @@ def build_loop_iteration_runner(
|
|
|
52
53
|
)
|
|
53
54
|
family = get_model_family(str(config.space.language_model))
|
|
54
55
|
|
|
55
|
-
if
|
|
56
|
+
if not config.space.language_model.supports_forced_tool_choice:
|
|
57
|
+
# The model returns HTTP 400 for a named or "any" tool_choice, so the
|
|
58
|
+
# tool is requested in the prompt instead. Checked before the family
|
|
59
|
+
# runners because that failure is hard.
|
|
60
|
+
runner: LoopIterationRunner = PromptForcedToolLoopIterationRunner(
|
|
61
|
+
config=base_config
|
|
62
|
+
)
|
|
63
|
+
elif family == "qwen":
|
|
56
64
|
qwen_cfg = config.agent.experimental.loop_configuration.model_specific.qwen
|
|
57
|
-
runner
|
|
65
|
+
runner = QwenLoopIterationRunner(
|
|
58
66
|
config=BasicLoopIterationRunnerConfig(
|
|
59
67
|
max_loop_iterations=qwen_cfg.max_loop_iterations
|
|
60
68
|
),
|
|
@@ -528,12 +528,16 @@ GPT_FRONTIER_MODELS: frozenset[LanguageModelName] = frozenset(
|
|
|
528
528
|
LanguageModelName.AZURE_GPT_56_TERRA_2026_0709,
|
|
529
529
|
LanguageModelName.AZURE_GPT_56_LUNA_2026_0709,
|
|
530
530
|
LanguageModelName.AZURE_GPT_6_ASTRA_2026_0903,
|
|
531
|
+
LanguageModelName.AZURE_GPT_6_LUNA_2026_0922,
|
|
532
|
+
LanguageModelName.AZURE_GPT_6_SOL_2026_0922,
|
|
531
533
|
LanguageModelName.LITELLM_OPENAI_GPT_55,
|
|
532
534
|
LanguageModelName.LITELLM_OPENAI_GPT_55_PRO,
|
|
533
535
|
LanguageModelName.LITELLM_OPENAI_GPT_56_SOL,
|
|
534
536
|
LanguageModelName.LITELLM_OPENAI_GPT_56_TERRA,
|
|
535
537
|
LanguageModelName.LITELLM_OPENAI_GPT_56_LUNA,
|
|
536
538
|
LanguageModelName.LITELLM_OPENAI_GPT_6_ASTRA,
|
|
539
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_LUNA,
|
|
540
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_SOL,
|
|
537
541
|
}
|
|
538
542
|
)
|
|
539
543
|
|
|
@@ -16,10 +16,12 @@ from unique_toolkit.agentic.loop_runner import (
|
|
|
16
16
|
MistralLoopIterationRunner,
|
|
17
17
|
PlanningConfig,
|
|
18
18
|
PlanningMiddleware,
|
|
19
|
+
PromptForcedToolLoopIterationRunner,
|
|
19
20
|
QwenLoopIterationRunner,
|
|
20
21
|
ResponsesBasicLoopIterationRunner,
|
|
21
22
|
ResponsesPlanningMiddleware,
|
|
22
23
|
)
|
|
24
|
+
from unique_toolkit.language_model.infos import LanguageModelInfo, LanguageModelName
|
|
23
25
|
|
|
24
26
|
from unique_orchestrator._builders.loop_iteration_runner import (
|
|
25
27
|
build_loop_iteration_runner,
|
|
@@ -43,6 +45,7 @@ class TestGetModelFamily:
|
|
|
43
45
|
def testget_model_family__returns_none__for_other_models(self) -> None:
|
|
44
46
|
assert get_model_family("gpt-4o") is None
|
|
45
47
|
assert get_model_family("claude-3") is None
|
|
48
|
+
assert get_model_family("litellm:anthropic-claude-opus-5-5") is None
|
|
46
49
|
|
|
47
50
|
|
|
48
51
|
class TestBuildResponsesLoopIterationRunner:
|
|
@@ -518,7 +521,7 @@ class TestBuildLoopIterationRunnerModelFamilyIntegration:
|
|
|
518
521
|
self,
|
|
519
522
|
) -> None:
|
|
520
523
|
config: UniqueAIConfig = UniqueAIConfig()
|
|
521
|
-
config.space.language_model = "gpt-4o"
|
|
524
|
+
config.space.language_model = LanguageModelInfo(name="gpt-4o")
|
|
522
525
|
runner = build_loop_iteration_runner(
|
|
523
526
|
config=config,
|
|
524
527
|
history_manager=MagicMock(),
|
|
@@ -532,7 +535,7 @@ class TestBuildLoopIterationRunnerModelFamilyIntegration:
|
|
|
532
535
|
self,
|
|
533
536
|
) -> None:
|
|
534
537
|
config: UniqueAIConfig = UniqueAIConfig()
|
|
535
|
-
config.space.language_model = "mistral-large"
|
|
538
|
+
config.space.language_model = LanguageModelInfo(name="mistral-large")
|
|
536
539
|
runner = build_loop_iteration_runner(
|
|
537
540
|
config=config,
|
|
538
541
|
history_manager=MagicMock(),
|
|
@@ -546,7 +549,7 @@ class TestBuildLoopIterationRunnerModelFamilyIntegration:
|
|
|
546
549
|
self,
|
|
547
550
|
) -> None:
|
|
548
551
|
config: UniqueAIConfig = UniqueAIConfig()
|
|
549
|
-
config.space.language_model = "litellm/qwen3"
|
|
552
|
+
config.space.language_model = LanguageModelInfo(name="litellm/qwen3")
|
|
550
553
|
runner = build_loop_iteration_runner(
|
|
551
554
|
config=config,
|
|
552
555
|
history_manager=MagicMock(),
|
|
@@ -554,3 +557,68 @@ class TestBuildLoopIterationRunnerModelFamilyIntegration:
|
|
|
554
557
|
llm_service=MagicMock(),
|
|
555
558
|
)
|
|
556
559
|
assert isinstance(runner, QwenLoopIterationRunner)
|
|
560
|
+
|
|
561
|
+
@pytest.mark.ai
|
|
562
|
+
def test_build_loop_iteration_runner__returns_prompt_forced_tool_runner__for_opus_55(
|
|
563
|
+
self,
|
|
564
|
+
) -> None:
|
|
565
|
+
"""
|
|
566
|
+
Purpose: Verify Opus 5.5 model info builds the prompt-forced-tool runner.
|
|
567
|
+
Why this matters: Forced tool calls on that model must not send a named choice.
|
|
568
|
+
Setup summary: Use the Opus 5.5 LanguageModelInfo and build the runner.
|
|
569
|
+
"""
|
|
570
|
+
config: UniqueAIConfig = UniqueAIConfig()
|
|
571
|
+
config.space.language_model = LanguageModelInfo.from_name(
|
|
572
|
+
LanguageModelName.ANTHROPIC_CLAUDE_OPUS_5_5
|
|
573
|
+
)
|
|
574
|
+
assert config.space.language_model.supports_forced_tool_choice is False
|
|
575
|
+
runner = build_loop_iteration_runner(
|
|
576
|
+
config=config,
|
|
577
|
+
history_manager=MagicMock(),
|
|
578
|
+
chat_service=MagicMock(),
|
|
579
|
+
llm_service=MagicMock(),
|
|
580
|
+
)
|
|
581
|
+
assert isinstance(runner, PromptForcedToolLoopIterationRunner)
|
|
582
|
+
assert runner._config.max_loop_iterations == config.agent.max_loop_iterations
|
|
583
|
+
|
|
584
|
+
@pytest.mark.ai
|
|
585
|
+
def test_build_loop_iteration_runner__returns_basic_runner__for_opus_5(
|
|
586
|
+
self,
|
|
587
|
+
) -> None:
|
|
588
|
+
"""
|
|
589
|
+
Purpose: Verify Opus 5 keeps the basic runner with a named tool_choice.
|
|
590
|
+
Why this matters: Only models flagged in LanguageModelInfo lose forced tools.
|
|
591
|
+
Setup summary: Use the Opus 5 LanguageModelInfo and build the runner.
|
|
592
|
+
"""
|
|
593
|
+
config: UniqueAIConfig = UniqueAIConfig()
|
|
594
|
+
config.space.language_model = LanguageModelInfo.from_name(
|
|
595
|
+
LanguageModelName.ANTHROPIC_CLAUDE_OPUS_5
|
|
596
|
+
)
|
|
597
|
+
runner = build_loop_iteration_runner(
|
|
598
|
+
config=config,
|
|
599
|
+
history_manager=MagicMock(),
|
|
600
|
+
chat_service=MagicMock(),
|
|
601
|
+
llm_service=MagicMock(),
|
|
602
|
+
)
|
|
603
|
+
assert type(runner) is BasicLoopIterationRunner
|
|
604
|
+
|
|
605
|
+
@pytest.mark.ai
|
|
606
|
+
def test_build_loop_iteration_runner__prefers_prompt_forced_tool__over_family_runner(
|
|
607
|
+
self,
|
|
608
|
+
) -> None:
|
|
609
|
+
"""
|
|
610
|
+
Purpose: Verify the forced-tool flag wins over the Mistral family runner.
|
|
611
|
+
Why this matters: Mistral sends tool_choice any, which such a model rejects.
|
|
612
|
+
Setup summary: Flag a Mistral-named model info and build the runner.
|
|
613
|
+
"""
|
|
614
|
+
config: UniqueAIConfig = UniqueAIConfig()
|
|
615
|
+
config.space.language_model = LanguageModelInfo(
|
|
616
|
+
name="mistral-large", supports_forced_tool_choice=False
|
|
617
|
+
)
|
|
618
|
+
runner = build_loop_iteration_runner(
|
|
619
|
+
config=config,
|
|
620
|
+
history_manager=MagicMock(),
|
|
621
|
+
chat_service=MagicMock(),
|
|
622
|
+
llm_service=MagicMock(),
|
|
623
|
+
)
|
|
624
|
+
assert isinstance(runner, PromptForcedToolLoopIterationRunner)
|
|
@@ -311,12 +311,16 @@ class TestUniqueAIConfigGptFrontierModelsResponsesApiValidator:
|
|
|
311
311
|
LanguageModelName.AZURE_GPT_56_TERRA_2026_0709,
|
|
312
312
|
LanguageModelName.AZURE_GPT_56_LUNA_2026_0709,
|
|
313
313
|
LanguageModelName.AZURE_GPT_6_ASTRA_2026_0903,
|
|
314
|
+
LanguageModelName.AZURE_GPT_6_LUNA_2026_0922,
|
|
315
|
+
LanguageModelName.AZURE_GPT_6_SOL_2026_0922,
|
|
314
316
|
LanguageModelName.LITELLM_OPENAI_GPT_55,
|
|
315
317
|
LanguageModelName.LITELLM_OPENAI_GPT_55_PRO,
|
|
316
318
|
LanguageModelName.LITELLM_OPENAI_GPT_56_SOL,
|
|
317
319
|
LanguageModelName.LITELLM_OPENAI_GPT_56_TERRA,
|
|
318
320
|
LanguageModelName.LITELLM_OPENAI_GPT_56_LUNA,
|
|
319
321
|
LanguageModelName.LITELLM_OPENAI_GPT_6_ASTRA,
|
|
322
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_LUNA,
|
|
323
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_SOL,
|
|
320
324
|
],
|
|
321
325
|
)
|
|
322
326
|
def test_enables_responses_api_for_affected_models(
|
|
@@ -340,12 +344,16 @@ class TestUniqueAIConfigGptFrontierModelsResponsesApiValidator:
|
|
|
340
344
|
LanguageModelName.AZURE_GPT_56_TERRA_2026_0709,
|
|
341
345
|
LanguageModelName.AZURE_GPT_56_LUNA_2026_0709,
|
|
342
346
|
LanguageModelName.AZURE_GPT_6_ASTRA_2026_0903,
|
|
347
|
+
LanguageModelName.AZURE_GPT_6_LUNA_2026_0922,
|
|
348
|
+
LanguageModelName.AZURE_GPT_6_SOL_2026_0922,
|
|
343
349
|
LanguageModelName.LITELLM_OPENAI_GPT_55,
|
|
344
350
|
LanguageModelName.LITELLM_OPENAI_GPT_55_PRO,
|
|
345
351
|
LanguageModelName.LITELLM_OPENAI_GPT_56_SOL,
|
|
346
352
|
LanguageModelName.LITELLM_OPENAI_GPT_56_TERRA,
|
|
347
353
|
LanguageModelName.LITELLM_OPENAI_GPT_56_LUNA,
|
|
348
354
|
LanguageModelName.LITELLM_OPENAI_GPT_6_ASTRA,
|
|
355
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_LUNA,
|
|
356
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_SOL,
|
|
349
357
|
],
|
|
350
358
|
)
|
|
351
359
|
def test_enables_responses_api_for_affected_models_with_tools(
|
|
@@ -378,12 +386,16 @@ class TestUniqueAIConfigGptFrontierModelsResponsesApiValidator:
|
|
|
378
386
|
LanguageModelName.AZURE_GPT_56_TERRA_2026_0709,
|
|
379
387
|
LanguageModelName.AZURE_GPT_56_LUNA_2026_0709,
|
|
380
388
|
LanguageModelName.AZURE_GPT_6_ASTRA_2026_0903,
|
|
389
|
+
LanguageModelName.AZURE_GPT_6_LUNA_2026_0922,
|
|
390
|
+
LanguageModelName.AZURE_GPT_6_SOL_2026_0922,
|
|
381
391
|
LanguageModelName.LITELLM_OPENAI_GPT_55,
|
|
382
392
|
LanguageModelName.LITELLM_OPENAI_GPT_55_PRO,
|
|
383
393
|
LanguageModelName.LITELLM_OPENAI_GPT_56_SOL,
|
|
384
394
|
LanguageModelName.LITELLM_OPENAI_GPT_56_TERRA,
|
|
385
395
|
LanguageModelName.LITELLM_OPENAI_GPT_56_LUNA,
|
|
386
396
|
LanguageModelName.LITELLM_OPENAI_GPT_6_ASTRA,
|
|
397
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_LUNA,
|
|
398
|
+
LanguageModelName.LITELLM_OPENAI_GPT_6_SOL,
|
|
387
399
|
],
|
|
388
400
|
)
|
|
389
401
|
def test_keeps_responses_api_enabled_when_already_enabled(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|