feat(vida): jeito de gente e console com o porquê de cada decisão
Console (console.py + tela Console no painel):
- cada parte registra o que fez e o motivo: modo vida (com necessidades
e humor), sentidos, celular (ordens e o que o rosto fez), IA local,
aprendizado e ideias do dia; últimas 400 linhas, ao vivo pelo SSE;
- tela com o "agora" (humor, necessidades, o que está fazendo, próxima
decisão, última decisão, jeito), filtros, detalhes, pausa e busca.
Jeito de gente:
- saudade: a festa cresce com o tempo fora (aceno, "Oi! Você voltou!",
"Senti sua falta!"); bom dia lembrando de ontem;
- pedidos com motivo ("Brinca comigo?", "Me faz um carinho?", mostrar a
figurinha nova), no máximo 1 a cada 20 min;
- larga atividade no meio quando fica chato; personalidade (curiosidade,
brincadeira, timidez) que pesa nos gestos e amadurece com o convívio;
- no rosto: acordar grogue, sonhar com algo do dia (balão no motor),
hesitar antes de gestos, errar na atividade e ficar sem graça, olhar
nos olhos e desviar, sorrir de volta (FaceLandmarker no rastreador do
painel) e reagir à luz (sensor de luz no app 0.10.0);
- ordem "dizer" com legenda e voz de robô.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -105,6 +105,8 @@ class ControlePC:
|
||||
self.rtc.encerrar()
|
||||
return novo.copy()
|
||||
|
||||
console = staticmethod(lambda origem, texto, motivo='', nivel='info', agora=None: None) # o main troca pelo console do painel
|
||||
|
||||
def resumo(self, host=''):
|
||||
"""Estado do celular para o painel (GET /app/status, /estado e evento 'telemetria')."""
|
||||
with self.lock:
|
||||
@@ -160,12 +162,14 @@ class ControlePC:
|
||||
if not isinstance(dados, dict):
|
||||
raise ValueError('Estado deve ser objeto JSON')
|
||||
with self.lock:
|
||||
antes = self.estado
|
||||
self.estado = dados
|
||||
self.celular_ip = ip_informado(dados) or h.client_address[0]
|
||||
if self.recarga["id"] and str(dados.get("tela_atualizada", "")) == self.recarga["id"]:
|
||||
self.recarga["confirmada"] = True
|
||||
self.status_at = time.monotonic()
|
||||
self.publicar('telemetria', self.resumo(h.headers.get("Host", "").split(":")[0]))
|
||||
self.mudancas(antes, dados)
|
||||
enviar({'ok': True})
|
||||
else:
|
||||
enviar(self.resumo(h.headers.get("Host", "").split(":")[0]))
|
||||
@@ -176,6 +180,21 @@ class ControlePC:
|
||||
enviar({'erro': str(e)}, 503)
|
||||
return True
|
||||
|
||||
def mudancas(self, antes, agora):
|
||||
"""O que mudou no celular desde o último status: vai para o console do painel."""
|
||||
if not antes:
|
||||
self.console('celular', 'Celular conectado', 'rosto %s' % agora.get('rosto', '?'))
|
||||
return
|
||||
if bool(antes.get('dormindo')) != bool(agora.get('dormindo')):
|
||||
self.console('celular', 'O rosto dormiu' if agora.get('dormindo') else 'O rosto acordou')
|
||||
if antes.get('atividade') != agora.get('atividade'):
|
||||
if agora.get('atividade'):
|
||||
self.console('celular', 'Começou a atividade: %s' % agora['atividade'])
|
||||
else:
|
||||
self.console('celular', 'Terminou a atividade: %s' % antes['atividade'])
|
||||
if bool(antes.get('tela_apagada')) != bool(agora.get('tela_apagada')):
|
||||
self.console('celular', 'Apagou a tela (dormindo há um tempo)' if agora.get('tela_apagada') else 'Acendeu a tela')
|
||||
|
||||
def registrar_recusa(self, rota, motivo):
|
||||
"""Pedido do celular recusado: aparece no journal (no máximo 1 linha por minuto)."""
|
||||
agora = time.monotonic()
|
||||
|
||||
Reference in New Issue
Block a user