pi-radar 0.6.0 → 0.9.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.
Files changed (29) hide show
  1. package/README.md +15 -1
  2. package/dist/extension/baseline.js +395 -125
  3. package/dist/extension/radar-children.js +240 -0
  4. package/dist/extension/radar-client.js +42 -8
  5. package/dist/extension/radar-execution.js +11 -10
  6. package/dist/extension/radar-launch.js +23 -24
  7. package/dist/extension/radar-publication.js +10 -9
  8. package/dist/extension/radar-runtime.js +1 -1
  9. package/dist/index.js +1772 -1615
  10. package/extension/baseline.ts +2 -0
  11. package/extension/generated-contracts.ts +12 -3
  12. package/extension/radar-children.ts +176 -0
  13. package/extension/radar-client.ts +60 -6
  14. package/extension/radar-execution.ts +5 -5
  15. package/extension/radar-launch.ts +42 -63
  16. package/extension/radar-publication.ts +12 -13
  17. package/extension/radar-runtime.ts +4 -1
  18. package/index.ts +1 -0
  19. package/package.json +8 -3
  20. package/schema/public/v1/observation-get-response.deserialize.schema.json +9 -1
  21. package/schema/public/v1/observation-get-response.serialize.schema.json +9 -1
  22. package/schema/public/v1/observation-snapshot.deserialize.schema.json +9 -1
  23. package/schema/public/v1/observation-snapshot.serialize.schema.json +9 -1
  24. package/schema/public/v1/presence-answer.deserialize.schema.json +1 -0
  25. package/schema/public/v1/presence-answer.serialize.schema.json +1 -0
  26. package/schema/public/v1/presence-report.deserialize.schema.json +0 -7
  27. package/schema/public/v1/presence-report.serialize.schema.json +0 -8
  28. package/schema/public/v1/spawn-list-page.deserialize.schema.json +7 -0
  29. package/schema/public/v1/spawn-list-page.serialize.schema.json +7 -0
@@ -269,6 +269,7 @@ export function createPublicationStore(root: string): PublicationStore {
269
269
  */
270
270
  export type RadarProcessSlot = {
271
271
  incarnation?: string;
272
+ launchRegistrationId?: string;
272
273
  publications: Map<string, RadarPublication>;
273
274
  };
274
275
 
@@ -280,7 +281,13 @@ export function radarProcessSlot(): RadarProcessSlot {
280
281
  const host = globalThis as typeof globalThis & {
281
282
  [PROCESS_SLOT]?: RadarProcessSlot;
282
283
  };
283
- return (host[PROCESS_SLOT] ??= createRadarProcessSlot());
284
+ if (!host[PROCESS_SLOT]) {
285
+ const slot = createRadarProcessSlot();
286
+ slot.launchRegistrationId = process.env.PI_RADAR_REGISTRATION_ID;
287
+ delete process.env.PI_RADAR_REGISTRATION_ID;
288
+ host[PROCESS_SLOT] = slot;
289
+ }
290
+ return host[PROCESS_SLOT];
284
291
  }
285
292
 
286
293
  /** The process incarnation, created on first use and kept for the process. */
@@ -975,7 +982,6 @@ function createPresenceReporter(input: PresenceReporterInput): RadarPresenceRepo
975
982
  type State = {
976
983
  version: 2;
977
984
  claim_id: string;
978
- initial_load?: boolean;
979
985
  session: string;
980
986
  registration_id?: string;
981
987
  subject_id?: string;
@@ -1033,13 +1039,6 @@ function createPresenceReporter(input: PresenceReporterInput): RadarPresenceRepo
1033
1039
  await releasePending();
1034
1040
  const registration = await input.registration();
1035
1041
  if (!registration?.process || state !== claim || stopped) return undefined;
1036
- // The first load spends the pre-minted launch claim. Reloads get a fresh
1037
- // claim; they must not reuse the released launch credential.
1038
- if (claim.initial_load) {
1039
- if (registration.spawn_token) claim.claim_id = registration.spawn_token;
1040
- claim.initial_load = false;
1041
- if (!save()) return undefined;
1042
- }
1043
1042
  const answer = await client.presence({
1044
1043
  ...registration, process: registration.process,
1045
1044
  session_id: claim.session, claim_id: claim.claim_id,
@@ -1079,7 +1078,7 @@ function createPresenceReporter(input: PresenceReporterInput): RadarPresenceRepo
1079
1078
  releases.push({ registration_id: state.registration_id, claim_id: state.claim_id });
1080
1079
  }
1081
1080
  standing = undefined;
1082
- state = { version: 2, session, claim_id: randomUUID(), initial_load: state === undefined, releases };
1081
+ state = { version: 2, session, claim_id: randomUUID(), releases };
1083
1082
  save(); stopped = false;
1084
1083
  void ensure();
1085
1084
  },
@@ -1159,7 +1158,7 @@ export type RadarPublicationOptions = {
1159
1158
  /** Set on a managed child: the sidecar its owner correlates the subject with. */
1160
1159
  binding?: { key: string; run: string; owner: string; label: string };
1161
1160
  /** A daemon-spawned child's one-use launch token; sent privately, never stored in the process record. */
1162
- spawnToken?: string;
1161
+ launchRegistrationId?: string;
1163
1162
  leaseMs?: number;
1164
1163
  heartbeatMs?: number;
1165
1164
  };
@@ -1234,8 +1233,8 @@ function createRadarPublicationInner(
1234
1233
  const store = options.store ?? createPublicationStore(dataRoot);
1235
1234
  const scheduler = options.scheduler ?? systemScheduler;
1236
1235
  const client = options.client;
1237
- const spawnToken = options.spawnToken;
1238
1236
  const slot = options.slot ?? radarProcessSlot();
1237
+ const launchRegistrationId = options.launchRegistrationId ?? slot.launchRegistrationId;
1239
1238
  const incarnation = options.incarnation ?? radarProcessIncarnation(slot);
1240
1239
 
1241
1240
  const cacheKey = `${
@@ -1424,7 +1423,7 @@ function createRadarPublicationInner(
1424
1423
  const { location: _initialLocation, ...identity } = record.registration;
1425
1424
  return { ...identity,
1426
1425
  ...(location?.state === "resolved" ? { location: location.location } : {}),
1427
- ...(spawnToken ? { spawn_token: spawnToken } : {}),
1426
+ ...(launchRegistrationId ? { registration_id: launchRegistrationId } : {}),
1428
1427
  };
1429
1428
  },
1430
1429
  heartbeatMs: options.heartbeatMs ?? RADAR_HEARTBEAT_MS,
@@ -1,10 +1,11 @@
1
1
  import type { RadarExecutionAdapter } from "./radar-execution.ts";
2
+ import type { RadarChildren } from "./radar-children.ts";
2
3
  import type { RadarHandoffPort } from "./radar-communication.ts";
3
4
  import type { RadarPublication } from "./radar-publication.ts";
4
5
 
5
6
  /** The event channel through which Pi extensions obtain the baseline runtime. */
6
7
  export const RADAR_RUNTIME_REQUEST = "pi-radar/runtime-request";
7
- export const RADAR_RUNTIME_VERSION = 2 as const;
8
+ export const RADAR_RUNTIME_VERSION = 3 as const;
8
9
 
9
10
  /** The sole baseline publisher's session-scoped runtime, shared with consumers. */
10
11
  export type RadarRuntimeServices = {
@@ -12,6 +13,8 @@ export type RadarRuntimeServices = {
12
13
  publication: RadarPublication;
13
14
  /** Durable handoffs bound to this process's registration and managed parent. */
14
15
  communication: RadarHandoffPort;
16
+ /** This process's own children, addressed by subject. */
17
+ children: RadarChildren;
15
18
  execution: RadarExecutionAdapter;
16
19
  };
17
20
 
package/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * as children from "./extension/radar-children.ts";
1
2
  export * as client from "./extension/radar-client.ts";
2
3
  export * as communication from "./extension/radar-communication.ts";
3
4
  export * as execution from "./extension/radar-execution.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-radar",
3
- "version": "0.6.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "description": "Radar daemon client, communication, publication, execution, location, launch and inspection surface for Pi extensions.",
6
6
  "license": "Apache-2.0",
@@ -23,6 +23,10 @@
23
23
  "types": "./index.ts",
24
24
  "import": "./dist/index.js"
25
25
  },
26
+ "./children": {
27
+ "types": "./extension/radar-children.ts",
28
+ "import": "./dist/extension/radar-children.js"
29
+ },
26
30
  "./client": {
27
31
  "types": "./extension/radar-client.ts",
28
32
  "import": "./dist/extension/radar-client.js"
@@ -72,6 +76,7 @@
72
76
  "README.md",
73
77
  "schema/public/v1/**",
74
78
  "extension/generated-contracts.ts",
79
+ "extension/radar-children.ts",
75
80
  "extension/radar-client.ts",
76
81
  "extension/radar-communication.ts",
77
82
  "extension/radar-execution.ts",
@@ -83,10 +88,10 @@
83
88
  "extension/baseline.ts"
84
89
  ],
85
90
  "scripts": {
86
- "build": "esbuild index.ts extension/generated-contracts.ts extension/radar-client.ts extension/radar-communication.ts extension/radar-execution.ts extension/radar-inspection.ts extension/radar-launch.ts extension/radar-location.ts extension/radar-publication.ts extension/radar-runtime.ts extension/baseline.ts --outbase=. --outdir=dist --bundle --platform=node --format=esm --target=node22",
91
+ "build": "esbuild index.ts extension/generated-contracts.ts extension/radar-children.ts extension/radar-client.ts extension/radar-communication.ts extension/radar-execution.ts extension/radar-inspection.ts extension/radar-launch.ts extension/radar-location.ts extension/radar-publication.ts extension/radar-runtime.ts extension/baseline.ts --outbase=. --outdir=dist --bundle --platform=node --format=esm --target=node22",
87
92
  "generate:contracts": "node tools/generate-contracts.mjs",
88
93
  "check:contracts": "node tools/generate-contracts.mjs --check",
89
- "typecheck:contracts": "tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext --allowImportingTsExtensions --types node index.ts extension/baseline.ts extension/generated-contracts.ts extension/generated-contracts.typecheck.ts extension/radar-client.ts extension/radar-communication.ts extension/radar-execution.ts extension/radar-launch.test.ts extension/radar-publication.ts extension/radar-runtime.ts extension/radar-runtime.test.ts",
94
+ "typecheck:contracts": "tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext --allowImportingTsExtensions --types node index.ts extension/baseline.ts extension/generated-contracts.ts extension/generated-contracts.typecheck.ts extension/radar-children.ts extension/radar-client.ts extension/radar-communication.ts extension/radar-execution.ts extension/radar-launch.test.ts extension/radar-publication.ts extension/radar-runtime.ts extension/radar-runtime.test.ts",
90
95
  "prepack": "npm run build",
91
96
  "test": "npm run check:contracts && npm run typecheck:contracts && node --experimental-strip-types --test extension/*.test.ts"
92
97
  },
@@ -2098,6 +2098,13 @@
2098
2098
  },
2099
2099
  "registration": {
2100
2100
  "$ref": "#/$defs/PublicRegistration"
2101
+ },
2102
+ "scoped": {
2103
+ "description": "Whether this process runs inside a Radar-established execution scope. A\nprocess started outside the managed launch path has none and is observed.",
2104
+ "type": [
2105
+ "boolean",
2106
+ "null"
2107
+ ]
2101
2108
  }
2102
2109
  },
2103
2110
  "required": [
@@ -2424,6 +2431,7 @@
2424
2431
  },
2425
2432
  "Standing": {
2426
2433
  "enum": [
2434
+ "reserved",
2427
2435
  "pending",
2428
2436
  "granted",
2429
2437
  "duplicate",
@@ -2440,7 +2448,7 @@
2440
2448
  },
2441
2449
  {
2442
2450
  "const": "captured",
2443
- "description": "The bootstrap's process is captured and released to exec.",
2451
+ "description": "The launch's process is captured and has been given its program.",
2444
2452
  "type": "string"
2445
2453
  },
2446
2454
  {
@@ -2201,6 +2201,13 @@
2201
2201
  },
2202
2202
  "registration": {
2203
2203
  "$ref": "#/$defs/PublicRegistration"
2204
+ },
2205
+ "scoped": {
2206
+ "description": "Whether this process runs inside a Radar-established execution scope. A\nprocess started outside the managed launch path has none and is observed.",
2207
+ "type": [
2208
+ "boolean",
2209
+ "null"
2210
+ ]
2204
2211
  }
2205
2212
  },
2206
2213
  "required": [
@@ -2543,6 +2550,7 @@
2543
2550
  },
2544
2551
  "Standing": {
2545
2552
  "enum": [
2553
+ "reserved",
2546
2554
  "pending",
2547
2555
  "granted",
2548
2556
  "duplicate",
@@ -2559,7 +2567,7 @@
2559
2567
  },
2560
2568
  {
2561
2569
  "const": "captured",
2562
- "description": "The bootstrap's process is captured and released to exec.",
2570
+ "description": "The launch's process is captured and has been given its program.",
2563
2571
  "type": "string"
2564
2572
  },
2565
2573
  {
@@ -1963,6 +1963,13 @@
1963
1963
  },
1964
1964
  "registration": {
1965
1965
  "$ref": "#/$defs/PublicRegistration"
1966
+ },
1967
+ "scoped": {
1968
+ "description": "Whether this process runs inside a Radar-established execution scope. A\nprocess started outside the managed launch path has none and is observed.",
1969
+ "type": [
1970
+ "boolean",
1971
+ "null"
1972
+ ]
1966
1973
  }
1967
1974
  },
1968
1975
  "required": [
@@ -2289,6 +2296,7 @@
2289
2296
  },
2290
2297
  "Standing": {
2291
2298
  "enum": [
2299
+ "reserved",
2292
2300
  "pending",
2293
2301
  "granted",
2294
2302
  "duplicate",
@@ -2305,7 +2313,7 @@
2305
2313
  },
2306
2314
  {
2307
2315
  "const": "captured",
2308
- "description": "The bootstrap's process is captured and released to exec.",
2316
+ "description": "The launch's process is captured and has been given its program.",
2309
2317
  "type": "string"
2310
2318
  },
2311
2319
  {
@@ -2057,6 +2057,13 @@
2057
2057
  },
2058
2058
  "registration": {
2059
2059
  "$ref": "#/$defs/PublicRegistration"
2060
+ },
2061
+ "scoped": {
2062
+ "description": "Whether this process runs inside a Radar-established execution scope. A\nprocess started outside the managed launch path has none and is observed.",
2063
+ "type": [
2064
+ "boolean",
2065
+ "null"
2066
+ ]
2060
2067
  }
2061
2068
  },
2062
2069
  "required": [
@@ -2399,6 +2406,7 @@
2399
2406
  },
2400
2407
  "Standing": {
2401
2408
  "enum": [
2409
+ "reserved",
2402
2410
  "pending",
2403
2411
  "granted",
2404
2412
  "duplicate",
@@ -2415,7 +2423,7 @@
2415
2423
  },
2416
2424
  {
2417
2425
  "const": "captured",
2418
- "description": "The bootstrap's process is captured and released to exec.",
2426
+ "description": "The launch's process is captured and has been given its program.",
2419
2427
  "type": "string"
2420
2428
  },
2421
2429
  {
@@ -2,6 +2,7 @@
2
2
  "$defs": {
3
3
  "Standing": {
4
4
  "enum": [
5
+ "reserved",
5
6
  "pending",
6
7
  "granted",
7
8
  "duplicate",
@@ -2,6 +2,7 @@
2
2
  "$defs": {
3
3
  "Standing": {
4
4
  "enum": [
5
+ "reserved",
5
6
  "pending",
6
7
  "granted",
7
8
  "duplicate",
@@ -122,13 +122,6 @@
122
122
  "source": {
123
123
  "type": "string"
124
124
  },
125
- "spawn_token": {
126
- "default": null,
127
- "type": [
128
- "string",
129
- "null"
130
- ]
131
- },
132
125
  "subject_id": {
133
126
  "default": null,
134
127
  "type": [
@@ -123,13 +123,6 @@
123
123
  "source": {
124
124
  "type": "string"
125
125
  },
126
- "spawn_token": {
127
- "default": null,
128
- "type": [
129
- "string",
130
- "null"
131
- ]
132
- },
133
126
  "subject_id": {
134
127
  "default": null,
135
128
  "type": [
@@ -147,7 +140,6 @@
147
140
  "registration_id",
148
141
  "subject_id",
149
142
  "location",
150
- "spawn_token",
151
143
  "owner",
152
144
  "run",
153
145
  "label"
@@ -20,6 +20,13 @@
20
20
  },
21
21
  "source": {
22
22
  "type": "string"
23
+ },
24
+ "subject_id": {
25
+ "description": "The durable agent the bound child attaches as. Absent for an edge without\na tracked launch and in records written before it was recorded.",
26
+ "type": [
27
+ "string",
28
+ "null"
29
+ ]
23
30
  }
24
31
  },
25
32
  "required": [
@@ -20,6 +20,13 @@
20
20
  },
21
21
  "source": {
22
22
  "type": "string"
23
+ },
24
+ "subject_id": {
25
+ "description": "The durable agent the bound child attaches as. Absent for an edge without\na tracked launch and in records written before it was recorded.",
26
+ "type": [
27
+ "string",
28
+ "null"
29
+ ]
23
30
  }
24
31
  },
25
32
  "required": [