orxt 0.1.0__py3-none-any.whl

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 (131) hide show
  1. orxt/agent/__init__.py +18 -0
  2. orxt/agent/_categories.py +29 -0
  3. orxt/agent/_loader.py +61 -0
  4. orxt/agent/_prompt.py +57 -0
  5. orxt/agent/_types.py +29 -0
  6. orxt/agent/py.typed +0 -0
  7. orxt/cli/__init__.py +0 -0
  8. orxt/cli/_cli.py +527 -0
  9. orxt/cli/_formatters.py +108 -0
  10. orxt/cli/py.typed +0 -0
  11. orxt/knowledge_module/__init__.py +26 -0
  12. orxt/knowledge_module/_cognee_import.py +20 -0
  13. orxt/knowledge_module/_config.py +25 -0
  14. orxt/knowledge_module/_freshness.py +34 -0
  15. orxt/knowledge_module/_ingest.py +68 -0
  16. orxt/knowledge_module/_retrieve.py +57 -0
  17. orxt/knowledge_module/_types.py +61 -0
  18. orxt/knowledge_module/py.typed +0 -0
  19. orxt/mcp/__init__.py +9 -0
  20. orxt/mcp/_server.py +383 -0
  21. orxt/mcp/_tools.py +239 -0
  22. orxt/mcp/py.typed +0 -0
  23. orxt/notepad/__init__.py +10 -0
  24. orxt/notepad/_reader.py +45 -0
  25. orxt/notepad/_types.py +5 -0
  26. orxt/notepad/py.typed +0 -0
  27. orxt/overseer/__init__.py +20 -0
  28. orxt/overseer/_autonomy.py +15 -0
  29. orxt/overseer/_handoff.py +65 -0
  30. orxt/overseer/_health.py +81 -0
  31. orxt/overseer/_inbox.py +28 -0
  32. orxt/overseer/_knowledge.py +73 -0
  33. orxt/overseer/_learning.py +95 -0
  34. orxt/overseer/_memory.py +169 -0
  35. orxt/overseer/_overseer.py +148 -0
  36. orxt/overseer/_tools.py +207 -0
  37. orxt/overseer/prompts/overseer_base.md +162 -0
  38. orxt/overseer/py.typed +0 -0
  39. orxt/protocols/__init__.py +94 -0
  40. orxt/protocols/_autonomy.py +46 -0
  41. orxt/protocols/_checks.py +51 -0
  42. orxt/protocols/_constraints.py +26 -0
  43. orxt/protocols/_errors.py +11 -0
  44. orxt/protocols/_events.py +113 -0
  45. orxt/protocols/_execution.py +70 -0
  46. orxt/protocols/_task.py +118 -0
  47. orxt/protocols/_tool.py +20 -0
  48. orxt/protocols/_tools.py +136 -0
  49. orxt/protocols/py.typed +0 -0
  50. orxt/scheduler/__init__.py +67 -0
  51. orxt/scheduler/_agent_execution.py +1177 -0
  52. orxt/scheduler/_base.py +346 -0
  53. orxt/scheduler/_enforcement.py +704 -0
  54. orxt/scheduler/_events.py +50 -0
  55. orxt/scheduler/_executor.py +1006 -0
  56. orxt/scheduler/_graph.py +130 -0
  57. orxt/scheduler/_lifecycle_handlers.py +338 -0
  58. orxt/scheduler/_loader.py +177 -0
  59. orxt/scheduler/_locks.py +28 -0
  60. orxt/scheduler/_overseer.py +636 -0
  61. orxt/scheduler/_services.py +79 -0
  62. orxt/scheduler/_task_dispatch.py +491 -0
  63. orxt/scheduler/_types.py +63 -0
  64. orxt/scheduler/_validator.py +181 -0
  65. orxt/scheduler/py.typed +0 -0
  66. orxt/secrets/__init__.py +3 -0
  67. orxt/secrets/_registry.py +39 -0
  68. orxt/secrets/py.typed +0 -0
  69. orxt/services/__init__.py +62 -0
  70. orxt/services/_config.py +37 -0
  71. orxt/services/_events.py +17 -0
  72. orxt/services/_inbox.py +49 -0
  73. orxt/services/_run.py +131 -0
  74. orxt/services/_trace.py +87 -0
  75. orxt/services/_validate.py +36 -0
  76. orxt/services/py.typed +0 -0
  77. orxt/session/__init__.py +13 -0
  78. orxt/session/_factory.py +56 -0
  79. orxt/session/_pricing.py +79 -0
  80. orxt/session/_session.py +243 -0
  81. orxt/session/py.typed +0 -0
  82. orxt/tool/__init__.py +91 -0
  83. orxt/tool/_consult_tool.py +120 -0
  84. orxt/tool/_exec_tool.py +124 -0
  85. orxt/tool/_git_tool.py +215 -0
  86. orxt/tool/_http_tool.py +129 -0
  87. orxt/tool/_notepad_tool.py +66 -0
  88. orxt/tool/_path.py +70 -0
  89. orxt/tool/_pipeline.py +123 -0
  90. orxt/tool/_preview.py +91 -0
  91. orxt/tool/_read_tools.py +853 -0
  92. orxt/tool/_shell_tool.py +147 -0
  93. orxt/tool/_task_tools.py +335 -0
  94. orxt/tool/_validation.py +23 -0
  95. orxt/tool/_write_integration.py +74 -0
  96. orxt/tool/_write_tools.py +433 -0
  97. orxt/tool/py.typed +0 -0
  98. orxt/trace/__init__.py +75 -0
  99. orxt/trace/_lock.py +54 -0
  100. orxt/trace/_reader.py +223 -0
  101. orxt/trace/_recovery.py +88 -0
  102. orxt/trace/_schema.py +310 -0
  103. orxt/trace/_transitions.py +57 -0
  104. orxt/trace/_types.py +120 -0
  105. orxt/trace/_writer.py +649 -0
  106. orxt/trace/py.typed +0 -0
  107. orxt/transport/__init__.py +45 -0
  108. orxt/transport/_events.py +131 -0
  109. orxt/transport/_provider.py +48 -0
  110. orxt/transport/_state_machine.py +23 -0
  111. orxt/transport/_transport.py +832 -0
  112. orxt/transport/providers/__init__.py +9 -0
  113. orxt/transport/providers/_anthropic.py +191 -0
  114. orxt/transport/providers/_openai.py +172 -0
  115. orxt/transport/py.typed +0 -0
  116. orxt/verify/__init__.py +29 -0
  117. orxt/verify/_execution.py +138 -0
  118. orxt/verify/_runner.py +49 -0
  119. orxt/verify/_types.py +23 -0
  120. orxt/verify/py.typed +0 -0
  121. orxt/write_safety/__init__.py +16 -0
  122. orxt/write_safety/_atomic.py +30 -0
  123. orxt/write_safety/_queue.py +39 -0
  124. orxt/write_safety/_replay.py +42 -0
  125. orxt/write_safety/_stale.py +72 -0
  126. orxt/write_safety/py.typed +0 -0
  127. orxt-0.1.0.dist-info/METADATA +16 -0
  128. orxt-0.1.0.dist-info/RECORD +131 -0
  129. orxt-0.1.0.dist-info/WHEEL +4 -0
  130. orxt-0.1.0.dist-info/entry_points.txt +2 -0
  131. orxt-0.1.0.dist-info/licenses/LICENSE +61 -0
orxt/agent/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from orxt.agent._categories import load_categories, resolve_category
4
+ from orxt.agent._loader import load_agent, load_agents
5
+ from orxt.agent._prompt import resolve_includes, resolve_prompt
6
+ from orxt.agent._types import Agent, ExecToolConfig, ShellConfig
7
+
8
+ __all__ = [
9
+ "Agent",
10
+ "ExecToolConfig",
11
+ "ShellConfig",
12
+ "load_agent",
13
+ "load_agents",
14
+ "load_categories",
15
+ "resolve_category",
16
+ "resolve_includes",
17
+ "resolve_prompt",
18
+ ]
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ import tomllib
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from pathlib import Path
8
+
9
+ from orxt.agent._types import Agent
10
+
11
+
12
+ def load_categories(path: Path) -> dict[str, str]:
13
+ if not path.is_file():
14
+ msg = f"Categories file not found: {path}"
15
+ raise FileNotFoundError(msg)
16
+ with path.open("rb") as f:
17
+ data = tomllib.load(f)
18
+ if "categories" not in data:
19
+ msg = f"Missing [categories] section in {path}"
20
+ raise ValueError(msg)
21
+ categories: dict[str, str] = data["categories"]
22
+ return categories
23
+
24
+
25
+ def resolve_category(agent: Agent, categories: dict[str, str]) -> str:
26
+ if agent.category not in categories:
27
+ msg = f"Unknown category: {agent.category}"
28
+ raise ValueError(msg)
29
+ return categories[agent.category]
orxt/agent/_loader.py ADDED
@@ -0,0 +1,61 @@
1
+ from __future__ import annotations
2
+
3
+ import tomllib
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ from orxt.agent._prompt import resolve_includes
7
+ from orxt.agent._types import Agent
8
+
9
+ if TYPE_CHECKING:
10
+ from pathlib import Path
11
+
12
+
13
+ def load_agent(path: Path) -> Agent:
14
+ if not path.is_file():
15
+ msg = f"Agent file not found: {path}"
16
+ raise FileNotFoundError(msg)
17
+ with path.open("rb") as f:
18
+ data = tomllib.load(f)
19
+
20
+ agent_section: dict[str, Any] = dict(data.get("agent", {}))
21
+ if "tools" not in data:
22
+ msg = f"Missing [tools] section in {path}"
23
+ raise ValueError(msg)
24
+ tools_section: dict[str, Any] = data["tools"]
25
+
26
+ prompt_rel = agent_section.pop("prompt", "")
27
+ prompt_path = (path.parent / prompt_rel).resolve()
28
+ if not prompt_path.is_file():
29
+ msg = f"Prompt file not found: {prompt_path}"
30
+ raise FileNotFoundError(msg)
31
+ prompt_text = prompt_path.read_text()
32
+ prompt_text = resolve_includes(prompt_text, prompt_path.parent)
33
+
34
+ agent_section["prompt"] = prompt_text
35
+ if "allow" not in tools_section:
36
+ msg = f"Missing 'allow' key in [tools] section in {path}"
37
+ raise ValueError(msg)
38
+ unknown_keys = set(tools_section.keys()) - {"allow"}
39
+ if unknown_keys:
40
+ names = ", ".join(sorted(unknown_keys))
41
+ msg = f"Unknown keys in [tools] section: {names}"
42
+ raise ValueError(msg)
43
+ agent_section["allow"] = tools_section["allow"]
44
+
45
+ exec_configs: list[dict[str, Any]] = data.get("exec", [])
46
+ shell_section: dict[str, Any] | None = data.get("shell")
47
+ agent_section["exec_tools"] = exec_configs
48
+ agent_section["shell_config"] = shell_section
49
+
50
+ return Agent(**agent_section)
51
+
52
+
53
+ def load_agents(directory: Path) -> dict[str, Agent]:
54
+ agents: dict[str, Agent] = {}
55
+ for toml_path in sorted(directory.glob("*.toml")):
56
+ agent = load_agent(toml_path)
57
+ if agent.name in agents:
58
+ msg = f"Duplicate agent name: {agent.name}"
59
+ raise ValueError(msg)
60
+ agents[agent.name] = agent
61
+ return agents
orxt/agent/_prompt.py ADDED
@@ -0,0 +1,57 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from pathlib import Path
8
+
9
+ _INCLUDE_RE = re.compile(r"\{include:([^}]+)\}")
10
+ _VAR_RE = re.compile(r"\{([a-zA-Z_][a-zA-Z0-9_]*)\}")
11
+
12
+
13
+ def resolve_includes(template: str, base_dir: Path) -> str:
14
+ return _resolve_includes(template, base_dir, frozenset())
15
+
16
+
17
+ def _resolve_includes(
18
+ template: str, base_dir: Path, seen: frozenset[Path]
19
+ ) -> str:
20
+ def replacer(match: re.Match[str]) -> str:
21
+ rel_path = match.group(1)
22
+ abs_path = (base_dir / rel_path).resolve()
23
+ if abs_path in seen:
24
+ msg = f"Circular include detected: {abs_path}"
25
+ raise ValueError(msg)
26
+ if not abs_path.is_file():
27
+ msg = f"Include file not found: {abs_path}"
28
+ raise FileNotFoundError(msg)
29
+ content = abs_path.read_text()
30
+ return _resolve_includes(content, abs_path.parent, seen | {abs_path})
31
+
32
+ return _INCLUDE_RE.sub(replacer, template)
33
+
34
+
35
+ def resolve_prompt(template: str, variables: dict[str, str]) -> str:
36
+ placeholders = set(_VAR_RE.findall(template))
37
+ var_keys = set(variables.keys())
38
+
39
+ unresolved = placeholders - var_keys
40
+ if unresolved:
41
+ name = sorted(unresolved)[0]
42
+ msg = f"Unresolved placeholder: {{{name}}}"
43
+ raise ValueError(msg)
44
+
45
+ unused = var_keys - placeholders
46
+ if unused:
47
+ name = sorted(unused)[0]
48
+ msg = f"Unused variable: {name}"
49
+ raise ValueError(msg)
50
+
51
+ if not placeholders:
52
+ return template
53
+
54
+ def replacer(match: re.Match[str]) -> str:
55
+ return variables[match.group(1)]
56
+
57
+ return _VAR_RE.sub(replacer, template)
orxt/agent/_types.py ADDED
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from pydantic import BaseModel, ConfigDict
4
+
5
+
6
+ class ExecToolConfig(BaseModel):
7
+ model_config = ConfigDict(frozen=True, strict=True, extra="forbid")
8
+ name: str
9
+ executable: str
10
+ description: str
11
+ timeout_ceiling: int = 300
12
+
13
+
14
+ class ShellConfig(BaseModel):
15
+ model_config = ConfigDict(frozen=True, strict=True, extra="forbid")
16
+ allowed_binaries: list[str]
17
+ description: str = "Execute shell commands with whitelisted binaries"
18
+ timeout_ceiling: int = 300
19
+
20
+
21
+ class Agent(BaseModel):
22
+ model_config = ConfigDict(frozen=True, strict=True, extra="forbid")
23
+ name: str
24
+ description: str
25
+ prompt: str
26
+ category: str
27
+ allow: list[str]
28
+ exec_tools: list[ExecToolConfig] = []
29
+ shell_config: ShellConfig | None = None
orxt/agent/py.typed ADDED
File without changes
orxt/cli/__init__.py ADDED
File without changes