@zhushanwen/pi-session-reader 0.11.0 → 0.12.0
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 +5 -5
- package/src/__tests__/cross-package-subagent-core.test.ts +34 -25
- package/src/__tests__/entry-anchor.test.ts +3 -3
- package/src/__tests__/execution-tree.test.ts +85 -86
- package/src/__tests__/family-zcode.test.ts +24 -14
- package/src/__tests__/family.test.ts +4 -4
- package/src/__tests__/find.test.ts +50 -5
- package/src/__tests__/index.test.ts +3 -3
- package/src/__tests__/rebuild-manifest-dual-write.test.ts +29 -22
- package/src/__tests__/render.test.ts +2 -2
- package/src/__tests__/result.test.ts +20 -11
- package/src/__tests__/roots.test.ts +64 -26
- package/src/__tests__/subagents.test.ts +108 -52
- package/src/__tests__/tool-handler.test.ts +133 -83
- package/src/__tests__/workflow.test.ts +5 -5
- package/src/__tests__/zcode-manifest.test.ts +18 -10
- package/src/__tests__/zcode-routing.test.ts +21 -19
- package/src/__tests__/zcode-whitelist.test.ts +1 -1
- package/src/core/family.ts +6 -6
- package/src/core/render.ts +2 -2
- package/src/core/toolcall.ts +1 -1
- package/src/core/workflow.ts +9 -9
- package/src/discovery/entry-anchor.ts +5 -5
- package/src/discovery/find.ts +9 -1
- package/src/discovery/roots.ts +95 -7
- package/src/discovery/subagents.ts +24 -17
- package/src/discovery/whitelist.ts +4 -4
- package/src/discovery/workflows.ts +8 -8
- package/src/discovery/zcode-manifest.ts +22 -27
- package/src/extract.ts +1 -1
- package/src/index.ts +2 -2
- package/src/no-match.ts +1 -1
- package/src/result-action.ts +1 -1
- package/src/search-across.ts +3 -3
- package/src/tool-format.ts +12 -12
- package/src/tool-handler.ts +27 -19
- package/src/tui/session-command.ts +1 -1
- package/src/zcode-anchor-classify.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-session-reader",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"taiji": {
|
|
@@ -16,16 +16,16 @@
|
|
|
16
16
|
"pi-package"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@zhushanwen/extension-protocol": "0.
|
|
19
|
+
"@zhushanwen/extension-protocol": "0.22.0",
|
|
20
20
|
"@zhushanwen/pi-ext-guards": "0.5.0",
|
|
21
21
|
"@zhushanwen/pi-extension-logger": "0.6.2",
|
|
22
|
-
"@zhushanwen/
|
|
23
|
-
"@zhushanwen/session-
|
|
22
|
+
"@zhushanwen/session-core": "0.12.0",
|
|
23
|
+
"@zhushanwen/zcode-session-source": "0.2.7"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@vitest/coverage-v8": "^4.1.9",
|
|
27
27
|
"vitest": "^4.1.8",
|
|
28
|
-
"@zhushanwen/subagent-core": "1.
|
|
28
|
+
"@zhushanwen/subagent-core": "1.6.0"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"index.ts",
|
|
@@ -21,16 +21,16 @@ import {
|
|
|
21
21
|
} from '@zhushanwen/subagent-core/execution/assembly/path-encoding.ts'
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* W4 跨包集成测试([collect 退役] 改造保留:原「E1 落标出口产出 manifest
|
|
25
|
-
* 随 sync
|
|
26
|
-
* 是可丢缓存,boot
|
|
24
|
+
* W4 跨包集成测试([collect 退役] 改造保留:原「E1 落标出口产出 manifest」驱动侧
|
|
25
|
+
* 随 sync 批机制删除,现行真实派生视图出口 = store 重建通道 rebuildIndexes——manifest
|
|
26
|
+
* 是可丢缓存,boot 全量路径按磁盘子文件锚幂等补缺)。「subagent-core 真实 tmpdir
|
|
27
27
|
* 产出磁盘状态 → session-reader result action sa- id 反查,不 mock manifest 写入」
|
|
28
28
|
* 的跨包契约保持不变。
|
|
29
29
|
*
|
|
30
30
|
* 与 result.test.ts 的分工:result.test.ts 的 fixture **手工预写** manifest;本文件
|
|
31
|
-
* manifest
|
|
31
|
+
* manifest 内容必须来自派生视图代码路径——subagent-core 侧真实驱动(真实 RecordStore
|
|
32
32
|
* 落盘 register/轮终 entry → initSession 内 orphan 覆写真实跑 → rebuildIndexes
|
|
33
|
-
* derivedManifestRecord
|
|
33
|
+
* derivedManifestRecord 派生视图真写 records/<sa-id>.json),session-reader 侧零 mock
|
|
34
34
|
* 读同一 tmpdir 断言反查闭环。
|
|
35
35
|
*
|
|
36
36
|
* 构造形态取自 subagent-core sync-collect-recovery.test.ts 的 kill -9 同构主用例
|
|
@@ -42,17 +42,14 @@ import {
|
|
|
42
42
|
* mkdtemp(tmpdir) 自建自删(红线:零真实数据目录触碰)。
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
45
|
+
/** 剥身份 env(subagent-core 测试纪律同款):身份 env 会让 service 误判自己是
|
|
46
|
+
* 子进程跳过恢复扫描。 */
|
|
47
47
|
const ENV_KEYS_TO_STRIP = [
|
|
48
48
|
'PI_SUBAGENT_ROOT_SESSION_ID',
|
|
49
49
|
'PI_SUBAGENT_SELF_RECORD_ID',
|
|
50
50
|
'PI_SUBAGENT_DEPTH',
|
|
51
51
|
'PI_SUBAGENT_ROOT_CWD',
|
|
52
52
|
'PI_SUBAGENT_FORK_DEPTH',
|
|
53
|
-
'TAIJI_SUBAGENT_RELAY_SOCKET',
|
|
54
|
-
'TAIJI_SUBAGENT_RELAY_NODE',
|
|
55
|
-
'TAIJI_SUBAGENT_RELAY_SCRIPT',
|
|
56
53
|
] as const
|
|
57
54
|
|
|
58
55
|
const ROOT_SESSION = 'root-cross-pkg'
|
|
@@ -119,30 +116,42 @@ interface MemberSeed {
|
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
describe('跨包集成:subagent-core 重建 manifest → session-reader result 反查(W4)', () => {
|
|
119
|
+
let dataDir: string
|
|
122
120
|
let agentDir: string
|
|
123
121
|
let mainFile: string
|
|
124
122
|
let services: SubagentService[]
|
|
125
123
|
|
|
126
124
|
beforeEach(() => {
|
|
127
125
|
for (const k of ENV_KEYS_TO_STRIP) delete process.env[k]
|
|
128
|
-
agentDir =
|
|
129
|
-
|
|
126
|
+
// 生产拓扑复刻([session-store-layout-inversion 域 9]):agentDir = <dataDir>/agent
|
|
127
|
+
//(session-reader 的 agentDir 语义),subagent-core 写侧经新公式落存储树
|
|
128
|
+
// <dataDir>/ext-sessions/<rootSid>/subagents/——listRecordManifests 双根扫描的新根
|
|
129
|
+
//(dirname(agentDir)/ext-sessions)与写侧落点相遇
|
|
130
|
+
dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cross-pkg-subagent-core-'))
|
|
131
|
+
agentDir = path.join(dataDir, 'agent')
|
|
132
|
+
fs.mkdirSync(agentDir, { recursive: true })
|
|
133
|
+
fs.mkdirSync(getSubagentSessionDir(ROOT_SESSION, dataDir), { recursive: true })
|
|
134
|
+
// 恢复 service 的内部 store 经 getSubagentRecordsDir(resolveStoreRootSessionId())
|
|
135
|
+
//(env dataDir 兜底)解析——钉 env 把写删目标收进本 mkdtemp 树(自建自删红线,
|
|
136
|
+
// subagent-core 同族测试先例 subagent-service-model-switch.test.ts)
|
|
137
|
+
process.env['TAIJI_AGENT_DATA_DIR'] = dataDir
|
|
130
138
|
mainFile = path.join(agentDir, 'main-session.jsonl')
|
|
131
139
|
services = []
|
|
132
140
|
})
|
|
133
141
|
|
|
134
142
|
afterEach(() => {
|
|
135
143
|
for (const s of services) s.dispose()
|
|
136
|
-
|
|
144
|
+
delete process.env['TAIJI_AGENT_DATA_DIR']
|
|
145
|
+
fs.rmSync(dataDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 })
|
|
137
146
|
})
|
|
138
147
|
|
|
139
148
|
/** 真实 RecordStore(写文件 pi:种子经真实 register 通路 + v2 条目构造器
|
|
140
149
|
* (toRegisteredEntryData,[v1 兼容层删除] v1 快照写点 toSubagentRecordEntry 已删)
|
|
141
|
-
* 落主文件)。 */
|
|
150
|
+
* 落主文件)。[u-subagent dir 晚绑定] store/manifest 构造 = 目录取值函数。 */
|
|
142
151
|
function makeSeedStore(): RecordStore {
|
|
143
152
|
return new RecordStore(
|
|
144
|
-
getSubagentSessionDir(
|
|
145
|
-
new ManifestStore(getSubagentRecordsDir(
|
|
153
|
+
() => getSubagentSessionDir(ROOT_SESSION, dataDir),
|
|
154
|
+
new ManifestStore(() => getSubagentRecordsDir(ROOT_SESSION, dataDir)),
|
|
146
155
|
makeWritingPi(mainFile),
|
|
147
156
|
)
|
|
148
157
|
}
|
|
@@ -172,7 +181,7 @@ describe('跨包集成:subagent-core 重建 manifest → session-reader result
|
|
|
172
181
|
* 形态同 subagent-core W1 用例)——**不写**三 sidecar,保证恢复走
|
|
173
182
|
* finalizeOrphanRecord 真实路径。 */
|
|
174
183
|
function writeChildSessionFile(m: MemberSeed): string {
|
|
175
|
-
const childFile = path.join(getSubagentSessionDir(
|
|
184
|
+
const childFile = path.join(getSubagentSessionDir(ROOT_SESSION, dataDir), `${m.id}.jsonl`)
|
|
176
185
|
const ts = new Date(1000).toISOString()
|
|
177
186
|
const lines: string[] = [
|
|
178
187
|
JSON.stringify({ type: 'session', version: 3, id: `sess-${m.id}`, timestamp: ts, cwd: agentDir }),
|
|
@@ -202,7 +211,7 @@ describe('跨包集成:subagent-core 重建 manifest → session-reader result
|
|
|
202
211
|
data: { id: m.id, agent: '/agents/worker.md', mode: 'background', task: 'cross-package task', startedAt: 1000, rootSessionId: ROOT_SESSION, depth: 0 },
|
|
203
212
|
}),
|
|
204
213
|
JSON.stringify({
|
|
205
|
-
// 登记 §3.3
|
|
214
|
+
// 登记 §3.3:主/子文件条目范围 = v2 注册条(身份域;运行态事实源在 record 事件文件)。
|
|
206
215
|
type: 'custom', id: `cid-${m.id}-2`, parentId: `cid-${m.id}-1`, timestamp: ts,
|
|
207
216
|
customType: 'subagent-record',
|
|
208
217
|
data: {
|
|
@@ -247,7 +256,7 @@ describe('跨包集成:subagent-core 重建 manifest → session-reader result
|
|
|
247
256
|
}
|
|
248
257
|
|
|
249
258
|
/** 全链路驱动:种子 → 恢复 service(orphan 覆写)→ rebuildIndexes(现行 boot
|
|
250
|
-
* 全量重建通道——derivedManifestRecord
|
|
259
|
+
* 全量重建通道——derivedManifestRecord 派生视图真写 manifest)。返回子 session 文件
|
|
251
260
|
* 路径表。[collect 退役] 原 E1 落标出口(recoverSyncCollectBatch →
|
|
252
261
|
* appendBatchFinalizedEntry)随 sync 批机制删除。 */
|
|
253
262
|
async function driveManifestRebuild(members: MemberSeed[]): Promise<Map<string, string>> {
|
|
@@ -259,11 +268,11 @@ describe('跨包集成:subagent-core 重建 manifest → session-reader result
|
|
|
259
268
|
}
|
|
260
269
|
const service = makeRecoveryService()
|
|
261
270
|
service.rebuildIndexes()
|
|
262
|
-
// derivedManifestRecord
|
|
271
|
+
// derivedManifestRecord 派生视图为同步落盘——全成员 manifest 即刻可见(W3 派生视图
|
|
263
272
|
// 代码路径的产物,非手工预写)。
|
|
264
273
|
for (const m of members) {
|
|
265
274
|
expect(
|
|
266
|
-
fs.existsSync(path.join(getSubagentRecordsDir(
|
|
275
|
+
fs.existsSync(path.join(getSubagentRecordsDir(ROOT_SESSION, dataDir), `${m.id}.json`)),
|
|
267
276
|
`manifest of ${m.id}`,
|
|
268
277
|
).toBe(true)
|
|
269
278
|
}
|
|
@@ -280,12 +289,12 @@ describe('跨包集成:subagent-core 重建 manifest → session-reader result
|
|
|
280
289
|
}
|
|
281
290
|
const childFiles = await driveManifestRebuild([m])
|
|
282
291
|
|
|
283
|
-
// manifest 内容断言(rebuildIndexes → derivedManifestRecord
|
|
284
|
-
// 非手工预写):sessionFile 来自 W1
|
|
285
|
-
// 处于 idle(重建单规则)、无旧终态遗留位 → legacy status
|
|
292
|
+
// manifest 内容断言(rebuildIndexes → derivedManifestRecord 派生视图路径的产物,
|
|
293
|
+
// 非手工预写):sessionFile 来自 W1 派生视图扩展。[U2/U3 两态桥接] 恢复链覆写后成员
|
|
294
|
+
// 处于 idle(重建单规则)、无旧终态遗留位 → legacy status 如实派生 "running"
|
|
286
295
|
//(legacyManifestStatusFields 单点派生,session-reader 视角的活跃成员)。
|
|
287
296
|
const manifest = JSON.parse(
|
|
288
|
-
fs.readFileSync(path.join(getSubagentRecordsDir(
|
|
297
|
+
fs.readFileSync(path.join(getSubagentRecordsDir(ROOT_SESSION, dataDir), 'sa-cross-1.json'), 'utf-8'),
|
|
289
298
|
) as Record<string, unknown>
|
|
290
299
|
expect(manifest).toMatchObject({
|
|
291
300
|
id: 'sa-cross-1',
|
|
@@ -370,13 +370,13 @@ describe('候选文件列表:顺序回退 + 命中即止(越界语义由调
|
|
|
370
370
|
})
|
|
371
371
|
})
|
|
372
372
|
|
|
373
|
-
describe('
|
|
373
|
+
describe('协议字面量漂移检查(跨包契约)', () => {
|
|
374
374
|
it('entry-anchor 本地 customType 字面量 === subagent-core 写侧单源', () => {
|
|
375
|
-
//
|
|
375
|
+
// 源码本地持有磁盘协议字符串(生产依赖范围不引 subagent-core),此处锚定两侧同值
|
|
376
376
|
expect(SUBAGENT_RECORD_CUSTOM_TYPE).toBe('subagent-record')
|
|
377
377
|
})
|
|
378
378
|
|
|
379
|
-
it('entry-anchor 本地 v2 认识版本 === subagent-core
|
|
379
|
+
it('entry-anchor 本地 v2 认识版本 === subagent-core 写侧单源(写侧再升版本本检查先红)', () => {
|
|
380
380
|
expect(SUBAGENT_RECORD_ENTRY_VERSION).toBe(2)
|
|
381
381
|
})
|
|
382
382
|
})
|