pi-cockpit 0.24.1 → 0.24.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.
- package/README.md +5 -3
- package/package.json +2 -2
- package/src/footer.ts +25 -1
- package/src/index.ts +0 -19
- package/src/tui-i18n.ts +0 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A responsive **agent cockpit** for [Pi](https://pi.dev): wide terminals get a docked Maestro operations sidebar, narrow terminals automatically fall back to the existing Todo and Agent widgets, and every layout keeps the Starship-style footer.
|
|
4
4
|
|
|
5
|
-
It is the third plugin of the `pi-maestro-flow` project (alongside `pi-maestro-flow` and `pi-maestro-teammate`). It is installed and registered with `pi-maestro-flow`, but it also runs standalone. Current version: **0.
|
|
5
|
+
It is the third plugin of the `pi-maestro-flow` project (alongside `pi-maestro-flow` and `pi-maestro-teammate`). It is installed and registered with `pi-maestro-flow`, but it also runs standalone. Current version: **0.24.2**.
|
|
6
6
|
|
|
7
7
|
The dock is a non-capturing top-right overlay. Cockpit reserves its columns by wrapping the active TUI renderer at runtime, so the Pi workspace reflows instead of rendering underneath it. No Pi source files are modified.
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ The dock is a non-capturing top-right overlay. Cockpit reserves its columns by w
|
|
|
25
25
|
`pi-cockpit` comes automatically with the orchestration layer — installing `pi-maestro-flow` pulls `pi-cockpit` and registers it into `settings.packages` on postinstall, no manual setup required. To use it on its own:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
pi install npm:pi-cockpit@0.
|
|
28
|
+
pi install npm:pi-cockpit@0.24.2 # standalone from npm
|
|
29
29
|
# or, for one run:
|
|
30
30
|
pi -e ./packages/pi-cockpit
|
|
31
31
|
```
|
|
@@ -141,7 +141,9 @@ The tab title is `frame + pi - <session> - <working state>`. The session part fo
|
|
|
141
141
|
|
|
142
142
|
## Sidebar compatibility
|
|
143
143
|
|
|
144
|
-
The split-pane wrapper depends on Pi's current TUI renderer shape and is
|
|
144
|
+
The split-pane wrapper depends on Pi's current TUI renderer shape. Host hooks retain runtime capability checks and reversible fallbacks; there is no startup version-allowlist warning. A render integration failure disables the split and retries the original renderer at full width. The `/cockpit` panel exposes a read-only "host patches" row with recorded patch status and degradation reasons.
|
|
145
|
+
|
|
146
|
+
Native startup, viewport-stability and compaction-style regressions have been exercised against the installed Pi `0.99.2` SDK and its real dynamic TUI reference. This is not a certification of every interactive surface: dynamic references currently leave the split pane unattached, while the sidebar can still report attachment success. This existing limitation also affects `0.99.0`.
|
|
145
147
|
|
|
146
148
|
Do not enable `pi-cockpit`'s dock and `pi-atelier@0.7.0`'s sidebar together. Both reserve columns by wrapping the same renderer, and `pi-atelier@0.7.0` does not participate in Cockpit's split-owner marker protocol. Use `"sidebar": { "mode": "off" }` when running Atelier.
|
|
147
149
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cockpit",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
4
4
|
"description": "Responsive Maestro operations sidebar, fallback status widgets, and footer for Pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@earendil-works/pi-coding-agent": "0.99.0",
|
|
73
73
|
"@earendil-works/pi-tui": "0.99.0",
|
|
74
74
|
"@types/node": "^22.0.0",
|
|
75
|
-
"pi-maestro-teammate": "2.
|
|
75
|
+
"pi-maestro-teammate": "2.8.0",
|
|
76
76
|
"typebox": "1.3.27",
|
|
77
77
|
"typescript": "^5.5.0"
|
|
78
78
|
},
|
package/src/footer.ts
CHANGED
|
@@ -196,6 +196,14 @@ function extensionStatusColor(status: ExtensionStatusSegment): ThemeColor {
|
|
|
196
196
|
if (mode === "READY" || mode === "PLAN READY") return "accent";
|
|
197
197
|
return "muted";
|
|
198
198
|
}
|
|
199
|
+
if (status.key === "maestro-plan-auto") return "warning";
|
|
200
|
+
if (status.key === "self-evolve") return "success";
|
|
201
|
+
if (status.key === "decision-policy") {
|
|
202
|
+
if (status.text.startsWith("DEC !")) return "error";
|
|
203
|
+
if (status.text.startsWith("DEC ?")) return "accent";
|
|
204
|
+
if (status.text.startsWith("DEC ▶")) return "warning";
|
|
205
|
+
if (status.text.startsWith("DEC ✓")) return "success";
|
|
206
|
+
}
|
|
199
207
|
if (status.key !== "approval-mode") return "muted";
|
|
200
208
|
const mode = approvalMode(status);
|
|
201
209
|
if (UNSAFE_APPROVAL_MODES.has(mode)) return "error";
|
|
@@ -207,6 +215,8 @@ function extensionStatusColor(status: ExtensionStatusSegment): ThemeColor {
|
|
|
207
215
|
|
|
208
216
|
const HIDDEN_EXTENSION_STATUS_KEYS = new Set([
|
|
209
217
|
"maestro-auto-compact-mode",
|
|
218
|
+
// The active thinking level already belongs to the model identity on line one.
|
|
219
|
+
"maestro-effort",
|
|
210
220
|
"mcp",
|
|
211
221
|
"swarm-best",
|
|
212
222
|
"team-swarm",
|
|
@@ -216,6 +226,8 @@ function isVisibleExtensionStatus(status: ExtensionStatusSegment, thinking?: str
|
|
|
216
226
|
if (status.text === "" || status.text === thinking) return false;
|
|
217
227
|
if (HIDDEN_EXTENSION_STATUS_KEYS.has(status.key)) return false;
|
|
218
228
|
if (status.key === "self-evolve" && /^EVOL off$/i.test(status.text.trim())) return false;
|
|
229
|
+
if (status.key === "maestro-plan-auto" && /^PLAN-AUTO off$/i.test(status.text.trim())) return false;
|
|
230
|
+
if (status.key === "decision-policy" && /^DEC ○ (?:未配置|A:off E:off)$/i.test(status.text.trim())) return false;
|
|
219
231
|
return !/^(?:TEAM SWARM\b|BEST\b|COMPLETED$|ACT$)/i.test(status.text.trim());
|
|
220
232
|
}
|
|
221
233
|
|
|
@@ -223,6 +235,14 @@ function paintExtensionStatus(
|
|
|
223
235
|
status: ExtensionStatusSegment,
|
|
224
236
|
theme: PaintTheme,
|
|
225
237
|
): string {
|
|
238
|
+
const marker = status.key === "decision-policy"
|
|
239
|
+
? /^(DEC) ([○!?▶✓])(.*)$/.exec(status.text)
|
|
240
|
+
: status.key === "self-evolve" ? /^(EVOL) (●)(.*)$/.exec(status.text) : null;
|
|
241
|
+
if (marker) {
|
|
242
|
+
return theme.fg("muted", `${marker[1]} `)
|
|
243
|
+
+ theme.fg(extensionStatusColor(status), marker[2])
|
|
244
|
+
+ theme.fg("muted", marker[3]);
|
|
245
|
+
}
|
|
226
246
|
const text = status.key === "approval-mode" && UNSAFE_APPROVAL_MODES.has(approvalMode(status))
|
|
227
247
|
? "YOLO"
|
|
228
248
|
: status.key === "maestro-auto-compact-mode"
|
|
@@ -307,6 +327,7 @@ export function renderFooter(p: FooterParts): string[] {
|
|
|
307
327
|
const visibleStatuses = (p.extensionStatuses ?? []).filter(
|
|
308
328
|
(status) => isVisibleExtensionStatus(status, p.thinking),
|
|
309
329
|
);
|
|
330
|
+
const fastStatus = visibleStatuses.find((status) => status.key === "codex-fast");
|
|
310
331
|
const controlStatuses = visibleStatuses.filter(
|
|
311
332
|
(status) => status.key === "mode"
|
|
312
333
|
|| status.key === "approval-mode"
|
|
@@ -331,6 +352,9 @@ export function renderFooter(p: FooterParts): string[] {
|
|
|
331
352
|
priority: 5,
|
|
332
353
|
minWidth: utils.measure(g.model) + 1 + utils.measure(g.ellipsis) + 3,
|
|
333
354
|
});
|
|
355
|
+
if (fastStatus) {
|
|
356
|
+
leftParts.push({ text: theme.fg("success", "FAST"), priority: 4, clippable: false });
|
|
357
|
+
}
|
|
334
358
|
if (p.thinking && p.thinking !== "off") {
|
|
335
359
|
leftParts.push({ text: theme.fg("muted", p.thinking), priority: 4, clippable: false });
|
|
336
360
|
}
|
|
@@ -454,7 +478,7 @@ export function renderFooter(p: FooterParts): string[] {
|
|
|
454
478
|
if (p.maestroWorkflow) {
|
|
455
479
|
lines.push(utils.clip(renderMaestroWorkflowLine(p.maestroWorkflow, theme, g), width, ell));
|
|
456
480
|
}
|
|
457
|
-
const statuses = visibleStatuses.filter((status) => !controlStatuses.includes(status));
|
|
481
|
+
const statuses = visibleStatuses.filter((status) => status !== fastStatus && !controlStatuses.includes(status));
|
|
458
482
|
if (statuses.length > 0) {
|
|
459
483
|
const statusSeparator = ` ${sep} `;
|
|
460
484
|
const fittedStatuses = fitSegmentsByPriority(
|
package/src/index.ts
CHANGED
|
@@ -389,24 +389,6 @@ export default function (pi: ExtensionAPI): void {
|
|
|
389
389
|
let viewportStabilityPatch: ViewportStabilityPatch | undefined;
|
|
390
390
|
let compactionStylePatch: CompactionStylePatch | undefined;
|
|
391
391
|
|
|
392
|
-
// Host SDK versions the TUI patches were validated against. A mismatch does
|
|
393
|
-
// not block anything — every patch fails closed — but the user should know
|
|
394
|
-
// the cockpit is running on an unverified host shape.
|
|
395
|
-
const VERIFIED_PI_TUI = /^(0\.83\.|0\.84\.|0\.99\.0$)/;
|
|
396
|
-
let hostVersionWarned = false;
|
|
397
|
-
const checkHostVersion = (ctx: ExtensionContext): void => {
|
|
398
|
-
if (hostVersionWarned) return;
|
|
399
|
-
try {
|
|
400
|
-
// Public coding-agent VERSION is the host compatibility diagnostic;
|
|
401
|
-
// package.json deep exports are not part of the SDK contract.
|
|
402
|
-
const version = VERSION;
|
|
403
|
-
if (VERIFIED_PI_TUI.test(version)) return;
|
|
404
|
-
hostVersionWarned = true;
|
|
405
|
-
ctx.ui.notify(tuiT("notice.hostVersion", { version }), "warning");
|
|
406
|
-
} catch {
|
|
407
|
-
// version probe is best-effort; never block session start
|
|
408
|
-
}
|
|
409
|
-
};
|
|
410
392
|
const ensureViewportStability = (tui: TUI): void => {
|
|
411
393
|
// Native fullscreen owns a fixed application viewport and has no main-screen
|
|
412
394
|
// applyLineResets hook. Do not cache that expected miss: the same dynamic TUI
|
|
@@ -2025,7 +2007,6 @@ export default function (pi: ExtensionAPI): void {
|
|
|
2025
2007
|
publishUiOwnership();
|
|
2026
2008
|
lastCtx = ctx;
|
|
2027
2009
|
uiPromptDepth = 0;
|
|
2028
|
-
checkHostVersion(ctx);
|
|
2029
2010
|
ambientSurfaces.reset();
|
|
2030
2011
|
agentReads.bindSession(ctx.sessionManager.getSessionId());
|
|
2031
2012
|
agents = agentReads.current;
|
package/src/tui-i18n.ts
CHANGED
|
@@ -321,7 +321,6 @@ export const COCKPIT_TUI_CATALOGS: TranslationCatalogs = {
|
|
|
321
321
|
"editor.historyUnavailable": "Input history unavailable: {message}",
|
|
322
322
|
"notice.sidebarWidthSaveFailed": "Cockpit sidebar width kept for this session; save failed: {message}",
|
|
323
323
|
"notice.sidebarUnavailable": "Cockpit sidebar unavailable: {message}",
|
|
324
|
-
"notice.hostVersion": "Cockpit host patches were verified against pi-tui 0.83.x/0.84.x; running on {version} — degraded surfaces fail closed.",
|
|
325
324
|
"notice.themeUnavailable": "theme \"{name}\" unavailable — {message}",
|
|
326
325
|
"notice.themeSelected": "theme: {name}",
|
|
327
326
|
"notice.notFound": "not found",
|
|
@@ -653,7 +652,6 @@ export const COCKPIT_TUI_CATALOGS: TranslationCatalogs = {
|
|
|
653
652
|
"editor.historyUnavailable": "输入历史不可用:{message}",
|
|
654
653
|
"notice.sidebarWidthSaveFailed": "侧边栏宽度仅在本会话保留;保存失败:{message}",
|
|
655
654
|
"notice.sidebarUnavailable": "Cockpit 侧边栏不可用:{message}",
|
|
656
|
-
"notice.hostVersion": "Cockpit 宿主补丁已验证 pi-tui 0.83.x/0.84.x;当前 {version} —— 不兼容的面会静默降级。",
|
|
657
655
|
"notice.themeUnavailable": "主题 \"{name}\" 不可用 — {message}",
|
|
658
656
|
"notice.themeSelected": "主题:{name}",
|
|
659
657
|
"notice.notFound": "未找到",
|