feat(vida): modo autônomo, o Carinha como bichinho virtual
Novo módulo vida.py: energia, alegria, companhia e diversão caem com o tempo e sobem com presença (PIR), movimento, conversa e carinho. Delas sai o humor e, do humor, os atos: gestos, cochilo quando cansado, dormir à noite sem ninguém por perto, acenar pedindo atenção quando carente com gente perto, tocar reações da biblioteca e inventar figurinhas novas com o Gemini (no máximo 3 por dia, 90 min entre elas). - O celular recebe "humor x" e escolhe os gestos soltos por ele. - Toque na tela do celular conta como carinho/cutucada (/vida/cuidar). - Respeita E-Stop e o modo presença (ninguém em casa = quieto). - Painel: cartão Vida no Ao vivo com humor, barras, cuidados, ritmo e diário; liga por padrão. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+31
-4
@@ -41,6 +41,7 @@ from conversa import Conversa
|
||||
from treinamento import Treinamento
|
||||
from api_config import ConfigAPI
|
||||
from historico import Historico
|
||||
from vida import Vida
|
||||
|
||||
TRAVA = threading.Lock()
|
||||
|
||||
@@ -70,7 +71,7 @@ ESTATICOS = {"/carinha.html", "/camera.html", "/reacoes-render.js", "/rastreador
|
||||
|
||||
# Rotas que não exigem token: só o necessário para a página do rosto abrir e o app se achar.
|
||||
PUBLICAS_GET = {"/app/health", "/faces", "/gestos", "/config", "/ia/modelo", "/app.apk"}
|
||||
PREFIXOS_API = ("/eventos", "/estado", "/fila", "/rtc/", "/conversa/", "/treinamento/", "/historico/",
|
||||
PREFIXOS_API = ("/eventos", "/estado", "/fila", "/rtc/", "/conversa/", "/treinamento/", "/historico/", "/vida/",
|
||||
"/app/", "/braco/", "/servos/", "/ia/", "/api/", "/gesto/", "/face/", "/diag/")
|
||||
|
||||
|
||||
@@ -237,7 +238,7 @@ class Handler(SimpleHTTPRequestHandler):
|
||||
|
||||
def modulos(self):
|
||||
s = self.server
|
||||
return [getattr(s, nome) for nome in ("api_config", "historico", "treinamento", "conversa", "cerebro",
|
||||
return [getattr(s, nome) for nome in ("api_config", "historico", "vida", "treinamento", "conversa", "cerebro",
|
||||
"braco", "servos", "controle") if hasattr(s, nome)]
|
||||
|
||||
def estado(self):
|
||||
@@ -262,6 +263,8 @@ class Handler(SimpleHTTPRequestHandler):
|
||||
dados["api"] = s.api_config.status()
|
||||
if hasattr(s, "historico"):
|
||||
dados["pir"] = dict(s.historico.pir, presenca=dict(s.historico.presenca))
|
||||
if hasattr(s, "vida"):
|
||||
dados["vida"] = s.vida.status()
|
||||
return dados
|
||||
|
||||
def do_GET(self):
|
||||
@@ -454,7 +457,7 @@ class Servidor(ThreadingHTTPServer):
|
||||
|
||||
|
||||
def ligar_eventos(servidor):
|
||||
for nome in ("controle", "servos", "cerebro", "conversa", "treinamento", "historico"):
|
||||
for nome in ("controle", "servos", "cerebro", "conversa", "treinamento", "historico", "vida"):
|
||||
if hasattr(servidor, nome):
|
||||
getattr(servidor, nome).publicar = EVENTOS.publicar
|
||||
|
||||
@@ -479,10 +482,34 @@ def main():
|
||||
servidor.cerebro.chave = servidor.token
|
||||
servidor.conversa = Conversa(Path.cwd() / 'memoria.db', servidor.cerebro)
|
||||
servidor.treinamento = Treinamento(Path.cwd() / 'treinamento.db')
|
||||
servidor.conversa.memoria.on_registrar = servidor.treinamento.registrar
|
||||
servidor.historico = Historico(Path.cwd())
|
||||
servidor.vida = vida = Vida(Path.cwd() / 'vida.json')
|
||||
|
||||
def registrar_conversa(papel, texto):
|
||||
servidor.treinamento.registrar(papel, texto)
|
||||
if papel == 'user':
|
||||
vida.estimulo('conversa') # alguém conversou com ele: companhia
|
||||
servidor.conversa.memoria.on_registrar = registrar_conversa
|
||||
|
||||
def celular_dormindo():
|
||||
resumo = servidor.controle.resumo()
|
||||
return bool(resumo['estado'].get('dormindo')) if resumo['online'] else None
|
||||
|
||||
def alguem_perto():
|
||||
h = servidor.historico
|
||||
recente = max(h.pir.get('ultimo') or 0, h.ultimo.get('movimento', 0))
|
||||
return bool(h.pir.get('ativo')) or time.time() - recente < 120
|
||||
|
||||
vida.enfileirar = enfileirar
|
||||
vida.treinamento = servidor.treinamento
|
||||
vida.celular_dormindo = celular_dormindo
|
||||
vida.celular_online = lambda: servidor.controle.resumo()['online']
|
||||
vida.alguem_perto = alguem_perto
|
||||
# E-Stop parado, ou modo presença com ninguém em casa (dormindo em silêncio): não faz nada
|
||||
vida.bloqueado = lambda: ESTOP["ativo"] or servidor.historico.presenca.get("estado") == "ausente"
|
||||
|
||||
def presenca(tipo):
|
||||
vida.estimulo(tipo)
|
||||
# PIR viu alguém: se o rosto estiver dormindo (e talvez com a tela apagada), acorda
|
||||
if tipo == "pir":
|
||||
with servidor.controle.lock:
|
||||
|
||||
Reference in New Issue
Block a user