kiarina-agi-runner 2.14.0__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 (57) hide show
  1. kiarina_agi_runner-2.14.0/.gitignore +35 -0
  2. kiarina_agi_runner-2.14.0/.mise/tasks/package/current +7 -0
  3. kiarina_agi_runner-2.14.0/.vscode/settings.json +9 -0
  4. kiarina_agi_runner-2.14.0/CHANGELOG.md +20 -0
  5. kiarina_agi_runner-2.14.0/Makefile +17 -0
  6. kiarina_agi_runner-2.14.0/PKG-INFO +60 -0
  7. kiarina_agi_runner-2.14.0/README.ja.md +24 -0
  8. kiarina_agi_runner-2.14.0/README.md +24 -0
  9. kiarina_agi_runner-2.14.0/pyproject.toml +48 -0
  10. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/__init__.py +35 -0
  11. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_exceptions/missing_tools_error.py +8 -0
  12. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_helpers/invoke_agent.py +43 -0
  13. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_helpers/run_agent.py +206 -0
  14. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_helpers/stream_agent.py +43 -0
  15. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_models/base_agent.py +239 -0
  16. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_schemas/agent_context.py +66 -0
  17. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_services/agent_registry.py +27 -0
  18. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_settings.py +30 -0
  19. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_types/agent.py +17 -0
  20. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_types/agent_name.py +3 -0
  21. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_types/agent_options.py +16 -0
  22. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent/_types/agent_specifier.py +12 -0
  23. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent_impl/vanilla/__init__.py +3 -0
  24. kiarina_agi_runner-2.14.0/src/kiarina/agi/agent_impl/vanilla/_models/vanilla_agent.py +5 -0
  25. kiarina_agi_runner-2.14.0/src/kiarina/agi/py.typed +0 -0
  26. kiarina_agi_runner-2.14.0/src/kiarina/agi/structured_output/__init__.py +9 -0
  27. kiarina_agi_runner-2.14.0/src/kiarina/agi/structured_output/_helpers/generate_dict.py +54 -0
  28. kiarina_agi_runner-2.14.0/src/kiarina/agi/structured_output/_helpers/generate_model.py +58 -0
  29. kiarina_agi_runner-2.14.0/src/kiarina/agi/structured_output/_helpers/select_option.py +64 -0
  30. kiarina_agi_runner-2.14.0/src/kiarina/agi/task_runner/__init__.py +9 -0
  31. kiarina_agi_runner-2.14.0/src/kiarina/agi/task_runner/_helpers/invoke_task.py +43 -0
  32. kiarina_agi_runner-2.14.0/src/kiarina/agi/task_runner/_helpers/run_task.py +73 -0
  33. kiarina_agi_runner-2.14.0/src/kiarina/agi/task_runner/_helpers/stream_task.py +43 -0
  34. kiarina_agi_runner-2.14.0/tests/.pytest-args +3 -0
  35. kiarina_agi_runner-2.14.0/tests/agent/__init__.py +0 -0
  36. kiarina_agi_runner-2.14.0/tests/agent/_helpers/__init__.py +0 -0
  37. kiarina_agi_runner-2.14.0/tests/agent/_helpers/test_invoke_agent.py +9 -0
  38. kiarina_agi_runner-2.14.0/tests/agent/_helpers/test_run_agent.py +259 -0
  39. kiarina_agi_runner-2.14.0/tests/agent/_helpers/test_stream_agent.py +8 -0
  40. kiarina_agi_runner-2.14.0/tests/agent/_models/__init__.py +0 -0
  41. kiarina_agi_runner-2.14.0/tests/agent/_models/test_base_agent.py +314 -0
  42. kiarina_agi_runner-2.14.0/tests/agent/_schemas/__init__.py +0 -0
  43. kiarina_agi_runner-2.14.0/tests/agent/_schemas/test_agent_context.py +11 -0
  44. kiarina_agi_runner-2.14.0/tests/agent_impl/__init__.py +0 -0
  45. kiarina_agi_runner-2.14.0/tests/agent_impl/vanilla/__init__.py +0 -0
  46. kiarina_agi_runner-2.14.0/tests/agent_impl/vanilla/_models/__init__.py +0 -0
  47. kiarina_agi_runner-2.14.0/tests/agent_impl/vanilla/_models/test_vanilla_agent.py +7 -0
  48. kiarina_agi_runner-2.14.0/tests/conftest.py +96 -0
  49. kiarina_agi_runner-2.14.0/tests/structured_output/__init__.py +0 -0
  50. kiarina_agi_runner-2.14.0/tests/structured_output/_helpers/test_generate_dict.py +30 -0
  51. kiarina_agi_runner-2.14.0/tests/structured_output/_helpers/test_generate_model.py +30 -0
  52. kiarina_agi_runner-2.14.0/tests/structured_output/_helpers/test_select_option.py +28 -0
  53. kiarina_agi_runner-2.14.0/tests/task_runner/__init__.py +0 -0
  54. kiarina_agi_runner-2.14.0/tests/task_runner/_helpers/__init__.py +0 -0
  55. kiarina_agi_runner-2.14.0/tests/task_runner/_helpers/test_invoke_task.py +10 -0
  56. kiarina_agi_runner-2.14.0/tests/task_runner/_helpers/test_run_task.py +15 -0
  57. kiarina_agi_runner-2.14.0/tests/task_runner/_helpers/test_stream_task.py +10 -0
@@ -0,0 +1,35 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ .pytest_cache/
11
+ .coverage
12
+ coverage.xml
13
+ htmlcov/
14
+
15
+ # uv
16
+ .uv_cache/
17
+
18
+ # Virtual environments & config
19
+ .venv/
20
+ .env
21
+
22
+ # OS
23
+ .DS_Store
24
+
25
+ # Project specific
26
+ *.log
27
+ tmp/
28
+ **/test_settings.yaml
29
+
30
+ # mise tasks (always include)
31
+ !.mise/tasks/
32
+ !.mise/tasks/**
33
+
34
+ # Test assets downloaded via mise
35
+ tests/assets/
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ #MISE description="Print the current package name"
3
+
4
+ set -euo pipefail
5
+
6
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ basename "$(dirname "$(dirname "$(dirname "$script_dir")")")"
@@ -0,0 +1,9 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests",
4
+ "-rs",
5
+ "-v"
6
+ ],
7
+ "python.testing.unittestEnabled": false,
8
+ "python.testing.pytestEnabled": true
9
+ }
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.14.0] - 2026-07-10
11
+
12
+ ### Added
13
+
14
+ - Add agent execution, task runner, and structured output helper APIs for AI agents.
15
+
16
+ ## [2.13.0] - 2026-07-10
17
+
18
+ ### Added
19
+
20
+ - Initial release.
@@ -0,0 +1,17 @@
1
+ .PHONY: format lint test build clean check
2
+ .DEFAULT_GOAL := check
3
+
4
+ format:
5
+ mise run format
6
+ lint:
7
+ mise run lint
8
+ test:
9
+ mise run test
10
+ build:
11
+ mise run build
12
+ clean:
13
+ mise run clean
14
+ check:
15
+ mise run format
16
+ mise run lint
17
+ mise run test --coverage
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: kiarina-agi-runner
3
+ Version: 2.14.0
4
+ Summary: Agent, task runner, and structured output helpers for AI agents
5
+ Project-URL: Homepage, https://github.com/kiarina/kiarina-python
6
+ Project-URL: Repository, https://github.com/kiarina/kiarina-python
7
+ Project-URL: Issues, https://github.com/kiarina/kiarina-python/issues
8
+ Project-URL: Changelog, https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-agi-runner/CHANGELOG.md
9
+ Project-URL: Documentation, https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-agi-runner#readme
10
+ Author-email: kiarina <kiarinadawa@gmail.com>
11
+ Maintainer-email: kiarina <kiarinadawa@gmail.com>
12
+ License-Expression: MIT
13
+ Keywords: agents,ai,runner,structured-output,tasks
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: kiarina-agi-base>=2.7.0
24
+ Requires-Dist: kiarina-agi-data-builder>=2.13.0
25
+ Requires-Dist: kiarina-agi-data>=2.7.0
26
+ Requires-Dist: kiarina-agi-file>=2.8.0
27
+ Requires-Dist: kiarina-agi-flow>=2.11.0
28
+ Requires-Dist: kiarina-agi-text>=2.8.0
29
+ Requires-Dist: kiarina-agi-tool>=2.12.0
30
+ Requires-Dist: kiarina-utils-common>=2.8.0
31
+ Requires-Dist: kiarina-utils-file>=2.3.1
32
+ Requires-Dist: pydantic-settings-manager>=3.2.0
33
+ Requires-Dist: pydantic-settings<3,>=2.10.1
34
+ Requires-Dist: pydantic<3,>=2.11.7
35
+ Description-Content-Type: text/markdown
36
+
37
+ # kiarina-agi-runner
38
+
39
+ English | [日本語](README.ja.md)
40
+
41
+ ## What is this?
42
+
43
+ `kiarina-agi-runner` provides agent execution, task runners, and structured output helpers for AI agents.
44
+
45
+ ## Dependencies
46
+
47
+ | Package | Version | License |
48
+ | --- | --- | --- |
49
+ | [kiarina-agi-base](../kiarina-agi-base/) | `>=2.7.0` | MIT |
50
+ | [kiarina-agi-data](../kiarina-agi-data/) | `>=2.7.0` | MIT |
51
+ | [kiarina-agi-data-builder](../kiarina-agi-data-builder/) | `>=2.13.0` | MIT |
52
+ | [kiarina-agi-file](../kiarina-agi-file/) | `>=2.8.0` | MIT |
53
+ | [kiarina-agi-flow](../kiarina-agi-flow/) | `>=2.11.0` | MIT |
54
+ | [kiarina-agi-text](../kiarina-agi-text/) | `>=2.8.0` | MIT |
55
+ | [kiarina-agi-tool](../kiarina-agi-tool/) | `>=2.12.0` | MIT |
56
+ | [kiarina-utils-common](../kiarina-utils-common/) | `>=2.8.0` | MIT |
57
+ | [kiarina-utils-file](../kiarina-utils-file/) | `>=2.3.1` | MIT |
58
+ | [Pydantic](https://github.com/pydantic/pydantic) | `>=2.11.7,<3` | MIT |
59
+ | [pydantic-settings](https://github.com/pydantic/pydantic-settings) | `>=2.10.1,<3` | MIT |
60
+ | [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) | `>=3.2.0` | MIT |
@@ -0,0 +1,24 @@
1
+ # kiarina-agi-runner
2
+
3
+ [English](README.md) | 日本語
4
+
5
+ ## What is this?
6
+
7
+ `kiarina-agi-runner` は、AI agent の agent 実行、task runner、structured output helper を構成するための package です。
8
+
9
+ ## Dependencies
10
+
11
+ | Package | Version | License |
12
+ | --- | --- | --- |
13
+ | [kiarina-agi-base](../kiarina-agi-base/) | `>=2.7.0` | MIT |
14
+ | [kiarina-agi-data](../kiarina-agi-data/) | `>=2.7.0` | MIT |
15
+ | [kiarina-agi-data-builder](../kiarina-agi-data-builder/) | `>=2.13.0` | MIT |
16
+ | [kiarina-agi-file](../kiarina-agi-file/) | `>=2.8.0` | MIT |
17
+ | [kiarina-agi-flow](../kiarina-agi-flow/) | `>=2.11.0` | MIT |
18
+ | [kiarina-agi-text](../kiarina-agi-text/) | `>=2.8.0` | MIT |
19
+ | [kiarina-agi-tool](../kiarina-agi-tool/) | `>=2.12.0` | MIT |
20
+ | [kiarina-utils-common](../kiarina-utils-common/) | `>=2.8.0` | MIT |
21
+ | [kiarina-utils-file](../kiarina-utils-file/) | `>=2.3.1` | MIT |
22
+ | [Pydantic](https://github.com/pydantic/pydantic) | `>=2.11.7,<3` | MIT |
23
+ | [pydantic-settings](https://github.com/pydantic/pydantic-settings) | `>=2.10.1,<3` | MIT |
24
+ | [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) | `>=3.2.0` | MIT |
@@ -0,0 +1,24 @@
1
+ # kiarina-agi-runner
2
+
3
+ English | [日本語](README.ja.md)
4
+
5
+ ## What is this?
6
+
7
+ `kiarina-agi-runner` provides agent execution, task runners, and structured output helpers for AI agents.
8
+
9
+ ## Dependencies
10
+
11
+ | Package | Version | License |
12
+ | --- | --- | --- |
13
+ | [kiarina-agi-base](../kiarina-agi-base/) | `>=2.7.0` | MIT |
14
+ | [kiarina-agi-data](../kiarina-agi-data/) | `>=2.7.0` | MIT |
15
+ | [kiarina-agi-data-builder](../kiarina-agi-data-builder/) | `>=2.13.0` | MIT |
16
+ | [kiarina-agi-file](../kiarina-agi-file/) | `>=2.8.0` | MIT |
17
+ | [kiarina-agi-flow](../kiarina-agi-flow/) | `>=2.11.0` | MIT |
18
+ | [kiarina-agi-text](../kiarina-agi-text/) | `>=2.8.0` | MIT |
19
+ | [kiarina-agi-tool](../kiarina-agi-tool/) | `>=2.12.0` | MIT |
20
+ | [kiarina-utils-common](../kiarina-utils-common/) | `>=2.8.0` | MIT |
21
+ | [kiarina-utils-file](../kiarina-utils-file/) | `>=2.3.1` | MIT |
22
+ | [Pydantic](https://github.com/pydantic/pydantic) | `>=2.11.7,<3` | MIT |
23
+ | [pydantic-settings](https://github.com/pydantic/pydantic-settings) | `>=2.10.1,<3` | MIT |
24
+ | [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) | `>=3.2.0` | MIT |
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "kiarina-agi-runner"
3
+ version = "2.14.0"
4
+ description = "Agent, task runner, and structured output helpers for AI agents"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [{ name = "kiarina", email = "kiarinadawa@gmail.com" }]
8
+ maintainers = [{ name = "kiarina", email = "kiarinadawa@gmail.com" }]
9
+ keywords = ["ai", "agents", "runner", "tasks", "structured-output"]
10
+ classifiers = [
11
+ "Development Status :: 4 - Beta",
12
+ "Intended Audience :: Developers",
13
+ "Operating System :: OS Independent",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Programming Language :: Python :: 3.13",
17
+ "Topic :: Software Development :: Libraries :: Python Modules",
18
+ "Typing :: Typed",
19
+ ]
20
+ requires-python = ">=3.12"
21
+ dependencies = [
22
+ "kiarina-agi-base>=2.7.0",
23
+ "kiarina-agi-data>=2.7.0",
24
+ "kiarina-agi-data-builder>=2.13.0",
25
+ "kiarina-agi-file>=2.8.0",
26
+ "kiarina-agi-flow>=2.11.0",
27
+ "kiarina-agi-text>=2.8.0",
28
+ "kiarina-agi-tool>=2.12.0",
29
+ "kiarina-utils-common>=2.8.0",
30
+ "kiarina-utils-file>=2.3.1",
31
+ "pydantic>=2.11.7,<3",
32
+ "pydantic-settings>=2.10.1,<3",
33
+ "pydantic-settings-manager>=3.2.0",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/kiarina/kiarina-python"
38
+ Repository = "https://github.com/kiarina/kiarina-python"
39
+ Issues = "https://github.com/kiarina/kiarina-python/issues"
40
+ Changelog = "https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-agi-runner/CHANGELOG.md"
41
+ Documentation = "https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-agi-runner#readme"
42
+
43
+ [build-system]
44
+ requires = ["hatchling"]
45
+ build-backend = "hatchling.build"
46
+
47
+ [tool.hatch.build.targets.wheel]
48
+ packages = ["src/kiarina"]
@@ -0,0 +1,35 @@
1
+ from ._exceptions.missing_tools_error import MissingToolsError
2
+ from ._helpers.invoke_agent import invoke_agent
3
+ from ._helpers.run_agent import run_agent
4
+ from ._helpers.stream_agent import stream_agent
5
+ from ._models.base_agent import BaseAgent
6
+ from ._schemas.agent_context import AgentContext
7
+ from ._services.agent_registry import agent_registry
8
+ from ._settings import AgentSettings, settings_manager
9
+ from ._types.agent import Agent
10
+ from ._types.agent_name import AgentName
11
+ from ._types.agent_options import AgentOptions
12
+ from ._types.agent_specifier import AgentSpecifier
13
+
14
+ __all__ = [
15
+ # ._helpers
16
+ "invoke_agent",
17
+ "run_agent",
18
+ "stream_agent",
19
+ # ._exceptions
20
+ "MissingToolsError",
21
+ # ._models
22
+ "BaseAgent",
23
+ # ._schemas
24
+ "AgentContext",
25
+ # ._services
26
+ "agent_registry",
27
+ # ._settings
28
+ "AgentSettings",
29
+ "settings_manager",
30
+ # ._types
31
+ "Agent",
32
+ "AgentName",
33
+ "AgentOptions",
34
+ "AgentSpecifier",
35
+ ]
@@ -0,0 +1,8 @@
1
+ from kiarina.agi.tool_info import ToolName
2
+
3
+
4
+ class MissingToolsError(Exception):
5
+ def __init__(self, tool_names: list[ToolName]) -> None:
6
+ unique_tool_names = list(dict.fromkeys(tool_names))
7
+ self.tool_names: list[ToolName] = unique_tool_names
8
+ super().__init__(f"Missing tools: {', '.join(unique_tool_names)}")
@@ -0,0 +1,43 @@
1
+ import asyncio
2
+ from collections.abc import AsyncIterator
3
+ from typing import Any
4
+
5
+ from kiarina.agi.chat_model import ChatOptions
6
+ from kiarina.agi.cost_recorder import CostRecorder
7
+ from kiarina.agi.event import Event
8
+ from kiarina.agi.history import History
9
+ from kiarina.agi.prompt import PromptOptions
10
+ from kiarina.agi.run_context import RunContext
11
+ from kiarina.agi.tool import ToolOptions
12
+ from kiarina.agi.workflow import WorkflowOptions
13
+
14
+ from .._types.agent_options import AgentOptions
15
+ from .run_agent import run_agent
16
+
17
+
18
+ async def invoke_agent(
19
+ history: History,
20
+ *,
21
+ chat_options: ChatOptions | None = None,
22
+ prompt_options: PromptOptions | None = None,
23
+ workflow_options: WorkflowOptions | None = None,
24
+ tool_options: ToolOptions | None = None,
25
+ agent_options: AgentOptions | None = None,
26
+ cost_recorder: CostRecorder | None = None,
27
+ run_context: RunContext,
28
+ stop_event: asyncio.Event | None = None,
29
+ **kwargs: Any,
30
+ ) -> AsyncIterator[Event]:
31
+ async for event in run_agent(
32
+ history,
33
+ chat_options={**(chat_options or {}), "streaming": False},
34
+ prompt_options=prompt_options,
35
+ workflow_options=workflow_options,
36
+ tool_options=tool_options,
37
+ agent_options=agent_options,
38
+ cost_recorder=cost_recorder,
39
+ run_context=run_context,
40
+ stop_event=stop_event,
41
+ **kwargs,
42
+ ):
43
+ yield event
@@ -0,0 +1,206 @@
1
+ import asyncio
2
+ import logging
3
+ from collections.abc import AsyncIterator
4
+ from typing import Any
5
+
6
+ from kiarina.agi.chat_limits import ChatLimits
7
+ from kiarina.agi.chat_model import ChatOptions
8
+ from kiarina.agi.cost_recorder import CostRecorder
9
+ from kiarina.agi.event import Event
10
+ from kiarina.agi.history import History
11
+ from kiarina.agi.message import AIMessage, Message, ToolMessage
12
+ from kiarina.agi.prompt import PromptOptions
13
+ from kiarina.agi.run_context import RunContext
14
+ from kiarina.agi.tool import ToolOptions
15
+ from kiarina.agi.workflow import WorkflowOptions
16
+
17
+ from .._exceptions.missing_tools_error import MissingToolsError
18
+ from .._schemas.agent_context import AgentContext
19
+ from .._services.agent_registry import agent_registry
20
+ from .._settings import settings_manager
21
+ from .._types.agent import Agent
22
+ from .._types.agent_options import AgentOptions
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ async def run_agent(
28
+ history: History,
29
+ *,
30
+ chat_options: ChatOptions | None = None,
31
+ prompt_options: PromptOptions | None = None,
32
+ workflow_options: WorkflowOptions | None = None,
33
+ tool_options: ToolOptions | None = None,
34
+ agent_options: AgentOptions | None = None,
35
+ cost_recorder: CostRecorder | None = None,
36
+ run_context: RunContext,
37
+ stop_event: asyncio.Event | None = None,
38
+ **kwargs: Any,
39
+ ) -> AsyncIterator[Event]:
40
+ agent_options = agent_options or {}
41
+
42
+ agent = agent_options.get("agent")
43
+
44
+ if not isinstance(agent, Agent):
45
+ agent = agent_registry.resolve(agent)
46
+
47
+ file_limits = agent_options.get("file_limits")
48
+
49
+ if not isinstance(file_limits, ChatLimits):
50
+ file_limits = ChatLimits.from_specifier(file_limits or "")
51
+
52
+ max_iterations = (
53
+ agent_options.get("max_iterations") or settings_manager.settings.max_iterations
54
+ )
55
+
56
+ until_end = agent_options.get("until_end") or False
57
+ until_tool_calls = agent_options.get("until_tool_calls") or []
58
+ until_tool_runs = agent_options.get("until_tool_runs") or []
59
+
60
+ ctx = AgentContext.create(
61
+ file_limits=file_limits,
62
+ chat_options=chat_options,
63
+ prompt_options=prompt_options,
64
+ workflow_options=workflow_options,
65
+ tool_options=tool_options,
66
+ cost_recorder=cost_recorder,
67
+ run_context=run_context,
68
+ **kwargs,
69
+ )
70
+
71
+ iterations = 0
72
+
73
+ while True:
74
+ if stop_event is not None and stop_event.is_set():
75
+ logger.debug("Agent loop stopped by stop event")
76
+ break
77
+
78
+ if _is_conversation_end(history):
79
+ break
80
+
81
+ if _is_iteration_end(history, agent_options, iterations, max_iterations):
82
+ break
83
+
84
+ iterations += 1
85
+ new_events: list[Event] = []
86
+ ctx.run_context = run_context.with_metadata(
87
+ loop=_format_loop(
88
+ iterations=iterations,
89
+ max_iterations=max_iterations,
90
+ until_end=until_end,
91
+ until_tool_calls=until_tool_calls,
92
+ until_tool_runs=until_tool_runs,
93
+ ),
94
+ agent=str(agent),
95
+ )
96
+
97
+ try:
98
+ async for event in _run_agent_iteration(ctx, history, agent):
99
+ yield event
100
+ new_events.append(event)
101
+
102
+ except MissingToolsError as e:
103
+ logger.debug(f"Missing tools called: {', '.join(e.tool_names)}")
104
+ break
105
+
106
+ last_message = _get_last_message_from_events(new_events)
107
+
108
+ if last_message is None:
109
+ break
110
+
111
+ if isinstance(last_message, ToolMessage) and last_message.return_direct:
112
+ break
113
+
114
+ if until_tool_calls and isinstance(last_message, AIMessage):
115
+ if any(
116
+ tool_call.name in until_tool_calls
117
+ for tool_call in last_message.tool_calls
118
+ ):
119
+ logger.debug("Until tool calls reached")
120
+ break
121
+
122
+ if until_tool_runs and isinstance(last_message, ToolMessage):
123
+ if last_message.tool_name in until_tool_runs:
124
+ logger.debug("Until tool runs reached")
125
+ break
126
+
127
+
128
+ async def _run_agent_iteration(
129
+ ctx: AgentContext,
130
+ history: History,
131
+ agent: Agent,
132
+ ) -> AsyncIterator[Event]:
133
+ async for event in agent.pre_run(ctx, history):
134
+ yield event
135
+
136
+ async for event in agent.run(ctx, history):
137
+ yield event
138
+
139
+ async for event in agent.post_run(ctx, history):
140
+ yield event
141
+
142
+
143
+ def _is_conversation_end(history: History) -> bool:
144
+ message = _get_last_message(history)
145
+ return isinstance(message, AIMessage) and not message.tool_calls
146
+
147
+
148
+ def _is_iteration_end(
149
+ history: History,
150
+ agent_options: AgentOptions,
151
+ iterations: int,
152
+ max_iterations: int,
153
+ ) -> bool:
154
+ return iterations >= max_iterations and not _should_continue_until_end(
155
+ history,
156
+ agent_options,
157
+ )
158
+
159
+
160
+ def _should_continue_until_end(
161
+ history: History,
162
+ agent_options: AgentOptions,
163
+ ) -> bool:
164
+ return agent_options.get("until_end", False) and _is_last_tool_call(history)
165
+
166
+
167
+ def _is_last_tool_call(history: History) -> bool:
168
+ message = _get_last_message(history)
169
+ return isinstance(message, AIMessage) and bool(message.tool_calls)
170
+
171
+
172
+ def _format_loop(
173
+ *,
174
+ iterations: int,
175
+ max_iterations: int,
176
+ until_end: bool,
177
+ until_tool_calls: list[str],
178
+ until_tool_runs: list[str],
179
+ ) -> str:
180
+ return (
181
+ f"{iterations}/{max_iterations}"
182
+ f"{' until_end' if until_end else ''}"
183
+ f"{' until_tool_calls(' + ','.join(until_tool_calls) + ')' if until_tool_calls else ''}"
184
+ f"{' until_tool_runs(' + ','.join(until_tool_runs) + ')' if until_tool_runs else ''}"
185
+ ).strip()
186
+
187
+
188
+ def _get_last_message(history: History) -> Message | None:
189
+ messages = history.get_messages()
190
+
191
+ if not messages:
192
+ return None
193
+
194
+ return messages[-1]
195
+
196
+
197
+ def _get_last_message_from_events(events: list[Event]) -> Message | None:
198
+ for event in reversed(events):
199
+ if (
200
+ event.type == "human_message"
201
+ or event.type == "ai_message"
202
+ or event.type == "tool_message"
203
+ ):
204
+ return event.message
205
+
206
+ return None
@@ -0,0 +1,43 @@
1
+ import asyncio
2
+ from collections.abc import AsyncIterator
3
+ from typing import Any
4
+
5
+ from kiarina.agi.chat_model import ChatOptions
6
+ from kiarina.agi.cost_recorder import CostRecorder
7
+ from kiarina.agi.event import Event
8
+ from kiarina.agi.history import History
9
+ from kiarina.agi.prompt import PromptOptions
10
+ from kiarina.agi.run_context import RunContext
11
+ from kiarina.agi.tool import ToolOptions
12
+ from kiarina.agi.workflow import WorkflowOptions
13
+
14
+ from .._types.agent_options import AgentOptions
15
+ from .run_agent import run_agent
16
+
17
+
18
+ async def stream_agent(
19
+ history: History,
20
+ *,
21
+ chat_options: ChatOptions | None = None,
22
+ prompt_options: PromptOptions | None = None,
23
+ workflow_options: WorkflowOptions | None = None,
24
+ tool_options: ToolOptions | None = None,
25
+ agent_options: AgentOptions | None = None,
26
+ cost_recorder: CostRecorder | None = None,
27
+ run_context: RunContext,
28
+ stop_event: asyncio.Event | None = None,
29
+ **kwargs: Any,
30
+ ) -> AsyncIterator[Event]:
31
+ async for event in run_agent(
32
+ history,
33
+ chat_options={**(chat_options or {}), "streaming": True},
34
+ prompt_options=prompt_options,
35
+ workflow_options=workflow_options,
36
+ tool_options=tool_options,
37
+ agent_options=agent_options,
38
+ cost_recorder=cost_recorder,
39
+ run_context=run_context,
40
+ stop_event=stop_event,
41
+ **kwargs,
42
+ ):
43
+ yield event