agent-chief 0.3.1__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.
- agent_chief-0.3.1.dist-info/METADATA +324 -0
- agent_chief-0.3.1.dist-info/RECORD +83 -0
- agent_chief-0.3.1.dist-info/WHEEL +4 -0
- agent_chief-0.3.1.dist-info/entry_points.txt +2 -0
- agent_chief-0.3.1.dist-info/licenses/LICENSE +21 -0
- cli/__init__.py +0 -0
- cli/connect.py +142 -0
- cli/init.py +201 -0
- cli/main.py +435 -0
- cli/runtime.py +262 -0
- context/__init__.py +0 -0
- context/infer.py +110 -0
- context/providers/__init__.py +0 -0
- context/providers/calendar.py +101 -0
- context/providers/clock.py +28 -0
- core/__init__.py +0 -0
- core/brain.py +403 -0
- core/config.py +36 -0
- core/digest.py +107 -0
- core/embedding.py +77 -0
- core/learner.py +246 -0
- core/policy.py +109 -0
- core/schema.py +96 -0
- core/scorer.py +256 -0
- core/state.py +292 -0
- delivery/__init__.py +0 -0
- delivery/base.py +69 -0
- delivery/desktop.py +31 -0
- delivery/telegram.py +90 -0
- delivery/terminal.py +17 -0
- demo/__init__.py +0 -0
- demo/day_of_engineer.json +642 -0
- demo/runner.py +255 -0
- dispatch/__init__.py +0 -0
- dispatch/acceptance.py +88 -0
- dispatch/executor.py +133 -0
- eval/__init__.py +6 -0
- eval/generate_golden.py +269 -0
- eval/golden.jsonl +201 -0
- eval/learning.py +185 -0
- eval/reports/.gitkeep +0 -0
- eval/reports/learning.md +34 -0
- eval/runner.py +222 -0
- ingest/__init__.py +0 -0
- ingest/connectors/__init__.py +38 -0
- ingest/connectors/composio.py +106 -0
- ingest/http.py +219 -0
- ingest/mcp_server.py +65 -0
- ingest/normalize.py +55 -0
- ingest/sources/__init__.py +0 -0
- ingest/sources/base.py +51 -0
- ingest/sources/github.py +43 -0
- ingest/sources/rss.py +52 -0
- judge/__init__.py +0 -0
- judge/anthropic.py +35 -0
- judge/base.py +150 -0
- judge/deepseek.py +8 -0
- judge/factory.py +50 -0
- judge/fixtures.py +26 -0
- judge/ollama.py +27 -0
- judge/openai.py +31 -0
- judge/pricing.py +53 -0
- judge/prompts.py +97 -0
- judge/templates/v1/context.j2 +3 -0
- judge/templates/v1/distill.j2 +4 -0
- judge/templates/v1/retry.j2 +1 -0
- judge/templates/v1/system.j2 +12 -0
- judge/templates/v1/topic_infer.j2 +2 -0
- judge/templates/v1/user.j2 +2 -0
- judge/templates/v1/verify.j2 +4 -0
- memory/__init__.py +0 -0
- memory/associate.py +33 -0
- memory/store.py +62 -0
- policy/POLICY.template.md +9 -0
- policy/USER.template.md +3 -0
- policy/__init__.py +0 -0
- skills/__init__.py +0 -0
- skills/claude-code/SKILL.md +56 -0
- skills/openclaw/SKILL.md +56 -0
- skills/openclaw/__init__.py +0 -0
- skills/openclaw/hook.py +74 -0
- ui/__init__.py +6 -0
- ui/console.html +191 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-chief
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Chief — the chief of staff for your agents and information sources
|
|
5
|
+
Project-URL: Homepage, https://github.com/SmileLikeYe/agent-chief
|
|
6
|
+
Project-URL: Repository, https://github.com/SmileLikeYe/agent-chief
|
|
7
|
+
Project-URL: Issues, https://github.com/SmileLikeYe/agent-chief/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/SmileLikeYe/agent-chief/releases
|
|
9
|
+
Author: SmileLikeYe
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: agents,attention,chief-of-staff,interruption-management,llm,local-first,mcp,notifications,triage
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Communications
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: aiosqlite>=0.22.1
|
|
24
|
+
Requires-Dist: fastapi>=0.139.0
|
|
25
|
+
Requires-Dist: fastmcp>=3.4.2
|
|
26
|
+
Requires-Dist: httpx>=0.28.1
|
|
27
|
+
Requires-Dist: jinja2>=3.1
|
|
28
|
+
Requires-Dist: plyer>=2.1.0
|
|
29
|
+
Requires-Dist: pydantic>=2.7
|
|
30
|
+
Requires-Dist: questionary>=2.1.1
|
|
31
|
+
Requires-Dist: rich>=13.7
|
|
32
|
+
Requires-Dist: typer>=0.12
|
|
33
|
+
Requires-Dist: uvicorn>=0.50.0
|
|
34
|
+
Provides-Extra: embeddings
|
|
35
|
+
Requires-Dist: sentence-transformers>=3.0; extra == 'embeddings'
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
<div align="center">
|
|
39
|
+
|
|
40
|
+
<img src="docs/assets/logo.svg" alt="Chief" width="640"/>
|
|
41
|
+
|
|
42
|
+
**Your agents don't need more power. They need a chief of staff.**
|
|
43
|
+
|
|
44
|
+
[](https://github.com/SmileLikeYe/agent-chief/actions/workflows/ci.yml)
|
|
45
|
+
[](https://github.com/SmileLikeYe/agent-chief/releases)
|
|
46
|
+
[](pyproject.toml)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
[](https://github.com/astral-sh/ruff)
|
|
49
|
+
[](#privacy)
|
|
50
|
+
|
|
51
|
+
[Quickstart](#-60-second-quickstart) · [How it works](#-how-it-decides) ·
|
|
52
|
+
[Connect your agent](#-connect-your-agent-3-lines) · [Docs](docs/) ·
|
|
53
|
+
[简体中文](README.zh-CN.md)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
<!-- metrics:start -->
|
|
60
|
+
**24 events in → 1 interruption** (96% intercepted: 14 blocked outright, the rest batched, dispatched, or remembered)
|
|
61
|
+
· only **75% of events ever reach the LLM** — the noisiest 25% dies on hard rules in microseconds, for free
|
|
62
|
+
· stable-prefix prompts: **70% of judge input tokens cache-hit** (system + context blocks)
|
|
63
|
+
· projected judgment cost **$0.104 per 1,000 events** (DeepSeek list prices, cache-aware)
|
|
64
|
+
|
|
65
|
+
*(every number regenerates from the deterministic demo replay: `make readme-metrics`)*
|
|
66
|
+
<!-- metrics:end -->
|
|
67
|
+
|
|
68
|
+
Chief sits between you and everything that wants your attention — agents,
|
|
69
|
+
heartbeats, CI, RSS, watchers. Everything flows into it; it thinks for itself;
|
|
70
|
+
then it does exactly one of three things:
|
|
71
|
+
|
|
72
|
+
1. 🔔 **Interrupt** you — only when worth it, at the right moment, *arriving with a plan*.
|
|
73
|
+
2. 🤖 **Dispatch** work to your agents — and verify the result before reporting ("done" is a claim, not a proof).
|
|
74
|
+
3. 📚 **Curate** into memory — facts and intents not worth mentioning now, waiting to be connected later.
|
|
75
|
+
|
|
76
|
+
<div align="center">
|
|
77
|
+
|
|
78
|
+

|
|
79
|
+
|
|
80
|
+
*A day of an engineer's life: 24 events in → 14 blocked · 6 batched · 3 handled · **interrupted exactly once**.*
|
|
81
|
+
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
## ✨ Highlights
|
|
85
|
+
|
|
86
|
+
| | |
|
|
87
|
+
|---|---|
|
|
88
|
+
| 🧠 **Three-stage worthiness engine** | Hard rules (µs) → similarity classifier (ms) → LLM judge (only when needed). Cheap first, smart last. |
|
|
89
|
+
| 🎭 **Scene-aware timing** | Sleeping / deep work / meeting / commute — per-scene interrupt thresholds. The *same* event rings at your desk and waits in a digest at 2 AM. |
|
|
90
|
+
| 🕶️ **Shadow mode** | For its first 7 days Chief never actually interrupts — it shows you what it *would* have done, and earns the right to ring. |
|
|
91
|
+
| 📝 **Explainable, editable policy** | Everything it learns distills nightly into a human-readable `POLICY.md`. Your edits win, effective immediately. |
|
|
92
|
+
| ✅ **Verified dispatch** | Agents report "done"; Chief checks. Acceptance command or LLM second opinion — fails closed. |
|
|
93
|
+
| 🔌 **Protocol, not pipes** | One `POST /v1/events` (or MCP `propose`) connects anything in minutes. |
|
|
94
|
+
| 🔒 **Local-first** | One SQLite file + markdown under `~/.chief`. No cloud, no telemetry, no web UI. |
|
|
95
|
+
|
|
96
|
+
## ⚡ 60-second quickstart
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uvx agent-chief demo # zero keys, zero config, fully offline
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You'll watch a day of an engineer's life replay: 24 events in → 14 blocked ·
|
|
103
|
+
6 batched · 3 handled (all verified) · **interrupted exactly once**.
|
|
104
|
+
|
|
105
|
+
Ready for real sources?
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
uvx agent-chief init # 60s wizard, every question skippable
|
|
109
|
+
chief run # the resident brain
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 🔕 Kill the "all clear" reports
|
|
113
|
+
|
|
114
|
+
If you run heartbeat agents, you know the ritual: *"All clear, nothing to
|
|
115
|
+
report."* Every few hours. Forever. Each one costs a glance, and the glances
|
|
116
|
+
add up until you stop reading — including the one that mattered.
|
|
117
|
+
|
|
118
|
+
Chief drops zero-information reports on the floor (regex **and** embedding
|
|
119
|
+
similarity against a canned empty-report set, both required — a security scan
|
|
120
|
+
that *mentions* "all clear" still gets through). The demo opens and closes with
|
|
121
|
+
this, because it's the single most requested feature among heartbeat users.
|
|
122
|
+
|
|
123
|
+
## 🔍 Explainable judgment, every single time
|
|
124
|
+
|
|
125
|
+
No decision is a black box. Every Decision carries its **reason, five scored
|
|
126
|
+
components, the rules it matched, and what it cost** — and `chief trace`
|
|
127
|
+
replays the whole chain after the fact:
|
|
128
|
+
|
|
129
|
+
```console
|
|
130
|
+
$ chief trace evt_20260706_1040_ab12
|
|
131
|
+
CI failed on main: test_auth_flow broken by PR #482 dev.ci · github-actions
|
|
132
|
+
route dispatch at stage 3 in scene deep_work (confidence 0.85)
|
|
133
|
+
score 0.87 urgency=0.90 relevance=0.90 actionability=0.85 novelty=0.80 confidence=0.90
|
|
134
|
+
┌────────────┬───────┬──────────────────────┐
|
|
135
|
+
│ stage │ ms │ note │
|
|
136
|
+
│ stage1 │ 0.1 │ no hard rule fired │
|
|
137
|
+
│ associate │ 1.2 │ 0 memory hits │
|
|
138
|
+
│ judge │ 812.4 │ backend deepseek │
|
|
139
|
+
│ route │ 0.3 │ routed dispatch │
|
|
140
|
+
└────────────┴───────┴──────────────────────┘
|
|
141
|
+
tokens: 1104 in (704 cached) / 96 out · prompt v1 · cost $0.000301
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Prompts are versioned templates (`judge/templates/v1/`), the version is
|
|
145
|
+
stamped into every decision, and **no prompt change merges without an eval
|
|
146
|
+
diff** on the 200-case golden set (`chief eval --compare v1 v2`). If the LLM
|
|
147
|
+
backend dies, Chief degrades to rules-only conservative routing — never
|
|
148
|
+
interrupts while blind — and heals itself when the backend returns.
|
|
149
|
+
|
|
150
|
+
## 📈 It learns your preferences — and proves it
|
|
151
|
+
|
|
152
|
+
The 👍/👎 you give ("worth my attention" / "don't bother me") is a reward
|
|
153
|
+
signal; the per-topic EMA weights are the policy; feedback trains them. Chief
|
|
154
|
+
ships an eval that measures the loop closing — a simulated user with hidden
|
|
155
|
+
preferences, corrected only by the ±1 signal:
|
|
156
|
+
|
|
157
|
+
```console
|
|
158
|
+
$ chief eval --learning
|
|
159
|
+
Routing agreement: 0% → 100% (+100%) · converged in 2 rounds
|
|
160
|
+
r 0 | | 0%
|
|
161
|
+
r 1 |█████████████████ | 86%
|
|
162
|
+
r 2 |████████████████████| 100%
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
No labels, no gradient, no black box (SPEC §13: explainable by construction).
|
|
166
|
+
It corrects the *borderline* calls — the ones that actually need judgment,
|
|
167
|
+
since stage-1 rules already handle the obvious. Watch the learned per-topic
|
|
168
|
+
lean in the console's **Learning** tab, or reproduce the curve with
|
|
169
|
+
`chief eval --learning`.
|
|
170
|
+
|
|
171
|
+
> 📝 The engineering story behind Chief — the funnel, per-model cost accounting,
|
|
172
|
+
> and the falsifiable learning loop — is written up in
|
|
173
|
+
> **[docs/blog](docs/blog/heartbeat-agents-are-training-you-to-ignore-them.md)**.
|
|
174
|
+
|
|
175
|
+
## 🕶️ Shadow mode: trust is earned
|
|
176
|
+
|
|
177
|
+
For its first 7 days (or 50 graded samples), Chief **never actually interrupts
|
|
178
|
+
you**. Would-be interrupts land in the digest annotated
|
|
179
|
+
`⚡ would have: interrupted you (score 0.87, scene deep_work)` with ✓/✗ grading
|
|
180
|
+
buttons. You watch it think, grade its calls, and only when it graduates does it
|
|
181
|
+
earn the right to ring. Graduation comes with a **Tact Report** (`chief report`).
|
|
182
|
+
|
|
183
|
+
## 🧠 How it decides
|
|
184
|
+
|
|
185
|
+
Two axes, never one: **content worthiness × scene tolerance**.
|
|
186
|
+
|
|
187
|
+
```mermaid
|
|
188
|
+
flowchart LR
|
|
189
|
+
subgraph sources [Anything]
|
|
190
|
+
A1[Agents] & A2[CI / GitHub] & A3[RSS / watchers] & A4[Heartbeats]
|
|
191
|
+
end
|
|
192
|
+
sources -->|"POST /v1/events · MCP propose"| N[Normalize<br/>+ topic inference]
|
|
193
|
+
N --> S1{"Stage 1<br/>hard rules (µs)"}
|
|
194
|
+
S1 -->|survives| S2{"Stage 2<br/>similarity (ms)"}
|
|
195
|
+
S2 -->|unfamiliar| M[Associate<br/>memory] --> S3{"Stage 3<br/>LLM judge"}
|
|
196
|
+
S3 --> R["score × scene<br/>threshold"]
|
|
197
|
+
S2 -->|familiar| R
|
|
198
|
+
R --> I[🔔 interrupt]
|
|
199
|
+
R --> D[📰 digest]
|
|
200
|
+
R --> P[🤖 dispatch → verify] --> I
|
|
201
|
+
R --> C[📚 curate]
|
|
202
|
+
R --> X[🗑 drop]
|
|
203
|
+
SC["Scene engine<br/>clock · calendar · focus"] -.-> R
|
|
204
|
+
L["Learner<br/>EMA · nightly distill"] -.-> S1 & S2 & R
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
- A three-stage worthiness engine: hard rules (µs) → similarity classifier (ms)
|
|
208
|
+
→ LLM judge (pluggable: **Ollama local**, DeepSeek, Anthropic, OpenAI).
|
|
209
|
+
- A scene engine (clock, calendar, focus, lock state — pluggable providers)
|
|
210
|
+
with per-scene interrupt thresholds; low-confidence scenes degrade toward silence.
|
|
211
|
+
- Every learned preference distills nightly into a **human-readable
|
|
212
|
+
[`POLICY.md`](policy/POLICY.template.md)** you can read and edit; your edits
|
|
213
|
+
win, effective immediately.
|
|
214
|
+
|
|
215
|
+
Deep dive: **[docs/architecture.md](docs/architecture.md)**.
|
|
216
|
+
|
|
217
|
+
## 🔌 Connect your agent (3 lines)
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
curl -X POST http://localhost:8787/v1/events \
|
|
221
|
+
-H "Authorization: Bearer $CHIEF_TOKEN" -H "Content-Type: application/json" \
|
|
222
|
+
-d '{"source":"my-agent","topic":"dev.ci","summary":"CI failed on main"}'
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Chief answers with a Decision — route, score, and a one-line reason. MCP agents
|
|
226
|
+
use the `propose` tool instead, and `chief lite` gives zero-daemon judgment for
|
|
227
|
+
one-shot callers. Full contract: **[docs/protocol.md](docs/protocol.md)**
|
|
228
|
+
· runnable samples: **[examples/](examples/)**.
|
|
229
|
+
|
|
230
|
+
## 🖥️ The console — see it think, correct it in one click
|
|
231
|
+
|
|
232
|
+
`chief ui` (or the resident `chief run`) serves a local console at
|
|
233
|
+
`http://127.0.0.1:8787/ui` — single user, token-gated, no cloud:
|
|
234
|
+
|
|
235
|
+
- **Today** — digest queue, interrupts, LLM share and spend at a glance
|
|
236
|
+
- **History** — every decision with its reason, score, cost; searchable
|
|
237
|
+
- **Rules** — edit `POLICY.md` in place; your edits win, live immediately
|
|
238
|
+
- **Tasks** — approve/reject dispatched work (verification still applies)
|
|
239
|
+
- **👍/👎 on every decision** — "worth my attention" / "don't bother me";
|
|
240
|
+
Chief's learner weighs these above every inferred signal
|
|
241
|
+
|
|
242
|
+
<!-- console screenshot: docs/assets/console.png (make console-shot) -->
|
|
243
|
+
|
|
244
|
+
## 🔌 Out-of-the-box sources
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
chief connect composio --secret whsec_… # GitHub, Gmail, Slack, 500+ apps
|
|
248
|
+
chief connect github # gh notifications poller
|
|
249
|
+
chief connect rss --url https://hnrss.org/frontpage
|
|
250
|
+
chief sources # see what's wired up
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**[Composio](https://composio.dev)** is the flagship connector: point its
|
|
254
|
+
trigger webhooks at `/v1/connectors/composio` (HMAC-verified) and every
|
|
255
|
+
connected app flows through Chief's judgment. The connector registry leaves
|
|
256
|
+
documented slots for zapier/n8n-style automations and MCP-push agents — one
|
|
257
|
+
adapter module each.
|
|
258
|
+
|
|
259
|
+
## 🧩 Skills: make your agents good citizens
|
|
260
|
+
|
|
261
|
+
Drop-in skills teach agent hosts to route through Chief instead of pinging you:
|
|
262
|
+
|
|
263
|
+
- **[skills/claude-code/](skills/claude-code/SKILL.md)** — Claude Code agents
|
|
264
|
+
propose via `chief lite` (no daemon needed) and obey the route.
|
|
265
|
+
- **[skills/openclaw/](skills/openclaw/SKILL.md)** — OpenClaw agents propose
|
|
266
|
+
via MCP; interrupts ride OpenClaw's own channels back to you.
|
|
267
|
+
|
|
268
|
+
Both encode the same iron rule: *the agent MUST NOT message the user directly.*
|
|
269
|
+
|
|
270
|
+
## 🔗 Integrations: Chief as the judgment layer
|
|
271
|
+
|
|
272
|
+
Noisy upstream bots in, one accountable judgment layer in the middle:
|
|
273
|
+
**[examples/integrations/](examples/integrations/)** ships a runnable
|
|
274
|
+
stock-analysis-bot feed (watch five "all good" reports die and three real
|
|
275
|
+
findings survive) and a generic webhook template any agent can copy — both
|
|
276
|
+
fully offline.
|
|
277
|
+
|
|
278
|
+
## 📁 Project layout
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
core/ brain loop, 3-stage scorer, learner, digest, SQLite state
|
|
282
|
+
context/ scene engine + providers (clock, calendar)
|
|
283
|
+
judge/ pluggable LLM judges: ollama · deepseek · anthropic · openai · fixtures
|
|
284
|
+
ingest/ webhook (FastAPI), MCP server, GitHub/RSS pollers, normalizer
|
|
285
|
+
dispatch/ executors (claude-code, whitelisted shell) + verification
|
|
286
|
+
delivery/ terminal · desktop · telegram (feedback buttons)
|
|
287
|
+
memory/ curate, associate, expire → archive
|
|
288
|
+
demo/ the offline day-of-engineer replay fixture + runner
|
|
289
|
+
skills/ OpenClaw integration (propose-and-obey)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## 🧪 Quality
|
|
293
|
+
|
|
294
|
+
218 tests run fully offline — no keys, no network. The demo's routing table is
|
|
295
|
+
a full-table regression: all 24 events' routes are pinned in CI forever.
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
make test lint # pytest + ruff
|
|
299
|
+
make demo # the offline replay
|
|
300
|
+
make release-check # build the wheel, run the demo from it via uvx
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## 🗺 Roadmap & contributing
|
|
304
|
+
|
|
305
|
+
See [ROADMAP.md](ROADMAP.md) for what's deliberately out of v1 (web UI, cloud
|
|
306
|
+
sync, Slack/Discord delivery, …) and [CONTRIBUTING.md](CONTRIBUTING.md) to get
|
|
307
|
+
hacking — the dev loop is `uv sync --dev && make test`. Design decisions live
|
|
308
|
+
as one-line ADRs in [docs/decisions.md](docs/decisions.md);
|
|
309
|
+
[SPEC.md](SPEC.md) is the full implementation spec the project was built from,
|
|
310
|
+
step by step ([PROGRESS.md](PROGRESS.md)).
|
|
311
|
+
|
|
312
|
+
## 🔒 Privacy
|
|
313
|
+
|
|
314
|
+
Local-first by construction: one SQLite file + markdown under `~/.chief`.
|
|
315
|
+
No cloud, no telemetry, no web UI, no arbitrary shell execution. The only
|
|
316
|
+
network calls are the ones you configure (your LLM backend, your Telegram bot).
|
|
317
|
+
|
|
318
|
+
## ⭐ Star history
|
|
319
|
+
|
|
320
|
+
[](https://star-history.com/#SmileLikeYe/agent-chief&Date)
|
|
321
|
+
|
|
322
|
+
## 📄 License
|
|
323
|
+
|
|
324
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cli/connect.py,sha256=hkAdy9TJWzFr53cWu8rvAnhnTxOjEP_lrZYi9sWBQBk,5278
|
|
3
|
+
cli/init.py,sha256=2rDr4001gY3VQfQY-XUHMFM_TWj4LobY9sbnaQsD7_U,6176
|
|
4
|
+
cli/main.py,sha256=pNIrhXaqRyRcS7IkzD_FSdEdg2EyJklo7wcD0uumCII,14557
|
|
5
|
+
cli/runtime.py,sha256=M3kcvhRb78bWyPbf1771J-1EaZCWcJ75omq_ISXxf_Q,9606
|
|
6
|
+
context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
context/infer.py,sha256=nN5eGffD7TVg0cfmgsR-1cMAY9BJC2YmMAIw34Ov5Fs,3915
|
|
8
|
+
context/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
context/providers/calendar.py,sha256=RncSzwbJjfmm1yWcnvhKQPNDmHE3gVe4l2ystISdnb4,3098
|
|
10
|
+
context/providers/clock.py,sha256=stB0LdmXgVGB44cVQ97Zn275bqSzGxDxZc6B0suREeQ,748
|
|
11
|
+
core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
core/brain.py,sha256=addobzmXF24OUxor8wtg7VPHM7v4aKh_OYTgbKq0f34,16081
|
|
13
|
+
core/config.py,sha256=-vw3XBJf4aK-NsF3aitTErGsbe-K3gMviCgL45HK908,740
|
|
14
|
+
core/digest.py,sha256=3i61wOyMoxjMngUmXe6ytXRgG3Re0v9gzA9a4T4Hr5Y,3814
|
|
15
|
+
core/embedding.py,sha256=D-697p2NQy4pqobKq-EZqRvtU8-3fr3nnsgD6TXIY2Y,2419
|
|
16
|
+
core/learner.py,sha256=rCF_fxNoLNg3mkXgpEtbQVR2Bfu7Vl9XcuIDl5WYaFE,9673
|
|
17
|
+
core/policy.py,sha256=4P9jC46L-sWkP2GJDB0NLTL5mSrt0KJv8RRtTHXufho,3907
|
|
18
|
+
core/schema.py,sha256=1nnztlsSWMUjckvtl0SaSHvl49ddy0C1mAoH7Qebfk8,2614
|
|
19
|
+
core/scorer.py,sha256=4e7h91SB6YXYtIK8fl_M_uE4oAOTh3Y5z6ihnEtb1CE,9080
|
|
20
|
+
core/state.py,sha256=O9HhLbncSN26647S9tMMmu-L1skL_cfzAOvPjZAuapk,12061
|
|
21
|
+
delivery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
+
delivery/base.py,sha256=IRgjY4c4wgGdiYysYnqHBoVCSTXG_Sj62LNg3ZdcFCE,2239
|
|
23
|
+
delivery/desktop.py,sha256=8dWHg4TtvAy64Zbae2-LjoOExv48i2cITUYAqVo7Cio,1004
|
|
24
|
+
delivery/telegram.py,sha256=-uLrHBxssXsLKdifEaxY1liEF1PKz1Z_olZ14sMSB5E,3543
|
|
25
|
+
delivery/terminal.py,sha256=2gdEWCvfRicr-dTCJGaMU6AJQaB64UiDuxhMCw1W_yg,552
|
|
26
|
+
demo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
demo/day_of_engineer.json,sha256=VA10oRVPZsjYC5ctlTXCrF72RB1lBSjp5z4HOuqWsxM,17597
|
|
28
|
+
demo/runner.py,sha256=ofUyjoYhfMpOluKswIvE0HyBPWwAaYaOB36XK7YtmVk,9277
|
|
29
|
+
dispatch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
+
dispatch/acceptance.py,sha256=lqNprHWMlP5_RxGVQctQYz00HvU8KuyjEKBAqoQYPrY,2945
|
|
31
|
+
dispatch/executor.py,sha256=0k2YhiiuJRwB-iXfLeDYXIcKC456QFvOm1rf8UL-Fw0,4655
|
|
32
|
+
eval/__init__.py,sha256=H7YCzkOuxGtWgN6XfSre21GOqiiAfbHcNQK_LUY5Q_c,266
|
|
33
|
+
eval/generate_golden.py,sha256=dZoJpDGmfg7CWqcHdJK9EdDJGfNEegx0SNieg2Dwt9g,10979
|
|
34
|
+
eval/golden.jsonl,sha256=wnoZj7vSmDZ96N8D3BzyG6oQJOg3oiTy-zdsciKh59E,105755
|
|
35
|
+
eval/learning.py,sha256=OJOHvZiuC2B5-9vURS8WSaA-J5-zxP3EjypzMP6yiS0,8074
|
|
36
|
+
eval/runner.py,sha256=YRaExD1u8OJ8DWo6NMhGuso7XUuiPRJFtCOptF9jaAA,7819
|
|
37
|
+
eval/reports/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
eval/reports/learning.md,sha256=gktqJcdcO_ex_HetQDEB3rxR1OT2Hq3m4dnkt81j3Fk,1525
|
|
39
|
+
ingest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
|
+
ingest/http.py,sha256=CvFunMnzfduxgKklV06DWeUkF-nsfmMKlzi1nXVJDLo,9096
|
|
41
|
+
ingest/mcp_server.py,sha256=umvHjyNdgJ0e5Nz2Xaai6jZD8y3KMgnvgwee2WpClzA,2537
|
|
42
|
+
ingest/normalize.py,sha256=HJ2LztmxOE8t5qTR_bPenShvs2FxZQsvS0KX36e_bHc,2023
|
|
43
|
+
ingest/connectors/__init__.py,sha256=n-BXMadM-R8Zeg_5TqwMXsMTCYdmzuJypkbJPjR6Pvo,2033
|
|
44
|
+
ingest/connectors/composio.py,sha256=yvM1hrOAubJYMFvFFvt4tWrPjl1bBXCskzcS18Mgduw,3884
|
|
45
|
+
ingest/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
+
ingest/sources/base.py,sha256=IOTFStzoNzJ12oEr0FMKX7zOUXh4RH-eNo4deiFNaRM,1737
|
|
47
|
+
ingest/sources/github.py,sha256=iFWpEHQtIf4RB7kqTBqZISHmaTb8L2qshKyemeZoy2M,1556
|
|
48
|
+
ingest/sources/rss.py,sha256=54a5FGBmZvY3ESFO46ZmeB16C3pgkFP9NvqN9hBg_lM,1790
|
|
49
|
+
judge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
|
+
judge/anthropic.py,sha256=dKw4jJPBGugrEQxCovr1qK5KtVW9IYn1gvA1yZzpqNE,1364
|
|
51
|
+
judge/base.py,sha256=w2HPBXpwf_KQGXgnwSxUWdVHlmbiR9R9aBEHqQEi_yU,5352
|
|
52
|
+
judge/deepseek.py,sha256=CUOvwpsndhBHTNscDu94UL0v5WhJspVcoCXlnid0lNQ,223
|
|
53
|
+
judge/factory.py,sha256=Py7zeRGxLblrfyH1Wj7wVl20y94Ml5OO9hwY5tonLOU,1696
|
|
54
|
+
judge/fixtures.py,sha256=3VmwX42vBXnsvSzTzATI-cprmw4_0hGVeNxTKpNlwes,851
|
|
55
|
+
judge/ollama.py,sha256=cqITQsShPKYOSXuqz4_Y67I-wNyxJuul_0U8CN13YbA,874
|
|
56
|
+
judge/openai.py,sha256=I6yrr_UAJ_5-N_eGgMjdmzgfaqDzzrwErSKwxy02Z6w,1250
|
|
57
|
+
judge/pricing.py,sha256=8h1PBMtDdHRxYqOYT0EtNT-ejBiNPF8QVG2zkik17Mk,2568
|
|
58
|
+
judge/prompts.py,sha256=wZr3temoIgU862DVXs4FGvCBu6LPZVu1-4PhwbhcavQ,3401
|
|
59
|
+
judge/templates/v1/context.j2,sha256=RzT49TXfHyL9hniMOSZuAGFOh5L1fYSqkhF3tcRaVfQ,131
|
|
60
|
+
judge/templates/v1/distill.j2,sha256=m6HXezlORQ8uFBZC6AOYt8JDlZQtjmqLl8Y4uOzzPG0,232
|
|
61
|
+
judge/templates/v1/retry.j2,sha256=YfoQjk1J0Nw_6kRrPf6dbIQAI2RuiPH-UJet0IJ2Cek,125
|
|
62
|
+
judge/templates/v1/system.j2,sha256=O2OQ6r8a5-LyF3SP3XG0qpZKz3iaju5F83pkzVqzZAY,777
|
|
63
|
+
judge/templates/v1/topic_infer.j2,sha256=NMgkT3lIyWTdvIeHqh8eWcXlhjs9BbmIGBHC9UyMCZs,164
|
|
64
|
+
judge/templates/v1/user.j2,sha256=LtwCQQkerPYRW3JlhJdlGZHSc-CqE33dBEDtPYLXDJo,97
|
|
65
|
+
judge/templates/v1/verify.j2,sha256=0SizlJItqfJ3YCyfpiAr8N-B7-qNvcCt2vqRxhVABC8,204
|
|
66
|
+
memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
|
+
memory/associate.py,sha256=GfRiDt0lWps88Fx5qfmeDm4hA2QqS30q2DRzQIthX_g,956
|
|
68
|
+
memory/store.py,sha256=9DDFUgeoRpx2bL5YpyjjlZwk4sjTqG4SQeewYVeWjVY,2185
|
|
69
|
+
policy/POLICY.template.md,sha256=4LfYQr5hLuArNyXnjD-j8XlUEh8mg6wtU8St-f5YHkM,130
|
|
70
|
+
policy/USER.template.md,sha256=BPhdZJ2STQZT-GFdxI555UqgsxrriqCgtqJ_ceXUO4E,74
|
|
71
|
+
policy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
+
skills/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
+
skills/claude-code/SKILL.md,sha256=S691-I-FG3zovRyK8KyHcEGPeXzhhJovWpPPrTW5O5w,2296
|
|
74
|
+
skills/openclaw/SKILL.md,sha256=tvXm2mlXiXKFq3VIzbg89rCL0NkWElw1HvaJabhP6w4,2269
|
|
75
|
+
skills/openclaw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
|
+
skills/openclaw/hook.py,sha256=6rZW_eP6Jl6Ai61148iW8WM7k0lgyZ49XriVOFFnRiU,2449
|
|
77
|
+
ui/__init__.py,sha256=FOAADGRiLgpvtK8nWAA9oQNj1pqXUppDVefd_oiA9Mk,238
|
|
78
|
+
ui/console.html,sha256=KV7q4zihsIfYv_C3lYQiusEZ9f784iDctOfSov9Z4ck,10454
|
|
79
|
+
agent_chief-0.3.1.dist-info/METADATA,sha256=NdDmscurj5D25RFZsrzJ8pRicyu4aDTraMwPrwVBY00,14867
|
|
80
|
+
agent_chief-0.3.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
81
|
+
agent_chief-0.3.1.dist-info/entry_points.txt,sha256=RF6w2blJQtBS8tYrU9tn6ozRWigW8xMW6Ml4SU0Rpws,39
|
|
82
|
+
agent_chief-0.3.1.dist-info/licenses/LICENSE,sha256=gAWc9EgnR4F1P5UoitqjY98lQyexagPVTKo3dViksvQ,1068
|
|
83
|
+
agent_chief-0.3.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SmileLikeYe
|
|
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.
|
cli/__init__.py
ADDED
|
File without changes
|
cli/connect.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""SPEC v3.2 Step 35: one-click source connection.
|
|
2
|
+
|
|
3
|
+
`chief connect <source>` edits ~/.chief/config.toml surgically (everything
|
|
4
|
+
else preserved) and prints the exact next actions. Config writing stays
|
|
5
|
+
dependency-free: our schema is flat sections (plus one nested `connectors.*`
|
|
6
|
+
level) of strings/bools/ints/string-lists, so a tiny serializer suffices.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import base64
|
|
10
|
+
import hashlib
|
|
11
|
+
import hmac
|
|
12
|
+
import json
|
|
13
|
+
import tomllib
|
|
14
|
+
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
|
|
17
|
+
from core.config import chief_home, config_path, load_config
|
|
18
|
+
|
|
19
|
+
console = Console(soft_wrap=True, highlight=False) # keep URLs copy-pastable
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UnsupportedConfig(Exception):
|
|
23
|
+
"""The existing config uses TOML our tiny serializer can't round-trip."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _scalar(v) -> str:
|
|
27
|
+
if isinstance(v, bool):
|
|
28
|
+
return "true" if v else "false"
|
|
29
|
+
if isinstance(v, int | float):
|
|
30
|
+
return str(v)
|
|
31
|
+
if isinstance(v, str):
|
|
32
|
+
return json.dumps(v)
|
|
33
|
+
if isinstance(v, list) and all(isinstance(i, str | int | float | bool) for i in v):
|
|
34
|
+
return "[" + ", ".join(json.dumps(i) for i in v) + "]"
|
|
35
|
+
raise UnsupportedConfig(f"cannot serialize value {v!r}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _serialize(cfg: dict) -> str:
|
|
39
|
+
# our schema is flat sections plus one connectors.* level; anything deeper
|
|
40
|
+
# (or a root-level scalar, or a list of tables) we refuse rather than corrupt
|
|
41
|
+
lines: list[str] = []
|
|
42
|
+
for section, body in cfg.items():
|
|
43
|
+
if not isinstance(body, dict):
|
|
44
|
+
raise UnsupportedConfig(f"root-level key {section!r} is not a section")
|
|
45
|
+
scalars = {k: v for k, v in body.items() if not isinstance(v, dict)}
|
|
46
|
+
tables = {k: v for k, v in body.items() if isinstance(v, dict)}
|
|
47
|
+
if scalars or not tables:
|
|
48
|
+
lines.append(f"[{section}]")
|
|
49
|
+
lines += [f"{k} = {_scalar(v)}" for k, v in scalars.items()]
|
|
50
|
+
lines.append("")
|
|
51
|
+
for sub, subbody in tables.items():
|
|
52
|
+
if any(isinstance(v, dict) for v in subbody.values()):
|
|
53
|
+
raise UnsupportedConfig(f"[{section}.{sub}] nests too deep")
|
|
54
|
+
lines.append(f"[{section}.{sub}]")
|
|
55
|
+
lines += [f"{k} = {_scalar(v)}" for k, v in subbody.items()]
|
|
56
|
+
lines.append("")
|
|
57
|
+
return "\n".join(lines)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _update_config(mutate) -> dict:
|
|
61
|
+
path = config_path()
|
|
62
|
+
raw = path.read_text(encoding="utf-8") if path.exists() else ""
|
|
63
|
+
cfg = tomllib.loads(raw) if raw else {}
|
|
64
|
+
mutate(cfg)
|
|
65
|
+
try:
|
|
66
|
+
rendered = _serialize(cfg)
|
|
67
|
+
except UnsupportedConfig as exc:
|
|
68
|
+
raise SystemExit(
|
|
69
|
+
f"chief connect can't safely rewrite {path} ({exc}).\n"
|
|
70
|
+
f"Edit the config by hand — add the section shown in the docs — and re-run."
|
|
71
|
+
) from exc
|
|
72
|
+
chief_home().mkdir(parents=True, exist_ok=True)
|
|
73
|
+
if raw:
|
|
74
|
+
path.with_suffix(".toml.bak").write_text(raw, encoding="utf-8") # keep a backup
|
|
75
|
+
path.write_text(rendered, encoding="utf-8")
|
|
76
|
+
return cfg
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def connect_composio(secret: str) -> None:
|
|
80
|
+
_update_config(
|
|
81
|
+
lambda cfg: cfg.setdefault("connectors", {}).setdefault("composio", {}).update(
|
|
82
|
+
{"webhook_secret": secret}
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
port = load_config().get("ingest", {}).get("webhook_port", 8787)
|
|
86
|
+
|
|
87
|
+
# prove the secret + verifier agree before the user leaves the terminal
|
|
88
|
+
from ingest.connectors.composio import verify_signature
|
|
89
|
+
|
|
90
|
+
body = json.dumps({"probe": True}).encode()
|
|
91
|
+
mac = base64.b64encode(
|
|
92
|
+
hmac.new(secret.encode(), b"wh_probe.0." + body, hashlib.sha256).digest()
|
|
93
|
+
).decode()
|
|
94
|
+
assert verify_signature(secret, "wh_probe", "0", body, f"v1,{mac}")
|
|
95
|
+
console.print("✅ secret stored · signed sample verified locally")
|
|
96
|
+
console.print(
|
|
97
|
+
f"\nNext, in the Composio dashboard (composio.dev):\n"
|
|
98
|
+
f" 1. connect the apps you want (GitHub, Gmail, Slack, …)\n"
|
|
99
|
+
f" 2. enable their triggers\n"
|
|
100
|
+
f" 3. set the webhook subscription URL to\n"
|
|
101
|
+
f" [bold]https://<your-tunnel>/v1/connectors/composio[/bold]\n"
|
|
102
|
+
f" (local port {port}; use cloudflared/ngrok/tailscale funnel)\n"
|
|
103
|
+
f" 4. fire a test trigger and watch it in chief ui → History"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def connect_github() -> None:
|
|
108
|
+
import shutil
|
|
109
|
+
|
|
110
|
+
_update_config(lambda cfg: cfg.setdefault("ingest", {}).update({"github": True}))
|
|
111
|
+
if shutil.which("gh"):
|
|
112
|
+
console.print("✅ github notifications poller enabled (5 min via `gh api`)")
|
|
113
|
+
else:
|
|
114
|
+
console.print(
|
|
115
|
+
"✅ enabled — but [yellow]`gh` CLI not found[/yellow]: "
|
|
116
|
+
"install it and run `gh auth login` before `chief run`"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def connect_rss(url: str) -> None:
|
|
121
|
+
def mutate(cfg):
|
|
122
|
+
urls = cfg.setdefault("ingest", {}).setdefault("rss_urls", [])
|
|
123
|
+
if url not in urls:
|
|
124
|
+
urls.append(url)
|
|
125
|
+
|
|
126
|
+
_update_config(mutate)
|
|
127
|
+
console.print(f"✅ feed added — polled every 30 min: {url}")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def show_sources() -> None:
|
|
131
|
+
from rich.table import Table
|
|
132
|
+
|
|
133
|
+
from ingest.connectors import connector_status
|
|
134
|
+
|
|
135
|
+
table = Table(title="sources")
|
|
136
|
+
table.add_column("connector")
|
|
137
|
+
table.add_column("status")
|
|
138
|
+
table.add_column("")
|
|
139
|
+
for s in connector_status():
|
|
140
|
+
status = "[green]connected[/green]" if s["connected"] else "[dim]not configured[/dim]"
|
|
141
|
+
table.add_row(s["name"], status, s["detail"])
|
|
142
|
+
console.print(table)
|