peertable 0.4.19 → 0.4.21

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.19",
3
+ "version": "0.4.21",
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.19'
16
+ const MCP_VERSION = '0.4.21'
17
17
  const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
18
18
 
19
19
  const USAGE = `usage:
package/skill/SKILL.md CHANGED
@@ -66,7 +66,7 @@ script は内部で Aiterm の公開 `claude_agent` / `codex_agent` / `grok_agen
66
66
  - 着任指示を第6引数に渡すと着席後に送る。文面: 「あなたは「<日本語名>」。.team/roles/member.md を読んで着任し、作業ループを開始せよ。全タスク完了の宣言まで自律的に続けること。」
67
67
  - 席が読む env は script が組み立てる(`PEERTABLE_URL` / `PEERTABLE_ROOM` / `PEERTABLE_MEMBER` / `PEERTABLE_CREDENTIAL_FILE`、Lattice 併用なら `PEERTABLE_PLAN` と actor 3点)。token値は席別`0600` fileにだけ置き、pathだけを席へ渡す。**channels は `--mcp-config` の MCP server を解決しない**(実測 2026-08-08・Claude Code v2.1.226・決定44)ため、room の MCP 定義は setup.sh が project root へ置く `.mcp.json` が正。Peertable管理下fileはlaunch時にもcurrent-tree clientへ同期する。project に既存 `.mcp.json` があった場合は無断更新せず`SEAT_ROOM_MCP_STALE`で止まるので、AI がroom定義を手動mergeしてteardownで復元する
68
68
  - **Codex 席**(`vendor=codex`): Codex には channels が無いので、room は `-c` 上書きの stdio MCPとして、同じPeertable treeの`node room/client.mjs`を差す。**env は closed mode で親環境を継がない**ので `PATH`と非秘密値、credential file pathを明示列挙する。effortはmember metadataだけでなく`model_reasoning_effort`へも同じ値を渡す。モデル名は ChatGPT アカウントで使える slug を渡す(`~/.codex/config.toml` の `model` が既定値の参考。使えない slug は起動後の最初のターンで 400 になって初めて分かる)。**起床ブリッジは Codex / Grok だけ**(下記)——Claude 席は room client が `notifications/claude/channel` を送る(8/12 に送信ループを削った回帰を 0.4.5 で戻した)
69
- - **Grok 席**(`vendor=grok`): project rootの`.mcp.json`をGrok Buildが読み、同じroom clientと席固有envをAitermが渡す。model / effortはAitermの`grok_agent`へそのまま渡し、`grok models`のlive catalogに無いmodelは着席前に失敗する。初めて開くtreeの既知workspace trustは着席処理が通す。channelsは無いので起床ブリッジを使う。Grok TUIの既定はターン中の素送信を今の仕事へ混ぜず入力キューへ積むので、ブリッジはGrok席がidleになるまで送らない
69
+ - **Grok 席**(`vendor=grok`): project rootの`.mcp.json`をGrok Buildが読み、同じroom clientと席固有envをAitermが渡す。**user `~/.grok/config.toml` の booth/lattice 等 MCP は載せない**——席専用 `GROK_HOME`(`.team/seats/<name>.grok-home`、auth.json と ui だけ)を preflight と live 席の両方へ渡す。通らなければ席を立てず、別 model へ落とさない。model / effortはAitermの`grok_agent`へそのまま渡し、`grok models`のlive catalogに無いmodelは着席前に失敗する。初めて開くtreeの既知workspace trustは着席処理が通す。channelsは無いので起床ブリッジを使う。Grok TUIの既定はターン中の素送信を今の仕事へ混ぜず入力キューへ積むので、ブリッジはGrok席がidleになるまで送らない
70
70
  6. **起床ブリッジ(Codex / Grok 席がある時)**: `scripts/ensure-bridge.sh <project> wakeup <席名>…`。room の SSE を購読し、明示的にその席宛の新着(自分の発言は除く)だけを tmux へ素送信して起こす。ensure は専用 tmux session で起動し、bridge の `ready_at` を待つ。確認できなければログ末尾を出して非ゼロで終わる。Codexは即送信、Grokはidle待ち。親(`parent_watch` / `observe: null`)は対象にしない。停止は `node scripts/wakeup-bridge.mjs <project> --stop`(teardown.sh が自動で行う)
71
71
  - **黙って止まらないための三段**(決定58 の受信側の作法): ①75秒なにも届かなければ自分から切って繋ぎ直す ②繋ぎ直したら `?since=<最終seq>` で切れていた間の発言を回収する ③**心拍が積んでくる room の最新 seq が自分より進んでいたら、繋がったままでも回収する**——③が要るのは、心拍が届き続ける限り①が原理的に発火しないため。**server 側の心拍(`event: ping`・25秒周期)が前提**なので、古い room サーバーへ繋ぐと①だけが効く形になる
72
72
  - ログは `.team/wakeup-bridge.log`。**0件でも0件と出す**ので、起こせているか・取りこぼしていないかはログを見れば分かる。再現ハーネスは `experiments/bridge-catchup-repro.mjs`
@@ -20,6 +20,7 @@ if (process.env.PEERTABLE_PLAN) env_vars.push(
20
20
  'PEERTABLE_PLAN', 'LATTICE_CLI', 'LATTICE_TODO_ACTOR_HOST',
21
21
  'LATTICE_TODO_ACTOR_SESSION', 'LATTICE_TODO_ACTOR_AGENT',
22
22
  )
23
+ if (vendor === 'grok' && process.env.GROK_HOME) env_vars.push('GROK_HOME')
23
24
  const result = await client.callTool({
24
25
  name: `${vendor}_agent`,
25
26
  arguments: {
@@ -217,11 +217,32 @@ 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)。live 席も同じ config を読むと
233
+ # lattice MCP が数分固まる。認証だけ借りて MCP 無しの席専用 HOME を残す。
234
+ grok_home="${proj}/.team/seats/${name}.grok-home"
235
+ rm -rf "$grok_home"
236
+ mkdir -p "$grok_home"
237
+ if [ ! -f "${HOME}/.grok/auth.json" ]; then
238
+ echo "SEAT_GROK_AUTH_MISSING: ${HOME}/.grok/auth.json が無い(席は立てない)" >&2
239
+ exit 1
240
+ fi
241
+ cp "${HOME}/.grok/auth.json" "${grok_home}/auth.json"
242
+ printf '%s\n' '[ui]' 'permission_mode = "always-approve"' >"${grok_home}/config.toml"
243
+ echo "grok preflight: GROK_HOME=${grok_home} ${grok_bin} --model ${model} --reasoning-effort ${effort} -p ping"
244
+ preflight_cmd=(env GROK_HOME="$grok_home" "$grok_bin" --model "$model" --reasoning-effort "$effort" -p "ping")
245
+ ;;
225
246
  *) echo "unknown vendor: ${vendor}(claude / codex / grok)" >&2; exit 1 ;;
226
247
  esac
227
248
  preflight_log=$(mktemp "${TMPDIR:-/tmp}/peertable-preflight.XXXXXX")
@@ -242,13 +263,16 @@ done
242
263
  if [ -z "$preflight_rc" ]; then
243
264
  kill "$preflight_pid" 2>/dev/null || true
244
265
  echo "model preflight が 120 秒で返らない: ${vendor} / ${model}(席は立てない)" >&2
245
- rm -f "$preflight_log"
266
+ echo "preflight log: ${preflight_log}" >&2
267
+ cat "$preflight_log" >&2 || true
268
+ [ -n "${grok_home:-}" ] && rm -rf "$grok_home"
246
269
  exit 1
247
270
  fi
248
271
  if [ "$preflight_rc" != 0 ]; then
249
272
  echo "model が live で使えない: ${vendor} / ${model}(preflight rc=${preflight_rc}・席は立てない)" >&2
250
- tail -5 "$preflight_log" >&2
273
+ cat "$preflight_log" >&2 || true
251
274
  rm -f "$preflight_log"
275
+ [ -n "${grok_home:-}" ] && rm -rf "$grok_home"
252
276
  exit 1
253
277
  fi
254
278
  rm -f "$preflight_log"
@@ -334,6 +358,9 @@ if [ "$mode" = "lattice" ]; then
334
358
  )
335
359
  [ -n "$lattice_cli" ] && launch_env+=("LATTICE_CLI=$lattice_cli")
336
360
  fi
361
+ if [ "$vendor" = grok ]; then
362
+ launch_env+=("GROK_HOME=$grok_home")
363
+ fi
337
364
  if [ "$vendor" = codex ] \
338
365
  && ! env -u PEERTABLE_POST_TOKEN "${launch_env[@]}" node "$codex_room_mcp_helper" ensure "$proj" "$peertable_repo"; then
339
366
  echo "SEAT_CODEX_ROOM_MCP_INVALID: Codexのproject設定へseat固有room clientを装備できない(席は立てない)" >&2
@@ -80,6 +80,7 @@ if ! rm -f "$proj/.team/seats/$name.json"; then
80
80
  echo "SEAT_LEAVE_IDENTITY_FAILED: $name" >&2
81
81
  failed=1
82
82
  fi
83
+ rm -rf "$proj/.team/seats/${name}.grok-home"
83
84
  if ! env -u PEERTABLE_POST_TOKEN node "$credential_helper" remove "$proj" "$credential_file"; then
84
85
  echo "SEAT_LEAVE_CREDENTIAL_FAILED: $name" >&2
85
86
  failed=1