thinkpool-pair 0.7.346 → 0.7.348

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 { cleanTerminalName, fallbackTerminalName, modelTerminalNameInput } from './terminal-name.mjs'
58
+ import { cleanTerminalName, 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'
@@ -1497,7 +1497,7 @@ const requestManagedTerminalName = async (id, task, retry = true) => {
1497
1497
  const data = await response.json().catch(() => ({}))
1498
1498
  // Bridge-created lanes can receive their task before the browser has
1499
1499
  // inserted the terminal row. Retry that non-billable race once; every
1500
- // provider failure simply keeps the already-visible local fallback.
1500
+ // provider failure leaves the terminal on its ordinary default label.
1501
1501
  if (retry && response.status === 404 && data?.code === 'terminal_pending') {
1502
1502
  const timer = setTimeout(() => { void requestManagedTerminalName(id, task, false) }, 1500)
1503
1503
  timer.unref?.()
@@ -1511,18 +1511,16 @@ const requestManagedTerminalName = async (id, task, retry = true) => {
1511
1511
  }
1512
1512
  }
1513
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.
1514
+ // First real task only. Naming is managed-model-only: keep the terminal's
1515
+ // ordinary default label until Groq returns instead of showing a local guess.
1516
1516
  const autoNameTerminal = (id, text) => {
1517
1517
  const entry = sessions.get(id)
1518
1518
  if (!entry || termNames[id] || manualNameTouched.has(id) || autoNameAttempts.has(id)) return
1519
1519
  if (entry.log?.some((event) => event?.kind === 'you')) return
1520
- const fallback = fallbackTerminalName(text)
1521
- if (!fallback) return
1522
- autoNameAttempts.add(id)
1523
- applyAutoTerminalName(id, fallback)
1524
1520
  const task = modelTerminalNameInput(text)
1525
- if (task) void requestManagedTerminalName(id, task)
1521
+ if (!task) return
1522
+ autoNameAttempts.add(id)
1523
+ void requestManagedTerminalName(id, task)
1526
1524
  }
1527
1525
 
1528
1526
  // (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.346",
3
+ "version": "0.7.348",
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
@@ -23,6 +23,7 @@ const ISSUE = /\b(?:broken|buggy|crash(?:es|ed|ing)?|duplicate|error|fail(?:s|ed
23
23
  const REQUEST = /^(?:please\s+)?(?:can|could|would|will)\s+(?:we|you)\b|^(?:please\s+)?(?:how about|let's|let us|we need to|i want you to)\b/i
24
24
  const SECRET = /(?<![\p{L}\p{N}])(?:sk-(?:proj-)?[a-z0-9_-]{8,}|gsk_[a-z0-9_-]{8,}|xox[baprs]-[a-z0-9_-]{8,}|gh[pousr]_[a-z0-9_-]{8,}|glpat-[a-z0-9_-]{8,}|npm_[a-z0-9]{24,}|(?:sk|rk)_(?:live|test)_[a-z0-9]{8,}|whsec_[a-z0-9]{8,}|AIza[a-z0-9_-]{8,}|AKIA[A-Z0-9]{12,}|bearer\s+[a-z0-9._-]{8,}|eyJ[a-z0-9_-]{8,}\.[a-z0-9_-]{8,}\.[a-z0-9_-]{8,})(?![\p{L}\p{N}])/giu
25
25
  const HANDOFF_MARKER = /^---\s*(?:the person's next message|current person request(?:\s*\([^\n]*\))?|side task)\s*---\s*$/gim
26
+ const CURRENT_REQUEST_MARKER = /^(?:#{1,6}\s*)?CURRENT PERSON REQUEST(?:\s*\([^\n]*\))?\s*:?\s*/gim
26
27
  const QUESTION_WORDS = new Set(['how', 'what', 'when', 'where', 'which', 'who', 'whom', 'whose', 'why'])
27
28
  const PREFERENCE_WORDS = new Set(['avoid', 'choose', 'include', 'need', 'use', 'want'])
28
29
  const PREFERENCE_OBJECT_WORDS = new Set(['avoid', 'choose', 'include', 'use'])
@@ -330,11 +331,20 @@ const truncateUtf8 = (value, maxBytes = MODEL_INPUT_MAX_BYTES) => {
330
331
  return result.trim()
331
332
  }
332
333
 
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.
334
+ const managedTaskText = (value) => {
335
+ let text = stripPromptNoise(value)
336
+ if (!text) return null
337
+ const currentRequests = [...text.matchAll(CURRENT_REQUEST_MARKER)]
338
+ const currentRequest = currentRequests.at(-1)
339
+ if (currentRequest) text = text.slice(currentRequest.index + currentRequest[0].length)
340
+ return (explicitIntent(text) || text).trim() || null
341
+ }
342
+
343
+ // The managed namer never receives room/system envelopes, secrets, URLs, or
344
+ // host paths. Preserve every clause of the current task so the model—not the
345
+ // brittle local title heuristic—chooses the primary outcome and constraints.
336
346
  export function modelTerminalNameInput(text) {
337
- const body = withoutHostReferences(withoutSecrets(extractTerminalTask(text) || ''))
347
+ const body = withoutHostReferences(withoutSecrets(managedTaskText(text) || ''))
338
348
  .replace(/[`*_>#()[\]{}]/g, ' ')
339
349
  .replace(/\s+/g, ' ')
340
350
  .trim()