@ccmsg/cli 0.8.0 → 0.8.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/package.json
CHANGED
package/src/instance/instance.ts
CHANGED
package/src/sessions/registry.ts
CHANGED
|
@@ -536,14 +536,52 @@ export class Sessions implements UpstreamResource {
|
|
|
536
536
|
...[...own.present]
|
|
537
537
|
.filter((sid) => !this.#connected.has(sid))
|
|
538
538
|
.map((sid) => this.#unconnected(sid, now, own)),
|
|
539
|
-
...this.#lastLive.entries(now).map((entry) => (
|
|
540
|
-
...entry,
|
|
541
|
-
state: this.classify(entry.sid, now, own) ?? "disappeared",
|
|
542
|
-
pinned: this.#pinned(entry.sid),
|
|
543
|
-
})),
|
|
539
|
+
...this.#lastLive.entries(now).map((entry) => this.#lost(entry, now, own)),
|
|
544
540
|
];
|
|
545
541
|
}
|
|
546
542
|
|
|
543
|
+
/** One row of `peers`, for a producer that knows which session moved.
|
|
544
|
+
*
|
|
545
|
+
* The same three sources the list is built from, asked about one sid: a
|
|
546
|
+
* connection here, a session the harness names, an entry among the sessions
|
|
547
|
+
* this instance has lost. A sid none of them holds is one this instance has
|
|
548
|
+
* no row for, and it says so rather than inventing one. */
|
|
549
|
+
#peerRow(sid: Sid, now: Timestamp, own: Own): PeerInfo | undefined {
|
|
550
|
+
const held = this.#connected.get(sid);
|
|
551
|
+
if (held !== undefined) return this.#peer(held, now, own);
|
|
552
|
+
if (own.present.has(sid)) return this.#unconnected(sid, now, own);
|
|
553
|
+
const entry = this.#lastLive.get(sid);
|
|
554
|
+
return entry === undefined ? undefined : this.#lost(entry, now, own);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** A session this instance has lost, as a row: what was observed of it,
|
|
558
|
+
* with the two fields a row derives worked out at read time (M4). */
|
|
559
|
+
#lost(entry: StoredEntry, now: Timestamp, own: Own): PeerInfo {
|
|
560
|
+
return {
|
|
561
|
+
...entry,
|
|
562
|
+
state: this.classify(entry.sid, now, own) ?? "disappeared",
|
|
563
|
+
pinned: this.#pinned(entry.sid),
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/** The gateway saw inference for one session again (§5.1).
|
|
568
|
+
*
|
|
569
|
+
* What moved is one attribute of one row, so that row is what goes out. The
|
|
570
|
+
* sessions domain is not recomputed for it: which sessions there are has not
|
|
571
|
+
* changed, and the whole of that work would be spent to restate a clock.
|
|
572
|
+
*
|
|
573
|
+
* A sid this instance has no row for publishes nothing. The gateway sits
|
|
574
|
+
* above every config home and its events name only a session id, so one
|
|
575
|
+
* belonging to another config home must not become a row here — the same
|
|
576
|
+
* narrowing the row's own reading of the gateway makes. */
|
|
577
|
+
gatewayMoved(sid: Sid): void {
|
|
578
|
+
const now = Date.now();
|
|
579
|
+
const row = this.#peerRow(sid, now, this.#own());
|
|
580
|
+
if (row === undefined) return;
|
|
581
|
+
const peers = this.#sentPeers.diffRow(row) as PeerElement[];
|
|
582
|
+
if (peers.length > 0) this.deps.publish("peers", { peers });
|
|
583
|
+
}
|
|
584
|
+
|
|
547
585
|
/** Every row `agents` states: the harness's own view, as it stated it. */
|
|
548
586
|
agentRows(own: Own = this.#own()): AgentInfo[] {
|
|
549
587
|
return [...own.rows.values()];
|
package/src/topics/elements.ts
CHANGED
|
Binary file
|
package/src/upstream/gateway.ts
CHANGED
|
@@ -114,6 +114,9 @@ export interface GatewayDeps {
|
|
|
114
114
|
/** The gateway saw something happen for a session, which is an input of the
|
|
115
115
|
* sessions domain (§5.1) rather than of either topic. */
|
|
116
116
|
readonly onActivity?: () => void;
|
|
117
|
+
/** A session already known to be running was seen again: its clock moved,
|
|
118
|
+
* and the row that carries it is what says so. */
|
|
119
|
+
readonly onMoved?: (sid: Sid) => void;
|
|
117
120
|
readonly log?: (msg: string, fields?: Record<string, unknown>) => void;
|
|
118
121
|
/** Replaces the outward read in tests. */
|
|
119
122
|
readonly fetch?: typeof fetch;
|
|
@@ -139,6 +142,7 @@ export class Gateway {
|
|
|
139
142
|
self: deps.self,
|
|
140
143
|
publish: deps.publish,
|
|
141
144
|
...(deps.onActivity === undefined ? {} : { onActivity: deps.onActivity }),
|
|
145
|
+
...(deps.onMoved === undefined ? {} : { onMoved: deps.onMoved }),
|
|
142
146
|
});
|
|
143
147
|
this.status =
|
|
144
148
|
deps.setup.statusUrl === undefined
|
package/src/upstream/requests.ts
CHANGED
|
@@ -14,16 +14,23 @@ export interface LlmRequestsDeps {
|
|
|
14
14
|
/** The one way a value reaches subscribers (§6.1). */
|
|
15
15
|
readonly publish: (topic: string, data: unknown) => void;
|
|
16
16
|
/** An event moved when a session was last seen running inference, which is
|
|
17
|
-
* an input of the sessions domain (§5.1) and not of this topic.
|
|
17
|
+
* an input of the sessions domain (§5.1) and not of this topic. Told when
|
|
18
|
+
* the window opened, which is the moment the classification can change. */
|
|
18
19
|
readonly onActivity?: () => void;
|
|
20
|
+
/** The same session seen again inside a window already open: one attribute
|
|
21
|
+
* of one row moved. Told apart from the above because what it asks for is
|
|
22
|
+
* that row restated rather than the whole domain recomputed. */
|
|
23
|
+
readonly onMoved?: (sid: Sid) => void;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/** Which of a session's gateway facts moved.
|
|
22
27
|
*
|
|
23
|
-
* `live` is the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
28
|
+
* `live` is the moment the classification of §5.1 can change, because the
|
|
29
|
+
* window either opened or closed, and the sessions domain recomputes for it.
|
|
30
|
+
* `clock` is the same session seen again inside a window that was already open
|
|
31
|
+
* — the value of an attribute, not a section anything is in — so what it asks
|
|
32
|
+
* for is that one row restated. Both reach a subscriber; they differ in how
|
|
33
|
+
* much work is done to say so. */
|
|
27
34
|
type GatewayMove = "live" | "clock" | "none";
|
|
28
35
|
|
|
29
36
|
/** Series remembered at once. The prune below already holds this near the
|
|
@@ -77,7 +84,7 @@ export class LlmRequests implements UpstreamResource {
|
|
|
77
84
|
* near-ordered in practice, but a redelivery can put an older one after a
|
|
78
85
|
* newer, and a countdown must not walk backwards. */
|
|
79
86
|
record(info: LlmRequestObservation): void {
|
|
80
|
-
|
|
87
|
+
this.moved(info.sid, this.active(info.sid, info.received_at));
|
|
81
88
|
const key = seriesKey(info.sid, info.prefix);
|
|
82
89
|
const held = this.#series.get(key);
|
|
83
90
|
if (held !== undefined && held.info.received_at >= info.received_at) return;
|
|
@@ -99,7 +106,13 @@ export class LlmRequests implements UpstreamResource {
|
|
|
99
106
|
* the window belongs to the request that opened it — and only says the
|
|
100
107
|
* session was still running inference at that instant. */
|
|
101
108
|
note(sid: Sid, at: Timestamp): void {
|
|
102
|
-
|
|
109
|
+
this.moved(sid, this.active(sid, at));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Tell whoever holds the row what this event moved for that session. */
|
|
113
|
+
private moved(sid: Sid, move: GatewayMove): void {
|
|
114
|
+
if (move === "live") this.deps.onActivity?.();
|
|
115
|
+
else if (move === "clock") this.deps.onMoved?.(sid);
|
|
103
116
|
}
|
|
104
117
|
|
|
105
118
|
/** When the gateway last saw inference for a session (§5.1). Undefined once
|
|
@@ -148,11 +161,10 @@ export class LlmRequests implements UpstreamResource {
|
|
|
148
161
|
|
|
149
162
|
/** Note the session was seen, and say what that moved.
|
|
150
163
|
*
|
|
151
|
-
* A session already inside its window moves its clock and nothing else
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* differs only in an attribute (§5.2). */
|
|
164
|
+
* A session already inside its window moves its clock and nothing else, so
|
|
165
|
+
* the row it lands on is restated on its own: inference is observed several
|
|
166
|
+
* times a second, and recomputing the domain for each would spend the whole
|
|
167
|
+
* of that work on one attribute of one row (§5.2). */
|
|
156
168
|
private active(sid: Sid, at: Timestamp): GatewayMove {
|
|
157
169
|
const held = this.#activeAt.get(sid);
|
|
158
170
|
if (held !== undefined && held >= at) return "none";
|