squadrant 0.13.1 → 0.13.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/index.js +71 -16
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +27 -4
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
package/dist/squadrantd.js
CHANGED
|
@@ -543,6 +543,8 @@ function reduce(rec, ev, now) {
|
|
|
543
543
|
return { ...stampAttempt(base, {}, now), state: "blocked", question: ev.question, pendingTool: void 0 };
|
|
544
544
|
case "task.reattached":
|
|
545
545
|
return stampAttempt(base, {}, now);
|
|
546
|
+
case "task.first-turn.confirmed":
|
|
547
|
+
return { ...rec, firstTurnConfirmedAt: now, lastEvent: ev.type };
|
|
546
548
|
case "task.stalled":
|
|
547
549
|
case "task.idle":
|
|
548
550
|
case "task.quiet":
|
|
@@ -580,6 +582,7 @@ function recoverStall(rec, now) {
|
|
|
580
582
|
// packages/core/dist/daemon/reduce.js
|
|
581
583
|
var DEFAULT_TASK_TIMEOUT_MS = 8 * 60 * 60 * 1e3;
|
|
582
584
|
var TERMINAL_RECORD_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
585
|
+
var TERMINAL_RECORD_KEEP_PER_PROJECT = 20;
|
|
583
586
|
var ATTENTION_STATES = /* @__PURE__ */ new Set(["done", "blocked", "failed", "stalled", "awaiting-input"]);
|
|
584
587
|
var REAPABLE_SURFACE_STATES = /* @__PURE__ */ new Set(["working", "stalled", "awaiting-input", "blocked"]);
|
|
585
588
|
var IDLE_DEBOUNCE_MS = 12e3;
|
|
@@ -689,7 +692,9 @@ var KNOWN_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
689
692
|
"task.timeout",
|
|
690
693
|
"task.reconcile-failed",
|
|
691
694
|
"task.cancelled",
|
|
692
|
-
"task.session.ended"
|
|
695
|
+
"task.session.ended",
|
|
696
|
+
"task.first-turn.confirmed"
|
|
697
|
+
// #466: delivery confirmation
|
|
693
698
|
]);
|
|
694
699
|
function createDaemon(deps) {
|
|
695
700
|
const { store, now } = deps;
|
|
@@ -808,6 +813,13 @@ function createDaemon(deps) {
|
|
|
808
813
|
async sweep() {
|
|
809
814
|
const t = now();
|
|
810
815
|
const surfaceAlive = deps.isSurfaceAlive ?? (async () => "unknown");
|
|
816
|
+
const projects = new Set(store.listAll().map((r) => r.project));
|
|
817
|
+
for (const project of projects) {
|
|
818
|
+
const terminal = store.list(project).filter((r) => TERMINAL_STATES.has(r.state)).sort((a, b) => b.lastHeartbeat - a.lastHeartbeat);
|
|
819
|
+
for (const r of terminal.slice(TERMINAL_RECORD_KEEP_PER_PROJECT)) {
|
|
820
|
+
store.delete(r.project, r.id);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
811
823
|
for (const r of store.listAll()) {
|
|
812
824
|
if (TERMINAL_STATES.has(r.state) && t - r.lastHeartbeat > TERMINAL_RECORD_TTL_MS) {
|
|
813
825
|
store.delete(r.project, r.id);
|
|
@@ -822,7 +834,13 @@ function createDaemon(deps) {
|
|
|
822
834
|
const msg = `CREW TIMEOUT ${tag}: wall-clock exceeded ${hrs}h (id: ${r.id}, state: ${prevState})`;
|
|
823
835
|
const synthEvent = { type: "task.timeout", id: r.id, taskTimeoutMs: ceiling };
|
|
824
836
|
store.put({ ...r, state: "cancelled", lastEvent: "sweep.task-timeout" });
|
|
825
|
-
|
|
837
|
+
let shouldNotify = true;
|
|
838
|
+
if (r.mode === "interactive") {
|
|
839
|
+
const liveness = await surfaceAlive(r);
|
|
840
|
+
if (liveness === "gone")
|
|
841
|
+
shouldNotify = false;
|
|
842
|
+
}
|
|
843
|
+
if (deps.notify && shouldNotify) {
|
|
826
844
|
try {
|
|
827
845
|
const p = deps.notify({ project: r.project, message: msg, record: r, event: synthEvent });
|
|
828
846
|
if (p && typeof p.catch === "function") {
|
|
@@ -856,9 +874,14 @@ function createDaemon(deps) {
|
|
|
856
874
|
if (deps.notify && quietNotifiedAt.get(r.id) !== liveness) {
|
|
857
875
|
quietNotifiedAt.set(r.id, liveness);
|
|
858
876
|
const tag = crewTag(r);
|
|
859
|
-
const mins = Math.max(1, Math.round(quiet / 6e4));
|
|
860
|
-
const message = `CREW QUIET ${tag}: working ~${mins}min with no tool activity \u2014 likely deep thinking (no reply expected yet).`;
|
|
861
877
|
const synthEvent = { type: "task.quiet", id: r.id, quietMs: quiet };
|
|
878
|
+
let message;
|
|
879
|
+
if (!r.firstTurnConfirmedAt) {
|
|
880
|
+
message = `\u26A0\uFE0F CREW UNDELIVERED ${tag}: first turn may not have landed (0 activity) \u2014 re-send the task or check the spawn.`;
|
|
881
|
+
} else {
|
|
882
|
+
const mins = Math.max(1, Math.round(quiet / 6e4));
|
|
883
|
+
message = `CREW QUIET ${tag}: working ~${mins}min with no tool activity \u2014 likely deep thinking (no reply expected yet).`;
|
|
884
|
+
}
|
|
862
885
|
try {
|
|
863
886
|
const p = deps.notify({ project: r.project, message, record: r, event: synthEvent });
|
|
864
887
|
if (p && typeof p.catch === "function")
|