Initial Central AI Hub docs: brief, rules, README, outline context, architecture
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.env
|
||||||
|
*.visual-check.*
|
||||||
91
AGENTS.md
Normal file
91
AGENTS.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Central AI Hub (`central_ai_llm_master`)
|
||||||
|
|
||||||
|
## Mission
|
||||||
|
|
||||||
|
Build the **Hub**. The Hub is one small service. Every way in reaches every
|
||||||
|
ability through it. Build the ability once. All ways in get it.
|
||||||
|
|
||||||
|
## Authority
|
||||||
|
|
||||||
|
Read `hub_brief.md` in this folder first. It is the agreed design. If this file
|
||||||
|
and the brief disagree, the brief wins.
|
||||||
|
|
||||||
|
- `hub_brief.md` — the agreed brief (source of truth).
|
||||||
|
- `README.md` — technical readme.
|
||||||
|
- `docs/outline/` — AI context. Start with `00-index.md`.
|
||||||
|
|
||||||
|
## What the Hub does
|
||||||
|
|
||||||
|
Five steps, in order:
|
||||||
|
|
||||||
|
1. **Hear** — take voice or text from any way in.
|
||||||
|
2. **Understand** — the LLM works out what was asked.
|
||||||
|
3. **Check** — is this person allowed to ask for this?
|
||||||
|
4. **Route** — send it to the right destination.
|
||||||
|
5. **Answer** — return a short reply in the right shape for the device.
|
||||||
|
|
||||||
|
The reply can be text, spoken audio (TTS), Artemis commands, a notification, an
|
||||||
|
email, or a mix. TTS can play on the house speakers or on the phone.
|
||||||
|
|
||||||
|
## The dividing line
|
||||||
|
|
||||||
|
> Does this need a decision, or does it need to happen?
|
||||||
|
|
||||||
|
- **Happen** — fast and certain. Go straight to the destination. No LLM in the
|
||||||
|
path of the action.
|
||||||
|
- **Decision** — slow, multi-step, worth recording. Send to Paperclip.
|
||||||
|
|
||||||
|
**Paperclip is the work bench, not the switchboard.**
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
1. All models go through **OmniRoute**. Never call a provider directly.
|
||||||
|
2. All secrets come from **`environment.d`**. Never hard-code.
|
||||||
|
3. Own service, own port, own folder.
|
||||||
|
4. No LLM in the path of a fast or consequential action.
|
||||||
|
5. Paperclip only for slow, multi-step, recorded work.
|
||||||
|
6. Replies return to the source and stay short.
|
||||||
|
7. Restricted actions need **tap-to-approve** on the admin app.
|
||||||
|
8. Only the admin app changes parental controls.
|
||||||
|
9. A new ability registers with the Hub. Build it once.
|
||||||
|
|
||||||
|
## Build order
|
||||||
|
|
||||||
|
1. **Thin slice, end to end.** Issue a Paperclip API key. File one job from a
|
||||||
|
script. Get the result announced back. Prove the round trip.
|
||||||
|
2. **Hub skeleton.** Hear → understand → route → answer, with one destination.
|
||||||
|
3. **Approval flow.** "Did you ask for this?" on the admin app.
|
||||||
|
4. **Internet control.** Standalone service with a plain API. Device-side
|
||||||
|
enforcement. Admin-only.
|
||||||
|
5. **Artemis.** Standalone service with a plain API. Screen control only.
|
||||||
|
6. **Move Jervis's tools** into the Hub. Jervis becomes voice-only.
|
||||||
|
7. **Phone Kotlin app.** Wake word, voice to the Hub, replies and approvals.
|
||||||
|
8. **Email and school pipelines.** Stay independent. Connect when ready.
|
||||||
|
|
||||||
|
## Definition of done (phase 1)
|
||||||
|
|
||||||
|
- A Paperclip API key exists.
|
||||||
|
- One job is filed by script and its result is spoken.
|
||||||
|
- The round trip is recorded in `docs/outline/04-agent-runbook.md`.
|
||||||
|
|
||||||
|
## How this project relates to the other projects
|
||||||
|
|
||||||
|
This project owns the **shared Hub**. It does not own the destinations.
|
||||||
|
|
||||||
|
| Project | Relation |
|
||||||
|
|---|---|
|
||||||
|
| Email agent | Own pipeline. Reports through the Hub when ready. |
|
||||||
|
| Compass / NHS | Own pipeline. Reports through the Hub when ready. |
|
||||||
|
| Internet use control | Destination. Exposes a plain API. The Hub calls it. |
|
||||||
|
| Artemis | Destination. Exposes a plain API. The Hub calls it. |
|
||||||
|
| Jervis | Becomes voice-only. Its tools move here. |
|
||||||
|
| dsh | Calls the Hub for actions. |
|
||||||
|
|
||||||
|
Each project writes its own docs. Do not copy theirs here. Link to them.
|
||||||
|
|
||||||
|
## Do not
|
||||||
|
|
||||||
|
- Do not build one central brain. No single personality or memory.
|
||||||
|
- Do not put Paperclip in the path of a fast command.
|
||||||
|
- Do not duplicate a destination inside the Hub.
|
||||||
|
- Do not add a spoken keycode as the only lock for restricted actions.
|
||||||
81
README.md
Normal file
81
README.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Central AI Hub
|
||||||
|
|
||||||
|
One small service that every way in reaches every ability through. Built once,
|
||||||
|
shared by the phone app, the house voice, chat, and the admin app.
|
||||||
|
|
||||||
|
## Demonstrated Skills & Tech Stack
|
||||||
|
|
||||||
|
- **Core Technologies**: Go or Python service · HTTP JSON API · MQTT · LLM
|
||||||
|
intent routing · OmniRoute gateway · Docker
|
||||||
|
- **Key Tools**: Jervis (voice) · Home Assistant · Paperclip · Artemis ·
|
||||||
|
internet use control · Apprise / NTFY · OmniRoute
|
||||||
|
- **Engineering Capabilities**: service design · intent routing · authorization
|
||||||
|
and approval flows · event-driven integration · deterministic safety for
|
||||||
|
high-consequence actions
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Phase 1 — prove the Paperclip round trip
|
||||||
|
# 1. Create an agent API key in Paperclip.
|
||||||
|
# 2. Export it for the test only.
|
||||||
|
export PAPERCLIP_API_KEY=<redacted>
|
||||||
|
# 3. File one job.
|
||||||
|
curl -s -X POST http://192.168.20.13:3100/api/issues \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"title":"round-trip test","description":"prove the return path"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Full steps: `docs/outline/04-agent-runbook.md`.
|
||||||
|
|
||||||
|
## System Architecture
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
subgraph IN["Ways in"]
|
||||||
|
PHONE["Phone app<br/>wake word + voice"]
|
||||||
|
ADMIN["Admin app<br/>restricted actions"]
|
||||||
|
ESP["ESP32 voice<br/>Hey Jervis"]
|
||||||
|
DSH["dsh chat"]
|
||||||
|
CONSOLE["Console portal"]
|
||||||
|
end
|
||||||
|
|
||||||
|
HUB{{"HUB<br/>hear - understand - check - route - answer"}}
|
||||||
|
|
||||||
|
subgraph OUT["Destinations"]
|
||||||
|
HA["Home Assistant"]
|
||||||
|
SPK["Speakers<br/>Jervis TTS"]
|
||||||
|
NET["Internet control"]
|
||||||
|
ART["Artemis<br/>phone screen"]
|
||||||
|
PC["Paperclip<br/>slow jobs"]
|
||||||
|
WEB["Web search"]
|
||||||
|
APP["Apprise / NTFY"]
|
||||||
|
end
|
||||||
|
|
||||||
|
PHONE --> HUB
|
||||||
|
ESP --> HUB
|
||||||
|
DSH --> HUB
|
||||||
|
CONSOLE --> HUB
|
||||||
|
ADMIN --> HUB
|
||||||
|
HUB --> HA
|
||||||
|
HUB --> SPK
|
||||||
|
HUB --> NET
|
||||||
|
HUB --> ART
|
||||||
|
HUB --> PC
|
||||||
|
HUB --> WEB
|
||||||
|
HUB --> APP
|
||||||
|
PC -. result .-> HUB
|
||||||
|
```
|
||||||
|
|
||||||
|
*Interactive architecture map:* [maps.lab.audasmedia.com.au/central_ai_llm_master](https://maps.lab.audasmedia.com.au/central_ai_llm_master/docs/)
|
||||||
|
|
||||||
|
## Usage & Configuration
|
||||||
|
|
||||||
|
- **Model calls** go through OmniRoute at `http://192.168.20.13:20129/v1`.
|
||||||
|
- **Secrets** come from `~/.config/environment.d/10-secrets.conf`.
|
||||||
|
- **Paperclip** is at `http://192.168.20.13:3100`. An API key is required.
|
||||||
|
- **Home Assistant** is at `http://192.168.20.30:8123`.
|
||||||
|
- **Jervis** (voice) is at `http://192.168.20.13:8501`.
|
||||||
|
|
||||||
|
The design brief is `hub_brief.md`. Project instructions are `AGENTS.md`.
|
||||||
61
docs/archify/hub.architecture.json
Normal file
61
docs/archify/hub.architecture.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"schema_version": 1,
|
||||||
|
"diagram_type": "architecture",
|
||||||
|
"meta": {
|
||||||
|
"title": "Central AI Hub",
|
||||||
|
"output": "docs/hub-architecture-map.html",
|
||||||
|
"quality_profile": "showcase",
|
||||||
|
"views": [
|
||||||
|
{
|
||||||
|
"id": "fast-command",
|
||||||
|
"label": "Fast command",
|
||||||
|
"focus": ["esp32", "hub", "ha", "spk"],
|
||||||
|
"note": "A fast command goes straight to the destination. No LLM waits in the action path."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "slow-job",
|
||||||
|
"label": "Slow job",
|
||||||
|
"focus": ["phone", "hub", "pc"],
|
||||||
|
"note": "A slow job goes to Paperclip. The result returns to the Hub later."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "restricted",
|
||||||
|
"label": "Restricted action",
|
||||||
|
"focus": ["admin", "hub", "net"],
|
||||||
|
"note": "Only the admin app can change parental controls. Voice may ask; the app confirms."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{ "id": "phone", "type": "frontend", "label": "Phone app", "sublabel": "wake word + voice", "pos": [40, 80], "size": [150, 64] },
|
||||||
|
{ "id": "admin", "type": "security", "label": "Admin app", "sublabel": "restricted actions", "pos": [40, 200], "size": [150, 64] },
|
||||||
|
{ "id": "esp32", "type": "external", "label": "ESP32 voice", "sublabel": "Hey Jervis", "pos": [40, 320], "size": [150, 64] },
|
||||||
|
{ "id": "dsh", "type": "frontend", "label": "dsh chat", "sublabel": "per person", "pos": [40, 440], "size": [150, 64] },
|
||||||
|
{ "id": "hub", "type": "backend", "label": "Hub", "sublabel": "hear - understand - check - route - answer", "pos": [390, 260], "size": [190, 80], "tag": "one shared service" },
|
||||||
|
{ "id": "ha", "type": "external", "label": "Home Assistant", "sublabel": "devices, timers", "pos": [790, 40], "size": [160, 64] },
|
||||||
|
{ "id": "spk", "type": "external", "label": "Speakers", "sublabel": "Jervis TTS", "pos": [790, 150], "size": [160, 64] },
|
||||||
|
{ "id": "net", "type": "backend", "label": "Internet control", "sublabel": "parental limits", "pos": [790, 260], "size": [160, 64] },
|
||||||
|
{ "id": "art", "type": "backend", "label": "Artemis", "sublabel": "phone screen", "pos": [790, 370], "size": [160, 64] },
|
||||||
|
{ "id": "pc", "type": "backend", "label": "Paperclip", "sublabel": "slow jobs", "pos": [790, 480], "size": [160, 64] },
|
||||||
|
{ "id": "web", "type": "cloud", "label": "Web search", "sublabel": "Tavily", "pos": [790, 590], "size": [160, 64] },
|
||||||
|
{ "id": "app", "type": "backend", "label": "Apprise / NTFY", "sublabel": "notify + email", "pos": [790, 700], "size": [160, 64] }
|
||||||
|
],
|
||||||
|
"boundaries": [
|
||||||
|
{ "kind": "region", "label": "Ways in", "wraps": ["phone", "admin", "esp32", "dsh"], "pad": 26 },
|
||||||
|
{ "kind": "region", "label": "Destinations", "wraps": ["ha", "spk", "net", "art", "pc", "web", "app"], "pad": 26 }
|
||||||
|
],
|
||||||
|
"connections": [
|
||||||
|
{ "id": "phone-in", "from": "phone", "to": "hub", "label": "voice or text" },
|
||||||
|
{ "id": "admin-in", "from": "admin", "to": "hub", "label": "restricted" },
|
||||||
|
{ "id": "esp-in", "from": "esp32", "to": "hub", "label": "command" },
|
||||||
|
{ "id": "dsh-in", "from": "dsh", "to": "hub", "label": "action request" },
|
||||||
|
{ "id": "to-ha", "from": "hub", "to": "ha", "label": "do it" },
|
||||||
|
{ "id": "to-spk", "from": "hub", "to": "spk", "label": "speak" },
|
||||||
|
{ "id": "to-net", "from": "hub", "to": "net", "label": "confirm" },
|
||||||
|
{ "id": "to-art", "from": "hub", "to": "art", "label": "screen control" },
|
||||||
|
{ "id": "to-pc", "from": "hub", "to": "pc", "label": "file job" },
|
||||||
|
{ "id": "to-web", "from": "hub", "to": "web", "label": "search" },
|
||||||
|
{ "id": "to-app", "from": "hub", "to": "app", "label": "notify" },
|
||||||
|
{ "id": "pc-back", "from": "pc", "to": "hub", "label": "result", "variant": "dashed" }
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
docs/diagrams/hub-architecture.png
Normal file
BIN
docs/diagrams/hub-architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
13716
docs/hub-architecture-map.html
Normal file
13716
docs/hub-architecture-map.html
Normal file
File diff suppressed because it is too large
Load Diff
36
docs/hub-architecture.mmd
Normal file
36
docs/hub-architecture.mmd
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
flowchart LR
|
||||||
|
subgraph IN["Ways in"]
|
||||||
|
PHONE["Phone app<br/>wake word + voice"]
|
||||||
|
ADMIN["Admin app<br/>restricted actions"]
|
||||||
|
ESP["ESP32 voice<br/>Hey Jervis"]
|
||||||
|
DSH["dsh chat"]
|
||||||
|
CONSOLE["Console portal"]
|
||||||
|
end
|
||||||
|
|
||||||
|
HUB{{"HUB<br/>hear - understand - check - route - answer"}}
|
||||||
|
|
||||||
|
subgraph OUT["Destinations"]
|
||||||
|
HA["Home Assistant"]
|
||||||
|
SPK["Speakers<br/>Jervis TTS"]
|
||||||
|
NET["Internet control"]
|
||||||
|
ART["Artemis<br/>phone screen"]
|
||||||
|
PC["Paperclip<br/>slow jobs"]
|
||||||
|
WEB["Web search"]
|
||||||
|
APP["Apprise / NTFY"]
|
||||||
|
end
|
||||||
|
|
||||||
|
PHONE --> HUB
|
||||||
|
ESP --> HUB
|
||||||
|
DSH --> HUB
|
||||||
|
CONSOLE --> HUB
|
||||||
|
ADMIN --> HUB
|
||||||
|
HUB --> HA
|
||||||
|
HUB --> SPK
|
||||||
|
HUB --> NET
|
||||||
|
HUB --> ART
|
||||||
|
HUB --> PC
|
||||||
|
HUB --> WEB
|
||||||
|
HUB --> APP
|
||||||
|
PC -. result .-> HUB
|
||||||
|
|
||||||
|
click HUB "https://maps.lab.audasmedia.com.au/central_ai_llm_master/docs/" "View Archify Map"
|
||||||
38
docs/outline/00-index.md
Normal file
38
docs/outline/00-index.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Central AI Hub — AI Document Index
|
||||||
|
|
||||||
|
> **Target**: AI Agents
|
||||||
|
> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||||
|
|
||||||
|
## Document Catalog (Inject Specific Document)
|
||||||
|
|
||||||
|
Read this index to inject the exact file you need. Do not search all files.
|
||||||
|
|
||||||
|
| Document Title | Path | Scope / Description |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **System Overview** | `docs/outline/01-system-overview.md` | Explains the Hub purpose, its five steps, and the destinations. |
|
||||||
|
| **Configuration & Env** | `docs/outline/02-config-and-env.md` | Lists services, ports, env vars, and secret paths. |
|
||||||
|
| **Code Structure Map** | `docs/outline/03-code-map.md` | Shows the planned folder layout and entry points. |
|
||||||
|
| **AI Agent Runbook** | `docs/outline/04-agent-runbook.md` | Gives steps to build, test, and restart Hub work. |
|
||||||
|
| **Design Brief** | `hub_brief.md` | The agreed design. This file is the source of truth. |
|
||||||
|
| **Project Rules** | `AGENTS.md` | Mission, rules, build order, and project relations. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## System Summary
|
||||||
|
|
||||||
|
The Hub is one service. Every way in reaches every ability through it. The Hub
|
||||||
|
does five steps: hear, understand, check, route, and answer. The Hub does not
|
||||||
|
hold a personality or a memory. The Hub does not do the destination work.
|
||||||
|
|
||||||
|
## Core Configuration
|
||||||
|
|
||||||
|
- **Env File**: `~/.config/environment.d/10-secrets.conf`
|
||||||
|
- **Config Directory**: `docs/`
|
||||||
|
- **Active Ports**: Hub port not allocated yet.
|
||||||
|
|
||||||
|
## Agent Restart Steps
|
||||||
|
|
||||||
|
1. Read the Document Catalog above. Inject only required files.
|
||||||
|
2. Read `hub_brief.md`.
|
||||||
|
3. Check git status: `git status`.
|
||||||
|
4. Check recent commits: `git log -n 5 --oneline`.
|
||||||
59
docs/outline/01-system-overview.md
Normal file
59
docs/outline/01-system-overview.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Central AI Hub — System Overview
|
||||||
|
|
||||||
|
> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
The Hub is one service. Every way in reaches every ability through the Hub. Build
|
||||||
|
each ability once. All ways in get it.
|
||||||
|
|
||||||
|
Today, Jervis (voice) and dsh (chat) each understand the user and act. A third
|
||||||
|
way in, the phone app, would repeat the same work. The Hub stops this repeat.
|
||||||
|
|
||||||
|
## The Five Steps
|
||||||
|
|
||||||
|
1. **Hear** — take voice or text from any way in.
|
||||||
|
2. **Understand** — the LLM works out what the user asked.
|
||||||
|
3. **Check** — test whether the user may ask for this.
|
||||||
|
4. **Route** — send the request to one destination.
|
||||||
|
5. **Answer** — return a short reply in the right shape.
|
||||||
|
|
||||||
|
## Ways In
|
||||||
|
|
||||||
|
- Phone app (Kotlin) — wake word, voice, controls.
|
||||||
|
- Admin app (Kotlin) — restricted actions only.
|
||||||
|
- ESP32 voice — "Hey Jervis".
|
||||||
|
- dsh chat — per-person chat.
|
||||||
|
- Console portal — web dashboard.
|
||||||
|
|
||||||
|
## Destinations
|
||||||
|
|
||||||
|
| Destination | Job |
|
||||||
|
|---|---|
|
||||||
|
| Home Assistant | Lights, switches, timers, calendar. |
|
||||||
|
| Speakers (Jervis) | Speak and announce. |
|
||||||
|
| Internet control | Parental limits on kids' devices. |
|
||||||
|
| Artemis | Operate the phone screen. |
|
||||||
|
| Paperclip | Slow, multi-step, recorded work. |
|
||||||
|
| Web search | Tavily search. |
|
||||||
|
| Apprise / NTFY | Notifications and email. |
|
||||||
|
|
||||||
|
## Reply Shapes
|
||||||
|
|
||||||
|
The Hub returns one reply. The reply can hold text, spoken audio (TTS), Artemis
|
||||||
|
commands, a notification, or an email. TTS can play on the house speakers or on
|
||||||
|
the phone. The Hub returns the reply to the source.
|
||||||
|
|
||||||
|
## The Dividing Line
|
||||||
|
|
||||||
|
The Hub asks one question: does this need a decision, or does it need to happen?
|
||||||
|
|
||||||
|
- **Happen** — fast and certain. Go straight to the destination. No LLM in the
|
||||||
|
path of the action.
|
||||||
|
- **Decision** — slow, multi-step, worth recording. Send to Paperclip.
|
||||||
|
|
||||||
|
## What the Hub Is Not
|
||||||
|
|
||||||
|
- Not a central brain. No single personality or memory.
|
||||||
|
- Not Paperclip. The Hub does not wait minutes for an answer.
|
||||||
|
- Not a destination. The Hub does not turn off the internet itself.
|
||||||
43
docs/outline/02-config-and-env.md
Normal file
43
docs/outline/02-config-and-env.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Central AI Hub — Configuration & Environment
|
||||||
|
|
||||||
|
> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||||
|
|
||||||
|
## Secrets
|
||||||
|
|
||||||
|
All secrets come from `~/.config/environment.d/10-secrets.conf` on each machine.
|
||||||
|
Never hard-code a secret. Never commit a secret.
|
||||||
|
|
||||||
|
Relevant keys:
|
||||||
|
|
||||||
|
| Key | Use |
|
||||||
|
|---|---|
|
||||||
|
| `OMNIROUTE_API_KEY` | Model calls through OmniRoute. |
|
||||||
|
| `PAPERCLIP_API_KEY` | File jobs to Paperclip. Does not exist yet. |
|
||||||
|
| `TAVILY_API_KEY` | Web search. |
|
||||||
|
| `OL_API_KEY` | Outline docs. |
|
||||||
|
| `VIKUNJA_TOKEN` | Vikunja tasks. |
|
||||||
|
| `GITEA_TOKEN` | Gitea repository. |
|
||||||
|
|
||||||
|
## Services and Ports
|
||||||
|
|
||||||
|
| Service | Host | Port | Use |
|
||||||
|
|---|---|---|---|
|
||||||
|
| OmniRoute | 192.168.20.13 | 20129 | Model gateway. |
|
||||||
|
| Paperclip | 192.168.20.13 | 3100 | Job orchestration. |
|
||||||
|
| Jervis (voice) | 192.168.20.13 | 8501 | Speak and announce. |
|
||||||
|
| Home Assistant | 192.168.20.30 | 8123 | Devices and timers. |
|
||||||
|
| MQTT | 192.168.20.13 | 1883 | Voice topics. |
|
||||||
|
| Apprise | 192.168.20.35 | 8210 | Notifications. |
|
||||||
|
| Hub | not allocated | — | This service. |
|
||||||
|
|
||||||
|
## Config Paths
|
||||||
|
|
||||||
|
- Brief: `hub_brief.md`
|
||||||
|
- Rules: `AGENTS.md`
|
||||||
|
- Docs: `docs/`
|
||||||
|
- Outline context: `docs/outline/`
|
||||||
|
|
||||||
|
## Rule
|
||||||
|
|
||||||
|
A new project gets its own service, its own port, and its own folder. Do not
|
||||||
|
merge a destination into the Hub.
|
||||||
56
docs/outline/03-code-map.md
Normal file
56
docs/outline/03-code-map.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Central AI Hub — Code Structure Map
|
||||||
|
|
||||||
|
> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||||
|
> **Status**: Planned. The Hub is not built yet.
|
||||||
|
|
||||||
|
## Planned Folder Layout
|
||||||
|
|
||||||
|
```text
|
||||||
|
central_ai_llm_master/
|
||||||
|
AGENTS.md project rules for agents
|
||||||
|
hub_brief.md agreed design (source of truth)
|
||||||
|
README.md technical readme
|
||||||
|
docs/
|
||||||
|
hub-architecture.mmd Mermaid source
|
||||||
|
hub-architecture-map.html Archify map
|
||||||
|
diagrams/ rendered images
|
||||||
|
archify/ Archify JSON input
|
||||||
|
outline/ AI context documents
|
||||||
|
vikunja-tasks.json human task list
|
||||||
|
src/ Hub service code (to build)
|
||||||
|
main.* HTTP entry point
|
||||||
|
hear/ takes voice or text
|
||||||
|
understand/ LLM intent routing
|
||||||
|
check/ authorization and approval
|
||||||
|
route/ dispatch to a destination
|
||||||
|
answer/ reply shaping (text, TTS, notify)
|
||||||
|
destinations/ one client per destination
|
||||||
|
tests/ unit and round-trip tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## Entry Points
|
||||||
|
|
||||||
|
| Entry point | Use |
|
||||||
|
|---|---|
|
||||||
|
| `POST /ask` | Send a voice transcript or text. Returns a reply. |
|
||||||
|
| `POST /approve` | Admin app confirms a restricted action. |
|
||||||
|
| `GET /health` | Liveness check. |
|
||||||
|
|
||||||
|
The API contract is not final. See `hub_brief.md`.
|
||||||
|
|
||||||
|
## Primary Dependencies
|
||||||
|
|
||||||
|
- HTTP server (Go or Python — decide before build).
|
||||||
|
- HTTP client for OmniRoute, Home Assistant, Paperclip.
|
||||||
|
- MQTT client for voice topics.
|
||||||
|
- Tavily API client for web search.
|
||||||
|
|
||||||
|
## Destinations
|
||||||
|
|
||||||
|
Each destination gets one client under `src/destinations/`. The client calls the
|
||||||
|
destination API. The client does not hold business logic.
|
||||||
|
|
||||||
|
## Source Control
|
||||||
|
|
||||||
|
- Gitea: `sam/central_ai_llm_master`
|
||||||
|
- Local: `/home/sam/paseo/projects/central_ai_llm_master/`
|
||||||
55
docs/outline/04-agent-runbook.md
Normal file
55
docs/outline/04-agent-runbook.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Central AI Hub — AI Agent Runbook
|
||||||
|
|
||||||
|
> **Writing Style**: ASD-STE100 Simplified Technical English (`ste-writing`).
|
||||||
|
|
||||||
|
## Phase 1 — Prove the Paperclip Round Trip
|
||||||
|
|
||||||
|
This phase has no Hub code. It proves the missing link: a job that leaves and a
|
||||||
|
result that returns.
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
1. Create a Paperclip agent API key for this project.
|
||||||
|
- Paperclip board: `http://192.168.20.13:3100`.
|
||||||
|
- Store the key in `~/.config/environment.d/10-secrets.conf` as
|
||||||
|
`PAPERCLIP_API_KEY`. Never commit it.
|
||||||
|
2. File one job with `curl`. Use the issue-create endpoint.
|
||||||
|
3. Confirm the job appears in the Paperclip board.
|
||||||
|
4. Wait for the agent to close the job.
|
||||||
|
5. Send the result to Jervis `POST /announce` so the house speaks it.
|
||||||
|
6. Record the result in this file.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export PAPERCLIP_API_KEY=<from secrets>
|
||||||
|
curl -s -X POST http://192.168.20.13:3100/api/issues \
|
||||||
|
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"title":"round-trip test","description":"prove the return path"}'
|
||||||
|
|
||||||
|
# Speak the result.
|
||||||
|
curl -s -X POST http://192.168.20.13:8501/announce \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"text":"Round trip works."}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Definition of Done
|
||||||
|
|
||||||
|
- The job appears in Paperclip.
|
||||||
|
- The job closes.
|
||||||
|
- The house speaks the result.
|
||||||
|
- This file records the result.
|
||||||
|
|
||||||
|
## After Phase 1
|
||||||
|
|
||||||
|
Follow the build order in `AGENTS.md`. Do not start a destination before the
|
||||||
|
round trip works.
|
||||||
|
|
||||||
|
## Health Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -s http://192.168.20.13:3100/health # Paperclip
|
||||||
|
curl -s http://192.168.20.13:8501/health # Jervis
|
||||||
|
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.20.30:8123/ # HA
|
||||||
|
```
|
||||||
16
docs/vikunja-tasks.json
Normal file
16
docs/vikunja-tasks.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"title": "Central AI Hub - Human Task Overview",
|
||||||
|
"description": "High-level task checklist for human team members.",
|
||||||
|
"tasks": [
|
||||||
|
{ "title": "Create Paperclip agent API key and store in secrets", "done": false },
|
||||||
|
{ "title": "Prove the Paperclip round trip (file job, speak result)", "done": false },
|
||||||
|
{ "title": "Decide the Hub language and port", "done": false },
|
||||||
|
{ "title": "Build the Hub skeleton (hear, understand, route, answer)", "done": false },
|
||||||
|
{ "title": "Add the tap-to-approve flow on the admin app", "done": false },
|
||||||
|
{ "title": "Build the internet control destination service", "done": false },
|
||||||
|
{ "title": "Build the Artemis destination service", "done": false },
|
||||||
|
{ "title": "Move Jervis action tools into the Hub", "done": false },
|
||||||
|
{ "title": "Build the phone Kotlin app", "done": false },
|
||||||
|
{ "title": "Connect the email and school pipelines", "done": false }
|
||||||
|
]
|
||||||
|
}
|
||||||
150
hub_brief.md
Normal file
150
hub_brief.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# The Hub — a short brief
|
||||||
|
|
||||||
|
**Purpose:** tell every project where it fits and the rules it must follow.
|
||||||
|
**Written:** 2026-10-10
|
||||||
|
**Status:** agreed direction, not a build order.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The idea in one line
|
||||||
|
|
||||||
|
**Share the plumbing. Keep the brains separate. Put one small hub in the middle.**
|
||||||
|
|
||||||
|
Every way in (phone, house voice, chat) reaches every ability (lights, internet,
|
||||||
|
Artemis, Paperclip) through one place — built once, not repeated.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What already works (do not rebuild)
|
||||||
|
|
||||||
|
| System | What it is |
|
||||||
|
|---|---|
|
||||||
|
| **Jervis** | The house voice. ESP32 "Hey Jervis" → STT → agent → TTS → speakers. Controls HA, timers, reminders, shopping, calendar, music, weather, web search, family messages. |
|
||||||
|
| **dsh** | Per-person chat (sam / jo / harry / finn). Memory, images, video, documents. |
|
||||||
|
| **Console portal** | Logins and dashboard for the family. |
|
||||||
|
| **Front Door Cam** | Its own separate ESP32. Visitor detection, Gemini sees the person, voice asks them to speak. |
|
||||||
|
| **OmniRoute** | The model gateway. All models go through here. |
|
||||||
|
| **Home Assistant** | Devices, timers, calendar, notifications. |
|
||||||
|
| **Shared** | Apprise, Snapcast, STT/TTS, n8n, secrets in `environment.d`. |
|
||||||
|
|
||||||
|
These stay. The hub is added, not a replacement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is new
|
||||||
|
|
||||||
|
- The **Hub** (this brief).
|
||||||
|
- **Email agent** — its own pipeline.
|
||||||
|
- **School (Compass / Teams)** — its own pipeline.
|
||||||
|
- **Internet use control** — a destination the hub calls.
|
||||||
|
- **Artemis** — a destination the hub calls.
|
||||||
|
- **Kotlin phone app** — a new way in (wake word, voice, controls).
|
||||||
|
- **Admin app + kids app** — parental control, admin only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What the Hub is
|
||||||
|
|
||||||
|
One service that does five steps:
|
||||||
|
|
||||||
|
1. **Hear** — takes voice or text from any way in.
|
||||||
|
2. **Understand** — the LLM works out what was asked.
|
||||||
|
3. **Check** — is this person allowed to ask for this?
|
||||||
|
4. **Route** — sends it to the right destination.
|
||||||
|
5. **Answer** — returns a short reply in the right shape for the device.
|
||||||
|
|
||||||
|
The reply can be **text**, **spoken audio (TTS)**, **Artemis commands**, **a phone
|
||||||
|
notification**, **an email**, or a mix. TTS can play on the **house speakers** or
|
||||||
|
on the **phone**.
|
||||||
|
|
||||||
|
### What the Hub is NOT
|
||||||
|
|
||||||
|
- **Not a central brain.** It does not hold one personality or one memory.
|
||||||
|
- **Not Paperclip.** It never waits minutes for an answer.
|
||||||
|
- **Not a destination.** It does not turn off the internet itself. It sends the
|
||||||
|
request to the service that does.
|
||||||
|
|
||||||
|
### The dividing line
|
||||||
|
|
||||||
|
One question sorts every request:
|
||||||
|
|
||||||
|
> **Does this need a decision, or does it need to happen?**
|
||||||
|
|
||||||
|
- **Happen** (fast, certain) → straight to the destination: HA, internet control,
|
||||||
|
Artemis, speakers. No LLM in the path of the action.
|
||||||
|
- **Decision** (slow, multi-step, worth recording) → Paperclip.
|
||||||
|
|
||||||
|
**Paperclip is the work bench, not the switchboard.** It is never in the path of
|
||||||
|
a fast or high-consequence command.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Where each system fits
|
||||||
|
|
||||||
|
| System | Role | With the Hub |
|
||||||
|
|---|---|---|
|
||||||
|
| **Jervis** | House voice | Becomes the **voice** (speak / announce), not a list of tools. Its action tools move into the Hub over time. |
|
||||||
|
| **dsh** | Chat | Calls the Hub for actions instead of keeping its own copies. |
|
||||||
|
| **Console portal** | Login + dashboard | Unchanged. May show Hub status and approvals. |
|
||||||
|
| **Front Door Cam** | Visitor intercom | Stays separate. May use the Hub only to speak. |
|
||||||
|
| **Email agent** | Own pipeline (n8n) | Standalone. May report results through the Hub. |
|
||||||
|
| **School agent** | Own pipeline (n8n) | Standalone. May report results through the Hub. |
|
||||||
|
| **Internet control** | Destination | The Hub calls its API. Enforcement happens on the kids' devices. |
|
||||||
|
| **Artemis** | Destination | The Hub calls its API. Artemis touches the phone screen. |
|
||||||
|
| **Paperclip** | Work bench | The Hub files jobs and hears the answer back. |
|
||||||
|
| **Phone app** | Way in | Sends voice to the Hub. Shows replies, notifications, approvals. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rules every project follows
|
||||||
|
|
||||||
|
1. **All models go through OmniRoute.** Never call a provider directly.
|
||||||
|
2. **All secrets come from `environment.d`.** Never hard-code.
|
||||||
|
3. **Own service, own port, own folder.** Do not merge into another project.
|
||||||
|
4. **No LLM in the path of a fast or consequential action.** Deterministic calls
|
||||||
|
for anything that turns something off.
|
||||||
|
5. **Paperclip only for slow, multi-step, recorded work.** Never make a person
|
||||||
|
wait on it.
|
||||||
|
6. **Replies return to the source, and stay short.** Speaker → one line. Phone →
|
||||||
|
notification. Chat → text. No long-winded answers.
|
||||||
|
7. **Restricted commands need tap-to-approve** on the admin app. This includes
|
||||||
|
parental controls and any job filed to Paperclip.
|
||||||
|
8. **Only the admin app can change parental controls.** Kids' apps and desktop
|
||||||
|
exes may only obey and report.
|
||||||
|
9. **New work registers with the Hub.** A capability is added once, and every way
|
||||||
|
in gets it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Safety
|
||||||
|
|
||||||
|
- **Voice is shared and unauthenticated.** Anyone in the house can speak.
|
||||||
|
- **The admin app is the only trusted door** for restricted actions.
|
||||||
|
- **A spoken keycode is not the lock.** It can be overheard and misheard. Voice
|
||||||
|
may *ask*; the admin app **confirms** with "Did you ask for this?".
|
||||||
|
- **Approval is required** for parental controls and Paperclip jobs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build order
|
||||||
|
|
||||||
|
1. **Thin slice, end to end.** Issue a Paperclip API key, file one job from a
|
||||||
|
script, and get the result announced back. Proves the round trip.
|
||||||
|
2. **Hub skeleton.** Hear → understand → route → answer, with one destination
|
||||||
|
(HA or speakers) working.
|
||||||
|
3. **Approval flow.** "Did you ask for this?" on the admin app.
|
||||||
|
4. **Internet control.** Standalone service with a plain API. Device-side
|
||||||
|
enforcement. Admin-only.
|
||||||
|
5. **Artemis.** Standalone service with a plain API. Screen control only.
|
||||||
|
6. **Move Jervis's tools** into the Hub. Jervis becomes voice-only.
|
||||||
|
7. **Phone Kotlin app.** Wake word, voice to the Hub, replies and approvals.
|
||||||
|
8. **Email and school pipelines** stay independent and connect when ready.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What is still open
|
||||||
|
|
||||||
|
- Exact API contract for a job (title, brief, project, agent).
|
||||||
|
- How Artemis receives voice (stream vs file) and when phone TTS is used.
|
||||||
|
- Which Paperclip company / projects to use.
|
||||||
|
- Identity: how the Hub knows which family member is speaking.
|
||||||
Reference in New Issue
Block a user