@zonease/happy 0.6.56 → 0.6.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/{api-9wvM_aF-.mjs → api-B9shq-xZ.mjs} +47 -12
  2. package/dist/{api-BGc484qf.cjs → api-ByiU9yXy.cjs} +51 -12
  3. package/dist/{auth-CPfJalJM.cjs → auth-BG6e5Uem.cjs} +4 -4
  4. package/dist/{auth-DqAM-lIh.mjs → auth-BRh7v1qh.mjs} +4 -4
  5. package/dist/{auth-B6vskzfm.cjs → auth-DnFrlXqp.cjs} +2 -2
  6. package/dist/{auth-BnEa31tI.mjs → auth-DnRtIM3d.mjs} +2 -2
  7. package/dist/{browser-CkQP96Zi.mjs → browser-BeERlPhN.mjs} +1 -1
  8. package/dist/{browser-CnxzD1lA.cjs → browser-DjONS-B5.cjs} +1 -1
  9. package/dist/{claudeLocal-B5uxtoit.mjs → claudeLocal-CYtFfvTZ.mjs} +1 -1
  10. package/dist/{claudeLocal-CV4fT0Gg.cjs → claudeLocal-CuHH7tvQ.cjs} +1 -1
  11. package/dist/{config-C__p7EWC.cjs → config-BHwOLuFT.cjs} +1 -1
  12. package/dist/{config-C9hdBdfj.mjs → config-BkUfgaM5.mjs} +1 -1
  13. package/dist/{connect-DQjpjfYn.cjs → connect-B9rWe2GY.cjs} +4 -4
  14. package/dist/{connect-BeORCRXq.mjs → connect-BoTU3RCi.mjs} +4 -4
  15. package/dist/{controlClient-DWBW6jRF.cjs → controlClient-BqCwo6Pm.cjs} +1 -1
  16. package/dist/{controlClient-VY0CGL8k.mjs → controlClient-BuKaeD-y.mjs} +1 -1
  17. package/dist/{cursorApprovalHook-D_8btpsY.mjs → cursorApprovalHook-BADH_Ul1.mjs} +2 -2
  18. package/dist/{cursorApprovalHook-BuDSRM-6.cjs → cursorApprovalHook-Ckdd65co.cjs} +2 -2
  19. package/dist/{cursorApprovalServer-j9RphnEG.cjs → cursorApprovalServer--suu8J98.cjs} +1 -1
  20. package/dist/{cursorApprovalServer-BOUd2-Fg.mjs → cursorApprovalServer-BeTT3FNN.mjs} +1 -1
  21. package/dist/{deviceKeys-c_sN01Mm.cjs → deviceKeys-CSfs6juX.cjs} +2 -2
  22. package/dist/{deviceKeys-DvfaTff3.mjs → deviceKeys-DSXcQgLf.mjs} +2 -2
  23. package/dist/{doctor-DQtQbfG-.mjs → doctor-C77QV3rd.mjs} +2 -2
  24. package/dist/{doctor-CD46A-_Y.cjs → doctor-CxWWwoLX.cjs} +2 -2
  25. package/dist/{downloadImage-B6A4x8Jw.mjs → downloadImage-C3FHGZDr.mjs} +1 -1
  26. package/dist/{downloadImage-DGdHCFi3.cjs → downloadImage-DZBxkdwy.cjs} +1 -1
  27. package/dist/{enroll-D9CEuRI_.cjs → enroll-BjZCaXT4.cjs} +3 -3
  28. package/dist/{enroll-CyHWNKNt.mjs → enroll-D5V8LH6P.mjs} +3 -3
  29. package/dist/{evidence-BuYebdrN.mjs → evidence-DL-E4Qfd.mjs} +1 -1
  30. package/dist/{evidence-CCrpzsTA.cjs → evidence-DbFF210m.cjs} +1 -1
  31. package/dist/{formatImageMessage-5qaaT_Wq.mjs → formatImageMessage-C6glTFta.mjs} +1 -1
  32. package/dist/{formatImageMessage-DttKW75w.cjs → formatImageMessage-CHjdeDGM.cjs} +1 -1
  33. package/dist/index.cjs +46 -46
  34. package/dist/index.mjs +46 -46
  35. package/dist/{install-B0hT_tLv.cjs → install-9E-3IeF3.cjs} +2 -2
  36. package/dist/{install-eIXFuZbC.mjs → install-BPCWw2Vc.mjs} +2 -2
  37. package/dist/{install-1Y6dAcMp.mjs → install-DbRGuSWv.mjs} +1 -1
  38. package/dist/{install-C4cwObCN.cjs → install-Td8RvuEV.cjs} +1 -1
  39. package/dist/lib.cjs +3 -3
  40. package/dist/lib.d.cts +10 -0
  41. package/dist/lib.d.mts +10 -0
  42. package/dist/lib.mjs +3 -3
  43. package/dist/{loadableToolOutput-BKDTnyoF.mjs → loadableToolOutput-C0tAWFJM.mjs} +2 -2
  44. package/dist/{loadableToolOutput-Cb-18__b.cjs → loadableToolOutput-C5EQglQm.cjs} +2 -2
  45. package/dist/{persistence-CNXsXPLm.cjs → persistence-50wmDoBE.cjs} +1 -1
  46. package/dist/{persistence-IdEuIeMz.mjs → persistence-Da0uhblK.mjs} +2 -2
  47. package/dist/{push-tXs96IyG.mjs → push-BR82p4YC.mjs} +6 -6
  48. package/dist/{push-XL6Sb0Vw.cjs → push-Bbf139Sy.cjs} +6 -6
  49. package/dist/{registerKillSessionHandler-D9tmPdw5.cjs → registerKillSessionHandler-CHPzUrtO.cjs} +3 -3
  50. package/dist/{registerKillSessionHandler-vF5c8YZF.mjs → registerKillSessionHandler-CxHjAcQu.mjs} +3 -3
  51. package/dist/{run-BKfeeheJ.cjs → run-C6hmGRwH.cjs} +167 -8
  52. package/dist/{run-BvpCwXkt.mjs → run-DjaUrH7x.mjs} +167 -8
  53. package/dist/{runClaude-DDsG7eMR.cjs → runClaude-BR15B5bw.cjs} +20 -19
  54. package/dist/{runClaude-BiVqZQOm.mjs → runClaude-CKFHv0nI.mjs} +19 -18
  55. package/dist/{runCodex-C-8SvnpP.mjs → runCodex-BAlT1EGt.mjs} +18 -17
  56. package/dist/{runCodex-Bh519-dW.cjs → runCodex-BpVY3LQi.cjs} +18 -17
  57. package/dist/{runCursor-CYbvOqUa.cjs → runCursor-BUx34tPB.cjs} +18 -17
  58. package/dist/{runCursor-3AFNF0y2.mjs → runCursor-Dj3orwMw.mjs} +18 -17
  59. package/dist/{runGemini-ExHXGZBY.cjs → runGemini-Bdzns1qW.cjs} +20 -19
  60. package/dist/{runGemini-Dh2JRfOJ.mjs → runGemini-SEsV1VfH.mjs} +20 -19
  61. package/dist/{runOneShot-CVcw-K0_.mjs → runOneShot-BTHgA1q4.mjs} +2 -2
  62. package/dist/{runOneShot-CEVKtkx_.cjs → runOneShot-CK10IG0U.cjs} +2 -2
  63. package/dist/{serve-C4dOQ0jP.mjs → serve-BErPXI_R.mjs} +7 -6
  64. package/dist/{serve-D0IhhySV.cjs → serve-BHe5QkCA.cjs} +7 -6
  65. package/dist/{session-CwMxRPXS.mjs → session-CZyeSNaA.mjs} +6 -5
  66. package/dist/{session-DK9eudJT.cjs → session-FttaWXf3.cjs} +6 -5
  67. package/dist/sessionDecrypt-BsOlrqRs.mjs +64 -0
  68. package/dist/sessionDecrypt-DWm_k5dq.cjs +66 -0
  69. package/dist/{sessionKeyCache-DDzTs7E5.mjs → sessionKeyCache-BBzsFcnN.mjs} +1 -1
  70. package/dist/{sessionKeyCache-JjjYAxdf.cjs → sessionKeyCache-CmORI8jN.cjs} +1 -1
  71. package/dist/{sessionList-IYAtPIev.mjs → sessionList-D_Y-1Cir.mjs} +2 -2
  72. package/dist/{sessionList-DZmmAP3q.cjs → sessionList-lxpW_76R.cjs} +3 -3
  73. package/dist/{sessionSummary-CsIfkyZA.cjs → sessionSummary-BP2T8GHr.cjs} +3 -64
  74. package/dist/{sessionSummary-CQQyTHRC.mjs → sessionSummary-YLlUeUre.mjs} +3 -63
  75. package/dist/{setupOfflineReconnection-C1yzDMt6.mjs → setupOfflineReconnection-B4aU1Nix.mjs} +3 -3
  76. package/dist/{setupOfflineReconnection-DwtIEUeJ.cjs → setupOfflineReconnection-CldeNWUW.cjs} +3 -3
  77. package/dist/{spawnHappyCLI-BbMkZhMk.cjs → spawnHappyCLI-BNUBk0w5.cjs} +1 -1
  78. package/dist/{spawnHappyCLI-DlTg87jS.mjs → spawnHappyCLI-Cv2VARTw.mjs} +1 -1
  79. package/dist/{ssh-DSVjanff.mjs → ssh-CBvM1RVJ.mjs} +5 -5
  80. package/dist/{ssh-D31o750w.cjs → ssh-DXOMR-gb.cjs} +5 -5
  81. package/dist/{task-D9ZjWCcw.mjs → task-CQonykFe.mjs} +7 -6
  82. package/dist/{task--Apxd9oF.cjs → task-DrX3H3_Y.cjs} +7 -6
  83. package/dist/{uninstall-Bo2uaLRP.mjs → uninstall-BijW1rTR.mjs} +2 -2
  84. package/dist/{uninstall-CZJcoC06.cjs → uninstall-CPQjax_f.cjs} +2 -2
  85. package/dist/{update-BiV4YqG3.mjs → update-DaJjoz93.mjs} +3 -3
  86. package/dist/{update-D-bTjP2k.cjs → update-g3D05Tvv.cjs} +3 -3
  87. package/package.json +1 -1
package/dist/lib.mjs CHANGED
@@ -1,5 +1,5 @@
1
- export { A as ApiClient, a as ApiSessionClient } from './api-9wvM_aF-.mjs';
2
- export { c as configuration, l as logger } from './persistence-IdEuIeMz.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient } from './api-B9shq-xZ.mjs';
2
+ export { c as configuration, l as logger } from './persistence-Da0uhblK.mjs';
3
3
  export { R as RawJSONLinesSchema } from './types-BoJh4Qfv.mjs';
4
4
  import 'axios';
5
5
  import 'node:events';
@@ -28,6 +28,6 @@ import 'crypto';
28
28
  import 'tweetnacl';
29
29
  import '@stablelib/base64';
30
30
  import 'expo-server-sdk';
31
- import './sessionKeyCache-DDzTs7E5.mjs';
31
+ import './sessionKeyCache-BBzsFcnN.mjs';
32
32
  import 'chalk';
33
33
  import 'fs';
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { l as logger } from './persistence-IdEuIeMz.mjs';
3
- import { s as saveToolOutputRecord } from './api-9wvM_aF-.mjs';
2
+ import { l as logger } from './persistence-Da0uhblK.mjs';
3
+ import { s as saveToolOutputRecord } from './api-B9shq-xZ.mjs';
4
4
 
5
5
  class BaseReasoningProcessor {
6
6
  accumulator = "";
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var node_crypto = require('node:crypto');
4
- var logger = require('./persistence-CNXsXPLm.cjs');
5
- var api = require('./api-BGc484qf.cjs');
4
+ var logger = require('./persistence-50wmDoBE.cjs');
5
+ var api = require('./api-ByiU9yXy.cjs');
6
6
 
7
7
  class BaseReasoningProcessor {
8
8
  accumulator = "";
@@ -35,7 +35,7 @@ function isDebug() {
35
35
  }
36
36
 
37
37
  var name = "@zonease/happy";
38
- var version = "0.6.56";
38
+ var version = "0.6.58";
39
39
  var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
40
40
  var author = "ZonEaseTech";
41
41
  var license = "MIT";
@@ -14,7 +14,7 @@ function isDebug() {
14
14
  }
15
15
 
16
16
  var name = "@zonease/happy";
17
- var version = "0.6.56";
17
+ var version = "0.6.58";
18
18
  var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
19
19
  var author = "ZonEaseTech";
20
20
  var license = "MIT";
@@ -944,4 +944,4 @@ var persistence = /*#__PURE__*/Object.freeze({
944
944
  writeDaemonState: writeDaemonState
945
945
  });
946
946
 
947
- export { getProfileEnvironmentVariables as A, encryptLegacy as B, getRandomBytes as C, libsodiumEncryptForPublicKey as D, logger$1 as E, persistence as F, readSettings as a, clearCredentials as b, configuration as c, clearMachineId as d, encodeBase64 as e, encrypt as f, decrypt as g, decodeBase64 as h, isDebug as i, encryptWithDataKey as j, decryptWithDataKey as k, logger as l, readDaemonState as m, clearDaemonState as n, libsodiumPublicKeyFromSecretKey as o, packageJson as p, decryptLegacy as q, readCredentials as r, encodeBase64Url as s, writeCredentialsLegacy as t, updateSettings as u, acquireDaemonLock as v, writeCredentialsDataKey as w, writeDaemonState as x, releaseDaemonLock as y, validateProfileForAgent as z };
947
+ export { getProfileEnvironmentVariables as A, encryptLegacy as B, getRandomBytes as C, libsodiumEncryptForPublicKey as D, logger$1 as E, persistence as F, readSettings as a, clearCredentials as b, configuration as c, clearMachineId as d, encodeBase64 as e, encrypt as f, decrypt as g, decodeBase64 as h, isDebug as i, encryptWithDataKey as j, decryptWithDataKey as k, logger as l, readDaemonState as m, clearDaemonState as n, decryptLegacy as o, packageJson as p, libsodiumPublicKeyFromSecretKey as q, readCredentials as r, encodeBase64Url as s, writeCredentialsLegacy as t, updateSettings as u, acquireDaemonLock as v, writeCredentialsDataKey as w, writeDaemonState as x, releaseDaemonLock as y, validateProfileForAgent as z };
@@ -1,7 +1,7 @@
1
1
  import { stat, readFile } from 'node:fs/promises';
2
2
  import { io } from 'socket.io-client';
3
- import { c as configuration, e as encodeBase64, f as encrypt, g as decrypt, h as decodeBase64 } from './persistence-IdEuIeMz.mjs';
4
- import { resolveDeviceForCommand } from './ssh-DSVjanff.mjs';
3
+ import { c as configuration, e as encodeBase64, f as encrypt, g as decrypt, h as decodeBase64 } from './persistence-Da0uhblK.mjs';
4
+ import { resolveDeviceForCommand } from './ssh-CBvM1RVJ.mjs';
5
5
  import 'node:fs';
6
6
  import 'node:os';
7
7
  import 'node:path';
@@ -10,16 +10,16 @@ import 'node:crypto';
10
10
  import 'tweetnacl';
11
11
  import 'chalk';
12
12
  import 'fs';
13
- import './deviceKeys-DvfaTff3.mjs';
13
+ import './deviceKeys-DSXcQgLf.mjs';
14
14
  import 'axios';
15
- import './auth-BnEa31tI.mjs';
15
+ import './auth-DnRtIM3d.mjs';
16
16
  import 'qrcode-terminal';
17
17
  import './time-DgsBLJA_.mjs';
18
- import './browser-CkQP96Zi.mjs';
18
+ import './browser-BeERlPhN.mjs';
19
19
  import 'open';
20
20
  import 'react';
21
21
  import 'ink';
22
- import './controlClient-VY0CGL8k.mjs';
22
+ import './controlClient-BuKaeD-y.mjs';
23
23
  import './projectPath-BTBIMB57.mjs';
24
24
  import 'path';
25
25
  import 'url';
@@ -2,8 +2,8 @@
2
2
 
3
3
  var promises = require('node:fs/promises');
4
4
  var socket_ioClient = require('socket.io-client');
5
- var logger = require('./persistence-CNXsXPLm.cjs');
6
- var ssh = require('./ssh-D31o750w.cjs');
5
+ var logger = require('./persistence-50wmDoBE.cjs');
6
+ var ssh = require('./ssh-DXOMR-gb.cjs');
7
7
  require('node:fs');
8
8
  require('node:os');
9
9
  require('node:path');
@@ -12,16 +12,16 @@ require('node:crypto');
12
12
  require('tweetnacl');
13
13
  require('chalk');
14
14
  require('fs');
15
- require('./deviceKeys-c_sN01Mm.cjs');
15
+ require('./deviceKeys-CSfs6juX.cjs');
16
16
  require('axios');
17
- require('./auth-B6vskzfm.cjs');
17
+ require('./auth-DnFrlXqp.cjs');
18
18
  require('qrcode-terminal');
19
19
  require('./time-Bj2HRkKH.cjs');
20
- require('./browser-CnxzD1lA.cjs');
20
+ require('./browser-DjONS-B5.cjs');
21
21
  require('open');
22
22
  require('react');
23
23
  require('ink');
24
- require('./controlClient-DWBW6jRF.cjs');
24
+ require('./controlClient-BqCwo6Pm.cjs');
25
25
  require('./projectPath-ChLhdOyt.cjs');
26
26
  require('path');
27
27
  require('url');
@@ -7,8 +7,8 @@ var node_http = require('node:http');
7
7
  var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
8
8
  var types_js = require('@modelcontextprotocol/sdk/types.js');
9
9
  var z = require('zod');
10
- var logger = require('./persistence-CNXsXPLm.cjs');
11
- var deviceKeys = require('./deviceKeys-c_sN01Mm.cjs');
10
+ var logger = require('./persistence-50wmDoBE.cjs');
11
+ var deviceKeys = require('./deviceKeys-CSfs6juX.cjs');
12
12
  var axios = require('axios');
13
13
  var promises = require('node:fs/promises');
14
14
  var node_crypto = require('node:crypto');
@@ -18,7 +18,7 @@ require('./index-DBev4hhV.cjs');
18
18
  var node_child_process = require('node:child_process');
19
19
  require('node:events');
20
20
  require('socket.io-client');
21
- require('./api-BGc484qf.cjs');
21
+ require('./api-ByiU9yXy.cjs');
22
22
  require('tweetnacl');
23
23
  require('ws');
24
24
  require('crypto');
@@ -5,8 +5,8 @@ import { createServer } from 'node:http';
5
5
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
6
  import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
7
7
  import { z } from 'zod';
8
- import { c as configuration, l as logger, r as readCredentials } from './persistence-IdEuIeMz.mjs';
9
- import { l as listDevices, d as deviceExec } from './deviceKeys-DvfaTff3.mjs';
8
+ import { c as configuration, l as logger, r as readCredentials } from './persistence-Da0uhblK.mjs';
9
+ import { l as listDevices, d as deviceExec } from './deviceKeys-DSXcQgLf.mjs';
10
10
  import axios from 'axios';
11
11
  import { stat, readFile } from 'node:fs/promises';
12
12
  import { randomUUID } from 'node:crypto';
@@ -16,7 +16,7 @@ import './index-7P6T8CE4.mjs';
16
16
  import { execSync } from 'node:child_process';
17
17
  import 'node:events';
18
18
  import 'socket.io-client';
19
- import './api-9wvM_aF-.mjs';
19
+ import './api-B9shq-xZ.mjs';
20
20
  import 'tweetnacl';
21
21
  import 'ws';
22
22
  import 'crypto';
@@ -3,15 +3,17 @@
3
3
  var fs$1 = require('fs/promises');
4
4
  var os = require('os');
5
5
  var tmp = require('tmp');
6
- var api = require('./api-BGc484qf.cjs');
7
- var logger = require('./persistence-CNXsXPLm.cjs');
8
- var auth = require('./auth-B6vskzfm.cjs');
6
+ var api = require('./api-ByiU9yXy.cjs');
7
+ var logger = require('./persistence-50wmDoBE.cjs');
8
+ var doctor$1 = require('./doctor-C08m5Z9f.cjs');
9
+ var sessionDecrypt = require('./sessionDecrypt-DWm_k5dq.cjs');
10
+ var auth = require('./auth-DnFrlXqp.cjs');
9
11
  var child_process = require('child_process');
10
- var doctor = require('./doctor-CD46A-_Y.cjs');
11
- var spawnHappyCLI = require('./spawnHappyCLI-BbMkZhMk.cjs');
12
- var controlClient = require('./controlClient-DWBW6jRF.cjs');
13
- var deviceKeys = require('./deviceKeys-c_sN01Mm.cjs');
14
- var install = require('./install-C4cwObCN.cjs');
12
+ var doctor = require('./doctor-CxWWwoLX.cjs');
13
+ var spawnHappyCLI = require('./spawnHappyCLI-BNUBk0w5.cjs');
14
+ var controlClient = require('./controlClient-BqCwo6Pm.cjs');
15
+ var deviceKeys = require('./deviceKeys-CSfs6juX.cjs');
16
+ var install = require('./install-Td8RvuEV.cjs');
15
17
  var fastify = require('fastify');
16
18
  var fs = require('node:fs');
17
19
  var promises = require('node:fs/promises');
@@ -42,6 +44,104 @@ function _interopNamespaceDefault(e) {
42
44
 
43
45
  var tmp__namespace = /*#__PURE__*/_interopNamespaceDefault(tmp);
44
46
 
47
+ function pickAgent(metadata) {
48
+ switch (metadata.flavor) {
49
+ case "codex":
50
+ case "gemini":
51
+ case "cursor":
52
+ return metadata.flavor;
53
+ default:
54
+ return "claude";
55
+ }
56
+ }
57
+ function pickForkSource(id, agent, metadata) {
58
+ switch (agent) {
59
+ case "claude":
60
+ return typeof metadata.claudeSessionId === "string" ? metadata.claudeSessionId : null;
61
+ case "codex":
62
+ return typeof metadata.codexSessionId === "string" ? metadata.codexSessionId : null;
63
+ case "cursor":
64
+ return typeof metadata.cursorSessionId === "string" ? metadata.cursorSessionId : null;
65
+ case "gemini":
66
+ return id;
67
+ }
68
+ }
69
+ function planSessionAdoption(opts) {
70
+ const plan = { track: [], resume: [], skipped: [] };
71
+ const mine = opts.sessions.filter((s) => s.active && s.metadata && s.metadata.machineId === opts.machineId).sort((a, b) => b.activeAt - a.activeAt);
72
+ for (const session of mine) {
73
+ const metadata = session.metadata;
74
+ const pid = typeof metadata.hostPid === "number" ? metadata.hostPid : null;
75
+ if (pid !== null && opts.alivePids.has(pid)) {
76
+ plan.track.push({ id: session.id, pid, metadata });
77
+ continue;
78
+ }
79
+ const directory = typeof metadata.path === "string" ? metadata.path : null;
80
+ if (!directory) {
81
+ plan.skipped.push({ id: session.id, reason: "no path in metadata" });
82
+ continue;
83
+ }
84
+ const agent = pickAgent(metadata);
85
+ const forkSource = pickForkSource(session.id, agent, metadata);
86
+ if (!forkSource) {
87
+ plan.skipped.push({ id: session.id, reason: `no ${agent} session id to resume from` });
88
+ continue;
89
+ }
90
+ plan.resume.push({
91
+ id: session.id,
92
+ agent,
93
+ directory,
94
+ forkSource,
95
+ title: typeof metadata.summary?.text === "string" ? metadata.summary.text : typeof metadata.name === "string" ? metadata.name : void 0,
96
+ metadata
97
+ });
98
+ }
99
+ return plan;
100
+ }
101
+ async function adoptSessionsFromPreviousRun(deps) {
102
+ const report = { tracked: 0, resumed: [], failed: [], skipped: [] };
103
+ const [sessions, alivePids] = await Promise.all([deps.listActiveSessions(), deps.listAliveSessionPids()]);
104
+ const plan = planSessionAdoption({ sessions, alivePids, machineId: deps.machineId });
105
+ report.skipped = plan.skipped;
106
+ for (const session of plan.track) {
107
+ deps.track(session);
108
+ report.tracked++;
109
+ }
110
+ for (const session of plan.resume) {
111
+ try {
112
+ const forked = await deps.fork(session.agent, session.forkSource);
113
+ if (!forked.success || !forked.resumeSessionId) {
114
+ report.failed.push({ id: session.id, reason: forked.errorMessage || `${session.agent} fork failed` });
115
+ continue;
116
+ }
117
+ const spawned = await deps.spawnSession({
118
+ machineId: deps.machineId,
119
+ directory: session.directory,
120
+ agent: session.agent,
121
+ resumeSessionId: forked.resumeSessionId,
122
+ intent: "resume",
123
+ sessionTitle: session.title,
124
+ skipForkSession: true,
125
+ approvedNewDirectoryCreation: false
126
+ });
127
+ if (spawned.type !== "success") {
128
+ report.failed.push({
129
+ id: session.id,
130
+ reason: spawned.type === "error" ? spawned.errorMessage : `directory missing: ${spawned.directory}`
131
+ });
132
+ continue;
133
+ }
134
+ if (!await deps.archiveSession(session.id)) {
135
+ logger.logger.warn(`[DAEMON ADOPT] Resumed ${session.id} as ${spawned.sessionId} but could not mark the old session inactive`);
136
+ }
137
+ report.resumed.push({ from: session.id, to: spawned.sessionId });
138
+ } catch (error) {
139
+ report.failed.push({ id: session.id, reason: error instanceof Error ? error.message : String(error) });
140
+ }
141
+ }
142
+ return report;
143
+ }
144
+
45
145
  let caffeinateProcess = null;
46
146
  function startCaffeinate() {
47
147
  if (logger.configuration.disableCaffeinate) {
@@ -2082,6 +2182,65 @@ ${error.message}
2082
2182
  });
2083
2183
  apiMachine.connect();
2084
2184
  connectedMachine = apiMachine;
2185
+ const adoptionTimer = setTimeout(() => {
2186
+ adoptSessionsFromPreviousRun({
2187
+ machineId,
2188
+ listActiveSessions: async () => {
2189
+ const rows = await api$1.listSessionsUpdatedSince(Date.now() - 4 * 60 * 60 * 1e3);
2190
+ return rows.map((row) => ({
2191
+ id: row.id,
2192
+ active: !!row.active,
2193
+ activeAt: typeof row.activeAt === "number" ? row.activeAt : 0,
2194
+ metadata: sessionDecrypt.decryptSessionRow(credentials, row)?.metadata ?? null
2195
+ }));
2196
+ },
2197
+ listAliveSessionPids: async () => {
2198
+ const processes = await doctor$1.findAllHappyProcesses();
2199
+ return new Set(processes.filter((p) => p.type === "daemon-spawned-session" || p.type === "user-session" || p.type === "dev-daemon-spawned" || p.type === "dev-session").map((p) => p.pid));
2200
+ },
2201
+ fork: async (agent, source) => {
2202
+ switch (agent) {
2203
+ case "claude": {
2204
+ const projectId = await api.findClaudeProjectId(source);
2205
+ if (!projectId) return { success: false, errorMessage: `Claude session ${source} not found on disk` };
2206
+ const r = await api.forkSession(projectId, source);
2207
+ return { success: r.success, resumeSessionId: r.newSessionId, errorMessage: r.errorMessage };
2208
+ }
2209
+ case "codex": {
2210
+ const r = await api.forkCodexSession(source);
2211
+ return { success: r.success, resumeSessionId: r.newFilePath, errorMessage: r.errorMessage };
2212
+ }
2213
+ case "gemini": {
2214
+ const r = await api.forkGeminiSession(source);
2215
+ return { success: r.success, resumeSessionId: r.newSessionId, errorMessage: r.errorMessage };
2216
+ }
2217
+ case "cursor": {
2218
+ const r = await api.forkCursorSession(source);
2219
+ return { success: r.success, resumeSessionId: r.newChatId, errorMessage: r.errorMessage };
2220
+ }
2221
+ }
2222
+ },
2223
+ spawnSession,
2224
+ archiveSession: (sessionId) => api$1.archiveSession(sessionId),
2225
+ track: ({ id, pid, metadata }) => {
2226
+ if (pidToTrackedSession.has(pid)) return;
2227
+ pidToTrackedSession.set(pid, {
2228
+ startedBy: "adopted after daemon restart",
2229
+ happySessionId: id,
2230
+ happySessionMetadataFromLocalWebhook: metadata,
2231
+ pid
2232
+ });
2233
+ }
2234
+ }).then((report) => {
2235
+ logger.logger.info(`[DAEMON ADOPT] tracked ${report.tracked} running session(s), resumed ${report.resumed.length}, failed ${report.failed.length}, skipped ${report.skipped.length}`);
2236
+ for (const r of report.resumed) logger.logger.info(`[DAEMON ADOPT] resumed ${r.from} as ${r.to}`);
2237
+ for (const f of report.failed) logger.logger.warn(`[DAEMON ADOPT] could not resume ${f.id}: ${f.reason}`);
2238
+ for (const s of report.skipped) logger.logger.debug(`[DAEMON ADOPT] skipped ${s.id}: ${s.reason}`);
2239
+ }).catch((error) => {
2240
+ logger.logger.warn("[DAEMON ADOPT] failed to adopt previous sessions", error);
2241
+ });
2242
+ }, 5e3);
2243
+ adoptionTimer.unref();
2085
2244
  apiMachine.updateMachineMetadata((current) => ({ ...current, ...machineMetadata })).catch((error) => {
2086
2245
  logger.logger.debug("[DAEMON RUN] Failed to update machine metadata", error);
2087
2246
  });
@@ -1,15 +1,17 @@
1
1
  import fs from 'fs/promises';
2
2
  import os from 'os';
3
3
  import * as tmp from 'tmp';
4
- import { A as ApiClient } from './api-9wvM_aF-.mjs';
5
- import { c as configuration, l as logger, p as packageJson, v as acquireDaemonLock, a as readSettings, i as isDebug, e as encodeBase64, x as writeDaemonState, m as readDaemonState, y as releaseDaemonLock, z as validateProfileForAgent, A as getProfileEnvironmentVariables } from './persistence-IdEuIeMz.mjs';
6
- import { authAndSetupMachineIfNeeded } from './auth-BnEa31tI.mjs';
4
+ import { A as ApiClient, f as forkCursorSession, c as forkGeminiSession, d as forkCodexSession, e as findClaudeProjectId, g as forkSession } from './api-B9shq-xZ.mjs';
5
+ import { l as logger, c as configuration, p as packageJson, v as acquireDaemonLock, a as readSettings, i as isDebug, e as encodeBase64, x as writeDaemonState, m as readDaemonState, y as releaseDaemonLock, z as validateProfileForAgent, A as getProfileEnvironmentVariables } from './persistence-Da0uhblK.mjs';
6
+ import { findAllHappyProcesses } from './doctor-ON7pN5G5.mjs';
7
+ import { d as decryptSessionRow } from './sessionDecrypt-BsOlrqRs.mjs';
8
+ import { authAndSetupMachineIfNeeded } from './auth-DnRtIM3d.mjs';
7
9
  import { spawn, execSync, exec } from 'child_process';
8
- import { getEnvironmentInfo } from './doctor-DQtQbfG-.mjs';
9
- import { s as spawnHappyCLI } from './spawnHappyCLI-DlTg87jS.mjs';
10
- import { isDaemonRunningCurrentlyInstalledHappyVersion, stopDaemon, cleanupDaemonState } from './controlClient-VY0CGL8k.mjs';
11
- import { a as readCachedDeviceKey, d as deviceExec } from './deviceKeys-DvfaTff3.mjs';
12
- import { P as PLIST_LABEL } from './install-1Y6dAcMp.mjs';
10
+ import { getEnvironmentInfo } from './doctor-C77QV3rd.mjs';
11
+ import { s as spawnHappyCLI } from './spawnHappyCLI-Cv2VARTw.mjs';
12
+ import { isDaemonRunningCurrentlyInstalledHappyVersion, stopDaemon, cleanupDaemonState } from './controlClient-BuKaeD-y.mjs';
13
+ import { a as readCachedDeviceKey, d as deviceExec } from './deviceKeys-DSXcQgLf.mjs';
14
+ import { P as PLIST_LABEL } from './install-DbRGuSWv.mjs';
13
15
  import fastify from 'fastify';
14
16
  import { createReadStream } from 'node:fs';
15
17
  import { stat } from 'node:fs/promises';
@@ -21,6 +23,104 @@ import { join } from 'path';
21
23
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
22
24
  import { b as buildOutputSummary, m as mapFinishStatus, a as buildOrchestratorEnv, c as appendOutputChunk } from './common-BdNgghUJ.mjs';
23
25
 
26
+ function pickAgent(metadata) {
27
+ switch (metadata.flavor) {
28
+ case "codex":
29
+ case "gemini":
30
+ case "cursor":
31
+ return metadata.flavor;
32
+ default:
33
+ return "claude";
34
+ }
35
+ }
36
+ function pickForkSource(id, agent, metadata) {
37
+ switch (agent) {
38
+ case "claude":
39
+ return typeof metadata.claudeSessionId === "string" ? metadata.claudeSessionId : null;
40
+ case "codex":
41
+ return typeof metadata.codexSessionId === "string" ? metadata.codexSessionId : null;
42
+ case "cursor":
43
+ return typeof metadata.cursorSessionId === "string" ? metadata.cursorSessionId : null;
44
+ case "gemini":
45
+ return id;
46
+ }
47
+ }
48
+ function planSessionAdoption(opts) {
49
+ const plan = { track: [], resume: [], skipped: [] };
50
+ const mine = opts.sessions.filter((s) => s.active && s.metadata && s.metadata.machineId === opts.machineId).sort((a, b) => b.activeAt - a.activeAt);
51
+ for (const session of mine) {
52
+ const metadata = session.metadata;
53
+ const pid = typeof metadata.hostPid === "number" ? metadata.hostPid : null;
54
+ if (pid !== null && opts.alivePids.has(pid)) {
55
+ plan.track.push({ id: session.id, pid, metadata });
56
+ continue;
57
+ }
58
+ const directory = typeof metadata.path === "string" ? metadata.path : null;
59
+ if (!directory) {
60
+ plan.skipped.push({ id: session.id, reason: "no path in metadata" });
61
+ continue;
62
+ }
63
+ const agent = pickAgent(metadata);
64
+ const forkSource = pickForkSource(session.id, agent, metadata);
65
+ if (!forkSource) {
66
+ plan.skipped.push({ id: session.id, reason: `no ${agent} session id to resume from` });
67
+ continue;
68
+ }
69
+ plan.resume.push({
70
+ id: session.id,
71
+ agent,
72
+ directory,
73
+ forkSource,
74
+ title: typeof metadata.summary?.text === "string" ? metadata.summary.text : typeof metadata.name === "string" ? metadata.name : void 0,
75
+ metadata
76
+ });
77
+ }
78
+ return plan;
79
+ }
80
+ async function adoptSessionsFromPreviousRun(deps) {
81
+ const report = { tracked: 0, resumed: [], failed: [], skipped: [] };
82
+ const [sessions, alivePids] = await Promise.all([deps.listActiveSessions(), deps.listAliveSessionPids()]);
83
+ const plan = planSessionAdoption({ sessions, alivePids, machineId: deps.machineId });
84
+ report.skipped = plan.skipped;
85
+ for (const session of plan.track) {
86
+ deps.track(session);
87
+ report.tracked++;
88
+ }
89
+ for (const session of plan.resume) {
90
+ try {
91
+ const forked = await deps.fork(session.agent, session.forkSource);
92
+ if (!forked.success || !forked.resumeSessionId) {
93
+ report.failed.push({ id: session.id, reason: forked.errorMessage || `${session.agent} fork failed` });
94
+ continue;
95
+ }
96
+ const spawned = await deps.spawnSession({
97
+ machineId: deps.machineId,
98
+ directory: session.directory,
99
+ agent: session.agent,
100
+ resumeSessionId: forked.resumeSessionId,
101
+ intent: "resume",
102
+ sessionTitle: session.title,
103
+ skipForkSession: true,
104
+ approvedNewDirectoryCreation: false
105
+ });
106
+ if (spawned.type !== "success") {
107
+ report.failed.push({
108
+ id: session.id,
109
+ reason: spawned.type === "error" ? spawned.errorMessage : `directory missing: ${spawned.directory}`
110
+ });
111
+ continue;
112
+ }
113
+ if (!await deps.archiveSession(session.id)) {
114
+ logger.warn(`[DAEMON ADOPT] Resumed ${session.id} as ${spawned.sessionId} but could not mark the old session inactive`);
115
+ }
116
+ report.resumed.push({ from: session.id, to: spawned.sessionId });
117
+ } catch (error) {
118
+ report.failed.push({ id: session.id, reason: error instanceof Error ? error.message : String(error) });
119
+ }
120
+ }
121
+ return report;
122
+ }
123
+
24
124
  let caffeinateProcess = null;
25
125
  function startCaffeinate() {
26
126
  if (configuration.disableCaffeinate) {
@@ -2061,6 +2161,65 @@ ${error.message}
2061
2161
  });
2062
2162
  apiMachine.connect();
2063
2163
  connectedMachine = apiMachine;
2164
+ const adoptionTimer = setTimeout(() => {
2165
+ adoptSessionsFromPreviousRun({
2166
+ machineId,
2167
+ listActiveSessions: async () => {
2168
+ const rows = await api.listSessionsUpdatedSince(Date.now() - 4 * 60 * 60 * 1e3);
2169
+ return rows.map((row) => ({
2170
+ id: row.id,
2171
+ active: !!row.active,
2172
+ activeAt: typeof row.activeAt === "number" ? row.activeAt : 0,
2173
+ metadata: decryptSessionRow(credentials, row)?.metadata ?? null
2174
+ }));
2175
+ },
2176
+ listAliveSessionPids: async () => {
2177
+ const processes = await findAllHappyProcesses();
2178
+ return new Set(processes.filter((p) => p.type === "daemon-spawned-session" || p.type === "user-session" || p.type === "dev-daemon-spawned" || p.type === "dev-session").map((p) => p.pid));
2179
+ },
2180
+ fork: async (agent, source) => {
2181
+ switch (agent) {
2182
+ case "claude": {
2183
+ const projectId = await findClaudeProjectId(source);
2184
+ if (!projectId) return { success: false, errorMessage: `Claude session ${source} not found on disk` };
2185
+ const r = await forkSession(projectId, source);
2186
+ return { success: r.success, resumeSessionId: r.newSessionId, errorMessage: r.errorMessage };
2187
+ }
2188
+ case "codex": {
2189
+ const r = await forkCodexSession(source);
2190
+ return { success: r.success, resumeSessionId: r.newFilePath, errorMessage: r.errorMessage };
2191
+ }
2192
+ case "gemini": {
2193
+ const r = await forkGeminiSession(source);
2194
+ return { success: r.success, resumeSessionId: r.newSessionId, errorMessage: r.errorMessage };
2195
+ }
2196
+ case "cursor": {
2197
+ const r = await forkCursorSession(source);
2198
+ return { success: r.success, resumeSessionId: r.newChatId, errorMessage: r.errorMessage };
2199
+ }
2200
+ }
2201
+ },
2202
+ spawnSession,
2203
+ archiveSession: (sessionId) => api.archiveSession(sessionId),
2204
+ track: ({ id, pid, metadata }) => {
2205
+ if (pidToTrackedSession.has(pid)) return;
2206
+ pidToTrackedSession.set(pid, {
2207
+ startedBy: "adopted after daemon restart",
2208
+ happySessionId: id,
2209
+ happySessionMetadataFromLocalWebhook: metadata,
2210
+ pid
2211
+ });
2212
+ }
2213
+ }).then((report) => {
2214
+ logger.info(`[DAEMON ADOPT] tracked ${report.tracked} running session(s), resumed ${report.resumed.length}, failed ${report.failed.length}, skipped ${report.skipped.length}`);
2215
+ for (const r of report.resumed) logger.info(`[DAEMON ADOPT] resumed ${r.from} as ${r.to}`);
2216
+ for (const f of report.failed) logger.warn(`[DAEMON ADOPT] could not resume ${f.id}: ${f.reason}`);
2217
+ for (const s of report.skipped) logger.debug(`[DAEMON ADOPT] skipped ${s.id}: ${s.reason}`);
2218
+ }).catch((error) => {
2219
+ logger.warn("[DAEMON ADOPT] failed to adopt previous sessions", error);
2220
+ });
2221
+ }, 5e3);
2222
+ adoptionTimer.unref();
2064
2223
  apiMachine.updateMachineMetadata((current) => ({ ...current, ...machineMetadata })).catch((error) => {
2065
2224
  logger.debug("[DAEMON RUN] Failed to update machine metadata", error);
2066
2225
  });
@@ -4,20 +4,20 @@ var os = require('node:os');
4
4
  var node_crypto = require('node:crypto');
5
5
  var fs$1 = require('node:fs');
6
6
  var promises = require('node:fs/promises');
7
- var api = require('./api-BGc484qf.cjs');
8
- var logger = require('./persistence-CNXsXPLm.cjs');
9
- var claudeLocal = require('./claudeLocal-CV4fT0Gg.cjs');
7
+ var api = require('./api-ByiU9yXy.cjs');
8
+ var logger = require('./persistence-50wmDoBE.cjs');
9
+ var claudeLocal = require('./claudeLocal-CuHH7tvQ.cjs');
10
10
  var types = require('./types-DWeB7aqh.cjs');
11
11
  var path = require('node:path');
12
12
  var time = require('./time-Bj2HRkKH.cjs');
13
13
  var fs = require('fs/promises');
14
14
  var ink = require('ink');
15
- var downloadImage = require('./downloadImage-DGdHCFi3.cjs');
15
+ var downloadImage = require('./downloadImage-DZBxkdwy.cjs');
16
16
  var React = require('react');
17
17
  var node_child_process = require('node:child_process');
18
18
  var node_readline = require('node:readline');
19
19
  var node_url = require('node:url');
20
- var spawnHappyCLI = require('./spawnHappyCLI-BbMkZhMk.cjs');
20
+ var spawnHappyCLI = require('./spawnHappyCLI-BNUBk0w5.cjs');
21
21
  var projectPath = require('./projectPath-ChLhdOyt.cjs');
22
22
  require('axios');
23
23
  require('node:events');
@@ -28,12 +28,12 @@ require('crypto');
28
28
  require('@stablelib/base64');
29
29
  require('expo-server-sdk');
30
30
  require('chalk');
31
- var formatImageMessage = require('./formatImageMessage-DttKW75w.cjs');
31
+ var formatImageMessage = require('./formatImageMessage-CHjdeDGM.cjs');
32
32
  var node_util = require('node:util');
33
- var run = require('./run-BKfeeheJ.cjs');
34
- var doctor = require('./doctor-CD46A-_Y.cjs');
35
- var controlClient = require('./controlClient-DWBW6jRF.cjs');
36
- var registerKillSessionHandler = require('./registerKillSessionHandler-D9tmPdw5.cjs');
33
+ var run = require('./run-C6hmGRwH.cjs');
34
+ var doctor = require('./doctor-CxWWwoLX.cjs');
35
+ var controlClient = require('./controlClient-BqCwo6Pm.cjs');
36
+ var registerKillSessionHandler = require('./registerKillSessionHandler-CHPzUrtO.cjs');
37
37
  var node_http = require('node:http');
38
38
  require('zod');
39
39
  require('./index-DBev4hhV.cjs');
@@ -42,7 +42,7 @@ require('child_process');
42
42
  require('util');
43
43
  require('path');
44
44
  require('node:module');
45
- require('./sessionKeyCache-JjjYAxdf.cjs');
45
+ require('./sessionKeyCache-CmORI8jN.cjs');
46
46
  require('fs');
47
47
  require('./prompt-BTWDZZO0.cjs');
48
48
  require('./trimIdent-4gvk9Wk6.cjs');
@@ -50,17 +50,18 @@ require('./common-CZvSRU4p.cjs');
50
50
  require('url');
51
51
  require('os');
52
52
  require('tmp');
53
- require('./auth-B6vskzfm.cjs');
53
+ require('./doctor-C08m5Z9f.cjs');
54
+ require('ps-list');
55
+ require('cross-spawn');
56
+ require('./sessionDecrypt-DWm_k5dq.cjs');
57
+ require('./auth-DnFrlXqp.cjs');
54
58
  require('qrcode-terminal');
55
- require('./browser-CnxzD1lA.cjs');
59
+ require('./browser-DjONS-B5.cjs');
56
60
  require('open');
57
- require('./deviceKeys-c_sN01Mm.cjs');
58
- require('./install-C4cwObCN.cjs');
61
+ require('./deviceKeys-CSfs6juX.cjs');
62
+ require('./install-Td8RvuEV.cjs');
59
63
  require('fastify');
60
64
  require('fastify-type-provider-zod');
61
- require('./doctor-C08m5Z9f.cjs');
62
- require('ps-list');
63
- require('cross-spawn');
64
65
  require('@modelcontextprotocol/sdk/server/mcp.js');
65
66
  require('@modelcontextprotocol/sdk/server/streamableHttp.js');
66
67
  require('@modelcontextprotocol/sdk/types.js');
@@ -732,7 +733,7 @@ class AbortError extends Error {
732
733
  }
733
734
  }
734
735
 
735
- const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runClaude-DDsG7eMR.cjs', document.baseURI).href)));
736
+ const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('runClaude-BR15B5bw.cjs', document.baseURI).href)));
736
737
  const __dirname$1 = path.join(__filename$1, "..");
737
738
  function getGlobalClaudeVersion() {
738
739
  try {