peertable 0.8.3 → 0.8.4

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.8.3",
3
+ "version": "0.8.4",
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.8.3'
16
+ const MCP_VERSION = '0.8.4'
17
17
  const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..')
18
18
 
19
19
  const USAGE = `usage:
@@ -31,6 +31,9 @@ if [ -z "$parent_harness" ] && [ -n "$model" ]; then
31
31
  claude*|opus*|sonnet*|haiku*|fable*) parent_harness=claude ;;
32
32
  esac
33
33
  fi
34
+ if [ "$(node -p 'process.platform')" = win32 ]; then
35
+ member=$(node "$(dirname "$0")/platform/windows/parent-member-json.mjs" "$name" "$model" "$effort" "$parent_harness" "$mission")
36
+ else
34
37
  member=$(python3 - "$name" "$model" "$effort" "$parent_harness" "$mission" <<'PY'
35
38
  import json, sys
36
39
  name, model, effort, harness, mission = sys.argv[1:6]
@@ -50,6 +53,7 @@ body['delivery'] = {'kind': 'parent_watch', 'host': harness or ''}
50
53
  print(json.dumps(body, ensure_ascii=False))
51
54
  PY
52
55
  )
56
+ fi
53
57
  curl -sf -X POST "$url/api/$room/members" \
54
58
  -H "X-Peertable-Token: $PEERTABLE_POST_TOKEN" -H 'content-type: application/json' \
55
59
  -d "$member" > /dev/null
@@ -10,7 +10,7 @@
10
10
  import { execFileSync } from 'node:child_process'
11
11
  import { existsSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs'
12
12
  import { join } from 'node:path'
13
- import { resolveLatticeExecutable } from './seat-usage.mjs'
13
+ import { resolveLatticeExecutable, resolvePostToken } from './seat-usage.mjs'
14
14
  import { addressedToParent as messageAddressedToParent, latticeStaffingChanged, tableStallUpdate } from './parent-watch-logic.mjs'
15
15
 
16
16
  const args = process.argv.slice(2)
@@ -209,6 +209,24 @@ async function acceptLatticeState(next) {
209
209
  return true
210
210
  }
211
211
 
212
+ const receiptToken = resolvePostToken(process.env)
213
+ const postedParentReceipts = new Set()
214
+ async function postParentReceipt(seq) {
215
+ if (postedParentReceipts.has(seq)) return
216
+ postedParentReceipts.add(seq)
217
+ try {
218
+ const res = await fetch(`${serverUrl}/api/${encodeURIComponent(room)}/deliveries`, {
219
+ method: 'POST',
220
+ headers: { 'Content-Type': 'application/json', ...(receiptToken ? { 'X-Peertable-Token': receiptToken } : {}) },
221
+ body: JSON.stringify({ seq, recipient: parent, result: 'delivered', reason: 'parent_watch' }),
222
+ })
223
+ if (!res.ok) throw new Error(`HTTP ${res.status}`)
224
+ } catch (error) {
225
+ postedParentReceipts.delete(seq)
226
+ process.stderr.write(`PARENT_RECEIPT_FAILED: seq=${seq} ${error.message}\n`)
227
+ }
228
+ }
229
+
212
230
  async function acceptMessage(message) {
213
231
  if (!Number.isSafeInteger(message?.seq) || message.seq <= state.last_seq) return false
214
232
  const matched = addressedToParent(message)
@@ -225,6 +243,12 @@ async function acceptMessage(message) {
225
243
  body: roomUpdate ? (message.body || ROOM_UPDATE_FALLBACK) : message.body,
226
244
  message,
227
245
  })
246
+ // 親宛の名指しDMは、この中継(writeEvent成功=親の通知ストリームへ入った)をもって配達成立とし、
247
+ // server の配送 receipt へ delivered(reason: parent_watch) を書く(2026-08-25 オーナー裁定)。
248
+ // これが無いと送り手の席から親宛DMが永遠に pending に見え、報告の再記録ループで
249
+ // 席のターンを燃やし続ける(実被弾: mio が報告のたびに「bell配達pending」を再送)。
250
+ // to:"all" は席側配達(wakeup-bridge)が receipt を所有するので書かない。
251
+ if (!roomUpdate) await postParentReceipt(message.seq)
228
252
  }
229
253
  state = { ...state, last_seq: message.seq, last_event_at: now() }
230
254
  saveState(state)
@@ -0,0 +1,7 @@
1
+ const [name, model, effort, harness, mission] = process.argv.slice(2)
2
+ const body = { name, roles: ['統括'], observe: null, delivery: { kind: 'parent_watch', host: harness || '' } }
3
+ if (harness) { body.harness = harness; body.vendor = harness }
4
+ if (model) body.model = model
5
+ if (effort) body.effort = effort
6
+ if (mission) body.mission = mission
7
+ process.stdout.write(`${JSON.stringify(body)}\n`)