paris-immersion 0.1.4 → 0.1.5
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 +1 -1
- package/dist/lib/relay-agent.js +38 -6
- package/package.json +1 -1
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.
|
|
15
|
+
.version('0.1.5');
|
|
16
16
|
program
|
|
17
17
|
.command('login')
|
|
18
18
|
.description('Autenticar com sua conta Paris (device-code OR --token direto)')
|
package/dist/lib/relay-agent.js
CHANGED
|
@@ -72,12 +72,40 @@ export async function startRelayAgent(opts) {
|
|
|
72
72
|
// "no-op" (reconexão com mesma dimensão) e forçar o Claude a repintar.
|
|
73
73
|
let ptyCols = 80;
|
|
74
74
|
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;
|
|
81
|
+
let outBuf = '';
|
|
82
|
+
let flushTimer;
|
|
83
|
+
const flushOut = () => {
|
|
84
|
+
flushTimer = undefined;
|
|
85
|
+
if (!outBuf)
|
|
86
|
+
return;
|
|
87
|
+
const data = outBuf;
|
|
88
|
+
outBuf = '';
|
|
89
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
90
|
+
try {
|
|
91
|
+
ws.send(seal(key, TYPE_DATA, Buffer.from(data, 'utf8')), { binary: true });
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
/* ws caiu no meio */
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
75
98
|
// Mantém o Claude vivo por uma janela após o viewer sair, pra que uma
|
|
76
99
|
// reconexão (ex.: Safari derruba o ws periodicamente) REATACHE na MESMA sessão
|
|
77
100
|
// em vez de reiniciar o curso. O resize que o viewer manda ao reconectar faz a
|
|
78
101
|
// TUI do Claude repintar a tela atual.
|
|
79
102
|
const PTY_GRACE_MS = 600_000; // 10min — aluno que sai no meio e volta reatacha na MESMA sessão
|
|
80
103
|
const killPty = () => {
|
|
104
|
+
if (flushTimer) {
|
|
105
|
+
clearTimeout(flushTimer);
|
|
106
|
+
flushTimer = undefined;
|
|
107
|
+
}
|
|
108
|
+
outBuf = '';
|
|
81
109
|
if (pty) {
|
|
82
110
|
try {
|
|
83
111
|
pty.kill();
|
|
@@ -99,13 +127,17 @@ export async function startRelayAgent(opts) {
|
|
|
99
127
|
return;
|
|
100
128
|
}
|
|
101
129
|
pty.onData((d) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
outBuf += d;
|
|
131
|
+
// Flush imediato se acumulou muito (evita um frame gigante); senão coalesce.
|
|
132
|
+
if (outBuf.length >= MAX_OUT_BUF) {
|
|
133
|
+
if (flushTimer) {
|
|
134
|
+
clearTimeout(flushTimer);
|
|
135
|
+
flushTimer = undefined;
|
|
108
136
|
}
|
|
137
|
+
flushOut();
|
|
138
|
+
}
|
|
139
|
+
else if (!flushTimer) {
|
|
140
|
+
flushTimer = setTimeout(flushOut, COALESCE_MS);
|
|
109
141
|
}
|
|
110
142
|
});
|
|
111
143
|
pty.onExit?.(() => killPty());
|
package/package.json
CHANGED