thinkpool-pair 0.7.345 → 0.7.346

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 CHANGED
@@ -55,7 +55,7 @@ import { readCodexDefaultModel, readCodexModels, codexConfigForMode, codexThread
55
55
  import { codexAccountUsageLine, codexCreditsReportLine, codexLimitReportLine } from './codex-commands.mjs'
56
56
  import { withMcpSessionFactory } from './codex-mcp-http.mjs'
57
57
  import { startStructuredSession } from './runtime-session.mjs'
58
- import { fallbackTerminalName } from './terminal-name.mjs'
58
+ import { cleanTerminalName, fallbackTerminalName, modelTerminalNameInput } from './terminal-name.mjs'
59
59
  import { defaultStructuredMode, normalizeStructuredEffort, shouldDeferStructuredRuntime, structuredModeForSlice, structuredModeLocked, structuredModesForLane, structuredRuntimeForCommand, structuredRuntimeMetadata, structuredRuntimeSupportsMode } from './runtime-registry.mjs'
60
60
  import { commandCatalogForRuntime, commandHelpLine, reconcileCommandCatalog } from './command-catalog.mjs'
61
61
  import { gitDiffReport } from './git-diff-report.mjs'
@@ -1479,8 +1479,40 @@ const applyAutoTerminalName = (id, candidate) => {
1479
1479
  return true
1480
1480
  }
1481
1481
 
1482
- // First real task only. Naming is deterministic and entirely local: no provider
1483
- // receives the task, and every runtime follows the same zero-token path.
1482
+ const requestManagedTerminalName = async (id, task, retry = true) => {
1483
+ if (!codeAuthToken || !id || !task) return
1484
+ const controller = new AbortController()
1485
+ const timeout = setTimeout(() => controller.abort(), 4500)
1486
+ try {
1487
+ const response = await fetch(`${WEB_BASE}/api/code-terminal-name`, {
1488
+ method: 'POST',
1489
+ headers: {
1490
+ Authorization: `Bearer ${codeAuthToken}`,
1491
+ 'Content-Type': 'application/json',
1492
+ },
1493
+ body: JSON.stringify({ code: room, terminalId: id, task }),
1494
+ signal: controller.signal,
1495
+ })
1496
+ clearTimeout(timeout)
1497
+ const data = await response.json().catch(() => ({}))
1498
+ // Bridge-created lanes can receive their task before the browser has
1499
+ // inserted the terminal row. Retry that non-billable race once; every
1500
+ // provider failure simply keeps the already-visible local fallback.
1501
+ if (retry && response.status === 404 && data?.code === 'terminal_pending') {
1502
+ const timer = setTimeout(() => { void requestManagedTerminalName(id, task, false) }, 1500)
1503
+ timer.unref?.()
1504
+ return
1505
+ }
1506
+ if (!response.ok) return
1507
+ const candidate = cleanTerminalName(data?.name)
1508
+ if (candidate) applyAutoTerminalName(id, candidate)
1509
+ } catch {
1510
+ clearTimeout(timeout)
1511
+ }
1512
+ }
1513
+
1514
+ // First real task only. The zero-token local name appears immediately; a
1515
+ // managed tiny model may improve it later without delaying the agent turn.
1484
1516
  const autoNameTerminal = (id, text) => {
1485
1517
  const entry = sessions.get(id)
1486
1518
  if (!entry || termNames[id] || manualNameTouched.has(id) || autoNameAttempts.has(id)) return
@@ -1489,6 +1521,8 @@ const autoNameTerminal = (id, text) => {
1489
1521
  if (!fallback) return
1490
1522
  autoNameAttempts.add(id)
1491
1523
  applyAutoTerminalName(id, fallback)
1524
+ const task = modelTerminalNameInput(text)
1525
+ if (task) void requestManagedTerminalName(id, task)
1492
1526
  }
1493
1527
 
1494
1528
  // (cross-person grantee yield removed 2026-07-06 — owner-only serving now; the owner's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.345",
3
+ "version": "0.7.346",
4
4
  "description": "Connect Claude Code, Codex, or Hermes on your computer to a Thinkpool Code room.",
5
5
  "type": "module",
6
6
  "bin": {
package/terminal-name.mjs CHANGED
@@ -315,3 +315,29 @@ export function fallbackTerminalName(text) {
315
315
  .slice(0, 1600)
316
316
  return taskTitle(body)
317
317
  }
318
+
319
+ const MODEL_INPUT_MAX_BYTES = 1600
320
+
321
+ const truncateUtf8 = (value, maxBytes = MODEL_INPUT_MAX_BYTES) => {
322
+ let result = ''
323
+ let bytes = 0
324
+ for (const char of String(value || '')) {
325
+ const size = Buffer.byteLength(char, 'utf8')
326
+ if (bytes + size > maxBytes) break
327
+ result += char
328
+ bytes += size
329
+ }
330
+ return result.trim()
331
+ }
332
+
333
+ // The managed namer never receives the raw room prompt. Reuse the local
334
+ // extractor's authoritative-task selection, secret redaction, and host-reference
335
+ // stripping, then add a byte ceiling so multilingual text stays cost-bounded.
336
+ export function modelTerminalNameInput(text) {
337
+ const body = withoutHostReferences(withoutSecrets(extractTerminalTask(text) || ''))
338
+ .replace(/[`*_>#()[\]{}]/g, ' ')
339
+ .replace(/\s+/g, ' ')
340
+ .trim()
341
+ if (!body || containsSecret(body)) return null
342
+ return truncateUtf8(body)
343
+ }