@zhushanwen/pi-extension-logger 0.2.0 → 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/package.json +1 -1
- package/src/__tests__/extension-logger.test.ts +12 -12
- package/src/index.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-extension-logger",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shared logging helper for Pi extensions — three-channel routing (AI realtime / audit / debug) (shared library, not a Pi extension - no install.mjs needed)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -24,7 +24,7 @@ describe("extension-logger", () => {
|
|
|
24
24
|
afterEach(() => {
|
|
25
25
|
setPiHandle(undefined);
|
|
26
26
|
vi.restoreAllMocks();
|
|
27
|
-
// 还原环境变量,避免文件日志测试的
|
|
27
|
+
// 还原环境变量,避免文件日志测试的 XYZ_AGENT_DEBUG/PI_CODING_AGENT_DIR 泄漏到其它用例
|
|
28
28
|
process.env = { ...prevEnv };
|
|
29
29
|
});
|
|
30
30
|
|
|
@@ -137,7 +137,7 @@ describe("extension-logger", () => {
|
|
|
137
137
|
});
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
describe("
|
|
140
|
+
describe("XYZ_AGENT_DEBUG 文件日志", () => {
|
|
141
141
|
// 文件日志的 agentDir 通过 getAgentDir() 推导(读 PI_CODING_AGENT_DIR,
|
|
142
142
|
// 默认 ~/.pi/agent)。设 PI_CODING_AGENT_DIR 到 tmpdir 子目录,与组 A 的
|
|
143
143
|
// arch-boundary 改动(fileLog 用 getAgentDir())保持一致。
|
|
@@ -156,15 +156,15 @@ describe("extension-logger", () => {
|
|
|
156
156
|
}
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
it("
|
|
160
|
-
delete process.env.
|
|
159
|
+
it("XYZ_AGENT_DEBUG 未设时 debug 是 no-op(不抛错即可)", () => {
|
|
160
|
+
delete process.env.XYZ_AGENT_DEBUG;
|
|
161
161
|
const logger = createLogger("test", pi);
|
|
162
162
|
expect(() => logger.debug("no-op")).not.toThrow();
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
// ---- Suggestion #8:fileLog 实际写入路径 ----
|
|
166
|
-
it("
|
|
167
|
-
process.env.
|
|
166
|
+
it("XYZ_AGENT_DEBUG=1 时 debug 写入日志文件,内容含 [debug] 与序列化 data", () => {
|
|
167
|
+
process.env.XYZ_AGENT_DEBUG = "1";
|
|
168
168
|
// 固定日期 → 文件名 <extName>-2026-08-01.log
|
|
169
169
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
170
170
|
|
|
@@ -187,8 +187,8 @@ describe("extension-logger", () => {
|
|
|
187
187
|
expect(appendSpy).not.toHaveBeenCalled();
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
it("
|
|
191
|
-
process.env.
|
|
190
|
+
it("XYZ_AGENT_DEBUG=1 时 warn 既写文件又走 appendEntry(文件内容含 [warn])", () => {
|
|
191
|
+
process.env.XYZ_AGENT_DEBUG = "1";
|
|
192
192
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
193
193
|
|
|
194
194
|
const logger = createLogger("warn-ext", pi);
|
|
@@ -204,8 +204,8 @@ describe("extension-logger", () => {
|
|
|
204
204
|
expect(appendSpy).toHaveBeenCalledOnce();
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
it("
|
|
208
|
-
process.env.
|
|
207
|
+
it("XYZ_AGENT_DEBUG=1 写失败(只读目录)不 throw", () => {
|
|
208
|
+
process.env.XYZ_AGENT_DEBUG = "1";
|
|
209
209
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
210
210
|
|
|
211
211
|
// 已存在的 logs 目录改为只读,让 mkdirSync/appendFileSync 失败。
|
|
@@ -240,13 +240,13 @@ describe("extension-logger", () => {
|
|
|
240
240
|
const [, entry] = appendSpy.mock.calls[0]!;
|
|
241
241
|
// appendEntry payload 的 data 字段保留原对象(safeStringify 仅在文件日志路径用)
|
|
242
242
|
expect(entry).toMatchObject({ level: "warn" });
|
|
243
|
-
// 验证 safeStringify 的 fallback 分支:用
|
|
243
|
+
// 验证 safeStringify 的 fallback 分支:用 XYZ_AGENT_DEBUG=1 触发 fileLog,
|
|
244
244
|
// 文件内 data 应是 String() 形式(含 [object Object] 或循环结构字符串)
|
|
245
245
|
expect(() => JSON.stringify(cyclic)).toThrow(); // 对照:原对象确实不可序列化
|
|
246
246
|
});
|
|
247
247
|
|
|
248
248
|
it("BigInt:warn 不崩,文件日志路径走 String fallback", () => {
|
|
249
|
-
process.env.
|
|
249
|
+
process.env.XYZ_AGENT_DEBUG = "1";
|
|
250
250
|
const tmpAgentDir = mkdtempSync(join(tmpdir(), "pi-ext-bigint-"));
|
|
251
251
|
process.env.PI_CODING_AGENT_DIR = tmpAgentDir;
|
|
252
252
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// 三层通道:
|
|
11
11
|
// 1. AI 实时 → tool result / block reason(pi 原生,本模块不涉及)
|
|
12
12
|
// 2. 事后排查 → pi.appendEntry(custom entry 不进 LLM 上下文,不显 TUI)
|
|
13
|
-
// 3. 开发者调试 → 文件日志(
|
|
13
|
+
// 3. 开发者调试 → 文件日志(XYZ_AGENT_DEBUG=1 时写 ~/.pi/agent/logs/,默认 no-op)
|
|
14
14
|
//
|
|
15
15
|
// notify(用户操作反馈)刻意不封装——它是 UI 决策,留给各 extension 在命令/视图层
|
|
16
16
|
// 直接调 ctx.ui.notify。
|
|
@@ -38,7 +38,7 @@ export type LogLevel = "debug" | "warn" | "error";
|
|
|
38
38
|
* 自建太重)。warn/error 走 appendEntry 持久化;debug 默认 no-op。
|
|
39
39
|
*/
|
|
40
40
|
export interface ExtensionLogger {
|
|
41
|
-
/** 开发调试日志。默认 no-op;
|
|
41
|
+
/** 开发调试日志。默认 no-op;XYZ_AGENT_DEBUG=1 时写文件日志。不进 appendEntry。 */
|
|
42
42
|
debug(msg: string, data?: unknown): void;
|
|
43
43
|
/** 内部降级/竞态/IO 失败——appendEntry 持久化,不显 TUI,不进 LLM。 */
|
|
44
44
|
warn(msg: string, data?: unknown): void;
|
|
@@ -178,7 +178,7 @@ function prefixMsg(extName: string, msg: string): string {
|
|
|
178
178
|
/**
|
|
179
179
|
* 写文件日志到 `<agentDir>/logs/<extName>-YYYY-MM-DD.log`。
|
|
180
180
|
*
|
|
181
|
-
* 仅在
|
|
181
|
+
* 仅在 XYZ_AGENT_DEBUG 环境变量为 "1" 时写入(默认 no-op,生产环境零开销)。
|
|
182
182
|
* agentDir 通过 pi 的 SSOT `getAgentDir()` 推导(读
|
|
183
183
|
* `PI_CODING_AGENT_DIR`/`${APP_NAME}_CODING_AGENT_DIR`,默认 `~/.pi/agent`),
|
|
184
184
|
* 与其它 extension 的路径派生保持一致。
|
|
@@ -188,7 +188,7 @@ function prefixMsg(extName: string, msg: string): string {
|
|
|
188
188
|
* 行可能交错(可接受——debug 日志不要求严格顺序)。
|
|
189
189
|
*/
|
|
190
190
|
function fileLog(extName: string, level: LogLevel, msg: string, data?: unknown): void {
|
|
191
|
-
if (process.env.
|
|
191
|
+
if (process.env.XYZ_AGENT_DEBUG !== "1") return;
|
|
192
192
|
try {
|
|
193
193
|
const agentDir = getAgentDir();
|
|
194
194
|
const logDir = join(agentDir, "logs");
|