oagi-core 0.10.2__tar.gz → 0.10.3__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 (110) hide show
  1. {oagi_core-0.10.2 → oagi_core-0.10.3}/PKG-INFO +1 -1
  2. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/tasker_agent_example.py +1 -1
  3. {oagi_core-0.10.2 → oagi_core-0.10.3}/metapackage/pyproject.toml +2 -2
  4. {oagi_core-0.10.2 → oagi_core-0.10.3}/metapackage/uv.lock +5 -5
  5. {oagi_core-0.10.2 → oagi_core-0.10.3}/pyproject.toml +1 -1
  6. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/default.py +10 -4
  7. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/factories.py +23 -13
  8. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/planner.py +2 -1
  9. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/taskee_agent.py +12 -5
  10. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/tasker_agent.py +12 -5
  11. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/agent.py +28 -13
  12. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/display.py +2 -1
  13. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/server.py +1 -1
  14. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/utils.py +4 -3
  15. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/client/async_.py +19 -6
  16. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/client/base.py +14 -16
  17. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/client/sync.py +19 -6
  18. oagi_core-0.10.3/src/oagi/constants.py +43 -0
  19. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/pyautogui_action_handler.py +2 -1
  20. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/config.py +6 -3
  21. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/models.py +5 -3
  22. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/session_store.py +6 -4
  23. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/socketio_server.py +2 -1
  24. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/async_.py +4 -3
  25. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/async_short.py +3 -2
  26. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/base.py +2 -1
  27. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/short.py +3 -2
  28. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/sync.py +4 -3
  29. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/conftest.py +4 -3
  30. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_actor.py +6 -5
  31. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_agent_registry.py +12 -11
  32. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_async_client.py +25 -0
  33. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_cli.py +2 -1
  34. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_server/test_session_store.py +7 -6
  35. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_sync_client.py +24 -2
  36. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_taskee_agent.py +2 -1
  37. {oagi_core-0.10.2 → oagi_core-0.10.3}/uv.lock +1 -1
  38. {oagi_core-0.10.2 → oagi_core-0.10.3}/.github/workflows/ci.yml +0 -0
  39. {oagi_core-0.10.2 → oagi_core-0.10.3}/.github/workflows/release.yml +0 -0
  40. {oagi_core-0.10.2 → oagi_core-0.10.3}/.gitignore +0 -0
  41. {oagi_core-0.10.2 → oagi_core-0.10.3}/.python-version +0 -0
  42. {oagi_core-0.10.2 → oagi_core-0.10.3}/CONTRIBUTING.md +0 -0
  43. {oagi_core-0.10.2 → oagi_core-0.10.3}/LICENSE +0 -0
  44. {oagi_core-0.10.2 → oagi_core-0.10.3}/Makefile +0 -0
  45. {oagi_core-0.10.2 → oagi_core-0.10.3}/README.md +0 -0
  46. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/async_google_weather.py +0 -0
  47. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/execute_task_auto.py +0 -0
  48. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/execute_task_manual.py +0 -0
  49. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/google_weather.py +0 -0
  50. {oagi_core-0.10.2 → oagi_core-0.10.3}/examples/screenshot_with_config.py +0 -0
  51. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/__init__.py +0 -0
  52. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/__init__.py +0 -0
  53. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/__init__.py +0 -0
  54. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/agent_observer.py +0 -0
  55. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/events.py +0 -0
  56. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/exporters.py +0 -0
  57. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/protocol.py +0 -0
  58. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/observer/report_template.html +0 -0
  59. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/protocol.py +0 -0
  60. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/registry.py +0 -0
  61. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/__init__.py +0 -0
  62. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/memory.py +0 -0
  63. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/agent/tasker/models.py +0 -0
  64. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/__init__.py +0 -0
  65. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/main.py +0 -0
  66. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/cli/tracking.py +0 -0
  67. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/client/__init__.py +0 -0
  68. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/exceptions.py +0 -0
  69. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/__init__.py +0 -0
  70. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/_macos.py +0 -0
  71. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/async_pyautogui_action_handler.py +0 -0
  72. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/async_screenshot_maker.py +0 -0
  73. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/pil_image.py +0 -0
  74. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/handler/screenshot_maker.py +0 -0
  75. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/logging.py +0 -0
  76. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/__init__.py +0 -0
  77. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/agent_wrappers.py +0 -0
  78. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/server/main.py +0 -0
  79. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/task/__init__.py +0 -0
  80. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/__init__.py +0 -0
  81. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/action_handler.py +0 -0
  82. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/async_action_handler.py +0 -0
  83. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/async_image_provider.py +0 -0
  84. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/image.py +0 -0
  85. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/image_provider.py +0 -0
  86. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/models/__init__.py +0 -0
  87. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/models/action.py +0 -0
  88. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/models/client.py +0 -0
  89. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/models/image_config.py +0 -0
  90. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/models/step.py +0 -0
  91. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/step_observer.py +0 -0
  92. {oagi_core-0.10.2 → oagi_core-0.10.3}/src/oagi/types/url.py +0 -0
  93. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/__init__.py +0 -0
  94. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_action_parsing.py +0 -0
  95. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_agent/test_agent_wrappers.py +0 -0
  96. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_agent/test_default_agent.py +0 -0
  97. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_async_actor.py +0 -0
  98. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_async_handlers.py +0 -0
  99. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_logging.py +0 -0
  100. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_mac_double_click.py +0 -0
  101. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_observer.py +0 -0
  102. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_pil_image.py +0 -0
  103. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_planner.py +0 -0
  104. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_planner_memory.py +0 -0
  105. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_pyautogui_action_handler.py +0 -0
  106. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_screenshot_maker.py +0 -0
  107. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_server/__init__.py +0 -0
  108. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_server/test_config.py +0 -0
  109. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_server/test_socketio_integration.py +0 -0
  110. {oagi_core-0.10.2 → oagi_core-0.10.3}/tests/test_tasker_agent.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: oagi-core
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Official API of OpenAGI Foundation
5
5
  Project-URL: Homepage, https://github.com/agiopen-org/oagi
6
6
  Author-email: OpenAGI Foundation <contact@agiopen.org>
@@ -27,7 +27,7 @@ async def main():
27
27
  tasker = TaskerAgent(
28
28
  api_key=os.getenv("OAGI_API_KEY"),
29
29
  base_url=os.getenv("OAGI_BASE_URL", "https://api.agiopen.org"),
30
- model="sft-bigs1-1027-s2-1113-mixoc-1107-32b",
30
+ model="lux-actor-1",
31
31
  max_steps=30,
32
32
  temperature=0.5,
33
33
  step_observer=observer,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oagi"
7
- version = "0.10.2"
7
+ version = "0.10.3"
8
8
  description = "Official API of OpenAGI Foundation (metapackage with all features)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -16,7 +16,7 @@ authors = [
16
16
  requires-python = ">= 3.10"
17
17
 
18
18
  dependencies = [
19
- "oagi-core[desktop,server]==0.10.2",
19
+ "oagi-core[desktop,server]==0.10.3",
20
20
  ]
21
21
 
22
22
  [project.urls]
@@ -397,27 +397,27 @@ sdist = { url = "https://files.pythonhosted.org/packages/28/fa/b2ba8229b9381e8f6
397
397
 
398
398
  [[package]]
399
399
  name = "oagi"
400
- version = "0.10.2"
400
+ version = "0.10.3"
401
401
  source = { editable = "." }
402
402
  dependencies = [
403
403
  { name = "oagi-core", extra = ["desktop", "server"] },
404
404
  ]
405
405
 
406
406
  [package.metadata]
407
- requires-dist = [{ name = "oagi-core", extras = ["desktop", "server"], specifier = "==0.10.1" }]
407
+ requires-dist = [{ name = "oagi-core", extras = ["desktop", "server"], specifier = "==0.10.2" }]
408
408
 
409
409
  [[package]]
410
410
  name = "oagi-core"
411
- version = "0.10.1"
411
+ version = "0.10.2"
412
412
  source = { registry = "https://pypi.org/simple" }
413
413
  dependencies = [
414
414
  { name = "httpx" },
415
415
  { name = "pydantic" },
416
416
  { name = "rich" },
417
417
  ]
418
- sdist = { url = "https://files.pythonhosted.org/packages/9c/2d/83e5e2efe2591858e2aceaed4329d995c78cc9602b6a9fd9331096559351/oagi_core-0.10.1.tar.gz", hash = "sha256:264b88fb5b1e24f7284af3e82243d846817f6b1d0be108280491383e671e5b8d", size = 261938, upload-time = "2025-11-25T13:19:31.714Z" }
418
+ sdist = { url = "https://files.pythonhosted.org/packages/07/2f/11b7e37049b2faa1e1147a75624c024a93c32287f243c213ca96fc096452/oagi_core-0.10.2.tar.gz", hash = "sha256:2d7fb47031cdc2155ea5ea9c06b4b58c0d70091de95a36fa4dedf5d710a09862", size = 267130, upload-time = "2025-11-26T13:50:36.977Z" }
419
419
  wheels = [
420
- { url = "https://files.pythonhosted.org/packages/54/bb/3242e763f93360eeb6a5a5b1e61845cd3e27a485c442aeb9a918f6e4f3f6/oagi_core-0.10.1-py3-none-any.whl", hash = "sha256:5438e4310fab1aee3ffbe3d43963f04fc10d3747d24897b89f34df850bb76f89", size = 83830, upload-time = "2025-11-25T13:19:30.237Z" },
420
+ { url = "https://files.pythonhosted.org/packages/d0/c8/a1d95327afe6237eaf474d74ba66461e51baaf5948d458cb12be62dbf8a8/oagi_core-0.10.2-py3-none-any.whl", hash = "sha256:3b9dd3ade24a1c605d671ed7f35efcd00f729be603a63173c7f92f8177d56750", size = 87220, upload-time = "2025-11-26T13:50:35.872Z" },
421
421
  ]
422
422
 
423
423
  [package.optional-dependencies]
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "oagi-core"
7
- version = "0.10.2"
7
+ version = "0.10.3"
8
8
  description = "Official API of OpenAGI Foundation"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -10,6 +10,12 @@ import asyncio
10
10
  import logging
11
11
 
12
12
  from .. import AsyncActor
13
+ from ..constants import (
14
+ DEFAULT_MAX_STEPS,
15
+ DEFAULT_STEP_DELAY,
16
+ DEFAULT_TEMPERATURE,
17
+ MODEL_ACTOR,
18
+ )
13
19
  from ..types import (
14
20
  ActionEvent,
15
21
  AsyncActionHandler,
@@ -36,11 +42,11 @@ class AsyncDefaultAgent:
36
42
  self,
37
43
  api_key: str | None = None,
38
44
  base_url: str | None = None,
39
- model: str = "lux-actor-1",
40
- max_steps: int = 20,
41
- temperature: float | None = 0.5,
45
+ model: str = MODEL_ACTOR,
46
+ max_steps: int = DEFAULT_MAX_STEPS,
47
+ temperature: float | None = DEFAULT_TEMPERATURE,
42
48
  step_observer: AsyncObserver | None = None,
43
- step_delay: float = 0.3,
49
+ step_delay: float = DEFAULT_STEP_DELAY,
44
50
  ):
45
51
  self.api_key = api_key
46
52
  self.base_url = base_url
@@ -6,6 +6,16 @@
6
6
  # Licensed under the MIT License.
7
7
  # -----------------------------------------------------------------------------
8
8
  from oagi.agent.tasker import TaskerAgent
9
+ from oagi.constants import (
10
+ DEFAULT_MAX_STEPS,
11
+ DEFAULT_MAX_STEPS_TASKER,
12
+ DEFAULT_MAX_STEPS_THINKER,
13
+ DEFAULT_REFLECTION_INTERVAL_TASKER,
14
+ DEFAULT_STEP_DELAY,
15
+ DEFAULT_TEMPERATURE_LOW,
16
+ MODEL_ACTOR,
17
+ MODEL_THINKER,
18
+ )
9
19
  from oagi.types import AsyncStepObserver
10
20
 
11
21
  from .default import AsyncDefaultAgent
@@ -17,11 +27,11 @@ from .registry import async_agent_register
17
27
  def create_default_agent(
18
28
  api_key: str | None = None,
19
29
  base_url: str | None = None,
20
- model: str = "lux-actor-1",
21
- max_steps: int = 20,
22
- temperature: float = 0.1,
30
+ model: str = MODEL_ACTOR,
31
+ max_steps: int = DEFAULT_MAX_STEPS,
32
+ temperature: float = DEFAULT_TEMPERATURE_LOW,
23
33
  step_observer: AsyncStepObserver | None = None,
24
- step_delay: float = 0.3,
34
+ step_delay: float = DEFAULT_STEP_DELAY,
25
35
  ) -> AsyncAgent:
26
36
  return AsyncDefaultAgent(
27
37
  api_key=api_key,
@@ -38,11 +48,11 @@ def create_default_agent(
38
48
  def create_thinker_agent(
39
49
  api_key: str | None = None,
40
50
  base_url: str | None = None,
41
- model: str = "lux-thinker-1",
42
- max_steps: int = 100,
43
- temperature: float = 0.1,
51
+ model: str = MODEL_THINKER,
52
+ max_steps: int = DEFAULT_MAX_STEPS_THINKER,
53
+ temperature: float = DEFAULT_TEMPERATURE_LOW,
44
54
  step_observer: AsyncStepObserver | None = None,
45
- step_delay: float = 0.3,
55
+ step_delay: float = DEFAULT_STEP_DELAY,
46
56
  ) -> AsyncAgent:
47
57
  return AsyncDefaultAgent(
48
58
  api_key=api_key,
@@ -59,12 +69,12 @@ def create_thinker_agent(
59
69
  def create_planner_agent(
60
70
  api_key: str | None = None,
61
71
  base_url: str | None = None,
62
- model: str = "lux-actor-1",
63
- max_steps: int = 30,
64
- temperature: float = 0.1,
65
- reflection_interval: int = 20,
72
+ model: str = MODEL_ACTOR,
73
+ max_steps: int = DEFAULT_MAX_STEPS_TASKER,
74
+ temperature: float = DEFAULT_TEMPERATURE_LOW,
75
+ reflection_interval: int = DEFAULT_REFLECTION_INTERVAL_TASKER,
66
76
  step_observer: AsyncStepObserver | None = None,
67
- step_delay: float = 0.3,
77
+ step_delay: float = DEFAULT_STEP_DELAY,
68
78
  ) -> AsyncAgent:
69
79
  tasker = TaskerAgent(
70
80
  api_key=api_key,
@@ -10,6 +10,7 @@ import json
10
10
  from typing import Any
11
11
 
12
12
  from ...client import AsyncClient
13
+ from ...constants import DEFAULT_REFLECTION_INTERVAL
13
14
  from ...types import URL, Image
14
15
  from .memory import PlannerMemory
15
16
  from .models import Action, PlannerOutput, ReflectionOutput
@@ -175,7 +176,7 @@ class Planner:
175
176
  memory: PlannerMemory | None = None,
176
177
  todo_index: int | None = None,
177
178
  current_instruction: str | None = None,
178
- reflection_interval: int = 4,
179
+ reflection_interval: int = DEFAULT_REFLECTION_INTERVAL,
179
180
  ) -> ReflectionOutput:
180
181
  """Reflect on recent actions and progress.
181
182
 
@@ -12,6 +12,13 @@ from datetime import datetime
12
12
  from typing import Any
13
13
 
14
14
  from oagi import AsyncActor
15
+ from oagi.constants import (
16
+ DEFAULT_MAX_STEPS,
17
+ DEFAULT_REFLECTION_INTERVAL,
18
+ DEFAULT_STEP_DELAY,
19
+ DEFAULT_TEMPERATURE,
20
+ MODEL_ACTOR,
21
+ )
15
22
  from oagi.types import (
16
23
  URL,
17
24
  ActionEvent,
@@ -52,15 +59,15 @@ class TaskeeAgent(AsyncAgent):
52
59
  self,
53
60
  api_key: str | None = None,
54
61
  base_url: str | None = None,
55
- model: str = "lux-actor-1",
56
- max_steps: int = 20,
57
- reflection_interval: int = 4,
58
- temperature: float = 0.5,
62
+ model: str = MODEL_ACTOR,
63
+ max_steps: int = DEFAULT_MAX_STEPS,
64
+ reflection_interval: int = DEFAULT_REFLECTION_INTERVAL,
65
+ temperature: float = DEFAULT_TEMPERATURE,
59
66
  planner: Planner | None = None,
60
67
  external_memory: PlannerMemory | None = None,
61
68
  todo_index: int | None = None,
62
69
  step_observer: AsyncObserver | None = None,
63
- step_delay: float = 0.3,
70
+ step_delay: float = DEFAULT_STEP_DELAY,
64
71
  ):
65
72
  """Initialize the taskee agent.
66
73
 
@@ -9,6 +9,13 @@
9
9
  import logging
10
10
  from typing import Any
11
11
 
12
+ from oagi.constants import (
13
+ DEFAULT_MAX_STEPS_TASKER,
14
+ DEFAULT_REFLECTION_INTERVAL,
15
+ DEFAULT_STEP_DELAY,
16
+ DEFAULT_TEMPERATURE,
17
+ MODEL_ACTOR,
18
+ )
12
19
  from oagi.types import AsyncActionHandler, AsyncImageProvider, AsyncObserver, SplitEvent
13
20
 
14
21
  from ..protocol import AsyncAgent
@@ -34,13 +41,13 @@ class TaskerAgent(AsyncAgent):
34
41
  self,
35
42
  api_key: str | None = None,
36
43
  base_url: str | None = None,
37
- model: str = "lux-actor-1",
38
- max_steps: int = 60,
39
- temperature: float = 0.5,
40
- reflection_interval: int = 4,
44
+ model: str = MODEL_ACTOR,
45
+ max_steps: int = DEFAULT_MAX_STEPS_TASKER,
46
+ temperature: float = DEFAULT_TEMPERATURE,
47
+ reflection_interval: int = DEFAULT_REFLECTION_INTERVAL,
41
48
  planner: Planner | None = None,
42
49
  step_observer: AsyncObserver | None = None,
43
- step_delay: float = 0.3,
50
+ step_delay: float = DEFAULT_STEP_DELAY,
44
51
  ):
45
52
  """Initialize the tasker agent.
46
53
 
@@ -14,6 +14,17 @@ import time
14
14
  import traceback
15
15
 
16
16
  from oagi.agent.observer import AsyncAgentObserver
17
+ from oagi.constants import (
18
+ API_KEY_HELP_URL,
19
+ DEFAULT_BASE_URL,
20
+ DEFAULT_MAX_STEPS,
21
+ DEFAULT_MAX_STEPS_THINKER,
22
+ DEFAULT_STEP_DELAY,
23
+ DEFAULT_TEMPERATURE,
24
+ MODE_ACTOR,
25
+ MODEL_ACTOR,
26
+ MODEL_THINKER,
27
+ )
17
28
  from oagi.exceptions import check_optional_dependency
18
29
 
19
30
  from .display import display_step_table
@@ -32,7 +43,7 @@ def add_agent_parser(subparsers: argparse._SubParsersAction) -> None:
32
43
  "instruction", type=str, help="Task instruction for the agent to execute"
33
44
  )
34
45
  run_parser.add_argument(
35
- "--model", type=str, help="Model to use (default: lux-actor-1)"
46
+ "--model", type=str, help=f"Model to use (default: {MODEL_ACTOR})"
36
47
  )
37
48
  run_parser.add_argument(
38
49
  "--max-steps", type=int, help="Maximum number of steps (default: 20)"
@@ -43,8 +54,8 @@ def add_agent_parser(subparsers: argparse._SubParsersAction) -> None:
43
54
  run_parser.add_argument(
44
55
  "--mode",
45
56
  type=str,
46
- default="actor",
47
- help="Agent mode to use (default: actor). Available modes: actor, planner",
57
+ default=MODE_ACTOR,
58
+ help=f"Agent mode to use (default: {MODE_ACTOR}). Available modes: actor, planner",
48
59
  )
49
60
  run_parser.add_argument(
50
61
  "--oagi-api-key", type=str, help="OAGI API key (default: OAGI_API_KEY env var)"
@@ -52,7 +63,7 @@ def add_agent_parser(subparsers: argparse._SubParsersAction) -> None:
52
63
  run_parser.add_argument(
53
64
  "--oagi-base-url",
54
65
  type=str,
55
- help="OAGI base URL (default: https://api.agiopen.org, or OAGI_BASE_URL env var)",
66
+ help=f"OAGI base URL (default: {DEFAULT_BASE_URL}, or OAGI_BASE_URL env var)",
56
67
  )
57
68
  run_parser.add_argument(
58
69
  "--export",
@@ -68,7 +79,7 @@ def add_agent_parser(subparsers: argparse._SubParsersAction) -> None:
68
79
  run_parser.add_argument(
69
80
  "--step-delay",
70
81
  type=float,
71
- help="Delay in seconds after each step before next screenshot (default: 0.3)",
82
+ help=f"Delay in seconds after each step before next screenshot (default: {DEFAULT_STEP_DELAY})",
72
83
  )
73
84
 
74
85
  # agent permission command
@@ -189,19 +200,23 @@ def run_agent(args: argparse.Namespace) -> None:
189
200
  if not api_key:
190
201
  print(
191
202
  "Error: OAGI API key not provided.\n"
192
- "Set OAGI_API_KEY environment variable or use --oagi-api-key flag.",
203
+ "Set OAGI_API_KEY environment variable or use --oagi-api-key flag.\n"
204
+ f"Get your API key at {API_KEY_HELP_URL}",
193
205
  file=sys.stderr,
194
206
  )
195
207
  sys.exit(1)
196
208
 
197
- base_url = args.oagi_base_url or os.getenv(
198
- "OAGI_BASE_URL", "https://api.agiopen.org"
209
+ base_url = args.oagi_base_url or os.getenv("OAGI_BASE_URL", DEFAULT_BASE_URL)
210
+ model = args.model or MODEL_ACTOR
211
+ default_max_steps = (
212
+ DEFAULT_MAX_STEPS_THINKER if model == MODEL_THINKER else DEFAULT_MAX_STEPS
199
213
  )
200
- model = args.model or "lux-actor-1"
201
- max_steps = args.max_steps or 20
202
- temperature = args.temperature if args.temperature is not None else 0.5
203
- mode = args.mode or "actor"
204
- step_delay = args.step_delay if args.step_delay is not None else 0.3
214
+ max_steps = args.max_steps or default_max_steps
215
+ temperature = (
216
+ args.temperature if args.temperature is not None else DEFAULT_TEMPERATURE
217
+ )
218
+ mode = args.mode or MODE_ACTOR
219
+ step_delay = args.step_delay if args.step_delay is not None else DEFAULT_STEP_DELAY
205
220
  export_format = args.export
206
221
  export_file = args.export_file
207
222
 
@@ -29,7 +29,8 @@ def display_step_table(
29
29
  actions_display = []
30
30
  for action in step.actions[:3]:
31
31
  arg = action.argument[:20] if action.argument else ""
32
- actions_display.append(f"{action.type.value}({arg})")
32
+ count_str = f" x{action.count}" if action.count and action.count > 1 else ""
33
+ actions_display.append(f"{action.type.value}({arg}){count_str}")
33
34
 
34
35
  actions_str = ", ".join(actions_display)
35
36
  if len(step.actions) > 3:
@@ -25,7 +25,7 @@ def add_server_parser(subparsers: argparse._SubParsersAction) -> None:
25
25
  start_parser.add_argument(
26
26
  "--host",
27
27
  type=str,
28
- help="Server host (default: 0.0.0.0, or OAGI_SERVER_HOST env var)",
28
+ help="Server host (default: 127.0.0.1, or OAGI_SERVER_HOST env var)",
29
29
  )
30
30
  start_parser.add_argument(
31
31
  "--port",
@@ -11,6 +11,7 @@ import os
11
11
  import sys
12
12
  from importlib.metadata import version as get_version
13
13
 
14
+ from oagi.constants import DEFAULT_BASE_URL, MODEL_ACTOR
14
15
  from oagi.exceptions import check_optional_dependency
15
16
 
16
17
 
@@ -55,10 +56,10 @@ def display_version() -> None:
55
56
  def display_config() -> None:
56
57
  config_vars = {
57
58
  "OAGI_API_KEY": os.getenv("OAGI_API_KEY", ""),
58
- "OAGI_BASE_URL": os.getenv("OAGI_BASE_URL", "https://api.agiopen.org"),
59
- "OAGI_DEFAULT_MODEL": os.getenv("OAGI_DEFAULT_MODEL", "lux-actor-1"),
59
+ "OAGI_BASE_URL": os.getenv("OAGI_BASE_URL", DEFAULT_BASE_URL),
60
+ "OAGI_DEFAULT_MODEL": os.getenv("OAGI_DEFAULT_MODEL", MODEL_ACTOR),
60
61
  "OAGI_LOG_LEVEL": os.getenv("OAGI_LOG_LEVEL", "INFO"),
61
- "OAGI_SERVER_HOST": os.getenv("OAGI_SERVER_HOST", "0.0.0.0"),
62
+ "OAGI_SERVER_HOST": os.getenv("OAGI_SERVER_HOST", "127.0.0.1"),
62
63
  "OAGI_SERVER_PORT": os.getenv("OAGI_SERVER_PORT", "8000"),
63
64
  "OAGI_MAX_STEPS": os.getenv("OAGI_MAX_STEPS", "30"),
64
65
  }
@@ -10,6 +10,13 @@ from functools import wraps
10
10
 
11
11
  import httpx
12
12
 
13
+ from ..constants import (
14
+ API_HEALTH_ENDPOINT,
15
+ API_V1_FILE_UPLOAD_ENDPOINT,
16
+ API_V1_GENERATE_ENDPOINT,
17
+ API_V2_MESSAGE_ENDPOINT,
18
+ HTTP_CLIENT_TIMEOUT,
19
+ )
13
20
  from ..logging import get_logger
14
21
  from ..types import Image
15
22
  from ..types.models import GenerateResponse, LLMResponse, UploadFileResponse
@@ -41,7 +48,7 @@ class AsyncClient(BaseClient[httpx.AsyncClient]):
41
48
  def __init__(self, base_url: str | None = None, api_key: str | None = None):
42
49
  super().__init__(base_url, api_key)
43
50
  self.client = httpx.AsyncClient(base_url=self.base_url)
44
- self.upload_client = httpx.AsyncClient(timeout=60) # client for uploading image
51
+ self.upload_client = httpx.AsyncClient(timeout=HTTP_CLIENT_TIMEOUT)
45
52
  logger.info(f"AsyncClient initialized with base_url: {self.base_url}")
46
53
 
47
54
  async def __aenter__(self):
@@ -121,7 +128,10 @@ class AsyncClient(BaseClient[httpx.AsyncClient]):
121
128
  # Make request
122
129
  try:
123
130
  response = await self.client.post(
124
- "/v2/message", json=payload, headers=headers, timeout=self.timeout
131
+ API_V2_MESSAGE_ENDPOINT,
132
+ json=payload,
133
+ headers=headers,
134
+ timeout=self.timeout,
125
135
  )
126
136
  return self._process_response(response)
127
137
  except (httpx.TimeoutException, httpx.NetworkError) as e:
@@ -136,7 +146,7 @@ class AsyncClient(BaseClient[httpx.AsyncClient]):
136
146
  """
137
147
  logger.debug("Making async health check request")
138
148
  try:
139
- response = await self.client.get("/health")
149
+ response = await self.client.get(API_HEALTH_ENDPOINT)
140
150
  response.raise_for_status()
141
151
  result = response.json()
142
152
  logger.debug("Async health check successful")
@@ -158,12 +168,12 @@ class AsyncClient(BaseClient[httpx.AsyncClient]):
158
168
  Returns:
159
169
  UploadFileResponse: The response from /v1/file/upload with uuid and presigned S3 URL
160
170
  """
161
- logger.debug("Making async API request to /v1/file/upload")
171
+ logger.debug(f"Making async API request to {API_V1_FILE_UPLOAD_ENDPOINT}")
162
172
 
163
173
  try:
164
174
  headers = self._build_headers(api_version)
165
175
  response = await self.client.get(
166
- "/v1/file/upload", headers=headers, timeout=self.timeout
176
+ API_V1_FILE_UPLOAD_ENDPOINT, headers=headers, timeout=self.timeout
167
177
  )
168
178
  return self._process_upload_response(response)
169
179
  except (httpx.TimeoutException, httpx.NetworkError, httpx.HTTPStatusError) as e:
@@ -283,7 +293,10 @@ class AsyncClient(BaseClient[httpx.AsyncClient]):
283
293
  # Make request
284
294
  try:
285
295
  response = await self.client.post(
286
- "/v1/generate", json=payload, headers=headers, timeout=self.timeout
296
+ API_V1_GENERATE_ENDPOINT,
297
+ json=payload,
298
+ headers=headers,
299
+ timeout=self.timeout,
287
300
  )
288
301
  return self._process_generate_response(response)
289
302
  except (httpx.TimeoutException, httpx.NetworkError) as e:
@@ -11,6 +11,7 @@ from typing import Any, Generic, TypeVar
11
11
 
12
12
  import httpx
13
13
 
14
+ from ..constants import API_KEY_HELP_URL, DEFAULT_BASE_URL, HTTP_CLIENT_TIMEOUT
14
15
  from ..exceptions import (
15
16
  APIError,
16
17
  AuthenticationError,
@@ -41,20 +42,19 @@ class BaseClient(Generic[HttpClientT]):
41
42
 
42
43
  def __init__(self, base_url: str | None = None, api_key: str | None = None):
43
44
  # Get from environment if not provided
44
- self.base_url = (
45
- base_url or os.getenv("OAGI_BASE_URL") or "https://api.agiopen.org"
46
- )
45
+ self.base_url = base_url or os.getenv("OAGI_BASE_URL") or DEFAULT_BASE_URL
47
46
  self.api_key = api_key or os.getenv("OAGI_API_KEY")
48
47
 
49
48
  # Validate required configuration
50
49
  if not self.api_key:
51
50
  raise ConfigurationError(
52
51
  "OAGI API key must be provided either as 'api_key' parameter or "
53
- "OAGI_API_KEY environment variable"
52
+ "OAGI_API_KEY environment variable. "
53
+ f"Get your API key at {API_KEY_HELP_URL}"
54
54
  )
55
55
 
56
56
  self.base_url = self.base_url.rstrip("/")
57
- self.timeout = 60
57
+ self.timeout = HTTP_CLIENT_TIMEOUT
58
58
  self.client: HttpClientT # Will be set by subclasses
59
59
 
60
60
  logger.info(f"Client initialized with base_url: {self.base_url}")
@@ -273,22 +273,20 @@ class BaseClient(Generic[HttpClientT]):
273
273
  NetworkError: If network error occurs
274
274
  APIError: If API returns error or invalid response
275
275
  """
276
+ response_data = self._parse_response_json(response)
277
+
278
+ # Check for error status codes first (follows _process_response pattern)
279
+ if response.status_code != 200:
280
+ self._handle_response_error(response, response_data)
281
+
276
282
  try:
277
- response_data = response.json()
278
283
  upload_file_response = UploadFileResponse(**response_data)
279
284
  logger.debug("Calling /v1/file/upload successful")
280
285
  return upload_file_response
281
- except ValueError:
282
- logger.error(f"Non-JSON API response: {response.status_code}")
283
- raise APIError(
284
- f"Invalid response format (status {response.status_code})",
285
- status_code=response.status_code,
286
- response=response,
287
- )
288
- except KeyError as e:
289
- logger.error(f"Invalid response: {response.status_code}")
286
+ except Exception as e:
287
+ logger.error(f"Invalid upload response: {response.status_code}")
290
288
  raise APIError(
291
- f"Invalid presigned S3 URL response: missing field {e}",
289
+ f"Invalid presigned S3 URL response: {e}",
292
290
  status_code=response.status_code,
293
291
  response=response,
294
292
  )
@@ -11,6 +11,13 @@ from functools import wraps
11
11
  import httpx
12
12
  from httpx import Response
13
13
 
14
+ from ..constants import (
15
+ API_HEALTH_ENDPOINT,
16
+ API_V1_FILE_UPLOAD_ENDPOINT,
17
+ API_V1_GENERATE_ENDPOINT,
18
+ API_V2_MESSAGE_ENDPOINT,
19
+ HTTP_CLIENT_TIMEOUT,
20
+ )
14
21
  from ..logging import get_logger
15
22
  from ..types import Image
16
23
  from ..types.models import GenerateResponse, LLMResponse, UploadFileResponse
@@ -46,7 +53,7 @@ class SyncClient(BaseClient[httpx.Client]):
46
53
  def __init__(self, base_url: str | None = None, api_key: str | None = None):
47
54
  super().__init__(base_url, api_key)
48
55
  self.client = httpx.Client(base_url=self.base_url)
49
- self.upload_client = httpx.Client(timeout=60) # client for uploading image
56
+ self.upload_client = httpx.Client(timeout=HTTP_CLIENT_TIMEOUT)
50
57
  logger.info(f"SyncClient initialized with base_url: {self.base_url}")
51
58
 
52
59
  def __enter__(self):
@@ -124,7 +131,10 @@ class SyncClient(BaseClient[httpx.Client]):
124
131
  # Make request
125
132
  try:
126
133
  response = self.client.post(
127
- "/v2/message", json=payload, headers=headers, timeout=self.timeout
134
+ API_V2_MESSAGE_ENDPOINT,
135
+ json=payload,
136
+ headers=headers,
137
+ timeout=self.timeout,
128
138
  )
129
139
  return self._process_response(response)
130
140
  except (httpx.TimeoutException, httpx.NetworkError) as e:
@@ -139,7 +149,7 @@ class SyncClient(BaseClient[httpx.Client]):
139
149
  """
140
150
  logger.debug("Making health check request")
141
151
  try:
142
- response = self.client.get("/health")
152
+ response = self.client.get(API_HEALTH_ENDPOINT)
143
153
  response.raise_for_status()
144
154
  result = response.json()
145
155
  logger.debug("Health check successful")
@@ -161,12 +171,12 @@ class SyncClient(BaseClient[httpx.Client]):
161
171
  Returns:
162
172
  UploadFileResponse: The response from /v1/file/upload with uuid and presigned S3 URL
163
173
  """
164
- logger.debug("Making API request to /v1/file/upload")
174
+ logger.debug(f"Making API request to {API_V1_FILE_UPLOAD_ENDPOINT}")
165
175
 
166
176
  try:
167
177
  headers = self._build_headers(api_version)
168
178
  response = self.client.get(
169
- "/v1/file/upload", headers=headers, timeout=self.timeout
179
+ API_V1_FILE_UPLOAD_ENDPOINT, headers=headers, timeout=self.timeout
170
180
  )
171
181
  return self._process_upload_response(response)
172
182
  except (httpx.TimeoutException, httpx.NetworkError, httpx.HTTPStatusError) as e:
@@ -286,7 +296,10 @@ class SyncClient(BaseClient[httpx.Client]):
286
296
  # Make request
287
297
  try:
288
298
  response = self.client.post(
289
- "/v1/generate", json=payload, headers=headers, timeout=self.timeout
299
+ API_V1_GENERATE_ENDPOINT,
300
+ json=payload,
301
+ headers=headers,
302
+ timeout=self.timeout,
290
303
  )
291
304
  return self._process_generate_response(response)
292
305
  except (httpx.TimeoutException, httpx.NetworkError) as e:
@@ -0,0 +1,43 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Copyright (c) OpenAGI Foundation
3
+ # All rights reserved.
4
+ #
5
+ # This file is part of the official API project.
6
+ # Licensed under the MIT License.
7
+ # -----------------------------------------------------------------------------
8
+
9
+ # URLs & API Endpoints
10
+ DEFAULT_BASE_URL = "https://api.agiopen.org"
11
+ API_KEY_HELP_URL = "https://developer.agiopen.org/api-keys"
12
+ API_V2_MESSAGE_ENDPOINT = "/v2/message"
13
+ API_V1_FILE_UPLOAD_ENDPOINT = "/v1/file/upload"
14
+ API_V1_GENERATE_ENDPOINT = "/v1/generate"
15
+ API_HEALTH_ENDPOINT = "/health"
16
+
17
+ # Model identifiers
18
+ MODEL_ACTOR = "lux-actor-1"
19
+ MODEL_THINKER = "lux-thinker-1"
20
+
21
+ # Agent modes
22
+ MODE_ACTOR = "actor"
23
+ MODE_THINKER = "thinker"
24
+ MODE_TASKER = "tasker"
25
+
26
+ # Default max steps per model
27
+ DEFAULT_MAX_STEPS = 20
28
+ DEFAULT_MAX_STEPS_THINKER = 100
29
+ DEFAULT_MAX_STEPS_TASKER = 60
30
+
31
+ # Reflection intervals
32
+ DEFAULT_REFLECTION_INTERVAL = 4
33
+ DEFAULT_REFLECTION_INTERVAL_TASKER = 20
34
+
35
+ # Timing & Delays
36
+ DEFAULT_STEP_DELAY = 0.3
37
+
38
+ # Temperature Defaults
39
+ DEFAULT_TEMPERATURE = 0.5
40
+ DEFAULT_TEMPERATURE_LOW = 0.1
41
+
42
+ # Timeout Values
43
+ HTTP_CLIENT_TIMEOUT = 60
@@ -64,7 +64,8 @@ class PyautoguiConfig(BaseModel):
64
64
  default=0.5, description="Duration for drag operations in seconds"
65
65
  )
66
66
  scroll_amount: int = Field(
67
- default=30, description="Amount to scroll (positive for up, negative for down)"
67
+ default=2 if sys.platform == "darwin" else 100,
68
+ description="Amount to scroll (positive for up, negative for down)",
68
69
  )
69
70
  wait_duration: float = Field(
70
71
  default=1.0, description="Duration for wait actions in seconds"