very-happy-cli 0.2.159 → 0.2.161

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 (259) hide show
  1. package/dist/{AcpBackend-VsfkZiVF.mjs → AcpBackend-6U6pQgx1.mjs} +4 -2
  2. package/dist/{AcpBackend-DUYFlyfN.cjs → AcpBackend-Ba98QDif.cjs} +78 -76
  3. package/dist/{AcpSessionManager-Bdv8LWXh.cjs → AcpSessionManager-BAY1Pggx.cjs} +9 -9
  4. package/dist/{AcpSessionManager-rYtVb0kN.mjs → AcpSessionManager-CoMWFVw3.mjs} +1 -1
  5. package/dist/BasePermissionHandler-2R0uH2CI.cjs +157 -0
  6. package/dist/BasePermissionHandler-BvvhBTja.mjs +155 -0
  7. package/dist/BaseReasoningProcessor-DyhO1uoU.mjs +198 -0
  8. package/dist/BaseReasoningProcessor-fsVNmCEF.cjs +200 -0
  9. package/dist/RemoteModeDisplay-D-HewyXg.mjs +150 -0
  10. package/dist/RemoteModeDisplay-NC1gPHtj.cjs +153 -0
  11. package/dist/agentAttachments-Dbw8iMCZ.cjs +20 -0
  12. package/dist/agentAttachments-M_B5qEF2.mjs +18 -0
  13. package/dist/agentGuidance-B5NATuFa.cjs +28 -0
  14. package/dist/agentGuidance-CQuNlNx8.mjs +20 -0
  15. package/dist/{agentHome-CvsJyeQB.mjs → agentHome-Ck1i1TQB.mjs} +8 -22
  16. package/dist/{agentHome-CHh4lmjM.cjs → agentHome-DvNnGphb.cjs} +14 -28
  17. package/dist/api-B2vLMS-z.cjs +3346 -0
  18. package/dist/api-SffjRQ1b.mjs +3339 -0
  19. package/dist/{types-Dh-s4Lqs.mjs → apiMachine-BpW9t8MO.mjs} +9116 -16205
  20. package/dist/{types-BbvK1Tr_.cjs → apiMachine-gFA54X7y.cjs} +9104 -16247
  21. package/dist/assistantTools-BfA0R3_m.cjs +380 -0
  22. package/dist/assistantTools-CgiTbnWb.mjs +376 -0
  23. package/dist/attachmentContent-CSGxr71v.mjs +82 -0
  24. package/dist/attachmentContent-DMMZzevR.cjs +88 -0
  25. package/dist/attachmentLimits-CzVrqgLR.cjs +354 -0
  26. package/dist/attachmentLimits-yba1uHFO.mjs +348 -0
  27. package/dist/auth-Bt4ceBBy.cjs +227 -0
  28. package/dist/auth-CYHjQ8oQ.mjs +225 -0
  29. package/dist/auth-DdyVZSo6.mjs +218 -0
  30. package/dist/auth-x4CEoysH.cjs +220 -0
  31. package/dist/authRelay-BdYkC1Po.cjs +156 -0
  32. package/dist/authRelay-DSAvg1uv.mjs +143 -0
  33. package/dist/{auto-DKmEls8Z.cjs → auto-BDXDUnjB.cjs} +70 -79
  34. package/dist/{auto-nb8GhRRy.mjs → auto-CXLlRi3a.mjs} +27 -36
  35. package/dist/backgroundTaskActivity-8PdPxrvy.mjs +149 -0
  36. package/dist/backgroundTaskActivity-CBvUdj39.cjs +157 -0
  37. package/dist/bootstrap-BNQq05jR.mjs +112 -0
  38. package/dist/bootstrap-CkgIq8N3.cjs +116 -0
  39. package/dist/browser-9pyhQr1R.mjs +20 -0
  40. package/dist/browser-BDOlKWYe.cjs +22 -0
  41. package/dist/claudeCliPath-BqkaH2oR.mjs +8 -0
  42. package/dist/claudeCliPath-U4HHmV4r.cjs +10 -0
  43. package/dist/claudeLocal-BDuGFnjJ.cjs +343 -0
  44. package/dist/claudeLocal-CQa8qnwq.mjs +339 -0
  45. package/dist/claudeLocalLauncher-Bd5I2-j6.cjs +154 -0
  46. package/dist/claudeLocalLauncher-CDqQI9ak.mjs +152 -0
  47. package/dist/cliUpdate-DsKXPFYp.cjs +120 -0
  48. package/dist/cliUpdate-Y34VGe9Y.mjs +112 -0
  49. package/dist/client-Brn-UwVk.mjs +100 -0
  50. package/dist/client-CXb1VJui.mjs +112 -0
  51. package/dist/client-C_axwRry.cjs +104 -0
  52. package/dist/client-DOBWJL3u.cjs +119 -0
  53. package/dist/codex/happyMcpStdioBridge.cjs +33 -14
  54. package/dist/codex/happyMcpStdioBridge.mjs +26 -7
  55. package/dist/codexAppServerClient-ZzhUTWPo.cjs +1090 -0
  56. package/dist/codexAppServerClient-oeQKD6Qf.mjs +1088 -0
  57. package/dist/codexCommand-C7H0NpBe.cjs +2088 -0
  58. package/dist/codexCommand-CJ82bl3l.mjs +2086 -0
  59. package/dist/codexThreadFork-BCaEMBiM.mjs +338 -0
  60. package/dist/codexThreadFork-BZqF-9bX.cjs +350 -0
  61. package/dist/{config-ClLtM6F3.mjs → config-BglnktIo.mjs} +7 -40
  62. package/dist/{config-DLx-vW3I.cjs → config-CYpL1Ahd.cjs} +26 -59
  63. package/dist/configuration-DoWFJUPm.mjs +170 -0
  64. package/dist/configuration-v9f8LM9T.cjs +181 -0
  65. package/dist/connect-hgcNjyAB.mjs +682 -0
  66. package/dist/connect-yEvjdRvx.cjs +684 -0
  67. package/dist/constants-BC4St0xd.mjs +11 -0
  68. package/dist/constants-VJ0N6WuG.cjs +17 -0
  69. package/dist/contentLogMetadata-BlWI0egu.mjs +51 -0
  70. package/dist/contentLogMetadata-ZSFk_NjQ.cjs +54 -0
  71. package/dist/context-B45vMtSZ.cjs +69 -0
  72. package/dist/context-C9GHPLEm.mjs +65 -0
  73. package/dist/controlClient-DjoKTtgK.mjs +260 -0
  74. package/dist/controlClient-fEHE85bH.cjs +279 -0
  75. package/dist/createSessionMetadata-BRLB9CNO.cjs +58 -0
  76. package/dist/createSessionMetadata-mIeehclp.mjs +54 -0
  77. package/dist/defaultPermissionMode-BnxJPVHT.mjs +4 -0
  78. package/dist/defaultPermissionMode-CxmTXUQR.cjs +7 -0
  79. package/dist/detectCLI-CSGMlV51.mjs +58 -0
  80. package/dist/detectCLI-DR9ZaN6B.cjs +61 -0
  81. package/dist/deterministicJson-DKDP_mM-.cjs +507 -0
  82. package/dist/deterministicJson-p835AdAU.mjs +502 -0
  83. package/dist/doctor-BPkYWSuq.mjs +75 -0
  84. package/dist/doctor-BeUuQXFs.mjs +391 -0
  85. package/dist/doctor-hVNnSZJn.cjs +395 -0
  86. package/dist/doctor-u46qYYKX.cjs +79 -0
  87. package/dist/doctorReadiness-BCZGcN0a.cjs +151 -0
  88. package/dist/doctorReadiness-C208SMN9.mjs +142 -0
  89. package/dist/editPaths-BVfS_FFL.mjs +68 -0
  90. package/dist/editPaths-Bqp4OFPw.cjs +73 -0
  91. package/dist/ensureDaemonRunning-CO7d1gOC.mjs +61 -0
  92. package/dist/ensureDaemonRunning-Dg9aZfjs.cjs +64 -0
  93. package/dist/handleResumeCommand-BiTPK0qd.mjs +240 -0
  94. package/dist/handleResumeCommand-DnVmy7a3.cjs +245 -0
  95. package/dist/ids-B6ZC0HGt.cjs +13 -0
  96. package/dist/ids-DU6sLx4C.mjs +10 -0
  97. package/dist/index-B6UGRQ7h.mjs +102 -0
  98. package/dist/{index-2mCaeKyf.mjs → index-CAFwetLk.mjs} +68 -38
  99. package/dist/index-Cqx-Raq6.mjs +68 -0
  100. package/dist/index-D3kI0hDR.cjs +107 -0
  101. package/dist/index-DA7yINuk.cjs +994 -0
  102. package/dist/{index-BEOMECtE.cjs → index-LIn6nCcq.cjs} +121 -91
  103. package/dist/index-Pf2cV9cn.cjs +182 -0
  104. package/dist/index-SPGPenK5.mjs +158 -0
  105. package/dist/index-gNTWtSKN.cjs +71 -0
  106. package/dist/index-qdS1friN.mjs +949 -0
  107. package/dist/index.cjs +5 -46
  108. package/dist/index.mjs +5 -46
  109. package/dist/{install-BPhJppvd.mjs → install-BO_W7VhL.mjs} +37 -37
  110. package/dist/install-Bu85vlHD.cjs +88 -0
  111. package/dist/install-ClUUl3yp.mjs +86 -0
  112. package/dist/{install-BOHrUaFM.cjs → install-Cs5qAPrB.cjs} +38 -38
  113. package/dist/{installPiTools-DuZ6jZvX.cjs → installPiTools-BKnXjrVu.cjs} +2 -3
  114. package/dist/{installPiTools-Cj7yU9Fc.mjs → installPiTools-B_CdM5_2.mjs} +1 -2
  115. package/dist/{installTerminalHooks-Cou3WUf3.cjs → installTerminalHooks-BQZbvxsZ.cjs} +5 -40
  116. package/dist/{installTerminalHooks-WeznjkuC.mjs → installTerminalHooks-By7gBMEF.mjs} +3 -38
  117. package/dist/lib.cjs +28 -19
  118. package/dist/lib.d.cts +12 -2
  119. package/dist/lib.d.mts +12 -2
  120. package/dist/lib.mjs +23 -14
  121. package/dist/lidState-C2dI0FAN.mjs +297 -0
  122. package/dist/lidState-KHHu1015.cjs +305 -0
  123. package/dist/limits-C-a7gr04.cjs +43 -0
  124. package/dist/limits-DIo7rEBR.mjs +36 -0
  125. package/dist/localHappyAgentAuth-BXiHPXdC.cjs +86 -0
  126. package/dist/localHappyAgentAuth-DCsetiyG.mjs +82 -0
  127. package/dist/logger-Bc8-u1w0.cjs +275 -0
  128. package/dist/logger-fXoNzNuB.mjs +271 -0
  129. package/dist/loginShellEnv-BkuYtExZ.cjs +182 -0
  130. package/dist/loginShellEnv-Dw8M7tkI.mjs +167 -0
  131. package/dist/machineMetadata-BHjehxJY.mjs +38 -0
  132. package/dist/machineMetadata-BibDMFVx.cjs +41 -0
  133. package/dist/main-BktM4A1K.mjs +939 -0
  134. package/dist/main-CLaX-t-b.cjs +941 -0
  135. package/dist/manager-BQ4flvQZ.mjs +101 -0
  136. package/dist/manager-Cly8xVIR.cjs +105 -0
  137. package/dist/{mcp-Dy3f_K0h.mjs → mcp-CeUd9KDr.mjs} +27 -33
  138. package/dist/{mcp-CPYbtsYG.cjs → mcp-GBfE70nk.cjs} +42 -48
  139. package/dist/messageBuffer-BWlGgR3A.mjs +71 -0
  140. package/dist/messageBuffer-fJMH6uY8.cjs +73 -0
  141. package/dist/mirrorProtocol-BNLtoWjO.mjs +170 -0
  142. package/dist/mirrorProtocol-BUtmg1ws.cjs +186 -0
  143. package/dist/oneShotPrompts-CL0dip9C.cjs +16 -0
  144. package/dist/oneShotPrompts-DT4p6RNd.mjs +12 -0
  145. package/dist/package-Cl5BEP5x.cjs +173 -0
  146. package/dist/package-uOg9SCKi.mjs +171 -0
  147. package/dist/path-B7zW-WwE.cjs +18 -0
  148. package/dist/path-D2wdaNSk.mjs +15 -0
  149. package/dist/peerTools-CIeiy9wn.cjs +283 -0
  150. package/dist/peerTools-Dz3_7Bkk.mjs +272 -0
  151. package/dist/permissionMode-CH4FoZfU.mjs +80 -0
  152. package/dist/permissionMode-CrV-XuMs.cjs +87 -0
  153. package/dist/persistence-CBNMzSa8.cjs +414 -0
  154. package/dist/persistence-oET5n61f.mjs +372 -0
  155. package/dist/piExtension.mjs +2 -1
  156. package/dist/piRunnerArgs-Bf7RUF__.cjs +66 -0
  157. package/dist/piRunnerArgs-Dk1ncwHF.mjs +59 -0
  158. package/dist/{piRuntime-NtF0YqjH.cjs → piRuntime-B_6TE9Eb.cjs} +4 -4
  159. package/dist/{piRuntime-kLZNpAAl.mjs → piRuntime-BwRdhK_N.mjs} +2 -2
  160. package/dist/{piTerminal-B0fEOV_2.mjs → piTerminal-Bap3R8Re.mjs} +32 -35
  161. package/dist/{piTerminal-9J0GAKzb.cjs → piTerminal-CagmEoez.cjs} +32 -35
  162. package/dist/previewPath-B0rBdhy1.cjs +83 -0
  163. package/dist/previewPath-CXN4Vag0.mjs +81 -0
  164. package/dist/projectPath-BTBIMB57.mjs +10 -0
  165. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  166. package/dist/registerCommonHandlers-BjSV2Skz.cjs +538 -0
  167. package/dist/registerCommonHandlers-CrgvJsOy.mjs +536 -0
  168. package/dist/registerKillSessionHandler-6TC2S3lf.cjs +366 -0
  169. package/dist/registerKillSessionHandler-Cbc8Rgtd.mjs +363 -0
  170. package/dist/remoteSessionClient-BNx78NLb.cjs +634 -0
  171. package/dist/remoteSessionClient-CO7qOjR0.mjs +612 -0
  172. package/dist/resources-BdFBQi8r.mjs +117 -0
  173. package/dist/resources-JDPugcDq.cjs +120 -0
  174. package/dist/run-2l5vSt2h.mjs +5743 -0
  175. package/dist/run-D5xAEWSB.cjs +5766 -0
  176. package/dist/runClaude-BX6ixjtW.cjs +894 -0
  177. package/dist/runClaude-BgN6xo05.mjs +892 -0
  178. package/dist/runClaudeDeps-Bp20MScE.cjs +4168 -0
  179. package/dist/runClaudeDeps-COBBhD9o.mjs +4129 -0
  180. package/dist/{runGemini-F-mqx3_K.cjs → runGemini-CSMPkt0p.cjs} +202 -175
  181. package/dist/{runGemini-DV6Ouadt.mjs → runGemini-Cc2jq-uh.mjs} +58 -31
  182. package/dist/{runOpenClaw-D7MlPS5n.mjs → runOpenClaw-CIlCwdW2.mjs} +31 -32
  183. package/dist/{runOpenClaw-Qqo9j63M.cjs → runOpenClaw-YBwua4Rf.cjs} +64 -65
  184. package/dist/sandbox-C4gXLP1p.cjs +187 -0
  185. package/dist/sandbox-CNkwOtHI.mjs +180 -0
  186. package/dist/selfCheck-CU8xSDsl.cjs +87 -0
  187. package/dist/selfCheck-hJ6PCh7v.mjs +84 -0
  188. package/dist/{send-CLhYXNgy.mjs → send-CGHcKZ-w.mjs} +12 -5
  189. package/dist/{send-4qJTCAYW.cjs → send-DY9Nr-x4.cjs} +16 -9
  190. package/dist/server-II51Mimf.cjs +407 -0
  191. package/dist/server-m2b5pamZ.mjs +404 -0
  192. package/dist/sessionLock-7ePAYDOg.cjs +205 -0
  193. package/dist/sessionLock-Cw6FmbMv.mjs +197 -0
  194. package/dist/sessionModeFile-BVCV5f7E.cjs +36 -0
  195. package/dist/sessionModeFile-CDmDyRkD.mjs +32 -0
  196. package/dist/sessionOps-C_f1wKOr.mjs +760 -0
  197. package/dist/sessionOps-DJdExmBy.cjs +783 -0
  198. package/dist/sessionScanner-CaAHLyNV.mjs +206 -0
  199. package/dist/sessionScanner-D1goKdd3.cjs +209 -0
  200. package/dist/{sessions-Bh1pyddi.cjs → sessions-DGs6ALNo.cjs} +37 -28
  201. package/dist/{sessions-CzIH2rGp.mjs → sessions-DnvmWUel.mjs} +17 -8
  202. package/dist/setupOfflineReconnection-CVViqZft.mjs +72 -0
  203. package/dist/setupOfflineReconnection-R7XuR_sj.cjs +74 -0
  204. package/dist/smallFastModel-BLNgMrwR.mjs +18 -0
  205. package/dist/smallFastModel-D_uxGMo3.cjs +21 -0
  206. package/dist/{spawn-CmFOSVdW.cjs → spawn-CXTH7qg1.cjs} +61 -65
  207. package/dist/{spawn-CPIWlPOM.mjs → spawn-DNYSvFtC.mjs} +35 -40
  208. package/dist/spawnAgents-BGQiEF-w.cjs +52 -0
  209. package/dist/spawnAgents-DZzZ9jMI.mjs +45 -0
  210. package/dist/spawnHappyCLI-BhYj84rv.cjs +66 -0
  211. package/dist/spawnHappyCLI-cqWQbwsb.mjs +64 -0
  212. package/dist/specialCommands-BSqhYg5X.mjs +52 -0
  213. package/dist/specialCommands-DSsTeRej.cjs +54 -0
  214. package/dist/startFileWatcher-CKKx-8ZO.cjs +71 -0
  215. package/dist/startFileWatcher-CdegMbJj.mjs +69 -0
  216. package/dist/startupPlan-BLMbfQIH.cjs +12 -0
  217. package/dist/startupPlan-DFMyNgAs.mjs +10 -0
  218. package/dist/streamRelay-BiKw59Cc.cjs +233 -0
  219. package/dist/streamRelay-FPVbHpbM.mjs +231 -0
  220. package/dist/sync-CVk4QERO.cjs +71 -0
  221. package/dist/sync-CxD-w_40.mjs +69 -0
  222. package/dist/systemPrompt-BygJcmbi.cjs +97 -0
  223. package/dist/systemPrompt-DmtypUc7.mjs +94 -0
  224. package/dist/{teams-CEahj4cm.mjs → teams-BOC6nIPL.mjs} +9 -40
  225. package/dist/{teams-CB1R9-Z9.cjs → teams-BsvpOBfn.cjs} +14 -45
  226. package/dist/template-BaHAmH2K.cjs +129 -0
  227. package/dist/template-CiOPa2rd.mjs +121 -0
  228. package/dist/{terminalTitleSuggest-DKgX3osW.mjs → terminalTitleSuggest-CeKsX_V6.mjs} +1 -9
  229. package/dist/{terminalTitleSuggest-Dji8I0Jy.cjs → terminalTitleSuggest-DhvRFX3H.cjs} +0 -10
  230. package/dist/terminals-B_bfC9c2.cjs +250 -0
  231. package/dist/terminals-Dlg0x3nY.mjs +235 -0
  232. package/dist/time-BZNdNiIV.mjs +38 -0
  233. package/dist/time-CNRE4ChD.cjs +42 -0
  234. package/dist/titleGenerator-CFRhU-xq.cjs +172 -0
  235. package/dist/titleGenerator-ox6ptCsp.mjs +166 -0
  236. package/dist/tmuxSocket-B8Yx20sT.mjs +19 -0
  237. package/dist/tmuxSocket-D-Xt6Vn-.cjs +24 -0
  238. package/dist/{todo-DqyRI4wP.cjs → todo-B-KB7oAB.cjs} +15 -12
  239. package/dist/{todo-Cknp5D4U.mjs → todo-C5KBVbUw.mjs} +11 -8
  240. package/dist/tools-BZabNIid.mjs +177 -0
  241. package/dist/tools-BmQQUATY.mjs +60 -0
  242. package/dist/tools-CsSovyNp.cjs +180 -0
  243. package/dist/tools-lMDra4Pv.cjs +63 -0
  244. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  245. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  246. package/dist/types-CRS-srZK.cjs +66 -0
  247. package/dist/types-CkqAACXx.mjs +64 -0
  248. package/dist/uninstall-B1WLtC1d.mjs +47 -0
  249. package/dist/uninstall-fvA5aWpU.cjs +49 -0
  250. package/package.json +7 -7
  251. package/scripts/session_hook_forwarder.cjs +9 -2
  252. package/dist/agentGuidance-BRDN1NoZ.cjs +0 -2217
  253. package/dist/agentGuidance-KgvYuF3R.mjs +0 -2145
  254. package/dist/index-BF6WfgV5.mjs +0 -19624
  255. package/dist/index-C-JazrMB.mjs +0 -52
  256. package/dist/index-blDSadUR.cjs +0 -58
  257. package/dist/index-rH3DrQ5B.cjs +0 -19688
  258. package/dist/limits-BH5CV5vR.cjs +0 -2683
  259. package/dist/limits-CjRj8IX5.mjs +0 -2558
@@ -0,0 +1,354 @@
1
+ 'use strict';
2
+
3
+ var z = require('zod');
4
+ var index = require('./index-DA7yINuk.cjs');
5
+
6
+ z.z.object({
7
+ teamsVersion: z.z.number().int().positive().optional(),
8
+ teamLaunchVersion: z.z.number().int().positive().optional(),
9
+ host: z.z.string(),
10
+ platform: z.z.string(),
11
+ happyCliVersion: z.z.string(),
12
+ homeDir: z.z.string(),
13
+ happyHomeDir: z.z.string(),
14
+ happyLibDir: z.z.string(),
15
+ cliAvailability: z.z.object({
16
+ claude: z.z.boolean(),
17
+ codex: z.z.boolean(),
18
+ gemini: z.z.boolean(),
19
+ openclaw: z.z.boolean(),
20
+ pi: z.z.boolean().optional(),
21
+ // absent on daemons that predate the pi runner
22
+ detectedAt: z.z.number()
23
+ }).optional(),
24
+ resumeSupport: z.z.object({
25
+ rpcAvailable: z.z.boolean(),
26
+ requiresSameMachine: z.z.boolean(),
27
+ requiresHappyAgentAuth: z.z.boolean(),
28
+ happyAgentAuthenticated: z.z.boolean(),
29
+ detectedAt: z.z.number()
30
+ }).optional()
31
+ });
32
+ const ClaudeAuthStateSchema = z.z.object({
33
+ probeVersion: z.z.number(),
34
+ daemonPid: z.z.number(),
35
+ status: z.z.union([z.z.enum(["ok", "not-logged-in", "unknown", "error", "claude-missing"]), z.z.string()]),
36
+ authMethod: z.z.string().optional(),
37
+ subscriptionType: z.z.string().optional(),
38
+ diagnosis: z.z.string().optional(),
39
+ detail: z.z.string().optional(),
40
+ repairable: z.z.string().optional(),
41
+ context: z.z.object({
42
+ platform: z.z.string(),
43
+ lineage: z.z.string(),
44
+ credentialStore: z.z.string()
45
+ }),
46
+ checkedAt: z.z.number()
47
+ });
48
+ const CliUpdateStateSchema = z.z.object({
49
+ currentVersion: z.z.string(),
50
+ recommendedVersion: z.z.string().nullable(),
51
+ minimumVersion: z.z.string().nullable(),
52
+ status: z.z.enum(["current", "available", "required"]),
53
+ /** B-351/B-503: the version this machine may install by itself, as decided
54
+ * by the relay (exact pin or the promoted `latest`); null means no
55
+ * unattended install. */
56
+ autoUpdateVersion: z.z.string().nullable().optional(),
57
+ retrySupported: z.z.boolean().optional(),
58
+ manualUpdateSupported: z.z.boolean().optional(),
59
+ checkedAt: z.z.number(),
60
+ /**
61
+ * B-321: a new bundle is on disk but refused to run, so the daemon is still
62
+ * serving the old code. Present only while that is true. Optional and additive:
63
+ * old web builds ignore it, old daemons never send it (iron rule 4).
64
+ */
65
+ handoverHold: z.z.object({ reason: z.z.string(), at: z.z.number() }).nullable().optional(),
66
+ /** B-327: the last thing the machine's auto-update did, or why it did nothing. */
67
+ autoUpdate: z.z.object({
68
+ source: z.z.string().optional(),
69
+ state: z.z.union([z.z.enum(["installing", "installed", "failed", "skipped"]), z.z.string()]),
70
+ version: z.z.string().nullable(),
71
+ detail: z.z.string().optional(),
72
+ at: z.z.number()
73
+ }).nullable().optional()
74
+ });
75
+ const WebTerminalListItemSchema = z.z.object({
76
+ id: z.z.string(),
77
+ title: z.z.string().optional(),
78
+ /** New daemons always send an array (including []); absence identifies an
79
+ * old daemon that cannot persist terminal tags. */
80
+ tags: z.z.array(z.z.string()).optional(),
81
+ cwd: z.z.string().optional(),
82
+ createdAt: z.z.number().optional(),
83
+ activityAt: z.z.number().optional(),
84
+ agentState: z.z.enum(["working", "needs_input", "idle", "shell"]).optional(),
85
+ agentKind: z.z.string().optional(),
86
+ agentObservedAt: z.z.number().optional(),
87
+ /** B-105: mirror session of the claude running inside the terminal. */
88
+ mirrorSessionId: z.z.string().optional(),
89
+ /** B-150: auto-restored after a restart (ms epoch) — the directory and the
90
+ * conversation carried over, the processes did not. Cleared once opened. */
91
+ restoredAt: z.z.number().optional(),
92
+ /** B-265: @vh_title_manual is set (user renamed it). */
93
+ manual: z.z.boolean().optional(),
94
+ /** B-273: opened attached to the user's tmux session of this name. */
95
+ attachTmux: z.z.string().optional(),
96
+ /** B-486: direct-pty shell (no tmux) — not restorable after a daemon restart. */
97
+ direct: z.z.boolean().optional()
98
+ });
99
+ const ClosedTerminalRecordSchema = z.z.object({
100
+ id: z.z.string(),
101
+ title: z.z.string().optional(),
102
+ cwd: z.z.string().optional(),
103
+ /** B-105: shadow mirror session — structured history of the claude that ran
104
+ * inside the terminal, still reachable after the terminal is gone. */
105
+ mirrorSessionId: z.z.string().optional(),
106
+ /** B-149: claude conversation id, for one-click resume of a dead terminal. */
107
+ claudeSessionId: z.z.string().optional(),
108
+ /** B-149: 'daemon-gap' = died while no daemon was watching (restart/reboot);
109
+ * absent means an ordinary observed close. */
110
+ reason: z.z.enum(["closed", "daemon-gap"]).optional(),
111
+ /** B-265: tags + manual-rename flag at close time (restored verbatim). */
112
+ tags: z.z.array(z.z.string()).optional(),
113
+ manual: z.z.boolean().optional(),
114
+ /** B-273: attached user tmux session name — restore re-attaches. */
115
+ attachTmux: z.z.string().optional(),
116
+ closedAt: z.z.number()
117
+ });
118
+ z.z.object({
119
+ agentVersions: index.AgentVersionsSchema.optional(),
120
+ agentVersionEpoch: z.z.number().optional(),
121
+ status: z.z.union([
122
+ z.z.enum(["running", "shutting-down"]),
123
+ z.z.string()
124
+ // Forward compatibility
125
+ ]),
126
+ pid: z.z.number().optional(),
127
+ httpPort: z.z.number().optional(),
128
+ startedAt: z.z.number().optional(),
129
+ shutdownRequestedAt: z.z.number().optional(),
130
+ shutdownSource: z.z.union([
131
+ z.z.enum(["mobile-app", "cli", "os-signal", "unknown"]),
132
+ z.z.string()
133
+ // Forward compatibility
134
+ ]).optional(),
135
+ /**
136
+ * Push channel for this machine's web-terminal list (see
137
+ * terminal/webTerminal.ts list tracking). The daemon rewrites this field
138
+ * whenever the tracked list signature changes; the server persists it with
139
+ * the rest of daemonState and broadcasts `update-machine`, so every web
140
+ * client gets the terminal list/titles/agent states pushed instead of
141
+ * polling `list-terminals` — and an OFFLINE machine's last list stays
142
+ * readable from the server's persisted copy.
143
+ *
144
+ * Trust rule for consumers: the snapshot is only authoritative when
145
+ * `updatedAt >= startedAt` — i.e. it was written by the CURRENT daemon run.
146
+ * A downgraded daemon spreads the stale field forward (`{...state}`) but
147
+ * bumps `startedAt` on connect without restamping `updatedAt`, which is
148
+ * exactly what makes clients fall back to polling. Old clients ignore the
149
+ * field entirely.
150
+ */
151
+ webTerminals: z.z.object({
152
+ updatedAt: z.z.number(),
153
+ terminals: z.z.array(WebTerminalListItemSchema)
154
+ }).optional(),
155
+ /**
156
+ * Recently closed terminals (B-084), newest first, capped at 20 — written
157
+ * alongside webTerminals in the same daemonState pushes (every close also
158
+ * changes the live list, so the two always travel together). Old clients
159
+ * ignore the field; old daemons never write it (web renders nothing).
160
+ */
161
+ closedTerminals: z.z.array(ClosedTerminalRecordSchema).optional(),
162
+ /**
163
+ * B-265 capability flag: this daemon answers `restore-terminal`. Same trust
164
+ * rule as webTerminals — only `detectedAt >= startedAt` counts, because a
165
+ * downgraded daemon spreads the stale field forward on connect.
166
+ */
167
+ terminalRestore: z.z.object({
168
+ rpcAvailable: z.z.boolean(),
169
+ detectedAt: z.z.number()
170
+ }).optional(),
171
+ /**
172
+ * B-273 capability flag: this daemon answers `list-tmux-sessions` and
173
+ * honours `open-terminal.attachTmux`. Same trust rule (`detectedAt >=
174
+ * startedAt`). Stamped unconditionally — on a machine without tmux the
175
+ * RPC just answers an empty list.
176
+ */
177
+ tmuxSessions: z.z.object({
178
+ rpcAvailable: z.z.boolean(),
179
+ detectedAt: z.z.number(),
180
+ /** B-282: `kill-terminal` honours `alsoAttached`. */
181
+ killAttached: z.z.boolean().optional()
182
+ }).optional(),
183
+ /**
184
+ * B-290 capability flag: this daemon answers `claude-list-history` (import a
185
+ * Claude Code conversation that was never started through very-happy).
186
+ * Same trust rule (`detectedAt >= startedAt`).
187
+ */
188
+ claudeHistory: z.z.object({
189
+ rpcAvailable: z.z.boolean(),
190
+ detectedAt: z.z.number()
191
+ }).optional(),
192
+ /**
193
+ * B-464 capability flag: this daemon answers `codex-list-history` /
194
+ * `codex-import-session` (import a Codex CLI / desktop thread that was never
195
+ * started through very-happy). Same trust rule (`detectedAt >= startedAt`).
196
+ */
197
+ codexHistory: z.z.object({
198
+ rpcAvailable: z.z.boolean(),
199
+ detectedAt: z.z.number()
200
+ }).optional(),
201
+ /**
202
+ * B-486: can web terminals on this machine be durable? `tmuxAvailable:
203
+ * false` ⇒ every new terminal is a direct shell that dies with the daemon,
204
+ * so the web tells the user to install tmux. Same trust rule
205
+ * (`detectedAt >= startedAt`); old webs ignore it.
206
+ */
207
+ terminalHost: z.z.object({
208
+ tmuxAvailable: z.z.boolean(),
209
+ tmuxVersion: z.z.string().optional(),
210
+ detectedAt: z.z.number()
211
+ }).optional(),
212
+ /** Relay-owned CLI compatibility/update policy last checked by this daemon. */
213
+ cliUpdate: CliUpdateStateSchema.optional(),
214
+ /**
215
+ * B-276: result of the daemon-context Claude auth preflight (spec
216
+ * 2026-09-claude-auth-preflight). Trust rule for consumers:
217
+ * `claudeAuth.daemonPid === daemonState.pid` — daemonState survives daemon
218
+ * restarts (the server returns the existing row and connect spreads it
219
+ * forward), so a downgraded daemon carries this field along unchanged.
220
+ */
221
+ claudeAuth: ClaudeAuthStateSchema.optional()
222
+ });
223
+ const MessageMetaSchema = z.z.object({
224
+ sentFrom: z.z.string().optional(),
225
+ // Source identifier
226
+ permissionMode: z.z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "read-only", "safe-yolo", "yolo"]).optional(),
227
+ // Permission mode for this message
228
+ model: z.z.string().nullable().optional(),
229
+ // Model name for this message (null = reset)
230
+ fallbackModel: z.z.string().nullable().optional(),
231
+ // Fallback model for this message (null = reset)
232
+ customSystemPrompt: z.z.string().nullable().optional(),
233
+ // Custom system prompt for this message (null = reset)
234
+ appendSystemPrompt: z.z.string().nullable().optional(),
235
+ // Append to system prompt for this message (null = reset)
236
+ allowedTools: z.z.array(z.z.string()).nullable().optional(),
237
+ // Allowed tools for this message (null = reset)
238
+ disallowedTools: z.z.array(z.z.string()).nullable().optional(),
239
+ // Disallowed tools for this message (null = reset)
240
+ /**
241
+ * Thinking depth for this message (null = reset to the machine default).
242
+ * Deliberately a plain string, not an enum: an unknown value must not make
243
+ * zod reject the WHOLE message the way the `dontAsk` permission enum did
244
+ * (AGENTS 铁律 14). runClaude validates it against its own allow-list and
245
+ * ignores anything else. Absent here until 0.2.105, which is why every
246
+ * released CLI silently dropped the web's effort selection.
247
+ */
248
+ effort: z.z.string().nullable().optional(),
249
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
250
+ delivery: z.z.enum(["queue", "steer"]).optional()
251
+ });
252
+ z.z.object({
253
+ session: z.z.object({
254
+ id: z.z.string(),
255
+ tag: z.z.string(),
256
+ seq: z.z.number(),
257
+ createdAt: z.z.number(),
258
+ updatedAt: z.z.number(),
259
+ metadata: z.z.string(),
260
+ metadataVersion: z.z.number(),
261
+ agentState: z.z.string().nullable(),
262
+ agentStateVersion: z.z.number()
263
+ })
264
+ });
265
+ const UserMessageSchema = z.z.object({
266
+ role: z.z.literal("user"),
267
+ content: z.z.object({
268
+ type: z.z.literal("text"),
269
+ text: z.z.string()
270
+ }),
271
+ localKey: z.z.string().optional(),
272
+ // Mobile messages include this
273
+ meta: MessageMetaSchema.optional()
274
+ });
275
+ const FileEventMessageSchema = z.z.object({
276
+ role: z.z.literal("session"),
277
+ content: z.z.object({
278
+ type: z.z.literal("session"),
279
+ data: z.z.object({
280
+ id: z.z.string(),
281
+ time: z.z.number(),
282
+ role: z.z.literal("user"),
283
+ ev: z.z.object({
284
+ t: z.z.literal("file"),
285
+ ref: z.z.string(),
286
+ name: z.z.string(),
287
+ size: z.z.number(),
288
+ mimeType: z.z.string().optional(),
289
+ image: z.z.object({
290
+ width: z.z.number(),
291
+ height: z.z.number(),
292
+ // Optional — native iOS picker has no Canvas to compute thumbhash.
293
+ // App-side schema relaxed this in the same commit; keeping CLI in
294
+ // sync so the file event isn't silently rejected by Zod and the
295
+ // attachment never reaches Claude.
296
+ thumbhash: z.z.string().optional()
297
+ }).optional()
298
+ })
299
+ })
300
+ })
301
+ });
302
+ const AgentMessageSchema = z.z.object({
303
+ role: z.z.literal("agent"),
304
+ content: z.z.object({
305
+ type: z.z.literal("output"),
306
+ data: z.z.any()
307
+ }),
308
+ meta: MessageMetaSchema.optional()
309
+ });
310
+ z.z.union([UserMessageSchema, AgentMessageSchema]);
311
+
312
+ class AsyncLock {
313
+ permits = 1;
314
+ promiseResolverQueue = [];
315
+ async inLock(func) {
316
+ try {
317
+ await this.lock();
318
+ return await func();
319
+ } finally {
320
+ this.unlock();
321
+ }
322
+ }
323
+ async lock() {
324
+ if (this.permits > 0) {
325
+ this.permits = this.permits - 1;
326
+ return;
327
+ }
328
+ await new Promise((resolve) => this.promiseResolverQueue.push(resolve));
329
+ }
330
+ unlock() {
331
+ this.permits += 1;
332
+ if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
333
+ throw new Error("this.permits should never be > 0 when there is someone waiting.");
334
+ } else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
335
+ this.permits -= 1;
336
+ const nextResolver = this.promiseResolverQueue.shift();
337
+ if (nextResolver) {
338
+ setTimeout(() => {
339
+ nextResolver(true);
340
+ }, 0);
341
+ }
342
+ }
343
+ }
344
+ }
345
+
346
+ const MAX_CHAT_ATTACHMENT_SOURCE_BYTES = 50 * 1024 * 1024;
347
+ const CHAT_ATTACHMENT_ENCRYPTION_OVERHEAD_BYTES = 40;
348
+ const MAX_CHAT_ATTACHMENT_ENCRYPTED_BYTES = MAX_CHAT_ATTACHMENT_SOURCE_BYTES + CHAT_ATTACHMENT_ENCRYPTION_OVERHEAD_BYTES;
349
+
350
+ exports.AsyncLock = AsyncLock;
351
+ exports.FileEventMessageSchema = FileEventMessageSchema;
352
+ exports.MAX_CHAT_ATTACHMENT_ENCRYPTED_BYTES = MAX_CHAT_ATTACHMENT_ENCRYPTED_BYTES;
353
+ exports.MAX_CHAT_ATTACHMENT_SOURCE_BYTES = MAX_CHAT_ATTACHMENT_SOURCE_BYTES;
354
+ exports.UserMessageSchema = UserMessageSchema;
@@ -0,0 +1,348 @@
1
+ import { z } from 'zod';
2
+ import { k as AgentVersionsSchema } from './index-qdS1friN.mjs';
3
+
4
+ z.object({
5
+ teamsVersion: z.number().int().positive().optional(),
6
+ teamLaunchVersion: z.number().int().positive().optional(),
7
+ host: z.string(),
8
+ platform: z.string(),
9
+ happyCliVersion: z.string(),
10
+ homeDir: z.string(),
11
+ happyHomeDir: z.string(),
12
+ happyLibDir: z.string(),
13
+ cliAvailability: z.object({
14
+ claude: z.boolean(),
15
+ codex: z.boolean(),
16
+ gemini: z.boolean(),
17
+ openclaw: z.boolean(),
18
+ pi: z.boolean().optional(),
19
+ // absent on daemons that predate the pi runner
20
+ detectedAt: z.number()
21
+ }).optional(),
22
+ resumeSupport: z.object({
23
+ rpcAvailable: z.boolean(),
24
+ requiresSameMachine: z.boolean(),
25
+ requiresHappyAgentAuth: z.boolean(),
26
+ happyAgentAuthenticated: z.boolean(),
27
+ detectedAt: z.number()
28
+ }).optional()
29
+ });
30
+ const ClaudeAuthStateSchema = z.object({
31
+ probeVersion: z.number(),
32
+ daemonPid: z.number(),
33
+ status: z.union([z.enum(["ok", "not-logged-in", "unknown", "error", "claude-missing"]), z.string()]),
34
+ authMethod: z.string().optional(),
35
+ subscriptionType: z.string().optional(),
36
+ diagnosis: z.string().optional(),
37
+ detail: z.string().optional(),
38
+ repairable: z.string().optional(),
39
+ context: z.object({
40
+ platform: z.string(),
41
+ lineage: z.string(),
42
+ credentialStore: z.string()
43
+ }),
44
+ checkedAt: z.number()
45
+ });
46
+ const CliUpdateStateSchema = z.object({
47
+ currentVersion: z.string(),
48
+ recommendedVersion: z.string().nullable(),
49
+ minimumVersion: z.string().nullable(),
50
+ status: z.enum(["current", "available", "required"]),
51
+ /** B-351/B-503: the version this machine may install by itself, as decided
52
+ * by the relay (exact pin or the promoted `latest`); null means no
53
+ * unattended install. */
54
+ autoUpdateVersion: z.string().nullable().optional(),
55
+ retrySupported: z.boolean().optional(),
56
+ manualUpdateSupported: z.boolean().optional(),
57
+ checkedAt: z.number(),
58
+ /**
59
+ * B-321: a new bundle is on disk but refused to run, so the daemon is still
60
+ * serving the old code. Present only while that is true. Optional and additive:
61
+ * old web builds ignore it, old daemons never send it (iron rule 4).
62
+ */
63
+ handoverHold: z.object({ reason: z.string(), at: z.number() }).nullable().optional(),
64
+ /** B-327: the last thing the machine's auto-update did, or why it did nothing. */
65
+ autoUpdate: z.object({
66
+ source: z.string().optional(),
67
+ state: z.union([z.enum(["installing", "installed", "failed", "skipped"]), z.string()]),
68
+ version: z.string().nullable(),
69
+ detail: z.string().optional(),
70
+ at: z.number()
71
+ }).nullable().optional()
72
+ });
73
+ const WebTerminalListItemSchema = z.object({
74
+ id: z.string(),
75
+ title: z.string().optional(),
76
+ /** New daemons always send an array (including []); absence identifies an
77
+ * old daemon that cannot persist terminal tags. */
78
+ tags: z.array(z.string()).optional(),
79
+ cwd: z.string().optional(),
80
+ createdAt: z.number().optional(),
81
+ activityAt: z.number().optional(),
82
+ agentState: z.enum(["working", "needs_input", "idle", "shell"]).optional(),
83
+ agentKind: z.string().optional(),
84
+ agentObservedAt: z.number().optional(),
85
+ /** B-105: mirror session of the claude running inside the terminal. */
86
+ mirrorSessionId: z.string().optional(),
87
+ /** B-150: auto-restored after a restart (ms epoch) — the directory and the
88
+ * conversation carried over, the processes did not. Cleared once opened. */
89
+ restoredAt: z.number().optional(),
90
+ /** B-265: @vh_title_manual is set (user renamed it). */
91
+ manual: z.boolean().optional(),
92
+ /** B-273: opened attached to the user's tmux session of this name. */
93
+ attachTmux: z.string().optional(),
94
+ /** B-486: direct-pty shell (no tmux) — not restorable after a daemon restart. */
95
+ direct: z.boolean().optional()
96
+ });
97
+ const ClosedTerminalRecordSchema = z.object({
98
+ id: z.string(),
99
+ title: z.string().optional(),
100
+ cwd: z.string().optional(),
101
+ /** B-105: shadow mirror session — structured history of the claude that ran
102
+ * inside the terminal, still reachable after the terminal is gone. */
103
+ mirrorSessionId: z.string().optional(),
104
+ /** B-149: claude conversation id, for one-click resume of a dead terminal. */
105
+ claudeSessionId: z.string().optional(),
106
+ /** B-149: 'daemon-gap' = died while no daemon was watching (restart/reboot);
107
+ * absent means an ordinary observed close. */
108
+ reason: z.enum(["closed", "daemon-gap"]).optional(),
109
+ /** B-265: tags + manual-rename flag at close time (restored verbatim). */
110
+ tags: z.array(z.string()).optional(),
111
+ manual: z.boolean().optional(),
112
+ /** B-273: attached user tmux session name — restore re-attaches. */
113
+ attachTmux: z.string().optional(),
114
+ closedAt: z.number()
115
+ });
116
+ z.object({
117
+ agentVersions: AgentVersionsSchema.optional(),
118
+ agentVersionEpoch: z.number().optional(),
119
+ status: z.union([
120
+ z.enum(["running", "shutting-down"]),
121
+ z.string()
122
+ // Forward compatibility
123
+ ]),
124
+ pid: z.number().optional(),
125
+ httpPort: z.number().optional(),
126
+ startedAt: z.number().optional(),
127
+ shutdownRequestedAt: z.number().optional(),
128
+ shutdownSource: z.union([
129
+ z.enum(["mobile-app", "cli", "os-signal", "unknown"]),
130
+ z.string()
131
+ // Forward compatibility
132
+ ]).optional(),
133
+ /**
134
+ * Push channel for this machine's web-terminal list (see
135
+ * terminal/webTerminal.ts list tracking). The daemon rewrites this field
136
+ * whenever the tracked list signature changes; the server persists it with
137
+ * the rest of daemonState and broadcasts `update-machine`, so every web
138
+ * client gets the terminal list/titles/agent states pushed instead of
139
+ * polling `list-terminals` — and an OFFLINE machine's last list stays
140
+ * readable from the server's persisted copy.
141
+ *
142
+ * Trust rule for consumers: the snapshot is only authoritative when
143
+ * `updatedAt >= startedAt` — i.e. it was written by the CURRENT daemon run.
144
+ * A downgraded daemon spreads the stale field forward (`{...state}`) but
145
+ * bumps `startedAt` on connect without restamping `updatedAt`, which is
146
+ * exactly what makes clients fall back to polling. Old clients ignore the
147
+ * field entirely.
148
+ */
149
+ webTerminals: z.object({
150
+ updatedAt: z.number(),
151
+ terminals: z.array(WebTerminalListItemSchema)
152
+ }).optional(),
153
+ /**
154
+ * Recently closed terminals (B-084), newest first, capped at 20 — written
155
+ * alongside webTerminals in the same daemonState pushes (every close also
156
+ * changes the live list, so the two always travel together). Old clients
157
+ * ignore the field; old daemons never write it (web renders nothing).
158
+ */
159
+ closedTerminals: z.array(ClosedTerminalRecordSchema).optional(),
160
+ /**
161
+ * B-265 capability flag: this daemon answers `restore-terminal`. Same trust
162
+ * rule as webTerminals — only `detectedAt >= startedAt` counts, because a
163
+ * downgraded daemon spreads the stale field forward on connect.
164
+ */
165
+ terminalRestore: z.object({
166
+ rpcAvailable: z.boolean(),
167
+ detectedAt: z.number()
168
+ }).optional(),
169
+ /**
170
+ * B-273 capability flag: this daemon answers `list-tmux-sessions` and
171
+ * honours `open-terminal.attachTmux`. Same trust rule (`detectedAt >=
172
+ * startedAt`). Stamped unconditionally — on a machine without tmux the
173
+ * RPC just answers an empty list.
174
+ */
175
+ tmuxSessions: z.object({
176
+ rpcAvailable: z.boolean(),
177
+ detectedAt: z.number(),
178
+ /** B-282: `kill-terminal` honours `alsoAttached`. */
179
+ killAttached: z.boolean().optional()
180
+ }).optional(),
181
+ /**
182
+ * B-290 capability flag: this daemon answers `claude-list-history` (import a
183
+ * Claude Code conversation that was never started through very-happy).
184
+ * Same trust rule (`detectedAt >= startedAt`).
185
+ */
186
+ claudeHistory: z.object({
187
+ rpcAvailable: z.boolean(),
188
+ detectedAt: z.number()
189
+ }).optional(),
190
+ /**
191
+ * B-464 capability flag: this daemon answers `codex-list-history` /
192
+ * `codex-import-session` (import a Codex CLI / desktop thread that was never
193
+ * started through very-happy). Same trust rule (`detectedAt >= startedAt`).
194
+ */
195
+ codexHistory: z.object({
196
+ rpcAvailable: z.boolean(),
197
+ detectedAt: z.number()
198
+ }).optional(),
199
+ /**
200
+ * B-486: can web terminals on this machine be durable? `tmuxAvailable:
201
+ * false` ⇒ every new terminal is a direct shell that dies with the daemon,
202
+ * so the web tells the user to install tmux. Same trust rule
203
+ * (`detectedAt >= startedAt`); old webs ignore it.
204
+ */
205
+ terminalHost: z.object({
206
+ tmuxAvailable: z.boolean(),
207
+ tmuxVersion: z.string().optional(),
208
+ detectedAt: z.number()
209
+ }).optional(),
210
+ /** Relay-owned CLI compatibility/update policy last checked by this daemon. */
211
+ cliUpdate: CliUpdateStateSchema.optional(),
212
+ /**
213
+ * B-276: result of the daemon-context Claude auth preflight (spec
214
+ * 2026-09-claude-auth-preflight). Trust rule for consumers:
215
+ * `claudeAuth.daemonPid === daemonState.pid` — daemonState survives daemon
216
+ * restarts (the server returns the existing row and connect spreads it
217
+ * forward), so a downgraded daemon carries this field along unchanged.
218
+ */
219
+ claudeAuth: ClaudeAuthStateSchema.optional()
220
+ });
221
+ const MessageMetaSchema = z.object({
222
+ sentFrom: z.string().optional(),
223
+ // Source identifier
224
+ permissionMode: z.enum(["default", "acceptEdits", "bypassPermissions", "plan", "read-only", "safe-yolo", "yolo"]).optional(),
225
+ // Permission mode for this message
226
+ model: z.string().nullable().optional(),
227
+ // Model name for this message (null = reset)
228
+ fallbackModel: z.string().nullable().optional(),
229
+ // Fallback model for this message (null = reset)
230
+ customSystemPrompt: z.string().nullable().optional(),
231
+ // Custom system prompt for this message (null = reset)
232
+ appendSystemPrompt: z.string().nullable().optional(),
233
+ // Append to system prompt for this message (null = reset)
234
+ allowedTools: z.array(z.string()).nullable().optional(),
235
+ // Allowed tools for this message (null = reset)
236
+ disallowedTools: z.array(z.string()).nullable().optional(),
237
+ // Disallowed tools for this message (null = reset)
238
+ /**
239
+ * Thinking depth for this message (null = reset to the machine default).
240
+ * Deliberately a plain string, not an enum: an unknown value must not make
241
+ * zod reject the WHOLE message the way the `dontAsk` permission enum did
242
+ * (AGENTS 铁律 14). runClaude validates it against its own allow-list and
243
+ * ignores anything else. Absent here until 0.2.105, which is why every
244
+ * released CLI silently dropped the web's effort selection.
245
+ */
246
+ effort: z.string().nullable().optional(),
247
+ /** Omitted/queue waits for the current turn; steer targets the live turn. */
248
+ delivery: z.enum(["queue", "steer"]).optional()
249
+ });
250
+ z.object({
251
+ session: z.object({
252
+ id: z.string(),
253
+ tag: z.string(),
254
+ seq: z.number(),
255
+ createdAt: z.number(),
256
+ updatedAt: z.number(),
257
+ metadata: z.string(),
258
+ metadataVersion: z.number(),
259
+ agentState: z.string().nullable(),
260
+ agentStateVersion: z.number()
261
+ })
262
+ });
263
+ const UserMessageSchema = z.object({
264
+ role: z.literal("user"),
265
+ content: z.object({
266
+ type: z.literal("text"),
267
+ text: z.string()
268
+ }),
269
+ localKey: z.string().optional(),
270
+ // Mobile messages include this
271
+ meta: MessageMetaSchema.optional()
272
+ });
273
+ const FileEventMessageSchema = z.object({
274
+ role: z.literal("session"),
275
+ content: z.object({
276
+ type: z.literal("session"),
277
+ data: z.object({
278
+ id: z.string(),
279
+ time: z.number(),
280
+ role: z.literal("user"),
281
+ ev: z.object({
282
+ t: z.literal("file"),
283
+ ref: z.string(),
284
+ name: z.string(),
285
+ size: z.number(),
286
+ mimeType: z.string().optional(),
287
+ image: z.object({
288
+ width: z.number(),
289
+ height: z.number(),
290
+ // Optional — native iOS picker has no Canvas to compute thumbhash.
291
+ // App-side schema relaxed this in the same commit; keeping CLI in
292
+ // sync so the file event isn't silently rejected by Zod and the
293
+ // attachment never reaches Claude.
294
+ thumbhash: z.string().optional()
295
+ }).optional()
296
+ })
297
+ })
298
+ })
299
+ });
300
+ const AgentMessageSchema = z.object({
301
+ role: z.literal("agent"),
302
+ content: z.object({
303
+ type: z.literal("output"),
304
+ data: z.any()
305
+ }),
306
+ meta: MessageMetaSchema.optional()
307
+ });
308
+ z.union([UserMessageSchema, AgentMessageSchema]);
309
+
310
+ class AsyncLock {
311
+ permits = 1;
312
+ promiseResolverQueue = [];
313
+ async inLock(func) {
314
+ try {
315
+ await this.lock();
316
+ return await func();
317
+ } finally {
318
+ this.unlock();
319
+ }
320
+ }
321
+ async lock() {
322
+ if (this.permits > 0) {
323
+ this.permits = this.permits - 1;
324
+ return;
325
+ }
326
+ await new Promise((resolve) => this.promiseResolverQueue.push(resolve));
327
+ }
328
+ unlock() {
329
+ this.permits += 1;
330
+ if (this.permits > 1 && this.promiseResolverQueue.length > 0) {
331
+ throw new Error("this.permits should never be > 0 when there is someone waiting.");
332
+ } else if (this.permits === 1 && this.promiseResolverQueue.length > 0) {
333
+ this.permits -= 1;
334
+ const nextResolver = this.promiseResolverQueue.shift();
335
+ if (nextResolver) {
336
+ setTimeout(() => {
337
+ nextResolver(true);
338
+ }, 0);
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ const MAX_CHAT_ATTACHMENT_SOURCE_BYTES = 50 * 1024 * 1024;
345
+ const CHAT_ATTACHMENT_ENCRYPTION_OVERHEAD_BYTES = 40;
346
+ const MAX_CHAT_ATTACHMENT_ENCRYPTED_BYTES = MAX_CHAT_ATTACHMENT_SOURCE_BYTES + CHAT_ATTACHMENT_ENCRYPTION_OVERHEAD_BYTES;
347
+
348
+ export { AsyncLock as A, FileEventMessageSchema as F, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, UserMessageSchema as U, MAX_CHAT_ATTACHMENT_ENCRYPTED_BYTES as a };