@vtstech/pi-status 1.0.9 → 1.1.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/README.md +6 -4
- package/package.json +2 -2
- package/status.js +32 -68
package/README.md
CHANGED
|
@@ -14,16 +14,18 @@ pi install "npm:@vtstech/pi-status"
|
|
|
14
14
|
|
|
15
15
|
Automatically loaded — no commands needed. Displays a 2-line status bar at the bottom of the Pi interface.
|
|
16
16
|
|
|
17
|
-
**Line 1:**
|
|
17
|
+
**Line 1 (conf):**
|
|
18
18
|
```
|
|
19
|
-
|
|
19
|
+
qwen3.5:0.8b · ~/.pi/agent · medium · CPU 9%
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
**Line 2:**
|
|
22
|
+
**Line 2 (load):**
|
|
23
23
|
```
|
|
24
|
-
|
|
24
|
+
qwen3.5:0.8b · M:33k · S:9.0%/128k · RAM 2.2G/15.1G · Resp 5m24s · temp:0.0 · max:16384
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
CPU/RAM/Swap are only shown when using a local Ollama provider (not for cloud/remote).
|
|
28
|
+
|
|
27
29
|
## What's Displayed
|
|
28
30
|
|
|
29
31
|
- **Working directory** — compact `~`-relative path
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vtstech/pi-status",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "System monitor / status bar extension for Pi Coding Agent",
|
|
5
5
|
"main": "status.js",
|
|
6
6
|
"keywords": ["pi-extensions"],
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/VTSTech/pi-coding-agent"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@vtstech/pi-shared": "1.
|
|
17
|
+
"@vtstech/pi-shared": "1.1.1"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"@mariozechner/pi-coding-agent": ">=0.66"
|
package/status.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
// .build-npm/status/status.temp.ts
|
|
2
2
|
import os from "node:os";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { execSync } from "node:child_process";
|
|
6
|
-
import { getOllamaBaseUrl } from "@vtstech/pi-shared/ollama";
|
|
3
|
+
import { execSync as gitExecSync } from "node:child_process";
|
|
4
|
+
import { getOllamaBaseUrl, fetchModelContextLength, readModelsJson } from "@vtstech/pi-shared/ollama";
|
|
7
5
|
import { fmtBytes, fmtDur } from "@vtstech/pi-shared/format";
|
|
8
|
-
import { readRecentAuditEntries } from "@vtstech/pi-shared/security";
|
|
9
6
|
function status_temp_default(pi) {
|
|
10
7
|
let lastResponseTime = null;
|
|
11
8
|
let agentStartTime = null;
|
|
@@ -69,7 +66,7 @@ function status_temp_default(pi) {
|
|
|
69
66
|
}
|
|
70
67
|
function getSwap() {
|
|
71
68
|
try {
|
|
72
|
-
const out =
|
|
69
|
+
const out = gitExecSync("cat /proc/meminfo", { encoding: "utf-8", timeout: 3e3 });
|
|
73
70
|
const swapTotal2 = Number(out.match(/SwapTotal:\s+(\d+)/)?.[1]) * 1024;
|
|
74
71
|
const swapFree = Number(out.match(/SwapFree:\s+(\d+)/)?.[1]) * 1024;
|
|
75
72
|
if (swapTotal2 > 0) return { used: swapTotal2 - swapFree, total: swapTotal2 };
|
|
@@ -107,26 +104,9 @@ function status_temp_default(pi) {
|
|
|
107
104
|
nativeCtxPromise = (async () => {
|
|
108
105
|
try {
|
|
109
106
|
const ollamaBase = getOllamaBaseUrl();
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
body: JSON.stringify({ name: modelId }),
|
|
114
|
-
signal: AbortSignal.timeout(5e3)
|
|
115
|
-
});
|
|
116
|
-
if (!res.ok) return;
|
|
117
|
-
const data = await res.json();
|
|
118
|
-
for (const key of Object.keys(data?.model_info ?? {})) {
|
|
119
|
-
if (key.endsWith(".context_length")) {
|
|
120
|
-
const val = data.model_info[key];
|
|
121
|
-
if (typeof val === "number") {
|
|
122
|
-
footerNativeCtx = val >= 1e3 ? `${(val / 1e3).toFixed(0)}k` : String(val);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const numCtx = data?.model_info?.["num_ctx"];
|
|
128
|
-
if (typeof numCtx === "number") {
|
|
129
|
-
footerNativeCtx = numCtx >= 1e3 ? `${(numCtx / 1e3).toFixed(0)}k` : String(numCtx);
|
|
107
|
+
const ctx = await fetchModelContextLength(ollamaBase, modelId);
|
|
108
|
+
if (ctx != null) {
|
|
109
|
+
footerNativeCtx = ctx >= 1e3 ? `${(ctx / 1e3).toFixed(0)}k` : String(ctx);
|
|
130
110
|
}
|
|
131
111
|
} catch {
|
|
132
112
|
} finally {
|
|
@@ -136,30 +116,33 @@ function status_temp_default(pi) {
|
|
|
136
116
|
}
|
|
137
117
|
return footerNativeCtx;
|
|
138
118
|
}
|
|
139
|
-
function
|
|
140
|
-
const now = Date.now();
|
|
141
|
-
if (now - ollamaLoadedLastCheck < OLLAMA_LOADED_INTERVAL) return ollamaLoadedCache;
|
|
142
|
-
ollamaLoadedLastCheck = now;
|
|
119
|
+
async function fetchOllamaLoadedModel() {
|
|
143
120
|
try {
|
|
144
121
|
const ollamaBase = getOllamaBaseUrl();
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (Array.isArray(models) && models.length > 0) {
|
|
154
|
-
ollamaLoadedCache = models[0].name || models[0].model || "unknown";
|
|
155
|
-
return ollamaLoadedCache;
|
|
156
|
-
}
|
|
122
|
+
const res = await fetch(`${ollamaBase}/api/ps`, {
|
|
123
|
+
signal: AbortSignal.timeout(5e3)
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok) return "";
|
|
126
|
+
const data = await res.json();
|
|
127
|
+
const models = data?.models || [];
|
|
128
|
+
if (Array.isArray(models) && models.length > 0) {
|
|
129
|
+
return models[0].name || models[0].model || "";
|
|
157
130
|
}
|
|
158
131
|
} catch {
|
|
159
132
|
}
|
|
160
|
-
ollamaLoadedCache = "";
|
|
161
133
|
return "";
|
|
162
134
|
}
|
|
135
|
+
function getOllamaLoadedModel() {
|
|
136
|
+
const now = Date.now();
|
|
137
|
+
if (now - ollamaLoadedLastCheck < OLLAMA_LOADED_INTERVAL) return ollamaLoadedCache;
|
|
138
|
+
ollamaLoadedLastCheck = now;
|
|
139
|
+
fetchOllamaLoadedModel().then((loaded) => {
|
|
140
|
+
ollamaLoadedCache = loaded;
|
|
141
|
+
}).catch(() => {
|
|
142
|
+
ollamaLoadedCache = "";
|
|
143
|
+
});
|
|
144
|
+
return ollamaLoadedCache;
|
|
145
|
+
}
|
|
163
146
|
function extractParams(payload) {
|
|
164
147
|
const params = [];
|
|
165
148
|
if (payload.temperature !== void 0) params.push(`temp:${payload.temperature}`);
|
|
@@ -184,7 +167,7 @@ function status_temp_default(pi) {
|
|
|
184
167
|
function getGitBranch() {
|
|
185
168
|
if (gitBranchCache) return gitBranchCache;
|
|
186
169
|
try {
|
|
187
|
-
const branch =
|
|
170
|
+
const branch = gitExecSync("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
|
|
188
171
|
encoding: "utf-8",
|
|
189
172
|
timeout: 3e3
|
|
190
173
|
}).trim();
|
|
@@ -193,18 +176,8 @@ function status_temp_default(pi) {
|
|
|
193
176
|
}
|
|
194
177
|
return gitBranchCache;
|
|
195
178
|
}
|
|
196
|
-
function
|
|
197
|
-
|
|
198
|
-
const entries = readRecentAuditEntries(50);
|
|
199
|
-
blockedCount = 0;
|
|
200
|
-
for (const entry of entries) {
|
|
201
|
-
if (entry.blocked === true || entry.safe === false || entry.action === "block") {
|
|
202
|
-
blockedCount++;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
} catch {
|
|
206
|
-
blockedCount = 0;
|
|
207
|
-
}
|
|
179
|
+
function incrementBlockedCount() {
|
|
180
|
+
blockedCount++;
|
|
208
181
|
}
|
|
209
182
|
function updateMetrics() {
|
|
210
183
|
cpuUsage = getCpuUsage();
|
|
@@ -220,15 +193,7 @@ function status_temp_default(pi) {
|
|
|
220
193
|
hasSwap = false;
|
|
221
194
|
}
|
|
222
195
|
ollamaLoaded = getOllamaLoadedModel();
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
const raw = fs.readFileSync(
|
|
226
|
-
path.join(os.homedir(), ".pi", "agent", "models.json"),
|
|
227
|
-
"utf-8"
|
|
228
|
-
);
|
|
229
|
-
modelsJson = JSON.parse(raw);
|
|
230
|
-
} catch {
|
|
231
|
-
}
|
|
196
|
+
const modelsJson = readModelsJson();
|
|
232
197
|
isLocalProvider = modelsJson ? detectLocalProvider(modelsJson) : false;
|
|
233
198
|
if (currentCtx) {
|
|
234
199
|
footerModel = currentCtx.model?.id || "";
|
|
@@ -245,7 +210,6 @@ function status_temp_default(pi) {
|
|
|
245
210
|
getNativeModelCtx(modelId);
|
|
246
211
|
}
|
|
247
212
|
}
|
|
248
|
-
refreshBlockedCount();
|
|
249
213
|
}
|
|
250
214
|
pi.on("session_start", async (_event, ctx) => {
|
|
251
215
|
currentCtx = ctx;
|
|
@@ -255,7 +219,7 @@ function status_temp_default(pi) {
|
|
|
255
219
|
ctx.ui.setFooter((tui, theme, footerData) => {
|
|
256
220
|
tuiRef = tui;
|
|
257
221
|
const dim = (s) => theme?.fg?.("dim", s) ?? s;
|
|
258
|
-
const red = (s) => theme?.fg?.("
|
|
222
|
+
const red = (s) => theme?.fg?.("error", s) ?? s;
|
|
259
223
|
const yellow = (s) => theme?.fg?.("yellow", s) ?? s;
|
|
260
224
|
const sep = dim(" \xB7 ");
|
|
261
225
|
const truncateLine = (line, maxW) => {
|
|
@@ -393,7 +357,7 @@ function status_temp_default(pi) {
|
|
|
393
357
|
if (isBlocked) {
|
|
394
358
|
securityFlashTool = event.tool ?? event.name ?? "unknown";
|
|
395
359
|
securityFlashUntil = Date.now() + 3e3;
|
|
396
|
-
|
|
360
|
+
incrementBlockedCount();
|
|
397
361
|
if (tuiRef) tuiRef.requestRender();
|
|
398
362
|
}
|
|
399
363
|
});
|