@seat-mesh/daemon 0.1.26 → 0.1.29
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/border-paint.d.ts +13 -0
- package/dist/border/border-paint.d.ts.map +1 -0
- package/dist/border/border-paint.js +230 -0
- package/dist/border/border-paint.js.map +1 -0
- package/dist/checkback/checkback-fire.d.ts +8 -0
- package/dist/checkback/checkback-fire.d.ts.map +1 -0
- package/dist/checkback/checkback-fire.js +52 -0
- package/dist/checkback/checkback-fire.js.map +1 -0
- package/dist/checkback/checkback-fire.test.d.ts +2 -0
- package/dist/checkback/checkback-fire.test.d.ts.map +1 -0
- package/dist/checkback/checkback-fire.test.js +36 -0
- package/dist/checkback/checkback-fire.test.js.map +1 -0
- package/dist/connectivity/cc-limit-retry.d.ts +11 -0
- package/dist/connectivity/cc-limit-retry.d.ts.map +1 -0
- package/dist/connectivity/cc-limit-retry.js +73 -0
- package/dist/connectivity/cc-limit-retry.js.map +1 -0
- package/dist/connectivity/connectivity-recovery.d.ts +88 -0
- package/dist/connectivity/connectivity-recovery.d.ts.map +1 -0
- package/dist/connectivity/connectivity-recovery.js +529 -0
- package/dist/connectivity/connectivity-recovery.js.map +1 -0
- package/dist/connectivity/connectivity-recovery.test.d.ts +2 -0
- package/dist/connectivity/connectivity-recovery.test.d.ts.map +1 -0
- package/dist/connectivity/connectivity-recovery.test.js +170 -0
- package/dist/connectivity/connectivity-recovery.test.js.map +1 -0
- package/dist/connectivity/oc-resume-ack.d.ts +32 -0
- package/dist/connectivity/oc-resume-ack.d.ts.map +1 -0
- package/dist/connectivity/oc-resume-ack.js +89 -0
- package/dist/connectivity/oc-resume-ack.js.map +1 -0
- package/dist/connectivity/oc-resume-ack.test.d.ts +2 -0
- package/dist/connectivity/oc-resume-ack.test.d.ts.map +1 -0
- package/dist/connectivity/oc-resume-ack.test.js +23 -0
- package/dist/connectivity/oc-resume-ack.test.js.map +1 -0
- package/dist/connectivity/oc-resume.d.ts +25 -0
- package/dist/connectivity/oc-resume.d.ts.map +1 -0
- package/dist/connectivity/oc-resume.js +84 -0
- package/dist/connectivity/oc-resume.js.map +1 -0
- package/dist/inbox/delivery-hold.d.ts +11 -0
- package/dist/inbox/delivery-hold.d.ts.map +1 -0
- package/dist/inbox/delivery-hold.js +34 -0
- package/dist/inbox/delivery-hold.js.map +1 -0
- package/dist/inbox/delivery-hold.test.d.ts +2 -0
- package/dist/inbox/delivery-hold.test.d.ts.map +1 -0
- package/dist/inbox/delivery-hold.test.js +40 -0
- package/dist/inbox/delivery-hold.test.js.map +1 -0
- package/dist/inbox/inbox-overload.d.ts +19 -0
- package/dist/inbox/inbox-overload.d.ts.map +1 -0
- package/dist/inbox/inbox-overload.js +45 -0
- package/dist/inbox/inbox-overload.js.map +1 -0
- package/dist/inbox/inbox-overload.test.d.ts +2 -0
- package/dist/inbox/inbox-overload.test.d.ts.map +1 -0
- package/dist/inbox/inbox-overload.test.js +43 -0
- package/dist/inbox/inbox-overload.test.js.map +1 -0
- package/dist/inbox/pane-ops-drain.d.ts +14 -0
- package/dist/inbox/pane-ops-drain.d.ts.map +1 -0
- package/dist/inbox/pane-ops-drain.js +53 -0
- package/dist/inbox/pane-ops-drain.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/inject/compose-gate.d.ts +23 -0
- package/dist/inject/compose-gate.d.ts.map +1 -0
- package/dist/inject/compose-gate.js +113 -0
- package/dist/inject/compose-gate.js.map +1 -0
- package/dist/inject/compose-gate.test.d.ts +2 -0
- package/dist/inject/compose-gate.test.d.ts.map +1 -0
- package/dist/inject/compose-gate.test.js +35 -0
- package/dist/inject/compose-gate.test.js.map +1 -0
- package/dist/inject/inject-delivery.d.ts +39 -0
- package/dist/inject/inject-delivery.d.ts.map +1 -0
- package/dist/inject/inject-delivery.js +171 -0
- package/dist/inject/inject-delivery.js.map +1 -0
- package/dist/inject/inject-delivery.test.d.ts +2 -0
- package/dist/inject/inject-delivery.test.d.ts.map +1 -0
- package/dist/inject/inject-delivery.test.js +33 -0
- package/dist/inject/inject-delivery.test.js.map +1 -0
- package/dist/jsonl-store.d.ts.map +1 -1
- package/dist/jsonl-store.js +4 -0
- package/dist/jsonl-store.js.map +1 -1
- package/dist/mesh-inbox-server.js +13 -13
- package/dist/mesh-inbox-server.js.map +1 -1
- package/dist/mesh-orchestrator.d.ts.map +1 -1
- package/dist/mesh-orchestrator.js +1 -0
- package/dist/mesh-orchestrator.js.map +1 -1
- package/dist/notify/notify-act-ui.d.ts +7 -0
- package/dist/notify/notify-act-ui.d.ts.map +1 -0
- package/dist/notify/notify-act-ui.js +59 -0
- package/dist/notify/notify-act-ui.js.map +1 -0
- package/dist/notify/notify-act.d.ts +45 -0
- package/dist/notify/notify-act.d.ts.map +1 -0
- package/dist/notify/notify-act.js +133 -0
- package/dist/notify/notify-act.js.map +1 -0
- package/dist/notify/notify-act.test.d.ts +2 -0
- package/dist/notify/notify-act.test.d.ts.map +1 -0
- package/dist/notify/notify-act.test.js +29 -0
- package/dist/notify/notify-act.test.js.map +1 -0
- package/dist/orchestrator/mesh-orchestrator.d.ts +32 -0
- package/dist/orchestrator/mesh-orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/mesh-orchestrator.js +642 -0
- package/dist/orchestrator/mesh-orchestrator.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +17 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +11 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/workers.d.ts +11 -0
- package/dist/orchestrator/workers.d.ts.map +1 -0
- package/dist/orchestrator/workers.js +12 -0
- package/dist/orchestrator/workers.js.map +1 -0
- package/dist/peer/peer-backlog.d.ts +18 -0
- package/dist/peer/peer-backlog.d.ts.map +1 -0
- package/dist/peer/peer-backlog.js +288 -0
- package/dist/peer/peer-backlog.js.map +1 -0
- package/dist/peer/peer-backlog.test.d.ts +2 -0
- package/dist/peer/peer-backlog.test.d.ts.map +1 -0
- package/dist/peer/peer-backlog.test.js +38 -0
- package/dist/peer/peer-backlog.test.js.map +1 -0
- package/dist/peer/peer-comms-checkback.d.ts +5 -0
- package/dist/peer/peer-comms-checkback.d.ts.map +1 -0
- package/dist/peer/peer-comms-checkback.js +68 -0
- package/dist/peer/peer-comms-checkback.js.map +1 -0
- package/dist/peer/peer-pending.d.ts +9 -0
- package/dist/peer/peer-pending.d.ts.map +1 -0
- package/dist/peer/peer-pending.js +19 -0
- package/dist/peer/peer-pending.js.map +1 -0
- package/dist/peer/peer-pending.test.d.ts +2 -0
- package/dist/peer/peer-pending.test.d.ts.map +1 -0
- package/dist/peer/peer-pending.test.js +76 -0
- package/dist/peer/peer-pending.test.js.map +1 -0
- package/dist/peer/peer-skip.d.ts +20 -0
- package/dist/peer/peer-skip.d.ts.map +1 -0
- package/dist/peer/peer-skip.js +56 -0
- package/dist/peer/peer-skip.js.map +1 -0
- package/dist/peer/peer-skip.test.d.ts +2 -0
- package/dist/peer/peer-skip.test.d.ts.map +1 -0
- package/dist/peer/peer-skip.test.js +63 -0
- package/dist/peer/peer-skip.test.js.map +1 -0
- package/dist/peer/peer-target-resolve.d.ts +8 -0
- package/dist/peer/peer-target-resolve.d.ts.map +1 -0
- package/dist/peer/peer-target-resolve.js +13 -0
- package/dist/peer/peer-target-resolve.js.map +1 -0
- package/dist/peer-backlog.d.ts.map +1 -1
- package/dist/peer-backlog.js +25 -0
- package/dist/peer-backlog.js.map +1 -1
- package/dist/peer-pending.test.js +17 -0
- package/dist/peer-pending.test.js.map +1 -1
- package/dist/queue/bullmq-runtime.d.ts +19 -0
- package/dist/queue/bullmq-runtime.d.ts.map +1 -0
- package/dist/queue/bullmq-runtime.js +78 -0
- package/dist/queue/bullmq-runtime.js.map +1 -0
- package/dist/state/ppa-state.d.ts +32 -0
- package/dist/state/ppa-state.d.ts.map +1 -0
- package/dist/state/ppa-state.js +63 -0
- package/dist/state/ppa-state.js.map +1 -0
- package/dist/store/create-queue-store.d.ts +8 -0
- package/dist/store/create-queue-store.d.ts.map +1 -0
- package/dist/store/create-queue-store.js +19 -0
- package/dist/store/create-queue-store.js.map +1 -0
- package/dist/store/jsonl-dedupe.test.d.ts +2 -0
- package/dist/store/jsonl-dedupe.test.d.ts.map +1 -0
- package/dist/store/jsonl-dedupe.test.js +62 -0
- package/dist/store/jsonl-dedupe.test.js.map +1 -0
- package/dist/store/jsonl-store.checkback.test.d.ts +2 -0
- package/dist/store/jsonl-store.checkback.test.d.ts.map +1 -0
- package/dist/store/jsonl-store.checkback.test.js +55 -0
- package/dist/store/jsonl-store.checkback.test.js.map +1 -0
- package/dist/store/jsonl-store.d.ts +129 -0
- package/dist/store/jsonl-store.d.ts.map +1 -0
- package/dist/store/jsonl-store.js +316 -0
- package/dist/store/jsonl-store.js.map +1 -0
- package/dist/store/sqlite-store.d.ts +52 -0
- package/dist/store/sqlite-store.d.ts.map +1 -0
- package/dist/store/sqlite-store.js +456 -0
- package/dist/store/sqlite-store.js.map +1 -0
- package/dist/store/sqlite-store.test.d.ts +2 -0
- package/dist/store/sqlite-store.test.d.ts.map +1 -0
- package/dist/store/sqlite-store.test.js +76 -0
- package/dist/store/sqlite-store.test.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LoadedProfile, ProviderRegistry, ResolvedUxConfig } from "@seat-mesh/core";
|
|
2
|
+
import type { QueueStore } from "../store/create-queue-store.js";
|
|
3
|
+
export interface BorderPaintConnectivity {
|
|
4
|
+
proxyDownActive: boolean;
|
|
5
|
+
ocLimitedPaneIds: Set<string>;
|
|
6
|
+
}
|
|
7
|
+
/** Immediate border refresh for one pane (e.g. after resume ack clears OC-LIMIT). */
|
|
8
|
+
export declare function repaintMeshPaneBorder(registry: ProviderRegistry, store: QueueStore, paneId: string, connectivity?: BorderPaintConnectivity, inheritGlobal?: boolean, label?: string, stateDir?: string, ux?: ResolvedUxConfig | null, loaded?: LoadedProfile): void;
|
|
9
|
+
/** Paint name | tasks | inbox | checkbacks | status. Inbox never stomps status. */
|
|
10
|
+
export declare function paintMeshBorders(loaded: LoadedProfile, registry: ProviderRegistry, store: QueueStore, session: string, baseWindow: string, workersWindow: string, minisWindow: string, skipPaneIds?: Set<string>, connectivity?: BorderPaintConnectivity, stateDir?: string): void;
|
|
11
|
+
/** Yield between panes so GET /health can answer mid-paint. */
|
|
12
|
+
export declare function paintMeshBordersAsync(loaded: LoadedProfile, registry: ProviderRegistry, store: QueueStore, session: string, baseWindow: string, workersWindow: string, minisWindow: string, skipPaneIds?: Set<string>, connectivity?: BorderPaintConnectivity, stateDir?: string): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=border-paint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"border-paint.d.ts","sourceRoot":"","sources":["../../src/border/border-paint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAsBxG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAgCjE,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC/B;AAoID,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,uBAAuB,EACtC,aAAa,UAAQ,EACrB,KAAK,SAAK,EACV,QAAQ,CAAC,EAAE,MAAM,EACjB,EAAE,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAC5B,MAAM,CAAC,EAAE,aAAa,GACrB,IAAI,CAoBN;AAmBD,mFAAmF;AACnF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,GAAG,CAAC,MAAM,CAAa,EACpC,YAAY,CAAC,EAAE,uBAAuB,EACtC,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAwCN;AASD,+DAA+D;AAC/D,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,WAAW,GAAE,GAAG,CAAC,MAAM,CAAa,EACpC,YAAY,CAAC,EAAE,uBAAuB,EACtC,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA0Cf"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { baseColumnIds, evaluateUxRules, isManagerKind, isSecretaryKind, resolveUxConfig, } from "@seat-mesh/core";
|
|
3
|
+
import { applyMeshSessionBorders, bannerNameFromMeta, capturePaneSnapshot, coordPaneForRole, formatBannerCheckbacks, formatBannerInbox, formatBannerTasks, listMeshMinis, listMeshWorkers, paneMetaForPane, readSeatSnapshot, } from "@seat-mesh/tmux";
|
|
4
|
+
import { classifyCoordDelivery } from "../inject/compose-gate.js";
|
|
5
|
+
import { isInboxDelivered } from "../store/create-queue-store.js";
|
|
6
|
+
import { countPeerPendingForPane, countPeerPendingGlobal } from "../peer/peer-pending.js";
|
|
7
|
+
import { PpaStateStore } from "../state/ppa-state.js";
|
|
8
|
+
let ppaStore = null;
|
|
9
|
+
function ppaForStateDir(stateDir) {
|
|
10
|
+
if (!ppaStore)
|
|
11
|
+
ppaStore = new PpaStateStore(stateDir);
|
|
12
|
+
return ppaStore;
|
|
13
|
+
}
|
|
14
|
+
function tmuxSet(paneId, key, value) {
|
|
15
|
+
spawnSync("tmux", ["set-option", "-p", "-t", paneId, key, value], { encoding: "utf8" });
|
|
16
|
+
}
|
|
17
|
+
const BORDER_PAINT_BATCH = 6;
|
|
18
|
+
let borderPaintOffset = 0;
|
|
19
|
+
function yieldEventLoop() {
|
|
20
|
+
return new Promise((resolve) => setImmediate(resolve));
|
|
21
|
+
}
|
|
22
|
+
function phaseLabel(phase, busyLabel, limitKind) {
|
|
23
|
+
if (phase === "busy")
|
|
24
|
+
return busyLabel ?? "BUSY";
|
|
25
|
+
if (phase === "limit")
|
|
26
|
+
return limitKind ?? "LIMIT";
|
|
27
|
+
if (phase === "typing")
|
|
28
|
+
return "typing";
|
|
29
|
+
if (phase === "afk")
|
|
30
|
+
return "AFK";
|
|
31
|
+
if (phase === "plain_shell")
|
|
32
|
+
return "empty";
|
|
33
|
+
return "idle";
|
|
34
|
+
}
|
|
35
|
+
function borderFromState(st, ux, snap, provId) {
|
|
36
|
+
if (st.phase === "limit") {
|
|
37
|
+
if (ux) {
|
|
38
|
+
const uxHit = evaluateUxRules(snap, provId, ux);
|
|
39
|
+
if (uxHit?.border)
|
|
40
|
+
return uxHit.border;
|
|
41
|
+
}
|
|
42
|
+
if (st.limitKind === "oc-connect")
|
|
43
|
+
return "PROXY-DOWN";
|
|
44
|
+
if (st.limitKind === "cc-limit")
|
|
45
|
+
return "CC-LIMIT";
|
|
46
|
+
return `OC-LIMIT:${st.limitKind ?? "limit"}`;
|
|
47
|
+
}
|
|
48
|
+
if (ux) {
|
|
49
|
+
const uxHit = evaluateUxRules(snap, provId, ux);
|
|
50
|
+
if (uxHit?.border)
|
|
51
|
+
return uxHit.border;
|
|
52
|
+
}
|
|
53
|
+
return phaseLabel(st.phase, st.busyLabel, st.limitKind);
|
|
54
|
+
}
|
|
55
|
+
function inboxWaitSuffix(paneId, registry, unsent) {
|
|
56
|
+
if (unsent <= 0)
|
|
57
|
+
return undefined;
|
|
58
|
+
const snap = capturePaneSnapshot(paneId);
|
|
59
|
+
const prov = snap ? registry.detect(snap) : null;
|
|
60
|
+
const st = prov && snap ? prov.composerState(snap) : null;
|
|
61
|
+
if (!prov || !snap || !st)
|
|
62
|
+
return "pending";
|
|
63
|
+
const gate = classifyCoordDelivery(paneId, st, snap.captureTail, prov.id);
|
|
64
|
+
if (gate.phase === "wait-typing")
|
|
65
|
+
return "wait";
|
|
66
|
+
if (gate.phase === "wait-busy")
|
|
67
|
+
return "wait";
|
|
68
|
+
if (gate.phase === "wait-settle")
|
|
69
|
+
return "settle";
|
|
70
|
+
return "pending";
|
|
71
|
+
}
|
|
72
|
+
function paintOnePaneBorder(loaded, registry, store, paneId, connectivity, inheritGlobal, label, ppa, counts, ux, coordInbox) {
|
|
73
|
+
const meta = paneMetaForPane(paneId);
|
|
74
|
+
const name = bannerNameFromMeta(meta, label);
|
|
75
|
+
tmuxSet(paneId, "@mesh_name", name);
|
|
76
|
+
const seat = readSeatSnapshot(loaded, {
|
|
77
|
+
role: meta?.role || label,
|
|
78
|
+
slot: meta?.slot || null,
|
|
79
|
+
mini: meta?.mini || null,
|
|
80
|
+
});
|
|
81
|
+
tmuxSet(paneId, "@mesh_tasks", formatBannerTasks(seat?.tasks.open ?? 0));
|
|
82
|
+
let inboxN = countPeerPendingForPane(store, paneId);
|
|
83
|
+
let wait;
|
|
84
|
+
if (coordInbox) {
|
|
85
|
+
inboxN += counts.unsent + (counts.unsent === 0 ? counts.unresolved : 0);
|
|
86
|
+
wait = inboxWaitSuffix(paneId, registry, counts.unsent);
|
|
87
|
+
}
|
|
88
|
+
const ownerCb = store
|
|
89
|
+
.readCheckbacks()
|
|
90
|
+
.filter((r) => r.status === "active" && r.ownerPane === paneId).length;
|
|
91
|
+
tmuxSet(paneId, "@mesh_inbox", formatBannerInbox(inboxN, wait, ownerCb));
|
|
92
|
+
tmuxSet(paneId, "@mesh_checkbacks", formatBannerCheckbacks(ownerCb));
|
|
93
|
+
tmuxSet(paneId, "@mesh_patience", ownerCb > 0 ? `PS:${ownerCb}` : "");
|
|
94
|
+
const snap = capturePaneSnapshot(paneId);
|
|
95
|
+
if (!snap) {
|
|
96
|
+
tmuxSet(paneId, "@mesh_status", "empty");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const prov = registry.detect(snap);
|
|
100
|
+
if (!prov) {
|
|
101
|
+
tmuxSet(paneId, "@mesh_status", "empty");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const st = prov.composerState(snap);
|
|
105
|
+
let borderStatus = borderFromState(st, ux, snap, prov.id);
|
|
106
|
+
if (st.phase !== "limit" && inheritGlobal && connectivity) {
|
|
107
|
+
// Global PROXY-DOWN is an OpenCode/CPE episode — do not paint it on Claude/agent/coord panes.
|
|
108
|
+
if (connectivity.proxyDownActive && prov.id === "opencode") {
|
|
109
|
+
borderStatus = "PROXY-DOWN";
|
|
110
|
+
}
|
|
111
|
+
else if (connectivity.ocLimitedPaneIds.has(paneId)) {
|
|
112
|
+
borderStatus = "OC-LIMIT:oc-limit";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
tmuxSet(paneId, "@mesh_status", borderStatus);
|
|
116
|
+
if (ppa && label) {
|
|
117
|
+
ppa.touch({
|
|
118
|
+
paneId,
|
|
119
|
+
label,
|
|
120
|
+
agent: prov.id,
|
|
121
|
+
border: borderStatus,
|
|
122
|
+
composerPhase: st.phase,
|
|
123
|
+
composerLabel: st.busyLabel ?? st.limitKind ?? "",
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function sessionWindows(loaded, session, baseWindow, workersWindow, minisWindow) {
|
|
128
|
+
const wins = [baseWindow, workersWindow, minisWindow];
|
|
129
|
+
const nvim = loaded.profile.layout?.nvim?.window;
|
|
130
|
+
if (nvim)
|
|
131
|
+
wins.push(nvim);
|
|
132
|
+
applyMeshSessionBorders(session, [...new Set(wins.filter(Boolean))]);
|
|
133
|
+
return wins;
|
|
134
|
+
}
|
|
135
|
+
function paintCounts(store) {
|
|
136
|
+
const inbox = store.readInbox();
|
|
137
|
+
const unresolved = inbox.filter((r) => !r.resolved).length;
|
|
138
|
+
const unsent = inbox.filter((r) => !r.resolved && !isInboxDelivered(r)).length;
|
|
139
|
+
return { unsent, unresolved };
|
|
140
|
+
}
|
|
141
|
+
/** Immediate border refresh for one pane (e.g. after resume ack clears OC-LIMIT). */
|
|
142
|
+
export function repaintMeshPaneBorder(registry, store, paneId, connectivity, inheritGlobal = false, label = "", stateDir, ux, loaded) {
|
|
143
|
+
const ppa = stateDir ? ppaForStateDir(stateDir) : null;
|
|
144
|
+
const counts = paintCounts(store);
|
|
145
|
+
if (!loaded) {
|
|
146
|
+
tmuxSet(paneId, "@mesh_status", "idle");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
paintOnePaneBorder(loaded, registry, store, paneId, connectivity, inheritGlobal, label, ppa, counts, ux, isManagerKind(label));
|
|
150
|
+
}
|
|
151
|
+
function collectWorkerMiniTargets(session, workersWindow, minisWindow) {
|
|
152
|
+
return [
|
|
153
|
+
...listMeshWorkers(session, workersWindow).map((w) => ({
|
|
154
|
+
paneId: w.paneId,
|
|
155
|
+
label: `slot-${w.slot}`,
|
|
156
|
+
})),
|
|
157
|
+
...listMeshMinis(session, minisWindow).map((m) => ({
|
|
158
|
+
paneId: m.paneId,
|
|
159
|
+
label: `mini-${m.mini}`,
|
|
160
|
+
})),
|
|
161
|
+
];
|
|
162
|
+
}
|
|
163
|
+
/** Paint name | tasks | inbox | checkbacks | status. Inbox never stomps status. */
|
|
164
|
+
export function paintMeshBorders(loaded, registry, store, session, baseWindow, workersWindow, minisWindow, skipPaneIds = new Set(), connectivity, stateDir) {
|
|
165
|
+
const ux = loaded.profile.ux !== undefined ? resolveUxConfig(loaded.profile.ux) : null;
|
|
166
|
+
const ppa = stateDir ? ppaForStateDir(stateDir) : null;
|
|
167
|
+
const counts = paintCounts(store);
|
|
168
|
+
sessionWindows(loaded, session, baseWindow, workersWindow, minisWindow);
|
|
169
|
+
const paintOne = (paneId, inheritGlobal = false, label = "", coordInbox = false) => {
|
|
170
|
+
if (skipPaneIds.has(paneId))
|
|
171
|
+
return;
|
|
172
|
+
paintOnePaneBorder(loaded, registry, store, paneId, connectivity, inheritGlobal, label, ppa, counts, ux, coordInbox);
|
|
173
|
+
};
|
|
174
|
+
const targets = collectWorkerMiniTargets(session, workersWindow, minisWindow);
|
|
175
|
+
if (targets.length) {
|
|
176
|
+
const batch = workerMiniPaintBatch(targets.length, store);
|
|
177
|
+
for (let i = 0; i < batch; i++) {
|
|
178
|
+
const t = targets[(borderPaintOffset + i) % targets.length];
|
|
179
|
+
paintOne(t.paneId, false, t.label, false);
|
|
180
|
+
}
|
|
181
|
+
borderPaintOffset = (borderPaintOffset + batch) % targets.length;
|
|
182
|
+
}
|
|
183
|
+
for (const col of baseColumnIds(loaded.profile.layout)) {
|
|
184
|
+
const pane = coordPaneForRole(session, baseWindow, col);
|
|
185
|
+
if (!pane)
|
|
186
|
+
continue;
|
|
187
|
+
const kinds = loaded.profile.layout?.base.kinds;
|
|
188
|
+
paintOne(pane, isSecretaryKind(col, kinds), col, isManagerKind(col, kinds));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** When no live peer queue, refresh every worker/mini banner (clear stale backlog counts). */
|
|
192
|
+
function workerMiniPaintBatch(targetLen, store) {
|
|
193
|
+
if (targetLen <= 0)
|
|
194
|
+
return 0;
|
|
195
|
+
if (countPeerPendingGlobal(store) === 0)
|
|
196
|
+
return targetLen;
|
|
197
|
+
return Math.min(BORDER_PAINT_BATCH, targetLen);
|
|
198
|
+
}
|
|
199
|
+
/** Yield between panes so GET /health can answer mid-paint. */
|
|
200
|
+
export async function paintMeshBordersAsync(loaded, registry, store, session, baseWindow, workersWindow, minisWindow, skipPaneIds = new Set(), connectivity, stateDir) {
|
|
201
|
+
const ux = loaded.profile.ux !== undefined ? resolveUxConfig(loaded.profile.ux) : null;
|
|
202
|
+
const ppa = stateDir ? ppaForStateDir(stateDir) : null;
|
|
203
|
+
const counts = paintCounts(store);
|
|
204
|
+
sessionWindows(loaded, session, baseWindow, workersWindow, minisWindow);
|
|
205
|
+
const paintOne = (paneId, inheritGlobal = false, label = "", coordInbox = false) => {
|
|
206
|
+
if (skipPaneIds.has(paneId))
|
|
207
|
+
return;
|
|
208
|
+
paintOnePaneBorder(loaded, registry, store, paneId, connectivity, inheritGlobal, label, ppa, counts, ux, coordInbox);
|
|
209
|
+
};
|
|
210
|
+
const targets = collectWorkerMiniTargets(session, workersWindow, minisWindow);
|
|
211
|
+
if (targets.length) {
|
|
212
|
+
const batch = workerMiniPaintBatch(targets.length, store);
|
|
213
|
+
for (let i = 0; i < batch; i++) {
|
|
214
|
+
if (i > 0)
|
|
215
|
+
await yieldEventLoop();
|
|
216
|
+
const t = targets[(borderPaintOffset + i) % targets.length];
|
|
217
|
+
paintOne(t.paneId, false, t.label, false);
|
|
218
|
+
}
|
|
219
|
+
borderPaintOffset = (borderPaintOffset + batch) % targets.length;
|
|
220
|
+
}
|
|
221
|
+
for (const col of baseColumnIds(loaded.profile.layout)) {
|
|
222
|
+
await yieldEventLoop();
|
|
223
|
+
const pane = coordPaneForRole(session, baseWindow, col);
|
|
224
|
+
if (!pane)
|
|
225
|
+
continue;
|
|
226
|
+
const kinds = loaded.profile.layout?.base.kinds;
|
|
227
|
+
paintOne(pane, isSecretaryKind(col, kinds), col, isManagerKind(col, kinds));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=border-paint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"border-paint.js","sourceRoot":"","sources":["../../src/border/border-paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EACL,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,IAAI,QAAQ,GAAyB,IAAI,CAAC;AAE1C,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC,QAAQ;QAAE,QAAQ,GAAG,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC;IACtD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,GAAW,EAAE,KAAa;IACzD,SAAS,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B,SAAS,cAAc;IACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,SAAkB,EAAE,SAAkB;IACvE,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,SAAS,IAAI,MAAM,CAAC;IACjD,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,SAAS,IAAI,OAAO,CAAC;IACnD,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACxC,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,KAAK,KAAK,aAAa;QAAE,OAAO,OAAO,CAAC;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC;AAOD,SAAS,eAAe,CACtB,EAAiB,EACjB,EAAuC,EACvC,IAAyD,EACzD,MAAc;IAEd,IAAI,EAAE,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QACzB,IAAI,EAAE,EAAE,CAAC;YACP,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;YAChD,IAAI,KAAK,EAAE,MAAM;gBAAE,OAAO,KAAK,CAAC,MAAM,CAAC;QACzC,CAAC;QACD,IAAI,EAAE,CAAC,SAAS,KAAK,YAAY;YAAE,OAAO,YAAY,CAAC;QACvD,IAAI,EAAE,CAAC,SAAS,KAAK,UAAU;YAAE,OAAO,UAAU,CAAC;QACnD,OAAO,YAAY,EAAE,CAAC,SAAS,IAAI,OAAO,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,EAAE,EAAE,CAAC;QACP,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,MAAM;YAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IACzC,CAAC;IACD,OAAO,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,eAAe,CACtB,MAAc,EACd,QAA0B,EAC1B,MAAc;IAEd,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,IAAI,IAAI,CAAC,KAAK,KAAK,aAAa;QAAE,OAAO,MAAM,CAAC;IAChD,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,IAAI,CAAC,KAAK,KAAK,aAAa;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,kBAAkB,CACzB,MAAqB,EACrB,QAA0B,EAC1B,KAAiB,EACjB,MAAc,EACd,YAAiD,EACjD,aAAsB,EACtB,KAAa,EACb,GAAyB,EACzB,MAA8C,EAC9C,EAAuC,EACvC,UAAmB;IAEnB,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;IAEpC,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE;QACpC,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,KAAK;QACzB,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI;QACxB,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI;KACzB,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAEzE,IAAI,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACpD,IAAI,IAAwB,CAAC;IAC7B,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,OAAO,GAAG,KAAK;SAClB,cAAc,EAAE;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IACzE,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEtE,MAAM,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,YAAY,GAAG,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1D,IAAI,EAAE,CAAC,KAAK,KAAK,OAAO,IAAI,aAAa,IAAI,YAAY,EAAE,CAAC;QAC1D,8FAA8F;QAC9F,IAAI,YAAY,CAAC,eAAe,IAAI,IAAI,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAC3D,YAAY,GAAG,YAAY,CAAC;QAC9B,CAAC;aAAM,IAAI,YAAY,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,YAAY,GAAG,mBAAmB,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,CAAC;YACR,MAAM;YACN,KAAK;YACL,KAAK,EAAE,IAAI,CAAC,EAAE;YACd,MAAM,EAAE,YAAY;YACpB,aAAa,EAAE,EAAE,CAAC,KAAK;YACvB,aAAa,EAAE,EAAE,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CACrB,MAAqB,EACrB,OAAe,EACf,UAAkB,EAClB,aAAqB,EACrB,WAAmB;IAEnB,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;IACjD,IAAI,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,uBAAuB,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAAiB;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;IAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/E,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CACnC,QAA0B,EAC1B,KAAiB,EACjB,MAAc,EACd,YAAsC,EACtC,aAAa,GAAG,KAAK,EACrB,KAAK,GAAG,EAAE,EACV,QAAiB,EACjB,EAA4B,EAC5B,MAAsB;IAEtB,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IACD,kBAAkB,CAChB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,EACH,MAAM,EACN,EAAE,EACF,aAAa,CAAC,KAAK,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,OAAe,EACf,aAAqB,EACrB,WAAmB;IAEnB,OAAO;QACL,GAAG,eAAe,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE;SACxB,CAAC,CAAC;QACH,GAAG,aAAa,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE;SACxB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAC9B,MAAqB,EACrB,QAA0B,EAC1B,KAAiB,EACjB,OAAe,EACf,UAAkB,EAClB,aAAqB,EACrB,WAAmB,EACnB,cAA2B,IAAI,GAAG,EAAE,EACpC,YAAsC,EACtC,QAAiB;IAEjB,MAAM,EAAE,GACN,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,aAAa,GAAG,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,EAAE;QACzF,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QACpC,kBAAkB,CAChB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,EACH,MAAM,EACN,EAAE,EACF,UAAU,CACX,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAC;YAC7D,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;QACD,iBAAiB,GAAG,CAAC,iBAAiB,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;QAChD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,SAAS,oBAAoB,CAAC,SAAiB,EAAE,KAAiB;IAChE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7B,IAAI,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1D,OAAO,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAqB,EACrB,QAA0B,EAC1B,KAAiB,EACjB,OAAe,EACf,UAAkB,EAClB,aAAqB,EACrB,WAAmB,EACnB,cAA2B,IAAI,GAAG,EAAE,EACpC,YAAsC,EACtC,QAAiB;IAEjB,MAAM,EAAE,GACN,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAExE,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,aAAa,GAAG,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,EAAE;QACzF,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAO;QACpC,kBAAkB,CAChB,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,EACH,MAAM,EACN,EAAE,EACF,UAAU,CACX,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,cAAc,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAE,CAAC;YAC7D,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;QACD,iBAAiB,GAAG,CAAC,iBAAiB,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,MAAM,cAAc,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC;QAChD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CheckbackRow } from "../store/jsonl-store.js";
|
|
2
|
+
/** Lower runs first when multiple checkbacks are due (supervise must not starve). */
|
|
3
|
+
export declare function checkbackFirePriority(kind: string | undefined): number;
|
|
4
|
+
/** Indices of active due rows, sorted for fire order. */
|
|
5
|
+
export declare function sortDueCheckbackIndices(rows: CheckbackRow[], nowMs: number): number[];
|
|
6
|
+
/** Failed inject: push back so head-of-line cannot block supervise forever. */
|
|
7
|
+
export declare function deferCheckbackAfterFailedFire(row: CheckbackRow, nowMs: number): void;
|
|
8
|
+
//# sourceMappingURL=checkback-fire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkback-fire.d.ts","sourceRoot":"","sources":["../../src/checkback/checkback-fire.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAkBtE;AAED,yDAAyD;AACzD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBrF;AAED,+EAA+E;AAC/E,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAKpF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Lower runs first when multiple checkbacks are due (supervise must not starve). */
|
|
2
|
+
export function checkbackFirePriority(kind) {
|
|
3
|
+
switch (kind) {
|
|
4
|
+
case "secretary-supervise":
|
|
5
|
+
return 0;
|
|
6
|
+
case "balance-lead-tick":
|
|
7
|
+
return 1;
|
|
8
|
+
case "coord-expect":
|
|
9
|
+
return 2;
|
|
10
|
+
case "cc-limit-retry":
|
|
11
|
+
return 2;
|
|
12
|
+
case "coord-nudge":
|
|
13
|
+
return 3;
|
|
14
|
+
case "mesh-watch":
|
|
15
|
+
return 2;
|
|
16
|
+
default:
|
|
17
|
+
if (kind?.endsWith("-nudge") && kind !== "manager-nudge")
|
|
18
|
+
return 3;
|
|
19
|
+
return 10;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Indices of active due rows, sorted for fire order. */
|
|
23
|
+
export function sortDueCheckbackIndices(rows, nowMs) {
|
|
24
|
+
const due = [];
|
|
25
|
+
for (let i = 0; i < rows.length; i++) {
|
|
26
|
+
const row = rows[i];
|
|
27
|
+
if (row.status !== "active")
|
|
28
|
+
continue;
|
|
29
|
+
const exp = row.expiresAt ? Date.parse(row.expiresAt) : 0;
|
|
30
|
+
if (!exp || exp > nowMs)
|
|
31
|
+
continue;
|
|
32
|
+
due.push(i);
|
|
33
|
+
}
|
|
34
|
+
due.sort((a, b) => {
|
|
35
|
+
const pa = checkbackFirePriority(rows[a].kind);
|
|
36
|
+
const pb = checkbackFirePriority(rows[b].kind);
|
|
37
|
+
if (pa !== pb)
|
|
38
|
+
return pa - pb;
|
|
39
|
+
const ea = Date.parse(rows[a].expiresAt ?? "") || 0;
|
|
40
|
+
const eb = Date.parse(rows[b].expiresAt ?? "") || 0;
|
|
41
|
+
return ea - eb;
|
|
42
|
+
});
|
|
43
|
+
return due;
|
|
44
|
+
}
|
|
45
|
+
/** Failed inject: push back so head-of-line cannot block supervise forever. */
|
|
46
|
+
export function deferCheckbackAfterFailedFire(row, nowMs) {
|
|
47
|
+
const renew = row.renewSec && row.renewSec > 0 ? row.renewSec : 180;
|
|
48
|
+
const bumpSec = Math.min(Math.max(renew, 30), 90);
|
|
49
|
+
row.expiresAt = new Date(nowMs + bumpSec * 1000).toISOString();
|
|
50
|
+
row.updatedAt = new Date().toISOString();
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=checkback-fire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkback-fire.js","sourceRoot":"","sources":["../../src/checkback/checkback-fire.ts"],"names":[],"mappings":"AAEA,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,IAAwB;IAC5D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,qBAAqB;YACxB,OAAO,CAAC,CAAC;QACX,KAAK,mBAAmB;YACtB,OAAO,CAAC,CAAC;QACX,KAAK,cAAc;YACjB,OAAO,CAAC,CAAC;QACX,KAAK,gBAAgB;YACnB,OAAO,CAAC,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,CAAC,CAAC;QACX,KAAK,YAAY;YACf,OAAO,CAAC,CAAC;QACX;YACE,IAAI,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,eAAe;gBAAE,OAAO,CAAC,CAAC;YACnE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,uBAAuB,CAAC,IAAoB,EAAE,KAAa;IACzE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ;YAAE,SAAS;QACtC,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,GAAG,IAAI,GAAG,GAAG,KAAK;YAAE,SAAS;QAClC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChB,MAAM,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,6BAA6B,CAAC,GAAiB,EAAE,KAAa;IAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkback-fire.test.d.ts","sourceRoot":"","sources":["../../src/checkback/checkback-fire.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { checkbackFirePriority, sortDueCheckbackIndices } from "./checkback-fire.js";
|
|
3
|
+
describe("checkbackFirePriority", () => {
|
|
4
|
+
it("supervise beats comms", () => {
|
|
5
|
+
expect(checkbackFirePriority("secretary-supervise")).toBeLessThan(checkbackFirePriority("room-comms"));
|
|
6
|
+
});
|
|
7
|
+
});
|
|
8
|
+
describe("sortDueCheckbackIndices", () => {
|
|
9
|
+
it("due supervise fires before older generic checkback", () => {
|
|
10
|
+
const now = Date.parse("2026-09-13T10:16:00.000Z");
|
|
11
|
+
const stamp = "2026-09-13T10:00:00.000Z";
|
|
12
|
+
const rows = [
|
|
13
|
+
{
|
|
14
|
+
id: "old-mini",
|
|
15
|
+
kind: "checkback",
|
|
16
|
+
status: "active",
|
|
17
|
+
expiresAt: "2026-09-13T09:22:00.000Z",
|
|
18
|
+
renewSec: 180,
|
|
19
|
+
createdAt: stamp,
|
|
20
|
+
updatedAt: stamp,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: "mesh-secretary-supervise",
|
|
24
|
+
kind: "secretary-supervise",
|
|
25
|
+
status: "active",
|
|
26
|
+
expiresAt: "2026-09-13T10:15:39.000Z",
|
|
27
|
+
renewSec: 600,
|
|
28
|
+
createdAt: stamp,
|
|
29
|
+
updatedAt: stamp,
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
const order = sortDueCheckbackIndices(rows, now);
|
|
33
|
+
expect(order).toEqual([1, 0]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=checkback-fire.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkback-fire.test.js","sourceRoot":"","sources":["../../src/checkback/checkback-fire.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAErF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAC/D,qBAAqB,CAAC,YAAY,CAAC,CACpC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,0BAA0B,CAAC;QACzC,MAAM,IAAI,GAAmB;YAC3B;gBACE,EAAE,EAAE,UAAU;gBACd,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,0BAA0B;gBACrC,QAAQ,EAAE,GAAG;gBACb,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,KAAK;aACjB;YACD;gBACE,EAAE,EAAE,0BAA0B;gBAC9B,IAAI,EAAE,qBAAqB;gBAC3B,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,0BAA0B;gBACrC,QAAQ,EAAE,GAAG;gBACb,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,KAAK;aACjB;SACF,CAAC;QACF,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PaneSnapshot, ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
import type { QueueStore } from "../store/create-queue-store.js";
|
|
3
|
+
/** Stable id for same pane + Claude resume session (cancel when pane replaced). */
|
|
4
|
+
export declare function paneSessionFingerprint(registry: ProviderRegistry, snap: PaneSnapshot): string;
|
|
5
|
+
/** Parse "try again at 8:00 PM" style from Claude limit screen (Asia/Manila default). */
|
|
6
|
+
export declare function parseCcLimitRetryAtMs(captureTail: string, now?: number): number | null;
|
|
7
|
+
export declare function armCcLimitRetryCheckback(store: QueueStore, paneId: string, fingerprint: string, expiresAtMs: number, log: (line: string) => void): void;
|
|
8
|
+
export declare function ccLimitRetryFingerprintFromExpect(expect: string): string | null;
|
|
9
|
+
export declare function paneMatchesCcLimitFingerprint(registry: ProviderRegistry, paneId: string, fingerprint: string): boolean;
|
|
10
|
+
export declare function meshInboxCcLimitRetryContinue(role: string): string;
|
|
11
|
+
//# sourceMappingURL=cc-limit-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cc-limit-retry.d.ts","sourceRoot":"","sources":["../../src/connectivity/cc-limit-retry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAK/E,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,YAAY,GACjB,MAAM,CASR;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,MAAM,GAAG,IAAI,CAY1F;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC1B,IAAI,CAyBN;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/E;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAIT;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { meshInboxContinueLead } from "@seat-mesh/core";
|
|
3
|
+
import { capturePaneSnapshot } from "@seat-mesh/tmux";
|
|
4
|
+
const CC_LIMIT_RETRY_ID_PREFIX = "cb-cc-limit-retry-";
|
|
5
|
+
/** Stable id for same pane + Claude resume session (cancel when pane replaced). */
|
|
6
|
+
export function paneSessionFingerprint(registry, snap) {
|
|
7
|
+
const prov = registry.detect(snap);
|
|
8
|
+
const det = prov?.detect(snap);
|
|
9
|
+
const resume = det?.resumeId ?? "";
|
|
10
|
+
const cmd = snap.currentCommand ?? "";
|
|
11
|
+
const h = createHash("sha256")
|
|
12
|
+
.update(`${prov?.id ?? "?"}|${resume}|${cmd}`)
|
|
13
|
+
.digest("hex");
|
|
14
|
+
return h.slice(0, 16);
|
|
15
|
+
}
|
|
16
|
+
/** Parse "try again at 8:00 PM" style from Claude limit screen (Asia/Manila default). */
|
|
17
|
+
export function parseCcLimitRetryAtMs(captureTail, now = Date.now()) {
|
|
18
|
+
const m = captureTail.match(/try again (?:at )?(\d{1,2}):(\d{2})\s*(AM|PM)?/i);
|
|
19
|
+
if (!m)
|
|
20
|
+
return null;
|
|
21
|
+
let hour = Number(m[1]);
|
|
22
|
+
const min = Number(m[2]);
|
|
23
|
+
const ampm = (m[3] ?? "").toUpperCase();
|
|
24
|
+
if (ampm === "PM" && hour < 12)
|
|
25
|
+
hour += 12;
|
|
26
|
+
if (ampm === "AM" && hour === 12)
|
|
27
|
+
hour = 0;
|
|
28
|
+
const d = new Date(now);
|
|
29
|
+
d.setHours(hour, min, 0, 0);
|
|
30
|
+
if (d.getTime() <= now)
|
|
31
|
+
d.setDate(d.getDate() + 1);
|
|
32
|
+
return d.getTime();
|
|
33
|
+
}
|
|
34
|
+
export function armCcLimitRetryCheckback(store, paneId, fingerprint, expiresAtMs, log) {
|
|
35
|
+
const id = `${CC_LIMIT_RETRY_ID_PREFIX}${paneId.replace(/%/g, "")}`;
|
|
36
|
+
const rows = store.readCheckbacks();
|
|
37
|
+
const nowIso = new Date().toISOString();
|
|
38
|
+
const expiresAt = new Date(expiresAtMs).toISOString();
|
|
39
|
+
const existing = rows.find((r) => r.id === id && r.status === "active");
|
|
40
|
+
if (existing?.expect?.includes(fingerprint)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const row = {
|
|
44
|
+
id,
|
|
45
|
+
kind: "cc-limit-retry",
|
|
46
|
+
status: "active",
|
|
47
|
+
expect: `F-cc-limit-retry ${fingerprint}`,
|
|
48
|
+
ownerPane: paneId,
|
|
49
|
+
expiresAt,
|
|
50
|
+
renewSec: 300,
|
|
51
|
+
createdAt: existing?.createdAt ?? nowIso,
|
|
52
|
+
updatedAt: nowIso,
|
|
53
|
+
senderLabel: "inbox",
|
|
54
|
+
recipientLabel: paneId,
|
|
55
|
+
sessionFingerprint: fingerprint,
|
|
56
|
+
};
|
|
57
|
+
store.upsertCheckback(row);
|
|
58
|
+
log(`cc-limit-retry armed pane=${paneId} at=${expiresAt} fp=${fingerprint}`);
|
|
59
|
+
}
|
|
60
|
+
export function ccLimitRetryFingerprintFromExpect(expect) {
|
|
61
|
+
const m = expect.match(/^F-cc-limit-retry ([a-f0-9]+)/);
|
|
62
|
+
return m?.[1] ?? null;
|
|
63
|
+
}
|
|
64
|
+
export function paneMatchesCcLimitFingerprint(registry, paneId, fingerprint) {
|
|
65
|
+
const snap = capturePaneSnapshot(paneId);
|
|
66
|
+
if (!snap)
|
|
67
|
+
return false;
|
|
68
|
+
return paneSessionFingerprint(registry, snap) === fingerprint;
|
|
69
|
+
}
|
|
70
|
+
export function meshInboxCcLimitRetryContinue(role) {
|
|
71
|
+
return meshInboxContinueLead(role);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=cc-limit-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cc-limit-retry.js","sourceRoot":"","sources":["../../src/connectivity/cc-limit-retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type LoadedProfile, type ProviderRegistry } from "@seat-mesh/core";
|
|
2
|
+
import { type ResumeWaveMeta } from "./oc-resume.js";
|
|
3
|
+
/**
|
|
4
|
+
* Seconds left on the Proxy-SMART file cooldown (0 = none / expired).
|
|
5
|
+
* Reads the same stamp file cpe-proxy-smart-restart.sh writes — never the daemon's
|
|
6
|
+
* own state — so the daemon and any harness script agree on cooldown status.
|
|
7
|
+
*/
|
|
8
|
+
export declare function smartRestartCooldownLeftSec(stampPath?: string, cooldownSec?: number, nowMs?: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Consecutive ipify probe failures before treating carrier as down (debounce flaky curls).
|
|
11
|
+
* Exported for unit testing without tmux/process spawning.
|
|
12
|
+
*/
|
|
13
|
+
export declare function updateIpifyProbeStreak(state: Pick<ConnectivityRecoveryState, "ipifyFailStreak">, carrierOk: boolean, threshold: number): {
|
|
14
|
+
confirmedDown: boolean;
|
|
15
|
+
streak: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Pure rising-edge/episode reducer for the OC-LIMIT (rate-limit) state machine.
|
|
19
|
+
* Exported for unit testing without tmux/process spawning.
|
|
20
|
+
*/
|
|
21
|
+
export declare function updateRateLimitEpisode(state: Pick<ConnectivityRecoveryState, "rateLimitEpisodeActive" | "lastRateLimitSeenAt">, anyRateLimitNow: boolean, nowMs?: number, graceMs?: number): {
|
|
22
|
+
action: "start" | "continue" | "clear" | "none";
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Pure decision: after Proxy-SMART exits, should rotate-until run next?
|
|
26
|
+
* Mirrors inbox-server.mjs shouldRunRotateUntilAfterSmart — chain rotate-until
|
|
27
|
+
* when SMART was skipped (cooldown), failed, or the carrier IP did not change.
|
|
28
|
+
*/
|
|
29
|
+
export declare function shouldChainRotateUntilAfterSmart(input: {
|
|
30
|
+
exitCode: number;
|
|
31
|
+
ipBefore: string | null;
|
|
32
|
+
ipAfter: string | null;
|
|
33
|
+
}): boolean;
|
|
34
|
+
/** Exported for unit tests. */
|
|
35
|
+
export declare function updatePaneConnectStreak(streakMap: Map<string, number>, paneId: string, sawConnect: boolean, threshold: number): {
|
|
36
|
+
confirmed: boolean;
|
|
37
|
+
streak: number;
|
|
38
|
+
};
|
|
39
|
+
/** Drop OC-LIMIT border state for a pane once resume ack confirms it is working again. */
|
|
40
|
+
export declare function clearOcLimitBannerForPane(state: ConnectivityRecoveryState, paneId: string): boolean;
|
|
41
|
+
/** When no panes remain limited, end the OC-LIMIT episode so borders and proxy recovery unlock. */
|
|
42
|
+
export declare function maybeEndRateLimitEpisode(state: ConnectivityRecoveryState): void;
|
|
43
|
+
export interface ConnectivityRecoveryState {
|
|
44
|
+
ocLimited: Set<string>;
|
|
45
|
+
connectPanes: Set<string>;
|
|
46
|
+
proxyDownActive: boolean;
|
|
47
|
+
recoveryRunning: boolean;
|
|
48
|
+
lastProxyUpAt: number;
|
|
49
|
+
lastRotateAt: number;
|
|
50
|
+
/** Carrier IP when PROXY-DOWN episode started (for notify on recovery). */
|
|
51
|
+
carrierIpAtEpisodeStart: string | null;
|
|
52
|
+
/** True while ANY OC pane has shown a rate-limit this episode (rising-edge gate). */
|
|
53
|
+
rateLimitEpisodeActive: boolean;
|
|
54
|
+
/** ms epoch a rate-limited pane was last observed (episode-clear grace timer). */
|
|
55
|
+
lastRateLimitSeenAt: number;
|
|
56
|
+
/** ms epoch the current PROXY-DOWN episode started (0 = no active episode). */
|
|
57
|
+
proxyDownEpisodeStartAt: number;
|
|
58
|
+
/** True once the "still down" toast has fired for the current episode (no repeat spam). */
|
|
59
|
+
proxyDownStuckNotified: boolean;
|
|
60
|
+
/** One Proxy-SMART/rotate-until per OC-LIMIT episode — no restart loop while banner persists. */
|
|
61
|
+
rateLimitRecoveryStarted: boolean;
|
|
62
|
+
/** Consecutive daemon polls where ipify via proxy failed (reset on success). */
|
|
63
|
+
ipifyFailStreak: number;
|
|
64
|
+
}
|
|
65
|
+
export declare function newConnectivityRecoveryState(): ConnectivityRecoveryState;
|
|
66
|
+
/**
|
|
67
|
+
* Pure decision: has a PROXY-DOWN episode been running long enough, with no
|
|
68
|
+
* "still down" toast sent yet, to warrant telling operator it's stuck (not silent)?
|
|
69
|
+
* Exported for unit testing without tmux/process spawning.
|
|
70
|
+
*/
|
|
71
|
+
export declare function shouldNotifyProxyDownStuck(state: Pick<ConnectivityRecoveryState, "proxyDownEpisodeStartAt" | "proxyDownStuckNotified">, nowMs?: number, thresholdMs?: number): boolean;
|
|
72
|
+
export interface ConnectivityPollInput {
|
|
73
|
+
loaded: LoadedProfile;
|
|
74
|
+
registry: ProviderRegistry;
|
|
75
|
+
workspace: string;
|
|
76
|
+
session: string;
|
|
77
|
+
baseWindow: string;
|
|
78
|
+
workersWindow: string;
|
|
79
|
+
minisWindow: string;
|
|
80
|
+
state: ConnectivityRecoveryState;
|
|
81
|
+
log: (line: string) => void;
|
|
82
|
+
resumeOpenCodePanes: (reason: string, meta?: ResumeWaveMeta) => void;
|
|
83
|
+
/** Claude cc-limit rising edge — schedule session-scoped retry checkback. */
|
|
84
|
+
onCcLimitRise?: (paneId: string, snap: import("@seat-mesh/core").PaneSnapshot) => void;
|
|
85
|
+
}
|
|
86
|
+
/** Scan all monitor panes; update limit sets; trigger async recovery on rising edges only. */
|
|
87
|
+
export declare function pollConnectivityRecovery(input: ConnectivityPollInput): void;
|
|
88
|
+
//# sourceMappingURL=connectivity-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectivity-recovery.d.ts","sourceRoot":"","sources":["../../src/connectivity/connectivity-recovery.ts"],"names":[],"mappings":"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"}
|