peertable 0.4.18 → 0.4.20

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.18",
3
+ "version": "0.4.20",
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.18'
16
+ const MCP_VERSION = '0.4.20'
17
17
  const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
18
18
 
19
19
  const USAGE = `usage:
@@ -217,11 +217,29 @@ fi
217
217
  # model unavailable で 0 秒失敗し、席は一度も仕事をできなかった(room [11])。
218
218
  # バナーは CLI が起動したことしか言わないので、**live に応答するかは非対話入口で先に測る**。
219
219
  # 席を畳む前に測るのが要点である——ここで落ちれば、動いている席を殺さずに済む。
220
+ export PATH="${HOME}/.grok/bin:${PATH}"
220
221
  preflight_dir="${TMPDIR:-/tmp}"
221
222
  case "$vendor" in
222
223
  claude) preflight_cmd=(claude --model "$model" -p "ping") ;;
223
224
  codex) preflight_cmd=(codex exec --model "$model" --skip-git-repo-check "ping") ;;
224
- grok) preflight_cmd=(grok --model "$model" --reasoning-effort "$effort" -p "ping") ;;
225
+ grok)
226
+ grok_bin=$(command -v grok || true)
227
+ if [ -z "$grok_bin" ]; then
228
+ echo "SEAT_GROK_CLI_MISSING: grok が PATH に無い(席は立てない)" >&2
229
+ exit 1
230
+ fi
231
+ # 通常 GROK_HOME の config は booth 等 MCP を起動する。preflight がそれを待つと
232
+ # 120 秒で空ログのまま死ぬ(2026-08-20)。認証だけ借りて MCP 無しで ping する。
233
+ grok_home=$(mktemp -d "${TMPDIR:-/tmp}/peertable-grok-home.XXXXXX")
234
+ if [ ! -f "${HOME}/.grok/auth.json" ]; then
235
+ echo "SEAT_GROK_AUTH_MISSING: ${HOME}/.grok/auth.json が無い(席は立てない)" >&2
236
+ exit 1
237
+ fi
238
+ cp "${HOME}/.grok/auth.json" "${grok_home}/auth.json"
239
+ printf '%s\n' '[ui]' 'permission_mode = "always-approve"' >"${grok_home}/config.toml"
240
+ echo "grok preflight: GROK_HOME=${grok_home} ${grok_bin} --model ${model} --reasoning-effort ${effort} -p ping"
241
+ preflight_cmd=(env GROK_HOME="$grok_home" "$grok_bin" --model "$model" --reasoning-effort "$effort" -p "ping")
242
+ ;;
225
243
  *) echo "unknown vendor: ${vendor}(claude / codex / grok)" >&2; exit 1 ;;
226
244
  esac
227
245
  preflight_log=$(mktemp "${TMPDIR:-/tmp}/peertable-preflight.XXXXXX")
@@ -242,16 +260,20 @@ done
242
260
  if [ -z "$preflight_rc" ]; then
243
261
  kill "$preflight_pid" 2>/dev/null || true
244
262
  echo "model preflight が 120 秒で返らない: ${vendor} / ${model}(席は立てない)" >&2
245
- rm -f "$preflight_log"
263
+ echo "preflight log: ${preflight_log}" >&2
264
+ cat "$preflight_log" >&2 || true
265
+ [ -n "${grok_home:-}" ] && rm -rf "$grok_home"
246
266
  exit 1
247
267
  fi
248
268
  if [ "$preflight_rc" != 0 ]; then
249
269
  echo "model が live で使えない: ${vendor} / ${model}(preflight rc=${preflight_rc}・席は立てない)" >&2
250
- tail -5 "$preflight_log" >&2
270
+ cat "$preflight_log" >&2 || true
251
271
  rm -f "$preflight_log"
272
+ [ -n "${grok_home:-}" ] && rm -rf "$grok_home"
252
273
  exit 1
253
274
  fi
254
275
  rm -f "$preflight_log"
276
+ [ -n "${grok_home:-}" ] && rm -rf "$grok_home"
255
277
 
256
278
  sock=$(node "$(dirname "$0")/tmux-socket.mjs")
257
279
  sess="peer-$name"
@@ -606,28 +628,8 @@ fi
606
628
 
607
629
  # 席の素性(roles / settings / mission)を room へ渡す。一覧チップと席の名簿が同じ欄を見る。
608
630
  tmux_ns=$(node "$(dirname "$0")/tmux-socket.mjs" --namespace)
609
- meta=$(python3 - "$name" "$vendor" "$model" "$effort" "$sock" "$sess" "$role" "$mission" "$aiterm_session_id" "$tmux_ns" <<'PY'
610
- import json, sys
611
- name, vendor, model, effort, sock, sess, roles_raw, mission, aiterm_session_id, tmux_ns = sys.argv[1:11]
612
- observe = {'tmux_socket': sock, 'tmux_target': sess}
613
- if tmux_ns:
614
- observe['tmux_namespace'] = tmux_ns
615
- roles = [item for item in roles_raw.split(',') if item]
616
- settings = {'vendor': vendor, 'model': model}
617
- if effort:
618
- settings['effort'] = effort
619
- body = {
620
- 'name': name, 'vendor': vendor, 'model': model, 'role': roles[0] if roles else '',
621
- 'roles': roles, 'settings': settings, 'aiterm_session_id': aiterm_session_id,
622
- 'observe': observe,
623
- }
624
- if effort:
625
- body['effort'] = effort
626
- if mission:
627
- body['mission'] = mission
628
- print(json.dumps(body, ensure_ascii=False))
629
- PY
630
- )
631
+ # python stdout Windows cp932 になり 実装 が壊れる。Node UTF-8 JSON を出す。
632
+ meta=$(node "$(dirname "$0")/seat-metadata.mjs" "$name" "$vendor" "$model" "$effort" "$sock" "$sess" "$role" "$mission" "$aiterm_session_id" "$tmux_ns")
631
633
  if env -u PEERTABLE_POST_TOKEN node "$credential_helper" request "$credential_file" POST \
632
634
  "$url/api/$room/members" "$meta" >/dev/null; then
633
635
  # **200 は保存の証拠にならない**。素性欄を知らない server も 200 {"ok":true} を返して黙って捨てる
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ // 着席 metadata を UTF-8 JSON で出す。python stdout の cp932 経由は日本語 roles を壊す。
3
+ const [name, vendor, model, effort, sock, sess, rolesRaw, mission, aitermSessionId, tmuxNs] = process.argv.slice(2)
4
+ const roles = String(rolesRaw || '').split(',').map((item) => item.trim()).filter(Boolean)
5
+ const settings = { vendor, model }
6
+ if (effort) settings.effort = effort
7
+ const observe = { tmux_socket: sock, tmux_target: sess }
8
+ if (tmuxNs) observe.tmux_namespace = tmuxNs
9
+ const body = {
10
+ name,
11
+ vendor,
12
+ model,
13
+ role: roles[0] || '',
14
+ roles,
15
+ settings,
16
+ aiterm_session_id: aitermSessionId,
17
+ observe,
18
+ }
19
+ if (effort) body.effort = effort
20
+ if (mission) body.mission = mission
21
+ process.stdout.write(`${JSON.stringify(body)}\n`)