@kybernesis/create 0.26.0 → 0.26.1

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/doctor.d.ts CHANGED
@@ -46,6 +46,12 @@ export interface ComputerInspection {
46
46
  /** The noVNC port is bound on loopback. */
47
47
  screenBound: boolean | null;
48
48
  vncPasswordSet: boolean;
49
+ /**
50
+ * Live xfsettingsd processes in the running computer. One is right; more
51
+ * were left by display restarts before @kybernesis/computer 0.3.1, and each
52
+ * holds one of Xvfb's client slots.
53
+ */
54
+ settingsDaemons?: number | null;
49
55
  }
50
56
  /**
51
57
  * A computer that is configured but not running is the quiet failure here:
@@ -54,4 +60,6 @@ export interface ComputerInspection {
54
60
  */
55
61
  export declare function computerDoctorChecks(c: ComputerInspection): Check[];
56
62
  export declare function inspectComputer(cwd: string): ComputerInspection | null;
63
+ /** @internal Lines of `ps -o stat=` output that are not zombies (a zombie holds no X connection). */
64
+ export declare function countLiveProcesses(stats: string): number;
57
65
  export {};
package/dist/doctor.js CHANGED
@@ -736,6 +736,8 @@ export async function doctor() {
736
736
  console.log(`\n ${fails ? red(`${fails} failing`) : green("0 failing")}, ${warns ? yellow(`${warns} warnings`) : "0 warnings"}\n`);
737
737
  process.exit(fails ? 1 : 0);
738
738
  }
739
+ /** Xvfb ran out of client slots at about 240 settings daemons; fail well before that. */
740
+ const SETTINGS_DAEMONS_FAIL = 100;
739
741
  /**
740
742
  * A computer that is configured but not running is the quiet failure here:
741
743
  * every session would try to start it and the first turn pays the whole boot,
@@ -773,6 +775,15 @@ export function computerDoctorChecks(c) {
773
775
  detail: "the container was created without the noVNC port mapping; `docker rm -f " + c.name + "` and `eve build` to recreate it (volumes keep the home and /workspace)",
774
776
  });
775
777
  }
778
+ if (c.containerState === "running" && typeof c.settingsDaemons === "number" && c.settingsDaemons > 1) {
779
+ checks.push({
780
+ verdict: c.settingsDaemons >= SETTINGS_DAEMONS_FAIL ? "fail" : "warn",
781
+ label: `the computer has ${c.settingsDaemons} display settings daemons running (one is right)`,
782
+ detail: "each restart of its display left one behind, and each holds an X client slot; at about 240 the screen stops accepting windows and `eve build` fails. " +
783
+ "Upgrade @kybernesis/computer to 0.3.1 or later (`kyb upgrade`), then clear the extras: " +
784
+ "`docker exec " + c.name + " sh -c 'n=$(pgrep -n -x xfsettingsd); for p in $(pgrep -x xfsettingsd); do [ $p = $n ] || kill $p; done'`",
785
+ });
786
+ }
776
787
  if (!c.vncPasswordSet) {
777
788
  checks.push({
778
789
  verdict: "warn",
@@ -794,11 +805,19 @@ export function inspectComputer(cwd) {
794
805
  const state = capture("docker", ["inspect", "-f", "{{.State.Running}}", name]);
795
806
  const containerState = state === null ? "unknown" : state.trim() === "true" ? "running" : state.trim() === "false" ? "stopped" : "missing";
796
807
  const ports = containerState === "running" ? capture("docker", ["port", name, "6080"]) : null;
808
+ const daemons = containerState === "running"
809
+ ? capture("docker", ["exec", name, "sh", "-c", "ps -C xfsettingsd -o stat= || true"])
810
+ : null;
797
811
  return {
798
812
  configured: true,
799
813
  name,
800
814
  containerState,
801
815
  screenBound: containerState === "running" ? Boolean(ports && ports.trim().length > 0) : null,
802
816
  vncPasswordSet: Boolean(env.COMPUTER_VNC_PASSWORD?.trim()),
817
+ settingsDaemons: daemons === null ? null : countLiveProcesses(daemons),
803
818
  };
804
819
  }
820
+ /** @internal Lines of `ps -o stat=` output that are not zombies (a zombie holds no X connection). */
821
+ export function countLiveProcesses(stats) {
822
+ return stats.split("\n").filter((line) => line.trim() && !line.trim().startsWith("Z")).length;
823
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/create",
3
- "version": "0.26.0",
3
+ "version": "0.26.1",
4
4
  "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent \u2014 plus doctor and upgrade.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",