thinkpool-pair 0.7.162 → 0.7.163

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
@@ -42,7 +42,7 @@ import { reapTerminalRow as _reapTerminalRow } from './reap-terminal.mjs'
42
42
  // resolveProviderEnv(id) → {ANTHROPIC_BASE_URL,ANTHROPIC_AUTH_TOKEN,ANTHROPIC_MODEL} for a
43
43
  // registered custom provider, or null for the built-in/unknown (leave the default env intact).
44
44
  // Multi-provider BYOK slice 1: a lane spawned with a `provider` id runs on that endpoint.
45
- import { resolveProviderEnv } from './providers.mjs'
45
+ import { resolveProviderEnv, providerNameMap } from './providers.mjs'
46
46
  import { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk'
47
47
  import { z } from 'zod'
48
48
  import { startClaudeSession } from './claude-session.mjs'
@@ -885,8 +885,12 @@ const termNames = loadNames(room)
885
885
  // a hardcoded shorthand set on other devices / after reload). Max 2026-07-02.
886
886
  let roomModels = null
887
887
 
888
- const announce = () =>
889
- bcast('bridge', {
888
+ const announce = () => {
889
+ // Per-lane provider projection: resolve the registry id→NAME once per announce
890
+ // (name-only, NEVER key/baseUrl) so a cross-device viewer can badge a lane opened
891
+ // on a custom provider without the owner's account-channel registry.
892
+ const provNames = providerNameMap()
893
+ return bcast('bridge', {
890
894
  v: 2, name, repo: repoLabel, branch: readBranch(),
891
895
  // sdkWarn: the auto-pulled agent SDK failed its boot compatibility smoke test —
892
896
  // surfaced so the room can show a banner (turns may misbehave; pin a good SDK).
@@ -945,9 +949,15 @@ const announce = () =>
945
949
  // turnActive). Authoritative — the bridge owns the turn — so the /code
946
950
  // dashboard reads "N agents working" off the roster instead of sniffing
947
951
  // the live code-event stream (which a passive dashboard channel misses).
948
- ...[...sessions.entries()].map(([id, s]) => ({ id, cmd: s.cmd, kind: 'structured', alive: true, busy: s.session?.turnActive ?? false, commands: s.commands, mode: s.mode || undefined, name: termNames[id] || undefined, model: s.model || undefined, ...(s.archiveOldestSeq != null ? { oldestSeq: s.archiveOldestSeq } : {}), ...(s.spawnedBy ? { spawned: true, spawnedBy: s.spawnedBy } : {}), ...(s.flowSessionId ? { flowId: s.flowSessionId, flowRole: s.flowTaskKey ? 'lane' : 'conductor' } : {}) })),
952
+ ...[...sessions.entries()].map(([id, s]) => ({ id, cmd: s.cmd, kind: 'structured', alive: true, busy: s.session?.turnActive ?? false, commands: s.commands, mode: s.mode || undefined, name: termNames[id] || undefined, model: s.model || undefined, ...(s.archiveOldestSeq != null ? { oldestSeq: s.archiveOldestSeq } : {}), ...(s.spawnedBy ? { spawned: true, spawnedBy: s.spawnedBy } : {}), ...(s.flowSessionId ? { flowId: s.flowSessionId, flowRole: s.flowTaskKey ? 'lane' : 'conductor' } : {}),
953
+ // provider: the registered LLM-provider this lane runs on, NAME-ONLY {id,name}
954
+ // (NEVER the key or baseUrl). Additive; older clients ignore it. Omitted for the
955
+ // built-in/default Claude path (no badge). Makes the lane's provider badge +
956
+ // /model honesty cross-device (was device-local via localStorage) and survives a
957
+ // bridge restart (entry.provider is persisted with the session).
958
+ ...(s.provider && s.provider !== 'anthropic' ? { provider: { id: s.provider, name: provNames[s.provider] || s.provider } } : {}) })),
949
959
  ],
950
- })
960
+ }) }
951
961
 
952
962
  // Owner reclaim (Contract C-CODE-3 invariant 3): a grantee-served bridge that sees
953
963
  // the OWNER's bridge announce on this same room channel stands down — the owner's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.162",
3
+ "version": "0.7.163",
4
4
  "description": "Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.",
5
5
  "type": "module",
6
6
  "bin": {
package/providers.mjs CHANGED
@@ -211,6 +211,20 @@ export function announceProviders() {
211
211
  return [{ id: BUILTIN_ID, name: 'Anthropic (Claude)', model: null }, ...custom]
212
212
  }
213
213
 
214
+ /**
215
+ * id → name map for the ROOM announce's per-lane provider projection (name-only,
216
+ * NEVER key or baseUrl). Built once per announce so a cross-device viewer resolves
217
+ * a lane's provider badge without the owner's account-channel registry. Built-in
218
+ * `anthropic` is omitted (the default path shows no badge). A stale/removed id has
219
+ * no entry; the caller falls back to the bare id (a random UUID — not key material).
220
+ * @returns {Record<string,string>}
221
+ */
222
+ export function providerNameMap() {
223
+ const m = {}
224
+ for (const p of loadProviders()) if (p?.id && p.id !== BUILTIN_ID) m[p.id] = p.name
225
+ return m
226
+ }
227
+
214
228
  function keyHint(key) {
215
229
  const k = String(key || '')
216
230
  return k.length <= 4 ? k : k.slice(-4)