pi-radar 0.3.0 → 0.4.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/README.md +4 -2
- package/dist/extension/baseline.js +227 -402
- package/dist/extension/radar-client.js +53 -13
- package/dist/extension/radar-communication.js +5 -5
- package/dist/extension/radar-execution.js +168 -383
- package/dist/extension/radar-launch.js +13 -13
- package/dist/extension/radar-publication.js +160 -299
- package/dist/index.js +239 -414
- package/extension/generated-contracts.ts +1249 -13
- package/extension/radar-client.ts +92 -29
- package/extension/radar-communication.ts +5 -5
- package/extension/radar-execution.ts +11 -58
- package/extension/radar-launch.ts +21 -21
- package/extension/radar-publication.ts +209 -412
- package/package.json +3 -4
- package/schema/public/v1/handoff-publish-params.deserialize.schema.json +2 -2
- package/schema/public/v1/handoff-publish-params.serialize.schema.json +2 -2
- package/schema/public/v1/handoff-receipt.deserialize.schema.json +4 -4
- package/schema/public/v1/handoff-receipt.serialize.schema.json +4 -4
- package/schema/public/v1/handoff.deserialize.schema.json +4 -4
- package/schema/public/v1/handoff.serialize.schema.json +4 -4
- package/schema/public/v1/observation-get-params.deserialize.schema.json +46 -0
- package/schema/public/v1/observation-get-params.serialize.schema.json +52 -0
- package/schema/public/v1/observation-get-response.deserialize.schema.json +2731 -0
- package/schema/public/v1/observation-get-response.serialize.schema.json +2862 -0
- package/schema/public/v1/observation-snapshot.deserialize.schema.json +2616 -0
- package/schema/public/v1/observation-snapshot.serialize.schema.json +2741 -0
- package/schema/public/v1/presence-answer.deserialize.schema.json +40 -0
- package/schema/public/v1/presence-answer.serialize.schema.json +40 -0
- package/schema/public/v1/presence-release.deserialize.schema.json +51 -0
- package/schema/public/v1/presence-release.serialize.schema.json +52 -0
- package/schema/public/v1/presence-report.deserialize.schema.json +149 -0
- package/schema/public/v1/presence-report.serialize.schema.json +157 -0
- package/extension/radar-session-marker.ts +0 -146
- package/schema/public/v1/launch-identity-marker.deserialize.schema.json +0 -32
- package/schema/public/v1/launch-identity-marker.serialize.schema.json +0 -32
package/dist/index.js
CHANGED
|
@@ -144,6 +144,25 @@ function recordAt(value, field) {
|
|
|
144
144
|
function isUuid(value) {
|
|
145
145
|
return typeof value === "string" && UUID.test(value);
|
|
146
146
|
}
|
|
147
|
+
function decodePresenceAnswer(value) {
|
|
148
|
+
const registrationId = recordAt(value, "registration_id");
|
|
149
|
+
const claimId = recordAt(value, "claim_id");
|
|
150
|
+
const standing = recordAt(value, "standing");
|
|
151
|
+
const subjectId = recordAt(value, "subject_id");
|
|
152
|
+
if (!isUuid(registrationId) || !isUuid(claimId) || !["pending", "granted", "duplicate", "released"].includes(String(standing)) || subjectId !== void 0 && !isUuid(subjectId) || standing === "granted" && !isUuid(subjectId))
|
|
153
|
+
return protocol("presence reply carries no valid claim standing");
|
|
154
|
+
return { ok: true, value };
|
|
155
|
+
}
|
|
156
|
+
function managementAt(value) {
|
|
157
|
+
const field = recordAt(value, "management");
|
|
158
|
+
const state = stringAt(field, "state");
|
|
159
|
+
if (state === "managed") {
|
|
160
|
+
const subjectId = stringAt(field, "subject_id");
|
|
161
|
+
return subjectId === void 0 ? void 0 : { state, subject_id: subjectId };
|
|
162
|
+
}
|
|
163
|
+
if (state === "duplicate" || state === "pending" || state === "unmanaged") return { state };
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
147
166
|
function stringAt(value, field) {
|
|
148
167
|
if (typeof value !== "object" || value === null) return void 0;
|
|
149
168
|
const found = value[field];
|
|
@@ -164,7 +183,7 @@ function handoffAt(value) {
|
|
|
164
183
|
const content = stringAt(value, "content");
|
|
165
184
|
const published = numberAt(value, "published_at_unix_ms");
|
|
166
185
|
const correlation = typeof value === "object" && value !== null ? value.correlation_id : void 0;
|
|
167
|
-
if (version !== 1 || !isUuid(id) || !isUuid(stringAt(sender, "
|
|
186
|
+
if (version !== 1 || !isUuid(id) || !isUuid(stringAt(sender, "registration_id")) || !isUuid(stringAt(sender, "session_id")) || !isUuid(stringAt(sender, "subject_id")) || !isUuid(stringAt(sender, "execution_id")) || !Number.isSafeInteger(senderGeneration) || (senderGeneration ?? 0) < 1 || !isUuid(target) || summary === void 0 || content === void 0 || published === void 0 || !Number.isSafeInteger(published) || published < 0 || correlation !== void 0 && correlation !== null && (typeof correlation !== "string" || correlation.length === 0 || Buffer.byteLength(correlation, "utf8") > 256 || new RegExp("\\p{Cc}", "u").test(correlation))) return void 0;
|
|
168
187
|
return value;
|
|
169
188
|
}
|
|
170
189
|
function handoffReceiptAt(value) {
|
|
@@ -173,7 +192,7 @@ function handoffReceiptAt(value) {
|
|
|
173
192
|
const recipient = recordAt(value, "recipient");
|
|
174
193
|
const generation = numberAt(recipient, "execution_generation");
|
|
175
194
|
const received = numberAt(value, "received_at_unix_ms");
|
|
176
|
-
if (version !== 1 || !isUuid(handoffId) || !isUuid(stringAt(recipient, "
|
|
195
|
+
if (version !== 1 || !isUuid(handoffId) || !isUuid(stringAt(recipient, "registration_id")) || !isUuid(stringAt(recipient, "session_id")) || !isUuid(stringAt(recipient, "subject_id")) || !isUuid(stringAt(recipient, "execution_id")) || !Number.isSafeInteger(generation) || (generation ?? 0) < 1 || received === void 0 || !Number.isSafeInteger(received) || received < 0) return void 0;
|
|
177
196
|
return value;
|
|
178
197
|
}
|
|
179
198
|
function writerBinding(value) {
|
|
@@ -331,7 +350,7 @@ function spawnEdge(value) {
|
|
|
331
350
|
const bound = recordAt(value, "bound");
|
|
332
351
|
const source = stringAt(bound, "source");
|
|
333
352
|
const incarnation = stringAt(bound, "incarnation");
|
|
334
|
-
const agentId = stringAt(bound, "
|
|
353
|
+
const agentId = stringAt(bound, "registration_id");
|
|
335
354
|
const exit = exitAt(recordAt(value, "exit_observation"));
|
|
336
355
|
return {
|
|
337
356
|
ok: true,
|
|
@@ -345,7 +364,7 @@ function spawnEdge(value) {
|
|
|
345
364
|
bound: {
|
|
346
365
|
source,
|
|
347
366
|
incarnation,
|
|
348
|
-
...isUuid(agentId) ? {
|
|
367
|
+
...isUuid(agentId) ? { registration_id: agentId } : {}
|
|
349
368
|
}
|
|
350
369
|
} : {},
|
|
351
370
|
...exit !== void 0 ? { exit_observation: exit } : {}
|
|
@@ -743,6 +762,22 @@ function createRadarClient(options = {}) {
|
|
|
743
762
|
return {
|
|
744
763
|
socketPath,
|
|
745
764
|
ping,
|
|
765
|
+
async presence(request) {
|
|
766
|
+
return withRegistry(async () => {
|
|
767
|
+
const answer = await call("agent.presence", { ...request });
|
|
768
|
+
if (!answer.ok) return answer;
|
|
769
|
+
return decodePresenceAnswer(answer.value);
|
|
770
|
+
});
|
|
771
|
+
},
|
|
772
|
+
async releasePresence(request) {
|
|
773
|
+
return withRegistry(async () => {
|
|
774
|
+
const answer = await call("agent.release", { ...request });
|
|
775
|
+
if (!answer.ok) return answer;
|
|
776
|
+
const decoded = decodePresenceAnswer(answer.value);
|
|
777
|
+
if (!decoded.ok) return decoded;
|
|
778
|
+
return decoded.value.standing === "released" ? decoded : protocol("release reply did not confirm the claim release");
|
|
779
|
+
});
|
|
780
|
+
},
|
|
746
781
|
async register(registration) {
|
|
747
782
|
return withRegistry(async () => {
|
|
748
783
|
const answer = await call("agent.register", {
|
|
@@ -758,15 +793,15 @@ function createRadarClient(options = {}) {
|
|
|
758
793
|
});
|
|
759
794
|
if (answer.ok === false) return answer;
|
|
760
795
|
const record = answer.value.registration;
|
|
761
|
-
const agentId = stringAt(record, "
|
|
762
|
-
if (!isUuid(agentId)) return protocol("registration reply carries no
|
|
763
|
-
return { ok: true, value: {
|
|
796
|
+
const agentId = stringAt(record, "registration_id");
|
|
797
|
+
if (!isUuid(agentId)) return protocol("registration reply carries no registration_id");
|
|
798
|
+
return { ok: true, value: { registration_id: agentId } };
|
|
764
799
|
});
|
|
765
800
|
},
|
|
766
801
|
async acquire(request) {
|
|
767
802
|
return withRegistryChannel(request.channel, async () => {
|
|
768
803
|
const answer = await call("agent.acquire", {
|
|
769
|
-
|
|
804
|
+
registration_id: request.registration_id,
|
|
770
805
|
channel: request.channel,
|
|
771
806
|
publisher: request.publisher,
|
|
772
807
|
...request.replace !== void 0 ? { replace: request.replace } : {}
|
|
@@ -795,7 +830,7 @@ function createRadarClient(options = {}) {
|
|
|
795
830
|
}
|
|
796
831
|
return withRegistryChannel(request.channel, async () => {
|
|
797
832
|
const answer = await call("agent.publish", {
|
|
798
|
-
|
|
833
|
+
registration_id: request.registration_id,
|
|
799
834
|
channel: request.channel,
|
|
800
835
|
writer_handle: request.writer_handle,
|
|
801
836
|
sequence: request.sequence,
|
|
@@ -814,7 +849,7 @@ function createRadarClient(options = {}) {
|
|
|
814
849
|
async context(request) {
|
|
815
850
|
return withRegistry(async () => {
|
|
816
851
|
const answer = await call("agent.context", {
|
|
817
|
-
|
|
852
|
+
registration_id: request.registration_id,
|
|
818
853
|
publisher: request.publisher,
|
|
819
854
|
...request.writer_handle !== void 0 ? { writer_handle: request.writer_handle } : {},
|
|
820
855
|
...request.replace !== void 0 ? { replace: request.replace } : {},
|
|
@@ -830,9 +865,14 @@ function createRadarClient(options = {}) {
|
|
|
830
865
|
if (writer === void 0)
|
|
831
866
|
return protocol("context reply carries no writer binding");
|
|
832
867
|
const warning = stringAt(answer.value, "warning");
|
|
868
|
+
const management = managementAt(answer.value);
|
|
833
869
|
return {
|
|
834
870
|
ok: true,
|
|
835
|
-
value: {
|
|
871
|
+
value: {
|
|
872
|
+
writer,
|
|
873
|
+
...warning !== void 0 ? { warning } : {},
|
|
874
|
+
...management !== void 0 ? { management } : {}
|
|
875
|
+
}
|
|
836
876
|
};
|
|
837
877
|
});
|
|
838
878
|
},
|
|
@@ -909,7 +949,7 @@ function createRadarClient(options = {}) {
|
|
|
909
949
|
message: "agent.get requires a canonical agent UUID"
|
|
910
950
|
};
|
|
911
951
|
return withRegistry(async () => {
|
|
912
|
-
const answer = await call("agent.get", {
|
|
952
|
+
const answer = await call("agent.get", { registration_id: agentId });
|
|
913
953
|
if (answer.ok === false) return answer;
|
|
914
954
|
return agentProcessAt(recordAt(answer.value, "agent"));
|
|
915
955
|
});
|
|
@@ -963,7 +1003,7 @@ function createRadarClient(options = {}) {
|
|
|
963
1003
|
async communicationPublish(request) {
|
|
964
1004
|
return withContract(RADAR_COMMUNICATION_CONTRACT, async () => {
|
|
965
1005
|
const answer = await call("communication.publish", {
|
|
966
|
-
|
|
1006
|
+
sender_registration_id: request.sender_registration_id,
|
|
967
1007
|
recipient_subject_id: request.recipient_subject_id,
|
|
968
1008
|
...request.correlation_id !== void 0 ? { correlation_id: request.correlation_id } : {},
|
|
969
1009
|
summary: request.summary,
|
|
@@ -1238,7 +1278,7 @@ __export(radar_communication_exports, {
|
|
|
1238
1278
|
function createRadarHandoffPort(client, publication, parentSubjectId = () => process.env.PI_RADAR_MANAGED_PARENT_SUBJECT_ID) {
|
|
1239
1279
|
async function agentId() {
|
|
1240
1280
|
const subject = await publication.subject();
|
|
1241
|
-
return subject === void 0 ? { ok: false, code: "absent", message: "this process has no current Radar registration" } : { ok: true, value: subject.
|
|
1281
|
+
return subject === void 0 ? { ok: false, code: "absent", message: "this process has no current Radar registration" } : { ok: true, value: subject.registration_id };
|
|
1242
1282
|
}
|
|
1243
1283
|
return {
|
|
1244
1284
|
async publish(request) {
|
|
@@ -1249,24 +1289,24 @@ function createRadarHandoffPort(client, publication, parentSubjectId = () => pro
|
|
|
1249
1289
|
return { ok: false, code: "absent", message: "this managed execution has no Radar parent subject" };
|
|
1250
1290
|
return client.communicationPublish({
|
|
1251
1291
|
...request,
|
|
1252
|
-
|
|
1292
|
+
sender_registration_id: identity.value,
|
|
1253
1293
|
recipient_subject_id: parent
|
|
1254
1294
|
});
|
|
1255
1295
|
},
|
|
1256
1296
|
async inbox() {
|
|
1257
1297
|
const identity = await agentId();
|
|
1258
1298
|
if (identity.ok === false) return identity;
|
|
1259
|
-
return client.communicationInbox({
|
|
1299
|
+
return client.communicationInbox({ registration_id: identity.value });
|
|
1260
1300
|
},
|
|
1261
1301
|
async get(handoff_id) {
|
|
1262
1302
|
const identity = await agentId();
|
|
1263
1303
|
if (identity.ok === false) return identity;
|
|
1264
|
-
return client.communicationGet({
|
|
1304
|
+
return client.communicationGet({ registration_id: identity.value, handoff_id });
|
|
1265
1305
|
},
|
|
1266
1306
|
async ack(handoff_id) {
|
|
1267
1307
|
const identity = await agentId();
|
|
1268
1308
|
if (identity.ok === false) return identity;
|
|
1269
|
-
return client.communicationAck({
|
|
1309
|
+
return client.communicationAck({ registration_id: identity.value, handoff_id });
|
|
1270
1310
|
}
|
|
1271
1311
|
};
|
|
1272
1312
|
}
|
|
@@ -1309,77 +1349,7 @@ import {
|
|
|
1309
1349
|
writeSync
|
|
1310
1350
|
} from "node:fs";
|
|
1311
1351
|
import { dirname as dirname2, join as join2, parse, resolve, sep } from "node:path";
|
|
1312
|
-
|
|
1313
|
-
// extension/radar-session-marker.ts
|
|
1314
|
-
var RADAR_LAUNCH_MARKER_TYPE = "pi-radar.launch-identity";
|
|
1315
|
-
var RADAR_LAUNCH_MARKER_VERSION = 1;
|
|
1316
|
-
var RADAR_MAX_EXECUTION_GENERATION = 4294967295;
|
|
1317
|
-
var RADAR_MANAGED_SUBJECT_ENV = "PI_RADAR_MANAGED_SUBJECT_ID";
|
|
1318
|
-
var RADAR_MANAGED_LAUNCH_ENV = "PI_RADAR_MANAGED_LAUNCH_ID";
|
|
1319
|
-
var RADAR_MANAGED_GENERATION_ENV = "PI_RADAR_MANAGED_EXECUTION_GENERATION";
|
|
1320
|
-
var UUID2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
1321
|
-
function decodeRadarLaunchMarker(value) {
|
|
1322
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
1323
|
-
const record = value;
|
|
1324
|
-
if (Object.keys(record).sort().join(",") !== "execution_generation,launch_id,subject_id,version") {
|
|
1325
|
-
return void 0;
|
|
1326
|
-
}
|
|
1327
|
-
if (record.version !== RADAR_LAUNCH_MARKER_VERSION || typeof record.subject_id !== "string" || !UUID2.test(record.subject_id) || typeof record.launch_id !== "string" || !UUID2.test(record.launch_id) || !Number.isSafeInteger(record.execution_generation) || record.execution_generation < 1 || record.execution_generation > RADAR_MAX_EXECUTION_GENERATION) {
|
|
1328
|
-
return void 0;
|
|
1329
|
-
}
|
|
1330
|
-
return {
|
|
1331
|
-
version: RADAR_LAUNCH_MARKER_VERSION,
|
|
1332
|
-
subject_id: record.subject_id,
|
|
1333
|
-
launch_id: record.launch_id,
|
|
1334
|
-
execution_generation: record.execution_generation
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
|
-
function appendRadarLaunchMarker(appendEntry, marker) {
|
|
1338
|
-
const validated = decodeRadarLaunchMarker(marker);
|
|
1339
|
-
if (!validated) throw new Error("invalid Radar launch identity marker");
|
|
1340
|
-
appendEntry(RADAR_LAUNCH_MARKER_TYPE, validated);
|
|
1341
|
-
}
|
|
1342
|
-
function latestRadarLaunchMarker(branch) {
|
|
1343
|
-
let latest;
|
|
1344
|
-
for (const entry of branch) {
|
|
1345
|
-
if (entry.type === "custom" && entry.customType === RADAR_LAUNCH_MARKER_TYPE) {
|
|
1346
|
-
latest = entry;
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
if (!latest) return { status: "absent" };
|
|
1350
|
-
const marker = decodeRadarLaunchMarker(latest.data);
|
|
1351
|
-
return marker ? { status: "valid", marker } : { status: "invalid" };
|
|
1352
|
-
}
|
|
1353
|
-
function radarLaunchMarkerFromEnvironment(env = process.env) {
|
|
1354
|
-
const rawGeneration = env[RADAR_MANAGED_GENERATION_ENV];
|
|
1355
|
-
if (env[RADAR_MANAGED_SUBJECT_ENV] === void 0 || env[RADAR_MANAGED_LAUNCH_ENV] === void 0 || rawGeneration === void 0 || !/^[1-9][0-9]*$/.test(rawGeneration)) {
|
|
1356
|
-
return void 0;
|
|
1357
|
-
}
|
|
1358
|
-
return decodeRadarLaunchMarker({
|
|
1359
|
-
version: RADAR_LAUNCH_MARKER_VERSION,
|
|
1360
|
-
subject_id: env[RADAR_MANAGED_SUBJECT_ENV],
|
|
1361
|
-
launch_id: env[RADAR_MANAGED_LAUNCH_ENV],
|
|
1362
|
-
execution_generation: Number(rawGeneration)
|
|
1363
|
-
});
|
|
1364
|
-
}
|
|
1365
|
-
function activeRadarLaunchMarker(host) {
|
|
1366
|
-
if (!host.sessionManager) return { status: "absent" };
|
|
1367
|
-
return latestRadarLaunchMarker(host.sessionManager.getBranch());
|
|
1368
|
-
}
|
|
1369
|
-
function persistRadarLaunchMarker(host, env = process.env) {
|
|
1370
|
-
const marker = radarLaunchMarkerFromEnvironment(env);
|
|
1371
|
-
if (!marker) return "absent";
|
|
1372
|
-
if (!host.appendEntry || !host.sessionManager) return "unsupported";
|
|
1373
|
-
const current = latestRadarLaunchMarker(host.sessionManager.getBranch());
|
|
1374
|
-
if (current.status === "valid" && sameMarker(current.marker, marker)) return "unchanged";
|
|
1375
|
-
appendRadarLaunchMarker(host.appendEntry, marker);
|
|
1376
|
-
return "written";
|
|
1377
|
-
}
|
|
1378
|
-
function sameMarker(a, b) {
|
|
1379
|
-
return a.version === b.version && a.subject_id === b.subject_id && a.launch_id === b.launch_id && a.execution_generation === b.execution_generation;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// extension/radar-publication.ts
|
|
1352
|
+
var DUPLICATE_SESSION_DIAGNOSTIC = "Radar rejected this session claim as a duplicate; reload or resume the session before retrying";
|
|
1383
1353
|
var RADAR_PUBLICATION_VERSION = 1;
|
|
1384
1354
|
var RADAR_LEASE_MS = 3e4;
|
|
1385
1355
|
var RADAR_HEARTBEAT_MS = 15e3;
|
|
@@ -1404,7 +1374,7 @@ function readProcessBirth() {
|
|
|
1404
1374
|
return void 0;
|
|
1405
1375
|
}
|
|
1406
1376
|
}
|
|
1407
|
-
var RECORD_NAME = /^(?:subjects|channels|context|bindings)\/[a-z0-9-]{1,64}\.json$/;
|
|
1377
|
+
var RECORD_NAME = /^(?:registrations|presence|subjects|channels|context|bindings)\/[a-z0-9-]{1,64}\.json$/;
|
|
1408
1378
|
var MAX_RECORD_BYTES = 64 * 1024;
|
|
1409
1379
|
var PRIVATE_MODE = 448;
|
|
1410
1380
|
var RECORD_MODE = 384;
|
|
@@ -1689,39 +1659,6 @@ function pendingAt(value, keys = PENDING_KEYS, codec = executionCodec) {
|
|
|
1689
1659
|
return void 0;
|
|
1690
1660
|
return { sequence, snapshot, lease_ms: lease, observed_at: observed };
|
|
1691
1661
|
}
|
|
1692
|
-
var CONTEXT_PENDING_KEYS = "lease_ms,observed_at,sequence,session";
|
|
1693
|
-
var CONTEXT_PENDING_MARKED_KEYS = "launch_identity,lease_ms,observed_at,sequence,session";
|
|
1694
|
-
var CONTEXT_ACCEPTED_KEYS = "lease_ms,observed_at,sent_at,sequence,session";
|
|
1695
|
-
var CONTEXT_ACCEPTED_MARKED_KEYS = "launch_identity,lease_ms,observed_at,sent_at,sequence,session";
|
|
1696
|
-
function sessionAt(value) {
|
|
1697
|
-
if (typeof value !== "object" || value === null) return void 0;
|
|
1698
|
-
const found = value.session;
|
|
1699
|
-
if (found === null) return null;
|
|
1700
|
-
return typeof found === "string" ? found : void 0;
|
|
1701
|
-
}
|
|
1702
|
-
function sameLaunchIdentity(a, b) {
|
|
1703
|
-
return a === b || a !== void 0 && b !== void 0 && a.version === b.version && a.subject_id === b.subject_id && a.launch_id === b.launch_id && a.execution_generation === b.execution_generation;
|
|
1704
|
-
}
|
|
1705
|
-
function contextReportAt(value, keys, markedKeys) {
|
|
1706
|
-
const marked = exactKeys(value, markedKeys);
|
|
1707
|
-
if (!exactKeys(value, keys) && !marked) return void 0;
|
|
1708
|
-
const sequence = numberAt2(value, "sequence");
|
|
1709
|
-
const lease = numberAt2(value, "lease_ms");
|
|
1710
|
-
const observed = textAt(value, "observed_at");
|
|
1711
|
-
const session = sessionAt(value);
|
|
1712
|
-
if (sequence === void 0 || sequence < 1) return void 0;
|
|
1713
|
-
if (lease === void 0 || observed === void 0 || session === void 0)
|
|
1714
|
-
return void 0;
|
|
1715
|
-
const marker = marked ? decodeRadarLaunchMarker(value.launch_identity) : void 0;
|
|
1716
|
-
if (marked && marker === void 0) return void 0;
|
|
1717
|
-
return {
|
|
1718
|
-
sequence,
|
|
1719
|
-
session,
|
|
1720
|
-
lease_ms: lease,
|
|
1721
|
-
observed_at: observed,
|
|
1722
|
-
...marker !== void 0 ? { launch_identity: marker } : {}
|
|
1723
|
-
};
|
|
1724
|
-
}
|
|
1725
1662
|
function createChannelWriter(input) {
|
|
1726
1663
|
const { store, client, scheduler, recordName, channel, publisher } = input;
|
|
1727
1664
|
const codec = input.codec ?? executionCodec;
|
|
@@ -1737,7 +1674,7 @@ function createChannelWriter(input) {
|
|
|
1737
1674
|
function blank(agentId) {
|
|
1738
1675
|
return {
|
|
1739
1676
|
version: RADAR_PUBLICATION_VERSION,
|
|
1740
|
-
|
|
1677
|
+
registration_id: agentId,
|
|
1741
1678
|
channel,
|
|
1742
1679
|
publisher,
|
|
1743
1680
|
sequence: 0
|
|
@@ -1745,7 +1682,7 @@ function createChannelWriter(input) {
|
|
|
1745
1682
|
}
|
|
1746
1683
|
function loadRecord() {
|
|
1747
1684
|
const value = store.read(recordName);
|
|
1748
|
-
const agentId = textAt(value, "
|
|
1685
|
+
const agentId = textAt(value, "registration_id");
|
|
1749
1686
|
const storedPublisher = recordAt2(value, "publisher");
|
|
1750
1687
|
if (numberAt2(value, "version") !== RADAR_PUBLICATION_VERSION || agentId === void 0 || !isUuid(agentId) || textAt(value, "channel") !== channel || textAt(storedPublisher, "source") !== publisher.source || textAt(storedPublisher, "incarnation") !== publisher.incarnation || textAt(storedPublisher, "reporting_owner") !== publisher.reporting_owner)
|
|
1751
1688
|
return blank("");
|
|
@@ -1760,7 +1697,7 @@ function createChannelWriter(input) {
|
|
|
1760
1697
|
const sentAt = numberAt2(acceptedValue, "sent_at");
|
|
1761
1698
|
return {
|
|
1762
1699
|
version: RADAR_PUBLICATION_VERSION,
|
|
1763
|
-
|
|
1700
|
+
registration_id: agentId,
|
|
1764
1701
|
channel,
|
|
1765
1702
|
publisher,
|
|
1766
1703
|
...handle !== void 0 && generation !== void 0 ? { writer: { handle, generation } } : {},
|
|
@@ -1801,12 +1738,12 @@ function createChannelWriter(input) {
|
|
|
1801
1738
|
if (record.writer !== void 0) return true;
|
|
1802
1739
|
const agentId = await input.subject(recovering);
|
|
1803
1740
|
if (agentId === void 0) return false;
|
|
1804
|
-
if (record.
|
|
1741
|
+
if (record.registration_id !== agentId) {
|
|
1805
1742
|
record = blank(agentId);
|
|
1806
1743
|
save();
|
|
1807
1744
|
}
|
|
1808
1745
|
const answer = await client.acquire({
|
|
1809
|
-
|
|
1746
|
+
registration_id: agentId,
|
|
1810
1747
|
channel,
|
|
1811
1748
|
publisher
|
|
1812
1749
|
});
|
|
@@ -1836,7 +1773,7 @@ function createChannelWriter(input) {
|
|
|
1836
1773
|
const writer = record.writer;
|
|
1837
1774
|
if (writer === void 0) return;
|
|
1838
1775
|
const answer = await client.publish({
|
|
1839
|
-
|
|
1776
|
+
registration_id: record.registration_id,
|
|
1840
1777
|
channel,
|
|
1841
1778
|
writer_handle: writer.handle,
|
|
1842
1779
|
sequence: pending.sequence,
|
|
@@ -1930,9 +1867,9 @@ function createChannelWriter(input) {
|
|
|
1930
1867
|
stopPump();
|
|
1931
1868
|
const writer = record.writer;
|
|
1932
1869
|
if (writer === void 0) return;
|
|
1933
|
-
const agentId = record.
|
|
1870
|
+
const agentId = record.registration_id;
|
|
1934
1871
|
try {
|
|
1935
|
-
void client.retire({
|
|
1872
|
+
void client.retire({ registration_id: agentId, channel, writer_handle: writer.handle }).then((answer) => {
|
|
1936
1873
|
if (answer.ok === true) {
|
|
1937
1874
|
try {
|
|
1938
1875
|
record.retired_at = new Date(scheduler.now()).toISOString();
|
|
@@ -1955,214 +1892,127 @@ function createChannelWriter(input) {
|
|
|
1955
1892
|
diagnostic: () => record.diagnostic
|
|
1956
1893
|
};
|
|
1957
1894
|
}
|
|
1958
|
-
function
|
|
1959
|
-
const { store, client, scheduler, recordName
|
|
1960
|
-
let
|
|
1961
|
-
let
|
|
1962
|
-
let
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
function blank(agentId) {
|
|
1970
|
-
return {
|
|
1971
|
-
version: RADAR_PUBLICATION_VERSION,
|
|
1972
|
-
agent_id: agentId,
|
|
1973
|
-
publisher,
|
|
1974
|
-
sequence: 0
|
|
1975
|
-
};
|
|
1976
|
-
}
|
|
1977
|
-
function loadRecord() {
|
|
1978
|
-
const value = store.read(recordName);
|
|
1979
|
-
const agentId = textAt(value, "agent_id");
|
|
1980
|
-
const storedPublisher = recordAt2(value, "publisher");
|
|
1981
|
-
if (numberAt2(value, "version") !== RADAR_PUBLICATION_VERSION || agentId === void 0 || !isUuid(agentId) && agentId !== "" || textAt(storedPublisher, "source") !== publisher.source || textAt(storedPublisher, "incarnation") !== publisher.incarnation || textAt(storedPublisher, "reporting_owner") !== publisher.reporting_owner)
|
|
1982
|
-
return blank("");
|
|
1983
|
-
const writer = recordAt2(value, "writer");
|
|
1984
|
-
const handle = textAt(writer, "handle");
|
|
1985
|
-
const generation = numberAt2(writer, "generation");
|
|
1986
|
-
if (writer !== void 0 && (!exactKeys(writer, WRITER_KEYS) || !isUuid(handle) || generation === void 0))
|
|
1987
|
-
return blank(agentId);
|
|
1988
|
-
const pending = contextReportAt(
|
|
1989
|
-
recordAt2(value, "pending"),
|
|
1990
|
-
CONTEXT_PENDING_KEYS,
|
|
1991
|
-
CONTEXT_PENDING_MARKED_KEYS
|
|
1992
|
-
);
|
|
1993
|
-
const acceptedValue = recordAt2(value, "accepted");
|
|
1994
|
-
const accepted = contextReportAt(
|
|
1995
|
-
acceptedValue,
|
|
1996
|
-
CONTEXT_ACCEPTED_KEYS,
|
|
1997
|
-
CONTEXT_ACCEPTED_MARKED_KEYS
|
|
1998
|
-
);
|
|
1999
|
-
const sentAt = numberAt2(acceptedValue, "sent_at");
|
|
2000
|
-
return {
|
|
2001
|
-
version: RADAR_PUBLICATION_VERSION,
|
|
2002
|
-
agent_id: agentId,
|
|
2003
|
-
publisher,
|
|
2004
|
-
...handle !== void 0 && generation !== void 0 ? { writer: { handle, generation } } : {},
|
|
2005
|
-
sequence: numberAt2(value, "sequence") ?? 0,
|
|
2006
|
-
...pending !== void 0 ? { pending } : {},
|
|
2007
|
-
...accepted !== void 0 && sentAt !== void 0 ? { accepted: { ...accepted, sent_at: sentAt } } : {},
|
|
2008
|
-
...textAt(value, "diagnostic") !== void 0 ? { diagnostic: textAt(value, "diagnostic") } : {}
|
|
2009
|
-
};
|
|
2010
|
-
}
|
|
2011
|
-
function note(message) {
|
|
2012
|
-
if (record.diagnostic !== void 0) return;
|
|
2013
|
-
record.diagnostic = message.slice(0, 256);
|
|
2014
|
-
save();
|
|
1895
|
+
function createPresenceReporter(input) {
|
|
1896
|
+
const { store, client, scheduler, recordName } = input;
|
|
1897
|
+
let state;
|
|
1898
|
+
let standing;
|
|
1899
|
+
let diagnostic;
|
|
1900
|
+
try {
|
|
1901
|
+
const saved = store.read(recordName);
|
|
1902
|
+
if (saved?.version === 2 && isUuid(saved.claim_id) && isUuid(saved.session) && Array.isArray(saved.releases))
|
|
1903
|
+
state = saved;
|
|
1904
|
+
} catch (error) {
|
|
1905
|
+
diagnostic = `presence storage unavailable: ${String(error)}`;
|
|
2015
1906
|
}
|
|
1907
|
+
let timer;
|
|
1908
|
+
let stopped = false;
|
|
1909
|
+
let running;
|
|
2016
1910
|
function save() {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
function startPump() {
|
|
2025
|
-
if (pump !== void 0 || stopped || fenced) return;
|
|
2026
|
-
pump = scheduler.setInterval(() => kick(), input.heartbeatMs);
|
|
2027
|
-
pump.unref?.();
|
|
2028
|
-
}
|
|
2029
|
-
function stopPump() {
|
|
2030
|
-
if (pump === void 0) return;
|
|
2031
|
-
scheduler.clearInterval(pump);
|
|
2032
|
-
pump = void 0;
|
|
1911
|
+
try {
|
|
1912
|
+
if (state) store.write(recordName, state);
|
|
1913
|
+
return true;
|
|
1914
|
+
} catch (error) {
|
|
1915
|
+
diagnostic = `presence storage unavailable: ${String(error)}`;
|
|
1916
|
+
return false;
|
|
1917
|
+
}
|
|
2033
1918
|
}
|
|
2034
|
-
async function
|
|
2035
|
-
if (
|
|
2036
|
-
const
|
|
2037
|
-
if (
|
|
2038
|
-
|
|
2039
|
-
|
|
1919
|
+
async function releasePending() {
|
|
1920
|
+
if (!state) return;
|
|
1921
|
+
const registration = await input.registration();
|
|
1922
|
+
if (!registration?.process) return;
|
|
1923
|
+
for (const release of [...state.releases]) {
|
|
1924
|
+
const answer = await client.releasePresence({ ...release, process: registration.process });
|
|
1925
|
+
if (!answer.ok) return;
|
|
1926
|
+
state.releases = state.releases.filter((r) => r.claim_id !== release.claim_id);
|
|
2040
1927
|
save();
|
|
2041
1928
|
}
|
|
2042
|
-
return true;
|
|
2043
1929
|
}
|
|
2044
|
-
function
|
|
2045
|
-
|
|
1930
|
+
function schedule() {
|
|
1931
|
+
if (stopped || timer) return;
|
|
1932
|
+
timer = scheduler.setTimeout(() => {
|
|
1933
|
+
timer = void 0;
|
|
1934
|
+
void ensure();
|
|
1935
|
+
}, input.heartbeatMs);
|
|
1936
|
+
timer.unref?.();
|
|
2046
1937
|
}
|
|
2047
|
-
async function
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
1938
|
+
async function ensure() {
|
|
1939
|
+
if (running) return running;
|
|
1940
|
+
if (stopped || !state) return void 0;
|
|
1941
|
+
const claim = state;
|
|
1942
|
+
if (!save()) return void 0;
|
|
1943
|
+
running = (async () => {
|
|
1944
|
+
await releasePending();
|
|
1945
|
+
const registration = await input.registration();
|
|
1946
|
+
if (!registration?.process || state !== claim || stopped) return void 0;
|
|
1947
|
+
const answer = await client.presence({
|
|
1948
|
+
...registration,
|
|
1949
|
+
process: registration.process,
|
|
1950
|
+
session_id: claim.session,
|
|
1951
|
+
claim_id: claim.claim_id,
|
|
1952
|
+
...claim.registration_id ? { registration_id: claim.registration_id } : {},
|
|
1953
|
+
...claim.subject_id ? { subject_id: claim.subject_id } : {}
|
|
1954
|
+
});
|
|
1955
|
+
if (state !== claim) return void 0;
|
|
1956
|
+
if (!answer.ok) {
|
|
1957
|
+
if (!["absent", "timeout", "transport"].includes(answer.code)) diagnostic = answer.message;
|
|
1958
|
+
return void 0;
|
|
2061
1959
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
handle: answer.value.writer.handle,
|
|
2067
|
-
generation: answer.value.writer.generation
|
|
2068
|
-
};
|
|
2069
|
-
record.sequence = Math.max(record.sequence, answer.value.writer.sequence);
|
|
2070
|
-
record.accepted = {
|
|
2071
|
-
...pending,
|
|
2072
|
-
sent_at: answer.value.warning === void 0 ? scheduler.now() : record.accepted?.sent_at ?? scheduler.now()
|
|
2073
|
-
};
|
|
2074
|
-
record.pending = void 0;
|
|
1960
|
+
claim.registration_id = answer.value.registration_id;
|
|
1961
|
+
claim.subject_id = answer.value.standing === "granted" ? answer.value.subject_id ?? void 0 : void 0;
|
|
1962
|
+
standing = answer.value.standing === "granted" ? { state: "managed", subject_id: claim.subject_id } : answer.value.standing === "duplicate" ? { state: "duplicate" } : answer.value.standing === "pending" ? { state: "pending" } : { state: "unmanaged" };
|
|
1963
|
+
diagnostic = answer.value.standing === "duplicate" ? DUPLICATE_SESSION_DIAGNOSTIC : void 0;
|
|
2075
1964
|
save();
|
|
2076
|
-
return;
|
|
2077
|
-
}
|
|
2078
|
-
if (answer.code === "refused" || answer.code === "bad_params" || // A daemon that speaks the registry but does not serve this record would
|
|
2079
|
-
// refuse every retry the same way; one diagnostic beats a silent retry
|
|
2080
|
-
// loop once per heartbeat.
|
|
2081
|
-
answer.code === "unknown_method") {
|
|
2082
|
-
fence(answer.message);
|
|
2083
|
-
return;
|
|
2084
|
-
}
|
|
2085
|
-
if (answer.code === "not_found") {
|
|
2086
|
-
record = blank("");
|
|
2087
|
-
recovering = true;
|
|
2088
|
-
save();
|
|
2089
|
-
return;
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
async function stage(session, launchIdentity) {
|
|
2093
|
-
const pending = {
|
|
2094
|
-
sequence: record.sequence + 1,
|
|
2095
|
-
session,
|
|
2096
|
-
lease_ms: input.leaseMs,
|
|
2097
|
-
observed_at: new Date(scheduler.now()).toISOString(),
|
|
2098
|
-
...launchIdentity !== void 0 ? { launch_identity: launchIdentity } : {}
|
|
2099
|
-
};
|
|
2100
|
-
record.pending = pending;
|
|
2101
|
-
save();
|
|
2102
|
-
await send(pending);
|
|
2103
|
-
}
|
|
2104
|
-
async function drainOnce() {
|
|
2105
|
-
if (fenced) return;
|
|
2106
|
-
if (record.pending !== void 0) {
|
|
2107
|
-
await send(record.pending);
|
|
2108
|
-
return;
|
|
2109
|
-
}
|
|
2110
|
-
if (desired === void 0) return;
|
|
2111
|
-
if (!await ensureSubject()) return;
|
|
2112
|
-
if (fenced) return;
|
|
2113
|
-
if (record.writer === void 0 || record.accepted === void 0 || record.accepted.session !== desired || !sameLaunchIdentity(record.accepted.launch_identity, desiredMarker)) {
|
|
2114
|
-
await stage(desired, desiredMarker);
|
|
2115
|
-
return;
|
|
2116
|
-
}
|
|
2117
|
-
if (heartbeatDue()) await stage(record.accepted.session, desiredMarker);
|
|
2118
|
-
}
|
|
2119
|
-
async function drain() {
|
|
2120
|
-
if (running || stopped || fenced) return;
|
|
2121
|
-
running = true;
|
|
1965
|
+
return claim.registration_id;
|
|
1966
|
+
})();
|
|
2122
1967
|
try {
|
|
2123
|
-
await
|
|
1968
|
+
return await running;
|
|
2124
1969
|
} catch (error) {
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
try {
|
|
2128
|
-
note(`context storage failure: ${String(error).slice(0, 180)}`);
|
|
2129
|
-
} catch {
|
|
2130
|
-
}
|
|
1970
|
+
diagnostic = `presence unavailable: ${String(error)}`;
|
|
1971
|
+
return void 0;
|
|
2131
1972
|
} finally {
|
|
2132
|
-
running =
|
|
2133
|
-
if (
|
|
2134
|
-
|
|
2135
|
-
kick();
|
|
2136
|
-
}
|
|
1973
|
+
running = void 0;
|
|
1974
|
+
if (!stopped && state !== claim) void ensure();
|
|
1975
|
+
else schedule();
|
|
2137
1976
|
}
|
|
2138
1977
|
}
|
|
2139
|
-
function kick() {
|
|
2140
|
-
if (stopped || fenced) return;
|
|
2141
|
-
startPump();
|
|
2142
|
-
if (running) {
|
|
2143
|
-
again = true;
|
|
2144
|
-
return;
|
|
2145
|
-
}
|
|
2146
|
-
void drain().catch(() => void 0);
|
|
2147
|
-
}
|
|
2148
1978
|
return {
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
1979
|
+
report(session) {
|
|
1980
|
+
const releases = [...state?.releases ?? []];
|
|
1981
|
+
if (state?.registration_id && !releases.some((release) => release.claim_id === state.claim_id)) {
|
|
1982
|
+
releases.push({ registration_id: state.registration_id, claim_id: state.claim_id });
|
|
1983
|
+
}
|
|
1984
|
+
standing = void 0;
|
|
1985
|
+
state = { version: 2, session, claim_id: randomUUID2(), releases };
|
|
1986
|
+
save();
|
|
1987
|
+
stopped = false;
|
|
1988
|
+
void ensure();
|
|
1989
|
+
},
|
|
1990
|
+
ensure,
|
|
1991
|
+
async release() {
|
|
1992
|
+
const releasing = state;
|
|
1993
|
+
standing = void 0;
|
|
1994
|
+
stopped = true;
|
|
1995
|
+
if (timer) scheduler.clearTimeout(timer);
|
|
1996
|
+
timer = void 0;
|
|
1997
|
+
if (running) await running;
|
|
1998
|
+
if (state === releasing) standing = void 0;
|
|
1999
|
+
if (releasing?.registration_id && !releasing.releases.some((r) => r.claim_id === releasing.claim_id)) {
|
|
2000
|
+
releasing.releases.push({ registration_id: releasing.registration_id, claim_id: releasing.claim_id });
|
|
2001
|
+
if (!save()) return;
|
|
2002
|
+
}
|
|
2003
|
+
await releasePending();
|
|
2156
2004
|
},
|
|
2157
2005
|
stop() {
|
|
2158
2006
|
stopped = true;
|
|
2159
|
-
|
|
2007
|
+
if (timer) scheduler.clearTimeout(timer);
|
|
2008
|
+
timer = void 0;
|
|
2160
2009
|
},
|
|
2161
2010
|
reopen() {
|
|
2162
2011
|
stopped = false;
|
|
2163
|
-
|
|
2012
|
+
void ensure();
|
|
2164
2013
|
},
|
|
2165
|
-
|
|
2014
|
+
management: () => standing,
|
|
2015
|
+
diagnostic: () => diagnostic
|
|
2166
2016
|
};
|
|
2167
2017
|
}
|
|
2168
2018
|
var STORE_IDENTITY = /* @__PURE__ */ new WeakMap();
|
|
@@ -2191,10 +2041,13 @@ function unavailablePublication(error) {
|
|
|
2191
2041
|
};
|
|
2192
2042
|
return {
|
|
2193
2043
|
execution: writer,
|
|
2194
|
-
|
|
2195
|
-
|
|
2044
|
+
presence: {
|
|
2045
|
+
report: () => void 0,
|
|
2046
|
+
ensure: async () => void 0,
|
|
2047
|
+
release: async () => void 0,
|
|
2196
2048
|
stop: () => void 0,
|
|
2197
2049
|
reopen: () => void 0,
|
|
2050
|
+
management: () => void 0,
|
|
2198
2051
|
diagnostic: () => diagnostic
|
|
2199
2052
|
},
|
|
2200
2053
|
facts: { ...writer, update: () => void 0 },
|
|
@@ -2221,33 +2074,29 @@ function createRadarPublicationInner(options) {
|
|
|
2221
2074
|
cached.reopen();
|
|
2222
2075
|
return cached;
|
|
2223
2076
|
}
|
|
2224
|
-
const
|
|
2077
|
+
const registrationName = `registrations/${createHash("sha256").update(`${options.registration.source}\0${incarnation}`).digest("hex").slice(0, 32)}.json`;
|
|
2225
2078
|
const channelRecord = (channel, target) => `channels/${createHash("sha256").update(`${channel}\0${incarnation}\0${target ?? ""}`).digest("hex").slice(0, 32)}.json`;
|
|
2226
|
-
const
|
|
2227
|
-
function
|
|
2228
|
-
const value = store.read(
|
|
2079
|
+
const presenceRecord = `presence/${createHash("sha256").update(`presence\0${incarnation}`).digest("hex").slice(0, 32)}.json`;
|
|
2080
|
+
function readRegistration() {
|
|
2081
|
+
const value = store.read(registrationName);
|
|
2229
2082
|
const registration = recordAt2(value, "registration");
|
|
2230
2083
|
if (numberAt2(value, "version") !== RADAR_PUBLICATION_VERSION || textAt(registration, "source") !== options.registration.source || textAt(registration, "incarnation") !== incarnation)
|
|
2231
2084
|
return void 0;
|
|
2232
|
-
const storedAgentId = textAt(value, "
|
|
2085
|
+
const storedAgentId = textAt(value, "registration_id");
|
|
2233
2086
|
return {
|
|
2234
2087
|
version: RADAR_PUBLICATION_VERSION,
|
|
2235
2088
|
registration,
|
|
2236
|
-
...storedAgentId !== void 0 && isUuid(storedAgentId) ? {
|
|
2089
|
+
...storedAgentId !== void 0 && isUuid(storedAgentId) ? { registration_id: storedAgentId } : {}
|
|
2237
2090
|
};
|
|
2238
2091
|
}
|
|
2239
|
-
const stored =
|
|
2240
|
-
let
|
|
2092
|
+
const stored = readRegistration();
|
|
2093
|
+
let processRecord = stored;
|
|
2241
2094
|
let registrationDiagnostic;
|
|
2242
2095
|
let registrationRecord;
|
|
2243
2096
|
async function ensureRegistration() {
|
|
2244
|
-
if (
|
|
2097
|
+
if (processRecord !== void 0) return processRecord;
|
|
2245
2098
|
registrationRecord ??= (async () => {
|
|
2246
2099
|
const resolution = options.location ? await options.location() : { state: "absent", reason: "this process publishes no location" };
|
|
2247
|
-
if (resolution.state === "pending") {
|
|
2248
|
-
registrationDiagnostic = `location bootstrap pending: ${resolution.reason}`.slice(0, 256);
|
|
2249
|
-
return void 0;
|
|
2250
|
-
}
|
|
2251
2100
|
const built = {
|
|
2252
2101
|
version: RADAR_PUBLICATION_VERSION,
|
|
2253
2102
|
registration: {
|
|
@@ -2258,13 +2107,13 @@ function createRadarPublicationInner(options) {
|
|
|
2258
2107
|
}
|
|
2259
2108
|
};
|
|
2260
2109
|
try {
|
|
2261
|
-
store.write(
|
|
2110
|
+
store.write(registrationName, built);
|
|
2262
2111
|
} catch (error) {
|
|
2263
2112
|
registrationDiagnostic ??= `private storage unavailable: ${String(error)}`.slice(0, 256);
|
|
2264
2113
|
return void 0;
|
|
2265
2114
|
}
|
|
2266
2115
|
registrationDiagnostic = void 0;
|
|
2267
|
-
|
|
2116
|
+
processRecord = built;
|
|
2268
2117
|
return built;
|
|
2269
2118
|
})();
|
|
2270
2119
|
try {
|
|
@@ -2273,11 +2122,10 @@ function createRadarPublicationInner(options) {
|
|
|
2273
2122
|
registrationRecord = void 0;
|
|
2274
2123
|
}
|
|
2275
2124
|
}
|
|
2276
|
-
let agentId = stored?.
|
|
2125
|
+
let agentId = stored?.registration_id;
|
|
2277
2126
|
let subjectReady;
|
|
2278
2127
|
async function ensureSubject(recheck) {
|
|
2279
|
-
if (recheck
|
|
2280
|
-
if (agentId !== void 0) return agentId;
|
|
2128
|
+
if (!recheck && agentId !== void 0) return agentId;
|
|
2281
2129
|
subjectReady ??= (async () => {
|
|
2282
2130
|
const ready = await client.ping();
|
|
2283
2131
|
if (ready.ok === false) {
|
|
@@ -2287,18 +2135,11 @@ function createRadarPublicationInner(options) {
|
|
|
2287
2135
|
}
|
|
2288
2136
|
const record = await ensureRegistration();
|
|
2289
2137
|
if (record === void 0) return void 0;
|
|
2290
|
-
const
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
}
|
|
2294
|
-
|
|
2295
|
-
if (answer.code !== "absent" && answer.code !== "timeout" && answer.code !== "transport")
|
|
2296
|
-
registrationDiagnostic ??= `subject registration refused: ${answer.message}`.slice(0, 256);
|
|
2297
|
-
return void 0;
|
|
2298
|
-
}
|
|
2299
|
-
agentId = answer.value.agent_id;
|
|
2300
|
-
subject = { ...record, agent_id: agentId };
|
|
2301
|
-
store.write(subjectName, subject);
|
|
2138
|
+
const registered = await presence.ensure();
|
|
2139
|
+
if (registered === void 0) return void 0;
|
|
2140
|
+
agentId = registered;
|
|
2141
|
+
processRecord = { ...record, registration_id: agentId };
|
|
2142
|
+
store.write(registrationName, processRecord);
|
|
2302
2143
|
if (options.binding !== void 0) writeBinding(options.binding);
|
|
2303
2144
|
return agentId;
|
|
2304
2145
|
})();
|
|
@@ -2312,7 +2153,7 @@ function createRadarPublicationInner(options) {
|
|
|
2312
2153
|
if (agentId === void 0) return;
|
|
2313
2154
|
store.write(`bindings/${binding.key}.json`, {
|
|
2314
2155
|
version: RADAR_PUBLICATION_VERSION,
|
|
2315
|
-
|
|
2156
|
+
registration_id: agentId,
|
|
2316
2157
|
incarnation,
|
|
2317
2158
|
run: binding.run,
|
|
2318
2159
|
owner: binding.owner,
|
|
@@ -2336,14 +2177,22 @@ function createRadarPublicationInner(options) {
|
|
|
2336
2177
|
leaseMs: options.leaseMs ?? RADAR_LEASE_MS,
|
|
2337
2178
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
2338
2179
|
});
|
|
2339
|
-
const
|
|
2180
|
+
const presence = createPresenceReporter({
|
|
2340
2181
|
store,
|
|
2341
2182
|
client,
|
|
2342
2183
|
scheduler,
|
|
2343
|
-
recordName:
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2184
|
+
recordName: presenceRecord,
|
|
2185
|
+
registration: async () => {
|
|
2186
|
+
const record = await ensureRegistration();
|
|
2187
|
+
if (!record) return void 0;
|
|
2188
|
+
const location = await options.location?.();
|
|
2189
|
+
const { location: _initialLocation, ...identity } = record.registration;
|
|
2190
|
+
return {
|
|
2191
|
+
...identity,
|
|
2192
|
+
...location?.state === "resolved" ? { location: location.location } : {},
|
|
2193
|
+
...spawnToken ? { spawn_token: spawnToken } : {}
|
|
2194
|
+
};
|
|
2195
|
+
},
|
|
2347
2196
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
2348
2197
|
});
|
|
2349
2198
|
const facts = createChannelWriter({
|
|
@@ -2361,7 +2210,7 @@ function createRadarPublicationInner(options) {
|
|
|
2361
2210
|
const assignmentWriters = /* @__PURE__ */ new Map();
|
|
2362
2211
|
const publication = {
|
|
2363
2212
|
execution,
|
|
2364
|
-
|
|
2213
|
+
presence,
|
|
2365
2214
|
facts,
|
|
2366
2215
|
assignment(target, reportingOwner) {
|
|
2367
2216
|
const existing = assignmentWriters.get(target);
|
|
@@ -2376,7 +2225,7 @@ function createRadarPublicationInner(options) {
|
|
|
2376
2225
|
publisher: publisher("herdsman-owner", reportingOwner),
|
|
2377
2226
|
codec: assignmentCodec,
|
|
2378
2227
|
// The owner publishes about a subject it did not register: the exact
|
|
2379
|
-
//
|
|
2228
|
+
// registration_id from the child's sidecar is the whole correlation.
|
|
2380
2229
|
subject: async () => target,
|
|
2381
2230
|
leaseMs: options.leaseMs ?? RADAR_LEASE_MS,
|
|
2382
2231
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
@@ -2396,7 +2245,7 @@ function createRadarPublicationInner(options) {
|
|
|
2396
2245
|
registrationDiagnostic ??= `Radar binding unavailable: ${String(error).slice(0, 180)}`;
|
|
2397
2246
|
return void 0;
|
|
2398
2247
|
}
|
|
2399
|
-
const bound = textAt(value, "
|
|
2248
|
+
const bound = textAt(value, "registration_id");
|
|
2400
2249
|
const boundIncarnation = textAt(value, "incarnation");
|
|
2401
2250
|
const run = textAt(value, "run");
|
|
2402
2251
|
const owner = textAt(value, "owner");
|
|
@@ -2406,7 +2255,7 @@ function createRadarPublicationInner(options) {
|
|
|
2406
2255
|
return void 0;
|
|
2407
2256
|
return {
|
|
2408
2257
|
version: RADAR_PUBLICATION_VERSION,
|
|
2409
|
-
|
|
2258
|
+
registration_id: bound,
|
|
2410
2259
|
incarnation: boundIncarnation,
|
|
2411
2260
|
run,
|
|
2412
2261
|
owner,
|
|
@@ -2422,25 +2271,27 @@ function createRadarPublicationInner(options) {
|
|
|
2422
2271
|
if (agentId2 === void 0) return void 0;
|
|
2423
2272
|
const record = await ensureRegistration();
|
|
2424
2273
|
if (record === void 0) return void 0;
|
|
2425
|
-
const
|
|
2426
|
-
const
|
|
2274
|
+
const currentLocation = await options.location?.();
|
|
2275
|
+
const location = currentLocation?.state === "resolved" ? currentLocation.location : void 0;
|
|
2276
|
+
const standing = presence.management();
|
|
2277
|
+
const subjectId = standing?.state === "managed" ? standing.subject_id : void 0;
|
|
2427
2278
|
return {
|
|
2428
|
-
|
|
2279
|
+
registration_id: agentId2,
|
|
2429
2280
|
...subjectId !== void 0 ? { subject_id: subjectId } : {},
|
|
2430
2281
|
...location !== void 0 ? { location } : {}
|
|
2431
2282
|
};
|
|
2432
2283
|
},
|
|
2433
|
-
diagnostic: () => registrationDiagnostic ?? execution.diagnostic() ??
|
|
2284
|
+
diagnostic: () => registrationDiagnostic ?? execution.diagnostic() ?? presence.diagnostic() ?? facts.diagnostic(),
|
|
2434
2285
|
stop() {
|
|
2435
2286
|
for (const writer of assignmentWriters.values()) writer.stop();
|
|
2436
2287
|
execution.stop();
|
|
2437
|
-
|
|
2288
|
+
presence.stop();
|
|
2438
2289
|
facts.stop();
|
|
2439
2290
|
},
|
|
2440
2291
|
reopen() {
|
|
2441
2292
|
for (const writer of assignmentWriters.values()) writer.reopen();
|
|
2442
2293
|
execution.reopen();
|
|
2443
|
-
|
|
2294
|
+
presence.reopen();
|
|
2444
2295
|
facts.reopen();
|
|
2445
2296
|
}
|
|
2446
2297
|
};
|
|
@@ -2478,10 +2329,13 @@ function unavailablePublication2() {
|
|
|
2478
2329
|
return {
|
|
2479
2330
|
execution: writer,
|
|
2480
2331
|
facts: { ...writer, update: () => void 0 },
|
|
2481
|
-
|
|
2482
|
-
|
|
2332
|
+
presence: {
|
|
2333
|
+
report: () => void 0,
|
|
2483
2334
|
stop: () => void 0,
|
|
2484
2335
|
reopen: () => void 0,
|
|
2336
|
+
management: () => void 0,
|
|
2337
|
+
ensure: async () => void 0,
|
|
2338
|
+
release: async () => void 0,
|
|
2485
2339
|
diagnostic: () => "Radar private storage is unavailable"
|
|
2486
2340
|
},
|
|
2487
2341
|
assignment: () => writer,
|
|
@@ -2564,11 +2418,11 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2564
2418
|
...lastOutcome !== void 0 ? { last_outcome: lastOutcome } : {}
|
|
2565
2419
|
};
|
|
2566
2420
|
}
|
|
2567
|
-
function reportSession(context
|
|
2421
|
+
function reportSession(context) {
|
|
2568
2422
|
const session = context?.sessionManager?.getSessionId?.();
|
|
2569
2423
|
if (!isUuid(session)) return;
|
|
2570
2424
|
try {
|
|
2571
|
-
publication.
|
|
2425
|
+
publication.presence.report(session);
|
|
2572
2426
|
} catch {
|
|
2573
2427
|
}
|
|
2574
2428
|
}
|
|
@@ -2632,38 +2486,8 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2632
2486
|
})
|
|
2633
2487
|
);
|
|
2634
2488
|
on("session_start", (_event, context) => {
|
|
2635
|
-
const sessionHost = {
|
|
2636
|
-
appendEntry: pi.appendEntry ? (customType, data) => pi.appendEntry?.(customType, data) : void 0,
|
|
2637
|
-
sessionManager: context?.sessionManager
|
|
2638
|
-
};
|
|
2639
|
-
let launchIdentity;
|
|
2640
|
-
try {
|
|
2641
|
-
const result = persistRadarLaunchMarker(
|
|
2642
|
-
sessionHost,
|
|
2643
|
-
options.markerEnvironment
|
|
2644
|
-
);
|
|
2645
|
-
if (result === "written" || result === "unchanged") {
|
|
2646
|
-
const expected = radarLaunchMarkerFromEnvironment(options.markerEnvironment);
|
|
2647
|
-
const activeMarker = activeRadarLaunchMarker(sessionHost);
|
|
2648
|
-
if (expected && activeMarker.status === "valid" && JSON.stringify(activeMarker.marker) === JSON.stringify(expected)) {
|
|
2649
|
-
launchIdentity = activeMarker.marker;
|
|
2650
|
-
} else {
|
|
2651
|
-
options.diagnostic?.("Radar launch marker was not visible on the active Pi session branch");
|
|
2652
|
-
}
|
|
2653
|
-
} else if (result === "unsupported") {
|
|
2654
|
-
options.diagnostic?.("Pi host does not support Radar launch identity session entries");
|
|
2655
|
-
} else if (options.markerEnvironment && [
|
|
2656
|
-
"PI_RADAR_MANAGED_SUBJECT_ID",
|
|
2657
|
-
"PI_RADAR_MANAGED_LAUNCH_ID",
|
|
2658
|
-
"PI_RADAR_MANAGED_EXECUTION_GENERATION"
|
|
2659
|
-
].some((key) => options.markerEnvironment?.[key] !== void 0)) {
|
|
2660
|
-
options.diagnostic?.("incomplete or invalid Radar launch identity environment");
|
|
2661
|
-
}
|
|
2662
|
-
} catch (error) {
|
|
2663
|
-
options.diagnostic?.(`could not persist Radar launch marker: ${String(error)}`);
|
|
2664
|
-
}
|
|
2665
2489
|
rootSession = true;
|
|
2666
|
-
reportSession(context
|
|
2490
|
+
reportSession(context);
|
|
2667
2491
|
publishFacts(context);
|
|
2668
2492
|
publication.reopen();
|
|
2669
2493
|
active = context?.isIdle?.() === false;
|
|
@@ -2694,8 +2518,9 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2694
2518
|
}
|
|
2695
2519
|
emit();
|
|
2696
2520
|
});
|
|
2697
|
-
on("session_shutdown", () => {
|
|
2521
|
+
on("session_shutdown", async () => {
|
|
2698
2522
|
suspend();
|
|
2523
|
+
await publication.presence.release();
|
|
2699
2524
|
});
|
|
2700
2525
|
function suspend() {
|
|
2701
2526
|
if (stopped) return;
|
|
@@ -2903,7 +2728,7 @@ function trajectory(reason) {
|
|
|
2903
2728
|
return `the daemon's current record of this launch's child is ${reason}`;
|
|
2904
2729
|
}
|
|
2905
2730
|
async function observeRadarChild(client, provenance) {
|
|
2906
|
-
if (provenance.
|
|
2731
|
+
if (provenance.registration_id === void 0)
|
|
2907
2732
|
return unknownChild("not bound to a child by this launch");
|
|
2908
2733
|
if (provenance.pane_id === void 0)
|
|
2909
2734
|
return unknownChild("without a pane this launch recorded for it");
|
|
@@ -2914,11 +2739,11 @@ async function observeRadarChild(client, provenance) {
|
|
|
2914
2739
|
);
|
|
2915
2740
|
const topology = read.value;
|
|
2916
2741
|
const edge = topology.edge;
|
|
2917
|
-
if (edge.bound === void 0 || edge.bound.
|
|
2742
|
+
if (edge.bound === void 0 || edge.bound.registration_id === void 0)
|
|
2918
2743
|
return unknownChild("not bound to a child by the daemon");
|
|
2919
|
-
if (edge.bound.
|
|
2744
|
+
if (edge.bound.registration_id !== provenance.registration_id)
|
|
2920
2745
|
return unknownChild(
|
|
2921
|
-
`bound to another subject (${edge.bound.
|
|
2746
|
+
`bound to another subject (${edge.bound.registration_id}), not to ${provenance.registration_id}`
|
|
2922
2747
|
);
|
|
2923
2748
|
if (edge.location?.pane === void 0)
|
|
2924
2749
|
return unknownChild("recorded without a pane");
|
|
@@ -2936,7 +2761,7 @@ async function observeRadarChild(client, provenance) {
|
|
|
2936
2761
|
return unknownChild(
|
|
2937
2762
|
`not currently placed (state ${topology.state ?? "unreported"})`
|
|
2938
2763
|
);
|
|
2939
|
-
const reply = await client.agentGet(edge.bound.
|
|
2764
|
+
const reply = await client.agentGet(edge.bound.registration_id);
|
|
2940
2765
|
if (reply.ok === false)
|
|
2941
2766
|
return unknownChild(
|
|
2942
2767
|
`process verdict not readable (${reply.code}: ${reply.message})`
|
|
@@ -2964,7 +2789,7 @@ async function observeRadarChild(client, provenance) {
|
|
|
2964
2789
|
kind: "live",
|
|
2965
2790
|
evidence: {
|
|
2966
2791
|
request_id: provenance.request_id,
|
|
2967
|
-
|
|
2792
|
+
registration_id: edge.bound.registration_id,
|
|
2968
2793
|
source: edge.bound.source,
|
|
2969
2794
|
incarnation: edge.bound.incarnation,
|
|
2970
2795
|
pane_id: edge.location.pane
|
|
@@ -3024,7 +2849,7 @@ async function launchRadarWorker(options) {
|
|
|
3024
2849
|
const deadline = Date.now() + options.timeoutMs;
|
|
3025
2850
|
const remaining = () => Math.max(0, deadline - Date.now());
|
|
3026
2851
|
const pane = launch.parent.location?.pane;
|
|
3027
|
-
if (!isUuid(launch.parent.
|
|
2852
|
+
if (!isUuid(launch.parent.registration_id))
|
|
3028
2853
|
return refusedLaunch(
|
|
3029
2854
|
"the launch has no exact parent registration to spawn under"
|
|
3030
2855
|
);
|
|
@@ -3038,7 +2863,7 @@ async function launchRadarWorker(options) {
|
|
|
3038
2863
|
);
|
|
3039
2864
|
const spawned = await client.spawn({
|
|
3040
2865
|
request_id: launch.request_id,
|
|
3041
|
-
parent: launch.parent.
|
|
2866
|
+
parent: launch.parent.registration_id,
|
|
3042
2867
|
parent_session_id: launch.parent_session_id,
|
|
3043
2868
|
executable: launch.executable,
|
|
3044
2869
|
managed: { parent_subject_id: launch.parent.subject_id },
|
|
@@ -3063,10 +2888,10 @@ async function launchRadarWorker(options) {
|
|
|
3063
2888
|
...signal !== void 0 ? { signal } : {}
|
|
3064
2889
|
});
|
|
3065
2890
|
if (bound.kind !== "bound") return bound;
|
|
3066
|
-
const agentId = bound.
|
|
2891
|
+
const agentId = bound.registration_id;
|
|
3067
2892
|
if (launch.onBound !== void 0) {
|
|
3068
2893
|
try {
|
|
3069
|
-
launch.onBound({
|
|
2894
|
+
launch.onBound({ registration_id: agentId, pane_id: bound.pane_id });
|
|
3070
2895
|
} catch (error) {
|
|
3071
2896
|
return unresolvedLaunch(
|
|
3072
2897
|
launch.request_id,
|
|
@@ -3094,7 +2919,7 @@ async function launchRadarWorker(options) {
|
|
|
3094
2919
|
kind: "ready",
|
|
3095
2920
|
value: {
|
|
3096
2921
|
request_id: launch.request_id,
|
|
3097
|
-
|
|
2922
|
+
registration_id: agentId,
|
|
3098
2923
|
pane_id: bound.pane_id,
|
|
3099
2924
|
bound_process: {
|
|
3100
2925
|
source: bound.source,
|
|
@@ -3140,7 +2965,7 @@ async function waitForChild(client, requestId, options) {
|
|
|
3140
2965
|
requestId,
|
|
3141
2966
|
"the daemon observed the launched child's process exit"
|
|
3142
2967
|
);
|
|
3143
|
-
const agentId = edge.bound?.
|
|
2968
|
+
const agentId = edge.bound?.registration_id;
|
|
3144
2969
|
if (agentId !== void 0 && isUuid(agentId)) {
|
|
3145
2970
|
const source = edge.bound?.source;
|
|
3146
2971
|
const incarnation = edge.bound?.incarnation;
|
|
@@ -3151,7 +2976,7 @@ async function waitForChild(client, requestId, options) {
|
|
|
3151
2976
|
);
|
|
3152
2977
|
return {
|
|
3153
2978
|
kind: "bound",
|
|
3154
|
-
|
|
2979
|
+
registration_id: agentId,
|
|
3155
2980
|
pane_id: pane,
|
|
3156
2981
|
source,
|
|
3157
2982
|
incarnation
|