@zhushanwen/pi-system-prompt 1.1.2 → 1.1.3

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-system-prompt",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "System prompt injection extension for Pi — reads config and appends to system prompt",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -32,7 +32,7 @@
32
32
  "vitest": "^4.1.8"
33
33
  },
34
34
  "dependencies": {
35
- "@zhushanwen/pi-extension-logger": "0.3.1"
35
+ "@zhushanwen/pi-extension-logger": "0.4.0"
36
36
  },
37
37
  "scripts": {
38
38
  "typecheck": "npx tsc --noEmit",
@@ -9,7 +9,7 @@
9
9
  * - -nc / --no-context-files 守卫:global 注入跳过、append 不受影响
10
10
  * - global 候选选择:候选序优先、空白内容跳过继续找、目录缺失降级
11
11
  * - fail-safe:handler 全程 throw → return undefined + logger.error 可观测;logger 自身抛错的
12
- * 终极兜底 console.debug;systemPrompt 非法类型的旧 quirk 锚定
12
+ * 终极兜底 process.stderr.write;systemPrompt 非法类型的旧 quirk 锚定
13
13
  *
14
14
  * mock 策略(参照 msg-id-mapper 测试模式):pi SDK import type 零运行时解析,
15
15
  * ExtensionAPI 用结构化桩;node:fs mock 后按路径分流(env 指向假目录,不碰真实文件系统)。
package/src/index.ts CHANGED
@@ -7,9 +7,12 @@
7
7
  * 2. When `append.enabled === true` and `append.prompt` is non-blank,
8
8
  * appends the user's text to the event's systemPrompt.
9
9
  * 3. Reads the global instructions file `~/.agents/AGENTS.md` (candidates
10
- * AGENTS.md / AGENTS.MD / CLAUDE.md / CLAUDE.MD mirroring pi's native
11
- * `loadContextFileFromDir`) every turn and appends it under a labeled
12
- * header. Opt-in by file existence: no file no injection. Skipped when
10
+ * AGENTS.md / AGENTS.MD / CLAUDE.md / CLAUDE.MD) every turn and appends it
11
+ * under a labeled header. Modeled on pi's native `loadContextFileFromDir`
12
+ * but deliberately narrower: pi 0.84.4 also probes `AGENTS.override.md`
13
+ * and applies its candidate list to project dirs, whereas this list only
14
+ * targets the global agents directory and never picks up override files.
15
+ * Opt-in by file existence: no file → no injection. Skipped when
13
16
  * pi was spawned with `--no-context-files` (consistent with pi's native
14
17
  * context-file opt-out). `XYZ_GLOBAL_AGENTS_DIR` overrides the global
15
18
  * directory (test hook / escape hatch).
@@ -56,7 +59,13 @@ function cachedReadFileSync(filePath: string): string | null {
56
59
  }
57
60
  }
58
61
 
59
- /** Global instruction candidates, mirroring pi's loadContextFileFromDir. */
62
+ /**
63
+ * Global instruction candidates. Modeled on pi's native loadContextFileFromDir
64
+ * but deliberately not a strict mirror: pi 0.84.4 probes
65
+ * ["AGENTS.override.md", "AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"]
66
+ * against project dirs, while these candidates apply only to the global agents
67
+ * directory and intentionally exclude AGENTS.override.md.
68
+ */
60
69
  const GLOBAL_AGENTS_CANDIDATES = ['AGENTS.md', 'AGENTS.MD', 'CLAUDE.md', 'CLAUDE.MD']
61
70
 
62
71
  /**
@@ -96,8 +105,9 @@ function resolveGlobalAgentsDir(): string {
96
105
 
97
106
  /**
98
107
  * Read the global instructions file. First candidate that exists and is a
99
- * regular file with non-blank content wins (mirrors pi's loadContextFileFromDir
100
- * semantics). Returns { path, content } or null; never throws.
108
+ * regular file with non-blank content wins (selection semantics consistent
109
+ * with pi's native loader; the candidate list itself is narrower, see
110
+ * GLOBAL_AGENTS_CANDIDATES). Returns { path, content } or null; never throws.
101
111
  */
102
112
  function readGlobalAgentsFile(): { path: string; content: string } | null {
103
113
  const dir = resolveGlobalAgentsDir()
@@ -149,7 +159,7 @@ function readConfig(dataDir: string): {
149
159
  }
150
160
  // Merge defensively — every field has its own default.
151
161
  // replace 字段仅防御性解析保持 config 结构完整,不参与本 hook 逻辑——
152
- // replace 走 --system-prompt CLI(ADR-0038),hook 只处理 append。
162
+ // replace 走 --system-prompt CLI(ADR-0044),hook 只处理 append。
153
163
  return {
154
164
  version: typeof parsed.version === 'number' ? parsed.version : 1,
155
165
  replace: readSection(parsed.replace),
@@ -219,13 +229,19 @@ function buildSystemPrompt(event: BeforeAgentStartEvent): { systemPrompt: string
219
229
  return newPrompt === event.systemPrompt ? undefined : { systemPrompt: newPrompt }
220
230
  }
221
231
 
222
- /** 落盘诊断(pi stderr 经 rpc-client 写入 logs/pi-*.jsonl),不泄露配置内容。 */
232
+ /**
233
+ * 落盘诊断,不泄露配置内容。
234
+ *
235
+ * 通道:extension-logger 的 error → appendEntry 写入 session JSONL(需 setPiHandle
236
+ * 注入 pi handle 后生效);XYZ_AGENT_DEBUG=1 时另落文件日志。仅当 logger 自身抛错
237
+ * 时才兜底 process.stderr.write(下方 catch),不外泄到 agent loop。
238
+ */
223
239
  function logHookFailure(err: unknown): void {
224
240
  try {
225
241
  const msg = err instanceof Error ? `${err.name}: ${err.message}` : String(err)
226
242
  logger.error(`before_agent_start hook failed: ${msg}`)
227
243
  } catch (nestedErr) {
228
- // best-effort:stderr 写失败的终极兜底——console 内部吞错不会抛,仍不外泄到 agent loop。
244
+ // best-effort:logger 抛错时的终极兜底 process.stderr.write——其内部吞错不会抛,仍不外泄到 agent loop。
229
245
  try {
230
246
  process.stderr.write(`[xyz-system-prompt-extension] logHookFailure also failed: ${String(nestedErr)}\n`)
231
247
  } catch (finalErr) {