peertable 0.4.35 → 0.4.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peertable",
3
- "version": "0.4.35",
3
+ "version": "0.4.37",
4
4
  "description": "A round table of peer agents. No orchestrator at the head. Turn Claude Code, Codex, and Grok sessions into a team of equal, long-lived peers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/room/client.mjs CHANGED
@@ -13,7 +13,7 @@ import { findModelsDoc, resolveSeatIdentity } from '../skill/scripts/resolve-sea
13
13
 
14
14
  // client.mjs 側のハードコード版数。package.json の version と一致していることを
15
15
  // diagnostics の version_consistency が見る(2 つの版数源の drift 検出。決定45)
16
- const MCP_VERSION = '0.4.35'
16
+ const MCP_VERSION = '0.4.37'
17
17
  const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
18
18
 
19
19
  const USAGE = `usage:
@@ -440,6 +440,7 @@ mcp_consent_accepted=false
440
440
  codex_hooks_accepted=false
441
441
  codex_update_accepted=false
442
442
  codex_trust_accepted=false
443
+ claude_trust_accepted=false
443
444
  while [ $SECONDS -lt "$room_ready_deadline" ]; do
444
445
  # Grok Build は初めて開く作業treeで、room MCPを初期化する前にworkspace trustを尋ねる。
445
446
  # Peertableが正式に着席させるtreeなので、この既知文言だけを一度通す。未知の確認画面を
@@ -494,6 +495,22 @@ while [ $SECONDS -lt "$room_ready_deadline" ]; do
494
495
  ;;
495
496
  esac
496
497
  fi
498
+ # 未信頼ディレクトリでは room MCP 同意より前に workspace trust が出る。既定選択肢
499
+ # (1. Yes, I trust this folder)を Enter で通す。この既知文言だけを一度通す。
500
+ if [ "$vendor" = claude ] && [ "$claude_trust_accepted" != true ]; then
501
+ claude_trust_screen=$(tmux_at capture-pane -t "$sess" -p 2>/dev/null || true)
502
+ case "$claude_trust_screen" in
503
+ *"Is this a project you created or one you trust"*|*"trust this folder"*)
504
+ if ! tmux_at send-keys -t "$sess" Enter; then
505
+ echo "SEAT_CLAUDE_TRUST_FAILED: workspace trustへ応答できない" >&2
506
+ exit 1
507
+ fi
508
+ claude_trust_accepted=true
509
+ room_ready_deadline=$((SECONDS + 90))
510
+ echo "claude workspace trust: accepted"
511
+ ;;
512
+ esac
513
+ fi
497
514
  # aiterm claude_agent は --dangerously-skip-permissions を付けない。project の room MCP
498
515
  # 同意が member 登録より前に出る。選択肢2(this and all future)だけを通す。
499
516
  if [ "$vendor" = claude ] && [ "$mcp_consent_accepted" != true ]; then
@@ -159,8 +159,12 @@ const addressedToParent = message => messageAddressedToParent(message, parent)
159
159
 
160
160
  function exitWhenParentStdinCloses() {
161
161
  if (mode !== '--follow') return
162
+ // Claude Monitor など stdin を与えない persistent 実行では、stdin が最初から
163
+ // 閉じているのを親端末の終了と誤認して即死する。stdin が TTY でない、または
164
+ // PEERTABLE_WATCH_NO_STDIN=1 の時は stdin 追従を張らない(SKILL は Monitor 起動を指示する)。
165
+ if (process.env.PEERTABLE_WATCH_NO_STDIN === '1') return
162
166
  const stdin = process.stdin
163
- if (!stdin || stdin.destroyed) return
167
+ if (!stdin || stdin.destroyed || stdin.isTTY !== true) return
164
168
  const quit = () => process.exit(0)
165
169
  stdin.on('end', quit)
166
170
  stdin.on('close', quit)
@@ -125,7 +125,8 @@ const parseRoleList = (roles) => {
125
125
  return list
126
126
  }
127
127
 
128
- export function resolveSeatPlacement(role, markdown, { source = '' } = {}) {
128
+ export function resolveSeatPlacement(role, markdown, { source = '', vendor = '' } = {}) {
129
+ const wantVendor = String(vendor ?? '').trim()
129
130
  const wanted = String(role ?? '').trim()
130
131
  if (!wanted) {
131
132
  return { error: 'SEAT_ROLE_REQUIRED', message: 'role が空(02_models の役割名が要る)' }
@@ -150,6 +151,10 @@ export function resolveSeatPlacement(role, markdown, { source = '' } = {}) {
150
151
  dropped.push({ rank, reason: 'not-in-ledger', cell: parsed.cell })
151
152
  continue
152
153
  }
154
+ if (wantVendor && hit.vendor !== wantVendor) {
155
+ dropped.push({ rank, reason: `vendor-mismatch(want ${wantVendor})`, cell: parsed.cell })
156
+ continue
157
+ }
153
158
  if (hit.slug === 'haiku') {
154
159
  return { role: wanted, rank, vendor: hit.vendor, model: hit.slug, effort: '', source, dropped }
155
160
  }
@@ -169,7 +174,7 @@ export function resolveSeatPlacement(role, markdown, { source = '' } = {}) {
169
174
  }
170
175
  return {
171
176
  error: 'SEAT_PLACEMENT_UNRESOLVABLE',
172
- message: `${wanted} を着席可能な vendor/model/effort へ解決できない`,
177
+ message: `${wanted}${wantVendor ? `(vendor=${wantVendor})` : ''} を着席可能な vendor/model/effort へ解決できない`,
173
178
  dropped,
174
179
  }
175
180
  }
@@ -226,7 +231,7 @@ export function resolveSeatIdentity({
226
231
  }
227
232
  }
228
233
 
229
- const first = resolveSeatPlacement(roleList[0], markdown, { source })
234
+ const first = resolveSeatPlacement(roleList[0], markdown, { source, vendor: requestedVendor })
230
235
  if (first.error) return first
231
236
  return {
232
237
  roles: roleList,