@code-yeongyu/senpi 2026.9.27-4 → 2026.9.28

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 (271) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/bundle/chunks/{app-server-command-3GVJZFFH.js → app-server-command-TOPTGVQB.js} +1 -1
  3. package/dist/bundle/chunks/{azure-openai-responses-4SUOOZZ4.js → azure-openai-responses-FCZNBRWE.js} +1 -1
  4. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  5. package/dist/bundle/chunks/{chunk-PSCNHY7D.js → chunk-3GMFUEU7.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-HBG6SQU5.js → chunk-62XHQXCZ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-SLL375O7.js → chunk-7DY2JPUX.js} +1 -1
  8. package/dist/bundle/chunks/chunk-7YUGCTEV.js +15 -0
  9. package/dist/bundle/chunks/{chunk-FWBSGMAE.js → chunk-A4UMPXQF.js} +1 -1
  10. package/dist/bundle/chunks/chunk-BBK6SSYT.js +2 -0
  11. package/dist/bundle/chunks/{chunk-C2425O2Q.js → chunk-CNQ4JB45.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-27IFXX3B.js → chunk-DRN4FQCE.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-22MGY5JQ.js → chunk-EHSZ7UCW.js} +1 -1
  14. package/dist/bundle/chunks/chunk-FHJYIU3U.js +5 -0
  15. package/dist/bundle/chunks/chunk-GJUCSTAG.js +19 -0
  16. package/dist/bundle/chunks/{chunk-VMKAYXHL.js → chunk-KIOTFUG6.js} +25 -20
  17. package/dist/bundle/chunks/{chunk-2BMD37YV.js → chunk-LUPPSEQW.js} +1 -1
  18. package/dist/bundle/chunks/chunk-OAIVTS5X.js +8 -0
  19. package/dist/bundle/chunks/{chunk-NRGMT74E.js → chunk-QOVUQZO4.js} +1 -1
  20. package/dist/bundle/chunks/chunk-SN4ZHPMN.js +135 -0
  21. package/dist/bundle/chunks/{chunk-IKXPBYSO.js → chunk-UJFLZ2M2.js} +1 -1
  22. package/dist/bundle/chunks/{chunk-4T4GFAGK.js → chunk-VFSXUT7K.js} +1 -1
  23. package/dist/bundle/chunks/{cli-main-66NFBKVH.js → cli-main-ARR54ET6.js} +1 -1
  24. package/dist/bundle/chunks/{google-generative-ai-ZTGKZTGU.js → google-generative-ai-LFCBHG3Y.js} +1 -1
  25. package/dist/bundle/chunks/{google-vertex-CCZ376YK.js → google-vertex-C474FXU7.js} +1 -1
  26. package/dist/bundle/chunks/{help-fast-path-NZ3I2UEN.js → help-fast-path-3U3YDEZ6.js} +1 -1
  27. package/dist/bundle/chunks/{host-command-RORPAC5X.js → host-command-6CJ7YM6W.js} +1 -1
  28. package/dist/bundle/chunks/{host-lifecycle-UDMJGLOR.js → host-lifecycle-RZIMOFDM.js} +1 -1
  29. package/dist/bundle/chunks/host-lifecycle.js +6 -6
  30. package/dist/bundle/chunks/interactive-host-runtime-A3GEIFTU.js +4 -0
  31. package/dist/bundle/chunks/{interactive-mode-LOAADKLH.js → interactive-mode-ITSFLGF6.js} +1 -1
  32. package/dist/bundle/chunks/{list-tips-S5CANO5W.js → list-tips-FPXDXN7R.js} +1 -1
  33. package/dist/bundle/chunks/multi-session-host-B4WMZE2G.js +21 -0
  34. package/dist/bundle/chunks/{openai-codex-responses-YSGZZDD5.js → openai-codex-responses-2LDIFL6Z.js} +1 -1
  35. package/dist/bundle/chunks/{openai-completions-KWHRWCBN.js → openai-completions-7KZLPKYP.js} +1 -1
  36. package/dist/bundle/chunks/{openai-images-6U5FCN5S.js → openai-images-I7DR7ERP.js} +1 -1
  37. package/dist/bundle/chunks/{openai-responses-7PWMBGYX.js → openai-responses-LCHS3AF3.js} +1 -1
  38. package/dist/bundle/chunks/{openrouter-images-QIKWQZUD.js → openrouter-images-IPNDRK6C.js} +1 -1
  39. package/dist/bundle/chunks/{package-manager-cli-5EEDA35I.js → package-manager-cli-DXHQ6RKA.js} +1 -1
  40. package/dist/bundle/chunks/{rotation-stream-KZG4OVR7.js → rotation-stream-ZVJEGA2G.js} +1 -1
  41. package/dist/bundle/chunks/{rpc-mode-HOEA5NGQ.js → rpc-mode-PFPNP65F.js} +1 -1
  42. package/dist/bundle/chunks/session-picker-KOPOV6Q4.js +2 -0
  43. package/dist/bundle/chunks/session-worker.js +311 -302
  44. package/dist/bundle/cli.js +1 -1
  45. package/dist/bundle/index.js +1 -1
  46. package/dist/bundle/rpc-entry.js +1 -1
  47. package/dist/cli/args.js +1 -1
  48. package/dist/cli/args.js.map +1 -1
  49. package/dist/cli/host-command.d.ts +8 -1
  50. package/dist/cli/host-command.d.ts.map +1 -1
  51. package/dist/cli/host-command.js +66 -14
  52. package/dist/cli/host-command.js.map +1 -1
  53. package/dist/core/agent-session.d.ts +18 -1
  54. package/dist/core/agent-session.d.ts.map +1 -1
  55. package/dist/core/agent-session.js +119 -3
  56. package/dist/core/agent-session.js.map +1 -1
  57. package/dist/core/retry-fallback/candidates.d.ts +26 -0
  58. package/dist/core/retry-fallback/candidates.d.ts.map +1 -0
  59. package/dist/core/retry-fallback/candidates.js +41 -0
  60. package/dist/core/retry-fallback/candidates.js.map +1 -0
  61. package/dist/core/retry-fallback/circuit-probes.d.ts +30 -0
  62. package/dist/core/retry-fallback/circuit-probes.d.ts.map +1 -0
  63. package/dist/core/retry-fallback/circuit-probes.js +60 -0
  64. package/dist/core/retry-fallback/circuit-probes.js.map +1 -0
  65. package/dist/core/retry-fallback/circuit.d.ts +101 -0
  66. package/dist/core/retry-fallback/circuit.d.ts.map +1 -0
  67. package/dist/core/retry-fallback/circuit.js +175 -0
  68. package/dist/core/retry-fallback/circuit.js.map +1 -0
  69. package/dist/core/retry-fallback/controller-types.d.ts +58 -0
  70. package/dist/core/retry-fallback/controller-types.d.ts.map +1 -0
  71. package/dist/core/retry-fallback/controller-types.js +2 -0
  72. package/dist/core/retry-fallback/controller-types.js.map +1 -0
  73. package/dist/core/retry-fallback/controller.d.ts +21 -49
  74. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  75. package/dist/core/retry-fallback/controller.js +88 -42
  76. package/dist/core/retry-fallback/controller.js.map +1 -1
  77. package/dist/core/sdk.d.ts.map +1 -1
  78. package/dist/core/sdk.js +25 -17
  79. package/dist/core/sdk.js.map +1 -1
  80. package/dist/core/session-failure-report.d.ts +33 -0
  81. package/dist/core/session-failure-report.d.ts.map +1 -0
  82. package/dist/core/session-failure-report.js +62 -0
  83. package/dist/core/session-failure-report.js.map +1 -0
  84. package/dist/core/settings-manager.d.ts +3 -0
  85. package/dist/core/settings-manager.d.ts.map +1 -1
  86. package/dist/core/settings-manager.js +4 -0
  87. package/dist/core/settings-manager.js.map +1 -1
  88. package/dist/core/slash-commands.d.ts.map +1 -1
  89. package/dist/core/slash-commands.js +1 -0
  90. package/dist/core/slash-commands.js.map +1 -1
  91. package/dist/index.d.ts +1 -1
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +1 -1
  94. package/dist/index.js.map +1 -1
  95. package/dist/modes/index.d.ts +1 -0
  96. package/dist/modes/index.d.ts.map +1 -1
  97. package/dist/modes/index.js +2 -0
  98. package/dist/modes/index.js.map +1 -1
  99. package/dist/modes/interactive/help-content.d.ts.map +1 -1
  100. package/dist/modes/interactive/help-content.js +3 -0
  101. package/dist/modes/interactive/help-content.js.map +1 -1
  102. package/dist/modes/interactive/interactive-host-attach.d.ts +10 -0
  103. package/dist/modes/interactive/interactive-host-attach.d.ts.map +1 -0
  104. package/dist/modes/interactive/interactive-host-attach.js +14 -0
  105. package/dist/modes/interactive/interactive-host-attach.js.map +1 -0
  106. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  107. package/dist/modes/interactive/interactive-host-runtime.js +3 -6
  108. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  109. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  110. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  111. package/dist/modes/interactive/interactive-mode.js +66 -1
  112. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  113. package/dist/modes/interactive/session-failure-info.d.ts +3 -0
  114. package/dist/modes/interactive/session-failure-info.d.ts.map +1 -0
  115. package/dist/modes/interactive/session-failure-info.js +21 -0
  116. package/dist/modes/interactive/session-failure-info.js.map +1 -0
  117. package/dist/modes/interactive/tips/catalog/model-tips.d.ts +7 -7
  118. package/dist/modes/interactive/tips/catalog/model-tips.d.ts.map +1 -1
  119. package/dist/modes/interactive/tips/catalog/model-tips.js +7 -1
  120. package/dist/modes/interactive/tips/catalog/model-tips.js.map +1 -1
  121. package/dist/modes/interactive/tips/catalog/session-tips.d.ts.map +1 -1
  122. package/dist/modes/interactive/tips/catalog/session-tips.js +1 -1
  123. package/dist/modes/interactive/tips/catalog/session-tips.js.map +1 -1
  124. package/dist/modes/rpc/host-attach-hold.d.ts +16 -0
  125. package/dist/modes/rpc/host-attach-hold.d.ts.map +1 -0
  126. package/dist/modes/rpc/host-attach-hold.js +9 -0
  127. package/dist/modes/rpc/host-attach-hold.js.map +1 -0
  128. package/dist/modes/rpc/host-cleanup-paths.d.ts +20 -0
  129. package/dist/modes/rpc/host-cleanup-paths.d.ts.map +1 -0
  130. package/dist/modes/rpc/host-cleanup-paths.js +13 -0
  131. package/dist/modes/rpc/host-cleanup-paths.js.map +1 -0
  132. package/dist/modes/rpc/host-client-occupancy.d.ts +24 -0
  133. package/dist/modes/rpc/host-client-occupancy.d.ts.map +1 -0
  134. package/dist/modes/rpc/host-client-occupancy.js +53 -0
  135. package/dist/modes/rpc/host-client-occupancy.js.map +1 -0
  136. package/dist/modes/rpc/host-daemon-paths.d.ts +61 -8
  137. package/dist/modes/rpc/host-daemon-paths.d.ts.map +1 -1
  138. package/dist/modes/rpc/host-daemon-paths.js +128 -11
  139. package/dist/modes/rpc/host-daemon-paths.js.map +1 -1
  140. package/dist/modes/rpc/host-daemon-registration.d.ts +11 -1
  141. package/dist/modes/rpc/host-daemon-registration.d.ts.map +1 -1
  142. package/dist/modes/rpc/host-daemon-registration.js +28 -15
  143. package/dist/modes/rpc/host-daemon-registration.js.map +1 -1
  144. package/dist/modes/rpc/host-endpoints.d.ts +12 -0
  145. package/dist/modes/rpc/host-endpoints.d.ts.map +1 -0
  146. package/dist/modes/rpc/host-endpoints.js +59 -0
  147. package/dist/modes/rpc/host-endpoints.js.map +1 -0
  148. package/dist/modes/rpc/host-ensure-lock.d.ts +11 -0
  149. package/dist/modes/rpc/host-ensure-lock.d.ts.map +1 -0
  150. package/dist/modes/rpc/host-ensure-lock.js +49 -0
  151. package/dist/modes/rpc/host-ensure-lock.js.map +1 -0
  152. package/dist/modes/rpc/host-ensure.d.ts +7 -0
  153. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  154. package/dist/modes/rpc/host-ensure.js +42 -65
  155. package/dist/modes/rpc/host-ensure.js.map +1 -1
  156. package/dist/modes/rpc/host-gc-evidence.d.ts +18 -0
  157. package/dist/modes/rpc/host-gc-evidence.d.ts.map +1 -0
  158. package/dist/modes/rpc/host-gc-evidence.js +128 -0
  159. package/dist/modes/rpc/host-gc-evidence.js.map +1 -0
  160. package/dist/modes/rpc/host-gc.d.ts +28 -0
  161. package/dist/modes/rpc/host-gc.d.ts.map +1 -0
  162. package/dist/modes/rpc/host-gc.js +110 -0
  163. package/dist/modes/rpc/host-gc.js.map +1 -0
  164. package/dist/modes/rpc/host-generations.d.ts +10 -2
  165. package/dist/modes/rpc/host-generations.d.ts.map +1 -1
  166. package/dist/modes/rpc/host-generations.js +12 -7
  167. package/dist/modes/rpc/host-generations.js.map +1 -1
  168. package/dist/modes/rpc/host-handoff.d.ts +6 -0
  169. package/dist/modes/rpc/host-handoff.d.ts.map +1 -1
  170. package/dist/modes/rpc/host-handoff.js +31 -4
  171. package/dist/modes/rpc/host-handoff.js.map +1 -1
  172. package/dist/modes/rpc/host-lifecycle-policy.d.ts +53 -0
  173. package/dist/modes/rpc/host-lifecycle-policy.d.ts.map +1 -0
  174. package/dist/modes/rpc/host-lifecycle-policy.js +64 -0
  175. package/dist/modes/rpc/host-lifecycle-policy.js.map +1 -0
  176. package/dist/modes/rpc/host-lifecycle.d.ts +1 -44
  177. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  178. package/dist/modes/rpc/host-lifecycle.js +23 -85
  179. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  180. package/dist/modes/rpc/host-observe-request.d.ts +17 -0
  181. package/dist/modes/rpc/host-observe-request.d.ts.map +1 -0
  182. package/dist/modes/rpc/host-observe-request.js +30 -0
  183. package/dist/modes/rpc/host-observe-request.js.map +1 -0
  184. package/dist/modes/rpc/host-probe.d.ts +12 -0
  185. package/dist/modes/rpc/host-probe.d.ts.map +1 -1
  186. package/dist/modes/rpc/host-probe.js +28 -1
  187. package/dist/modes/rpc/host-probe.js.map +1 -1
  188. package/dist/modes/rpc/host-protocol-info.d.ts +2 -0
  189. package/dist/modes/rpc/host-protocol-info.d.ts.map +1 -1
  190. package/dist/modes/rpc/host-protocol-info.js +1 -0
  191. package/dist/modes/rpc/host-protocol-info.js.map +1 -1
  192. package/dist/modes/rpc/host-readiness.d.ts +22 -0
  193. package/dist/modes/rpc/host-readiness.d.ts.map +1 -0
  194. package/dist/modes/rpc/host-readiness.js +44 -0
  195. package/dist/modes/rpc/host-readiness.js.map +1 -0
  196. package/dist/modes/rpc/host-runner.d.ts +13 -0
  197. package/dist/modes/rpc/host-runner.d.ts.map +1 -1
  198. package/dist/modes/rpc/host-runner.js +23 -4
  199. package/dist/modes/rpc/host-runner.js.map +1 -1
  200. package/dist/modes/rpc/host-status-all.d.ts +31 -0
  201. package/dist/modes/rpc/host-status-all.d.ts.map +1 -0
  202. package/dist/modes/rpc/host-status-all.js +78 -0
  203. package/dist/modes/rpc/host-status-all.js.map +1 -0
  204. package/dist/modes/rpc/host-status-rows.d.ts +35 -0
  205. package/dist/modes/rpc/host-status-rows.d.ts.map +1 -0
  206. package/dist/modes/rpc/host-status-rows.js +42 -0
  207. package/dist/modes/rpc/host-status-rows.js.map +1 -0
  208. package/dist/modes/rpc/host-status.d.ts +32 -1
  209. package/dist/modes/rpc/host-status.d.ts.map +1 -1
  210. package/dist/modes/rpc/host-status.js +33 -27
  211. package/dist/modes/rpc/host-status.js.map +1 -1
  212. package/dist/modes/rpc/host-successor.d.ts +3 -1
  213. package/dist/modes/rpc/host-successor.d.ts.map +1 -1
  214. package/dist/modes/rpc/host-successor.js +105 -42
  215. package/dist/modes/rpc/host-successor.js.map +1 -1
  216. package/dist/modes/rpc/host-watchdog.d.ts +6 -0
  217. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  218. package/dist/modes/rpc/host-watchdog.js +12 -13
  219. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  220. package/dist/modes/rpc/loop-lag-watchdog.d.ts +16 -0
  221. package/dist/modes/rpc/loop-lag-watchdog.d.ts.map +1 -1
  222. package/dist/modes/rpc/loop-lag-watchdog.js +34 -2
  223. package/dist/modes/rpc/loop-lag-watchdog.js.map +1 -1
  224. package/dist/modes/rpc/multi-session-host.d.ts +2 -1
  225. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  226. package/dist/modes/rpc/multi-session-host.js +33 -6
  227. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  228. package/dist/modes/rpc/rpc-mode.d.ts +2 -2
  229. package/dist/modes/rpc/rpc-mode.js +2 -2
  230. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  231. package/dist/modes/rpc/rpc-types.d.ts +16 -0
  232. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  233. package/dist/modes/rpc/rpc-types.js.map +1 -1
  234. package/dist/modes/rpc/session-command-router.d.ts +9 -1
  235. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  236. package/dist/modes/rpc/session-command-router.js +4 -1
  237. package/dist/modes/rpc/session-command-router.js.map +1 -1
  238. package/dist/modes/rpc/session-path-key.d.ts +3 -1
  239. package/dist/modes/rpc/session-path-key.d.ts.map +1 -1
  240. package/dist/modes/rpc/session-path-key.js +3 -1
  241. package/dist/modes/rpc/session-path-key.js.map +1 -1
  242. package/docs/rpc.md +186 -19
  243. package/docs/settings.md +25 -1
  244. package/docs/usage.md +5 -2
  245. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  246. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  247. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  248. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  249. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts +6 -0
  251. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts.map +1 -1
  252. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js +36 -0
  253. package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js.map +1 -1
  254. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +1 -0
  255. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  256. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +14 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  258. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  259. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  260. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  261. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  262. package/package.json +7 -7
  263. package/dist/bundle/chunks/chunk-3DEXCYNN.js +0 -135
  264. package/dist/bundle/chunks/chunk-5X4KSPK5.js +0 -12
  265. package/dist/bundle/chunks/chunk-KMD5ZONU.js +0 -5
  266. package/dist/bundle/chunks/chunk-PEHZYGYA.js +0 -8
  267. package/dist/bundle/chunks/chunk-PRC5XIIH.js +0 -2
  268. package/dist/bundle/chunks/chunk-QKY33652.js +0 -18
  269. package/dist/bundle/chunks/interactive-host-runtime-TIFT2SKR.js +0 -4
  270. package/dist/bundle/chunks/multi-session-host-GRHKB7Q2.js +0 -21
  271. package/dist/bundle/chunks/session-picker-FTFCQYHH.js +0 -2
@@ -0,0 +1,3 @@
1
+ import type { SessionFailureReport } from "../../core/session-failure-report.ts";
2
+ export declare function formatSessionFailureInfo(report: SessionFailureReport | undefined): string;
3
+ //# sourceMappingURL=session-failure-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-failure-info.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/session-failure-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAIjF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,SAAS,GAAG,MAAM,CAezF"}
@@ -0,0 +1,21 @@
1
+ import { formatDuration } from "../../utils/duration.js";
2
+ import { theme } from "./theme/theme.js";
3
+ export function formatSessionFailureInfo(report) {
4
+ if (!report)
5
+ return "";
6
+ const failed = report.erroredRequests + report.abortedRequests;
7
+ if (failed === 0)
8
+ return "";
9
+ const label = (text) => theme.fg("dim", text);
10
+ const share = `${(report.failureShare * 100).toFixed(1)}% failed`;
11
+ let info = `\n${theme.bold("Failures")}\n`;
12
+ info += `${label("Requests:")} ${report.requests} ${label(`(${report.erroredRequests} errored, ${report.abortedRequests} aborted, ${share})`)}\n`;
13
+ info += `${label("Time in failed requests:")} ${formatDuration(report.failedDurationMs)}\n`;
14
+ if (report.postFailureRequests > 0) {
15
+ const misses = report.postFailureFullMissRequests;
16
+ const tokens = report.postFailureFullMissInputTokens.toLocaleString();
17
+ info += `${label("Retries after a failure with no cache hit:")} ${misses} of ${report.postFailureRequests} ${label(`(${tokens} uncached input tokens)`)}\n`;
18
+ }
19
+ return info;
20
+ }
21
+ //# sourceMappingURL=session-failure-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-failure-info.js","sourceRoot":"","sources":["../../../src/modes/interactive/session-failure-info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,MAAM,UAAU,wBAAwB,CAAC,MAAwC;IAChF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAC/D,IAAI,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAClE,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC3C,IAAI,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,eAAe,aAAa,MAAM,CAAC,eAAe,aAAa,KAAK,GAAG,CAAC,IAAI,CAAC;IAClJ,IAAI,IAAI,GAAG,KAAK,CAAC,0BAA0B,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC;IAC5F,IAAI,MAAM,CAAC,mBAAmB,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,2BAA2B,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,CAAC,8BAA8B,CAAC,cAAc,EAAE,CAAC;QACtE,IAAI,IAAI,GAAG,KAAK,CAAC,4CAA4C,CAAC,IAAI,MAAM,OAAO,MAAM,CAAC,mBAAmB,IAAI,KAAK,CAAC,IAAI,MAAM,yBAAyB,CAAC,IAAI,CAAC;IAC7J,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC","sourcesContent":["import type { SessionFailureReport } from \"../../core/session-failure-report.ts\";\nimport { formatDuration } from \"../../utils/duration.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport function formatSessionFailureInfo(report: SessionFailureReport | undefined): string {\n\tif (!report) return \"\";\n\tconst failed = report.erroredRequests + report.abortedRequests;\n\tif (failed === 0) return \"\";\n\tconst label = (text: string) => theme.fg(\"dim\", text);\n\tconst share = `${(report.failureShare * 100).toFixed(1)}% failed`;\n\tlet info = `\\n${theme.bold(\"Failures\")}\\n`;\n\tinfo += `${label(\"Requests:\")} ${report.requests} ${label(`(${report.erroredRequests} errored, ${report.abortedRequests} aborted, ${share})`)}\\n`;\n\tinfo += `${label(\"Time in failed requests:\")} ${formatDuration(report.failedDurationMs)}\\n`;\n\tif (report.postFailureRequests > 0) {\n\t\tconst misses = report.postFailureFullMissRequests;\n\t\tconst tokens = report.postFailureFullMissInputTokens.toLocaleString();\n\t\tinfo += `${label(\"Retries after a failure with no cache hit:\")} ${misses} of ${report.postFailureRequests} ${label(`(${tokens} uncached input tokens)`)}\\n`;\n\t}\n\treturn info;\n}\n"]}
@@ -4,19 +4,19 @@ export declare const MODEL_TIPS: ({
4
4
  render: (keys: (binding: import("@earendil-works/pi-tui").Keybinding) => string) => string;
5
5
  requiresCommand?: undefined;
6
6
  } | {
7
+ id: string;
8
+ bindings: never[];
9
+ requiresCommand: string;
10
+ render: () => string;
11
+ } | {
12
+ requiresCommand?: undefined;
7
13
  id: string;
8
14
  bindings: ("app.model.cycleBackward" | "app.model.cycleForward")[];
9
15
  render: (keys: (binding: import("@earendil-works/pi-tui").Keybinding) => string) => string;
10
- requiresCommand?: undefined;
11
16
  } | {
17
+ requiresCommand?: undefined;
12
18
  id: string;
13
19
  bindings: ("app.model.select" | "app.models.toggleFavorite")[];
14
20
  render: (keys: (binding: import("@earendil-works/pi-tui").Keybinding) => string) => string;
15
- requiresCommand?: undefined;
16
- } | {
17
- id: string;
18
- bindings: never[];
19
- requiresCommand: string;
20
- render: () => string;
21
21
  })[];
22
22
  //# sourceMappingURL=model-tips.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-tips.d.ts","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/model-tips.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;IAwDa,CAAC"}
1
+ {"version":3,"file":"model-tips.d.ts","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/model-tips.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;IAgEa,CAAC"}
@@ -3,7 +3,13 @@ export const MODEL_TIPS = [
3
3
  {
4
4
  id: "thinking-level",
5
5
  bindings: ["app.thinking.cycle"],
6
- render: (keys) => `Use ${keys("app.thinking.cycle")} to cycle the model's thinking level.`,
6
+ render: (keys) => `Use /thinking <level> to set the thinking level, /thinking to pick one, or ${keys("app.thinking.cycle")} to cycle through them.`,
7
+ },
8
+ {
9
+ id: "efforts-command",
10
+ bindings: [],
11
+ requiresCommand: "efforts",
12
+ render: () => "Use /efforts <level> to set the reasoning effort for the current model; /efforts alone lists the levels it supports.",
7
13
  },
8
14
  {
9
15
  id: "favorite-model-rotation",
@@ -1 +1 @@
1
- {"version":3,"file":"model-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/model-tips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB;QACC,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,CAAC,oBAAoB,CAAC;QAChC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,oBAAoB,CAAC,uCAAuC;KAC1F;IACD;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,CAAC,wBAAwB,EAAE,yBAAyB,CAAC;QAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,uCAAuC,IAAI,CAAC,wBAAwB,CAAC,sBAAsB,IAAI,CAAC,yBAAyB,CAAC,GAAG;KAC9H;IACD;QACC,EAAE,EAAE,0BAA0B;QAC9B,QAAQ,EAAE,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;QAC3D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,gCAAgC,IAAI,CAAC,kBAAkB,CAAC,cAAc,IAAI,CAAC,2BAA2B,CAAC,sCAAsC;KAC9I;IACD;QACC,EAAE,EAAE,sBAAsB;QAC1B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,4FAA4F;KAC1G;IACD;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,CAAC,wBAAwB,CAAC;QACpC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,SAAS,QAAQ,6DAA6D,IAAI,CAAC,wBAAwB,CAAC,kBAAkB;KAC/H;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,6FAA6F;KAC3G;IACD;QACC,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,iGAAiG;KAC/G;IACD;QACC,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,iGAAiG;KAC/G;IACD;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CACZ,oHAAoH;KACrH;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CAAC,qFAAqF;KACnG;CACkC,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport type { TipDefinition } from \"./types.ts\";\n\nexport const MODEL_TIPS = [\n\t{\n\t\tid: \"thinking-level\",\n\t\tbindings: [\"app.thinking.cycle\"],\n\t\trender: (keys) => `Use ${keys(\"app.thinking.cycle\")} to cycle the model's thinking level.`,\n\t},\n\t{\n\t\tid: \"favorite-model-rotation\",\n\t\tbindings: [\"app.model.cycleForward\", \"app.model.cycleBackward\"],\n\t\trender: (keys) =>\n\t\t\t`Rotate through favorite models with ${keys(\"app.model.cycleForward\")}; go backward with ${keys(\"app.model.cycleBackward\")}.`,\n\t},\n\t{\n\t\tid: \"model-selector-favorites\",\n\t\tbindings: [\"app.model.select\", \"app.models.toggleFavorite\"],\n\t\trender: (keys) =>\n\t\t\t`Open the model selector with ${keys(\"app.model.select\")}, then use ${keys(\"app.models.toggleFavorite\")} to toggle the highlighted favorite.`,\n\t},\n\t{\n\t\tid: \"model-command-search\",\n\t\tbindings: [],\n\t\trender: () => \"Use /model to open the selector, or /model <pattern> to jump straight to a matching model.\",\n\t},\n\t{\n\t\tid: \"model-cycling-scope\",\n\t\tbindings: [\"app.model.cycleForward\"],\n\t\trender: (keys) =>\n\t\t\t`Start ${APP_NAME} with --models \"anthropic/*,gpt-5*\" to limit which models ${keys(\"app.model.cycleForward\")} cycles through.`,\n\t},\n\t{\n\t\tid: \"thinking-budgets\",\n\t\tbindings: [],\n\t\trender: () => \"Set thinkingBudgets in settings.json to choose the token budget behind each thinking level.\",\n\t},\n\t{\n\t\tid: \"prompt-preset\",\n\t\tbindings: [],\n\t\trender: () => \"Set promptPreset in settings.json when a model does not auto-detect the system prompt you want.\",\n\t},\n\t{\n\t\tid: \"provider-login\",\n\t\tbindings: [],\n\t\trender: () => \"Use /login to add a subscription or API-key provider, and /logout to remove stored credentials.\",\n\t},\n\t{\n\t\tid: \"fallback-chains-setting\",\n\t\tbindings: [],\n\t\trender: () =>\n\t\t\t\"retry.fallbackChains in settings.json maps a model to ordered fallbacks, so a failed turn retries on the next one.\",\n\t},\n\t{\n\t\tid: \"fallback-command\",\n\t\tbindings: [],\n\t\trequiresCommand: \"fallback\",\n\t\trender: () => \"Use /fallback to inspect and manage the retry fallback chain for the current model.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
1
+ {"version":3,"file":"model-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/model-tips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,MAAM,CAAC,MAAM,UAAU,GAAG;IACzB;QACC,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,CAAC,oBAAoB,CAAC;QAChC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,8EAA8E,IAAI,CAAC,oBAAoB,CAAC,yBAAyB;KAClI;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,SAAS;QAC1B,MAAM,EAAE,GAAG,EAAE,CACZ,sHAAsH;KACvH;IACD;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,CAAC,wBAAwB,EAAE,yBAAyB,CAAC;QAC/D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,uCAAuC,IAAI,CAAC,wBAAwB,CAAC,sBAAsB,IAAI,CAAC,yBAAyB,CAAC,GAAG;KAC9H;IACD;QACC,EAAE,EAAE,0BAA0B;QAC9B,QAAQ,EAAE,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;QAC3D,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,gCAAgC,IAAI,CAAC,kBAAkB,CAAC,cAAc,IAAI,CAAC,2BAA2B,CAAC,sCAAsC;KAC9I;IACD;QACC,EAAE,EAAE,sBAAsB;QAC1B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,4FAA4F;KAC1G;IACD;QACC,EAAE,EAAE,qBAAqB;QACzB,QAAQ,EAAE,CAAC,wBAAwB,CAAC;QACpC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,SAAS,QAAQ,6DAA6D,IAAI,CAAC,wBAAwB,CAAC,kBAAkB;KAC/H;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,6FAA6F;KAC3G;IACD;QACC,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,iGAAiG;KAC/G;IACD;QACC,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,iGAAiG;KAC/G;IACD;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CACZ,oHAAoH;KACrH;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,UAAU;QAC3B,MAAM,EAAE,GAAG,EAAE,CAAC,qFAAqF;KACnG;CACkC,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport type { TipDefinition } from \"./types.ts\";\n\nexport const MODEL_TIPS = [\n\t{\n\t\tid: \"thinking-level\",\n\t\tbindings: [\"app.thinking.cycle\"],\n\t\trender: (keys) =>\n\t\t\t`Use /thinking <level> to set the thinking level, /thinking to pick one, or ${keys(\"app.thinking.cycle\")} to cycle through them.`,\n\t},\n\t{\n\t\tid: \"efforts-command\",\n\t\tbindings: [],\n\t\trequiresCommand: \"efforts\",\n\t\trender: () =>\n\t\t\t\"Use /efforts <level> to set the reasoning effort for the current model; /efforts alone lists the levels it supports.\",\n\t},\n\t{\n\t\tid: \"favorite-model-rotation\",\n\t\tbindings: [\"app.model.cycleForward\", \"app.model.cycleBackward\"],\n\t\trender: (keys) =>\n\t\t\t`Rotate through favorite models with ${keys(\"app.model.cycleForward\")}; go backward with ${keys(\"app.model.cycleBackward\")}.`,\n\t},\n\t{\n\t\tid: \"model-selector-favorites\",\n\t\tbindings: [\"app.model.select\", \"app.models.toggleFavorite\"],\n\t\trender: (keys) =>\n\t\t\t`Open the model selector with ${keys(\"app.model.select\")}, then use ${keys(\"app.models.toggleFavorite\")} to toggle the highlighted favorite.`,\n\t},\n\t{\n\t\tid: \"model-command-search\",\n\t\tbindings: [],\n\t\trender: () => \"Use /model to open the selector, or /model <pattern> to jump straight to a matching model.\",\n\t},\n\t{\n\t\tid: \"model-cycling-scope\",\n\t\tbindings: [\"app.model.cycleForward\"],\n\t\trender: (keys) =>\n\t\t\t`Start ${APP_NAME} with --models \"anthropic/*,gpt-5*\" to limit which models ${keys(\"app.model.cycleForward\")} cycles through.`,\n\t},\n\t{\n\t\tid: \"thinking-budgets\",\n\t\tbindings: [],\n\t\trender: () => \"Set thinkingBudgets in settings.json to choose the token budget behind each thinking level.\",\n\t},\n\t{\n\t\tid: \"prompt-preset\",\n\t\tbindings: [],\n\t\trender: () => \"Set promptPreset in settings.json when a model does not auto-detect the system prompt you want.\",\n\t},\n\t{\n\t\tid: \"provider-login\",\n\t\tbindings: [],\n\t\trender: () => \"Use /login to add a subscription or API-key provider, and /logout to remove stored credentials.\",\n\t},\n\t{\n\t\tid: \"fallback-chains-setting\",\n\t\tbindings: [],\n\t\trender: () =>\n\t\t\t\"retry.fallbackChains in settings.json maps a model to ordered fallbacks, so a failed turn retries on the next one.\",\n\t},\n\t{\n\t\tid: \"fallback-command\",\n\t\tbindings: [],\n\t\trequiresCommand: \"fallback\",\n\t\trender: () => \"Use /fallback to inspect and manage the retry fallback chain for the current model.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-tips.d.ts","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/session-tips.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY;;;;GAoDW,CAAC"}
1
+ {"version":3,"file":"session-tips.d.ts","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/session-tips.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY;;;;GAqDW,CAAC"}
@@ -23,7 +23,7 @@ export const SESSION_TIPS = [
23
23
  {
24
24
  id: "continue-session",
25
25
  bindings: [],
26
- render: () => `${APP_NAME} -c continues your most recent session; ${APP_NAME} -r opens the session picker.`,
26
+ render: () => `Use /resume or /sessions to reopen a past session; from the shell, ${APP_NAME} -r opens the same picker and ${APP_NAME} -c continues the most recent one.`,
27
27
  },
28
28
  {
29
29
  id: "session-name",
@@ -1 +1 @@
1
- {"version":3,"file":"session-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/session-tips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,yEAAyE;KACvF;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,0EAA0E;KACxF;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,sEAAsE;KACpF;IACD;QACC,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,gGAAgG;KAC9G;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,2CAA2C,QAAQ,+BAA+B;KAC3G;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,2FAA2F;KACzG;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,4EAA4E;KAC1F;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,mGAAmG;KACjH;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,gGAAgG;KAC9G;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CACZ,0HAA0H;KAC3H;CACkC,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport type { TipDefinition } from \"./types.ts\";\n\nexport const SESSION_TIPS = [\n\t{\n\t\tid: \"favorite-models-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /favorite-models to choose and reorder the models in your rotation.\",\n\t},\n\t{\n\t\tid: \"tree-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /tree to revisit earlier points and switch between session branches.\",\n\t},\n\t{\n\t\tid: \"fork-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /fork to create a separate session from an earlier user message.\",\n\t},\n\t{\n\t\tid: \"clone-session\",\n\t\tbindings: [],\n\t\trender: () => \"Use /clone to duplicate the current branch into its own session before trying something risky.\",\n\t},\n\t{\n\t\tid: \"continue-session\",\n\t\tbindings: [],\n\t\trender: () => `${APP_NAME} -c continues your most recent session; ${APP_NAME} -r opens the session picker.`,\n\t},\n\t{\n\t\tid: \"session-name\",\n\t\tbindings: [],\n\t\trender: () => \"Use /rename [name] to label a session so it is easy to spot in the footer and in /resume.\",\n\t},\n\t{\n\t\tid: \"session-info\",\n\t\tbindings: [],\n\t\trender: () => \"Use /session to see the session file, id, message count, tokens, and cost.\",\n\t},\n\t{\n\t\tid: \"export-share\",\n\t\tbindings: [],\n\t\trender: () => \"Use /export to write the session to HTML or JSONL, or /share to upload it as a private gist link.\",\n\t},\n\t{\n\t\tid: \"compact-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /compact to compact context now, or /compact <prompt> to tell the summarizer what to keep.\",\n\t},\n\t{\n\t\tid: \"auto-compaction\",\n\t\tbindings: [],\n\t\trender: () =>\n\t\t\t\"Auto-compaction is on by default - the (auto) marker in the footer shows it; tune it with compaction.* in settings.json.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
1
+ {"version":3,"file":"session-tips.js","sourceRoot":"","sources":["../../../../../src/modes/interactive/tips/catalog/session-tips.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B;QACC,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,yEAAyE;KACvF;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,0EAA0E;KACxF;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,sEAAsE;KACpF;IACD;QACC,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,gGAAgG;KAC9G;IACD;QACC,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CACZ,sEAAsE,QAAQ,iCAAiC,QAAQ,oCAAoC;KAC5J;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,2FAA2F;KACzG;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,4EAA4E;KAC1F;IACD;QACC,EAAE,EAAE,cAAc;QAClB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,mGAAmG;KACjH;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,gGAAgG;KAC9G;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,GAAG,EAAE,CACZ,0HAA0H;KAC3H;CACkC,CAAC","sourcesContent":["import { APP_NAME } from \"../../../../config.ts\";\nimport type { TipDefinition } from \"./types.ts\";\n\nexport const SESSION_TIPS = [\n\t{\n\t\tid: \"favorite-models-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /favorite-models to choose and reorder the models in your rotation.\",\n\t},\n\t{\n\t\tid: \"tree-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /tree to revisit earlier points and switch between session branches.\",\n\t},\n\t{\n\t\tid: \"fork-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /fork to create a separate session from an earlier user message.\",\n\t},\n\t{\n\t\tid: \"clone-session\",\n\t\tbindings: [],\n\t\trender: () => \"Use /clone to duplicate the current branch into its own session before trying something risky.\",\n\t},\n\t{\n\t\tid: \"continue-session\",\n\t\tbindings: [],\n\t\trender: () =>\n\t\t\t`Use /resume or /sessions to reopen a past session; from the shell, ${APP_NAME} -r opens the same picker and ${APP_NAME} -c continues the most recent one.`,\n\t},\n\t{\n\t\tid: \"session-name\",\n\t\tbindings: [],\n\t\trender: () => \"Use /rename [name] to label a session so it is easy to spot in the footer and in /resume.\",\n\t},\n\t{\n\t\tid: \"session-info\",\n\t\tbindings: [],\n\t\trender: () => \"Use /session to see the session file, id, message count, tokens, and cost.\",\n\t},\n\t{\n\t\tid: \"export-share\",\n\t\tbindings: [],\n\t\trender: () => \"Use /export to write the session to HTML or JSONL, or /share to upload it as a private gist link.\",\n\t},\n\t{\n\t\tid: \"compact-command\",\n\t\tbindings: [],\n\t\trender: () => \"Use /compact to compact context now, or /compact <prompt> to tell the summarizer what to keep.\",\n\t},\n\t{\n\t\tid: \"auto-compaction\",\n\t\tbindings: [],\n\t\trender: () =>\n\t\t\t\"Auto-compaction is on by default - the (auto) marker in the footer shows it; tune it with compaction.* in settings.json.\",\n\t},\n] satisfies readonly TipDefinition[];\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The ensuring client's claim on a host between `ensureHost()` proving it ready and that client's
3
+ * own attach. It is the very connection the readiness answer arrived on, kept open, so the
4
+ * supervisor counts it as an attachment and never measures idle time across the gap: a transient
5
+ * host with a short idle window cannot exit before the client that asked for it has attached.
6
+ *
7
+ * The claim ends when the caller releases it, and the operating system ends it when the ensuring
8
+ * process dies, so an abandoned ensure never pins a host. It never keeps its own process alive.
9
+ */
10
+ import type { Socket } from "node:net";
11
+ export interface HostAttachHold {
12
+ /** Ends the claim. Idempotent; call it once the client's own connection is attached. */
13
+ release(): void;
14
+ }
15
+ export declare function holdAttachment(socket: Socket): HostAttachHold;
16
+ //# sourceMappingURL=host-attach-hold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-attach-hold.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-attach-hold.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC9B,wFAAwF;IACxF,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAO7D"}
@@ -0,0 +1,9 @@
1
+ export function holdAttachment(socket) {
2
+ // A host broadcasts lifecycle records to every connection; drain them so the pipe never backs up.
3
+ socket.removeAllListeners("data");
4
+ socket.resume();
5
+ socket.on("error", () => socket.destroy());
6
+ socket.unref();
7
+ return { release: () => socket.destroy() };
8
+ }
9
+ //# sourceMappingURL=host-attach-hold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-attach-hold.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-attach-hold.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,cAAc,CAAC,MAAc;IAC5C,kGAAkG;IAClG,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * The ensuring client's claim on a host between `ensureHost()` proving it ready and that client's\n * own attach. It is the very connection the readiness answer arrived on, kept open, so the\n * supervisor counts it as an attachment and never measures idle time across the gap: a transient\n * host with a short idle window cannot exit before the client that asked for it has attached.\n *\n * The claim ends when the caller releases it, and the operating system ends it when the ensuring\n * process dies, so an abandoned ensure never pins a host. It never keeps its own process alive.\n */\nimport type { Socket } from \"node:net\";\n\nexport interface HostAttachHold {\n\t/** Ends the claim. Idempotent; call it once the client's own connection is attached. */\n\trelease(): void;\n}\n\nexport function holdAttachment(socket: Socket): HostAttachHold {\n\t// A host broadcasts lifecycle records to every connection; drain them so the pipe never backs up.\n\tsocket.removeAllListeners(\"data\");\n\tsocket.resume();\n\tsocket.on(\"error\", () => socket.destroy());\n\tsocket.unref();\n\treturn { release: () => socket.destroy() };\n}\n"]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * What a host child removes when its supervisor dies without cleaning up, in the order it removes
3
+ * them. The registration pointer comes LAST: every reader takes "no pointer" to mean "this endpoint
4
+ * has no host", so the pointer may only disappear once everything it describes is already gone
5
+ * (senpi#2241).
6
+ */
7
+ export interface HostCleanupTargets {
8
+ readonly pointerFile: string;
9
+ readonly generationPidFile: string;
10
+ readonly settingsFile: string;
11
+ readonly publicSocket: string;
12
+ /**
13
+ * A successor writes no registration of its own until the ensure that spawned it does, and the
14
+ * files under these paths still describe the generation being replaced.
15
+ */
16
+ readonly successor: boolean;
17
+ readonly platform: NodeJS.Platform;
18
+ }
19
+ export declare function hostCrashCleanupPaths(targets: HostCleanupTargets): string[];
20
+ //# sourceMappingURL=host-cleanup-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-cleanup-paths.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-cleanup-paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;CACnC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAU3E"}
@@ -0,0 +1,13 @@
1
+ export function hostCrashCleanupPaths(targets) {
2
+ // POSIX public sockets are removed ownership-checked by the host child
3
+ // (token: the scratch-directory sidecar plus HOST_PUBLIC_SOCKET_ENV),
4
+ // never by path from a crash-path cleanup: a blind removal here would
5
+ // unlink a newer host's freshly published entry after a takeover.
6
+ // Windows named pipes have no filesystem entry to own, so they stay
7
+ // listed for the crash-path cleanup.
8
+ const publicEntry = targets.platform === "win32" ? [targets.publicSocket] : [];
9
+ if (targets.successor)
10
+ return publicEntry;
11
+ return [targets.generationPidFile, targets.settingsFile, ...publicEntry, targets.pointerFile];
12
+ }
13
+ //# sourceMappingURL=host-cleanup-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-cleanup-paths.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-cleanup-paths.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,qBAAqB,CAAC,OAA2B;IAChE,uEAAuE;IACvE,sEAAsE;IACtE,sEAAsE;IACtE,kEAAkE;IAClE,oEAAoE;IACpE,qCAAqC;IACrC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,IAAI,OAAO,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IAC1C,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;AAC/F,CAAC","sourcesContent":["/**\n * What a host child removes when its supervisor dies without cleaning up, in the order it removes\n * them. The registration pointer comes LAST: every reader takes \"no pointer\" to mean \"this endpoint\n * has no host\", so the pointer may only disappear once everything it describes is already gone\n * (senpi#2241).\n */\nexport interface HostCleanupTargets {\n\treadonly pointerFile: string;\n\treadonly generationPidFile: string;\n\treadonly settingsFile: string;\n\treadonly publicSocket: string;\n\t/**\n\t * A successor writes no registration of its own until the ensure that spawned it does, and the\n\t * files under these paths still describe the generation being replaced.\n\t */\n\treadonly successor: boolean;\n\treadonly platform: NodeJS.Platform;\n}\n\nexport function hostCrashCleanupPaths(targets: HostCleanupTargets): string[] {\n\t// POSIX public sockets are removed ownership-checked by the host child\n\t// (token: the scratch-directory sidecar plus HOST_PUBLIC_SOCKET_ENV),\n\t// never by path from a crash-path cleanup: a blind removal here would\n\t// unlink a newer host's freshly published entry after a takeover.\n\t// Windows named pipes have no filesystem entry to own, so they stay\n\t// listed for the crash-path cleanup.\n\tconst publicEntry = targets.platform === \"win32\" ? [targets.publicSocket] : [];\n\tif (targets.successor) return publicEntry;\n\treturn [targets.generationPidFile, targets.settingsFile, ...publicEntry, targets.pointerFile];\n}\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The supervisor's view of its public-socket clients, split by what they mean for idle exit. A socket
3
+ * host applies the same view to its own connections for its empty-exit window.
4
+ *
5
+ * A client is UNCLASSIFIED until its first request line arrives, an OBSERVER while every line it has
6
+ * sent is an observing read (`host-observe-request.ts`), and ATTACHED from the first line that is
7
+ * anything else - or from a first line too long to be a read. Only attached clients are occupancy.
8
+ * An unclassified client neither counts nor lets the host exit: its first line may be the readiness
9
+ * probe of an ensure that is about to open a session.
10
+ */
11
+ import type { Socket } from "node:net";
12
+ export declare class ClientOccupancy {
13
+ private readonly clients;
14
+ private readonly observers;
15
+ private readonly attached;
16
+ private readonly onAttach;
17
+ constructor(onAttach: () => void);
18
+ get attachedCount(): number;
19
+ get unclassifiedCount(): number;
20
+ admit(client: Socket): void;
21
+ release(client: Socket): void;
22
+ destroyAll(): void;
23
+ }
24
+ //# sourceMappingURL=host-client-occupancy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-client-occupancy.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-client-occupancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMvC,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IAEtC,YAAY,QAAQ,EAAE,MAAM,IAAI,EAE/B;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAwB1B;IAED,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAI5B;IAED,UAAU,IAAI,IAAI,CAEjB;CACD"}
@@ -0,0 +1,53 @@
1
+ import { isObservingRequest } from "./host-observe-request.js";
2
+ const MAX_CLASSIFIED_LINE_BYTES = 64 * 1024;
3
+ const NEWLINE = 0x0a;
4
+ export class ClientOccupancy {
5
+ constructor(onAttach) {
6
+ this.clients = new Set();
7
+ this.observers = new Set();
8
+ this.attached = new Set();
9
+ this.onAttach = onAttach;
10
+ }
11
+ get attachedCount() {
12
+ return this.attached.size;
13
+ }
14
+ get unclassifiedCount() {
15
+ return this.clients.size - this.observers.size - this.attached.size;
16
+ }
17
+ admit(client) {
18
+ this.clients.add(client);
19
+ let pending = Buffer.alloc(0);
20
+ const attach = () => {
21
+ client.off("data", classify);
22
+ pending = Buffer.alloc(0);
23
+ this.observers.delete(client);
24
+ this.attached.add(client);
25
+ this.onAttach();
26
+ };
27
+ const classify = (chunk) => {
28
+ pending = Buffer.concat([pending, chunk]);
29
+ for (let newline = pending.indexOf(NEWLINE); newline !== -1; newline = pending.indexOf(NEWLINE)) {
30
+ const line = pending.subarray(0, newline).toString("utf8");
31
+ pending = pending.subarray(newline + 1);
32
+ if (!isObservingRequest(line)) {
33
+ attach();
34
+ return;
35
+ }
36
+ this.observers.add(client);
37
+ }
38
+ if (pending.length > MAX_CLASSIFIED_LINE_BYTES)
39
+ attach();
40
+ };
41
+ client.on("data", classify);
42
+ }
43
+ release(client) {
44
+ this.clients.delete(client);
45
+ this.observers.delete(client);
46
+ this.attached.delete(client);
47
+ }
48
+ destroyAll() {
49
+ for (const client of this.clients)
50
+ client.destroy();
51
+ }
52
+ }
53
+ //# sourceMappingURL=host-client-occupancy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-client-occupancy.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-client-occupancy.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,CAAC;AAC5C,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB,MAAM,OAAO,eAAe;IAM3B,YAAY,QAAoB;QALf,YAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAC5B,cAAS,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,aAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QAI7C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,CAAC;IAED,IAAI,aAAa;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,iBAAiB;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,MAAc;QACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,IAAI,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,GAAS,EAAE;YACzB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC7B,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAQ,EAAE;YACxC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC1C,KAAK,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjG,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC3D,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBACxC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/B,MAAM,EAAE,CAAC;oBACT,OAAO;gBACR,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,GAAG,yBAAyB;gBAAE,MAAM,EAAE,CAAC;QAC1D,CAAC,CAAC;QACF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,MAAc;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,UAAU;QACT,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IACrD,CAAC;CACD","sourcesContent":["/**\n * The supervisor's view of its public-socket clients, split by what they mean for idle exit. A socket\n * host applies the same view to its own connections for its empty-exit window.\n *\n * A client is UNCLASSIFIED until its first request line arrives, an OBSERVER while every line it has\n * sent is an observing read (`host-observe-request.ts`), and ATTACHED from the first line that is\n * anything else - or from a first line too long to be a read. Only attached clients are occupancy.\n * An unclassified client neither counts nor lets the host exit: its first line may be the readiness\n * probe of an ensure that is about to open a session.\n */\nimport type { Socket } from \"node:net\";\nimport { isObservingRequest } from \"./host-observe-request.ts\";\n\nconst MAX_CLASSIFIED_LINE_BYTES = 64 * 1024;\nconst NEWLINE = 0x0a;\n\nexport class ClientOccupancy {\n\tprivate readonly clients = new Set<Socket>();\n\tprivate readonly observers = new Set<Socket>();\n\tprivate readonly attached = new Set<Socket>();\n\tprivate readonly onAttach: () => void;\n\n\tconstructor(onAttach: () => void) {\n\t\tthis.onAttach = onAttach;\n\t}\n\n\tget attachedCount(): number {\n\t\treturn this.attached.size;\n\t}\n\n\tget unclassifiedCount(): number {\n\t\treturn this.clients.size - this.observers.size - this.attached.size;\n\t}\n\n\tadmit(client: Socket): void {\n\t\tthis.clients.add(client);\n\t\tlet pending = Buffer.alloc(0);\n\t\tconst attach = (): void => {\n\t\t\tclient.off(\"data\", classify);\n\t\t\tpending = Buffer.alloc(0);\n\t\t\tthis.observers.delete(client);\n\t\t\tthis.attached.add(client);\n\t\t\tthis.onAttach();\n\t\t};\n\t\tconst classify = (chunk: Buffer): void => {\n\t\t\tpending = Buffer.concat([pending, chunk]);\n\t\t\tfor (let newline = pending.indexOf(NEWLINE); newline !== -1; newline = pending.indexOf(NEWLINE)) {\n\t\t\t\tconst line = pending.subarray(0, newline).toString(\"utf8\");\n\t\t\t\tpending = pending.subarray(newline + 1);\n\t\t\t\tif (!isObservingRequest(line)) {\n\t\t\t\t\tattach();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.observers.add(client);\n\t\t\t}\n\t\t\tif (pending.length > MAX_CLASSIFIED_LINE_BYTES) attach();\n\t\t};\n\t\tclient.on(\"data\", classify);\n\t}\n\n\trelease(client: Socket): void {\n\t\tthis.clients.delete(client);\n\t\tthis.observers.delete(client);\n\t\tthis.attached.delete(client);\n\t}\n\n\tdestroyAll(): void {\n\t\tfor (const client of this.clients) client.destroy();\n\t}\n}\n"]}
@@ -4,14 +4,18 @@ export declare const HOST_DAEMON_LAYOUT = 2;
4
4
  export declare const HOST_DAEMON_DIR_ENV = "SENPI_RPC_HOST_DAEMON_DIR";
5
5
  export declare const HOST_STATE_FILE_MODE = 384;
6
6
  export interface HostDaemonPaths {
7
+ /** The endpoint these paths belong to, exactly as its directory name was derived from. */
8
+ readonly socket: string;
7
9
  /** `<agentDir>/rpc-host-daemon`: shared by every endpoint, and by any legacy host's own state. */
8
10
  readonly flatDir: string;
9
11
  /** The only file this build writes into the flat directory: `{ layout, dir }`. */
10
12
  readonly layoutMarker: string;
11
13
  /** A LEGACY host's registration. Read-only evidence that another host may be running. */
12
14
  readonly legacyPidFile: string;
13
- /** This endpoint's state directory, `<flatDir>/<sha256(socket)[:16]>`. */
15
+ /** This endpoint's state directory, `<flatDir>/<sha256(canonical socket)[:16]>`. */
14
16
  readonly dir: string;
17
+ /** Durable identity `{ layout, socket, created_at }`: survives every generation's release. */
18
+ readonly endpointFile: string;
15
19
  /** The pointer at the current generation. Deliberately unparseable as a legacy pidfile. */
16
20
  readonly pointerFile: string;
17
21
  /** Cross-version ensure lock for this endpoint (the endpoint lock itself lives in the temp dir). */
@@ -21,6 +25,8 @@ export interface HostDaemonPaths {
21
25
  readonly generationsDir: string;
22
26
  readonly reservationsDir: string;
23
27
  }
28
+ /** The files inside one endpoint's directory, for a reader that has the directory but not its socket. */
29
+ export type HostDaemonDirectory = Omit<HostDaemonPaths, "socket" | "flatDir" | "layoutMarker" | "legacyPidFile">;
24
30
  export interface HostGenerationPaths {
25
31
  readonly dir: string;
26
32
  /** Where the pointer names this generation: relative to the daemon directory holding it. */
@@ -30,13 +36,44 @@ export interface HostGenerationPaths {
30
36
  readonly scratchDir: string;
31
37
  }
32
38
  /**
33
- * The directory name every client recomputes from the socket alone: `sha256(<canonical endpoint>)`,
34
- * where the canonical endpoint is the socket path on POSIX and the normalized lower-cased path on
35
- * win32 (the same canonicalization the pipe name is derived from, so two spellings of one endpoint
36
- * share one directory). Deliberately total: naming a directory must never fail on a path shape the
37
- * transport would reject, or a client could not even report WHERE it was looking.
39
+ * The one spelling of an endpoint every client derives the same way. On POSIX that is the socket path
40
+ * with its directory resolved through its deepest existing ancestor (`/tmp` vs `/private/tmp`, a
41
+ * symlinked agent directory) - the identity the ensure lock is keyed by - and a path already spelled
42
+ * that way comes back unchanged. On win32 it is the normalized lower-cased path the pipe name is derived
43
+ * from. An abstract socket has no directory to resolve. Deliberately total: naming a directory must never
44
+ * fail on a path shape the transport would reject, or a client could not even report WHERE it was looking.
45
+ */
46
+ export declare function canonicalEndpointPath(socket: string, platform?: NodeJS.Platform): string;
47
+ /**
48
+ * The directory name every client recomputes from the socket alone: `sha256(<canonical endpoint>)`, so
49
+ * every spelling of one endpoint shares one directory, and a canonical spelling keeps the name it had
50
+ * when the name was hashed from the spelling itself.
38
51
  */
39
52
  export declare function daemonDirectoryName(socket: string, platform?: NodeJS.Platform): string;
53
+ /** Whether two spellings name one endpoint. */
54
+ export declare function sameEndpoint(socket: string, other: string): boolean;
55
+ /**
56
+ * Whether a record naming `socket` belongs in the directory called `name`: the canonical name, or the
57
+ * name a build that hashed the spelling itself gave it - that directory has to stay listable, and
58
+ * therefore collectable by `host gc`, after the upgrade.
59
+ */
60
+ export declare function socketNamesDirectory(socket: string, name: string): boolean;
61
+ /**
62
+ * The owner-keyed shard naming contract every client computes identically - senpi, omo (library
63
+ * import) and the Desktop (a local mirror checked against `senpi host shard-path`): `p` shards belong
64
+ * to a parent session, `i` shards to an interactive thread. The key is `sha256("<kind>:<owner>")` in
65
+ * hex, first 16 characters; the socket is `<root>/<kind>-<key>.sock`.
66
+ */
67
+ export type ShardKind = "p" | "i";
68
+ export declare function shardKey(kind: ShardKind, ownerId: string): string;
69
+ /** The socket of a shard whose key is already known. No hashing: the key IS the name. */
70
+ export declare function shardSocketPathForKey(root: string, kind: ShardKind, key: string): string;
71
+ export declare function shardSocketPath(root: string, kind: ShardKind, ownerId: string): string;
72
+ /** Which shard a socket names, from its basename alone; `null` for any other endpoint. */
73
+ export declare function parseShardSocket(socket: string): {
74
+ readonly kind: ShardKind;
75
+ readonly key: string;
76
+ } | null;
40
77
  /**
41
78
  * The daemon directory of ONE endpoint. Both fields are named rather than positional on purpose:
42
79
  * two strings in a row is exactly the call a refactor silently swaps, and swapping these two would
@@ -52,8 +89,8 @@ export declare function createHostDaemonPaths(target: {
52
89
  * The names live here alone, so the directory a client recomputes and the one a host is handed
53
90
  * can never drift apart.
54
91
  */
55
- export declare function hostDaemonDirectoryPaths(dir: string): Omit<HostDaemonPaths, "flatDir" | "layoutMarker" | "legacyPidFile">;
56
- export declare function generationPaths(paths: HostDaemonPaths, instanceId: string): HostGenerationPaths;
92
+ export declare function hostDaemonDirectoryPaths(dir: string): HostDaemonDirectory;
93
+ export declare function generationPaths(paths: HostDaemonDirectory, instanceId: string): HostGenerationPaths;
57
94
  /** A daemon directory that cannot be created or written, named so the caller can say WHICH path failed. */
58
95
  export declare class HostDaemonStateError extends Error {
59
96
  readonly path: string;
@@ -65,6 +102,22 @@ export declare class HostDaemonStateError extends Error {
65
102
  * created with - and this one holds the evidence that decides who may signal the daemon.
66
103
  */
67
104
  export declare function createDaemonDirectories(paths: HostDaemonPaths): Promise<void>;
105
+ /**
106
+ * Writes `endpoint.json` when it is absent and never rewrites a valid one: the first writer's
107
+ * `created_at` is the endpoint's birth. The file is written whole to a temporary name and LINKED
108
+ * into place, so a reader never sees it half-written and a second writer racing the first loses on
109
+ * the link rather than replacing it. `repair` - asserted only by an ensure under this socket's ensure
110
+ * lock, where `gc` cannot be deciding about the directory - also replaces a file that does not name a
111
+ * socket of this directory (torn by a crash of an older build, or foreign), which would otherwise
112
+ * leave the endpoint unaddressable, and never `gc`-able, for good.
113
+ *
114
+ * A filesystem without hard links (exFAT/FAT, some network and FUSE mounts: `link()` fails with
115
+ * ENOTSUP, EPERM, ENOSYS...) gets the exclusive create of the final file instead. That write is not
116
+ * atomic, but the first writer still wins, and a file torn by a crash is exactly what `repair` rewrites.
117
+ */
118
+ export declare function ensureEndpointIdentity(paths: HostDaemonPaths, socket: string, options?: {
119
+ readonly repair?: boolean;
120
+ }): Promise<void>;
68
121
  /** Creates one generation's private directory. Same failure shape as the daemon directory itself. */
69
122
  export declare function createGenerationDirectory(generation: HostGenerationPaths): Promise<void>;
70
123
  //# sourceMappingURL=host-daemon-paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-daemon-paths.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-daemon-paths.ts"],"names":[],"mappings":"AAgCA,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,mGAAmG;AACnG,eAAO,MAAM,mBAAmB,8BAA8B,CAAC;AAG/D,eAAO,MAAM,oBAAoB,MAAQ,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC/B,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAGxG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,eAAe,CAQlB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,GACT,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,cAAc,GAAG,eAAe,CAAC,CAUrE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,CAS/F;AAED,2GAA2G;AAC3G,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAMvC;CACD;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBnF;AAED,qGAAqG;AACrG,wBAAsB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9F"}
1
+ {"version":3,"file":"host-daemon-paths.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-daemon-paths.ts"],"names":[],"mappings":"AAwCA,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,mGAAmG;AACnG,eAAO,MAAM,mBAAmB,8BAA8B,CAAC;AAG/D,eAAO,MAAM,oBAAoB,MAAQ,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC/B,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,yFAAyF;IACzF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACjC;AAED,yGAAyG;AACzG,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,CAAC,CAAC;AAEjH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAI1G;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAExG;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1E;AAMD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,GAAG,CAAC;AAElC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtF;AAID,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK1G;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,eAAe,CASlB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAWzE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,CASnG;AAED,2GAA2G;AAC3G,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAMvC;CACD;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC3C,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,OAAO,CAAC,IAAI,CAAC,CAkBf;AAgCD,qGAAqG;AACrG,wBAAsB,yBAAyB,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9F"}