@cohortapp/agent-sdk 2.18.7 → 2.18.8
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cohortapp/agent-sdk",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.8",
|
|
4
4
|
"description": "Cohort Agent SDK — autonomous AI colleague runtime. Deploy senior AI colleagues on dedicated Mac minis, wired to the Cohort operating surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -417,6 +417,46 @@ restart_daemon(){
|
|
|
417
417
|
if [ -z "$DAEMON_LABEL" ]; then log "no -daemon plist under ~/Library/LaunchAgents — nothing to kickstart (maestro upgrade installs it; doctor will say)"; return 0; fi
|
|
418
418
|
launchctl kickstart -k "gui/$UID_/$DAEMON_LABEL" >> "$LOG" 2>&1 || log "WARN: kickstart $DAEMON_LABEL nonzero"
|
|
419
419
|
}
|
|
420
|
+
session_beating(){ # is the front door actually ANSWERING, not merely loaded?
|
|
421
|
+
# `session_reconciled` asks whether the job is loaded and a supervisor process
|
|
422
|
+
# is alive. Both were true on the seats that went silent: on 2026-09-24 three
|
|
423
|
+
# front doors had been wedged on an unanswered modal for days with their
|
|
424
|
+
# supervisors up and their jobs loaded. A process that exists is not a
|
|
425
|
+
# colleague who answers — the same substitution this gate's daemon half was
|
|
426
|
+
# rewritten to stop making.
|
|
427
|
+
local hb="$AGENT_DIR/state/session/heartbeat.json" age
|
|
428
|
+
[ -f "$hb" ] || return 1
|
|
429
|
+
age="$(node -e '
|
|
430
|
+
try {
|
|
431
|
+
const j = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
|
432
|
+
const t = Date.parse(j && j.ts);
|
|
433
|
+
process.stdout.write(Number.isFinite(t) ? String(Math.round((Date.now() - t) / 1000)) : "");
|
|
434
|
+
} catch {}
|
|
435
|
+
' "$hb" 2>/dev/null)"
|
|
436
|
+
[ -n "$age" ] || return 1
|
|
437
|
+
[ "$age" -le "$SESSION_STALE_S" ]
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
revive_session(){ # a wedged front door cannot restart itself; restart it FOR it
|
|
441
|
+
# The upgrade notice asks the session to restart "at an idle moment". A
|
|
442
|
+
# session sitting on a modal never reaches an idle moment, so the polite ask
|
|
443
|
+
# is exactly the wrong instrument for the one case that needs it. A hard
|
|
444
|
+
# kickstart drops a wedged session and the new supervisor launches a fresh
|
|
445
|
+
# one — which clears the modal by construction and, from this release,
|
|
446
|
+
# watches the pane so it does not happen again.
|
|
447
|
+
[ -n "$SESSION_LABEL" ] || return 0
|
|
448
|
+
# An UNLOADED job is a different fault with a different remedy (`maestro
|
|
449
|
+
# session start`), and kickstarting a label launchd does not know just fails.
|
|
450
|
+
# Leave that one to session_reconciled, which already names it.
|
|
451
|
+
label_loaded "$SESSION_LABEL" || return 0
|
|
452
|
+
session_beating && return 0
|
|
453
|
+
log "front door $SESSION_LABEL is loaded but not beating (> ${SESSION_STALE_S}s) — kickstarting it rather than waiting for a session that cannot answer"
|
|
454
|
+
launchctl kickstart -k "gui/$(id -u)/$SESSION_LABEL" >> "$LOG" 2>&1 \
|
|
455
|
+
&& { log "front door $SESSION_LABEL restarted"; return 0; }
|
|
456
|
+
log "WARN: could not kickstart $SESSION_LABEL (maestro session restart --force)"
|
|
457
|
+
return 1
|
|
458
|
+
}
|
|
459
|
+
|
|
420
460
|
session_reconciled(){ # only asked when a -session plist was generated; never a rollback reason
|
|
421
461
|
label_loaded "$SESSION_LABEL" || { log "reconcile-failed: session job $SESSION_LABEL is not loaded (maestro session start)"; return 1; }
|
|
422
462
|
pgrep -f "$AGENT_DIR/scripts/session/supervisor" >/dev/null 2>&1 || { log "reconcile-failed: $SESSION_LABEL is loaded but no supervisor process is alive for $AGENT_DIR (maestro session status)"; return 1; }
|
|
@@ -544,6 +584,12 @@ if [ "$CUR" = "$LATEST" ] || [ "$(printf '%s\n%s\n' "$CUR" "$LATEST" | sort -V |
|
|
|
544
584
|
if is_healthy; then
|
|
545
585
|
log "healthy on $CUR"
|
|
546
586
|
sibling_job_audit
|
|
587
|
+
# The up-to-date path is NOT exempt from the front door, for the same
|
|
588
|
+
# reason it stopped being exempt from the daemon: the seats that went
|
|
589
|
+
# silent for days were all "up to date". A daemon that beats while the
|
|
590
|
+
# front door is wedged is a seat that looks perfect from here and answers
|
|
591
|
+
# nobody.
|
|
592
|
+
revive_session || true
|
|
547
593
|
if [ -n "$STALE_HOP" ]; then
|
|
548
594
|
# A real version hop: complete it the way an automatic one completes —
|
|
549
595
|
# the notice tells the session to restart itself onto the new code.
|
|
@@ -597,6 +643,11 @@ fi
|
|
|
597
643
|
# installed version, never a LATEST). Fail-open: an unreadable last.json holds
|
|
598
644
|
# nothing.
|
|
599
645
|
FAILED_HOLD_S="${MAESTRO_AUTOUPDATE_FAILED_HOLD_S:-86400}"
|
|
646
|
+
# How long a front door may go without beating before this run restarts it FOR
|
|
647
|
+
# it. Ten minutes: long enough that a busy session is never interrupted (the
|
|
648
|
+
# heartbeat rides every tool use), short enough that a wedged one is measured in
|
|
649
|
+
# minutes rather than the days it took to notice the last three.
|
|
650
|
+
SESSION_STALE_S="${MAESTRO_SESSION_STALE_S:-600}"
|
|
600
651
|
failed_hold_reason(){ # prints "<reason> at <at>" when LATEST failed health within FAILED_HOLD_S
|
|
601
652
|
node -e '
|
|
602
653
|
const [file, latest, holdS] = process.argv.slice(1);
|
|
@@ -668,7 +719,11 @@ restart_daemon
|
|
|
668
719
|
|
|
669
720
|
if is_healthy; then
|
|
670
721
|
REASON=""
|
|
671
|
-
|
|
722
|
+
# Revive BEFORE reconciling: the new code is installed, and a front door that
|
|
723
|
+
# is not beating must be restarted onto it rather than left holding an inbox
|
|
724
|
+
# it cannot answer.
|
|
725
|
+
revive_session || REASON="session-revive-failed"
|
|
726
|
+
if [ -n "$SESSION_LABEL" ] && ! session_reconciled; then REASON="${REASON:-session-reconcile-failed}"; fi
|
|
672
727
|
log "OK: healthy on $LATEST${REASON:+ ($REASON)}"
|
|
673
728
|
sibling_job_audit
|
|
674
729
|
write_upgrade_notice "$CUR" "$LATEST"
|