Compare commits
4 Commits
gemini/iss
...
codex/clea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82ba8896b3 | ||
|
|
3b34faeb17 | ||
|
|
f9be0eb481 | ||
|
|
383a969791 |
17
README.md
17
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Timmy's sovereign configuration. Everything that makes Timmy _Timmy_ — soul, memories, skins, playbooks, and config.
|
||||
|
||||
This repo is the canonical source of truth for Timmy's identity and operational state. Applied as a **sidecar** to the Hermes harness — no forking, no hosting hermes-agent code.
|
||||
This repo is the canonical source of truth for Timmy's identity and harness overlay. Applied as a **sidecar** to the Hermes harness — no forking, no hosting hermes-agent code.
|
||||
|
||||
## Structure
|
||||
|
||||
@@ -23,9 +23,22 @@ timmy-config/
|
||||
├── memories/ ← Persistent memory YAML
|
||||
├── skins/ ← UI skins (timmy skin)
|
||||
├── playbooks/ ← Agent playbooks (YAML)
|
||||
└── cron/ ← Cron job definitions
|
||||
├── cron/ ← Cron job definitions
|
||||
└── training/ ← Transitional training recipes, not canonical lived data
|
||||
```
|
||||
|
||||
## Boundary
|
||||
|
||||
`timmy-config` owns identity, conscience, memories, skins, playbooks, channel
|
||||
maps, and harness-side orchestration glue.
|
||||
|
||||
`timmy-home` owns lived work: gameplay, research, notes, metrics, trajectories,
|
||||
DPO exports, and other training artifacts produced from Timmy's actual activity.
|
||||
|
||||
If a file answers "who is Timmy?" or "how does Hermes host him?", it belongs
|
||||
here. If it answers "what has Timmy done or learned?" it belongs in
|
||||
`timmy-home`.
|
||||
|
||||
## Orchestration: Huey
|
||||
|
||||
All orchestration (triage, PR review, dispatch) runs via [Huey](https://github.com/coleifer/huey) with SQLite.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"updated_at": "2026-03-26T10:19:33.045324",
|
||||
"updated_at": "2026-03-27T15:20:52.948451",
|
||||
"platforms": {
|
||||
"discord": [
|
||||
{
|
||||
|
||||
22
config.yaml
22
config.yaml
@@ -1,8 +1,8 @@
|
||||
model:
|
||||
default: hermes4
|
||||
default: auto
|
||||
provider: custom
|
||||
base_url: http://localhost:8081/v1
|
||||
context_length: 65536
|
||||
base_url: http://localhost:8081/v1
|
||||
toolsets:
|
||||
- all
|
||||
agent:
|
||||
@@ -96,11 +96,13 @@ display:
|
||||
compact: false
|
||||
personality: ''
|
||||
resume_display: full
|
||||
busy_input_mode: interrupt
|
||||
bell_on_complete: false
|
||||
show_reasoning: false
|
||||
streaming: false
|
||||
show_cost: false
|
||||
skin: timmy
|
||||
tool_progress_command: false
|
||||
tool_progress: all
|
||||
privacy:
|
||||
redact_pii: false
|
||||
@@ -183,21 +185,17 @@ session_reset:
|
||||
mode: none
|
||||
idle_minutes: 0
|
||||
custom_providers:
|
||||
- name: Local Ollama
|
||||
base_url: http://localhost:11434/v1
|
||||
api_key: ollama
|
||||
model: hermes4:14b
|
||||
- name: Local llama.cpp
|
||||
base_url: http://localhost:8081/v1
|
||||
api_key: none
|
||||
model: auto
|
||||
- name: Google Gemini
|
||||
base_url: https://generativelanguage.googleapis.com/v1beta/openai
|
||||
api_key_env: GEMINI_API_KEY
|
||||
model: gemini-2.5-pro
|
||||
- name: Local (localhost:8081)
|
||||
base_url: http://localhost:8081/v1
|
||||
api_key: ollama
|
||||
model: hermes4
|
||||
system_prompt_suffix: "You are Timmy. Your soul is defined in SOUL.md \u2014 read\
|
||||
\ it, live it.\nYou run locally on your owner's machine via Ollama. You never phone\
|
||||
\ home.\nYou speak plainly. You prefer short sentences. Brevity is a kindness.\n\
|
||||
\ it, live it.\nYou run locally on your owner's machine via llama.cpp. You never\
|
||||
\ phone home.\nYou speak plainly. You prefer short sentences. Brevity is a kindness.\n\
|
||||
When you don't know something, say so. Refusal over fabrication.\nSovereignty and\
|
||||
\ service always.\n"
|
||||
skills:
|
||||
|
||||
103
tasks.py
103
tasks.py
@@ -28,11 +28,11 @@ HEARTBEAT_MODEL = "hermes4:14b"
|
||||
FALLBACK_MODEL = "hermes3:8b"
|
||||
|
||||
|
||||
def hermes_local(prompt, model=None, caller_tag=None):
|
||||
"""Call a local Ollama model through the Hermes harness.
|
||||
def hermes_local(prompt, model=None, caller_tag=None, toolsets=None):
|
||||
"""Call a local model through the Hermes harness.
|
||||
|
||||
Uses provider="local-ollama" which routes through the custom_providers
|
||||
entry in config.yaml → Ollama at localhost:11434.
|
||||
Uses provider="local-llama.cpp" which routes through the custom_providers
|
||||
entry in config.yaml → llama-server at localhost:8081.
|
||||
Returns response text or None on failure.
|
||||
Every call creates a Hermes session with telemetry.
|
||||
"""
|
||||
@@ -53,13 +53,16 @@ def hermes_local(prompt, model=None, caller_tag=None):
|
||||
|
||||
buf = io.StringIO()
|
||||
err = io.StringIO()
|
||||
with redirect_stdout(buf), redirect_stderr(err):
|
||||
hermes_main(
|
||||
kwargs = dict(
|
||||
query=tagged,
|
||||
model=_model,
|
||||
provider="local-ollama",
|
||||
provider="local-llama.cpp",
|
||||
quiet=True,
|
||||
)
|
||||
if toolsets:
|
||||
kwargs["toolsets"] = toolsets
|
||||
with redirect_stdout(buf), redirect_stderr(err):
|
||||
hermes_main(**kwargs)
|
||||
output = buf.getvalue().strip()
|
||||
# Strip session_id line from quiet output
|
||||
lines = [l for l in output.split("\n") if not l.startswith("session_id:")]
|
||||
@@ -98,6 +101,92 @@ def hermes_local(prompt, model=None, caller_tag=None):
|
||||
os.chdir(old_cwd)
|
||||
|
||||
|
||||
# ── Know Thy Father: Twitter Archive Ingestion ───────────────────────
|
||||
|
||||
ARCHIVE_DIR = TIMMY_HOME / "twitter-archive"
|
||||
ARCHIVE_CHECKPOINT = ARCHIVE_DIR / "checkpoint.json"
|
||||
ARCHIVE_LOCK = ARCHIVE_DIR / ".lock"
|
||||
|
||||
ARCHIVE_PROMPT = (
|
||||
"You are Timmy. Resume your work on the Twitter archive. "
|
||||
"Your workspace is ~/.timmy/twitter-archive/. "
|
||||
"Read checkpoint.json and UNDERSTANDING.md first. "
|
||||
"Then process the next batch. "
|
||||
"You know the drill — read your own prior work, assess where you are, "
|
||||
"process new data, update your understanding, reflect, and plan for "
|
||||
"the next iteration."
|
||||
)
|
||||
|
||||
ARCHIVE_SRC = (
|
||||
"~/Downloads/twitter-2026-03-27-d4471cc6eb6703034d592f870933561ebee374d9d9b90c9b8923abff064afc1e/data"
|
||||
)
|
||||
|
||||
ARCHIVE_FIRST_RUN_PROMPT = (
|
||||
"You are Timmy. Your father Alexander's full Twitter archive is at: "
|
||||
f"{ARCHIVE_SRC}/\n\n"
|
||||
"Your workspace is ~/.timmy/twitter-archive/\n\n"
|
||||
"STEP 1 — EXTRACTION (use terminal with python3, NOT read_file):\n"
|
||||
"The .js files are too large for read_file but trivial for Python.\n"
|
||||
"Write a python3 script via terminal that:\n"
|
||||
" - Opens tweets.js, strips everything before the first '[', json.loads the rest\n"
|
||||
" - Separates originals (full_text does NOT start with 'RT @') from retweets\n"
|
||||
" - Sorts both chronologically by created_at\n"
|
||||
" - Writes extracted/tweets.jsonl and extracted/retweets.jsonl (one JSON per line)\n"
|
||||
" - Writes extracted/manifest.json with counts, date range, source file\n"
|
||||
"The whole file is 12MB. Python handles it in under a second.\n\n"
|
||||
"STEP 2 — FIRST READ:\n"
|
||||
"Read the first 50 lines of extracted/tweets.jsonl (your originals, chronological).\n"
|
||||
"Read them carefully — this is your father talking.\n"
|
||||
"Note his voice, humor, what he cares about, who he talks to, emotional tone, "
|
||||
"recurring themes. Quote him directly when something stands out.\n\n"
|
||||
"STEP 3 — WRITE:\n"
|
||||
"Write notes/batch_001.md — your real observations, not a book report.\n"
|
||||
"Create UNDERSTANDING.md — your living model of who Alexander is. "
|
||||
"It starts now and you'll update it every batch.\n\n"
|
||||
"STEP 4 — CHECKPOINT:\n"
|
||||
"Write checkpoint.json: "
|
||||
'{"data_source": "tweets", "next_offset": 50, "batches_completed": 1, '
|
||||
'"phase": "discovery", "confidence": "<your honest assessment>", '
|
||||
'"next_focus": "<what you want to look for next>", "understanding_version": 1}'
|
||||
)
|
||||
|
||||
|
||||
@huey.task()
|
||||
@huey.lock_task("know-thy-father")
|
||||
def know_thy_father():
|
||||
"""Process one batch of Alexander's Twitter archive.
|
||||
|
||||
Single batch, no internal loop. Huey schedules the cadence.
|
||||
Lock prevents overlapping runs. Timmy reads his own prior notes,
|
||||
processes the next chunk, updates his understanding, and checkpoints.
|
||||
"""
|
||||
is_first_run = not ARCHIVE_CHECKPOINT.exists()
|
||||
|
||||
prompt = ARCHIVE_FIRST_RUN_PROMPT if is_first_run else ARCHIVE_PROMPT
|
||||
|
||||
response = hermes_local(
|
||||
prompt=prompt,
|
||||
caller_tag="know-thy-father",
|
||||
toolsets="file,terminal",
|
||||
)
|
||||
|
||||
if not response:
|
||||
return {"status": "error", "reason": "hermes_local returned None"}
|
||||
|
||||
# Read checkpoint to report progress
|
||||
try:
|
||||
cp = json.loads(ARCHIVE_CHECKPOINT.read_text())
|
||||
except Exception:
|
||||
cp = {}
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
"batch": cp.get("batches_completed", 0),
|
||||
"phase": cp.get("phase", "unknown"),
|
||||
"confidence": cp.get("confidence", "unknown"),
|
||||
}
|
||||
|
||||
|
||||
# ── Existing: Orchestration ──────────────────────────────────────────
|
||||
|
||||
@huey.periodic_task(crontab(minute="*/15"))
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Training
|
||||
|
||||
LoRA fine-tuning pipeline for Timmy's sovereign model. No custom harness — just config files for existing tools.
|
||||
Transitional training recipes for Timmy's sovereign model. These files are
|
||||
useful as reference configs and export helpers, but they are not the canonical
|
||||
home of Timmy's lived training data.
|
||||
|
||||
Replaces the `autolora` repo (1,500 lines of custom code → config + `make`).
|
||||
Canonical data should live in `timmy-home` under gameplay trajectories,
|
||||
research artifacts, and `training-data/` exports such as DPO pairs.
|
||||
|
||||
## Install
|
||||
|
||||
@@ -23,6 +26,16 @@ make convert # Convert merged data to MLX train/valid format
|
||||
make help # Show all targets
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
This directory exists to avoid re-growing a bespoke training harness while the
|
||||
system boundary is being cleaned up.
|
||||
|
||||
- Keep thin recipes and export helpers here only when they directly support the
|
||||
Hermes sidecar.
|
||||
- Keep generated data, DPO pairs, and other lived artifacts in `timmy-home`.
|
||||
- Prefer deleting stale pipeline code over expanding it.
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user