@camstack/addon-pipeline-orchestrator 0.1.12 → 0.1.14

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/dist/index.mjs CHANGED
@@ -8591,10 +8591,30 @@ const StatusSchema = object({
8591
8591
  }
8592
8592
  });
8593
8593
  const LinkStateSchema = _enum(["unlinked", "linked", "error"]);
8594
+ const ExportSetupFieldSchema = object({
8595
+ label: string(),
8596
+ value: string(),
8597
+ /** Mask the value by default + render a reveal toggle (client id, secrets). */
8598
+ secret: boolean().optional()
8599
+ });
8600
+ const ExportSetupSchema = object({
8601
+ /** A string to render as a scannable QR — HAP `X-HM://…` URI, a pairing URL, etc. Omitted when there's nothing to scan. */
8602
+ qr: string().optional(),
8603
+ /** Label/value rows shown with a copy button (HAP setup code, OAuth URLs, client id, linked-account count, …). */
8604
+ fields: array(ExportSetupFieldSchema).readonly().optional(),
8605
+ /** Free-form operator instructions rendered above the fields. */
8606
+ note: string().optional()
8607
+ });
8594
8608
  const DeviceExportStatusSchema = object({
8595
8609
  linkState: LinkStateSchema,
8596
8610
  exposedDeviceCount: number(),
8597
- error: string().optional()
8611
+ error: string().optional(),
8612
+ /**
8613
+ * Optional pairing/account info the panel renders in a generic
8614
+ * "Setup" section. Addon-agnostic — the addon id identifies the
8615
+ * export target, never an `ecosystem` key here.
8616
+ */
8617
+ setup: ExportSetupSchema.optional()
8598
8618
  });
8599
8619
  const DeviceKindSchema = string();
8600
8620
  const ExposedDeviceSchema = object({
@@ -10272,51 +10292,6 @@ const AuthResultSchema = object({
10272
10292
  validateToken: method(object({ token: string() }), AuthResultSchema.nullable())
10273
10293
  }
10274
10294
  });
10275
- const AuthProviderInfoSchema = object({
10276
- /** Stable id matching the addon id (used for `getLoginUrl({addonId,…})`). */
10277
- addonId: string(),
10278
- /**
10279
- * Per-instance id when one addon registers multiple "logical"
10280
- * providers (e.g. OIDC with Google + Microsoft + custom). The login
10281
- * URL becomes `/addon/${addonId}/${instanceId}/start` — handler reads
10282
- * `:instanceId` from the route. Empty/unset means the addon is a
10283
- * single-instance provider; the URL is `/addon/${addonId}/start`.
10284
- */
10285
- instanceId: string().optional(),
10286
- /** Display label shown on the login button + admin row. */
10287
- displayName: string(),
10288
- /** Optional iconography hint (lucide-react icon name OR emoji). */
10289
- icon: string().optional(),
10290
- /** When true, the provider exposes a redirect-based login flow
10291
- * (`getLoginUrl` returns a URL the browser navigates to). */
10292
- hasRedirectFlow: boolean(),
10293
- /** When true, the provider exposes a credential-form login flow
10294
- * (`validateCredentials` accepts username + password). */
10295
- hasCredentialFlow: boolean(),
10296
- /** Provider kind, drives admin-UI hint dispatch (oidc / saml / totp / …). */
10297
- kind: string().optional(),
10298
- /** Operator-facing status string (e.g. "Connected to https://login.acme.com"). */
10299
- status: string().optional(),
10300
- /** When false, the provider is registered but disabled by config; the
10301
- * UI surfaces it as inactive without enumerating it for login. */
10302
- enabled: boolean()
10303
- });
10304
- ({
10305
- methods: {
10306
- /** All registered auth providers, both enabled and disabled. */
10307
- listProviders: method(_void(), array(AuthProviderInfoSchema).readonly()),
10308
- /**
10309
- * Toggle a provider's enabled flag. Disabled providers stay
10310
- * registered but aren't surfaced on the login page. The orchestrator
10311
- * persists the state in `addon-settings` so it survives restarts.
10312
- */
10313
- setProviderEnabled: method(
10314
- object({ addonId: string(), enabled: boolean() }),
10315
- object({ success: literal(true) }),
10316
- { kind: "mutation", auth: "admin" }
10317
- )
10318
- }
10319
- });
10320
10295
  const NetworkEndpointSchema = object({
10321
10296
  url: string(),
10322
10297
  hostname: string(),
@@ -10348,55 +10323,13 @@ const NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
10348
10323
  getEndpoint: method(_void(), NetworkEndpointSchema.nullable()),
10349
10324
  getStatus: method(_void(), NetworkAccessStatusSchema),
10350
10325
  /**
10351
- * Enumerate every active ingress entry. Default implementation (when
10352
- * the provider omits this method) is derived from `getEndpoint()` —
10353
- * see the remote-access orchestrator for the fallback path.
10326
+ * Enumerate every active ingress entry. Providers that expose only a
10327
+ * single endpoint may omit this method; callers fall back to
10328
+ * `getEndpoint()` in that case.
10354
10329
  */
10355
10330
  listEndpoints: method(_void(), array(NetworkEndpointEntrySchema).readonly())
10356
10331
  }
10357
10332
  });
10358
- const RemoteAccessEndpointSchema = object({
10359
- url: string(),
10360
- hostname: string(),
10361
- port: number(),
10362
- protocol: _enum(["http", "https"])
10363
- });
10364
- const RemoteAccessProviderInfoSchema = object({
10365
- /** Stable id matching the addon id. */
10366
- addonId: string(),
10367
- /** Display label shown on the admin row — sourced from the addon manifest. */
10368
- displayName: string(),
10369
- /** When false, the provider is registered but disabled. */
10370
- enabled: boolean(),
10371
- /** True when the underlying tunnel/connection is up. */
10372
- connected: boolean(),
10373
- /** Public-facing endpoint, when connected. Null otherwise. */
10374
- endpoint: RemoteAccessEndpointSchema.nullable(),
10375
- /** Last error message (when connected=false), if available. */
10376
- error: string().optional()
10377
- });
10378
- ({
10379
- methods: {
10380
- /** All registered remote-access providers + their live status. */
10381
- listProviders: method(_void(), array(RemoteAccessProviderInfoSchema).readonly()),
10382
- /**
10383
- * Start a specific provider's tunnel. Per-provider config still
10384
- * lives on the addon's settings panel; this is just the on/off
10385
- * trigger so the admin UI can manage the lifecycle from one place.
10386
- */
10387
- startProvider: method(
10388
- object({ addonId: string() }),
10389
- RemoteAccessEndpointSchema,
10390
- { kind: "mutation", auth: "admin" }
10391
- ),
10392
- /** Stop a specific provider's tunnel (idempotent on already-stopped). */
10393
- stopProvider: method(
10394
- object({ addonId: string() }),
10395
- object({ success: literal(true) }),
10396
- { kind: "mutation", auth: "admin" }
10397
- )
10398
- }
10399
- });
10400
10333
  const TurnServerSchema = object({
10401
10334
  /** Single URL or list of URLs (e.g. "turn:turn.example.com:3478?transport=udp"). */
10402
10335
  urls: union([string(), array(string())]),
@@ -10416,45 +10349,6 @@ const TurnServerSchema = object({
10416
10349
  )
10417
10350
  }
10418
10351
  });
10419
- const TurnProviderInfoSchema = object({
10420
- /** Stable id matching the addon id. */
10421
- addonId: string(),
10422
- /** Display label shown on the admin row — sourced from the addon manifest. */
10423
- displayName: string(),
10424
- /** When false, the provider is registered but disabled. */
10425
- enabled: boolean(),
10426
- /** Number of servers this provider is currently exposing. */
10427
- serverCount: number(),
10428
- /**
10429
- * Flat list of every TURN/STUN URL this provider currently exposes.
10430
- * One row per URL (multi-URL ICE server entries are flattened). The
10431
- * admin UI shows this in a compact per-provider list so operators
10432
- * can verify what's actually being negotiated without having to dig
10433
- * into the combined `getAllServers` output.
10434
- */
10435
- urls: array(string()).readonly(),
10436
- /** Last fetch error (when serverCount=0 due to API failure), if any. */
10437
- error: string().optional()
10438
- });
10439
- ({
10440
- methods: {
10441
- /** All registered TURN providers + per-provider stats. */
10442
- listProviders: method(_void(), array(TurnProviderInfoSchema).readonly()),
10443
- /**
10444
- * Combined list of TURN/STUN servers from all ENABLED providers.
10445
- * Consumed by the WebRTC layer at session-creation time —
10446
- * implementations may fetch fresh short-lived credentials each
10447
- * call (e.g. Cloudflare API), so consumers SHOULD call per-session.
10448
- */
10449
- getAllServers: method(_void(), array(TurnServerSchema).readonly()),
10450
- /** Toggle a provider's enabled flag. */
10451
- setProviderEnabled: method(
10452
- object({ addonId: string(), enabled: boolean() }),
10453
- object({ success: literal(true) }),
10454
- { kind: "mutation", auth: "admin" }
10455
- )
10456
- }
10457
- });
10458
10352
  const SnapshotImageSchema = object({
10459
10353
  base64: string(),
10460
10354
  contentType: string()
@@ -11922,7 +11816,7 @@ const AllowedAddressesSchema = object({
11922
11816
  )
11923
11817
  }
11924
11818
  });
11925
- const MeshEndpointSchema$1 = object({
11819
+ const MeshEndpointSchema = object({
11926
11820
  /** Stable identifier within the provider (e.g. `mesh-ipv4`, `magicdns`, `funnel`). */
11927
11821
  id: string(),
11928
11822
  /** Operator-facing label (e.g. "Mesh IPv4", "MagicDNS"). */
@@ -11995,7 +11889,7 @@ const MeshStatusSchema = object({
11995
11889
  /** Number of peers visible to this host (excluding self). */
11996
11890
  peerCount: number(),
11997
11891
  /** Every endpoint this provider exposes for the current host. */
11998
- endpoints: array(MeshEndpointSchema$1).readonly(),
11892
+ endpoints: array(MeshEndpointSchema).readonly(),
11999
11893
  /** Last error from the daemon, when not joined. */
12000
11894
  error: string().optional(),
12001
11895
  // ── Account / tenant identity (generic across providers) ────────
@@ -12028,7 +11922,25 @@ const MeshStatusSchema = object({
12028
11922
  * doesn't rotate keys for the bound host. Operator-facing surface
12029
11923
  * for "your access expires on …" banners.
12030
11924
  */
12031
- keyExpiry: number().nullable()
11925
+ keyExpiry: number().nullable(),
11926
+ // ── Onboard-daemon handoff (Tailscale, generic slot) ────────────
11927
+ /**
11928
+ * When the provider runs its OWN mesh daemon (e.g. the Tailscale
11929
+ * client addon in `onboard` mode spawns a private `tailscaled`),
11930
+ * this carries the local control-socket path. Companion addons that
11931
+ * must drive the SAME daemon — chiefly `tailscale-ingress` for
11932
+ * Serve/Funnel — read it to point their CLI at the right socket
11933
+ * instead of the system default. Empty when the provider uses the
11934
+ * host's system daemon (or doesn't have the concept).
11935
+ */
11936
+ daemonSocket: string().optional(),
11937
+ /**
11938
+ * Path to the mesh CLI binary the provider downloaded for onboard
11939
+ * mode. Companion addons reuse it so they don't need a system
11940
+ * install when the operator chose a fully self-contained mesh.
11941
+ * Empty in host mode.
11942
+ */
11943
+ daemonCliPath: string().optional()
12032
11944
  });
12033
11945
  ({
12034
11946
  methods: {
@@ -12140,105 +12052,6 @@ const MeshStatusSchema = object({
12140
12052
  // tabs driven by this cap.
12141
12053
  }
12142
12054
  });
12143
- const MeshEndpointSchema = object({
12144
- id: string(),
12145
- label: string(),
12146
- scope: _enum(["mesh", "public"]),
12147
- url: string(),
12148
- hostname: string(),
12149
- port: number(),
12150
- protocol: _enum(["http", "https"])
12151
- });
12152
- const MeshProviderInfoSchema = object({
12153
- /** Stable id matching the addon id. */
12154
- addonId: string(),
12155
- /** Display label shown on the admin row — sourced from the addon manifest. */
12156
- displayName: string(),
12157
- /** True when the host is joined to this provider's mesh. */
12158
- joined: boolean(),
12159
- /** Local mesh IP (empty when not joined). */
12160
- meshIp: string(),
12161
- /** MagicDNS / mesh hostname (empty when not configured). */
12162
- magicDnsHostname: string(),
12163
- /** Peer count (excluding self). */
12164
- peerCount: number(),
12165
- /** Active endpoints (mesh IP + MagicDNS + optional public Funnel). */
12166
- endpoints: array(MeshEndpointSchema).readonly(),
12167
- /** Last error reported by the provider. */
12168
- error: string().optional(),
12169
- // ── Generic identity fields mirrored from MeshStatus ─────────────
12170
- /** Tenant / tailnet / network display name. Empty pre-join. */
12171
- tenantName: string(),
12172
- /** Mesh DNS suffix (e.g. tailXXXX.ts.net). Empty when not configured. */
12173
- magicDnsSuffix: string(),
12174
- /** Authenticated user / account login. Null for token-only providers. */
12175
- userLogin: string().nullable(),
12176
- /** Provider control-plane URL. */
12177
- controlPlaneUrl: string(),
12178
- /** Machine-key expiry (epoch ms). Null when keys don't rotate. */
12179
- keyExpiry: number().nullable()
12180
- });
12181
- ({
12182
- methods: {
12183
- /** All registered mesh-network providers + live status. */
12184
- listProviders: method(_void(), array(MeshProviderInfoSchema).readonly()),
12185
- /**
12186
- * Join the mesh of a specific provider. Per-provider config still
12187
- * lives on its settings panel; the orchestrator forwards.
12188
- */
12189
- joinProvider: method(
12190
- object({
12191
- addonId: string(),
12192
- authKey: string().min(8),
12193
- hostname: string().optional()
12194
- }),
12195
- object({ joined: literal(true) }),
12196
- { kind: "mutation" }
12197
- ),
12198
- leaveProvider: method(
12199
- object({ addonId: string() }),
12200
- object({ success: literal(true) }),
12201
- { kind: "mutation" }
12202
- ),
12203
- /**
12204
- * Browser-redirect login flow. Forwards to the named provider's
12205
- * `mesh-network.startLogin` and returns the URL the daemon
12206
- * prints. UI opens it in a new tab, then polls `listProviders`
12207
- * for `joined: true`.
12208
- */
12209
- startLoginProvider: method(
12210
- object({
12211
- addonId: string(),
12212
- hostname: string().optional()
12213
- }),
12214
- object({ loginUrl: string() }),
12215
- { kind: "mutation" }
12216
- ),
12217
- /**
12218
- * Sign out of the provider's account entirely (`mesh-network.logout`).
12219
- * Distinct from `leaveProvider` which only takes the host off-mesh;
12220
- * `logoutProvider` wipes credentials so the next start requires a
12221
- * fresh login.
12222
- */
12223
- logoutProvider: method(
12224
- object({ addonId: string() }),
12225
- object({ loggedOut: literal(true) }),
12226
- { kind: "mutation" }
12227
- ),
12228
- /**
12229
- * Per-provider peer list. Forwards to `mesh-network.listPeers` on
12230
- * the addressed provider. Separate from `listProviders` because
12231
- * peer payloads can be large on a heavily-populated tailnet —
12232
- * fetch only when the operator opens the Peers tab.
12233
- */
12234
- listProviderPeers: method(
12235
- object({ addonId: string() }),
12236
- object({
12237
- peers: array(MeshPeerSchema).readonly()
12238
- })
12239
- )
12240
- }
12241
- });
12242
12055
  const MethodAccessSchema = _enum(["view", "create", "delete"]);
12243
12056
  const AllowedProviderSchema = union([literal("*"), array(string())]);
12244
12057
  const AllowedDevicesSchema = record(string(), union([literal("*"), array(string())]));
@@ -12914,6 +12727,21 @@ const AddonAutoUpdateSchema = ChannelWithInheritSchema;
12914
12727
  const RestartAddonResultSchema = unknown();
12915
12728
  const InstallPackageResultSchema = unknown();
12916
12729
  const ReloadPackagesResultSchema = unknown();
12730
+ const UpdateFrameworkPackageResultSchema = object({
12731
+ packageName: string(),
12732
+ fromVersion: string(),
12733
+ toVersion: string(),
12734
+ /** Ms-epoch the server scheduled its self-restart. */
12735
+ restartingAt: number()
12736
+ });
12737
+ const FrameworkPackageStatusSchema = object({
12738
+ packageName: string(),
12739
+ currentVersion: string(),
12740
+ latestVersion: string().nullable(),
12741
+ hasUpdate: boolean(),
12742
+ /** Optional manifest description for the row tooltip. */
12743
+ description: string().optional()
12744
+ });
12917
12745
  const LogStreamEntrySchema = object({
12918
12746
  timestamp: string(),
12919
12747
  level: string(),
@@ -12973,13 +12801,29 @@ const CustomActionInputSchema = object({
12973
12801
  object({ query: string().optional() }),
12974
12802
  array(SearchResultSchema)
12975
12803
  ),
12804
+ /**
12805
+ * Available package updates for a node. `nodeId` omitted (or
12806
+ * `'hub'`) checks the hub's own installed packages; an agent
12807
+ * `nodeId` checks that agent's installed roster against npm
12808
+ * (the hub does the npm lookups + diff — agents stay npm-free).
12809
+ */
12976
12810
  listUpdates: method(
12977
- _void(),
12811
+ object({ nodeId: string().optional() }),
12978
12812
  array(PackageUpdateSchema).readonly(),
12979
12813
  { auth: "admin" }
12980
12814
  ),
12815
+ /**
12816
+ * Update one package on a node. `nodeId` omitted (or `'hub'`)
12817
+ * installs on the hub via npm; an agent `nodeId` makes the hub
12818
+ * pack the resolved version and push the tarball to that agent
12819
+ * (`$agent.deploy` + `$agent.reload`) — agents need no npm runtime.
12820
+ */
12981
12821
  updatePackage: method(
12982
- object({ name: string().min(1), version: string().optional() }),
12822
+ object({
12823
+ name: string().min(1),
12824
+ version: string().optional(),
12825
+ nodeId: string().optional()
12826
+ }),
12983
12827
  unknown(),
12984
12828
  { kind: "mutation", auth: "admin" }
12985
12829
  ),
@@ -13000,12 +12844,128 @@ const CustomActionInputSchema = object({
13000
12844
  object({ rolledBackTo: string().nullable() }),
13001
12845
  { kind: "mutation", auth: "admin" }
13002
12846
  ),
13003
- forceRefresh: method(_void(), unknown(), { kind: "mutation", auth: "admin" }),
12847
+ /** Re-check updates for a node, bypassing any cache. `nodeId`
12848
+ * omitted (or `'hub'`) refreshes the hub; an agent `nodeId`
12849
+ * re-checks that agent's roster. */
12850
+ forceRefresh: method(
12851
+ object({ nodeId: string().optional() }),
12852
+ unknown(),
12853
+ { kind: "mutation", auth: "admin" }
12854
+ ),
13004
12855
  restartServer: method(
13005
12856
  object({ confirm: literal(true) }),
13006
12857
  unknown(),
13007
12858
  { kind: "mutation", auth: "admin" }
13008
12859
  ),
12860
+ /**
12861
+ * Most-recent restart marker (kind / packageName / from→to versions
12862
+ * / requestedBy / requestedAt). Returns `null` when this process
12863
+ * didn't boot from a tracked restart, or when the
12864
+ * post-boot retention window (5 min) has elapsed.
12865
+ *
12866
+ * Drives the admin-UI reconnect overlay's success toast — the
12867
+ * `system.restart-completed` event itself is fired before the
12868
+ * client has time to re-subscribe, so the client queries this on
12869
+ * first reconnect instead.
12870
+ */
12871
+ getLastRestart: method(
12872
+ _void(),
12873
+ object({
12874
+ kind: _enum(["framework-update", "manual", "system"]),
12875
+ packageName: string().optional(),
12876
+ fromVersion: string().optional(),
12877
+ toVersion: string().optional(),
12878
+ requestedBy: string().optional(),
12879
+ requestedAt: number()
12880
+ }).nullable(),
12881
+ { auth: "admin" }
12882
+ ),
12883
+ /**
12884
+ * Snapshot of the framework packages installed under the hub's
12885
+ * `<appRoot>/node_modules/`. Each row carries the currently
12886
+ * installed version and (best-effort) the latest version
12887
+ * available on npm. Drives the admin-UI "System packages" panel.
12888
+ *
12889
+ * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
12890
+ */
12891
+ listFrameworkPackages: method(
12892
+ _void(),
12893
+ array(FrameworkPackageStatusSchema).readonly(),
12894
+ { auth: "admin" }
12895
+ ),
12896
+ /**
12897
+ * Cluster-wide capability-provider discovery. Returns the list of
12898
+ * `{ addonId, mode, isActive }` tuples for whatever addon(s)
12899
+ * currently provide the requested capability across the cluster.
12900
+ *
12901
+ * Why this lives on `addons` (and not on a `capabilities` cap of
12902
+ * its own): the hub's main-process `CapabilityRegistry` already
12903
+ * aggregates registrations from every forked group-runner and
12904
+ * remote agent via Moleculer event propagation — there's no
12905
+ * cross-process registry mirror to build, just an introspection
12906
+ * shim.
12907
+ *
12908
+ * Use this from addon code when you need to know whether another
12909
+ * addon has registered a specific cap (e.g. `tailscale-ingress`
12910
+ * checking `tailscale-client` is up before calling `tailscale
12911
+ * serve`). Don't reach for `ctx.capabilities.getCollectionEntries`
12912
+ * — that reads the LOCAL registry of the calling addon's group
12913
+ * runner and never sees providers in other processes. See
12914
+ * `CLAUDE.md` → Critical rules → ctx.api vs ctx.capabilities.
12915
+ */
12916
+ listCapabilityProviders: method(
12917
+ object({ capName: string().min(1) }),
12918
+ array(object({
12919
+ addonId: string(),
12920
+ mode: _enum(["singleton", "collection"]),
12921
+ isActive: boolean()
12922
+ })).readonly()
12923
+ ),
12924
+ /**
12925
+ * Toggle a single collection-cap provider on/off. Generic write-side
12926
+ * counterpart of `listCapabilityProviders` — drives the per-provider
12927
+ * Enable/Disable affordance in admin pages (TURN servers, etc.)
12928
+ * without needing a bespoke orchestrator cap.
12929
+ *
12930
+ * Reaches the hub's `CapabilityRegistry` directly:
12931
+ * `enableCollectionProvider` / `disableCollectionProvider` flip the
12932
+ * registry-level `disabledProviders` set. `getCollectionEntries`
12933
+ * already filters disabled providers out, so a disabled provider
12934
+ * drops out of every collection aggregate immediately. Only valid
12935
+ * for `mode: 'collection'` caps — the registry no-ops + warns for
12936
+ * singletons.
12937
+ */
12938
+ setCapabilityProviderEnabled: method(
12939
+ object({
12940
+ capName: string().min(1),
12941
+ addonId: string().min(1),
12942
+ enabled: boolean()
12943
+ }),
12944
+ object({ success: literal(true) }),
12945
+ { kind: "mutation", auth: "admin" }
12946
+ ),
12947
+ /**
12948
+ * Live-update one of the framework packages marked
12949
+ * `camstack.system: true` (`@camstack/types|kernel|core|sdk|ui-library`).
12950
+ * Runs `npm install --prefix <appRoot> <name>@<version> --no-save`,
12951
+ * writes a `.restart-pending` marker, emits `system.restarting`
12952
+ * and schedules a graceful process exit. The supervisor (Docker /
12953
+ * Electron / systemd) brings the hub back up; on first boot after
12954
+ * the restart the marker fires `system.restart-completed`.
12955
+ *
12956
+ * `version` defaults to `'latest'`. The allow-list of valid
12957
+ * `packageName` values is enforced server-side.
12958
+ *
12959
+ * Spec: docs/superpowers/specs/2026-05-14-framework-live-update-design.md
12960
+ */
12961
+ updateFrameworkPackage: method(
12962
+ object({
12963
+ packageName: string().min(1),
12964
+ version: string().optional()
12965
+ }),
12966
+ UpdateFrameworkPackageResultSchema,
12967
+ { kind: "mutation", auth: "admin" }
12968
+ ),
13009
12969
  getVersions: method(
13010
12970
  object({ name: string() }),
13011
12971
  array(PackageVersionInfoSchema).readonly()
@@ -13076,6 +13036,7 @@ var EventCategory = /* @__PURE__ */ ((EventCategory2) => {
13076
13036
  EventCategory2["SystemBoot"] = "system.boot";
13077
13037
  EventCategory2["SystemAddonsReady"] = "system.addons-ready";
13078
13038
  EventCategory2["SystemRestarting"] = "system.restarting";
13039
+ EventCategory2["SystemRestartCompleted"] = "system.restart-completed";
13079
13040
  EventCategory2["SystemReadyState"] = "system.ready-state";
13080
13041
  EventCategory2["AddonStarted"] = "addon.started";
13081
13042
  EventCategory2["AddonStopped"] = "addon.stopped";