thinkpool-pair 0.3.1 → 0.3.4
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/bridge.mjs +30 -7
- package/package.json +1 -1
package/bridge.mjs
CHANGED
|
@@ -135,7 +135,9 @@ const announce = () =>
|
|
|
135
135
|
channel.send({ type: 'broadcast', event: 'bridge', payload: {
|
|
136
136
|
v: 2, name, repo: repoLabel, branch,
|
|
137
137
|
agents: installedAgents,
|
|
138
|
-
|
|
138
|
+
// cols/rows: the PTY's one true size — web viewers render this grid and
|
|
139
|
+
// scale it to their own page instead of voting to reflow it.
|
|
140
|
+
terms: [...terms.entries()].map(([id, t]) => ({ id, cmd: t.cmd, alive: true, cols: t.term.cols, rows: t.term.rows })),
|
|
139
141
|
} })
|
|
140
142
|
|
|
141
143
|
// One flush timer batches every terminal's pending bytes (~35ms cadence).
|
|
@@ -149,12 +151,27 @@ const flushAll = () => {
|
|
|
149
151
|
}
|
|
150
152
|
const flushTimer = setInterval(flushAll, 35)
|
|
151
153
|
|
|
154
|
+
// ── shared-PTY geometry ───────────────────────────────────────────
|
|
155
|
+
// The room's view is the product: the shared PTY never goes below
|
|
156
|
+
// FLOOR_COLS×FLOOR_ROWS, no matter what the host does to their local
|
|
157
|
+
// window. Below the floor the HOST's rendering wraps oddly (the agent
|
|
158
|
+
// keeps drawing for the floor width) — the pair's view stays clean.
|
|
159
|
+
// Pin an exact size with TP_COLS/TP_ROWS (disables host-following).
|
|
160
|
+
const FLOOR_COLS = 100, FLOOR_ROWS = 28
|
|
161
|
+
const PIN_COLS = parseInt(process.env.TP_COLS, 10) || null
|
|
162
|
+
const PIN_ROWS = parseInt(process.env.TP_ROWS, 10) || null
|
|
163
|
+
const attachedDims = () => ({
|
|
164
|
+
cols: PIN_COLS || Math.max(process.stdout.columns || FLOOR_COLS, FLOOR_COLS),
|
|
165
|
+
rows: PIN_ROWS || Math.max(process.stdout.rows || FLOOR_ROWS, FLOOR_ROWS),
|
|
166
|
+
})
|
|
167
|
+
|
|
152
168
|
function openTerm({ id, cmd, args = [], attached = false, cols, rows }) {
|
|
153
169
|
if (terms.has(id)) return
|
|
170
|
+
const ad = attached ? attachedDims() : null
|
|
154
171
|
const term = pty.spawn(cmd, args, {
|
|
155
172
|
name: 'xterm-256color',
|
|
156
|
-
cols: cols || (attached ?
|
|
157
|
-
rows: rows || (attached ?
|
|
173
|
+
cols: cols || (attached ? ad.cols : 100),
|
|
174
|
+
rows: rows || (attached ? ad.rows : 30),
|
|
158
175
|
cwd: process.cwd(), env: process.env,
|
|
159
176
|
})
|
|
160
177
|
const entry = { term, cmd, attached, scrollback: '', buf: '' }
|
|
@@ -192,10 +209,14 @@ process.stdin.on('data', d => {
|
|
|
192
209
|
if (t) t.term.write(d.toString('utf8'))
|
|
193
210
|
else if (d.includes(3)) shutdown() // Ctrl-C once detached/headless
|
|
194
211
|
})
|
|
195
|
-
// attached terminal follows the host's TTY size
|
|
212
|
+
// attached terminal follows the host's TTY size — but never below the
|
|
213
|
+
// floor, and never at all when pinned. Re-announce so viewers rescale.
|
|
196
214
|
process.stdout.on('resize', () => {
|
|
197
215
|
const t = attachedId && terms.get(attachedId)
|
|
198
|
-
if (t)
|
|
216
|
+
if (!t) return
|
|
217
|
+
const { cols, rows } = attachedDims()
|
|
218
|
+
if (t.term.cols === cols && t.term.rows === rows) return
|
|
219
|
+
try { t.term.resize(cols, rows); announce() } catch { /* noop */ }
|
|
199
220
|
})
|
|
200
221
|
|
|
201
222
|
channel
|
|
@@ -205,10 +226,12 @@ channel
|
|
|
205
226
|
if (t) t.term.write(payload.data)
|
|
206
227
|
})
|
|
207
228
|
.on('broadcast', { event: 'resize' }, ({ payload }) => {
|
|
208
|
-
// headless terms are web-sized (last writer wins); the attached term is
|
|
229
|
+
// headless terms are web-sized (last writer wins); the attached term is
|
|
230
|
+
// host-sized. Floor at 80 cols — one narrow phone viewer must not reflow
|
|
231
|
+
// the shared PTY into a 40-col column for everyone (2026-06-10 bug).
|
|
209
232
|
if (!payload?.cols || !payload?.rows) return
|
|
210
233
|
const t = terms.get(payload.term)
|
|
211
|
-
if (t && !t.attached) { try { t.term.resize(payload.cols, payload.rows) } catch { /* noop */ } }
|
|
234
|
+
if (t && !t.attached) { try { t.term.resize(Math.max(payload.cols, 80), Math.max(payload.rows, 20)); announce() } catch { /* noop */ } }
|
|
212
235
|
})
|
|
213
236
|
.on('broadcast', { event: 'term-open' }, ({ payload }) => {
|
|
214
237
|
if (!payload?.id || !payload?.cmd) return
|
package/package.json
CHANGED