very-happy-cli 0.2.162 → 0.2.164
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--TmFHgRH.mjs → AcpBackend-B8l1ZePt.mjs} +3 -3
- package/dist/{AcpBackend-9asD_DL7.cjs → AcpBackend-CHDqSii9.cjs} +3 -3
- package/dist/{AcpSessionManager-BvIuBzoO.cjs → AcpSessionManager-9yN2iH4b.cjs} +1 -1
- package/dist/{AcpSessionManager-BSIBnWUb.mjs → AcpSessionManager-BQnDJvct.mjs} +1 -1
- package/dist/{BasePermissionHandler-D4B-NNu2.cjs → BasePermissionHandler-DGQYvBPg.cjs} +1 -1
- package/dist/{BasePermissionHandler-DUBySe0f.mjs → BasePermissionHandler-DgtAtJTV.mjs} +1 -1
- package/dist/{BaseReasoningProcessor-CqLl-ikP.cjs → BaseReasoningProcessor-BqalZhQO.cjs} +1 -1
- package/dist/{BaseReasoningProcessor-9TybUGTq.mjs → BaseReasoningProcessor-Dfacnfhj.mjs} +1 -1
- package/dist/{agentHome-DQrq_FG1.mjs → agentHome-DM0urHEI.mjs} +4 -4
- package/dist/{agentHome-BohNUYnE.cjs → agentHome-DtsPKfTS.cjs} +4 -4
- package/dist/{api-CQnLOqRS.cjs → api-EKlS0r1w.cjs} +57 -15
- package/dist/{api-D57dsd6_.mjs → api-Yoh_zKdR.mjs} +57 -15
- package/dist/{apiMachine-fFFaWxYy.cjs → apiMachine-q71suojS.cjs} +20 -17
- package/dist/{apiMachine-78Aqzg--.mjs → apiMachine-s3HiV-SL.mjs} +20 -17
- package/dist/{assistantTools-mEz6uNqL.mjs → assistantTools-BWfAV349.mjs} +6 -6
- package/dist/{assistantTools-CwESq24n.cjs → assistantTools-D3cZvgUX.cjs} +6 -6
- package/dist/{attachmentContent-s1xPha4Q.mjs → attachmentContent-BLyyo1al.mjs} +2 -2
- package/dist/{attachmentContent-GHOk6Muq.cjs → attachmentContent-Bakb0XV3.cjs} +2 -2
- package/dist/{attachmentLimits-D5pgmASK.mjs → attachmentLimits-B8nzhw-i.mjs} +1 -1
- package/dist/{attachmentLimits-DzlBPyJP.cjs → attachmentLimits-eJZ4ZBjF.cjs} +1 -1
- package/dist/{auth-BOaHWquu.mjs → auth-BTfv8yW0.mjs} +8 -8
- package/dist/{auth-BbSdXMQ_.cjs → auth-Cn3dQInF.cjs} +5 -5
- package/dist/{auth-C8V7-oUT.mjs → auth-Cxhx5evk.mjs} +5 -5
- package/dist/{auth-B8EagV6G.cjs → auth-Hpg4Yxfa.cjs} +8 -8
- package/dist/{auto-CWDOX35m.mjs → auto-BAAEVGZa.mjs} +15 -14
- package/dist/{auto-Bw_h0yVc.cjs → auto-CK8irHum.cjs} +15 -14
- package/dist/{bootstrap-BKmsYSwh.mjs → bootstrap-CTNjn_aj.mjs} +2 -2
- package/dist/{bootstrap-DvZjEa9_.cjs → bootstrap-D9SUykG_.cjs} +2 -2
- package/dist/{browser-CBZj-1Wx.cjs → browser-C8ztaIkm.cjs} +1 -1
- package/dist/{browser-CrMAr5fI.mjs → browser-DydXWySF.mjs} +1 -1
- package/dist/{claudeLocal-dhdlcQ6F.mjs → claudeLocal-CdJJovWq.mjs} +5 -5
- package/dist/{claudeLocal-Bpw-u9et.cjs → claudeLocal-CsLFMvFU.cjs} +5 -5
- package/dist/{claudeLocalLauncher-BFfGT4eY.mjs → claudeLocalLauncher-CKazNnl0.mjs} +10 -10
- package/dist/{claudeLocalLauncher-DWFWuLhY.cjs → claudeLocalLauncher-DRc-tET5.cjs} +10 -10
- package/dist/{claudeSessionFork-D9-mANmu.cjs → claudeSessionFork-BWdhyy9B.cjs} +1 -1
- package/dist/{claudeSessionFork-_DUrXaqd.mjs → claudeSessionFork-BfPW9D2S.mjs} +1 -1
- package/dist/{client-CVQJWqjx.cjs → client-BZtKFCJr.cjs} +2 -2
- package/dist/{client-DiBTHWNU.cjs → client-C1GAIJ04.cjs} +3 -3
- package/dist/{client-DwqHDsLb.mjs → client-DkoV3VWl.mjs} +2 -2
- package/dist/{client-Dk7x-s-O.mjs → client-Do5CHQnZ.mjs} +3 -3
- package/dist/codex/happyMcpStdioBridge.cjs +15 -15
- package/dist/codex/happyMcpStdioBridge.mjs +15 -15
- package/dist/{codexAppServerClient-C2ybs2mZ.mjs → codexAppServerClient-CfF33X-8.mjs} +2 -2
- package/dist/{codexAppServerClient-DlKv5TjG.cjs → codexAppServerClient-JddkV_aP.cjs} +2 -2
- package/dist/{codexCommand-4vLE31fj.cjs → codexCommand-Bdj3XZbi.cjs} +43 -40
- package/dist/{codexCommand-DnmFr9Qx.mjs → codexCommand-btJso8yC.mjs} +43 -40
- package/dist/{config-Btd4B05_.cjs → config-DpCNivmg.cjs} +3 -3
- package/dist/{config-CSOG_ZcP.mjs → config-nziuMb7g.mjs} +3 -3
- package/dist/{configuration-A5gW_0GE.mjs → configuration-CiBUH72C.mjs} +1 -1
- package/dist/{configuration-UsI0sxEv.cjs → configuration-PXAE4-FP.cjs} +1 -1
- package/dist/{connect-C9yxp8Om.cjs → connect-D7ehaW2C.cjs} +13 -13
- package/dist/{connect-DWYj8LP_.mjs → connect-XHdi6Vtc.mjs} +13 -13
- package/dist/{context-BXnxalWW.mjs → context-BpEYcuLv.mjs} +1 -1
- package/dist/{context-0FjjA4vJ.cjs → context-DhvXl1oC.cjs} +1 -1
- package/dist/{controlClient-BXktrQ4z.cjs → controlClient-DI-Er-Ww.cjs} +3 -3
- package/dist/{controlClient-CYzHrh3e.mjs → controlClient-DzmCQrY_.mjs} +3 -3
- package/dist/{createSessionMetadata-Dyg33ZlU.mjs → createSessionMetadata-B47GrTX6.mjs} +2 -2
- package/dist/{createSessionMetadata-EX1eAlHx.cjs → createSessionMetadata-D04x6OMW.cjs} +2 -2
- package/dist/{deterministicJson-eha_oMZ2.cjs → deterministicJson-BM8e8QwP.cjs} +9 -9
- package/dist/{deterministicJson-DiR7EOMO.mjs → deterministicJson-CKqT3awl.mjs} +9 -9
- package/dist/{doctor-FuCvKdRa.mjs → doctor-CSgzbG5L.mjs} +6 -6
- package/dist/{doctor-DunLBgVi.cjs → doctor-Cl6cqvok.cjs} +6 -6
- package/dist/{ensureDaemonRunning-B4dZFmUy.cjs → ensureDaemonRunning-CJ4-U32n.cjs} +5 -5
- package/dist/{ensureDaemonRunning-EZkb-CAF.mjs → ensureDaemonRunning-fPVSsjIm.mjs} +5 -5
- package/dist/forkBackfill-8eLDeS73.cjs +66 -0
- package/dist/forkBackfill-DYIjlN1Z.mjs +62 -0
- package/dist/{handleResumeCommand-CsXendKb.mjs → handleResumeCommand-B84dt2aH.mjs} +5 -5
- package/dist/{handleResumeCommand-CKMIw4pE.cjs → handleResumeCommand-bX-aNF_z.cjs} +5 -5
- package/dist/{index-DRhWHEuW.cjs → index-B2UvSWo_.cjs} +3 -3
- package/dist/{index-BOhgL3rh.cjs → index-CP2fh7JX.cjs} +38 -38
- package/dist/{index-9L39wqYR.mjs → index-CRJtZCK-.mjs} +39 -39
- package/dist/{index-CvXcVQ06.mjs → index-CbF87SeZ.mjs} +3 -3
- package/dist/{index-CZWAiydF.cjs → index-DaTxsAC3.cjs} +4 -4
- package/dist/{index-DJ-oV52i.cjs → index-DqlyNgt4.cjs} +6 -1
- package/dist/{index-DK2JpTJf.mjs → index-OEGj3BxE.mjs} +4 -4
- package/dist/{index-BBg9j0XK.mjs → index-vVWpCoTr.mjs} +6 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{install-B2duVo9a.mjs → install-CurvoW2u.mjs} +3 -3
- package/dist/{install-C8WyZI9K.cjs → install-__Mni4NU.cjs} +3 -3
- package/dist/lib.cjs +17 -17
- package/dist/lib.d.cts +47 -0
- package/dist/lib.d.mts +47 -0
- package/dist/lib.mjs +17 -17
- package/dist/{lidState-CigXWxhe.mjs → lidState-BbR6y9rq.mjs} +66 -2
- package/dist/{lidState-Ds-6ytZV.cjs → lidState-De2HP6nu.cjs} +67 -1
- package/dist/{localHappyAgentAuth-CaCyKzYp.mjs → localHappyAgentAuth-C7rDePjF.mjs} +1 -1
- package/dist/{localHappyAgentAuth-l0Na-5Ys.cjs → localHappyAgentAuth-CboZb3_a.cjs} +1 -1
- package/dist/{logger-CGE4C8ho.mjs → logger-8dtZPn3n.mjs} +2 -2
- package/dist/{logger-7ucWm9wp.cjs → logger-B1k7eZnq.cjs} +2 -2
- package/dist/{machineMetadata-ue1nkowa.mjs → machineMetadata-Bhp_w3-_.mjs} +3 -3
- package/dist/{machineMetadata-lMPtpF16.cjs → machineMetadata-C4OfKn6I.cjs} +3 -3
- package/dist/{main-3fIFXD-t.mjs → main-BQTaUrz0.mjs} +44 -44
- package/dist/{main-CFI0datL.cjs → main-eAiLspBM.cjs} +44 -44
- package/dist/{mcp-DARQBZ7l.mjs → mcp-DXCdbQHM.mjs} +14 -14
- package/dist/{mcp-DfxLAc1G.cjs → mcp-fapbM7Q4.cjs} +14 -14
- package/dist/{package-D1A-8ZJy.cjs → package-CC_txQ31.cjs} +8 -8
- package/dist/{package-DQsvY1XN.mjs → package-tVYgFJoK.mjs} +8 -8
- package/dist/{peerTools-D19hhSQF.mjs → peerTools-C1cduHh1.mjs} +4 -4
- package/dist/{peerTools-DLwNaEEV.cjs → peerTools-CqIcCEIg.cjs} +4 -4
- package/dist/{persistence-Cw8aLoyL.mjs → persistence-C_xFQLsD.mjs} +3 -3
- package/dist/{persistence-i0nQMLlk.cjs → persistence-d3ZyER6o.cjs} +3 -3
- package/dist/{piRunnerArgs-BUyxPxjZ.cjs → piRunnerArgs-DSxolPlV.cjs} +1 -1
- package/dist/{piRunnerArgs-58t454gw.mjs → piRunnerArgs-aq0zJX1Q.mjs} +1 -1
- package/dist/{piRuntime-DVPixFjl.mjs → piRuntime-BnNl5Lmb.mjs} +1 -1
- package/dist/{piRuntime-Dff73XCb.cjs → piRuntime-Dne1LPu-.cjs} +1 -1
- package/dist/{piTerminal-gHWFAyzq.mjs → piTerminal-CKWxWtW-.mjs} +16 -16
- package/dist/{piTerminal-Dz1RrO70.cjs → piTerminal-fjado4cR.cjs} +16 -16
- package/dist/{registerCommonHandlers-CMROPdJz.cjs → registerCommonHandlers-Dausbdsb.cjs} +2 -2
- package/dist/{registerCommonHandlers-Ckv5boQI.mjs → registerCommonHandlers-bSskMveZ.mjs} +2 -2
- package/dist/{registerKillSessionHandler-Cll4-o8Y.mjs → registerKillSessionHandler-Ben5lAsN.mjs} +6 -6
- package/dist/{registerKillSessionHandler-CA9-oelM.cjs → registerKillSessionHandler-CgKyzwqw.cjs} +6 -6
- package/dist/{remoteSessionClient-DX9jHLeW.cjs → remoteSessionClient-BkJt8SHa.cjs} +5 -5
- package/dist/{remoteSessionClient-BMjsbuBh.mjs → remoteSessionClient-DnCIuZpQ.mjs} +5 -5
- package/dist/{run-CjbGo2wb.cjs → run-B8dxbDsg.cjs} +33 -33
- package/dist/{run-CrunzDlt.mjs → run-BEYMVE4J.mjs} +32 -32
- package/dist/{runClaude-KN-4Y4LH.cjs → runClaude-Cy_HzLyO.cjs} +26 -23
- package/dist/{runClaude-WDBWRtnF.mjs → runClaude-Dd_P1c0f.mjs} +26 -23
- package/dist/{runClaudeDeps-QaEx8y5r.mjs → runClaudeDeps-JG7EUH7B.mjs} +441 -49
- package/dist/{runClaudeDeps-DW-8lnHv.cjs → runClaudeDeps-dxv910DR.cjs} +436 -44
- package/dist/{runGemini-Nf6SKBpw.mjs → runGemini-CpaBuvoW.mjs} +34 -34
- package/dist/{runGemini-Djmwjdv1.cjs → runGemini-DY1IDW_f.cjs} +34 -34
- package/dist/{runOpenClaw-CAqP5KFH.cjs → runOpenClaw-C0VARcYj.cjs} +20 -20
- package/dist/{runOpenClaw-9nHtmYbN.mjs → runOpenClaw-C7vrDQbq.mjs} +20 -20
- package/dist/{sandbox-C8Dd8GPM.cjs → sandbox-Bx9-M9rN.cjs} +4 -4
- package/dist/{sandbox-SP0THMt0.mjs → sandbox-DRUJZuaM.mjs} +4 -4
- package/dist/{selfCheck-D9ZXrK7h.cjs → selfCheck-Ba1sECTO.cjs} +34 -34
- package/dist/selfCheck-DdT8r263.mjs +84 -0
- package/dist/{send-DOx9aQsx.mjs → send-BrzkbMy2.mjs} +8 -8
- package/dist/{send-LPk6Q5HI.cjs → send-Dqdpx-w5.cjs} +8 -8
- package/dist/{server-BZNi8Hq_.mjs → server-CPMPoEAA.mjs} +4 -4
- package/dist/{server-CxT8jNyn.cjs → server-CfB8EWCg.cjs} +6 -6
- package/dist/{sessionLock-y9rnA4LK.cjs → sessionLock-BsP3Y_nG.cjs} +2 -2
- package/dist/{sessionLock-CfLqJfeI.mjs → sessionLock-DukLVzAQ.mjs} +2 -2
- package/dist/{sessionModeFile-BKxgNH3P.mjs → sessionModeFile-CSvi4H_t.mjs} +1 -1
- package/dist/{sessionModeFile-B5YeoQJh.cjs → sessionModeFile-JWWF6Nn7.cjs} +1 -1
- package/dist/{sessionOps-CdwVPSZz.mjs → sessionOps-BlMg1uAa.mjs} +5 -5
- package/dist/{sessionOps-GsELm2PZ.cjs → sessionOps-HuoMXcIZ.cjs} +4 -4
- package/dist/{sessionScanner-aLEv7mD3.cjs → sessionScanner-BWU6KvZw.cjs} +3 -3
- package/dist/{sessionScanner-Cdukzo70.mjs → sessionScanner-Ct-JoNHP.mjs} +3 -3
- package/dist/{sessions-Dne-OiRL.mjs → sessions-3Hw1xXMV.mjs} +9 -9
- package/dist/{sessions-CfG4WGN0.cjs → sessions-AjflCj5y.cjs} +9 -9
- package/dist/{setupOfflineReconnection-DiQma2Cc.mjs → setupOfflineReconnection-B_9xp36H.mjs} +2 -2
- package/dist/{setupOfflineReconnection-CFwltTcP.cjs → setupOfflineReconnection-Cxh9Sz9M.cjs} +2 -2
- package/dist/{spawn-DkgP2BGF.mjs → spawn-BXEVKCQK.mjs} +38 -18
- package/dist/{spawn-BI_sdgWs.cjs → spawn-CN8PH11G.cjs} +38 -17
- package/dist/{spawnAgents-Y1LjnCt9.mjs → spawnAgents-Czi2VDzj.mjs} +1 -1
- package/dist/{spawnAgents-iSu1Xzs5.cjs → spawnAgents-McixdtV1.cjs} +1 -1
- package/dist/{spawnHappyCLI-9mx4lPxh.mjs → spawnHappyCLI-BFN0h2fK.mjs} +1 -1
- package/dist/{spawnHappyCLI-BRdx0sAX.cjs → spawnHappyCLI-Cj-9-d_7.cjs} +1 -1
- package/dist/{startFileWatcher-C2HC2_Dg.cjs → startFileWatcher-BfMu444W.cjs} +1 -1
- package/dist/{startFileWatcher-COD5UKNs.mjs → startFileWatcher-Csql7gdv.mjs} +1 -1
- package/dist/{streamRelay-BLgU9X3R.mjs → streamRelay-BzMEEvJU.mjs} +1 -1
- package/dist/{streamRelay-DnObXZZj.cjs → streamRelay-C0AffuX6.cjs} +1 -1
- package/dist/{sync-Dj92ZJ8Y.cjs → sync--uxtLWbo.cjs} +5 -1
- package/dist/{sync-BpLasLu2.mjs → sync-SCvDzRy6.mjs} +5 -1
- package/dist/{systemPrompt-CyEz_IfR.cjs → systemPrompt-C1tRiZ-u.cjs} +2 -2
- package/dist/{systemPrompt-DsQoUgQw.mjs → systemPrompt-D0KMySrK.mjs} +2 -2
- package/dist/{teams-BETNMjpZ.mjs → teams-By-hcvMF.mjs} +6 -6
- package/dist/{teams-Ctx9zXn4.cjs → teams-CYDIFXEC.cjs} +6 -6
- package/dist/{time-CLwVAz6s.cjs → time-C7BplxuS.cjs} +1 -1
- package/dist/{time-CVvxdEDh.mjs → time-CRvAaC5H.mjs} +1 -1
- package/dist/{titleGenerator-B4AW3dLr.mjs → titleGenerator-CUG-n2r3.mjs} +1 -1
- package/dist/{titleGenerator-FDpdizn7.cjs → titleGenerator-Kw3sTnNQ.cjs} +2 -2
- package/dist/{todo-C3tyFeq1.cjs → todo-B7a7J5Ng.cjs} +6 -6
- package/dist/{todo-Jk4Vs7hP.mjs → todo-yuIsUvU8.mjs} +6 -6
- package/dist/{tools-CGxq3I52.cjs → tools-BTBgpiRc.cjs} +2 -2
- package/dist/{tools-O5beDK-s.cjs → tools-D7UeLMZ7.cjs} +1 -1
- package/dist/{tools-_kFe4m_l.mjs → tools-RvMKw7yx.mjs} +1 -1
- package/dist/{tools-BA1qkiV1.mjs → tools-gUjkPpCw.mjs} +2 -2
- package/dist/{uninstall-DHKF90lo.cjs → uninstall-D5D16-KM.cjs} +3 -3
- package/dist/{uninstall-C_mdAZlm.mjs → uninstall-Dx9FmLXs.mjs} +3 -3
- package/package.json +8 -8
- package/dist/selfCheck-7FaZtVu2.mjs +0 -84
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { l as logger } from './logger-
|
|
2
|
-
import { k as notifyDaemonSessionEvent, m as notifyDaemonClaudeAuthFailed } from './controlClient-
|
|
3
|
-
export { g as reportSessionEditToDaemon } from './controlClient-
|
|
1
|
+
import { l as logger } from './logger-8dtZPn3n.mjs';
|
|
2
|
+
import { k as notifyDaemonSessionEvent, m as notifyDaemonClaudeAuthFailed } from './controlClient-DzmCQrY_.mjs';
|
|
3
|
+
export { g as reportSessionEditToDaemon } from './controlClient-DzmCQrY_.mjs';
|
|
4
4
|
import { s as sameBackgroundTasks, c as createBackgroundTaskTracker } from './backgroundTaskActivity-8PdPxrvy.mjs';
|
|
5
5
|
import { randomInt, randomUUID, createHash } from 'node:crypto';
|
|
6
6
|
import { M as MessageBuffer } from './messageBuffer-BWlGgR3A.mjs';
|
|
7
7
|
import { query } from './index-B6UGRQ7h.mjs';
|
|
8
8
|
import { AbortError } from '@anthropic-ai/claude-agent-sdk';
|
|
9
9
|
import { m as mapToClaudeMode, p as parseClaudePermissionMode, c as resolveRemoteClaudePermissionMode } from './permissionMode-CH4FoZfU.mjs';
|
|
10
|
-
import { c as claudeCheckSession, s as systemPrompt } from './systemPrompt-
|
|
10
|
+
import { c as claudeCheckSession, s as systemPrompt } from './systemPrompt-D0KMySrK.mjs';
|
|
11
11
|
import { join, resolve, dirname } from 'node:path';
|
|
12
12
|
import { p as parseSpecialCommand } from './specialCommands-BSqhYg5X.mjs';
|
|
13
13
|
import 'axios';
|
|
14
14
|
import 'node:events';
|
|
15
15
|
import 'socket.io-client';
|
|
16
|
-
import { A as AsyncLock } from './attachmentLimits-
|
|
16
|
+
import { A as AsyncLock } from './attachmentLimits-B8nzhw-i.mjs';
|
|
17
17
|
import 'tweetnacl';
|
|
18
|
-
import { c as configuration, e as ensurePrivateDirectory } from './configuration-
|
|
19
|
-
import './index-
|
|
20
|
-
import './registerCommonHandlers-
|
|
18
|
+
import { c as configuration, e as ensurePrivateDirectory } from './configuration-CiBUH72C.mjs';
|
|
19
|
+
import './index-vVWpCoTr.mjs';
|
|
20
|
+
import './registerCommonHandlers-bSskMveZ.mjs';
|
|
21
21
|
import 'os';
|
|
22
22
|
import 'child_process';
|
|
23
23
|
import '@paralleldrive/cuid2';
|
|
24
|
-
import './persistence-
|
|
24
|
+
import './persistence-C_xFQLsD.mjs';
|
|
25
25
|
import { c as contentLogMetadata } from './contentLogMetadata-BlWI0egu.mjs';
|
|
26
26
|
import 'chalk';
|
|
27
27
|
export { R as RawJSONLinesSchema } from './types-CkqAACXx.mjs';
|
|
28
28
|
import { g as getProjectPath } from './path-D2wdaNSk.mjs';
|
|
29
29
|
import { access } from 'fs/promises';
|
|
30
|
-
import { d as delay } from './time-
|
|
30
|
+
import { d as delay } from './time-CRvAaC5H.mjs';
|
|
31
31
|
import { mkdirSync, writeFileSync, readFileSync, unlinkSync, renameSync, statSync, existsSync } from 'node:fs';
|
|
32
|
-
import { h as hashObject, i as isSelfReportFresh } from './deterministicJson-
|
|
33
|
-
export { c as createSelfReportState, s as startHappyServer } from './deterministicJson-
|
|
34
|
-
import { F as Future } from './sessionScanner-
|
|
35
|
-
export { c as createSessionScanner } from './sessionScanner-
|
|
32
|
+
import { h as hashObject, i as isSelfReportFresh } from './deterministicJson-CKqT3awl.mjs';
|
|
33
|
+
export { c as createSelfReportState, s as startHappyServer } from './deterministicJson-CKqT3awl.mjs';
|
|
34
|
+
import { F as Future } from './sessionScanner-Ct-JoNHP.mjs';
|
|
35
|
+
export { c as createSessionScanner } from './sessionScanner-Ct-JoNHP.mjs';
|
|
36
36
|
import { execSync } from 'node:child_process';
|
|
37
|
-
import { S as StreamRelay } from './streamRelay-
|
|
38
|
-
import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-
|
|
39
|
-
import {
|
|
40
|
-
import { F as ForkSourceMissingError } from './claudeSessionFork-
|
|
41
|
-
export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-
|
|
42
|
-
export { g as getEnvironmentInfo } from './doctor-
|
|
37
|
+
import { S as StreamRelay } from './streamRelay-BzMEEvJU.mjs';
|
|
38
|
+
import { C as CLAUDE_ATTACHMENT_KINDS, c as chatAttachmentDirectory, a as stageClaudeAttachments, b as appendStagedAttachmentsToPrompt } from './attachmentContent-BLyyo1al.mjs';
|
|
39
|
+
import { writeFile, rename, unlink, readFile } from 'node:fs/promises';
|
|
40
|
+
import { F as ForkSourceMissingError } from './claudeSessionFork-BfPW9D2S.mjs';
|
|
41
|
+
export { M as MessageQueue2, r as registerKillSessionHandler } from './registerKillSessionHandler-Ben5lAsN.mjs';
|
|
42
|
+
export { g as getEnvironmentInfo } from './doctor-CSgzbG5L.mjs';
|
|
43
43
|
import { createServer } from 'node:http';
|
|
44
44
|
export { E as EditReportThrottle, b as extractClaudeEditPaths } from './editPaths-BVfS_FFL.mjs';
|
|
45
45
|
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
46
|
-
import { r as resolveClaudeBinary, a as runClaudeOneShot } from './titleGenerator-
|
|
47
|
-
export { T as TitleGenerator } from './titleGenerator-
|
|
46
|
+
import { r as resolveClaudeBinary, a as runClaudeOneShot } from './titleGenerator-CUG-n2r3.mjs';
|
|
47
|
+
export { T as TitleGenerator } from './titleGenerator-CUG-n2r3.mjs';
|
|
48
48
|
import { B as BOARD_ANALYZER_PROMPT_PREFIX } from './oneShotPrompts-DT4p6RNd.mjs';
|
|
49
49
|
import 'node:util';
|
|
50
50
|
import './smallFastModel-BLNgMrwR.mjs';
|
|
@@ -52,33 +52,33 @@ import './trimIdent-BAjmv_TG.mjs';
|
|
|
52
52
|
import 'node:os';
|
|
53
53
|
import './agentGuidance-CQuNlNx8.mjs';
|
|
54
54
|
import 'zod';
|
|
55
|
-
import './package-
|
|
55
|
+
import './package-tVYgFJoK.mjs';
|
|
56
56
|
import 'util';
|
|
57
57
|
import 'crypto';
|
|
58
58
|
import 'path';
|
|
59
59
|
import 'cross-spawn';
|
|
60
60
|
import './authRelay-DSAvg1uv.mjs';
|
|
61
|
-
import './client-
|
|
62
|
-
import './context-
|
|
63
|
-
import './sessionOps-
|
|
61
|
+
import './client-Do5CHQnZ.mjs';
|
|
62
|
+
import './context-BpEYcuLv.mjs';
|
|
63
|
+
import './sessionOps-BlMg1uAa.mjs';
|
|
64
64
|
import './resources-BdFBQi8r.mjs';
|
|
65
|
-
import './tools-
|
|
66
|
-
import './tools-
|
|
67
|
-
import './client-
|
|
68
|
-
import './peerTools-
|
|
65
|
+
import './tools-RvMKw7yx.mjs';
|
|
66
|
+
import './tools-gUjkPpCw.mjs';
|
|
67
|
+
import './client-DkoV3VWl.mjs';
|
|
68
|
+
import './peerTools-C1cduHh1.mjs';
|
|
69
69
|
import './ids-DU6sLx4C.mjs';
|
|
70
|
-
import './remoteSessionClient-
|
|
70
|
+
import './remoteSessionClient-DnCIuZpQ.mjs';
|
|
71
71
|
import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
72
72
|
import '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
73
73
|
import './limits-DIo7rEBR.mjs';
|
|
74
|
-
import './assistantTools-
|
|
74
|
+
import './assistantTools-BWfAV349.mjs';
|
|
75
75
|
import './terminals-Dlg0x3nY.mjs';
|
|
76
76
|
import './terminalTitleSuggest-CeKsX_V6.mjs';
|
|
77
77
|
import './tmuxSocket-B8Yx20sT.mjs';
|
|
78
|
-
import './bootstrap-
|
|
78
|
+
import './bootstrap-CTNjn_aj.mjs';
|
|
79
79
|
import './previewPath-CXN4Vag0.mjs';
|
|
80
|
-
import './sync-
|
|
81
|
-
import './startFileWatcher-
|
|
80
|
+
import './sync-SCvDzRy6.mjs';
|
|
81
|
+
import './startFileWatcher-Csql7gdv.mjs';
|
|
82
82
|
import 'node:readline';
|
|
83
83
|
import './doctor-BPkYWSuq.mjs';
|
|
84
84
|
import 'ps-list';
|
|
@@ -2893,16 +2893,55 @@ function rewindTranscriptLines(lines, action, target) {
|
|
|
2893
2893
|
});
|
|
2894
2894
|
return [...before.map((entry) => entry.line), ...relinked];
|
|
2895
2895
|
}
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2896
|
+
function transcriptSourceId(lines, claudeSessionId) {
|
|
2897
|
+
let source = null;
|
|
2898
|
+
for (const line of lines) {
|
|
2899
|
+
if (!line || !line.includes('"sessionId"')) continue;
|
|
2900
|
+
let parsed;
|
|
2901
|
+
try {
|
|
2902
|
+
parsed = JSON.parse(line);
|
|
2903
|
+
} catch {
|
|
2904
|
+
continue;
|
|
2905
|
+
}
|
|
2906
|
+
if (typeof parsed?.sessionId === "string" && parsed.sessionId && parsed.sessionId !== claudeSessionId) source = parsed.sessionId;
|
|
2907
|
+
}
|
|
2908
|
+
return source;
|
|
2909
|
+
}
|
|
2910
|
+
const MAX_LINEAGE_DEPTH = 4;
|
|
2911
|
+
async function readTranscriptLines(projectDir, claudeSessionId) {
|
|
2912
|
+
const path = join(projectDir, `${claudeSessionId}.jsonl`);
|
|
2899
2913
|
try {
|
|
2900
|
-
|
|
2914
|
+
return (await readFile(path, "utf-8")).split("\n");
|
|
2901
2915
|
} catch (error) {
|
|
2902
|
-
if (error.code === "ENOENT") throw new ForkSourceMissingError(
|
|
2916
|
+
if (error.code === "ENOENT") throw new ForkSourceMissingError(path);
|
|
2903
2917
|
throw error;
|
|
2904
2918
|
}
|
|
2905
|
-
|
|
2919
|
+
}
|
|
2920
|
+
async function rewindAcrossLineage(load, claudeSessionId, action, target) {
|
|
2921
|
+
let id = claudeSessionId;
|
|
2922
|
+
let lines = await load(id);
|
|
2923
|
+
if (!lines) throw new ForkSourceMissingError(id);
|
|
2924
|
+
for (let depth = 0; ; depth++) {
|
|
2925
|
+
try {
|
|
2926
|
+
return { kept: rewindTranscriptLines(lines, action, target), from: id };
|
|
2927
|
+
} catch (error) {
|
|
2928
|
+
if (!(error instanceof ConversationRewindError) || error.code !== "not-found" || depth >= MAX_LINEAGE_DEPTH) throw error;
|
|
2929
|
+
const source = transcriptSourceId(lines, id);
|
|
2930
|
+
const sourceLines = source ? await load(source) : null;
|
|
2931
|
+
if (!source || !sourceLines) throw error;
|
|
2932
|
+
id = source;
|
|
2933
|
+
lines = sourceLines;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
async function rewindClaudeTranscript(projectDir, claudeSessionId, action, target) {
|
|
2938
|
+
const { kept } = await rewindAcrossLineage(async (id) => {
|
|
2939
|
+
if (id === claudeSessionId) return readTranscriptLines(projectDir, id);
|
|
2940
|
+
return readTranscriptLines(projectDir, id).catch((error) => {
|
|
2941
|
+
if (error instanceof ForkSourceMissingError) return null;
|
|
2942
|
+
throw error;
|
|
2943
|
+
});
|
|
2944
|
+
}, claudeSessionId, action, target);
|
|
2906
2945
|
if (kept === null) return null;
|
|
2907
2946
|
const newId = randomUUID();
|
|
2908
2947
|
const destination = join(projectDir, `${newId}.jsonl`);
|
|
@@ -2917,6 +2956,7 @@ async function rewindClaudeTranscript(projectDir, claudeSessionId, action, targe
|
|
|
2917
2956
|
return newId;
|
|
2918
2957
|
}
|
|
2919
2958
|
|
|
2959
|
+
const REQUEST_ID = /^[A-Za-z0-9_-]{1,100}$/;
|
|
2920
2960
|
const STOP_WAIT_MS = 8e3;
|
|
2921
2961
|
function createConversationRewind(deps) {
|
|
2922
2962
|
let inFlight = false;
|
|
@@ -2926,6 +2966,7 @@ function createConversationRewind(deps) {
|
|
|
2926
2966
|
const action = request.action;
|
|
2927
2967
|
const sourceId = typeof request.sourceId === "string" && request.sourceId.length > 0 && request.sourceId.length <= 200 ? request.sourceId : void 0;
|
|
2928
2968
|
const text = typeof request.text === "string" && request.text.length <= 2e5 ? request.text : void 0;
|
|
2969
|
+
const requestId = typeof request.requestId === "string" && REQUEST_ID.test(request.requestId) ? request.requestId : void 0;
|
|
2929
2970
|
if (action !== "edit" && action !== "delete" || !sourceId && !text?.trim()) {
|
|
2930
2971
|
return { ok: false, code: "invalid", error: "Invalid rewind request" };
|
|
2931
2972
|
}
|
|
@@ -2942,7 +2983,9 @@ function createConversationRewind(deps) {
|
|
|
2942
2983
|
if (!current) return { ok: false, code: "no-conversation", error: "The agent has no conversation to change yet" };
|
|
2943
2984
|
const uuids = sourceId ? [sourceId, ...deps.aliases(sourceId)] : [];
|
|
2944
2985
|
const next = await rewrite(deps.projectDir(), current, action, { uuids, text });
|
|
2986
|
+
const recorded = requestId && deps.beginPending ? deps.beginPending({ requestId, action, sourceClaudeSessionId: current, claudeSessionId: next, at: (deps.now ?? Date.now)() }) : null;
|
|
2945
2987
|
await deps.switchConversation(next);
|
|
2988
|
+
if (recorded) await recorded;
|
|
2946
2989
|
return { ok: true, action, freshConversation: next === null };
|
|
2947
2990
|
} catch (error) {
|
|
2948
2991
|
if (error instanceof ConversationRewindError) return { ok: false, code: error.code, error: error.message };
|
|
@@ -2954,7 +2997,326 @@ function createConversationRewind(deps) {
|
|
|
2954
2997
|
};
|
|
2955
2998
|
}
|
|
2956
2999
|
|
|
3000
|
+
const REWIND_CONFIRM_MS = 12e4;
|
|
3001
|
+
function parseRewindRecord(raw) {
|
|
3002
|
+
if (!raw || typeof raw !== "object") return null;
|
|
3003
|
+
const r = raw;
|
|
3004
|
+
if (typeof r.requestId !== "string" || !r.requestId) return null;
|
|
3005
|
+
if (r.action !== "edit" && r.action !== "delete") return null;
|
|
3006
|
+
if (typeof r.sourceClaudeSessionId !== "string" || !r.sourceClaudeSessionId) return null;
|
|
3007
|
+
if (r.claudeSessionId !== null && typeof r.claudeSessionId !== "string") return null;
|
|
3008
|
+
if (typeof r.at !== "number" || !Number.isFinite(r.at)) return null;
|
|
3009
|
+
if (typeof r.state !== "string") return null;
|
|
3010
|
+
return {
|
|
3011
|
+
requestId: r.requestId,
|
|
3012
|
+
action: r.action,
|
|
3013
|
+
sourceClaudeSessionId: r.sourceClaudeSessionId,
|
|
3014
|
+
claudeSessionId: r.claudeSessionId,
|
|
3015
|
+
at: r.at,
|
|
3016
|
+
state: r.state
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
function pendingResumeId(claudeArgs) {
|
|
3020
|
+
if (!claudeArgs) return null;
|
|
3021
|
+
const index = claudeArgs.indexOf("--resume");
|
|
3022
|
+
const next = index >= 0 ? claudeArgs[index + 1] : void 0;
|
|
3023
|
+
return next && !next.startsWith("-") && next.includes("-") ? next : null;
|
|
3024
|
+
}
|
|
3025
|
+
function decideRewind(record, confirmedRequestIds, now, currentClaudeSessionId) {
|
|
3026
|
+
if (!record || record.state !== "pending") return { kind: "none" };
|
|
3027
|
+
if (confirmedRequestIds.has(record.requestId)) return { kind: "confirm" };
|
|
3028
|
+
const deadline = record.at + REWIND_CONFIRM_MS;
|
|
3029
|
+
if (now < deadline) return { kind: "wait", ms: deadline - now };
|
|
3030
|
+
if (currentClaudeSessionId !== record.claudeSessionId) return { kind: "supersede" };
|
|
3031
|
+
return { kind: "revert", to: record.sourceClaudeSessionId };
|
|
3032
|
+
}
|
|
3033
|
+
function chainRewindRecord(next, pending) {
|
|
3034
|
+
if (!pending || pending.state !== "pending") return next;
|
|
3035
|
+
return { ...next, sourceClaudeSessionId: pending.sourceClaudeSessionId };
|
|
3036
|
+
}
|
|
3037
|
+
function transcriptDropOf(body) {
|
|
3038
|
+
const b = body;
|
|
3039
|
+
if (b?.role !== "session" || b.content?.type !== "session") return null;
|
|
3040
|
+
const ev = b.content.data?.ev;
|
|
3041
|
+
if (ev?.t !== "transcript-drop" || typeof ev.fromSeq !== "number") return null;
|
|
3042
|
+
return {
|
|
3043
|
+
fromSeq: ev.fromSeq,
|
|
3044
|
+
...typeof ev.toSeq === "number" ? { toSeq: ev.toSeq } : {},
|
|
3045
|
+
...typeof ev.requestId === "string" && ev.requestId ? { requestId: ev.requestId } : {}
|
|
3046
|
+
};
|
|
3047
|
+
}
|
|
3048
|
+
function tombstoneRequestIds(records) {
|
|
3049
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3050
|
+
for (const record of records) {
|
|
3051
|
+
const drop = transcriptDropOf(record.body);
|
|
3052
|
+
if (drop?.requestId) ids.add(drop.requestId);
|
|
3053
|
+
}
|
|
3054
|
+
return ids;
|
|
3055
|
+
}
|
|
3056
|
+
function visibleUserLocalIds(records) {
|
|
3057
|
+
const drops = [];
|
|
3058
|
+
for (const record of records) {
|
|
3059
|
+
const drop = transcriptDropOf(record.body);
|
|
3060
|
+
if (drop) drops.push({ seq: record.seq, ...drop });
|
|
3061
|
+
}
|
|
3062
|
+
const hidden = (seq) => drops.some((drop) => seq >= drop.fromSeq && seq < (drop.toSeq ?? drop.seq));
|
|
3063
|
+
return records.filter((record) => record.body?.role === "user" && typeof record.localId === "string" && record.localId).filter((record) => !hidden(record.seq)).map((record) => record.localId);
|
|
3064
|
+
}
|
|
3065
|
+
function transcriptLineage(lines, claudeSessionId) {
|
|
3066
|
+
const promptUuids = /* @__PURE__ */ new Set();
|
|
3067
|
+
for (const line of lines) {
|
|
3068
|
+
if (!line) continue;
|
|
3069
|
+
let parsed;
|
|
3070
|
+
try {
|
|
3071
|
+
parsed = JSON.parse(line);
|
|
3072
|
+
} catch {
|
|
3073
|
+
continue;
|
|
3074
|
+
}
|
|
3075
|
+
if (typeof parsed?.uuid === "string" && transcriptPromptText(parsed) !== null) promptUuids.add(parsed.uuid);
|
|
3076
|
+
}
|
|
3077
|
+
return { promptUuids, sourceClaudeSessionId: transcriptSourceId(lines, claudeSessionId) };
|
|
3078
|
+
}
|
|
3079
|
+
function decideLineageRepair(input) {
|
|
3080
|
+
if (!input.source) return { kind: "none" };
|
|
3081
|
+
const missing = input.visibleLocalIds.filter((id) => !input.current.promptUuids.has(id) && input.source.promptUuids.has(id));
|
|
3082
|
+
if (missing.length === 0) return { kind: "none" };
|
|
3083
|
+
const onlyInCurrent = input.visibleLocalIds.filter((id) => input.current.promptUuids.has(id) && !input.source.promptUuids.has(id));
|
|
3084
|
+
return { kind: "revert", to: input.source.claudeSessionId, missing, onlyInCurrent };
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
const REWIND_POLL_MS = 15e3;
|
|
3088
|
+
class RewindReconciler {
|
|
3089
|
+
constructor(deps) {
|
|
3090
|
+
this.deps = deps;
|
|
3091
|
+
}
|
|
3092
|
+
pending = null;
|
|
3093
|
+
/** The last rewind this process rolled back — a late tombstone re-applies it. */
|
|
3094
|
+
lastReverted = null;
|
|
3095
|
+
confirmedIds = /* @__PURE__ */ new Set();
|
|
3096
|
+
waiters = [];
|
|
3097
|
+
timer = null;
|
|
3098
|
+
checking = null;
|
|
3099
|
+
disposed = false;
|
|
3100
|
+
get pendingRecord() {
|
|
3101
|
+
return this.pending;
|
|
3102
|
+
}
|
|
3103
|
+
/** Synchronously marks the rewind pending; the returned promise is the metadata write. */
|
|
3104
|
+
begin(record) {
|
|
3105
|
+
const next = chainRewindRecord({ ...record, state: "pending" }, this.pending);
|
|
3106
|
+
this.pending = next;
|
|
3107
|
+
this.arm(next);
|
|
3108
|
+
this.deps.log(`[rewind] pending ${next.requestId}: ${next.sourceClaudeSessionId} -> ${next.claudeSessionId ?? "(fresh)"}`);
|
|
3109
|
+
const written = this.deps.writeRecord(next);
|
|
3110
|
+
if (this.confirmedIds.has(next.requestId)) void this.apply(next, { kind: "confirm" });
|
|
3111
|
+
return written;
|
|
3112
|
+
}
|
|
3113
|
+
/** Every inbound session record. */
|
|
3114
|
+
observe(body) {
|
|
3115
|
+
const requestId = transcriptDropOf(body)?.requestId;
|
|
3116
|
+
if (!requestId) return;
|
|
3117
|
+
this.confirmedIds.add(requestId);
|
|
3118
|
+
const record = this.pending;
|
|
3119
|
+
if (record && record.requestId === requestId) {
|
|
3120
|
+
void this.apply(record, { kind: "confirm" });
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
void this.reapplyIfReverted(requestId);
|
|
3124
|
+
}
|
|
3125
|
+
/**
|
|
3126
|
+
* The web hides the turns only AFTER it saw our record, but its tombstone
|
|
3127
|
+
* may still land after the deadline (slow outbox). The log then says
|
|
3128
|
+
* "rewound": follow it, or screen and agent disagree again. Synchronous up
|
|
3129
|
+
* to the abort, so the edited prompt that follows the tombstone is not
|
|
3130
|
+
* dequeued by the old query.
|
|
3131
|
+
*/
|
|
3132
|
+
reapplyIfReverted(requestId) {
|
|
3133
|
+
const reverted = this.lastReverted;
|
|
3134
|
+
if (this.pending || reverted?.requestId !== requestId || this.deps.currentClaudeSessionId() !== reverted.sourceClaudeSessionId) {
|
|
3135
|
+
return Promise.resolve();
|
|
3136
|
+
}
|
|
3137
|
+
this.lastReverted = null;
|
|
3138
|
+
this.deps.log(`[rewind] late tombstone for reverted ${requestId}; re-applying the rewind`);
|
|
3139
|
+
return this.deps.switchConversation(reverted.claudeSessionId).then(() => this.deps.writeRecord({ ...reverted, state: "confirmed" })).catch((error) => this.deps.log("[rewind] re-applying failed", error));
|
|
3140
|
+
}
|
|
3141
|
+
/** Resolves when no rewind is pending (or `signal` aborts). */
|
|
3142
|
+
settled(signal) {
|
|
3143
|
+
if (!this.pending || signal?.aborted) return Promise.resolve();
|
|
3144
|
+
return new Promise((resolve) => {
|
|
3145
|
+
const done = () => {
|
|
3146
|
+
signal?.removeEventListener("abort", done);
|
|
3147
|
+
resolve();
|
|
3148
|
+
};
|
|
3149
|
+
this.waiters.push(done);
|
|
3150
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
check() {
|
|
3154
|
+
if (!this.checking) {
|
|
3155
|
+
this.checking = this.runCheck().finally(() => {
|
|
3156
|
+
this.checking = null;
|
|
3157
|
+
});
|
|
3158
|
+
}
|
|
3159
|
+
return this.checking;
|
|
3160
|
+
}
|
|
3161
|
+
/** Wrapper start / resume: decide a leftover pending record, else repair a legacy split. */
|
|
3162
|
+
async startup() {
|
|
3163
|
+
const record = parseRewindRecord(this.deps.readRecord());
|
|
3164
|
+
if (record?.state === "pending") {
|
|
3165
|
+
this.pending = chainRewindRecord(record, this.pending);
|
|
3166
|
+
this.deps.log(`[rewind] startup: pending record ${record.requestId} from ${new Date(record.at).toISOString()}`);
|
|
3167
|
+
await this.check();
|
|
3168
|
+
return;
|
|
3169
|
+
}
|
|
3170
|
+
if (record?.state === "reverted") {
|
|
3171
|
+
this.lastReverted = record;
|
|
3172
|
+
if (tombstoneRequestIds(await this.deps.readLog()).has(record.requestId)) {
|
|
3173
|
+
await this.reapplyIfReverted(record.requestId);
|
|
3174
|
+
return;
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
await this.repairLineage();
|
|
3178
|
+
}
|
|
3179
|
+
dispose() {
|
|
3180
|
+
this.disposed = true;
|
|
3181
|
+
this.clearTimer();
|
|
3182
|
+
this.release();
|
|
3183
|
+
}
|
|
3184
|
+
arm(record, ms) {
|
|
3185
|
+
if (this.disposed) return;
|
|
3186
|
+
if (this.timer) clearTimeout(this.timer);
|
|
3187
|
+
const wait = ms ?? Math.min(REWIND_POLL_MS, Math.max(0, decideWaitMs(record, this.deps.now())));
|
|
3188
|
+
this.timer = setTimeout(() => {
|
|
3189
|
+
this.timer = null;
|
|
3190
|
+
void this.check().catch((error) => this.deps.log("[rewind] check failed", error));
|
|
3191
|
+
}, wait);
|
|
3192
|
+
this.timer.unref?.();
|
|
3193
|
+
}
|
|
3194
|
+
async runCheck() {
|
|
3195
|
+
const record = this.pending;
|
|
3196
|
+
if (!record) return;
|
|
3197
|
+
let decision = this.decide(record);
|
|
3198
|
+
if (decision.kind !== "confirm" && decision.kind !== "none") {
|
|
3199
|
+
try {
|
|
3200
|
+
for (const id of tombstoneRequestIds(await this.deps.readLog())) this.confirmedIds.add(id);
|
|
3201
|
+
} catch (error) {
|
|
3202
|
+
this.deps.log("[rewind] reading the session log failed; retrying", error);
|
|
3203
|
+
if (this.pending === record) this.arm(record, REWIND_POLL_MS);
|
|
3204
|
+
return;
|
|
3205
|
+
}
|
|
3206
|
+
if (this.pending !== record) return;
|
|
3207
|
+
decision = this.decide(record);
|
|
3208
|
+
}
|
|
3209
|
+
await this.apply(record, decision);
|
|
3210
|
+
}
|
|
3211
|
+
decide(record) {
|
|
3212
|
+
return decideRewind(record, this.confirmedIds, this.deps.now(), this.deps.currentClaudeSessionId());
|
|
3213
|
+
}
|
|
3214
|
+
async apply(record, decision) {
|
|
3215
|
+
if (this.pending !== record) return;
|
|
3216
|
+
switch (decision.kind) {
|
|
3217
|
+
case "none":
|
|
3218
|
+
this.pending = null;
|
|
3219
|
+
this.release();
|
|
3220
|
+
return;
|
|
3221
|
+
case "wait":
|
|
3222
|
+
this.arm(record);
|
|
3223
|
+
return;
|
|
3224
|
+
case "confirm":
|
|
3225
|
+
this.finish(record, "confirmed");
|
|
3226
|
+
return;
|
|
3227
|
+
case "supersede":
|
|
3228
|
+
this.deps.log(`[rewind] ${record.requestId} unconfirmed but the agent already moved on; closing it`);
|
|
3229
|
+
this.finish(record, "superseded");
|
|
3230
|
+
return;
|
|
3231
|
+
case "revert": {
|
|
3232
|
+
this.deps.log(`[rewind] ${record.requestId} never confirmed by the log; switching back to ${decision.to}`);
|
|
3233
|
+
this.pending = null;
|
|
3234
|
+
this.clearTimer();
|
|
3235
|
+
this.lastReverted = record;
|
|
3236
|
+
try {
|
|
3237
|
+
await this.deps.switchConversation(decision.to);
|
|
3238
|
+
} catch (error) {
|
|
3239
|
+
this.deps.log("[rewind] switching back failed; retrying", error);
|
|
3240
|
+
if (!this.pending && this.lastReverted === record) {
|
|
3241
|
+
this.lastReverted = null;
|
|
3242
|
+
this.pending = record;
|
|
3243
|
+
this.arm(record, REWIND_POLL_MS);
|
|
3244
|
+
}
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
if (this.lastReverted === record) this.record(record, "reverted");
|
|
3248
|
+
if (!this.pending) this.release();
|
|
3249
|
+
return;
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
finish(record, state) {
|
|
3254
|
+
if (this.pending !== record) return;
|
|
3255
|
+
this.pending = null;
|
|
3256
|
+
this.clearTimer();
|
|
3257
|
+
this.lastReverted = null;
|
|
3258
|
+
this.record(record, state);
|
|
3259
|
+
this.release();
|
|
3260
|
+
}
|
|
3261
|
+
record(record, state) {
|
|
3262
|
+
this.deps.log(`[rewind] ${record.requestId} ${state}`);
|
|
3263
|
+
void this.deps.writeRecord({ ...record, state }).catch((error) => this.deps.log("[rewind] recording state failed", error));
|
|
3264
|
+
}
|
|
3265
|
+
clearTimer() {
|
|
3266
|
+
if (this.timer) clearTimeout(this.timer);
|
|
3267
|
+
this.timer = null;
|
|
3268
|
+
}
|
|
3269
|
+
release() {
|
|
3270
|
+
const waiters = this.waiters;
|
|
3271
|
+
this.waiters = [];
|
|
3272
|
+
for (const resolve of waiters) resolve();
|
|
3273
|
+
}
|
|
3274
|
+
async repairLineage() {
|
|
3275
|
+
const current = this.deps.currentClaudeSessionId();
|
|
3276
|
+
if (!current) return;
|
|
3277
|
+
const lines = await this.deps.readTranscript(current);
|
|
3278
|
+
if (!lines) return;
|
|
3279
|
+
const lineage = transcriptLineage(lines, current);
|
|
3280
|
+
if (!lineage.sourceClaudeSessionId) return;
|
|
3281
|
+
const sourceLines = await this.deps.readTranscript(lineage.sourceClaudeSessionId);
|
|
3282
|
+
if (!sourceLines) return;
|
|
3283
|
+
const source = transcriptLineage(sourceLines, lineage.sourceClaudeSessionId);
|
|
3284
|
+
const repair = decideLineageRepair({
|
|
3285
|
+
visibleLocalIds: visibleUserLocalIds(await this.deps.readLog()),
|
|
3286
|
+
current: lineage,
|
|
3287
|
+
source: { claudeSessionId: lineage.sourceClaudeSessionId, promptUuids: source.promptUuids }
|
|
3288
|
+
});
|
|
3289
|
+
if (repair.kind === "none") return;
|
|
3290
|
+
if (this.pending || this.deps.currentClaudeSessionId() !== current) return;
|
|
3291
|
+
this.deps.log(`[rewind] startup: ${current} is an unconfirmed rewound copy (${repair.missing.length} visible prompt(s) only in ${repair.to}); switching back`, {
|
|
3292
|
+
missing: repair.missing,
|
|
3293
|
+
forgottenAfterSplit: repair.onlyInCurrent
|
|
3294
|
+
});
|
|
3295
|
+
await this.deps.switchConversation(repair.to);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
function decideWaitMs(record, now) {
|
|
3299
|
+
const decision = decideRewind(record, /* @__PURE__ */ new Set(), now, record.claudeSessionId);
|
|
3300
|
+
return decision.kind === "wait" ? decision.ms : 0;
|
|
3301
|
+
}
|
|
3302
|
+
async function persistRewindRecord(client, record, opts = {}) {
|
|
3303
|
+
const owns = (raw) => {
|
|
3304
|
+
const existing = parseRewindRecord(raw);
|
|
3305
|
+
return record.state === "pending" || !existing || existing.requestId === record.requestId;
|
|
3306
|
+
};
|
|
3307
|
+
if (!owns(client.getMetadata()?.rewind)) return;
|
|
3308
|
+
client.updateMetadata((metadata) => owns(metadata?.rewind) ? { ...metadata, rewind: record } : metadata);
|
|
3309
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 8e3);
|
|
3310
|
+
while (Date.now() < deadline) {
|
|
3311
|
+
const current = parseRewindRecord(client.getMetadata()?.rewind);
|
|
3312
|
+
if (current?.requestId === record.requestId && current.state === record.state) return;
|
|
3313
|
+
await new Promise((resolve) => setTimeout(resolve, opts.pollMs ?? 100));
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
|
|
2957
3317
|
const ABORT_INTERRUPT_GRACE_MS = 4e3;
|
|
3318
|
+
const REWIND_LOG_WINDOW = 500;
|
|
3319
|
+
const REWIND_STARTUP_BUDGET_MS = 15e3;
|
|
2958
3320
|
async function claudeRemoteLauncher(session, onPermissionModeChange, onEffectivePermissionMode, onPromptFinalized) {
|
|
2959
3321
|
logger.debug("[claudeRemoteLauncher] Starting remote launcher");
|
|
2960
3322
|
const hasTTY = process.stdout.isTTY && process.stdin.isTTY;
|
|
@@ -3056,8 +3418,35 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3056
3418
|
return first;
|
|
3057
3419
|
};
|
|
3058
3420
|
let silentRelaunch = false;
|
|
3421
|
+
const agentConversationId = () => session.sessionId ?? pendingResumeId(session.claudeArgs);
|
|
3422
|
+
const switchConversation = async (claudeSessionId) => {
|
|
3423
|
+
if (claudeSessionId) session.onSessionFound(claudeSessionId);
|
|
3424
|
+
else session.clearSessionId();
|
|
3425
|
+
if (!abortController || abortController.signal.aborted) return;
|
|
3426
|
+
silentRelaunch = true;
|
|
3427
|
+
await abort();
|
|
3428
|
+
};
|
|
3429
|
+
const rewindReconciler = new RewindReconciler({
|
|
3430
|
+
now: Date.now,
|
|
3431
|
+
readRecord: () => session.client.getMetadata()?.rewind,
|
|
3432
|
+
writeRecord: (record) => persistRewindRecord(session.client, record),
|
|
3433
|
+
readLog: () => session.client.readLogTail(REWIND_LOG_WINDOW),
|
|
3434
|
+
currentClaudeSessionId: () => agentConversationId(),
|
|
3435
|
+
readTranscript: async (claudeSessionId) => {
|
|
3436
|
+
try {
|
|
3437
|
+
return (await readFile(join(getProjectPath(session.path), `${claudeSessionId}.jsonl`), "utf-8")).split("\n");
|
|
3438
|
+
} catch (error) {
|
|
3439
|
+
if (error.code === "ENOENT") return null;
|
|
3440
|
+
throw error;
|
|
3441
|
+
}
|
|
3442
|
+
},
|
|
3443
|
+
switchConversation,
|
|
3444
|
+
log: (message, data) => logger.debug(message, data)
|
|
3445
|
+
});
|
|
3446
|
+
const observeSessionRecord = (body) => rewindReconciler.observe(body);
|
|
3447
|
+
session.client.on("message", observeSessionRecord);
|
|
3059
3448
|
session.client.rpcHandlerManager.registerHandler("conversation-rewind", createConversationRewind({
|
|
3060
|
-
claudeSessionId: () =>
|
|
3449
|
+
claudeSessionId: () => agentConversationId(),
|
|
3061
3450
|
projectDir: () => getProjectPath(session.path),
|
|
3062
3451
|
isThinking: () => session.thinking,
|
|
3063
3452
|
stopTurn: doAbort,
|
|
@@ -3066,12 +3455,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3066
3455
|
const alias = promptAliases.get(sourceId);
|
|
3067
3456
|
return alias ? [alias] : [];
|
|
3068
3457
|
},
|
|
3069
|
-
switchConversation
|
|
3070
|
-
|
|
3071
|
-
else session.clearSessionId();
|
|
3072
|
-
silentRelaunch = true;
|
|
3073
|
-
await abort();
|
|
3074
|
-
}
|
|
3458
|
+
switchConversation,
|
|
3459
|
+
beginPending: (record) => rewindReconciler.begin(record)
|
|
3075
3460
|
}));
|
|
3076
3461
|
let livePermissionModeHandler = null;
|
|
3077
3462
|
let idlePermissionModeHandler = null;
|
|
@@ -3229,6 +3614,10 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3229
3614
|
try {
|
|
3230
3615
|
const modeGate = new LaunchModeGate(session.queue.modeHasher);
|
|
3231
3616
|
let previousSessionId = null;
|
|
3617
|
+
await Promise.race([
|
|
3618
|
+
rewindReconciler.startup().catch((error) => logger.debug("[rewind] startup reconcile failed", error)),
|
|
3619
|
+
new Promise((resolve) => setTimeout(resolve, REWIND_STARTUP_BUDGET_MS).unref?.())
|
|
3620
|
+
]);
|
|
3232
3621
|
while (!exitReason) {
|
|
3233
3622
|
logger.debug("[remote]: launch");
|
|
3234
3623
|
messageBuffer.addMessage("\u2550".repeat(40), "status");
|
|
@@ -3285,6 +3674,7 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3285
3674
|
if (typeof parked.message === "string") onPromptFinalized?.(parked.message);
|
|
3286
3675
|
return parked;
|
|
3287
3676
|
}
|
|
3677
|
+
await rewindReconciler.settled(controller.signal);
|
|
3288
3678
|
let msg = await session.queue.waitForMessagesAndGetAsString(controller.signal);
|
|
3289
3679
|
if (msg) {
|
|
3290
3680
|
if (modeGate.requiresRelaunch(msg.hash, msg.isolate)) {
|
|
@@ -3477,6 +3867,8 @@ async function claudeRemoteLauncher(session, onPermissionModeChange, onEffective
|
|
|
3477
3867
|
}
|
|
3478
3868
|
}
|
|
3479
3869
|
} finally {
|
|
3870
|
+
session.client.off("message", observeSessionRecord);
|
|
3871
|
+
rewindReconciler.dispose();
|
|
3480
3872
|
permissionHandler.reset();
|
|
3481
3873
|
const t0 = Date.now();
|
|
3482
3874
|
logger.debug(`[remote]: cleanup begin exitReason=${exitReason} hasInk=${!!inkInstance} rawMode=${process.stdin.isRaw}`);
|
|
@@ -3526,7 +3918,7 @@ async function loop(opts) {
|
|
|
3526
3918
|
logger.debug(`[loop] Iteration with mode: ${mode}`);
|
|
3527
3919
|
switch (mode) {
|
|
3528
3920
|
case "local": {
|
|
3529
|
-
const { claudeLocalLauncher } = await import('./claudeLocalLauncher-
|
|
3921
|
+
const { claudeLocalLauncher } = await import('./claudeLocalLauncher-CKazNnl0.mjs');
|
|
3530
3922
|
const result = await claudeLocalLauncher(session);
|
|
3531
3923
|
switch (result.type) {
|
|
3532
3924
|
case "switch":
|