unique_orchestrator 2026.32.0.dev2__tar.gz → 2026.32.0.dev4__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 (34) hide show
  1. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/PKG-INFO +5 -5
  2. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/pyproject.toml +5 -5
  3. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/prompts/system_prompt.jinja2 +4 -1
  4. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/unique_ai_builder.py +41 -9
  5. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/README.md +0 -0
  6. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/__init__.py +0 -0
  7. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/__init__.py +0 -0
  8. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/history_manager.py +0 -0
  9. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/inject_tool_reminders.py +0 -0
  10. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/loop_iteration_runner.py +0 -0
  11. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/open_file_setup.py +0 -0
  12. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/_builders/skill_setup.py +0 -0
  13. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/config.py +0 -0
  14. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/prompts/generic_reference_prompt.jinja2 +0 -0
  15. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/prompts/user_message_prompt.jinja2 +0 -0
  16. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/settings.py +0 -0
  17. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_agent_config_rjsf_ui_schema.py +0 -0
  18. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_build_loop_iteration_runner.py +0 -0
  19. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_config_services_validators.py +0 -0
  20. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_qwen_max_loop_iterations.py +0 -0
  21. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_register_code_interpreter_postprocessors.py +0 -0
  22. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_async_modify.py +0 -0
  23. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_execution_timing.py +0 -0
  24. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_get_filtered_user_metadata.py +0 -0
  25. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_log_tool_calls.py +0 -0
  26. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_loop_debug_params.py +0 -0
  27. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_persist_tool_calls.py +0 -0
  28. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_plan_or_execute_include.py +0 -0
  29. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_reference_order.py +0 -0
  30. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_render_system_prompt_user_instructions.py +0 -0
  31. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_unique_ai_token_usage.py +0 -0
  32. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/tests/test_utils_resolve_other_options.py +0 -0
  33. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/unique_ai.py +0 -0
  34. {unique_orchestrator-2026.32.0.dev2 → unique_orchestrator-2026.32.0.dev4}/unique_orchestrator/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-orchestrator
3
- Version: 2026.32.0.dev2
3
+ Version: 2026.32.0.dev4
4
4
  Summary:
5
5
  Author: Andreas Hauri
6
6
  Author-email: Andreas Hauri <andreas.hauri@unique.ai>
@@ -9,15 +9,15 @@ 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.32.0.dev6,<2026.32.0rc0
12
+ Requires-Dist: unique-toolkit>=2026.32.0.dev8,<2026.32.0rc0
13
13
  Requires-Dist: unique-stock-ticker>=2026.32.0.dev1,<2026.32.0rc0
14
- Requires-Dist: unique-follow-up-questions>=2026.32.0.dev0,<2026.32.0rc0
15
- Requires-Dist: unique-internal-search>=2026.32.0.dev1,<2026.32.0rc0
14
+ Requires-Dist: unique-follow-up-questions>=2026.32.0.dev1,<2026.32.0rc0
15
+ Requires-Dist: unique-internal-search>=2026.32.0.dev2,<2026.32.0rc0
16
16
  Requires-Dist: unique-deep-research>=2026.32.0.dev1,<2026.32.0rc0
17
17
  Requires-Dist: unique-web-search>=2026.32.0.dev2,<2026.32.0rc0
18
18
  Requires-Dist: unique-swot>=2026.32.0.dev0,<2026.32.0rc0
19
19
  Requires-Dist: unique-skill-tool>=2026.32.0.dev0,<2026.32.0rc0
20
- Requires-Dist: unique-user-memory>=2026.32.0.dev2,<2026.32.0rc0
20
+ Requires-Dist: unique-user-memory>=2026.32.0.dev4,<2026.32.0rc0
21
21
  Requires-Dist: openai>=1.109.1,<3
22
22
  Requires-Python: >=3.12, <4
23
23
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_orchestrator"
3
- version = "2026.32.0.dev2"
3
+ version = "2026.32.0.dev4"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  license = { text = "Proprietary" }
@@ -13,15 +13,15 @@ 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.32.0.dev6,<2026.32.0rc0",
16
+ "unique-toolkit>=2026.32.0.dev8,<2026.32.0rc0",
17
17
  "unique-stock-ticker>=2026.32.0.dev1,<2026.32.0rc0",
18
- "unique-follow-up-questions>=2026.32.0.dev0,<2026.32.0rc0",
19
- "unique-internal-search>=2026.32.0.dev1,<2026.32.0rc0",
18
+ "unique-follow-up-questions>=2026.32.0.dev1,<2026.32.0rc0",
19
+ "unique-internal-search>=2026.32.0.dev2,<2026.32.0rc0",
20
20
  "unique-deep-research>=2026.32.0.dev1,<2026.32.0rc0",
21
21
  "unique-web-search>=2026.32.0.dev2,<2026.32.0rc0",
22
22
  "unique-swot>=2026.32.0.dev0,<2026.32.0rc0",
23
23
  "unique-skill-tool>=2026.32.0.dev0,<2026.32.0rc0",
24
- "unique-user-memory>=2026.32.0.dev2,<2026.32.0rc0",
24
+ "unique-user-memory>=2026.32.0.dev4,<2026.32.0rc0",
25
25
  "openai>=1.109.1,<3",
26
26
  ]
27
27
 
@@ -30,7 +30,10 @@ Here is some metadata about the user, which may help you write better queries, a
30
30
  # What I know about you
31
31
  The following profile was distilled from past conversations with this user. Treat it as durable user context: adapt your tone, examples, and depth to it. If the user asks what you know or remember about them, you may share this memory back to them, including verbatim if they request it. Do not treat it as authoritative for facts about the world.
32
32
 
33
- You can read this memory while answering. Memory updates happen only in a postprocessing step after your final answer, so do not claim that you can directly edit the memory during the main response.
33
+ The memory is maintained for you: an automatic postprocessing step re-reads every turn after your final answer and updates the profile on its own. You can read the memory while answering, but you cannot add to, edit, or delete it during your response, and nothing the user says changes whether the update runs. Therefore:
34
+ - Never ask the user whether something should be remembered, saved, or added to their profile.
35
+ - Never offer to update the memory, and never state that you have updated it, are updating it, or will update it.
36
+ - When the user shares a new fact about themselves, or asks you to remember or forget something, acknowledge it in one short clause and continue with their actual request.
34
37
 
35
38
  {{ user_memory }}
36
39
  {%- endif %}
@@ -69,7 +69,8 @@ from unique_toolkit.experimental.integrations.openai.streaming.event_routing imp
69
69
  )
70
70
  from unique_toolkit.language_model.infos import LanguageModelInfo, ModelCapabilities
71
71
  from unique_toolkit.protocols.support import ResponsesSupportCompleteWithReferences
72
- from unique_user_memory.user_memory import load_user_memory
72
+ from unique_user_memory.user_memory import load_user_memory, profile_body
73
+ from unique_user_memory.user_memory_message_log import UserMemoryMessageLogger
73
74
  from unique_user_memory.user_memory_postprocessor import UserMemoryPostprocessor
74
75
 
75
76
  from unique_orchestrator._builders import (
@@ -298,6 +299,7 @@ async def _build_common(
298
299
  config: UniqueAIConfig,
299
300
  ) -> _CommonComponents:
300
301
  chat_service = ChatService(event)
302
+ message_step_logger = MessageStepLogger(chat_service)
301
303
 
302
304
  llm_service = LanguageModelService.from_event(event)
303
305
 
@@ -393,14 +395,40 @@ async def _build_common(
393
395
  if user_memory_config.use_orchestrator_language_model
394
396
  else user_memory_config.language_model
395
397
  )
396
- user_memory_state = await load_user_memory(
397
- event=event,
398
- config=user_memory_config,
399
- language_model=memory_language_model,
398
+ memory_message_step_logger = UserMemoryMessageLogger(
399
+ message_step_logger,
400
400
  logger=logger,
401
401
  )
402
- if user_memory_state is not None:
403
- user_memory_text = user_memory_state.text
402
+ await memory_message_step_logger.log_loading_start()
403
+ user_memory_state = None
404
+ load_succeeded = False
405
+ try:
406
+ user_memory_state = await load_user_memory(
407
+ event=event,
408
+ config=user_memory_config,
409
+ language_model=memory_language_model,
410
+ logger=logger,
411
+ )
412
+ load_succeeded = True
413
+ except Exception as exc:
414
+ # Soft-fail like a None return: keep the turn running without
415
+ # memory, but always close the RUNNING loading Step first.
416
+ logger.warning(
417
+ "[user-memory] load raised - running without memory: [%s] %s",
418
+ type(exc).__name__,
419
+ exc,
420
+ )
421
+ finally:
422
+ if not load_succeeded:
423
+ await memory_message_step_logger.log_loading_failed()
424
+
425
+ if load_succeeded and user_memory_state is not None:
426
+ await memory_message_step_logger.log_loading_complete(
427
+ with_settings_entry=True
428
+ )
429
+ # The postprocessor keeps the full file (it needs the frontmatter to
430
+ # carry turn_count forward); the prompt only gets the Markdown body.
431
+ user_memory_text = profile_body(user_memory_state.text)
404
432
  postprocessor_manager.add_postprocessor(
405
433
  UserMemoryPostprocessor(
406
434
  config=user_memory_config,
@@ -408,9 +436,13 @@ async def _build_common(
408
436
  event=event,
409
437
  state=user_memory_state,
410
438
  logger=logger,
411
- chat_service=chat_service,
439
+ message_step_logger=memory_message_step_logger,
412
440
  )
413
441
  )
442
+ elif load_succeeded:
443
+ await memory_message_step_logger.log_loading_complete(
444
+ with_settings_entry=False
445
+ )
414
446
 
415
447
  return _CommonComponents(
416
448
  chat_service=chat_service,
@@ -429,7 +461,7 @@ async def _build_common(
429
461
  user_memory_text=user_memory_text,
430
462
  postprocessor_manager=postprocessor_manager,
431
463
  response_watcher=response_watcher,
432
- message_step_logger=MessageStepLogger(chat_service),
464
+ message_step_logger=message_step_logger,
433
465
  )
434
466
 
435
467