pi-radar 0.2.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 +10 -4
- package/dist/extension/baseline.js +333 -394
- package/dist/extension/radar-client.js +126 -11
- package/dist/extension/radar-communication.js +39 -0
- package/dist/extension/radar-execution.js +169 -382
- package/dist/extension/radar-launch.js +18 -13
- package/dist/extension/radar-publication.js +161 -298
- package/dist/extension/radar-runtime.js +1 -1
- package/dist/index.js +356 -407
- package/extension/baseline.ts +2 -0
- package/extension/generated-contracts.ts +1310 -10
- package/extension/radar-client.ts +191 -23
- package/extension/radar-communication.ts +66 -0
- package/extension/radar-execution.ts +11 -58
- package/extension/radar-launch.ts +29 -22
- package/extension/radar-publication.ts +211 -410
- package/extension/radar-runtime.ts +4 -1
- package/index.ts +1 -0
- package/package.json +9 -5
- package/schema/public/v1/handoff-inbox.deserialize.schema.json +18 -0
- package/schema/public/v1/handoff-inbox.serialize.schema.json +18 -0
- package/schema/public/v1/handoff-publish-params.deserialize.schema.json +33 -0
- package/schema/public/v1/handoff-publish-params.serialize.schema.json +33 -0
- package/schema/public/v1/handoff-receipt.deserialize.schema.json +66 -0
- package/schema/public/v1/handoff-receipt.serialize.schema.json +66 -0
- package/schema/public/v1/handoff.deserialize.schema.json +84 -0
- package/schema/public/v1/handoff.serialize.schema.json +84 -0
- 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
|
@@ -46,7 +46,7 @@ export type LaunchMailbox<State extends LaunchState> = {
|
|
|
46
46
|
* the child's exact command into it, and still reports that pane in its own
|
|
47
47
|
* inventory;
|
|
48
48
|
* 2. a child registered with the launch's private token, so the edge names the
|
|
49
|
-
* exact `
|
|
49
|
+
* exact `registration_id` that child obtained — never a label, pane or session;
|
|
50
50
|
* 3. that child wrote a fresh startup acknowledgment for this launch generation
|
|
51
51
|
* after Herdsman startup finished, naming the pane the daemon created as its
|
|
52
52
|
* own location.
|
|
@@ -64,9 +64,11 @@ export type LaunchMailbox<State extends LaunchState> = {
|
|
|
64
64
|
* different leaves the launch unresolved rather than placed.
|
|
65
65
|
*/
|
|
66
66
|
|
|
67
|
-
/** The exact parent this launch may use, and nothing inferred about it. */
|
|
67
|
+
/** The exact managed parent this launch may use, and nothing inferred about it. */
|
|
68
68
|
export type RadarLaunchParent = {
|
|
69
|
-
|
|
69
|
+
registration_id: string;
|
|
70
|
+
/** Stable subject from this process's current Radar registration. */
|
|
71
|
+
subject_id: string;
|
|
70
72
|
location?: RadarLocation;
|
|
71
73
|
};
|
|
72
74
|
|
|
@@ -107,12 +109,12 @@ export type RadarWorkerLaunch = {
|
|
|
107
109
|
* because a binding that was not persisted is one no later reader can hold the
|
|
108
110
|
* child by.
|
|
109
111
|
*/
|
|
110
|
-
onBound?: (bound: {
|
|
112
|
+
onBound?: (bound: { registration_id: string; pane_id: string }) => void;
|
|
111
113
|
};
|
|
112
114
|
|
|
113
115
|
export type RadarWorkerLaunched<State = unknown> = {
|
|
114
116
|
request_id: string;
|
|
115
|
-
|
|
117
|
+
registration_id: string;
|
|
116
118
|
pane_id: string;
|
|
117
119
|
/**
|
|
118
120
|
* The process the daemon bound this launch's edge to, taken from that same
|
|
@@ -141,7 +143,7 @@ export type RadarLaunchOutcome<State = unknown> =
|
|
|
141
143
|
*/
|
|
142
144
|
export type RadarChildEvidence = {
|
|
143
145
|
request_id: string;
|
|
144
|
-
|
|
146
|
+
registration_id: string;
|
|
145
147
|
source: string;
|
|
146
148
|
incarnation: string;
|
|
147
149
|
pane_id: string;
|
|
@@ -190,12 +192,12 @@ export async function observeRadarChild(
|
|
|
190
192
|
provenance: {
|
|
191
193
|
request_id: string;
|
|
192
194
|
pane_id: string | undefined;
|
|
193
|
-
|
|
195
|
+
registration_id: string | undefined;
|
|
194
196
|
/** The session this launch's mailbox records for the child. */
|
|
195
197
|
session_id: string | undefined;
|
|
196
198
|
},
|
|
197
199
|
): Promise<RadarChildObservation> {
|
|
198
|
-
if (provenance.
|
|
200
|
+
if (provenance.registration_id === undefined)
|
|
199
201
|
return unknownChild("not bound to a child by this launch");
|
|
200
202
|
// A launch that recorded no pane has nothing to compare the daemon's read
|
|
201
203
|
// against: the child's own claim about where it runs is not where the launch
|
|
@@ -209,11 +211,11 @@ export async function observeRadarChild(
|
|
|
209
211
|
);
|
|
210
212
|
const topology = read.value;
|
|
211
213
|
const edge = topology.edge;
|
|
212
|
-
if (edge.bound === undefined || edge.bound.
|
|
214
|
+
if (edge.bound === undefined || edge.bound.registration_id === undefined)
|
|
213
215
|
return unknownChild("not bound to a child by the daemon");
|
|
214
|
-
if (edge.bound.
|
|
216
|
+
if (edge.bound.registration_id !== provenance.registration_id)
|
|
215
217
|
return unknownChild(
|
|
216
|
-
`bound to another subject (${edge.bound.
|
|
218
|
+
`bound to another subject (${edge.bound.registration_id}), not to ${provenance.registration_id}`,
|
|
217
219
|
);
|
|
218
220
|
if (edge.location?.pane === undefined)
|
|
219
221
|
return unknownChild("recorded without a pane");
|
|
@@ -239,7 +241,7 @@ export async function observeRadarChild(
|
|
|
239
241
|
// The edge says where the child was bound, not that its process still runs.
|
|
240
242
|
// The registry's verdict on the bound subject, and the location it registered
|
|
241
243
|
// with, are what prove the child live.
|
|
242
|
-
const reply = await client.agentGet(edge.bound.
|
|
244
|
+
const reply = await client.agentGet(edge.bound.registration_id);
|
|
243
245
|
if (reply.ok === false)
|
|
244
246
|
return unknownChild(
|
|
245
247
|
`process verdict not readable (${reply.code}: ${reply.message})`,
|
|
@@ -269,7 +271,7 @@ export async function observeRadarChild(
|
|
|
269
271
|
kind: "live",
|
|
270
272
|
evidence: {
|
|
271
273
|
request_id: provenance.request_id,
|
|
272
|
-
|
|
274
|
+
registration_id: edge.bound.registration_id,
|
|
273
275
|
source: edge.bound.source,
|
|
274
276
|
incarnation: edge.bound.incarnation,
|
|
275
277
|
pane_id: edge.location.pane,
|
|
@@ -391,10 +393,14 @@ export async function launchRadarWorker<State extends LaunchState>(
|
|
|
391
393
|
const deadline = Date.now() + options.timeoutMs;
|
|
392
394
|
const remaining = (): number => Math.max(0, deadline - Date.now());
|
|
393
395
|
const pane = launch.parent.location?.pane;
|
|
394
|
-
if (!isUuid(launch.parent.
|
|
396
|
+
if (!isUuid(launch.parent.registration_id))
|
|
395
397
|
return refusedLaunch(
|
|
396
398
|
"the launch has no exact parent registration to spawn under",
|
|
397
399
|
);
|
|
400
|
+
if (!isUuid(launch.parent.subject_id))
|
|
401
|
+
return refusedLaunch(
|
|
402
|
+
"the launch has no managed Radar subject for its parent",
|
|
403
|
+
);
|
|
398
404
|
// A spawn is created under the pane its parent registered, and this port
|
|
399
405
|
// registers no location it was not given: without one there is nothing to
|
|
400
406
|
// place the child beside, and a name or session lookup is not a substitute.
|
|
@@ -405,9 +411,10 @@ export async function launchRadarWorker<State extends LaunchState>(
|
|
|
405
411
|
|
|
406
412
|
const spawned = await client.spawn({
|
|
407
413
|
request_id: launch.request_id,
|
|
408
|
-
parent: launch.parent.
|
|
414
|
+
parent: launch.parent.registration_id,
|
|
409
415
|
parent_session_id: launch.parent_session_id,
|
|
410
416
|
executable: launch.executable,
|
|
417
|
+
managed: { parent_subject_id: launch.parent.subject_id },
|
|
411
418
|
argv: launch.argv,
|
|
412
419
|
...(launch.cwd !== "" ? { cwd: launch.cwd } : {}),
|
|
413
420
|
...(Object.keys(launch.env).length > 0 ? { env: launch.env } : {}),
|
|
@@ -430,13 +437,13 @@ export async function launchRadarWorker<State extends LaunchState>(
|
|
|
430
437
|
...(signal !== undefined ? { signal } : {}),
|
|
431
438
|
});
|
|
432
439
|
if (bound.kind !== "bound") return bound;
|
|
433
|
-
const agentId = bound.
|
|
440
|
+
const agentId = bound.registration_id;
|
|
434
441
|
// The binding is recorded before the readiness wait, not after it: the child
|
|
435
442
|
// may never acknowledge, and the subject and pane the daemon named are still
|
|
436
443
|
// what a reload has to prove this child by.
|
|
437
444
|
if (launch.onBound !== undefined) {
|
|
438
445
|
try {
|
|
439
|
-
launch.onBound({
|
|
446
|
+
launch.onBound({ registration_id: agentId, pane_id: bound.pane_id });
|
|
440
447
|
} catch (error) {
|
|
441
448
|
return unresolvedLaunch(
|
|
442
449
|
launch.request_id,
|
|
@@ -468,7 +475,7 @@ export async function launchRadarWorker<State extends LaunchState>(
|
|
|
468
475
|
kind: "ready",
|
|
469
476
|
value: {
|
|
470
477
|
request_id: launch.request_id,
|
|
471
|
-
|
|
478
|
+
registration_id: agentId,
|
|
472
479
|
pane_id: bound.pane_id,
|
|
473
480
|
bound_process: {
|
|
474
481
|
source: bound.source,
|
|
@@ -491,7 +498,7 @@ export async function launchRadarWorker<State extends LaunchState>(
|
|
|
491
498
|
type BoundChild =
|
|
492
499
|
| {
|
|
493
500
|
kind: "bound";
|
|
494
|
-
|
|
501
|
+
registration_id: string;
|
|
495
502
|
pane_id: string;
|
|
496
503
|
source: string;
|
|
497
504
|
incarnation: string;
|
|
@@ -502,7 +509,7 @@ type BoundChild =
|
|
|
502
509
|
* Poll the edge this request id authored until a child presents its token.
|
|
503
510
|
*
|
|
504
511
|
* The daemon binds the edge once, to the exact registration the token produced,
|
|
505
|
-
* so `bound.
|
|
512
|
+
* so `bound.registration_id` is the child identity. A refusal or an unknown launch
|
|
506
513
|
* effect ends the wait at once: neither becomes a child by waiting longer. An
|
|
507
514
|
* edge whose recorded pane the daemon no longer reports ends it too: waiting
|
|
508
515
|
* cannot create the pane a launch claims, and a location read afterwards would
|
|
@@ -552,7 +559,7 @@ async function waitForChild(
|
|
|
552
559
|
requestId,
|
|
553
560
|
"the daemon observed the launched child's process exit",
|
|
554
561
|
);
|
|
555
|
-
const agentId = edge.bound?.
|
|
562
|
+
const agentId = edge.bound?.registration_id;
|
|
556
563
|
if (agentId !== undefined && isUuid(agentId)) {
|
|
557
564
|
// A child the daemon bound without the process it registered as is a
|
|
558
565
|
// child no assignment can be addressed to, and an unaddressed Radar
|
|
@@ -572,7 +579,7 @@ async function waitForChild(
|
|
|
572
579
|
);
|
|
573
580
|
return {
|
|
574
581
|
kind: "bound",
|
|
575
|
-
|
|
582
|
+
registration_id: agentId,
|
|
576
583
|
pane_id: pane,
|
|
577
584
|
source,
|
|
578
585
|
incarnation,
|