@zhushanwen/pi-session-reader 0.5.1 → 0.6.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.
@@ -1,7 +1,7 @@
1
1
  import type { AutocompleteItem } from '@earendil-works/pi-tui'
2
2
  import type { ExtensionCommandContext } from '@earendil-works/pi-coding-agent'
3
3
  import { SessionManager, type SessionInfo } from '@earendil-works/pi-coding-agent'
4
- import { toCandidate } from './hash-provider.js'
4
+ import { toCandidate, DEFAULT_LIMIT } from './hash-provider.js'
5
5
 
6
6
  /**
7
7
  * M4 TUI 层:/session-pick 命令(design 附录 P-hash-trigger 降级兜底 + 非 # 场景入口)。
@@ -21,13 +21,12 @@ import { toCandidate } from './hash-provider.js'
21
21
  * cwdSessionDir 注入(同 hash-provider,零 pi 依赖核心逻辑,可单测)。
22
22
  */
23
23
 
24
- /** /session-pick 列表上限(对齐 # 弹窗 DEFAULT_LIMIT,design G6)。 */
25
- const PICK_LIMIT = 10
26
-
27
24
  /** label 追加的短 uuid 长度(uuid v7 时间前缀,同目录同毫秒创建概率可忽略,消歧足够)。 */
28
25
  const SHORT_UUID_LEN = 8
29
26
 
30
- /** /session-pick 命令配置(Omit<RegisteredCommand, 'name' | 'sourceInfo'>)。 */
27
+ /** /session-pick 命令配置:返回结构类型(description + 参数补全 + handler),
28
+ * 形态等价于 RegisteredCommand 减 name/sourceInfo(这两项由 pi 注册方提供),
29
+ * 按仓内现状写为内联类型而非 Omit<>。 */
31
30
  export function createSessionCommand(
32
31
  getCwdSessionDir: () => string,
33
32
  ): {
@@ -39,11 +38,16 @@ export function createSessionCommand(
39
38
  description: 'Pick a session and insert a #uuid reference into the editor.',
40
39
  async getArgumentCompletions(argumentPrefix) {
41
40
  const trimmed = argumentPrefix.trim()
42
- const all = await SessionManager.listAll(getCwdSessionDir())
41
+ // 目录未就绪(无 live session 上下文,getCwdSessionDir 返回空串)→ 空手返回,绝不调
42
+ // listAll('')——pi 的 listAll 对空字符串 falsy 走默认全盘分支(3488 项 / ~8s,会让补全
43
+ // 卡死;同款 guard 见 hash-provider provideHashCandidates)
44
+ const cwdSessionDir = getCwdSessionDir()
45
+ if (!cwdSessionDir) return null
46
+ const all = await SessionManager.listAll(cwdSessionDir)
43
47
  // uuid 片段过滤(与 # 弹窗一致);空 prefix → recent(listAll 已按 modified 倒序)
44
48
  const filtered =
45
49
  trimmed === '' ? all : all.filter((s) => s.id.includes(trimmed))
46
- const top = filtered.slice(0, PICK_LIMIT)
50
+ const top = filtered.slice(0, DEFAULT_LIMIT)
47
51
  if (top.length === 0) return null
48
52
  // value 用完整 uuid(剥 # 后,命令参数位置不带 #)
49
53
  return top.map((s) => {
@@ -53,10 +57,17 @@ export function createSessionCommand(
53
57
  },
54
58
  async handler(args, ctx) {
55
59
  const trimmed = args.trim()
56
- const all = await SessionManager.listAll(getCwdSessionDir())
60
+ // 同 getArgumentCompletions 的空串 guard:无 live session 上下文时按零匹配处理,
61
+ // 不触发 listAll 全盘分支
62
+ const cwdSessionDir = getCwdSessionDir()
63
+ if (!cwdSessionDir) {
64
+ ctx.ui.notify('未找到匹配的 session。', 'warning')
65
+ return
66
+ }
67
+ const all = await SessionManager.listAll(cwdSessionDir)
57
68
  const filtered =
58
69
  trimmed === '' ? all : all.filter((s) => s.id.includes(trimmed))
59
- const top = filtered.slice(0, PICK_LIMIT)
70
+ const top = filtered.slice(0, DEFAULT_LIMIT)
60
71
  if (top.length === 0) {
61
72
  ctx.ui.notify('未找到匹配的 session。', 'warning')
62
73
  return
@@ -65,8 +76,9 @@ export function createSessionCommand(
65
76
  const labels = top.map((s) => formatSessionLabel(s))
66
77
  const chosen = await ctx.ui.select('选择一个 session 插入 # 引用', labels)
67
78
  if (chosen === undefined) return
79
+ // chosen 必属 labels(select 契约返回列表成员或 undefined,后者上一行已拦截),
80
+ // indexOf 恒命中——不再保留 idx<0 死防御分支
68
81
  const idx = labels.indexOf(chosen)
69
- if (idx < 0) return
70
82
  // 选中后插入 # + 完整 uuid(剥 # 算片段,再补 # 插入编辑器)
71
83
  const frag = toCandidate(top[idx]).insertText.slice(1)
72
84
  // /session-pick 提交后编辑器已清空,直接 set # uuid 供用户补完指令再发送;