refactor: notify/footer 持久配置收编到 config/,chrome bridge 地址固定

仓库规则要求 config/ 为唯一配置来源、不以环境变量作持久默认值:
- pi-notify 改读 config/pi-notify.json(逐字段校验回退,复用原 parsers 钳制)
- pi-minimal-footer 改读 config/pi-minimal-footer.json
- pi-chrome 移除 PI_CHROME_BRIDGE_HOST/PORT,固定 127.0.0.1:17318
  (浏览器端 service_worker.js 硬编码同一地址,单侧可配只会断连)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
云服务部-叶林立
2026-10-21 19:16:47 -07:00
co-authored by Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent 0c45b1a438
commit e996f59469
19 changed files with 366 additions and 121 deletions
+6 -6
View File
@@ -34,14 +34,14 @@ pi install npm:@ogulcancelik/pi-minimal-footer
## Configuration
Environment variables (all optional):
Persistent defaults are read from `config/pi-minimal-footer.json` inside the installed bundle; a missing or invalid file falls back to the defaults shown:
| Variable | Description | Default |
| ------------------------------- | -------------------------------------------------------- | ------- |
| `PI_MINIMAL_FOOTER_SHOW_CWD` | Show current working directory in footer status line | `1` |
| `PI_MINIMAL_FOOTER_SHOW_BRANCH` | Show git branch/dirty/ahead/behind in footer status line | `1` |
| Field | Description | Default |
| ------------ | -------------------------------------------------------- | ------- |
| `showCwd` | Show current working directory in footer status line | `true` |
| `showBranch` | Show git branch/dirty/ahead/behind in footer status line | `true` |
Accepted false values: `0`, `false`, `no`, `off` (case-insensitive).
Only `true`/`false` values are honoured; anything else falls back to the default for that field.
## How it works
+1 -1
View File
@@ -5,4 +5,4 @@
- 导入包版本:`@ogulcancelik/pi-minimal-footer@0.1.10`
- 导入日期:2026-08-19
本目录由 `my-pi` 直接维护;它不是 submodule,也不保留上游 Git 元数据。本地改动新增了 Pi 扩展状态渲染(把 `ctx.ui.setStatus()` 发布的每个非空状态渲染为普通 footer 片段)。
本目录由 `my-pi` 直接维护;它不是 submodule,也不保留上游 Git 元数据。本地改动新增了 Pi 扩展状态渲染(把 `ctx.ui.setStatus()` 发布的每个非空状态渲染为普通 footer 片段),并把 showCwd/showBranch 持久配置由 `PI_MINIMAL_FOOTER_*` 环境变量改为组合包 `config/pi-minimal-footer.json`。
+3 -16
View File
@@ -15,6 +15,7 @@ import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { homedir } from "node:os";
import { collectFooterStatusItems } from "./status.ts";
import { readFooterSettings } from "./settings.ts";
// ============ Types ============
@@ -43,19 +44,6 @@ interface GitCache {
const USAGE_REFRESH_INTERVAL = 5 * 60_000; // 5 minutes
const usageCache = new Map<string, UsageSnapshot>(); // keyed by provider
// ============ Env Flags ============
function parseBooleanEnv(value: string | undefined, fallback: boolean): boolean {
if (value === undefined) return fallback;
const normalized = value.trim().toLowerCase();
if (!normalized) return fallback;
if (["1", "true", "yes", "on"].includes(normalized)) return true;
if (["0", "false", "no", "off"].includes(normalized)) return false;
return fallback;
}
// ============ Identity Cache ============
let codexEmailPrefix: string | null | undefined; // undefined = not yet resolved
@@ -754,9 +742,8 @@ export default function (pi: ExtensionAPI) {
const BAR_FILLED = "━";
const BAR_EMPTY = "─";
// Optional visibility toggles (default: enabled)
const showCwd = parseBooleanEnv(process.env.PI_MINIMAL_FOOTER_SHOW_CWD, true);
const showBranch = parseBooleanEnv(process.env.PI_MINIMAL_FOOTER_SHOW_BRANCH, true);
// Optional visibility toggles from bundle config (default: enabled)
const { showCwd, showBranch } = readFooterSettings();
function formatTokenCount(tokens: number): string {
if (tokens >= 1_000_000) {
+30
View File
@@ -0,0 +1,30 @@
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
export interface FooterSettings {
showCwd: boolean;
showBranch: boolean;
}
// Bundle-level `config/` is the single source of truth: the extension reads
// `config/pi-minimal-footer.json` from inside the installed bundle (resolved
// relative to this source file), never environment variables.
export const FOOTER_CONFIG_PATH = fileURLToPath(
new URL("../config/pi-minimal-footer.json", import.meta.url),
);
export function readFooterSettings(configPath: string = FOOTER_CONFIG_PATH): FooterSettings {
try {
const parsed = JSON.parse(readFileSync(configPath, "utf8")) as unknown;
const raw =
parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
? (parsed as Record<string, unknown>)
: {};
return {
showCwd: typeof raw.showCwd === "boolean" ? raw.showCwd : true,
showBranch: typeof raw.showBranch === "boolean" ? raw.showBranch : true,
};
} catch {
return { showCwd: true, showBranch: true };
}
}
+51
View File
@@ -0,0 +1,51 @@
import assert from "node:assert/strict";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, it } from "node:test";
import { readFooterSettings } from "../settings.ts";
let tempDir: string | undefined;
afterEach(() => {
if (tempDir) {
rmSync(tempDir, { recursive: true, force: true });
tempDir = undefined;
}
});
function configPath(contents: string): string {
tempDir = mkdtempSync(join(tmpdir(), "pi-minimal-footer-settings-"));
const path = join(tempDir, "pi-minimal-footer.json");
writeFileSync(path, contents);
return path;
}
const expectedDefaults = { showCwd: true, showBranch: true };
describe("readFooterSettings", () => {
it("returns all defaults when the config file is missing", () => {
assert.deepEqual(readFooterSettings("/does/not/exist/pi-minimal-footer.json"), expectedDefaults);
});
it("returns all defaults for malformed or non-object JSON", () => {
for (const contents of ["not json", "[1,2]", "42"]) {
assert.deepEqual(readFooterSettings(configPath(contents)), expectedDefaults, contents);
}
});
it("adopts explicit boolean values", () => {
assert.deepEqual(
readFooterSettings(configPath(JSON.stringify({ showCwd: false, showBranch: false }))),
{ showCwd: false, showBranch: false },
);
});
it("falls back per-field for non-boolean values", () => {
assert.deepEqual(
readFooterSettings(configPath(JSON.stringify({ showCwd: "no", showBranch: 0 }))),
expectedDefaults,
);
});
});