@slock-ai/computer 0.0.15 → 0.0.16

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.
@@ -11,7 +11,7 @@ interface ServerStatusRow {
11
11
  serverMachineId: string;
12
12
  serverUrl: string;
13
13
  attachedAt: string | null;
14
- daemonLogPath: string;
14
+ serverRunnerLogPath: string;
15
15
  daemon: DaemonState;
16
16
  /** v6 §11 health enum surfaced in `status` table (PR-H §3.3). */
17
17
  health: ServerHealth;
@@ -22,7 +22,7 @@ interface ComputerStatusReport {
22
22
  userId: string | null;
23
23
  loginServerUrl: string | null;
24
24
  userSessionError: string | null;
25
- supervisor: DaemonState & {
25
+ service: DaemonState & {
26
26
  logPath: string;
27
27
  };
28
28
  servers: ServerStatusRow[];
@@ -45,13 +45,13 @@ interface RunnerListItem {
45
45
  * budget near breach, see §1/§2)
46
46
  * crashed — observed exit / fatal signal
47
47
  * stopped — intentional stop (operator-driven via `runners stop` or
48
- * supervisor shutdown)
48
+ * service shutdown)
49
49
  */
50
50
  declare const RUNNER_STATE_VALUES: readonly ["starting", "running", "degraded", "crashed", "stopped"];
51
51
  type RunnerState = (typeof RUNNER_STATE_VALUES)[number];
52
52
  declare function isRunnerState(value: unknown): value is RunnerState;
53
53
  /**
54
- * Service (supervisor) lifecycle states (§3.2). Mirrors runner shape but
54
+ * Service (service) lifecycle states (§3.2). Mirrors runner shape but
55
55
  * narrower — the service is a singleton per install root.
56
56
  *
57
57
  * starting — pidfile written, socket not yet listening
@@ -465,7 +465,7 @@ declare function readServiceStatus(installRoot: string): Promise<ServiceStatusRe
465
465
  * Read a single attached server's daemon state row plus the runners
466
466
  * currently running on it. Throws `StateReaderError("NOT_ATTACHED")` if
467
467
  * `serverId` is not in the attached set, or `"INVALID_ATTACHMENT"` if
468
- * the attachment.json under that id is unreadable.
468
+ * the runner.state.json under that id is unreadable.
469
469
  */
470
470
  declare function readRunnerStatus(installRoot: string, serverId: string): Promise<RunnerStatusResult>;
471
471
  /**
package/dist/lib/index.js CHANGED
@@ -126,22 +126,38 @@ function serverDir(slockHome, serverId) {
126
126
  return path.join(serversDir(slockHome), assertValidServerId(serverId));
127
127
  }
128
128
  function serverAttachmentPath(slockHome, serverId) {
129
- return path.join(serverDir(slockHome, serverId), "attachment.json");
129
+ return path.join(serverDir(slockHome, serverId), "runner.state.json");
130
130
  }
131
- function serverDaemonPidPath(slockHome, serverId) {
132
- return path.join(serverDir(slockHome, serverId), "daemon.pid");
131
+ function serverRunnerPidPath(slockHome, serverId) {
132
+ return path.join(serverDir(slockHome, serverId), "server-runner.pid");
133
133
  }
134
- function serverDaemonLogPath(slockHome, serverId) {
135
- return path.join(serverDir(slockHome, serverId), "daemon.log");
134
+ function serverRunnerLogPath(slockHome, serverId) {
135
+ return path.join(serverDir(slockHome, serverId), "server-runner.log");
136
136
  }
137
137
  function serverHealthPath(slockHome, serverId) {
138
138
  return path.join(serverDir(slockHome, serverId), "health.json");
139
139
  }
140
- function supervisorPidPath(slockHome) {
140
+ function serviceRunDir(slockHome) {
141
+ return path.join(computerDir(slockHome), "run");
142
+ }
143
+ function servicePidPath(slockHome) {
144
+ return path.join(serviceRunDir(slockHome), "service.pid");
145
+ }
146
+ function legacyServicePidPath(slockHome) {
147
+ return path.join(computerDir(slockHome), "service.pid");
148
+ }
149
+ function legacySupervisorPidPath(slockHome) {
141
150
  return path.join(computerDir(slockHome), "supervisor.pid");
142
151
  }
143
- function supervisorLogPath(slockHome) {
144
- return path.join(computerDir(slockHome), "supervisor.log");
152
+ function servicePidReadFallback(slockHome) {
153
+ return [
154
+ servicePidPath(slockHome),
155
+ legacyServicePidPath(slockHome),
156
+ legacySupervisorPidPath(slockHome)
157
+ ];
158
+ }
159
+ function serviceLogPath(slockHome) {
160
+ return path.join(serviceRunDir(slockHome), "service.log");
145
161
  }
146
162
 
147
163
  // src/serverState.ts
@@ -220,6 +236,41 @@ function isProcessAlive(pid) {
220
236
  }
221
237
  }
222
238
 
239
+ // src/internal/service-pid-fallback.ts
240
+ async function findLiveServicePidReadOnly(slockHome, deps = {}) {
241
+ const readPidfile = deps.readPidfile ?? readPidfileAt;
242
+ const isAlive = deps.isProcessAlive ?? isProcessAlive;
243
+ return walkFallback(slockHome, readPidfile, isAlive, async () => void 0);
244
+ }
245
+ async function walkFallback(slockHome, readPidfile, isAlive, clearStale) {
246
+ const candidates = servicePidReadFallback(slockHome);
247
+ let firstStalePidfile = null;
248
+ let firstStalePid = null;
249
+ for (const candidate of candidates) {
250
+ const candidatePid = await readPidfile(candidate);
251
+ if (candidatePid === null) continue;
252
+ if (isAlive(candidatePid)) {
253
+ return {
254
+ pid: candidatePid,
255
+ pidfilePath: candidate,
256
+ firstStalePidfile,
257
+ firstStalePid
258
+ };
259
+ }
260
+ await clearStale(candidate);
261
+ if (firstStalePidfile === null) {
262
+ firstStalePidfile = candidate;
263
+ firstStalePid = candidatePid;
264
+ }
265
+ }
266
+ return {
267
+ pid: null,
268
+ pidfilePath: candidates[0],
269
+ firstStalePidfile,
270
+ firstStalePid
271
+ };
272
+ }
273
+
223
274
  // src/health.ts
224
275
  import { readFile as readFile4, writeFile as writeFile3, unlink as unlink3, mkdir as mkdir3, appendFile } from "fs/promises";
225
276
  import { dirname as dirname3 } from "path";
@@ -274,6 +325,10 @@ async function pidStatus(pidfile) {
274
325
  const pid = await readPidfileAt(pidfile);
275
326
  return pid !== null && isProcessAlive(pid) ? { running: true, pid } : { running: false };
276
327
  }
328
+ async function serviceState(slockHome) {
329
+ const { pid } = await findLiveServicePidReadOnly(slockHome);
330
+ return pid !== null ? { running: true, pid } : { running: false };
331
+ }
277
332
  async function deriveHealth(slockHome, serverId, daemon) {
278
333
  if (!daemon.running) return "offline";
279
334
  if (await isDegraded(slockHome, serverId)) return "degraded";
@@ -283,20 +338,20 @@ async function buildStatusReport(installRoot) {
283
338
  const sessionRead = await readUserSession(userSessionPath(installRoot));
284
339
  const session = sessionRead.session;
285
340
  const attachments = await listServerAttachments(installRoot);
286
- const supervisor = {
287
- ...await pidStatus(supervisorPidPath(installRoot)),
288
- logPath: supervisorLogPath(installRoot)
341
+ const service = {
342
+ ...await serviceState(installRoot),
343
+ logPath: serviceLogPath(installRoot)
289
344
  };
290
345
  const servers = [];
291
346
  for (const a of attachments) {
292
- const daemon = await pidStatus(serverDaemonPidPath(installRoot, a.serverId));
347
+ const daemon = await pidStatus(serverRunnerPidPath(installRoot, a.serverId));
293
348
  servers.push({
294
349
  serverId: a.serverId,
295
350
  serverSlug: a.serverSlug ?? null,
296
351
  serverMachineId: a.serverMachineId,
297
352
  serverUrl: a.serverUrl,
298
353
  attachedAt: a.attachedAt ?? null,
299
- daemonLogPath: serverDaemonLogPath(installRoot, a.serverId),
354
+ serverRunnerLogPath: serverRunnerLogPath(installRoot, a.serverId),
300
355
  daemon,
301
356
  health: await deriveHealth(installRoot, a.serverId, daemon)
302
357
  });
@@ -308,7 +363,7 @@ async function buildStatusReport(installRoot) {
308
363
  userId: session ? str(session.userId) : null,
309
364
  loginServerUrl: session ? str(session.serverUrl) : null,
310
365
  userSessionError: sessionRead.state === "invalid" ? sessionRead.error : null,
311
- supervisor,
366
+ service,
312
367
  servers
313
368
  };
314
369
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/computer",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Slock Computer — standalone human/local-machine control-plane CLI (login + attach). Distinct from the agent-facing @slock-ai/cli.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -44,6 +44,7 @@
44
44
  "build": "pnpm run build:deps && tsup",
45
45
  "test": "node --import tsx --test --test-force-exit 'src/**/*.test.ts'",
46
46
  "typecheck": "tsc --noEmit",
47
- "lint:boundaries": "node scripts/check-boundaries.mjs"
47
+ "lint:boundaries": "node scripts/check-boundaries.mjs",
48
+ "lint:naming": "node scripts/check-naming.mjs"
48
49
  }
49
50
  }