@cotal-ai/core 0.1.0
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/LICENSE +202 -0
- package/dist/agent-file.d.ts +24 -0
- package/dist/agent-file.d.ts.map +1 -0
- package/dist/agent-file.js +106 -0
- package/dist/agent-file.js.map +1 -0
- package/dist/command.d.ts +15 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +2 -0
- package/dist/command.js.map +1 -0
- package/dist/connector.d.ts +43 -0
- package/dist/connector.d.ts.map +1 -0
- package/dist/connector.js +2 -0
- package/dist/connector.js.map +1 -0
- package/dist/endpoint.d.ts +193 -0
- package/dist/endpoint.d.ts.map +1 -0
- package/dist/endpoint.js +628 -0
- package/dist/endpoint.js.map +1 -0
- package/dist/identity.d.ts +26 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +29 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/link.d.ts +37 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +39 -0
- package/dist/link.js.map +1 -0
- package/dist/provision.d.ts +68 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +204 -0
- package/dist/provision.js.map +1 -0
- package/dist/registry.d.ts +24 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +26 -0
- package/dist/registry.js.map +1 -0
- package/dist/streams.d.ts +47 -0
- package/dist/streams.d.ts.map +1 -0
- package/dist/streams.js +97 -0
- package/dist/streams.js.map +1 -0
- package/dist/subjects.d.ts +83 -0
- package/dist/subjects.d.ts.map +1 -0
- package/dist/subjects.js +186 -0
- package/dist/subjects.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +31 -0
package/dist/endpoint.js
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { connect, credsAuthenticator, nanos, AuthorizationError, PermissionViolationError, UserAuthenticationExpiredError, } from "@nats-io/transport-node";
|
|
4
|
+
import { idFromCreds } from "./identity.js";
|
|
5
|
+
import { createSpaceStreams, dmDurableConfig, taskDurableConfig } from "./streams.js";
|
|
6
|
+
import { jetstream, jetstreamManager, AckPolicy, DeliverPolicy, } from "@nats-io/jetstream";
|
|
7
|
+
import { Kvm } from "@nats-io/kv";
|
|
8
|
+
import { anycastSubject, chatStream, chatDurable, chatSubject, collapseFilterSubjects, controlServiceSubject, dmStream, dmDurable, isConcreteChannel, normalizeMentions, parseSubject, presenceBucket, spacePrefix, spaceWildcard, taskStream, taskDurable, unicastSubject, } from "./subjects.js";
|
|
9
|
+
export const DEFAULT_SERVER = "nats://127.0.0.1:4222";
|
|
10
|
+
/**
|
|
11
|
+
* Events: "message" (CotalMessage), "presence" (PresenceEvent), "roster" (Presence[]), "error" (Error).
|
|
12
|
+
*
|
|
13
|
+
* Callers MUST attach an "error" listener before `start()`: async faults (incl. NATS
|
|
14
|
+
* permission denials, surfaced via `watchStatus`) are emitted as "error", and Node throws
|
|
15
|
+
* synchronously on an unhandled "error" — a missing listener turns any such fault into a
|
|
16
|
+
* process crash instead of a logged denial.
|
|
17
|
+
*/
|
|
18
|
+
export class CotalEndpoint extends EventEmitter {
|
|
19
|
+
card;
|
|
20
|
+
space;
|
|
21
|
+
channels;
|
|
22
|
+
servers;
|
|
23
|
+
token;
|
|
24
|
+
user;
|
|
25
|
+
pass;
|
|
26
|
+
creds;
|
|
27
|
+
tls;
|
|
28
|
+
heartbeatMs;
|
|
29
|
+
ttlMs;
|
|
30
|
+
doRegister;
|
|
31
|
+
doWatch;
|
|
32
|
+
doConsume;
|
|
33
|
+
ackWaitMs;
|
|
34
|
+
inactiveThresholdMs;
|
|
35
|
+
nc;
|
|
36
|
+
js;
|
|
37
|
+
jsm;
|
|
38
|
+
kv;
|
|
39
|
+
subs = [];
|
|
40
|
+
streamMsgs = [];
|
|
41
|
+
heartbeatTimer;
|
|
42
|
+
sweepTimer;
|
|
43
|
+
roster = new Map();
|
|
44
|
+
status = "idle";
|
|
45
|
+
activity;
|
|
46
|
+
stopped = false;
|
|
47
|
+
constructor(opts) {
|
|
48
|
+
super();
|
|
49
|
+
this.space = opts.space;
|
|
50
|
+
// Identity precedence: an explicit card.id, else the creds' identity, else a random
|
|
51
|
+
// uuid. When both an id and creds are given they MUST name the same nkey — otherwise
|
|
52
|
+
// the subject sender token wouldn't match the authenticated user and every publish
|
|
53
|
+
// would be denied (a silent-failure class).
|
|
54
|
+
const credId = opts.creds ? idFromCreds(opts.creds) : undefined;
|
|
55
|
+
if (opts.card.id && credId && opts.card.id !== credId)
|
|
56
|
+
throw new Error(`card.id ${opts.card.id} != creds identity ${credId} — they must be the same nkey`);
|
|
57
|
+
const id = opts.card.id ?? credId ?? randomUUID();
|
|
58
|
+
this.card = { ...opts.card, id };
|
|
59
|
+
this.servers = opts.servers ?? DEFAULT_SERVER;
|
|
60
|
+
this.token = opts.token;
|
|
61
|
+
this.user = opts.user;
|
|
62
|
+
this.pass = opts.pass;
|
|
63
|
+
this.creds = opts.creds;
|
|
64
|
+
this.tls = opts.tls ?? false;
|
|
65
|
+
this.channels = opts.channels ?? ["general"];
|
|
66
|
+
this.heartbeatMs = opts.heartbeatMs ?? 2000;
|
|
67
|
+
this.ttlMs = opts.ttlMs ?? 6000;
|
|
68
|
+
this.doRegister = opts.registerPresence ?? true;
|
|
69
|
+
this.doWatch = opts.watchPresence ?? true;
|
|
70
|
+
this.doConsume = opts.consume ?? true;
|
|
71
|
+
this.ackWaitMs = opts.ackWaitMs ?? 60_000;
|
|
72
|
+
this.inactiveThresholdMs = opts.inactiveThresholdMs ?? 600_000;
|
|
73
|
+
}
|
|
74
|
+
ref() {
|
|
75
|
+
return { id: this.card.id, name: this.card.name, role: this.card.role };
|
|
76
|
+
}
|
|
77
|
+
async start() {
|
|
78
|
+
this.nc = await connect({
|
|
79
|
+
servers: this.servers,
|
|
80
|
+
name: `cotal:${this.card.name}`,
|
|
81
|
+
// Per-identity inbox namespace (the "Private Inbox" pattern). nats.js routes ALL
|
|
82
|
+
// generated inboxes — request replies, JetStream pull delivery, kv.watch ordered-
|
|
83
|
+
// consumer delivery — through this prefix. Paired with sub.allow=[_INBOX_<id>.>]
|
|
84
|
+
// (auth mode) it stops a peer from subscribing the wildcard inbox to sniff others'
|
|
85
|
+
// DM deliveries. Set unconditionally so the prefix can never drift from the ACL.
|
|
86
|
+
inboxPrefix: `_INBOX_${this.card.id}`,
|
|
87
|
+
...authOpts({ token: this.token, user: this.user, pass: this.pass, creds: this.creds, tls: this.tls }),
|
|
88
|
+
});
|
|
89
|
+
this.watchStatus();
|
|
90
|
+
this.js = jetstream(this.nc);
|
|
91
|
+
if (this.doWatch || this.doRegister) {
|
|
92
|
+
const kvm = new Kvm(this.nc);
|
|
93
|
+
// The presence bucket is a JetStream stream. Open mode lazily creates it; auth mode
|
|
94
|
+
// OPENs it (it's pre-created at `cotal up`; KV stream-create is denied to agents).
|
|
95
|
+
this.kv = this.creds
|
|
96
|
+
? await kvm.open(presenceBucket(this.space))
|
|
97
|
+
: await kvm.create(presenceBucket(this.space), { ttl: this.ttlMs });
|
|
98
|
+
}
|
|
99
|
+
if (this.doWatch) {
|
|
100
|
+
await this.startPresenceWatch();
|
|
101
|
+
this.sweepTimer = setInterval(() => this.sweep(), Math.max(500, Math.floor(this.ttlMs / 3)));
|
|
102
|
+
}
|
|
103
|
+
if (this.doRegister) {
|
|
104
|
+
await this.publishPresence();
|
|
105
|
+
this.heartbeatTimer = setInterval(() => {
|
|
106
|
+
this.publishPresence().catch((e) => this.emit("error", e));
|
|
107
|
+
}, this.heartbeatMs);
|
|
108
|
+
}
|
|
109
|
+
if (this.doConsume) {
|
|
110
|
+
this.jsm = await jetstreamManager(this.nc);
|
|
111
|
+
// Open mode: lazily create the streams on the first endpoint. Auth mode: they are
|
|
112
|
+
// pre-created at `cotal up` and STREAM.CREATE is denied to agents, so skip.
|
|
113
|
+
if (!this.creds)
|
|
114
|
+
await this.ensureStreams();
|
|
115
|
+
await this.startConsumers();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async stop() {
|
|
119
|
+
if (this.stopped)
|
|
120
|
+
return;
|
|
121
|
+
this.stopped = true;
|
|
122
|
+
if (this.heartbeatTimer)
|
|
123
|
+
clearInterval(this.heartbeatTimer);
|
|
124
|
+
if (this.sweepTimer)
|
|
125
|
+
clearInterval(this.sweepTimer);
|
|
126
|
+
for (const msgs of this.streamMsgs) {
|
|
127
|
+
try {
|
|
128
|
+
msgs.stop();
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
/* already closed */
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
if (this.doRegister) {
|
|
136
|
+
this.status = "offline";
|
|
137
|
+
await this.publishPresence();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
/* best-effort graceful leave */
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
await this.nc?.drain();
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
/* ignore */
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// ---- messaging -----------------------------------------------------------
|
|
151
|
+
/** Multicast: broadcast to everyone on a channel. */
|
|
152
|
+
async multicast(text, opts) {
|
|
153
|
+
// Publish must target a concrete sub-channel — you can't broadcast to a
|
|
154
|
+
// wildcard. Default to the first concrete channel we're on (channels[0] may
|
|
155
|
+
// itself be a wildcard subscription like `team.>`).
|
|
156
|
+
const channel = opts?.channel ?? this.channels.find(isConcreteChannel) ?? "general";
|
|
157
|
+
if (!isConcreteChannel(channel))
|
|
158
|
+
throw new Error(`cannot publish to wildcard channel "${channel}" — pick a concrete sub-channel`);
|
|
159
|
+
const msg = {
|
|
160
|
+
id: randomUUID(),
|
|
161
|
+
ts: Date.now(),
|
|
162
|
+
space: this.space,
|
|
163
|
+
from: this.ref(),
|
|
164
|
+
channel,
|
|
165
|
+
// Priority/wake hint, not routing — validation (against the roster) is the connector's
|
|
166
|
+
// job; core just canonicalizes and omits the field when empty.
|
|
167
|
+
mentions: normalizeMentions(opts?.mentions),
|
|
168
|
+
parts: opts?.parts ?? [{ kind: "text", text }],
|
|
169
|
+
replyTo: opts?.replyTo,
|
|
170
|
+
contextId: opts?.contextId,
|
|
171
|
+
};
|
|
172
|
+
await this.publishMsg(chatSubject(this.space, this.card.id, channel), msg);
|
|
173
|
+
return msg;
|
|
174
|
+
}
|
|
175
|
+
/** Unicast: direct message to one specific instance. */
|
|
176
|
+
async unicast(instanceId, text, opts) {
|
|
177
|
+
const msg = {
|
|
178
|
+
id: randomUUID(),
|
|
179
|
+
ts: Date.now(),
|
|
180
|
+
space: this.space,
|
|
181
|
+
from: this.ref(),
|
|
182
|
+
to: instanceId,
|
|
183
|
+
parts: opts?.parts ?? [{ kind: "text", text }],
|
|
184
|
+
replyTo: opts?.replyTo,
|
|
185
|
+
contextId: opts?.contextId,
|
|
186
|
+
};
|
|
187
|
+
await this.publishMsg(unicastSubject(this.space, instanceId, this.card.id), msg);
|
|
188
|
+
return msg;
|
|
189
|
+
}
|
|
190
|
+
/** Anycast: deliver to ANY one instance of a service (role) — queue-group load balancing. */
|
|
191
|
+
async anycast(service, text, opts) {
|
|
192
|
+
const msg = {
|
|
193
|
+
id: randomUUID(),
|
|
194
|
+
ts: Date.now(),
|
|
195
|
+
space: this.space,
|
|
196
|
+
from: this.ref(),
|
|
197
|
+
toService: service,
|
|
198
|
+
parts: opts?.parts ?? [{ kind: "text", text }],
|
|
199
|
+
replyTo: opts?.replyTo,
|
|
200
|
+
contextId: opts?.contextId,
|
|
201
|
+
};
|
|
202
|
+
await this.publishMsg(anycastSubject(this.space, service, this.card.id), msg);
|
|
203
|
+
return msg;
|
|
204
|
+
}
|
|
205
|
+
/** Subscribe to a read-only observer feed. Defaults to the whole space; an observer under
|
|
206
|
+
* auth must pass `chatWildcard(space)` since its `sub.allow` only covers chat (DM/anycast
|
|
207
|
+
* stay confidential), otherwise the space-wildcard subscribe is denied and the feed dies. */
|
|
208
|
+
tap(handler, opts) {
|
|
209
|
+
if (!this.nc)
|
|
210
|
+
return;
|
|
211
|
+
const sub = this.nc.subscribe(opts?.subject ?? spaceWildcard(this.space));
|
|
212
|
+
this.subs.push(sub);
|
|
213
|
+
void (async () => {
|
|
214
|
+
for await (const m of sub) {
|
|
215
|
+
let decoded;
|
|
216
|
+
try {
|
|
217
|
+
decoded = m.json();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
decoded = undefined;
|
|
221
|
+
}
|
|
222
|
+
handler(m.subject, decoded);
|
|
223
|
+
}
|
|
224
|
+
})().catch((e) => this.emit("error", e));
|
|
225
|
+
}
|
|
226
|
+
// ---- control plane (request/reply) --------------------------------------
|
|
227
|
+
/** Serve control requests for a service (manager side). */
|
|
228
|
+
serveControl(service, handler) {
|
|
229
|
+
if (!this.nc)
|
|
230
|
+
throw new Error("endpoint not started");
|
|
231
|
+
const sub = this.nc.subscribe(controlServiceSubject(this.space, service, "*"), {
|
|
232
|
+
queue: service,
|
|
233
|
+
});
|
|
234
|
+
this.subs.push(sub);
|
|
235
|
+
void (async () => {
|
|
236
|
+
for await (const m of sub) {
|
|
237
|
+
let reply;
|
|
238
|
+
try {
|
|
239
|
+
const req = m.json();
|
|
240
|
+
// Authenticity guard (fail closed): control is the most privileged surface
|
|
241
|
+
// (start/stop). The sender is encoded in the subject (ctl.<svc>.<sender>), which
|
|
242
|
+
// the server policed who could publish; the payload `from` is advisory and must
|
|
243
|
+
// match. Reject before the handler acts on a request claiming a forged sender.
|
|
244
|
+
const parsed = parseSubject(m.subject);
|
|
245
|
+
if (!parsed || req.from?.id !== parsed.sender) {
|
|
246
|
+
this.emit("error", new Error(`rejected control request on ${m.subject}: from ${req.from?.id ?? "(none)"} ` +
|
|
247
|
+
`does not match subject sender ${parsed?.sender ?? "(unparseable)"}`));
|
|
248
|
+
reply = { ok: false, error: "sender mismatch — request rejected" };
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
reply = await handler(req);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch (e) {
|
|
255
|
+
reply = { ok: false, error: e.message };
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
m.respond(JSON.stringify(reply));
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
/* no reply inbox */
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
})().catch((e) => this.emit("error", e));
|
|
265
|
+
}
|
|
266
|
+
/** Send a control request to a service and await its reply (client side). */
|
|
267
|
+
async requestControl(service, req, timeoutMs = 5000) {
|
|
268
|
+
if (!this.nc)
|
|
269
|
+
throw new Error("endpoint not started");
|
|
270
|
+
const m = await this.nc.request(controlServiceSubject(this.space, service, this.card.id), JSON.stringify({ ...req, from: req.from ?? this.ref() }), { timeout: timeoutMs });
|
|
271
|
+
return m.json();
|
|
272
|
+
}
|
|
273
|
+
// ---- presence ------------------------------------------------------------
|
|
274
|
+
getRoster() {
|
|
275
|
+
return [...this.roster.values()].sort((a, b) => a.card.name.localeCompare(b.card.name));
|
|
276
|
+
}
|
|
277
|
+
async setActivity(activity) {
|
|
278
|
+
this.activity = activity;
|
|
279
|
+
await this.publishPresence();
|
|
280
|
+
}
|
|
281
|
+
async setStatus(status) {
|
|
282
|
+
this.status = status;
|
|
283
|
+
await this.publishPresence();
|
|
284
|
+
}
|
|
285
|
+
// ---- channel discovery ---------------------------------------------------
|
|
286
|
+
/** List channels that have messages in the chat stream, with message counts.
|
|
287
|
+
* Works even on observer endpoints (no consumers needed). */
|
|
288
|
+
async listChannels() {
|
|
289
|
+
if (!this.nc)
|
|
290
|
+
throw new Error("endpoint not started");
|
|
291
|
+
const mgr = await jetstreamManager(this.nc);
|
|
292
|
+
let info;
|
|
293
|
+
try {
|
|
294
|
+
info = await mgr.streams.info(chatStream(this.space), { subjects_filter: ">" });
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
// Subjects now carry the sender (chat.<sender>.<channel>), so collapse across senders:
|
|
300
|
+
// sum each channel's counts regardless of who published.
|
|
301
|
+
const counts = new Map();
|
|
302
|
+
if (info.state.subjects) {
|
|
303
|
+
for (const [subject, count] of Object.entries(info.state.subjects)) {
|
|
304
|
+
const p = parseSubject(subject);
|
|
305
|
+
if (p?.kind === "chat")
|
|
306
|
+
counts.set(p.rest, (counts.get(p.rest) ?? 0) + count);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return [...counts]
|
|
310
|
+
.map(([channel, messages]) => ({ channel, messages }))
|
|
311
|
+
.sort((a, b) => a.channel.localeCompare(b.channel));
|
|
312
|
+
}
|
|
313
|
+
/** Fetch recent messages from a channel's JetStream backlog. */
|
|
314
|
+
async channelHistory(channel, opts) {
|
|
315
|
+
// history from any sender
|
|
316
|
+
return this.streamHistory(chatStream(this.space), chatSubject(this.space, "*", channel), opts?.limit ?? 100);
|
|
317
|
+
}
|
|
318
|
+
/** Fetch recent DMs (any sender→any recipient) from the space's DM backlog. God-view only:
|
|
319
|
+
* a normal agent/observer's ACL denies CONSUMER.CREATE on DM_<space>, so this throws-and-
|
|
320
|
+
* skips for them — only an `admin`-profile cred can read it. */
|
|
321
|
+
async dmHistory(opts) {
|
|
322
|
+
// every inst.<target>.<sender> DM
|
|
323
|
+
return this.streamHistory(dmStream(this.space), unicastSubject(this.space, "*", "*"), opts?.limit ?? 100);
|
|
324
|
+
}
|
|
325
|
+
/** Drain up to `limit` recent messages matching `subject` from a stream's backlog via a
|
|
326
|
+
* throwaway consumer. Fetches exactly the pending count (from consumer info) so it returns
|
|
327
|
+
* the moment the backlog is delivered — a plain `fetch({max_messages: limit})` would instead
|
|
328
|
+
* block for the pull's full expiry (~30s) whenever the backlog is smaller than `limit`. */
|
|
329
|
+
async streamHistory(stream, subject, limit) {
|
|
330
|
+
if (!this.nc)
|
|
331
|
+
throw new Error("endpoint not started");
|
|
332
|
+
const js = jetstream(this.nc);
|
|
333
|
+
const msgs = [];
|
|
334
|
+
try {
|
|
335
|
+
const consumer = await js.consumers.get(stream, { filter_subjects: [subject] });
|
|
336
|
+
const pending = Math.min(limit, (await consumer.info()).num_pending);
|
|
337
|
+
if (pending === 0)
|
|
338
|
+
return msgs;
|
|
339
|
+
const iter = await consumer.fetch({ max_messages: pending });
|
|
340
|
+
for await (const m of iter) {
|
|
341
|
+
try {
|
|
342
|
+
msgs.push(m.json());
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
/* skip undecodable */
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
/* stream missing or consumer create denied (non-admin) */
|
|
351
|
+
}
|
|
352
|
+
return msgs;
|
|
353
|
+
}
|
|
354
|
+
// ---- internals -----------------------------------------------------------
|
|
355
|
+
/**
|
|
356
|
+
* Surface the connection's async status errors on our `error` event. NATS reports
|
|
357
|
+
* publish permission violations *only* here (subscription/request ones too), never on
|
|
358
|
+
* the failing call — so without this an over-tight ACL silently drops the agent's
|
|
359
|
+
* traffic and it just looks "absent". We annotate permission denials explicitly so a
|
|
360
|
+
* denial is never mistaken for absence (which already has a benign cause: MCP reconnect).
|
|
361
|
+
*/
|
|
362
|
+
watchStatus() {
|
|
363
|
+
if (!this.nc)
|
|
364
|
+
return;
|
|
365
|
+
void (async () => {
|
|
366
|
+
for await (const s of this.nc.status()) {
|
|
367
|
+
if (s.type === "error")
|
|
368
|
+
this.emit("error", describeStatusError(s.error));
|
|
369
|
+
}
|
|
370
|
+
})().catch((e) => {
|
|
371
|
+
if (!this.stopped)
|
|
372
|
+
this.emit("error", e);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
async publishMsg(subject, msg) {
|
|
376
|
+
if (!this.js)
|
|
377
|
+
throw new Error("endpoint not started");
|
|
378
|
+
// msgID = message id → free server-side dedup across JetStream redelivery.
|
|
379
|
+
await this.js.publish(subject, JSON.stringify(msg), { msgID: msg.id });
|
|
380
|
+
}
|
|
381
|
+
/** Create the three backing streams for this space (idempotent). Open-mode lazy create;
|
|
382
|
+
* the same definitions are used by `cotal up` at privileged setup. */
|
|
383
|
+
async ensureStreams() {
|
|
384
|
+
if (!this.jsm)
|
|
385
|
+
throw new Error("endpoint not started");
|
|
386
|
+
await createSpaceStreams(this.jsm, this.space);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Privileged: pre-create an agent's DM inbox durable (auth mode), so the agent can BIND
|
|
390
|
+
* it without holding CONSUMER.CREATE on DM_<space>. The creator sets the filter to
|
|
391
|
+
* inst.<targetId>.* — the agent never gets to choose it, which is what stops a peer from
|
|
392
|
+
* creating a durable filtered to someone else's inbox. Idempotent (byte-identical config),
|
|
393
|
+
* safe to call again on manager restart. The caller must be permissive on DM_<space>.
|
|
394
|
+
*/
|
|
395
|
+
async provisionDmInbox(targetId) {
|
|
396
|
+
const jsm = await this.manager();
|
|
397
|
+
await jsm.consumers.add(dmStream(this.space), dmDurableConfig(this.space, targetId));
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Privileged: pre-create a role's shared TASK work-queue durable (auth mode), so agents
|
|
401
|
+
* of that role can BIND it without holding CONSUMER.CREATE on TASK_<space>. The creator
|
|
402
|
+
* sets the filter to svc.<role>.* — agents never choose it, which stops cross-role drain.
|
|
403
|
+
* Idempotent per role. The caller must be permissive on TASK_<space>.
|
|
404
|
+
*/
|
|
405
|
+
async provisionTaskQueue(role) {
|
|
406
|
+
const jsm = await this.manager();
|
|
407
|
+
await jsm.consumers.add(taskStream(this.space), taskDurableConfig(this.space, role));
|
|
408
|
+
}
|
|
409
|
+
/** Lazily obtain a JetStream manager — so a non-consuming endpoint (e.g. the supervisor,
|
|
410
|
+
* consume:false) can still pre-create others' durables. */
|
|
411
|
+
async manager() {
|
|
412
|
+
if (!this.nc)
|
|
413
|
+
throw new Error("endpoint not started");
|
|
414
|
+
this.jsm ??= await jetstreamManager(this.nc);
|
|
415
|
+
return this.jsm;
|
|
416
|
+
}
|
|
417
|
+
/** Bind this endpoint's durable consumers: DM inbox, chat, and (if a role) the task queue. */
|
|
418
|
+
async startConsumers() {
|
|
419
|
+
if (!this.jsm)
|
|
420
|
+
throw new Error("endpoint not started");
|
|
421
|
+
const id = this.card.id;
|
|
422
|
+
const ack_wait = nanos(this.ackWaitMs);
|
|
423
|
+
const inactive_threshold = nanos(this.inactiveThresholdMs);
|
|
424
|
+
// Unicast: this instance's private DM inbox. Open mode self-creates; auth mode BINDS a
|
|
425
|
+
// durable the provisioner pre-created (agents are denied CONSUMER.CREATE on DM_<space>,
|
|
426
|
+
// since the create-time filter_subject is the attack surface — see provisionDmInbox).
|
|
427
|
+
if (!this.creds) {
|
|
428
|
+
await this.jsm.consumers.add(dmStream(this.space), dmDurableConfig(this.space, id, {
|
|
429
|
+
ackWaitMs: this.ackWaitMs,
|
|
430
|
+
inactiveThresholdMs: this.inactiveThresholdMs,
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
await this.pump(dmStream(this.space), dmDurable(id));
|
|
434
|
+
// Multicast: every message on our channels, at our own pace (replays the retained window).
|
|
435
|
+
if (this.channels.length) {
|
|
436
|
+
await this.jsm.consumers.add(chatStream(this.space), {
|
|
437
|
+
durable_name: chatDurable(id),
|
|
438
|
+
// Wildcard channels (team.>) may subsume concrete ones (team.backend);
|
|
439
|
+
// JetStream rejects overlapping filter_subjects, so collapse first.
|
|
440
|
+
filter_subjects: collapseFilterSubjects(this.channels.map((ch) => chatSubject(this.space, "*", ch))),
|
|
441
|
+
ack_policy: AckPolicy.Explicit,
|
|
442
|
+
ack_wait,
|
|
443
|
+
deliver_policy: DeliverPolicy.All,
|
|
444
|
+
inactive_threshold,
|
|
445
|
+
});
|
|
446
|
+
await this.pump(chatStream(this.space), chatDurable(id));
|
|
447
|
+
}
|
|
448
|
+
// Anycast: a shared work-queue consumer for our role — one instance grabs each task.
|
|
449
|
+
// Open mode self-creates; auth mode BINDS the provisioner-pre-created svc_<role>
|
|
450
|
+
// durable (agents are denied CONSUMER.CREATE on TASK_<space>, since the create-time
|
|
451
|
+
// filter is the cross-role-drain attack surface — see provisionTaskQueue).
|
|
452
|
+
if (this.card.role) {
|
|
453
|
+
if (!this.creds) {
|
|
454
|
+
await this.jsm.consumers.add(taskStream(this.space), taskDurableConfig(this.space, this.card.role, { ackWaitMs: this.ackWaitMs }));
|
|
455
|
+
}
|
|
456
|
+
await this.pump(taskStream(this.space), taskDurable(this.card.role));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/** Drive one consumer: decode, drop our own echo, and hand each message to listeners with ack control. */
|
|
460
|
+
async pump(stream, durable) {
|
|
461
|
+
if (!this.js)
|
|
462
|
+
throw new Error("endpoint not started");
|
|
463
|
+
const consumer = await this.js.consumers.get(stream, durable);
|
|
464
|
+
const msgs = await consumer.consume();
|
|
465
|
+
this.streamMsgs.push(msgs);
|
|
466
|
+
void (async () => {
|
|
467
|
+
for await (const m of msgs) {
|
|
468
|
+
let msg;
|
|
469
|
+
try {
|
|
470
|
+
msg = m.json();
|
|
471
|
+
}
|
|
472
|
+
catch (e) {
|
|
473
|
+
m.term(); // undecodable — never redeliver
|
|
474
|
+
this.emit("error", e);
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
// Authenticity guard (fail closed): the sender is encoded in the subject, which the
|
|
478
|
+
// server policed who could publish. The payload `from` is advisory — it must match,
|
|
479
|
+
// and a missing `from` or an unparseable subject on a delivery is itself an anomaly.
|
|
480
|
+
// Reject (term — a spoof is permanently invalid, never redeliver) BEFORE any handler.
|
|
481
|
+
const parsed = parseSubject(m.subject);
|
|
482
|
+
if (!parsed || !msg.from || msg.from.id !== parsed.sender) {
|
|
483
|
+
m.term();
|
|
484
|
+
this.emit("error", new Error(`dropped message on ${m.subject}: payload from ${msg.from?.id ?? "(none)"} ` +
|
|
485
|
+
`does not match subject sender ${parsed?.sender ?? "(unparseable)"}`));
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (msg.from.id === this.card.id) {
|
|
489
|
+
m.ack(); // our own echo — advance past it
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
const delivery = { ack: () => m.ack(), nak: () => m.nak() };
|
|
493
|
+
this.emit("message", msg, delivery);
|
|
494
|
+
}
|
|
495
|
+
})().catch((e) => {
|
|
496
|
+
if (!this.stopped)
|
|
497
|
+
this.emit("error", e);
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
async publishPresence() {
|
|
501
|
+
if (!this.kv)
|
|
502
|
+
return;
|
|
503
|
+
const p = {
|
|
504
|
+
card: this.card,
|
|
505
|
+
status: this.status,
|
|
506
|
+
activity: this.activity,
|
|
507
|
+
ts: Date.now(),
|
|
508
|
+
};
|
|
509
|
+
await this.kv.put(this.card.id, JSON.stringify(p));
|
|
510
|
+
}
|
|
511
|
+
async startPresenceWatch() {
|
|
512
|
+
if (!this.kv)
|
|
513
|
+
return;
|
|
514
|
+
const iter = await this.kv.watch();
|
|
515
|
+
void (async () => {
|
|
516
|
+
for await (const e of iter)
|
|
517
|
+
this.handleKvEntry(e);
|
|
518
|
+
})().catch((e) => this.emit("error", e));
|
|
519
|
+
}
|
|
520
|
+
handleKvEntry(e) {
|
|
521
|
+
if (e.operation === "DEL" || e.operation === "PURGE") {
|
|
522
|
+
this.markOffline(e.key);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
let p;
|
|
526
|
+
try {
|
|
527
|
+
p = e.json();
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
this.applyPresence(e.key, p);
|
|
533
|
+
}
|
|
534
|
+
applyPresence(id, raw) {
|
|
535
|
+
const prev = this.roster.get(id);
|
|
536
|
+
const stale = Date.now() - raw.ts > this.ttlMs;
|
|
537
|
+
const p = stale && raw.status !== "offline" ? { ...raw, status: "offline" } : raw;
|
|
538
|
+
// First time we hear about an already-offline peer (stale snapshot): record quietly.
|
|
539
|
+
if (!prev && p.status === "offline") {
|
|
540
|
+
this.roster.set(id, p);
|
|
541
|
+
this.emit("roster", this.getRoster());
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
// Heartbeat refresh with no real change: bump liveness quietly and don't
|
|
545
|
+
// emit — otherwise the periodic keep-alive looks like a stream of "updates".
|
|
546
|
+
if (prev &&
|
|
547
|
+
prev.status !== "offline" &&
|
|
548
|
+
p.status !== "offline" &&
|
|
549
|
+
prev.status === p.status &&
|
|
550
|
+
prev.activity === p.activity) {
|
|
551
|
+
this.roster.set(id, p);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
this.roster.set(id, p);
|
|
555
|
+
const type = p.status === "offline"
|
|
556
|
+
? "offline"
|
|
557
|
+
: !prev || prev.status === "offline"
|
|
558
|
+
? "join"
|
|
559
|
+
: "update";
|
|
560
|
+
this.emit("presence", { type, presence: p });
|
|
561
|
+
this.emit("roster", this.getRoster());
|
|
562
|
+
}
|
|
563
|
+
/** Mark a known peer offline (on KV delete/purge), keeping it in the roster. */
|
|
564
|
+
markOffline(id) {
|
|
565
|
+
const prev = this.roster.get(id);
|
|
566
|
+
if (!prev || prev.status === "offline")
|
|
567
|
+
return;
|
|
568
|
+
const offline = { ...prev, status: "offline" };
|
|
569
|
+
this.roster.set(id, offline);
|
|
570
|
+
this.emit("presence", { type: "offline", presence: offline });
|
|
571
|
+
this.emit("roster", this.getRoster());
|
|
572
|
+
}
|
|
573
|
+
sweep() {
|
|
574
|
+
const now = Date.now();
|
|
575
|
+
let changed = false;
|
|
576
|
+
for (const [, p] of this.roster) {
|
|
577
|
+
if (p.status !== "offline" && now - p.ts > this.ttlMs) {
|
|
578
|
+
p.status = "offline";
|
|
579
|
+
this.emit("presence", { type: "offline", presence: p });
|
|
580
|
+
changed = true;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (changed)
|
|
584
|
+
this.emit("roster", this.getRoster());
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
function authOpts(a) {
|
|
588
|
+
const tls = a.tls ? {} : undefined;
|
|
589
|
+
// creds (JWT/nkey) are mutually exclusive with token/user/pass — reject rather than
|
|
590
|
+
// silently pick one, so a misconfigured caller fails loud.
|
|
591
|
+
if (a.creds) {
|
|
592
|
+
if (a.token || a.user || a.pass)
|
|
593
|
+
throw new Error("creds are mutually exclusive with token/user/pass auth");
|
|
594
|
+
return { authenticator: credsAuthenticator(new TextEncoder().encode(a.creds)), tls };
|
|
595
|
+
}
|
|
596
|
+
return { token: a.token, user: a.user, pass: a.pass, tls };
|
|
597
|
+
}
|
|
598
|
+
/** Turn a raw async-status error into one whose message says *why* — a permission
|
|
599
|
+
* violation looks like absence unless it's named as a denial. */
|
|
600
|
+
function describeStatusError(err) {
|
|
601
|
+
if (err instanceof PermissionViolationError) {
|
|
602
|
+
return new Error(`NATS permission denied: cannot ${err.operation} "${err.subject}" — check this ` +
|
|
603
|
+
`endpoint's ACLs (a denied peer looks "absent" rather than blocked)`, { cause: err });
|
|
604
|
+
}
|
|
605
|
+
return err;
|
|
606
|
+
}
|
|
607
|
+
/** Whether a NATS server is *running* at `servers`. True on a successful connect AND on an
|
|
608
|
+
* auth rejection — an auth error means a server is there, just refusing these creds (so the
|
|
609
|
+
* caller should surface the real auth failure, not a misleading "server down", and `up`
|
|
610
|
+
* must not try to start a duplicate on the bound port). Only a genuine connection failure
|
|
611
|
+
* (refused / timeout / no server) returns false. */
|
|
612
|
+
export async function isReachable(servers = DEFAULT_SERVER, opts = {}) {
|
|
613
|
+
try {
|
|
614
|
+
const nc = await connect({
|
|
615
|
+
servers,
|
|
616
|
+
timeout: opts.timeoutMs ?? 1000,
|
|
617
|
+
reconnect: false,
|
|
618
|
+
maxReconnectAttempts: 0,
|
|
619
|
+
...authOpts(opts),
|
|
620
|
+
});
|
|
621
|
+
await nc.close();
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
624
|
+
catch (e) {
|
|
625
|
+
return e instanceof AuthorizationError || e instanceof UserAuthenticationExpiredError;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
//# sourceMappingURL=endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../src/endpoint.ts"],"names":[],"mappings":"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"}
|