| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
1. chat.py renamed the temp file AFTER releasing the flock, so two writers could each
read the pre-replace snapshot and the later rename silently dropped the earlier
message. os.replace now happens inside the lock.
2. The agent cursor was global. After hermes-reset it pointed past the end of the new
empty thread, so every read returned nothing — the agent would think it had been
ignored. Key is now per thread and reset clears every chat cursor.
3. chat-relay.sh had no overlap guard: a slow agent run (up to 5 min) could collide with
the next tick and answer the same thread twice. flock -n on /tmp/chat-relay.lock.
Verified: stale cursor 'webx11_chat_agent_cursor_oldthread00000' set to 9999999999999,
hermes-reset -> zero cursor keys remain, read returns {messages:[], note:'no new messages...'}.
|
|
|
retired (v4.6.71 phase B)
- api/chat/{lib,post,poll}.php: thread = sha256(token)[0:16]; flock read-modify-write;
tmp+rename; ms epoch cursor; per-thread + per-IP windows with retry_after_ms;
401/413/507/405 carry a machine code, only rate_limited is retryable
- _docs/chat-contract.md: frozen shapes, incl. why the cursor is ms and not ts
- scripts/chat.py: list/show/reply, UTC, locked, atomic replace
- api/debug/agent-replies.php POST -> 410 Gone with pointers (one write path)
Measured: 401 no-token, 201+id, poll 1 msg, poll>since 1 new, data/chat 403,
4001 chars 413 (codepoints), 429 with Retry-After 576, round trip via chat.py.
|