@zonease/happy 0.6.58 → 0.6.60

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-B9shq-xZ.mjs → api--fA9drop.mjs} +2 -2
  2. package/dist/{api-ByiU9yXy.cjs → api-DwiOsTuU.cjs} +3 -3
  3. package/dist/{auth-DnRtIM3d.mjs → auth-B1Qy9v3F.mjs} +2 -2
  4. package/dist/{auth-DnFrlXqp.cjs → auth-D2z0WId5.cjs} +2 -2
  5. package/dist/{auth-BG6e5Uem.cjs → auth-TOfB7aIs.cjs} +4 -4
  6. package/dist/{auth-BRh7v1qh.mjs → auth-ZsDiF0iS.mjs} +4 -4
  7. package/dist/{browser-BeERlPhN.mjs → browser-ChGfY23u.mjs} +1 -1
  8. package/dist/{browser-DjONS-B5.cjs → browser-DPXZcBi-.cjs} +1 -1
  9. package/dist/{claudeLocal-CuHH7tvQ.cjs → claudeLocal-BtbtPj3C.cjs} +1 -1
  10. package/dist/{claudeLocal-CYtFfvTZ.mjs → claudeLocal-Cs-BIAw0.mjs} +1 -1
  11. package/dist/codex/happyMcpStdioBridge.cjs +9 -0
  12. package/dist/codex/happyMcpStdioBridge.mjs +9 -0
  13. package/dist/{config-BHwOLuFT.cjs → config-BHH3wR9_.cjs} +1 -1
  14. package/dist/{config-BkUfgaM5.mjs → config-Bgg5VgXT.mjs} +1 -1
  15. package/dist/{connect-B9rWe2GY.cjs → connect-BqLN8m_j.cjs} +4 -4
  16. package/dist/{connect-BoTU3RCi.mjs → connect-CYcS7eHZ.mjs} +4 -4
  17. package/dist/{controlClient-BuKaeD-y.mjs → controlClient-COoWtF6Y.mjs} +1 -1
  18. package/dist/{controlClient-BqCwo6Pm.cjs → controlClient-DMxcJC-j.cjs} +1 -1
  19. package/dist/{cursorApprovalHook-BADH_Ul1.mjs → cursorApprovalHook-BFXFD77c.mjs} +2 -2
  20. package/dist/{cursorApprovalHook-Ckdd65co.cjs → cursorApprovalHook-DcyH8JX5.cjs} +2 -2
  21. package/dist/{cursorApprovalServer--suu8J98.cjs → cursorApprovalServer-dAADRfXB.cjs} +1 -1
  22. package/dist/{cursorApprovalServer-BeTT3FNN.mjs → cursorApprovalServer-mFYKPgz8.mjs} +1 -1
  23. package/dist/{deviceKeys-CSfs6juX.cjs → deviceKeys-Ttjgv9qm.cjs} +2 -2
  24. package/dist/{deviceKeys-DSXcQgLf.mjs → deviceKeys-chmGamFc.mjs} +2 -2
  25. package/dist/{doctor-C77QV3rd.mjs → doctor-BxY-J5MM.mjs} +2 -2
  26. package/dist/{doctor-CxWWwoLX.cjs → doctor-CX5edsk3.cjs} +2 -2
  27. package/dist/{downloadImage-C3FHGZDr.mjs → downloadImage-DJ0qW4xQ.mjs} +1 -1
  28. package/dist/{downloadImage-DZBxkdwy.cjs → downloadImage-DvHbBiN2.cjs} +1 -1
  29. package/dist/{enroll-D5V8LH6P.mjs → enroll-Cq4SU81g.mjs} +3 -3
  30. package/dist/{enroll-BjZCaXT4.cjs → enroll-CrHKoQhQ.cjs} +3 -3
  31. package/dist/{evidence-DbFF210m.cjs → evidence-BaKd7bX-.cjs} +1 -1
  32. package/dist/{evidence-DL-E4Qfd.mjs → evidence-Uz0vrlbA.mjs} +1 -1
  33. package/dist/{formatImageMessage-C6glTFta.mjs → formatImageMessage-Ck_SVHgI.mjs} +1 -1
  34. package/dist/{formatImageMessage-CHjdeDGM.cjs → formatImageMessage-DE96y8-H.cjs} +1 -1
  35. package/dist/index.cjs +46 -46
  36. package/dist/index.mjs +46 -46
  37. package/dist/{install-BPCWw2Vc.mjs → install-BZRHw4E1.mjs} +2 -2
  38. package/dist/{install-DbRGuSWv.mjs → install-CYdjwe-t.mjs} +1 -1
  39. package/dist/{install-Td8RvuEV.cjs → install-Ce6JldUY.cjs} +1 -1
  40. package/dist/{install-9E-3IeF3.cjs → install-PYgh1lAM.cjs} +2 -2
  41. package/dist/lib.cjs +3 -3
  42. package/dist/lib.mjs +3 -3
  43. package/dist/{loadableToolOutput-C0tAWFJM.mjs → loadableToolOutput-D5HoFtRR.mjs} +2 -2
  44. package/dist/{loadableToolOutput-C5EQglQm.cjs → loadableToolOutput-tPvkyCoE.cjs} +2 -2
  45. package/dist/{persistence-50wmDoBE.cjs → persistence-CZptiAaZ.cjs} +1 -1
  46. package/dist/{persistence-Da0uhblK.mjs → persistence-CcOX4WLf.mjs} +1 -1
  47. package/dist/{push-Bbf139Sy.cjs → push-BAENK6I6.cjs} +6 -6
  48. package/dist/{push-BR82p4YC.mjs → push-BSoeS633.mjs} +6 -6
  49. package/dist/{registerKillSessionHandler-CxHjAcQu.mjs → registerKillSessionHandler-CKWBWTcY.mjs} +62 -7
  50. package/dist/{registerKillSessionHandler-CHPzUrtO.cjs → registerKillSessionHandler-DIFqoCCd.cjs} +62 -7
  51. package/dist/{run-C6hmGRwH.cjs → run-38zHldyV.cjs} +9 -9
  52. package/dist/{run-DjaUrH7x.mjs → run-Cjw5klTK.mjs} +9 -9
  53. package/dist/{runClaude-CKFHv0nI.mjs → runClaude-B_CIlNN4.mjs} +16 -16
  54. package/dist/{runClaude-BR15B5bw.cjs → runClaude-CBEEtvJr.cjs} +17 -17
  55. package/dist/{runCodex-BAlT1EGt.mjs → runCodex-BDwhTF1q.mjs} +16 -16
  56. package/dist/{runCodex-BpVY3LQi.cjs → runCodex-C7lK__L-.cjs} +16 -16
  57. package/dist/{runCursor-BUx34tPB.cjs → runCursor--yWGI0To.cjs} +15 -15
  58. package/dist/{runCursor-Dj3orwMw.mjs → runCursor-P37XaTHj.mjs} +15 -15
  59. package/dist/{runGemini-SEsV1VfH.mjs → runGemini-2371Fh4z.mjs} +22 -18
  60. package/dist/{runGemini-Bdzns1qW.cjs → runGemini-eqHuZV15.cjs} +22 -18
  61. package/dist/{runOneShot-CK10IG0U.cjs → runOneShot-B9isSc3w.cjs} +2 -2
  62. package/dist/{runOneShot-BTHgA1q4.mjs → runOneShot-BPrFFCeI.mjs} +2 -2
  63. package/dist/{serve-BErPXI_R.mjs → serve-C_lMTDXi.mjs} +7 -7
  64. package/dist/{serve-BHe5QkCA.cjs → serve-DaL6Qn8d.cjs} +7 -7
  65. package/dist/{session-FttaWXf3.cjs → session-BulXwxs1.cjs} +6 -6
  66. package/dist/{session-CZyeSNaA.mjs → session-hdOJQKlO.mjs} +6 -6
  67. package/dist/{sessionDecrypt-BsOlrqRs.mjs → sessionDecrypt-BQnoJy4t.mjs} +3 -3
  68. package/dist/{sessionDecrypt-DWm_k5dq.cjs → sessionDecrypt-Bscb-Kfw.cjs} +3 -3
  69. package/dist/{sessionKeyCache-CmORI8jN.cjs → sessionKeyCache-By8_OSDl.cjs} +1 -1
  70. package/dist/{sessionKeyCache-BBzsFcnN.mjs → sessionKeyCache-DxPdM8uz.mjs} +1 -1
  71. package/dist/{sessionList-D_Y-1Cir.mjs → sessionList-BEBpDXjL.mjs} +2 -2
  72. package/dist/{sessionList-lxpW_76R.cjs → sessionList-BoyXqg6y.cjs} +2 -2
  73. package/dist/{sessionSummary-YLlUeUre.mjs → sessionSummary-C9zR15PT.mjs} +2 -2
  74. package/dist/{sessionSummary-BP2T8GHr.cjs → sessionSummary-PwepM55y.cjs} +2 -2
  75. package/dist/{setupOfflineReconnection-CldeNWUW.cjs → setupOfflineReconnection-B_vI2UBK.cjs} +11 -6
  76. package/dist/{setupOfflineReconnection-B4aU1Nix.mjs → setupOfflineReconnection-HnT3f6i6.mjs} +11 -6
  77. package/dist/{spawnHappyCLI-BNUBk0w5.cjs → spawnHappyCLI-C3WkMK2n.cjs} +1 -1
  78. package/dist/{spawnHappyCLI-Cv2VARTw.mjs → spawnHappyCLI-CgVBVqUH.mjs} +1 -1
  79. package/dist/{ssh-DXOMR-gb.cjs → ssh-Cfv2KOik.cjs} +5 -5
  80. package/dist/{ssh-CBvM1RVJ.mjs → ssh-CirivsXx.mjs} +5 -5
  81. package/dist/{task-DrX3H3_Y.cjs → task-CdYJn3YO.cjs} +7 -7
  82. package/dist/{task-CQonykFe.mjs → task-D8bPWquQ.mjs} +7 -7
  83. package/dist/{uninstall-BijW1rTR.mjs → uninstall-BNC1O3n5.mjs} +2 -2
  84. package/dist/{uninstall-CPQjax_f.cjs → uninstall-C4s6P4_x.cjs} +2 -2
  85. package/dist/{update-DaJjoz93.mjs → update--zUf8Pu-.mjs} +3 -3
  86. package/dist/{update-g3D05Tvv.cjs → update-CY67NiY0.cjs} +3 -3
  87. package/package.json +1 -1
@@ -35,7 +35,7 @@ function isDebug() {
35
35
  }
36
36
 
37
37
  var name = "@zonease/happy";
38
- var version = "0.6.58";
38
+ var version = "0.6.60";
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.58";
17
+ var version = "0.6.60";
18
18
  var description = "Mobile and Web client for Claude Code, Codex, and Gemini";
19
19
  var author = "ZonEaseTech";
20
20
  var license = "MIT";
@@ -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-50wmDoBE.cjs');
6
- var ssh = require('./ssh-DXOMR-gb.cjs');
5
+ var logger = require('./persistence-CZptiAaZ.cjs');
6
+ var ssh = require('./ssh-Cfv2KOik.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-CSfs6juX.cjs');
15
+ require('./deviceKeys-Ttjgv9qm.cjs');
16
16
  require('axios');
17
- require('./auth-DnFrlXqp.cjs');
17
+ require('./auth-D2z0WId5.cjs');
18
18
  require('qrcode-terminal');
19
19
  require('./time-Bj2HRkKH.cjs');
20
- require('./browser-DjONS-B5.cjs');
20
+ require('./browser-DPXZcBi-.cjs');
21
21
  require('open');
22
22
  require('react');
23
23
  require('ink');
24
- require('./controlClient-BqCwo6Pm.cjs');
24
+ require('./controlClient-DMxcJC-j.cjs');
25
25
  require('./projectPath-ChLhdOyt.cjs');
26
26
  require('path');
27
27
  require('url');
@@ -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-Da0uhblK.mjs';
4
- import { resolveDeviceForCommand } from './ssh-CBvM1RVJ.mjs';
3
+ import { c as configuration, e as encodeBase64, f as encrypt, g as decrypt, h as decodeBase64 } from './persistence-CcOX4WLf.mjs';
4
+ import { resolveDeviceForCommand } from './ssh-CirivsXx.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-DSXcQgLf.mjs';
13
+ import './deviceKeys-chmGamFc.mjs';
14
14
  import 'axios';
15
- import './auth-DnRtIM3d.mjs';
15
+ import './auth-B1Qy9v3F.mjs';
16
16
  import 'qrcode-terminal';
17
17
  import './time-DgsBLJA_.mjs';
18
- import './browser-BeERlPhN.mjs';
18
+ import './browser-ChGfY23u.mjs';
19
19
  import 'open';
20
20
  import 'react';
21
21
  import 'ink';
22
- import './controlClient-BuKaeD-y.mjs';
22
+ import './controlClient-COoWtF6Y.mjs';
23
23
  import './projectPath-BTBIMB57.mjs';
24
24
  import 'path';
25
25
  import 'url';
@@ -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-Da0uhblK.mjs';
9
- import { l as listDevices, d as deviceExec } from './deviceKeys-DSXcQgLf.mjs';
8
+ import { c as configuration, l as logger, r as readCredentials } from './persistence-CcOX4WLf.mjs';
9
+ import { l as listDevices, d as deviceExec } from './deviceKeys-chmGamFc.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-B9shq-xZ.mjs';
19
+ import './api--fA9drop.mjs';
20
20
  import 'tweetnacl';
21
21
  import 'ws';
22
22
  import 'crypto';
@@ -77,7 +77,7 @@ async function resolveBugId(credentials, reference) {
77
77
  }
78
78
  return match.id;
79
79
  }
80
- async function attachBugImage(credentials, bugId, filePath) {
80
+ async function attachBugImage(credentials, bugId, filePath, commentId) {
81
81
  const mimeType = IMAGE_MIME_TYPES[extname(filePath).toLowerCase()];
82
82
  if (!mimeType) {
83
83
  throw new Error("only .jpg, .jpeg and .png are supported");
@@ -88,13 +88,14 @@ async function attachBugImage(credentials, bugId, filePath) {
88
88
  }
89
89
  const form = new FormData();
90
90
  form.append("file", new Blob([await readFile(filePath)], { type: mimeType }), basename(filePath));
91
+ if (commentId) form.append("commentId", commentId);
91
92
  await axios.post(`${configuration.serverUrl}/v1/bugs/${bugId}/attachments`, form, authHeaders(credentials));
92
93
  }
93
- async function attachImages(credentials, bugId, images, alreadyAttached) {
94
+ async function attachImages(credentials, bugId, images, alreadyAttached, commentId) {
94
95
  const room = Math.max(MAX_BUG_IMAGES - alreadyAttached, 0);
95
96
  const attachments = [];
96
97
  for (const file of images.slice(0, room)) {
97
- await attachBugImage(credentials, bugId, file).then(() => attachments.push({ file, ok: true })).catch((error) => attachments.push({ file, ok: false, error: error instanceof Error ? error.message : String(error) }));
98
+ await attachBugImage(credentials, bugId, file, commentId).then(() => attachments.push({ file, ok: true })).catch((error) => attachments.push({ file, ok: false, error: error instanceof Error ? error.message : String(error) }));
98
99
  }
99
100
  for (const file of images.slice(room)) {
100
101
  attachments.push({ file, ok: false, error: `skipped \u2014 a bug takes at most ${MAX_BUG_IMAGES} images` });
@@ -136,6 +137,39 @@ async function editBug(credentials, input) {
136
137
  }
137
138
  return { ...bug, attachments: await attachImages(credentials, bugId, images, bug.attachmentCount ?? 0) };
138
139
  }
140
+ function withImageMarkers(body, imageCount) {
141
+ const placed = /* @__PURE__ */ new Set();
142
+ for (const match of body.matchAll(/\[\[bug-image:(\d+)\]\]/g)) placed.add(Number(match[1]));
143
+ const missing = [];
144
+ for (let index = 1; index <= imageCount; index++) {
145
+ if (!placed.has(index)) missing.push(`[[bug-image:${index}]]`);
146
+ }
147
+ return missing.length ? [body.trim(), ...missing].filter(Boolean).join("\n\n") : body.trim();
148
+ }
149
+ async function commentOnBug(credentials, input) {
150
+ const images = (input.images ?? []).slice(0, MAX_BUG_IMAGES);
151
+ const skipped = (input.images ?? []).slice(MAX_BUG_IMAGES);
152
+ const body = withImageMarkers(input.body, images.length);
153
+ if (!body) {
154
+ throw new Error("nothing to post \u2014 pass a body, images, or both");
155
+ }
156
+ const bugId = await resolveBugId(credentials, input.bug);
157
+ const response = await axios.post(
158
+ `${configuration.serverUrl}/v1/bugs/${bugId}/comments`,
159
+ { body },
160
+ authHeaders(credentials)
161
+ );
162
+ const { bug, commentId } = response.data;
163
+ const result = { id: bug.id, displayId: bug.displayId, commentId, commentCount: bug.commentCount };
164
+ if (!images.length && !skipped.length) {
165
+ return result;
166
+ }
167
+ const attachments = await attachImages(credentials, bugId, images, 0, commentId);
168
+ for (const file of skipped) {
169
+ attachments.push({ file, ok: false, error: `skipped \u2014 a comment takes at most ${MAX_BUG_IMAGES} images` });
170
+ }
171
+ return { ...result, attachments };
172
+ }
139
173
  async function setBugStatus(credentials, input) {
140
174
  const bugId = await resolveBugId(credentials, input.bug);
141
175
  const response = await axios.patch(
@@ -428,6 +462,27 @@ ${lines.join("\n")}` : header }] };
428
462
  return toToolError(`Failed to edit bug: ${error instanceof Error ? error.message : String(error)}`);
429
463
  }
430
464
  });
465
+ mcp.registerTool("comment_bug", {
466
+ description: "Post a comment under a bug on the user's Happy bug board. Everyone following the bug is notified (Feishu), which an edit to the description does not do. Use it to report a result \u2014 a retest that passed or failed, a fix that shipped, a question for the reporter \u2014 instead of appending it to the description.",
467
+ title: "Comment on Bug",
468
+ inputSchema: {
469
+ bug: z.string().describe('Which bug, as the user refers to it: "BUG-236", "#236" or "236". An internal bug id also works.'),
470
+ body: z.string().describe("The comment text. To place a screenshot inside it, put [[bug-image:N]] where the Nth entry of images should appear; images left unplaced follow the text."),
471
+ images: z.array(z.string()).optional().describe("Absolute paths to screenshots on this machine, in the order the [[bug-image:N]] markers refer to them. JPEG and PNG only, up to 10, 20MB each.")
472
+ }
473
+ }, async (args) => {
474
+ const credentials = await readCredentials();
475
+ if (!credentials) {
476
+ return toToolError("No Happy credentials on this machine.");
477
+ }
478
+ try {
479
+ const result = await commentOnBug(credentials, args);
480
+ logger.debug("[happyMCP] Commented on bug:", result.displayId);
481
+ return toToolSuccess({ ok: true, ...result });
482
+ } catch (error) {
483
+ return toToolError(`Failed to comment on bug: ${error instanceof Error ? error.message : String(error)}`);
484
+ }
485
+ });
431
486
  mcp.registerTool("set_bug_status", {
432
487
  description: "Move a bug on the user's Happy bug board to another status: close it once a fix is verified, put it back in progress, send it to verification, or return it to pending. Use whenever the user says a bug is fixed, verified, closed, reopened, or should go back to someone.",
433
488
  title: "Set Bug Status",
@@ -473,7 +528,7 @@ ${lines.join("\n")}` : header }] };
473
528
  async function startHappyServer(client) {
474
529
  const transports = /* @__PURE__ */ new Map();
475
530
  const enableOrchestratorTools = shouldEnableOrchestratorTools();
476
- const toolNames = ["change_title", "preview_html", "device_list", "device_exec", "list_bugs", "get_bug", "submit_bug", "edit_bug", "delete_bug", "set_bug_status"];
531
+ const toolNames = ["change_title", "preview_html", "device_list", "device_exec", "list_bugs", "get_bug", "submit_bug", "edit_bug", "delete_bug", "set_bug_status", "comment_bug"];
477
532
  const originalConsoleError = console.error;
478
533
  console.error = (...args) => {
479
534
  logger.debug("[happyMCP] console.error:", ...args);
@@ -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-50wmDoBE.cjs');
11
- var deviceKeys = require('./deviceKeys-CSfs6juX.cjs');
10
+ var logger = require('./persistence-CZptiAaZ.cjs');
11
+ var deviceKeys = require('./deviceKeys-Ttjgv9qm.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-ByiU9yXy.cjs');
21
+ require('./api-DwiOsTuU.cjs');
22
22
  require('tweetnacl');
23
23
  require('ws');
24
24
  require('crypto');
@@ -79,7 +79,7 @@ async function resolveBugId(credentials, reference) {
79
79
  }
80
80
  return match.id;
81
81
  }
82
- async function attachBugImage(credentials, bugId, filePath) {
82
+ async function attachBugImage(credentials, bugId, filePath, commentId) {
83
83
  const mimeType = IMAGE_MIME_TYPES[path.extname(filePath).toLowerCase()];
84
84
  if (!mimeType) {
85
85
  throw new Error("only .jpg, .jpeg and .png are supported");
@@ -90,13 +90,14 @@ async function attachBugImage(credentials, bugId, filePath) {
90
90
  }
91
91
  const form = new FormData();
92
92
  form.append("file", new Blob([await promises.readFile(filePath)], { type: mimeType }), path.basename(filePath));
93
+ if (commentId) form.append("commentId", commentId);
93
94
  await axios.post(`${logger.configuration.serverUrl}/v1/bugs/${bugId}/attachments`, form, authHeaders(credentials));
94
95
  }
95
- async function attachImages(credentials, bugId, images, alreadyAttached) {
96
+ async function attachImages(credentials, bugId, images, alreadyAttached, commentId) {
96
97
  const room = Math.max(MAX_BUG_IMAGES - alreadyAttached, 0);
97
98
  const attachments = [];
98
99
  for (const file of images.slice(0, room)) {
99
- await attachBugImage(credentials, bugId, file).then(() => attachments.push({ file, ok: true })).catch((error) => attachments.push({ file, ok: false, error: error instanceof Error ? error.message : String(error) }));
100
+ await attachBugImage(credentials, bugId, file, commentId).then(() => attachments.push({ file, ok: true })).catch((error) => attachments.push({ file, ok: false, error: error instanceof Error ? error.message : String(error) }));
100
101
  }
101
102
  for (const file of images.slice(room)) {
102
103
  attachments.push({ file, ok: false, error: `skipped \u2014 a bug takes at most ${MAX_BUG_IMAGES} images` });
@@ -138,6 +139,39 @@ async function editBug(credentials, input) {
138
139
  }
139
140
  return { ...bug, attachments: await attachImages(credentials, bugId, images, bug.attachmentCount ?? 0) };
140
141
  }
142
+ function withImageMarkers(body, imageCount) {
143
+ const placed = /* @__PURE__ */ new Set();
144
+ for (const match of body.matchAll(/\[\[bug-image:(\d+)\]\]/g)) placed.add(Number(match[1]));
145
+ const missing = [];
146
+ for (let index = 1; index <= imageCount; index++) {
147
+ if (!placed.has(index)) missing.push(`[[bug-image:${index}]]`);
148
+ }
149
+ return missing.length ? [body.trim(), ...missing].filter(Boolean).join("\n\n") : body.trim();
150
+ }
151
+ async function commentOnBug(credentials, input) {
152
+ const images = (input.images ?? []).slice(0, MAX_BUG_IMAGES);
153
+ const skipped = (input.images ?? []).slice(MAX_BUG_IMAGES);
154
+ const body = withImageMarkers(input.body, images.length);
155
+ if (!body) {
156
+ throw new Error("nothing to post \u2014 pass a body, images, or both");
157
+ }
158
+ const bugId = await resolveBugId(credentials, input.bug);
159
+ const response = await axios.post(
160
+ `${logger.configuration.serverUrl}/v1/bugs/${bugId}/comments`,
161
+ { body },
162
+ authHeaders(credentials)
163
+ );
164
+ const { bug, commentId } = response.data;
165
+ const result = { id: bug.id, displayId: bug.displayId, commentId, commentCount: bug.commentCount };
166
+ if (!images.length && !skipped.length) {
167
+ return result;
168
+ }
169
+ const attachments = await attachImages(credentials, bugId, images, 0, commentId);
170
+ for (const file of skipped) {
171
+ attachments.push({ file, ok: false, error: `skipped \u2014 a comment takes at most ${MAX_BUG_IMAGES} images` });
172
+ }
173
+ return { ...result, attachments };
174
+ }
141
175
  async function setBugStatus(credentials, input) {
142
176
  const bugId = await resolveBugId(credentials, input.bug);
143
177
  const response = await axios.patch(
@@ -430,6 +464,27 @@ ${lines.join("\n")}` : header }] };
430
464
  return toToolError(`Failed to edit bug: ${error instanceof Error ? error.message : String(error)}`);
431
465
  }
432
466
  });
467
+ mcp.registerTool("comment_bug", {
468
+ description: "Post a comment under a bug on the user's Happy bug board. Everyone following the bug is notified (Feishu), which an edit to the description does not do. Use it to report a result \u2014 a retest that passed or failed, a fix that shipped, a question for the reporter \u2014 instead of appending it to the description.",
469
+ title: "Comment on Bug",
470
+ inputSchema: {
471
+ bug: z.z.string().describe('Which bug, as the user refers to it: "BUG-236", "#236" or "236". An internal bug id also works.'),
472
+ body: z.z.string().describe("The comment text. To place a screenshot inside it, put [[bug-image:N]] where the Nth entry of images should appear; images left unplaced follow the text."),
473
+ images: z.z.array(z.z.string()).optional().describe("Absolute paths to screenshots on this machine, in the order the [[bug-image:N]] markers refer to them. JPEG and PNG only, up to 10, 20MB each.")
474
+ }
475
+ }, async (args) => {
476
+ const credentials = await logger.readCredentials();
477
+ if (!credentials) {
478
+ return toToolError("No Happy credentials on this machine.");
479
+ }
480
+ try {
481
+ const result = await commentOnBug(credentials, args);
482
+ logger.logger.debug("[happyMCP] Commented on bug:", result.displayId);
483
+ return toToolSuccess({ ok: true, ...result });
484
+ } catch (error) {
485
+ return toToolError(`Failed to comment on bug: ${error instanceof Error ? error.message : String(error)}`);
486
+ }
487
+ });
433
488
  mcp.registerTool("set_bug_status", {
434
489
  description: "Move a bug on the user's Happy bug board to another status: close it once a fix is verified, put it back in progress, send it to verification, or return it to pending. Use whenever the user says a bug is fixed, verified, closed, reopened, or should go back to someone.",
435
490
  title: "Set Bug Status",
@@ -475,7 +530,7 @@ ${lines.join("\n")}` : header }] };
475
530
  async function startHappyServer(client) {
476
531
  const transports = /* @__PURE__ */ new Map();
477
532
  const enableOrchestratorTools = prompt.shouldEnableOrchestratorTools();
478
- const toolNames = ["change_title", "preview_html", "device_list", "device_exec", "list_bugs", "get_bug", "submit_bug", "edit_bug", "delete_bug", "set_bug_status"];
533
+ const toolNames = ["change_title", "preview_html", "device_list", "device_exec", "list_bugs", "get_bug", "submit_bug", "edit_bug", "delete_bug", "set_bug_status", "comment_bug"];
479
534
  const originalConsoleError = console.error;
480
535
  console.error = (...args) => {
481
536
  logger.logger.debug("[happyMCP] console.error:", ...args);
@@ -3,17 +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-ByiU9yXy.cjs');
7
- var logger = require('./persistence-50wmDoBE.cjs');
6
+ var api = require('./api-DwiOsTuU.cjs');
7
+ var logger = require('./persistence-CZptiAaZ.cjs');
8
8
  var doctor$1 = require('./doctor-C08m5Z9f.cjs');
9
- var sessionDecrypt = require('./sessionDecrypt-DWm_k5dq.cjs');
10
- var auth = require('./auth-DnFrlXqp.cjs');
9
+ var sessionDecrypt = require('./sessionDecrypt-Bscb-Kfw.cjs');
10
+ var auth = require('./auth-D2z0WId5.cjs');
11
11
  var child_process = require('child_process');
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');
12
+ var doctor = require('./doctor-CX5edsk3.cjs');
13
+ var spawnHappyCLI = require('./spawnHappyCLI-C3WkMK2n.cjs');
14
+ var controlClient = require('./controlClient-DMxcJC-j.cjs');
15
+ var deviceKeys = require('./deviceKeys-Ttjgv9qm.cjs');
16
+ var install = require('./install-Ce6JldUY.cjs');
17
17
  var fastify = require('fastify');
18
18
  var fs = require('node:fs');
19
19
  var promises = require('node:fs/promises');
@@ -1,17 +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, 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';
4
+ import { A as ApiClient, f as forkCursorSession, c as forkGeminiSession, d as forkCodexSession, e as findClaudeProjectId, g as forkSession } from './api--fA9drop.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-CcOX4WLf.mjs';
6
6
  import { findAllHappyProcesses } from './doctor-ON7pN5G5.mjs';
7
- import { d as decryptSessionRow } from './sessionDecrypt-BsOlrqRs.mjs';
8
- import { authAndSetupMachineIfNeeded } from './auth-DnRtIM3d.mjs';
7
+ import { d as decryptSessionRow } from './sessionDecrypt-BQnoJy4t.mjs';
8
+ import { authAndSetupMachineIfNeeded } from './auth-B1Qy9v3F.mjs';
9
9
  import { spawn, execSync, exec } from 'child_process';
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';
10
+ import { getEnvironmentInfo } from './doctor-BxY-J5MM.mjs';
11
+ import { s as spawnHappyCLI } from './spawnHappyCLI-CgVBVqUH.mjs';
12
+ import { isDaemonRunningCurrentlyInstalledHappyVersion, stopDaemon, cleanupDaemonState } from './controlClient-COoWtF6Y.mjs';
13
+ import { a as readCachedDeviceKey, d as deviceExec } from './deviceKeys-chmGamFc.mjs';
14
+ import { P as PLIST_LABEL } from './install-CYdjwe-t.mjs';
15
15
  import fastify from 'fastify';
16
16
  import { createReadStream } from 'node:fs';
17
17
  import { stat } from 'node:fs/promises';
@@ -2,20 +2,20 @@ import os, { homedir } from 'node:os';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { existsSync, mkdirSync, writeFileSync, unlinkSync, readdirSync } from 'node:fs';
4
4
  import { readFile, mkdir, writeFile, stat, copyFile } from 'node:fs/promises';
5
- import { I as InvalidateSync, p as AsyncLock, m as connectionState, A as ApiClient, r as resolveToolsDir, b as startOfflineReconnection, e as findClaudeProjectId } from './api-B9shq-xZ.mjs';
6
- import { l as logger, i as isDebug, c as configuration, a as readSettings, p as packageJson } from './persistence-Da0uhblK.mjs';
7
- import { g as getProjectPath, a as claudeLocal, E as ExitCodeError, b as claudeCheckSession, s as systemPrompt } from './claudeLocal-CYtFfvTZ.mjs';
5
+ import { I as InvalidateSync, p as AsyncLock, m as connectionState, A as ApiClient, r as resolveToolsDir, b as startOfflineReconnection, e as findClaudeProjectId } from './api--fA9drop.mjs';
6
+ import { l as logger, i as isDebug, c as configuration, a as readSettings, p as packageJson } from './persistence-CcOX4WLf.mjs';
7
+ import { g as getProjectPath, a as claudeLocal, E as ExitCodeError, b as claudeCheckSession, s as systemPrompt } from './claudeLocal-Cs-BIAw0.mjs';
8
8
  import { R as RawJSONLinesSchema } from './types-BoJh4Qfv.mjs';
9
9
  import { join, resolve } from 'node:path';
10
10
  import { d as delay } from './time-DgsBLJA_.mjs';
11
11
  import { watch, access } from 'fs/promises';
12
12
  import { useStdout, useInput, Box, Text, render } from 'ink';
13
- import { b as parseSpecialCommand, a as MessageBuffer, M as MessageQueue2, h as hashObject } from './downloadImage-C3FHGZDr.mjs';
13
+ import { b as parseSpecialCommand, a as MessageBuffer, M as MessageQueue2, h as hashObject } from './downloadImage-DJ0qW4xQ.mjs';
14
14
  import React, { useState, useRef, useEffect, useCallback } from 'react';
15
15
  import { execSync, spawn } from 'node:child_process';
16
16
  import { createInterface } from 'node:readline';
17
17
  import { fileURLToPath } from 'node:url';
18
- import { i as isBun } from './spawnHappyCLI-Cv2VARTw.mjs';
18
+ import { i as isBun } from './spawnHappyCLI-CgVBVqUH.mjs';
19
19
  import { p as projectPath } from './projectPath-BTBIMB57.mjs';
20
20
  import 'axios';
21
21
  import 'node:events';
@@ -26,12 +26,12 @@ import 'crypto';
26
26
  import '@stablelib/base64';
27
27
  import 'expo-server-sdk';
28
28
  import 'chalk';
29
- import { a as formatMessageForClaude } from './formatImageMessage-C6glTFta.mjs';
29
+ import { a as formatMessageForClaude } from './formatImageMessage-Ck_SVHgI.mjs';
30
30
  import { isDeepStrictEqual } from 'node:util';
31
- import { i as initialMachineMetadata, s as stopCaffeinate, a as startCaffeinate } from './run-DjaUrH7x.mjs';
32
- import { getEnvironmentInfo } from './doctor-C77QV3rd.mjs';
33
- import { notifyDaemonSessionStarted } from './controlClient-BuKaeD-y.mjs';
34
- import { c as createMcpContext, r as registerKillSessionHandler, d as detectGitWorktree } from './registerKillSessionHandler-CxHjAcQu.mjs';
31
+ import { i as initialMachineMetadata, s as stopCaffeinate, a as startCaffeinate } from './run-Cjw5klTK.mjs';
32
+ import { getEnvironmentInfo } from './doctor-BxY-J5MM.mjs';
33
+ import { notifyDaemonSessionStarted } from './controlClient-COoWtF6Y.mjs';
34
+ import { c as createMcpContext, r as registerKillSessionHandler, d as detectGitWorktree } from './registerKillSessionHandler-CKWBWTcY.mjs';
35
35
  import { createServer } from 'node:http';
36
36
  import 'zod';
37
37
  import './index-7P6T8CE4.mjs';
@@ -40,7 +40,7 @@ import 'child_process';
40
40
  import 'util';
41
41
  import 'path';
42
42
  import 'node:module';
43
- import './sessionKeyCache-BBzsFcnN.mjs';
43
+ import './sessionKeyCache-DxPdM8uz.mjs';
44
44
  import 'fs';
45
45
  import './prompt-BsAZsPbo.mjs';
46
46
  import './trimIdent-BAjmv_TG.mjs';
@@ -51,13 +51,13 @@ import 'tmp';
51
51
  import './doctor-ON7pN5G5.mjs';
52
52
  import 'ps-list';
53
53
  import 'cross-spawn';
54
- import './sessionDecrypt-BsOlrqRs.mjs';
55
- import './auth-DnRtIM3d.mjs';
54
+ import './sessionDecrypt-BQnoJy4t.mjs';
55
+ import './auth-B1Qy9v3F.mjs';
56
56
  import 'qrcode-terminal';
57
- import './browser-BeERlPhN.mjs';
57
+ import './browser-ChGfY23u.mjs';
58
58
  import 'open';
59
- import './deviceKeys-DSXcQgLf.mjs';
60
- import './install-DbRGuSWv.mjs';
59
+ import './deviceKeys-chmGamFc.mjs';
60
+ import './install-CYdjwe-t.mjs';
61
61
  import 'fastify';
62
62
  import 'fastify-type-provider-zod';
63
63
  import '@modelcontextprotocol/sdk/server/mcp.js';
@@ -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-ByiU9yXy.cjs');
8
- var logger = require('./persistence-50wmDoBE.cjs');
9
- var claudeLocal = require('./claudeLocal-CuHH7tvQ.cjs');
7
+ var api = require('./api-DwiOsTuU.cjs');
8
+ var logger = require('./persistence-CZptiAaZ.cjs');
9
+ var claudeLocal = require('./claudeLocal-BtbtPj3C.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-DZBxkdwy.cjs');
15
+ var downloadImage = require('./downloadImage-DvHbBiN2.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-BNUBk0w5.cjs');
20
+ var spawnHappyCLI = require('./spawnHappyCLI-C3WkMK2n.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-CHjdeDGM.cjs');
31
+ var formatImageMessage = require('./formatImageMessage-DE96y8-H.cjs');
32
32
  var node_util = require('node:util');
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');
33
+ var run = require('./run-38zHldyV.cjs');
34
+ var doctor = require('./doctor-CX5edsk3.cjs');
35
+ var controlClient = require('./controlClient-DMxcJC-j.cjs');
36
+ var registerKillSessionHandler = require('./registerKillSessionHandler-DIFqoCCd.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-CmORI8jN.cjs');
45
+ require('./sessionKeyCache-By8_OSDl.cjs');
46
46
  require('fs');
47
47
  require('./prompt-BTWDZZO0.cjs');
48
48
  require('./trimIdent-4gvk9Wk6.cjs');
@@ -53,13 +53,13 @@ require('tmp');
53
53
  require('./doctor-C08m5Z9f.cjs');
54
54
  require('ps-list');
55
55
  require('cross-spawn');
56
- require('./sessionDecrypt-DWm_k5dq.cjs');
57
- require('./auth-DnFrlXqp.cjs');
56
+ require('./sessionDecrypt-Bscb-Kfw.cjs');
57
+ require('./auth-D2z0WId5.cjs');
58
58
  require('qrcode-terminal');
59
- require('./browser-DjONS-B5.cjs');
59
+ require('./browser-DPXZcBi-.cjs');
60
60
  require('open');
61
- require('./deviceKeys-CSfs6juX.cjs');
62
- require('./install-Td8RvuEV.cjs');
61
+ require('./deviceKeys-Ttjgv9qm.cjs');
62
+ require('./install-Ce6JldUY.cjs');
63
63
  require('fastify');
64
64
  require('fastify-type-provider-zod');
65
65
  require('@modelcontextprotocol/sdk/server/mcp.js');
@@ -733,7 +733,7 @@ class AbortError extends Error {
733
733
  }
734
734
  }
735
735
 
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
+ 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-CBEEtvJr.cjs', document.baseURI).href)));
737
737
  const __dirname$1 = path.join(__filename$1, "..");
738
738
  function getGlobalClaudeVersion() {
739
739
  try {
@@ -1,17 +1,17 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
- import { h as saveDiffRecords, i as extractUserText, j as isSystemMessage, k as generateStableUuid, l as findCodexSessionFile, m as connectionState, A as ApiClient } from './api-B9shq-xZ.mjs';
3
+ import { h as saveDiffRecords, i as extractUserText, j as isSystemMessage, k as generateStableUuid, l as findCodexSessionFile, m as connectionState, A as ApiClient } from './api--fA9drop.mjs';
4
4
  import { spawn, execSync } from 'node:child_process';
5
5
  import { createInterface } from 'node:readline';
6
- import { l as logger, i as isDebug, a as readSettings } from './persistence-Da0uhblK.mjs';
7
- import { B as BasePermissionHandler, c as createSessionMetadata, s as setupOfflineReconnection } from './setupOfflineReconnection-B4aU1Nix.mjs';
8
- import { B as BaseReasoningProcessor, h as handleConfigMetadataEvent, s as summarizeBashToolOutput } from './loadableToolOutput-C0tAWFJM.mjs';
6
+ import { l as logger, i as isDebug, a as readSettings } from './persistence-CcOX4WLf.mjs';
7
+ import { B as BasePermissionHandler, c as createSessionMetadata, s as setupOfflineReconnection } from './setupOfflineReconnection-HnT3f6i6.mjs';
8
+ import { B as BaseReasoningProcessor, h as handleConfigMetadataEvent, s as summarizeBashToolOutput } from './loadableToolOutput-D5HoFtRR.mjs';
9
9
  import { randomUUID } from 'node:crypto';
10
- import { M as MessageQueue2, h as hashObject, a as MessageBuffer, p as parseClear, d as downloadImage } from './downloadImage-C3FHGZDr.mjs';
11
- import { i as initialMachineMetadata, s as stopCaffeinate } from './run-DjaUrH7x.mjs';
12
- import { c as createMcpContext, r as registerKillSessionHandler } from './registerKillSessionHandler-CxHjAcQu.mjs';
10
+ import { M as MessageQueue2, h as hashObject, a as MessageBuffer, p as parseClear, d as downloadImage } from './downloadImage-DJ0qW4xQ.mjs';
11
+ import { i as initialMachineMetadata, s as stopCaffeinate } from './run-Cjw5klTK.mjs';
12
+ import { c as createMcpContext, r as registerKillSessionHandler } from './registerKillSessionHandler-CKWBWTcY.mjs';
13
13
  import { g as getFirstTurnInstruction } from './constants-pmXZGibX.mjs';
14
- import { notifyDaemonSessionStarted } from './controlClient-BuKaeD-y.mjs';
14
+ import { notifyDaemonSessionStarted } from './controlClient-COoWtF6Y.mjs';
15
15
  import { inspect } from 'node:util';
16
16
  import { readFile } from 'node:fs/promises';
17
17
  import { basename, isAbsolute } from 'node:path';
@@ -36,7 +36,7 @@ import 'crypto';
36
36
  import 'tweetnacl';
37
37
  import '@stablelib/base64';
38
38
  import 'expo-server-sdk';
39
- import './sessionKeyCache-BBzsFcnN.mjs';
39
+ import './sessionKeyCache-DxPdM8uz.mjs';
40
40
  import 'chalk';
41
41
  import 'fs';
42
42
  import 'os';
@@ -44,15 +44,15 @@ import 'tmp';
44
44
  import './doctor-ON7pN5G5.mjs';
45
45
  import 'ps-list';
46
46
  import 'cross-spawn';
47
- import './sessionDecrypt-BsOlrqRs.mjs';
48
- import './auth-DnRtIM3d.mjs';
47
+ import './sessionDecrypt-BQnoJy4t.mjs';
48
+ import './auth-B1Qy9v3F.mjs';
49
49
  import 'qrcode-terminal';
50
- import './browser-BeERlPhN.mjs';
50
+ import './browser-ChGfY23u.mjs';
51
51
  import 'open';
52
- import './doctor-C77QV3rd.mjs';
53
- import './spawnHappyCLI-Cv2VARTw.mjs';
54
- import './deviceKeys-DSXcQgLf.mjs';
55
- import './install-DbRGuSWv.mjs';
52
+ import './doctor-BxY-J5MM.mjs';
53
+ import './spawnHappyCLI-CgVBVqUH.mjs';
54
+ import './deviceKeys-chmGamFc.mjs';
55
+ import './install-CYdjwe-t.mjs';
56
56
  import './trimIdent-BAjmv_TG.mjs';
57
57
  import 'fastify';
58
58
  import 'fastify-type-provider-zod';