@selesai/code 0.13.0 → 0.13.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.
Files changed (461) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/core/agent-session.d.ts +1 -1
  3. package/dist/core/agent-session.js +1 -1
  4. package/dist/core/sdk.d.ts +2 -2
  5. package/dist/core/sdk.js +1 -1
  6. package/dist/core/system-prompt.d.ts +1 -1
  7. package/dist/core/system-prompt.js +1 -1
  8. package/dist/extensions/ascii.txt +9 -0
  9. package/dist/extensions/package.json +1 -2
  10. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  11. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  12. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  13. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  14. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  25. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  26. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  27. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  28. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  29. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  34. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  35. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  36. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  38. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  39. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  40. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  41. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  42. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  43. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  44. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  45. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  46. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  47. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  48. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  65. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  66. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  67. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  68. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  69. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  70. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  71. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  72. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  73. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  74. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  91. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  92. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  93. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  97. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  98. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  99. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  100. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  101. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  102. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  118. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  119. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  120. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  121. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  122. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  123. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  124. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  125. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  126. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  127. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  128. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  129. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  143. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  144. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  145. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  149. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  150. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  151. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  152. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  153. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  154. package/dist/extensions/pi-subagents/README.md +12 -6
  155. package/dist/extensions/pi-subagents/VISION.md +81 -0
  156. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  157. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  158. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  161. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  162. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  163. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  164. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  165. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  166. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  167. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  168. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  169. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  170. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  171. package/dist/extensions/pi-subagents/package.json +3 -1
  172. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  173. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  174. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  175. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  178. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  179. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  180. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  181. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  182. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  183. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  184. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  185. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  186. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  187. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  188. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  189. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  190. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  192. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  193. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  194. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  195. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  196. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  197. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  198. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  200. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -3
  201. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  202. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  203. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  204. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  205. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  206. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  207. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  208. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  209. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  210. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  211. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  212. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  213. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  215. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  216. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  217. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  218. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  219. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  220. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  221. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  222. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  223. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  224. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  225. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  226. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  227. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  228. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  230. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  231. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  232. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  233. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  234. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  235. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  236. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  237. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  238. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  239. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  241. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  243. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  245. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  247. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  250. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  251. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  252. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  253. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  255. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  259. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  260. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  261. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  262. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  263. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  264. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  265. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  266. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  267. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  268. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  269. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  270. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  271. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  272. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  273. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  274. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  275. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  276. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  277. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  278. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  279. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  280. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  281. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  282. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  283. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  284. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  285. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  286. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  287. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  288. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  289. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  290. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  291. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  292. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  293. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  294. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  295. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  296. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  297. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  298. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  299. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  300. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  301. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  304. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  305. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  306. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  307. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  308. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  309. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  310. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  311. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  312. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  313. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  314. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  315. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  316. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  317. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  318. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  319. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  320. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  321. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  322. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  323. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  324. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  325. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  326. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  327. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  328. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  329. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  330. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  331. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  332. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  333. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  334. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  335. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  336. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  337. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  338. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  339. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  340. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  341. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  342. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  344. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  345. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  346. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  347. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  348. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  349. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  350. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  351. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  352. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  353. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  354. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  355. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  356. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  357. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  358. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  359. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  360. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  361. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  362. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  364. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  365. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  366. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  367. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  368. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  369. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  371. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +132 -0
  372. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  373. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  374. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  375. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  376. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  377. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  378. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  379. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  380. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  381. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  382. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  383. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  384. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  385. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  386. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  387. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  388. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  389. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  390. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  391. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  392. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  393. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  394. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  395. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  396. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  397. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  398. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  399. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  400. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  401. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  402. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  403. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  404. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  405. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  406. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  407. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  408. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  409. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  410. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  411. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  412. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  413. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  414. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  415. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  416. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  417. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  418. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  419. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  420. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  421. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  422. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  423. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  424. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  425. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  426. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  427. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  428. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  429. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  449. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  450. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  451. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  452. package/dist/modes/interactive/interactive-mode.js +7 -7
  453. package/dist/skills/workflow/SKILL.md +65 -50
  454. package/package.json +112 -110
  455. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  456. package/dist/extensions/enable-readonly-tools.ts +0 -24
  457. package/dist/extensions/model-prompt-injector/config.json +0 -16
  458. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  459. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  460. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  461. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Shared better-sqlite3 loader with ABI mismatch recovery.
3
+ *
4
+ * Pi installs extension deps under ~/.selesai/agent/npm. When the host Node that
5
+ * runs Pi (e.g. Homebrew) differs from the Node that compiled better-sqlite3,
6
+ * require() throws NODE_MODULE_VERSION errors. Detect that, attempt one
7
+ * npm rebuild against the current runtime, and surface a clear recovery path.
8
+ */
9
+
10
+ import { createRequire } from "node:module";
11
+ import { spawnSync } from "node:child_process";
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+
15
+ export type BetterSqlite3DatabaseCtor = new (
16
+ dbPath: string,
17
+ options?: { readonly?: boolean; fileMustExist?: boolean; timeout?: number },
18
+ ) => unknown;
19
+
20
+ export interface SqliteNativeLoadOptions {
21
+ /** Override createRequire base URL (tests). */
22
+ requireFrom?: string | URL;
23
+ /** Inject require() for tests. */
24
+ requireImpl?: NodeRequire;
25
+ /** Inject rebuild runner for tests. */
26
+ rebuild?: (packageRoot: string) => { ok: boolean; detail: string };
27
+ /** Force treating the first load failure as rebuild-eligible (tests). */
28
+ allowRebuild?: boolean;
29
+ }
30
+
31
+ export class BetterSqlite3LoadError extends Error {
32
+ readonly code = "BETTER_SQLITE3_LOAD_FAILED";
33
+ readonly packageRoot: string | null;
34
+ readonly causeError: unknown;
35
+
36
+ constructor(message: string, options: { packageRoot?: string | null; cause?: unknown } = {}) {
37
+ super(message);
38
+ this.name = "BetterSqlite3LoadError";
39
+ this.packageRoot = options.packageRoot ?? null;
40
+ this.causeError = options.cause;
41
+ }
42
+ }
43
+
44
+ const ABI_MISMATCH_RE =
45
+ /NODE_MODULE_VERSION|was compiled against a different Node\.js version|ERR_DLOPEN_FAILED/i;
46
+
47
+ /**
48
+ * True when running under Bun (including the compiled Pi binary).
49
+ *
50
+ * Compiled Pi cannot resolve `better-sqlite3` — neither the bare specifier nor
51
+ * the package's own transitive `require("bindings")` resolve from an on-disk
52
+ * extension file, so every code path that needs SQLite must route through
53
+ * `bun:sqlite` instead of loading the native module.
54
+ */
55
+ export function isBunRuntime(): boolean {
56
+ return "Bun" in globalThis;
57
+ }
58
+
59
+ export function isNativeModuleAbiMismatch(error: unknown): boolean {
60
+ if (!error) return false;
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ if (ABI_MISMATCH_RE.test(message)) return true;
63
+ if (typeof error === "object" && error !== null) {
64
+ const code = "code" in error ? String((error as { code?: unknown }).code ?? "") : "";
65
+ if (code === "ERR_DLOPEN_FAILED") return true;
66
+ }
67
+ return false;
68
+ }
69
+
70
+ export function resolveBetterSqlite3PackageRoot(requireImpl: NodeRequire): string | null {
71
+ try {
72
+ const entry = requireImpl.resolve("better-sqlite3");
73
+ let dir = path.dirname(entry);
74
+ while (true) {
75
+ const pkgPath = path.join(dir, "package.json");
76
+ if (fs.existsSync(pkgPath)) {
77
+ try {
78
+ const raw = fs.readFileSync(pkgPath, "utf-8");
79
+ const pkg = JSON.parse(raw) as { name?: unknown };
80
+ if (pkg && typeof pkg === "object" && pkg.name === "better-sqlite3") return dir;
81
+ } catch {
82
+ // keep walking
83
+ }
84
+ }
85
+ const parent = path.dirname(dir);
86
+ if (parent === dir) break;
87
+ dir = parent;
88
+ }
89
+
90
+ // Classic layout fallback: .../node_modules/better-sqlite3/<...>
91
+ const parts = entry.split(path.sep);
92
+ const idx = parts.lastIndexOf("better-sqlite3");
93
+ if (idx >= 0) {
94
+ return parts.slice(0, idx + 1).join(path.sep) || null;
95
+ }
96
+ return path.dirname(entry);
97
+ } catch {
98
+ return null;
99
+ }
100
+ }
101
+ function defaultRebuild(packageRoot: string): { ok: boolean; detail: string } {
102
+ const npmExecPath = typeof process.env.npm_execpath === "string" && process.env.npm_execpath
103
+ ? process.env.npm_execpath
104
+ : null;
105
+
106
+ const attempts: Array<{ command: string; args: string[]; shell?: boolean }> = [];
107
+ if (npmExecPath) {
108
+ attempts.push({ command: process.execPath, args: [npmExecPath, "rebuild", "better-sqlite3"] });
109
+ }
110
+ attempts.push({ command: "npm", args: ["rebuild", "better-sqlite3"] });
111
+
112
+ const details: string[] = [];
113
+ for (const attempt of attempts) {
114
+ const result = spawnSync(attempt.command, attempt.args, {
115
+ cwd: packageRoot,
116
+ encoding: "utf-8",
117
+ env: process.env,
118
+ timeout: 120_000,
119
+ shell: attempt.shell ?? false,
120
+ });
121
+ if (result.error) {
122
+ details.push(`${attempt.command}: ${result.error.message}`);
123
+ continue;
124
+ }
125
+ if (result.status === 0) {
126
+ return { ok: true, detail: (result.stdout || result.stderr || "rebuild ok").trim() };
127
+ }
128
+ const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
129
+ details.push(`${attempt.command} exited ${result.status}${output ? `: ${output}` : ""}`);
130
+ }
131
+
132
+ return { ok: false, detail: details.join(" | ") || "rebuild failed" };
133
+ }
134
+
135
+ function unwrapModule(mod: { default?: BetterSqlite3DatabaseCtor } | BetterSqlite3DatabaseCtor): BetterSqlite3DatabaseCtor {
136
+ return (mod as { default?: BetterSqlite3DatabaseCtor }).default ?? (mod as BetterSqlite3DatabaseCtor);
137
+ }
138
+
139
+ function clearBetterSqlite3RequireCache(requireImpl: NodeRequire, packageRoot: string | null): void {
140
+ for (const key of Object.keys(requireImpl.cache)) {
141
+ if (!key.includes(`${path.sep}better-sqlite3${path.sep}`) && !key.endsWith(`${path.sep}better-sqlite3`)) {
142
+ continue;
143
+ }
144
+ if (packageRoot && !key.startsWith(packageRoot)) continue;
145
+ delete requireImpl.cache[key];
146
+ }
147
+ }
148
+
149
+ export function formatBetterSqlite3AbiError(options: {
150
+ originalError: unknown;
151
+ packageRoot: string | null;
152
+ rebuildAttempted: boolean;
153
+ rebuildDetail?: string;
154
+ }): string {
155
+ const original = options.originalError instanceof Error
156
+ ? options.originalError.message
157
+ : String(options.originalError);
158
+ const runtime = `Node ${process.version} (NODE_MODULE_VERSION ${process.versions.modules}) via ${process.execPath}`;
159
+ const location = options.packageRoot ?? "(better-sqlite3 package root unknown)";
160
+ const rebuildLine = options.rebuildAttempted
161
+ ? (options.rebuildDetail
162
+ ? `Automatic rebuild was attempted and failed: ${options.rebuildDetail}`
163
+ : "Automatic rebuild was attempted and failed.")
164
+ : "Automatic rebuild was not attempted.";
165
+
166
+ return [
167
+ "pi-hermes-memory could not load the native better-sqlite3 module for this Node runtime.",
168
+ `Runtime: ${runtime}`,
169
+ `Module: ${location}`,
170
+ `Original error: ${original}`,
171
+ rebuildLine,
172
+ "Fix: rebuild the extension install against the same Node that runs Pi, then restart Pi:",
173
+ options.packageRoot
174
+ ? ` cd "${options.packageRoot}" && npm rebuild better-sqlite3`
175
+ : " cd ~/.selesai/agent/npm && npm rebuild better-sqlite3",
176
+ "If you installed Pi with Homebrew, either rebuild as above after brew Node upgrades, or install Pi with npm so the extension and host share one Node toolchain.",
177
+ ].join("\n");
178
+ }
179
+
180
+ /**
181
+ * Load better-sqlite3, attempting one rebuild on ABI/dlopen mismatch.
182
+ */
183
+ export function loadBetterSqlite3(options: SqliteNativeLoadOptions = {}): BetterSqlite3DatabaseCtor {
184
+ const requireImpl = options.requireImpl
185
+ ?? createRequire(options.requireFrom ?? import.meta.url);
186
+
187
+ const loadOnce = (): BetterSqlite3DatabaseCtor => {
188
+ const mod = requireImpl("better-sqlite3") as { default?: BetterSqlite3DatabaseCtor } | BetterSqlite3DatabaseCtor;
189
+ return unwrapModule(mod);
190
+ };
191
+
192
+ try {
193
+ return loadOnce();
194
+ } catch (firstError) {
195
+ const packageRoot = resolveBetterSqlite3PackageRoot(requireImpl);
196
+ const canRebuild = options.allowRebuild ?? isNativeModuleAbiMismatch(firstError);
197
+ if (!canRebuild || !packageRoot) {
198
+ if (isNativeModuleAbiMismatch(firstError)) {
199
+ throw new BetterSqlite3LoadError(
200
+ formatBetterSqlite3AbiError({
201
+ originalError: firstError,
202
+ packageRoot,
203
+ rebuildAttempted: false,
204
+ }),
205
+ { packageRoot, cause: firstError },
206
+ );
207
+ }
208
+ throw firstError;
209
+ }
210
+
211
+ const rebuild = options.rebuild ?? defaultRebuild;
212
+ const rebuildResult = rebuild(packageRoot);
213
+ clearBetterSqlite3RequireCache(requireImpl, packageRoot);
214
+
215
+ if (rebuildResult.ok) {
216
+ try {
217
+ return loadOnce();
218
+ } catch (secondError) {
219
+ throw new BetterSqlite3LoadError(
220
+ formatBetterSqlite3AbiError({
221
+ originalError: secondError,
222
+ packageRoot,
223
+ rebuildAttempted: true,
224
+ rebuildDetail: rebuildResult.detail,
225
+ }),
226
+ { packageRoot, cause: secondError },
227
+ );
228
+ }
229
+ }
230
+
231
+ throw new BetterSqlite3LoadError(
232
+ formatBetterSqlite3AbiError({
233
+ originalError: firstError,
234
+ packageRoot,
235
+ rebuildAttempted: true,
236
+ rebuildDetail: rebuildResult.detail,
237
+ }),
238
+ { packageRoot, cause: firstError },
239
+ );
240
+ }
241
+ }
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Standing instructions — bounded, user-authored directives injected into
3
+ * every session regardless of memoryMode.
4
+ *
5
+ * Why this is a separate store rather than a flag on MEMORY.md / USER.md
6
+ * (#121): in policy-only mode a persisted constraint only takes effect if the
7
+ * model decides to call memory_search *before* the action the constraint would
8
+ * have prevented. For a prohibition that is exactly the moment the model has no
9
+ * reason to look, so the recall path is structurally unable to enforce it,
10
+ * independent of model quality. Such constraints have to be unconditionally
11
+ * present instead.
12
+ *
13
+ * Provenance is a property of the storage, not of a flag: background review,
14
+ * consolidation and the correction detector all write through MemoryStore and
15
+ * never touch this file, so a model-generated memory has no path into the
16
+ * always-injected block. Only a direct user edit or /memory-pin can write here.
17
+ *
18
+ * The budget is hard and separate from the Markdown stores: a user whose
19
+ * MEMORY.md + USER.md already run to tens of KB must still be able to pin a
20
+ * handful of rules without paying for the rest.
21
+ */
22
+
23
+ import * as fs from "node:fs/promises";
24
+ import * as path from "node:path";
25
+ import {
26
+ STANDING_MAX_CHARS,
27
+ STANDING_MAX_ENTRIES,
28
+ } from "../constants.js";
29
+ import { scanContent } from "./content-scanner.js";
30
+ import { withMarkdownMutationLock } from "./markdown-mutation-lock.js";
31
+
32
+ export interface StandingInstructionResult {
33
+ success: boolean;
34
+ error?: string;
35
+ message?: string;
36
+ instructions?: string[];
37
+ }
38
+
39
+ /** What actually reached the prompt, so callers can report truncation loudly. */
40
+ export interface StandingInstructionRender {
41
+ block: string;
42
+ injectedCount: number;
43
+ omittedCount: number;
44
+ }
45
+
46
+ export class StandingInstructions {
47
+ private instructions: string[] = [];
48
+ private loaded = false;
49
+
50
+ constructor(
51
+ private readonly filePath: string,
52
+ private readonly maxEntries: number = STANDING_MAX_ENTRIES,
53
+ private readonly maxChars: number = STANDING_MAX_CHARS,
54
+ ) {}
55
+
56
+ getFilePath(): string {
57
+ return this.filePath;
58
+ }
59
+
60
+ async load(): Promise<void> {
61
+ try {
62
+ const raw = await fs.readFile(this.filePath, "utf-8");
63
+ this.instructions = parseInstructions(raw);
64
+ } catch (error) {
65
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
66
+ this.instructions = [];
67
+ }
68
+ this.loaded = true;
69
+ }
70
+
71
+ isLoaded(): boolean {
72
+ return this.loaded;
73
+ }
74
+
75
+ list(): string[] {
76
+ return [...this.instructions];
77
+ }
78
+
79
+ async add(text: string): Promise<StandingInstructionResult> {
80
+ const instruction = normalizeInstruction(text);
81
+ if (!instruction) {
82
+ return { success: false, error: "A standing instruction cannot be empty." };
83
+ }
84
+
85
+ // Same scan every memory write goes through. A file the user is told is
86
+ // "always in context" is the most attractive injection target we have.
87
+ const blocked = scanContent(instruction);
88
+ if (blocked) return { success: false, error: blocked };
89
+
90
+ return this.mutate((current) => {
91
+ if (current.some((existing) => existing.toLowerCase() === instruction.toLowerCase())) {
92
+ return { error: "That standing instruction is already pinned." };
93
+ }
94
+ if (current.length >= this.maxEntries) {
95
+ return {
96
+ error: `Standing instructions are capped at ${this.maxEntries} entries`
97
+ + ` (currently ${current.length}). Remove one first with /memory-pin remove <n>.`,
98
+ };
99
+ }
100
+ const projected = [...current, instruction];
101
+ const projectedChars = projected.join("\n").length;
102
+ if (projectedChars > this.maxChars) {
103
+ return {
104
+ error: `Standing instructions are capped at ${this.maxChars} characters`
105
+ + ` and this entry would make ${projectedChars}. Shorten it, or remove an existing`
106
+ + ` instruction and keep long-form context in regular memory.`,
107
+ };
108
+ }
109
+ return { next: projected, message: `Pinned standing instruction ${projected.length}: ${instruction}` };
110
+ });
111
+ }
112
+
113
+ async remove(position: number): Promise<StandingInstructionResult> {
114
+ return this.mutate((current) => {
115
+ if (!Number.isInteger(position) || position < 1 || position > current.length) {
116
+ return {
117
+ error: current.length === 0
118
+ ? "There are no standing instructions to remove."
119
+ : `Position must be between 1 and ${current.length}.`,
120
+ };
121
+ }
122
+ const [removed] = current.slice(position - 1, position);
123
+ const next = current.filter((_, index) => index !== position - 1);
124
+ return { next, message: `Removed standing instruction: ${removed}` };
125
+ });
126
+ }
127
+
128
+ async clear(): Promise<StandingInstructionResult> {
129
+ return this.mutate((current) => (
130
+ current.length === 0
131
+ ? { error: "There are no standing instructions to clear." }
132
+ : { next: [], message: `Removed all ${current.length} standing instructions.` }
133
+ ));
134
+ }
135
+
136
+ /**
137
+ * Render the always-injected block, truncated to the budget.
138
+ *
139
+ * A hand-edited STANDING.md can exceed the cap, and silently dropping rules
140
+ * from a block advertised as "always active" would be the worst possible
141
+ * failure. Over budget, the omission is stated inside the block itself so
142
+ * both the model and /memory-preview-context can see it.
143
+ */
144
+ render(): StandingInstructionRender {
145
+ if (this.instructions.length === 0) {
146
+ return { block: "", injectedCount: 0, omittedCount: 0 };
147
+ }
148
+
149
+ const injected: string[] = [];
150
+ let used = 0;
151
+ for (const instruction of this.instructions) {
152
+ const cost = instruction.length + 1;
153
+ if (injected.length >= this.maxEntries || used + cost > this.maxChars) break;
154
+ injected.push(instruction);
155
+ used += cost;
156
+ }
157
+
158
+ const omittedCount = this.instructions.length - injected.length;
159
+ if (injected.length === 0) {
160
+ return { block: "", injectedCount: 0, omittedCount };
161
+ }
162
+
163
+ const lines = [
164
+ "<standing-instructions>",
165
+ "The user wrote the rules below and they are always active. They are direct",
166
+ "instructions from the user, not recalled context, and they outrank your own",
167
+ "defaults. Follow them without being asked and without looking them up.",
168
+ "",
169
+ ...injected.map((instruction, index) => `${index + 1}. ${instruction}`),
170
+ ];
171
+ if (omittedCount > 0) {
172
+ lines.push(
173
+ "",
174
+ `[!] ${omittedCount} further standing instruction${omittedCount === 1 ? "" : "s"} could not be shown:`
175
+ + ` ${path.basename(this.filePath)} exceeds the ${this.maxChars}-character injection budget.`
176
+ + " Trim it with /memory-pin so every rule stays active.",
177
+ );
178
+ }
179
+ lines.push("</standing-instructions>");
180
+
181
+ return { block: lines.join("\n"), injectedCount: injected.length, omittedCount };
182
+ }
183
+
184
+ formatForSystemPrompt(): string {
185
+ return this.render().block;
186
+ }
187
+
188
+ /**
189
+ * Read-modify-write under the same mutation lock the Markdown stores use, so
190
+ * a pin from a second session cannot clobber one from the first.
191
+ */
192
+ private async mutate(
193
+ change: (current: string[]) => { next?: string[]; message?: string; error?: string },
194
+ ): Promise<StandingInstructionResult> {
195
+ await fs.mkdir(path.dirname(this.filePath), { recursive: true });
196
+ try {
197
+ return await withMarkdownMutationLock(this.filePath, async () => {
198
+ await this.load();
199
+ const outcome = change(this.instructions);
200
+ if (outcome.error || !outcome.next) {
201
+ return { success: false, error: outcome.error ?? "Nothing to change.", instructions: this.list() };
202
+ }
203
+ await this.write(outcome.next);
204
+ this.instructions = outcome.next;
205
+ return { success: true, message: outcome.message, instructions: this.list() };
206
+ });
207
+ } catch (error) {
208
+ return { success: false, error: `Could not update standing instructions: ${String(error).slice(0, 200)}` };
209
+ }
210
+ }
211
+
212
+ /** Atomic write: temp file in the same directory, then rename. */
213
+ private async write(instructions: string[]): Promise<void> {
214
+ const content = instructions.length ? `${instructions.join("\n")}\n` : "";
215
+ const tmpDir = await fs.mkdtemp(path.join(path.dirname(this.filePath), ".tmp-standing-"));
216
+ const tmpPath = path.join(tmpDir, "write.tmp");
217
+ try {
218
+ await fs.writeFile(tmpPath, content, "utf-8");
219
+ await fs.rename(tmpPath, this.filePath);
220
+ } finally {
221
+ await fs.rm(tmpDir, { recursive: true, force: true });
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * One instruction per line. Blank lines, `#` comments and a leading `-`/`*`
228
+ * bullet are tolerated so a hand-edited STANDING.md stays a normal Markdown
229
+ * file rather than a format the user has to get exactly right.
230
+ */
231
+ function parseInstructions(raw: string): string[] {
232
+ const seen = new Set<string>();
233
+ const instructions: string[] = [];
234
+ for (const line of raw.split("\n")) {
235
+ const instruction = normalizeInstruction(line);
236
+ if (!instruction || instruction.startsWith("#")) continue;
237
+ const key = instruction.toLowerCase();
238
+ if (seen.has(key)) continue;
239
+ seen.add(key);
240
+ instructions.push(instruction);
241
+ }
242
+ return instructions;
243
+ }
244
+
245
+ function normalizeInstruction(text: string): string {
246
+ return text.replace(/^\s*[-*]\s+/, "").replace(/\s+/g, " ").trim();
247
+ }
@@ -0,0 +1,95 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { Type } from "typebox";
3
+ import { StringEnum } from "@earendil-works/pi-ai";
4
+ import { DatabaseManager } from '../store/db.js';
5
+ import { searchMemories, getMemoryStats } from '../store/sqlite-memory-store.js';
6
+ import type { MemoryCategory } from '../types.js';
7
+ import { createSharedToolResultRenderer } from './shared-output-view.js';
8
+ import { searchResultView } from './tool-result-views.js';
9
+
10
+ interface SearchResult {
11
+ success: boolean;
12
+ count?: number;
13
+ message?: string;
14
+ output?: string;
15
+ }
16
+
17
+ function mutationTarget(entry: { target: "memory" | "user" | "failure"; project: string | null }): "memory" | "user" | "failure" | "project" {
18
+ // A project name scopes ordinary memory entries, but project-attributed
19
+ // failures still live in (and must be mutated through) the failure store.
20
+ return entry.target === "memory" && entry.project ? "project" : entry.target;
21
+ }
22
+
23
+ function scopeLabel(project: string | null): string {
24
+ return project ? `project:${encodeURIComponent(project)}` : "global";
25
+ }
26
+
27
+ export function registerMemorySearchTool(pi: ExtensionAPI, dbManager: DatabaseManager): void {
28
+ pi.registerTool({
29
+ name: 'memory_search',
30
+ label: 'Memory Search',
31
+ description: `Search extended memory store for relevant entries. Use this when you need context beyond what's in the system prompt — the extended store has unlimited capacity and is searchable.
32
+
33
+ Use cases:
34
+ - Find memories about a specific topic: "What do I know about auth setup?"
35
+ - Search project-specific memories: "What conventions does project X follow?"
36
+ - Find user preferences: "What are the user's testing preferences?"
37
+ - Search for past failures: "memory_search('auth', category='failure')"
38
+
39
+ Returns matching memory entries with their mutation target, scope, and dates. The displayed target is the value required by memory_replace and memory_remove.`,
40
+ promptSnippet: 'Search extended memory store (unlimited capacity)',
41
+ promptGuidelines: [
42
+ 'Use memory_search when you need context beyond what is in the system prompt.',
43
+ 'Use memory_search to find project-specific memories or user preferences.',
44
+ 'Use memory_search with category filter to find specific types of memories (failure, correction, insight, etc.).',
45
+ ],
46
+ renderResult: createSharedToolResultRenderer(searchResultView),
47
+ parameters: Type.Object({
48
+ query: Type.String({ description: 'Search query. Use natural language or specific terms.' }),
49
+ project: Type.Optional(Type.String({ description: 'Filter by project name. Pass null for global memories only.' })),
50
+ target: Type.Optional(StringEnum(['memory', 'user', 'failure'] as const, { description: 'Filter by target type (memory, user, or failure).' })),
51
+ category: Type.Optional(StringEnum(['failure', 'correction', 'insight', 'preference', 'convention', 'tool-quirk'] as const, { description: 'Filter by memory category.' })),
52
+ limit: Type.Optional(Type.Number({ description: 'Maximum results to return (default: 10, max: 20).' })),
53
+ }),
54
+ execute: async (_id: string, args: { query: string; project?: string; target?: string; category?: string; limit?: number }) => {
55
+ const query = args.query;
56
+ const project = args.project;
57
+ const target = args.target;
58
+ const category = args.category as MemoryCategory | undefined;
59
+ const limit = Math.min(args.limit || 10, 20);
60
+
61
+ if (!query || query.trim().length === 0) {
62
+ const result: SearchResult = { success: false, message: 'query is required' };
63
+ return { content: [{ type: 'text' as const, text: result.message! }], details: result };
64
+ }
65
+
66
+ const stats = getMemoryStats(dbManager);
67
+ if (stats.total === 0) {
68
+ const result: SearchResult = { success: false, message: 'No memories in extended store yet. Use memory_add to store memories.' };
69
+ return { content: [{ type: 'text' as const, text: result.message! }], details: result };
70
+ }
71
+
72
+ const results = searchMemories(dbManager, query, { project, target, category, limit });
73
+
74
+ if (results.length === 0) {
75
+ const result: SearchResult = { success: true, count: 0, message: `No memories found matching "${query}". Try a different search term or broader query.` };
76
+ return { content: [{ type: 'text' as const, text: result.message! }], details: result };
77
+ }
78
+
79
+ let output = `Found ${results.length} memories matching "${query}":\n\n`;
80
+
81
+ for (const entry of results) {
82
+ const target = mutationTarget(entry);
83
+ const projectLabel = `scope=${scopeLabel(entry.project)}`;
84
+ const mutationTargetLabel = `[target=${target}]`;
85
+ const targetLabel = entry.target === 'user' ? '👤' : entry.target === 'failure' ? '⚠️' : '🧠';
86
+ const categoryLabel = entry.category ? ` [${entry.category}]` : '';
87
+ output += `${targetLabel} ${projectLabel} ${mutationTargetLabel}${categoryLabel} ${entry.content}\n`;
88
+ output += ` Created: ${entry.created} | Last used: ${entry.lastReferenced}\n\n`;
89
+ }
90
+
91
+ const finalResult: SearchResult = { success: true, count: results.length, output: output.trim() };
92
+ return { content: [{ type: 'text' as const, text: output.trim() }], details: finalResult };
93
+ },
94
+ });
95
+ }