@pennixrv/trellis-core 0.6.17

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.
Files changed (218) hide show
  1. package/LICENSE +235 -0
  2. package/dist/channel/api/assert.d.ts +3 -0
  3. package/dist/channel/api/assert.d.ts.map +1 -0
  4. package/dist/channel/api/assert.js +11 -0
  5. package/dist/channel/api/assert.js.map +1 -0
  6. package/dist/channel/api/context.d.ts +21 -0
  7. package/dist/channel/api/context.d.ts.map +1 -0
  8. package/dist/channel/api/context.js +99 -0
  9. package/dist/channel/api/context.js.map +1 -0
  10. package/dist/channel/api/create.d.ts +9 -0
  11. package/dist/channel/api/create.d.ts.map +1 -0
  12. package/dist/channel/api/create.js +104 -0
  13. package/dist/channel/api/create.js.map +1 -0
  14. package/dist/channel/api/inbox.d.ts +51 -0
  15. package/dist/channel/api/inbox.d.ts.map +1 -0
  16. package/dist/channel/api/inbox.js +176 -0
  17. package/dist/channel/api/inbox.js.map +1 -0
  18. package/dist/channel/api/interrupt.d.ts +31 -0
  19. package/dist/channel/api/interrupt.d.ts.map +1 -0
  20. package/dist/channel/api/interrupt.js +102 -0
  21. package/dist/channel/api/interrupt.js.map +1 -0
  22. package/dist/channel/api/post-thread.d.ts +14 -0
  23. package/dist/channel/api/post-thread.d.ts.map +1 -0
  24. package/dist/channel/api/post-thread.js +109 -0
  25. package/dist/channel/api/post-thread.js.map +1 -0
  26. package/dist/channel/api/read.d.ts +17 -0
  27. package/dist/channel/api/read.d.ts.map +1 -0
  28. package/dist/channel/api/read.js +44 -0
  29. package/dist/channel/api/read.js.map +1 -0
  30. package/dist/channel/api/resolve.d.ts +21 -0
  31. package/dist/channel/api/resolve.d.ts.map +1 -0
  32. package/dist/channel/api/resolve.js +28 -0
  33. package/dist/channel/api/resolve.js.map +1 -0
  34. package/dist/channel/api/runtime.d.ts +70 -0
  35. package/dist/channel/api/runtime.d.ts.map +1 -0
  36. package/dist/channel/api/runtime.js +11 -0
  37. package/dist/channel/api/runtime.js.map +1 -0
  38. package/dist/channel/api/send.d.ts +4 -0
  39. package/dist/channel/api/send.d.ts.map +1 -0
  40. package/dist/channel/api/send.js +52 -0
  41. package/dist/channel/api/send.js.map +1 -0
  42. package/dist/channel/api/spawn.d.ts +13 -0
  43. package/dist/channel/api/spawn.d.ts.map +1 -0
  44. package/dist/channel/api/spawn.js +74 -0
  45. package/dist/channel/api/spawn.js.map +1 -0
  46. package/dist/channel/api/title.d.ts +5 -0
  47. package/dist/channel/api/title.d.ts.map +1 -0
  48. package/dist/channel/api/title.js +40 -0
  49. package/dist/channel/api/title.js.map +1 -0
  50. package/dist/channel/api/types.d.ts +65 -0
  51. package/dist/channel/api/types.d.ts.map +1 -0
  52. package/dist/channel/api/types.js +2 -0
  53. package/dist/channel/api/types.js.map +1 -0
  54. package/dist/channel/api/watch-channels.d.ts +40 -0
  55. package/dist/channel/api/watch-channels.d.ts.map +1 -0
  56. package/dist/channel/api/watch-channels.js +143 -0
  57. package/dist/channel/api/watch-channels.js.map +1 -0
  58. package/dist/channel/api/watch.d.ts +11 -0
  59. package/dist/channel/api/watch.d.ts.map +1 -0
  60. package/dist/channel/api/watch.js +17 -0
  61. package/dist/channel/api/watch.js.map +1 -0
  62. package/dist/channel/api/workers.d.ts +69 -0
  63. package/dist/channel/api/workers.d.ts.map +1 -0
  64. package/dist/channel/api/workers.js +145 -0
  65. package/dist/channel/api/workers.js.map +1 -0
  66. package/dist/channel/index.d.ts +38 -0
  67. package/dist/channel/index.d.ts.map +1 -0
  68. package/dist/channel/index.js +23 -0
  69. package/dist/channel/index.js.map +1 -0
  70. package/dist/channel/internal/store/channel-metadata.d.ts +23 -0
  71. package/dist/channel/internal/store/channel-metadata.d.ts.map +1 -0
  72. package/dist/channel/internal/store/channel-metadata.js +94 -0
  73. package/dist/channel/internal/store/channel-metadata.js.map +1 -0
  74. package/dist/channel/internal/store/delivery.d.ts +27 -0
  75. package/dist/channel/internal/store/delivery.d.ts.map +1 -0
  76. package/dist/channel/internal/store/delivery.js +37 -0
  77. package/dist/channel/internal/store/delivery.js.map +1 -0
  78. package/dist/channel/internal/store/events.d.ts +215 -0
  79. package/dist/channel/internal/store/events.d.ts.map +1 -0
  80. package/dist/channel/internal/store/events.js +209 -0
  81. package/dist/channel/internal/store/events.js.map +1 -0
  82. package/dist/channel/internal/store/filter.d.ts +21 -0
  83. package/dist/channel/internal/store/filter.d.ts.map +1 -0
  84. package/dist/channel/internal/store/filter.js +75 -0
  85. package/dist/channel/internal/store/filter.js.map +1 -0
  86. package/dist/channel/internal/store/inbox.d.ts +17 -0
  87. package/dist/channel/internal/store/inbox.d.ts.map +1 -0
  88. package/dist/channel/internal/store/inbox.js +30 -0
  89. package/dist/channel/internal/store/inbox.js.map +1 -0
  90. package/dist/channel/internal/store/lock.d.ts +17 -0
  91. package/dist/channel/internal/store/lock.d.ts.map +1 -0
  92. package/dist/channel/internal/store/lock.js +88 -0
  93. package/dist/channel/internal/store/lock.js.map +1 -0
  94. package/dist/channel/internal/store/paths.d.ts +57 -0
  95. package/dist/channel/internal/store/paths.d.ts.map +1 -0
  96. package/dist/channel/internal/store/paths.js +264 -0
  97. package/dist/channel/internal/store/paths.js.map +1 -0
  98. package/dist/channel/internal/store/schema.d.ts +77 -0
  99. package/dist/channel/internal/store/schema.d.ts.map +1 -0
  100. package/dist/channel/internal/store/schema.js +127 -0
  101. package/dist/channel/internal/store/schema.js.map +1 -0
  102. package/dist/channel/internal/store/seq.d.ts +23 -0
  103. package/dist/channel/internal/store/seq.d.ts.map +1 -0
  104. package/dist/channel/internal/store/seq.js +175 -0
  105. package/dist/channel/internal/store/seq.js.map +1 -0
  106. package/dist/channel/internal/store/thread-state.d.ts +37 -0
  107. package/dist/channel/internal/store/thread-state.d.ts.map +1 -0
  108. package/dist/channel/internal/store/thread-state.js +206 -0
  109. package/dist/channel/internal/store/thread-state.js.map +1 -0
  110. package/dist/channel/internal/store/watch.d.ts +10 -0
  111. package/dist/channel/internal/store/watch.d.ts.map +1 -0
  112. package/dist/channel/internal/store/watch.js +129 -0
  113. package/dist/channel/internal/store/watch.js.map +1 -0
  114. package/dist/channel/internal/store/worker-state.d.ts +56 -0
  115. package/dist/channel/internal/store/worker-state.d.ts.map +1 -0
  116. package/dist/channel/internal/store/worker-state.js +220 -0
  117. package/dist/channel/internal/store/worker-state.js.map +1 -0
  118. package/dist/index.d.ts +3 -0
  119. package/dist/index.d.ts.map +1 -0
  120. package/dist/index.js +7 -0
  121. package/dist/index.js.map +1 -0
  122. package/dist/mem/adapters/claude.d.ts +22 -0
  123. package/dist/mem/adapters/claude.d.ts.map +1 -0
  124. package/dist/mem/adapters/claude.js +209 -0
  125. package/dist/mem/adapters/claude.js.map +1 -0
  126. package/dist/mem/adapters/codex.d.ts +55 -0
  127. package/dist/mem/adapters/codex.d.ts.map +1 -0
  128. package/dist/mem/adapters/codex.js +344 -0
  129. package/dist/mem/adapters/codex.js.map +1 -0
  130. package/dist/mem/adapters/grok.d.ts +41 -0
  131. package/dist/mem/adapters/grok.d.ts.map +1 -0
  132. package/dist/mem/adapters/grok.js +202 -0
  133. package/dist/mem/adapters/grok.js.map +1 -0
  134. package/dist/mem/adapters/opencode.d.ts +35 -0
  135. package/dist/mem/adapters/opencode.d.ts.map +1 -0
  136. package/dist/mem/adapters/opencode.js +437 -0
  137. package/dist/mem/adapters/opencode.js.map +1 -0
  138. package/dist/mem/adapters/pi.d.ts +24 -0
  139. package/dist/mem/adapters/pi.d.ts.map +1 -0
  140. package/dist/mem/adapters/pi.js +290 -0
  141. package/dist/mem/adapters/pi.js.map +1 -0
  142. package/dist/mem/adapters/zcode.d.ts +76 -0
  143. package/dist/mem/adapters/zcode.d.ts.map +1 -0
  144. package/dist/mem/adapters/zcode.js +434 -0
  145. package/dist/mem/adapters/zcode.js.map +1 -0
  146. package/dist/mem/context.d.ts +23 -0
  147. package/dist/mem/context.d.ts.map +1 -0
  148. package/dist/mem/context.js +120 -0
  149. package/dist/mem/context.js.map +1 -0
  150. package/dist/mem/dialogue.d.ts +32 -0
  151. package/dist/mem/dialogue.d.ts.map +1 -0
  152. package/dist/mem/dialogue.js +0 -0
  153. package/dist/mem/dialogue.js.map +1 -0
  154. package/dist/mem/filter.d.ts +31 -0
  155. package/dist/mem/filter.d.ts.map +1 -0
  156. package/dist/mem/filter.js +66 -0
  157. package/dist/mem/filter.js.map +1 -0
  158. package/dist/mem/index.d.ts +18 -0
  159. package/dist/mem/index.d.ts.map +1 -0
  160. package/dist/mem/index.js +17 -0
  161. package/dist/mem/index.js.map +1 -0
  162. package/dist/mem/internal/jsonl.d.ts +35 -0
  163. package/dist/mem/internal/jsonl.d.ts.map +1 -0
  164. package/dist/mem/internal/jsonl.js +125 -0
  165. package/dist/mem/internal/jsonl.js.map +1 -0
  166. package/dist/mem/internal/paths.d.ts +67 -0
  167. package/dist/mem/internal/paths.d.ts.map +1 -0
  168. package/dist/mem/internal/paths.js +194 -0
  169. package/dist/mem/internal/paths.js.map +1 -0
  170. package/dist/mem/internal/sqlite-readonly.d.ts +77 -0
  171. package/dist/mem/internal/sqlite-readonly.d.ts.map +1 -0
  172. package/dist/mem/internal/sqlite-readonly.js +797 -0
  173. package/dist/mem/internal/sqlite-readonly.js.map +1 -0
  174. package/dist/mem/phase.d.ts +45 -0
  175. package/dist/mem/phase.d.ts.map +1 -0
  176. package/dist/mem/phase.js +220 -0
  177. package/dist/mem/phase.js.map +1 -0
  178. package/dist/mem/projects.d.ts +13 -0
  179. package/dist/mem/projects.d.ts.map +1 -0
  180. package/dist/mem/projects.js +47 -0
  181. package/dist/mem/projects.js.map +1 -0
  182. package/dist/mem/search.d.ts +39 -0
  183. package/dist/mem/search.d.ts.map +1 -0
  184. package/dist/mem/search.js +133 -0
  185. package/dist/mem/search.js.map +1 -0
  186. package/dist/mem/sessions.d.ts +38 -0
  187. package/dist/mem/sessions.d.ts.map +1 -0
  188. package/dist/mem/sessions.js +318 -0
  189. package/dist/mem/sessions.js.map +1 -0
  190. package/dist/mem/types.d.ts +188 -0
  191. package/dist/mem/types.d.ts.map +1 -0
  192. package/dist/mem/types.js +10 -0
  193. package/dist/mem/types.js.map +1 -0
  194. package/dist/task/index.d.ts +9 -0
  195. package/dist/task/index.d.ts.map +1 -0
  196. package/dist/task/index.js +9 -0
  197. package/dist/task/index.js.map +1 -0
  198. package/dist/task/paths.d.ts +37 -0
  199. package/dist/task/paths.d.ts.map +1 -0
  200. package/dist/task/paths.js +49 -0
  201. package/dist/task/paths.js.map +1 -0
  202. package/dist/task/phase.d.ts +27 -0
  203. package/dist/task/phase.d.ts.map +1 -0
  204. package/dist/task/phase.js +24 -0
  205. package/dist/task/phase.js.map +1 -0
  206. package/dist/task/records.d.ts +39 -0
  207. package/dist/task/records.d.ts.map +1 -0
  208. package/dist/task/records.js +89 -0
  209. package/dist/task/records.js.map +1 -0
  210. package/dist/task/schema.d.ts +77 -0
  211. package/dist/task/schema.d.ts.map +1 -0
  212. package/dist/task/schema.js +220 -0
  213. package/dist/task/schema.js.map +1 -0
  214. package/dist/testing/index.d.ts +2 -0
  215. package/dist/testing/index.d.ts.map +1 -0
  216. package/dist/testing/index.js +4 -0
  217. package/dist/testing/index.js.map +1 -0
  218. package/package.json +78 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Project / time-range / source filters for mem session selection.
3
+ *
4
+ * These primitives belong to mem session filtering only — they are not
5
+ * promoted into a cross-domain `core/internal` until another core subdomain
6
+ * needs exactly the same semantics.
7
+ */
8
+ import type { MemFilter } from "./types.js";
9
+ /** Single-point range check: `since ≤ t ≤ until`. Pass-through when `iso` is
10
+ * undefined or unparseable. Internal-only — session list filtering uses
11
+ * {@link inRangeOverlap}. */
12
+ export declare function inRange(iso: string | undefined, f: MemFilter): boolean;
13
+ /**
14
+ * Interval-overlap range check for sessions with both a start and an end
15
+ * timestamp. A session is kept iff its lifetime `[start, end]` overlaps the
16
+ * query window `[since, until]`.
17
+ *
18
+ * Long / cross-day sessions (created before `--since` but still active inside
19
+ * the window) must survive — single-point `inRange(created, f)` dropped them.
20
+ *
21
+ * Degenerate inputs:
22
+ * - both undefined → pass through (no timestamp = don't filter)
23
+ * - one undefined → fall back to single-point semantics on the other end
24
+ * - unparseable iso → defer to the parsable end (or pass through if both bad)
25
+ */
26
+ export declare function inRangeOverlap(start: string | undefined, end: string | undefined, f: MemFilter): boolean;
27
+ /** True iff `sessionCwd` is within `target` (exact match or descendant
28
+ * directory). When `target` is undefined there is no scoping and everything
29
+ * matches; sessions with an unknown cwd are dropped under scoping. */
30
+ export declare function sameProject(sessionCwd: string | undefined, target: string | undefined): boolean;
31
+ //# sourceMappingURL=filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/mem/filter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;6BAE6B;AAC7B,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,OAAO,CAOtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,CAAC,EAAE,SAAS,GACX,OAAO,CAaT;AAED;;sEAEsE;AACtE,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,OAAO,CAMT"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Project / time-range / source filters for mem session selection.
3
+ *
4
+ * These primitives belong to mem session filtering only — they are not
5
+ * promoted into a cross-domain `core/internal` until another core subdomain
6
+ * needs exactly the same semantics.
7
+ */
8
+ import * as path from "node:path";
9
+ /** Single-point range check: `since ≤ t ≤ until`. Pass-through when `iso` is
10
+ * undefined or unparseable. Internal-only — session list filtering uses
11
+ * {@link inRangeOverlap}. */
12
+ export function inRange(iso, f) {
13
+ if (!iso)
14
+ return true;
15
+ const t = new Date(iso);
16
+ if (Number.isNaN(+t))
17
+ return true;
18
+ if (f.since && t < f.since)
19
+ return false;
20
+ if (f.until && t > f.until)
21
+ return false;
22
+ return true;
23
+ }
24
+ /**
25
+ * Interval-overlap range check for sessions with both a start and an end
26
+ * timestamp. A session is kept iff its lifetime `[start, end]` overlaps the
27
+ * query window `[since, until]`.
28
+ *
29
+ * Long / cross-day sessions (created before `--since` but still active inside
30
+ * the window) must survive — single-point `inRange(created, f)` dropped them.
31
+ *
32
+ * Degenerate inputs:
33
+ * - both undefined → pass through (no timestamp = don't filter)
34
+ * - one undefined → fall back to single-point semantics on the other end
35
+ * - unparseable iso → defer to the parsable end (or pass through if both bad)
36
+ */
37
+ export function inRangeOverlap(start, end, f) {
38
+ const s = start ?? end;
39
+ const e = end ?? start;
40
+ if (!s && !e)
41
+ return true;
42
+ if (f.since && e) {
43
+ const eT = new Date(e);
44
+ if (!Number.isNaN(+eT) && eT < f.since)
45
+ return false;
46
+ }
47
+ if (f.until && s) {
48
+ const sT = new Date(s);
49
+ if (!Number.isNaN(+sT) && sT > f.until)
50
+ return false;
51
+ }
52
+ return true;
53
+ }
54
+ /** True iff `sessionCwd` is within `target` (exact match or descendant
55
+ * directory). When `target` is undefined there is no scoping and everything
56
+ * matches; sessions with an unknown cwd are dropped under scoping. */
57
+ export function sameProject(sessionCwd, target) {
58
+ if (!target)
59
+ return true;
60
+ if (!sessionCwd)
61
+ return false;
62
+ const a = path.resolve(sessionCwd);
63
+ const b = path.resolve(target);
64
+ return a === b || a.startsWith(b + path.sep);
65
+ }
66
+ //# sourceMappingURL=filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/mem/filter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC;;6BAE6B;AAC7B,MAAM,UAAU,OAAO,CAAC,GAAuB,EAAE,CAAY;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAyB,EACzB,GAAuB,EACvB,CAAY;IAEZ,MAAM,CAAC,GAAG,KAAK,IAAI,GAAG,CAAC;IACvB,MAAM,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC;IACvB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;sEAEsE;AACtE,MAAM,UAAU,WAAW,CACzB,UAA8B,EAC9B,MAA0B;IAE1B,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Public surface for `@pennixrv/trellis-core/mem` — reusable retrieval and
3
+ * dialogue-context extraction over persisted Claude Code / Codex / OpenCode
4
+ * sessions.
5
+ *
6
+ * This subpackage is intentionally NOT re-exported from the root
7
+ * `@pennixrv/trellis-core` barrel. Import it explicitly:
8
+ *
9
+ * import { searchMemSessions } from "@pennixrv/trellis-core/mem";
10
+ *
11
+ * v1 scope: persisted-session search and context extraction only. It does not
12
+ * read channel / forum / thread event logs and has no cursor / pagination.
13
+ */
14
+ export { listMemSessions, searchMemSessions, extractMemDialogue, MemSessionNotFoundError, } from "./sessions.js";
15
+ export { readMemContext } from "./context.js";
16
+ export { listMemProjects } from "./projects.js";
17
+ export type { MemSourceKind, MemSourceFilter, MemPhase, DialogueRole, DialogueTurn, MemFilter, MemSessionInfo, SearchExcerpt, SearchHit, MemWarning, MemSearchMatch, MemSearchResult, MemContextTurn, MemContextResult, BrainstormWindow, MemDialogueGroup, MemExtractResult, MemProjectSummary, ListMemSessionsOptions, SearchMemSessionsOptions, ReadMemContextOptions, ExtractMemDialogueOptions, ListMemProjectsOptions, } from "./types.js";
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mem/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,YAAY,EACV,aAAa,EACb,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,cAAc,EACd,aAAa,EACb,SAAS,EACT,UAAU,EACV,cAAc,EACd,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Public surface for `@pennixrv/trellis-core/mem` — reusable retrieval and
3
+ * dialogue-context extraction over persisted Claude Code / Codex / OpenCode
4
+ * sessions.
5
+ *
6
+ * This subpackage is intentionally NOT re-exported from the root
7
+ * `@pennixrv/trellis-core` barrel. Import it explicitly:
8
+ *
9
+ * import { searchMemSessions } from "@pennixrv/trellis-core/mem";
10
+ *
11
+ * v1 scope: persisted-session search and context extraction only. It does not
12
+ * read channel / forum / thread event logs and has no cursor / pagination.
13
+ */
14
+ export { listMemSessions, searchMemSessions, extractMemDialogue, MemSessionNotFoundError, } from "./sessions.js";
15
+ export { readMemContext } from "./context.js";
16
+ export { listMemProjects } from "./projects.js";
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mem/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Streaming JSONL / JSON readers for the persisted-session adapters.
3
+ *
4
+ * Zero-dependency on purpose — `@pennixrv/trellis-core` does not depend on
5
+ * `zod`. The original CLI implementation validated every line against a Zod
6
+ * schema; the external session formats were all declared `.loose()` with every
7
+ * field `.optional()`, so the only thing the schema actually rejected was a
8
+ * top-level non-object line — which the `0x7b` byte-prefix fast-reject already
9
+ * filters. Adapters therefore receive each parsed line cast to a hand-written
10
+ * loose interface and read fields defensively.
11
+ */
12
+ /**
13
+ * Walk a JSONL file line-by-line, invoking `onLine` with each parsed object.
14
+ * Bad JSON lines are skipped. Returning the literal `"stop"` from `onLine`
15
+ * halts iteration.
16
+ *
17
+ * Chunked sync streaming: 256 KB read window, leftover preserved across chunks
18
+ * for split-line reassembly — bounded heap on multi-MB session files and a
19
+ * `"stop"` short-circuit that avoids reading the whole file when only the head
20
+ * is needed.
21
+ *
22
+ * Byte-prefix fast-reject: a JSONL event line virtually always begins with `{`.
23
+ * Lines whose first byte is not `{` are blanks / log preambles / partial writes
24
+ * and are skipped before paying the `JSON.parse` cost.
25
+ */
26
+ export declare function readJsonl<T>(file: string, onLine: (obj: T) => unknown): void;
27
+ /** Read just the first parseable JSONL object (stops after one line). */
28
+ export declare function readJsonlFirst<T>(file: string): T | undefined;
29
+ /** Find the first JSONL object satisfying `predicate`, scanning at most
30
+ * `maxLines` lines. */
31
+ export declare function findInJsonl<T>(file: string, predicate: (obj: T) => boolean, maxLines?: number): T | undefined;
32
+ /** Read and JSON-parse a whole file; returns `undefined` on read / parse
33
+ * failure. The caller is responsible for shape-checking the result. */
34
+ export declare function readJsonFile<T>(file: string): T | undefined;
35
+ //# sourceMappingURL=jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../src/mem/internal/jsonl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAqD5E;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAO7D;AAED;uBACuB;AACvB,wBAAgB,WAAW,CAAC,CAAC,EAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,EAC9B,QAAQ,SAAM,GACb,CAAC,GAAG,SAAS,CAYf;AAED;uEACuE;AACvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAM3D"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Streaming JSONL / JSON readers for the persisted-session adapters.
3
+ *
4
+ * Zero-dependency on purpose — `@pennixrv/trellis-core` does not depend on
5
+ * `zod`. The original CLI implementation validated every line against a Zod
6
+ * schema; the external session formats were all declared `.loose()` with every
7
+ * field `.optional()`, so the only thing the schema actually rejected was a
8
+ * top-level non-object line — which the `0x7b` byte-prefix fast-reject already
9
+ * filters. Adapters therefore receive each parsed line cast to a hand-written
10
+ * loose interface and read fields defensively.
11
+ */
12
+ import * as fs from "node:fs";
13
+ const CHUNK = 256 * 1024;
14
+ const OPEN_BRACE = 0x7b; // '{'
15
+ /**
16
+ * Walk a JSONL file line-by-line, invoking `onLine` with each parsed object.
17
+ * Bad JSON lines are skipped. Returning the literal `"stop"` from `onLine`
18
+ * halts iteration.
19
+ *
20
+ * Chunked sync streaming: 256 KB read window, leftover preserved across chunks
21
+ * for split-line reassembly — bounded heap on multi-MB session files and a
22
+ * `"stop"` short-circuit that avoids reading the whole file when only the head
23
+ * is needed.
24
+ *
25
+ * Byte-prefix fast-reject: a JSONL event line virtually always begins with `{`.
26
+ * Lines whose first byte is not `{` are blanks / log preambles / partial writes
27
+ * and are skipped before paying the `JSON.parse` cost.
28
+ */
29
+ export function readJsonl(file, onLine) {
30
+ let fd;
31
+ try {
32
+ fd = fs.openSync(file, "r");
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ const buf = Buffer.alloc(CHUNK);
38
+ let leftover = "";
39
+ try {
40
+ let stop = false;
41
+ while (!stop) {
42
+ const n = fs.readSync(fd, buf, 0, CHUNK, null);
43
+ if (n === 0)
44
+ break;
45
+ const chunk = leftover + buf.toString("utf8", 0, n);
46
+ let from = 0;
47
+ while (true) {
48
+ const nl = chunk.indexOf("\n", from);
49
+ if (nl === -1) {
50
+ leftover = chunk.slice(from);
51
+ break;
52
+ }
53
+ const line = chunk.slice(from, nl);
54
+ from = nl + 1;
55
+ if (!line)
56
+ continue;
57
+ if (line.charCodeAt(0) !== OPEN_BRACE)
58
+ continue;
59
+ let raw;
60
+ try {
61
+ raw = JSON.parse(line);
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ if (onLine(raw) === "stop") {
67
+ stop = true;
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ if (!stop && leftover) {
73
+ // File ended without a trailing newline — process the last partial line.
74
+ const line = leftover;
75
+ if (line.charCodeAt(0) === OPEN_BRACE) {
76
+ try {
77
+ const raw = JSON.parse(line);
78
+ onLine(raw);
79
+ }
80
+ catch {
81
+ /* skip */
82
+ }
83
+ }
84
+ }
85
+ }
86
+ finally {
87
+ fs.closeSync(fd);
88
+ }
89
+ }
90
+ /** Read just the first parseable JSONL object (stops after one line). */
91
+ export function readJsonlFirst(file) {
92
+ let result;
93
+ readJsonl(file, (obj) => {
94
+ result = obj;
95
+ return "stop";
96
+ });
97
+ return result;
98
+ }
99
+ /** Find the first JSONL object satisfying `predicate`, scanning at most
100
+ * `maxLines` lines. */
101
+ export function findInJsonl(file, predicate, maxLines = 200) {
102
+ let count = 0;
103
+ let hit;
104
+ readJsonl(file, (obj) => {
105
+ count++;
106
+ if (predicate(obj)) {
107
+ hit = obj;
108
+ return "stop";
109
+ }
110
+ if (count >= maxLines)
111
+ return "stop";
112
+ });
113
+ return hit;
114
+ }
115
+ /** Read and JSON-parse a whole file; returns `undefined` on read / parse
116
+ * failure. The caller is responsible for shape-checking the result. */
117
+ export function readJsonFile(file) {
118
+ try {
119
+ return JSON.parse(fs.readFileSync(file, "utf8"));
120
+ }
121
+ catch {
122
+ return undefined;
123
+ }
124
+ }
125
+ //# sourceMappingURL=jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../../src/mem/internal/jsonl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Default home-based session roots for the persisted-session adapters.
3
+ *
4
+ * `HOME` is captured once at module load — consumers that need to point the
5
+ * adapters at a fake home (tests) must mock `node:os` before importing any
6
+ * mem module.
7
+ */
8
+ export declare const HOME: string;
9
+ export declare const CLAUDE_PROJECTS: string;
10
+ export declare const CODEX_SESSIONS: string;
11
+ /** ZCode (Zhipu) persisted-session SQLite store. The companion `-wal` file is
12
+ * auto-detected by the readonly parser. */
13
+ export declare const ZCODE_DB: string;
14
+ /** Grok CLI session root: `<cwd url-encoded>/<session-id>/chat_history.jsonl`.
15
+ * The sibling `session_search.sqlite` is a search index only and is not read —
16
+ * this adapter needs no database and adds no dependency. */
17
+ export declare const GROK_SESSIONS: string;
18
+ /**
19
+ * OpenCode's data root: `$XDG_DATA_HOME/opencode`, falling back to
20
+ * `~/.local/share/opencode`.
21
+ *
22
+ * OpenCode applies this XDG rule on every platform — it has no Windows
23
+ * `%LOCALAPPDATA%` or macOS `Application Support` branch — so a Windows install
24
+ * stores its database under `%USERPROFILE%\.local\share\opencode` unless
25
+ * `XDG_DATA_HOME` is set. Verified against the shipped 1.18 bundle:
26
+ * `XDG_DATA_HOME || join(homedir, ".local", "share")` then `join(that,
27
+ * "opencode")`.
28
+ *
29
+ * Read per call rather than at module load so a caller (or test) that sets
30
+ * `XDG_DATA_HOME` sees its own value.
31
+ */
32
+ export declare function opencodeDataDir(): string;
33
+ /**
34
+ * Resolve the OpenCode session database, or `undefined` when this machine has
35
+ * none (a normal empty result, not an error).
36
+ *
37
+ * Mirrors OpenCode's own resolution order:
38
+ * 1. `OPENCODE_DB` — absolute path used as-is, relative name joined to the
39
+ * data dir, and `:memory:` meaning there is no file to read at all.
40
+ * 2. `<data>/opencode.db` — the release channels (`latest` / `beta` /
41
+ * `prod`) and anyone setting `OPENCODE_DISABLE_CHANNEL_DB`.
42
+ * 3. `<data>/opencode-<channel>.db` — other channels write a suffixed file.
43
+ * The channel is baked into the user's binary and is not discoverable
44
+ * from here, so the most recently written one wins.
45
+ */
46
+ export declare function opencodeDbPath(): string | undefined;
47
+ export declare const PI_AGENT_DIR: string;
48
+ export declare const PI_SESSIONS: string;
49
+ /** Claude sanitizes a cwd into its on-disk project dir name by replacing
50
+ * every path separator (`/` and Windows `\`), drive colon (`:`), `_`, and `.`
51
+ * with `-`. Confirmed empirically against `~/.claude/projects/`:
52
+ * `/Users/x/.codex/...` → `-Users-x--codex-...`, `snap_note` → `snap-note`. */
53
+ export declare function claudeProjectDirFromCwd(cwd: string): string;
54
+ /** Grok names each project dir with the URL-encoded absolute cwd, e.g.
55
+ * `/Users/x/proj` → `%2FUsers%2Fx%2Fproj`. */
56
+ export declare function grokProjectDirFromCwd(cwd: string): string;
57
+ /** Inverse of {@link grokProjectDirFromCwd}. Returns `undefined` when the name
58
+ * is not valid percent-encoding rather than throwing on a stray `%`. */
59
+ export declare function grokCwdFromProjectDir(dirName: string): string | undefined;
60
+ /** Pi encodes a cwd as `--<resolved-cwd-with-separators-as-dashes>--`. */
61
+ export declare function piProjectDirFromCwd(cwd: string): string;
62
+ /** Discover Pi session roots visible from the current process and project. */
63
+ export declare function piSessionRoots(cwd?: string): string[];
64
+ /** Lazy stack-based recursive file walk — yields every file path under
65
+ * `root`. Missing roots and unreadable directories are skipped silently. */
66
+ export declare function walkDir(root: string): Generator<string>;
67
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/mem/internal/paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,IAAI,QAAe,CAAC;AACjC,eAAO,MAAM,eAAe,QAAyC,CAAC;AACtE,eAAO,MAAM,cAAc,QAAwC,CAAC;AACpE;2CAC2C;AAC3C,eAAO,MAAM,QAAQ,QAAsD,CAAC;AAC5E;;4DAE4D;AAC5D,eAAO,MAAM,aAAa,QAAuC,CAAC;AAElE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAIxC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,SAAS,CA8BnD;AASD,eAAO,MAAM,YAAY,QAExB,CAAC;AACF,eAAO,MAAM,WAAW,QAGvB,CAAC;AAiBF;;;+EAG+E;AAC/E,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;8CAC8C;AAC9C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;wEACwE;AACxE,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMzE;AAED,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAsBrD;AAED;4EAC4E;AAC5E,wBAAiB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAkBxD"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Default home-based session roots for the persisted-session adapters.
3
+ *
4
+ * `HOME` is captured once at module load — consumers that need to point the
5
+ * adapters at a fake home (tests) must mock `node:os` before importing any
6
+ * mem module.
7
+ */
8
+ import * as fs from "node:fs";
9
+ import * as os from "node:os";
10
+ import * as path from "node:path";
11
+ export const HOME = os.homedir();
12
+ export const CLAUDE_PROJECTS = path.join(HOME, ".claude", "projects");
13
+ export const CODEX_SESSIONS = path.join(HOME, ".codex", "sessions");
14
+ /** ZCode (Zhipu) persisted-session SQLite store. The companion `-wal` file is
15
+ * auto-detected by the readonly parser. */
16
+ export const ZCODE_DB = path.join(HOME, ".zcode", "cli", "db", "db.sqlite");
17
+ /** Grok CLI session root: `<cwd url-encoded>/<session-id>/chat_history.jsonl`.
18
+ * The sibling `session_search.sqlite` is a search index only and is not read —
19
+ * this adapter needs no database and adds no dependency. */
20
+ export const GROK_SESSIONS = path.join(HOME, ".grok", "sessions");
21
+ /**
22
+ * OpenCode's data root: `$XDG_DATA_HOME/opencode`, falling back to
23
+ * `~/.local/share/opencode`.
24
+ *
25
+ * OpenCode applies this XDG rule on every platform — it has no Windows
26
+ * `%LOCALAPPDATA%` or macOS `Application Support` branch — so a Windows install
27
+ * stores its database under `%USERPROFILE%\.local\share\opencode` unless
28
+ * `XDG_DATA_HOME` is set. Verified against the shipped 1.18 bundle:
29
+ * `XDG_DATA_HOME || join(homedir, ".local", "share")` then `join(that,
30
+ * "opencode")`.
31
+ *
32
+ * Read per call rather than at module load so a caller (or test) that sets
33
+ * `XDG_DATA_HOME` sees its own value.
34
+ */
35
+ export function opencodeDataDir() {
36
+ const xdg = process.env.XDG_DATA_HOME?.trim();
37
+ if (xdg)
38
+ return path.join(xdg, "opencode");
39
+ return path.join(HOME, ".local", "share", "opencode");
40
+ }
41
+ /**
42
+ * Resolve the OpenCode session database, or `undefined` when this machine has
43
+ * none (a normal empty result, not an error).
44
+ *
45
+ * Mirrors OpenCode's own resolution order:
46
+ * 1. `OPENCODE_DB` — absolute path used as-is, relative name joined to the
47
+ * data dir, and `:memory:` meaning there is no file to read at all.
48
+ * 2. `<data>/opencode.db` — the release channels (`latest` / `beta` /
49
+ * `prod`) and anyone setting `OPENCODE_DISABLE_CHANNEL_DB`.
50
+ * 3. `<data>/opencode-<channel>.db` — other channels write a suffixed file.
51
+ * The channel is baked into the user's binary and is not discoverable
52
+ * from here, so the most recently written one wins.
53
+ */
54
+ export function opencodeDbPath() {
55
+ const dir = opencodeDataDir();
56
+ const override = process.env.OPENCODE_DB?.trim();
57
+ if (override) {
58
+ if (override === ":memory:")
59
+ return undefined;
60
+ const expanded = expandHome(override);
61
+ return path.isAbsolute(expanded) ? expanded : path.join(dir, expanded);
62
+ }
63
+ const primary = path.join(dir, "opencode.db");
64
+ if (fs.existsSync(primary))
65
+ return primary;
66
+ let entries;
67
+ try {
68
+ entries = fs.readdirSync(dir, { withFileTypes: true });
69
+ }
70
+ catch {
71
+ return undefined;
72
+ }
73
+ let newest;
74
+ for (const entry of entries) {
75
+ if (!entry.isFile() || !/^opencode-.+\.db$/.test(entry.name))
76
+ continue;
77
+ const file = path.join(dir, entry.name);
78
+ try {
79
+ const { mtimeMs } = fs.statSync(file);
80
+ if (!newest || mtimeMs > newest.mtimeMs)
81
+ newest = { file, mtimeMs };
82
+ }
83
+ catch {
84
+ /* raced away between readdir and stat — skip it */
85
+ }
86
+ }
87
+ return newest?.file;
88
+ }
89
+ function expandHome(p) {
90
+ if (p === "~")
91
+ return HOME;
92
+ if (p.startsWith(`~${path.sep}`))
93
+ return path.join(HOME, p.slice(2));
94
+ if (p.startsWith("~/"))
95
+ return path.join(HOME, p.slice(2));
96
+ return p;
97
+ }
98
+ export const PI_AGENT_DIR = expandHome(process.env.PI_CODING_AGENT_DIR ?? path.join(HOME, ".pi", "agent"));
99
+ export const PI_SESSIONS = expandHome(process.env.PI_CODING_AGENT_SESSION_DIR ??
100
+ path.join(PI_AGENT_DIR, "sessions"));
101
+ function readPiSettingsSessionDir(settingsFile) {
102
+ try {
103
+ const raw = JSON.parse(fs.readFileSync(settingsFile, "utf8"));
104
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
105
+ return undefined;
106
+ const sessionDir = raw.sessionDir;
107
+ if (typeof sessionDir !== "string" || !sessionDir.trim())
108
+ return undefined;
109
+ const expanded = expandHome(sessionDir);
110
+ return path.isAbsolute(expanded)
111
+ ? expanded
112
+ : path.resolve(path.dirname(settingsFile), expanded);
113
+ }
114
+ catch {
115
+ return undefined;
116
+ }
117
+ }
118
+ /** Claude sanitizes a cwd into its on-disk project dir name by replacing
119
+ * every path separator (`/` and Windows `\`), drive colon (`:`), `_`, and `.`
120
+ * with `-`. Confirmed empirically against `~/.claude/projects/`:
121
+ * `/Users/x/.codex/...` → `-Users-x--codex-...`, `snap_note` → `snap-note`. */
122
+ export function claudeProjectDirFromCwd(cwd) {
123
+ return path.join(CLAUDE_PROJECTS, cwd.replace(/[/\\:_.]/g, "-"));
124
+ }
125
+ /** Grok names each project dir with the URL-encoded absolute cwd, e.g.
126
+ * `/Users/x/proj` → `%2FUsers%2Fx%2Fproj`. */
127
+ export function grokProjectDirFromCwd(cwd) {
128
+ return path.join(GROK_SESSIONS, encodeURIComponent(path.resolve(cwd)));
129
+ }
130
+ /** Inverse of {@link grokProjectDirFromCwd}. Returns `undefined` when the name
131
+ * is not valid percent-encoding rather than throwing on a stray `%`. */
132
+ export function grokCwdFromProjectDir(dirName) {
133
+ try {
134
+ return decodeURIComponent(dirName);
135
+ }
136
+ catch {
137
+ return undefined;
138
+ }
139
+ }
140
+ /** Pi encodes a cwd as `--<resolved-cwd-with-separators-as-dashes>--`. */
141
+ export function piProjectDirFromCwd(cwd) {
142
+ const resolvedCwd = path.resolve(cwd);
143
+ const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
144
+ return path.join(path.join(PI_AGENT_DIR, "sessions"), safePath);
145
+ }
146
+ /** Discover Pi session roots visible from the current process and project. */
147
+ export function piSessionRoots(cwd) {
148
+ const roots = [path.join(PI_AGENT_DIR, "sessions"), PI_SESSIONS];
149
+ const globalSettingsDir = readPiSettingsSessionDir(path.join(PI_AGENT_DIR, "settings.json"));
150
+ if (globalSettingsDir)
151
+ roots.push(globalSettingsDir);
152
+ if (cwd) {
153
+ const projectSettingsDir = readPiSettingsSessionDir(path.join(path.resolve(cwd), ".pi", "settings.json"));
154
+ if (projectSettingsDir)
155
+ roots.push(projectSettingsDir);
156
+ }
157
+ const seen = new Set();
158
+ const out = [];
159
+ for (const root of roots) {
160
+ const normalized = path.resolve(root);
161
+ if (seen.has(normalized))
162
+ continue;
163
+ seen.add(normalized);
164
+ out.push(root);
165
+ }
166
+ return out;
167
+ }
168
+ /** Lazy stack-based recursive file walk — yields every file path under
169
+ * `root`. Missing roots and unreadable directories are skipped silently. */
170
+ export function* walkDir(root) {
171
+ if (!fs.existsSync(root))
172
+ return;
173
+ const stack = [root];
174
+ while (stack.length) {
175
+ const cur = stack.pop();
176
+ if (cur === undefined)
177
+ break;
178
+ let entries;
179
+ try {
180
+ entries = fs.readdirSync(cur, { withFileTypes: true });
181
+ }
182
+ catch {
183
+ continue;
184
+ }
185
+ for (const e of entries) {
186
+ const p = path.join(cur, e.name);
187
+ if (e.isDirectory())
188
+ stack.push(p);
189
+ else if (e.isFile())
190
+ yield p;
191
+ }
192
+ }
193
+ }
194
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/mem/internal/paths.ts"],"names":[],"mappings":"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"}