unique_orchestrator 2026.22.0.dev4__tar.gz → 2026.22.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.
Files changed (29) hide show
  1. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/PKG-INFO +2 -2
  2. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/pyproject.toml +2 -2
  3. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/_builders/skill_setup.py +12 -7
  4. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/README.md +0 -0
  5. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/__init__.py +0 -0
  6. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/_builders/__init__.py +0 -0
  7. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/_builders/inject_tool_reminders.py +0 -0
  8. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/_builders/loop_iteration_runner.py +0 -0
  9. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/_builders/open_file_setup.py +0 -0
  10. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/config.py +0 -0
  11. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/prompts/generic_reference_prompt.jinja2 +0 -0
  12. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/prompts/system_prompt.jinja2 +0 -0
  13. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/prompts/user_message_prompt.jinja2 +0 -0
  14. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/settings.py +0 -0
  15. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_build_loop_iteration_runner.py +0 -0
  16. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_config_services_validators.py +0 -0
  17. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_qwen_max_loop_iterations.py +0 -0
  18. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_register_code_interpreter_postprocessors.py +0 -0
  19. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_async_modify.py +0 -0
  20. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_execution_timing.py +0 -0
  21. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_get_filtered_user_metadata.py +0 -0
  22. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_log_tool_calls.py +0 -0
  23. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_persist_tool_calls.py +0 -0
  24. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_plan_or_execute_include.py +0 -0
  25. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_reference_order.py +0 -0
  26. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/tests/test_unique_ai_render_system_prompt_user_instructions.py +0 -0
  27. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/unique_ai.py +0 -0
  28. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.0.dev5}/unique_orchestrator/unique_ai_builder.py +0 -0
  29. {unique_orchestrator-2026.22.0.dev4 → unique_orchestrator-2026.22.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.22.0.dev4
3
+ Version: 2026.22.0.dev5
4
4
  Summary:
5
5
  Author: Andreas Hauri
6
6
  Author-email: Andreas Hauri <andreas.hauri@unique.ai>
@@ -16,7 +16,7 @@ Requires-Dist: unique-internal-search>=2026.22.0.dev2,<2026.22.0rc0
16
16
  Requires-Dist: unique-deep-research>=2026.22.0.dev2,<2026.22.0rc0
17
17
  Requires-Dist: unique-web-search>=2026.22.0.dev4,<2026.22.0rc0
18
18
  Requires-Dist: unique-swot>=2026.22.0.dev2,<2026.22.0rc0
19
- Requires-Dist: unique-skill-tool>=2026.22.0.dev3,<2026.22.0rc0
19
+ Requires-Dist: unique-skill-tool>=2026.22.0.dev4,<2026.22.0rc0
20
20
  Requires-Dist: openai>=1.109.1,<3
21
21
  Requires-Dist: python-frontmatter>=1.1.0,<2
22
22
  Requires-Python: >=3.12, <4
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_orchestrator"
3
- version = "2026.22.0.dev4"
3
+ version = "2026.22.0.dev5"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  license = { text = "Proprietary" }
@@ -20,7 +20,7 @@ dependencies = [
20
20
  "unique-deep-research>=2026.22.0.dev2,<2026.22.0rc0",
21
21
  "unique-web-search>=2026.22.0.dev4,<2026.22.0rc0",
22
22
  "unique-swot>=2026.22.0.dev2,<2026.22.0rc0",
23
- "unique-skill-tool>=2026.22.0.dev3,<2026.22.0rc0",
23
+ "unique-skill-tool>=2026.22.0.dev4,<2026.22.0rc0",
24
24
  "openai>=1.109.1,<3",
25
25
  "python-frontmatter>=1.1.0,<2",
26
26
  ]
@@ -50,7 +50,6 @@ from pydantic import ValidationError
50
50
  from unique_skill_tool.config import SkillToolConfig
51
51
  from unique_skill_tool.schemas import SkillDefinition
52
52
  from unique_skill_tool.service import SkillTool
53
- from unique_skill_tool.utils import normalize_skill_name
54
53
  from unique_toolkit.agentic.tools.config import ToolBuildConfig
55
54
  from unique_toolkit.agentic.tools.schemas import ToolCallResponse
56
55
  from unique_toolkit.app.schemas import SkillReference
@@ -140,8 +139,8 @@ def _build_skill(
140
139
  is rejected by ``SkillDefinition`` rather than silently flowing into
141
140
  the OpenAI tool enum where the model could never emit it verbatim.
142
141
 
143
- ``content_id`` and ``content_key`` are used only for log messages so
144
- operators can locate the offending file in the knowledge base.
142
+ ``content_id`` is stored on the returned definition so it can be used
143
+ as a lookup key to load the SKILL.md.
145
144
  """
146
145
  if not file_text.strip():
147
146
  return None
@@ -164,6 +163,7 @@ def _build_skill(
164
163
  name=name,
165
164
  description=description,
166
165
  content=body,
166
+ content_id=content_id,
167
167
  )
168
168
  except ValidationError as exc:
169
169
  logger.warning(
@@ -325,7 +325,8 @@ async def preload_invoked_skills(
325
325
  indistinguishable from skills the model activates itself:
326
326
 
327
327
  1. Resolves each ``skill_choices`` entry against the registered
328
- ``SkillTool`` registry (by normalized name or ``content_id``).
328
+ ``SkillTool`` registry by ``content_id``. Entries without a
329
+ ``content_id`` are skipped — every skill choice must carry one.
329
330
  2. For each matched skill, synthesizes a ``LanguageModelFunction``
330
331
  and runs it through the already-registered ``SkillTool`` — the
331
332
  exact same code path ``UniqueAI._handle_tool_calls`` uses.
@@ -340,13 +341,17 @@ async def preload_invoked_skills(
340
341
  if not isinstance(skill_tool, SkillTool):
341
342
  return
342
343
 
344
+ # content_id → skill.
345
+ content_id_index: dict[str, SkillDefinition] = {
346
+ s.content_id: s for s in skill_tool.skill_registry.values() if s.content_id
347
+ }
348
+
343
349
  forced_skills: list[SkillDefinition] = []
344
350
  seen_forced: set[str] = set()
345
351
  for choice in skill_choices:
346
352
  forced_skill: SkillDefinition | None = None
347
- if choice.name:
348
- normalized_name = normalize_skill_name(choice.name)
349
- forced_skill = skill_tool.skill_registry.get(normalized_name)
353
+ if choice.content_id:
354
+ forced_skill = content_id_index.get(choice.content_id)
350
355
  if forced_skill is None:
351
356
  continue
352
357
  if forced_skill.name in seen_forced: