paris-immersion 0.1.5 → 0.1.7

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
@@ -12,7 +12,7 @@ import { serveCommand } from './commands/serve.js';
12
12
  const program = new Command()
13
13
  .name('paris')
14
14
  .description('Paris Immersion — CLI do aluno (login, workspace, tarefas)')
15
- .version('0.1.5');
15
+ .version('0.1.7');
16
16
  program
17
17
  .command('login')
18
18
  .description('Autenticar com sua conta Paris (device-code OR --token direto)')
@@ -12,6 +12,7 @@ import { WebSocket } from 'ws';
12
12
  import { spawnCoachPty } from '../commands/serve.js';
13
13
  const TYPE_DATA = 0x00;
14
14
  const TYPE_RESIZE = 0x01;
15
+ const TYPE_WORKSPACE = 0x02; // agent → viewer: caminho do workspace (pro handoff nativo)
15
16
  /** plaintext = type(1) || body → frame = nonce(12) || AES-256-GCM(enc||tag). */
16
17
  function seal(key, type, body) {
17
18
  const nonce = crypto.randomBytes(12);
@@ -72,12 +73,14 @@ export async function startRelayAgent(opts) {
72
73
  // "no-op" (reconexão com mesma dimensão) e forçar o Claude a repintar.
73
74
  let ptyCols = 80;
74
75
  let ptyRows = 24;
75
- // Coalescing da saída do pty: o Claude emite a tela em RAJADAS de muitos
76
- // chunks pequenos. Cifrar/enviar cada um (1 AES-GCM + 1 frame WS por chunk)
77
- // é caro e deixa a escrita lenta. Junta numa janela curta → 1 frame por
78
- // rajada. ~12ms é imperceptível e corta o overhead drasticamente.
79
- const COALESCE_MS = 12;
80
- const MAX_OUT_BUF = 64 * 1024;
76
+ // Coalescing da saída do pty: o Claude faz streaming token-a-token (~20-30ms
77
+ // entre tokens). Com janela curta, cada token vira um frame (1 AES-GCM + 1
78
+ // frame WS + 1 round-trip + 1 render) → escrita picotada/lenta. Uma janela
79
+ // maior junta VÁRIOS tokens por frame → escrita lisa, muito menos overhead.
80
+ // O custo é ~Xms a mais de latência — imperceptível pra leitura do curso.
81
+ // Ajustável por env (PARIS_RELAY_COALESCE_MS) pra afinar sem republicar.
82
+ const COALESCE_MS = Math.min(250, Math.max(0, Number(process.env.PARIS_RELAY_COALESCE_MS) || 55));
83
+ const MAX_OUT_BUF = 256 * 1024;
81
84
  let outBuf = '';
82
85
  let flushTimer;
83
86
  const flushOut = () => {
@@ -181,6 +184,16 @@ export async function startRelayAgent(opts) {
181
184
  killTimer = undefined;
182
185
  }
183
186
  startPty(); // no-op se já tem Claude vivo → reatacha na mesma sessão
187
+ // Informa o caminho do workspace pro browser oferecer o handoff nativo
188
+ // ("seguir no terminal nativo" → cd <ws> && claude --continue).
189
+ if (opts.cwd && ws && ws.readyState === WebSocket.OPEN) {
190
+ try {
191
+ ws.send(seal(key, TYPE_WORKSPACE, Buffer.from(opts.cwd, 'utf8')), { binary: true });
192
+ }
193
+ catch {
194
+ /* noop */
195
+ }
196
+ }
184
197
  }
185
198
  else if (m.t === 'viewer-left') {
186
199
  // Não mata na hora — janela de graça pra reconexão reatachar.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paris-immersion",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
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": {