@jmfederico/pi-web 1.202606.0 → 1.202606.2

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 (95) hide show
  1. package/README.md +23 -7
  2. package/dist/client/assets/{CodeViewer-N88Bx8F6.js → CodeViewer-iYSv2-dg.js} +1 -1
  3. package/dist/client/assets/{TerminalPanel-DKiL51Xi.js → TerminalPanel-BpFW6j27.js} +4 -4
  4. package/dist/client/assets/index-D4dbiKXF.js +2210 -0
  5. package/dist/client/index.html +1 -1
  6. package/dist/config.js +63 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/pi-web-plugins/info/pi-web-plugin.js +8 -1
  9. package/dist/pi-web-plugins/updates/package.json +9 -0
  10. package/dist/pi-web-plugins/{pi-web → updates}/pi-web-plugin.js +38 -30
  11. package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
  12. package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
  13. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
  14. package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
  15. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +292 -0
  16. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
  17. package/dist/plugin-api/unstable.d.ts +22 -0
  18. package/dist/plugin-api.d.ts +169 -0
  19. package/dist/server/app.js +63 -26
  20. package/dist/server/app.js.map +1 -1
  21. package/dist/server/configRoutes.js +123 -0
  22. package/dist/server/configRoutes.js.map +1 -0
  23. package/dist/server/git/gitEnv.js +15 -0
  24. package/dist/server/git/gitEnv.js.map +1 -0
  25. package/dist/server/git/gitService.js +2 -1
  26. package/dist/server/git/gitService.js.map +1 -1
  27. package/dist/server/gitRoutes.js +3 -3
  28. package/dist/server/gitRoutes.js.map +1 -1
  29. package/dist/server/machines/machineClient.js +134 -0
  30. package/dist/server/machines/machineClient.js.map +1 -0
  31. package/dist/server/machines/machinePluginProxyRoutes.js +187 -0
  32. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
  33. package/dist/server/machines/machineProxyRoutes.js +92 -0
  34. package/dist/server/machines/machineProxyRoutes.js.map +1 -0
  35. package/dist/server/machines/machineRoutes.js +56 -0
  36. package/dist/server/machines/machineRoutes.js.map +1 -0
  37. package/dist/server/machines/machineService.js +260 -0
  38. package/dist/server/machines/machineService.js.map +1 -0
  39. package/dist/server/machines/machineStore.js +128 -0
  40. package/dist/server/machines/machineStore.js.map +1 -0
  41. package/dist/server/piWebPluginService.js +45 -15
  42. package/dist/server/piWebPluginService.js.map +1 -1
  43. package/dist/server/piWebStatus.js +127 -36
  44. package/dist/server/piWebStatus.js.map +1 -1
  45. package/dist/server/piWebStatusCache.js +32 -0
  46. package/dist/server/piWebStatusCache.js.map +1 -0
  47. package/dist/server/sessiond/sessionProxyRoutes.js +17 -14
  48. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  49. package/dist/server/sessiond.js +18 -7
  50. package/dist/server/sessiond.js.map +1 -1
  51. package/dist/server/sessions/piSessionManagerGateway.js +87 -0
  52. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
  53. package/dist/server/sessions/piSessionService.js +147 -66
  54. package/dist/server/sessions/piSessionService.js.map +1 -1
  55. package/dist/server/sessions/sessionArchiveStore.js +12 -0
  56. package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
  57. package/dist/server/sessions/sessionNameGenerator.js +2 -0
  58. package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
  59. package/dist/server/sessions/sessionRoutes.js +126 -43
  60. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  61. package/dist/server/terminalProxyRoutes.js +20 -10
  62. package/dist/server/terminalProxyRoutes.js.map +1 -1
  63. package/dist/server/terminals/terminalRoutes.js +11 -0
  64. package/dist/server/terminals/terminalRoutes.js.map +1 -1
  65. package/dist/server/terminals/terminalService.js +6 -0
  66. package/dist/server/terminals/terminalService.js.map +1 -1
  67. package/dist/server/workspaceExplorerRoutes.js +4 -4
  68. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  69. package/dist/server/workspaces/fileSuggestions.js +98 -17
  70. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  71. package/dist/server/workspaces/gitWorktreeDiscovery.js +3 -2
  72. package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -1
  73. package/dist/server/workspaces/workspaceDeletionRoutes.js +113 -0
  74. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
  75. package/dist/shared/apiTypes.d.ts +498 -0
  76. package/dist/shared/apiTypes.js +3 -1
  77. package/dist/shared/apiTypes.js.map +1 -1
  78. package/dist/shared/capabilities.js +25 -0
  79. package/dist/shared/capabilities.js.map +1 -0
  80. package/dist/shared/federatedRoutes.js +61 -0
  81. package/dist/shared/federatedRoutes.js.map +1 -0
  82. package/dist/shared/machinePluginIds.js +41 -0
  83. package/dist/shared/machinePluginIds.js.map +1 -0
  84. package/dist/shared/piWebStatusParsing.js +43 -0
  85. package/dist/shared/piWebStatusParsing.js.map +1 -1
  86. package/dist/shared/pluginIds.js +5 -0
  87. package/dist/shared/pluginIds.js.map +1 -0
  88. package/dist/shared/workspaceDeletion.js +12 -0
  89. package/dist/shared/workspaceDeletion.js.map +1 -0
  90. package/docs/plugins.md +278 -71
  91. package/package.json +8 -12
  92. package/plugin-api/unstable.d.ts +1 -0
  93. package/plugin-api.d.ts +1 -148
  94. package/dist/client/assets/index-DeSR1RUE.js +0 -1446
  95. package/dist/pi-web-plugins/pi-web/package.json +0 -9
@@ -0,0 +1,92 @@
1
+ import { FEDERATED_HTTP_ROUTES, FEDERATED_WEBSOCKET_ROUTES } from "../../shared/federatedRoutes.js";
2
+ import { bridgeSockets } from "../webSocketBridge.js";
3
+ import { RemoteMachineRequestError } from "./machineClient.js";
4
+ import { MachineService } from "./machineService.js";
5
+ export const REMOTE_HTTP_ROUTES = FEDERATED_HTTP_ROUTES;
6
+ export const REMOTE_WEBSOCKET_ROUTES = FEDERATED_WEBSOCKET_ROUTES;
7
+ const SAFE_RESPONSE_HEADERS = new Set([
8
+ "content-type",
9
+ "content-length",
10
+ "cache-control",
11
+ "last-modified",
12
+ "etag",
13
+ "content-security-policy",
14
+ "x-content-type-options",
15
+ ]);
16
+ export function registerMachineProxyRoutes(app, machines = new MachineService()) {
17
+ for (const spec of REMOTE_HTTP_ROUTES) {
18
+ app.route({
19
+ method: spec.method,
20
+ url: `/api/machines/:machineId${spec.path}`,
21
+ handler: (request, reply) => proxyHttpRequest(machines, request.params.machineId, request.method, request.url, request.body, reply),
22
+ });
23
+ }
24
+ for (const path of REMOTE_WEBSOCKET_ROUTES) {
25
+ app.get(`/api/machines/:machineId${path}`, { websocket: true }, async (socket, request) => {
26
+ await proxyWebSocket(machines, request.params.machineId, request.url, socket);
27
+ });
28
+ }
29
+ }
30
+ async function proxyHttpRequest(machines, machineId, method, requestUrl, body, reply) {
31
+ if (machineId === "local") {
32
+ return reply.code(501).send({ error: "Local machine route is not registered for this endpoint" });
33
+ }
34
+ const client = await machines.remoteClient(machineId);
35
+ if (client === undefined) {
36
+ return reply.code(404).send({ error: "Machine not found" });
37
+ }
38
+ try {
39
+ const upstream = await client.request(method, remoteApiPath(machineId, requestUrl), body);
40
+ reply.code(upstream.statusCode);
41
+ applySafeHeaders(reply, upstream.headers);
42
+ if (upstream.body === undefined)
43
+ return await reply.send();
44
+ return await reply.send(upstream.body);
45
+ }
46
+ catch (error) {
47
+ return sendGatewayError(reply, machineId, error);
48
+ }
49
+ }
50
+ async function proxyWebSocket(machines, machineId, requestUrl, socket) {
51
+ if (machineId === "local") {
52
+ socket.close(1011, "Local machine route is not registered for this endpoint");
53
+ return;
54
+ }
55
+ const client = await machines.remoteClient(machineId);
56
+ if (client === undefined) {
57
+ socket.close(1008, "Machine not found");
58
+ return;
59
+ }
60
+ try {
61
+ bridgeSockets(socket, client.connectWebSocket(remoteApiPath(machineId, requestUrl)));
62
+ }
63
+ catch {
64
+ socket.close(1011, "Remote machine unavailable");
65
+ }
66
+ }
67
+ function remoteApiPath(machineId, requestUrl) {
68
+ const machinePrefix = `/api/machines/${encodeURIComponent(machineId)}`;
69
+ const stripped = requestUrl.startsWith(machinePrefix) ? requestUrl.slice(machinePrefix.length) : requestUrl;
70
+ const compatPath = stripped.startsWith("/") ? stripped : `/${stripped}`;
71
+ return `/api${compatPath}`;
72
+ }
73
+ function applySafeHeaders(reply, headers) {
74
+ for (const [name, value] of Object.entries(headers)) {
75
+ if (value === undefined)
76
+ continue;
77
+ if (!SAFE_RESPONSE_HEADERS.has(name.toLowerCase()))
78
+ continue;
79
+ reply.header(name, value);
80
+ }
81
+ }
82
+ function sendGatewayError(reply, machineId, error) {
83
+ const statusCode = error instanceof RemoteMachineRequestError ? error.statusCode : 502;
84
+ const label = statusCode === 504 ? "Remote machine timeout" : "Remote machine unavailable";
85
+ return reply.code(statusCode).send({
86
+ error: label,
87
+ machineId,
88
+ statusCode,
89
+ detail: error instanceof Error ? error.message : String(error),
90
+ });
91
+ }
92
+ //# sourceMappingURL=machineProxyRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machineProxyRoutes.js","sourceRoot":"","sources":["../../../src/server/machines/machineProxyRoutes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { MachineService } from "./machineService.js";
2
+ export function registerMachineRoutes(app, machines = new MachineService()) {
3
+ app.get("/api/machines", async () => ({ machines: await machines.list() }));
4
+ app.post("/api/machines", async (request, reply) => {
5
+ try {
6
+ return await machines.add(request.body);
7
+ }
8
+ catch (error) {
9
+ return reply.code(400).send({ error: errorMessage(error) });
10
+ }
11
+ });
12
+ app.get("/api/machines/:machineId/health", async (request, reply) => {
13
+ const health = await machines.health(request.params.machineId);
14
+ if (health === undefined)
15
+ return reply.code(404).send({ error: "Machine not found" });
16
+ return health;
17
+ });
18
+ app.get("/api/machines/:machineId/runtime", async (request, reply) => {
19
+ const runtime = await machines.runtime(request.params.machineId);
20
+ if (runtime === undefined)
21
+ return reply.code(404).send({ error: "Machine not found" });
22
+ return runtime;
23
+ });
24
+ app.get("/api/machines/:machineId", async (request, reply) => {
25
+ const machine = await machines.get(request.params.machineId);
26
+ if (machine === undefined)
27
+ return reply.code(404).send({ error: "Machine not found" });
28
+ return machine;
29
+ });
30
+ app.patch("/api/machines/:machineId", async (request, reply) => {
31
+ try {
32
+ const machine = await machines.update(request.params.machineId, request.body);
33
+ if (machine === undefined)
34
+ return await reply.code(404).send({ error: "Machine not found" });
35
+ return machine;
36
+ }
37
+ catch (error) {
38
+ return reply.code(400).send({ error: errorMessage(error) });
39
+ }
40
+ });
41
+ app.delete("/api/machines/:machineId", async (request, reply) => {
42
+ try {
43
+ const removed = await machines.remove(request.params.machineId);
44
+ if (!removed)
45
+ return await reply.code(404).send({ error: "Machine not found" });
46
+ return { deleted: true };
47
+ }
48
+ catch (error) {
49
+ return reply.code(400).send({ error: errorMessage(error) });
50
+ }
51
+ });
52
+ }
53
+ function errorMessage(error) {
54
+ return error instanceof Error ? error.message : String(error);
55
+ }
56
+ //# sourceMappingURL=machineRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machineRoutes.js","sourceRoot":"","sources":["../../../src/server/machines/machineRoutes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAoD,MAAM,qBAAqB,CAAC;AAEvG,MAAM,UAAU,qBAAqB,CAAC,GAAoB,EAAE,QAAQ,GAAG,IAAI,cAAc,EAAE;IACzF,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAE5E,GAAG,CAAC,IAAI,CAA+B,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/E,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAoC,iCAAiC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACrG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/D,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACtF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAoC,kCAAkC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtG,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjE,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACvF,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAoC,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9F,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACvF,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,CAA8D,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1H,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9E,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YAC7F,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAAoC,0BAA0B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjG,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAChE,IAAI,CAAC,OAAO;gBAAE,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YAChF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,260 @@
1
+ import { isPiWebCapability } from "../../shared/capabilities.js";
2
+ import { getPiWebRuntime } from "../piWebStatus.js";
3
+ import { DEFAULT_REMOTE_HEALTH_TIMEOUT_MS, RemoteMachineClient, validateConfiguredMachineHeaders } from "./machineClient.js";
4
+ import { MachineStore } from "./machineStore.js";
5
+ const LOCAL_MACHINE_TIMESTAMP = "1970-01-01T00:00:00.000Z";
6
+ const DEFAULT_HEALTH_CACHE_TTL_MS = 5_000;
7
+ export class MachineService {
8
+ constructor(store = new MachineStore(), deps = {}) {
9
+ this.store = store;
10
+ this.deps = deps;
11
+ this.healthCache = new Map();
12
+ this.runtimeCache = new Map();
13
+ }
14
+ async list() {
15
+ return [localMachine(), ...(await this.store.list()).map(publicMachine)];
16
+ }
17
+ async get(id) {
18
+ if (id === "local")
19
+ return localMachine();
20
+ const machine = (await this.store.list()).find((stored) => stored.id === id);
21
+ return machine === undefined ? undefined : publicMachine(machine);
22
+ }
23
+ async add(input) {
24
+ const name = validateName(input.name);
25
+ const baseUrl = validateBaseUrl(input.baseUrl);
26
+ const stored = await this.store.add({ name, baseUrl, ...optionalSecrets(input) });
27
+ return publicMachine(stored);
28
+ }
29
+ async update(id, input) {
30
+ if (id === "local")
31
+ throw new Error("Local machine cannot be changed");
32
+ const patch = {};
33
+ if (input.name !== undefined)
34
+ patch.name = validateName(input.name);
35
+ if (input.baseUrl !== undefined)
36
+ patch.baseUrl = validateBaseUrl(input.baseUrl);
37
+ if (input.token !== undefined)
38
+ patch.token = input.token;
39
+ if (input.headers !== undefined)
40
+ patch.headers = validateHeaders(input.headers);
41
+ const stored = await this.store.update(id, patch);
42
+ if (stored !== undefined) {
43
+ this.healthCache.delete(id);
44
+ this.runtimeCache.delete(id);
45
+ }
46
+ return stored === undefined ? undefined : publicMachine(stored);
47
+ }
48
+ async remove(id) {
49
+ if (id === "local")
50
+ throw new Error("Local machine cannot be deleted");
51
+ const removed = await this.store.remove(id);
52
+ if (removed) {
53
+ this.healthCache.delete(id);
54
+ this.runtimeCache.delete(id);
55
+ }
56
+ return removed;
57
+ }
58
+ async storedRemote(id) {
59
+ if (id === "local")
60
+ return undefined;
61
+ return (await this.store.list()).find((machine) => machine.id === id);
62
+ }
63
+ async remoteClient(id) {
64
+ const machine = await this.storedRemote(id);
65
+ return machine === undefined ? undefined : this.clientFor(machine);
66
+ }
67
+ async health(id) {
68
+ const cached = this.healthCache.get(id);
69
+ const now = this.now().getTime();
70
+ if (cached !== undefined && cached.expiresAt > now)
71
+ return cached.health;
72
+ const health = id === "local" ? await this.localHealth() : await this.remoteHealth(id);
73
+ if (health === undefined)
74
+ return undefined;
75
+ this.healthCache.set(id, { expiresAt: now + (this.deps.healthCacheTtlMs ?? DEFAULT_HEALTH_CACHE_TTL_MS), health });
76
+ return health;
77
+ }
78
+ async runtime(id) {
79
+ const cached = this.runtimeCache.get(id);
80
+ const now = this.now().getTime();
81
+ if (cached !== undefined && cached.expiresAt > now)
82
+ return cached.runtime;
83
+ const runtime = id === "local" ? await this.localRuntime() : await this.remoteRuntime(id);
84
+ if (runtime === undefined)
85
+ return undefined;
86
+ this.runtimeCache.set(id, { expiresAt: now + (this.deps.runtimeCacheTtlMs ?? DEFAULT_HEALTH_CACHE_TTL_MS), runtime });
87
+ return runtime;
88
+ }
89
+ async localHealth() {
90
+ const checkedAt = this.now().toISOString();
91
+ try {
92
+ const runtime = await (this.deps.localRuntime ?? getPiWebRuntime)();
93
+ return {
94
+ machineId: "local",
95
+ ok: true,
96
+ checkedAt,
97
+ status: "online",
98
+ web: componentStatusFromRuntime(runtime.components.web),
99
+ sessiond: componentStatusFromRuntime(runtime.components.sessiond),
100
+ };
101
+ }
102
+ catch (error) {
103
+ return { machineId: "local", ok: false, checkedAt, status: "error", error: errorMessage(error) };
104
+ }
105
+ }
106
+ async remoteHealth(id) {
107
+ const machine = await this.storedRemote(id);
108
+ if (machine === undefined)
109
+ return undefined;
110
+ const checkedAt = this.now().toISOString();
111
+ try {
112
+ const response = await this.clientFor(machine).requestJson("GET", "/api/pi-web/status", undefined, { timeoutMs: DEFAULT_REMOTE_HEALTH_TIMEOUT_MS });
113
+ if (response.statusCode >= 200 && response.statusCode < 300 && isPiWebStatusResponse(response.body)) {
114
+ return { machineId: id, ok: true, checkedAt, status: "online", web: response.body.components.web, sessiond: response.body.components.sessiond };
115
+ }
116
+ return { machineId: id, ok: false, checkedAt, status: "error", error: `Remote health returned HTTP ${String(response.statusCode)}` };
117
+ }
118
+ catch (error) {
119
+ return { machineId: id, ok: false, checkedAt, status: "offline", error: errorMessage(error) };
120
+ }
121
+ }
122
+ async localRuntime() {
123
+ const checkedAt = this.now().toISOString();
124
+ try {
125
+ return machineRuntime("local", checkedAt, await (this.deps.localRuntime ?? getPiWebRuntime)());
126
+ }
127
+ catch (error) {
128
+ return { machineId: "local", ok: false, checkedAt, error: errorMessage(error) };
129
+ }
130
+ }
131
+ async remoteRuntime(id) {
132
+ const machine = await this.storedRemote(id);
133
+ if (machine === undefined)
134
+ return undefined;
135
+ const checkedAt = this.now().toISOString();
136
+ try {
137
+ const response = await this.clientFor(machine).requestJson("GET", "/api/pi-web/runtime", undefined, { timeoutMs: DEFAULT_REMOTE_HEALTH_TIMEOUT_MS });
138
+ if (response.statusCode >= 200 && response.statusCode < 300 && isPiWebRuntimeResponse(response.body))
139
+ return machineRuntime(id, checkedAt, response.body);
140
+ return { machineId: id, ok: false, checkedAt, error: `Remote runtime returned HTTP ${String(response.statusCode)}` };
141
+ }
142
+ catch (error) {
143
+ return { machineId: id, ok: false, checkedAt, error: errorMessage(error) };
144
+ }
145
+ }
146
+ clientFor(machine) {
147
+ return this.deps.remoteClientFactory?.(machine) ?? new RemoteMachineClient(machine);
148
+ }
149
+ now() {
150
+ return this.deps.now?.() ?? new Date();
151
+ }
152
+ }
153
+ export function localMachine() {
154
+ return { id: "local", name: "Local", kind: "local", createdAt: LOCAL_MACHINE_TIMESTAMP, updatedAt: LOCAL_MACHINE_TIMESTAMP };
155
+ }
156
+ function publicMachine(machine) {
157
+ return { id: machine.id, name: machine.name, kind: "remote", baseUrl: machine.baseUrl, createdAt: machine.createdAt, updatedAt: machine.updatedAt };
158
+ }
159
+ function validateName(value) {
160
+ const name = value?.trim();
161
+ if (name === undefined || name === "")
162
+ throw new Error("Machine name is required");
163
+ return name;
164
+ }
165
+ function validateBaseUrl(value) {
166
+ const raw = value?.trim();
167
+ if (raw === undefined || raw === "")
168
+ throw new Error("Machine baseUrl is required");
169
+ let url;
170
+ try {
171
+ url = new URL(raw);
172
+ }
173
+ catch {
174
+ throw new Error("Machine baseUrl must be a valid URL");
175
+ }
176
+ if (url.protocol !== "http:" && url.protocol !== "https:")
177
+ throw new Error("Machine baseUrl must use http or https");
178
+ if (url.username !== "" || url.password !== "")
179
+ throw new Error("Machine baseUrl must not include credentials");
180
+ if (url.search !== "" || url.hash !== "")
181
+ throw new Error("Machine baseUrl must not include query or hash");
182
+ return url.href.replace(/\/$/u, "");
183
+ }
184
+ function optionalSecrets(input) {
185
+ return {
186
+ ...(input.token === undefined ? {} : { token: input.token }),
187
+ ...(input.headers === undefined ? {} : { headers: validateHeaders(input.headers) }),
188
+ };
189
+ }
190
+ function validateHeaders(value) {
191
+ return validateConfiguredMachineHeaders(value) ?? {};
192
+ }
193
+ function errorMessage(error) {
194
+ return error instanceof Error ? error.message : String(error);
195
+ }
196
+ function componentStatusFromRuntime(runtime) {
197
+ return {
198
+ component: runtime.component,
199
+ label: runtime.label,
200
+ ...(runtime.runtimeVersion === undefined ? {} : { runtimeVersion: runtime.runtimeVersion }),
201
+ stale: false,
202
+ available: runtime.available,
203
+ ...(runtime.error === undefined ? {} : { error: runtime.error }),
204
+ };
205
+ }
206
+ function machineRuntime(machineId, checkedAt, runtime) {
207
+ return {
208
+ machineId,
209
+ ok: true,
210
+ checkedAt,
211
+ packageName: runtime.packageName,
212
+ generatedAt: runtime.generatedAt,
213
+ components: runtime.components,
214
+ capabilities: runtime.capabilities,
215
+ };
216
+ }
217
+ function isPiWebStatusResponse(value) {
218
+ if (!isRecord(value))
219
+ return false;
220
+ const components = value["components"];
221
+ if (!isRecord(components))
222
+ return false;
223
+ return isPiWebComponentStatus(components["web"]) && isPiWebComponentStatus(components["sessiond"]);
224
+ }
225
+ function isPiWebRuntimeResponse(value) {
226
+ if (!isRecord(value))
227
+ return false;
228
+ const packageName = value["packageName"];
229
+ const generatedAt = value["generatedAt"];
230
+ const components = value["components"];
231
+ const capabilities = value["capabilities"];
232
+ if (typeof packageName !== "string" || typeof generatedAt !== "string" || !isRecord(components) || !isPiWebCapabilityArray(capabilities))
233
+ return false;
234
+ return isPiWebRuntimeComponent(components["web"]) && isPiWebRuntimeComponent(components["sessiond"]);
235
+ }
236
+ function isPiWebComponentStatus(value) {
237
+ if (!isRecord(value))
238
+ return false;
239
+ const component = value["component"];
240
+ return (component === "web" || component === "sessiond")
241
+ && typeof value["label"] === "string"
242
+ && typeof value["stale"] === "boolean"
243
+ && typeof value["available"] === "boolean";
244
+ }
245
+ function isPiWebRuntimeComponent(value) {
246
+ if (!isRecord(value))
247
+ return false;
248
+ const component = value["component"];
249
+ return (component === "web" || component === "sessiond")
250
+ && typeof value["label"] === "string"
251
+ && typeof value["available"] === "boolean"
252
+ && isPiWebCapabilityArray(value["capabilities"]);
253
+ }
254
+ function isPiWebCapabilityArray(value) {
255
+ return Array.isArray(value) && value.every(isPiWebCapability);
256
+ }
257
+ function isRecord(value) {
258
+ return typeof value === "object" && value !== null && !Array.isArray(value);
259
+ }
260
+ //# sourceMappingURL=machineService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machineService.js","sourceRoot":"","sources":["../../../src/server/machines/machineService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { piWebDataDir } from "../../config.js";
5
+ const MACHINE_STORE_FILE_MODE = 0o600;
6
+ export function defaultMachineStorePath(env = process.env, cwd = process.cwd()) {
7
+ return join(piWebDataDir(env, cwd), "machines.json");
8
+ }
9
+ export function machineStorePath(env = process.env, cwd = process.cwd()) {
10
+ const configured = env["PI_WEB_MACHINES_FILE"];
11
+ if (configured === undefined || configured === "")
12
+ return defaultMachineStorePath(env, cwd);
13
+ return resolve(cwd, configured);
14
+ }
15
+ export class MachineStore {
16
+ constructor(filePath = machineStorePath()) {
17
+ this.filePath = filePath;
18
+ }
19
+ async list() {
20
+ return (await this.read()).machines;
21
+ }
22
+ async add(input) {
23
+ const data = await this.read();
24
+ const now = new Date().toISOString();
25
+ const machine = {
26
+ id: randomUUID(),
27
+ name: input.name,
28
+ kind: "remote",
29
+ baseUrl: input.baseUrl,
30
+ ...(input.token === undefined ? {} : { token: input.token }),
31
+ ...(input.headers === undefined ? {} : { headers: input.headers }),
32
+ createdAt: now,
33
+ updatedAt: now,
34
+ };
35
+ data.machines.push(machine);
36
+ await this.write(data);
37
+ return machine;
38
+ }
39
+ async update(id, patch) {
40
+ const data = await this.read();
41
+ const index = data.machines.findIndex((machine) => machine.id === id);
42
+ if (index < 0)
43
+ return undefined;
44
+ const current = data.machines[index];
45
+ if (current === undefined)
46
+ return undefined;
47
+ const next = { ...current, ...patch, updatedAt: new Date().toISOString() };
48
+ data.machines[index] = next;
49
+ await this.write(data);
50
+ return next;
51
+ }
52
+ async remove(id) {
53
+ const data = await this.read();
54
+ const machines = data.machines.filter((machine) => machine.id !== id);
55
+ if (machines.length === data.machines.length)
56
+ return false;
57
+ await this.write({ machines });
58
+ return true;
59
+ }
60
+ async read() {
61
+ try {
62
+ const value = JSON.parse(await readFile(this.filePath, "utf8"));
63
+ const parsed = parseMachineFile(value);
64
+ await restrictMachineStorePermissions(this.filePath);
65
+ return parsed;
66
+ }
67
+ catch (error) {
68
+ if (isNodeErrorWithCode(error, "ENOENT"))
69
+ return { machines: [] };
70
+ throw error;
71
+ }
72
+ }
73
+ async write(data) {
74
+ await mkdir(dirname(this.filePath), { recursive: true });
75
+ await writeFile(this.filePath, `${JSON.stringify(data, null, 2)}\n`, { encoding: "utf8", mode: MACHINE_STORE_FILE_MODE });
76
+ await restrictMachineStorePermissions(this.filePath);
77
+ }
78
+ }
79
+ function parseMachineFile(value) {
80
+ if (!isRecord(value) || !Array.isArray(value["machines"]))
81
+ throw new Error("Invalid machine file");
82
+ return { machines: value["machines"].map(parseStoredMachine) };
83
+ }
84
+ function parseStoredMachine(value) {
85
+ if (!isRecord(value))
86
+ throw new Error("Invalid machine");
87
+ const id = value["id"];
88
+ const name = value["name"];
89
+ const kind = value["kind"];
90
+ const baseUrl = value["baseUrl"];
91
+ const createdAt = value["createdAt"];
92
+ const updatedAt = value["updatedAt"];
93
+ if (typeof id !== "string" || typeof name !== "string" || kind !== "remote" || typeof baseUrl !== "string" || typeof createdAt !== "string" || typeof updatedAt !== "string")
94
+ throw new Error("Invalid machine");
95
+ const token = optionalString(value["token"], "token");
96
+ const headers = optionalStringRecord(value["headers"], "headers");
97
+ return { id, name, kind, baseUrl, createdAt, updatedAt, ...(token === undefined ? {} : { token }), ...(headers === undefined ? {} : { headers }) };
98
+ }
99
+ function optionalString(value, key) {
100
+ if (value === undefined)
101
+ return undefined;
102
+ if (typeof value !== "string")
103
+ throw new Error(`Invalid machine ${key}`);
104
+ return value;
105
+ }
106
+ function optionalStringRecord(value, key) {
107
+ if (value === undefined)
108
+ return undefined;
109
+ if (!isRecord(value))
110
+ throw new Error(`Invalid machine ${key}`);
111
+ return Object.fromEntries(Object.entries(value).map(([header, headerValue]) => {
112
+ if (typeof headerValue !== "string")
113
+ throw new Error(`Invalid machine ${key}`);
114
+ return [header, headerValue];
115
+ }));
116
+ }
117
+ async function restrictMachineStorePermissions(path) {
118
+ if (process.platform === "win32")
119
+ return;
120
+ await chmod(path, MACHINE_STORE_FILE_MODE);
121
+ }
122
+ function isRecord(value) {
123
+ return typeof value === "object" && value !== null && !Array.isArray(value);
124
+ }
125
+ function isNodeErrorWithCode(error, code) {
126
+ return error instanceof Error && "code" in error && error.code === code;
127
+ }
128
+ //# sourceMappingURL=machineStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machineStore.js","sourceRoot":"","sources":["../../../src/server/machines/machineStore.ts"],"names":[],"mappings":"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"}