Download (fresh):
- solveforce_phone_two.py — Download
- SHA‑256:
745183884701b5c7c7dcc4b8d77abcd50ebcb1776ad67455eef26a9767031c79
What Step Two adds
- Dynamic plugin auto‑loader
--plugins-dir <dir>: load every*.pyplugin at boot./plugins: lists all plugins (builtin + dynamic), their origin, file path, and any loader errors.- No overrides: dynamic plugins can’t shadow built‑ins; collisions are reported.
- Hot reload (opt‑in admin)
--allow-admin --admin-token "<secret>"to enable admin routes./admin/refresh?token=<secret>: rescans--plugins-dirand reloads plugins safely./admin/scaffold?name=<plugin>&token=<secret>: writes a new stub plugin file (see safety below).
- Scaffolder (CLI)
- Create a plugin file from your phone without opening an editor:
python solveforce_phone_two.py --plugins-dir plugins --scaffold hello # -> creates plugins/hello.py (read-only stub) - Safe names only:
[A-Za-z0-9_]. If the file exists, it won’t overwrite.
- Create a plugin file from your phone without opening an editor:
- Dynamic UI
/uinow fetches/pluginsand renders buttons for every plugin—no code edits required to expose new ones.
- Everything from Step One remains
/health,/state,/read,/translate,/metrics, JSONL exports (--export,--export-dir), optional poller (--poll N).
Phone commands (Termux)
Local only:
python solveforce_phone_two.py --host 127.0.0.1 --port 8080 --poll 0
LAN + exports + dynamic plugins:
mkdir -p /sdcard/solveforce/exports ~/solveforce/plugins
python solveforce_phone_two.py \
--host 0.0.0.0 --port 8080 --poll 5 \
--export --export-dir /sdcard/solveforce/exports \
--plugins-dir ~/solveforce/plugins
Enable admin hot‑reload + scaffolding (optional, guarded):
python solveforce_phone_two.py \
--host 0.0.0.0 --port 8080 \
--plugins-dir ~/solveforce/plugins \
--allow-admin --admin-token S3cRet123
Now you can hit:
/admin/refresh?token=S3cRet123/admin/scaffold?name=hello&token=S3cRet123
Default is safe: admin routes are disabled unless you pass
--allow-admin. A token is required if set.
How dynamic plugins work
File: ~/solveforce/plugins/hello.py
from solveforce_phone_two import Plugin
class HelloPlugin(Plugin):
NAME = "hello"
ORIGIN = "dynamic"
def read(self):
from datetime import datetime
return {"hello": "world", "ts": datetime.utcnow().isoformat()+"Z"}
# explicit form also supported:
# PLUGIN = HelloPlugin
- The loader accepts either
PLUGIN = <subclass or instance>or the firstPluginsubclass it finds. - On
/plugins, you’ll see:{ "plugins": {"hello": {"origin": "dynamic", "path": "/.../plugins/hello.py"}, ...}, "dyn_errors": [] } - Press the hello button in
/uito read it. - Exports: if
--exportis on, each read writesexports/hello.jsonl.
Safety & Transparency (short, stern, honest)
- Read‑only by design: plugins implement
read()only. No control paths are shipped. - Admin endpoints are OFF unless you turn them on explicitly.
- Scaffolder sanitizes names and never overwrites existing files.
- No implicit network exposure: we bind to
127.0.0.1by default;0.0.0.0is your active decision.
Suggestion for your public page
Add a new section:
Step Two — Dynamic Plugins (Auto‑Loader + Scaffolder)
--plugins-dirto point at a folder on the phone./pluginslists runtime plugins, builtin vs. dynamic./admin/refresh(with token) reloads without restarts.--scaffold NAMEto generate a safe stub:python solveforce_phone_two.py --plugins-dir plugins --scaffold meter- Minimal stub template (published inline) so the community can see exactly what’s generated.
If you want Step Three (richer metrics + live /events stream for the UI), say the word and I’ll ship it fully wired.