@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 +2 -2
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/index.ts +25 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-system-prompt",
|
|
3
|
-
"version": "1.1.
|
|
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.
|
|
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
|
-
* 终极兜底
|
|
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
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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
|
-
/**
|
|
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 (
|
|
100
|
-
*
|
|
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-
|
|
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
|
-
/**
|
|
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:
|
|
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) {
|