@zonease/happy 0.6.38 → 0.6.40

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 (112) hide show
  1. package/bin/happy.mjs +10 -0
  2. package/dist/{types-DvTsFaqR.cjs → api-C7FyJfZ1.cjs} +400 -1964
  3. package/dist/{types-BWpRU1VN.mjs → api-D6WL40-U.mjs} +220 -1729
  4. package/dist/auth-C7ZScWEw.cjs +274 -0
  5. package/dist/auth-DCsIoZLT.cjs +183 -0
  6. package/dist/auth-DO9GexAR.mjs +181 -0
  7. package/dist/auth-DxJ3VvrX.mjs +270 -0
  8. package/dist/browser-AoVGRX7y.mjs +20 -0
  9. package/dist/browser-DzgO4oaD.cjs +22 -0
  10. package/dist/claudeLocal-C6BdzhDx.cjs +352 -0
  11. package/dist/claudeLocal-CWNGpJ0-.mjs +344 -0
  12. package/dist/codex/happyMcpStdioBridge.cjs +4 -1
  13. package/dist/codex/happyMcpStdioBridge.mjs +4 -1
  14. package/dist/common-BdNgghUJ.mjs +75 -0
  15. package/dist/common-CZvSRU4p.cjs +83 -0
  16. package/dist/{config-0Xnc8ARM.cjs → config-CclB3QW9.cjs} +21 -34
  17. package/dist/{config-_GW4YBCP.mjs → config-DZk-mJ0K.mjs} +7 -20
  18. package/dist/connect-BXLUKJ5P.mjs +679 -0
  19. package/dist/connect-k9CqDJ-T.cjs +681 -0
  20. package/dist/{constants-B4x1K7by.cjs → constants-E_UWYTo3.cjs} +2 -2
  21. package/dist/{constants-BO9OAFOT.mjs → constants-pmXZGibX.mjs} +1 -1
  22. package/dist/controlClient-B23M-WPp.cjs +177 -0
  23. package/dist/controlClient-DB5tDU7V.mjs +167 -0
  24. package/dist/deviceKeys-BTdo34Uz.mjs +175 -0
  25. package/dist/deviceKeys-C540DcXl.cjs +182 -0
  26. package/dist/diagnose-B3D1a_v0.cjs +60 -0
  27. package/dist/diagnose-CuRKXxt1.mjs +58 -0
  28. package/dist/doctor-BQGLhrcI.cjs +214 -0
  29. package/dist/doctor-C08m5Z9f.cjs +78 -0
  30. package/dist/doctor-CU4JLGQ1.mjs +211 -0
  31. package/dist/doctor-ON7pN5G5.mjs +74 -0
  32. package/dist/downloadImage-DZXI3mXL.mjs +887 -0
  33. package/dist/downloadImage-cQ1Z7hkC.cjs +897 -0
  34. package/dist/enroll-B55BQR56.mjs +113 -0
  35. package/dist/enroll-Bo-CNio1.cjs +115 -0
  36. package/dist/evidence-DQp8QWcv.cjs +129 -0
  37. package/dist/evidence-DTYRAaOZ.mjs +127 -0
  38. package/dist/formatImageMessage-CixDYY6G.cjs +46 -0
  39. package/dist/formatImageMessage-DbKSSjMx.mjs +43 -0
  40. package/dist/github-DKcyF1zp.mjs +57 -0
  41. package/dist/github-h9GhJJ_C.cjs +59 -0
  42. package/dist/index-CDTNgfUf.cjs +578 -0
  43. package/dist/index-CPKdvi7J.mjs +554 -0
  44. package/dist/index.cjs +812 -40
  45. package/dist/index.mjs +813 -40
  46. package/dist/install-B1e6rdy7.mjs +94 -0
  47. package/dist/install-CgUPGIoF.mjs +95 -0
  48. package/dist/install-D7Ir7ciZ.cjs +96 -0
  49. package/dist/install-DSDufaPd.cjs +98 -0
  50. package/dist/lib.cjs +18 -12
  51. package/dist/lib.d.cts +77 -0
  52. package/dist/lib.d.mts +77 -0
  53. package/dist/lib.mjs +13 -7
  54. package/dist/{loadableToolOutput-va3RLplh.mjs → loadableToolOutput-Bfei9wPq.mjs} +4 -2
  55. package/dist/{loadableToolOutput-5vdQB98M.cjs → loadableToolOutput-CbLGtvST.cjs} +63 -61
  56. package/dist/mcpToolSchemas-CjeTfrAs.mjs +62 -0
  57. package/dist/mcpToolSchemas-DK42yoZ_.cjs +64 -0
  58. package/dist/persistence-CBTtC_dm.cjs +996 -0
  59. package/dist/persistence-DKfF81pd.mjs +944 -0
  60. package/dist/projectPath-BTBIMB57.mjs +10 -0
  61. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  62. package/dist/prompt-BTWDZZO0.cjs +25 -0
  63. package/dist/prompt-BsAZsPbo.mjs +22 -0
  64. package/dist/release-BMEzNONE.mjs +168 -0
  65. package/dist/release-EhOJeAZe.cjs +171 -0
  66. package/dist/run-BVZsMNwN.mjs +2164 -0
  67. package/dist/run-CURx7LhK.cjs +2188 -0
  68. package/dist/runClaude-6Gi0sYQy.mjs +3763 -0
  69. package/dist/runClaude-CL3Kt5ex.cjs +3766 -0
  70. package/dist/{runCodex-DiKzBf9q.mjs → runCodex-ClwEgJ7M.mjs} +36 -20
  71. package/dist/{runCodex-skq0j05d.cjs → runCodex-YKyVBkJ3.cjs} +169 -153
  72. package/dist/{runGemini-BeqrVq8R.mjs → runGemini-BPWxVr60.mjs} +34 -17
  73. package/dist/{runGemini-CVp-CEIh.cjs → runGemini-Xz2W1spn.cjs} +212 -195
  74. package/dist/{runOneShot-ltCpHbBB.mjs → runOneShot-CdCWiiLr.mjs} +14 -38
  75. package/dist/{runOneShot-BQNkNW61.cjs → runOneShot-DjZyCvDI.cjs} +31 -55
  76. package/dist/{serve-BNdoEDVx.mjs → serve-B48JttQ3.mjs} +12 -35
  77. package/dist/{serve-BECdtivY.cjs → serve-B8vaWQA0.cjs} +35 -58
  78. package/dist/session-BXboDn2V.mjs +108 -0
  79. package/dist/session-BZO25zxp.cjs +110 -0
  80. package/dist/sessionKeyCache-B6cGadYL.mjs +33 -0
  81. package/dist/sessionKeyCache-CDmexJ9p.cjs +36 -0
  82. package/dist/sessionList-CgAYZpNj.mjs +51 -0
  83. package/dist/sessionList-lQ-nqEhc.cjs +54 -0
  84. package/dist/sessionSummary-CcORiQSq.cjs +393 -0
  85. package/dist/sessionSummary-DCWQoaDP.mjs +387 -0
  86. package/dist/spawnHappyCLI-KiazE3kL.cjs +70 -0
  87. package/dist/spawnHappyCLI-yBIP_Oqi.mjs +66 -0
  88. package/dist/ssh-q5uZhqBf.mjs +359 -0
  89. package/dist/ssh-yMllSHu5.cjs +365 -0
  90. package/dist/systemdScope-BeOtAkhk.mjs +25 -0
  91. package/dist/systemdScope-DW3-UoKB.cjs +29 -0
  92. package/dist/task-_nr7J19j.cjs +167 -0
  93. package/dist/task-wNX1N2i4.mjs +165 -0
  94. package/dist/time-Bj2HRkKH.cjs +33 -0
  95. package/dist/time-DgsBLJA_.mjs +29 -0
  96. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  97. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  98. package/dist/types-BoJh4Qfv.mjs +57 -0
  99. package/dist/types-DWeB7aqh.cjs +59 -0
  100. package/dist/uninstall-Buaz7d-X.cjs +77 -0
  101. package/dist/uninstall-Dxf6_4mQ.mjs +75 -0
  102. package/dist/update-CGlIfa8e.cjs +111 -0
  103. package/dist/update-CnnoX2cV.mjs +109 -0
  104. package/dist/workflowCommon-B0d01Y_a.mjs +56 -0
  105. package/dist/workflowCommon-Bl568-rt.cjs +62 -0
  106. package/dist/workflowReports-BEWuQesA.cjs +113 -0
  107. package/dist/workflowReports-Dd8-4-8f.mjs +108 -0
  108. package/package.json +1 -1
  109. package/dist/index-BbCDDvoB.cjs +0 -11376
  110. package/dist/index-vvZXdswy.mjs +0 -11336
  111. package/dist/mcpToolSchemas-CdPXJQmb.mjs +0 -175
  112. package/dist/mcpToolSchemas-f-kttjFw.cjs +0 -186
@@ -0,0 +1,165 @@
1
+ import chalk from 'chalk';
2
+ import { resolve } from 'node:path';
3
+ import { r as readCredentials } from './persistence-DKfF81pd.mjs';
4
+ import { r as runSessionList } from './sessionList-CgAYZpNj.mjs';
5
+ import { r as runSessionSummary } from './sessionSummary-DCWQoaDP.mjs';
6
+ import { p as parseWorkflowArgs, s as stringFlag, b as booleanFlag, n as numberFlag, a as printOrWriteOutput } from './workflowCommon-B0d01Y_a.mjs';
7
+ import 'node:fs/promises';
8
+ import 'node:fs';
9
+ import 'node:os';
10
+ import 'zod';
11
+ import 'node:crypto';
12
+ import 'tweetnacl';
13
+ import 'fs';
14
+ import 'axios';
15
+ import './auth-DxJ3VvrX.mjs';
16
+ import 'qrcode-terminal';
17
+ import './time-DgsBLJA_.mjs';
18
+ import './browser-AoVGRX7y.mjs';
19
+ import 'open';
20
+ import 'react';
21
+ import 'ink';
22
+ import './sessionKeyCache-B6cGadYL.mjs';
23
+
24
+ function printTaskHelp() {
25
+ console.log(`
26
+ ${chalk.bold("happy task")} - Agent handoff helpers
27
+
28
+ ${chalk.bold("Usage:")}
29
+ happy task brief --session <sessionId> [options]
30
+ happy task brief <sessionId> [options]
31
+ happy task brief --recent [--project <path>] [options]
32
+
33
+ ${chalk.bold("Options:")}
34
+ --session <id> Happy session ID to summarize
35
+ --recent Pick the most recent session, optionally filtered by --project
36
+ --project <path> Project path filter for --recent
37
+ --limit <n> Raw messages to compact (default: 200)
38
+ --max-turns <n> Compact turns to include (default: 80)
39
+ --text-limit <n> Max chars per text block (default: 800)
40
+ --out <path> Write the brief to a markdown file
41
+ --json Print machine-readable JSON
42
+ -h, --help Show this help
43
+ `);
44
+ }
45
+ function collectSessionText(summary) {
46
+ const chunks = [];
47
+ if (summary.storedSummary) chunks.push(summary.storedSummary);
48
+ for (const turn of summary.turns) {
49
+ if (turn.user?.text) chunks.push(turn.user.text);
50
+ for (const text of turn.assistantTexts) chunks.push(text.text);
51
+ }
52
+ return chunks.join("\n");
53
+ }
54
+ function extractMatchingLines(text, patterns, limit) {
55
+ const seen = /* @__PURE__ */ new Set();
56
+ const lines = [];
57
+ for (const line of text.split("\n")) {
58
+ const trimmed = line.replace(/^[-*]\s*/, "").trim();
59
+ if (!trimmed || seen.has(trimmed)) continue;
60
+ if (patterns.some((pattern) => pattern.test(trimmed))) {
61
+ seen.add(trimmed);
62
+ lines.push(trimmed);
63
+ }
64
+ if (lines.length >= limit) break;
65
+ }
66
+ return lines;
67
+ }
68
+ function bulletList(lines, fallback) {
69
+ if (lines.length === 0) return `- ${fallback}`;
70
+ return lines.map((line) => `- ${line}`).join("\n");
71
+ }
72
+ function buildBriefMarkdown(summary, source) {
73
+ const text = collectSessionText(summary);
74
+ const done = extractMatchingLines(text, [/完成|已实现|通过|passed|fixed|implemented|verified/i], 6);
75
+ const blockers = extractMatchingLines(text, [/失败|阻塞|blocked|failed|error|E401|unrelated/i], 6);
76
+ const next = extractMatchingLines(text, [/继续|下一步|TODO|todo|next|publish|发布|验证|verify/i], 6);
77
+ return `# Happy Task Brief
78
+
79
+ - Source: ${source}
80
+ - Session: \`${summary.sessionId}\`
81
+ - Active: ${summary.active ? "yes" : "no"}
82
+ - Agent: ${summary.agent.name ?? "(unknown)"}${summary.agent.model ? ` / ${summary.agent.model}` : ""}
83
+ - Machine: ${summary.machine.name ?? summary.machine.id ?? "(unknown)"}
84
+ - Path: ${summary.path ?? "(unknown)"}
85
+ - Updated: ${new Date(summary.updatedAt).toISOString()}
86
+
87
+ ## Stored Summary
88
+
89
+ ${summary.storedSummary ?? "(none)"}
90
+
91
+ ## Recent Conversation
92
+
93
+ ${summary.summaryText}
94
+
95
+ ## Done / Evidence
96
+
97
+ ${bulletList(done, "No explicit completion evidence detected in the compact window.")}
98
+
99
+ ## Blockers / Risks
100
+
101
+ ${bulletList(blockers, "No explicit blocker detected in the compact window.")}
102
+
103
+ ## Suggested Next Actions
104
+
105
+ ${bulletList(next, "Continue from the latest user request and verify before reporting completion.")}
106
+
107
+ ## Continuation Prompt
108
+
109
+ Continue session \`${summary.sessionId}\` from this brief. Preserve existing user changes, inspect the repository rules before editing, implement only the requested scope, run focused verification, and summarize changed files plus test results in Chinese.
110
+ `;
111
+ }
112
+ function findRecentSession(sessions, projectPath) {
113
+ if (!projectPath) return sessions[0];
114
+ const resolved = resolve(projectPath);
115
+ return sessions.find((session) => {
116
+ if (!session.path) return false;
117
+ const path = resolve(session.path);
118
+ return path === resolved || path.startsWith(`${resolved}/`) || resolved.startsWith(`${path}/`);
119
+ });
120
+ }
121
+ async function handleTaskCommand(args) {
122
+ const action = args[0];
123
+ if (!action || action === "-h" || action === "--help") {
124
+ printTaskHelp();
125
+ return;
126
+ }
127
+ if (action !== "brief") {
128
+ throw new Error(`Unknown task command: ${action}. Use "happy task brief".`);
129
+ }
130
+ const parsed = parseWorkflowArgs(args.slice(1), /* @__PURE__ */ new Set(["--session", "--project", "--limit", "--max-turns", "--text-limit", "--out"]));
131
+ const credentials = await readCredentials();
132
+ if (!credentials) {
133
+ throw new Error('No happy credentials found. Run "happy auth login" first.');
134
+ }
135
+ let sessionId = stringFlag(parsed, "--session") ?? parsed.positionals[0];
136
+ let source = "session";
137
+ if (!sessionId && booleanFlag(parsed, "--recent")) {
138
+ const result = await runSessionList(credentials, { status: "all", limit: 150 });
139
+ const recent = findRecentSession(result.sessions, stringFlag(parsed, "--project"));
140
+ if (!recent) {
141
+ throw new Error("No matching recent session found.");
142
+ }
143
+ sessionId = recent.sessionId;
144
+ source = "recent";
145
+ }
146
+ if (!sessionId) {
147
+ throw new Error('Session ID required. Use "happy task brief --session <id>" or "--recent".');
148
+ }
149
+ const input = {
150
+ sessionId,
151
+ limit: numberFlag(parsed, "--limit"),
152
+ maxTurns: numberFlag(parsed, "--max-turns"),
153
+ textLimit: numberFlag(parsed, "--text-limit"),
154
+ includeTools: true
155
+ };
156
+ const summary = await runSessionSummary(credentials, input);
157
+ const brief = buildBriefMarkdown(summary, source);
158
+ if (booleanFlag(parsed, "--json")) {
159
+ console.log(JSON.stringify({ source, summary, brief }, null, 2));
160
+ return;
161
+ }
162
+ await printOrWriteOutput(brief, stringFlag(parsed, "--out"));
163
+ }
164
+
165
+ export { handleTaskCommand };
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ async function delay(ms) {
4
+ return new Promise((resolve) => setTimeout(resolve, ms));
5
+ }
6
+ function exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount) {
7
+ let maxDelayRet = minDelay + (maxDelay - minDelay) / maxFailureCount * Math.min(currentFailureCount, maxFailureCount);
8
+ return Math.round(Math.random() * maxDelayRet);
9
+ }
10
+ function createBackoff(opts) {
11
+ return async (callback) => {
12
+ let currentFailureCount = 0;
13
+ const minDelay = 250;
14
+ const maxDelay = 1e3;
15
+ const maxFailureCount = 50;
16
+ while (true) {
17
+ try {
18
+ return await callback();
19
+ } catch (e) {
20
+ if (currentFailureCount < maxFailureCount) {
21
+ currentFailureCount++;
22
+ }
23
+ let waitForRequest = exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount);
24
+ await delay(waitForRequest);
25
+ }
26
+ }
27
+ };
28
+ }
29
+ let backoff = createBackoff();
30
+
31
+ exports.backoff = backoff;
32
+ exports.delay = delay;
33
+ exports.exponentialBackoffDelay = exponentialBackoffDelay;
@@ -0,0 +1,29 @@
1
+ async function delay(ms) {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
4
+ function exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount) {
5
+ let maxDelayRet = minDelay + (maxDelay - minDelay) / maxFailureCount * Math.min(currentFailureCount, maxFailureCount);
6
+ return Math.round(Math.random() * maxDelayRet);
7
+ }
8
+ function createBackoff(opts) {
9
+ return async (callback) => {
10
+ let currentFailureCount = 0;
11
+ const minDelay = 250;
12
+ const maxDelay = 1e3;
13
+ const maxFailureCount = 50;
14
+ while (true) {
15
+ try {
16
+ return await callback();
17
+ } catch (e) {
18
+ if (currentFailureCount < maxFailureCount) {
19
+ currentFailureCount++;
20
+ }
21
+ let waitForRequest = exponentialBackoffDelay(currentFailureCount, minDelay, maxDelay, maxFailureCount);
22
+ await delay(waitForRequest);
23
+ }
24
+ }
25
+ };
26
+ }
27
+ let backoff = createBackoff();
28
+
29
+ export { backoff as b, delay as d, exponentialBackoffDelay as e };
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ function trimIdent(text) {
4
+ const lines = text.split("\n");
5
+ while (lines.length > 0 && lines[0].trim() === "") {
6
+ lines.shift();
7
+ }
8
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
9
+ lines.pop();
10
+ }
11
+ const minSpaces = lines.reduce((min, line) => {
12
+ if (line.trim() === "") {
13
+ return min;
14
+ }
15
+ const leadingSpaces = line.match(/^\s*/)[0].length;
16
+ return Math.min(min, leadingSpaces);
17
+ }, Infinity);
18
+ const trimmedLines = lines.map((line) => line.slice(minSpaces));
19
+ return trimmedLines.join("\n");
20
+ }
21
+
22
+ exports.trimIdent = trimIdent;
@@ -0,0 +1,20 @@
1
+ function trimIdent(text) {
2
+ const lines = text.split("\n");
3
+ while (lines.length > 0 && lines[0].trim() === "") {
4
+ lines.shift();
5
+ }
6
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
7
+ lines.pop();
8
+ }
9
+ const minSpaces = lines.reduce((min, line) => {
10
+ if (line.trim() === "") {
11
+ return min;
12
+ }
13
+ const leadingSpaces = line.match(/^\s*/)[0].length;
14
+ return Math.min(min, leadingSpaces);
15
+ }, Infinity);
16
+ const trimmedLines = lines.map((line) => line.slice(minSpaces));
17
+ return trimmedLines.join("\n");
18
+ }
19
+
20
+ export { trimIdent as t };
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+
3
+ const UsageSchema = z.object({
4
+ input_tokens: z.number().int().nonnegative(),
5
+ cache_creation_input_tokens: z.number().int().nonnegative().optional(),
6
+ cache_read_input_tokens: z.number().int().nonnegative().optional(),
7
+ output_tokens: z.number().int().nonnegative(),
8
+ service_tier: z.string().nullish()
9
+ }).passthrough();
10
+ const RawJSONLinesSchema = z.discriminatedUnion("type", [
11
+ // User message - validates uuid and message.content
12
+ z.object({
13
+ type: z.literal("user"),
14
+ isSidechain: z.boolean().optional(),
15
+ isMeta: z.boolean().optional(),
16
+ uuid: z.string(),
17
+ // Used in getMessageKey()
18
+ message: z.object({
19
+ content: z.union([z.string(), z.any()])
20
+ // Used in sessionScanner.ts
21
+ }).passthrough()
22
+ }).passthrough(),
23
+ // Assistant message - only validates uuid and type
24
+ // message object is optional to handle synthetic error messages (isApiErrorMessage: true)
25
+ // which may have different structure than normal assistant messages
26
+ z.object({
27
+ uuid: z.string(),
28
+ type: z.literal("assistant"),
29
+ message: z.object({
30
+ usage: UsageSchema.optional(),
31
+ // Used in apiSession.ts
32
+ model: z.string().optional()
33
+ // Used for cost calculation
34
+ }).passthrough().optional()
35
+ }).passthrough(),
36
+ // Summary message - validates summary and leafUuid
37
+ z.object({
38
+ type: z.literal("summary"),
39
+ summary: z.string(),
40
+ // Used in apiSession.ts
41
+ leafUuid: z.string()
42
+ // Used in getMessageKey()
43
+ }).passthrough(),
44
+ // System message - validates uuid
45
+ z.object({
46
+ type: z.literal("system"),
47
+ uuid: z.string()
48
+ // Used in getMessageKey()
49
+ }).passthrough(),
50
+ // Progress message - hook progress events, not counted toward message limits
51
+ z.object({
52
+ type: z.literal("progress"),
53
+ uuid: z.string()
54
+ }).passthrough()
55
+ ]);
56
+
57
+ export { RawJSONLinesSchema as R };
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var z = require('zod');
4
+
5
+ const UsageSchema = z.z.object({
6
+ input_tokens: z.z.number().int().nonnegative(),
7
+ cache_creation_input_tokens: z.z.number().int().nonnegative().optional(),
8
+ cache_read_input_tokens: z.z.number().int().nonnegative().optional(),
9
+ output_tokens: z.z.number().int().nonnegative(),
10
+ service_tier: z.z.string().nullish()
11
+ }).passthrough();
12
+ const RawJSONLinesSchema = z.z.discriminatedUnion("type", [
13
+ // User message - validates uuid and message.content
14
+ z.z.object({
15
+ type: z.z.literal("user"),
16
+ isSidechain: z.z.boolean().optional(),
17
+ isMeta: z.z.boolean().optional(),
18
+ uuid: z.z.string(),
19
+ // Used in getMessageKey()
20
+ message: z.z.object({
21
+ content: z.z.union([z.z.string(), z.z.any()])
22
+ // Used in sessionScanner.ts
23
+ }).passthrough()
24
+ }).passthrough(),
25
+ // Assistant message - only validates uuid and type
26
+ // message object is optional to handle synthetic error messages (isApiErrorMessage: true)
27
+ // which may have different structure than normal assistant messages
28
+ z.z.object({
29
+ uuid: z.z.string(),
30
+ type: z.z.literal("assistant"),
31
+ message: z.z.object({
32
+ usage: UsageSchema.optional(),
33
+ // Used in apiSession.ts
34
+ model: z.z.string().optional()
35
+ // Used for cost calculation
36
+ }).passthrough().optional()
37
+ }).passthrough(),
38
+ // Summary message - validates summary and leafUuid
39
+ z.z.object({
40
+ type: z.z.literal("summary"),
41
+ summary: z.z.string(),
42
+ // Used in apiSession.ts
43
+ leafUuid: z.z.string()
44
+ // Used in getMessageKey()
45
+ }).passthrough(),
46
+ // System message - validates uuid
47
+ z.z.object({
48
+ type: z.z.literal("system"),
49
+ uuid: z.z.string()
50
+ // Used in getMessageKey()
51
+ }).passthrough(),
52
+ // Progress message - hook progress events, not counted toward message limits
53
+ z.z.object({
54
+ type: z.z.literal("progress"),
55
+ uuid: z.z.string()
56
+ }).passthrough()
57
+ ]);
58
+
59
+ exports.RawJSONLinesSchema = RawJSONLinesSchema;
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var logger = require('./persistence-CBTtC_dm.cjs');
4
+ var fs = require('fs');
5
+ var child_process = require('child_process');
6
+ var path = require('path');
7
+ var os = require('os');
8
+ var systemdScope = require('./systemdScope-DW3-UoKB.cjs');
9
+ var controlClient = require('./controlClient-B23M-WPp.cjs');
10
+ require('node:fs/promises');
11
+ require('node:fs');
12
+ require('node:os');
13
+ require('node:path');
14
+ require('zod');
15
+ require('node:crypto');
16
+ require('tweetnacl');
17
+ require('chalk');
18
+ require('./projectPath-ChLhdOyt.cjs');
19
+ require('url');
20
+
21
+ const PLIST_LABEL = "com.happy-cli.daemon";
22
+ const PLIST_PATH = path.join(os.homedir(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
23
+ async function uninstall$2() {
24
+ if (!fs.existsSync(PLIST_PATH)) {
25
+ logger.logger.info("No LaunchAgent found. Auto-start is not enabled.");
26
+ return;
27
+ }
28
+ try {
29
+ child_process.execSync(`launchctl unload ${PLIST_PATH}`, { stdio: "ignore" });
30
+ } catch {
31
+ }
32
+ fs.unlinkSync(PLIST_PATH);
33
+ logger.logger.info("Daemon auto-start disabled.");
34
+ }
35
+
36
+ async function uninstall$1() {
37
+ const scopes = [systemdScope.systemdScopeFor(true), systemdScope.systemdScopeFor(false)].filter((scope) => fs.existsSync(scope.unitPath));
38
+ if (scopes.length === 0) {
39
+ logger.logger.info("No systemd service found. Auto-start is not enabled.");
40
+ return;
41
+ }
42
+ for (const scope of scopes) {
43
+ if (scope.system && !systemdScope.isRootUser()) {
44
+ logger.logger.info(`Skipping ${scope.unitPath} \u2014 removing it needs root: sudo happy daemon disable`);
45
+ continue;
46
+ }
47
+ try {
48
+ child_process.execSync(`systemctl ${scope.systemctlFlag} disable --now ${systemdScope.SERVICE_NAME}`.trim(), { stdio: "ignore" });
49
+ } catch {
50
+ }
51
+ fs.unlinkSync(scope.unitPath);
52
+ try {
53
+ child_process.execSync(`systemctl ${scope.systemctlFlag} daemon-reload`.trim(), { stdio: "ignore" });
54
+ } catch {
55
+ }
56
+ logger.logger.info(`Removed ${scope.unitPath}`);
57
+ }
58
+ logger.logger.info("Daemon auto-start disabled.");
59
+ }
60
+
61
+ async function uninstall() {
62
+ if (process.platform === "darwin") {
63
+ logger.logger.info("Removing daemon auto-start for macOS...");
64
+ await uninstall$2();
65
+ } else if (process.platform === "linux") {
66
+ logger.logger.info("Removing daemon auto-start for Linux...");
67
+ await uninstall$1();
68
+ } else {
69
+ throw new Error(`Unsupported platform: ${process.platform}. Only macOS and Linux are supported.`);
70
+ }
71
+ try {
72
+ await controlClient.stopDaemon();
73
+ } catch {
74
+ }
75
+ }
76
+
77
+ exports.uninstall = uninstall;
@@ -0,0 +1,75 @@
1
+ import { l as logger } from './persistence-DKfF81pd.mjs';
2
+ import { existsSync, unlinkSync } from 'fs';
3
+ import { execSync } from 'child_process';
4
+ import { join } from 'path';
5
+ import os from 'os';
6
+ import { s as systemdScopeFor, i as isRootUser, S as SERVICE_NAME } from './systemdScope-BeOtAkhk.mjs';
7
+ import { stopDaemon } from './controlClient-DB5tDU7V.mjs';
8
+ import 'node:fs/promises';
9
+ import 'node:fs';
10
+ import 'node:os';
11
+ import 'node:path';
12
+ import 'zod';
13
+ import 'node:crypto';
14
+ import 'tweetnacl';
15
+ import 'chalk';
16
+ import './projectPath-BTBIMB57.mjs';
17
+ import 'url';
18
+
19
+ const PLIST_LABEL = "com.happy-cli.daemon";
20
+ const PLIST_PATH = join(os.homedir(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
21
+ async function uninstall$2() {
22
+ if (!existsSync(PLIST_PATH)) {
23
+ logger.info("No LaunchAgent found. Auto-start is not enabled.");
24
+ return;
25
+ }
26
+ try {
27
+ execSync(`launchctl unload ${PLIST_PATH}`, { stdio: "ignore" });
28
+ } catch {
29
+ }
30
+ unlinkSync(PLIST_PATH);
31
+ logger.info("Daemon auto-start disabled.");
32
+ }
33
+
34
+ async function uninstall$1() {
35
+ const scopes = [systemdScopeFor(true), systemdScopeFor(false)].filter((scope) => existsSync(scope.unitPath));
36
+ if (scopes.length === 0) {
37
+ logger.info("No systemd service found. Auto-start is not enabled.");
38
+ return;
39
+ }
40
+ for (const scope of scopes) {
41
+ if (scope.system && !isRootUser()) {
42
+ logger.info(`Skipping ${scope.unitPath} \u2014 removing it needs root: sudo happy daemon disable`);
43
+ continue;
44
+ }
45
+ try {
46
+ execSync(`systemctl ${scope.systemctlFlag} disable --now ${SERVICE_NAME}`.trim(), { stdio: "ignore" });
47
+ } catch {
48
+ }
49
+ unlinkSync(scope.unitPath);
50
+ try {
51
+ execSync(`systemctl ${scope.systemctlFlag} daemon-reload`.trim(), { stdio: "ignore" });
52
+ } catch {
53
+ }
54
+ logger.info(`Removed ${scope.unitPath}`);
55
+ }
56
+ logger.info("Daemon auto-start disabled.");
57
+ }
58
+
59
+ async function uninstall() {
60
+ if (process.platform === "darwin") {
61
+ logger.info("Removing daemon auto-start for macOS...");
62
+ await uninstall$2();
63
+ } else if (process.platform === "linux") {
64
+ logger.info("Removing daemon auto-start for Linux...");
65
+ await uninstall$1();
66
+ } else {
67
+ throw new Error(`Unsupported platform: ${process.platform}. Only macOS and Linux are supported.`);
68
+ }
69
+ try {
70
+ await stopDaemon();
71
+ } catch {
72
+ }
73
+ }
74
+
75
+ export { uninstall };
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ var chalk = require('chalk');
4
+ var node_child_process = require('node:child_process');
5
+ var fs = require('node:fs');
6
+ var logger = require('./persistence-CBTtC_dm.cjs');
7
+ var controlClient = require('./controlClient-B23M-WPp.cjs');
8
+ var spawnHappyCLI = require('./spawnHappyCLI-KiazE3kL.cjs');
9
+ require('node:fs/promises');
10
+ require('node:os');
11
+ require('node:path');
12
+ require('zod');
13
+ require('node:crypto');
14
+ require('tweetnacl');
15
+ require('fs');
16
+ require('./projectPath-ChLhdOyt.cjs');
17
+ require('path');
18
+ require('url');
19
+ require('child_process');
20
+
21
+ const PACKAGE_NAME = "@zonease/happy";
22
+ function detectPackageManager() {
23
+ try {
24
+ const whichOutput = node_child_process.execSync("which happy", { encoding: "utf-8" }).trim();
25
+ const realPath = fs.realpathSync(whichOutput);
26
+ if (realPath.includes("/pnpm/") || realPath.includes("/pnpm-global/")) {
27
+ return "pnpm";
28
+ }
29
+ if (realPath.includes("/.yarn/") || realPath.includes("/yarn/")) {
30
+ return "yarn";
31
+ }
32
+ } catch {
33
+ }
34
+ return "npm";
35
+ }
36
+ function getUpgradeCommand(pm) {
37
+ switch (pm) {
38
+ case "pnpm":
39
+ return ["pnpm", "add", "-g", `${PACKAGE_NAME}@latest`];
40
+ case "yarn":
41
+ return ["yarn", "global", "add", `${PACKAGE_NAME}@latest`];
42
+ case "npm":
43
+ return ["npm", "install", "-g", `${PACKAGE_NAME}@latest`];
44
+ }
45
+ }
46
+ function getLatestVersion() {
47
+ try {
48
+ return node_child_process.execFileSync("npm", ["view", PACKAGE_NAME, "version"], { encoding: "utf-8" }).trim();
49
+ } catch {
50
+ return null;
51
+ }
52
+ }
53
+ async function handleUpdateCommand() {
54
+ const currentVersion = logger.packageJson.version;
55
+ console.log(chalk.gray("Checking for updates..."));
56
+ const latestVersion = getLatestVersion();
57
+ if (!latestVersion) {
58
+ console.error(chalk.red("Failed to check latest version. Please check your network connection."));
59
+ process.exit(1);
60
+ }
61
+ console.log(`Current version: ${chalk.cyan(currentVersion)}`);
62
+ console.log(`Latest version: ${chalk.cyan(latestVersion)}`);
63
+ console.log("");
64
+ if (currentVersion === latestVersion) {
65
+ console.log(chalk.green("\u2713 Already up to date"));
66
+ process.exit(0);
67
+ }
68
+ const pm = detectPackageManager();
69
+ const command = getUpgradeCommand(pm);
70
+ console.log(`Upgrading via ${chalk.bold(pm)}...`);
71
+ try {
72
+ node_child_process.execFileSync(command[0], command.slice(1), { stdio: "inherit" });
73
+ } catch {
74
+ console.error(chalk.red(`
75
+ \u2717 Upgrade failed. You can try manually:`));
76
+ console.error(chalk.gray(` ${command.join(" ")}`));
77
+ process.exit(1);
78
+ }
79
+ console.log(chalk.green(`
80
+ \u2713 Upgraded to ${latestVersion}`));
81
+ try {
82
+ const daemonRunning = await controlClient.checkIfDaemonRunningAndCleanupStaleState();
83
+ if (daemonRunning) {
84
+ console.log("Restarting daemon...");
85
+ await controlClient.stopDaemon();
86
+ const child = spawnHappyCLI.spawnHappyCLI(["daemon", "start-sync"], {
87
+ detached: true,
88
+ stdio: "ignore",
89
+ env: process.env
90
+ });
91
+ child.unref();
92
+ let started = false;
93
+ for (let i = 0; i < 50; i++) {
94
+ if (await controlClient.checkIfDaemonRunningAndCleanupStaleState()) {
95
+ started = true;
96
+ break;
97
+ }
98
+ await new Promise((resolve) => setTimeout(resolve, 100));
99
+ }
100
+ if (started) {
101
+ console.log(chalk.green("\u2713 Daemon restarted"));
102
+ } else {
103
+ console.log(chalk.yellow('\u26A0 Daemon restart timed out. Run "happy daemon start" manually.'));
104
+ }
105
+ }
106
+ } catch {
107
+ }
108
+ process.exit(0);
109
+ }
110
+
111
+ exports.handleUpdateCommand = handleUpdateCommand;