sentinelayer-cli 0.35.1 → 0.35.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/session.js +24 -2
- package/src/session/listener.js +3 -0
- package/src/session/recap.js +4 -4
package/package.json
CHANGED
package/src/commands/session.js
CHANGED
|
@@ -1851,6 +1851,23 @@ function listenerPresenceHeartbeatFingerprint(lifecycle = {}) {
|
|
|
1851
1851
|
);
|
|
1852
1852
|
}
|
|
1853
1853
|
|
|
1854
|
+
export function listenerLifecycleIdempotencyStep(lifecycle = {}) {
|
|
1855
|
+
const lifecycleType = normalizeString(lifecycle?.type) || "heartbeat";
|
|
1856
|
+
const heartbeatCount = Number(lifecycle?.heartbeatCount);
|
|
1857
|
+
if (
|
|
1858
|
+
lifecycleType === "heartbeat" &&
|
|
1859
|
+
Number.isInteger(heartbeatCount) &&
|
|
1860
|
+
heartbeatCount > 0
|
|
1861
|
+
) {
|
|
1862
|
+
return heartbeatCount;
|
|
1863
|
+
}
|
|
1864
|
+
const pollCount = Number(lifecycle?.pollCount);
|
|
1865
|
+
if (Number.isInteger(pollCount) && pollCount >= 0) {
|
|
1866
|
+
return pollCount;
|
|
1867
|
+
}
|
|
1868
|
+
return 0;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1854
1871
|
export function shouldPublishListenerPresenceHeartbeat({
|
|
1855
1872
|
lifecycle = {},
|
|
1856
1873
|
nowMs = Date.now(),
|
|
@@ -1900,6 +1917,10 @@ async function publishListenerPresenceEvent({
|
|
|
1900
1917
|
} = {}) {
|
|
1901
1918
|
const normalizedType = normalizeString(lifecycle.type) || "heartbeat";
|
|
1902
1919
|
const eventName = listenerLifecycleEventName(normalizedType);
|
|
1920
|
+
const idempotencyStep = listenerLifecycleIdempotencyStep({
|
|
1921
|
+
...lifecycle,
|
|
1922
|
+
type: normalizedType,
|
|
1923
|
+
});
|
|
1903
1924
|
const identity = inferSessionAgentIdentity({
|
|
1904
1925
|
agentId,
|
|
1905
1926
|
model: agentModel,
|
|
@@ -1918,8 +1939,8 @@ async function publishListenerPresenceEvent({
|
|
|
1918
1939
|
provider: normalizeString(identity.provider) || undefined,
|
|
1919
1940
|
clientKind: normalizeString(identity.clientKind) || "cli",
|
|
1920
1941
|
},
|
|
1921
|
-
eventId: `session-listener-${listenerId}-${normalizedType}-${
|
|
1922
|
-
idempotencyToken: `session-listener:${listenerId}:${normalizedType}:${
|
|
1942
|
+
eventId: `session-listener-${listenerId}-${normalizedType}-${idempotencyStep}`,
|
|
1943
|
+
idempotencyToken: `session-listener:${listenerId}:${normalizedType}:${idempotencyStep}`,
|
|
1923
1944
|
payload: compactPayload({
|
|
1924
1945
|
source: "session_listen",
|
|
1925
1946
|
listenerId,
|
|
@@ -1930,6 +1951,7 @@ async function publishListenerPresenceEvent({
|
|
|
1930
1951
|
cursorSuffix: lifecycle.cursorSuffix,
|
|
1931
1952
|
cursorSource: lifecycle.cursorSource,
|
|
1932
1953
|
pollCount: lifecycle.pollCount,
|
|
1954
|
+
heartbeatCount: lifecycle.heartbeatCount,
|
|
1933
1955
|
matched: lifecycle.matched,
|
|
1934
1956
|
emitted: lifecycle.emitted,
|
|
1935
1957
|
persistedCursor: lifecycle.persistedCursor,
|
package/src/session/listener.js
CHANGED
|
@@ -292,6 +292,7 @@ export async function listenSessionEvents({
|
|
|
292
292
|
let activeTransport = normalizedTransport === "poll" ? "poll" : "stream";
|
|
293
293
|
let streamAttempted = false;
|
|
294
294
|
let streamFallbackReason = "";
|
|
295
|
+
let heartbeatCount = 0;
|
|
295
296
|
let catchupNotified = false;
|
|
296
297
|
let catchupEventCount = 0;
|
|
297
298
|
let catchupMatchingEventCount = 0;
|
|
@@ -340,6 +341,7 @@ export async function listenSessionEvents({
|
|
|
340
341
|
cursor: cursor || null,
|
|
341
342
|
cursorSuffix,
|
|
342
343
|
pollCount,
|
|
344
|
+
heartbeatCount,
|
|
343
345
|
matched,
|
|
344
346
|
emitted,
|
|
345
347
|
persistedCursor,
|
|
@@ -474,6 +476,7 @@ export async function listenSessionEvents({
|
|
|
474
476
|
}
|
|
475
477
|
|
|
476
478
|
async function notifyHeartbeat({ stopping = false, nextPollMs = null } = {}) {
|
|
479
|
+
heartbeatCount += 1;
|
|
477
480
|
const heartbeatAtMs = Number(_nowMs()) || Date.now();
|
|
478
481
|
const humanActive = isRecentActivity(lastHumanActivityMs, heartbeatAtMs, activeWindowMs);
|
|
479
482
|
await notifyLifecycle(
|
package/src/session/recap.js
CHANGED
|
@@ -786,7 +786,7 @@ function buildRecapText({
|
|
|
786
786
|
function buildTaskLedgerText(taskLedger = emptyTaskLedgerSummary()) {
|
|
787
787
|
const total = Number(taskLedger.total || 0);
|
|
788
788
|
if (!total) {
|
|
789
|
-
return "
|
|
789
|
+
return "Session tasks: none queued";
|
|
790
790
|
}
|
|
791
791
|
const active = Number(taskLedger.active || 0);
|
|
792
792
|
const counts = [
|
|
@@ -813,7 +813,7 @@ function buildTaskLedgerText(taskLedger = emptyTaskLedgerSummary()) {
|
|
|
813
813
|
.map((task) => `${task.priority} ${task.status} ${task.owner}: ${task.task}`)
|
|
814
814
|
.join(" | ")}`
|
|
815
815
|
: "";
|
|
816
|
-
return [`
|
|
816
|
+
return [`Session tasks: ${active} active of ${total} total (${counts})`, ownerText, recentText]
|
|
817
817
|
.filter(Boolean)
|
|
818
818
|
.join(". ");
|
|
819
819
|
}
|
|
@@ -849,7 +849,7 @@ function buildWorkPlanText(workPlan = emptyWorkPlanSummary()) {
|
|
|
849
849
|
suppressionReason === "historical_generic_plan_section"
|
|
850
850
|
? "Current/next items suppressed because this generic plan is mostly historical completed work."
|
|
851
851
|
: "Current/next items suppressed because the plan file is large.";
|
|
852
|
-
return `
|
|
852
|
+
return `Workspace plan: ${open} open / ${completed} done in ${sourceWindowText}${sourceReasonText}. ${suppressionText}`;
|
|
853
853
|
}
|
|
854
854
|
const currentSection = normalizeString(workPlan.currentSection);
|
|
855
855
|
const currentText = currentSection ? ` Current: ${currentSection}.` : "";
|
|
@@ -866,7 +866,7 @@ function buildWorkPlanText(workPlan = emptyWorkPlanSummary()) {
|
|
|
866
866
|
.join("; ")}.`
|
|
867
867
|
: "";
|
|
868
868
|
const truncatedText = workPlan.truncated ? " Recent window only." : "";
|
|
869
|
-
return `
|
|
869
|
+
return `Workspace plan: ${open} open / ${completed} done in ${sourceText}${sourceReasonText}.${currentText}${nextText}${truncatedText}`;
|
|
870
870
|
}
|
|
871
871
|
|
|
872
872
|
function roundCurrency(value) {
|