@zhushanwen/pi-smart-context 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/README.md +1 -1
- package/package.json +3 -3
- package/src/__tests__/index-generation.test.ts +1 -1
- package/src/__tests__/sdk-contract.test.ts +1 -1
- package/src/compact-handler.ts +2 -2
- package/src/index.ts +4 -4
- package/src/llm.ts +3 -3
- package/src/notices.ts +3 -3
- package/src/tool.ts +4 -4
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
- cross-model:调用 pi 原生 `compact()` 仅换模型与凭证——split-turn / fileOps / previousSummary 原生组装
|
|
11
11
|
- **3 档阈值提醒**(默认 400K/500K/600K):`agent_settled` 越档检查,每档一次、多档合并、压缩后重置,nextTurn 投递(随下一次 prompt 注入,不自起 run);已提醒档位经 `pi.appendEntry` 落在 session entries(`smart-context:fired`),reload / 进程重启后从 entries 重建,同一档不会重复提醒;措辞是数据投递不是指令
|
|
12
12
|
- **排除模型**(精准 `provider/modelId` 匹配):工具拒绝 + 不提醒 + 回落 pi 原生生成;切换跨界时注入一条可用性通知,downshift(切小窗模型将触线)时建议先压缩
|
|
13
|
-
- **通知车道**:压缩结果 / 阈值提醒 / 模型切换四类通知统一走 nextTurn(custom role 随下次 prompt 注入,不自起 run)——工具压缩掐断的 turn 由 taiji runtime 在 `compaction_end`
|
|
13
|
+
- **通知车道**:压缩结果 / 阈值提醒 / 模型切换四类通知统一走 nextTurn(custom role 随下次 prompt 注入,不自起 run)——工具压缩掐断的 turn 由 taiji runtime 在 `compaction_end` 判定后经投递内核追加续跑投递
|
|
14
14
|
- **健壮性**:摘要收缩校验、max-tokens 截断 fail-closed、接管失败 3 次熔断(本 session 内停止接管)、transcript 回查指针、压缩后最近文件内容重注入(≤5 文件/50K)、多轮压缩降智提示(累计压缩 ≥2 次后附加)
|
|
15
15
|
- **subagent 进程**自动静默(`TAIJI_AGENT_SUBAGENT` 标记)
|
|
16
16
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-smart-context",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"taiji": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"pi-package"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@zhushanwen/extension-protocol": "0.
|
|
39
|
+
"@zhushanwen/extension-protocol": "0.23.0",
|
|
40
40
|
"@zhushanwen/pi-ext-guards": "0.5.0",
|
|
41
41
|
"@zhushanwen/pi-extension-logger": "0.6.2",
|
|
42
|
-
"@zhushanwen/pi-llm-shared": "0.
|
|
42
|
+
"@zhushanwen/pi-llm-shared": "0.12.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@vitest/coverage-v8": "^4.1.9",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// wrapper(() => isCtxStale())——registerCompactContextTool 在 factory 体同步执行,简写
|
|
6
6
|
// 属性 { isCtxStale } 会把该行时刻的初始 () => false 快照进 deps 对象,session_start
|
|
7
7
|
// handler 内的重新赋值不回写已构造对象 → compact onComplete/onError(E1 实锤崩溃点)
|
|
8
|
-
//
|
|
8
|
+
// 检查的前置代际检查恒不生效,stale 分诊 100% 退化为 PS-30 文案兜底。
|
|
9
9
|
//
|
|
10
10
|
// 可区分快照 vs live 的唯一拓扑是 factory 重跑(生产主路径:pi 每次 session 替换
|
|
11
11
|
// newSession/fork/switchSession 都重跑 factory 函数体,loader.ts extensionCache 只缓存
|
|
@@ -31,7 +31,7 @@ describe("pi SDK 契约(compact 接管路径依赖的导出形状)", () => {
|
|
|
31
31
|
];
|
|
32
32
|
const ctx = buildSessionContext(entries as never);
|
|
33
33
|
expect(Array.isArray(ctx.messages)).toBe(true);
|
|
34
|
-
// compaction entry
|
|
34
|
+
// compaction entry 派生为一条消息 + 保留段消息(旧摘要在前缀中,D12 same-mode 前提)
|
|
35
35
|
expect(ctx.messages.length).toBeGreaterThanOrEqual(2);
|
|
36
36
|
});
|
|
37
37
|
|
package/src/compact-handler.ts
CHANGED
|
@@ -83,7 +83,7 @@ interface SessionManagerSessionFileLike {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* sessionManager
|
|
86
|
+
* sessionManager 会话文件访问形状的运行时检查(D13-4):
|
|
87
87
|
* 只收窄到对象(字段存在性/类型由消费侧可选链 + ?? 兜底,与原语义一致)。
|
|
88
88
|
*/
|
|
89
89
|
function isSessionManagerSessionFileLike(sm: unknown): sm is SessionManagerSessionFileLike {
|
|
@@ -95,7 +95,7 @@ function isSessionManagerSessionFileLike(sm: unknown): sm is SessionManagerSessi
|
|
|
95
95
|
* getSessionFile 若不可得则返回空串(指针省略,不失败)。
|
|
96
96
|
*/
|
|
97
97
|
function getSessionFilePath(ctx: ExtensionContext): string {
|
|
98
|
-
// 经 unknown
|
|
98
|
+
// 经 unknown 再检查:sessionFile 是 sessionManager 的类型未暴露字段(宽于其声明)
|
|
99
99
|
const sm: unknown = ctx.sessionManager;
|
|
100
100
|
const accessor = isSessionManagerSessionFileLike(sm) ? sm : undefined;
|
|
101
101
|
try {
|
package/src/index.ts
CHANGED
|
@@ -150,7 +150,7 @@ export default function smartContextExtension(pi: ExtensionAPI): void {
|
|
|
150
150
|
// isCtxStale 必须传 live 绑定 wrapper 而非简写属性:本行在 factory 体同步执行,简写
|
|
151
151
|
// { isCtxStale } 会把此刻的初始 () => false 快照进 deps 对象,上方 session_start
|
|
152
152
|
// handler 的重新赋值不回写已构造对象 → compact onComplete/onError(E1 实锤崩溃点)
|
|
153
|
-
//
|
|
153
|
+
// 检查的前置代际检查恒不生效。wrapper 每次调用读闭包当前绑定。
|
|
154
154
|
registerCompactContextTool(pi, { isCtxStale: () => isCtxStale() });
|
|
155
155
|
|
|
156
156
|
// ── 阈值提醒(D3/D4):agent_settled 越档检查 + marker 持久化 + nextTurn 一次性投递 ──
|
|
@@ -184,7 +184,7 @@ export default function smartContextExtension(pi: ExtensionAPI): void {
|
|
|
184
184
|
// 会在 agent 空闲后自起一个提醒 run,与用户消息同抢 prompt 跑道(故事 C 的三重放大器之一)。
|
|
185
185
|
// 防循环:crossed 全部已标记 fired,marker 与提醒触发的 settled 不会重复发。
|
|
186
186
|
// 事件回调内直接调用捕获的 pi——session 替换窗口可能 stale(crash-resilience D1
|
|
187
|
-
//
|
|
187
|
+
// 普查接入点),检查 stale 静默降级(不杀 pi 进程),非 stale 错误原样上抛。
|
|
188
188
|
guardStaleCtx(() => {
|
|
189
189
|
sendSmartContextNotice(pi, message, "threshold-reminder");
|
|
190
190
|
}, {
|
|
@@ -211,7 +211,7 @@ export default function smartContextExtension(pi: ExtensionAPI): void {
|
|
|
211
211
|
debugLog(`switch notice: ${nowExcluded ? "unavailable" : "available"} (${modelId})`);
|
|
212
212
|
// 状态通知(非紧急):triggerTurn:false 不唤醒轮次——LLM 在下一轮自然看到并自行
|
|
213
213
|
// 调整(compact 工具 execute 有运行时门控校验兜底),不为通知烧一整轮全量上下文。
|
|
214
|
-
// session 替换窗口可能 stale(D1
|
|
214
|
+
// session 替换窗口可能 stale(D1 普查接入点)——检查 stale 静默降级
|
|
215
215
|
guardStaleCtx(() => {
|
|
216
216
|
sendSmartContextNotice(pi, notice, "model-switch");
|
|
217
217
|
}, {
|
|
@@ -232,7 +232,7 @@ export default function smartContextExtension(pi: ExtensionAPI): void {
|
|
|
232
232
|
if (downshift && isGatingActive(config, modelId)) {
|
|
233
233
|
debugLog("downshift notice fired");
|
|
234
234
|
// "建议"非紧急(同 S1 裁决):triggerTurn:false 不唤醒轮次,用户继续对话时
|
|
235
|
-
// LLM 自行决策是否先压缩。session 替换窗口可能 stale(D1
|
|
235
|
+
// LLM 自行决策是否先压缩。session 替换窗口可能 stale(D1 普查接入点)——检查 stale 静默降级
|
|
236
236
|
guardStaleCtx(() => {
|
|
237
237
|
sendSmartContextNotice(pi, downshift, "model-downshift");
|
|
238
238
|
}, {
|
package/src/llm.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type { ExtensionContext, ToolInfo } from "@earendil-works/pi-coding-agent
|
|
|
17
17
|
import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* ToolInfo → pi-ai Tool
|
|
20
|
+
* ToolInfo → pi-ai Tool 派生视图:三字段直取。parameters 是 typebox schema(主会话同源对象,
|
|
21
21
|
* 序列化后与主请求一致——缓存对齐的关键是不改造、原样透传)。
|
|
22
22
|
*/
|
|
23
23
|
export function projectTools(toolInfos: readonly ToolInfo[]): LlmTool[] {
|
|
@@ -67,11 +67,11 @@ export interface SameModelCallOptions {
|
|
|
67
67
|
systemPrompt: string;
|
|
68
68
|
/** 完整上下文 messages + 末尾已追加的压缩指令 message。 */
|
|
69
69
|
messages: Message[];
|
|
70
|
-
/**
|
|
70
|
+
/** 主会话工具派生视图(缓存对齐)。 */
|
|
71
71
|
tools: LlmTool[];
|
|
72
72
|
signal?: AbortSignal;
|
|
73
73
|
sessionId?: string;
|
|
74
|
-
/**
|
|
74
|
+
/** 工具派生视图与 LLM 调用的依赖注入(单测 mock 点)。 */
|
|
75
75
|
deps?: {
|
|
76
76
|
getApiKeyAndHeaders?: (model: Model<never> | Model<string>) => Promise<{ ok: true; apiKey?: string; headers?: Record<string, string>; env?: Record<string, string> } | { ok: false; error: string }>;
|
|
77
77
|
call?: (model: Model<never> | Model<string>, context: LlmContext, options: SimpleStreamOptions) => Promise<SimpleResponseLike>;
|
package/src/notices.ts
CHANGED
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* `Agent is already processing` 拒绝。
|
|
10
10
|
*
|
|
11
11
|
* 语义定性(设计 D4「C-ext-19 合规定性」四类两分):
|
|
12
|
-
* - 阈值提醒 / model_select 两条 = **提醒语义**(与 scheduler 2026-09-15
|
|
12
|
+
* - 阈值提醒 / model_select 两条 = **提醒语义**(与 scheduler 2026-09-15 逐条处理完毕先例同类:
|
|
13
13
|
* 提醒不承载必须必达的结果);
|
|
14
14
|
* - 压缩结果 onComplete / onError = **结果语义**,本改造是**存量域内改判而非新建
|
|
15
15
|
* at-most-once 通道**:原 steer 通道即 at-most-once 且自起 run,nextTurn 化后必达性
|
|
16
|
-
*
|
|
17
|
-
* pi-boundary-reliability 附录 B
|
|
16
|
+
* (常驻至被消费)与运行侧(不自起 run)同时持平或改善;账本化正向要求的完整迁移维持
|
|
17
|
+
* pi-boundary-reliability 附录 B 挂着不处理不变(设计 §1.3 Out)。
|
|
18
18
|
*
|
|
19
19
|
* 已接受代价(设计 D4 四要素):阈值提醒不再于 agent 空闲时立即生效,改为随用户下一条消息
|
|
20
20
|
* 注入——pi 内建 overflow/threshold 自动压缩兜底在场,无人在场时上下文可能持续增长。
|
package/src/tool.ts
CHANGED
|
@@ -125,7 +125,7 @@ export function registerCompactContextTool(
|
|
|
125
125
|
* G1 代际检测(crash-resilience D1):compact 是 fire-and-forget——onComplete/onError
|
|
126
126
|
* 回调在压缩 LLM 调用期间异步触发,用户此间切换/重载 session 后回调持有的 pi 已
|
|
127
127
|
* stale(E1 实锤崩溃点)。index.ts 注入模块级代数比对闭包,前置检查 + 错误分诊
|
|
128
|
-
*
|
|
128
|
+
* 双保险;缺省时检查退化为纯文案兜底分诊(PS-30 门禁守文案)。
|
|
129
129
|
*/
|
|
130
130
|
isCtxStale?: () => boolean;
|
|
131
131
|
},
|
|
@@ -192,8 +192,8 @@ export function registerCompactContextTool(
|
|
|
192
192
|
// session/新建/重载高频触发)下 sendMessage 命中 stale ctx 同步抛错即
|
|
193
193
|
// 杀死 pi 进程(pi 1.0.0 实装:dist/core/extensions/loader.js 的 assertActive
|
|
194
194
|
// wrapper 对 stale 即 throw "no longer active",在 runtime 调用前同步 throw)。
|
|
195
|
-
//
|
|
196
|
-
// stale
|
|
195
|
+
// 检查 stale 静默降级(结果不投递,用户可重试 /compact),非
|
|
196
|
+
// stale 错误原样上抛(检查不吞真实 bug)。
|
|
197
197
|
onComplete: (r: unknown) => {
|
|
198
198
|
guardStaleCtx(() => {
|
|
199
199
|
const result = toCompactionResultLike(r);
|
|
@@ -218,7 +218,7 @@ export function registerCompactContextTool(
|
|
|
218
218
|
});
|
|
219
219
|
},
|
|
220
220
|
onError: (err: Error) => {
|
|
221
|
-
//
|
|
221
|
+
// 压缩本身的失败信息先落日志(检查体外——stale 降级时该观测保留)
|
|
222
222
|
debugLog(`compact_context error: ${err.message}`);
|
|
223
223
|
guardStaleCtx(() => {
|
|
224
224
|
sendSmartContextNotice(
|