agentic-loop 0.3.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.
- agentic_loop/__init__.py +31 -0
- agentic_loop/abort.py +19 -0
- agentic_loop/api.py +119 -0
- agentic_loop/cli.py +299 -0
- agentic_loop/config.py +73 -0
- agentic_loop/connectors/__init__.py +0 -0
- agentic_loop/connectors/base.py +39 -0
- agentic_loop/connectors/mcp.py +99 -0
- agentic_loop/llm/__init__.py +0 -0
- agentic_loop/llm/client.py +44 -0
- agentic_loop/llm/openai_compat.py +163 -0
- agentic_loop/llm/retry.py +41 -0
- agentic_loop/loop.py +228 -0
- agentic_loop/observability/__init__.py +0 -0
- agentic_loop/observability/journal.py +46 -0
- agentic_loop/orchestration/__init__.py +0 -0
- agentic_loop/orchestration/automations.py +54 -0
- agentic_loop/orchestration/goal.py +114 -0
- agentic_loop/orchestration/memory.py +145 -0
- agentic_loop/orchestration/orchestrator.py +119 -0
- agentic_loop/orchestration/subagents.py +66 -0
- agentic_loop/skills/__init__.py +0 -0
- agentic_loop/skills/loader.py +52 -0
- agentic_loop/state.py +28 -0
- agentic_loop/terminal.py +55 -0
- agentic_loop/tools/__init__.py +3 -0
- agentic_loop/tools/builtin.py +3 -0
- agentic_loop/tools/mcp_bridge.py +36 -0
- agentic_loop/tools/registry.py +222 -0
- agentic_loop/worktree/__init__.py +0 -0
- agentic_loop/worktree/manager.py +47 -0
- agentic_loop-0.3.0.dist-info/METADATA +110 -0
- agentic_loop-0.3.0.dist-info/RECORD +37 -0
- agentic_loop-0.3.0.dist-info/WHEEL +5 -0
- agentic_loop-0.3.0.dist-info/entry_points.txt +2 -0
- agentic_loop-0.3.0.dist-info/licenses/LICENSE +21 -0
- agentic_loop-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import re
|
|
6
|
+
import subprocess
|
|
7
|
+
import time
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any, Awaitable, Callable
|
|
11
|
+
|
|
12
|
+
from agentic_loop.llm.openai_compat import parse_tool_arguments
|
|
13
|
+
|
|
14
|
+
ToolHandler = Callable[[dict[str, Any]], Awaitable[str] | str]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class RegisteredTool:
|
|
19
|
+
name: str
|
|
20
|
+
description: str
|
|
21
|
+
parameters: dict[str, Any]
|
|
22
|
+
handler: ToolHandler
|
|
23
|
+
requires_bash: bool = False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ToolRegistry:
|
|
27
|
+
def __init__(self, *, cwd: Path, allow_bash: bool = False) -> None:
|
|
28
|
+
self.cwd = cwd.resolve()
|
|
29
|
+
self.allow_bash = allow_bash
|
|
30
|
+
self._tools: dict[str, RegisteredTool] = {}
|
|
31
|
+
|
|
32
|
+
def register(
|
|
33
|
+
self,
|
|
34
|
+
name: str,
|
|
35
|
+
description: str,
|
|
36
|
+
parameters: dict[str, Any],
|
|
37
|
+
handler: ToolHandler,
|
|
38
|
+
*,
|
|
39
|
+
requires_bash: bool = False,
|
|
40
|
+
) -> None:
|
|
41
|
+
self._tools[name] = RegisteredTool(
|
|
42
|
+
name=name,
|
|
43
|
+
description=description,
|
|
44
|
+
parameters=parameters,
|
|
45
|
+
handler=handler,
|
|
46
|
+
requires_bash=requires_bash,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def schemas(self) -> list[dict[str, Any]]:
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
"type": "function",
|
|
53
|
+
"function": {
|
|
54
|
+
"name": tool.name,
|
|
55
|
+
"description": tool.description,
|
|
56
|
+
"parameters": tool.parameters,
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
for tool in self._tools.values()
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
async def execute(self, name: str, arguments: str) -> str:
|
|
63
|
+
if name not in self._tools:
|
|
64
|
+
return f"Error: unknown tool '{name}'"
|
|
65
|
+
|
|
66
|
+
tool = self._tools[name]
|
|
67
|
+
if tool.requires_bash and not self.allow_bash:
|
|
68
|
+
return "Error: bash tool disabled. Re-run with --allow-bash."
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
args = parse_tool_arguments(arguments)
|
|
72
|
+
except ValueError as exc:
|
|
73
|
+
return f"Error: {exc}"
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
result = tool.handler(args)
|
|
77
|
+
if asyncio.iscoroutine(result):
|
|
78
|
+
result = await result
|
|
79
|
+
return str(result)
|
|
80
|
+
except Exception as exc: # noqa: BLE001 - tool errors become observations
|
|
81
|
+
return f"Error: {exc}"
|
|
82
|
+
|
|
83
|
+
def list_names(self) -> list[str]:
|
|
84
|
+
return sorted(self._tools.keys())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _resolve_path(cwd: Path, raw: str) -> Path:
|
|
88
|
+
path = Path(raw)
|
|
89
|
+
if not path.is_absolute():
|
|
90
|
+
path = cwd / path
|
|
91
|
+
resolved = path.resolve()
|
|
92
|
+
if cwd not in resolved.parents and resolved != cwd:
|
|
93
|
+
raise ValueError(f"Path escapes workspace: {raw}")
|
|
94
|
+
return resolved
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def read_file_handler(cwd: Path, args: dict[str, Any]) -> str:
|
|
98
|
+
path = _resolve_path(cwd, str(args["path"]))
|
|
99
|
+
if not path.is_file():
|
|
100
|
+
return f"Error: file not found: {path}"
|
|
101
|
+
try:
|
|
102
|
+
return path.read_text(encoding="utf-8")
|
|
103
|
+
except UnicodeDecodeError:
|
|
104
|
+
return path.read_text(encoding="utf-8", errors="replace")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async def write_file_handler(cwd: Path, args: dict[str, Any]) -> str:
|
|
108
|
+
path = _resolve_path(cwd, str(args["path"]))
|
|
109
|
+
content = str(args.get("content", ""))
|
|
110
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
111
|
+
path.write_text(content, encoding="utf-8")
|
|
112
|
+
return f"Wrote {len(content)} bytes to {path.relative_to(cwd)}"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
async def grep_handler(cwd: Path, args: dict[str, Any]) -> str:
|
|
116
|
+
pattern = str(args["pattern"])
|
|
117
|
+
root = _resolve_path(cwd, str(args.get("path", ".")))
|
|
118
|
+
if root.is_file():
|
|
119
|
+
targets = [root]
|
|
120
|
+
else:
|
|
121
|
+
targets = [p for p in root.rglob("*") if p.is_file()]
|
|
122
|
+
|
|
123
|
+
regex = re.compile(pattern)
|
|
124
|
+
matches: list[str] = []
|
|
125
|
+
for file_path in targets:
|
|
126
|
+
if ".venv" in file_path.parts or ".git" in file_path.parts:
|
|
127
|
+
continue
|
|
128
|
+
try:
|
|
129
|
+
text = file_path.read_text(encoding="utf-8", errors="ignore")
|
|
130
|
+
except OSError:
|
|
131
|
+
continue
|
|
132
|
+
for idx, line in enumerate(text.splitlines(), start=1):
|
|
133
|
+
if regex.search(line):
|
|
134
|
+
rel = file_path.relative_to(cwd)
|
|
135
|
+
matches.append(f"{rel}:{idx}:{line[:200]}")
|
|
136
|
+
if len(matches) >= 100:
|
|
137
|
+
return "\n".join(matches) + "\n...(truncated at 100 matches)"
|
|
138
|
+
|
|
139
|
+
if not matches:
|
|
140
|
+
return "No matches found."
|
|
141
|
+
return "\n".join(matches)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
async def bash_handler(cwd: Path, args: dict[str, Any]) -> str:
|
|
145
|
+
command = str(args["command"])
|
|
146
|
+
timeout = float(args.get("timeout", 60))
|
|
147
|
+
proc = await asyncio.create_subprocess_shell(
|
|
148
|
+
command,
|
|
149
|
+
cwd=str(cwd),
|
|
150
|
+
stdout=subprocess.PIPE,
|
|
151
|
+
stderr=subprocess.PIPE,
|
|
152
|
+
)
|
|
153
|
+
try:
|
|
154
|
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout)
|
|
155
|
+
except asyncio.TimeoutError:
|
|
156
|
+
proc.kill()
|
|
157
|
+
return f"Error: timeout after {timeout}s"
|
|
158
|
+
|
|
159
|
+
parts: list[str] = []
|
|
160
|
+
if stdout:
|
|
161
|
+
parts.append(stdout.decode("utf-8", errors="replace"))
|
|
162
|
+
if stderr:
|
|
163
|
+
parts.append(stderr.decode("utf-8", errors="replace"))
|
|
164
|
+
if proc.returncode not in (0, None):
|
|
165
|
+
parts.append(f"exit code: {proc.returncode}")
|
|
166
|
+
return "\n".join(parts).strip() or "(no output)"
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def build_default_registry(*, cwd: Path, allow_bash: bool = False) -> ToolRegistry:
|
|
170
|
+
registry = ToolRegistry(cwd=cwd, allow_bash=allow_bash)
|
|
171
|
+
|
|
172
|
+
registry.register(
|
|
173
|
+
"read_file",
|
|
174
|
+
"Read a UTF-8 text file relative to the workspace.",
|
|
175
|
+
{
|
|
176
|
+
"type": "object",
|
|
177
|
+
"properties": {"path": {"type": "string", "description": "File path"}},
|
|
178
|
+
"required": ["path"],
|
|
179
|
+
},
|
|
180
|
+
lambda args: read_file_handler(cwd, args),
|
|
181
|
+
)
|
|
182
|
+
registry.register(
|
|
183
|
+
"write_file",
|
|
184
|
+
"Write content to a file relative to the workspace.",
|
|
185
|
+
{
|
|
186
|
+
"type": "object",
|
|
187
|
+
"properties": {
|
|
188
|
+
"path": {"type": "string"},
|
|
189
|
+
"content": {"type": "string"},
|
|
190
|
+
},
|
|
191
|
+
"required": ["path", "content"],
|
|
192
|
+
},
|
|
193
|
+
lambda args: write_file_handler(cwd, args),
|
|
194
|
+
)
|
|
195
|
+
registry.register(
|
|
196
|
+
"grep",
|
|
197
|
+
"Search file contents under a path using a regex pattern.",
|
|
198
|
+
{
|
|
199
|
+
"type": "object",
|
|
200
|
+
"properties": {
|
|
201
|
+
"pattern": {"type": "string"},
|
|
202
|
+
"path": {"type": "string", "description": "File or directory", "default": "."},
|
|
203
|
+
},
|
|
204
|
+
"required": ["pattern"],
|
|
205
|
+
},
|
|
206
|
+
lambda args: grep_handler(cwd, args),
|
|
207
|
+
)
|
|
208
|
+
registry.register(
|
|
209
|
+
"bash",
|
|
210
|
+
"Run a shell command in the workspace directory.",
|
|
211
|
+
{
|
|
212
|
+
"type": "object",
|
|
213
|
+
"properties": {
|
|
214
|
+
"command": {"type": "string"},
|
|
215
|
+
"timeout": {"type": "number", "default": 60},
|
|
216
|
+
},
|
|
217
|
+
"required": ["command"],
|
|
218
|
+
},
|
|
219
|
+
lambda args: bash_handler(cwd, args),
|
|
220
|
+
requires_bash=True,
|
|
221
|
+
)
|
|
222
|
+
return registry
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import uuid
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class WorktreeInfo:
|
|
11
|
+
path: Path
|
|
12
|
+
branch: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class WorktreeManager:
|
|
16
|
+
def __init__(self, repo_root: Path) -> None:
|
|
17
|
+
self.repo_root = repo_root.resolve()
|
|
18
|
+
self.base_dir = self.repo_root / ".agentic-loop" / "worktrees"
|
|
19
|
+
|
|
20
|
+
def create(self, *, prefix: str = "agent") -> WorktreeInfo:
|
|
21
|
+
self.base_dir.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
branch = f"{prefix}/{uuid.uuid4().hex[:8]}"
|
|
23
|
+
path = self.base_dir / branch.replace("/", "-")
|
|
24
|
+
subprocess.run(
|
|
25
|
+
["git", "worktree", "add", "-b", branch, str(path)],
|
|
26
|
+
cwd=str(self.repo_root),
|
|
27
|
+
check=True,
|
|
28
|
+
capture_output=True,
|
|
29
|
+
text=True,
|
|
30
|
+
)
|
|
31
|
+
return WorktreeInfo(path=path, branch=branch)
|
|
32
|
+
|
|
33
|
+
def remove(self, info: WorktreeInfo) -> None:
|
|
34
|
+
subprocess.run(
|
|
35
|
+
["git", "worktree", "remove", "--force", str(info.path)],
|
|
36
|
+
cwd=str(self.repo_root),
|
|
37
|
+
check=False,
|
|
38
|
+
capture_output=True,
|
|
39
|
+
text=True,
|
|
40
|
+
)
|
|
41
|
+
subprocess.run(
|
|
42
|
+
["git", "branch", "-D", info.branch],
|
|
43
|
+
cwd=str(self.repo_root),
|
|
44
|
+
check=False,
|
|
45
|
+
capture_output=True,
|
|
46
|
+
text=True,
|
|
47
|
+
)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentic-loop
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Lightweight Loop Engineering orchestrator for self-hosted agent loops
|
|
5
|
+
Author: Agentic-Loop contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/WenSongWang/Agentic-Loop
|
|
8
|
+
Project-URL: Repository, https://github.com/WenSongWang/Agentic-Loop
|
|
9
|
+
Project-URL: Documentation, https://github.com/WenSongWang/Agentic-Loop#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/WenSongWang/Agentic-Loop/issues
|
|
11
|
+
Keywords: agent,llm,loop-engineering,orchestrator,mcp
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: openai>=1.40.0
|
|
24
|
+
Requires-Dist: pydantic>=2.7.0
|
|
25
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
29
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
30
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
31
|
+
Provides-Extra: webhook
|
|
32
|
+
Requires-Dist: fastapi>=0.115.0; extra == "webhook"
|
|
33
|
+
Requires-Dist: uvicorn>=0.32.0; extra == "webhook"
|
|
34
|
+
Provides-Extra: mcp
|
|
35
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: pytest>=8.0; extra == "all"
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "all"
|
|
39
|
+
Requires-Dist: build>=1.0; extra == "all"
|
|
40
|
+
Requires-Dist: twine>=5.0; extra == "all"
|
|
41
|
+
Requires-Dist: fastapi>=0.115.0; extra == "all"
|
|
42
|
+
Requires-Dist: uvicorn>=0.32.0; extra == "all"
|
|
43
|
+
Requires-Dist: mcp>=1.0.0; extra == "all"
|
|
44
|
+
Dynamic: license-file
|
|
45
|
+
|
|
46
|
+
# Agentic Loop
|
|
47
|
+
|
|
48
|
+
Lightweight **Loop Engineering** orchestrator — self-hosted agent loops with tools, state memory, sub-agents, `/goal`, and scheduled automations.
|
|
49
|
+
|
|
50
|
+
Fork-friendly (MIT). See [docs/architecture.md](docs/architecture.md) and [docs/extending.md](docs/extending.md).
|
|
51
|
+
|
|
52
|
+
## Install from PyPI
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
pip install agentic-loop
|
|
56
|
+
pip install "agentic-loop[webhook]" # FastAPI server example
|
|
57
|
+
pip install "agentic-loop[mcp]" # MCP connector
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
See [docs/publishing.md](docs/publishing.md) for maintainers.
|
|
61
|
+
|
|
62
|
+
## Quick Start (development)
|
|
63
|
+
|
|
64
|
+
```powershell
|
|
65
|
+
python -m venv .venv
|
|
66
|
+
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
|
|
67
|
+
copy .env.example .env # set OPENAI_API_KEY + DMXAPI base URL
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```powershell
|
|
71
|
+
agentic-loop run "Summarize README" --dry-run
|
|
72
|
+
agentic-loop loop --every 5m "Triage issues" --once --dry-run
|
|
73
|
+
agentic-loop goal "tests pass" "Fix tests" --dry-run
|
|
74
|
+
agentic-loop state show
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Example project: [examples/daily-triage](examples/daily-triage/)
|
|
78
|
+
|
|
79
|
+
## Commands
|
|
80
|
+
|
|
81
|
+
| Command | Purpose |
|
|
82
|
+
| :--- | :--- |
|
|
83
|
+
| `run` | Single agent loop with tools |
|
|
84
|
+
| `loop --every 5m` | Automation (Addy: Automations) |
|
|
85
|
+
| `goal "condition" "prompt"` | Run until evaluator confirms goal |
|
|
86
|
+
| `state show` | Persistent memory (state.json + triage) |
|
|
87
|
+
|
|
88
|
+
Common flags: `--cwd`, `--max-turns`, `--skill`, `--agent`, `--allow-bash`, `--dry-run`, `--no-stream`, `--json`
|
|
89
|
+
|
|
90
|
+
## Loop Engineering modules
|
|
91
|
+
|
|
92
|
+
| Module | CLI / path |
|
|
93
|
+
| :--- | :--- |
|
|
94
|
+
| Memory | `state show` → `.agentic-loop/state.json` |
|
|
95
|
+
| Skills | `--skill name` → `skills/*/SKILL.md` |
|
|
96
|
+
| Sub-agents | `--agent name` → `.agentic-loop/agents/*.toml` |
|
|
97
|
+
| Goal | `goal` + `EVALUATOR_MODEL` |
|
|
98
|
+
| Automations | `loop --every` |
|
|
99
|
+
|
|
100
|
+
Run logs: `.agentic-loop/runs/<run_id>.jsonl`
|
|
101
|
+
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
pytest tests/ -q
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
agentic_loop/__init__.py,sha256=dSeVtMzZR0uX75LZL3-B-miBiRX_5dcTN3a5RtJAZdQ,964
|
|
2
|
+
agentic_loop/abort.py,sha256=zxFz2dYJrjQzXvmo73FoD4Jp3vLOjExR_eTVG6ia820,398
|
|
3
|
+
agentic_loop/api.py,sha256=T33a5ikWw_GWmPnCzu8wairKKzL6SgEt4x40_riNRz8,3605
|
|
4
|
+
agentic_loop/cli.py,sha256=GOJ5Nig2reAuQLaNsrwxF4WhW4x-Blvksl6TqBEk7RA,10559
|
|
5
|
+
agentic_loop/config.py,sha256=bXsuAketlUt_-OghM0ICOk5vSxT_VwCSQoNhY1CBTOs,2267
|
|
6
|
+
agentic_loop/loop.py,sha256=GCvkIVrztBl5j32k-wL85HOwkUy9-h1hSfjWI09t5XM,7092
|
|
7
|
+
agentic_loop/state.py,sha256=v-htIs-EoyPMu4HTL9nz0rnJpnOdXU_v3d5mR1fmIm4,772
|
|
8
|
+
agentic_loop/terminal.py,sha256=0301DEY8mbbX5ZEnPjKuQY_D5fumjKP_wQV2LwDL0VM,1557
|
|
9
|
+
agentic_loop/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
agentic_loop/connectors/base.py,sha256=th65FFfjnbmhP77gO4WK184SELoEjFNwvabZsHa3WlA,1112
|
|
11
|
+
agentic_loop/connectors/mcp.py,sha256=MN6yvLfCpXIsZiGjUrVjrnc0m0mnQh9_6umx0GZYY7A,3545
|
|
12
|
+
agentic_loop/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
agentic_loop/llm/client.py,sha256=GHclE7KWcyty2aOuP-cg4Y2Reayp3RENOnNvD-k1z8E,895
|
|
14
|
+
agentic_loop/llm/openai_compat.py,sha256=i_c7PtgAdoXP_E1t20bomGm094ENRXLmKySW7vgMwVA,5412
|
|
15
|
+
agentic_loop/llm/retry.py,sha256=AJkmWRXxxL2eD1I_9wl2-vG4_YiD-UPHvzfZH3ABb9A,1126
|
|
16
|
+
agentic_loop/observability/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
agentic_loop/observability/journal.py,sha256=veKe7hKl1INU_dvhPH9rriqoRmFlGKNRz7PNk1h1f04,1618
|
|
18
|
+
agentic_loop/orchestration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
agentic_loop/orchestration/automations.py,sha256=T_-oEC5zEy7IXV80VdOVMom1MmC42J9rbfi1d71SSkI,1429
|
|
20
|
+
agentic_loop/orchestration/goal.py,sha256=ckwegI60b2JkHdeO-KB6fmFG346j47QnwwUQflbsTVI,4138
|
|
21
|
+
agentic_loop/orchestration/memory.py,sha256=7dFy3hRow7EXBcSheqxVVu0MivV0dz3uJXPWQ5oxuL4,5081
|
|
22
|
+
agentic_loop/orchestration/orchestrator.py,sha256=kcQ94b420gCA210AmJ-d7BRwUlt-MFAaxGxUNYFXX38,4572
|
|
23
|
+
agentic_loop/orchestration/subagents.py,sha256=wKKIQmOUpIpnaaASfRCu2So6s-_1XkxnFNNpxlUc2AE,2024
|
|
24
|
+
agentic_loop/skills/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
agentic_loop/skills/loader.py,sha256=8L3CEIljA9uPVQTbx9zyJlHMSWZa8HPpvfQXuIPas_8,1663
|
|
26
|
+
agentic_loop/tools/__init__.py,sha256=4EG_o6B0mr9ApTD1tYMSPHbzwpOQUOsKkn2r-y4AfCk,131
|
|
27
|
+
agentic_loop/tools/builtin.py,sha256=tsC9Exx5aaRia45X4TW-AoQG3w9vre7PJdAniegGaNU,101
|
|
28
|
+
agentic_loop/tools/mcp_bridge.py,sha256=GC8uxTL_anzRzxpVvmqlySilU9kGXIom9nOmZJ5Nwf8,1099
|
|
29
|
+
agentic_loop/tools/registry.py,sha256=t6kVU0t4rY8YQaFqfZcNXScPz7N8-6FkfVG5i6XKHsA,6882
|
|
30
|
+
agentic_loop/worktree/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
agentic_loop/worktree/manager.py,sha256=jDGGtHQ0Vpd30Bnu4RFLuErwQRcTUD_nCONMWa4OWiw,1354
|
|
32
|
+
agentic_loop-0.3.0.dist-info/licenses/LICENSE,sha256=vbQY5BQgLg7CC7m5DKYj5lnEsGINwaLwAIO1Ur0Nojo,1082
|
|
33
|
+
agentic_loop-0.3.0.dist-info/METADATA,sha256=UP2-SazzuaWb9yZfTrOOyLQm7c7k1C4RaO3aeyJMpTs,3679
|
|
34
|
+
agentic_loop-0.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
35
|
+
agentic_loop-0.3.0.dist-info/entry_points.txt,sha256=Vsodee_rDwrXPHx9p5DVw3Woun-0xjCozcBz1-VWjbk,55
|
|
36
|
+
agentic_loop-0.3.0.dist-info/top_level.txt,sha256=sBWRV1VCNyRCzxzEyH3zSZPZ_QrCqdBkUfia0rhQ8pw,13
|
|
37
|
+
agentic_loop-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentic-Loop contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
agentic_loop
|