@nledford/omp-coord 0.3.0 → 0.3.1
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/.omp-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +8 -1
- package/docs/coordination.md +1 -1
- package/package.json +1 -1
- package/src/domain/history.ts +29 -3
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"name": "omp-coord",
|
|
8
8
|
"source": "./",
|
|
9
9
|
"description": "Shared subagent caps, build and test queues, claims, pause, a decision log and messages across omp sessions working in one project on one machine.",
|
|
10
|
-
"version": "0.3.
|
|
10
|
+
"version": "0.3.1",
|
|
11
11
|
"author": { "name": "Nathaniel Ledford" },
|
|
12
12
|
"homepage": "https://github.com/nledford/omp-coord",
|
|
13
13
|
"repository": "https://github.com/nledford/omp-coord",
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ Add each user-visible change under Unreleased as it lands, in one of: Added, Cha
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.1] - 2026-10-27
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `omp-coord interrupted` and `/coord interrupted` no longer list an agent that was revived (`write agent://<id>`) since its session left, from a session in the same folder, nor its nested helpers, and leave out a session with none left; before, a session restarted after a crash kept being told to revive agents that had long finished. A new agent that only reuses the name doesn't count as a revival.
|
|
14
|
+
|
|
9
15
|
## [0.3.0] - 2026-10-27
|
|
10
16
|
|
|
11
17
|
### Changed
|
|
@@ -76,7 +82,8 @@ Add each user-visible change under Unreleased as it lands, in one of: Added, Cha
|
|
|
76
82
|
- An SQLite event log per scope, with retention.
|
|
77
83
|
- Packaging as an omp plugin, with a marketplace catalog; queued commands run on omp's own Bun.
|
|
78
84
|
|
|
79
|
-
[Unreleased]: https://github.com/nledford/omp-coord/compare/v0.3.
|
|
85
|
+
[Unreleased]: https://github.com/nledford/omp-coord/compare/v0.3.1...HEAD
|
|
86
|
+
[0.3.1]: https://github.com/nledford/omp-coord/compare/v0.3.0...v0.3.1
|
|
80
87
|
[0.3.0]: https://github.com/nledford/omp-coord/compare/v0.2.3...v0.3.0
|
|
81
88
|
[0.2.3]: https://github.com/nledford/omp-coord/compare/v0.2.2...v0.2.3
|
|
82
89
|
[0.2.2]: https://github.com/nledford/omp-coord/compare/v0.2.1...v0.2.2
|
package/docs/coordination.md
CHANGED
|
@@ -36,6 +36,6 @@ With `resources.ports`, each session gets its own block of ports, in `OMP_COORD_
|
|
|
36
36
|
|
|
37
37
|
## After a crash
|
|
38
38
|
|
|
39
|
-
`/coord interrupted` (or `omp-coord interrupted`, which first drops sessions whose process is gone) lists, per session that left, the agents that were mid-run and the folder the session ran in. omp keeps their transcripts; revive each from a session in that folder with `write agent://<id>`.
|
|
39
|
+
`/coord interrupted` (or `omp-coord interrupted`, which first drops sessions whose process is gone) lists, per session that left, the agents that were mid-run and the folder the session ran in. omp keeps their transcripts; revive each from a session in that folder with `write agent://<id>`. An agent revived since from a session in that folder, and its nested helpers, are left out; a new agent that only reuses the name is not a revival.
|
|
40
40
|
|
|
41
41
|
`/coord agents` (or `omp-coord status --agents`) lists who runs: each agent's session, id, type, parent, pool and age, so a message to `B/<agent id>` goes to the agent you mean. `/coord stats` sums waits, refusals, peaks and job outcomes per day; `omp-coord doctor` checks the scope's health, and `doctor --fix` drops sessions and jobs whose process is gone.
|
package/package.json
CHANGED
package/src/domain/history.ts
CHANGED
|
@@ -11,18 +11,34 @@ export interface InterruptedSession {
|
|
|
11
11
|
/**
|
|
12
12
|
* Sessions that left (exited, or were found dead) at or after `since` while some of their agents were in a run:
|
|
13
13
|
* those runs started and never ended. Revive them with `write agent://<id>` from a session in the same folder.
|
|
14
|
+
*
|
|
15
|
+
* An agent revived since, from a session in the same folder, is no longer listed, and neither are its nested
|
|
16
|
+
* helpers (they aren't restarted; reviving the parent covers them); a session with nothing left is left out. A
|
|
17
|
+
* revival is a run that started without a spawn approval (`revived` in the event) by an id that session hadn't run
|
|
18
|
+
* before: a new agent that reuses the name was spawned, so it doesn't hide the old one. A session whose folder is
|
|
19
|
+
* unknown (its join event pruned) never hides anything.
|
|
14
20
|
*/
|
|
15
21
|
export function interrupted(events: BoardEvent[], since: number): InterruptedSession[] {
|
|
16
22
|
const cwd = new Map<string, string>();
|
|
17
23
|
const running = new Map<string, Map<string, { id: string; type: string; startedAt: number }>>();
|
|
24
|
+
const seen = new Map<string, Set<string>>();
|
|
25
|
+
// The latest revival per folder and agent id.
|
|
26
|
+
const revivedAt = new Map<string, number>();
|
|
18
27
|
const result: InterruptedSession[] = [];
|
|
19
28
|
for (const e of events) {
|
|
20
29
|
if (e.sessionId === null) continue;
|
|
21
30
|
const runs = running.get(e.sessionId) ?? new Map();
|
|
22
31
|
running.set(e.sessionId, runs);
|
|
23
32
|
if (e.type === "session_joined" && typeof e.data.cwd === "string") cwd.set(e.sessionId, e.data.cwd);
|
|
24
|
-
if (e.type === "run_started")
|
|
25
|
-
|
|
33
|
+
if (e.type === "run_started") {
|
|
34
|
+
const id = String(e.data.agentId);
|
|
35
|
+
runs.set(id, { id, type: String(e.data.agentType), startedAt: e.at });
|
|
36
|
+
const own = seen.get(e.sessionId) ?? new Set<string>();
|
|
37
|
+
seen.set(e.sessionId, own);
|
|
38
|
+
const folder = cwd.get(e.sessionId);
|
|
39
|
+
if (folder !== undefined && e.data.revived === true && !own.has(id)) revivedAt.set(`${folder}\u0000${id}`, e.at);
|
|
40
|
+
own.add(id);
|
|
41
|
+
}
|
|
26
42
|
if (e.type === "run_ended") runs.delete(String(e.data.agentId));
|
|
27
43
|
if (e.type === "session_left") {
|
|
28
44
|
if (e.at >= since && runs.size)
|
|
@@ -30,7 +46,17 @@ export function interrupted(events: BoardEvent[], since: number): InterruptedSes
|
|
|
30
46
|
running.delete(e.sessionId);
|
|
31
47
|
}
|
|
32
48
|
}
|
|
33
|
-
|
|
49
|
+
const revivedSince = (folder: string | undefined, id: string, leftAt: number): boolean =>
|
|
50
|
+
folder !== undefined && (revivedAt.get(`${folder}\u0000${id}`) ?? 0) > leftAt;
|
|
51
|
+
return result
|
|
52
|
+
.map(s => ({
|
|
53
|
+
...s,
|
|
54
|
+
agents: s.agents.filter(a => {
|
|
55
|
+
const top = a.id.split(".")[0] ?? a.id;
|
|
56
|
+
return !revivedSince(s.cwd, a.id, s.leftAt) && !revivedSince(s.cwd, top, s.leftAt);
|
|
57
|
+
}),
|
|
58
|
+
}))
|
|
59
|
+
.filter(s => s.agents.length > 0);
|
|
34
60
|
}
|
|
35
61
|
|
|
36
62
|
export interface QueueDay {
|