@netnodeag/kraftwerk 0.75.1 → 0.77.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 (63) hide show
  1. package/README.md +33 -27
  2. package/dist/cli/cloud.d.ts +2 -0
  3. package/dist/cli/cloud.js +262 -0
  4. package/dist/cli/daemon-control.js +4 -2
  5. package/dist/cli/daemon.js +9 -0
  6. package/dist/cli/doctor.d.ts +3 -1
  7. package/dist/cli/doctor.js +51 -9
  8. package/dist/cli/init.js +7 -4
  9. package/dist/cli/kraftwerk.js +13 -5
  10. package/dist/cli/routines.d.ts +2 -1
  11. package/dist/cli/routines.js +40 -4
  12. package/dist/cli/whoami.d.ts +9 -0
  13. package/dist/cli/whoami.js +48 -0
  14. package/dist/client/routes.d.ts +7 -0
  15. package/dist/client/routes.js +7 -0
  16. package/dist/config.d.ts +35 -28
  17. package/dist/config.js +43 -22
  18. package/dist/core/attention.d.ts +8 -1
  19. package/dist/core/attention.js +38 -2
  20. package/dist/core/cloud.d.ts +115 -0
  21. package/dist/core/cloud.js +94 -0
  22. package/dist/core/identity.d.ts +46 -0
  23. package/dist/core/identity.js +106 -0
  24. package/dist/core/routines.d.ts +81 -0
  25. package/dist/core/routines.js +174 -33
  26. package/dist/server/api/agents.d.ts +5 -1
  27. package/dist/server/api/agents.js +19 -2
  28. package/dist/server/api/cloud.d.ts +72 -0
  29. package/dist/server/api/cloud.js +38 -0
  30. package/dist/server/api/devices.d.ts +8 -8
  31. package/dist/server/api/index.d.ts +102 -13
  32. package/dist/server/api/index.js +2 -0
  33. package/dist/server/api/runs.d.ts +3 -1
  34. package/dist/server/api/runs.js +9 -1
  35. package/dist/server/api/workspace.d.ts +22 -2
  36. package/dist/server/api/workspace.js +7 -1
  37. package/dist/server/cloud.d.ts +65 -33
  38. package/dist/server/cloud.js +207 -188
  39. package/dist/server/hub-context.d.ts +1 -1
  40. package/dist/server/hub-context.js +3 -3
  41. package/dist/server/push.js +1 -1
  42. package/dist/server/relay.d.ts +13 -0
  43. package/dist/server/relay.js +29 -1
  44. package/dist/server/server.d.ts +3 -2
  45. package/dist/server/server.js +6 -6
  46. package/package.json +1 -1
  47. package/schema/kraftwerk.schema.json +9 -4
  48. package/web/dist/assets/{dist-CezfArgg.js → dist-BGHweZKi.js} +1 -1
  49. package/web/dist/assets/{dist-Y9aHncjU.js → dist-BVPxOqcx.js} +1 -1
  50. package/web/dist/assets/{dist-CLZjnhZZ.js → dist-CCNyRSAA.js} +1 -1
  51. package/web/dist/assets/{dist-QqFmuPda.js → dist-CXoAMU1b.js} +1 -1
  52. package/web/dist/assets/{dist-BI4umsk6.js → dist-DCFREMXk.js} +1 -1
  53. package/web/dist/assets/{dist-YNCNGGgK.js → dist-DT2Tjvwx.js} +1 -1
  54. package/web/dist/assets/{dist-CzM6tn0f.js → dist-DdA5PoVJ.js} +1 -1
  55. package/web/dist/assets/{dist-CYicby0c.js → dist-DoD3qX1P.js} +1 -1
  56. package/web/dist/assets/{dist-CODxhtAK.js → dist-FFA4-S6d.js} +1 -1
  57. package/web/dist/assets/{dist-DaGnyH_l.js → dist-yGx0qYbw.js} +1 -1
  58. package/web/dist/assets/dist-zjUUP5a9.js +1 -0
  59. package/web/dist/assets/{editor-DEb8z5-Q.js → editor-CyWapLQr.js} +3 -3
  60. package/web/dist/assets/index-CNXcNoKJ.js +231 -0
  61. package/web/dist/index.html +1 -1
  62. package/web/dist/assets/dist-DtktO5hc.js +0 -1
  63. package/web/dist/assets/index-kmyK4tFm.js +0 -231
@@ -27,7 +27,9 @@ export declare const routes: (Route<"agents.addJournal", {
27
27
  }, "/api/agents/:slug/journal", z.ZodObject<{
28
28
  entry: z.ZodDefault<z.ZodString>;
29
29
  kind: z.ZodOptional<z.ZodString>;
30
- }, z.core.$strip>> | Route<"agents.archive", import("../../core/agents.js").AgentDetail, "/api/agents/:slug/archive", z.ZodObject<{
30
+ }, z.core.$strip>> | Route<"agents.adoptRoutine", import("../../core/routines.js").AdoptResult & {
31
+ routine: import("../../core/routines.js").RoutineStatus;
32
+ }, "/api/agents/:slug/routines/:id/adopt", undefined> | Route<"agents.archive", import("../../core/agents.js").AgentDetail, "/api/agents/:slug/archive", z.ZodObject<{
31
33
  archived: z.ZodDefault<z.ZodBoolean>;
32
34
  }, z.core.$strip>> | Route<"agents.create", import("../../core/agents.js").AgentDetail, "/api/agents", z.ZodObject<{
33
35
  name: z.ZodOptional<z.ZodString>;
@@ -78,6 +80,8 @@ export declare const routes: (Route<"agents.addJournal", {
78
80
  schedule: z.ZodOptional<z.ZodString>;
79
81
  prompt: z.ZodOptional<z.ZodString>;
80
82
  enabled: z.ZodOptional<z.ZodBoolean>;
83
+ runsOn: z.ZodOptional<z.ZodNullable<z.ZodString>>;
84
+ private: z.ZodOptional<z.ZodBoolean>;
81
85
  }, z.core.$strip>> | Route<"agents.saveSkill", import("../../core/skills.js").SkillInfo & {
82
86
  content: string;
83
87
  }, "/api/agents/:slug/skills", z.ZodObject<{
@@ -287,7 +291,70 @@ export declare const routes: (Route<"agents.addJournal", {
287
291
  ok: true;
288
292
  }, "/api/chats/:id/task-stop", z.ZodObject<{
289
293
  taskId: z.ZodDefault<z.ZodString>;
290
- }, z.core.$strip>> | Route<"devices.code", {
294
+ }, z.core.$strip>> | Route<"cloud.set", {
295
+ daemon: boolean;
296
+ url: string;
297
+ state: import("../cloud.js").CloudState;
298
+ reason?: string;
299
+ source?: import("../../core/cloud.js").CloudUrlSource;
300
+ error?: string;
301
+ id?: string;
302
+ machine?: string;
303
+ account?: string | null;
304
+ interval?: number;
305
+ lastSeen?: string;
306
+ claimCode?: string | null;
307
+ claimUrl?: string | null;
308
+ workspaces?: number;
309
+ }, "/api/cloud", z.ZodObject<{
310
+ enabled: z.ZodBoolean;
311
+ url: z.ZodOptional<z.ZodString>;
312
+ }, z.core.$strip>> | Route<"cloud.status", {
313
+ daemon: boolean;
314
+ url: string;
315
+ state: import("../cloud.js").CloudState;
316
+ reason?: string;
317
+ source?: import("../../core/cloud.js").CloudUrlSource;
318
+ error?: string;
319
+ id?: string;
320
+ machine?: string;
321
+ account?: string | null;
322
+ interval?: number;
323
+ lastSeen?: string;
324
+ claimCode?: string | null;
325
+ claimUrl?: string | null;
326
+ workspaces?: number;
327
+ }, "/api/cloud", undefined> | Route<"cloud.sync", {
328
+ daemon: boolean;
329
+ url: string;
330
+ state: import("../cloud.js").CloudState;
331
+ reason?: string;
332
+ source?: import("../../core/cloud.js").CloudUrlSource;
333
+ error?: string;
334
+ id?: string;
335
+ machine?: string;
336
+ account?: string | null;
337
+ interval?: number;
338
+ lastSeen?: string;
339
+ claimCode?: string | null;
340
+ claimUrl?: string | null;
341
+ workspaces?: number;
342
+ }, "/api/cloud/sync", undefined> | Route<"cloud.unlink", {
343
+ daemon: boolean;
344
+ url: string;
345
+ state: import("../cloud.js").CloudState;
346
+ reason?: string;
347
+ source?: import("../../core/cloud.js").CloudUrlSource;
348
+ error?: string;
349
+ id?: string;
350
+ machine?: string;
351
+ account?: string | null;
352
+ interval?: number;
353
+ lastSeen?: string;
354
+ claimCode?: string | null;
355
+ claimUrl?: string | null;
356
+ workspaces?: number;
357
+ }, "/api/cloud/unlink", undefined> | Route<"devices.code", {
291
358
  code: string;
292
359
  expiresAt: string;
293
360
  urls: string[];
@@ -303,16 +370,16 @@ export declare const routes: (Route<"agents.addJournal", {
303
370
  code: z.ZodString;
304
371
  name: z.ZodDefault<z.ZodString>;
305
372
  }, z.core.$strip>> | Route<"devices.relay", {
373
+ enabled: boolean;
374
+ url: string | null;
375
+ fingerprint: string | null;
376
+ daemon: boolean;
306
377
  state: import("../relay.js").RelayState;
307
378
  id?: string;
308
379
  key?: string;
309
380
  error?: string;
310
381
  clients: number;
311
382
  since?: string;
312
- enabled: boolean;
313
- url: string | null;
314
- fingerprint: string | null;
315
- daemon: boolean;
316
383
  }, "/api/devices/relay", undefined> | Route<"devices.revoke", {
317
384
  ok: boolean;
318
385
  }, "/api/devices/:id", undefined> | Route<"devices.self", {
@@ -328,16 +395,16 @@ export declare const routes: (Route<"agents.addJournal", {
328
395
  }>;
329
396
  key: z.ZodString;
330
397
  }, z.core.$strip>> | Route<"devices.setRelay", {
398
+ enabled: boolean;
399
+ url: string;
400
+ fingerprint: string;
401
+ daemon: boolean;
331
402
  state: import("../relay.js").RelayState;
332
403
  id?: string;
333
404
  key?: string;
334
405
  error?: string;
335
406
  clients: number;
336
407
  since?: string;
337
- enabled: boolean;
338
- url: string;
339
- fingerprint: string;
340
- daemon: boolean;
341
408
  }, "/api/devices/relay", z.ZodObject<{
342
409
  enabled: z.ZodBoolean;
343
410
  url: z.ZodOptional<z.ZodString>;
@@ -399,7 +466,12 @@ export declare const routes: (Route<"agents.addJournal", {
399
466
  aliasPort?: number | undefined;
400
467
  }, "/api/hub/open", z.ZodObject<{
401
468
  root: z.ZodString;
402
- }, z.core.$strip>> | Route<"knowledge.concept", import("../../okf.js").ConceptDetail, "/api/knowledge/:bundle/concept", undefined> | Route<"knowledge.create", import("../../okf.js").BundleInfo, "/api/knowledge", z.ZodObject<{
469
+ }, z.core.$strip>> | Route<"identity.get", {
470
+ handle: string;
471
+ machine: string;
472
+ identity: string;
473
+ previous: string[];
474
+ }, "/api/identity", undefined> | Route<"knowledge.concept", import("../../okf.js").ConceptDetail, "/api/knowledge/:bundle/concept", undefined> | Route<"knowledge.create", import("../../okf.js").BundleInfo, "/api/knowledge", z.ZodObject<{
403
475
  name: z.ZodDefault<z.ZodString>;
404
476
  }, z.core.$strip>> | Route<"knowledge.delete", {
405
477
  ok: boolean;
@@ -430,7 +502,22 @@ export declare const routes: (Route<"agents.addJournal", {
430
502
  vibeables: boolean;
431
503
  projects: boolean;
432
504
  publicUrl: string;
433
- cloud: import("../cloud.js").CloudStatus;
505
+ cloud: {
506
+ included: boolean;
507
+ url: string;
508
+ state: import("../cloud.js").CloudState;
509
+ reason?: string;
510
+ source?: import("../../core/cloud.js").CloudUrlSource;
511
+ error?: string;
512
+ id?: string;
513
+ machine?: string;
514
+ account?: string | null;
515
+ interval?: number;
516
+ lastSeen?: string;
517
+ claimCode?: string | null;
518
+ claimUrl?: string | null;
519
+ workspaces?: number;
520
+ };
434
521
  switcher: import("../../config.js").SwitcherEntry[];
435
522
  }, "/api/meta", undefined> | Route<"notifications.clear", {
436
523
  ok: boolean;
@@ -497,7 +584,9 @@ export declare const routes: (Route<"agents.addJournal", {
497
584
  error?: string;
498
585
  off?: boolean;
499
586
  repo?: import("../../core/repos.js").RepoInfo;
500
- }>, "/api/repos/:slug/update", undefined> | Route<"routines.list", {
587
+ }>, "/api/repos/:slug/update", undefined> | Route<"routines.adopt", import("../../core/routines.js").AdoptResult, "/api/routines/adopt", z.ZodObject<{
588
+ retired: z.ZodDefault<z.ZodBoolean>;
589
+ }, z.core.$strip>> | Route<"routines.list", {
501
590
  routines: (import("../../core/routines.js").RoutineStatus & {
502
591
  agent: {
503
592
  slug: string;
@@ -3,6 +3,7 @@ import { agentRoutes } from "./agents.js";
3
3
  import { attentionRoutes } from "./attention.js";
4
4
  import { channelRoutes } from "./channels.js";
5
5
  import { chatRoutes } from "./chats.js";
6
+ import { cloudRoutes } from "./cloud.js";
6
7
  import { deviceRoutes } from "./devices.js";
7
8
  import { hubRoutes } from "./hub.js";
8
9
  import { fileRoutes } from "./files.js";
@@ -35,6 +36,7 @@ const domainRoutes = [
35
36
  ...gitRoutes,
36
37
  ...vibeableRoutes,
37
38
  ...deviceRoutes,
39
+ ...cloudRoutes,
38
40
  ...hubRoutes,
39
41
  ];
40
42
  const protocolRoute = route({ name: "protocol.get", method: "GET", path: "/api/protocol", summary: "the protocol version and every route", access: "public" }, async () => ({
@@ -1,6 +1,8 @@
1
1
  import * as z from "zod";
2
2
  /** Workflows, their runs, and the routines that start them. */
3
- export declare const runRoutes: (import("./router.js").Route<"routines.list", {
3
+ export declare const runRoutes: (import("./router.js").Route<"routines.adopt", import("../../core/routines.js").AdoptResult, "/api/routines/adopt", z.ZodObject<{
4
+ retired: z.ZodDefault<z.ZodBoolean>;
5
+ }, z.core.$strip>> | import("./router.js").Route<"routines.list", {
4
6
  routines: (import("../../core/routines.js").RoutineStatus & {
5
7
  agent: {
6
8
  slug: string;
@@ -2,7 +2,7 @@ import { promises as fs } from "node:fs";
2
2
  import * as z from "zod";
3
3
  import { getOutputDir } from "../../core/context.js";
4
4
  import { decide } from "../../core/decisions.js";
5
- import { allRoutines } from "../../core/routines.js";
5
+ import { adoptUnassigned, allRoutines } from "../../core/routines.js";
6
6
  import { dockerStatus, stopRun, triggerRun } from "../../core/runner.js";
7
7
  import { deleteRun, getRun, listRuns, readRunFile, safeRunDir } from "../../core/runs.js";
8
8
  import { deleteWorkflow, getWorkflow, listWorkflows } from "../../core/workflows.js";
@@ -59,6 +59,14 @@ export const runRoutes = [
59
59
  route({ name: "routines.list", method: "GET", path: "/api/routines", summary: "every agent's routines with run state and the workflows each one names" }, async () => ({
60
60
  routines: await allRoutines((await listWorkflows()).workflows),
61
61
  })),
62
+ route({
63
+ name: "routines.adopt",
64
+ method: "POST",
65
+ path: "/api/routines/adopt",
66
+ summary: "run these here: every enabled routine without runs_on (and, with {retired: true}, those naming a retired identity) gets this machine; routines.yml committed",
67
+ errors: 400,
68
+ body: z.object({ retired: z.boolean().default(false) }),
69
+ }, async (c) => adoptUnassigned({ retired: (await c.body()).retired })),
62
70
  route({ name: "runs.list", method: "GET", path: "/api/runs", summary: "every run in the output dir" }, async () => ({ outputDir: getOutputDir(), runs: await listRuns() })),
63
71
  route({ name: "runs.get", method: "GET", path: "/api/runs/:id", summary: "one run: phases, gates, files" }, async (c) => (await validRun(getRun(c.params.id))) ?? fail(404, "not found")),
64
72
  route({ name: "runs.fileText", method: "GET", path: "/api/runs/:id/text", summary: "one run file's text ?name=, tail-capped" }, async (c) => {
@@ -6,7 +6,12 @@ type StartReply = StartResult & {
6
6
  here?: true;
7
7
  };
8
8
  /** The workspace itself: identity and features, settings, the other workspaces, updates. */
9
- export declare const workspaceRoutes: (import("./router.js").Route<"meta.get", {
9
+ export declare const workspaceRoutes: (import("./router.js").Route<"identity.get", {
10
+ handle: string;
11
+ machine: string;
12
+ identity: string;
13
+ previous: string[];
14
+ }, "/api/identity", undefined> | import("./router.js").Route<"meta.get", {
10
15
  workspaceName: string;
11
16
  workspaceSlug: string;
12
17
  workspaceIcon: string;
@@ -30,7 +35,22 @@ export declare const workspaceRoutes: (import("./router.js").Route<"meta.get", {
30
35
  projects: boolean;
31
36
  /** @deprecated Always "": the Cloudflare Tunnel that set it was removed in 0.65. Removed with protocol 2. */
32
37
  publicUrl: string;
33
- cloud: import("../cloud.js").CloudStatus;
38
+ cloud: {
39
+ included: boolean;
40
+ url: string;
41
+ state: import("../cloud.js").CloudState;
42
+ reason?: string;
43
+ source?: import("../../core/cloud.js").CloudUrlSource;
44
+ error?: string;
45
+ id?: string;
46
+ machine?: string;
47
+ account?: string | null;
48
+ interval?: number;
49
+ lastSeen?: string;
50
+ claimCode?: string | null;
51
+ claimUrl?: string | null;
52
+ workspaces?: number;
53
+ };
34
54
  switcher: import("../../config.js").SwitcherEntry[];
35
55
  }, "/api/meta", undefined> | import("./router.js").Route<"search.agents", {
36
56
  workspaces: (import("../../core/search.js").WorkspaceAgents & {
@@ -11,6 +11,7 @@ import { getSettings, saveSettings } from "../../core/settings.js";
11
11
  import { canSelfUpdate, startUpdate, updateStatus } from "../../core/update.js";
12
12
  import { getDiskVersion, getPkgName, getPkgVersion, RESTART_EXIT_CODE, supervised } from "../version.js";
13
13
  import { disposeAllDevs } from "../../core/vibeables.js";
14
+ import { identityString, readIdentity } from "../../core/identity.js";
14
15
  import { fail, reply, route } from "./router.js";
15
16
  /** A feature block with a folder (repos, vibeables, projects); saveSettings checks the root. Nested blocks are plain objects: saveSettings reads only these fields. */
16
17
  const RootBlock = z.object({ enabled: z.boolean(), root: z.string().optional() });
@@ -104,10 +105,15 @@ export const workspaceRoutes = [
104
105
  projects: (ws?.config.projects && ws.config.projects.enabled !== false) === true,
105
106
  /** @deprecated Always "": the Cloudflare Tunnel that set it was removed in 0.65. Removed with protocol 2. */
106
107
  publicUrl: "",
107
- cloud: cloudStatus(),
108
+ // The machine's cloud record (only the daemon registers one); `included`: this workspace rides along (no cloud.enabled: false veto).
109
+ cloud: { ...cloudStatus(), included: ws?.config.cloud?.enabled !== false },
108
110
  switcher,
109
111
  };
110
112
  }),
113
+ route({ name: "identity.get", method: "GET", path: "/api/identity", summary: "this machine's identity (handle@machine) — what routines name in runs_on" }, async () => {
114
+ const id = await readIdentity();
115
+ return { handle: id.handle, machine: id.machine, identity: identityString(id), previous: id.previous };
116
+ }),
111
117
  route({ name: "settings.get", method: "GET", path: "/api/settings", summary: "kraftwerk.yml, parsed, with resolved paths" }, async () => getSettings()),
112
118
  route({ name: "settings.save", method: "PUT", path: "/api/settings", summary: "write the UI-editable subset of kraftwerk.yml", errors: 400, body: SettingsFields }, async (c) => saveSettings((await c.body()))),
113
119
  route({ name: "workspaces.list", method: "GET", path: "/api/workspaces", summary: "every known workspace incl. this one, with state and counts" }, async () => placeInHub(await listWorkspacesDetailed())),
@@ -1,53 +1,85 @@
1
+ import { type CloudUrlSource } from "../core/cloud.js";
1
2
  /**
2
- * The cloud manager client: kraftwerk.yml `cloud:` makes this instance
3
- * register with the kraftwerk cloud when the inspector starts and heartbeat
4
- * while it runs — the same record ~/.kraftwerk/instances holds locally,
5
- * kept on a server so an admin (and, with an account token, the user)
6
- * sees every instance across machines.
3
+ * The machine client: the daemon registers THIS MACHINE with the kraftwerk
4
+ * cloud once and heartbeats while it runs; the workspaces it serves ride
5
+ * along as children of that record (see core/cloud.ts for the contract and
6
+ * the settings). One per process, and only the daemon starts it
7
+ * (startMachineCloud from `kraftwerk daemon`): a standalone `kraftwerk ui`
8
+ * and test fixtures never talk to the cloud.
7
9
  *
8
- * Identity: the first registration hands out an id + secret, stored under
9
- * ~/.kraftwerk/cloud/<hash(url, root)>.json and presented on every later
10
- * call, so a restart updates the record instead of creating a new one.
11
- * When the cloud does not recognise the id (data reset) it hands out a
12
- * fresh one and the file is rewritten.
13
- *
14
- * Everything is best-effort: a cloud that is down never affects the UI.
15
- * The status is reported in /api/meta so the UI can show it.
10
+ * start ensure the machine key (relay.json, relay stays off), drop the
11
+ * retired per-workspace identities (~/.kraftwerk/cloud/), and,
12
+ * unless cloud.json or KRAFTWERK_CLOUD_URL=off says no, register
13
+ * — anonymous: the answer carries a claim code until someone
14
+ * claims the machine (`kraftwerk login`, or the code in the UI)
15
+ * heartbeat every `interval` the cloud asked for; the workspace list rides
16
+ * along whenever it changed (opened, closed, vetoed, claimed).
17
+ * A claim made in the cloud arrives in the answer
18
+ * privacy while unclaimed, entries carry name/slug/ws-id only — no
19
+ * roots; once claimed, roots too
20
+ * recovery a cloud that no longer knows the machine (data reset) gets a
21
+ * fresh registration; a cloud that is down is retried at the
22
+ * same cadence and never affects the UI
23
+ * goodbye on shutdown (bounded), and when `kraftwerk cloud off` reaches
24
+ * the running daemon
16
25
  */
17
26
  export type CloudState = "off" | "connecting" | "connected" | "error";
18
27
  export interface CloudStatus {
19
28
  url: string;
20
29
  state: CloudState;
21
- /** Last error message while connecting or heartbeating. */
30
+ /** Why it is off, when it is. */
31
+ reason?: string;
32
+ /** Where the URL came from (env, cloud.json, a deprecated kraftwerk.yml cloud.url, the default). */
33
+ source?: CloudUrlSource;
34
+ /** Last error message while registering or heartbeating. */
22
35
  error?: string;
23
- /** Instance id in the cloud once registered. */
36
+ /** The machine's id in the cloud (its relay id). */
24
37
  id?: string;
25
- /** Email of the linked kraftwerk account, when a token was presented and accepted. */
38
+ /** This machine's handle@machine. */
39
+ machine?: string;
40
+ /** Email of the account that claimed the machine; null while unclaimed. */
26
41
  account?: string | null;
27
- /** Effective seconds between heartbeats (the cloud may raise the configured one). */
42
+ /** Effective seconds between heartbeats (what the cloud asked for). */
28
43
  interval?: number;
44
+ /** Last successful register or heartbeat. */
29
45
  lastSeen?: string;
30
- /** XXXX-XXXX the user types into the cloud UI to claim this instance; null once claimed. */
46
+ /** XXXX-XXXX that claims this machine in the cloud; null once claimed. */
31
47
  claimCode?: string | null;
32
- /** The cloud page that claims this instance after sign-in. */
48
+ /** The cloud page that claims this machine after sign-in. */
33
49
  claimUrl?: string | null;
50
+ /** Workspaces reported (vetoed ones left out). */
51
+ workspaces?: number;
34
52
  }
53
+ /** What the daemon serves right now. */
54
+ export type WorkspaceSource = () => Array<{
55
+ root: string;
56
+ slug: string;
57
+ name: string;
58
+ }>;
35
59
  export declare const cloudStatus: () => CloudStatus;
36
60
  /**
37
- * Start the client once the inspector listens. Resolves after the first
38
- * registration attempt (success or not); the heartbeat loop runs on its
39
- * own afterwards.
61
+ * Start the machine client (the daemon, once its workspaces are open).
62
+ * Resolves after the first registration attempt; the heartbeat runs on its
63
+ * own afterwards. A second start in the same process is ignored.
64
+ */
65
+ export declare function startMachineCloud(opts: {
66
+ version: string;
67
+ workspaces: WorkspaceSource;
68
+ owner?: unknown;
69
+ }): Promise<CloudStatus>;
70
+ /**
71
+ * Settings changed (`kraftwerk cloud on|off`, a URL): turn the client on or
72
+ * off to match; off says goodbye first. Without a started client (a
73
+ * standalone server) nothing happens.
40
74
  */
41
- export declare function startCloudSync(url: string, version: string): Promise<void>;
42
- /** Stop the heartbeat loop (server close, tests). */
43
- export declare function stopCloudSync(): void;
75
+ export declare function applyMachineCloud(): Promise<CloudStatus>;
76
+ /** A round now (the CLI's `login` waits for a claim): registers when needed, else heartbeats. */
77
+ export declare function syncMachineCloud(): Promise<CloudStatus>;
78
+ /** Release the claim (`kraftwerk logout`): the cloud hands out a fresh claim code. */
79
+ export declare function unlinkMachineCloud(): Promise<CloudStatus>;
44
80
  /**
45
- * Tell the cloud we are going away, so the record flips to "stopped" now
46
- * instead of after the grace period. Bounded: an exit handler waits for
47
- * this, and a slow cloud must not hold the process.
81
+ * Stop the client and tell the cloud the machine is going away (bounded:
82
+ * an exit handler waits for this). `owner`: only the client that owner
83
+ * started (a hub stopping in a test leaves another's alone).
48
84
  */
49
- export declare function cloudGoodbye(): Promise<void>;
50
- /** Every served workspace: stop its heartbeat (the server closes). */
51
- export declare function stopAllCloudSync(): void;
52
- /** Every served workspace says goodbye, in parallel (still bounded per workspace). */
53
- export declare function cloudGoodbyeAll(): Promise<void>;
85
+ export declare function stopMachineCloud(owner?: unknown): Promise<void>;