very-happy-cli 0.2.165 → 0.2.167
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.
- package/README.md +1 -1
- package/dist/{AcpBackend-DCfNt9bD.cjs → AcpBackend-D1IKJGz_.cjs} +3 -3
- package/dist/{AcpBackend-C11FnVw5.mjs → AcpBackend-kFZlee5E.mjs} +3 -3
- package/dist/{AcpSessionManager-BQnDJvct.mjs → AcpSessionManager-B7FIrsys.mjs} +1 -1
- package/dist/{AcpSessionManager-9yN2iH4b.cjs → AcpSessionManager-Zf00QnlL.cjs} +1 -1
- package/dist/{BasePermissionHandler-BwQHxl6M.cjs → BasePermissionHandler-DHxYAK5L.cjs} +1 -1
- package/dist/{BasePermissionHandler-CwJ48yiB.mjs → BasePermissionHandler-DS0kRTNI.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-ClF2g1qz.mjs → BaseReasoningProcessor-BRtCCt7q.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-81lf_M8G.cjs → BaseReasoningProcessor-CsjVdt_H.cjs} +1 -1
- package/dist/{agentGuidance-CQuNlNx8.mjs → agentGuidance-BDYt2Qy2.mjs} +4 -2
- package/dist/{agentGuidance-B5NATuFa.cjs → agentGuidance-BtBx2xxE.cjs} +4 -1
- package/dist/{agentHome-DvR176E5.mjs → agentHome-Ct-VXFeG.mjs} +4 -4
- package/dist/{agentHome-D3Nn82kI.cjs → agentHome-DeAWzhSe.cjs} +4 -4
- package/dist/{api-AzdzTKFs.cjs → api-BZYLRDM9.cjs} +93 -13
- package/dist/{api-DTVPUE7g.mjs → api-CReZazeT.mjs} +93 -13
- package/dist/{apiMachine-B_cJldfa.cjs → apiMachine-BgMxGPsR.cjs} +2173 -66
- package/dist/{apiMachine-BQ-b4Lu3.mjs → apiMachine-CWndf1Vn.mjs} +2176 -69
- package/dist/{attachmentContent-muDCe4Gy.cjs → attachmentContent-HcJqFQW8.cjs} +2 -2
- package/dist/{attachmentContent-dzIs-wis.mjs → attachmentContent-j875mwU7.mjs} +2 -2
- package/dist/{attachmentLimits-eJZ4ZBjF.cjs → attachmentLimits-BEYEEBm8.cjs} +40 -2
- package/dist/{attachmentLimits-B8nzhw-i.mjs → attachmentLimits-CxG3T18E.mjs} +40 -2
- package/dist/{auth-Jtmvh1w4.mjs → auth-BIHuc7vY.mjs} +10 -10
- package/dist/{auth-BY5ujhGn.mjs → auth-CFS9Lfgv.mjs} +5 -5
- package/dist/{auth-DtP-B4gf.cjs → auth-Myr2Q42x.cjs} +10 -10
- package/dist/{auth-CfLd3phE.cjs → auth-VzWpbo5P.cjs} +5 -5
- package/dist/{auto-ClNnbSoF.cjs → auto-Bf6Dr7_o.cjs} +85 -21
- package/dist/{auto-DjWfR1UB.mjs → auto-Df9-zmuN.mjs} +84 -22
- package/dist/{bootstrap-D_ExGrY2.mjs → bootstrap-BSOxYpaP.mjs} +2 -2
- package/dist/{bootstrap-B1dMZA-u.cjs → bootstrap-Dj8WBiR2.cjs} +2 -2
- package/dist/{browser-mwzpOmcw.mjs → browser-BCFIHOvo.mjs} +1 -1
- package/dist/{browser-_gV7tcPs.cjs → browser-BoCV40yC.cjs} +1 -1
- package/dist/{claudeLocal-G5UmJ81F.cjs → claudeLocal-CGsq7Kul.cjs} +7 -7
- package/dist/{claudeLocal-BeHToEK5.mjs → claudeLocal-D5-eA9SC.mjs} +7 -7
- package/dist/{claudeLocalLauncher-Cq6bqAT4.mjs → claudeLocalLauncher-C9Cc438l.mjs} +15 -12
- package/dist/{claudeLocalLauncher-B4y2BsmO.cjs → claudeLocalLauncher-Cf9QeYDT.cjs} +15 -12
- package/dist/{claudeSessionFork-CDJq_b9r.cjs → claudeSessionFork-Byd8zD1U.cjs} +1 -1
- package/dist/{claudeSessionFork-CokUhS4r.mjs → claudeSessionFork-CMzAva8G.mjs} +1 -1
- package/dist/{client-Do7cGPEq.cjs → client-BKnKRLSt.cjs} +3 -3
- package/dist/{client-CJZKBZCE.mjs → client-C7FYMer0.mjs} +2 -2
- package/dist/{client-uN9d6Git.cjs → client-D0T5-6Ds.cjs} +2 -2
- package/dist/{client-BwaWdlCm.mjs → client-Dsfy_SAb.mjs} +3 -3
- package/dist/codex/happyMcpStdioBridge.cjs +23 -18
- package/dist/codex/happyMcpStdioBridge.mjs +22 -17
- package/dist/{codexAppServerClient-B0QaMQsC.mjs → codexAppServerClient-Dd_4TxHv.mjs} +48 -4
- package/dist/{codexAppServerClient-BuSdeUxT.cjs → codexAppServerClient-TiW9OBk4.cjs} +47 -3
- package/dist/{codexCommand-C3gdjMAw.mjs → codexCommand-BZSr4MKI.mjs} +170 -69
- package/dist/{codexCommand-YdYmykAR.cjs → codexCommand-Bxryqh90.cjs} +170 -69
- package/dist/{config-CGCIFRCN.mjs → config-C_Pj7yxV.mjs} +3 -3
- package/dist/{config-ChoHFnfO.cjs → config-DXPash-r.cjs} +3 -3
- package/dist/{configuration-BE61XNsg.cjs → configuration-C3piBtxY.cjs} +1 -1
- package/dist/{configuration-L1qcGTFM.mjs → configuration-WspKd2C2.mjs} +2 -2
- package/dist/{connect-D5IKfcfd.cjs → connect-BN-IBElA.cjs} +14 -14
- package/dist/{connect-CFD0Em6a.mjs → connect-DGPZs5px.mjs} +14 -14
- package/dist/{context-DaCCB4cm.mjs → context-Cr6a3NTg.mjs} +1 -1
- package/dist/{context-3WVw8qPz.cjs → context-Jrq4-eCZ.cjs} +1 -1
- package/dist/{controlClient-RWTlQA4_.cjs → controlClient-BI6Fw3fQ.cjs} +28 -5
- package/dist/{controlClient-Ci7HTMII.mjs → controlClient-DTheOlvC.mjs} +27 -6
- package/dist/{createSessionMetadata-CWR-AB2A.mjs → createSessionMetadata-BEZ4DIDA.mjs} +57 -5
- package/dist/{createSessionMetadata-CPGTztXP.cjs → createSessionMetadata-zQSz3hgk.cjs} +56 -3
- package/dist/defaultPermissionMode-Cif_RHGb.mjs +191 -0
- package/dist/defaultPermissionMode-DNKNzk7l.cjs +197 -0
- package/dist/{deterministicJson-BBwG-Ase.mjs → deterministicJson-BMMifViN.mjs} +36 -52
- package/dist/{deterministicJson-C4Jo2RWy.cjs → deterministicJson-C7O2ulKY.cjs} +41 -59
- package/dist/{doctor-ZOQLE5AH.cjs → doctor-BykBaMTr.cjs} +6 -6
- package/dist/{doctor-CAC6qY9Z.mjs → doctor-D1KKyPzB.mjs} +6 -6
- package/dist/{assistantTools-BsrG3PD-.cjs → downloadTarget-CWTb2-EM.cjs} +44 -6
- package/dist/{assistantTools-DPGga5lM.mjs → downloadTarget-Cp48jrIP.mjs} +45 -8
- package/dist/{ensureDaemonRunning-b1pvEFcS.mjs → ensureDaemonRunning-Ba5fYoxb.mjs} +5 -5
- package/dist/{ensureDaemonRunning-mIgX2vnc.cjs → ensureDaemonRunning-CCxX7MoP.cjs} +5 -5
- package/dist/{handleResumeCommand-CTGbZkCL.mjs → handleResumeCommand-BTUGlNjB.mjs} +5 -5
- package/dist/{handleResumeCommand-DGNhbv-3.cjs → handleResumeCommand-yPdDQHqz.cjs} +5 -5
- package/dist/{index-vVWpCoTr.mjs → index-B0HEEYGh.mjs} +22 -5
- package/dist/{index-BzIxE0Eu.cjs → index-BjhKqDa0.cjs} +3 -3
- package/dist/{index-BgzjPv07.mjs → index-C3_83bqS.mjs} +3 -3
- package/dist/{index-DqlyNgt4.cjs → index-C9hI8a10.cjs} +26 -4
- package/dist/{index-DjtBengz.mjs → index-CE2GgPbr.mjs} +40 -39
- package/dist/{index-Diu6HdWH.mjs → index-D8m8Ripb.mjs} +4 -4
- package/dist/{index-DrSPR59N.cjs → index-DifM62wX.cjs} +39 -38
- package/dist/{index-DIodyAqF.cjs → index-PNMQPKhz.cjs} +4 -4
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-BO_W7VhL.mjs → install-BdvKiOQw.mjs} +2 -0
- package/dist/{install-Cp_aB-NQ.mjs → install-C0-QFn9s.mjs} +3 -3
- package/dist/{install-Cs5qAPrB.cjs → install-Cf6AFSWC.cjs} +2 -0
- package/dist/{install-DrUQk2DJ.cjs → install-CqZVeze8.cjs} +3 -3
- package/dist/lib.cjs +12 -12
- package/dist/lib.d.cts +116 -2
- package/dist/lib.d.mts +116 -2
- package/dist/lib.mjs +12 -12
- package/dist/{lidState-BLHLmhwd.mjs → lidState-B2ZxdREe.mjs} +1 -1
- package/dist/{lidState-z9ekRpZu.cjs → lidState-Bc2K9H9l.cjs} +1 -1
- package/dist/{localHappyAgentAuth-BWvmc_Hg.mjs → localHappyAgentAuth-B5XPEMwk.mjs} +1 -1
- package/dist/{localHappyAgentAuth-BCx0y1qW.cjs → localHappyAgentAuth-T5GOvRha.cjs} +1 -1
- package/dist/{logger-D0hkk7Vo.cjs → logger-B_MWPbZz.cjs} +2 -2
- package/dist/{logger-CknSVkIe.mjs → logger-CbBv3q_b.mjs} +2 -2
- package/dist/{machineMetadata-BDCYOXQg.cjs → machineMetadata-BafS4JY8.cjs} +4 -3
- package/dist/{machineMetadata-Cj1DoFot.mjs → machineMetadata-DHg238U4.mjs} +4 -3
- package/dist/{main-COAPGIso.cjs → main-DNrA0qBy.cjs} +45 -45
- package/dist/{main-CKUfkVG_.mjs → main-DXAK0n7x.mjs} +45 -45
- package/dist/{manager-BQ4flvQZ.mjs → manager-BEsI4qt3.mjs} +9 -3
- package/dist/{manager-Cly8xVIR.cjs → manager-HrEj442o.cjs} +8 -2
- package/dist/{mcp-BILnw4si.cjs → mcp-AvPOhDXy.cjs} +24 -19
- package/dist/{mcp-DeYUfpo8.mjs → mcp-BotAjCdD.mjs} +23 -18
- package/dist/mirrorProtocol-BdcN6QlN.cjs +1270 -0
- package/dist/mirrorProtocol-BwHm8odn.mjs +1247 -0
- package/dist/{package-UkmvSFsg.cjs → package-C9ZP9bpX.cjs} +7 -7
- package/dist/{package-VIUXrYZ1.mjs → package-DU1DxhH9.mjs} +7 -7
- package/dist/{peerTools-CttfOxti.cjs → peerTools-Dkbu7gag.cjs} +4 -4
- package/dist/{peerTools-SWITnkqz.mjs → peerTools-os2DVjA0.mjs} +4 -4
- package/dist/{persistence-C6ztVW1W.cjs → persistence-BYGl0QYw.cjs} +147 -25
- package/dist/{persistence-DujtUH94.mjs → persistence-ON0zpHfb.mjs} +123 -12
- package/dist/{piRunnerArgs-BVJHIjlk.mjs → piRunnerArgs-CYsnT9sV.mjs} +1 -1
- package/dist/{piRunnerArgs-tBQg6xDw.cjs → piRunnerArgs-DpbvstUX.cjs} +1 -1
- package/dist/{piRuntime-DZzjF9It.cjs → piRuntime-CDnILlCd.cjs} +1 -1
- package/dist/{piRuntime-DKFA8u8t.mjs → piRuntime-CmEid-wu.mjs} +1 -1
- package/dist/{piTerminal-BTSaFlpV.mjs → piTerminal-0eNlXSlL.mjs} +17 -17
- package/dist/{piTerminal-t5pQHCPT.cjs → piTerminal-B57TgMON.cjs} +17 -17
- package/dist/precheckCompat-CWOi5c9L.cjs +29 -0
- package/dist/precheckCompat-DeEbilbr.mjs +26 -0
- package/dist/rateLimitWindows-CusGIqlq.cjs +258 -0
- package/dist/rateLimitWindows-vZ9Bo7aT.mjs +248 -0
- package/dist/{registerCommonHandlers-BR0J4g64.mjs → registerCommonHandlers-B0PVff2U.mjs} +2 -2
- package/dist/{registerCommonHandlers--8ds2auE.cjs → registerCommonHandlers-DVYB3iVn.cjs} +2 -2
- package/dist/{registerKillSessionHandler-Czz0tdki.mjs → registerKillSessionHandler-BJMHJHXe.mjs} +15 -10
- package/dist/{registerKillSessionHandler-CI23l8aJ.cjs → registerKillSessionHandler-BwXGKtg_.cjs} +15 -10
- package/dist/{remoteSessionClient-DCAUHgPz.mjs → remoteSessionClient-BzPXSC21.mjs} +5 -5
- package/dist/{remoteSessionClient-BAkIwM2S.cjs → remoteSessionClient-PyUAIhwK.cjs} +5 -5
- package/dist/{tools-BVRoGcQH.mjs → reportProgressTool-BvB13EwC.mjs} +67 -10
- package/dist/{tools-mWqsE6ji.cjs → reportProgressTool-D4KB_4cP.cjs} +73 -9
- package/dist/{run-CkKujjn8.cjs → run-BC8jzq_h.cjs} +558 -122
- package/dist/{run-B75qm2I6.mjs → run-O2M8LsWf.mjs} +556 -120
- package/dist/{runClaude-B1T9DLLi.cjs → runClaude-C7jPa8VP.cjs} +93 -26
- package/dist/{runClaude-aBfBweec.mjs → runClaude-DGkr5E7s.mjs} +93 -26
- package/dist/{runClaudeDeps-BGjNGfuZ.cjs → runClaudeDeps-5kzncqME.cjs} +113 -35
- package/dist/{runClaudeDeps-BOrPP4J1.mjs → runClaudeDeps-CX_TxS78.mjs} +116 -37
- package/dist/{runGemini-BuAA_OQb.cjs → runGemini-BfYA4Uqc.cjs} +43 -36
- package/dist/{runGemini-a-V7JE-J.mjs → runGemini-CwmGBH3L.mjs} +43 -36
- package/dist/{runOpenClaw-DUSwXg1A.mjs → runOpenClaw-BYAPYFyL.mjs} +18 -18
- package/dist/{runOpenClaw-BBVffIh9.cjs → runOpenClaw-C72jut7v.cjs} +18 -18
- package/dist/{sandbox-Fd2G5yaq.cjs → sandbox-Bqkp8IT7.cjs} +4 -4
- package/dist/{sandbox-Brb_5wzc.mjs → sandbox-DlVnK1Vi.mjs} +4 -4
- package/dist/{selfCheck-NuJKMInJ.cjs → selfCheck-B4lLZplk.cjs} +34 -34
- package/dist/selfCheck-DYTGBdIO.mjs +84 -0
- package/dist/{send-DEQJiq_x.mjs → send-B5bWW9Tl.mjs} +8 -8
- package/dist/{send-4dgHKC3u.cjs → send-BCwS6n_s.cjs} +8 -8
- package/dist/{server-C6AlUFkw.mjs → server-CEJfRQfj.mjs} +4 -4
- package/dist/{server-DWGcDmHG.cjs → server-CFWZehnC.cjs} +6 -6
- package/dist/{sessionLock-Dm8QyGo4.mjs → sessionLock-AwOYsKT7.mjs} +12 -4
- package/dist/{sessionLock-B1GgaO1q.cjs → sessionLock-LBWNjpHf.cjs} +12 -3
- package/dist/{sessionModeFile-BvOEJ4Fl.cjs → sessionModeFile-CyPuZRIU.cjs} +1 -1
- package/dist/{sessionModeFile-CuNAWCKL.mjs → sessionModeFile-fvFn1JVG.mjs} +1 -1
- package/dist/{sessionOps-DG5MMEp_.mjs → sessionOps-DZRH4-hV.mjs} +4 -4
- package/dist/{sessionOps-JP64uJmc.cjs → sessionOps-DzbZI3Eq.cjs} +4 -4
- package/dist/{sessionScanner-DqSk5Ol_.mjs → sessionScanner-Q_Ei2flB.mjs} +75 -19
- package/dist/{sessionScanner-BBPEgJ5S.cjs → sessionScanner-i-cgwFVw.cjs} +75 -19
- package/dist/{sessions-4isbBAWi.mjs → sessions-DAmjMAZN.mjs} +9 -9
- package/dist/{sessions-DgJuw_i0.cjs → sessions-DYK5hD4T.cjs} +9 -9
- package/dist/{setupOfflineReconnection-_MoZtsro.mjs → setupOfflineReconnection-BfDBxNdo.mjs} +2 -2
- package/dist/{setupOfflineReconnection-CKJKVIUS.cjs → setupOfflineReconnection-C2LO3hSP.cjs} +2 -2
- package/dist/{spawn-BTOG4tTm.mjs → spawn-BmjG5j5Y.mjs} +15 -14
- package/dist/{spawn-CshERWbY.cjs → spawn-GK_sXE8h.cjs} +15 -14
- package/dist/{spawnAgents-Czi2VDzj.mjs → spawnAgents-HDaE3C0-.mjs} +1 -1
- package/dist/{spawnAgents-McixdtV1.cjs → spawnAgents-vglexX9N.cjs} +1 -1
- package/dist/{spawnHappyCLI-Dc4xYm8P.mjs → spawnHappyCLI-B2h0P4b5.mjs} +1 -1
- package/dist/{spawnHappyCLI-Dd5_8Vex.cjs → spawnHappyCLI-J4iEhfyZ.cjs} +1 -1
- package/dist/specialCommands-DisVxagO.mjs +93 -0
- package/dist/specialCommands-DmJMKspE.cjs +96 -0
- package/dist/{startFileWatcher-B0VlG-Fn.mjs → startFileWatcher-CeK1k5gt.mjs} +1 -1
- package/dist/{startFileWatcher-1LedLBY-.cjs → startFileWatcher-xKo8AoYl.cjs} +1 -1
- package/dist/{streamRelay-C0AffuX6.cjs → streamRelay-Ce9sgcOV.cjs} +1 -1
- package/dist/{streamRelay-BzMEEvJU.mjs → streamRelay-Iogsh51a.mjs} +1 -1
- package/dist/{sync-DwUUGGFz.cjs → sync-Bvc-vh6C.cjs} +1 -1
- package/dist/{sync-Dfm6K2te.mjs → sync-CCwYpJMS.mjs} +1 -1
- package/dist/{systemPrompt-D41Zw1a3.mjs → systemPrompt-BNIkP3tR.mjs} +3 -3
- package/dist/{systemPrompt-CB1Ls0AE.cjs → systemPrompt-DwOddbuG.cjs} +3 -3
- package/dist/{teams-D8Ly3i6u.mjs → teams-DRrLBcys.mjs} +7 -7
- package/dist/{teams-NWv2ji16.cjs → teams-GHMCRZOw.cjs} +7 -7
- package/dist/{time-BbzJ7PJQ.cjs → time-BXvtjhe9.cjs} +1 -1
- package/dist/{time-v1Y_qEJp.mjs → time-PG5Dfwdv.mjs} +1 -1
- package/dist/{titleGenerator-cH6IkPRi.cjs → titleGenerator-B07bZA0V.cjs} +2 -2
- package/dist/{titleGenerator-BhoblAQY.mjs → titleGenerator-CIzfpfZW.mjs} +1 -1
- package/dist/{todo-D1hgWV6d.cjs → todo-B0aeoNu3.cjs} +6 -6
- package/dist/{todo-CuNct-fw.mjs → todo-CfL7SBFc.mjs} +6 -6
- package/dist/{tools-jof0Bu54.mjs → tools-D91mq5Ib.mjs} +1 -1
- package/dist/{tools-c2fb0CF5.cjs → tools-DJIANHSh.cjs} +1 -1
- package/dist/transcriptCursor-B7T_gkQ0.mjs +102 -0
- package/dist/transcriptCursor-DcXGLeSc.cjs +106 -0
- package/dist/{uninstall-BB7WYYAk.mjs → uninstall-5xz3Xvhf.mjs} +3 -3
- package/dist/{uninstall-VPH5GfrA.cjs → uninstall-AtzOfdrj.cjs} +3 -3
- package/package.json +7 -7
- package/scripts/terminal_status_forwarder.cjs +89 -0
- package/dist/defaultPermissionMode-BnxJPVHT.mjs +0 -4
- package/dist/defaultPermissionMode-CxmTXUQR.cjs +0 -7
- package/dist/mirrorProtocol-BNLtoWjO.mjs +0 -170
- package/dist/mirrorProtocol-BUtmg1ws.cjs +0 -186
- package/dist/selfCheck-BgwJ3NGS.mjs +0 -84
- package/dist/specialCommands-BSqhYg5X.mjs +0 -52
- package/dist/specialCommands-DSsTeRej.cjs +0 -54
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { c as configuration } from './configuration-
|
|
2
|
-
import {
|
|
3
|
-
import { readCredentialsForConfiguredRelay } from './persistence-
|
|
4
|
-
import { r as readTeamScope, t as teamScopePath } from './context-
|
|
1
|
+
import { c as configuration } from './configuration-WspKd2C2.mjs';
|
|
2
|
+
import { d as createBuiltinTodoClient, B as BUILTIN_TODO_SKILL } from './index-B0HEEYGh.mjs';
|
|
3
|
+
import { c as readCredentialsForConfiguredRelay } from './persistence-ON0zpHfb.mjs';
|
|
4
|
+
import { r as readTeamScope, t as teamScopePath } from './context-Cr6a3NTg.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'node:path';
|
|
8
|
-
import './package-
|
|
8
|
+
import './package-DU1DxhH9.mjs';
|
|
9
9
|
import 'node:fs/promises';
|
|
10
10
|
import 'zod';
|
|
11
11
|
import '@paralleldrive/cuid2';
|
|
12
12
|
import './authRelay-DSAvg1uv.mjs';
|
|
13
13
|
import 'node:crypto';
|
|
14
14
|
import 'tweetnacl';
|
|
15
|
-
import './logger-
|
|
15
|
+
import './logger-CbBv3q_b.mjs';
|
|
16
16
|
import 'chalk';
|
|
17
17
|
import 'node:util';
|
|
18
18
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { c as createTeamsClient } from './client-
|
|
2
|
+
import { c as createTeamsClient } from './client-Dsfy_SAb.mjs';
|
|
3
3
|
|
|
4
4
|
const TEAM_TOOL_NAMES = ["team_create", "team_join", "team_inspect", "team_delegate", "team_message", "team_submit", "team_accept", "team_return", "team_cancel", "team_handoff", "team_schedule_create", "team_schedule_pause", "team_schedule_resume", "team_schedule_cancel"];
|
|
5
5
|
const id = z.string().min(1).max(128);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var z = require('zod');
|
|
4
|
-
var client = require('./client-
|
|
4
|
+
var client = require('./client-BKnKRLSt.cjs');
|
|
5
5
|
|
|
6
6
|
const TEAM_TOOL_NAMES = ["team_create", "team_join", "team_inspect", "team_delegate", "team_message", "team_submit", "team_accept", "team_return", "team_cancel", "team_handoff", "team_schedule_create", "team_schedule_pause", "team_schedule_resume", "team_schedule_cancel"];
|
|
7
7
|
const id = z.z.string().min(1).max(128);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { open } from 'node:fs/promises';
|
|
2
|
+
import { isAbsolute, basename } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const TRANSCRIPT_BOUNDARY_BYTES = 64;
|
|
5
|
+
function planTranscriptRead(cursor, stat) {
|
|
6
|
+
if (!cursor) return { start: 0, reset: null, verifyAt: null };
|
|
7
|
+
if (cursor.dev !== stat.dev || cursor.ino !== stat.ino) return { start: 0, reset: "replaced", verifyAt: null };
|
|
8
|
+
if (stat.size < cursor.offset) return { start: 0, reset: "truncated", verifyAt: null };
|
|
9
|
+
if (cursor.boundary.length === 0) return { start: cursor.offset, reset: null, verifyAt: null };
|
|
10
|
+
return { start: cursor.offset, reset: null, verifyAt: cursor.offset - cursor.boundary.length };
|
|
11
|
+
}
|
|
12
|
+
function advanceTranscriptCursor(previous, stat, start, bytes) {
|
|
13
|
+
const lastNewline = bytes.lastIndexOf(10);
|
|
14
|
+
const consumed = lastNewline === -1 ? 0 : lastNewline + 1;
|
|
15
|
+
const lines = consumed === 0 ? [] : bytes.subarray(0, consumed).toString("utf-8").split("\n").filter((line) => line.trim().length > 0);
|
|
16
|
+
const carried = previous && start === previous.offset ? previous.boundary : Buffer.alloc(0);
|
|
17
|
+
const tail = Buffer.concat([carried, bytes.subarray(0, consumed)]);
|
|
18
|
+
return {
|
|
19
|
+
lines,
|
|
20
|
+
cursor: {
|
|
21
|
+
offset: start + consumed,
|
|
22
|
+
dev: stat.dev,
|
|
23
|
+
ino: stat.ino,
|
|
24
|
+
boundary: Buffer.from(tail.subarray(Math.max(0, tail.length - TRANSCRIPT_BOUNDARY_BYTES)))
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function readTranscriptIncrement(path, cursor, opts = {}) {
|
|
29
|
+
let handle;
|
|
30
|
+
try {
|
|
31
|
+
handle = await open(path, "r");
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const st = await handle.stat();
|
|
37
|
+
const stat = { dev: st.dev, ino: st.ino, size: st.size };
|
|
38
|
+
let { start, reset, verifyAt } = planTranscriptRead(cursor, stat);
|
|
39
|
+
if (verifyAt !== null && cursor) {
|
|
40
|
+
const probe = Buffer.alloc(cursor.boundary.length);
|
|
41
|
+
const { bytesRead: bytesRead2 } = await handle.read(probe, 0, probe.length, verifyAt);
|
|
42
|
+
if (bytesRead2 !== probe.length || !probe.equals(cursor.boundary)) {
|
|
43
|
+
start = 0;
|
|
44
|
+
reset = "rewritten";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const base = reset ? null : cursor;
|
|
48
|
+
const end = opts.limit === void 0 ? stat.size : Math.min(stat.size, Math.max(0, opts.limit));
|
|
49
|
+
const length = Math.max(0, end - start);
|
|
50
|
+
if (length === 0) {
|
|
51
|
+
return { lines: [], cursor: base ? { ...base, dev: stat.dev, ino: stat.ino } : advanceTranscriptCursor(null, stat, 0, Buffer.alloc(0)).cursor, reset };
|
|
52
|
+
}
|
|
53
|
+
const buffer = Buffer.alloc(length);
|
|
54
|
+
const { bytesRead } = await handle.read(buffer, 0, length, start);
|
|
55
|
+
const { lines, cursor: next } = advanceTranscriptCursor(base, stat, start, buffer.subarray(0, bytesRead));
|
|
56
|
+
return { lines, cursor: next, reset };
|
|
57
|
+
} finally {
|
|
58
|
+
await handle.close().catch(() => void 0);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function isValidTranscriptHint(sessionId, path) {
|
|
62
|
+
return typeof path === "string" && path.length > 0 && path.length <= 4096 && isAbsolute(path) && basename(path) === `${sessionId}.jsonl`;
|
|
63
|
+
}
|
|
64
|
+
class TranscriptPathHints {
|
|
65
|
+
constructor(max = 64) {
|
|
66
|
+
this.max = max;
|
|
67
|
+
}
|
|
68
|
+
paths = /* @__PURE__ */ new Map();
|
|
69
|
+
listeners = /* @__PURE__ */ new Set();
|
|
70
|
+
/** Called synchronously whenever a session's hinted path is set/changed. */
|
|
71
|
+
subscribe(listener) {
|
|
72
|
+
this.listeners.add(listener);
|
|
73
|
+
return () => {
|
|
74
|
+
this.listeners.delete(listener);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
note(sessionId, path) {
|
|
78
|
+
if (!isValidTranscriptHint(sessionId, path)) return false;
|
|
79
|
+
const changed = this.paths.get(sessionId) !== path;
|
|
80
|
+
this.paths.delete(sessionId);
|
|
81
|
+
this.paths.set(sessionId, path);
|
|
82
|
+
if (changed) {
|
|
83
|
+
for (const listener of this.listeners) {
|
|
84
|
+
try {
|
|
85
|
+
listener(sessionId, path);
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
while (this.paths.size > this.max) {
|
|
91
|
+
const oldest = this.paths.keys().next().value;
|
|
92
|
+
if (oldest === void 0) break;
|
|
93
|
+
this.paths.delete(oldest);
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
get(sessionId) {
|
|
98
|
+
return this.paths.get(sessionId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { TranscriptPathHints as T, isValidTranscriptHint as i, readTranscriptIncrement as r };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const TRANSCRIPT_BOUNDARY_BYTES = 64;
|
|
7
|
+
function planTranscriptRead(cursor, stat) {
|
|
8
|
+
if (!cursor) return { start: 0, reset: null, verifyAt: null };
|
|
9
|
+
if (cursor.dev !== stat.dev || cursor.ino !== stat.ino) return { start: 0, reset: "replaced", verifyAt: null };
|
|
10
|
+
if (stat.size < cursor.offset) return { start: 0, reset: "truncated", verifyAt: null };
|
|
11
|
+
if (cursor.boundary.length === 0) return { start: cursor.offset, reset: null, verifyAt: null };
|
|
12
|
+
return { start: cursor.offset, reset: null, verifyAt: cursor.offset - cursor.boundary.length };
|
|
13
|
+
}
|
|
14
|
+
function advanceTranscriptCursor(previous, stat, start, bytes) {
|
|
15
|
+
const lastNewline = bytes.lastIndexOf(10);
|
|
16
|
+
const consumed = lastNewline === -1 ? 0 : lastNewline + 1;
|
|
17
|
+
const lines = consumed === 0 ? [] : bytes.subarray(0, consumed).toString("utf-8").split("\n").filter((line) => line.trim().length > 0);
|
|
18
|
+
const carried = previous && start === previous.offset ? previous.boundary : Buffer.alloc(0);
|
|
19
|
+
const tail = Buffer.concat([carried, bytes.subarray(0, consumed)]);
|
|
20
|
+
return {
|
|
21
|
+
lines,
|
|
22
|
+
cursor: {
|
|
23
|
+
offset: start + consumed,
|
|
24
|
+
dev: stat.dev,
|
|
25
|
+
ino: stat.ino,
|
|
26
|
+
boundary: Buffer.from(tail.subarray(Math.max(0, tail.length - TRANSCRIPT_BOUNDARY_BYTES)))
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function readTranscriptIncrement(path, cursor, opts = {}) {
|
|
31
|
+
let handle;
|
|
32
|
+
try {
|
|
33
|
+
handle = await promises.open(path, "r");
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const st = await handle.stat();
|
|
39
|
+
const stat = { dev: st.dev, ino: st.ino, size: st.size };
|
|
40
|
+
let { start, reset, verifyAt } = planTranscriptRead(cursor, stat);
|
|
41
|
+
if (verifyAt !== null && cursor) {
|
|
42
|
+
const probe = Buffer.alloc(cursor.boundary.length);
|
|
43
|
+
const { bytesRead: bytesRead2 } = await handle.read(probe, 0, probe.length, verifyAt);
|
|
44
|
+
if (bytesRead2 !== probe.length || !probe.equals(cursor.boundary)) {
|
|
45
|
+
start = 0;
|
|
46
|
+
reset = "rewritten";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const base = reset ? null : cursor;
|
|
50
|
+
const end = opts.limit === void 0 ? stat.size : Math.min(stat.size, Math.max(0, opts.limit));
|
|
51
|
+
const length = Math.max(0, end - start);
|
|
52
|
+
if (length === 0) {
|
|
53
|
+
return { lines: [], cursor: base ? { ...base, dev: stat.dev, ino: stat.ino } : advanceTranscriptCursor(null, stat, 0, Buffer.alloc(0)).cursor, reset };
|
|
54
|
+
}
|
|
55
|
+
const buffer = Buffer.alloc(length);
|
|
56
|
+
const { bytesRead } = await handle.read(buffer, 0, length, start);
|
|
57
|
+
const { lines, cursor: next } = advanceTranscriptCursor(base, stat, start, buffer.subarray(0, bytesRead));
|
|
58
|
+
return { lines, cursor: next, reset };
|
|
59
|
+
} finally {
|
|
60
|
+
await handle.close().catch(() => void 0);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function isValidTranscriptHint(sessionId, path$1) {
|
|
64
|
+
return typeof path$1 === "string" && path$1.length > 0 && path$1.length <= 4096 && path.isAbsolute(path$1) && path.basename(path$1) === `${sessionId}.jsonl`;
|
|
65
|
+
}
|
|
66
|
+
class TranscriptPathHints {
|
|
67
|
+
constructor(max = 64) {
|
|
68
|
+
this.max = max;
|
|
69
|
+
}
|
|
70
|
+
paths = /* @__PURE__ */ new Map();
|
|
71
|
+
listeners = /* @__PURE__ */ new Set();
|
|
72
|
+
/** Called synchronously whenever a session's hinted path is set/changed. */
|
|
73
|
+
subscribe(listener) {
|
|
74
|
+
this.listeners.add(listener);
|
|
75
|
+
return () => {
|
|
76
|
+
this.listeners.delete(listener);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
note(sessionId, path) {
|
|
80
|
+
if (!isValidTranscriptHint(sessionId, path)) return false;
|
|
81
|
+
const changed = this.paths.get(sessionId) !== path;
|
|
82
|
+
this.paths.delete(sessionId);
|
|
83
|
+
this.paths.set(sessionId, path);
|
|
84
|
+
if (changed) {
|
|
85
|
+
for (const listener of this.listeners) {
|
|
86
|
+
try {
|
|
87
|
+
listener(sessionId, path);
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
while (this.paths.size > this.max) {
|
|
93
|
+
const oldest = this.paths.keys().next().value;
|
|
94
|
+
if (oldest === void 0) break;
|
|
95
|
+
this.paths.delete(oldest);
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
get(sessionId) {
|
|
100
|
+
return this.paths.get(sessionId);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
exports.TranscriptPathHints = TranscriptPathHints;
|
|
105
|
+
exports.isValidTranscriptHint = isValidTranscriptHint;
|
|
106
|
+
exports.readTranscriptIncrement = readTranscriptIncrement;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { l as logger } from './logger-
|
|
1
|
+
import { l as logger } from './logger-CbBv3q_b.mjs';
|
|
2
2
|
import { existsSync, unlinkSync } from 'fs';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import 'chalk';
|
|
5
5
|
import 'node:util';
|
|
6
|
-
import './configuration-
|
|
6
|
+
import './configuration-WspKd2C2.mjs';
|
|
7
7
|
import 'node:fs';
|
|
8
8
|
import 'node:os';
|
|
9
9
|
import 'node:path';
|
|
10
|
-
import './package-
|
|
10
|
+
import './package-DU1DxhH9.mjs';
|
|
11
11
|
import 'node:fs/promises';
|
|
12
12
|
|
|
13
13
|
const PLIST_LABEL = "com.happy-cli.daemon";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./logger-
|
|
3
|
+
var logger = require('./logger-B_MWPbZz.cjs');
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var child_process = require('child_process');
|
|
6
6
|
require('chalk');
|
|
7
7
|
require('node:util');
|
|
8
|
-
require('./configuration-
|
|
8
|
+
require('./configuration-C3piBtxY.cjs');
|
|
9
9
|
require('node:fs');
|
|
10
10
|
require('node:os');
|
|
11
11
|
require('node:path');
|
|
12
|
-
require('./package-
|
|
12
|
+
require('./package-C9ZP9bpX.cjs');
|
|
13
13
|
require('node:fs/promises');
|
|
14
14
|
|
|
15
15
|
const PLIST_LABEL = "com.happy-cli.daemon";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.167",
|
|
4
4
|
"description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"contributors": [
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
"zod": "^4.0.0"
|
|
118
118
|
},
|
|
119
119
|
"optionalDependencies": {
|
|
120
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
121
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
122
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
123
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
124
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
125
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
120
|
+
"very-happy-tools-arm64-darwin": "0.2.167",
|
|
121
|
+
"very-happy-tools-x64-darwin": "0.2.167",
|
|
122
|
+
"very-happy-tools-arm64-linux": "0.2.167",
|
|
123
|
+
"very-happy-tools-x64-linux": "0.2.167",
|
|
124
|
+
"very-happy-tools-arm64-win32": "0.2.167",
|
|
125
|
+
"very-happy-tools-x64-win32": "0.2.167"
|
|
126
126
|
},
|
|
127
127
|
"devDependencies": {
|
|
128
128
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Terminal Status Hook Forwarder (B-547)
|
|
4
|
+
*
|
|
5
|
+
* Wired ONLY through the per-terminal `--settings` file the daemon writes
|
|
6
|
+
* when it types a `claude …` command into a vh web terminal (never into the
|
|
7
|
+
* user's ~/.claude/settings.json). Usage, as built by terminalHookCommand():
|
|
8
|
+
*
|
|
9
|
+
* node terminal_status_forwarder.cjs <terminalId> <happyHome> <claudePid>
|
|
10
|
+
*
|
|
11
|
+
* Reads claude's hook JSON from stdin, keeps a small whitelist of fields
|
|
12
|
+
* (no prompt text, no tool input/output, no assistant text — the prompt is
|
|
13
|
+
* reduced to a short hash used only as a turn identity), and POSTs it to the
|
|
14
|
+
* daemon's /terminal-agent-hook with the control token from daemon.state.json.
|
|
15
|
+
*
|
|
16
|
+
* Contract with claude: write NOTHING to stdout (PermissionRequest /
|
|
17
|
+
* UserPromptSubmit treat stdout as a decision / extra context) and always
|
|
18
|
+
* exit 0. Every failure is silent.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const http = require('http');
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
const crypto = require('crypto');
|
|
25
|
+
|
|
26
|
+
const [terminalId, happyHome, claudePid] = process.argv.slice(2);
|
|
27
|
+
if (!terminalId || !/^[A-Za-z0-9_-]{1,64}$/.test(terminalId) || !happyHome) process.exit(0);
|
|
28
|
+
|
|
29
|
+
let port = null;
|
|
30
|
+
let controlToken = null;
|
|
31
|
+
try {
|
|
32
|
+
const state = JSON.parse(fs.readFileSync(path.join(happyHome, 'daemon.state.json'), 'utf-8'));
|
|
33
|
+
if (state && typeof state.httpPort === 'number') port = state.httpPort;
|
|
34
|
+
if (state && typeof state.controlToken === 'string') controlToken = state.controlToken;
|
|
35
|
+
} catch {
|
|
36
|
+
// no daemon → nothing to report to
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const FIELDS = [
|
|
40
|
+
'hook_event_name', 'session_id', 'transcript_path', 'cwd', 'prompt_id', 'agent_id',
|
|
41
|
+
'source', 'notification_type', 'trigger', 'reason', 'tool_name',
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const chunks = [];
|
|
45
|
+
process.stdin.on('data', (chunk) => chunks.push(chunk));
|
|
46
|
+
process.stdin.on('end', () => {
|
|
47
|
+
if (!port) process.exit(0);
|
|
48
|
+
let input = {};
|
|
49
|
+
try {
|
|
50
|
+
input = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
|
|
51
|
+
} catch {
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
if (!input || typeof input !== 'object') process.exit(0);
|
|
55
|
+
const payload = { terminalId };
|
|
56
|
+
for (const key of FIELDS) {
|
|
57
|
+
if (typeof input[key] === 'string' && input[key].length <= 4096) payload[key] = input[key];
|
|
58
|
+
}
|
|
59
|
+
if (claudePid && /^\d{1,10}$/.test(claudePid)) payload.claudePid = Number(claudePid);
|
|
60
|
+
if (typeof input.prompt === 'string') {
|
|
61
|
+
payload.promptHash = crypto.createHash('sha256').update(input.prompt).digest('hex').slice(0, 16);
|
|
62
|
+
}
|
|
63
|
+
// Older Claude Notification payloads carry no notification_type.
|
|
64
|
+
if (input.hook_event_name === 'Notification' && typeof input.notification_type !== 'string'
|
|
65
|
+
&& typeof input.message === 'string' && /permission/i.test(input.message)) {
|
|
66
|
+
payload.permissionHint = true;
|
|
67
|
+
}
|
|
68
|
+
const body = Buffer.from(JSON.stringify(payload));
|
|
69
|
+
const req = http.request({
|
|
70
|
+
host: '127.0.0.1',
|
|
71
|
+
port,
|
|
72
|
+
method: 'POST',
|
|
73
|
+
path: '/terminal-agent-hook',
|
|
74
|
+
timeout: 2000,
|
|
75
|
+
headers: {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
'Content-Length': body.length,
|
|
78
|
+
...(controlToken ? { Authorization: `Bearer ${controlToken}` } : {}),
|
|
79
|
+
},
|
|
80
|
+
}, (res) => {
|
|
81
|
+
res.resume();
|
|
82
|
+
res.on('end', () => process.exit(0));
|
|
83
|
+
});
|
|
84
|
+
req.on('timeout', () => req.destroy());
|
|
85
|
+
req.on('error', () => process.exit(0));
|
|
86
|
+
req.end(body);
|
|
87
|
+
});
|
|
88
|
+
process.stdin.on('error', () => process.exit(0));
|
|
89
|
+
process.stdin.resume();
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const DEFAULT_CLAUDE_PERMISSION_MODE = "default";
|
|
4
|
-
const DEFAULT_CODEX_PERMISSION_MODE = "default";
|
|
5
|
-
|
|
6
|
-
exports.DEFAULT_CLAUDE_PERMISSION_MODE = DEFAULT_CLAUDE_PERMISSION_MODE;
|
|
7
|
-
exports.DEFAULT_CODEX_PERMISSION_MODE = DEFAULT_CODEX_PERMISSION_MODE;
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
function summarizeSpawnSessionForLog(value) {
|
|
2
|
-
const input = value && typeof value === "object" ? value : {};
|
|
3
|
-
const environmentVariables = input.environmentVariables && typeof input.environmentVariables === "object" ? input.environmentVariables : {};
|
|
4
|
-
return {
|
|
5
|
-
...typeof input.agent === "string" ? { agent: input.agent } : {},
|
|
6
|
-
...typeof input.variant === "string" ? { variant: input.variant } : {},
|
|
7
|
-
...typeof input.sessionId === "string" ? { sessionId: input.sessionId } : {},
|
|
8
|
-
hasDirectory: typeof input.directory === "string" && input.directory.length > 0,
|
|
9
|
-
hasToken: typeof input.token === "string" && input.token.length > 0,
|
|
10
|
-
environmentVariableNames: Object.keys(environmentVariables).sort(),
|
|
11
|
-
resumesClaude: typeof input.resumeClaudeSessionId === "string" && input.resumeClaudeSessionId.length > 0,
|
|
12
|
-
resumesCodex: typeof input.resumeCodexThreadId === "string" && input.resumeCodexThreadId.length > 0,
|
|
13
|
-
importsClaude: typeof input.importedFromClaudeSessionId === "string" && input.importedFromClaudeSessionId.length > 0,
|
|
14
|
-
forceNew: input.forceNew === true,
|
|
15
|
-
...typeof input.permissionMode === "string" ? { permissionMode: input.permissionMode } : {}
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function sanitizeGeometry(cols, rows) {
|
|
20
|
-
const ok = (v) => typeof v === "number" && Number.isInteger(v) && v >= 2 && v <= 1e4;
|
|
21
|
-
return ok(cols) && ok(rows) ? { cols, rows } : void 0;
|
|
22
|
-
}
|
|
23
|
-
function sanitizeTagList(value) {
|
|
24
|
-
if (!Array.isArray(value)) return void 0;
|
|
25
|
-
const out = [];
|
|
26
|
-
for (const tag of value) {
|
|
27
|
-
if (typeof tag !== "string") continue;
|
|
28
|
-
const clean = tag.trim();
|
|
29
|
-
if (clean && !out.includes(clean)) out.push(clean);
|
|
30
|
-
if (out.length >= 64) break;
|
|
31
|
-
}
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
34
|
-
const LIVE_SNAPSHOT_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
35
|
-
const LIVE_SNAPSHOT_MAX = 100;
|
|
36
|
-
function sanitizeLiveSnapshot(raw, now, ttlMs = LIVE_SNAPSHOT_TTL_MS, max = LIVE_SNAPSHOT_MAX) {
|
|
37
|
-
const out = /* @__PURE__ */ new Map();
|
|
38
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return out;
|
|
39
|
-
const rows = [];
|
|
40
|
-
for (const [id, value] of Object.entries(raw)) {
|
|
41
|
-
if (!id || !value || typeof value !== "object") continue;
|
|
42
|
-
const { title, cwd, seenAt, tags, manual, attachTmux, cols: rawCols, rows: rawRows } = value;
|
|
43
|
-
if (typeof seenAt !== "number" || !Number.isFinite(seenAt)) continue;
|
|
44
|
-
if (now - seenAt >= ttlMs) continue;
|
|
45
|
-
const tagList = sanitizeTagList(tags);
|
|
46
|
-
rows.push([id, {
|
|
47
|
-
title: typeof title === "string" && title.trim() ? title : void 0,
|
|
48
|
-
cwd: typeof cwd === "string" && cwd ? cwd : void 0,
|
|
49
|
-
...tagList !== void 0 ? { tags: tagList } : {},
|
|
50
|
-
...manual === true ? { manual: true } : {},
|
|
51
|
-
...typeof attachTmux === "string" && attachTmux ? { attachTmux } : {},
|
|
52
|
-
...sanitizeGeometry(rawCols, rawRows) ?? {},
|
|
53
|
-
seenAt
|
|
54
|
-
}]);
|
|
55
|
-
}
|
|
56
|
-
rows.sort((a, b) => b[1].seenAt - a[1].seenAt);
|
|
57
|
-
for (const [id, info] of rows.slice(0, max)) out.set(id, info);
|
|
58
|
-
return out;
|
|
59
|
-
}
|
|
60
|
-
function serializeLiveSnapshot(map, max = LIVE_SNAPSHOT_MAX) {
|
|
61
|
-
const rows = [...map.entries()].sort((a, b) => b[1].seenAt - a[1].seenAt).slice(0, max);
|
|
62
|
-
const out = {};
|
|
63
|
-
for (const [id, info] of rows) out[id] = info;
|
|
64
|
-
return out;
|
|
65
|
-
}
|
|
66
|
-
function liveSnapshotChanged(prev, next) {
|
|
67
|
-
if (prev.size !== next.size) return true;
|
|
68
|
-
for (const [id, info] of next) {
|
|
69
|
-
const before = prev.get(id);
|
|
70
|
-
if (!before) return true;
|
|
71
|
-
if (before.title !== info.title || before.cwd !== info.cwd) return true;
|
|
72
|
-
if (!!before.manual !== !!info.manual) return true;
|
|
73
|
-
if ((before.attachTmux ?? "") !== (info.attachTmux ?? "")) return true;
|
|
74
|
-
if ((before.tags ?? []).join("\0") !== (info.tags ?? []).join("\0")) return true;
|
|
75
|
-
if (before.cols !== info.cols || before.rows !== info.rows) return true;
|
|
76
|
-
}
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
const CLAUDE_SESSION_ID_RE = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
80
|
-
function isClaudeSessionId(value) {
|
|
81
|
-
return typeof value === "string" && CLAUDE_SESSION_ID_RE.test(value);
|
|
82
|
-
}
|
|
83
|
-
function pickMirrorForTerminal(sessions, terminalId) {
|
|
84
|
-
if (!terminalId) return null;
|
|
85
|
-
let best = null;
|
|
86
|
-
for (const [id, session] of Object.entries(sessions || {})) {
|
|
87
|
-
const meta = session?.metadata;
|
|
88
|
-
if (!meta || meta.terminalId !== terminalId) continue;
|
|
89
|
-
const savedAt = typeof session.savedAt === "number" ? session.savedAt : 0;
|
|
90
|
-
if (best && savedAt <= best.savedAt) continue;
|
|
91
|
-
best = {
|
|
92
|
-
id,
|
|
93
|
-
savedAt,
|
|
94
|
-
claude: isClaudeSessionId(meta.claudeSessionId) ? meta.claudeSessionId : void 0
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return best ? { sessionId: best.id, claudeSessionId: best.claude } : null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function parseTerminalHookPayload(body) {
|
|
101
|
-
if (!body || typeof body !== "object") return null;
|
|
102
|
-
const raw = body;
|
|
103
|
-
const eventName = raw.hook_event_name;
|
|
104
|
-
if (eventName !== "SessionStart" && eventName !== "SessionEnd") return null;
|
|
105
|
-
const claudeSessionId = typeof raw.session_id === "string" && raw.session_id.length > 0 ? raw.session_id : typeof raw.sessionId === "string" && raw.sessionId.length > 0 ? raw.sessionId : null;
|
|
106
|
-
if (!claudeSessionId) return null;
|
|
107
|
-
const terminalId = typeof raw.terminalId === "string" && raw.terminalId.length > 0 ? raw.terminalId : null;
|
|
108
|
-
if (!terminalId) return null;
|
|
109
|
-
return {
|
|
110
|
-
event: eventName,
|
|
111
|
-
claudeSessionId,
|
|
112
|
-
terminalId,
|
|
113
|
-
transcriptPath: typeof raw.transcript_path === "string" && raw.transcript_path.length > 0 ? raw.transcript_path : void 0,
|
|
114
|
-
cwd: typeof raw.cwd === "string" && raw.cwd.length > 0 ? raw.cwd : void 0,
|
|
115
|
-
source: typeof raw.source === "string" && raw.source.length > 0 ? raw.source : void 0
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const FRESH_CONVERSATION_SOURCES = /* @__PURE__ */ new Set(["startup", "clear"]);
|
|
119
|
-
function decideMirrorBinding(event, binding) {
|
|
120
|
-
if (event.event === "SessionEnd") {
|
|
121
|
-
if (!binding) return { action: "ignore", reason: "no binding for terminal" };
|
|
122
|
-
if (binding.claudeSessionId !== event.claudeSessionId) {
|
|
123
|
-
return { action: "ignore", reason: "stale SessionEnd for a superseded claude session" };
|
|
124
|
-
}
|
|
125
|
-
if (binding.status === "ended") return { action: "ignore", reason: "already ended" };
|
|
126
|
-
return { action: "end" };
|
|
127
|
-
}
|
|
128
|
-
if (!binding) return { action: "create" };
|
|
129
|
-
if (binding.status === "active" && binding.claudeSessionId === event.claudeSessionId) {
|
|
130
|
-
return { action: "ignore", reason: "duplicate SessionStart for the bound session" };
|
|
131
|
-
}
|
|
132
|
-
if (FRESH_CONVERSATION_SOURCES.has(event.source ?? "startup")) {
|
|
133
|
-
return { action: "create", replaces: binding };
|
|
134
|
-
}
|
|
135
|
-
return { action: "continue" };
|
|
136
|
-
}
|
|
137
|
-
function mirrorLineKey(message) {
|
|
138
|
-
if (message.type === "summary") return `summary-${message.leafUuid}`;
|
|
139
|
-
if (message.type === "user" || message.type === "assistant" || message.type === "system") {
|
|
140
|
-
return message.uuid;
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
function mirrorLocalId(lineKey, envelopeIndex) {
|
|
145
|
-
return `mirror:${lineKey}:${envelopeIndex}`;
|
|
146
|
-
}
|
|
147
|
-
function extractCompleteLines(buf) {
|
|
148
|
-
const lastNl = buf.lastIndexOf(10);
|
|
149
|
-
if (lastNl === -1) return { lines: [], consumedBytes: 0 };
|
|
150
|
-
const text = buf.subarray(0, lastNl).toString("utf-8");
|
|
151
|
-
const lines = text.split("\n").filter((l) => l.trim().length > 0);
|
|
152
|
-
return { lines, consumedBytes: lastNl + 1 };
|
|
153
|
-
}
|
|
154
|
-
const MIRROR_SEND_MAX_CHARS = 16384;
|
|
155
|
-
function parseMirrorSendParams(params, isValidTerminalId) {
|
|
156
|
-
if (!params || typeof params !== "object") return { error: "invalid params" };
|
|
157
|
-
const { terminalId, text, submit } = params;
|
|
158
|
-
if (!isValidTerminalId(terminalId)) return { error: "invalid terminalId" };
|
|
159
|
-
if (typeof text !== "string" || text.length === 0) return { error: "text is required" };
|
|
160
|
-
if (text.length > MIRROR_SEND_MAX_CHARS) return { error: `text too long (max ${MIRROR_SEND_MAX_CHARS} chars)` };
|
|
161
|
-
return { terminalId, text, submit: submit !== false };
|
|
162
|
-
}
|
|
163
|
-
const MIRROR_BACKFILL_LINES_DEFAULT = 500;
|
|
164
|
-
function decideBackfill(messages, maxLines) {
|
|
165
|
-
const cap = Math.max(0, Math.floor(maxLines));
|
|
166
|
-
if (messages.length <= cap) return { replay: messages, truncated: false };
|
|
167
|
-
return { replay: messages.slice(messages.length - cap), truncated: true };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export { MIRROR_BACKFILL_LINES_DEFAULT as M, sanitizeLiveSnapshot as a, serializeLiveSnapshot as b, summarizeSpawnSessionForLog as c, parseMirrorSendParams as d, extractCompleteLines as e, decideBackfill as f, parseTerminalHookPayload as g, decideMirrorBinding as h, isClaudeSessionId as i, mirrorLocalId as j, liveSnapshotChanged as l, mirrorLineKey as m, pickMirrorForTerminal as p, sanitizeTagList as s };
|