paseo-plugin-machine-status 0.1.1 → 0.2.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/OVERVIEW.md +26 -0
- package/README.md +33 -11
- package/client/compat.tsx +123 -0
- package/client/pill.tsx +2 -1
- package/client/status.tsx +13 -4
- package/index.client.tsx +30 -11
- package/package.json +9 -2
package/OVERVIEW.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Machine Status shows what the daemon's Mac is doing while your agents work: CPU load, memory pressure, swap, disk, battery and thermal state, the ports and background processes your agents started, and the Docker engine. It also clears developer caches and stops runaway processes, with a confirmation step for each.
|
|
2
|
+
|
|
3
|
+
## What you get
|
|
4
|
+
|
|
5
|
+
- **Machine screen**, opened from the sidebar or ⌘K. Overview has stat tiles that expand into detail, CPU and memory charts, a dev-cache scanner, and a process table. Ports & services lists listening ports and what runs behind them. Docker shows the engine, containers and disk usage.
|
|
6
|
+
- **Load pill** beside every agent's composer with CPU load and memory pressure. Pressing it opens a compact card with the trend, the top CPU processes, and the development ports held by agents, so you can tell whether the machine is the problem without leaving the chat.
|
|
7
|
+
- On Paseo 0.11 and newer, ⌘K can open the screen straight on Ports & services or Docker.
|
|
8
|
+
|
|
9
|
+
## How it decides
|
|
10
|
+
|
|
11
|
+
- Memory follows Activity Monitor's split, and the pressure figure is macOS's own. Cached files are not counted as used.
|
|
12
|
+
- A background process belongs to an agent when it descends from the Paseo daemon in the process tree, not when its name looks like a provider. A port counts as a development port by its executable's path, not by its number. System ports are hidden until you choose **Show system**.
|
|
13
|
+
- Values the plugin cannot read are shown as missing rather than estimated. Per-core utilisation is not shown at all.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
- A macOS daemon on Paseo 0.8 to 0.12. On other platforms the screen says it cannot collect metrics.
|
|
18
|
+
- Docker Desktop, OrbStack or Rancher Desktop for the Docker tab. Without one, the tab says which is missing.
|
|
19
|
+
|
|
20
|
+
## What it can change
|
|
21
|
+
|
|
22
|
+
- **Dev caches**: only a fixed list of caches that their tools recreate (npm, pnpm, Yarn, Bun, Turbo, Xcode DerivedData, Cargo, Go, pip, uv). The client sends a cache id, never a path; each path must resolve below your home directory, and only its contents are removed.
|
|
23
|
+
- **Processes**: SIGTERM first, and force kill only as a separate confirmed step. Paseo and its parent processes are protected and checked again on every kill.
|
|
24
|
+
- **Docker**: start, stop, restart and remove containers, quit or start the engine, and prune stopped containers and dangling images. Volumes are never pruned.
|
|
25
|
+
|
|
26
|
+
Everything runs on the daemon through local commands such as `vm_stat`, `ps`, `lsof`, `netstat` and `docker`. Nothing is sent off the machine.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
|
-
<img src="https://img.shields.io/badge/Paseo-0.8.x%20%E2%80%93%200.
|
|
10
|
+
<img src="https://img.shields.io/badge/Paseo-0.8.x%20%E2%80%93%200.12.x-3987e5" alt="Supports Paseo 0.8.x through 0.12.x, including betas">
|
|
11
11
|
<img src="https://img.shields.io/badge/macOS-only-9aa1a6" alt="macOS only">
|
|
12
12
|
<img src="https://img.shields.io/badge/tests-237-199e70" alt="237 tests">
|
|
13
13
|
<img src="https://img.shields.io/badge/dependencies-none-c98500" alt="No runtime dependencies">
|
|
@@ -35,11 +35,11 @@ paseo plugin ls # expect: running
|
|
|
35
35
|
|
|
36
36
|
Paseo 0.8 has no npm sources, so install from Git there:
|
|
37
37
|
`paseo plugin add dutchakdev/paseo-plugin-machine-status`. Either way,
|
|
38
|
-
`paseo plugin update machine-status` pulls later releases. The plugin supports **Paseo 0.8.x through 0.
|
|
38
|
+
`paseo plugin update machine-status` pulls later releases. The plugin supports **Paseo 0.8.x through 0.12.x, including betas**,
|
|
39
39
|
on both the daemon, which runs its collectors, and the app, which runs its screens.
|
|
40
40
|
|
|
41
|
-
The manifest remains `>=0.8.0`, which already admits 0.9.x
|
|
42
|
-
prerelease's stable version core, so `0.
|
|
41
|
+
The manifest remains `>=0.8.0`, which already admits 0.9.x through 0.12.x. Paseo also checks a
|
|
42
|
+
prerelease's stable version core, so `0.12.0-beta.1` satisfies this range; see
|
|
43
43
|
[version requirements](https://paseo.sh/docs/plugins/reference#requirements).
|
|
44
44
|
|
|
45
45
|
To work on it locally instead:
|
|
@@ -56,7 +56,10 @@ paseo plugin ls # expect: running
|
|
|
56
56
|
Plugins must be enabled daemon-wide first, under **Settings → Plugins → Enable
|
|
57
57
|
plugins** (the root `pluginsEnabled` field in `~/.paseo/config.json`).
|
|
58
58
|
|
|
59
|
-
Open it from the **Machine** sidebar item, or ⌘K → "Machine status".
|
|
59
|
+
Open it from the **Machine** sidebar item, or ⌘K → "Machine status". On Paseo 0.11
|
|
60
|
+
and newer, ⌘K also offers "Machine: ports & services" and "Machine: Docker", which
|
|
61
|
+
open straight on that tab, and the tab travels in the screen's link (`?tab=services`,
|
|
62
|
+
`?tab=docker`), so reload and back keep it.
|
|
60
63
|
|
|
61
64
|
## The screen
|
|
62
65
|
|
|
@@ -328,8 +331,7 @@ confirmed step.
|
|
|
328
331
|
## Development
|
|
329
332
|
|
|
330
333
|
```bash
|
|
331
|
-
npm run typecheck
|
|
332
|
-
npm test # 237 tests
|
|
334
|
+
npm run check # typecheck, then the tests
|
|
333
335
|
paseo plugin reload machine-status # source edits need an explicit reload
|
|
334
336
|
paseo plugin logs machine-status
|
|
335
337
|
npm run preview # regenerates docs/preview.svg from the real palette
|
|
@@ -344,15 +346,35 @@ would otherwise surface as an RPC rejection at runtime. The live tests never
|
|
|
344
346
|
mutate anything: cleanup is only planned, and the kill tests assert refusals,
|
|
345
347
|
including a refusal to terminate the test runner itself.
|
|
346
348
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
349
|
+
### Paseo versions
|
|
350
|
+
|
|
351
|
+
The SDK stays pinned to 0.8.0 for typechecking and tests, so the compiler proves
|
|
352
|
+
the plugin uses only the oldest supported API. Paseo supplies the runtime instances
|
|
353
|
+
on every supported release line, so none of it ships with the plugin.
|
|
354
|
+
|
|
355
|
+
Paseo 0.11 replaced surfaces with screens and kept the old calls as deprecated
|
|
356
|
+
aliases. The manifest still admits 0.8, and each connected app evaluates the client
|
|
357
|
+
entry against its own version, so `client/compat.tsx` describes the 0.11 additions
|
|
358
|
+
locally and calls them only after checking that the app has them:
|
|
359
|
+
|
|
360
|
+
| App version | Screen | Sidebar | Opens with | Tab shortcuts in ⌘K |
|
|
361
|
+
| ----------- | ------ | ------- | ---------- | ------------------- |
|
|
362
|
+
| 0.11 and newer | `addScreen` | `addSidebarHeaderItem` + `SidebarRow` | `openScreen`, with `?tab=` | yes |
|
|
363
|
+
| 0.8 to 0.10 | `addSurface` | `addSidebarItem` | `openSurface`, overview tab | not offered |
|
|
364
|
+
|
|
365
|
+
Both paths register under the id `main`, so saved `/plugin/machine-status/main`
|
|
366
|
+
links open the same screen after an upgrade. `tests/compat.test.ts` pins both
|
|
367
|
+
paths, including a half-present API, which falls back rather than mixing the two.
|
|
368
|
+
The daemon half uses only `server.handle`, which has not changed since 0.8.
|
|
369
|
+
|
|
370
|
+
Releases are cut from tags by GitHub Actions; see [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
371
|
+
for the flow and [CHANGELOG.md](CHANGELOG.md) for what changed.
|
|
350
372
|
|
|
351
373
|
## Troubleshooting
|
|
352
374
|
|
|
353
375
|
| Symptom | Check |
|
|
354
376
|
| ------- | ----- |
|
|
355
|
-
| Sidebar item missing | `paseo plugin ls` reports `running`,
|
|
377
|
+
| Sidebar item missing | `paseo plugin ls` reports `running`, the client is on this host, and on 0.11+ the item is not hidden in **Settings → Sidebar** |
|
|
356
378
|
| "Metrics unavailable" | The daemon is not on macOS, or a `/usr/bin` tool is missing |
|
|
357
379
|
| Charts look empty | History starts empty; it fills as the tab stays open |
|
|
358
380
|
| A port shows "another user" | It belongs to root or another account; `lsof` cannot inspect it unprivileged |
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PluginClientContext,
|
|
3
|
+
PluginCommandCapabilities,
|
|
4
|
+
PluginHostProps,
|
|
5
|
+
PluginSurfaceProps,
|
|
6
|
+
} from "@getpaseo/plugin/client";
|
|
7
|
+
import * as ui from "@getpaseo/plugin/client/ui";
|
|
8
|
+
import type { ComponentType, FunctionComponent } from "react";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Paseo 0.11 replaced surfaces with screens: `addScreen`, `addSidebarHeaderItem`
|
|
12
|
+
* and `openScreen`. The manifest still admits 0.8, and every connected app runs
|
|
13
|
+
* this entry against its own version, so each call checks for the new method and
|
|
14
|
+
* falls back to the old one.
|
|
15
|
+
*
|
|
16
|
+
* The SDK stays pinned to 0.8.0 so typechecking proves the rest of the plugin
|
|
17
|
+
* uses only the oldest supported API. The 0.11 additions are described here,
|
|
18
|
+
* from the 0.11 SDK declarations, and are reachable only behind a runtime check.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const SCREEN_ID = "main";
|
|
22
|
+
const TITLE = "Machine";
|
|
23
|
+
const ICON = "Activity";
|
|
24
|
+
|
|
25
|
+
/** String keys and values: 0.11 carries them in the screen's URL. */
|
|
26
|
+
export type ScreenParams = Record<string, string>;
|
|
27
|
+
|
|
28
|
+
interface OpenScreenInput {
|
|
29
|
+
screenId: string;
|
|
30
|
+
params?: ScreenParams;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface SidebarItemProps extends PluginHostProps {
|
|
34
|
+
currentScreen: { screenId: string; params: ScreenParams } | null;
|
|
35
|
+
openScreen(input: OpenScreenInput): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** What 0.11 adds to the client context. */
|
|
39
|
+
interface ScreenApi {
|
|
40
|
+
addScreen(contribution: {
|
|
41
|
+
id: string;
|
|
42
|
+
title: string;
|
|
43
|
+
Component: ComponentType<MachineScreenProps>;
|
|
44
|
+
}): () => void;
|
|
45
|
+
addSidebarHeaderItem(contribution: {
|
|
46
|
+
id: string;
|
|
47
|
+
title: string;
|
|
48
|
+
Component: ComponentType<SidebarItemProps>;
|
|
49
|
+
}): () => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** What 0.11 adds to command and slash-command callbacks. */
|
|
53
|
+
interface OpenScreenApi {
|
|
54
|
+
openScreen(input: OpenScreenInput): void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** `@getpaseo/plugin/client/ui` gained this in 0.11; the older app runtime has no such export. */
|
|
58
|
+
type SidebarRowComponent = ComponentType<{ icon?: string; active?: boolean; onPress(): void }>;
|
|
59
|
+
|
|
60
|
+
/** What the screen receives on either API: 0.11 adds `params`, older hosts do not. */
|
|
61
|
+
export type MachineScreenProps = PluginSurfaceProps & { params?: ScreenParams };
|
|
62
|
+
|
|
63
|
+
function screenApi(client: PluginClientContext): ScreenApi | null {
|
|
64
|
+
const candidate = client as PluginClientContext & Partial<ScreenApi>;
|
|
65
|
+
return typeof candidate.addScreen === "function" && typeof candidate.addSidebarHeaderItem === "function"
|
|
66
|
+
? (candidate as PluginClientContext & ScreenApi)
|
|
67
|
+
: null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function openScreenApi(capabilities: object): OpenScreenApi | null {
|
|
71
|
+
const candidate = capabilities as Partial<OpenScreenApi>;
|
|
72
|
+
return typeof candidate.openScreen === "function" ? (candidate as OpenScreenApi) : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function registerMachineScreen(
|
|
76
|
+
client: PluginClientContext,
|
|
77
|
+
Component: FunctionComponent<MachineScreenProps>,
|
|
78
|
+
): void {
|
|
79
|
+
const screens = screenApi(client);
|
|
80
|
+
if (screens) {
|
|
81
|
+
screens.addScreen({ id: SCREEN_ID, title: TITLE, Component });
|
|
82
|
+
// Same id as the old sidebar item, so saved `/plugin/machine-status/main` links keep working.
|
|
83
|
+
screens.addSidebarHeaderItem({ id: SCREEN_ID, title: TITLE, Component: MachineSidebarItem });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
client.addSurface(SCREEN_ID, Component);
|
|
87
|
+
client.addSidebarItem({ id: SCREEN_ID, title: TITLE, icon: ICON, surface: SCREEN_ID });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function MachineSidebarItem({ currentScreen, openScreen }: SidebarItemProps) {
|
|
91
|
+
// Read off the namespace: the 0.8–0.10 ui runtime has no SidebarRow, and the
|
|
92
|
+
// item renders nothing rather than crash.
|
|
93
|
+
const SidebarRow = (ui as { SidebarRow?: SidebarRowComponent }).SidebarRow;
|
|
94
|
+
if (!SidebarRow) return null;
|
|
95
|
+
return (
|
|
96
|
+
<SidebarRow
|
|
97
|
+
icon={ICON}
|
|
98
|
+
active={currentScreen?.screenId === SCREEN_ID}
|
|
99
|
+
onPress={() => openScreen({ screenId: SCREEN_ID })}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Opens the Machine screen, on a tab when the host can carry params. Pre-0.11
|
|
106
|
+
* hosts open the surface on its default tab.
|
|
107
|
+
*/
|
|
108
|
+
export function openMachineScreen(
|
|
109
|
+
capabilities: Pick<PluginCommandCapabilities, "openSurface">,
|
|
110
|
+
params?: ScreenParams,
|
|
111
|
+
): void {
|
|
112
|
+
const screens = openScreenApi(capabilities);
|
|
113
|
+
if (screens) {
|
|
114
|
+
screens.openScreen(params ? { screenId: SCREEN_ID, params } : { screenId: SCREEN_ID });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
capabilities.openSurface(SCREEN_ID);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** True on 0.11+ apps, where a command can land on a specific tab. */
|
|
121
|
+
export function supportsScreenParams(client: PluginClientContext): boolean {
|
|
122
|
+
return openScreenApi(client) !== null;
|
|
123
|
+
}
|
package/client/pill.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
import { Icon } from "@getpaseo/plugin/client/react-native";
|
|
8
8
|
import React, { useSyncExternalStore } from "react";
|
|
9
9
|
import { readMetrics } from "../shared/contracts";
|
|
10
|
+
import { openMachineScreen } from "./compat";
|
|
10
11
|
import { createMachineCard } from "./pill-card";
|
|
11
12
|
import { pillReading, type PillReading } from "../shared/pill";
|
|
12
13
|
import { STATUS } from "../shared/viz";
|
|
@@ -72,7 +73,7 @@ interface TrackedAgent {
|
|
|
72
73
|
export function contributePills(client: PluginClientContext) {
|
|
73
74
|
const store = createReadingStore();
|
|
74
75
|
const icon = createIcon(store);
|
|
75
|
-
const card = createMachineCard(() => client
|
|
76
|
+
const card = createMachineCard(() => openMachineScreen(client));
|
|
76
77
|
const pills = new Map<string, { workspaceId: string; registration: PluginButtonRegistration }>();
|
|
77
78
|
let disposed = false;
|
|
78
79
|
let inFlight = false;
|
package/client/status.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { useRpc, type PluginSurfaceProps } from "@getpaseo/plugin/client";
|
|
2
2
|
import { useQuery } from "@tanstack/react-query";
|
|
3
|
-
import React, { useMemo, useState } from "react";
|
|
3
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
|
5
5
|
import { ColumnChart, Legend, Meter, Sparkbars, StackedColumnChart, StatTile } from "./charts";
|
|
6
6
|
import { ServicesTab } from "./services";
|
|
7
7
|
import { CleanupSection } from "./cleanup";
|
|
8
8
|
import { DockerTab } from "./docker";
|
|
9
|
+
import type { MachineScreenProps } from "./compat";
|
|
9
10
|
import { ContextMenuProvider } from "./menu";
|
|
10
11
|
import { readMetrics, type Metrics } from "../shared/contracts";
|
|
11
12
|
import { formatBytes, formatDuration, formatMinutes, formatPercent } from "../shared/format";
|
|
@@ -444,7 +445,7 @@ function DetailCard({
|
|
|
444
445
|
}
|
|
445
446
|
|
|
446
447
|
|
|
447
|
-
type TabId = "overview" | "services" | "docker";
|
|
448
|
+
export type TabId = "overview" | "services" | "docker";
|
|
448
449
|
|
|
449
450
|
const TABS: readonly { id: TabId; title: string }[] = [
|
|
450
451
|
{ id: "overview", title: "Overview" },
|
|
@@ -452,15 +453,23 @@ const TABS: readonly { id: TabId; title: string }[] = [
|
|
|
452
453
|
{ id: "docker", title: "Docker" },
|
|
453
454
|
];
|
|
454
455
|
|
|
456
|
+
/** `?tab=` from a 0.11 screen link; anything unknown, or no params at all, is the overview. */
|
|
457
|
+
function tabFromParams(params: MachineScreenProps["params"]): TabId {
|
|
458
|
+
return TABS.find((entry) => entry.id === params?.tab)?.id ?? "overview";
|
|
459
|
+
}
|
|
460
|
+
|
|
455
461
|
/**
|
|
456
462
|
* Only the selected tab is mounted. The services tab shells out to netstat, lsof
|
|
457
463
|
* and docker on a timer, and mounting it in the background would keep that
|
|
458
464
|
* running for a panel nobody is looking at.
|
|
459
465
|
*/
|
|
460
|
-
export function MachineStatusSurface(props:
|
|
466
|
+
export function MachineStatusSurface(props: MachineScreenProps) {
|
|
461
467
|
const chrome: Chrome = { theme: props.theme, compact: props.layout.compact };
|
|
462
468
|
const styles = useChromeStyles(chrome);
|
|
463
|
-
const
|
|
469
|
+
const linkedTab = tabFromParams(props.params);
|
|
470
|
+
const [tab, setTab] = useState<TabId>(linkedTab);
|
|
471
|
+
// Opening the already-open screen with another `tab` swaps params without a remount.
|
|
472
|
+
useEffect(() => setTab(linkedTab), [linkedTab]);
|
|
464
473
|
|
|
465
474
|
return (
|
|
466
475
|
<ContextMenuProvider chrome={chrome}>
|
package/index.client.tsx
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import type { PluginClientContext } from "@getpaseo/plugin/client";
|
|
2
|
+
import { openMachineScreen, registerMachineScreen, supportsScreenParams } from "./client/compat";
|
|
2
3
|
import { contributePills } from "./client/pill";
|
|
3
4
|
import { MachineStatusSurface } from "./client/status";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* The app half of the plugin: the Machine
|
|
7
|
+
* The app half of the plugin: the Machine screen, the ways into it from the
|
|
7
8
|
* sidebar and the Command Center, and the load pill beside each agent's composer.
|
|
8
9
|
*/
|
|
9
10
|
export default function contribute(client: PluginClientContext) {
|
|
10
|
-
client
|
|
11
|
-
|
|
12
|
-
client.addSidebarItem({
|
|
13
|
-
id: "main",
|
|
14
|
-
title: "Machine",
|
|
15
|
-
icon: "Activity",
|
|
16
|
-
surface: "main",
|
|
17
|
-
});
|
|
11
|
+
registerMachineScreen(client, MachineStatusSurface);
|
|
18
12
|
|
|
19
13
|
client.addCommandCenterItem({
|
|
20
14
|
id: "open-machine-status",
|
|
@@ -22,10 +16,35 @@ export default function contribute(client: PluginClientContext) {
|
|
|
22
16
|
icon: "Activity",
|
|
23
17
|
keywords: ["cpu", "memory", "disk", "swap", "battery", "thermal", "ports", "services"],
|
|
24
18
|
context: "global",
|
|
25
|
-
onSelect(
|
|
26
|
-
|
|
19
|
+
onSelect(capabilities) {
|
|
20
|
+
openMachineScreen(capabilities);
|
|
27
21
|
},
|
|
28
22
|
});
|
|
29
23
|
|
|
24
|
+
// Straight to a tab needs screen params. On older apps these would open the
|
|
25
|
+
// overview under a misleading title, so they are not offered there.
|
|
26
|
+
if (supportsScreenParams(client)) {
|
|
27
|
+
client.addCommandCenterItem({
|
|
28
|
+
id: "open-machine-services",
|
|
29
|
+
title: "Machine: ports & services",
|
|
30
|
+
icon: "Network",
|
|
31
|
+
keywords: ["ports", "listening", "lsof", "dev server"],
|
|
32
|
+
context: "global",
|
|
33
|
+
onSelect(capabilities) {
|
|
34
|
+
openMachineScreen(capabilities, { tab: "services" });
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
client.addCommandCenterItem({
|
|
38
|
+
id: "open-machine-docker",
|
|
39
|
+
title: "Machine: Docker",
|
|
40
|
+
icon: "Container",
|
|
41
|
+
keywords: ["docker", "containers", "orbstack", "rancher"],
|
|
42
|
+
context: "global",
|
|
43
|
+
onSelect(capabilities) {
|
|
44
|
+
openMachineScreen(capabilities, { tab: "docker" });
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
return contributePills(client);
|
|
31
50
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paseo-plugin-machine-status",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Machine dashboard, open ports and Docker control inside Paseo",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dutchakdev",
|
|
@@ -15,20 +15,26 @@
|
|
|
15
15
|
"macos",
|
|
16
16
|
"docker"
|
|
17
17
|
],
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22.12.0"
|
|
20
|
+
},
|
|
18
21
|
"scripts": {
|
|
19
22
|
"typecheck": "tsc --noEmit",
|
|
20
23
|
"test": "vitest run",
|
|
21
24
|
"test:watch": "vitest",
|
|
22
|
-
"preview": "tsx scripts/preview.ts"
|
|
25
|
+
"preview": "tsx scripts/preview.ts",
|
|
26
|
+
"check": "npm run typecheck && npm test"
|
|
23
27
|
},
|
|
24
28
|
"devDependencies": {
|
|
25
29
|
"@getpaseo/client": "0.8.0",
|
|
26
30
|
"@getpaseo/plugin": "0.8.0",
|
|
27
31
|
"@getpaseo/protocol": "0.8.0",
|
|
28
32
|
"@tanstack/react-query": "^5.90.11",
|
|
33
|
+
"@types/node": "22.20.5",
|
|
29
34
|
"@types/react": "~19.2.0",
|
|
30
35
|
"react": "19.1.0",
|
|
31
36
|
"react-native": "0.81.5",
|
|
37
|
+
"semver": "7.8.5",
|
|
32
38
|
"tsx": "^4.23.13",
|
|
33
39
|
"typescript": "^5.9.3",
|
|
34
40
|
"vitest": "^4.1.11",
|
|
@@ -36,6 +42,7 @@
|
|
|
36
42
|
},
|
|
37
43
|
"files": [
|
|
38
44
|
"paseo-plugin.json",
|
|
45
|
+
"OVERVIEW.md",
|
|
39
46
|
"index.client.tsx",
|
|
40
47
|
"index.server.ts",
|
|
41
48
|
"client/",
|