yoker 0.1.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.
- yoker-0.1.0/PKG-INFO +263 -0
- yoker-0.1.0/README.md +222 -0
- yoker-0.1.0/pyproject.toml +135 -0
- yoker-0.1.0/setup.cfg +4 -0
- yoker-0.1.0/src/yoker/__init__.py +11 -0
- yoker-0.1.0/src/yoker/__main__.py +34 -0
- yoker-0.1.0/src/yoker/agent.py +89 -0
- yoker-0.1.0/src/yoker/py.typed +0 -0
- yoker-0.1.0/src/yoker/tools.py +26 -0
- yoker-0.1.0/src/yoker.egg-info/PKG-INFO +263 -0
- yoker-0.1.0/src/yoker.egg-info/SOURCES.txt +13 -0
- yoker-0.1.0/src/yoker.egg-info/dependency_links.txt +1 -0
- yoker-0.1.0/src/yoker.egg-info/entry_points.txt +2 -0
- yoker-0.1.0/src/yoker.egg-info/requires.txt +21 -0
- yoker-0.1.0/src/yoker.egg-info/top_level.txt +1 -0
yoker-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yoker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python agent harness with configurable tools and guardrails - one who yokes agents together
|
|
5
|
+
Author-email: Christophe VG <contact@christophe.vg>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/christophevg/yoker
|
|
8
|
+
Project-URL: Documentation, https://yoker.readthedocs.io/
|
|
9
|
+
Project-URL: Repository, https://github.com/christophevg/yoker
|
|
10
|
+
Project-URL: Issues, https://github.com/christophevg/yoker/issues
|
|
11
|
+
Keywords: agent,llm,ollama,ai,harness
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Requires-Dist: ollama>=0.6.0
|
|
25
|
+
Requires-Dist: rich>=14.0.0
|
|
26
|
+
Requires-Dist: structlog>=23.0.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: sphinx>=7.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: myst-parser>=2.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: tox>=4.0.0; extra == "dev"
|
|
41
|
+
|
|
42
|
+
# Yoker
|
|
43
|
+
|
|
44
|
+
A Python-based agent harness with configurable tools, guardrails, and Ollama backend integration.
|
|
45
|
+
|
|
46
|
+
## Current Status
|
|
47
|
+
|
|
48
|
+
**Minimal prototype available!** The basic chat loop with tool calling is working:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Install (requires Python 3.10+)
|
|
52
|
+
pip install -e .
|
|
53
|
+
|
|
54
|
+
# Run interactive chat
|
|
55
|
+
python -m yoker
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The prototype includes:
|
|
59
|
+
- Interactive chat loop with Ollama
|
|
60
|
+
- Basic `read` tool for file reading
|
|
61
|
+
- Streaming responses
|
|
62
|
+
- Structured logging
|
|
63
|
+
|
|
64
|
+
See [Quick Start](#quick-start) below for details.
|
|
65
|
+
|
|
66
|
+
## Name
|
|
67
|
+
|
|
68
|
+
**"yoker"** - One who yokes. A person or device that joins or attaches things together, specifically one who yokes oxen or links things together.
|
|
69
|
+
|
|
70
|
+
From the agent noun of "yoke", which derives from PIE *\yeug-* meaning "to join" (same root as yoga, conjugate, junction).
|
|
71
|
+
|
|
72
|
+
Pairs beautifully with "clitic" (both are joining tools - clitic joins words, yoker joins agents).
|
|
73
|
+
|
|
74
|
+
See `docs/NAME.md` for full naming documentation.
|
|
75
|
+
|
|
76
|
+
## Vision
|
|
77
|
+
|
|
78
|
+
Create a lightweight, configurable agent harness that provides a structured environment for AI agents to operate within defined boundaries. The harness manages tool access, enforces guardrails, handles context persistence, and integrates with Ollama as the LLM backend.
|
|
79
|
+
|
|
80
|
+
## Goals
|
|
81
|
+
|
|
82
|
+
1. **Safety First**: Guardrails prevent agents from performing unintended operations
|
|
83
|
+
2. **Configurability**: All tools, parameters, and limits configurable via TOML
|
|
84
|
+
3. **Simplicity**: Specific tools instead of generic shell access
|
|
85
|
+
4. **Transparency**: Clear logging and reporting of all agent actions
|
|
86
|
+
5. **Extensibility**: Easy to add new tools while maintaining guardrails
|
|
87
|
+
6. **Compatibility**: Agent definitions compatible with Claude Code format
|
|
88
|
+
|
|
89
|
+
## Core Components
|
|
90
|
+
|
|
91
|
+
### 1. Configuration System
|
|
92
|
+
|
|
93
|
+
- **TOML configuration file**: Harness settings, tool guardrails, Ollama parameters
|
|
94
|
+
- **Markdown agent definitions**: With YAML frontmatter (compatible with Claude Code)
|
|
95
|
+
|
|
96
|
+
### 2. Tool System
|
|
97
|
+
|
|
98
|
+
MVP tools (no generic Bash):
|
|
99
|
+
|
|
100
|
+
| Tool | Purpose | Guardrails |
|
|
101
|
+
|------|---------|------------|
|
|
102
|
+
| List | Directory listing | Path restrictions, pattern filters |
|
|
103
|
+
| Read | File reading | Path restrictions, size limits |
|
|
104
|
+
| Write | File writing | Path restrictions, overwrite protection |
|
|
105
|
+
| Update | File editing | Path restrictions, diff validation |
|
|
106
|
+
| Search | Grep/glob-like | Path restrictions, pattern limits |
|
|
107
|
+
| Agent | Spawn subagents | Recursion depth, tool subset |
|
|
108
|
+
|
|
109
|
+
### 3. Context Manager
|
|
110
|
+
|
|
111
|
+
Persists context for consecutive LLM calls:
|
|
112
|
+
- Conversation history (JSONL format - append-friendly)
|
|
113
|
+
- Agent state
|
|
114
|
+
- Working memory
|
|
115
|
+
- Per-session files in configurable location
|
|
116
|
+
|
|
117
|
+
### 4. Ollama Integration
|
|
118
|
+
|
|
119
|
+
- Assumes Ollama is running externally
|
|
120
|
+
- All configurable parameters exposed
|
|
121
|
+
- Model selection per agent possible
|
|
122
|
+
|
|
123
|
+
### 5. Agent Definitions
|
|
124
|
+
|
|
125
|
+
Markdown files with YAML frontmatter:
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
---
|
|
129
|
+
name: researcher
|
|
130
|
+
description: Research assistant
|
|
131
|
+
tools: List, Read, Search
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# Researcher Agent
|
|
135
|
+
|
|
136
|
+
You are a research assistant...
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Architecture
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
┌─────────────────────────────────────────────────────────┐
|
|
143
|
+
│ Yoker │
|
|
144
|
+
├─────────────────────────────────────────────────────────┤
|
|
145
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
|
146
|
+
│ │ Config │ │ Context │ │ Logging/ │ │
|
|
147
|
+
│ │ Loader │ │ Manager │ │ Reporting │ │
|
|
148
|
+
│ │ (TOML) │ │ (JSONL) │ │ │ │
|
|
149
|
+
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
|
|
150
|
+
│ │ │ │ │
|
|
151
|
+
│ ▼ ▼ ▼ │
|
|
152
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
153
|
+
│ │ Tool Execution Layer ││
|
|
154
|
+
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌───────┐ ││
|
|
155
|
+
│ │ │List │ │Read │ │Write│ │Update│ │Search│ │Agent │ ││
|
|
156
|
+
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └───────┘ ││
|
|
157
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
158
|
+
│ │ │
|
|
159
|
+
│ ▼ │
|
|
160
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
161
|
+
│ │ Ollama Backend Client ││
|
|
162
|
+
│ │ (HTTP API, configurable parameters) ││
|
|
163
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
164
|
+
└─────────────────────────────────────────────────────────┘
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Project Structure
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
yoker/
|
|
171
|
+
├── src/yoker/ # Main package
|
|
172
|
+
├── tests/ # Test suite
|
|
173
|
+
├── docs/ # Sphinx documentation
|
|
174
|
+
├── examples/ # Example configurations
|
|
175
|
+
├── analysis/ # Functional analysis
|
|
176
|
+
├── pyproject.toml # Package configuration
|
|
177
|
+
└── README.md
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Quick Start
|
|
181
|
+
|
|
182
|
+
### Minimal Prototype
|
|
183
|
+
|
|
184
|
+
The current prototype provides a basic interactive chat with tool calling:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Install
|
|
188
|
+
pip install -e .
|
|
189
|
+
|
|
190
|
+
# Run
|
|
191
|
+
python -m yoker
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Example session:
|
|
195
|
+
```
|
|
196
|
+
Yoker v0.1.0 - Using model: glm-5:cloud
|
|
197
|
+
Type your message and press Enter. Press Ctrl+D to quit.
|
|
198
|
+
|
|
199
|
+
> What's in the README.md file?
|
|
200
|
+
|
|
201
|
+
I'll read the README.md file for you.
|
|
202
|
+
|
|
203
|
+
[13:49:49] INFO yoker.agent - Tool call: read({'path': 'README.md'})
|
|
204
|
+
[13:49:49] INFO yoker.agent - Tool result: # Yoker...
|
|
205
|
+
|
|
206
|
+
The README.md file describes **Yoker**, a Python-based agent harness...
|
|
207
|
+
|
|
208
|
+
> ^D
|
|
209
|
+
Goodbye!
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Planned Full Usage
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Create config
|
|
216
|
+
cat > yoker.toml << EOF
|
|
217
|
+
[ollama]
|
|
218
|
+
model = "llama3.2"
|
|
219
|
+
base_url = "http://localhost:11434"
|
|
220
|
+
|
|
221
|
+
[tools.list]
|
|
222
|
+
allowed_paths = ["/workspace"]
|
|
223
|
+
|
|
224
|
+
[tools.read]
|
|
225
|
+
allowed_paths = ["/workspace"]
|
|
226
|
+
max_size_kb = 100
|
|
227
|
+
|
|
228
|
+
[tools.agent]
|
|
229
|
+
max_recursion_depth = 3
|
|
230
|
+
|
|
231
|
+
[agents]
|
|
232
|
+
directory = "./agents"
|
|
233
|
+
EOF
|
|
234
|
+
|
|
235
|
+
# Create agent definition
|
|
236
|
+
mkdir agents
|
|
237
|
+
cat > agents/main.md << EOF
|
|
238
|
+
---
|
|
239
|
+
name: main
|
|
240
|
+
description: Default assistant
|
|
241
|
+
tools: List, Read, Write, Update, Search, Agent
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
You are a helpful assistant.
|
|
245
|
+
EOF
|
|
246
|
+
|
|
247
|
+
# Run harness (planned)
|
|
248
|
+
yoker --config yoker.toml
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Documentation
|
|
252
|
+
|
|
253
|
+
- Name documentation: `docs/NAME.md`
|
|
254
|
+
- Functional analysis: `analysis/functional.md`
|
|
255
|
+
- Interview notes: `analysis/interview.md`
|
|
256
|
+
|
|
257
|
+
## Integration with Clitic
|
|
258
|
+
|
|
259
|
+
Yoker provides the agent runtime, Clitic provides the TUI:
|
|
260
|
+
|
|
261
|
+
- Build agents using Yoker APIs
|
|
262
|
+
- Optionally add Clitic-based CLI interface
|
|
263
|
+
- Deploy agents with or without UI (daemon mode)
|
yoker-0.1.0/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Yoker
|
|
2
|
+
|
|
3
|
+
A Python-based agent harness with configurable tools, guardrails, and Ollama backend integration.
|
|
4
|
+
|
|
5
|
+
## Current Status
|
|
6
|
+
|
|
7
|
+
**Minimal prototype available!** The basic chat loop with tool calling is working:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install (requires Python 3.10+)
|
|
11
|
+
pip install -e .
|
|
12
|
+
|
|
13
|
+
# Run interactive chat
|
|
14
|
+
python -m yoker
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The prototype includes:
|
|
18
|
+
- Interactive chat loop with Ollama
|
|
19
|
+
- Basic `read` tool for file reading
|
|
20
|
+
- Streaming responses
|
|
21
|
+
- Structured logging
|
|
22
|
+
|
|
23
|
+
See [Quick Start](#quick-start) below for details.
|
|
24
|
+
|
|
25
|
+
## Name
|
|
26
|
+
|
|
27
|
+
**"yoker"** - One who yokes. A person or device that joins or attaches things together, specifically one who yokes oxen or links things together.
|
|
28
|
+
|
|
29
|
+
From the agent noun of "yoke", which derives from PIE *\yeug-* meaning "to join" (same root as yoga, conjugate, junction).
|
|
30
|
+
|
|
31
|
+
Pairs beautifully with "clitic" (both are joining tools - clitic joins words, yoker joins agents).
|
|
32
|
+
|
|
33
|
+
See `docs/NAME.md` for full naming documentation.
|
|
34
|
+
|
|
35
|
+
## Vision
|
|
36
|
+
|
|
37
|
+
Create a lightweight, configurable agent harness that provides a structured environment for AI agents to operate within defined boundaries. The harness manages tool access, enforces guardrails, handles context persistence, and integrates with Ollama as the LLM backend.
|
|
38
|
+
|
|
39
|
+
## Goals
|
|
40
|
+
|
|
41
|
+
1. **Safety First**: Guardrails prevent agents from performing unintended operations
|
|
42
|
+
2. **Configurability**: All tools, parameters, and limits configurable via TOML
|
|
43
|
+
3. **Simplicity**: Specific tools instead of generic shell access
|
|
44
|
+
4. **Transparency**: Clear logging and reporting of all agent actions
|
|
45
|
+
5. **Extensibility**: Easy to add new tools while maintaining guardrails
|
|
46
|
+
6. **Compatibility**: Agent definitions compatible with Claude Code format
|
|
47
|
+
|
|
48
|
+
## Core Components
|
|
49
|
+
|
|
50
|
+
### 1. Configuration System
|
|
51
|
+
|
|
52
|
+
- **TOML configuration file**: Harness settings, tool guardrails, Ollama parameters
|
|
53
|
+
- **Markdown agent definitions**: With YAML frontmatter (compatible with Claude Code)
|
|
54
|
+
|
|
55
|
+
### 2. Tool System
|
|
56
|
+
|
|
57
|
+
MVP tools (no generic Bash):
|
|
58
|
+
|
|
59
|
+
| Tool | Purpose | Guardrails |
|
|
60
|
+
|------|---------|------------|
|
|
61
|
+
| List | Directory listing | Path restrictions, pattern filters |
|
|
62
|
+
| Read | File reading | Path restrictions, size limits |
|
|
63
|
+
| Write | File writing | Path restrictions, overwrite protection |
|
|
64
|
+
| Update | File editing | Path restrictions, diff validation |
|
|
65
|
+
| Search | Grep/glob-like | Path restrictions, pattern limits |
|
|
66
|
+
| Agent | Spawn subagents | Recursion depth, tool subset |
|
|
67
|
+
|
|
68
|
+
### 3. Context Manager
|
|
69
|
+
|
|
70
|
+
Persists context for consecutive LLM calls:
|
|
71
|
+
- Conversation history (JSONL format - append-friendly)
|
|
72
|
+
- Agent state
|
|
73
|
+
- Working memory
|
|
74
|
+
- Per-session files in configurable location
|
|
75
|
+
|
|
76
|
+
### 4. Ollama Integration
|
|
77
|
+
|
|
78
|
+
- Assumes Ollama is running externally
|
|
79
|
+
- All configurable parameters exposed
|
|
80
|
+
- Model selection per agent possible
|
|
81
|
+
|
|
82
|
+
### 5. Agent Definitions
|
|
83
|
+
|
|
84
|
+
Markdown files with YAML frontmatter:
|
|
85
|
+
|
|
86
|
+
```markdown
|
|
87
|
+
---
|
|
88
|
+
name: researcher
|
|
89
|
+
description: Research assistant
|
|
90
|
+
tools: List, Read, Search
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
# Researcher Agent
|
|
94
|
+
|
|
95
|
+
You are a research assistant...
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Architecture
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
┌─────────────────────────────────────────────────────────┐
|
|
102
|
+
│ Yoker │
|
|
103
|
+
├─────────────────────────────────────────────────────────┤
|
|
104
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
|
105
|
+
│ │ Config │ │ Context │ │ Logging/ │ │
|
|
106
|
+
│ │ Loader │ │ Manager │ │ Reporting │ │
|
|
107
|
+
│ │ (TOML) │ │ (JSONL) │ │ │ │
|
|
108
|
+
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
|
|
109
|
+
│ │ │ │ │
|
|
110
|
+
│ ▼ ▼ ▼ │
|
|
111
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
112
|
+
│ │ Tool Execution Layer ││
|
|
113
|
+
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌───────┐ ││
|
|
114
|
+
│ │ │List │ │Read │ │Write│ │Update│ │Search│ │Agent │ ││
|
|
115
|
+
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └───────┘ ││
|
|
116
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
117
|
+
│ │ │
|
|
118
|
+
│ ▼ │
|
|
119
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
120
|
+
│ │ Ollama Backend Client ││
|
|
121
|
+
│ │ (HTTP API, configurable parameters) ││
|
|
122
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
123
|
+
└─────────────────────────────────────────────────────────┘
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Project Structure
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
yoker/
|
|
130
|
+
├── src/yoker/ # Main package
|
|
131
|
+
├── tests/ # Test suite
|
|
132
|
+
├── docs/ # Sphinx documentation
|
|
133
|
+
├── examples/ # Example configurations
|
|
134
|
+
├── analysis/ # Functional analysis
|
|
135
|
+
├── pyproject.toml # Package configuration
|
|
136
|
+
└── README.md
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Quick Start
|
|
140
|
+
|
|
141
|
+
### Minimal Prototype
|
|
142
|
+
|
|
143
|
+
The current prototype provides a basic interactive chat with tool calling:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Install
|
|
147
|
+
pip install -e .
|
|
148
|
+
|
|
149
|
+
# Run
|
|
150
|
+
python -m yoker
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Example session:
|
|
154
|
+
```
|
|
155
|
+
Yoker v0.1.0 - Using model: glm-5:cloud
|
|
156
|
+
Type your message and press Enter. Press Ctrl+D to quit.
|
|
157
|
+
|
|
158
|
+
> What's in the README.md file?
|
|
159
|
+
|
|
160
|
+
I'll read the README.md file for you.
|
|
161
|
+
|
|
162
|
+
[13:49:49] INFO yoker.agent - Tool call: read({'path': 'README.md'})
|
|
163
|
+
[13:49:49] INFO yoker.agent - Tool result: # Yoker...
|
|
164
|
+
|
|
165
|
+
The README.md file describes **Yoker**, a Python-based agent harness...
|
|
166
|
+
|
|
167
|
+
> ^D
|
|
168
|
+
Goodbye!
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Planned Full Usage
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Create config
|
|
175
|
+
cat > yoker.toml << EOF
|
|
176
|
+
[ollama]
|
|
177
|
+
model = "llama3.2"
|
|
178
|
+
base_url = "http://localhost:11434"
|
|
179
|
+
|
|
180
|
+
[tools.list]
|
|
181
|
+
allowed_paths = ["/workspace"]
|
|
182
|
+
|
|
183
|
+
[tools.read]
|
|
184
|
+
allowed_paths = ["/workspace"]
|
|
185
|
+
max_size_kb = 100
|
|
186
|
+
|
|
187
|
+
[tools.agent]
|
|
188
|
+
max_recursion_depth = 3
|
|
189
|
+
|
|
190
|
+
[agents]
|
|
191
|
+
directory = "./agents"
|
|
192
|
+
EOF
|
|
193
|
+
|
|
194
|
+
# Create agent definition
|
|
195
|
+
mkdir agents
|
|
196
|
+
cat > agents/main.md << EOF
|
|
197
|
+
---
|
|
198
|
+
name: main
|
|
199
|
+
description: Default assistant
|
|
200
|
+
tools: List, Read, Write, Update, Search, Agent
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
You are a helpful assistant.
|
|
204
|
+
EOF
|
|
205
|
+
|
|
206
|
+
# Run harness (planned)
|
|
207
|
+
yoker --config yoker.toml
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Documentation
|
|
211
|
+
|
|
212
|
+
- Name documentation: `docs/NAME.md`
|
|
213
|
+
- Functional analysis: `analysis/functional.md`
|
|
214
|
+
- Interview notes: `analysis/interview.md`
|
|
215
|
+
|
|
216
|
+
## Integration with Clitic
|
|
217
|
+
|
|
218
|
+
Yoker provides the agent runtime, Clitic provides the TUI:
|
|
219
|
+
|
|
220
|
+
- Build agents using Yoker APIs
|
|
221
|
+
- Optionally add Clitic-based CLI interface
|
|
222
|
+
- Deploy agents with or without UI (daemon mode)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "yoker"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A Python agent harness with configurable tools and guardrails - one who yokes agents together"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Christophe VG", email = "contact@christophe.vg"}
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
24
|
+
"Typing :: Typed",
|
|
25
|
+
]
|
|
26
|
+
keywords = ["agent", "llm", "ollama", "ai", "harness"]
|
|
27
|
+
|
|
28
|
+
dependencies = [
|
|
29
|
+
"httpx>=0.25.0",
|
|
30
|
+
"ollama>=0.6.0",
|
|
31
|
+
"rich>=14.0.0",
|
|
32
|
+
"structlog>=23.0.0",
|
|
33
|
+
"pyyaml>=6.0",
|
|
34
|
+
"tomli>=2.0;python_version<'3.11'",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=7.0.0",
|
|
40
|
+
"pytest-cov>=4.0.0",
|
|
41
|
+
"pytest-asyncio>=0.21.0",
|
|
42
|
+
"mypy>=1.0.0",
|
|
43
|
+
"ruff>=0.1.0",
|
|
44
|
+
"build>=1.0.0",
|
|
45
|
+
"twine>=5.0.0",
|
|
46
|
+
"sphinx>=7.0.0",
|
|
47
|
+
"sphinx-rtd-theme>=2.0.0",
|
|
48
|
+
"myst-parser>=2.0.0",
|
|
49
|
+
"tox>=4.0.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[project.urls]
|
|
53
|
+
Homepage = "https://github.com/christophevg/yoker"
|
|
54
|
+
Documentation = "https://yoker.readthedocs.io/"
|
|
55
|
+
Repository = "https://github.com/christophevg/yoker"
|
|
56
|
+
Issues = "https://github.com/christophevg/yoker/issues"
|
|
57
|
+
|
|
58
|
+
[project.scripts]
|
|
59
|
+
yoker = "yoker.__main__:main"
|
|
60
|
+
|
|
61
|
+
[tool.setuptools.packages.find]
|
|
62
|
+
where = ["src"]
|
|
63
|
+
|
|
64
|
+
[tool.setuptools.package-data]
|
|
65
|
+
yoker = ["py.typed"]
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
testpaths = ["tests"]
|
|
69
|
+
asyncio_mode = "auto"
|
|
70
|
+
addopts = "-v --cov=yoker --cov-report=term-missing"
|
|
71
|
+
|
|
72
|
+
[tool.mypy]
|
|
73
|
+
python_version = "3.10"
|
|
74
|
+
warn_return_any = true
|
|
75
|
+
warn_unused_configs = true
|
|
76
|
+
disallow_untyped_defs = true
|
|
77
|
+
disallow_incomplete_defs = true
|
|
78
|
+
check_untyped_defs = true
|
|
79
|
+
disallow_untyped_decorators = true
|
|
80
|
+
no_implicit_optional = true
|
|
81
|
+
warn_redundant_casts = true
|
|
82
|
+
warn_unused_ignores = true
|
|
83
|
+
warn_no_return = true
|
|
84
|
+
strict_equality = true
|
|
85
|
+
|
|
86
|
+
[tool.ruff]
|
|
87
|
+
line-length = 100
|
|
88
|
+
target-version = "py310"
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint]
|
|
91
|
+
select = [
|
|
92
|
+
"E", # pycodestyle errors
|
|
93
|
+
"W", # pycodestyle warnings
|
|
94
|
+
"F", # pyflakes
|
|
95
|
+
"I", # isort
|
|
96
|
+
"B", # flake8-bugbear
|
|
97
|
+
"C4", # flake8-comprehensions
|
|
98
|
+
"UP", # pyupgrade
|
|
99
|
+
]
|
|
100
|
+
ignore = [
|
|
101
|
+
"E501", # line too long (handled by formatter)
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[tool.ruff.lint.isort]
|
|
105
|
+
known-first-party = ["yoker"]
|
|
106
|
+
|
|
107
|
+
[tool.coverage.run]
|
|
108
|
+
source = ["src"]
|
|
109
|
+
branch = true
|
|
110
|
+
|
|
111
|
+
[tool.coverage.report]
|
|
112
|
+
exclude_lines = [
|
|
113
|
+
"pragma: no cover",
|
|
114
|
+
"def __repr__",
|
|
115
|
+
"raise NotImplementedError",
|
|
116
|
+
"if TYPE_CHECKING:",
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
[tool.tox]
|
|
120
|
+
env_list = ["py310", "py311", "py312"]
|
|
121
|
+
|
|
122
|
+
[tool.tox.env_run_base]
|
|
123
|
+
extras = ["dev"]
|
|
124
|
+
commands = [
|
|
125
|
+
["pytest", "-v", "--cov=yoker", "--cov-report=term-missing"],
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
[tool.tox.env.py310]
|
|
129
|
+
base_python = ["python3.10"]
|
|
130
|
+
|
|
131
|
+
[tool.tox.env.py311]
|
|
132
|
+
base_python = ["python3.11"]
|
|
133
|
+
|
|
134
|
+
[tool.tox.env.py312]
|
|
135
|
+
base_python = ["python3.12"]
|
yoker-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
yoker - A Python agent harness with configurable tools and guardrails.
|
|
3
|
+
|
|
4
|
+
One who yokes - the agent noun from "yoke" (PIE *yeug-* meaning "to join").
|
|
5
|
+
Pairs with "clitic" (both are joining tools).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
__author__ = "Christophe VG"
|
|
10
|
+
|
|
11
|
+
# Public API will be exported here as implementation progresses
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Entry point for running Yoker as a module.
|
|
2
|
+
|
|
3
|
+
Usage: python -m yoker
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
from rich.logging import RichHandler
|
|
9
|
+
|
|
10
|
+
from yoker import __version__
|
|
11
|
+
from yoker.agent import Agent
|
|
12
|
+
|
|
13
|
+
# Configure logging
|
|
14
|
+
logging.basicConfig(
|
|
15
|
+
level=logging.INFO,
|
|
16
|
+
format="%(name)s - %(message)s",
|
|
17
|
+
datefmt="[%X]",
|
|
18
|
+
handlers=[RichHandler()],
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Silence noisy modules
|
|
22
|
+
for module in ["httpx", "httpcore", "ollama"]:
|
|
23
|
+
logging.getLogger(module).setLevel(logging.WARNING)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main() -> None:
|
|
27
|
+
"""Run the interactive agent."""
|
|
28
|
+
print(f"Yoker v{__version__}")
|
|
29
|
+
print("=" * 40)
|
|
30
|
+
Agent().start()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
main()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Minimal Agent implementation for Yoker prototype."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from ollama import Client
|
|
6
|
+
|
|
7
|
+
from yoker.tools import AVAILABLE_TOOLS
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Agent:
|
|
13
|
+
"""Minimal agent that chats with Ollama and uses tools."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, model: str = "glm-5:cloud"):
|
|
16
|
+
self.client = Client()
|
|
17
|
+
self.model = model
|
|
18
|
+
self.tools = AVAILABLE_TOOLS
|
|
19
|
+
|
|
20
|
+
def start(self) -> None:
|
|
21
|
+
"""Start the interactive chat loop."""
|
|
22
|
+
messages: list[dict] = [
|
|
23
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
print(f"Yoker v0.1.0 - Using model: {self.model}")
|
|
27
|
+
print("Type your message and press Enter. Press Ctrl+D (or Ctrl+Z on Windows) to quit.\n")
|
|
28
|
+
|
|
29
|
+
while True:
|
|
30
|
+
try:
|
|
31
|
+
user_input = input("> ")
|
|
32
|
+
except EOFError:
|
|
33
|
+
print("\nGoodbye!")
|
|
34
|
+
break
|
|
35
|
+
|
|
36
|
+
if not user_input.strip():
|
|
37
|
+
continue
|
|
38
|
+
|
|
39
|
+
messages.append({"role": "user", "content": user_input})
|
|
40
|
+
|
|
41
|
+
# Process with model, handling tool calls in a loop
|
|
42
|
+
while True:
|
|
43
|
+
response = self.client.chat(
|
|
44
|
+
model=self.model,
|
|
45
|
+
messages=messages,
|
|
46
|
+
tools=list(self.tools.values()),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Extract response content
|
|
50
|
+
content = response.message.content or ""
|
|
51
|
+
tool_calls = response.message.tool_calls or []
|
|
52
|
+
|
|
53
|
+
# Show assistant response
|
|
54
|
+
if content:
|
|
55
|
+
print(f"\n{content}\n")
|
|
56
|
+
|
|
57
|
+
# If no tool calls, we're done with this turn
|
|
58
|
+
if not tool_calls:
|
|
59
|
+
break
|
|
60
|
+
|
|
61
|
+
# Add assistant message to history
|
|
62
|
+
messages.append({
|
|
63
|
+
"role": "assistant",
|
|
64
|
+
"content": content,
|
|
65
|
+
"tool_calls": tool_calls,
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
# Process tool calls
|
|
69
|
+
for call in tool_calls:
|
|
70
|
+
tool_name = call.function.name
|
|
71
|
+
tool_args = call.function.arguments
|
|
72
|
+
|
|
73
|
+
logger.info(f"Tool call: {tool_name}({tool_args})")
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
result = self.tools[tool_name](**tool_args)
|
|
77
|
+
except KeyError:
|
|
78
|
+
result = f"Error: Unknown tool '{tool_name}'"
|
|
79
|
+
except Exception as e:
|
|
80
|
+
result = f"Error executing tool: {e}"
|
|
81
|
+
|
|
82
|
+
logger.info(f"Tool result: {result[:100]}...")
|
|
83
|
+
|
|
84
|
+
# Add tool result to messages
|
|
85
|
+
messages.append({
|
|
86
|
+
"role": "tool",
|
|
87
|
+
"name": tool_name,
|
|
88
|
+
"content": str(result),
|
|
89
|
+
})
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Minimal tools for Yoker prototype."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def read(path: str) -> str:
|
|
7
|
+
"""Read the content of a file.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
path: The path to the file to read.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
The content of the file.
|
|
14
|
+
"""
|
|
15
|
+
try:
|
|
16
|
+
return Path(path).read_text()
|
|
17
|
+
except FileNotFoundError:
|
|
18
|
+
return f"Error: File not found: {path}"
|
|
19
|
+
except Exception as e:
|
|
20
|
+
return f"Error reading file: {e}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Tool registry - maps tool names to functions
|
|
24
|
+
AVAILABLE_TOOLS = {
|
|
25
|
+
"read": read,
|
|
26
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yoker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Python agent harness with configurable tools and guardrails - one who yokes agents together
|
|
5
|
+
Author-email: Christophe VG <contact@christophe.vg>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/christophevg/yoker
|
|
8
|
+
Project-URL: Documentation, https://yoker.readthedocs.io/
|
|
9
|
+
Project-URL: Repository, https://github.com/christophevg/yoker
|
|
10
|
+
Project-URL: Issues, https://github.com/christophevg/yoker/issues
|
|
11
|
+
Keywords: agent,llm,ollama,ai,harness
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Requires-Dist: ollama>=0.6.0
|
|
25
|
+
Requires-Dist: rich>=14.0.0
|
|
26
|
+
Requires-Dist: structlog>=23.0.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: sphinx>=7.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: myst-parser>=2.0.0; extra == "dev"
|
|
40
|
+
Requires-Dist: tox>=4.0.0; extra == "dev"
|
|
41
|
+
|
|
42
|
+
# Yoker
|
|
43
|
+
|
|
44
|
+
A Python-based agent harness with configurable tools, guardrails, and Ollama backend integration.
|
|
45
|
+
|
|
46
|
+
## Current Status
|
|
47
|
+
|
|
48
|
+
**Minimal prototype available!** The basic chat loop with tool calling is working:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Install (requires Python 3.10+)
|
|
52
|
+
pip install -e .
|
|
53
|
+
|
|
54
|
+
# Run interactive chat
|
|
55
|
+
python -m yoker
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The prototype includes:
|
|
59
|
+
- Interactive chat loop with Ollama
|
|
60
|
+
- Basic `read` tool for file reading
|
|
61
|
+
- Streaming responses
|
|
62
|
+
- Structured logging
|
|
63
|
+
|
|
64
|
+
See [Quick Start](#quick-start) below for details.
|
|
65
|
+
|
|
66
|
+
## Name
|
|
67
|
+
|
|
68
|
+
**"yoker"** - One who yokes. A person or device that joins or attaches things together, specifically one who yokes oxen or links things together.
|
|
69
|
+
|
|
70
|
+
From the agent noun of "yoke", which derives from PIE *\yeug-* meaning "to join" (same root as yoga, conjugate, junction).
|
|
71
|
+
|
|
72
|
+
Pairs beautifully with "clitic" (both are joining tools - clitic joins words, yoker joins agents).
|
|
73
|
+
|
|
74
|
+
See `docs/NAME.md` for full naming documentation.
|
|
75
|
+
|
|
76
|
+
## Vision
|
|
77
|
+
|
|
78
|
+
Create a lightweight, configurable agent harness that provides a structured environment for AI agents to operate within defined boundaries. The harness manages tool access, enforces guardrails, handles context persistence, and integrates with Ollama as the LLM backend.
|
|
79
|
+
|
|
80
|
+
## Goals
|
|
81
|
+
|
|
82
|
+
1. **Safety First**: Guardrails prevent agents from performing unintended operations
|
|
83
|
+
2. **Configurability**: All tools, parameters, and limits configurable via TOML
|
|
84
|
+
3. **Simplicity**: Specific tools instead of generic shell access
|
|
85
|
+
4. **Transparency**: Clear logging and reporting of all agent actions
|
|
86
|
+
5. **Extensibility**: Easy to add new tools while maintaining guardrails
|
|
87
|
+
6. **Compatibility**: Agent definitions compatible with Claude Code format
|
|
88
|
+
|
|
89
|
+
## Core Components
|
|
90
|
+
|
|
91
|
+
### 1. Configuration System
|
|
92
|
+
|
|
93
|
+
- **TOML configuration file**: Harness settings, tool guardrails, Ollama parameters
|
|
94
|
+
- **Markdown agent definitions**: With YAML frontmatter (compatible with Claude Code)
|
|
95
|
+
|
|
96
|
+
### 2. Tool System
|
|
97
|
+
|
|
98
|
+
MVP tools (no generic Bash):
|
|
99
|
+
|
|
100
|
+
| Tool | Purpose | Guardrails |
|
|
101
|
+
|------|---------|------------|
|
|
102
|
+
| List | Directory listing | Path restrictions, pattern filters |
|
|
103
|
+
| Read | File reading | Path restrictions, size limits |
|
|
104
|
+
| Write | File writing | Path restrictions, overwrite protection |
|
|
105
|
+
| Update | File editing | Path restrictions, diff validation |
|
|
106
|
+
| Search | Grep/glob-like | Path restrictions, pattern limits |
|
|
107
|
+
| Agent | Spawn subagents | Recursion depth, tool subset |
|
|
108
|
+
|
|
109
|
+
### 3. Context Manager
|
|
110
|
+
|
|
111
|
+
Persists context for consecutive LLM calls:
|
|
112
|
+
- Conversation history (JSONL format - append-friendly)
|
|
113
|
+
- Agent state
|
|
114
|
+
- Working memory
|
|
115
|
+
- Per-session files in configurable location
|
|
116
|
+
|
|
117
|
+
### 4. Ollama Integration
|
|
118
|
+
|
|
119
|
+
- Assumes Ollama is running externally
|
|
120
|
+
- All configurable parameters exposed
|
|
121
|
+
- Model selection per agent possible
|
|
122
|
+
|
|
123
|
+
### 5. Agent Definitions
|
|
124
|
+
|
|
125
|
+
Markdown files with YAML frontmatter:
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
---
|
|
129
|
+
name: researcher
|
|
130
|
+
description: Research assistant
|
|
131
|
+
tools: List, Read, Search
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# Researcher Agent
|
|
135
|
+
|
|
136
|
+
You are a research assistant...
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Architecture
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
┌─────────────────────────────────────────────────────────┐
|
|
143
|
+
│ Yoker │
|
|
144
|
+
├─────────────────────────────────────────────────────────┤
|
|
145
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
|
146
|
+
│ │ Config │ │ Context │ │ Logging/ │ │
|
|
147
|
+
│ │ Loader │ │ Manager │ │ Reporting │ │
|
|
148
|
+
│ │ (TOML) │ │ (JSONL) │ │ │ │
|
|
149
|
+
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
|
|
150
|
+
│ │ │ │ │
|
|
151
|
+
│ ▼ ▼ ▼ │
|
|
152
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
153
|
+
│ │ Tool Execution Layer ││
|
|
154
|
+
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌───────┐ ││
|
|
155
|
+
│ │ │List │ │Read │ │Write│ │Update│ │Search│ │Agent │ ││
|
|
156
|
+
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └───────┘ ││
|
|
157
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
158
|
+
│ │ │
|
|
159
|
+
│ ▼ │
|
|
160
|
+
│ ┌─────────────────────────────────────────────────────┐│
|
|
161
|
+
│ │ Ollama Backend Client ││
|
|
162
|
+
│ │ (HTTP API, configurable parameters) ││
|
|
163
|
+
│ └─────────────────────────────────────────────────────┘│
|
|
164
|
+
└─────────────────────────────────────────────────────────┘
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Project Structure
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
yoker/
|
|
171
|
+
├── src/yoker/ # Main package
|
|
172
|
+
├── tests/ # Test suite
|
|
173
|
+
├── docs/ # Sphinx documentation
|
|
174
|
+
├── examples/ # Example configurations
|
|
175
|
+
├── analysis/ # Functional analysis
|
|
176
|
+
├── pyproject.toml # Package configuration
|
|
177
|
+
└── README.md
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Quick Start
|
|
181
|
+
|
|
182
|
+
### Minimal Prototype
|
|
183
|
+
|
|
184
|
+
The current prototype provides a basic interactive chat with tool calling:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Install
|
|
188
|
+
pip install -e .
|
|
189
|
+
|
|
190
|
+
# Run
|
|
191
|
+
python -m yoker
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Example session:
|
|
195
|
+
```
|
|
196
|
+
Yoker v0.1.0 - Using model: glm-5:cloud
|
|
197
|
+
Type your message and press Enter. Press Ctrl+D to quit.
|
|
198
|
+
|
|
199
|
+
> What's in the README.md file?
|
|
200
|
+
|
|
201
|
+
I'll read the README.md file for you.
|
|
202
|
+
|
|
203
|
+
[13:49:49] INFO yoker.agent - Tool call: read({'path': 'README.md'})
|
|
204
|
+
[13:49:49] INFO yoker.agent - Tool result: # Yoker...
|
|
205
|
+
|
|
206
|
+
The README.md file describes **Yoker**, a Python-based agent harness...
|
|
207
|
+
|
|
208
|
+
> ^D
|
|
209
|
+
Goodbye!
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Planned Full Usage
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Create config
|
|
216
|
+
cat > yoker.toml << EOF
|
|
217
|
+
[ollama]
|
|
218
|
+
model = "llama3.2"
|
|
219
|
+
base_url = "http://localhost:11434"
|
|
220
|
+
|
|
221
|
+
[tools.list]
|
|
222
|
+
allowed_paths = ["/workspace"]
|
|
223
|
+
|
|
224
|
+
[tools.read]
|
|
225
|
+
allowed_paths = ["/workspace"]
|
|
226
|
+
max_size_kb = 100
|
|
227
|
+
|
|
228
|
+
[tools.agent]
|
|
229
|
+
max_recursion_depth = 3
|
|
230
|
+
|
|
231
|
+
[agents]
|
|
232
|
+
directory = "./agents"
|
|
233
|
+
EOF
|
|
234
|
+
|
|
235
|
+
# Create agent definition
|
|
236
|
+
mkdir agents
|
|
237
|
+
cat > agents/main.md << EOF
|
|
238
|
+
---
|
|
239
|
+
name: main
|
|
240
|
+
description: Default assistant
|
|
241
|
+
tools: List, Read, Write, Update, Search, Agent
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
You are a helpful assistant.
|
|
245
|
+
EOF
|
|
246
|
+
|
|
247
|
+
# Run harness (planned)
|
|
248
|
+
yoker --config yoker.toml
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Documentation
|
|
252
|
+
|
|
253
|
+
- Name documentation: `docs/NAME.md`
|
|
254
|
+
- Functional analysis: `analysis/functional.md`
|
|
255
|
+
- Interview notes: `analysis/interview.md`
|
|
256
|
+
|
|
257
|
+
## Integration with Clitic
|
|
258
|
+
|
|
259
|
+
Yoker provides the agent runtime, Clitic provides the TUI:
|
|
260
|
+
|
|
261
|
+
- Build agents using Yoker APIs
|
|
262
|
+
- Optionally add Clitic-based CLI interface
|
|
263
|
+
- Deploy agents with or without UI (daemon mode)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/yoker/__init__.py
|
|
4
|
+
src/yoker/__main__.py
|
|
5
|
+
src/yoker/agent.py
|
|
6
|
+
src/yoker/py.typed
|
|
7
|
+
src/yoker/tools.py
|
|
8
|
+
src/yoker.egg-info/PKG-INFO
|
|
9
|
+
src/yoker.egg-info/SOURCES.txt
|
|
10
|
+
src/yoker.egg-info/dependency_links.txt
|
|
11
|
+
src/yoker.egg-info/entry_points.txt
|
|
12
|
+
src/yoker.egg-info/requires.txt
|
|
13
|
+
src/yoker.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
httpx>=0.25.0
|
|
2
|
+
ollama>=0.6.0
|
|
3
|
+
rich>=14.0.0
|
|
4
|
+
structlog>=23.0.0
|
|
5
|
+
pyyaml>=6.0
|
|
6
|
+
|
|
7
|
+
[:python_version < "3.11"]
|
|
8
|
+
tomli>=2.0
|
|
9
|
+
|
|
10
|
+
[dev]
|
|
11
|
+
pytest>=7.0.0
|
|
12
|
+
pytest-cov>=4.0.0
|
|
13
|
+
pytest-asyncio>=0.21.0
|
|
14
|
+
mypy>=1.0.0
|
|
15
|
+
ruff>=0.1.0
|
|
16
|
+
build>=1.0.0
|
|
17
|
+
twine>=5.0.0
|
|
18
|
+
sphinx>=7.0.0
|
|
19
|
+
sphinx-rtd-theme>=2.0.0
|
|
20
|
+
myst-parser>=2.0.0
|
|
21
|
+
tox>=4.0.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
yoker
|