@zhushanwen/pi-ext-guards 0.4.0 → 0.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhushanwen/pi-ext-guards",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Shared runtime-environment guards for Pi extensions — oncePerProcess(key, fn) dedupes cross-session side-effect operations against pi factory re-invocation and handler accumulation (shared library, not a Pi extension, zero dependencies).",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -3,7 +3,7 @@
3
3
  // guardStaleCtx 单测——验收条款逐条对应(crash-resilience u1-ext-guard):
4
4
  // a. 前置代际检查:isCtxStale=true → fn 不执行、stale 静默降级(返回 undefined)
5
5
  // b. 非 stale 错误原样上抛(守卫不吞真实 bug,同步 throw 与 async rejection 双面)
6
- // c. onStale 回调:前置命中无参调用;文案分诊命中携带错误调用;缺省走 XYZ_AGENT_DEBUG=1 stderr
6
+ // c. onStale 回调:前置命中无参调用;文案分诊命中携带错误调用;缺省走 TAIJI_AGENT_DEBUG=1 stderr
7
7
  // d. 文案子串匹配:STALE_CTX_MARKER 命中即静默(isCtxStale=false 时文案兜底仍生效)
8
8
  // e. async fn:stale rejection → resolve undefined;非 stale rejection → 原样 reject
9
9
  // f. 正常路径:返回值/resolve 值原样透传(守卫不改变正常路径,A2 负面验证的单测面)
@@ -140,8 +140,8 @@ describe("guardStaleCtx async fn(F2 形态异步面,scheduler tick 迁移形
140
140
  });
141
141
 
142
142
  describe("guardStaleCtx onStale 缺省(默认 debug 日志)", () => {
143
- it("XYZ_AGENT_DEBUG=1:stderr 写入守卫降级行(含 label 与错误文案)", () => {
144
- vi.stubEnv("XYZ_AGENT_DEBUG", "1");
143
+ it("TAIJI_AGENT_DEBUG=1:stderr 写入守卫降级行(含 label 与错误文案)", () => {
144
+ vi.stubEnv("TAIJI_AGENT_DEBUG", "1");
145
145
  const stderr = vi.spyOn(process.stderr, "write").mockReturnValue(true);
146
146
 
147
147
  guardStaleCtx(() => {
@@ -154,8 +154,8 @@ describe("guardStaleCtx onStale 缺省(默认 debug 日志)", () => {
154
154
  expect(line).toContain(STALE_CTX_MARKER);
155
155
  });
156
156
 
157
- it("XYZ_AGENT_DEBUG 未设:静默(不写 stderr)", () => {
158
- vi.stubEnv("XYZ_AGENT_DEBUG", "");
157
+ it("TAIJI_AGENT_DEBUG 未设:静默(不写 stderr)", () => {
158
+ vi.stubEnv("TAIJI_AGENT_DEBUG", "");
159
159
  const stderr = vi.spyOn(process.stderr, "write").mockReturnValue(true);
160
160
 
161
161
  guardStaleCtx(() => {
@@ -59,14 +59,14 @@ describe("isEnoentError", () => {
59
59
  });
60
60
 
61
61
  describe("isSubagentProcess", () => {
62
- it("XYZ_AGENT_SUBAGENT=1 命中(引擎 spawn 链恒注入的现行标记)", () => {
63
- expect(isSubagentProcess({ XYZ_AGENT_SUBAGENT: "1" })).toBe(true);
62
+ it("TAIJI_AGENT_SUBAGENT=1 命中(引擎 spawn 链恒注入的现行标记)", () => {
63
+ expect(isSubagentProcess({ TAIJI_AGENT_SUBAGENT: "1" })).toBe(true);
64
64
  });
65
65
 
66
66
  it("值非 \"1\" 不命中(标记必须是引擎注入的字面 \"1\")", () => {
67
- expect(isSubagentProcess({ XYZ_AGENT_SUBAGENT: "0" })).toBe(false);
68
- expect(isSubagentProcess({ XYZ_AGENT_SUBAGENT: "" })).toBe(false);
69
- expect(isSubagentProcess({ XYZ_AGENT_SUBAGENT: "true" })).toBe(false);
67
+ expect(isSubagentProcess({ TAIJI_AGENT_SUBAGENT: "0" })).toBe(false);
68
+ expect(isSubagentProcess({ TAIJI_AGENT_SUBAGENT: "" })).toBe(false);
69
+ expect(isSubagentProcess({ TAIJI_AGENT_SUBAGENT: "true" })).toBe(false);
70
70
  });
71
71
 
72
72
  it("缺失不命中(顶层会话 → 消费方不降级)", () => {
@@ -74,28 +74,28 @@ describe("isSubagentProcess", () => {
74
74
  });
75
75
 
76
76
  it("env 参数注入隔离:传入的 env 与宿主 process.env 无关(宿主即使带标记,空 env 也不命中)", () => {
77
- const saved = process.env.XYZ_AGENT_SUBAGENT;
77
+ const saved = process.env.TAIJI_AGENT_SUBAGENT;
78
78
  try {
79
- process.env.XYZ_AGENT_SUBAGENT = "1";
79
+ process.env.TAIJI_AGENT_SUBAGENT = "1";
80
80
  // 显式传 env:宿主的标记不渗透,判据只看参数
81
81
  expect(isSubagentProcess({})).toBe(false);
82
- expect(isSubagentProcess({ XYZ_AGENT_SUBAGENT: "1" })).toBe(true);
82
+ expect(isSubagentProcess({ TAIJI_AGENT_SUBAGENT: "1" })).toBe(true);
83
83
  } finally {
84
- if (saved === undefined) delete process.env.XYZ_AGENT_SUBAGENT;
85
- else process.env.XYZ_AGENT_SUBAGENT = saved;
84
+ if (saved === undefined) delete process.env.TAIJI_AGENT_SUBAGENT;
85
+ else process.env.TAIJI_AGENT_SUBAGENT = saved;
86
86
  }
87
87
  });
88
88
 
89
89
  it("缺省参数读 process.env(不传 env 时以宿主环境为判据)", () => {
90
- const saved = process.env.XYZ_AGENT_SUBAGENT;
90
+ const saved = process.env.TAIJI_AGENT_SUBAGENT;
91
91
  try {
92
- process.env.XYZ_AGENT_SUBAGENT = "1";
92
+ process.env.TAIJI_AGENT_SUBAGENT = "1";
93
93
  expect(isSubagentProcess()).toBe(true);
94
- delete process.env.XYZ_AGENT_SUBAGENT;
94
+ delete process.env.TAIJI_AGENT_SUBAGENT;
95
95
  expect(isSubagentProcess()).toBe(false);
96
96
  } finally {
97
- if (saved === undefined) delete process.env.XYZ_AGENT_SUBAGENT;
98
- else process.env.XYZ_AGENT_SUBAGENT = saved;
97
+ if (saved === undefined) delete process.env.TAIJI_AGENT_SUBAGENT;
98
+ else process.env.TAIJI_AGENT_SUBAGENT = saved;
99
99
  }
100
100
  });
101
101
 
package/src/index.ts CHANGED
@@ -109,14 +109,14 @@ export function isEnoentError(err: unknown): boolean {
109
109
  // (base-tool-enhance background 降级——bte background 生命周期设计的 D14 项,
110
110
  // commit 8599abd0c,该设计未在现行 docs 留档 / smart-context R6 不注册工具,
111
111
  // 规则定义见 smart-context src/index.ts R 规则族注释)。判据锚
112
- // XYZ_AGENT_SUBAGENT=1——subagent-engine-sdk env.ts 的 buildEngineChildEnv 对每个引擎
112
+ // TAIJI_AGENT_SUBAGENT=1——subagent-engine-sdk env.ts 的 buildEngineChildEnv 对每个引擎
113
113
  // 子进程恒注入(L0 层最后写入),再经引擎内二次 spawn(buildOutboundChildEnv 全量
114
114
  // 继承)传到 subagent 内的 bash。旧判据(PI_SUBAGENT_ROOT_SESSION_ID /
115
115
  // PI_SUBAGENT_SELF_RECORD_ID 两键)在引擎协议化后已无写入方(20260914 探针证实,
116
116
  // 报告 .tmp/dev-flow/ext-simplify-17-d4-probe.md),判据失效态由 D4 重锚收敛于此。
117
117
 
118
118
  /** subagent 进程标记 env 键(引擎 spawn 链恒注入 "1",subagent-engine-sdk env.ts L0)。 */
119
- export const SUBAGENT_MARKER_ENV = "XYZ_AGENT_SUBAGENT";
119
+ export const SUBAGENT_MARKER_ENV = "TAIJI_AGENT_SUBAGENT";
120
120
 
121
121
  /**
122
122
  * 判断当前进程是否引擎链上的 subagent 子进程。
@@ -137,7 +137,7 @@ export function isSubagentProcess(
137
137
 
138
138
  // ── stale ctx 守卫(guardStaleCtx,崩溃韧性 D1)────────────────────────
139
139
  //
140
- // 背景(docs/design/crash-resilience.md §3.3 D1 / §2.2 事件 E1):pi 的 extension API
140
+ // 背景:pi 的 extension API
141
141
  // 对象(pi / ctx)在 session 替换(newSession/fork/switchSession/reload)后被 runner
142
142
  // 标记 stale,再调用其方法会**同步抛错**(loader.js/runner.js 的 assertActive,错误文案
143
143
  // 含 STALE_CTX_MARKER)。跨 session 生命周期存活的异步回调(compact 的 onComplete/onError、
@@ -172,7 +172,7 @@ export interface GuardStaleCtxOptions {
172
172
  isCtxStale?: () => boolean;
173
173
  /**
174
174
  * stale 降级通知(静默降级的观测点):前置检查命中时无参调用;fn 抛错被分诊为
175
- * stale 时以捕获的错误为参调用。缺省 = 仅 XYZ_AGENT_DEBUG=1 时写一行 stderr
175
+ * stale 时以捕获的错误为参调用。缺省 = 仅 TAIJI_AGENT_DEBUG=1 时写一行 stderr
176
176
  * debug(本包零依赖、无 pi handle,不能走 extension-logger;需要落盘日志的
177
177
  * 接入方传入自己的 debugLog/logger.warn)。
178
178
  */
@@ -189,9 +189,9 @@ function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
189
189
  );
190
190
  }
191
191
 
192
- /** 缺省降级通知:XYZ_AGENT_DEBUG=1 时 stderr 一行(对齐 extensions 包 XYZ_AGENT_DEBUG 惯例)。 */
192
+ /** 缺省降级通知:TAIJI_AGENT_DEBUG=1 时 stderr 一行(对齐 extensions 包 TAIJI_AGENT_DEBUG 惯例)。 */
193
193
  function defaultOnStale(label: string, error?: unknown): void {
194
- if (process.env.XYZ_AGENT_DEBUG !== "1") return;
194
+ if (process.env.TAIJI_AGENT_DEBUG !== "1") return;
195
195
  const detail =
196
196
  error === undefined
197
197
  ? "generation check (isCtxStale)"