very-happy-cli 0.2.166 → 0.2.168
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/dist/{AcpBackend-tRWk7yi7.mjs → AcpBackend-BoLDLYNT.mjs} +3 -3
- package/dist/{AcpBackend-20VHOXwb.cjs → AcpBackend-r83MMm-i.cjs} +3 -3
- package/dist/{BasePermissionHandler-COKc4pmt.cjs → BasePermissionHandler-CS0eRtT-.cjs} +1 -1
- package/dist/{BasePermissionHandler-CDCLIrZJ.mjs → BasePermissionHandler-DTcVlmKi.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-BDVKvooR.mjs → BaseReasoningProcessor-BddnNlXQ.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-DAGQdkNp.cjs → BaseReasoningProcessor-RJiBhA8h.cjs} +1 -1
- package/dist/{agentHome-2IbIjKCa.mjs → agentHome--LRsdUx6.mjs} +4 -4
- package/dist/{agentHome-KVWj6nCl.cjs → agentHome-D-e_j9hK.cjs} +4 -4
- package/dist/{api-DnNL5fLw.cjs → api-COSJ3Yb7.cjs} +88 -10
- package/dist/{api-Cmz3XS4P.mjs → api-hXLwtgMi.mjs} +88 -10
- package/dist/{apiMachine-DeoQ8QbZ.cjs → apiMachine-BTCUUGC6.cjs} +50 -15
- package/dist/{apiMachine-B6ySCFe0.mjs → apiMachine-BauSXWNd.mjs} +50 -15
- package/dist/{attachmentContent-DPWxHgX4.cjs → attachmentContent-BCK0AxDS.cjs} +2 -2
- package/dist/{attachmentContent-CTXapi-_.mjs → attachmentContent-CS0B2N0Q.mjs} +2 -2
- package/dist/{attachmentLimits-BfgKV5iE.cjs → attachmentLimits-BEYEEBm8.cjs} +13 -1
- package/dist/{attachmentLimits-C1PCCM79.mjs → attachmentLimits-CxG3T18E.mjs} +13 -1
- package/dist/{auth-pzWIFdOD.mjs → auth-BFeFguVs.mjs} +5 -5
- package/dist/{auth-BMaBjRAj.mjs → auth-BUXH1L2k.mjs} +10 -10
- package/dist/{auth-D4-eQz85.cjs → auth-CCj5KlYS.cjs} +10 -10
- package/dist/{auth-ietHtvwu.cjs → auth-CfB2XcAW.cjs} +5 -5
- package/dist/{auto-DL75Dx3I.mjs → auto-D5BYdAoT.mjs} +14 -14
- package/dist/{auto-DOWTQDPa.cjs → auto-ZCHKb4jo.cjs} +14 -14
- package/dist/{bootstrap-BpXIc2wn.cjs → bootstrap-DSX64t23.cjs} +2 -2
- package/dist/{bootstrap-XE8A7Ut2.mjs → bootstrap-DklT121U.mjs} +2 -2
- package/dist/{browser-CcG8GLRV.cjs → browser-CeekQeKt.cjs} +1 -1
- package/dist/{browser-DDFi1T8C.mjs → browser-DUf1dth8.mjs} +1 -1
- package/dist/{claudeLocal-DmM5Oyhv.mjs → claudeLocal-C8pXtb8q.mjs} +5 -5
- package/dist/{claudeLocal-DXBXwIOG.cjs → claudeLocal-hH0YYex3.cjs} +5 -5
- package/dist/{claudeLocalLauncher-Cs4eUC3P.mjs → claudeLocalLauncher-AtUe2tM-.mjs} +10 -10
- package/dist/{claudeLocalLauncher-C41Y6Kp4.cjs → claudeLocalLauncher-B-ta13pT.cjs} +10 -10
- package/dist/{claudeSessionFork-BdLnc2Hv.mjs → claudeSessionFork-BQPBKEHk.mjs} +1 -1
- package/dist/{claudeSessionFork-Cs0I3eGI.cjs → claudeSessionFork-Cq9FBfjD.cjs} +1 -1
- package/dist/{client-CbK33y_s.mjs → client-Bg6-mQKO.mjs} +3 -3
- package/dist/{client-GjTnsq6F.mjs → client-Cbl3ejoq.mjs} +2 -2
- package/dist/{client-JISJx2f-.cjs → client-DZpkmS5l.cjs} +3 -3
- package/dist/{client-DJ0kX_8M.cjs → client-EnFomCjx.cjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +14 -14
- package/dist/codex/happyMcpStdioBridge.mjs +14 -14
- package/dist/{codexAppServerClient-BTjn2ZCZ.cjs → codexAppServerClient-pllsN90-.cjs} +4 -4
- package/dist/{codexAppServerClient-CldXEojt.mjs → codexAppServerClient-sWuwtddZ.mjs} +4 -4
- package/dist/{codexCommand-DjMU-Ijf.mjs → codexCommand-DbTkMlW4.mjs} +137 -56
- package/dist/{codexCommand-BpD0N1F7.cjs → codexCommand-_jkx59gI.cjs} +137 -56
- package/dist/{config-DuLL0Ppe.cjs → config-BuIIZPZK.cjs} +3 -3
- package/dist/{config-DjSJKatx.mjs → config-FCOoREKj.mjs} +3 -3
- package/dist/{configuration-D2v3puap.mjs → configuration-BZo1JWNV.mjs} +2 -2
- package/dist/{configuration-B0cb3xA3.cjs → configuration-DeuGrnej.cjs} +1 -1
- package/dist/{connect-CnNNyM9I.mjs → connect-C2yHh85e.mjs} +13 -13
- package/dist/{connect-B7JWEzyg.cjs → connect-CjDdF12U.cjs} +13 -13
- package/dist/{context-BFUpYT39.cjs → context-BhvZtm3j.cjs} +1 -1
- package/dist/{context-DjfqLWzE.mjs → context-DZIIcfld.mjs} +1 -1
- package/dist/{controlClient-BMUJfUeF.mjs → controlClient-CXD-Xdny.mjs} +18 -4
- package/dist/{controlClient-CmnHGcyl.cjs → controlClient-IDE3se23.cjs} +18 -3
- package/dist/{createSessionMetadata-DbfRBhRu.cjs → createSessionMetadata-BCHFLSLk.cjs} +56 -3
- package/dist/{createSessionMetadata-DU0bCg2m.mjs → createSessionMetadata-DoLFya-Q.mjs} +57 -5
- package/dist/defaultPermissionMode-BtZtLdQz.cjs +197 -0
- package/dist/defaultPermissionMode-Dxfv-5Ud.mjs +191 -0
- package/dist/{deterministicJson-Dp3TVyap.cjs → deterministicJson-BqQKrUzw.cjs} +8 -8
- package/dist/{deterministicJson-D-WPUrZb.mjs → deterministicJson-CF1fJMaM.mjs} +8 -8
- package/dist/{doctor-BlXXyQ1L.mjs → doctor-C98yYhYr.mjs} +6 -6
- package/dist/{doctor-CkJmdPbi.cjs → doctor-D61ncaeL.cjs} +6 -6
- package/dist/{downloadTarget-DjSwMHun.mjs → downloadTarget-CaISZbNy.mjs} +6 -6
- package/dist/{downloadTarget-CiQqRIc-.cjs → downloadTarget-Dist9t2e.cjs} +6 -6
- package/dist/{ensureDaemonRunning-C_aIOhgG.cjs → ensureDaemonRunning-BB0hnWY_.cjs} +5 -5
- package/dist/{ensureDaemonRunning-CAQag1zE.mjs → ensureDaemonRunning-CNiqOarI.mjs} +5 -5
- package/dist/{handleResumeCommand-Ci7wacT-.mjs → handleResumeCommand-BzcANj0i.mjs} +5 -5
- package/dist/{handleResumeCommand-6KzBGDnl.cjs → handleResumeCommand-CkzW-T_f.cjs} +5 -5
- package/dist/{index-DEKIgZUo.cjs → index-BQU1sS9K.cjs} +4 -4
- package/dist/{index-DBmNwMX9.cjs → index-BeeWN9Et.cjs} +33 -33
- package/dist/{index-WGCT6SSV.mjs → index-CdmIOFwG.mjs} +34 -34
- package/dist/{index-HQsigW_J.mjs → index-D2hg_u5i.mjs} +3 -3
- package/dist/{index-DQplgo0W.mjs → index-Dgqk3lfG.mjs} +4 -4
- package/dist/{index-CaFCAlX8.cjs → index-DipBfs9w.cjs} +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-oJUvsFu9.mjs → install-CK1FvmYQ.mjs} +3 -3
- package/dist/{install-CejEiRGW.cjs → install-VtuffPLu.cjs} +3 -3
- package/dist/lib.cjs +11 -11
- package/dist/lib.d.cts +61 -0
- package/dist/lib.d.mts +61 -0
- package/dist/lib.mjs +11 -11
- package/dist/{lidState-D8BmnJV1.cjs → lidState-2IT0tas7.cjs} +1 -1
- package/dist/{lidState-BfximpjX.mjs → lidState-CJ3XkJRn.mjs} +1 -1
- package/dist/{localHappyAgentAuth-d7B6S_o7.cjs → localHappyAgentAuth-CPMh61Su.cjs} +1 -1
- package/dist/{localHappyAgentAuth-Ct1aXwqd.mjs → localHappyAgentAuth-DkLbntlf.mjs} +1 -1
- package/dist/{logger-BpQcwNnt.mjs → logger-C6zzu57a.mjs} +2 -2
- package/dist/{logger-JTcJU-uL.cjs → logger-Ockf1cjN.cjs} +2 -2
- package/dist/{machineMetadata-BBg_Njw3.cjs → machineMetadata-CoMYwSlG.cjs} +4 -3
- package/dist/{machineMetadata-CBdxABeI.mjs → machineMetadata-DmTGIZAV.mjs} +4 -3
- package/dist/{main-B5b1gA3K.mjs → main-B8TX9xPq.mjs} +45 -45
- package/dist/{main-C16fOGgn.cjs → main-CThJ9JQb.cjs} +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-BnNiBBax.cjs → mcp-Dwku1p2I.cjs} +14 -14
- package/dist/{mcp-DGNWgVdv.mjs → mcp-Yw93dOiW.mjs} +14 -14
- package/dist/mirrorProtocol-CQ5fAUgq.mjs +1247 -0
- package/dist/mirrorProtocol-CdPhEBSh.cjs +1270 -0
- package/dist/{package-BqwrPxL0.mjs → package-5xAdq5fu.mjs} +7 -7
- package/dist/{package-C1XvUQFy.cjs → package-DfoyJe1O.cjs} +7 -7
- package/dist/{peerTools-DPvbcs8V.cjs → peerTools-BEnBvEcU.cjs} +4 -4
- package/dist/{peerTools-CeCe-3lk.mjs → peerTools-uDR6MG0-.mjs} +4 -4
- package/dist/{persistence-2Xp_o6x6.cjs → persistence-B5oT6oQ9.cjs} +147 -25
- package/dist/{persistence-B9LmhAE2.mjs → persistence-B6M_W5iC.mjs} +123 -12
- package/dist/{piRunnerArgs-DI29dDNo.cjs → piRunnerArgs-MLN46-nK.cjs} +1 -1
- package/dist/{piRunnerArgs-7FaTyNOq.mjs → piRunnerArgs-vNIUWHqo.mjs} +1 -1
- package/dist/{piRuntime-R8XVChxK.cjs → piRuntime-DkUg8_5q.cjs} +1 -1
- package/dist/{piRuntime-0qEK5AqE.mjs → piRuntime-WMuI7f4q.mjs} +1 -1
- package/dist/{piTerminal-zcQKc8Sp.mjs → piTerminal-4NBSZVxd.mjs} +16 -16
- package/dist/{piTerminal-Ccj0KNPr.cjs → piTerminal-Bskvs69Z.cjs} +16 -16
- package/dist/{rateLimitWindows-C2Jk3Ih7.cjs → rateLimitWindows-C2-Ky86q.cjs} +1 -1
- package/dist/{rateLimitWindows-Dhfhbtqu.mjs → rateLimitWindows-CJ1xDAxa.mjs} +1 -1
- package/dist/{registerCommonHandlers-DdfGsFbM.mjs → registerCommonHandlers-BLHKlk5Z.mjs} +2 -2
- package/dist/{registerCommonHandlers-Aha_KfM3.cjs → registerCommonHandlers-COSTo15G.cjs} +2 -2
- package/dist/{registerKillSessionHandler-DboQlGcH.mjs → registerKillSessionHandler-BVQfhSgm.mjs} +14 -9
- package/dist/{registerKillSessionHandler-CjitOpUA.cjs → registerKillSessionHandler-DDZISNzu.cjs} +14 -9
- package/dist/{remoteSessionClient-BwI8rpQw.cjs → remoteSessionClient-B2pOMZRw.cjs} +5 -5
- package/dist/{remoteSessionClient-B2DtWuNP.mjs → remoteSessionClient-Dx0M2MXV.mjs} +5 -5
- package/dist/{reportProgressTool-B-Rcy0s3.cjs → reportProgressTool-C5vDEv9Y.cjs} +1 -1
- package/dist/{reportProgressTool-DnAD8wOa.mjs → reportProgressTool-CcwFr0ek.mjs} +1 -1
- package/dist/{run-Bh66Xs40.cjs → run-BKTv1E-D.cjs} +323 -37
- package/dist/{run-DPEwJpQR.mjs → run-BZjIDOGM.mjs} +322 -36
- package/dist/{runClaude-DLr_nBzw.mjs → runClaude-DFa77Ffl.mjs} +87 -25
- package/dist/{runClaude-C-lJdAKD.cjs → runClaude-DUlFZWiK.cjs} +87 -25
- package/dist/{runClaudeDeps-vWWLod7J.cjs → runClaudeDeps--TnER0c3.cjs} +100 -31
- package/dist/{runClaudeDeps-C7JV7nXG.mjs → runClaudeDeps-BYohagQU.mjs} +105 -36
- package/dist/{runGemini-o-CUSayc.cjs → runGemini-BSBejXek.cjs} +32 -32
- package/dist/{runGemini-tH6sLw-G.mjs → runGemini-CUiq1Zei.mjs} +32 -32
- package/dist/{runOpenClaw-C5DZvVhn.mjs → runOpenClaw-CgwRP4gR.mjs} +16 -16
- package/dist/{runOpenClaw-D24f35l0.cjs → runOpenClaw-DQFEi3E1.cjs} +16 -16
- package/dist/{sandbox-BaL1aslA.mjs → sandbox-BTwAN7Yi.mjs} +4 -4
- package/dist/{sandbox-TJZJ6ngw.cjs → sandbox-DuLRfMY3.cjs} +4 -4
- package/dist/selfCheck-DF26lf1b.mjs +84 -0
- package/dist/{selfCheck-Dugi0Nk_.cjs → selfCheck-DuOLndWl.cjs} +34 -34
- package/dist/{send-DDcJ3ayi.mjs → send-ComZSvT5.mjs} +8 -8
- package/dist/{send-CkWOSYmU.cjs → send-Dl4TJ0Ia.cjs} +8 -8
- package/dist/{server-7qFQ8J2u.cjs → server-CWmamKcS.cjs} +6 -6
- package/dist/{server-CUjRvQSd.mjs → server-CXFSsyZx.mjs} +4 -4
- package/dist/{sessionLock-DfhNICyS.cjs → sessionLock-BFD8cFNP.cjs} +12 -3
- package/dist/{sessionLock-DqVyHFAQ.mjs → sessionLock-DCKf-gjd.mjs} +12 -4
- package/dist/{sessionModeFile-M4OpiyrF.mjs → sessionModeFile-BYxsFSvc.mjs} +1 -1
- package/dist/{sessionModeFile-CIznKD7O.cjs → sessionModeFile-i-MVQRcU.cjs} +1 -1
- package/dist/{sessionOps-DOyy4gkY.cjs → sessionOps-BAQ_80Rg.cjs} +4 -4
- package/dist/{sessionOps-BnaEaOKs.mjs → sessionOps-CBXsQGV5.mjs} +4 -4
- package/dist/{sessionScanner-CcuOn9uU.mjs → sessionScanner-CwPBvQK2.mjs} +3 -3
- package/dist/{sessionScanner-Cu1yKlj4.cjs → sessionScanner-Dth3iDCi.cjs} +3 -3
- package/dist/{sessions-BQgk5Kw8.cjs → sessions-BULd_RQt.cjs} +9 -9
- package/dist/{sessions-C9O91rL1.mjs → sessions-DYAqiUS0.mjs} +9 -9
- package/dist/{setupOfflineReconnection-Byy8aeKT.mjs → setupOfflineReconnection-Bo9xb30l.mjs} +2 -2
- package/dist/{setupOfflineReconnection-DFmQ8s6I.cjs → setupOfflineReconnection-DI8BQf_g.cjs} +2 -2
- package/dist/{spawn-EZ2yrtWd.mjs → spawn-DmXpKIOT.mjs} +13 -13
- package/dist/{spawn-BS7LPmSm.cjs → spawn-oikb5mUh.cjs} +13 -13
- package/dist/{spawnHappyCLI-BAa49m0q.mjs → spawnHappyCLI-BCnZfffk.mjs} +1 -1
- package/dist/{spawnHappyCLI-DyaldIe5.cjs → spawnHappyCLI-Cs177BB4.cjs} +1 -1
- package/dist/{specialCommands-DouFaJ_0.cjs → specialCommands-CmrwEh71.cjs} +3 -3
- package/dist/{specialCommands-CCWtwIGZ.mjs → specialCommands-xD4uOtdG.mjs} +3 -3
- package/dist/{startFileWatcher-Dfs4whzr.mjs → startFileWatcher-De7rN8QW.mjs} +1 -1
- package/dist/{startFileWatcher-DQbbypJv.cjs → startFileWatcher-S_Af_QPR.cjs} +1 -1
- package/dist/{sync-x_lI_3j_.cjs → sync-BS9_zSQ2.cjs} +1 -1
- package/dist/{sync-BLpH13Kb.mjs → sync-CHOB3Org.mjs} +1 -1
- package/dist/{systemPrompt-4erwILTB.cjs → systemPrompt-D2ICcIsu.cjs} +1 -1
- package/dist/{systemPrompt-BanyDihy.mjs → systemPrompt-DNLUUejs.mjs} +1 -1
- package/dist/{teams-DzetlGWC.cjs → teams-BUbESH6L.cjs} +6 -6
- package/dist/{teams-D6BOT3lR.mjs → teams-By3oBC7r.mjs} +6 -6
- package/dist/{time-CfDKj6Bx.mjs → time-CN0jVVir.mjs} +1 -1
- package/dist/{time-T0YmeOhS.cjs → time-uSKpEhew.cjs} +1 -1
- package/dist/{titleGenerator-CoMxqKfP.cjs → titleGenerator-CLIXjn9b.cjs} +2 -2
- package/dist/{titleGenerator-ChImQ4q-.mjs → titleGenerator-CegRJ47n.mjs} +1 -1
- package/dist/{todo-CZZebKZg.cjs → todo-Bg1vurv9.cjs} +5 -5
- package/dist/{todo-SVtYxGON.mjs → todo-Bl3abqvy.mjs} +5 -5
- package/dist/{tools-3X2z3YDe.mjs → tools-BcLUrC57.mjs} +1 -1
- package/dist/{tools-IJ0TAcJs.cjs → tools-DuWKlc0k.cjs} +1 -1
- package/dist/{uninstall-CypD-kr1.mjs → uninstall-BlpZlM9U.mjs} +3 -3
- package/dist/{uninstall-CqqCWj7w.cjs → uninstall-DWnj2XVT.cjs} +3 -3
- package/package.json +7 -7
- package/dist/defaultPermissionMode-BnxJPVHT.mjs +0 -4
- package/dist/defaultPermissionMode-CxmTXUQR.cjs +0 -7
- package/dist/mirrorProtocol-BEGk2--0.cjs +0 -266
- package/dist/mirrorProtocol-h5WHpdhh.mjs +0 -248
- package/dist/selfCheck-DPi4lqme.mjs +0 -84
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { i as isClaudeSessionId,
|
|
2
|
-
import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel, d as detectDaemonSupervisor } from './piRunnerArgs-
|
|
1
|
+
import { i as isClaudeSessionId, g as extractCompleteLines, h as decideBackfill, j as parseTerminalHookPayload, k as decideMirrorBinding, M as MIRROR_BACKFILL_LINES_DEFAULT, m as mirrorLineKey, n as mirrorLocalId, o as initializeOwnedWorktree, e as summarizeSpawnSessionForLog, q as startAgentVersionChecks, W as WORKTREE_CAPABILITY_VERSION, t as currentWorktreeService } from './mirrorProtocol-CQ5fAUgq.mjs';
|
|
2
|
+
import { P as PI_ADAPTER_INSTALL_HINT, s as sanitizeSpawnModel, d as detectDaemonSupervisor } from './piRunnerArgs-vNIUWHqo.mjs';
|
|
3
3
|
import fs from 'fs/promises';
|
|
4
4
|
import * as tmp from 'tmp';
|
|
5
5
|
import axios from 'axios';
|
|
6
|
-
import { T as TurnActivityTracker, A as ApiClient } from './api-
|
|
6
|
+
import { T as TurnActivityTracker, A as ApiClient } from './api-hXLwtgMi.mjs';
|
|
7
7
|
import { S as SPAWN_AGENTS, i as isSpawnAgent, s as sanitizeSpawnPermissionMode, r as resolveSpawnPermissionMode, a as resolveFirstMessageMeta } from './spawnAgents-HDaE3C0-.mjs';
|
|
8
|
-
import { l as logger } from './logger-
|
|
8
|
+
import { l as logger } from './logger-C6zzu57a.mjs';
|
|
9
9
|
import { readdirSync, statSync, unlinkSync, realpathSync, mkdirSync, writeFileSync, accessSync, constants as constants$1, existsSync, readFileSync, openSync, fsyncSync, closeSync, renameSync } from 'node:fs';
|
|
10
10
|
import { join, isAbsolute, resolve, dirname, sep, basename, delimiter } from 'node:path';
|
|
11
|
-
import { p as pruneStaleCompileCaches } from './index-
|
|
12
|
-
import { a as authAndSetupMachineIfNeeded } from './auth-
|
|
13
|
-
import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-
|
|
11
|
+
import { p as pruneStaleCompileCaches } from './index-D2hg_u5i.mjs';
|
|
12
|
+
import { a as authAndSetupMachineIfNeeded } from './auth-BFeFguVs.mjs';
|
|
13
|
+
import { c as configuration, f as ensurePrivateDirectorySync, w as writePrivateFileSync } from './configuration-BZo1JWNV.mjs';
|
|
14
14
|
import { spawn, execSync } from 'child_process';
|
|
15
|
-
import { p as packageJson } from './package-
|
|
16
|
-
import { a as globalPrefixForPackage, g as getEnvironmentInfo } from './doctor-
|
|
17
|
-
import { s as spawnHappyCLI } from './spawnHappyCLI-
|
|
18
|
-
import { readPersistedSessions, readSettings, persistSession, readDaemonState, acquireDaemonLock, deletePersistedSessions, writeDaemonState, writeSettings, releaseDaemonLock } from './persistence-
|
|
19
|
-
import { i as isDaemonRunningCurrentlyInstalledHappyVersion,
|
|
20
|
-
import { e as sendUserMessage, f as readSessionMetadata, r as readSessionTranscript, l as listAccountSessions, a as listSessions, M as MAX_READ_LIMIT, s as sessionWebUrl, g as waitForSessionKey, d as archiveSession, j as analyzeLatestTurn, k as readSessionLog, m as TURN_WINDOW, n as userPromptText } from './sessionOps-
|
|
15
|
+
import { p as packageJson } from './package-5xAdq5fu.mjs';
|
|
16
|
+
import { a as globalPrefixForPackage, g as getEnvironmentInfo } from './doctor-C98yYhYr.mjs';
|
|
17
|
+
import { s as spawnHappyCLI } from './spawnHappyCLI-BCnZfffk.mjs';
|
|
18
|
+
import { b as readPersistedSessions, r as readSettings, l as latchKeepAwake, q as reportSignature, s as decideDaemonHibernation, t as nextCheckDelay, v as persistSession, d as readDaemonState, x as acquireDaemonLock, a as resolveCheckMs, y as resolveIdleMs, z as deletePersistedSessions, A as writeDaemonState, B as writeSettings, C as settingIdleMs, u as updateSettings, D as releaseDaemonLock } from './persistence-B6M_W5iC.mjs';
|
|
19
|
+
import { i as isDaemonRunningCurrentlyInstalledHappyVersion, b as stopDaemon, t as cleanupDaemonState } from './controlClient-CXD-Xdny.mjs';
|
|
20
|
+
import { e as sendUserMessage, f as readSessionMetadata, r as readSessionTranscript, l as listAccountSessions, a as listSessions, M as MAX_READ_LIMIT, s as sessionWebUrl, g as waitForSessionKey, d as archiveSession, j as analyzeLatestTurn, k as readSessionLog, m as TURN_WINDOW, n as userPromptText } from './sessionOps-CBXsQGV5.mjs';
|
|
21
21
|
import fastify from 'fastify';
|
|
22
22
|
import { z } from 'zod';
|
|
23
23
|
import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
|
|
@@ -25,45 +25,45 @@ import { d as decodeBase64, e as encodeBase64, h as decrypt } from './authRelay-
|
|
|
25
25
|
import { randomBytes, createHash, timingSafeEqual, randomUUID } from 'node:crypto';
|
|
26
26
|
import { c as checkPreviewPath } from './previewPath-CXN4Vag0.mjs';
|
|
27
27
|
import { a as BACKGROUND_TASKS_MAX, d as BACKGROUND_TASK_DESCRIPTION_MAX, e as BackgroundTaskTracker } from './backgroundTaskActivity-8PdPxrvy.mjs';
|
|
28
|
-
import { b as sanitizeRateLimitReport } from './rateLimitWindows-
|
|
29
|
-
import { f as formatEditConflictNotice, b as SESSION_PEER_SENT_FROM, s as sendPeerMessage, l as listPeerSessions, C as CLI_PEER_SENDER_ID } from './peerTools-
|
|
28
|
+
import { b as sanitizeRateLimitReport } from './rateLimitWindows-CJ1xDAxa.mjs';
|
|
29
|
+
import { f as formatEditConflictNotice, b as SESSION_PEER_SENT_FROM, s as sendPeerMessage, l as listPeerSessions, C as CLI_PEER_SENDER_ID } from './peerTools-uDR6MG0-.mjs';
|
|
30
30
|
import os, { hostname, homedir, userInfo, tmpdir } from 'node:os';
|
|
31
|
-
import { c as RemoteCallBudget, e as REMOTE_WRITE_CALLS_PER_MINUTE, d as deliverToSession, g as guardRemoteSessionOpsRequest, h as remoteError, i as REMOTE_OP_DEADLINE_MS, j as formatRemoteAuditLine, k as REMOTE_SEND_COMMIT_DEADLINE_MS, m as REMOTE_RESUME_WAIT_MS, n as capRemoteTranscript, o as capRemoteText, p as REMOTE_ANSWER_MAX_BYTES, q as REMOTE_TITLE_MAX_BYTES } from './remoteSessionClient-
|
|
32
|
-
import { assistantHome, bootstrapAssistantHome } from './bootstrap-
|
|
33
|
-
import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-
|
|
31
|
+
import { c as RemoteCallBudget, e as REMOTE_WRITE_CALLS_PER_MINUTE, d as deliverToSession, g as guardRemoteSessionOpsRequest, h as remoteError, i as REMOTE_OP_DEADLINE_MS, j as formatRemoteAuditLine, k as REMOTE_SEND_COMMIT_DEADLINE_MS, m as REMOTE_RESUME_WAIT_MS, n as capRemoteTranscript, o as capRemoteText, p as REMOTE_ANSWER_MAX_BYTES, q as REMOTE_TITLE_MAX_BYTES } from './remoteSessionClient-Dx0M2MXV.mjs';
|
|
32
|
+
import { assistantHome, bootstrapAssistantHome } from './bootstrap-DklT121U.mjs';
|
|
33
|
+
import { refreshAgentHomes, locateClaudeConversation, agentHomeSpawnEnv } from './index-Dgqk3lfG.mjs';
|
|
34
34
|
import { existsSync as existsSync$1, statSync as statSync$1, mkdtempSync, rmSync } from 'fs';
|
|
35
35
|
import { join as join$1 } from 'path';
|
|
36
36
|
import { spawn as spawn$1, execFile, spawnSync } from 'node:child_process';
|
|
37
37
|
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
38
38
|
import { d as daemonEndpointsMatch, r as resolveClaudeCredentialReadiness } from './doctorReadiness-C208SMN9.mjs';
|
|
39
|
-
import { g as getInitialMachineMetadata, a as getStartupCliAvailability } from './machineMetadata-
|
|
40
|
-
import { buildResumeLaunch } from './handleResumeCommand-
|
|
39
|
+
import { g as getInitialMachineMetadata, a as getStartupCliAvailability } from './machineMetadata-DmTGIZAV.mjs';
|
|
40
|
+
import { buildResumeLaunch } from './handleResumeCommand-BzcANj0i.mjs';
|
|
41
41
|
import { access, symlink, readFile, rm, unlink, readlink, lstat, constants, stat, open } from 'node:fs/promises';
|
|
42
42
|
import { p as parseExactVersion, c as compareExactVersions, f as fetchCliUpdateState, r as resolveCliUpdateCheckInterval, D as DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS } from './cliUpdate-Y34VGe9Y.mjs';
|
|
43
|
+
import { c as createAutomationsClient, i as isAutomationsUnavailable, d as AutomationsRequestError } from './client-Cbl3ejoq.mjs';
|
|
43
44
|
import { createRequire } from 'node:module';
|
|
44
45
|
import { g as getProjectPath } from './path-D2wdaNSk.mjs';
|
|
45
46
|
import { b as extractClaudeEditPaths } from './editPaths-BVfS_FFL.mjs';
|
|
46
|
-
import { s as startFileWatcher } from './startFileWatcher-
|
|
47
|
-
import { I as InvalidateSync } from './sync-
|
|
47
|
+
import { s as startFileWatcher } from './startFileWatcher-De7rN8QW.mjs';
|
|
48
|
+
import { I as InvalidateSync } from './sync-CHOB3Org.mjs';
|
|
48
49
|
import { R as RawJSONLinesSchema } from './types-CkqAACXx.mjs';
|
|
49
50
|
import { t as tmuxArgs, a as scrubTmuxClientEnv, s as shellescape } from './tmuxSocket-B8Yx20sT.mjs';
|
|
50
|
-
import { p as processIdentityFields, r as readSessionLock, t as terminateProcess } from './sessionLock-
|
|
51
|
+
import { p as processIdentityFields, r as readSessionLock, t as terminateProcess } from './sessionLock-DCKf-gjd.mjs';
|
|
51
52
|
import { findAllHappyProcesses } from './doctor-BPkYWSuq.mjs';
|
|
52
53
|
import { T as TEAM_SKILL } from './resources-BdFBQi8r.mjs';
|
|
53
54
|
import { promisify } from 'node:util';
|
|
54
55
|
import { t as AUTOMATION_SUMMARY_MAX_CHARS, u as AUTOMATION_PRECHECK_OUTPUT_MAX_CHARS, v as AUTOMATION_PRECHECK_DEFAULT_TIMEOUT_MS, a as AUTOMATION_PRECHECK_MAX_TIMEOUT_MS, w as AUTOMATION_CLAIM_MAX_RUNS, x as AUTOMATION_DAEMON_CAPABILITY_PRECHECK, y as AUTOMATION_DEFAULT_LEASE_MS, i as isAutomationRunTerminal } from './index-B0HEEYGh.mjs';
|
|
55
|
-
import { c as createAutomationsClient, i as isAutomationsUnavailable, d as AutomationsRequestError } from './client-GjTnsq6F.mjs';
|
|
56
56
|
import { c as clipText, r as renderAction, b as renderTemplate } from './template-CiOPa2rd.mjs';
|
|
57
57
|
import { d as describeAgentHome } from './loginShellEnv-Dw8M7tkI.mjs';
|
|
58
|
-
import './sessionModeFile-
|
|
59
|
-
import './lidState-
|
|
58
|
+
import './sessionModeFile-BYxsFSvc.mjs';
|
|
59
|
+
import './lidState-CJ3XkJRn.mjs';
|
|
60
60
|
import 'os';
|
|
61
61
|
import 'node:events';
|
|
62
62
|
import 'socket.io-client';
|
|
63
|
-
import './attachmentLimits-
|
|
63
|
+
import './attachmentLimits-CxG3T18E.mjs';
|
|
64
64
|
import './limits-DIo7rEBR.mjs';
|
|
65
|
-
import './time-
|
|
66
|
-
import './registerCommonHandlers-
|
|
65
|
+
import './time-CN0jVVir.mjs';
|
|
66
|
+
import './registerCommonHandlers-BLHKlk5Z.mjs';
|
|
67
67
|
import 'util';
|
|
68
68
|
import 'crypto';
|
|
69
69
|
import 'cross-spawn';
|
|
@@ -71,12 +71,12 @@ import '@paralleldrive/cuid2';
|
|
|
71
71
|
import './contentLogMetadata-BlWI0egu.mjs';
|
|
72
72
|
import 'chalk';
|
|
73
73
|
import 'tweetnacl';
|
|
74
|
-
import './browser-
|
|
74
|
+
import './browser-DUf1dth8.mjs';
|
|
75
75
|
import 'open';
|
|
76
76
|
import './ids-DU6sLx4C.mjs';
|
|
77
77
|
import 'url';
|
|
78
78
|
import './detectCLI-CSGMlV51.mjs';
|
|
79
|
-
import './localHappyAgentAuth-
|
|
79
|
+
import './localHappyAgentAuth-DkLbntlf.mjs';
|
|
80
80
|
import 'ps-list';
|
|
81
81
|
|
|
82
82
|
async function resolveRelaunchMetadata(snapshot, fetchServer) {
|
|
@@ -396,6 +396,29 @@ function isAuthorizedDaemonControlRequest(authorization, controlToken) {
|
|
|
396
396
|
return configuredTokenIsUsable && timingSafeEqual(expectedDigest, candidateDigest);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
+
const WrapperIdleSnapshotSchema = z.object({
|
|
400
|
+
flavor: z.string().max(64),
|
|
401
|
+
resumable: z.boolean(),
|
|
402
|
+
uiSession: z.boolean(),
|
|
403
|
+
variant: z.string().max(64).optional(),
|
|
404
|
+
spawnedBy: z.string().max(64).optional(),
|
|
405
|
+
tags: z.array(z.string().max(128)).max(64).optional(),
|
|
406
|
+
keepAwake: z.boolean(),
|
|
407
|
+
keepAwakeSetting: z.boolean().optional(),
|
|
408
|
+
thinking: z.boolean(),
|
|
409
|
+
queuedInputs: z.number().int().nonnegative(),
|
|
410
|
+
waitingForInput: z.boolean(),
|
|
411
|
+
pendingRequests: z.number().int().nonnegative(),
|
|
412
|
+
backgroundTasks: z.number().int().nonnegative(),
|
|
413
|
+
scheduledWakeups: z.number().int().nonnegative().optional(),
|
|
414
|
+
lastActivityAt: z.number(),
|
|
415
|
+
exiting: z.boolean().optional()
|
|
416
|
+
}).passthrough();
|
|
417
|
+
const HibernateCheckBodySchema = z.object({
|
|
418
|
+
sessionId: z.string().min(1).max(200),
|
|
419
|
+
pid: z.number().int().positive(),
|
|
420
|
+
report: WrapperIdleSnapshotSchema
|
|
421
|
+
});
|
|
399
422
|
const BackgroundTaskInfoSchema = z.object({
|
|
400
423
|
id: z.string().min(1).max(200),
|
|
401
424
|
type: z.string().max(64),
|
|
@@ -429,7 +452,8 @@ function startDaemonControlServer({
|
|
|
429
452
|
onSessionEdit,
|
|
430
453
|
listPeers,
|
|
431
454
|
isTurnActive,
|
|
432
|
-
onRateLimits
|
|
455
|
+
onRateLimits,
|
|
456
|
+
onHibernateCheck
|
|
433
457
|
}) {
|
|
434
458
|
return new Promise((resolve) => {
|
|
435
459
|
const app = fastify({
|
|
@@ -512,6 +536,29 @@ function startDaemonControlServer({
|
|
|
512
536
|
onSessionStateEvent?.(sessionId, event, spawnedBy);
|
|
513
537
|
return { status: "ok" };
|
|
514
538
|
});
|
|
539
|
+
if (onHibernateCheck) {
|
|
540
|
+
typed.post("/session-hibernate-check", {
|
|
541
|
+
schema: {
|
|
542
|
+
body: HibernateCheckBodySchema,
|
|
543
|
+
response: {
|
|
544
|
+
200: z.object({
|
|
545
|
+
hibernate: z.boolean(),
|
|
546
|
+
reason: z.string().optional(),
|
|
547
|
+
idleMs: z.number().optional(),
|
|
548
|
+
nextCheckMs: z.number().optional(),
|
|
549
|
+
keepAwake: z.boolean().optional()
|
|
550
|
+
})
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}, async (request) => {
|
|
554
|
+
try {
|
|
555
|
+
return await onHibernateCheck(request.body);
|
|
556
|
+
} catch (error) {
|
|
557
|
+
logger.debug("[CONTROL SERVER] hibernate check failed:", error);
|
|
558
|
+
return { hibernate: false, reason: "error" };
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
}
|
|
515
562
|
typed.post("/list", {
|
|
516
563
|
schema: {
|
|
517
564
|
response: {
|
|
@@ -2391,6 +2438,133 @@ function createUpdateController(deps) {
|
|
|
2391
2438
|
return { refresh, retry, request, tick, withHandover, holdHandover, isRunning: () => running };
|
|
2392
2439
|
}
|
|
2393
2440
|
|
|
2441
|
+
const AUTOMATION_BINDINGS_TTL_MS = 10 * 60 * 1e3;
|
|
2442
|
+
const HIBERNATION_IN_FLIGHT_MS = 6e4;
|
|
2443
|
+
const HIBERNATION_EXIT_WAIT_MS = 15e3;
|
|
2444
|
+
async function waitForPidsToExit(pids, isAlive, timeoutMs = HIBERNATION_EXIT_WAIT_MS, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now = Date.now) {
|
|
2445
|
+
const deadline = now() + timeoutMs;
|
|
2446
|
+
while (pids.some(isAlive)) {
|
|
2447
|
+
if (now() >= deadline) return false;
|
|
2448
|
+
await sleep(100);
|
|
2449
|
+
}
|
|
2450
|
+
return true;
|
|
2451
|
+
}
|
|
2452
|
+
function createDaemonHibernation(deps) {
|
|
2453
|
+
const now = () => (deps.now ?? Date.now)();
|
|
2454
|
+
const signatures = /* @__PURE__ */ new Map();
|
|
2455
|
+
const approved = /* @__PURE__ */ new Map();
|
|
2456
|
+
let bindings = null;
|
|
2457
|
+
let bindingsInFlight = null;
|
|
2458
|
+
async function automationBound(fresh = false) {
|
|
2459
|
+
if (!fresh && bindings && now() - bindings.at < AUTOMATION_BINDINGS_TTL_MS) return bindings.ids;
|
|
2460
|
+
if (fresh && bindingsInFlight) await bindingsInFlight;
|
|
2461
|
+
if (!bindingsInFlight) {
|
|
2462
|
+
bindingsInFlight = deps.loadAutomationBindings().then((ids) => {
|
|
2463
|
+
bindings = { at: now(), ids: new Set(ids) };
|
|
2464
|
+
return bindings.ids;
|
|
2465
|
+
}).catch((error) => {
|
|
2466
|
+
deps.log?.(`[hibernate] automation bindings unknown: ${error instanceof Error ? error.message : String(error)}`);
|
|
2467
|
+
return null;
|
|
2468
|
+
}).finally(() => {
|
|
2469
|
+
bindingsInFlight = null;
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
return bindingsInFlight;
|
|
2473
|
+
}
|
|
2474
|
+
function inFlight(except) {
|
|
2475
|
+
const t = now();
|
|
2476
|
+
for (const [id, at] of approved) {
|
|
2477
|
+
if (t - at > HIBERNATION_IN_FLIGHT_MS) approved.delete(id);
|
|
2478
|
+
else if (id !== except) return true;
|
|
2479
|
+
}
|
|
2480
|
+
return false;
|
|
2481
|
+
}
|
|
2482
|
+
async function check(request) {
|
|
2483
|
+
const idleMs = deps.idleMs();
|
|
2484
|
+
const t = now();
|
|
2485
|
+
const tracked = deps.tracked(request.sessionId, request.pid);
|
|
2486
|
+
const latchedBefore = deps.readKeepAwake?.(request.sessionId) ?? false;
|
|
2487
|
+
const latched = latchKeepAwake(request.report.keepAwakeSetting, latchedBefore || request.report.keepAwake);
|
|
2488
|
+
if (latched !== latchedBefore) deps.writeKeepAwake?.(request.sessionId, latched);
|
|
2489
|
+
if (latched && !request.report.keepAwake) request = { ...request, report: { ...request.report, keepAwake: true } };
|
|
2490
|
+
const signature = reportSignature(request.report);
|
|
2491
|
+
const previousSignature = signatures.get(request.sessionId);
|
|
2492
|
+
signatures.set(request.sessionId, signature);
|
|
2493
|
+
const base = {
|
|
2494
|
+
idleMs,
|
|
2495
|
+
now: t,
|
|
2496
|
+
sessionId: request.sessionId,
|
|
2497
|
+
pid: request.pid,
|
|
2498
|
+
report: request.report,
|
|
2499
|
+
trackedLive: !!tracked?.live,
|
|
2500
|
+
trackedSpawnedBy: tracked?.spawnedBy,
|
|
2501
|
+
teamsMember: deps.teamsMember(request.sessionId),
|
|
2502
|
+
turnActive: deps.turnActive(request.sessionId),
|
|
2503
|
+
backgroundTasks: deps.backgroundTasks(request.sessionId),
|
|
2504
|
+
previousSignature,
|
|
2505
|
+
hibernationInFlight: inFlight(request.sessionId)
|
|
2506
|
+
};
|
|
2507
|
+
let verdict = decideDaemonHibernation({ ...base, automationBound: /* @__PURE__ */ new Set() });
|
|
2508
|
+
if (verdict.ok || verdict.reason === "unconfirmed" || verdict.reason === "busy") {
|
|
2509
|
+
verdict = decideDaemonHibernation({ ...base, automationBound: await automationBound() });
|
|
2510
|
+
}
|
|
2511
|
+
if (verdict.ok) {
|
|
2512
|
+
verdict = decideDaemonHibernation({ ...base, automationBound: await automationBound(true) });
|
|
2513
|
+
}
|
|
2514
|
+
if (verdict.ok) {
|
|
2515
|
+
approved.set(request.sessionId, t);
|
|
2516
|
+
signatures.delete(request.sessionId);
|
|
2517
|
+
deps.log?.(`[hibernate] approved ${request.sessionId} (pid ${request.pid}, idle ${Math.round((t - request.report.lastActivityAt) / 1e3)}s)`);
|
|
2518
|
+
return { hibernate: true, idleMs, ...latched ? { keepAwake: true } : {} };
|
|
2519
|
+
}
|
|
2520
|
+
const next = verdict.reason === "unconfirmed" ? deps.checkMs : nextCheckDelay(verdict, request.report, idleMs, deps.checkMs, t);
|
|
2521
|
+
return { hibernate: false, reason: verdict.reason, idleMs, nextCheckMs: next, ...latched ? { keepAwake: true } : {} };
|
|
2522
|
+
}
|
|
2523
|
+
return {
|
|
2524
|
+
check,
|
|
2525
|
+
/** Called when the wrapper exits: true when this exit is the hibernation we approved. */
|
|
2526
|
+
consumeExit(sessionId) {
|
|
2527
|
+
const at = approved.get(sessionId);
|
|
2528
|
+
approved.delete(sessionId);
|
|
2529
|
+
signatures.delete(sessionId);
|
|
2530
|
+
return at !== void 0 && now() - at <= HIBERNATION_IN_FLIGHT_MS * 5;
|
|
2531
|
+
},
|
|
2532
|
+
/** Review P1-2: an approved hibernation whose wrapper has not exited yet. */
|
|
2533
|
+
pendingExit(sessionId) {
|
|
2534
|
+
const at = approved.get(sessionId);
|
|
2535
|
+
return at !== void 0 && now() - at <= HIBERNATION_IN_FLIGHT_MS * 5;
|
|
2536
|
+
},
|
|
2537
|
+
forget(sessionId) {
|
|
2538
|
+
signatures.delete(sessionId);
|
|
2539
|
+
},
|
|
2540
|
+
/** Drop the cached Automations bindings (e.g. after the setting changed). */
|
|
2541
|
+
invalidateBindings() {
|
|
2542
|
+
bindings = null;
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
async function collectAutomationBindings(client, machineId) {
|
|
2547
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2548
|
+
const automations = await client.list(machineId);
|
|
2549
|
+
for (const automation of automations) {
|
|
2550
|
+
const action = automation.action;
|
|
2551
|
+
if (action?.kind === "send" && typeof action.sessionId === "string") ids.add(action.sessionId);
|
|
2552
|
+
if (action?.kind === "spawn" && action.sticky) {
|
|
2553
|
+
for (const sticky of await client.stickies(automation.id)) ids.add(sticky.sessionId);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
return [...ids];
|
|
2557
|
+
}
|
|
2558
|
+
const AUTOMATION_WAKE_TIMEOUT_MS = 6e4;
|
|
2559
|
+
async function waitForSessionLive(sessionId, live, timeoutMs = AUTOMATION_WAKE_TIMEOUT_MS, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now = Date.now) {
|
|
2560
|
+
const deadline = now() + timeoutMs;
|
|
2561
|
+
while (!live(sessionId)) {
|
|
2562
|
+
if (now() >= deadline) return false;
|
|
2563
|
+
await sleep(250);
|
|
2564
|
+
}
|
|
2565
|
+
return true;
|
|
2566
|
+
}
|
|
2567
|
+
|
|
2394
2568
|
const CLAUDE_KEYCHAIN_SERVICE_PREFIX = "Claude Code";
|
|
2395
2569
|
function keychainIdentity(env = process.env, deps = {}) {
|
|
2396
2570
|
const home = deps.home ?? homedir();
|
|
@@ -3536,7 +3710,7 @@ function writeReceipt$1(home, receipt) {
|
|
|
3536
3710
|
|
|
3537
3711
|
const exec = promisify(execFile);
|
|
3538
3712
|
const git = async (directory, args) => (await exec("git", ["-C", directory, ...args], { timeout: 3e4, maxBuffer: 2 * 1024 * 1024 })).stdout.trim();
|
|
3539
|
-
async function prepareTeamWorktree(home, repository, id) {
|
|
3713
|
+
async function prepareTeamWorktree(home, repository, id, origin = "teams") {
|
|
3540
3714
|
if (repository === "~") repository = homedir();
|
|
3541
3715
|
else if (repository.startsWith("~/") || process.platform === "win32" && repository.startsWith("~\\")) repository = join(homedir(), repository.slice(2));
|
|
3542
3716
|
if (!isAbsolute(repository) || !/^[a-zA-Z0-9_-]{1,128}$/.test(id)) throw new Error("A team task requires an absolute repository path and valid operation id");
|
|
@@ -3553,6 +3727,7 @@ async function prepareTeamWorktree(home, repository, id) {
|
|
|
3553
3727
|
if (resolve(common) !== resolve(expected)) throw new Error("Team worktree belongs to another repository");
|
|
3554
3728
|
} else {
|
|
3555
3729
|
await git(repository, ["worktree", "add", "-b", branch, directory, "HEAD"]);
|
|
3730
|
+
await initializeOwnedWorktree({ source: repository, worktree: directory, branch, origin });
|
|
3556
3731
|
}
|
|
3557
3732
|
return { directory, repository, branch };
|
|
3558
3733
|
}
|
|
@@ -4200,6 +4375,35 @@ function createAutomationRunner(deps) {
|
|
|
4200
4375
|
}
|
|
4201
4376
|
})();
|
|
4202
4377
|
}
|
|
4378
|
+
function wakeThenSend(claimed, sessionId, text, stickyKey) {
|
|
4379
|
+
const { run, automation } = claimed;
|
|
4380
|
+
const item = track(claimed, "send", sessionId);
|
|
4381
|
+
item.waking = true;
|
|
4382
|
+
gating++;
|
|
4383
|
+
void (async () => {
|
|
4384
|
+
try {
|
|
4385
|
+
const woke = await deps.wakeHibernated(sessionId).catch(() => false);
|
|
4386
|
+
if (!tracked.has(run.id) || closed) return;
|
|
4387
|
+
item.waking = false;
|
|
4388
|
+
if (!woke || !deps.live(sessionId)) {
|
|
4389
|
+
await finish(item, { claimId: run.claimId, status: "failed", sessionId, error: `Session ${sessionId} was hibernated and could not be woken in time`, needsAttention: true, attentionReason: "session_wake_failed" });
|
|
4390
|
+
return;
|
|
4391
|
+
}
|
|
4392
|
+
persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId, ...stickyKey ? { stickyKey } : {} });
|
|
4393
|
+
try {
|
|
4394
|
+
await send(sessionId, text, { localId: `automation-${run.id}` });
|
|
4395
|
+
} catch (error) {
|
|
4396
|
+
await finish(item, { claimId: run.claimId, status: "failed", sessionId, error: clipText(`Message delivery failed: ${error instanceof Error ? error.message : String(error)}`, AUTOMATION_SUMMARY_MAX_CHARS), needsAttention: true, attentionReason: "send_failed" });
|
|
4397
|
+
return;
|
|
4398
|
+
}
|
|
4399
|
+
await reportRunning(item, sessionId, stickyKey);
|
|
4400
|
+
} finally {
|
|
4401
|
+
item.waking = false;
|
|
4402
|
+
gating--;
|
|
4403
|
+
}
|
|
4404
|
+
})();
|
|
4405
|
+
}
|
|
4406
|
+
const wakeable = (sessionId) => !deps.live(sessionId) && !!deps.wakeHibernated && deps.isHibernated?.(sessionId) === true;
|
|
4203
4407
|
async function perform(claimed, action, context, env) {
|
|
4204
4408
|
const { run, automation } = claimed;
|
|
4205
4409
|
const header = automationPromptHeader(automation.name, run.id);
|
|
@@ -4227,6 +4431,11 @@ function createAutomationRunner(deps) {
|
|
|
4227
4431
|
return;
|
|
4228
4432
|
}
|
|
4229
4433
|
if (action.kind === "send") {
|
|
4434
|
+
if (wakeable(action.sessionId)) {
|
|
4435
|
+
wakeThenSend(claimed, action.sessionId, `${header}
|
|
4436
|
+
${action.prompt}`);
|
|
4437
|
+
return;
|
|
4438
|
+
}
|
|
4230
4439
|
if (!deps.live(action.sessionId)) {
|
|
4231
4440
|
await failNow(claimed, "send", `Session ${action.sessionId} is not running on this machine`, "session_not_live", action.sessionId);
|
|
4232
4441
|
return;
|
|
@@ -4255,6 +4464,11 @@ ${action.prompt}`, { localId: `automation-${run.id}` });
|
|
|
4255
4464
|
const stickyKey = action.sticky ? renderTemplate(action.sticky.key, context) : void 0;
|
|
4256
4465
|
if (stickyKey) {
|
|
4257
4466
|
const bound = claimed.stickies.find((sticky) => sticky.key === stickyKey);
|
|
4467
|
+
if (bound && wakeable(bound.sessionId)) {
|
|
4468
|
+
wakeThenSend(claimed, bound.sessionId, `${header}
|
|
4469
|
+
${action.prompt}`, stickyKey);
|
|
4470
|
+
return;
|
|
4471
|
+
}
|
|
4258
4472
|
if (bound && deps.live(bound.sessionId)) {
|
|
4259
4473
|
persist({ runId: run.id, automationId: automation.id, kind: "send", phase: "running", claimId: run.claimId, sessionId: bound.sessionId, stickyKey });
|
|
4260
4474
|
try {
|
|
@@ -4276,7 +4490,7 @@ ${action.prompt}`, { localId: `automation-${run.id}` });
|
|
|
4276
4490
|
}
|
|
4277
4491
|
if (action.worktree) {
|
|
4278
4492
|
try {
|
|
4279
|
-
directory = (await prepareWorktree(home, directory, `auto-${run.id}
|
|
4493
|
+
directory = (await prepareWorktree(home, directory, `auto-${run.id}`, "automation")).directory;
|
|
4280
4494
|
} catch (error) {
|
|
4281
4495
|
await failNow(claimed, "spawn", `Worktree preparation failed: ${error instanceof Error ? error.message : String(error)}`, "worktree_failed");
|
|
4282
4496
|
return;
|
|
@@ -4308,7 +4522,7 @@ ${action.prompt}`, { localId: `automation-${run.id}`, ...meta });
|
|
|
4308
4522
|
await finish(item, item.pendingFinal);
|
|
4309
4523
|
continue;
|
|
4310
4524
|
}
|
|
4311
|
-
if (item.kind === "script") continue;
|
|
4525
|
+
if (item.kind === "script" || item.waking) continue;
|
|
4312
4526
|
const sessionId = item.sessionId;
|
|
4313
4527
|
const active = deps.turnActive(sessionId);
|
|
4314
4528
|
if (active) item.sawTurn = true;
|
|
@@ -4526,6 +4740,7 @@ async function startDaemon() {
|
|
|
4526
4740
|
let cliUpdateStateRef = null;
|
|
4527
4741
|
let lastHandoverHold = null;
|
|
4528
4742
|
let claudeCredentialStoreSetting = (await readSettings()).claudeCredentialStore === "file" ? "file" : "auto";
|
|
4743
|
+
let agentHibernationSetting = (await readSettings()).agentHibernationIdleMs;
|
|
4529
4744
|
try {
|
|
4530
4745
|
const homes = await refreshAgentHomes();
|
|
4531
4746
|
logger.debug(`[DAEMON RUN] Claude config dir: ${describeAgentHome(homes.claudeConfigDir)}; Codex home: ${describeAgentHome(homes.codexHome)}`);
|
|
@@ -4612,6 +4827,40 @@ async function startDaemon() {
|
|
|
4612
4827
|
const turnActivity = new TurnActivityTracker();
|
|
4613
4828
|
const backgroundTasks = new BackgroundTaskTracker();
|
|
4614
4829
|
const peerCoordinator = createPeerCoordinator({ getChildren: () => Array.from(pidToTrackedSession.values()) });
|
|
4830
|
+
const hibernationAutomations = createAutomationsClient({ serverUrl: configuration.serverUrl, token: credentials.token, client: "daemon-hibernate" });
|
|
4831
|
+
const daemonHibernation = createDaemonHibernation({
|
|
4832
|
+
idleMs: () => resolveIdleMs(agentHibernationSetting),
|
|
4833
|
+
checkMs: resolveCheckMs(),
|
|
4834
|
+
tracked: (sessionId, pid) => {
|
|
4835
|
+
const tracked = pidToTrackedSession.get(pid);
|
|
4836
|
+
if (!tracked || tracked.happySessionId !== sessionId) return null;
|
|
4837
|
+
let live = false;
|
|
4838
|
+
try {
|
|
4839
|
+
process.kill(pid, 0);
|
|
4840
|
+
live = true;
|
|
4841
|
+
} catch {
|
|
4842
|
+
live = false;
|
|
4843
|
+
}
|
|
4844
|
+
return { live, ...tracked.spawnedBy ? { spawnedBy: tracked.spawnedBy } : {} };
|
|
4845
|
+
},
|
|
4846
|
+
teamsMember: (sessionId) => teamWorker?.hasSession(sessionId) === true,
|
|
4847
|
+
turnActive: (sessionId) => turnActivity.activeSessions().includes(sessionId),
|
|
4848
|
+
backgroundTasks: (sessionId) => backgroundTasks.count(sessionId),
|
|
4849
|
+
loadAutomationBindings: async () => {
|
|
4850
|
+
try {
|
|
4851
|
+
return await collectAutomationBindings(hibernationAutomations, machineId);
|
|
4852
|
+
} catch (error) {
|
|
4853
|
+
if (isAutomationsUnavailable(error)) return [];
|
|
4854
|
+
throw error;
|
|
4855
|
+
}
|
|
4856
|
+
},
|
|
4857
|
+
log: (message) => logger.debug(`[DAEMON RUN] ${message}`),
|
|
4858
|
+
readKeepAwake: (sessionId) => readPersistedSessions()[sessionId]?.keepAwake === true,
|
|
4859
|
+
writeKeepAwake: (sessionId, value) => {
|
|
4860
|
+
const record = readPersistedSessions()[sessionId];
|
|
4861
|
+
if (record) persistSession(sessionId, { ...record, keepAwake: value || void 0 });
|
|
4862
|
+
}
|
|
4863
|
+
});
|
|
4615
4864
|
const sessionIdToFinishedSession = /* @__PURE__ */ new Map();
|
|
4616
4865
|
let teamWorker;
|
|
4617
4866
|
let automationRunner;
|
|
@@ -5225,6 +5474,13 @@ async function startDaemon() {
|
|
|
5225
5474
|
};
|
|
5226
5475
|
const resumeSessionImpl = async (happySessionId, options) => {
|
|
5227
5476
|
try {
|
|
5477
|
+
if (daemonHibernation.pendingExit(happySessionId)) {
|
|
5478
|
+
const dying = [...pidToTrackedSession.entries()].filter(([, s]) => s.happySessionId === happySessionId).map(([pid]) => pid);
|
|
5479
|
+
const exited = await waitForPidsToExit(dying, isPidAlive);
|
|
5480
|
+
logger.debug(`[DAEMON RUN] resume ${happySessionId}: waited for hibernating wrapper(s) ${dying.join(", ")} \u2192 ${exited ? "exited" : "still alive after timeout"}`);
|
|
5481
|
+
if (!exited) return { type: "error", errorMessage: `Session ${happySessionId} is still going to sleep; try again in a few seconds.` };
|
|
5482
|
+
for (const pid of dying) if (pidToTrackedSession.has(pid)) onChildExited(pid);
|
|
5483
|
+
}
|
|
5228
5484
|
for (const [pid, live] of pidToTrackedSession.entries()) {
|
|
5229
5485
|
if (live.happySessionId !== happySessionId) continue;
|
|
5230
5486
|
if (isPidAlive(pid)) {
|
|
@@ -5485,6 +5741,14 @@ async function startDaemon() {
|
|
|
5485
5741
|
if (session?.happySessionId) turnActivity.forget(session.happySessionId);
|
|
5486
5742
|
if (session?.happySessionId) backgroundTasks.forget(session.happySessionId);
|
|
5487
5743
|
if (session?.happySessionId) peerCoordinator.forget(session.happySessionId);
|
|
5744
|
+
if (session?.happySessionId && daemonHibernation.consumeExit(session.happySessionId)) {
|
|
5745
|
+
const persisted2 = readPersistedSessions()[session.happySessionId];
|
|
5746
|
+
if (persisted2) {
|
|
5747
|
+
const at = Date.now();
|
|
5748
|
+
persistSession(session.happySessionId, { ...persisted2, savedAt: at, hibernatedAt: at });
|
|
5749
|
+
}
|
|
5750
|
+
logger.debug(`[DAEMON RUN] Session ${session.happySessionId} hibernated (PID ${pid} exited)`);
|
|
5751
|
+
}
|
|
5488
5752
|
if (session?.happySessionId && session.encryption) {
|
|
5489
5753
|
sessionIdToFinishedSession.set(session.happySessionId, session);
|
|
5490
5754
|
logger.debug(`[DAEMON RUN] Process PID ${pid} exited, preserved session ${session.happySessionId} for resume`);
|
|
@@ -5580,6 +5844,7 @@ async function startDaemon() {
|
|
|
5580
5844
|
onRateLimits: (report) => {
|
|
5581
5845
|
apiMachineRef?.reportRateLimits(report);
|
|
5582
5846
|
},
|
|
5847
|
+
onHibernateCheck: (body) => daemonHibernation.check(body),
|
|
5583
5848
|
listPeers: () => peerCoordinator.list(),
|
|
5584
5849
|
// B-505: `daemon list` shows which sessions have a turn in flight, so an
|
|
5585
5850
|
// operator can check the WHOLE machine before a supervised restart.
|
|
@@ -5701,6 +5966,13 @@ async function startDaemon() {
|
|
|
5701
5966
|
setStore: (store) => claudeAuthService.setStore(store)
|
|
5702
5967
|
});
|
|
5703
5968
|
claudeAuthService.start();
|
|
5969
|
+
apiMachine.setAgentHibernationHandlers(resolveIdleMs(agentHibernationSetting), async (requested) => {
|
|
5970
|
+
const value = requested <= 0 ? 0 : settingIdleMs(requested);
|
|
5971
|
+
await updateSettings((current) => ({ ...current, agentHibernationIdleMs: value }));
|
|
5972
|
+
agentHibernationSetting = value;
|
|
5973
|
+
daemonHibernation.invalidateBindings();
|
|
5974
|
+
return resolveIdleMs(agentHibernationSetting);
|
|
5975
|
+
});
|
|
5704
5976
|
apiMachine.connect();
|
|
5705
5977
|
if (identityConflict?.confidence === "weak") {
|
|
5706
5978
|
void apiMachine.updateMachineMetadata((current) => ({
|
|
@@ -5848,18 +6120,32 @@ async function startDaemon() {
|
|
|
5848
6120
|
live: (id) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === id && isPidAlive(s.pid)),
|
|
5849
6121
|
turnActive: (id) => turnActivity.activeSessions().includes(id),
|
|
5850
6122
|
backgroundTasks: (id) => backgroundTasks.count(id),
|
|
6123
|
+
// B-587 review P2-5: a hibernated target is woken (resume) and the send
|
|
6124
|
+
// waits until its wrapper is back; anything else stays session_not_live.
|
|
6125
|
+
isHibernated: (id) => {
|
|
6126
|
+
const record = readPersistedSessions()[id];
|
|
6127
|
+
return !!record && typeof record.hibernatedAt === "number" && record.hibernatedAt >= record.savedAt;
|
|
6128
|
+
},
|
|
6129
|
+
wakeHibernated: async (id) => {
|
|
6130
|
+
const result = await resumeSession(id);
|
|
6131
|
+
if (result.type !== "success") return false;
|
|
6132
|
+
return waitForSessionLive(id, (sid) => [...pidToTrackedSession.values()].some((s) => s.happySessionId === sid && isPidAlive(s.pid)));
|
|
6133
|
+
},
|
|
5851
6134
|
log: (message) => logger.debug(`[DAEMON RUN] ${message}`)
|
|
5852
6135
|
});
|
|
5853
6136
|
void apiMachine.updateMachineMetadata((current) => ({
|
|
5854
6137
|
...current ?? initialMachineMetadata,
|
|
5855
6138
|
teamsVersion: 1,
|
|
5856
|
-
teamLaunchVersion: 1
|
|
6139
|
+
teamLaunchVersion: 1,
|
|
6140
|
+
// B-586: this daemon serves the worktree-* RPCs (web gates 「在新 worktree 中」 on it).
|
|
6141
|
+
worktreeVersion: WORKTREE_CAPABILITY_VERSION
|
|
5857
6142
|
})).catch(() => logger.debug("[DAEMON RUN] Teams capability publication will retry on reconnect"));
|
|
5858
6143
|
const cleanupAndShutdown = async (source, errorMessage) => {
|
|
5859
6144
|
logger.debug(`[DAEMON RUN] Starting proper cleanup (source: ${source}, errorMessage: ${errorMessage})...`);
|
|
5860
6145
|
const scrollbackFlush = apiMachine.flushTerminalScrollback();
|
|
5861
6146
|
teamWorker?.stop();
|
|
5862
6147
|
automationRunner?.stop({ killScripts: true });
|
|
6148
|
+
currentWorktreeService()?.stopAll();
|
|
5863
6149
|
if (restartOnStaleVersionAndHeartbeat) {
|
|
5864
6150
|
clearInterval(restartOnStaleVersionAndHeartbeat);
|
|
5865
6151
|
logger.debug("[DAEMON RUN] Health check interval cleared");
|