@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.
Files changed (3) hide show
  1. package/README.md +6 -4
  2. package/package.json +2 -2
  3. 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
- ~/.pi/agent · main · qwen3:0.6b · medium · 5.6%/128k · CPU 9% · RAM 2.2G/15.1G · Resp 5m24s · temp:0.0
19
+ qwen3.5:0.8b · ~/.pi/agent · medium · CPU 9%
20
20
  ```
21
21
 
22
- **Line 2:**
22
+ **Line 2 (load):**
23
23
  ```
24
- bash (12s)
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.0.9",
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.0.9"
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 * as fs from "node:fs";
4
- import * as path from "node:path";
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 = execSync("cat /proc/meminfo", { encoding: "utf-8", timeout: 3e3 });
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 res = await fetch(`${ollamaBase}/api/show`, {
111
- method: "POST",
112
- headers: { "Content-Type": "application/json" },
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 getOllamaLoadedModel() {
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 out = execSync(`curl -s "${ollamaBase}/api/ps"`, { encoding: "utf-8", timeout: 5e3 });
146
- if (out.trim()) {
147
- let data;
148
- try {
149
- data = JSON.parse(out.trim());
150
- } catch {
151
- }
152
- const models = data?.models || [];
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 = execSync("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
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 refreshBlockedCount() {
197
- try {
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
- let modelsJson = null;
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?.("red", s) ?? s;
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
- refreshBlockedCount();
360
+ incrementBlockedCount();
397
361
  if (tuiRef) tuiRef.requestRender();
398
362
  }
399
363
  });