@seat-mesh/daemon 0.1.2
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/dist/border-paint.d.ts +11 -0
- package/dist/border-paint.d.ts.map +1 -0
- package/dist/border-paint.js +163 -0
- package/dist/border-paint.js.map +1 -0
- package/dist/bullmq-runtime.d.ts +19 -0
- package/dist/bullmq-runtime.d.ts.map +1 -0
- package/dist/bullmq-runtime.js +78 -0
- package/dist/bullmq-runtime.js.map +1 -0
- package/dist/compose-gate.d.ts +18 -0
- package/dist/compose-gate.d.ts.map +1 -0
- package/dist/compose-gate.js +80 -0
- package/dist/compose-gate.js.map +1 -0
- package/dist/compose-gate.test.d.ts +2 -0
- package/dist/compose-gate.test.d.ts.map +1 -0
- package/dist/compose-gate.test.js +35 -0
- package/dist/compose-gate.test.js.map +1 -0
- package/dist/connectivity-recovery.d.ts +81 -0
- package/dist/connectivity-recovery.d.ts.map +1 -0
- package/dist/connectivity-recovery.js +454 -0
- package/dist/connectivity-recovery.js.map +1 -0
- package/dist/connectivity-recovery.test.d.ts +2 -0
- package/dist/connectivity-recovery.test.d.ts.map +1 -0
- package/dist/connectivity-recovery.test.js +147 -0
- package/dist/connectivity-recovery.test.js.map +1 -0
- package/dist/create-queue-store.d.ts +8 -0
- package/dist/create-queue-store.d.ts.map +1 -0
- package/dist/create-queue-store.js +13 -0
- package/dist/create-queue-store.js.map +1 -0
- package/dist/delivery-hold.d.ts +10 -0
- package/dist/delivery-hold.d.ts.map +1 -0
- package/dist/delivery-hold.js +21 -0
- package/dist/delivery-hold.js.map +1 -0
- package/dist/delivery-hold.test.d.ts +2 -0
- package/dist/delivery-hold.test.d.ts.map +1 -0
- package/dist/delivery-hold.test.js +35 -0
- package/dist/delivery-hold.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/inject-delivery.d.ts +26 -0
- package/dist/inject-delivery.d.ts.map +1 -0
- package/dist/inject-delivery.js +108 -0
- package/dist/inject-delivery.js.map +1 -0
- package/dist/inject-delivery.test.d.ts +2 -0
- package/dist/inject-delivery.test.d.ts.map +1 -0
- package/dist/inject-delivery.test.js +14 -0
- package/dist/inject-delivery.test.js.map +1 -0
- package/dist/jsonl-dedupe.test.d.ts +2 -0
- package/dist/jsonl-dedupe.test.d.ts.map +1 -0
- package/dist/jsonl-dedupe.test.js +27 -0
- package/dist/jsonl-dedupe.test.js.map +1 -0
- package/dist/jsonl-store.d.ts +103 -0
- package/dist/jsonl-store.d.ts.map +1 -0
- package/dist/jsonl-store.js +235 -0
- package/dist/jsonl-store.js.map +1 -0
- package/dist/mesh-inbox-server.d.ts +3 -0
- package/dist/mesh-inbox-server.d.ts.map +1 -0
- package/dist/mesh-inbox-server.js +483 -0
- package/dist/mesh-inbox-server.js.map +1 -0
- package/dist/mesh-inbox-supervisor.d.ts +3 -0
- package/dist/mesh-inbox-supervisor.d.ts.map +1 -0
- package/dist/mesh-inbox-supervisor.js +227 -0
- package/dist/mesh-inbox-supervisor.js.map +1 -0
- package/dist/mesh-orchestrator.d.ts +32 -0
- package/dist/mesh-orchestrator.d.ts.map +1 -0
- package/dist/mesh-orchestrator.js +340 -0
- package/dist/mesh-orchestrator.js.map +1 -0
- package/dist/oc-resume-ack.d.ts +32 -0
- package/dist/oc-resume-ack.d.ts.map +1 -0
- package/dist/oc-resume-ack.js +89 -0
- package/dist/oc-resume-ack.js.map +1 -0
- package/dist/oc-resume-ack.test.d.ts +2 -0
- package/dist/oc-resume-ack.test.d.ts.map +1 -0
- package/dist/oc-resume-ack.test.js +23 -0
- package/dist/oc-resume-ack.test.js.map +1 -0
- package/dist/oc-resume.d.ts +25 -0
- package/dist/oc-resume.d.ts.map +1 -0
- package/dist/oc-resume.js +102 -0
- package/dist/oc-resume.js.map +1 -0
- package/dist/orchestrator.d.ts +17 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +11 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/pane-ops-drain.d.ts +14 -0
- package/dist/pane-ops-drain.d.ts.map +1 -0
- package/dist/pane-ops-drain.js +53 -0
- package/dist/pane-ops-drain.js.map +1 -0
- package/dist/peer-backlog.d.ts +18 -0
- package/dist/peer-backlog.d.ts.map +1 -0
- package/dist/peer-backlog.js +137 -0
- package/dist/peer-backlog.js.map +1 -0
- package/dist/peer-comms-checkback.d.ts +5 -0
- package/dist/peer-comms-checkback.d.ts.map +1 -0
- package/dist/peer-comms-checkback.js +57 -0
- package/dist/peer-comms-checkback.js.map +1 -0
- package/dist/peer-skip.d.ts +10 -0
- package/dist/peer-skip.d.ts.map +1 -0
- package/dist/peer-skip.js +26 -0
- package/dist/peer-skip.js.map +1 -0
- package/dist/peer-skip.test.d.ts +2 -0
- package/dist/peer-skip.test.d.ts.map +1 -0
- package/dist/peer-skip.test.js +33 -0
- package/dist/peer-skip.test.js.map +1 -0
- package/dist/ppa-state.d.ts +32 -0
- package/dist/ppa-state.d.ts.map +1 -0
- package/dist/ppa-state.js +63 -0
- package/dist/ppa-state.js.map +1 -0
- package/dist/sqlite-store.d.ts +44 -0
- package/dist/sqlite-store.d.ts.map +1 -0
- package/dist/sqlite-store.js +422 -0
- package/dist/sqlite-store.js.map +1 -0
- package/dist/sqlite-store.test.d.ts +2 -0
- package/dist/sqlite-store.test.d.ts.map +1 -0
- package/dist/sqlite-store.test.js +63 -0
- package/dist/sqlite-store.test.js.map +1 -0
- package/dist/workers.d.ts +11 -0
- package/dist/workers.d.ts.map +1 -0
- package/dist/workers.js +12 -0
- package/dist/workers.js.map +1 -0
- package/package.json +28 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
export interface ResumeAckWave {
|
|
3
|
+
paneIds: Set<string>;
|
|
4
|
+
acked: Set<string>;
|
|
5
|
+
reason: string;
|
|
6
|
+
startedAt: number;
|
|
7
|
+
timeoutNotified: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function currentResumeAckWave(): ResumeAckWave | null;
|
|
10
|
+
/** Test-only: reset module state between cases. */
|
|
11
|
+
export declare function resetResumeAckWave(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Pure decision: given a wave's ack progress, what should the daemon do next?
|
|
14
|
+
* Exported for unit testing without tmux/process spawning.
|
|
15
|
+
*/
|
|
16
|
+
export declare function nextAckWaveAction(input: {
|
|
17
|
+
total: number;
|
|
18
|
+
ackedCount: number;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
timeoutNotified: boolean;
|
|
21
|
+
}, nowMs?: number, timeoutMs?: number): "idle" | "all-acked" | "timeout" | "waiting";
|
|
22
|
+
/**
|
|
23
|
+
* Call right after a resume wave is sent — arms ack tracking for exactly those panes.
|
|
24
|
+
* A fresh wave replaces whatever was pending (the newest resume is the one that matters).
|
|
25
|
+
*/
|
|
26
|
+
export declare function armResumeAckWave(paneIds: string[], reason: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Poll tick: check pending panes for proof they're actually working again (composer no
|
|
29
|
+
* longer shows `limit`), then notify operator once the wave fully confirms or times out.
|
|
30
|
+
*/
|
|
31
|
+
export declare function pollResumeAcks(registry: ProviderRegistry, workspace: string, log: (line: string) => void, onPaneAcked?: (paneId: string) => void): void;
|
|
32
|
+
//# sourceMappingURL=oc-resume-ack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume-ack.d.ts","sourceRoot":"","sources":["../src/oc-resume-ack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAOxD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAKD,wBAAgB,oBAAoB,IAAI,aAAa,GAAG,IAAI,CAE3D;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,EACzF,KAAK,GAAE,MAAmB,EAC1B,SAAS,GAAE,MAAuB,GACjC,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAK9C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CASxE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC3B,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GACrC,IAAI,CAwDN"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { capturePaneSnapshot } from "@seat-mesh/tmux";
|
|
2
|
+
import { notifyConnectivityStatus, RESUME_ACK_HOWTO } from "./oc-resume.js";
|
|
3
|
+
/** How long to wait for a resumed pane to prove it's working again before flagging it stuck. */
|
|
4
|
+
const ACK_TIMEOUT_MS = 5 * 60_000;
|
|
5
|
+
/** Module-level: at most one resume wave is tracked for ack at a time (a new wave replaces it). */
|
|
6
|
+
let activeWave = null;
|
|
7
|
+
export function currentResumeAckWave() {
|
|
8
|
+
return activeWave;
|
|
9
|
+
}
|
|
10
|
+
/** Test-only: reset module state between cases. */
|
|
11
|
+
export function resetResumeAckWave() {
|
|
12
|
+
activeWave = null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Pure decision: given a wave's ack progress, what should the daemon do next?
|
|
16
|
+
* Exported for unit testing without tmux/process spawning.
|
|
17
|
+
*/
|
|
18
|
+
export function nextAckWaveAction(input, nowMs = Date.now(), timeoutMs = ACK_TIMEOUT_MS) {
|
|
19
|
+
if (input.total <= 0)
|
|
20
|
+
return "idle";
|
|
21
|
+
if (input.ackedCount >= input.total)
|
|
22
|
+
return "all-acked";
|
|
23
|
+
if (!input.timeoutNotified && nowMs - input.startedAt >= timeoutMs)
|
|
24
|
+
return "timeout";
|
|
25
|
+
return "waiting";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Call right after a resume wave is sent — arms ack tracking for exactly those panes.
|
|
29
|
+
* A fresh wave replaces whatever was pending (the newest resume is the one that matters).
|
|
30
|
+
*/
|
|
31
|
+
export function armResumeAckWave(paneIds, reason) {
|
|
32
|
+
if (!paneIds.length)
|
|
33
|
+
return;
|
|
34
|
+
activeWave = {
|
|
35
|
+
paneIds: new Set(paneIds),
|
|
36
|
+
acked: new Set(),
|
|
37
|
+
reason,
|
|
38
|
+
startedAt: Date.now(),
|
|
39
|
+
timeoutNotified: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Poll tick: check pending panes for proof they're actually working again (composer no
|
|
44
|
+
* longer shows `limit`), then notify operator once the wave fully confirms or times out.
|
|
45
|
+
*/
|
|
46
|
+
export function pollResumeAcks(registry, workspace, log, onPaneAcked) {
|
|
47
|
+
const wave = activeWave;
|
|
48
|
+
if (!wave)
|
|
49
|
+
return;
|
|
50
|
+
for (const paneId of wave.paneIds) {
|
|
51
|
+
if (wave.acked.has(paneId))
|
|
52
|
+
continue;
|
|
53
|
+
const snap = capturePaneSnapshot(paneId);
|
|
54
|
+
if (!snap) {
|
|
55
|
+
wave.acked.add(paneId);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const prov = registry.detect(snap);
|
|
59
|
+
if (prov?.id !== "opencode") {
|
|
60
|
+
wave.acked.add(paneId);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (prov.composerState(snap).phase !== "limit") {
|
|
64
|
+
wave.acked.add(paneId);
|
|
65
|
+
log(`OC-RESUME ack ${paneId} confirmed working — clearing OC-LIMIT banner`);
|
|
66
|
+
onPaneAcked?.(paneId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const action = nextAckWaveAction({
|
|
70
|
+
total: wave.paneIds.size,
|
|
71
|
+
ackedCount: wave.acked.size,
|
|
72
|
+
startedAt: wave.startedAt,
|
|
73
|
+
timeoutNotified: wave.timeoutNotified,
|
|
74
|
+
});
|
|
75
|
+
if (action === "all-acked") {
|
|
76
|
+
log(`OC-RESUME all acked (${wave.acked.size}/${wave.paneIds.size}) reason=${wave.reason}`);
|
|
77
|
+
notifyConnectivityStatus(workspace, "OC resume", `All ${wave.paneIds.size} resumed OC panes acked — limit screens cleared (${wave.reason}).`, "No action needed.", "complete");
|
|
78
|
+
activeWave = null;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (action === "timeout") {
|
|
82
|
+
wave.timeoutNotified = true;
|
|
83
|
+
const stuck = wave.paneIds.size - wave.acked.size;
|
|
84
|
+
const ageSec = Math.round((Date.now() - wave.startedAt) / 1000);
|
|
85
|
+
log(`OC-RESUME ack timeout: ${stuck}/${wave.paneIds.size} unconfirmed after ${ageSec}s`);
|
|
86
|
+
notifyConnectivityStatus(workspace, "OC resume", `${stuck}/${wave.paneIds.size} resumed panes still not acked after ${ageSec}s (${wave.reason}).`, `${RESUME_ACK_HOWTO} Stuck panes: open pane, confirm limit text gone or press Enter once on resume.`, "incomplete");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=oc-resume-ack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume-ack.js","sourceRoot":"","sources":["../src/oc-resume-ack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume-ack.test.d.ts","sourceRoot":"","sources":["../src/oc-resume-ack.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { nextAckWaveAction } from "./oc-resume-ack.js";
|
|
3
|
+
describe("nextAckWaveAction (OC-RESUME ack-confirmation wave)", () => {
|
|
4
|
+
it("is idle when there is nothing to track", () => {
|
|
5
|
+
expect(nextAckWaveAction({ total: 0, ackedCount: 0, startedAt: 0, timeoutNotified: false }, 1_000, 300_000)).toBe("idle");
|
|
6
|
+
});
|
|
7
|
+
it("waits while some panes are still unconfirmed and under the timeout", () => {
|
|
8
|
+
expect(nextAckWaveAction({ total: 3, ackedCount: 1, startedAt: 1_000, timeoutNotified: false }, 1_000 + 60_000, 300_000)).toBe("waiting");
|
|
9
|
+
});
|
|
10
|
+
it("reports all-acked once every pane has confirmed, regardless of elapsed time", () => {
|
|
11
|
+
expect(nextAckWaveAction({ total: 3, ackedCount: 3, startedAt: 1_000, timeoutNotified: false }, 1_000 + 999_999, 300_000)).toBe("all-acked");
|
|
12
|
+
});
|
|
13
|
+
it("reports timeout once the threshold elapses with stragglers left", () => {
|
|
14
|
+
expect(nextAckWaveAction({ total: 3, ackedCount: 1, startedAt: 1_000, timeoutNotified: false }, 1_000 + 300_000, 300_000)).toBe("timeout");
|
|
15
|
+
});
|
|
16
|
+
it("never re-fires timeout once already notified", () => {
|
|
17
|
+
expect(nextAckWaveAction({ total: 3, ackedCount: 1, startedAt: 1_000, timeoutNotified: true }, 1_000 + 999_999, 300_000)).toBe("waiting");
|
|
18
|
+
});
|
|
19
|
+
it("prefers all-acked over timeout when both conditions technically hold", () => {
|
|
20
|
+
expect(nextAckWaveAction({ total: 3, ackedCount: 3, startedAt: 1_000, timeoutNotified: false }, 1_000 + 300_000, 300_000)).toBe("all-acked");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=oc-resume-ack.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume-ack.test.js","sourceRoot":"","sources":["../src/oc-resume-ack.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACnE,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CACJ,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,eAAe,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CACrG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,CACJ,iBAAiB,CACf,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EACrE,KAAK,GAAG,MAAM,EACd,OAAO,CACR,CACF,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,CACJ,iBAAiB,CACf,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EACrE,KAAK,GAAG,OAAO,EACf,OAAO,CACR,CACF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CACJ,iBAAiB,CACf,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EACrE,KAAK,GAAG,OAAO,EACf,OAAO,CACR,CACF,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CACJ,iBAAiB,CACf,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,EACpE,KAAK,GAAG,OAAO,EACf,OAAO,CACR,CACF,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CACJ,iBAAiB,CACf,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,EACrE,KAAK,GAAG,OAAO,EACf,OAAO,CACR,CACF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
/** Desktop toasts from mesh inbox daemon — not manager seat. */
|
|
3
|
+
export declare const INBOX_NOTIFY_SLOT = "inbox";
|
|
4
|
+
/** Shown on resume-sent / ack toasts so operator knows ack is inbox-automatic, not a manual command. */
|
|
5
|
+
export declare const RESUME_ACK_HOWTO: string;
|
|
6
|
+
export type InboxNotifyPhase = "starting" | "sent" | "complete" | "incomplete" | "escalating";
|
|
7
|
+
export declare function notifyConnectivityStatus(workspace: string, topic: string, sessionAbout: string, check: string, phase?: InboxNotifyPhase): void;
|
|
8
|
+
/** @deprecated Use resume wave notify with carrier meta instead. */
|
|
9
|
+
export declare function notifyProxyCarrierIp(workspace: string, fromIp: string | null, toIp: string, reason: string): void;
|
|
10
|
+
export declare function resumeOneOpenCodePane(paneId: string, registry: ProviderRegistry): {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
cmd?: string;
|
|
13
|
+
reason?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function resumeAllOpenCodePanes(paneIds: string[], registry: ProviderRegistry, log?: (line: string) => void): {
|
|
16
|
+
sent: number;
|
|
17
|
+
total: number;
|
|
18
|
+
sentPaneIds: string[];
|
|
19
|
+
};
|
|
20
|
+
export interface ResumeWaveMeta {
|
|
21
|
+
fromIp?: string | null;
|
|
22
|
+
toIp?: string | null;
|
|
23
|
+
}
|
|
24
|
+
export declare function notifyResumeWave(workspace: string, reason: string, sent: number, total: number, meta?: ResumeWaveMeta): void;
|
|
25
|
+
//# sourceMappingURL=oc-resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume.d.ts","sourceRoot":"","sources":["../src/oc-resume.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAIxD,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAEzC,wGAAwG;AACxG,eAAO,MAAM,gBAAgB,QAE+E,CAAC;AAE7G,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;AAsC9F,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,gBAA6B,GACnC,IAAI,CAEN;AAED,oEAAoE;AACpE,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,IAAI,CAYN;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gBAAgB,GACzB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAchD;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EAAE,EACjB,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAiBxD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,cAAc,GACpB,IAAI,CA0BN"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { formatOpenCodeResumeCommand } from "@seat-mesh/providers";
|
|
4
|
+
import { capturePaneSnapshot, injectToPane, withPaneInputEnabled } from "@seat-mesh/tmux";
|
|
5
|
+
/** Desktop toasts from mesh inbox daemon — not manager seat. */
|
|
6
|
+
export const INBOX_NOTIFY_SLOT = "inbox";
|
|
7
|
+
/** Shown on resume-sent / ack toasts so operator knows ack is inbox-automatic, not a manual command. */
|
|
8
|
+
export const RESUME_ACK_HOWTO = "Ack: automatic — when the OC composer is back (limit screen gone), inbox clears the OC-LIMIT border on that pane. " +
|
|
9
|
+
"Complete toast = all borders cleared. Incomplete after 5m = eyeball stuck panes. Nothing for you to run.";
|
|
10
|
+
function phaseLabel(phase) {
|
|
11
|
+
switch (phase) {
|
|
12
|
+
case "starting":
|
|
13
|
+
return "starting";
|
|
14
|
+
case "sent":
|
|
15
|
+
return "resume sent";
|
|
16
|
+
case "complete":
|
|
17
|
+
return "complete";
|
|
18
|
+
case "incomplete":
|
|
19
|
+
return "incomplete";
|
|
20
|
+
case "escalating":
|
|
21
|
+
return "escalating";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function notifyInbox(workspace, phase, topic, sessionAbout, check) {
|
|
25
|
+
const notifySh = path.join(workspace, "scripts/notify.sh");
|
|
26
|
+
const title = `${INBOX_NOTIFY_SLOT} · ${topic} (${phaseLabel(phase)})`;
|
|
27
|
+
let body = sessionAbout;
|
|
28
|
+
if (check)
|
|
29
|
+
body += `\n\nCheck: ${check}`;
|
|
30
|
+
try {
|
|
31
|
+
spawnSync("bash", [notifySh, title, body], {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
timeout: 5000,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
/* notify optional */
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function notifyConnectivityStatus(workspace, topic, sessionAbout, check, phase = "starting") {
|
|
41
|
+
notifyInbox(workspace, phase, topic, sessionAbout, check);
|
|
42
|
+
}
|
|
43
|
+
/** @deprecated Use resume wave notify with carrier meta instead. */
|
|
44
|
+
export function notifyProxyCarrierIp(workspace, fromIp, toIp, reason) {
|
|
45
|
+
const sessionAbout = fromIp && fromIp !== toIp
|
|
46
|
+
? `Proxy ${reason}: carrier ${fromIp} -> ${toIp}.`
|
|
47
|
+
: `Proxy ${reason}: carrier ${toIp}.`;
|
|
48
|
+
notifyInbox(workspace, "sent", "Proxy rotate", sessionAbout, "Waiting for OC panes to confirm resume...");
|
|
49
|
+
}
|
|
50
|
+
export function resumeOneOpenCodePane(paneId, registry) {
|
|
51
|
+
const snap = capturePaneSnapshot(paneId);
|
|
52
|
+
if (!snap)
|
|
53
|
+
return { ok: false };
|
|
54
|
+
const prov = registry.detect(snap);
|
|
55
|
+
if (prov?.id !== "opencode")
|
|
56
|
+
return { ok: false };
|
|
57
|
+
const cmd = formatOpenCodeResumeCommand(snap);
|
|
58
|
+
if (!cmd)
|
|
59
|
+
return { ok: false, reason: "no-ses-id" };
|
|
60
|
+
const plan = prov.injectPlan(snap);
|
|
61
|
+
let ok = false;
|
|
62
|
+
withPaneInputEnabled(paneId, () => {
|
|
63
|
+
injectToPane(paneId, cmd, plan, prov.id, snap.captureTail);
|
|
64
|
+
ok = true;
|
|
65
|
+
});
|
|
66
|
+
return ok ? { ok: true, cmd } : { ok: false, reason: "inject-failed" };
|
|
67
|
+
}
|
|
68
|
+
export function resumeAllOpenCodePanes(paneIds, registry, log) {
|
|
69
|
+
let sent = 0;
|
|
70
|
+
let total = 0;
|
|
71
|
+
const sentPaneIds = [];
|
|
72
|
+
for (const paneId of paneIds) {
|
|
73
|
+
const snap = capturePaneSnapshot(paneId);
|
|
74
|
+
if (!snap)
|
|
75
|
+
continue;
|
|
76
|
+
if (registry.detect(snap)?.id !== "opencode")
|
|
77
|
+
continue;
|
|
78
|
+
total += 1;
|
|
79
|
+
const r = resumeOneOpenCodePane(paneId, registry);
|
|
80
|
+
if (r.ok) {
|
|
81
|
+
sent += 1;
|
|
82
|
+
sentPaneIds.push(paneId);
|
|
83
|
+
log?.(`OC-RESUME ${paneId} ${r.cmd ?? "resume"}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { sent, total, sentPaneIds };
|
|
87
|
+
}
|
|
88
|
+
export function notifyResumeWave(workspace, reason, sent, total, meta) {
|
|
89
|
+
const ipLine = meta?.toIp && meta.fromIp !== meta.toIp
|
|
90
|
+
? `Carrier ${meta.fromIp ?? "?"} -> ${meta.toIp}. `
|
|
91
|
+
: meta?.toIp
|
|
92
|
+
? `Carrier ${meta.toIp}. `
|
|
93
|
+
: "";
|
|
94
|
+
if (sent > 0) {
|
|
95
|
+
notifyInbox(workspace, "sent", "OC resume", `${ipLine}Resume pasted to ${sent}/${total} OpenCode panes (${reason}).`, RESUME_ACK_HOWTO);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (total > 0) {
|
|
99
|
+
notifyInbox(workspace, "incomplete", "OC resume", `${ipLine}Found ${total} OC panes but resume was not delivered (${reason}).`, "Check OC panes manually — may be busy or keyboard-locked.");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=oc-resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oc-resume.js","sourceRoot":"","sources":["../src/oc-resume.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbox orchestrator — sole pane writer path (see mesh-orchestrator.ts).
|
|
3
|
+
*/
|
|
4
|
+
import type { QueueDrainPolicy, InjectJob, ProviderRegistry } from "@seat-mesh/core";
|
|
5
|
+
import { type MeshOrchestratorCtx, type DrainTickResult } from "./mesh-orchestrator.js";
|
|
6
|
+
export interface OrchestratorDeps {
|
|
7
|
+
registry: ProviderRegistry;
|
|
8
|
+
policy: QueueDrainPolicy;
|
|
9
|
+
ctx: MeshOrchestratorCtx;
|
|
10
|
+
enqueue: (job: InjectJob) => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class InboxOrchestrator {
|
|
13
|
+
private readonly deps;
|
|
14
|
+
constructor(deps: OrchestratorDeps);
|
|
15
|
+
drainTick(): Promise<DrainTickResult>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,mBAAmB,CAAC;IACzB,OAAO,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,gBAAgB;IAE7C,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;CAG5C"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { orchestratorDrainTick, } from "./mesh-orchestrator.js";
|
|
2
|
+
export class InboxOrchestrator {
|
|
3
|
+
deps;
|
|
4
|
+
constructor(deps) {
|
|
5
|
+
this.deps = deps;
|
|
6
|
+
}
|
|
7
|
+
async drainTick() {
|
|
8
|
+
return orchestratorDrainTick(this.deps.ctx);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,qBAAqB,GAGtB,MAAM,wBAAwB,CAAC;AAShC,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;IAAG,CAAC;IAEvD,KAAK,CAAC,SAAS;QACb,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LoadedProfile, PaneOpRow, ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
import type { QueueStore } from "./create-queue-store.js";
|
|
3
|
+
export interface PaneOpsDrainCtx {
|
|
4
|
+
loaded: LoadedProfile;
|
|
5
|
+
registry: ProviderRegistry;
|
|
6
|
+
store: QueueStore;
|
|
7
|
+
log: (line: string) => void;
|
|
8
|
+
isBusy: () => boolean;
|
|
9
|
+
setBusy: (v: boolean) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function drainPaneOpsOnce(ctx: PaneOpsDrainCtx): boolean;
|
|
12
|
+
export declare function enqueuePaneOp(store: QueueStore, kind: PaneOpRow["kind"], who: string, summary: string, payload: Record<string, unknown>): PaneOpRow;
|
|
13
|
+
export declare function queueAheadCount(store: QueueStore): number;
|
|
14
|
+
//# sourceMappingURL=pane-ops-drain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pane-ops-drain.d.ts","sourceRoot":"","sources":["../src/pane-ops-drain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAElF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/B;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAiC9D;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EACvB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,SAAS,CAYX;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { executePaneOp, saveMeshSession } from "@seat-mesh/tmux";
|
|
2
|
+
export function drainPaneOpsOnce(ctx) {
|
|
3
|
+
if (ctx.isBusy())
|
|
4
|
+
return false;
|
|
5
|
+
const rows = ctx.store.readPaneOps();
|
|
6
|
+
const row = rows.find((r) => r.status === "pending");
|
|
7
|
+
if (!row)
|
|
8
|
+
return false;
|
|
9
|
+
ctx.setBusy(true);
|
|
10
|
+
row.status = "running";
|
|
11
|
+
ctx.store.updatePaneOp(row);
|
|
12
|
+
ctx.log(`PANE-OP start ${row.id.slice(0, 8)} ${row.kind} who=${row.who} — ${row.summary}`);
|
|
13
|
+
const result = executePaneOp(ctx.loaded, row);
|
|
14
|
+
row.finishedAt = new Date().toISOString();
|
|
15
|
+
if (result.ok) {
|
|
16
|
+
row.status = "done";
|
|
17
|
+
ctx.log(`PANE-OP done ${row.id.slice(0, 8)} ${row.kind}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
row.status = "failed";
|
|
21
|
+
row.error = result.error;
|
|
22
|
+
ctx.log(`PANE-OP fail ${row.id.slice(0, 8)} ${row.kind}: ${result.error ?? "?"}`);
|
|
23
|
+
}
|
|
24
|
+
ctx.store.updatePaneOp(row);
|
|
25
|
+
if (result.ok) {
|
|
26
|
+
try {
|
|
27
|
+
const saved = saveMeshSession(ctx.loaded, ctx.registry);
|
|
28
|
+
ctx.log(`PANE-OP saved ${saved}`);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
ctx.log(`PANE-OP save warn: ${e.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
ctx.setBusy(false);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
export function enqueuePaneOp(store, kind, who, summary, payload) {
|
|
38
|
+
const row = {
|
|
39
|
+
id: crypto.randomUUID(),
|
|
40
|
+
at: new Date().toISOString(),
|
|
41
|
+
kind,
|
|
42
|
+
who,
|
|
43
|
+
summary,
|
|
44
|
+
payload,
|
|
45
|
+
status: "pending",
|
|
46
|
+
};
|
|
47
|
+
store.appendPaneOp(row);
|
|
48
|
+
return row;
|
|
49
|
+
}
|
|
50
|
+
export function queueAheadCount(store) {
|
|
51
|
+
return store.readPaneOps().filter((r) => r.status === "pending" || r.status === "running").length;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=pane-ops-drain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pane-ops-drain.js","sourceRoot":"","sources":["../src/pane-ops-drain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
import type { QueueStore, PeerRow } from "./create-queue-store.js";
|
|
3
|
+
export interface PeerBacklogRow extends PeerRow {
|
|
4
|
+
status: "backlog";
|
|
5
|
+
backlogAt: string;
|
|
6
|
+
holdReason: string;
|
|
7
|
+
}
|
|
8
|
+
/** Lightweight mail — deliver even when busy; agent ACKs in shell, hub stays rank-1. */
|
|
9
|
+
export declare function isAckClassPeer(msg: string): boolean;
|
|
10
|
+
/** Active HUB beats coordination mail — park unless ACK-class or explicit override. */
|
|
11
|
+
export declare function shouldBacklogPeerHold(reason: string, msg: string): boolean;
|
|
12
|
+
export declare function peerBacklogPath(store: QueueStore): string;
|
|
13
|
+
/** Re-queue oldest backlog row per idle pane (one promote per pane per tick). */
|
|
14
|
+
export declare function promotePeerBacklog(store: QueueStore, registry: ProviderRegistry, log: (line: string) => void): number;
|
|
15
|
+
export declare function parkPeerToBacklog(store: QueueStore, row: PeerRow, holdReason: string, log: (line: string) => void): void;
|
|
16
|
+
export declare function countPeerBacklog(store: QueueStore): number;
|
|
17
|
+
export declare function pendingPeerRows(store: QueueStore): PeerRow[];
|
|
18
|
+
//# sourceMappingURL=peer-backlog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-backlog.d.ts","sourceRoot":"","sources":["../src/peer-backlog.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGnE,MAAM,WAAW,cAAe,SAAQ,OAAO;IAC7C,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAM1E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEzD;AA6CD,iFAAiF;AACjF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC1B,MAAM,CA6CR;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC1B,IAAI,CAsBN;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,EAAE,CAE5D"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { capturePaneSnapshot, tmux } from "@seat-mesh/tmux";
|
|
3
|
+
import { isPeerDelivered } from "./create-queue-store.js";
|
|
4
|
+
const BUSY_HOLD = /^held:(busy|typing)/;
|
|
5
|
+
/** Lightweight mail — deliver even when busy; agent ACKs in shell, hub stays rank-1. */
|
|
6
|
+
export function isAckClassPeer(msg) {
|
|
7
|
+
const body = msg.replace(/^\[[^\]]+\]\s*/, "").trim();
|
|
8
|
+
return /^(ACK|FYI|STAND-?BY|MCP-?SYNCED|CHECKBACK\?)\b/i.test(body);
|
|
9
|
+
}
|
|
10
|
+
/** Active HUB beats coordination mail — park unless ACK-class or explicit override. */
|
|
11
|
+
export function shouldBacklogPeerHold(reason, msg) {
|
|
12
|
+
if (isAckClassPeer(msg))
|
|
13
|
+
return false;
|
|
14
|
+
if (/\bPRIORITY\b|\bSTOP other work\b/i.test(msg))
|
|
15
|
+
return false;
|
|
16
|
+
if (BUSY_HOLD.test(reason))
|
|
17
|
+
return true;
|
|
18
|
+
if (/^held:coord:/.test(reason))
|
|
19
|
+
return false;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
export function peerBacklogPath(store) {
|
|
23
|
+
return `${store.stateDir}/PEER-BACKLOG.jsonl`;
|
|
24
|
+
}
|
|
25
|
+
function readBacklog(store) {
|
|
26
|
+
const p = peerBacklogPath(store);
|
|
27
|
+
if (!fs.existsSync(p))
|
|
28
|
+
return [];
|
|
29
|
+
return fs
|
|
30
|
+
.readFileSync(p, "utf8")
|
|
31
|
+
.split("\n")
|
|
32
|
+
.map((l) => l.trim())
|
|
33
|
+
.filter(Boolean)
|
|
34
|
+
.map((l) => {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(l);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
.filter((r) => r !== null && r.status === "backlog");
|
|
43
|
+
}
|
|
44
|
+
function writeBacklog(store, rows) {
|
|
45
|
+
const p = peerBacklogPath(store);
|
|
46
|
+
fs.writeFileSync(p, rows.map((r) => JSON.stringify(r)).join("\n") + (rows.length ? "\n" : ""));
|
|
47
|
+
}
|
|
48
|
+
function paneStatusMark(paneId) {
|
|
49
|
+
return (tmux(["display-message", "-t", paneId, "-p", "#{@mesh_status}"]).out?.trim() ?? "");
|
|
50
|
+
}
|
|
51
|
+
function paneIdleForPromote(paneId, registry) {
|
|
52
|
+
const mark = paneStatusMark(paneId);
|
|
53
|
+
if (/\bBUSY\b/i.test(mark))
|
|
54
|
+
return false;
|
|
55
|
+
const snap = capturePaneSnapshot(paneId);
|
|
56
|
+
if (!snap)
|
|
57
|
+
return false;
|
|
58
|
+
const prov = registry.detect(snap);
|
|
59
|
+
if (!prov)
|
|
60
|
+
return false;
|
|
61
|
+
const st = prov.composerState(snap);
|
|
62
|
+
return st.phase === "empty" || st.phase === "afk";
|
|
63
|
+
}
|
|
64
|
+
/** Re-queue oldest backlog row per idle pane (one promote per pane per tick). */
|
|
65
|
+
export function promotePeerBacklog(store, registry, log) {
|
|
66
|
+
const backlog = readBacklog(store);
|
|
67
|
+
if (!backlog.length)
|
|
68
|
+
return 0;
|
|
69
|
+
const peer = store.readPeer();
|
|
70
|
+
const byPane = new Map();
|
|
71
|
+
for (const row of backlog) {
|
|
72
|
+
const list = byPane.get(row.targetPane) ?? [];
|
|
73
|
+
list.push(row);
|
|
74
|
+
byPane.set(row.targetPane, list);
|
|
75
|
+
}
|
|
76
|
+
let promoted = 0;
|
|
77
|
+
const kept = [];
|
|
78
|
+
for (const [, rows] of byPane) {
|
|
79
|
+
rows.sort((a, b) => a.backlogAt.localeCompare(b.backlogAt));
|
|
80
|
+
const paneId = rows[0].targetPane;
|
|
81
|
+
if (!paneIdleForPromote(paneId, registry)) {
|
|
82
|
+
kept.push(...rows);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const [first, ...rest] = rows;
|
|
86
|
+
const revived = {
|
|
87
|
+
id: first.id,
|
|
88
|
+
at: first.at,
|
|
89
|
+
kind: first.kind,
|
|
90
|
+
fromSlot: first.fromSlot,
|
|
91
|
+
fromPorts: first.fromPorts,
|
|
92
|
+
roomSlug: first.roomSlug,
|
|
93
|
+
fromAgent: first.fromAgent,
|
|
94
|
+
targetPane: first.targetPane,
|
|
95
|
+
targetLabel: first.targetLabel,
|
|
96
|
+
msg: first.msg,
|
|
97
|
+
sent: false,
|
|
98
|
+
};
|
|
99
|
+
peer.push(revived);
|
|
100
|
+
promoted++;
|
|
101
|
+
log(`PEER backlog promote id=${first.id} -> ${first.targetLabel}`);
|
|
102
|
+
kept.push(...rest);
|
|
103
|
+
}
|
|
104
|
+
if (promoted)
|
|
105
|
+
store.writePeer(peer);
|
|
106
|
+
writeBacklog(store, kept);
|
|
107
|
+
return promoted;
|
|
108
|
+
}
|
|
109
|
+
export function parkPeerToBacklog(store, row, holdReason, log) {
|
|
110
|
+
const peer = store.readPeer();
|
|
111
|
+
const i = peer.findIndex((r) => r.id === row.id);
|
|
112
|
+
if (i < 0)
|
|
113
|
+
return;
|
|
114
|
+
row.sent = true;
|
|
115
|
+
row.sentAt = new Date().toISOString();
|
|
116
|
+
row.deliverPane = "backlog";
|
|
117
|
+
row.deliverMode = "idle";
|
|
118
|
+
peer[i] = row;
|
|
119
|
+
store.writePeer(peer);
|
|
120
|
+
const entry = {
|
|
121
|
+
...row,
|
|
122
|
+
status: "backlog",
|
|
123
|
+
backlogAt: new Date().toISOString(),
|
|
124
|
+
holdReason,
|
|
125
|
+
};
|
|
126
|
+
const backlog = readBacklog(store);
|
|
127
|
+
backlog.push(entry);
|
|
128
|
+
writeBacklog(store, backlog);
|
|
129
|
+
log(`PEER backlog id=${row.id} -> ${row.targetLabel} reason=${holdReason}`);
|
|
130
|
+
}
|
|
131
|
+
export function countPeerBacklog(store) {
|
|
132
|
+
return readBacklog(store).length;
|
|
133
|
+
}
|
|
134
|
+
export function pendingPeerRows(store) {
|
|
135
|
+
return store.readPeer().filter((r) => !isPeerDelivered(r));
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=peer-backlog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-backlog.js","sourceRoot":"","sources":["../src/peer-backlog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LoadedProfile } from "@seat-mesh/core";
|
|
2
|
+
import type { QueueStore, PeerRow } from "./create-queue-store.js";
|
|
3
|
+
/** Arm poll-later on recipient after PEER inject (queued path). */
|
|
4
|
+
export declare function armRecipientCheckbackAfterPeer(store: QueueStore, loaded: LoadedProfile, row: PeerRow): void;
|
|
5
|
+
//# sourceMappingURL=peer-comms-checkback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-comms-checkback.d.ts","sourceRoot":"","sources":["../src/peer-comms-checkback.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAgB,UAAU,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AA0BjF,mEAAmE;AACnE,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,OAAO,GACX,IAAI,CAkCN"}
|