pi-radar 0.3.0 → 0.5.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 +6 -5
- 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
|
@@ -113,6 +113,25 @@ function recordAt(value, field) {
|
|
|
113
113
|
function isUuid(value) {
|
|
114
114
|
return typeof value === "string" && UUID.test(value);
|
|
115
115
|
}
|
|
116
|
+
function decodePresenceAnswer(value) {
|
|
117
|
+
const registrationId = recordAt(value, "registration_id");
|
|
118
|
+
const claimId = recordAt(value, "claim_id");
|
|
119
|
+
const standing = recordAt(value, "standing");
|
|
120
|
+
const subjectId = recordAt(value, "subject_id");
|
|
121
|
+
if (!isUuid(registrationId) || !isUuid(claimId) || !["pending", "granted", "duplicate", "released"].includes(String(standing)) || subjectId !== void 0 && !isUuid(subjectId) || standing === "granted" && !isUuid(subjectId))
|
|
122
|
+
return protocol("presence reply carries no valid claim standing");
|
|
123
|
+
return { ok: true, value };
|
|
124
|
+
}
|
|
125
|
+
function managementAt(value) {
|
|
126
|
+
const field = recordAt(value, "management");
|
|
127
|
+
const state = stringAt(field, "state");
|
|
128
|
+
if (state === "managed") {
|
|
129
|
+
const subjectId = stringAt(field, "subject_id");
|
|
130
|
+
return subjectId === void 0 ? void 0 : { state, subject_id: subjectId };
|
|
131
|
+
}
|
|
132
|
+
if (state === "duplicate" || state === "pending" || state === "unmanaged") return { state };
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
116
135
|
function stringAt(value, field) {
|
|
117
136
|
if (typeof value !== "object" || value === null) return void 0;
|
|
118
137
|
const found = value[field];
|
|
@@ -133,7 +152,7 @@ function handoffAt(value) {
|
|
|
133
152
|
const content = stringAt(value, "content");
|
|
134
153
|
const published = numberAt(value, "published_at_unix_ms");
|
|
135
154
|
const correlation = typeof value === "object" && value !== null ? value.correlation_id : void 0;
|
|
136
|
-
if (version !== 1 || !isUuid(id) || !isUuid(stringAt(sender, "
|
|
155
|
+
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;
|
|
137
156
|
return value;
|
|
138
157
|
}
|
|
139
158
|
function handoffReceiptAt(value) {
|
|
@@ -142,7 +161,7 @@ function handoffReceiptAt(value) {
|
|
|
142
161
|
const recipient = recordAt(value, "recipient");
|
|
143
162
|
const generation = numberAt(recipient, "execution_generation");
|
|
144
163
|
const received = numberAt(value, "received_at_unix_ms");
|
|
145
|
-
if (version !== 1 || !isUuid(handoffId) || !isUuid(stringAt(recipient, "
|
|
164
|
+
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;
|
|
146
165
|
return value;
|
|
147
166
|
}
|
|
148
167
|
function writerBinding(value) {
|
|
@@ -296,7 +315,7 @@ function spawnEdge(value) {
|
|
|
296
315
|
const bound = recordAt(value, "bound");
|
|
297
316
|
const source = stringAt(bound, "source");
|
|
298
317
|
const incarnation = stringAt(bound, "incarnation");
|
|
299
|
-
const agentId = stringAt(bound, "
|
|
318
|
+
const agentId = stringAt(bound, "registration_id");
|
|
300
319
|
const exit = exitAt(recordAt(value, "exit_observation"));
|
|
301
320
|
return {
|
|
302
321
|
ok: true,
|
|
@@ -310,7 +329,7 @@ function spawnEdge(value) {
|
|
|
310
329
|
bound: {
|
|
311
330
|
source,
|
|
312
331
|
incarnation,
|
|
313
|
-
...isUuid(agentId) ? {
|
|
332
|
+
...isUuid(agentId) ? { registration_id: agentId } : {}
|
|
314
333
|
}
|
|
315
334
|
} : {},
|
|
316
335
|
...exit !== void 0 ? { exit_observation: exit } : {}
|
|
@@ -650,6 +669,22 @@ function createRadarClient(options = {}) {
|
|
|
650
669
|
return {
|
|
651
670
|
socketPath,
|
|
652
671
|
ping,
|
|
672
|
+
async presence(request) {
|
|
673
|
+
return withRegistry(async () => {
|
|
674
|
+
const answer = await call("agent.presence", { ...request });
|
|
675
|
+
if (!answer.ok) return answer;
|
|
676
|
+
return decodePresenceAnswer(answer.value);
|
|
677
|
+
});
|
|
678
|
+
},
|
|
679
|
+
async releasePresence(request) {
|
|
680
|
+
return withRegistry(async () => {
|
|
681
|
+
const answer = await call("agent.release", { ...request });
|
|
682
|
+
if (!answer.ok) return answer;
|
|
683
|
+
const decoded = decodePresenceAnswer(answer.value);
|
|
684
|
+
if (!decoded.ok) return decoded;
|
|
685
|
+
return decoded.value.standing === "released" ? decoded : protocol("release reply did not confirm the claim release");
|
|
686
|
+
});
|
|
687
|
+
},
|
|
653
688
|
async register(registration) {
|
|
654
689
|
return withRegistry(async () => {
|
|
655
690
|
const answer = await call("agent.register", {
|
|
@@ -665,15 +700,15 @@ function createRadarClient(options = {}) {
|
|
|
665
700
|
});
|
|
666
701
|
if (answer.ok === false) return answer;
|
|
667
702
|
const record = answer.value.registration;
|
|
668
|
-
const agentId = stringAt(record, "
|
|
669
|
-
if (!isUuid(agentId)) return protocol("registration reply carries no
|
|
670
|
-
return { ok: true, value: {
|
|
703
|
+
const agentId = stringAt(record, "registration_id");
|
|
704
|
+
if (!isUuid(agentId)) return protocol("registration reply carries no registration_id");
|
|
705
|
+
return { ok: true, value: { registration_id: agentId } };
|
|
671
706
|
});
|
|
672
707
|
},
|
|
673
708
|
async acquire(request) {
|
|
674
709
|
return withRegistryChannel(request.channel, async () => {
|
|
675
710
|
const answer = await call("agent.acquire", {
|
|
676
|
-
|
|
711
|
+
registration_id: request.registration_id,
|
|
677
712
|
channel: request.channel,
|
|
678
713
|
publisher: request.publisher,
|
|
679
714
|
...request.replace !== void 0 ? { replace: request.replace } : {}
|
|
@@ -702,7 +737,7 @@ function createRadarClient(options = {}) {
|
|
|
702
737
|
}
|
|
703
738
|
return withRegistryChannel(request.channel, async () => {
|
|
704
739
|
const answer = await call("agent.publish", {
|
|
705
|
-
|
|
740
|
+
registration_id: request.registration_id,
|
|
706
741
|
channel: request.channel,
|
|
707
742
|
writer_handle: request.writer_handle,
|
|
708
743
|
sequence: request.sequence,
|
|
@@ -721,7 +756,7 @@ function createRadarClient(options = {}) {
|
|
|
721
756
|
async context(request) {
|
|
722
757
|
return withRegistry(async () => {
|
|
723
758
|
const answer = await call("agent.context", {
|
|
724
|
-
|
|
759
|
+
registration_id: request.registration_id,
|
|
725
760
|
publisher: request.publisher,
|
|
726
761
|
...request.writer_handle !== void 0 ? { writer_handle: request.writer_handle } : {},
|
|
727
762
|
...request.replace !== void 0 ? { replace: request.replace } : {},
|
|
@@ -737,9 +772,14 @@ function createRadarClient(options = {}) {
|
|
|
737
772
|
if (writer === void 0)
|
|
738
773
|
return protocol("context reply carries no writer binding");
|
|
739
774
|
const warning = stringAt(answer.value, "warning");
|
|
775
|
+
const management = managementAt(answer.value);
|
|
740
776
|
return {
|
|
741
777
|
ok: true,
|
|
742
|
-
value: {
|
|
778
|
+
value: {
|
|
779
|
+
writer,
|
|
780
|
+
...warning !== void 0 ? { warning } : {},
|
|
781
|
+
...management !== void 0 ? { management } : {}
|
|
782
|
+
}
|
|
743
783
|
};
|
|
744
784
|
});
|
|
745
785
|
},
|
|
@@ -816,7 +856,7 @@ function createRadarClient(options = {}) {
|
|
|
816
856
|
message: "agent.get requires a canonical agent UUID"
|
|
817
857
|
};
|
|
818
858
|
return withRegistry(async () => {
|
|
819
|
-
const answer = await call("agent.get", {
|
|
859
|
+
const answer = await call("agent.get", { registration_id: agentId });
|
|
820
860
|
if (answer.ok === false) return answer;
|
|
821
861
|
return agentProcessAt(recordAt(answer.value, "agent"));
|
|
822
862
|
});
|
|
@@ -870,7 +910,7 @@ function createRadarClient(options = {}) {
|
|
|
870
910
|
async communicationPublish(request) {
|
|
871
911
|
return withContract(RADAR_COMMUNICATION_CONTRACT, async () => {
|
|
872
912
|
const answer = await call("communication.publish", {
|
|
873
|
-
|
|
913
|
+
sender_registration_id: request.sender_registration_id,
|
|
874
914
|
recipient_subject_id: request.recipient_subject_id,
|
|
875
915
|
...request.correlation_id !== void 0 ? { correlation_id: request.correlation_id } : {},
|
|
876
916
|
summary: request.summary,
|
|
@@ -1141,7 +1181,7 @@ function boundedRadarSnapshot(snapshot) {
|
|
|
1141
1181
|
function createRadarHandoffPort(client, publication, parentSubjectId = () => process.env.PI_RADAR_MANAGED_PARENT_SUBJECT_ID) {
|
|
1142
1182
|
async function agentId() {
|
|
1143
1183
|
const subject = await publication.subject();
|
|
1144
|
-
return subject === void 0 ? { ok: false, code: "absent", message: "this process has no current Radar registration" } : { ok: true, value: subject.
|
|
1184
|
+
return subject === void 0 ? { ok: false, code: "absent", message: "this process has no current Radar registration" } : { ok: true, value: subject.registration_id };
|
|
1145
1185
|
}
|
|
1146
1186
|
return {
|
|
1147
1187
|
async publish(request) {
|
|
@@ -1152,24 +1192,24 @@ function createRadarHandoffPort(client, publication, parentSubjectId = () => pro
|
|
|
1152
1192
|
return { ok: false, code: "absent", message: "this managed execution has no Radar parent subject" };
|
|
1153
1193
|
return client.communicationPublish({
|
|
1154
1194
|
...request,
|
|
1155
|
-
|
|
1195
|
+
sender_registration_id: identity.value,
|
|
1156
1196
|
recipient_subject_id: parent
|
|
1157
1197
|
});
|
|
1158
1198
|
},
|
|
1159
1199
|
async inbox() {
|
|
1160
1200
|
const identity = await agentId();
|
|
1161
1201
|
if (identity.ok === false) return identity;
|
|
1162
|
-
return client.communicationInbox({
|
|
1202
|
+
return client.communicationInbox({ registration_id: identity.value });
|
|
1163
1203
|
},
|
|
1164
1204
|
async get(handoff_id) {
|
|
1165
1205
|
const identity = await agentId();
|
|
1166
1206
|
if (identity.ok === false) return identity;
|
|
1167
|
-
return client.communicationGet({
|
|
1207
|
+
return client.communicationGet({ registration_id: identity.value, handoff_id });
|
|
1168
1208
|
},
|
|
1169
1209
|
async ack(handoff_id) {
|
|
1170
1210
|
const identity = await agentId();
|
|
1171
1211
|
if (identity.ok === false) return identity;
|
|
1172
|
-
return client.communicationAck({
|
|
1212
|
+
return client.communicationAck({ registration_id: identity.value, handoff_id });
|
|
1173
1213
|
}
|
|
1174
1214
|
};
|
|
1175
1215
|
}
|
|
@@ -1190,77 +1230,7 @@ import {
|
|
|
1190
1230
|
writeSync
|
|
1191
1231
|
} from "node:fs";
|
|
1192
1232
|
import { dirname as dirname2, join as join2, parse, resolve, sep } from "node:path";
|
|
1193
|
-
|
|
1194
|
-
// extension/radar-session-marker.ts
|
|
1195
|
-
var RADAR_LAUNCH_MARKER_TYPE = "pi-radar.launch-identity";
|
|
1196
|
-
var RADAR_LAUNCH_MARKER_VERSION = 1;
|
|
1197
|
-
var RADAR_MAX_EXECUTION_GENERATION = 4294967295;
|
|
1198
|
-
var RADAR_MANAGED_SUBJECT_ENV = "PI_RADAR_MANAGED_SUBJECT_ID";
|
|
1199
|
-
var RADAR_MANAGED_LAUNCH_ENV = "PI_RADAR_MANAGED_LAUNCH_ID";
|
|
1200
|
-
var RADAR_MANAGED_GENERATION_ENV = "PI_RADAR_MANAGED_EXECUTION_GENERATION";
|
|
1201
|
-
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;
|
|
1202
|
-
function decodeRadarLaunchMarker(value) {
|
|
1203
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
1204
|
-
const record = value;
|
|
1205
|
-
if (Object.keys(record).sort().join(",") !== "execution_generation,launch_id,subject_id,version") {
|
|
1206
|
-
return void 0;
|
|
1207
|
-
}
|
|
1208
|
-
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) {
|
|
1209
|
-
return void 0;
|
|
1210
|
-
}
|
|
1211
|
-
return {
|
|
1212
|
-
version: RADAR_LAUNCH_MARKER_VERSION,
|
|
1213
|
-
subject_id: record.subject_id,
|
|
1214
|
-
launch_id: record.launch_id,
|
|
1215
|
-
execution_generation: record.execution_generation
|
|
1216
|
-
};
|
|
1217
|
-
}
|
|
1218
|
-
function appendRadarLaunchMarker(appendEntry, marker) {
|
|
1219
|
-
const validated = decodeRadarLaunchMarker(marker);
|
|
1220
|
-
if (!validated) throw new Error("invalid Radar launch identity marker");
|
|
1221
|
-
appendEntry(RADAR_LAUNCH_MARKER_TYPE, validated);
|
|
1222
|
-
}
|
|
1223
|
-
function latestRadarLaunchMarker(branch) {
|
|
1224
|
-
let latest;
|
|
1225
|
-
for (const entry of branch) {
|
|
1226
|
-
if (entry.type === "custom" && entry.customType === RADAR_LAUNCH_MARKER_TYPE) {
|
|
1227
|
-
latest = entry;
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
if (!latest) return { status: "absent" };
|
|
1231
|
-
const marker = decodeRadarLaunchMarker(latest.data);
|
|
1232
|
-
return marker ? { status: "valid", marker } : { status: "invalid" };
|
|
1233
|
-
}
|
|
1234
|
-
function radarLaunchMarkerFromEnvironment(env = process.env) {
|
|
1235
|
-
const rawGeneration = env[RADAR_MANAGED_GENERATION_ENV];
|
|
1236
|
-
if (env[RADAR_MANAGED_SUBJECT_ENV] === void 0 || env[RADAR_MANAGED_LAUNCH_ENV] === void 0 || rawGeneration === void 0 || !/^[1-9][0-9]*$/.test(rawGeneration)) {
|
|
1237
|
-
return void 0;
|
|
1238
|
-
}
|
|
1239
|
-
return decodeRadarLaunchMarker({
|
|
1240
|
-
version: RADAR_LAUNCH_MARKER_VERSION,
|
|
1241
|
-
subject_id: env[RADAR_MANAGED_SUBJECT_ENV],
|
|
1242
|
-
launch_id: env[RADAR_MANAGED_LAUNCH_ENV],
|
|
1243
|
-
execution_generation: Number(rawGeneration)
|
|
1244
|
-
});
|
|
1245
|
-
}
|
|
1246
|
-
function activeRadarLaunchMarker(host) {
|
|
1247
|
-
if (!host.sessionManager) return { status: "absent" };
|
|
1248
|
-
return latestRadarLaunchMarker(host.sessionManager.getBranch());
|
|
1249
|
-
}
|
|
1250
|
-
function persistRadarLaunchMarker(host, env = process.env) {
|
|
1251
|
-
const marker = radarLaunchMarkerFromEnvironment(env);
|
|
1252
|
-
if (!marker) return "absent";
|
|
1253
|
-
if (!host.appendEntry || !host.sessionManager) return "unsupported";
|
|
1254
|
-
const current = latestRadarLaunchMarker(host.sessionManager.getBranch());
|
|
1255
|
-
if (current.status === "valid" && sameMarker(current.marker, marker)) return "unchanged";
|
|
1256
|
-
appendRadarLaunchMarker(host.appendEntry, marker);
|
|
1257
|
-
return "written";
|
|
1258
|
-
}
|
|
1259
|
-
function sameMarker(a, b) {
|
|
1260
|
-
return a.version === b.version && a.subject_id === b.subject_id && a.launch_id === b.launch_id && a.execution_generation === b.execution_generation;
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
// extension/radar-publication.ts
|
|
1233
|
+
var DUPLICATE_SESSION_DIAGNOSTIC = "Radar rejected this session claim as a duplicate; reload or resume the session before retrying";
|
|
1264
1234
|
var RADAR_PUBLICATION_VERSION = 1;
|
|
1265
1235
|
var RADAR_LEASE_MS = 3e4;
|
|
1266
1236
|
var RADAR_HEARTBEAT_MS = 15e3;
|
|
@@ -1285,7 +1255,7 @@ function readProcessBirth() {
|
|
|
1285
1255
|
return void 0;
|
|
1286
1256
|
}
|
|
1287
1257
|
}
|
|
1288
|
-
var RECORD_NAME = /^(?:subjects|channels|context|bindings)\/[a-z0-9-]{1,64}\.json$/;
|
|
1258
|
+
var RECORD_NAME = /^(?:registrations|presence|subjects|channels|context|bindings)\/[a-z0-9-]{1,64}\.json$/;
|
|
1289
1259
|
var MAX_RECORD_BYTES = 64 * 1024;
|
|
1290
1260
|
var PRIVATE_MODE = 448;
|
|
1291
1261
|
var RECORD_MODE = 384;
|
|
@@ -1567,39 +1537,6 @@ function pendingAt(value, keys = PENDING_KEYS, codec = executionCodec) {
|
|
|
1567
1537
|
return void 0;
|
|
1568
1538
|
return { sequence, snapshot, lease_ms: lease, observed_at: observed };
|
|
1569
1539
|
}
|
|
1570
|
-
var CONTEXT_PENDING_KEYS = "lease_ms,observed_at,sequence,session";
|
|
1571
|
-
var CONTEXT_PENDING_MARKED_KEYS = "launch_identity,lease_ms,observed_at,sequence,session";
|
|
1572
|
-
var CONTEXT_ACCEPTED_KEYS = "lease_ms,observed_at,sent_at,sequence,session";
|
|
1573
|
-
var CONTEXT_ACCEPTED_MARKED_KEYS = "launch_identity,lease_ms,observed_at,sent_at,sequence,session";
|
|
1574
|
-
function sessionAt(value) {
|
|
1575
|
-
if (typeof value !== "object" || value === null) return void 0;
|
|
1576
|
-
const found = value.session;
|
|
1577
|
-
if (found === null) return null;
|
|
1578
|
-
return typeof found === "string" ? found : void 0;
|
|
1579
|
-
}
|
|
1580
|
-
function sameLaunchIdentity(a, b) {
|
|
1581
|
-
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;
|
|
1582
|
-
}
|
|
1583
|
-
function contextReportAt(value, keys, markedKeys) {
|
|
1584
|
-
const marked = exactKeys(value, markedKeys);
|
|
1585
|
-
if (!exactKeys(value, keys) && !marked) return void 0;
|
|
1586
|
-
const sequence = numberAt2(value, "sequence");
|
|
1587
|
-
const lease = numberAt2(value, "lease_ms");
|
|
1588
|
-
const observed = textAt(value, "observed_at");
|
|
1589
|
-
const session = sessionAt(value);
|
|
1590
|
-
if (sequence === void 0 || sequence < 1) return void 0;
|
|
1591
|
-
if (lease === void 0 || observed === void 0 || session === void 0)
|
|
1592
|
-
return void 0;
|
|
1593
|
-
const marker = marked ? decodeRadarLaunchMarker(value.launch_identity) : void 0;
|
|
1594
|
-
if (marked && marker === void 0) return void 0;
|
|
1595
|
-
return {
|
|
1596
|
-
sequence,
|
|
1597
|
-
session,
|
|
1598
|
-
lease_ms: lease,
|
|
1599
|
-
observed_at: observed,
|
|
1600
|
-
...marker !== void 0 ? { launch_identity: marker } : {}
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
1540
|
function createChannelWriter(input) {
|
|
1604
1541
|
const { store, client, scheduler, recordName, channel, publisher } = input;
|
|
1605
1542
|
const codec = input.codec ?? executionCodec;
|
|
@@ -1615,7 +1552,7 @@ function createChannelWriter(input) {
|
|
|
1615
1552
|
function blank(agentId) {
|
|
1616
1553
|
return {
|
|
1617
1554
|
version: RADAR_PUBLICATION_VERSION,
|
|
1618
|
-
|
|
1555
|
+
registration_id: agentId,
|
|
1619
1556
|
channel,
|
|
1620
1557
|
publisher,
|
|
1621
1558
|
sequence: 0
|
|
@@ -1623,7 +1560,7 @@ function createChannelWriter(input) {
|
|
|
1623
1560
|
}
|
|
1624
1561
|
function loadRecord() {
|
|
1625
1562
|
const value = store.read(recordName);
|
|
1626
|
-
const agentId = textAt(value, "
|
|
1563
|
+
const agentId = textAt(value, "registration_id");
|
|
1627
1564
|
const storedPublisher = recordAt2(value, "publisher");
|
|
1628
1565
|
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)
|
|
1629
1566
|
return blank("");
|
|
@@ -1638,7 +1575,7 @@ function createChannelWriter(input) {
|
|
|
1638
1575
|
const sentAt = numberAt2(acceptedValue, "sent_at");
|
|
1639
1576
|
return {
|
|
1640
1577
|
version: RADAR_PUBLICATION_VERSION,
|
|
1641
|
-
|
|
1578
|
+
registration_id: agentId,
|
|
1642
1579
|
channel,
|
|
1643
1580
|
publisher,
|
|
1644
1581
|
...handle !== void 0 && generation !== void 0 ? { writer: { handle, generation } } : {},
|
|
@@ -1679,12 +1616,12 @@ function createChannelWriter(input) {
|
|
|
1679
1616
|
if (record.writer !== void 0) return true;
|
|
1680
1617
|
const agentId = await input.subject(recovering);
|
|
1681
1618
|
if (agentId === void 0) return false;
|
|
1682
|
-
if (record.
|
|
1619
|
+
if (record.registration_id !== agentId) {
|
|
1683
1620
|
record = blank(agentId);
|
|
1684
1621
|
save();
|
|
1685
1622
|
}
|
|
1686
1623
|
const answer = await client.acquire({
|
|
1687
|
-
|
|
1624
|
+
registration_id: agentId,
|
|
1688
1625
|
channel,
|
|
1689
1626
|
publisher
|
|
1690
1627
|
});
|
|
@@ -1714,7 +1651,7 @@ function createChannelWriter(input) {
|
|
|
1714
1651
|
const writer = record.writer;
|
|
1715
1652
|
if (writer === void 0) return;
|
|
1716
1653
|
const answer = await client.publish({
|
|
1717
|
-
|
|
1654
|
+
registration_id: record.registration_id,
|
|
1718
1655
|
channel,
|
|
1719
1656
|
writer_handle: writer.handle,
|
|
1720
1657
|
sequence: pending.sequence,
|
|
@@ -1808,9 +1745,9 @@ function createChannelWriter(input) {
|
|
|
1808
1745
|
stopPump();
|
|
1809
1746
|
const writer = record.writer;
|
|
1810
1747
|
if (writer === void 0) return;
|
|
1811
|
-
const agentId = record.
|
|
1748
|
+
const agentId = record.registration_id;
|
|
1812
1749
|
try {
|
|
1813
|
-
void client.retire({
|
|
1750
|
+
void client.retire({ registration_id: agentId, channel, writer_handle: writer.handle }).then((answer) => {
|
|
1814
1751
|
if (answer.ok === true) {
|
|
1815
1752
|
try {
|
|
1816
1753
|
record.retired_at = new Date(scheduler.now()).toISOString();
|
|
@@ -1833,214 +1770,127 @@ function createChannelWriter(input) {
|
|
|
1833
1770
|
diagnostic: () => record.diagnostic
|
|
1834
1771
|
};
|
|
1835
1772
|
}
|
|
1836
|
-
function
|
|
1837
|
-
const { store, client, scheduler, recordName
|
|
1838
|
-
let
|
|
1839
|
-
let
|
|
1840
|
-
let
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
function blank(agentId) {
|
|
1848
|
-
return {
|
|
1849
|
-
version: RADAR_PUBLICATION_VERSION,
|
|
1850
|
-
agent_id: agentId,
|
|
1851
|
-
publisher,
|
|
1852
|
-
sequence: 0
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
function loadRecord() {
|
|
1856
|
-
const value = store.read(recordName);
|
|
1857
|
-
const agentId = textAt(value, "agent_id");
|
|
1858
|
-
const storedPublisher = recordAt2(value, "publisher");
|
|
1859
|
-
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)
|
|
1860
|
-
return blank("");
|
|
1861
|
-
const writer = recordAt2(value, "writer");
|
|
1862
|
-
const handle = textAt(writer, "handle");
|
|
1863
|
-
const generation = numberAt2(writer, "generation");
|
|
1864
|
-
if (writer !== void 0 && (!exactKeys(writer, WRITER_KEYS) || !isUuid(handle) || generation === void 0))
|
|
1865
|
-
return blank(agentId);
|
|
1866
|
-
const pending = contextReportAt(
|
|
1867
|
-
recordAt2(value, "pending"),
|
|
1868
|
-
CONTEXT_PENDING_KEYS,
|
|
1869
|
-
CONTEXT_PENDING_MARKED_KEYS
|
|
1870
|
-
);
|
|
1871
|
-
const acceptedValue = recordAt2(value, "accepted");
|
|
1872
|
-
const accepted = contextReportAt(
|
|
1873
|
-
acceptedValue,
|
|
1874
|
-
CONTEXT_ACCEPTED_KEYS,
|
|
1875
|
-
CONTEXT_ACCEPTED_MARKED_KEYS
|
|
1876
|
-
);
|
|
1877
|
-
const sentAt = numberAt2(acceptedValue, "sent_at");
|
|
1878
|
-
return {
|
|
1879
|
-
version: RADAR_PUBLICATION_VERSION,
|
|
1880
|
-
agent_id: agentId,
|
|
1881
|
-
publisher,
|
|
1882
|
-
...handle !== void 0 && generation !== void 0 ? { writer: { handle, generation } } : {},
|
|
1883
|
-
sequence: numberAt2(value, "sequence") ?? 0,
|
|
1884
|
-
...pending !== void 0 ? { pending } : {},
|
|
1885
|
-
...accepted !== void 0 && sentAt !== void 0 ? { accepted: { ...accepted, sent_at: sentAt } } : {},
|
|
1886
|
-
...textAt(value, "diagnostic") !== void 0 ? { diagnostic: textAt(value, "diagnostic") } : {}
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
1889
|
-
function note(message) {
|
|
1890
|
-
if (record.diagnostic !== void 0) return;
|
|
1891
|
-
record.diagnostic = message.slice(0, 256);
|
|
1892
|
-
save();
|
|
1773
|
+
function createPresenceReporter(input) {
|
|
1774
|
+
const { store, client, scheduler, recordName } = input;
|
|
1775
|
+
let state;
|
|
1776
|
+
let standing;
|
|
1777
|
+
let diagnostic;
|
|
1778
|
+
try {
|
|
1779
|
+
const saved = store.read(recordName);
|
|
1780
|
+
if (saved?.version === 2 && isUuid(saved.claim_id) && isUuid(saved.session) && Array.isArray(saved.releases))
|
|
1781
|
+
state = saved;
|
|
1782
|
+
} catch (error) {
|
|
1783
|
+
diagnostic = `presence storage unavailable: ${String(error)}`;
|
|
1893
1784
|
}
|
|
1785
|
+
let timer;
|
|
1786
|
+
let stopped = false;
|
|
1787
|
+
let running;
|
|
1894
1788
|
function save() {
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
function startPump() {
|
|
1903
|
-
if (pump !== void 0 || stopped || fenced) return;
|
|
1904
|
-
pump = scheduler.setInterval(() => kick(), input.heartbeatMs);
|
|
1905
|
-
pump.unref?.();
|
|
1906
|
-
}
|
|
1907
|
-
function stopPump() {
|
|
1908
|
-
if (pump === void 0) return;
|
|
1909
|
-
scheduler.clearInterval(pump);
|
|
1910
|
-
pump = void 0;
|
|
1789
|
+
try {
|
|
1790
|
+
if (state) store.write(recordName, state);
|
|
1791
|
+
return true;
|
|
1792
|
+
} catch (error) {
|
|
1793
|
+
diagnostic = `presence storage unavailable: ${String(error)}`;
|
|
1794
|
+
return false;
|
|
1795
|
+
}
|
|
1911
1796
|
}
|
|
1912
|
-
async function
|
|
1913
|
-
if (
|
|
1914
|
-
const
|
|
1915
|
-
if (
|
|
1916
|
-
|
|
1917
|
-
|
|
1797
|
+
async function releasePending() {
|
|
1798
|
+
if (!state) return;
|
|
1799
|
+
const registration = await input.registration();
|
|
1800
|
+
if (!registration?.process) return;
|
|
1801
|
+
for (const release of [...state.releases]) {
|
|
1802
|
+
const answer = await client.releasePresence({ ...release, process: registration.process });
|
|
1803
|
+
if (!answer.ok) return;
|
|
1804
|
+
state.releases = state.releases.filter((r) => r.claim_id !== release.claim_id);
|
|
1918
1805
|
save();
|
|
1919
1806
|
}
|
|
1920
|
-
return true;
|
|
1921
1807
|
}
|
|
1922
|
-
function
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1808
|
+
function schedule() {
|
|
1809
|
+
if (stopped || timer) return;
|
|
1810
|
+
timer = scheduler.setTimeout(() => {
|
|
1811
|
+
timer = void 0;
|
|
1812
|
+
void ensure();
|
|
1813
|
+
}, input.heartbeatMs);
|
|
1814
|
+
timer.unref?.();
|
|
1815
|
+
}
|
|
1816
|
+
async function ensure() {
|
|
1817
|
+
if (running) return running;
|
|
1818
|
+
if (stopped || !state) return void 0;
|
|
1819
|
+
const claim = state;
|
|
1820
|
+
if (!save()) return void 0;
|
|
1821
|
+
running = (async () => {
|
|
1822
|
+
await releasePending();
|
|
1823
|
+
const registration = await input.registration();
|
|
1824
|
+
if (!registration?.process || state !== claim || stopped) return void 0;
|
|
1825
|
+
const answer = await client.presence({
|
|
1826
|
+
...registration,
|
|
1827
|
+
process: registration.process,
|
|
1828
|
+
session_id: claim.session,
|
|
1829
|
+
claim_id: claim.claim_id,
|
|
1830
|
+
...claim.registration_id ? { registration_id: claim.registration_id } : {},
|
|
1831
|
+
...claim.subject_id ? { subject_id: claim.subject_id } : {}
|
|
1832
|
+
});
|
|
1833
|
+
if (state !== claim) return void 0;
|
|
1834
|
+
if (!answer.ok) {
|
|
1835
|
+
if (!["absent", "timeout", "transport"].includes(answer.code)) diagnostic = answer.message;
|
|
1836
|
+
return void 0;
|
|
1939
1837
|
}
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
handle: answer.value.writer.handle,
|
|
1945
|
-
generation: answer.value.writer.generation
|
|
1946
|
-
};
|
|
1947
|
-
record.sequence = Math.max(record.sequence, answer.value.writer.sequence);
|
|
1948
|
-
record.accepted = {
|
|
1949
|
-
...pending,
|
|
1950
|
-
sent_at: answer.value.warning === void 0 ? scheduler.now() : record.accepted?.sent_at ?? scheduler.now()
|
|
1951
|
-
};
|
|
1952
|
-
record.pending = void 0;
|
|
1838
|
+
claim.registration_id = answer.value.registration_id;
|
|
1839
|
+
claim.subject_id = answer.value.standing === "granted" ? answer.value.subject_id ?? void 0 : void 0;
|
|
1840
|
+
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" };
|
|
1841
|
+
diagnostic = answer.value.standing === "duplicate" ? DUPLICATE_SESSION_DIAGNOSTIC : void 0;
|
|
1953
1842
|
save();
|
|
1954
|
-
return;
|
|
1955
|
-
}
|
|
1956
|
-
if (answer.code === "refused" || answer.code === "bad_params" || // A daemon that speaks the registry but does not serve this record would
|
|
1957
|
-
// refuse every retry the same way; one diagnostic beats a silent retry
|
|
1958
|
-
// loop once per heartbeat.
|
|
1959
|
-
answer.code === "unknown_method") {
|
|
1960
|
-
fence(answer.message);
|
|
1961
|
-
return;
|
|
1962
|
-
}
|
|
1963
|
-
if (answer.code === "not_found") {
|
|
1964
|
-
record = blank("");
|
|
1965
|
-
recovering = true;
|
|
1966
|
-
save();
|
|
1967
|
-
return;
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
async function stage(session, launchIdentity) {
|
|
1971
|
-
const pending = {
|
|
1972
|
-
sequence: record.sequence + 1,
|
|
1973
|
-
session,
|
|
1974
|
-
lease_ms: input.leaseMs,
|
|
1975
|
-
observed_at: new Date(scheduler.now()).toISOString(),
|
|
1976
|
-
...launchIdentity !== void 0 ? { launch_identity: launchIdentity } : {}
|
|
1977
|
-
};
|
|
1978
|
-
record.pending = pending;
|
|
1979
|
-
save();
|
|
1980
|
-
await send(pending);
|
|
1981
|
-
}
|
|
1982
|
-
async function drainOnce() {
|
|
1983
|
-
if (fenced) return;
|
|
1984
|
-
if (record.pending !== void 0) {
|
|
1985
|
-
await send(record.pending);
|
|
1986
|
-
return;
|
|
1987
|
-
}
|
|
1988
|
-
if (desired === void 0) return;
|
|
1989
|
-
if (!await ensureSubject()) return;
|
|
1990
|
-
if (fenced) return;
|
|
1991
|
-
if (record.writer === void 0 || record.accepted === void 0 || record.accepted.session !== desired || !sameLaunchIdentity(record.accepted.launch_identity, desiredMarker)) {
|
|
1992
|
-
await stage(desired, desiredMarker);
|
|
1993
|
-
return;
|
|
1994
|
-
}
|
|
1995
|
-
if (heartbeatDue()) await stage(record.accepted.session, desiredMarker);
|
|
1996
|
-
}
|
|
1997
|
-
async function drain() {
|
|
1998
|
-
if (running || stopped || fenced) return;
|
|
1999
|
-
running = true;
|
|
1843
|
+
return claim.registration_id;
|
|
1844
|
+
})();
|
|
2000
1845
|
try {
|
|
2001
|
-
await
|
|
1846
|
+
return await running;
|
|
2002
1847
|
} catch (error) {
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
try {
|
|
2006
|
-
note(`context storage failure: ${String(error).slice(0, 180)}`);
|
|
2007
|
-
} catch {
|
|
2008
|
-
}
|
|
1848
|
+
diagnostic = `presence unavailable: ${String(error)}`;
|
|
1849
|
+
return void 0;
|
|
2009
1850
|
} finally {
|
|
2010
|
-
running =
|
|
2011
|
-
if (
|
|
2012
|
-
|
|
2013
|
-
kick();
|
|
2014
|
-
}
|
|
1851
|
+
running = void 0;
|
|
1852
|
+
if (!stopped && state !== claim) void ensure();
|
|
1853
|
+
else schedule();
|
|
2015
1854
|
}
|
|
2016
1855
|
}
|
|
2017
|
-
function kick() {
|
|
2018
|
-
if (stopped || fenced) return;
|
|
2019
|
-
startPump();
|
|
2020
|
-
if (running) {
|
|
2021
|
-
again = true;
|
|
2022
|
-
return;
|
|
2023
|
-
}
|
|
2024
|
-
void drain().catch(() => void 0);
|
|
2025
|
-
}
|
|
2026
1856
|
return {
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
1857
|
+
report(session) {
|
|
1858
|
+
const releases = [...state?.releases ?? []];
|
|
1859
|
+
if (state?.registration_id && !releases.some((release) => release.claim_id === state.claim_id)) {
|
|
1860
|
+
releases.push({ registration_id: state.registration_id, claim_id: state.claim_id });
|
|
1861
|
+
}
|
|
1862
|
+
standing = void 0;
|
|
1863
|
+
state = { version: 2, session, claim_id: randomUUID2(), releases };
|
|
1864
|
+
save();
|
|
1865
|
+
stopped = false;
|
|
1866
|
+
void ensure();
|
|
1867
|
+
},
|
|
1868
|
+
ensure,
|
|
1869
|
+
async release() {
|
|
1870
|
+
const releasing = state;
|
|
1871
|
+
standing = void 0;
|
|
1872
|
+
stopped = true;
|
|
1873
|
+
if (timer) scheduler.clearTimeout(timer);
|
|
1874
|
+
timer = void 0;
|
|
1875
|
+
if (running) await running;
|
|
1876
|
+
if (state === releasing) standing = void 0;
|
|
1877
|
+
if (releasing?.registration_id && !releasing.releases.some((r) => r.claim_id === releasing.claim_id)) {
|
|
1878
|
+
releasing.releases.push({ registration_id: releasing.registration_id, claim_id: releasing.claim_id });
|
|
1879
|
+
if (!save()) return;
|
|
1880
|
+
}
|
|
1881
|
+
await releasePending();
|
|
2034
1882
|
},
|
|
2035
1883
|
stop() {
|
|
2036
1884
|
stopped = true;
|
|
2037
|
-
|
|
1885
|
+
if (timer) scheduler.clearTimeout(timer);
|
|
1886
|
+
timer = void 0;
|
|
2038
1887
|
},
|
|
2039
1888
|
reopen() {
|
|
2040
1889
|
stopped = false;
|
|
2041
|
-
|
|
1890
|
+
void ensure();
|
|
2042
1891
|
},
|
|
2043
|
-
|
|
1892
|
+
management: () => standing,
|
|
1893
|
+
diagnostic: () => diagnostic
|
|
2044
1894
|
};
|
|
2045
1895
|
}
|
|
2046
1896
|
var STORE_IDENTITY = /* @__PURE__ */ new WeakMap();
|
|
@@ -2069,10 +1919,13 @@ function unavailablePublication(error) {
|
|
|
2069
1919
|
};
|
|
2070
1920
|
return {
|
|
2071
1921
|
execution: writer,
|
|
2072
|
-
|
|
2073
|
-
|
|
1922
|
+
presence: {
|
|
1923
|
+
report: () => void 0,
|
|
1924
|
+
ensure: async () => void 0,
|
|
1925
|
+
release: async () => void 0,
|
|
2074
1926
|
stop: () => void 0,
|
|
2075
1927
|
reopen: () => void 0,
|
|
1928
|
+
management: () => void 0,
|
|
2076
1929
|
diagnostic: () => diagnostic
|
|
2077
1930
|
},
|
|
2078
1931
|
facts: { ...writer, update: () => void 0 },
|
|
@@ -2099,33 +1952,29 @@ function createRadarPublicationInner(options) {
|
|
|
2099
1952
|
cached.reopen();
|
|
2100
1953
|
return cached;
|
|
2101
1954
|
}
|
|
2102
|
-
const
|
|
1955
|
+
const registrationName = `registrations/${createHash("sha256").update(`${options.registration.source}\0${incarnation}`).digest("hex").slice(0, 32)}.json`;
|
|
2103
1956
|
const channelRecord = (channel, target) => `channels/${createHash("sha256").update(`${channel}\0${incarnation}\0${target ?? ""}`).digest("hex").slice(0, 32)}.json`;
|
|
2104
|
-
const
|
|
2105
|
-
function
|
|
2106
|
-
const value = store.read(
|
|
1957
|
+
const presenceRecord = `presence/${createHash("sha256").update(`presence\0${incarnation}`).digest("hex").slice(0, 32)}.json`;
|
|
1958
|
+
function readRegistration() {
|
|
1959
|
+
const value = store.read(registrationName);
|
|
2107
1960
|
const registration = recordAt2(value, "registration");
|
|
2108
1961
|
if (numberAt2(value, "version") !== RADAR_PUBLICATION_VERSION || textAt(registration, "source") !== options.registration.source || textAt(registration, "incarnation") !== incarnation)
|
|
2109
1962
|
return void 0;
|
|
2110
|
-
const storedAgentId = textAt(value, "
|
|
1963
|
+
const storedAgentId = textAt(value, "registration_id");
|
|
2111
1964
|
return {
|
|
2112
1965
|
version: RADAR_PUBLICATION_VERSION,
|
|
2113
1966
|
registration,
|
|
2114
|
-
...storedAgentId !== void 0 && isUuid(storedAgentId) ? {
|
|
1967
|
+
...storedAgentId !== void 0 && isUuid(storedAgentId) ? { registration_id: storedAgentId } : {}
|
|
2115
1968
|
};
|
|
2116
1969
|
}
|
|
2117
|
-
const stored =
|
|
2118
|
-
let
|
|
1970
|
+
const stored = readRegistration();
|
|
1971
|
+
let processRecord = stored;
|
|
2119
1972
|
let registrationDiagnostic;
|
|
2120
1973
|
let registrationRecord;
|
|
2121
1974
|
async function ensureRegistration() {
|
|
2122
|
-
if (
|
|
1975
|
+
if (processRecord !== void 0) return processRecord;
|
|
2123
1976
|
registrationRecord ??= (async () => {
|
|
2124
1977
|
const resolution = options.location ? await options.location() : { state: "absent", reason: "this process publishes no location" };
|
|
2125
|
-
if (resolution.state === "pending") {
|
|
2126
|
-
registrationDiagnostic = `location bootstrap pending: ${resolution.reason}`.slice(0, 256);
|
|
2127
|
-
return void 0;
|
|
2128
|
-
}
|
|
2129
1978
|
const built = {
|
|
2130
1979
|
version: RADAR_PUBLICATION_VERSION,
|
|
2131
1980
|
registration: {
|
|
@@ -2136,13 +1985,13 @@ function createRadarPublicationInner(options) {
|
|
|
2136
1985
|
}
|
|
2137
1986
|
};
|
|
2138
1987
|
try {
|
|
2139
|
-
store.write(
|
|
1988
|
+
store.write(registrationName, built);
|
|
2140
1989
|
} catch (error) {
|
|
2141
1990
|
registrationDiagnostic ??= `private storage unavailable: ${String(error)}`.slice(0, 256);
|
|
2142
1991
|
return void 0;
|
|
2143
1992
|
}
|
|
2144
1993
|
registrationDiagnostic = void 0;
|
|
2145
|
-
|
|
1994
|
+
processRecord = built;
|
|
2146
1995
|
return built;
|
|
2147
1996
|
})();
|
|
2148
1997
|
try {
|
|
@@ -2151,11 +2000,10 @@ function createRadarPublicationInner(options) {
|
|
|
2151
2000
|
registrationRecord = void 0;
|
|
2152
2001
|
}
|
|
2153
2002
|
}
|
|
2154
|
-
let agentId = stored?.
|
|
2003
|
+
let agentId = stored?.registration_id;
|
|
2155
2004
|
let subjectReady;
|
|
2156
2005
|
async function ensureSubject(recheck) {
|
|
2157
|
-
if (recheck
|
|
2158
|
-
if (agentId !== void 0) return agentId;
|
|
2006
|
+
if (!recheck && agentId !== void 0) return agentId;
|
|
2159
2007
|
subjectReady ??= (async () => {
|
|
2160
2008
|
const ready = await client.ping();
|
|
2161
2009
|
if (ready.ok === false) {
|
|
@@ -2165,18 +2013,11 @@ function createRadarPublicationInner(options) {
|
|
|
2165
2013
|
}
|
|
2166
2014
|
const record = await ensureRegistration();
|
|
2167
2015
|
if (record === void 0) return void 0;
|
|
2168
|
-
const
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
|
-
if (answer.code !== "absent" && answer.code !== "timeout" && answer.code !== "transport")
|
|
2174
|
-
registrationDiagnostic ??= `subject registration refused: ${answer.message}`.slice(0, 256);
|
|
2175
|
-
return void 0;
|
|
2176
|
-
}
|
|
2177
|
-
agentId = answer.value.agent_id;
|
|
2178
|
-
subject = { ...record, agent_id: agentId };
|
|
2179
|
-
store.write(subjectName, subject);
|
|
2016
|
+
const registered = await presence.ensure();
|
|
2017
|
+
if (registered === void 0) return void 0;
|
|
2018
|
+
agentId = registered;
|
|
2019
|
+
processRecord = { ...record, registration_id: agentId };
|
|
2020
|
+
store.write(registrationName, processRecord);
|
|
2180
2021
|
if (options.binding !== void 0) writeBinding(options.binding);
|
|
2181
2022
|
return agentId;
|
|
2182
2023
|
})();
|
|
@@ -2190,7 +2031,7 @@ function createRadarPublicationInner(options) {
|
|
|
2190
2031
|
if (agentId === void 0) return;
|
|
2191
2032
|
store.write(`bindings/${binding.key}.json`, {
|
|
2192
2033
|
version: RADAR_PUBLICATION_VERSION,
|
|
2193
|
-
|
|
2034
|
+
registration_id: agentId,
|
|
2194
2035
|
incarnation,
|
|
2195
2036
|
run: binding.run,
|
|
2196
2037
|
owner: binding.owner,
|
|
@@ -2214,14 +2055,22 @@ function createRadarPublicationInner(options) {
|
|
|
2214
2055
|
leaseMs: options.leaseMs ?? RADAR_LEASE_MS,
|
|
2215
2056
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
2216
2057
|
});
|
|
2217
|
-
const
|
|
2058
|
+
const presence = createPresenceReporter({
|
|
2218
2059
|
store,
|
|
2219
2060
|
client,
|
|
2220
2061
|
scheduler,
|
|
2221
|
-
recordName:
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2062
|
+
recordName: presenceRecord,
|
|
2063
|
+
registration: async () => {
|
|
2064
|
+
const record = await ensureRegistration();
|
|
2065
|
+
if (!record) return void 0;
|
|
2066
|
+
const location = await options.location?.();
|
|
2067
|
+
const { location: _initialLocation, ...identity } = record.registration;
|
|
2068
|
+
return {
|
|
2069
|
+
...identity,
|
|
2070
|
+
...location?.state === "resolved" ? { location: location.location } : {},
|
|
2071
|
+
...spawnToken ? { spawn_token: spawnToken } : {}
|
|
2072
|
+
};
|
|
2073
|
+
},
|
|
2225
2074
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
2226
2075
|
});
|
|
2227
2076
|
const facts = createChannelWriter({
|
|
@@ -2239,7 +2088,7 @@ function createRadarPublicationInner(options) {
|
|
|
2239
2088
|
const assignmentWriters = /* @__PURE__ */ new Map();
|
|
2240
2089
|
const publication = {
|
|
2241
2090
|
execution,
|
|
2242
|
-
|
|
2091
|
+
presence,
|
|
2243
2092
|
facts,
|
|
2244
2093
|
assignment(target, reportingOwner) {
|
|
2245
2094
|
const existing = assignmentWriters.get(target);
|
|
@@ -2254,7 +2103,7 @@ function createRadarPublicationInner(options) {
|
|
|
2254
2103
|
publisher: publisher("herdsman-owner", reportingOwner),
|
|
2255
2104
|
codec: assignmentCodec,
|
|
2256
2105
|
// The owner publishes about a subject it did not register: the exact
|
|
2257
|
-
//
|
|
2106
|
+
// registration_id from the child's sidecar is the whole correlation.
|
|
2258
2107
|
subject: async () => target,
|
|
2259
2108
|
leaseMs: options.leaseMs ?? RADAR_LEASE_MS,
|
|
2260
2109
|
heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS
|
|
@@ -2274,7 +2123,7 @@ function createRadarPublicationInner(options) {
|
|
|
2274
2123
|
registrationDiagnostic ??= `Radar binding unavailable: ${String(error).slice(0, 180)}`;
|
|
2275
2124
|
return void 0;
|
|
2276
2125
|
}
|
|
2277
|
-
const bound = textAt(value, "
|
|
2126
|
+
const bound = textAt(value, "registration_id");
|
|
2278
2127
|
const boundIncarnation = textAt(value, "incarnation");
|
|
2279
2128
|
const run = textAt(value, "run");
|
|
2280
2129
|
const owner = textAt(value, "owner");
|
|
@@ -2284,7 +2133,7 @@ function createRadarPublicationInner(options) {
|
|
|
2284
2133
|
return void 0;
|
|
2285
2134
|
return {
|
|
2286
2135
|
version: RADAR_PUBLICATION_VERSION,
|
|
2287
|
-
|
|
2136
|
+
registration_id: bound,
|
|
2288
2137
|
incarnation: boundIncarnation,
|
|
2289
2138
|
run,
|
|
2290
2139
|
owner,
|
|
@@ -2300,25 +2149,27 @@ function createRadarPublicationInner(options) {
|
|
|
2300
2149
|
if (agentId2 === void 0) return void 0;
|
|
2301
2150
|
const record = await ensureRegistration();
|
|
2302
2151
|
if (record === void 0) return void 0;
|
|
2303
|
-
const
|
|
2304
|
-
const
|
|
2152
|
+
const currentLocation = await options.location?.();
|
|
2153
|
+
const location = currentLocation?.state === "resolved" ? currentLocation.location : void 0;
|
|
2154
|
+
const standing = presence.management();
|
|
2155
|
+
const subjectId = standing?.state === "managed" ? standing.subject_id : void 0;
|
|
2305
2156
|
return {
|
|
2306
|
-
|
|
2157
|
+
registration_id: agentId2,
|
|
2307
2158
|
...subjectId !== void 0 ? { subject_id: subjectId } : {},
|
|
2308
2159
|
...location !== void 0 ? { location } : {}
|
|
2309
2160
|
};
|
|
2310
2161
|
},
|
|
2311
|
-
diagnostic: () => registrationDiagnostic ?? execution.diagnostic() ??
|
|
2162
|
+
diagnostic: () => registrationDiagnostic ?? execution.diagnostic() ?? presence.diagnostic() ?? facts.diagnostic(),
|
|
2312
2163
|
stop() {
|
|
2313
2164
|
for (const writer of assignmentWriters.values()) writer.stop();
|
|
2314
2165
|
execution.stop();
|
|
2315
|
-
|
|
2166
|
+
presence.stop();
|
|
2316
2167
|
facts.stop();
|
|
2317
2168
|
},
|
|
2318
2169
|
reopen() {
|
|
2319
2170
|
for (const writer of assignmentWriters.values()) writer.reopen();
|
|
2320
2171
|
execution.reopen();
|
|
2321
|
-
|
|
2172
|
+
presence.reopen();
|
|
2322
2173
|
facts.reopen();
|
|
2323
2174
|
}
|
|
2324
2175
|
};
|
|
@@ -2350,10 +2201,13 @@ function unavailablePublication2() {
|
|
|
2350
2201
|
return {
|
|
2351
2202
|
execution: writer,
|
|
2352
2203
|
facts: { ...writer, update: () => void 0 },
|
|
2353
|
-
|
|
2354
|
-
|
|
2204
|
+
presence: {
|
|
2205
|
+
report: () => void 0,
|
|
2355
2206
|
stop: () => void 0,
|
|
2356
2207
|
reopen: () => void 0,
|
|
2208
|
+
management: () => void 0,
|
|
2209
|
+
ensure: async () => void 0,
|
|
2210
|
+
release: async () => void 0,
|
|
2357
2211
|
diagnostic: () => "Radar private storage is unavailable"
|
|
2358
2212
|
},
|
|
2359
2213
|
assignment: () => writer,
|
|
@@ -2436,11 +2290,11 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2436
2290
|
...lastOutcome !== void 0 ? { last_outcome: lastOutcome } : {}
|
|
2437
2291
|
};
|
|
2438
2292
|
}
|
|
2439
|
-
function reportSession(context
|
|
2293
|
+
function reportSession(context) {
|
|
2440
2294
|
const session = context?.sessionManager?.getSessionId?.();
|
|
2441
2295
|
if (!isUuid(session)) return;
|
|
2442
2296
|
try {
|
|
2443
|
-
publication.
|
|
2297
|
+
publication.presence.report(session);
|
|
2444
2298
|
} catch {
|
|
2445
2299
|
}
|
|
2446
2300
|
}
|
|
@@ -2504,38 +2358,8 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2504
2358
|
})
|
|
2505
2359
|
);
|
|
2506
2360
|
on("session_start", (_event, context) => {
|
|
2507
|
-
const sessionHost = {
|
|
2508
|
-
appendEntry: pi.appendEntry ? (customType, data) => pi.appendEntry?.(customType, data) : void 0,
|
|
2509
|
-
sessionManager: context?.sessionManager
|
|
2510
|
-
};
|
|
2511
|
-
let launchIdentity;
|
|
2512
|
-
try {
|
|
2513
|
-
const result = persistRadarLaunchMarker(
|
|
2514
|
-
sessionHost,
|
|
2515
|
-
options.markerEnvironment
|
|
2516
|
-
);
|
|
2517
|
-
if (result === "written" || result === "unchanged") {
|
|
2518
|
-
const expected = radarLaunchMarkerFromEnvironment(options.markerEnvironment);
|
|
2519
|
-
const activeMarker = activeRadarLaunchMarker(sessionHost);
|
|
2520
|
-
if (expected && activeMarker.status === "valid" && JSON.stringify(activeMarker.marker) === JSON.stringify(expected)) {
|
|
2521
|
-
launchIdentity = activeMarker.marker;
|
|
2522
|
-
} else {
|
|
2523
|
-
options.diagnostic?.("Radar launch marker was not visible on the active Pi session branch");
|
|
2524
|
-
}
|
|
2525
|
-
} else if (result === "unsupported") {
|
|
2526
|
-
options.diagnostic?.("Pi host does not support Radar launch identity session entries");
|
|
2527
|
-
} else if (options.markerEnvironment && [
|
|
2528
|
-
"PI_RADAR_MANAGED_SUBJECT_ID",
|
|
2529
|
-
"PI_RADAR_MANAGED_LAUNCH_ID",
|
|
2530
|
-
"PI_RADAR_MANAGED_EXECUTION_GENERATION"
|
|
2531
|
-
].some((key) => options.markerEnvironment?.[key] !== void 0)) {
|
|
2532
|
-
options.diagnostic?.("incomplete or invalid Radar launch identity environment");
|
|
2533
|
-
}
|
|
2534
|
-
} catch (error) {
|
|
2535
|
-
options.diagnostic?.(`could not persist Radar launch marker: ${String(error)}`);
|
|
2536
|
-
}
|
|
2537
2361
|
rootSession = true;
|
|
2538
|
-
reportSession(context
|
|
2362
|
+
reportSession(context);
|
|
2539
2363
|
publishFacts(context);
|
|
2540
2364
|
publication.reopen();
|
|
2541
2365
|
active = context?.isIdle?.() === false;
|
|
@@ -2566,8 +2390,9 @@ function createRadarExecutionAdapter(pi, options) {
|
|
|
2566
2390
|
}
|
|
2567
2391
|
emit();
|
|
2568
2392
|
});
|
|
2569
|
-
on("session_shutdown", () => {
|
|
2393
|
+
on("session_shutdown", async () => {
|
|
2570
2394
|
suspend();
|
|
2395
|
+
await publication.presence.release();
|
|
2571
2396
|
});
|
|
2572
2397
|
function suspend() {
|
|
2573
2398
|
if (stopped) return;
|