@zhushanwen/pi-msg-id-mapper 1.0.2 → 1.0.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 +4 -1
- package/src/__tests__/msg-id-mapper.test.ts +15 -7
- package/src/index.ts +6 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-msg-id-mapper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Client UUID ↔ user entry ID mapping extension for Pi — enables metadata preservation across sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"@vitest/coverage-v8": "^4.1.9",
|
|
33
33
|
"vitest": "^4.1.8"
|
|
34
34
|
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@zhushanwen/pi-extension-logger": "0.3.0"
|
|
37
|
+
},
|
|
35
38
|
"scripts": {
|
|
36
39
|
"typecheck": "npx tsc --noEmit",
|
|
37
40
|
"test": "vitest run"
|
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
* 运行:cd extensions/taiji/msg-id-mapper && npx vitest run
|
|
15
15
|
*/
|
|
16
16
|
import { describe, it, expect, vi, afterEach } from 'vitest'
|
|
17
|
+
const { loggerMock } = vi.hoisted(() => ({
|
|
18
|
+
loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
19
|
+
}))
|
|
20
|
+
vi.mock('@zhushanwen/pi-extension-logger', () => ({
|
|
21
|
+
getLogger: () => loggerMock,
|
|
22
|
+
createLogger: () => loggerMock,
|
|
23
|
+
}))
|
|
24
|
+
|
|
17
25
|
import createMapper from '../index'
|
|
18
26
|
import type {
|
|
19
27
|
ExtensionAPI,
|
|
@@ -147,12 +155,12 @@ describe('input hook · clientUuid 提取(extractClientUuid)', () => {
|
|
|
147
155
|
|
|
148
156
|
it('畸形 event(handler 内抛错)→ 兜底 return undefined 不外抛(console.error 可观测)', () => {
|
|
149
157
|
const h = createHarness()
|
|
150
|
-
const errSpy =
|
|
158
|
+
const errSpy = loggerMock.error
|
|
151
159
|
// event 为 null → 取 event.source 即 throw,走 catch 兜底
|
|
152
160
|
expect(h.inputRaw(null)).toBeUndefined()
|
|
153
161
|
expect(errSpy).toHaveBeenCalledWith(
|
|
154
|
-
'
|
|
155
|
-
expect.
|
|
162
|
+
'input hook error',
|
|
163
|
+
{ detail: expect.stringContaining('TypeError') },
|
|
156
164
|
)
|
|
157
165
|
})
|
|
158
166
|
})
|
|
@@ -240,7 +248,7 @@ describe('flush · 映射写入 / 幂等 / 重试 / 异常兜底(writeMapping
|
|
|
240
248
|
|
|
241
249
|
it('appendEntry 抛错 → flush 吞错不外抛,flag 未清,下次 hook 幂等重试', () => {
|
|
242
250
|
const h = createHarness()
|
|
243
|
-
const errSpy =
|
|
251
|
+
const errSpy = loggerMock.error
|
|
244
252
|
h.appendEntry.mockImplementation(() => {
|
|
245
253
|
throw new Error('jsonl write failed')
|
|
246
254
|
})
|
|
@@ -248,7 +256,7 @@ describe('flush · 映射写入 / 幂等 / 重试 / 异常兜底(writeMapping
|
|
|
248
256
|
h.input(`task ${marker(UUID)}`)
|
|
249
257
|
h.messageEnd('user')
|
|
250
258
|
expect(() => h.flush('message_start')).not.toThrow()
|
|
251
|
-
expect(errSpy).toHaveBeenCalledWith('
|
|
259
|
+
expect(errSpy).toHaveBeenCalledWith('flush error', { detail: expect.stringContaining('jsonl write failed') })
|
|
252
260
|
|
|
253
261
|
// 重试成功:appendEntry 恢复 → turn_end 补写(flag 未清的幂等重试语义)
|
|
254
262
|
h.appendEntry.mockImplementation(() => {})
|
|
@@ -258,7 +266,7 @@ describe('flush · 映射写入 / 幂等 / 重试 / 异常兜底(writeMapping
|
|
|
258
266
|
|
|
259
267
|
it('getLeafId 抛错 → flush 吞错不外抛(catch 兜底覆盖 writeMapping 全程)', () => {
|
|
260
268
|
const h = createHarness()
|
|
261
|
-
const errSpy =
|
|
269
|
+
const errSpy = loggerMock.error
|
|
262
270
|
h.input(`task ${marker(UUID)}`)
|
|
263
271
|
h.messageEnd('user')
|
|
264
272
|
|
|
@@ -267,7 +275,7 @@ describe('flush · 映射写入 / 幂等 / 重试 / 异常兜底(writeMapping
|
|
|
267
275
|
throw new Error('session manager gone')
|
|
268
276
|
}),
|
|
269
277
|
).not.toThrow()
|
|
270
|
-
expect(errSpy).toHaveBeenCalledWith('
|
|
278
|
+
expect(errSpy).toHaveBeenCalledWith('flush error', { detail: expect.stringContaining('session manager gone') })
|
|
271
279
|
})
|
|
272
280
|
|
|
273
281
|
it('无 user message_end(未置 flag)→ 三重安全网全不写', () => {
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
import type { ExtensionAPI, ExtensionContext, InputEvent, MessageEndEvent, MessageStartEvent, TurnEndEvent, AgentEndEvent } from '@earendil-works/pi-coding-agent'
|
|
32
|
+
import { getLogger } from '@zhushanwen/pi-extension-logger'
|
|
33
|
+
|
|
34
|
+
const logger = getLogger('xyz-client-msg-id-mapper')
|
|
32
35
|
|
|
33
36
|
// uuid = appendUser 生成的 user message id(`u-` + 36 字符 hex uuid,共 38 字符)。
|
|
34
37
|
// 与 shared SegmentsMetadataEntry.clientUuid 严格一致(同 appendUser 返回值):
|
|
@@ -67,7 +70,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
67
70
|
return { action: 'transform' as const, text: event.text.replace(TAG_STRIP, '').trimEnd() }
|
|
68
71
|
} catch (err) {
|
|
69
72
|
// 吞错,不阻断主流程(pi runner 也会 try/catch,但显式兜底避免意外 return)。
|
|
70
|
-
|
|
73
|
+
logger.error('input hook error', { detail: String(err) })
|
|
71
74
|
return undefined
|
|
72
75
|
}
|
|
73
76
|
})
|
|
@@ -81,7 +84,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
81
84
|
}
|
|
82
85
|
} catch (err) {
|
|
83
86
|
// best-effort:置 flag 失败不阻断消息流——仅丢失该条 clientUuid↔entryId 映射,对话不受影响。
|
|
84
|
-
|
|
87
|
+
logger.error('message_end hook error', { detail: String(err) })
|
|
85
88
|
}
|
|
86
89
|
return undefined
|
|
87
90
|
})
|
|
@@ -109,7 +112,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
109
112
|
writeMapping(ctx)
|
|
110
113
|
} catch (err) {
|
|
111
114
|
// best-effort:映射写入失败不阻断消息流——丢的是本条映射,下次 hook 会因 flag 未清而幂等重试。
|
|
112
|
-
|
|
115
|
+
logger.error('flush error', { detail: String(err) })
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
118
|
|