@code-yeongyu/senpi 2026.8.3 → 2026.8.4-2

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 (331) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +9 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/client/remote-session.d.ts +2 -2
  7. package/dist/client/transcript.d.ts +1 -1
  8. package/dist/core/agent-session.d.ts +6 -0
  9. package/dist/core/agent-session.d.ts.map +1 -1
  10. package/dist/core/agent-session.js +174 -39
  11. package/dist/core/agent-session.js.map +1 -1
  12. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-directive-dedupe.d.ts +26 -0
  13. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-directive-dedupe.d.ts.map +1 -0
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-directive-dedupe.js +98 -0
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/prompt-directive-dedupe.js.map +1 -0
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts +4 -0
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts.map +1 -1
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js +2 -0
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js.map +1 -1
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.d.ts.map +1 -1
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js +11 -2
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/session-stream.js.map +1 -1
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js +3 -1
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js.map +1 -1
  26. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +2 -1
  27. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  28. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +126 -26
  29. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  30. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  31. package/dist/core/extensions/builtin/compaction/index.js +12 -7
  32. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  33. package/dist/core/extensions/builtin/compaction/per-turn-cap.d.ts.map +1 -1
  34. package/dist/core/extensions/builtin/compaction/per-turn-cap.js +4 -1
  35. package/dist/core/extensions/builtin/compaction/per-turn-cap.js.map +1 -1
  36. package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts +4 -0
  37. package/dist/core/extensions/builtin/compaction/retained-message-safety.d.ts.map +1 -0
  38. package/dist/core/extensions/builtin/compaction/retained-message-safety.js +155 -0
  39. package/dist/core/extensions/builtin/compaction/retained-message-safety.js.map +1 -0
  40. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/speculative.js +21 -13
  42. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  43. package/dist/core/extensions/builtin/goal/cache-warm-renderer.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js +9 -14
  45. package/dist/core/extensions/builtin/goal/cache-warm-renderer.js.map +1 -1
  46. package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts +1 -0
  47. package/dist/core/extensions/builtin/goal/continuation-recovery.d.ts.map +1 -1
  48. package/dist/core/extensions/builtin/goal/continuation-recovery.js +7 -0
  49. package/dist/core/extensions/builtin/goal/continuation-recovery.js.map +1 -1
  50. package/dist/core/extensions/builtin/goal/continuation.d.ts +2 -1
  51. package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -1
  52. package/dist/core/extensions/builtin/goal/continuation.js +2 -1
  53. package/dist/core/extensions/builtin/goal/continuation.js.map +1 -1
  54. package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
  55. package/dist/core/extensions/builtin/goal/index.js +26 -11
  56. package/dist/core/extensions/builtin/goal/index.js.map +1 -1
  57. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +7 -1
  58. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts.map +1 -1
  59. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +14 -2
  60. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js.map +1 -1
  61. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts +3 -2
  62. package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
  63. package/dist/core/extensions/builtin/goal/monitor-continuation.js +89 -46
  64. package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
  65. package/dist/core/extensions/builtin/goal/wait-progress.d.ts +11 -0
  66. package/dist/core/extensions/builtin/goal/wait-progress.d.ts.map +1 -0
  67. package/dist/core/extensions/builtin/goal/wait-progress.js +30 -0
  68. package/dist/core/extensions/builtin/goal/wait-progress.js.map +1 -0
  69. package/dist/core/extensions/builtin/goal/wait-ticker.d.ts +38 -0
  70. package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -0
  71. package/dist/core/extensions/builtin/goal/wait-ticker.js +71 -0
  72. package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -0
  73. package/dist/core/extensions/builtin/gpt-apply-patch/extension.d.ts.map +1 -1
  74. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js +14 -1
  75. package/dist/core/extensions/builtin/gpt-apply-patch/extension.js.map +1 -1
  76. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts +1 -0
  77. package/dist/core/extensions/builtin/gpt-apply-patch/types.d.ts.map +1 -1
  78. package/dist/core/extensions/builtin/gpt-apply-patch/types.js.map +1 -1
  79. package/dist/core/extensions/builtin/loop-guard/renderer.d.ts.map +1 -1
  80. package/dist/core/extensions/builtin/loop-guard/renderer.js +4 -12
  81. package/dist/core/extensions/builtin/loop-guard/renderer.js.map +1 -1
  82. package/dist/core/extensions/builtin/mcp/expose/schema-compat.js +2 -0
  83. package/dist/core/extensions/builtin/mcp/expose/schema-compat.js.map +1 -1
  84. package/dist/core/extensions/builtin/mcp/service.d.ts +4 -0
  85. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  86. package/dist/core/extensions/builtin/mcp/service.js +11 -0
  87. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  88. package/dist/core/extensions/builtin/rule-activation/index.d.ts +6 -0
  89. package/dist/core/extensions/builtin/rule-activation/index.d.ts.map +1 -0
  90. package/dist/core/extensions/builtin/rule-activation/index.js +10 -0
  91. package/dist/core/extensions/builtin/rule-activation/index.js.map +1 -0
  92. package/dist/core/extensions/builtin/rule-activation/renderer.d.ts +3 -0
  93. package/dist/core/extensions/builtin/rule-activation/renderer.d.ts.map +1 -0
  94. package/dist/core/extensions/builtin/rule-activation/renderer.js +37 -0
  95. package/dist/core/extensions/builtin/rule-activation/renderer.js.map +1 -0
  96. package/dist/core/extensions/builtin/rule-activation/types.d.ts +15 -0
  97. package/dist/core/extensions/builtin/rule-activation/types.d.ts.map +1 -0
  98. package/dist/core/extensions/builtin/rule-activation/types.js +45 -0
  99. package/dist/core/extensions/builtin/rule-activation/types.js.map +1 -0
  100. package/dist/core/extensions/builtin/rules/config.d.ts +3 -0
  101. package/dist/core/extensions/builtin/rules/config.d.ts.map +1 -0
  102. package/dist/core/extensions/builtin/rules/config.js +24 -0
  103. package/dist/core/extensions/builtin/rules/config.js.map +1 -0
  104. package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
  105. package/dist/core/extensions/builtin/rules/index.js +17 -6
  106. package/dist/core/extensions/builtin/rules/index.js.map +1 -1
  107. package/dist/core/extensions/builtin/rules/rules/formatter.d.ts.map +1 -1
  108. package/dist/core/extensions/builtin/rules/rules/formatter.js +21 -5
  109. package/dist/core/extensions/builtin/rules/rules/formatter.js.map +1 -1
  110. package/dist/core/extensions/builtin/rules/rules/types.d.ts +1 -1
  111. package/dist/core/extensions/builtin/rules/rules/types.js.map +1 -1
  112. package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
  113. package/dist/core/extensions/builtin/service-tier.js +2 -3
  114. package/dist/core/extensions/builtin/service-tier.js.map +1 -1
  115. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts +1 -1
  116. package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
  117. package/dist/core/extensions/builtin/terminal/monitor-notify.js +14 -6
  118. package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
  119. package/dist/core/extensions/builtin/ttsr/detectors/repetitive-turns.d.ts +22 -0
  120. package/dist/core/extensions/builtin/ttsr/detectors/repetitive-turns.d.ts.map +1 -0
  121. package/dist/core/extensions/builtin/ttsr/detectors/repetitive-turns.js +93 -0
  122. package/dist/core/extensions/builtin/ttsr/detectors/repetitive-turns.js.map +1 -0
  123. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  124. package/dist/core/extensions/builtin/ttsr/index.js +60 -21
  125. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  126. package/dist/core/extensions/builtin/ttsr/prompts.d.ts +1 -0
  127. package/dist/core/extensions/builtin/ttsr/prompts.d.ts.map +1 -1
  128. package/dist/core/extensions/builtin/ttsr/prompts.js +5 -0
  129. package/dist/core/extensions/builtin/ttsr/prompts.js.map +1 -1
  130. package/dist/core/extensions/builtin/ttsr/repetitive-turns-lane.d.ts +23 -0
  131. package/dist/core/extensions/builtin/ttsr/repetitive-turns-lane.d.ts.map +1 -0
  132. package/dist/core/extensions/builtin/ttsr/repetitive-turns-lane.js +101 -0
  133. package/dist/core/extensions/builtin/ttsr/repetitive-turns-lane.js.map +1 -0
  134. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts +15 -0
  135. package/dist/core/extensions/builtin/ttsr/stream-remediation.d.ts.map +1 -0
  136. package/dist/core/extensions/builtin/ttsr/stream-remediation.js +22 -0
  137. package/dist/core/extensions/builtin/ttsr/stream-remediation.js.map +1 -0
  138. package/dist/core/extensions/builtin/ttsr/types.d.ts +1 -1
  139. package/dist/core/extensions/builtin/ttsr/types.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/ttsr/types.js.map +1 -1
  141. package/dist/core/extensions/notice/adapters.d.ts +15 -0
  142. package/dist/core/extensions/notice/adapters.d.ts.map +1 -0
  143. package/dist/core/extensions/notice/adapters.js +22 -0
  144. package/dist/core/extensions/notice/adapters.js.map +1 -0
  145. package/dist/core/extensions/notice/box.d.ts +8 -0
  146. package/dist/core/extensions/notice/box.d.ts.map +1 -0
  147. package/dist/core/extensions/notice/box.js +17 -0
  148. package/dist/core/extensions/notice/box.js.map +1 -0
  149. package/dist/core/extensions/notice/index.d.ts +4 -0
  150. package/dist/core/extensions/notice/index.d.ts.map +1 -0
  151. package/dist/core/extensions/notice/index.js +3 -0
  152. package/dist/core/extensions/notice/index.js.map +1 -0
  153. package/dist/core/extensions/notice/spec.d.ts +23 -0
  154. package/dist/core/extensions/notice/spec.d.ts.map +1 -0
  155. package/dist/core/extensions/notice/spec.js +2 -0
  156. package/dist/core/extensions/notice/spec.js.map +1 -0
  157. package/dist/core/model-resolver.d.ts.map +1 -1
  158. package/dist/core/model-resolver.js +1 -0
  159. package/dist/core/model-resolver.js.map +1 -1
  160. package/dist/core/model-runtime.d.ts.map +1 -1
  161. package/dist/core/model-runtime.js +2 -2
  162. package/dist/core/model-runtime.js.map +1 -1
  163. package/dist/core/provider-composer.d.ts.map +1 -1
  164. package/dist/core/provider-composer.js +8 -3
  165. package/dist/core/provider-composer.js.map +1 -1
  166. package/dist/core/provider-display-names.d.ts.map +1 -1
  167. package/dist/core/provider-display-names.js +1 -0
  168. package/dist/core/provider-display-names.js.map +1 -1
  169. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  170. package/dist/core/retry-fallback/settings.js +16 -1
  171. package/dist/core/retry-fallback/settings.js.map +1 -1
  172. package/dist/core/retry-fallback/validate.d.ts.map +1 -1
  173. package/dist/core/retry-fallback/validate.js +15 -2
  174. package/dist/core/retry-fallback/validate.js.map +1 -1
  175. package/dist/core/session-log.js +1 -1
  176. package/dist/core/session-log.js.map +1 -1
  177. package/dist/core/settings-manager.d.ts +7 -0
  178. package/dist/core/settings-manager.d.ts.map +1 -1
  179. package/dist/core/settings-manager.js +13 -0
  180. package/dist/core/settings-manager.js.map +1 -1
  181. package/dist/modes/interactive/components/continuity-notice.d.ts.map +1 -1
  182. package/dist/modes/interactive/components/continuity-notice.js +29 -2
  183. package/dist/modes/interactive/components/continuity-notice.js.map +1 -1
  184. package/dist/modes/interactive/components/custom-editor.d.ts +5 -0
  185. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  186. package/dist/modes/interactive/components/custom-editor.js +22 -1
  187. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  188. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  189. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  190. package/dist/modes/interactive/interactive-mode.js +42 -7
  191. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  192. package/dist/modes/interactive/interactive-stderr-guard.d.ts.map +1 -1
  193. package/dist/modes/interactive/interactive-stderr-guard.js +37 -0
  194. package/dist/modes/interactive/interactive-stderr-guard.js.map +1 -1
  195. package/docs/providers.md +29 -0
  196. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
  197. package/node_modules/@code-yeongyu/senpi-codemode/README.md +13 -3
  198. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  199. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/eval-status.ts +1 -1
  200. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +6 -6
  201. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-runtime.ts +4 -4
  202. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +2 -2
  203. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-snapshot.ts +2 -2
  204. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-request.ts +20 -2
  205. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +17 -2
  206. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +18 -7
  207. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +19 -5
  208. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  209. package/node_modules/@earendil-works/pi-ai/README.md +3 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  212. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
  213. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -0
  214. package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
  215. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +2 -2
  216. package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
  217. package/node_modules/@earendil-works/pi-ai/dist/models.js +1 -1
  218. package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
  219. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts +2 -1
  220. package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
  221. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +3 -1
  222. package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  224. package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
  225. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  231. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  234. package/node_modules/@earendil-works/pi-ai/dist/providers/ollama.d.ts +9 -0
  235. package/node_modules/@earendil-works/pi-ai/dist/providers/ollama.d.ts.map +1 -0
  236. package/node_modules/@earendil-works/pi-ai/dist/providers/ollama.js +142 -0
  237. package/node_modules/@earendil-works/pi-ai/dist/providers/ollama.js.map +1 -0
  238. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +1 -1
  239. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  241. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  242. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  243. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  244. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -1
  245. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  246. package/node_modules/@earendil-works/pi-tui/dist/slash-command-autocomplete.d.ts.map +1 -1
  247. package/node_modules/@earendil-works/pi-tui/dist/slash-command-autocomplete.js +36 -8
  248. package/node_modules/@earendil-works/pi-tui/dist/slash-command-autocomplete.js.map +1 -1
  249. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +2 -0
  250. package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
  251. package/node_modules/@earendil-works/pi-tui/dist/tui.js +49 -33
  252. package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
  253. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  254. package/package.json +8 -13
  255. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/client.d.ts +1 -1
  256. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/client.js +1 -1
  257. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/connection.d.ts +1 -1
  258. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/connection.js +1 -1
  259. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/errors.d.ts +1 -1
  260. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/session-handle.d.ts +1 -1
  261. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/state.d.ts +1 -1
  262. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/types.d.ts +1 -1
  263. package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/unix.js +1 -1
  264. package/node_modules/@earendil-works/pi-client/CHANGELOG.md +0 -7
  265. package/node_modules/@earendil-works/pi-client/README.md +0 -64
  266. package/node_modules/@earendil-works/pi-client/package.json +0 -56
  267. package/node_modules/@earendil-works/pi-protocol/README.md +0 -68
  268. package/node_modules/@earendil-works/pi-protocol/package.json +0 -48
  269. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/client.d.ts.map +0 -0
  270. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/client.js.map +0 -0
  271. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/connection.d.ts.map +0 -0
  272. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/connection.js.map +0 -0
  273. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/errors.d.ts.map +0 -0
  274. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/errors.js +0 -0
  275. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/errors.js.map +0 -0
  276. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/index.d.ts +0 -0
  277. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/index.d.ts.map +0 -0
  278. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/index.js +0 -0
  279. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/index.js.map +0 -0
  280. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/promise.d.ts +0 -0
  281. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/promise.d.ts.map +0 -0
  282. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/promise.js +0 -0
  283. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/promise.js.map +0 -0
  284. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/session-handle.d.ts.map +0 -0
  285. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/session-handle.js +0 -0
  286. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/session-handle.js.map +0 -0
  287. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/state.d.ts.map +0 -0
  288. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/state.js +0 -0
  289. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/state.js.map +0 -0
  290. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/transport.d.ts +0 -0
  291. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/transport.d.ts.map +0 -0
  292. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/transport.js +0 -0
  293. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/transport.js.map +0 -0
  294. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/types.d.ts.map +0 -0
  295. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/types.js +0 -0
  296. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/types.js.map +0 -0
  297. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/unix.d.ts +0 -0
  298. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/unix.d.ts.map +0 -0
  299. /package/{node_modules/@earendil-works/pi-client/dist → vendor/pi-client}/unix.js.map +0 -0
  300. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/decoder.d.ts +0 -0
  301. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/decoder.d.ts.map +0 -0
  302. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/decoder.js +0 -0
  303. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/decoder.js.map +0 -0
  304. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/encoder.d.ts +0 -0
  305. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/encoder.d.ts.map +0 -0
  306. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/encoder.js +0 -0
  307. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/encoder.js.map +0 -0
  308. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/index.d.ts +0 -0
  309. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/index.d.ts.map +0 -0
  310. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/index.js +0 -0
  311. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/index.js.map +0 -0
  312. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/options.d.ts +0 -0
  313. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/options.d.ts.map +0 -0
  314. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/options.js +0 -0
  315. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/cbor/options.js.map +0 -0
  316. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/codec.d.ts +0 -0
  317. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/codec.d.ts.map +0 -0
  318. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/codec.js +0 -0
  319. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/codec.js.map +0 -0
  320. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/framing.d.ts +0 -0
  321. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/framing.d.ts.map +0 -0
  322. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/framing.js +0 -0
  323. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/framing.js.map +0 -0
  324. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/index.d.ts +0 -0
  325. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/index.d.ts.map +0 -0
  326. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/index.js +0 -0
  327. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/index.js.map +0 -0
  328. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/schemas.d.ts +0 -0
  329. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/schemas.d.ts.map +0 -0
  330. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/schemas.js +0 -0
  331. /package/{node_modules/@earendil-works/pi-protocol/dist → vendor/pi-protocol}/schemas.js.map +0 -0
@@ -0,0 +1,10 @@
1
+ import { renderRuleActivationEntry } from "./renderer.js";
2
+ import { RULE_ACTIVATION_ENTRY_TYPE } from "./types.js";
3
+ export { RULE_ACTIVATION_ENTRY_TYPE, } from "./types.js";
4
+ export function registerRuleActivationRenderer(pi) {
5
+ pi.registerEntryRenderer(RULE_ACTIVATION_ENTRY_TYPE, renderRuleActivationEntry);
6
+ }
7
+ export function appendRuleActivation(pi, details) {
8
+ pi.appendEntry(RULE_ACTIVATION_ENTRY_TYPE, details);
9
+ }
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rule-activation/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAA8B,MAAM,YAAY,CAAC;AAEpF,OAAO,EAEN,0BAA0B,GAG1B,MAAM,YAAY,CAAC;AAEpB,MAAM,UAAU,8BAA8B,CAAC,EAAgB;IAC9D,EAAE,CAAC,qBAAqB,CAAC,0BAA0B,EAAE,yBAAyB,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EAAgB,EAAE,OAA8B;IACpF,EAAE,CAAC,WAAW,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC","sourcesContent":["import type { ExtensionAPI } from \"../../types.ts\";\nimport { renderRuleActivationEntry } from \"./renderer.ts\";\nimport { RULE_ACTIVATION_ENTRY_TYPE, type RuleActivationDetails } from \"./types.ts\";\n\nexport {\n\ttype ProjectRulesActivationDetails,\n\tRULE_ACTIVATION_ENTRY_TYPE,\n\ttype RuleActivationDetails,\n\ttype TtsrActivationDetails,\n} from \"./types.ts\";\n\nexport function registerRuleActivationRenderer(pi: ExtensionAPI): void {\n\tpi.registerEntryRenderer(RULE_ACTIVATION_ENTRY_TYPE, renderRuleActivationEntry);\n}\n\nexport function appendRuleActivation(pi: ExtensionAPI, details: RuleActivationDetails): void {\n\tpi.appendEntry(RULE_ACTIVATION_ENTRY_TYPE, details);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { EntryRenderer } from "../../types.ts";
2
+ export declare const renderRuleActivationEntry: EntryRenderer<unknown>;
3
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rule-activation/renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,eAAO,MAAM,yBAAyB,EAAE,aAAa,CAAC,OAAO,CAI3D,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { noticeEntryRenderer } from "../../notice/index.js";
2
+ import { parseRuleActivationDetails } from "./types.js";
3
+ export const renderRuleActivationEntry = noticeEntryRenderer((entry) => {
4
+ const details = parseRuleActivationDetails(entry.data);
5
+ if (details === undefined)
6
+ return undefined;
7
+ return { title: titleLine(details), why: summaryLine(details), expandedLine: detailLine(details) };
8
+ });
9
+ function titleLine(details) {
10
+ switch (details.kind) {
11
+ case "project-rules":
12
+ return `● Project rules · ${details.targetPath}`;
13
+ case "ttsr":
14
+ return `⚠ Stream rule · ${details.owner}`;
15
+ }
16
+ }
17
+ function summaryLine(details) {
18
+ switch (details.kind) {
19
+ case "project-rules": {
20
+ const noun = details.rules.length === 1 ? "instruction" : "instructions";
21
+ return `${details.rules.length} ${noun} matched and injected for this tool result.`;
22
+ }
23
+ case "ttsr":
24
+ return details.remediation === "nudge"
25
+ ? "Output interrupted; a corrective nudge was queued."
26
+ : "Corrupted generation discarded; bounded provider retry started.";
27
+ }
28
+ }
29
+ function detailLine(details) {
30
+ switch (details.kind) {
31
+ case "project-rules":
32
+ return details.rules.map((rule) => `rule ${rule}`).join("\n");
33
+ case "ttsr":
34
+ return `remediation ${details.remediation} · observed ${details.rules.join(", ")}`;
35
+ }
36
+ }
37
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rule-activation/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,0BAA0B,EAA8B,MAAM,YAAY,CAAC;AAEpF,MAAM,CAAC,MAAM,yBAAyB,GAA2B,mBAAmB,CAAC,CAAC,KAAK,EAAE,EAAE;IAC9F,MAAM,OAAO,GAAG,0BAA0B,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;AACpG,CAAC,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,OAA8B;IAChD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,eAAe;YACnB,OAAO,qBAAqB,OAAO,CAAC,UAAU,EAAE,CAAC;QAClD,KAAK,MAAM;YACV,OAAO,mBAAmB,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5C,CAAC;AACF,CAAC;AAED,SAAS,WAAW,CAAC,OAA8B;IAClD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,eAAe,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;YACzE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,6CAA6C,CAAC;QACrF,CAAC;QACD,KAAK,MAAM;YACV,OAAO,OAAO,CAAC,WAAW,KAAK,OAAO;gBACrC,CAAC,CAAC,oDAAoD;gBACtD,CAAC,CAAC,iEAAiE,CAAC;IACvE,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,OAA8B;IACjD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,eAAe;YACnB,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,KAAK,MAAM;YACV,OAAO,eAAe,OAAO,CAAC,WAAW,eAAe,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACrF,CAAC;AACF,CAAC","sourcesContent":["import { noticeEntryRenderer } from \"../../notice/index.ts\";\nimport type { EntryRenderer } from \"../../types.ts\";\nimport { parseRuleActivationDetails, type RuleActivationDetails } from \"./types.ts\";\n\nexport const renderRuleActivationEntry: EntryRenderer<unknown> = noticeEntryRenderer((entry) => {\n\tconst details = parseRuleActivationDetails(entry.data);\n\tif (details === undefined) return undefined;\n\treturn { title: titleLine(details), why: summaryLine(details), expandedLine: detailLine(details) };\n});\n\nfunction titleLine(details: RuleActivationDetails): string {\n\tswitch (details.kind) {\n\t\tcase \"project-rules\":\n\t\t\treturn `● Project rules · ${details.targetPath}`;\n\t\tcase \"ttsr\":\n\t\t\treturn `⚠ Stream rule · ${details.owner}`;\n\t}\n}\n\nfunction summaryLine(details: RuleActivationDetails): string {\n\tswitch (details.kind) {\n\t\tcase \"project-rules\": {\n\t\t\tconst noun = details.rules.length === 1 ? \"instruction\" : \"instructions\";\n\t\t\treturn `${details.rules.length} ${noun} matched and injected for this tool result.`;\n\t\t}\n\t\tcase \"ttsr\":\n\t\t\treturn details.remediation === \"nudge\"\n\t\t\t\t? \"Output interrupted; a corrective nudge was queued.\"\n\t\t\t\t: \"Corrupted generation discarded; bounded provider retry started.\";\n\t}\n}\n\nfunction detailLine(details: RuleActivationDetails): string {\n\tswitch (details.kind) {\n\t\tcase \"project-rules\":\n\t\t\treturn details.rules.map((rule) => `rule ${rule}`).join(\"\\n\");\n\t\tcase \"ttsr\":\n\t\t\treturn `remediation ${details.remediation} · observed ${details.rules.join(\", \")}`;\n\t}\n}\n"]}
@@ -0,0 +1,15 @@
1
+ export declare const RULE_ACTIVATION_ENTRY_TYPE = "rule-activation";
2
+ export interface ProjectRulesActivationDetails {
3
+ readonly kind: "project-rules";
4
+ readonly targetPath: string;
5
+ readonly rules: readonly string[];
6
+ }
7
+ export interface TtsrActivationDetails {
8
+ readonly kind: "ttsr";
9
+ readonly owner: string;
10
+ readonly rules: readonly string[];
11
+ readonly remediation: "nudge" | "provider-error";
12
+ }
13
+ export type RuleActivationDetails = ProjectRulesActivationDetails | TtsrActivationDetails;
14
+ export declare function parseRuleActivationDetails(value: unknown): RuleActivationDetails | undefined;
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rule-activation/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAE5D,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACjD;AAED,MAAM,MAAM,qBAAqB,GAAG,6BAA6B,GAAG,qBAAqB,CAAC;AAE1F,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GAAG,SAAS,CAW5F"}
@@ -0,0 +1,45 @@
1
+ export const RULE_ACTIVATION_ENTRY_TYPE = "rule-activation";
2
+ export function parseRuleActivationDetails(value) {
3
+ if (!isObject(value))
4
+ return undefined;
5
+ const kind = Reflect.get(value, "kind");
6
+ switch (kind) {
7
+ case "project-rules":
8
+ return parseProjectRulesActivation(value);
9
+ case "ttsr":
10
+ return parseTtsrActivation(value);
11
+ default:
12
+ return undefined;
13
+ }
14
+ }
15
+ function parseProjectRulesActivation(value) {
16
+ const targetPath = Reflect.get(value, "targetPath");
17
+ const rules = stringList(Reflect.get(value, "rules"));
18
+ if (typeof targetPath !== "string" || targetPath.length === 0 || rules === undefined)
19
+ return undefined;
20
+ return { kind: "project-rules", targetPath, rules };
21
+ }
22
+ function parseTtsrActivation(value) {
23
+ const owner = Reflect.get(value, "owner");
24
+ const rules = stringList(Reflect.get(value, "rules"));
25
+ const remediation = Reflect.get(value, "remediation");
26
+ if (typeof owner !== "string" ||
27
+ owner.length === 0 ||
28
+ rules === undefined ||
29
+ (remediation !== "nudge" && remediation !== "provider-error")) {
30
+ return undefined;
31
+ }
32
+ return { kind: "ttsr", owner, rules, remediation };
33
+ }
34
+ function stringList(value) {
35
+ if (!Array.isArray(value) ||
36
+ value.length === 0 ||
37
+ !value.every((entry) => typeof entry === "string" && entry.length > 0)) {
38
+ return undefined;
39
+ }
40
+ return value;
41
+ }
42
+ function isObject(value) {
43
+ return typeof value === "object" && value !== null && !Array.isArray(value);
44
+ }
45
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rule-activation/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAiB5D,MAAM,UAAU,0BAA0B,CAAC,KAAc;IACxD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACxC,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,eAAe;YACnB,OAAO,2BAA2B,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,MAAM;YACV,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACnC;YACC,OAAO,SAAS,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAS,2BAA2B,CAAC,KAAa;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACvG,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACtD,IACC,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,MAAM,KAAK,CAAC;QAClB,KAAK,KAAK,SAAS;QACnB,CAAC,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,gBAAgB,CAAC,EAC5D,CAAC;QACF,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IACjC,IACC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,KAAK,CAAC,MAAM,KAAK,CAAC;QAClB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EACrE,CAAC;QACF,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["export const RULE_ACTIVATION_ENTRY_TYPE = \"rule-activation\";\n\nexport interface ProjectRulesActivationDetails {\n\treadonly kind: \"project-rules\";\n\treadonly targetPath: string;\n\treadonly rules: readonly string[];\n}\n\nexport interface TtsrActivationDetails {\n\treadonly kind: \"ttsr\";\n\treadonly owner: string;\n\treadonly rules: readonly string[];\n\treadonly remediation: \"nudge\" | \"provider-error\";\n}\n\nexport type RuleActivationDetails = ProjectRulesActivationDetails | TtsrActivationDetails;\n\nexport function parseRuleActivationDetails(value: unknown): RuleActivationDetails | undefined {\n\tif (!isObject(value)) return undefined;\n\tconst kind = Reflect.get(value, \"kind\");\n\tswitch (kind) {\n\t\tcase \"project-rules\":\n\t\t\treturn parseProjectRulesActivation(value);\n\t\tcase \"ttsr\":\n\t\t\treturn parseTtsrActivation(value);\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nfunction parseProjectRulesActivation(value: object): ProjectRulesActivationDetails | undefined {\n\tconst targetPath = Reflect.get(value, \"targetPath\");\n\tconst rules = stringList(Reflect.get(value, \"rules\"));\n\tif (typeof targetPath !== \"string\" || targetPath.length === 0 || rules === undefined) return undefined;\n\treturn { kind: \"project-rules\", targetPath, rules };\n}\n\nfunction parseTtsrActivation(value: object): TtsrActivationDetails | undefined {\n\tconst owner = Reflect.get(value, \"owner\");\n\tconst rules = stringList(Reflect.get(value, \"rules\"));\n\tconst remediation = Reflect.get(value, \"remediation\");\n\tif (\n\t\ttypeof owner !== \"string\" ||\n\t\towner.length === 0 ||\n\t\trules === undefined ||\n\t\t(remediation !== \"nudge\" && remediation !== \"provider-error\")\n\t) {\n\t\treturn undefined;\n\t}\n\treturn { kind: \"ttsr\", owner, rules, remediation };\n}\n\nfunction stringList(value: unknown): readonly string[] | undefined {\n\tif (\n\t\t!Array.isArray(value) ||\n\t\tvalue.length === 0 ||\n\t\t!value.every((entry) => typeof entry === \"string\" && entry.length > 0)\n\t) {\n\t\treturn undefined;\n\t}\n\treturn value;\n}\n\nfunction isObject(value: unknown): value is object {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { PiRulesConfig } from "./rules/types.ts";
2
+ export declare function configFromEnvironment(env?: NodeJS.ProcessEnv): PiRulesConfig;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,aAAa,CAOzF"}
@@ -0,0 +1,24 @@
1
+ import { defaultConfig } from "./rules/engine.js";
2
+ const TRUTHY_VALUES = new Set(["1", "true", "yes", "on"]);
3
+ export function configFromEnvironment(env = process.env) {
4
+ const config = defaultConfig();
5
+ const disabled = readEnv(env, "PI_RULES_DISABLED");
6
+ config.disabled = disabled !== undefined && TRUTHY_VALUES.has(disabled.trim().toLowerCase());
7
+ config.maxRuleChars = parsePositiveInteger(readEnv(env, "PI_RULES_MAX_RULE_CHARS")) ?? config.maxRuleChars;
8
+ config.maxResultChars = parsePositiveInteger(readEnv(env, "PI_RULES_MAX_RESULT_CHARS")) ?? config.maxResultChars;
9
+ return config;
10
+ }
11
+ function readEnv(env, name) {
12
+ const value = env[name];
13
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
14
+ }
15
+ function parsePositiveInteger(value) {
16
+ if (value === undefined)
17
+ return undefined;
18
+ const normalized = value.trim();
19
+ if (!/^\d+$/.test(normalized))
20
+ return undefined;
21
+ const parsed = Number(normalized);
22
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
23
+ }
24
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,qBAAqB,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IACzE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IACnD,MAAM,CAAC,QAAQ,GAAG,QAAQ,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7F,MAAM,CAAC,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC;IAC3G,MAAM,CAAC,cAAc,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC;IACjH,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CAAC,GAAsB,EAAE,IAAY;IACpD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACjF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACtD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACxE,CAAC","sourcesContent":["import { defaultConfig } from \"./rules/engine.ts\";\nimport type { PiRulesConfig } from \"./rules/types.ts\";\n\nconst TRUTHY_VALUES = new Set([\"1\", \"true\", \"yes\", \"on\"]);\n\nexport function configFromEnvironment(env: NodeJS.ProcessEnv = process.env): PiRulesConfig {\n\tconst config = defaultConfig();\n\tconst disabled = readEnv(env, \"PI_RULES_DISABLED\");\n\tconfig.disabled = disabled !== undefined && TRUTHY_VALUES.has(disabled.trim().toLowerCase());\n\tconfig.maxRuleChars = parsePositiveInteger(readEnv(env, \"PI_RULES_MAX_RULE_CHARS\")) ?? config.maxRuleChars;\n\tconfig.maxResultChars = parsePositiveInteger(readEnv(env, \"PI_RULES_MAX_RESULT_CHARS\")) ?? config.maxResultChars;\n\treturn config;\n}\n\nfunction readEnv(env: NodeJS.ProcessEnv, name: string): string | undefined {\n\tconst value = env[name];\n\treturn typeof value === \"string\" && value.trim().length > 0 ? value : undefined;\n}\n\nfunction parsePositiveInteger(value: string | undefined): number | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = value.trim();\n\tif (!/^\\d+$/.test(normalized)) return undefined;\n\tconst parsed = Number(normalized);\n\treturn Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAanD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAkI/D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAgBnD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA0I/D"}
@@ -1,11 +1,14 @@
1
1
  import { readFileSync, realpathSync } from "node:fs";
2
2
  import { isAbsolute, relative } from "node:path";
3
+ import { appendRuleActivation, registerRuleActivationRenderer } from "../rule-activation/index.js";
3
4
  import { registerSlashCommands } from "./commands.js";
4
- import { createEngine, defaultConfig } from "./rules/engine.js";
5
+ import { configFromEnvironment } from "./config.js";
6
+ import { createEngine } from "./rules/engine.js";
5
7
  import { findRuleCandidates } from "./rules/finder.js";
6
8
  import { findProjectRoot } from "./rules/project-root.js";
7
9
  import { extractToolPaths } from "./rules/tool-paths.js";
8
10
  const MODE_VALUES = new Set(["static", "dynamic", "both", "off"]);
11
+ const DYNAMIC_CONTEXT_SCOPE = "live-context";
9
12
  export default function piRulesExtension(pi) {
10
13
  pi.registerFlag("pi-rules-disabled", {
11
14
  type: "boolean",
@@ -17,7 +20,8 @@ export default function piRulesExtension(pi) {
17
20
  default: "both",
18
21
  description: "Rule injection mode: static, dynamic, both, or off.",
19
22
  });
20
- const config = defaultConfig();
23
+ const config = configFromEnvironment();
24
+ const envDisabled = config.disabled;
21
25
  const engine = createEngine(config, {
22
26
  findCandidates: findRuleCandidates,
23
27
  readFile: (path) => {
@@ -32,11 +36,12 @@ export default function piRulesExtension(pi) {
32
36
  extractToolPaths,
33
37
  });
34
38
  registerSlashCommands(pi, engine);
39
+ registerRuleActivationRenderer(pi);
35
40
  function syncConfigFromFlags() {
36
41
  const disabled = pi.getFlag("pi-rules-disabled");
37
42
  const mode = pi.getFlag("pi-rules-mode");
38
43
  if (typeof disabled === "boolean") {
39
- engine.config.disabled = disabled;
44
+ engine.config.disabled = disabled || envDisabled;
40
45
  }
41
46
  if (typeof mode === "string" && isPiRulesMode(mode)) {
42
47
  engine.config.mode = mode;
@@ -102,15 +107,21 @@ export default function piRulesExtension(pi) {
102
107
  }
103
108
  const loaded = engine.loadDynamicRules(ctx.cwd, pendingFingerprints.map((target) => target.targetPath));
104
109
  engine.commitDynamicTargetFingerprints(fingerprints);
105
- const rules = loaded.rules.filter((rule) => !engine.isStaticInjected(rule) && !engine.isDynamicInjected(firstTargetPath, rule));
110
+ const rules = loaded.rules.filter((rule) => !engine.isStaticInjected(rule) && !engine.isDynamicInjected(DYNAMIC_CONTEXT_SCOPE, rule));
106
111
  if (rules.length === 0) {
107
112
  return undefined;
108
113
  }
109
114
  const firstPendingTarget = pendingFingerprints[0]?.targetPath ?? firstTargetPath;
110
- const block = engine.formatDynamic(rules, displayPath(ctx.cwd, firstPendingTarget));
115
+ const targetPath = displayPath(ctx.cwd, firstPendingTarget);
116
+ const block = engine.formatDynamic(rules, targetPath);
111
117
  for (const rule of rules) {
112
- engine.markDynamicInjected(firstTargetPath, rule);
118
+ engine.markDynamicInjected(DYNAMIC_CONTEXT_SCOPE, rule);
113
119
  }
120
+ appendRuleActivation(pi, {
121
+ kind: "project-rules",
122
+ targetPath,
123
+ rules: rules.map((rule) => rule.relativePath),
124
+ });
114
125
  return { content: [...event.content, { type: "text", text: block }] };
115
126
  });
116
127
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, realpathSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\n\nimport type { ExtensionAPI } from \"../../types.ts\";\n\nimport { registerSlashCommands } from \"./commands.ts\";\nimport { createEngine, defaultConfig } from \"./rules/engine.ts\";\nimport { findRuleCandidates } from \"./rules/finder.ts\";\nimport { findProjectRoot } from \"./rules/project-root.ts\";\nimport { extractToolPaths } from \"./rules/tool-paths.ts\";\nimport type { PiRulesConfig } from \"./rules/types.ts\";\n\ntype PiRulesMode = PiRulesConfig[\"mode\"];\n\nconst MODE_VALUES = new Set<string>([\"static\", \"dynamic\", \"both\", \"off\"]);\n\nexport default function piRulesExtension(pi: ExtensionAPI): void {\n\tpi.registerFlag(\"pi-rules-disabled\", {\n\t\ttype: \"boolean\",\n\t\tdefault: false,\n\t\tdescription: \"Disable pi-rules hooks.\",\n\t});\n\tpi.registerFlag(\"pi-rules-mode\", {\n\t\ttype: \"string\",\n\t\tdefault: \"both\",\n\t\tdescription: \"Rule injection mode: static, dynamic, both, or off.\",\n\t});\n\tconst config = defaultConfig();\n\tconst engine = createEngine(config, {\n\t\tfindCandidates: findRuleCandidates,\n\t\treadFile: (path) => {\n\t\t\ttry {\n\t\t\t\treturn readFileSync(path, \"utf-8\");\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tfindProjectRoot,\n\t\textractToolPaths,\n\t});\n\tregisterSlashCommands(pi, engine);\n\n\tfunction syncConfigFromFlags(): void {\n\t\tconst disabled = pi.getFlag(\"pi-rules-disabled\");\n\t\tconst mode = pi.getFlag(\"pi-rules-mode\");\n\n\t\tif (typeof disabled === \"boolean\") {\n\t\t\tengine.config.disabled = disabled;\n\t\t}\n\t\tif (typeof mode === \"string\" && isPiRulesMode(mode)) {\n\t\t\tengine.config.mode = mode;\n\t\t}\n\t}\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tengine.resetSession(ctx.cwd);\n\t\tpi.appendEntry(\"pi-rules.scan\", { cwd: ctx.cwd, reason: event.reason });\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"session_compact\", async (event, ctx) => {\n\t\t// Rejected compactions do not mutate session state; do not reset rules.\n\t\tif (!event.accepted) return undefined;\n\t\tengine.resetSession(ctx.cwd);\n\t\tpi.appendEntry(\"pi-rules.scan\", { cwd: ctx.cwd, reason: \"compact\" });\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled || engine.config.mode === \"off\" || engine.config.mode === \"dynamic\") {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst loaded = engine.loadStaticRules(ctx.cwd);\n\t\tconst nativeContextPaths = new Set(\n\t\t\tevent.systemPromptOptions.contextFiles?.flatMap((contextFile) => pathKeys(contextFile.path)) ?? [],\n\t\t);\n\t\tfor (const rule of loaded.rules) {\n\t\t\tif (nativeContextPaths.has(rule.path) || nativeContextPaths.has(rule.realPath)) {\n\t\t\t\tengine.markStaticInjected(rule);\n\t\t\t}\n\t\t}\n\t\t// Deliberately NOT gated on isStaticInjected: the host re-emits this from the BASE prompt\n\t\t// every user prompt, so a prior turn's mark would drop the block from turn 2 onward. The\n\t\t// marks below serve only the dynamic tool_result path.\n\t\tconst rules = loaded.rules.filter(\n\t\t\t(rule) => !nativeContextPaths.has(rule.path) && !nativeContextPaths.has(rule.realPath),\n\t\t);\n\n\t\tif (rules.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst block = engine.formatStatic(rules);\n\t\tfor (const rule of rules) {\n\t\t\tengine.markStaticInjected(rule);\n\t\t}\n\n\t\treturn { systemPrompt: event.systemPrompt + block };\n\t});\n\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled || engine.config.mode === \"off\" || engine.config.mode === \"static\" || event.isError) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst targetPaths = extractToolPaths(event, ctx.cwd);\n\t\tconst firstTargetPath = targetPaths[0];\n\t\tif (firstTargetPath === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst fingerprints = engine.fingerprintDynamicTargets(ctx.cwd, targetPaths);\n\t\tconst pendingFingerprints = fingerprints.filter((target) => !engine.isDynamicTargetFingerprintCurrent(target));\n\t\tif (pendingFingerprints.length === 0) {\n\t\t\tengine.commitDynamicTargetFingerprints(fingerprints);\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst loaded = engine.loadDynamicRules(\n\t\t\tctx.cwd,\n\t\t\tpendingFingerprints.map((target) => target.targetPath),\n\t\t);\n\t\tengine.commitDynamicTargetFingerprints(fingerprints);\n\t\tconst rules = loaded.rules.filter(\n\t\t\t(rule) => !engine.isStaticInjected(rule) && !engine.isDynamicInjected(firstTargetPath, rule),\n\t\t);\n\t\tif (rules.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst firstPendingTarget = pendingFingerprints[0]?.targetPath ?? firstTargetPath;\n\t\tconst block = engine.formatDynamic(rules, displayPath(ctx.cwd, firstPendingTarget));\n\t\tfor (const rule of rules) {\n\t\t\tengine.markDynamicInjected(firstTargetPath, rule);\n\t\t}\n\n\t\treturn { content: [...event.content, { type: \"text\", text: block }] };\n\t});\n}\n\nfunction isPiRulesMode(value: string): value is PiRulesMode {\n\treturn MODE_VALUES.has(value);\n}\n\nfunction pathKeys(filePath: string): string[] {\n\ttry {\n\t\treturn [filePath, realpathSync.native(filePath)];\n\t} catch {\n\t\treturn [filePath];\n\t}\n}\n\nfunction displayPath(cwd: string, filePath: string): string {\n\treturn isAbsolute(filePath) ? relative(cwd, filePath) : filePath;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/rules/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, realpathSync } from \"node:fs\";\nimport { isAbsolute, relative } from \"node:path\";\n\nimport type { ExtensionAPI } from \"../../types.ts\";\n\nimport { appendRuleActivation, registerRuleActivationRenderer } from \"../rule-activation/index.ts\";\nimport { registerSlashCommands } from \"./commands.ts\";\nimport { configFromEnvironment } from \"./config.ts\";\nimport { createEngine } from \"./rules/engine.ts\";\nimport { findRuleCandidates } from \"./rules/finder.ts\";\nimport { findProjectRoot } from \"./rules/project-root.ts\";\nimport { extractToolPaths } from \"./rules/tool-paths.ts\";\nimport type { PiRulesConfig } from \"./rules/types.ts\";\n\ntype PiRulesMode = PiRulesConfig[\"mode\"];\n\nconst MODE_VALUES = new Set<string>([\"static\", \"dynamic\", \"both\", \"off\"]);\nconst DYNAMIC_CONTEXT_SCOPE = \"live-context\";\n\nexport default function piRulesExtension(pi: ExtensionAPI): void {\n\tpi.registerFlag(\"pi-rules-disabled\", {\n\t\ttype: \"boolean\",\n\t\tdefault: false,\n\t\tdescription: \"Disable pi-rules hooks.\",\n\t});\n\tpi.registerFlag(\"pi-rules-mode\", {\n\t\ttype: \"string\",\n\t\tdefault: \"both\",\n\t\tdescription: \"Rule injection mode: static, dynamic, both, or off.\",\n\t});\n\tconst config = configFromEnvironment();\n\tconst envDisabled = config.disabled;\n\tconst engine = createEngine(config, {\n\t\tfindCandidates: findRuleCandidates,\n\t\treadFile: (path) => {\n\t\t\ttry {\n\t\t\t\treturn readFileSync(path, \"utf-8\");\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tfindProjectRoot,\n\t\textractToolPaths,\n\t});\n\tregisterSlashCommands(pi, engine);\n\tregisterRuleActivationRenderer(pi);\n\n\tfunction syncConfigFromFlags(): void {\n\t\tconst disabled = pi.getFlag(\"pi-rules-disabled\");\n\t\tconst mode = pi.getFlag(\"pi-rules-mode\");\n\n\t\tif (typeof disabled === \"boolean\") {\n\t\t\tengine.config.disabled = disabled || envDisabled;\n\t\t}\n\t\tif (typeof mode === \"string\" && isPiRulesMode(mode)) {\n\t\t\tengine.config.mode = mode;\n\t\t}\n\t}\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tengine.resetSession(ctx.cwd);\n\t\tpi.appendEntry(\"pi-rules.scan\", { cwd: ctx.cwd, reason: event.reason });\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"session_compact\", async (event, ctx) => {\n\t\t// Rejected compactions do not mutate session state; do not reset rules.\n\t\tif (!event.accepted) return undefined;\n\t\tengine.resetSession(ctx.cwd);\n\t\tpi.appendEntry(\"pi-rules.scan\", { cwd: ctx.cwd, reason: \"compact\" });\n\t\treturn undefined;\n\t});\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled || engine.config.mode === \"off\" || engine.config.mode === \"dynamic\") {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst loaded = engine.loadStaticRules(ctx.cwd);\n\t\tconst nativeContextPaths = new Set(\n\t\t\tevent.systemPromptOptions.contextFiles?.flatMap((contextFile) => pathKeys(contextFile.path)) ?? [],\n\t\t);\n\t\tfor (const rule of loaded.rules) {\n\t\t\tif (nativeContextPaths.has(rule.path) || nativeContextPaths.has(rule.realPath)) {\n\t\t\t\tengine.markStaticInjected(rule);\n\t\t\t}\n\t\t}\n\t\t// Deliberately NOT gated on isStaticInjected: the host re-emits this from the BASE prompt\n\t\t// every user prompt, so a prior turn's mark would drop the block from turn 2 onward. The\n\t\t// marks below serve only the dynamic tool_result path.\n\t\tconst rules = loaded.rules.filter(\n\t\t\t(rule) => !nativeContextPaths.has(rule.path) && !nativeContextPaths.has(rule.realPath),\n\t\t);\n\n\t\tif (rules.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst block = engine.formatStatic(rules);\n\t\tfor (const rule of rules) {\n\t\t\tengine.markStaticInjected(rule);\n\t\t}\n\n\t\treturn { systemPrompt: event.systemPrompt + block };\n\t});\n\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tsyncConfigFromFlags();\n\t\tif (engine.config.disabled || engine.config.mode === \"off\" || engine.config.mode === \"static\" || event.isError) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst targetPaths = extractToolPaths(event, ctx.cwd);\n\t\tconst firstTargetPath = targetPaths[0];\n\t\tif (firstTargetPath === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst fingerprints = engine.fingerprintDynamicTargets(ctx.cwd, targetPaths);\n\t\tconst pendingFingerprints = fingerprints.filter((target) => !engine.isDynamicTargetFingerprintCurrent(target));\n\t\tif (pendingFingerprints.length === 0) {\n\t\t\tengine.commitDynamicTargetFingerprints(fingerprints);\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst loaded = engine.loadDynamicRules(\n\t\t\tctx.cwd,\n\t\t\tpendingFingerprints.map((target) => target.targetPath),\n\t\t);\n\t\tengine.commitDynamicTargetFingerprints(fingerprints);\n\t\tconst rules = loaded.rules.filter(\n\t\t\t(rule) => !engine.isStaticInjected(rule) && !engine.isDynamicInjected(DYNAMIC_CONTEXT_SCOPE, rule),\n\t\t);\n\t\tif (rules.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst firstPendingTarget = pendingFingerprints[0]?.targetPath ?? firstTargetPath;\n\t\tconst targetPath = displayPath(ctx.cwd, firstPendingTarget);\n\t\tconst block = engine.formatDynamic(rules, targetPath);\n\t\tfor (const rule of rules) {\n\t\t\tengine.markDynamicInjected(DYNAMIC_CONTEXT_SCOPE, rule);\n\t\t}\n\t\tappendRuleActivation(pi, {\n\t\t\tkind: \"project-rules\",\n\t\t\ttargetPath,\n\t\t\trules: rules.map((rule) => rule.relativePath),\n\t\t});\n\n\t\treturn { content: [...event.content, { type: \"text\", text: block }] };\n\t});\n}\n\nfunction isPiRulesMode(value: string): value is PiRulesMode {\n\treturn MODE_VALUES.has(value);\n}\n\nfunction pathKeys(filePath: string): string[] {\n\ttry {\n\t\treturn [filePath, realpathSync.native(filePath)];\n\t} catch {\n\t\treturn [filePath];\n\t}\n}\n\nfunction displayPath(cwd: string, filePath: string): string {\n\treturn isAbsolute(filePath) ? relative(cwd, filePath) : filePath;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/formatter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACvB;AAyCD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAUlG;AAcD,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAChC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,aAAa,GACpB,MAAM,CAQR"}
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/formatter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACvB;AA2DD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAYlG;AAcD,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAChC,kBAAkB,EAAE,MAAM,EAC1B,OAAO,EAAE,aAAa,GACpB,MAAM,CAaR"}
@@ -3,6 +3,20 @@ import { truncateBudget, truncateRule } from "./truncator.js";
3
3
  function formatRule(rule) {
4
4
  return `Instructions from: ${rule.path}\n${rule.body}`;
5
5
  }
6
+ function formatWithinResultBudget(rules, options, render) {
7
+ let bodyBudget = options.maxResultChars;
8
+ while (bodyBudget > 0) {
9
+ const truncatedRules = truncateRules(rules, { ...options, maxResultChars: bodyBudget });
10
+ if (truncatedRules.length === 0)
11
+ return "";
12
+ const block = render(truncatedRules);
13
+ const overflow = block.length - options.maxResultChars;
14
+ if (overflow <= 0)
15
+ return block;
16
+ bodyBudget = Math.max(0, bodyBudget - overflow);
17
+ }
18
+ return "";
19
+ }
6
20
  function truncateRules(rules, options) {
7
21
  const perRuleTruncated = rules.map((rule) => ({
8
22
  path: rule.path,
@@ -32,9 +46,11 @@ export function formatStaticBlock(rules, options) {
32
46
  if (rules.length === 0) {
33
47
  return "";
34
48
  }
35
- const body = neutralizeEnvelopeMarkers(`${PROJECT_RULES_HEADING}\n${truncateRules(rules, options).map(formatRule).join("\n\n")}`);
36
- const envelope = `${PROJECT_RULES_START_MARKER}\n${body}\n${PROJECT_RULES_END_MARKER}`;
37
- return `\n\n${PROJECT_RULES_REGION_START_MARKER}\n${envelope}\n${PROJECT_RULES_REGION_END_MARKER}`;
49
+ return formatWithinResultBudget(rules, options, (truncatedRules) => {
50
+ const body = neutralizeEnvelopeMarkers(`${PROJECT_RULES_HEADING}\n${truncatedRules.map(formatRule).join("\n\n")}`);
51
+ const envelope = `${PROJECT_RULES_START_MARKER}\n${body}\n${PROJECT_RULES_END_MARKER}`;
52
+ return `\n\n${PROJECT_RULES_REGION_START_MARKER}\n${envelope}\n${PROJECT_RULES_REGION_END_MARKER}`;
53
+ });
38
54
  }
39
55
  /**
40
56
  * A raw region sentinel inside a rule would terminate extraction early and drop every rule after it;
@@ -51,8 +67,8 @@ export function formatDynamicBlock(rules, targetRelativePath, options) {
51
67
  if (rules.length === 0) {
52
68
  return "";
53
69
  }
54
- return `\n\nAdditional project instructions matched for ${targetRelativePath}:\n\n${truncateRules(rules, options)
70
+ return formatWithinResultBudget(rules, options, (truncatedRules) => `\n\nAdditional project instructions matched for ${targetRelativePath}:\n\n${truncatedRules
55
71
  .map(formatRule)
56
- .join("\n\n")}`;
72
+ .join("\n\n")}`);
57
73
  }
58
74
  //# sourceMappingURL=formatter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tPROJECT_RULES_END_MARKER,\n\tPROJECT_RULES_HEADING,\n\tPROJECT_RULES_REGION_END_MARKER,\n\tPROJECT_RULES_REGION_START_MARKER,\n\tPROJECT_RULES_START_MARKER,\n} from \"./constants.ts\";\nimport { truncateBudget, truncateRule } from \"./truncator.ts\";\nimport type { LoadedRule } from \"./types.ts\";\n\nexport interface FormatOptions {\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n}\n\ntype TruncatedRule = {\n\tpath: string;\n\trelativePath: string;\n\tbody: string;\n};\n\nfunction formatRule(rule: TruncatedRule): string {\n\treturn `Instructions from: ${rule.path}\\n${rule.body}`;\n}\n\nfunction truncateRules(rules: ReadonlyArray<LoadedRule>, options: FormatOptions): TruncatedRule[] {\n\tconst perRuleTruncated = rules.map((rule) => ({\n\t\tpath: rule.path,\n\t\trelativePath: rule.relativePath,\n\t\tbody: truncateRule(rule.body, { maxChars: options.maxRuleChars, relativePath: rule.relativePath }).body,\n\t}));\n\tconst budgetedRules = truncateBudget({\n\t\trules: perRuleTruncated.map((rule) => ({ body: rule.body, relativePath: rule.relativePath })),\n\t\tmaxResultChars: options.maxResultChars,\n\t});\n\tconst truncatedRules: TruncatedRule[] = [];\n\n\tfor (let index = 0; index < budgetedRules.length; index += 1) {\n\t\tconst sourceRule = perRuleTruncated[index];\n\t\tconst budgetedRule = budgetedRules[index];\n\t\tif (sourceRule === undefined || budgetedRule === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttruncatedRules.push({\n\t\t\tpath: sourceRule.path,\n\t\t\trelativePath: budgetedRule.relativePath,\n\t\t\tbody: budgetedRule.body,\n\t\t});\n\t}\n\n\treturn truncatedRules;\n}\n\nexport function formatStaticBlock(rules: ReadonlyArray<LoadedRule>, options: FormatOptions): string {\n\tif (rules.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst body = neutralizeEnvelopeMarkers(\n\t\t`${PROJECT_RULES_HEADING}\\n${truncateRules(rules, options).map(formatRule).join(\"\\n\\n\")}`,\n\t);\n\tconst envelope = `${PROJECT_RULES_START_MARKER}\\n${body}\\n${PROJECT_RULES_END_MARKER}`;\n\treturn `\\n\\n${PROJECT_RULES_REGION_START_MARKER}\\n${envelope}\\n${PROJECT_RULES_REGION_END_MARKER}`;\n}\n\n/**\n * A raw region sentinel inside a rule would terminate extraction early and drop every rule after it;\n * a raw semantic marker would instead corrupt the envelope structure the model reads.\n */\nfunction neutralizeEnvelopeMarkers(text: string): string {\n\treturn text\n\t\t.replaceAll(PROJECT_RULES_REGION_START_MARKER, \"&lt;!--senpi:project-rules:1:start--&gt;\")\n\t\t.replaceAll(PROJECT_RULES_REGION_END_MARKER, \"&lt;!--senpi:project-rules:1:end--&gt;\")\n\t\t.replaceAll(PROJECT_RULES_START_MARKER, \"&lt;project_rules&gt;\")\n\t\t.replaceAll(PROJECT_RULES_END_MARKER, \"&lt;/project_rules&gt;\");\n}\n\nexport function formatDynamicBlock(\n\trules: ReadonlyArray<LoadedRule>,\n\ttargetRelativePath: string,\n\toptions: FormatOptions,\n): string {\n\tif (rules.length === 0) {\n\t\treturn \"\";\n\t}\n\n\treturn `\\n\\nAdditional project instructions matched for ${targetRelativePath}:\\n\\n${truncateRules(rules, options)\n\t\t.map(formatRule)\n\t\t.join(\"\\n\\n\")}`;\n}\n"]}
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tPROJECT_RULES_END_MARKER,\n\tPROJECT_RULES_HEADING,\n\tPROJECT_RULES_REGION_END_MARKER,\n\tPROJECT_RULES_REGION_START_MARKER,\n\tPROJECT_RULES_START_MARKER,\n} from \"./constants.ts\";\nimport { truncateBudget, truncateRule } from \"./truncator.ts\";\nimport type { LoadedRule } from \"./types.ts\";\n\nexport interface FormatOptions {\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n}\n\ntype TruncatedRule = {\n\tpath: string;\n\trelativePath: string;\n\tbody: string;\n};\n\nfunction formatRule(rule: TruncatedRule): string {\n\treturn `Instructions from: ${rule.path}\\n${rule.body}`;\n}\n\nfunction formatWithinResultBudget(\n\trules: ReadonlyArray<LoadedRule>,\n\toptions: FormatOptions,\n\trender: (truncatedRules: ReadonlyArray<TruncatedRule>) => string,\n): string {\n\tlet bodyBudget = options.maxResultChars;\n\twhile (bodyBudget > 0) {\n\t\tconst truncatedRules = truncateRules(rules, { ...options, maxResultChars: bodyBudget });\n\t\tif (truncatedRules.length === 0) return \"\";\n\n\t\tconst block = render(truncatedRules);\n\t\tconst overflow = block.length - options.maxResultChars;\n\t\tif (overflow <= 0) return block;\n\t\tbodyBudget = Math.max(0, bodyBudget - overflow);\n\t}\n\treturn \"\";\n}\n\nfunction truncateRules(rules: ReadonlyArray<LoadedRule>, options: FormatOptions): TruncatedRule[] {\n\tconst perRuleTruncated = rules.map((rule) => ({\n\t\tpath: rule.path,\n\t\trelativePath: rule.relativePath,\n\t\tbody: truncateRule(rule.body, { maxChars: options.maxRuleChars, relativePath: rule.relativePath }).body,\n\t}));\n\tconst budgetedRules = truncateBudget({\n\t\trules: perRuleTruncated.map((rule) => ({ body: rule.body, relativePath: rule.relativePath })),\n\t\tmaxResultChars: options.maxResultChars,\n\t});\n\tconst truncatedRules: TruncatedRule[] = [];\n\n\tfor (let index = 0; index < budgetedRules.length; index += 1) {\n\t\tconst sourceRule = perRuleTruncated[index];\n\t\tconst budgetedRule = budgetedRules[index];\n\t\tif (sourceRule === undefined || budgetedRule === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\ttruncatedRules.push({\n\t\t\tpath: sourceRule.path,\n\t\t\trelativePath: budgetedRule.relativePath,\n\t\t\tbody: budgetedRule.body,\n\t\t});\n\t}\n\n\treturn truncatedRules;\n}\n\nexport function formatStaticBlock(rules: ReadonlyArray<LoadedRule>, options: FormatOptions): string {\n\tif (rules.length === 0) {\n\t\treturn \"\";\n\t}\n\n\treturn formatWithinResultBudget(rules, options, (truncatedRules) => {\n\t\tconst body = neutralizeEnvelopeMarkers(\n\t\t\t`${PROJECT_RULES_HEADING}\\n${truncatedRules.map(formatRule).join(\"\\n\\n\")}`,\n\t\t);\n\t\tconst envelope = `${PROJECT_RULES_START_MARKER}\\n${body}\\n${PROJECT_RULES_END_MARKER}`;\n\t\treturn `\\n\\n${PROJECT_RULES_REGION_START_MARKER}\\n${envelope}\\n${PROJECT_RULES_REGION_END_MARKER}`;\n\t});\n}\n\n/**\n * A raw region sentinel inside a rule would terminate extraction early and drop every rule after it;\n * a raw semantic marker would instead corrupt the envelope structure the model reads.\n */\nfunction neutralizeEnvelopeMarkers(text: string): string {\n\treturn text\n\t\t.replaceAll(PROJECT_RULES_REGION_START_MARKER, \"&lt;!--senpi:project-rules:1:start--&gt;\")\n\t\t.replaceAll(PROJECT_RULES_REGION_END_MARKER, \"&lt;!--senpi:project-rules:1:end--&gt;\")\n\t\t.replaceAll(PROJECT_RULES_START_MARKER, \"&lt;project_rules&gt;\")\n\t\t.replaceAll(PROJECT_RULES_END_MARKER, \"&lt;/project_rules&gt;\");\n}\n\nexport function formatDynamicBlock(\n\trules: ReadonlyArray<LoadedRule>,\n\ttargetRelativePath: string,\n\toptions: FormatOptions,\n): string {\n\tif (rules.length === 0) {\n\t\treturn \"\";\n\t}\n\n\treturn formatWithinResultBudget(\n\t\trules,\n\t\toptions,\n\t\t(truncatedRules) =>\n\t\t\t`\\n\\nAdditional project instructions matched for ${targetRelativePath}:\\n\\n${truncatedRules\n\t\t\t\t.map(formatRule)\n\t\t\t\t.join(\"\\n\\n\")}`,\n\t);\n}\n"]}
@@ -90,7 +90,7 @@ export interface TruncationResult {
90
90
  originalLength: number;
91
91
  }
92
92
  /**
93
- * Configuration knobs resolved from env vars and package.json.
93
+ * Configuration knobs resolved from environment variables.
94
94
  */
95
95
  export interface PiRulesConfig {
96
96
  disabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Public types for pi-rules.\n *\n * These types are stable contracts between modules. The frontmatter type\n * mirrors omo's `RuleMetadata` plus Claude (`paths`) and Copilot (`applyTo`)\n * aliases that are normalized into `globs` internally.\n */\n\n/**\n * YAML frontmatter parsed from a rule markdown file.\n * `paths` (Claude alias) and `applyTo` (Copilot alias) are normalized into\n * `globs` by the parser before any matcher sees this struct.\n */\nexport interface RuleFrontmatter {\n\tdescription?: string;\n\tglobs?: string | string[];\n\tpaths?: string | string[];\n\tapplyTo?: string | string[];\n\talwaysApply?: boolean;\n}\n\n/**\n * Result of parsing a rule markdown file.\n * `body` excludes the frontmatter delimiters and the YAML payload.\n */\nexport interface ParsedRule {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\t/**\n\t * Diagnostic message if frontmatter parsing failed but the body was salvaged.\n\t * Empty when parsing succeeded.\n\t */\n\tdiagnostic?: string;\n}\n\n/**\n * A discovered rule file candidate before parsing/matching.\n *\n * `path` is the absolute path as discovered (possibly via symlink).\n * `realPath` is the canonical resolved path used for dedup.\n * `source` identifies which discovery source produced this candidate.\n */\nexport interface RuleCandidate {\n\tpath: string;\n\trealPath: string;\n\tsource: RuleSource;\n\t/**\n\t * Distance from the target file directory to the directory containing this rule.\n\t * 0 = same directory, 9999 = global/user-home rule.\n\t */\n\tdistance: number;\n\tisGlobal: boolean;\n\t/**\n\t * True when this candidate is a SINGLE-FILE rule like AGENTS.md or\n\t * `.github/copilot-instructions.md` (frontmatter optional, applies always).\n\t */\n\tisSingleFile: boolean;\n\t/**\n\t * Path relative to project root, POSIX-normalized. Used for matcher and display.\n\t * Empty string for user-home global rules.\n\t */\n\trelativePath: string;\n}\n\n/**\n * A fully-loaded rule ready for injection.\n */\nexport interface LoadedRule extends RuleCandidate {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\tcontentHash: string;\n\tmatchReason: MatchReason;\n}\n\n/**\n * Source identifier for rule files. Used for deterministic ordering and display.\n */\nexport type RuleSource =\n\t| \".omo/rules\"\n\t| \".claude/rules\"\n\t| \".cursor/rules\"\n\t| \".github/instructions\"\n\t| \".github/copilot-instructions.md\"\n\t| \"AGENTS.md\"\n\t| \"CLAUDE.md\"\n\t| \"CONTEXT.md\"\n\t| \"~/.omo/rules\"\n\t| \"~/.opencode/rules\"\n\t| \"~/.claude/rules\"\n\t| \"~/.config/opencode/AGENTS.md\"\n\t| \"~/.claude/CLAUDE.md\";\n\n/**\n * Why a candidate matched the target file. Surfaced in the injection block so\n * the model can attribute its behavior to a specific rule.\n */\nexport type MatchReason = \"alwaysApply\" | \"single-file\" | { kind: \"glob\"; pattern: string } | { kind: \"no-match\" };\n\n/**\n * Truncation result.\n */\nexport interface TruncationResult {\n\tbody: string;\n\ttruncated: boolean;\n\toriginalLength: number;\n}\n\n/**\n * Configuration knobs resolved from env vars and package.json.\n */\nexport interface PiRulesConfig {\n\tdisabled: boolean;\n\tmode: \"static\" | \"dynamic\" | \"both\" | \"off\";\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n\tenabledSources: RuleSource[] | \"auto\";\n}\n\n/**\n * Per-session in-memory dedup state.\n *\n * `staticDedup` keys are `{cwd}::{rulePath}::{contentHash}` strings.\n * `dynamicDedup` stores `{targetPath}::{rulePath}::{contentHash}` strings grouped by target file.\n * `dynamicTargetFingerprints` maps a target file cache key to a digest of its\n * discovered rule candidates + file stats; loadDynamicRules short-circuits\n * targets whose fingerprint has not changed since the previous load.\n */\nexport interface SessionState {\n\tcwd: string | undefined;\n\tstaticDedup: Set<string>;\n\tdynamicDedup: Map<string, Set<string>>;\n\tdynamicTargetFingerprints: Map<string, string>;\n\tloadedRules: LoadedRule[];\n\tdiagnostics: RuleDiagnostic[];\n}\n\nexport interface RuleDiagnostic {\n\tseverity: \"warning\" | \"error\";\n\tsource: string;\n\tmessage: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Public types for pi-rules.\n *\n * These types are stable contracts between modules. The frontmatter type\n * mirrors omo's `RuleMetadata` plus Claude (`paths`) and Copilot (`applyTo`)\n * aliases that are normalized into `globs` internally.\n */\n\n/**\n * YAML frontmatter parsed from a rule markdown file.\n * `paths` (Claude alias) and `applyTo` (Copilot alias) are normalized into\n * `globs` by the parser before any matcher sees this struct.\n */\nexport interface RuleFrontmatter {\n\tdescription?: string;\n\tglobs?: string | string[];\n\tpaths?: string | string[];\n\tapplyTo?: string | string[];\n\talwaysApply?: boolean;\n}\n\n/**\n * Result of parsing a rule markdown file.\n * `body` excludes the frontmatter delimiters and the YAML payload.\n */\nexport interface ParsedRule {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\t/**\n\t * Diagnostic message if frontmatter parsing failed but the body was salvaged.\n\t * Empty when parsing succeeded.\n\t */\n\tdiagnostic?: string;\n}\n\n/**\n * A discovered rule file candidate before parsing/matching.\n *\n * `path` is the absolute path as discovered (possibly via symlink).\n * `realPath` is the canonical resolved path used for dedup.\n * `source` identifies which discovery source produced this candidate.\n */\nexport interface RuleCandidate {\n\tpath: string;\n\trealPath: string;\n\tsource: RuleSource;\n\t/**\n\t * Distance from the target file directory to the directory containing this rule.\n\t * 0 = same directory, 9999 = global/user-home rule.\n\t */\n\tdistance: number;\n\tisGlobal: boolean;\n\t/**\n\t * True when this candidate is a SINGLE-FILE rule like AGENTS.md or\n\t * `.github/copilot-instructions.md` (frontmatter optional, applies always).\n\t */\n\tisSingleFile: boolean;\n\t/**\n\t * Path relative to project root, POSIX-normalized. Used for matcher and display.\n\t * Empty string for user-home global rules.\n\t */\n\trelativePath: string;\n}\n\n/**\n * A fully-loaded rule ready for injection.\n */\nexport interface LoadedRule extends RuleCandidate {\n\tfrontmatter: RuleFrontmatter;\n\tbody: string;\n\tcontentHash: string;\n\tmatchReason: MatchReason;\n}\n\n/**\n * Source identifier for rule files. Used for deterministic ordering and display.\n */\nexport type RuleSource =\n\t| \".omo/rules\"\n\t| \".claude/rules\"\n\t| \".cursor/rules\"\n\t| \".github/instructions\"\n\t| \".github/copilot-instructions.md\"\n\t| \"AGENTS.md\"\n\t| \"CLAUDE.md\"\n\t| \"CONTEXT.md\"\n\t| \"~/.omo/rules\"\n\t| \"~/.opencode/rules\"\n\t| \"~/.claude/rules\"\n\t| \"~/.config/opencode/AGENTS.md\"\n\t| \"~/.claude/CLAUDE.md\";\n\n/**\n * Why a candidate matched the target file. Surfaced in the injection block so\n * the model can attribute its behavior to a specific rule.\n */\nexport type MatchReason = \"alwaysApply\" | \"single-file\" | { kind: \"glob\"; pattern: string } | { kind: \"no-match\" };\n\n/**\n * Truncation result.\n */\nexport interface TruncationResult {\n\tbody: string;\n\ttruncated: boolean;\n\toriginalLength: number;\n}\n\n/**\n * Configuration knobs resolved from environment variables.\n */\nexport interface PiRulesConfig {\n\tdisabled: boolean;\n\tmode: \"static\" | \"dynamic\" | \"both\" | \"off\";\n\tmaxRuleChars: number;\n\tmaxResultChars: number;\n\tenabledSources: RuleSource[] | \"auto\";\n}\n\n/**\n * Per-session in-memory dedup state.\n *\n * `staticDedup` keys are `{cwd}::{rulePath}::{contentHash}` strings.\n * `dynamicDedup` stores `{targetPath}::{rulePath}::{contentHash}` strings grouped by target file.\n * `dynamicTargetFingerprints` maps a target file cache key to a digest of its\n * discovered rule candidates + file stats; loadDynamicRules short-circuits\n * targets whose fingerprint has not changed since the previous load.\n */\nexport interface SessionState {\n\tcwd: string | undefined;\n\tstaticDedup: Set<string>;\n\tdynamicDedup: Map<string, Set<string>>;\n\tdynamicTargetFingerprints: Map<string, string>;\n\tloadedRules: LoadedRule[];\n\tdiagnostics: RuleDiagnostic[];\n}\n\nexport interface RuleDiagnostic {\n\tseverity: \"warning\" | \"error\";\n\tsource: string;\n\tmessage: string;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"service-tier.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/service-tier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAS,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,YAAY,EAAE,WAAW,EAAE,CAAC;AAc5B,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAalH;AAkCD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAqEnE"}
1
+ {"version":3,"file":"service-tier.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/service-tier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAS,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,YAAY,EAAE,WAAW,EAAE,CAAC;AAa5B,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAalH;AAkCD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAqEnE"}
@@ -1,5 +1,4 @@
1
1
  import { SettingsManager } from "../../settings-manager.js";
2
- const OPENAI_CODEX_PROVIDER = "openai-codex";
3
2
  const OPENAI_CODEX_RESPONSES_API = "openai-codex-responses";
4
3
  const FAST_MODEL_SUFFIX = "-fast";
5
4
  const PRIORITY_TIER = "priority";
@@ -65,7 +64,7 @@ export default function serviceTierExtension(pi) {
65
64
  sessionFastMode = false;
66
65
  pi.setSessionFastMode(false);
67
66
  const model = ctx.model;
68
- if (model?.provider !== OPENAI_CODEX_PROVIDER) {
67
+ if (model?.api !== OPENAI_CODEX_RESPONSES_API) {
69
68
  return;
70
69
  }
71
70
  const baseModel = findBaseModel(ctx.modelRegistry, model);
@@ -77,7 +76,7 @@ export default function serviceTierExtension(pi) {
77
76
  description: "Toggle OpenAI Codex fast mode for this session",
78
77
  handler: async (_args, ctx) => {
79
78
  const model = ctx.model;
80
- if (model?.provider !== OPENAI_CODEX_PROVIDER) {
79
+ if (model?.api !== OPENAI_CODEX_RESPONSES_API) {
81
80
  ctx.ui.notify("Fast mode is only available for OpenAI Codex models.", "warning");
82
81
  return;
83
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"service-tier.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/service-tier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport type { ModelRegistry } from \"../../model-registry.ts\";\nimport { SettingsManager } from \"../../settings-manager.ts\";\nimport type { ExtensionAPI, ServiceTier } from \"../types.ts\";\n\nexport type { ServiceTier };\n\ntype ProviderPayload = Record<string, unknown>;\n\nconst OPENAI_CODEX_PROVIDER = \"openai-codex\";\nconst OPENAI_CODEX_RESPONSES_API = \"openai-codex-responses\";\nconst FAST_MODEL_SUFFIX = \"-fast\";\nconst PRIORITY_TIER: ServiceTier = \"priority\";\nconst SERVICE_TIER_APIS: ReadonlySet<Api> = new Set([\"openai-responses\", OPENAI_CODEX_RESPONSES_API]);\n\nfunction isRecord(value: unknown): value is ProviderPayload {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nexport function addServiceTierToPayload(api: Api | undefined, payload: unknown, serviceTier?: ServiceTier): unknown {\n\tif (!api || !SERVICE_TIER_APIS.has(api) || !serviceTier) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload) || payload.service_tier !== undefined) {\n\t\treturn payload;\n\t}\n\n\treturn {\n\t\t...payload,\n\t\tservice_tier: serviceTier,\n\t};\n}\n\nfunction getRequestModelId(modelRegistry: ModelRegistry, model: Model<Api>): string {\n\treturn modelRegistry.getUpstreamModelId(model) ?? model.id;\n}\n\nfunction isCompatibleFastVariant(modelRegistry: ModelRegistry, baseModel: Model<Api>, fastModel: Model<Api>): boolean {\n\treturn (\n\t\tfastModel.provider === baseModel.provider &&\n\t\tfastModel.api === baseModel.api &&\n\t\tmodelRegistry.getServiceTier(fastModel) === \"priority\" &&\n\t\tgetRequestModelId(modelRegistry, fastModel) === getRequestModelId(modelRegistry, baseModel)\n\t);\n}\n\nfunction findBaseModel(modelRegistry: ModelRegistry, fastModel: Model<Api>): Model<Api> | undefined {\n\tif (!fastModel.id.endsWith(FAST_MODEL_SUFFIX)) {\n\t\treturn undefined;\n\t}\n\n\tconst baseModelId = fastModel.id.slice(0, -FAST_MODEL_SUFFIX.length);\n\tconst baseModel = modelRegistry.find(fastModel.provider, baseModelId);\n\treturn baseModel && isCompatibleFastVariant(modelRegistry, baseModel, fastModel) ? baseModel : undefined;\n}\n\nfunction findFastModel(modelRegistry: ModelRegistry, baseModel: Model<Api>): Model<Api> | undefined {\n\tif (baseModel.id.endsWith(FAST_MODEL_SUFFIX)) {\n\t\treturn undefined;\n\t}\n\n\tconst fastModel = modelRegistry.find(baseModel.provider, `${baseModel.id}${FAST_MODEL_SUFFIX}`);\n\treturn fastModel && isCompatibleFastVariant(modelRegistry, baseModel, fastModel) ? fastModel : undefined;\n}\n\nexport default function serviceTierExtension(pi: ExtensionAPI): void {\n\tlet settingsServiceTier: ServiceTier | undefined;\n\t/**\n\t * Session-level fast mode for Codex models that have no `-fast` catalog sibling.\n\t *\n\t * The catalog generator emits `-fast` priority variants only for the direct\n\t * `openai` provider, so `openai-codex` models never have a switch target. The\n\t * ChatGPT backend still offers the tier to subscriptions:\n\t * `chatgpt.com/backend-api/codex/models` advertises a `priority` service tier\n\t * labelled \"Fast\" (\"1.5x speed, increased usage\")\n\t * for gpt-5.4/5.5/5.6-*, and the first-party Codex CLI sends\n\t * `service_tier: \"priority\"` on subscription OAuth. The response echo is not a\n\t * confirmation channel — it reads `auto`/`default` whether or not a tier was\n\t * sent — so this toggle drives the request field directly. See issue #545.\n\t */\n\tlet sessionFastMode = false;\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tconst settingsManager = SettingsManager.create(ctx.cwd);\n\t\tsettingsServiceTier = settingsManager.getOpenAIServiceTier();\n\t\tsessionFastMode = false;\n\t\tpi.setSessionFastMode(false);\n\n\t\tconst model = ctx.model;\n\t\tif (model?.provider !== OPENAI_CODEX_PROVIDER) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst baseModel = findBaseModel(ctx.modelRegistry, model);\n\t\tif (baseModel) {\n\t\t\tawait pi.setSessionModel(baseModel);\n\t\t}\n\t});\n\n\tpi.registerCommand(\"fast\", {\n\t\tdescription: \"Toggle OpenAI Codex fast mode for this session\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tconst model = ctx.model;\n\t\t\tif (model?.provider !== OPENAI_CODEX_PROVIDER) {\n\t\t\t\tctx.ui.notify(\"Fast mode is only available for OpenAI Codex models.\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst baseModel = findBaseModel(ctx.modelRegistry, model);\n\t\t\tconst targetModel = baseModel ?? findFastModel(ctx.modelRegistry, model);\n\t\t\tif (!targetModel) {\n\t\t\t\tsessionFastMode = !sessionFastMode;\n\t\t\t\tpi.setSessionFastMode(sessionFastMode);\n\t\t\t\tctx.ui.notify(`Fast mode ${sessionFastMode ? \"enabled\" : \"disabled\"}: ${model.id}`, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!(await pi.setSessionModel(targetModel))) {\n\t\t\t\tctx.ui.notify(`Could not switch to ${targetModel.provider}/${targetModel.id}.`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst enabled = baseModel === undefined;\n\t\t\tctx.ui.notify(`Fast mode ${enabled ? \"enabled\" : \"disabled\"}: ${targetModel.id}`, \"info\");\n\t\t},\n\t});\n\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\tconst effectiveServiceTier =\n\t\t\tctx.model?.api === OPENAI_CODEX_RESPONSES_API\n\t\t\t\t? (ctx.serviceTier ?? (sessionFastMode ? PRIORITY_TIER : undefined))\n\t\t\t\t: (ctx.serviceTier ?? settingsServiceTier);\n\t\treturn addServiceTierToPayload(ctx.model?.api, event.payload, effectiveServiceTier);\n\t});\n}\n"]}
1
+ {"version":3,"file":"service-tier.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/service-tier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport type { ModelRegistry } from \"../../model-registry.ts\";\nimport { SettingsManager } from \"../../settings-manager.ts\";\nimport type { ExtensionAPI, ServiceTier } from \"../types.ts\";\n\nexport type { ServiceTier };\n\ntype ProviderPayload = Record<string, unknown>;\n\nconst OPENAI_CODEX_RESPONSES_API = \"openai-codex-responses\";\nconst FAST_MODEL_SUFFIX = \"-fast\";\nconst PRIORITY_TIER: ServiceTier = \"priority\";\nconst SERVICE_TIER_APIS: ReadonlySet<Api> = new Set([\"openai-responses\", OPENAI_CODEX_RESPONSES_API]);\n\nfunction isRecord(value: unknown): value is ProviderPayload {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nexport function addServiceTierToPayload(api: Api | undefined, payload: unknown, serviceTier?: ServiceTier): unknown {\n\tif (!api || !SERVICE_TIER_APIS.has(api) || !serviceTier) {\n\t\treturn payload;\n\t}\n\n\tif (!isRecord(payload) || payload.service_tier !== undefined) {\n\t\treturn payload;\n\t}\n\n\treturn {\n\t\t...payload,\n\t\tservice_tier: serviceTier,\n\t};\n}\n\nfunction getRequestModelId(modelRegistry: ModelRegistry, model: Model<Api>): string {\n\treturn modelRegistry.getUpstreamModelId(model) ?? model.id;\n}\n\nfunction isCompatibleFastVariant(modelRegistry: ModelRegistry, baseModel: Model<Api>, fastModel: Model<Api>): boolean {\n\treturn (\n\t\tfastModel.provider === baseModel.provider &&\n\t\tfastModel.api === baseModel.api &&\n\t\tmodelRegistry.getServiceTier(fastModel) === \"priority\" &&\n\t\tgetRequestModelId(modelRegistry, fastModel) === getRequestModelId(modelRegistry, baseModel)\n\t);\n}\n\nfunction findBaseModel(modelRegistry: ModelRegistry, fastModel: Model<Api>): Model<Api> | undefined {\n\tif (!fastModel.id.endsWith(FAST_MODEL_SUFFIX)) {\n\t\treturn undefined;\n\t}\n\n\tconst baseModelId = fastModel.id.slice(0, -FAST_MODEL_SUFFIX.length);\n\tconst baseModel = modelRegistry.find(fastModel.provider, baseModelId);\n\treturn baseModel && isCompatibleFastVariant(modelRegistry, baseModel, fastModel) ? baseModel : undefined;\n}\n\nfunction findFastModel(modelRegistry: ModelRegistry, baseModel: Model<Api>): Model<Api> | undefined {\n\tif (baseModel.id.endsWith(FAST_MODEL_SUFFIX)) {\n\t\treturn undefined;\n\t}\n\n\tconst fastModel = modelRegistry.find(baseModel.provider, `${baseModel.id}${FAST_MODEL_SUFFIX}`);\n\treturn fastModel && isCompatibleFastVariant(modelRegistry, baseModel, fastModel) ? fastModel : undefined;\n}\n\nexport default function serviceTierExtension(pi: ExtensionAPI): void {\n\tlet settingsServiceTier: ServiceTier | undefined;\n\t/**\n\t * Session-level fast mode for Codex models that have no `-fast` catalog sibling.\n\t *\n\t * The catalog generator emits `-fast` priority variants only for the direct\n\t * `openai` provider, so `openai-codex` models never have a switch target. The\n\t * ChatGPT backend still offers the tier to subscriptions:\n\t * `chatgpt.com/backend-api/codex/models` advertises a `priority` service tier\n\t * labelled \"Fast\" (\"1.5x speed, increased usage\")\n\t * for gpt-5.4/5.5/5.6-*, and the first-party Codex CLI sends\n\t * `service_tier: \"priority\"` on subscription OAuth. The response echo is not a\n\t * confirmation channel — it reads `auto`/`default` whether or not a tier was\n\t * sent — so this toggle drives the request field directly. See issue #545.\n\t */\n\tlet sessionFastMode = false;\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tconst settingsManager = SettingsManager.create(ctx.cwd);\n\t\tsettingsServiceTier = settingsManager.getOpenAIServiceTier();\n\t\tsessionFastMode = false;\n\t\tpi.setSessionFastMode(false);\n\n\t\tconst model = ctx.model;\n\t\tif (model?.api !== OPENAI_CODEX_RESPONSES_API) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst baseModel = findBaseModel(ctx.modelRegistry, model);\n\t\tif (baseModel) {\n\t\t\tawait pi.setSessionModel(baseModel);\n\t\t}\n\t});\n\n\tpi.registerCommand(\"fast\", {\n\t\tdescription: \"Toggle OpenAI Codex fast mode for this session\",\n\t\thandler: async (_args, ctx) => {\n\t\t\tconst model = ctx.model;\n\t\t\tif (model?.api !== OPENAI_CODEX_RESPONSES_API) {\n\t\t\t\tctx.ui.notify(\"Fast mode is only available for OpenAI Codex models.\", \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst baseModel = findBaseModel(ctx.modelRegistry, model);\n\t\t\tconst targetModel = baseModel ?? findFastModel(ctx.modelRegistry, model);\n\t\t\tif (!targetModel) {\n\t\t\t\tsessionFastMode = !sessionFastMode;\n\t\t\t\tpi.setSessionFastMode(sessionFastMode);\n\t\t\t\tctx.ui.notify(`Fast mode ${sessionFastMode ? \"enabled\" : \"disabled\"}: ${model.id}`, \"info\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!(await pi.setSessionModel(targetModel))) {\n\t\t\t\tctx.ui.notify(`Could not switch to ${targetModel.provider}/${targetModel.id}.`, \"error\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst enabled = baseModel === undefined;\n\t\t\tctx.ui.notify(`Fast mode ${enabled ? \"enabled\" : \"disabled\"}: ${targetModel.id}`, \"info\");\n\t\t},\n\t});\n\n\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\tconst effectiveServiceTier =\n\t\t\tctx.model?.api === OPENAI_CODEX_RESPONSES_API\n\t\t\t\t? (ctx.serviceTier ?? (sessionFastMode ? PRIORITY_TIER : undefined))\n\t\t\t\t: (ctx.serviceTier ?? settingsServiceTier);\n\t\treturn addServiceTierToPayload(ctx.model?.api, event.payload, effectiveServiceTier);\n\t});\n}\n"]}
@@ -22,7 +22,7 @@ export declare class MonitorNotifier {
22
22
  notifyEvent(event: MonitorEvent): void;
23
23
  /** Any explicit user or tool activity breaks a consecutive monitor-only wake streak. */
24
24
  noteActivity(): void;
25
- /** Explicit rearm is the only operation that releases the session-global wake pause. */
25
+ /** Explicit rearm resumes intermediate line delivery after the session-global wake pause. */
26
26
  rearm(id: string): void;
27
27
  dispose(): void;
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"monitor-notify.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEzF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAO7D,MAAM,WAAW,4BAA4B;IAC5C,GAAG,IAAI,MAAM,CAAC;IACd,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3D,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnC;AAQD,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,uBAAuB,CAAC;IACpD,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,4BAA4B,CAAC;CAClD;AA+CD;;;GAGG;AACH,qBAAa,eAAe;;IAa3B,YAAY,IAAI,EAAE,mBAAmB,EAGpC;IAED,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAarC;IAED,wFAAwF;IACxF,YAAY,IAAI,IAAI,CAEnB;IAED,wFAAwF;IACxF,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAKtB;IAED,OAAO,IAAI,IAAI,CAQd;CAqID"}
1
+ {"version":3,"file":"monitor-notify.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEzF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAO7D,MAAM,WAAW,4BAA4B;IAC5C,GAAG,IAAI,MAAM,CAAC;IACd,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3D,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnC;AAQD,MAAM,WAAW,mBAAoB,SAAQ,oBAAoB;IAChE,QAAQ,CAAC,WAAW,EAAE,MAAM,uBAAuB,CAAC;IACpD,sEAAsE;IACtE,QAAQ,CAAC,aAAa,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,4BAA4B,CAAC;CAClD;AA+CD;;;GAGG;AACH,qBAAa,eAAe;;IAa3B,YAAY,IAAI,EAAE,mBAAmB,EAGpC;IAED,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAkBrC;IAED,wFAAwF;IACxF,YAAY,IAAI,IAAI,CAEnB;IAED,6FAA6F;IAC7F,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAKtB;IAED,OAAO,IAAI,IAAI,CAQd;CAwID"}
@@ -68,8 +68,13 @@ export class MonitorNotifier {
68
68
  this.#scheduler = deps.scheduler ?? systemScheduler;
69
69
  }
70
70
  notifyEvent(event) {
71
- if (this.#wakeBudgetPaused)
72
- return;
71
+ if (this.#wakeBudgetPaused) {
72
+ if (event.type === "line")
73
+ return;
74
+ this.#wakeBudgetPaused = false;
75
+ this.#consecutiveWakes = 0;
76
+ this.#lastInjectionAt.delete(event.id);
77
+ }
73
78
  if (!getTerminalNotificationDelivery(this.#deps, MONITOR_NOTIFICATION_CUSTOM_TYPE))
74
79
  return;
75
80
  const settings = resolveSettings(this.#deps.getSettings());
@@ -88,7 +93,7 @@ export class MonitorNotifier {
88
93
  noteActivity() {
89
94
  this.#consecutiveWakes = 0;
90
95
  }
91
- /** Explicit rearm is the only operation that releases the session-global wake pause. */
96
+ /** Explicit rearm resumes intermediate line delivery after the session-global wake pause. */
92
97
  rearm(id) {
93
98
  this.#wakeBudgetPaused = false;
94
99
  this.#consecutiveWakes = 0;
@@ -158,8 +163,11 @@ export class MonitorNotifier {
158
163
  const overflowCount = [...this.#overflow.values()]
159
164
  .filter((overflow) => injectedIds.has(overflow.id))
160
165
  .reduce((total, overflow) => total + overflow.count, 0);
161
- const reachesBudget = this.#consecutiveWakes + 1 >= settings.wakeBudget;
162
- const pauseNotice = reachesBudget ? "Monitor paused - peek bash_output or re-arm this monitor." : "";
166
+ const deliversSummary = selected.some((event) => event.type === "summary");
167
+ const reachesBudget = !deliversSummary && this.#consecutiveWakes + 1 >= settings.wakeBudget;
168
+ const pauseNotice = reachesBudget
169
+ ? "Monitor paused after repeated updates. Completion still wakes this session; peek bash_output or re-arm only for intermediate events."
170
+ : "";
163
171
  const content = this.#buildMessage(selected, overflowCount, pauseNotice, settings.maxCharsPerInjection);
164
172
  delivery.send(content);
165
173
  for (const id of injectedIds) {
@@ -173,7 +181,7 @@ export class MonitorNotifier {
173
181
  }
174
182
  this.#events = deferred;
175
183
  this.#eventChars = deferred.reduce((total, event) => total + `Monitor event(${event.description}): ${eventBody(event)}`.length, 0);
176
- this.#consecutiveWakes++;
184
+ this.#consecutiveWakes = deliversSummary ? 0 : this.#consecutiveWakes + 1;
177
185
  if (reachesBudget) {
178
186
  this.#wakeBudgetPaused = true;
179
187
  this.#deps.pauseMonitors();