unique_orchestrator 2026.20.0.dev7__tar.gz → 2026.20.0.dev8__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.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/PKG-INFO +3 -3
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/pyproject.toml +3 -3
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/_builders/skill_setup.py +49 -17
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/config.py +0 -5
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/unique_ai.py +8 -9
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/README.md +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/__init__.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/_builders/__init__.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/_builders/inject_tool_reminders.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/_builders/loop_iteration_runner.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/_builders/open_file_setup.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/prompts/generic_reference_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/prompts/system_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/prompts/user_message_prompt.jinja2 +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_build_loop_iteration_runner.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_config_services_validators.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_qwen_max_loop_iterations.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_register_code_interpreter_postprocessors.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_async_modify.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_builder_selected_uploaded_files.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_builder_uploaded_search.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_execution_timing.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_get_filtered_user_metadata.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_log_tool_calls.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_persist_tool_calls.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_plan_or_execute_include.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_reference_order.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_render_system_prompt_user_instructions.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/tests/test_unique_ai_selected_uploaded_files.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/unique_ai_builder.py +0 -0
- {unique_orchestrator-2026.20.0.dev7 → unique_orchestrator-2026.20.0.dev8}/unique_orchestrator/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-orchestrator
|
|
3
|
-
Version: 2026.20.0.
|
|
3
|
+
Version: 2026.20.0.dev8
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Andreas Hauri
|
|
6
6
|
Author-email: Andreas Hauri <andreas.hauri@unique.ai>
|
|
@@ -8,14 +8,14 @@ License: Proprietary
|
|
|
8
8
|
Requires-Dist: pydantic>=2.8.2,<3
|
|
9
9
|
Requires-Dist: typing-extensions>=4.9.0,<5
|
|
10
10
|
Requires-Dist: jinja2>=3.1.0,<4
|
|
11
|
-
Requires-Dist: unique-toolkit>=2026.20.0.
|
|
11
|
+
Requires-Dist: unique-toolkit>=2026.20.0.dev12
|
|
12
12
|
Requires-Dist: unique-stock-ticker>=2026.20.0.dev6
|
|
13
13
|
Requires-Dist: unique-follow-up-questions>=2026.20.0.dev6
|
|
14
14
|
Requires-Dist: unique-internal-search>=2026.20.0.dev6
|
|
15
15
|
Requires-Dist: unique-deep-research>=2026.20.0.dev6
|
|
16
16
|
Requires-Dist: unique-web-search>=2026.20.0.dev7
|
|
17
17
|
Requires-Dist: unique-swot>=2026.20.0.dev7
|
|
18
|
-
Requires-Dist: unique-skill-tool>=2026.20.0.
|
|
18
|
+
Requires-Dist: unique-skill-tool>=2026.20.0.dev7
|
|
19
19
|
Requires-Dist: openai>=1.109.1,<3
|
|
20
20
|
Requires-Dist: python-frontmatter>=1.1.0,<2
|
|
21
21
|
Requires-Python: >=3.12, <4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "unique_orchestrator"
|
|
3
|
-
version = "2026.20.0.
|
|
3
|
+
version = "2026.20.0.dev8"
|
|
4
4
|
description = ""
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "Proprietary" }
|
|
@@ -12,14 +12,14 @@ dependencies = [
|
|
|
12
12
|
"pydantic>=2.8.2,<3",
|
|
13
13
|
"typing-extensions>=4.9.0,<5",
|
|
14
14
|
"jinja2>=3.1.0,<4",
|
|
15
|
-
"unique-toolkit>=2026.20.0.
|
|
15
|
+
"unique-toolkit>=2026.20.0.dev12",
|
|
16
16
|
"unique-stock-ticker>=2026.20.0.dev6",
|
|
17
17
|
"unique-follow-up-questions>=2026.20.0.dev6",
|
|
18
18
|
"unique-internal-search>=2026.20.0.dev6",
|
|
19
19
|
"unique-deep-research>=2026.20.0.dev6",
|
|
20
20
|
"unique-web-search>=2026.20.0.dev7",
|
|
21
21
|
"unique-swot>=2026.20.0.dev7",
|
|
22
|
-
"unique-skill-tool>=2026.20.0.
|
|
22
|
+
"unique-skill-tool>=2026.20.0.dev7",
|
|
23
23
|
"openai>=1.109.1,<3",
|
|
24
24
|
"python-frontmatter>=1.1.0,<2",
|
|
25
25
|
]
|
|
@@ -40,13 +40,15 @@ from __future__ import annotations
|
|
|
40
40
|
|
|
41
41
|
import asyncio
|
|
42
42
|
from logging import Logger
|
|
43
|
-
from typing import TYPE_CHECKING, Any
|
|
43
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
44
44
|
|
|
45
45
|
import frontmatter
|
|
46
46
|
from pydantic import ValidationError
|
|
47
|
+
from unique_skill_tool.config import SkillToolConfig
|
|
47
48
|
from unique_skill_tool.schemas import SkillDefinition
|
|
48
49
|
from unique_skill_tool.service import SkillTool
|
|
49
50
|
from unique_skill_tool.utils import extract_prefix_skills
|
|
51
|
+
from unique_toolkit.agentic.tools.config import ToolBuildConfig
|
|
50
52
|
from unique_toolkit.agentic.tools.schemas import ToolCallResponse
|
|
51
53
|
from unique_toolkit.content.schemas import Content, ContentInfo
|
|
52
54
|
from unique_toolkit.content.smart_rules import (
|
|
@@ -70,6 +72,16 @@ if TYPE_CHECKING:
|
|
|
70
72
|
from unique_orchestrator.config import UniqueAIConfig
|
|
71
73
|
|
|
72
74
|
|
|
75
|
+
def _find_skill_tool_build_config(
|
|
76
|
+
tools: list[ToolBuildConfig],
|
|
77
|
+
) -> ToolBuildConfig | None:
|
|
78
|
+
"""Return the SkillTool entry from ``space.tools`` if present."""
|
|
79
|
+
for tool in tools:
|
|
80
|
+
if tool.name == SkillTool.name:
|
|
81
|
+
return tool
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
|
|
73
85
|
_SUBTREE_PAGE_SIZE = 100
|
|
74
86
|
_MAX_SUBTREE_ITEMS = 10_000
|
|
75
87
|
|
|
@@ -294,21 +306,39 @@ async def configure_skill_tool(
|
|
|
294
306
|
content_service: ContentService,
|
|
295
307
|
tool_manager: ToolManager | ResponsesApiToolManager,
|
|
296
308
|
) -> None:
|
|
297
|
-
"""
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
309
|
+
"""Populate the SkillTool's skill registry when it is enabled in ``space.tools``.
|
|
310
|
+
|
|
311
|
+
The SkillTool is integrated like every other tool: it lives as a
|
|
312
|
+
``ToolBuildConfig`` entry in ``config.space.tools`` and is built by
|
|
313
|
+
:class:`ToolFactory` when the :class:`ToolManager` is constructed.
|
|
314
|
+
This function only handles the runtime concern of loading the skill
|
|
315
|
+
definitions from the knowledge base and injecting them into the
|
|
316
|
+
already-constructed tool instance.
|
|
317
|
+
|
|
318
|
+
The tool is treated as "active" only when both:
|
|
319
|
+
|
|
320
|
+
* an entry with name ``SkillTool.name`` is present in
|
|
321
|
+
``config.space.tools`` and its
|
|
322
|
+
:attr:`~ToolBuildConfig.is_enabled` flag is ``True``, **and**
|
|
323
|
+
* the resulting skill registry contains at least one skill.
|
|
324
|
+
|
|
325
|
+
When either is not the case the SkillTool is excluded from the
|
|
326
|
+
manager so it is never advertised to the model. Its system prompt
|
|
327
|
+
claims HIGHEST PRIORITY and would otherwise waste iterations or
|
|
328
|
+
provoke hallucinated skill names when no skills exist.
|
|
302
329
|
"""
|
|
303
|
-
|
|
304
|
-
if not
|
|
330
|
+
skill_tool_build_config = _find_skill_tool_build_config(config.space.tools)
|
|
331
|
+
if skill_tool_build_config is None or not skill_tool_build_config.is_enabled:
|
|
305
332
|
return
|
|
306
333
|
|
|
334
|
+
skill_config = cast(SkillToolConfig, skill_tool_build_config.configuration)
|
|
335
|
+
|
|
307
336
|
if not skill_config.scope_ids:
|
|
308
337
|
logger.warning(
|
|
309
338
|
"SkillTool is enabled but no scope_ids are configured — "
|
|
310
339
|
"no skills will be loaded."
|
|
311
340
|
)
|
|
341
|
+
tool_manager.exclude_tool(SkillTool.name)
|
|
312
342
|
return
|
|
313
343
|
|
|
314
344
|
knowledge_base_service = KnowledgeBaseService(
|
|
@@ -324,18 +354,20 @@ async def configure_skill_tool(
|
|
|
324
354
|
)
|
|
325
355
|
|
|
326
356
|
if not skill_registry:
|
|
327
|
-
logger.info(
|
|
328
|
-
|
|
329
|
-
)
|
|
357
|
+
logger.info("SkillTool has an empty skill registry — tool will be excluded.")
|
|
358
|
+
tool_manager.exclude_tool(SkillTool.name)
|
|
330
359
|
return
|
|
331
360
|
|
|
332
|
-
tool_manager.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
361
|
+
skill_tool = tool_manager.get_tool_by_name(SkillTool.name)
|
|
362
|
+
if not isinstance(skill_tool, SkillTool):
|
|
363
|
+
logger.warning(
|
|
364
|
+
"SkillTool is configured in space.tools but the manager did "
|
|
365
|
+
"not produce a SkillTool instance — skills will not be "
|
|
366
|
+
"available."
|
|
337
367
|
)
|
|
338
|
-
|
|
368
|
+
return
|
|
369
|
+
|
|
370
|
+
skill_tool.skill_registry = skill_registry
|
|
339
371
|
|
|
340
372
|
|
|
341
373
|
async def preload_invoked_skills(
|
|
@@ -9,9 +9,6 @@ from unique_deep_research.service import DeepResearchTool
|
|
|
9
9
|
from unique_follow_up_questions.config import FollowUpQuestionsConfig
|
|
10
10
|
from unique_internal_search.config import InternalSearchConfig
|
|
11
11
|
from unique_internal_search.service import InternalSearchTool
|
|
12
|
-
from unique_skill_tool.config import (
|
|
13
|
-
SkillToolConfig,
|
|
14
|
-
)
|
|
15
12
|
from unique_stock_ticker.config import StockTickerConfig
|
|
16
13
|
from unique_swot import SwotAnalysisTool, SwotAnalysisToolConfig
|
|
17
14
|
from unique_toolkit._common.validators import (
|
|
@@ -351,8 +348,6 @@ class ExperimentalConfig(BaseToolConfig):
|
|
|
351
348
|
|
|
352
349
|
open_file_tool_config: OpenFileToolConfig = OpenFileToolConfig()
|
|
353
350
|
|
|
354
|
-
skill_tool_config: SkillToolConfig = SkillToolConfig()
|
|
355
|
-
|
|
356
351
|
use_responses_api: bool = Field(
|
|
357
352
|
default=False,
|
|
358
353
|
description="If set, the main agent will use the Responses API from OpenAI",
|
|
@@ -214,15 +214,14 @@ class UniqueAI:
|
|
|
214
214
|
self._execution_times = []
|
|
215
215
|
run_start = time.perf_counter()
|
|
216
216
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
self._event.payload.user_message.text = stripped_text
|
|
217
|
+
stripped_text = await preload_invoked_skills(
|
|
218
|
+
event=self._event,
|
|
219
|
+
tool_manager=self._tool_manager,
|
|
220
|
+
history_manager=self._history_manager,
|
|
221
|
+
logger=self._logger,
|
|
222
|
+
)
|
|
223
|
+
if stripped_text is not None:
|
|
224
|
+
self._event.payload.user_message.text = stripped_text
|
|
226
225
|
|
|
227
226
|
sub = self._chat_service.cancellation.on_cancellation.subscribe(
|
|
228
227
|
self._on_cancellation
|
|
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
|