@zhushanwen/pi-extension-logger 0.4.1 → 0.6.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 +2 -2
- package/src/__tests__/extension-logger.test.ts +32 -32
- package/src/index.ts +27 -23
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-extension-logger",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Shared logging helper for Pi extensions —
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"description": "Shared logging helper for Pi extensions — two-channel routing (audit appendEntry / debug file log; the third AI-realtime channel stays with pi native) (shared library, not a Pi extension - no install.mjs needed)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"keywords": [
|
|
@@ -27,7 +27,7 @@ describe("extension-logger", () => {
|
|
|
27
27
|
setPiHandle(undefined);
|
|
28
28
|
clearRateLimiterState();
|
|
29
29
|
vi.restoreAllMocks();
|
|
30
|
-
// 还原环境变量,避免文件日志测试的
|
|
30
|
+
// 还原环境变量,避免文件日志测试的 TAIJI_AGENT_DEBUG/PI_CODING_AGENT_DIR 泄漏到其它用例
|
|
31
31
|
process.env = { ...prevEnv };
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -140,7 +140,7 @@ describe("extension-logger", () => {
|
|
|
140
140
|
});
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
-
describe("
|
|
143
|
+
describe("TAIJI_AGENT_DEBUG 文件日志", () => {
|
|
144
144
|
// 文件日志的 agentDir 通过 getAgentDir() 推导(读 PI_CODING_AGENT_DIR,
|
|
145
145
|
// 默认 ~/.pi/agent)。设 PI_CODING_AGENT_DIR 到 tmpdir 子目录,与组 A 的
|
|
146
146
|
// arch-boundary 改动(fileLog 用 getAgentDir())保持一致。
|
|
@@ -155,19 +155,19 @@ describe("extension-logger", () => {
|
|
|
155
155
|
afterEach(() => {
|
|
156
156
|
vi.useRealTimers();
|
|
157
157
|
if (tmpAgentDir) {
|
|
158
|
-
rmSync(tmpAgentDir, { recursive: true, force: true });
|
|
158
|
+
rmSync(tmpAgentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
159
159
|
}
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
it("
|
|
163
|
-
delete process.env.
|
|
162
|
+
it("TAIJI_AGENT_DEBUG 未设时 debug 是 no-op(不抛错即可)", () => {
|
|
163
|
+
delete process.env.TAIJI_AGENT_DEBUG;
|
|
164
164
|
const logger = createLogger("test", pi);
|
|
165
165
|
expect(() => logger.debug("no-op")).not.toThrow();
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
// ---- Suggestion #8:fileLog 实际写入路径 ----
|
|
169
|
-
it("
|
|
170
|
-
process.env.
|
|
169
|
+
it("TAIJI_AGENT_DEBUG=1 时 debug 写入日志文件,内容含 [debug] 与序列化 data", () => {
|
|
170
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
171
171
|
// 固定日期 → 文件名 <extName>-2026-08-01.log
|
|
172
172
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
173
173
|
|
|
@@ -190,8 +190,8 @@ describe("extension-logger", () => {
|
|
|
190
190
|
expect(appendSpy).not.toHaveBeenCalled();
|
|
191
191
|
});
|
|
192
192
|
|
|
193
|
-
it("
|
|
194
|
-
process.env.
|
|
193
|
+
it("TAIJI_AGENT_DEBUG=1 时 warn 既写文件又走 appendEntry(文件内容含 [warn])", () => {
|
|
194
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
195
195
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
196
196
|
|
|
197
197
|
const logger = createLogger("warn-ext", pi);
|
|
@@ -207,8 +207,8 @@ describe("extension-logger", () => {
|
|
|
207
207
|
expect(appendSpy).toHaveBeenCalledOnce();
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
it("
|
|
211
|
-
process.env.
|
|
210
|
+
it("TAIJI_AGENT_DEBUG=1 写失败(只读目录)不 throw", () => {
|
|
211
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
212
212
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
213
213
|
|
|
214
214
|
// 已存在的 logs 目录改为只读,让 mkdirSync/appendFileSync 失败。
|
|
@@ -226,7 +226,7 @@ describe("extension-logger", () => {
|
|
|
226
226
|
|
|
227
227
|
// 清理:先恢复写权限才能删除
|
|
228
228
|
chmodSync(logDir, RESTORE_MODE);
|
|
229
|
-
rmSync(readonlyAgentDir, { recursive: true, force: true });
|
|
229
|
+
rmSync(readonlyAgentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
230
230
|
});
|
|
231
231
|
});
|
|
232
232
|
|
|
@@ -243,13 +243,13 @@ describe("extension-logger", () => {
|
|
|
243
243
|
const [, entry] = appendSpy.mock.calls[0]!;
|
|
244
244
|
// appendEntry payload 的 data 字段保留原对象(safeStringify 仅在文件日志路径用)
|
|
245
245
|
expect(entry).toMatchObject({ level: "warn" });
|
|
246
|
-
// 验证 safeStringify 的 fallback 分支:用
|
|
246
|
+
// 验证 safeStringify 的 fallback 分支:用 TAIJI_AGENT_DEBUG=1 触发 fileLog,
|
|
247
247
|
// 文件内 data 应是 String() 形式(含 [object Object] 或循环结构字符串)
|
|
248
248
|
expect(() => JSON.stringify(cyclic)).toThrow(); // 对照:原对象确实不可序列化
|
|
249
249
|
});
|
|
250
250
|
|
|
251
251
|
it("BigInt:warn 不崩,文件日志路径走 String fallback", () => {
|
|
252
|
-
process.env.
|
|
252
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
253
253
|
const tmpAgentDir = mkdtempSync(join(tmpdir(), "pi-ext-bigint-"));
|
|
254
254
|
process.env.PI_CODING_AGENT_DIR = tmpAgentDir;
|
|
255
255
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
@@ -269,21 +269,21 @@ describe("extension-logger", () => {
|
|
|
269
269
|
expect(content).not.toContain('"count"');
|
|
270
270
|
|
|
271
271
|
vi.useRealTimers();
|
|
272
|
-
rmSync(tmpAgentDir, { recursive: true, force: true });
|
|
272
|
+
rmSync(tmpAgentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
273
273
|
});
|
|
274
274
|
});
|
|
275
275
|
|
|
276
276
|
// ============================================================
|
|
277
|
-
//
|
|
277
|
+
// TAIJI_AGENT_EXT_LOG 托管观测档(设计 file-lock-unification-and-reaper-sink §3.2-D4)
|
|
278
278
|
// ============================================================
|
|
279
|
-
describe("
|
|
279
|
+
describe("TAIJI_AGENT_EXT_LOG 托管观测档", () => {
|
|
280
280
|
let tmpAgentDir: string;
|
|
281
281
|
|
|
282
282
|
beforeEach(() => {
|
|
283
283
|
tmpAgentDir = mkdtempSync(join(tmpdir(), "pi-ext-extlog-"));
|
|
284
284
|
process.env.PI_CODING_AGENT_DIR = tmpAgentDir;
|
|
285
|
-
delete process.env.
|
|
286
|
-
delete process.env.
|
|
285
|
+
delete process.env.TAIJI_AGENT_DEBUG;
|
|
286
|
+
delete process.env.TAIJI_AGENT_EXT_LOG;
|
|
287
287
|
resetExtLogCleanupForTest();
|
|
288
288
|
vi.useFakeTimers();
|
|
289
289
|
});
|
|
@@ -291,7 +291,7 @@ describe("extension-logger", () => {
|
|
|
291
291
|
afterEach(() => {
|
|
292
292
|
vi.useRealTimers();
|
|
293
293
|
resetExtLogCleanupForTest();
|
|
294
|
-
rmSync(tmpAgentDir, { recursive: true, force: true });
|
|
294
|
+
rmSync(tmpAgentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
295
295
|
});
|
|
296
296
|
|
|
297
297
|
it("均未注入时 no-op:debug/warn/error 调用后 logs 目录都不创建(裸 pi 用户零磁盘影响)", () => {
|
|
@@ -302,8 +302,8 @@ describe("extension-logger", () => {
|
|
|
302
302
|
expect(existsSync(join(tmpAgentDir, "logs"))).toBe(false);
|
|
303
303
|
});
|
|
304
304
|
|
|
305
|
-
it("仅
|
|
306
|
-
process.env.
|
|
305
|
+
it("仅 TAIJI_AGENT_EXT_LOG=1:debug 调用以 info 级落盘(含序列化 data),不标 debug", () => {
|
|
306
|
+
process.env.TAIJI_AGENT_EXT_LOG = "1";
|
|
307
307
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
308
308
|
|
|
309
309
|
const logger = createLogger("extlog-ext", pi);
|
|
@@ -320,8 +320,8 @@ describe("extension-logger", () => {
|
|
|
320
320
|
expect(appendSpy).not.toHaveBeenCalled();
|
|
321
321
|
});
|
|
322
322
|
|
|
323
|
-
it("仅
|
|
324
|
-
process.env.
|
|
323
|
+
it("仅 TAIJI_AGENT_EXT_LOG=1:warn/error 照常落盘且保持原级标注", () => {
|
|
324
|
+
process.env.TAIJI_AGENT_EXT_LOG = "1";
|
|
325
325
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
326
326
|
|
|
327
327
|
const logger = createLogger("extlog-err", pi);
|
|
@@ -335,9 +335,9 @@ describe("extension-logger", () => {
|
|
|
335
335
|
expect(content).not.toContain("[info]");
|
|
336
336
|
});
|
|
337
337
|
|
|
338
|
-
it("
|
|
339
|
-
process.env.
|
|
340
|
-
process.env.
|
|
338
|
+
it("TAIJI_AGENT_DEBUG=1 与 EXT_LOG 同注入:按更详细的生效(debug 全量,原级标注)", () => {
|
|
339
|
+
process.env.TAIJI_AGENT_EXT_LOG = "1";
|
|
340
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
341
341
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
342
342
|
|
|
343
343
|
const logger = createLogger("both-ext", pi);
|
|
@@ -355,7 +355,7 @@ describe("extension-logger", () => {
|
|
|
355
355
|
});
|
|
356
356
|
|
|
357
357
|
it("保留期清理:7 天前的 <ext>-<date>.log 被删,近期与本包 pattern 外文件保留", () => {
|
|
358
|
-
process.env.
|
|
358
|
+
process.env.TAIJI_AGENT_EXT_LOG = "1";
|
|
359
359
|
// fake timers 冻结 Date 在真实当前时刻:文件 mtime 走真实时钟,utimesSync 把
|
|
360
360
|
// old 的 mtime 设为 8 天前(> 7 天保留期),recent 与 unrelated 保留。
|
|
361
361
|
const logDir = join(tmpAgentDir, "logs");
|
|
@@ -381,7 +381,7 @@ describe("extension-logger", () => {
|
|
|
381
381
|
});
|
|
382
382
|
|
|
383
383
|
it("清理只认 <ext>-YYYY-MM-DD.log pattern,不动其他 .log 文件", () => {
|
|
384
|
-
process.env.
|
|
384
|
+
process.env.TAIJI_AGENT_EXT_LOG = "1";
|
|
385
385
|
const logDir = join(tmpAgentDir, "logs");
|
|
386
386
|
mkdirSync(logDir, { recursive: true });
|
|
387
387
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
@@ -510,8 +510,8 @@ describe("extension-logger", () => {
|
|
|
510
510
|
expect(appendSpy).toHaveBeenCalledTimes(10);
|
|
511
511
|
});
|
|
512
512
|
|
|
513
|
-
it("fileLog 通道不受限(
|
|
514
|
-
process.env.
|
|
513
|
+
it("fileLog 通道不受限(TAIJI_AGENT_DEBUG=1 时 100 条全写文件)", () => {
|
|
514
|
+
process.env.TAIJI_AGENT_DEBUG = "1";
|
|
515
515
|
const tmpAgentDir = mkdtempSync(join(tmpdir(), "pi-ext-ratelimit-"));
|
|
516
516
|
process.env.PI_CODING_AGENT_DIR = tmpAgentDir;
|
|
517
517
|
vi.setSystemTime(new Date("2026-08-01T12:34:56.789Z"));
|
|
@@ -531,7 +531,7 @@ describe("extension-logger", () => {
|
|
|
531
531
|
const lines = content.split("\n").filter(Boolean);
|
|
532
532
|
expect(lines).toHaveLength(100);
|
|
533
533
|
|
|
534
|
-
rmSync(tmpAgentDir, { recursive: true, force: true });
|
|
534
|
+
rmSync(tmpAgentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
535
535
|
});
|
|
536
536
|
|
|
537
537
|
it("appendEntry 抛错时降级不 throw(限流计数正常)", () => {
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
//
|
|
3
|
-
// 共享 extension logger ——
|
|
3
|
+
// 共享 extension logger —— 双通道日志封装,按受众路由。
|
|
4
4
|
//
|
|
5
5
|
// 设计依据:pi 宿主层(ExtensionAPI/ExtensionContext)不提供 logger 接口。
|
|
6
6
|
// extension 只能裸 console(污染 TUI raw stderr)或自组 ctx.ui.notify(刷屏)+
|
|
7
|
-
// pi.appendEntry
|
|
7
|
+
// pi.appendEntry(持久化但用户不可见)。本模块封装这套通道,让 @zhushanwen/pi-*
|
|
8
8
|
// 各包统一调用,消除裸 console。
|
|
9
9
|
//
|
|
10
|
-
//
|
|
10
|
+
// 三通道分类法(本模块实装其中两通道;通道 1 为 pi 原生行为,仅登记不封装):
|
|
11
11
|
// 1. AI 实时 → tool result / block reason(pi 原生,本模块不涉及)
|
|
12
|
-
// 2. 事后排查 → pi.appendEntry(custom entry 不进 LLM 上下文,不显 TUI
|
|
13
|
-
// 3. 开发者调试 → 文件日志,双开关分级(写 <agentDir>/logs/,均未注入默认 no-op
|
|
14
|
-
// -
|
|
15
|
-
// -
|
|
12
|
+
// 2. 事后排查 → pi.appendEntry(custom entry 不进 LLM 上下文,不显 TUI)【实装】
|
|
13
|
+
// 3. 开发者调试 → 文件日志,双开关分级(写 <agentDir>/logs/,均未注入默认 no-op)【实装】:
|
|
14
|
+
// - TAIJI_AGENT_DEBUG=1 → DEBUG 全量(现状语义,level 原样标注)
|
|
15
|
+
// - TAIJI_AGENT_EXT_LOG=1 → INFO 级落盘(taiji 托管环境由 runtime spawn 时经
|
|
16
16
|
// buildOutboundChildEnv extras 注入,设计 file-lock-unification-and-reaper-sink
|
|
17
17
|
// §3.2-D4 / U3-3)+ 7 天保留期清理;debug() 调用此模式下重标 info 写入
|
|
18
18
|
// - 两变量同时注入按更详细的生效(DEBUG 全量优先)
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
//
|
|
21
21
|
// notify(用户操作反馈)刻意不封装——它是 UI 决策,留给各 extension 在命令/视图层
|
|
22
22
|
// 直接调 ctx.ui.notify。
|
|
23
|
+
//
|
|
24
|
+
// fileLog 单日文件无 size cap——显式豁免,依据:写入方为每 session 短命 pi 进程
|
|
25
|
+
// + 7 天保留期清理 + DEBUG 档系开发者主动排障。
|
|
23
26
|
|
|
24
27
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
25
28
|
import {
|
|
@@ -44,11 +47,11 @@ import { join } from "node:path";
|
|
|
44
47
|
// - key = msg 原文(不包含 data 参数)。若调用方把动态 id 拼进 msg
|
|
45
48
|
// (如 `session=${id}`),每条 msg 不同则限流不命中。根治靠调用方把
|
|
46
49
|
// 动态值放 data 参数(D4 已声明)。
|
|
47
|
-
// - fileLog 通道全量不限流(
|
|
50
|
+
// - fileLog 通道全量不限流(TAIJI_AGENT_DEBUG=1 / TAIJI_AGENT_EXT_LOG=1 时日志写文件)。
|
|
48
51
|
// - Map cap 512 超限时全量清空(简化策略,对齐 cap-1024 先例),
|
|
49
52
|
// 等价于所有 key 窗口重置,防无界增长。
|
|
50
53
|
//
|
|
51
|
-
// 设计依据:
|
|
54
|
+
// 设计依据:extension-log-cleanup-design §3.4 D4
|
|
52
55
|
// ============================================================
|
|
53
56
|
|
|
54
57
|
/** 同 key 每窗口允许直写 appendEntry 的最大条数。 */
|
|
@@ -73,7 +76,7 @@ interface RateLimiterEntry {
|
|
|
73
76
|
* key = `${extName}:${level}:${msg}`(msg 为原 msg,非 prefixed)。
|
|
74
77
|
* 同进程所有 logger 实例共享(模块级 singleton)。
|
|
75
78
|
*
|
|
76
|
-
* ⚠️ 生命周期与进程一致——
|
|
79
|
+
* ⚠️ 生命周期与进程一致——taiji 每 session 一个独立 pi 进程
|
|
77
80
|
* (见 runtime process-manager.ts 的类注释),故不存在跨 session 残留问题。
|
|
78
81
|
*/
|
|
79
82
|
const rateLimiterState = new Map<string, RateLimiterEntry>();
|
|
@@ -153,8 +156,8 @@ export interface PiLike {
|
|
|
153
156
|
appendEntry?(customType: string, data?: unknown): void;
|
|
154
157
|
}
|
|
155
158
|
|
|
156
|
-
/** 日志级别。debug = 开发调试;info =
|
|
157
|
-
|
|
159
|
+
/** 日志级别。debug = 开发调试;info = TAIJI_AGENT_EXT_LOG 模式下 debug() 的落盘标注;warn/error = 内部降级与失败(事后排查价值)。 */
|
|
160
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
158
161
|
|
|
159
162
|
/**
|
|
160
163
|
* Extension logger 接口。方法名即语义——不做运行时 level filtering(pi 不支持,
|
|
@@ -162,8 +165,8 @@ export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
|
162
165
|
*/
|
|
163
166
|
export interface ExtensionLogger {
|
|
164
167
|
/**
|
|
165
|
-
* 开发调试日志。默认 no-op;
|
|
166
|
-
*
|
|
168
|
+
* 开发调试日志。默认 no-op;TAIJI_AGENT_DEBUG=1 时写文件日志(原级标注);
|
|
169
|
+
* TAIJI_AGENT_EXT_LOG=1(无 DEBUG)时以 info 级落盘(托管环境 INFO 观测档)。
|
|
167
170
|
* 不进 appendEntry。
|
|
168
171
|
*/
|
|
169
172
|
debug(msg: string, data?: unknown): void;
|
|
@@ -219,11 +222,12 @@ export function setPiHandle(pi: PiLike | undefined): void {
|
|
|
219
222
|
/**
|
|
220
223
|
* 创建具名 logger。
|
|
221
224
|
*
|
|
222
|
-
* @param extName extension 名(如 "subagents"、"
|
|
225
|
+
* @param extName extension 名(如 "subagents"、"smart-context"),用作:
|
|
223
226
|
* - appendEntry 的 customType 前缀(`<extName>:log`)
|
|
224
227
|
* - 文件日志名(`<extName>-YYYY-MM-DD.log`)
|
|
225
228
|
* - msg 前缀(`[<extName>]`,自动补)
|
|
226
|
-
* @param pi 可选 pi handle
|
|
229
|
+
* @param pi 可选 pi handle;测试隔离注入用,生产一律 setPiHandle/getLogger。
|
|
230
|
+
* 不传则用 setPiHandle 注入的全局 handle
|
|
227
231
|
* @returns ExtensionLogger 实例(每次返回同一引用,便于模块级 const 缓存)
|
|
228
232
|
*/
|
|
229
233
|
export function createLogger(extName: string, pi?: PiLike): ExtensionLogger {
|
|
@@ -268,7 +272,7 @@ export function createLogger(extName: string, pi?: PiLike): ExtensionLogger {
|
|
|
268
272
|
// appendEntry 失败(session 已 disposed 等)→ 降级文件日志(下方 fileLog 兜底),不 throw
|
|
269
273
|
void appendErr;
|
|
270
274
|
}
|
|
271
|
-
// fileLog 全量不限流(
|
|
275
|
+
// fileLog 全量不限流(TAIJI_AGENT_DEBUG=1 排障时可见全部)
|
|
272
276
|
fileLog(extName, "warn", prefixed, data);
|
|
273
277
|
},
|
|
274
278
|
error(msg: string, data?: unknown): void {
|
|
@@ -343,10 +347,10 @@ function prefixMsg(extName: string, msg: string): string {
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
// ============================================================
|
|
346
|
-
//
|
|
350
|
+
// TAIJI_AGENT_EXT_LOG 托管观测档 + 保留期清理
|
|
347
351
|
// ============================================================
|
|
348
352
|
|
|
349
|
-
/** 托管观测档(
|
|
353
|
+
/** 托管观测档(TAIJI_AGENT_EXT_LOG=1)的日志保留天数,超期文件在首次落盘时清理。 */
|
|
350
354
|
const EXT_LOG_KEEP_DAYS = 7;
|
|
351
355
|
// 一天的毫秒数(数字分隔符形式对齐 session-reader hash-provider 的时间常量惯例)
|
|
352
356
|
const MS_PER_DAY = 86_400_000;
|
|
@@ -407,8 +411,8 @@ export function resetExtLogCleanupForTest(): void {
|
|
|
407
411
|
* 写文件日志到 `<agentDir>/logs/<extName>-YYYY-MM-DD.log`。
|
|
408
412
|
*
|
|
409
413
|
* 双开关分级(设计 file-lock-unification-and-reaper-sink §3.2-D4):
|
|
410
|
-
* -
|
|
411
|
-
* - 仅
|
|
414
|
+
* - TAIJI_AGENT_DEBUG=1 → DEBUG 全量,level 原样标注(现状语义不变);
|
|
415
|
+
* - 仅 TAIJI_AGENT_EXT_LOG=1 → INFO 级落盘:debug() 调用重标 info 写入,warn/error 照写;
|
|
412
416
|
* - 均未注入 → no-op(零 fs 调用,裸 pi 独立用户零磁盘/行为影响)。
|
|
413
417
|
* agentDir 通过 pi 的 SSOT `getAgentDir()` 推导(读
|
|
414
418
|
* `PI_CODING_AGENT_DIR`/`${APP_NAME}_CODING_AGENT_DIR`,默认 `~/.pi/agent`),
|
|
@@ -420,8 +424,8 @@ export function resetExtLogCleanupForTest(): void {
|
|
|
420
424
|
* 行可能交错(可接受——debug 日志不要求严格顺序)。
|
|
421
425
|
*/
|
|
422
426
|
function fileLog(extName: string, level: LogLevel, msg: string, data?: unknown): void {
|
|
423
|
-
const debugMode = process.env.
|
|
424
|
-
const extLogMode = !debugMode && process.env.
|
|
427
|
+
const debugMode = process.env.TAIJI_AGENT_DEBUG === "1";
|
|
428
|
+
const extLogMode = !debugMode && process.env.TAIJI_AGENT_EXT_LOG === "1";
|
|
425
429
|
if (!debugMode && !extLogMode) return;
|
|
426
430
|
// 托管观测档:debug() 调用降档标注为 info(INFO 级观测,非 DEBUG 全量)
|
|
427
431
|
const effectiveLevel: LogLevel = extLogMode && level === "debug" ? "info" : level;
|