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 +1 -1
- package/room/client.mjs +1 -1
- package/skill/scripts/launch-seat.sh +27 -25
- package/skill/scripts/seat-metadata.mjs +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peertable",
|
|
3
|
-
"version": "0.4.
|
|
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.
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
610
|
-
|
|
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`)
|