parawatch 0.3.12 → 0.3.14
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/core/ops.js +31 -5
- package/package.json +2 -1
package/dist/core/ops.js
CHANGED
|
@@ -423,10 +423,12 @@ export function leadOf(state, ended) {
|
|
|
423
423
|
if (!project)
|
|
424
424
|
return undefined;
|
|
425
425
|
if (!memo.has(project)) {
|
|
426
|
+
// the newest claim leads; claims keep log order, so a tie in time goes to the later one
|
|
426
427
|
const leads = state.claims
|
|
427
|
-
.
|
|
428
|
-
.
|
|
429
|
-
|
|
428
|
+
.map((c, i) => ({ c, i }))
|
|
429
|
+
.filter(({ c }) => c.role === "lead" && c.project === project && !c.done && !ended(c.session))
|
|
430
|
+
.sort((a, b) => (b.c.at ?? "").localeCompare(a.c.at ?? "") || b.i - a.i);
|
|
431
|
+
memo.set(project, leads[0]?.c.session);
|
|
430
432
|
}
|
|
431
433
|
return memo.get(project);
|
|
432
434
|
};
|
|
@@ -719,7 +721,7 @@ export function inboxScope(opts, session) {
|
|
|
719
721
|
// A lead waiting on its project from a session: what other live sessions own is theirs. It
|
|
720
722
|
// takes over the project cursor once, so it does not hear again what that wait delivered.
|
|
721
723
|
const mine = readCursor(consumer);
|
|
722
|
-
const merged = furthest(mine, readCursor(opts.project));
|
|
724
|
+
const merged = furthest(Object.keys(mine).length ? mine : bornAt(session), readCursor(opts.project));
|
|
723
725
|
if (JSON.stringify(merged) !== JSON.stringify(mine))
|
|
724
726
|
writeCursor(consumer, merged);
|
|
725
727
|
return { consumer, filter: { session, project: opts.project } };
|
|
@@ -728,12 +730,36 @@ export function inboxScope(opts, session) {
|
|
|
728
730
|
// A session that used to wait on its project starts where that wait stopped, so moving to its
|
|
729
731
|
// own cursor does not bring back news it has already handled.
|
|
730
732
|
if (claim && !Object.keys(readCursor(consumer)).length) {
|
|
731
|
-
const from = readCursor(claim.project);
|
|
733
|
+
const from = furthest(bornAt(session), readCursor(claim.project));
|
|
732
734
|
if (Object.keys(from).length)
|
|
733
735
|
writeCursor(consumer, from);
|
|
734
736
|
}
|
|
735
737
|
return { consumer, filter: { session, project: claim?.project } };
|
|
736
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Where a session's first wait starts: just before the session first shows in the log (a claim,
|
|
741
|
+
* a card it opened, a pull request linked to it, something handed to it). Nothing before that was
|
|
742
|
+
* its to act on, and a lead starting at the top of the log would hear every old pull request and
|
|
743
|
+
* answer of the project again. A session the log has not seen starts at the top; it has nothing
|
|
744
|
+
* of its own and no project yet.
|
|
745
|
+
*/
|
|
746
|
+
export function bornAt(session, events = readEvents()) {
|
|
747
|
+
const i = events.findIndex((ev) => {
|
|
748
|
+
switch (ev.type) {
|
|
749
|
+
case "run.claim":
|
|
750
|
+
return sameSession(ev.claim.session, session);
|
|
751
|
+
case "card.open":
|
|
752
|
+
return sameSession(ev.card.session, session);
|
|
753
|
+
case "pr.link":
|
|
754
|
+
return sameSession(ev.link.session, session);
|
|
755
|
+
case "card.hand":
|
|
756
|
+
return sameSession(ev.session, session);
|
|
757
|
+
default:
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
return i < 0 ? {} : advance({}, events.slice(0, i));
|
|
762
|
+
}
|
|
737
763
|
export function readInbox(consumer, filter, move) {
|
|
738
764
|
const events = readEvents();
|
|
739
765
|
const pos = readCursor(consumer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parawatch",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "A control tower for people running many AI coding agents in parallel: see what is running, what needs you, and wake the right agent when you answer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^22.10.1",
|
|
51
|
+
"happy-dom": "^21.0.4",
|
|
51
52
|
"tsx": "^4.19.2",
|
|
52
53
|
"typescript": "^5.7.2",
|
|
53
54
|
"vitest": "^2.1.8"
|