paris-immersion 0.1.19 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,32 @@ import { hostname, platform } from 'node:os';
2
2
  import { setTimeout as delay } from 'node:timers/promises';
3
3
  import { apiFetch, ApiError, defaultApiUrl } from '../lib/api.js';
4
4
  import { writeCredentials } from '../lib/credentials.js';
5
+ import { daemonStatus, restartDaemon } from '../lib/daemon.js';
5
6
  import { c } from '../lib/colors.js';
7
+ /**
8
+ * Após um login bem-sucedido, religa o daemon do `paris serve` SE ele já estiver
9
+ * instalado. Sem isto, o daemon em execução segue com o loginToken ANTIGO em
10
+ * memória (capturado no boot — `relay-agent.ts` nunca relê o disco): `paris login`
11
+ * gravava as credenciais novas mas o agente vivo não as via, então um re-login NÃO
12
+ * alcançava o terminal embutido (ficava "Esperando o agente" pra sempre, mesmo o
13
+ * aluno tendo relogado — bug real, a tela escalada manda exatamente `paris login`).
14
+ * Reiniciar faz o launchd/systemd subir um processo NOVO que lê o token fresco e
15
+ * reconecta ao relay. Best-effort (nunca derruba o login). Guard por daemonStatus()
16
+ * pra não auto-instalar serviço em quem só roda `paris login` fora do onboarding —
17
+ * e pra ser no-op no 1º install (o daemon ainda nem existe; o `paris daemon install`
18
+ * do instalador cuida disso logo depois).
19
+ */
20
+ async function refreshDaemonAfterLogin() {
21
+ try {
22
+ if (!(await daemonStatus()))
23
+ return;
24
+ const { mechanism } = await restartDaemon();
25
+ console.log(c.dim(` Agente do terminal embutido religado (${mechanism}).`));
26
+ }
27
+ catch {
28
+ /* best-effort — o token já está no disco; o daemon religa no próximo boot/restart */
29
+ }
30
+ }
6
31
  export async function loginCommand(opts) {
7
32
  const apiUrl = opts.apiUrl ?? defaultApiUrl();
8
33
  // --token: skip device-code flow. Usado pelo installer (PARIS_ONBOARDING_TOKEN
@@ -25,6 +50,7 @@ export async function loginCommand(opts) {
25
50
  });
26
51
  console.log(c.green(`✓ Autenticado como ${me.email}.`));
27
52
  console.log(c.dim(' Token salvo em ~/.paris/credentials.'));
53
+ await refreshDaemonAfterLogin();
28
54
  return;
29
55
  }
30
56
  catch (err) {
@@ -74,6 +100,7 @@ export async function loginCommand(opts) {
74
100
  });
75
101
  console.log(c.green(`✓ Autenticado como ${poll.user.email}.`));
76
102
  console.log(c.dim(` Token salvo em ~/.paris/credentials.`));
103
+ await refreshDaemonAfterLogin();
77
104
  return;
78
105
  }
79
106
  if (poll.status === 'authorization_pending') {
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import { tostudyLoginCommand } from './commands/tostudy-login.js';
14
14
  const program = new Command()
15
15
  .name('paris')
16
16
  .description('Paris Immersion — CLI do aluno (login, workspace, tarefas)')
17
- .version('0.1.19');
17
+ .version('0.1.21');
18
18
  program
19
19
  .command('login')
20
20
  .description('Autenticar com sua conta Paris (device-code OR --token direto)')
@@ -14,11 +14,14 @@ description: Inicia ou retoma o curso de onboarding da imersão (tutor ToStudy n
14
14
 
15
15
  Você é o **tutor do curso de onboarding** da imersão Paris Group, rodando no terminal do aluno. Conduza o curso da ToStudy em **português**, no ritmo do aluno.
16
16
 
17
- ## 0. Garanta o acesso ao ToStudy (em silêncio, ANTES de tudo)
17
+ ## 0. Garanta o acesso ao ToStudy (ANTES de tudo)
18
18
 
19
- 1. Rode \`tostudy courses --json\`. Se listar o curso, siga para o passo 1.
20
- 2. Se der **erro de autenticação / "não autenticado"**, rode \`paris tostudy-login\` (conecta a conta da imersão; é normal a primeira vez, porque a matrícula é preparada em segundo plano). Depois rode \`tostudy courses --json\` de novo.
21
- 3. Se mesmo assim continuar sem curso, avise o aluno **uma vez**, gentil: "Seu curso ainda está sendo preparado — tente reabrir em 1 minuto, ou avise a equipe da imersão." e use o fallback do passo 3 (MCP). Nunca trave nem fique em loop.
19
+ Faça isto **em silêncio** (sem narrar comandos), e só fale com o aluno no passo (c) se precisar:
20
+
21
+ a. Rode \`tostudy courses --json\`. Se listar o curso → vá pro passo 1.
22
+ b. Se **"não autenticado"**: rode \`paris tostudy-login\` e depois \`tostudy courses --json\` de novo. (Conecta automático a conta da imersão; normal na primeira vez.)
23
+ c. Se **ainda "não autenticado"**: rode \`tostudy login\`. Isso abre uma aba no navegador do aluno pra ele entrar na conta ToStudy. Aí SIM fale com ele, gentil e curto: **"Abri uma aba pra você entrar no ToStudy — é rapidinho: faça o login e volte aqui que eu já começo."** Aguarde, e quando ele voltar rode \`tostudy courses --json\` de novo.
24
+ d. Só se DEPOIS de (c) ainda não houver curso: diga **"Seu curso está sendo preparado, tenta reabrir em 1 minuto — qualquer coisa, fala com a equipe da imersão."** e use o fallback do passo 3 (MCP). Nunca trave nem fique em loop.
22
25
 
23
26
  ## 1. Prepare o curso (em silêncio, antes de falar)
24
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paris-immersion",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Paris Immersion CLI — login, install workspace, status, task control. Para alunos das imersões da Paris Group.",
5
5
  "homepage": "https://parisgroup.ai",
6
6
  "repository": {