@agfpd/iapeer 0.4.80 → 0.4.81
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/src/transport/index.ts +29 -12
package/package.json
CHANGED
package/src/transport/index.ts
CHANGED
|
@@ -307,7 +307,7 @@ async function deliverViaHost(
|
|
|
307
307
|
// a short grace covers it. The receiver's own assistant/tool turn never reproduces the
|
|
308
308
|
// `<iap from-personality=…>` wrapper, so it cannot forge a confirm. No such record within the grace →
|
|
309
309
|
// false-FAIL (the sender retries) — NOT a false-OK (silent loss the contract forbids).
|
|
310
|
-
const confirm = seam.confirmLanded ?? ((payload: string) => transcriptCarriesEnvelope(baseline, payload))
|
|
310
|
+
const confirm = seam.confirmLanded ?? ((payload: string) => transcriptCarriesEnvelope(baseline, payload, { env }))
|
|
311
311
|
const sleep = seam.sleep ?? ((ms: number) => new Promise<void>(r => setTimeout(r, ms)))
|
|
312
312
|
const graceMs = confirmGraceMs()
|
|
313
313
|
const graceDeadline = monotonicMs() + graceMs
|
|
@@ -579,20 +579,37 @@ function jsonStringValuesContain(value: unknown, needle: string): boolean {
|
|
|
579
579
|
* the full envelope is UNFORGEABLE by a concurrent turn — no false-OK. Because only bytes PAST the
|
|
580
580
|
* baseline offset are read, a pre-existing copy of an identical earlier message cannot pass either.
|
|
581
581
|
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
582
|
+
* Scans each baseline file from its captured offset AND any session file that APPEARS AFTER the baseline
|
|
583
|
+
* from offset 0 — the post-baseline pickup is load-bearing. A FRESH session (self-fresh/eager-fresh)
|
|
584
|
+
* writes its NEW jsonl LAZILY on the first delivered turn, so the confirming record for the FIRST delivery
|
|
585
|
+
* into that session lands in a file the baseline never captured (the fresh jsonl is born ~a beat AFTER the
|
|
586
|
+
* pre-deliver baseline snapshot). Iterating baseline-only made EVERY such first-delivery a false-FAIL: the
|
|
587
|
+
* dead OLD session file gets scanned, the live NEW one is ignored, and the confirm reported "not delivered"
|
|
588
|
+
* for a message the session had actually accepted + processed (verified live 2026-07-10: telegram-arthur →
|
|
589
|
+
* mrmechanic ok=false, yet the envelope stood in the fresh jsonl at +0.3s, within the grace). A
|
|
590
|
+
* post-baseline file is BRAND-NEW for this cwd, so reading it from 0 cannot match a pre-existing copy
|
|
591
|
+
* (nothing pre-existed), and the full `<iap from-personality=…>` envelope is unforgeable by the receiver's
|
|
592
|
+
* own assistant/tool turn — the SAME false-OK safety `compactTranscriptHasDone` already relies on. In
|
|
593
|
+
* production this loop runs ONLY for claude (codex confirms by the socket-ack BEFORE reaching here), so the
|
|
594
|
+
* per-poll re-list is a single cheap readdirSync of one project dir — never a recursive `~/.codex/sessions`
|
|
595
|
+
* walk. `env` scopes the re-list under a test HOME (default process.env).
|
|
588
596
|
*/
|
|
589
|
-
export function transcriptCarriesEnvelope(
|
|
597
|
+
export function transcriptCarriesEnvelope(
|
|
598
|
+
baseline: CompactDoneBaseline,
|
|
599
|
+
envelope: string,
|
|
600
|
+
opts: { env?: NodeJS.ProcessEnv } = {},
|
|
601
|
+
): boolean {
|
|
590
602
|
const needle = envelope.replace(/\r/g, '')
|
|
591
603
|
if (!needle) return false
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
604
|
+
// Baseline files at their pre-deliver offset; a file NOT in the baseline (born after it) is read from 0.
|
|
605
|
+
const offsets = new Map(baseline.files.map(f => [f.path, f.size]))
|
|
606
|
+
for (const path of compactCandidateFiles(baseline.runtime, baseline.cwd, opts.env)) {
|
|
607
|
+
if (!offsets.has(path)) offsets.set(path, 0)
|
|
608
|
+
}
|
|
609
|
+
for (const [path, offset] of offsets) {
|
|
610
|
+
// Read ONLY the tail past the offset — a full readFileSync here re-read the ENTIRE transcript
|
|
611
|
+
// (hundreds of MB for a long-running peer) on every ~100ms confirm-poll, stalling the single-threaded
|
|
612
|
+
// router event loop for the whole fleet.
|
|
596
613
|
const tail = readFileTailFrom(path, offset)
|
|
597
614
|
if (!tail) continue
|
|
598
615
|
for (const line of tail.split(/\r?\n/)) {
|