paris-immersion 0.1.31 → 0.1.33

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.
package/dist/index.js CHANGED
File without changes
@@ -16,10 +16,13 @@ const execFileP = promisify(execFile);
16
16
  * orca terminal create ... → aba nova com o claude + prompt, em foco
17
17
  */
18
18
  function findOrcaBin() {
19
+ // Caminhos fixos primeiro (instalador põe em ~/.local/bin), depois o PATH do
20
+ // processo — o daemon (launchd/systemd) herda um PATH rico do install.
19
21
  const candidates = [
20
22
  path.join(homedir(), '.local', 'bin', 'orca'),
21
23
  '/usr/local/bin/orca',
22
24
  '/opt/homebrew/bin/orca',
25
+ ...(process.env.PATH ?? '').split(path.delimiter).filter(Boolean).map((d) => path.join(d, 'orca')),
23
26
  ];
24
27
  for (const c of candidates) {
25
28
  if (existsSync(c))
@@ -39,11 +42,19 @@ export async function startMissionInOrca(opts) {
39
42
  return { ok: false, error: 'Workspace da imersão não encontrado nesta máquina.' };
40
43
  }
41
44
  try {
42
- // 1. App + runtime de pé (no-op se já rodando). `orca open` espera o runtime
43
- // ficar alcançável — timeout generoso pro cold start do app.
44
- await execFileP(orca, ['open'], { timeout: 45_000 });
45
- // 2. Workspace registrado (idempotente na prática: "já existe" é sucesso).
46
- await execFileP(orca, ['repo', 'add', opts.cwd, '--json'], { timeout: 15_000 }).catch(() => { });
45
+ // 1. App + runtime de pé (no-op se já rodando). BEST-EFFORT: `orca open`
46
+ // espera uma JANELA de desktop e estoura timeout quando o runtime roda
47
+ // headless — mas o `terminal create` funciona do mesmo jeito nesse caso.
48
+ // Quem decide sucesso/falha é o passo 3.
49
+ await execFileP(orca, ['open'], { timeout: 45_000 }).catch(() => { });
50
+ // 2. O Orca só registra REPO GIT — o workspace do `paris install` nasce sem
51
+ // .git, então inicializamos (best-effort, idempotente; a metodologia
52
+ // termina com o repo no GitHub de qualquer forma). Depois registra
53
+ // (`--path`; "já registrado" também é sucesso).
54
+ if (!existsSync(path.join(opts.cwd, '.git'))) {
55
+ await execFileP('git', ['init'], { cwd: opts.cwd, timeout: 10_000 }).catch(() => { });
56
+ }
57
+ await execFileP(orca, ['repo', 'add', '--path', opts.cwd, '--json'], { timeout: 15_000 }).catch(() => { });
47
58
  // 3. Aba de terminal com o Claude já na missão, em foco. Aspas simples no
48
59
  // prompt são escapadas pro shell da aba.
49
60
  const promptQ = opts.prompt.replace(/'/g, `'\\''`);
@@ -60,14 +71,34 @@ export async function startMissionInOrca(opts) {
60
71
  ];
61
72
  if (opts.title)
62
73
  args.push('--title', opts.title.slice(0, 60));
63
- await execFileP(orca, args, { timeout: 30_000 });
74
+ try {
75
+ await execFileP(orca, args, { timeout: 30_000 });
76
+ }
77
+ catch (err) {
78
+ // Runtime fora do ar (app fechado): sobe o app de verdade (`open -a` no
79
+ // mac não espera janela — diferente do `orca open`), dá fôlego pro boot
80
+ // e tenta UMA vez de novo. Cobre o aluno que fechou o Orca.
81
+ const e = err;
82
+ const out = `${e.stdout ?? ''}${e.stderr ?? ''}${e.message ?? ''}`;
83
+ if (!/runtime_unavailable|Could not read Orca runtime|Start the Orca app/i.test(out))
84
+ throw err;
85
+ if (process.platform === 'darwin') {
86
+ await execFileP('open', ['-a', 'Orca'], { timeout: 10_000 }).catch(() => { });
87
+ }
88
+ await new Promise((r) => setTimeout(r, 8_000));
89
+ await execFileP(orca, args, { timeout: 30_000 });
90
+ }
64
91
  return { ok: true };
65
92
  }
66
93
  catch (err) {
67
- const msg = err instanceof Error ? err.message : String(err);
94
+ // execFile rejeita com stdout/stderr anexados — é onde o orca CLI explica o
95
+ // motivo real (`{ok:false,error:{...}}` no stdout). Sem isso o erro visível
96
+ // era só "Command failed: orca terminal create ..." (inútil pra diagnosticar).
97
+ const e = err;
98
+ const detail = (e.stderr || e.stdout || e.message || String(err)).trim();
68
99
  return {
69
100
  ok: false,
70
- error: `Não consegui abrir a missão no Orca: ${msg.slice(0, 200)}`,
101
+ error: `Não consegui abrir a missão no Orca: ${detail.slice(0, 300)}`,
71
102
  };
72
103
  }
73
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paris-immersion",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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": {