@zonease/happy 0.6.41 → 0.6.43

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-XeHlmApX.cjs → api-B-PlVQY6.cjs} +50 -4
  2. package/dist/{api-K2-jr9ar.mjs → api-BUCtd3cB.mjs} +51 -5
  3. package/dist/{auth-BQvEuSs5.cjs → auth-BqGkUXvq.cjs} +2 -2
  4. package/dist/{auth-CjLkoM3m.mjs → auth-DQH6q_q-.mjs} +4 -4
  5. package/dist/{auth-BbvPcnkY.cjs → auth-OL3nNcDX.cjs} +4 -4
  6. package/dist/{auth-DS8fzlin.mjs → auth-qM2eojWx.mjs} +2 -2
  7. package/dist/{browser-C05SP_Tt.cjs → browser-CY7VNU0C.cjs} +1 -1
  8. package/dist/{browser-C05Ak6RL.mjs → browser-D5RN_Axa.mjs} +1 -1
  9. package/dist/{claudeLocal-DJNRlHIC.mjs → claudeLocal-BXK_vQXS.mjs} +1 -1
  10. package/dist/{claudeLocal-CpDhLCcZ.cjs → claudeLocal-HAXk0deK.cjs} +1 -1
  11. package/dist/{config-DWWtjKQx.mjs → config-2wMjzcHl.mjs} +1 -1
  12. package/dist/{config-B0mns9fF.cjs → config-CaKxWGVe.cjs} +1 -1
  13. package/dist/{connect-DXQC1CJe.mjs → connect-BAunPyp_.mjs} +5 -5
  14. package/dist/{connect-BxCScVNX.cjs → connect-Dt1vY1BC.cjs} +5 -5
  15. package/dist/{controlClient-DgjVRN8D.mjs → controlClient-BzzTNSfl.mjs} +1 -1
  16. package/dist/{controlClient-DgELDZgM.cjs → controlClient-yTkpwcOq.cjs} +1 -1
  17. package/dist/cursorApprovalHook-B2chnVni.cjs +115 -0
  18. package/dist/cursorApprovalHook-BDLPzI5l.mjs +113 -0
  19. package/dist/cursorApprovalServer-Ba1yOUCA.mjs +263 -0
  20. package/dist/cursorApprovalServer-xwxVGL3u.cjs +268 -0
  21. package/dist/{deviceKeys-CejCdWpw.mjs → deviceKeys-CQyFFPtt.mjs} +2 -2
  22. package/dist/{deviceKeys-BpIAWz13.cjs → deviceKeys-CdW-HPnz.cjs} +2 -2
  23. package/dist/{doctor-DznasgP3.cjs → doctor-D4xWXiE7.cjs} +2 -2
  24. package/dist/{doctor-B-LCMVN9.mjs → doctor-DDT2TXHH.mjs} +2 -2
  25. package/dist/downloadImage-3A6zY5AX.cjs +492 -0
  26. package/dist/downloadImage-BqNp0l7y.mjs +485 -0
  27. package/dist/{enroll-HjUqyGnD.mjs → enroll-BlZ0giJI.mjs} +3 -3
  28. package/dist/{enroll-BvfpRUGJ.cjs → enroll-DeYs89Ic.cjs} +3 -3
  29. package/dist/{evidence-CVgTjBrq.cjs → evidence-Bn1JXtdz.cjs} +1 -1
  30. package/dist/{evidence-BEQd1dCh.mjs → evidence-PUnN9yPK.mjs} +1 -1
  31. package/dist/{formatImageMessage-DVs57t3x.mjs → formatImageMessage-BRHeLf0-.mjs} +1 -1
  32. package/dist/{formatImageMessage-CmJTP_hU.cjs → formatImageMessage-bVFGFDJl.cjs} +1 -1
  33. package/dist/{index-CDTNgfUf.cjs → index-BeKrqPYR.cjs} +25 -1
  34. package/dist/{index-CPKdvi7J.mjs → index-DTV7drqs.mjs} +25 -1
  35. package/dist/index.cjs +95 -41
  36. package/dist/index.mjs +95 -41
  37. package/dist/{install-UTz_vYvB.mjs → install-BLPNuSeM.mjs} +2 -2
  38. package/dist/{install-B3mMGISS.mjs → install-BOIcR_Wr.mjs} +1 -1
  39. package/dist/{install-Ck22tYHP.cjs → install-Jrs6YUu8.cjs} +1 -1
  40. package/dist/{install-2Yl_L582.cjs → install-Q-YMwwwg.cjs} +2 -2
  41. package/dist/lib.cjs +4 -4
  42. package/dist/lib.d.cts +4 -2
  43. package/dist/lib.d.mts +4 -2
  44. package/dist/lib.mjs +4 -4
  45. package/dist/{loadableToolOutput-BZYlaqHn.cjs → loadableToolOutput-B3qpMqXT.cjs} +2 -458
  46. package/dist/{loadableToolOutput-4EvraaNY.mjs → loadableToolOutput-DzReWITb.mjs} +3 -456
  47. package/dist/{persistence-DrfN7TzY.cjs → persistence-D7zNFI-d.cjs} +7 -4
  48. package/dist/{persistence-CIUFyOwz.mjs → persistence-DbLMvLvk.mjs} +7 -4
  49. package/dist/{push-CCOXCcM_.cjs → push-RT6Y0Hr3.cjs} +6 -6
  50. package/dist/{push-USXj_pv0.mjs → push-z5wQ4Ki_.mjs} +6 -6
  51. package/dist/{downloadImage-ia5SzlCV.mjs → registerKillSessionHandler-DmfnJ0zq.mjs} +7 -487
  52. package/dist/{downloadImage-B_ygLAXY.cjs → registerKillSessionHandler-MoLdSQxM.cjs} +6 -492
  53. package/dist/{run-Dy6KX6m-.mjs → run-BFnSUK1o.mjs} +14 -9
  54. package/dist/{run-D3CopmEb.cjs → run-C5StYRIB.cjs} +14 -9
  55. package/dist/{runClaude-aHzvx6Ha.cjs → runClaude-ChRp6f5G.cjs} +27 -26
  56. package/dist/{runClaude-CWux2RDq.mjs → runClaude-CjENBdrX.mjs} +22 -21
  57. package/dist/{runCodex-D0ZxSj3O.mjs → runCodex-BzQWlRoj.mjs} +27 -25
  58. package/dist/{runCodex-G-Aq531U.cjs → runCodex-DcQGyotH.cjs} +32 -30
  59. package/dist/runCursor-B73z6MCN.mjs +752 -0
  60. package/dist/runCursor-BlPAxaTy.cjs +754 -0
  61. package/dist/{runGemini-DZC2i6vA.mjs → runGemini-BPv4UzuF.mjs} +18 -16
  62. package/dist/{runGemini-DxGgDAIM.cjs → runGemini-JFqaIC3u.cjs} +23 -21
  63. package/dist/{runOneShot-BgT-JNMA.cjs → runOneShot-2iV11e9L.cjs} +3 -3
  64. package/dist/{runOneShot-cxlk7VKA.mjs → runOneShot-DTukim2A.mjs} +3 -3
  65. package/dist/{serve-Dr3wPrtK.cjs → serve-BDwuAIK4.cjs} +7 -7
  66. package/dist/{serve-CKyvJNs0.mjs → serve-BnlYj5ek.mjs} +7 -7
  67. package/dist/{session-dYzbOo_W.cjs → session-Cp9LEESM.cjs} +5 -5
  68. package/dist/{session-vf2ZjFto.mjs → session-gfeFU8CA.mjs} +5 -5
  69. package/dist/{sessionKeyCache-dDquDzn0.cjs → sessionKeyCache-3Pme04yL.cjs} +1 -1
  70. package/dist/{sessionKeyCache-D2u3JUys.mjs → sessionKeyCache-DtBS_Sb3.mjs} +1 -1
  71. package/dist/{sessionList-C1k2PNg_.mjs → sessionList-B1w4BUdv.mjs} +2 -2
  72. package/dist/{sessionList-DmmtC7uR.cjs → sessionList-BR_5UDZJ.cjs} +2 -2
  73. package/dist/{sessionSummary-DGLoVOxd.cjs → sessionSummary-DLweYgHO.cjs} +3 -3
  74. package/dist/{sessionSummary-5a1QtFVS.mjs → sessionSummary-E-a2bg8W.mjs} +3 -3
  75. package/dist/setupOfflineReconnection-DHwthFtd.mjs +459 -0
  76. package/dist/setupOfflineReconnection-Dkp00dC9.cjs +463 -0
  77. package/dist/{spawnHappyCLI-CarRI4GM.cjs → spawnHappyCLI-C2uY9WV-.cjs} +1 -1
  78. package/dist/{spawnHappyCLI-D3EkTFIn.mjs → spawnHappyCLI-Dt7fbmbk.mjs} +1 -1
  79. package/dist/{ssh-B0hvEYIl.mjs → ssh-C-nEZiGP.mjs} +5 -5
  80. package/dist/{ssh-CBgVwKsB.cjs → ssh-CsnS89Lr.cjs} +5 -5
  81. package/dist/{task-CRo6W-3_.mjs → task-B-8_QGGX.mjs} +6 -6
  82. package/dist/{task-CMunPKCV.cjs → task-lrLb4FCL.cjs} +6 -6
  83. package/dist/{uninstall-BALE2up0.mjs → uninstall-CirMt_WC.mjs} +2 -2
  84. package/dist/{uninstall-BJ3eEGM4.cjs → uninstall-DMjUlEXT.cjs} +2 -2
  85. package/dist/{update-BfjtLrhO.mjs → update-CfXbYshs.mjs} +3 -3
  86. package/dist/{update-Bb3iijy8.cjs → update-mx2p28IP.cjs} +3 -3
  87. package/package.json +1 -1
package/dist/lib.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var api = require('./api-XeHlmApX.cjs');
4
- var logger = require('./persistence-DrfN7TzY.cjs');
3
+ var api = require('./api-B-PlVQY6.cjs');
4
+ var logger = require('./persistence-D7zNFI-d.cjs');
5
5
  var types = require('./types-DWeB7aqh.cjs');
6
6
  require('axios');
7
7
  require('node:events');
8
8
  require('socket.io-client');
9
9
  require('zod');
10
- require('./index-CDTNgfUf.cjs');
10
+ require('./index-BeKrqPYR.cjs');
11
11
  require('@paralleldrive/cuid2');
12
12
  require('./time-Bj2HRkKH.cjs');
13
13
  require('node:crypto');
@@ -30,7 +30,7 @@ require('tweetnacl');
30
30
  require('@stablelib/base64');
31
31
  require('node:readline');
32
32
  require('expo-server-sdk');
33
- require('./sessionKeyCache-dDquDzn0.cjs');
33
+ require('./sessionKeyCache-3Pme04yL.cjs');
34
34
  require('chalk');
35
35
  require('fs');
36
36
 
package/dist/lib.d.cts CHANGED
@@ -1073,6 +1073,7 @@ type Metadata = {
1073
1073
  }> | null;
1074
1074
  machineId?: string;
1075
1075
  claudeSessionId?: string;
1076
+ cursorSessionId?: string;
1076
1077
  tools?: string[];
1077
1078
  slashCommands?: string[];
1078
1079
  skills?: Array<{
@@ -1309,6 +1310,7 @@ type ACPMessageData = {
1309
1310
  type: 'token_count';
1310
1311
  [key: string]: unknown;
1311
1312
  };
1313
+ type ACPProvider = 'gemini' | 'codex' | 'claude' | 'opencode' | 'cursor';
1312
1314
  type OrchestratorProvider = 'claude' | 'codex' | 'gemini';
1313
1315
  type OrchestratorSubmitTask = {
1314
1316
  taskKey?: string;
@@ -1461,7 +1463,7 @@ declare class ApiSessionClient extends EventEmitter {
1461
1463
  * @param provider - The agent provider sending the message (e.g., 'gemini', 'codex', 'claude')
1462
1464
  * @param body - The message payload (type: 'message' | 'reasoning' | 'tool-call' | 'tool-result')
1463
1465
  */
1464
- sendAgentMessage(provider: 'gemini' | 'codex' | 'claude' | 'opencode', body: ACPMessageData): void;
1466
+ sendAgentMessage(provider: ACPProvider, body: ACPMessageData): void;
1465
1467
  /**
1466
1468
  * Send a batch of pre-built message content objects for backfill (session resume/copy).
1467
1469
  * Each item.content should be a complete message object (role + content) ready to encrypt.
@@ -1555,7 +1557,7 @@ interface SpawnSessionOptions {
1555
1557
  sessionTitle?: string;
1556
1558
  skipForkSession?: boolean;
1557
1559
  approvedNewDirectoryCreation?: boolean;
1558
- agent?: 'claude' | 'codex' | 'gemini';
1560
+ agent?: 'claude' | 'codex' | 'gemini' | 'cursor';
1559
1561
  token?: string;
1560
1562
  environmentVariables?: {
1561
1563
  ANTHROPIC_BASE_URL?: string;
package/dist/lib.d.mts CHANGED
@@ -1073,6 +1073,7 @@ type Metadata = {
1073
1073
  }> | null;
1074
1074
  machineId?: string;
1075
1075
  claudeSessionId?: string;
1076
+ cursorSessionId?: string;
1076
1077
  tools?: string[];
1077
1078
  slashCommands?: string[];
1078
1079
  skills?: Array<{
@@ -1309,6 +1310,7 @@ type ACPMessageData = {
1309
1310
  type: 'token_count';
1310
1311
  [key: string]: unknown;
1311
1312
  };
1313
+ type ACPProvider = 'gemini' | 'codex' | 'claude' | 'opencode' | 'cursor';
1312
1314
  type OrchestratorProvider = 'claude' | 'codex' | 'gemini';
1313
1315
  type OrchestratorSubmitTask = {
1314
1316
  taskKey?: string;
@@ -1461,7 +1463,7 @@ declare class ApiSessionClient extends EventEmitter {
1461
1463
  * @param provider - The agent provider sending the message (e.g., 'gemini', 'codex', 'claude')
1462
1464
  * @param body - The message payload (type: 'message' | 'reasoning' | 'tool-call' | 'tool-result')
1463
1465
  */
1464
- sendAgentMessage(provider: 'gemini' | 'codex' | 'claude' | 'opencode', body: ACPMessageData): void;
1466
+ sendAgentMessage(provider: ACPProvider, body: ACPMessageData): void;
1465
1467
  /**
1466
1468
  * Send a batch of pre-built message content objects for backfill (session resume/copy).
1467
1469
  * Each item.content should be a complete message object (role + content) ready to encrypt.
@@ -1555,7 +1557,7 @@ interface SpawnSessionOptions {
1555
1557
  sessionTitle?: string;
1556
1558
  skipForkSession?: boolean;
1557
1559
  approvedNewDirectoryCreation?: boolean;
1558
- agent?: 'claude' | 'codex' | 'gemini';
1560
+ agent?: 'claude' | 'codex' | 'gemini' | 'cursor';
1559
1561
  token?: string;
1560
1562
  environmentVariables?: {
1561
1563
  ANTHROPIC_BASE_URL?: string;
package/dist/lib.mjs CHANGED
@@ -1,11 +1,11 @@
1
- export { A as ApiClient, a as ApiSessionClient } from './api-K2-jr9ar.mjs';
2
- export { c as configuration, l as logger } from './persistence-CIUFyOwz.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient } from './api-BUCtd3cB.mjs';
2
+ export { c as configuration, l as logger } from './persistence-DbLMvLvk.mjs';
3
3
  export { R as RawJSONLinesSchema } from './types-BoJh4Qfv.mjs';
4
4
  import 'axios';
5
5
  import 'node:events';
6
6
  import 'socket.io-client';
7
7
  import 'zod';
8
- import './index-CPKdvi7J.mjs';
8
+ import './index-DTV7drqs.mjs';
9
9
  import '@paralleldrive/cuid2';
10
10
  import './time-DgsBLJA_.mjs';
11
11
  import 'node:crypto';
@@ -28,6 +28,6 @@ import 'tweetnacl';
28
28
  import '@stablelib/base64';
29
29
  import 'node:readline';
30
30
  import 'expo-server-sdk';
31
- import './sessionKeyCache-D2u3JUys.mjs';
31
+ import './sessionKeyCache-DtBS_Sb3.mjs';
32
32
  import 'chalk';
33
33
  import 'fs';
@@ -1,194 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var logger = require('./persistence-DrfN7TzY.cjs');
4
3
  var node_crypto = require('node:crypto');
5
- var fs = require('node:fs');
6
- var os = require('node:os');
7
- var path = require('node:path');
8
- var projectPath = require('./projectPath-ChLhdOyt.cjs');
9
- var api = require('./api-XeHlmApX.cjs');
10
- var downloadImage = require('./downloadImage-B_ygLAXY.cjs');
11
-
12
- class BasePermissionHandler {
13
- pendingRequests = /* @__PURE__ */ new Map();
14
- session;
15
- pushClient;
16
- isResetting = false;
17
- isUserInteractionTool(toolName) {
18
- return ["AskUserQuestion", "ExitPlanMode", "exit_plan_mode"].includes(toolName);
19
- }
20
- constructor(session, pushClient) {
21
- this.session = session;
22
- this.pushClient = pushClient;
23
- this.setupRpcHandler();
24
- }
25
- /**
26
- * Update the session reference (used after offline reconnection swaps sessions).
27
- * This is critical for avoiding stale session references after onSessionSwap.
28
- */
29
- updateSession(newSession) {
30
- logger.logger.debug(`${this.getLogPrefix()} Session reference updated`);
31
- this.session = newSession;
32
- this.setupRpcHandler();
33
- }
34
- /**
35
- * Setup RPC handler for permission responses.
36
- */
37
- setupRpcHandler() {
38
- this.session.rpcHandlerManager.registerHandler(
39
- "permission",
40
- async (response) => {
41
- const pending = this.pendingRequests.get(response.id);
42
- if (!pending) {
43
- logger.logger.debug(`${this.getLogPrefix()} Permission request not found or already resolved`);
44
- return;
45
- }
46
- this.pendingRequests.delete(response.id);
47
- const result = response.approved ? { decision: response.decision === "approved_for_session" ? "approved_for_session" : "approved" } : { decision: response.decision === "denied" ? "denied" : "abort" };
48
- pending.resolve(result);
49
- if (response.approved && (response.mode === "bypassPermissions" || response.decision === "approved_for_session")) {
50
- this.approvePendingRequestsForSession(response);
51
- }
52
- this.session.updateAgentState((currentState) => {
53
- const request = currentState.requests?.[response.id];
54
- if (!request) return currentState;
55
- const { [response.id]: _, ...remainingRequests } = currentState.requests || {};
56
- let res = {
57
- ...currentState,
58
- requests: remainingRequests,
59
- completedRequests: {
60
- ...currentState.completedRequests,
61
- [response.id]: {
62
- ...request,
63
- completedAt: Date.now(),
64
- status: response.approved ? "approved" : "denied",
65
- decision: result.decision,
66
- mode: response.mode,
67
- allowedTools: response.allowTools
68
- }
69
- }
70
- };
71
- return res;
72
- });
73
- logger.logger.debug(`${this.getLogPrefix()} Permission ${response.approved ? "approved" : "denied"} for ${pending.toolName}`);
74
- }
75
- );
76
- }
77
- approvePendingRequestsForSession(response) {
78
- const pendingSnapshot = Array.from(this.pendingRequests.entries());
79
- const completedAt = Date.now();
80
- for (const [id, pending] of pendingSnapshot) {
81
- if (this.isUserInteractionTool(pending.toolName)) {
82
- continue;
83
- }
84
- this.pendingRequests.delete(id);
85
- pending.resolve({ decision: "approved_for_session" });
86
- }
87
- if (pendingSnapshot.length === 0) {
88
- return;
89
- }
90
- this.session.updateAgentState((currentState) => {
91
- const requests = { ...currentState.requests || {} };
92
- const completedRequests = { ...currentState.completedRequests };
93
- let changed = false;
94
- for (const [id, pending] of pendingSnapshot) {
95
- if (this.isUserInteractionTool(pending.toolName)) {
96
- continue;
97
- }
98
- const request = requests[id];
99
- if (!request) {
100
- continue;
101
- }
102
- delete requests[id];
103
- completedRequests[id] = {
104
- ...request,
105
- completedAt,
106
- status: "approved",
107
- decision: "approved_for_session",
108
- mode: response.mode,
109
- allowedTools: response.allowTools
110
- };
111
- changed = true;
112
- }
113
- if (!changed) {
114
- return currentState;
115
- }
116
- return {
117
- ...currentState,
118
- requests,
119
- completedRequests
120
- };
121
- });
122
- }
123
- /**
124
- * Add a pending request to the agent state and send a push notification.
125
- */
126
- addPendingRequestToState(toolCallId, toolName, input) {
127
- this.pushClient.sendToAllDevices(
128
- "Permission Request",
129
- `${this.getAgentName()} wants to ${toolName}`,
130
- {
131
- sessionId: this.session.sessionId,
132
- requestId: toolCallId,
133
- tool: toolName,
134
- type: "permission_request"
135
- }
136
- );
137
- this.session.updateAgentState((currentState) => ({
138
- ...currentState,
139
- requests: {
140
- ...currentState.requests,
141
- [toolCallId]: {
142
- tool: toolName,
143
- arguments: input,
144
- createdAt: Date.now()
145
- }
146
- }
147
- }));
148
- }
149
- /**
150
- * Reset state for new sessions.
151
- * This method is idempotent - safe to call multiple times.
152
- */
153
- reset() {
154
- if (this.isResetting) {
155
- logger.logger.debug(`${this.getLogPrefix()} Reset already in progress, skipping`);
156
- return;
157
- }
158
- this.isResetting = true;
159
- try {
160
- const pendingSnapshot = Array.from(this.pendingRequests.entries());
161
- this.pendingRequests.clear();
162
- for (const [id, pending] of pendingSnapshot) {
163
- try {
164
- pending.reject(new Error("Session reset"));
165
- } catch (err) {
166
- logger.logger.debug(`${this.getLogPrefix()} Error rejecting pending request ${id}:`, err);
167
- }
168
- }
169
- this.session.updateAgentState((currentState) => {
170
- const pendingRequests = currentState.requests || {};
171
- const completedRequests = { ...currentState.completedRequests };
172
- for (const [id, request] of Object.entries(pendingRequests)) {
173
- completedRequests[id] = {
174
- ...request,
175
- completedAt: Date.now(),
176
- status: "canceled",
177
- reason: "Session reset"
178
- };
179
- }
180
- return {
181
- ...currentState,
182
- requests: {},
183
- completedRequests
184
- };
185
- });
186
- logger.logger.debug(`${this.getLogPrefix()} Permission handler reset`);
187
- } finally {
188
- this.isResetting = false;
189
- }
190
- }
191
- }
4
+ var logger = require('./persistence-D7zNFI-d.cjs');
5
+ var api = require('./api-B-PlVQY6.cjs');
192
6
 
193
7
  class BaseReasoningProcessor {
194
8
  accumulator = "";
@@ -384,273 +198,6 @@ class BaseReasoningProcessor {
384
198
  }
385
199
  }
386
200
 
387
- const DEFAULT_MAX_SKILLS = 400;
388
- const DEFAULT_MAX_DEPTH = 10;
389
- const SKILL_FILE = "SKILL.md";
390
- const IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
391
- ".git",
392
- "node_modules",
393
- "dist",
394
- "build",
395
- "references",
396
- "assets",
397
- "templates"
398
- ]);
399
- function parseFrontMatter(content) {
400
- if (!content.startsWith("---")) return {};
401
- const end = content.indexOf("\n---", 3);
402
- if (end < 0) return {};
403
- const block = content.slice(3, end).split(/\r?\n/);
404
- const result = {};
405
- for (let i = 0; i < block.length; i++) {
406
- const line = block[i];
407
- const match = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line.trim());
408
- if (!match) continue;
409
- const [, key, rawValue] = match;
410
- let value = rawValue.trim().replace(/^['"]|['"]$/g, "");
411
- if ((rawValue.trim() === ">-" || rawValue.trim() === ">" || rawValue.trim() === "|-" || rawValue.trim() === "|") && key === "description") {
412
- const continuation = [];
413
- while (i + 1 < block.length && /^\s+/.test(block[i + 1])) {
414
- i++;
415
- continuation.push(block[i].trim());
416
- }
417
- value = continuation.join(rawValue.trim().startsWith("|") ? "\n" : " ").trim();
418
- }
419
- if (key === "name" && value) result.name = value;
420
- if (key === "description" && value) result.description = value;
421
- }
422
- return result;
423
- }
424
- function deriveSkillName(skillFilePath) {
425
- return path.basename(path.dirname(skillFilePath));
426
- }
427
- function collectSkillFiles(root, maxDepth, maxFiles) {
428
- const files = [];
429
- function walk(dir, depth) {
430
- if (files.length >= maxFiles || depth > maxDepth) return;
431
- let entries;
432
- try {
433
- entries = fs.readdirSync(dir, { withFileTypes: true });
434
- } catch {
435
- return;
436
- }
437
- for (const entry of entries) {
438
- if (files.length >= maxFiles) return;
439
- const fullPath = path.join(dir, entry.name);
440
- if (entry.isFile() && entry.name === SKILL_FILE) {
441
- files.push(fullPath);
442
- continue;
443
- }
444
- if (!entry.isDirectory()) continue;
445
- if (IGNORED_DIRECTORIES.has(entry.name)) continue;
446
- walk(fullPath, depth + 1);
447
- }
448
- }
449
- if (fs.existsSync(root)) {
450
- walk(root, 0);
451
- }
452
- return files;
453
- }
454
- function skillRoots(homeDir, includePluginCache) {
455
- const roots = [
456
- { path: path.join(homeDir, ".agents", "skills"), source: "agents" },
457
- { path: path.join(homeDir, ".codex", "skills"), source: "codex" },
458
- { path: path.join(homeDir, ".claude", "skills"), source: "claude" }
459
- ];
460
- if (includePluginCache) {
461
- roots.push(
462
- { path: path.join(homeDir, ".codex", "plugins", "cache"), source: "codex-plugin-cache" },
463
- { path: path.join(homeDir, ".codex", ".tmp", "plugins", "plugins"), source: "codex-plugin-marketplace" }
464
- );
465
- }
466
- return roots;
467
- }
468
- function discoverCodexSkills(options = {}) {
469
- const homeDir = options.homeDir ?? os.homedir();
470
- const maxSkills = options.maxSkills ?? DEFAULT_MAX_SKILLS;
471
- const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
472
- const includePluginCache = options.includePluginCache ?? true;
473
- const result = [];
474
- const seen = /* @__PURE__ */ new Set();
475
- for (const root of skillRoots(homeDir, includePluginCache)) {
476
- if (result.length >= maxSkills) break;
477
- const skillFiles = collectSkillFiles(root.path, maxDepth, maxSkills - result.length);
478
- for (const skillFile of skillFiles) {
479
- if (result.length >= maxSkills) break;
480
- let content = "";
481
- try {
482
- content = fs.readFileSync(skillFile, "utf8");
483
- } catch {
484
- continue;
485
- }
486
- const frontMatter = parseFrontMatter(content);
487
- const name = (frontMatter.name || deriveSkillName(skillFile)).trim();
488
- if (!name) continue;
489
- const key = name.toLowerCase();
490
- if (seen.has(key)) continue;
491
- seen.add(key);
492
- result.push({
493
- name,
494
- description: frontMatter.description,
495
- source: root.source
496
- });
497
- }
498
- }
499
- return result;
500
- }
501
-
502
- function detectWorkspaceSubdirectories(cwd) {
503
- try {
504
- const entries = fs.readdirSync(cwd, { withFileTypes: true });
505
- const repos = [];
506
- for (const entry of entries) {
507
- if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
508
- const subDir = path.join(cwd, entry.name);
509
- const info = downloadImage.detectGitWorktree(subDir);
510
- if (info.isWorktree && info.worktreeBasePath && info.worktreeBranchName) {
511
- repos.push({
512
- path: subDir,
513
- basePath: info.worktreeBasePath,
514
- branchName: info.worktreeBranchName,
515
- displayName: entry.name
516
- });
517
- }
518
- }
519
- if (repos.length > 0) {
520
- return {
521
- isWorktree: true,
522
- workspaceRepos: repos,
523
- workspacePath: cwd
524
- };
525
- }
526
- } catch {
527
- }
528
- return {};
529
- }
530
- function detectWorktreeMetadata() {
531
- if (process.env.HAPPY_WORKSPACE_REPOS) {
532
- try {
533
- const repos = JSON.parse(process.env.HAPPY_WORKSPACE_REPOS);
534
- return {
535
- isWorktree: true,
536
- workspaceRepos: repos,
537
- workspacePath: process.env.HAPPY_WORKSPACE_PATH
538
- };
539
- } catch {
540
- }
541
- }
542
- if (process.env.HAPPY_WORKTREE_BASE_PATH) {
543
- return {
544
- isWorktree: true,
545
- worktreeBasePath: process.env.HAPPY_WORKTREE_BASE_PATH,
546
- worktreeBranchName: process.env.HAPPY_WORKTREE_BRANCH_NAME
547
- };
548
- }
549
- const info = downloadImage.detectGitWorktree(process.cwd());
550
- if (info.isWorktree) {
551
- return {
552
- isWorktree: true,
553
- worktreeBasePath: info.worktreeBasePath,
554
- worktreeBranchName: info.worktreeBranchName
555
- };
556
- }
557
- const workspaceResult = detectWorkspaceSubdirectories(process.cwd());
558
- if (workspaceResult.isWorktree) {
559
- return workspaceResult;
560
- }
561
- return {};
562
- }
563
- function createSessionMetadata(opts) {
564
- const state = {
565
- controlledByUser: false
566
- };
567
- const metadata = {
568
- path: process.cwd(),
569
- host: os.hostname(),
570
- version: logger.packageJson.version,
571
- os: os.platform(),
572
- machineId: opts.machineId,
573
- homeDir: os.homedir(),
574
- happyHomeDir: logger.configuration.happyHomeDir,
575
- happyLibDir: projectPath.projectPath(),
576
- happyToolsDir: api.resolveToolsDir(),
577
- startedFromDaemon: opts.startedBy === "daemon",
578
- hostPid: process.pid,
579
- startedBy: opts.startedBy || "terminal",
580
- lifecycleState: "running",
581
- lifecycleStateSince: Date.now(),
582
- flavor: opts.flavor,
583
- // Worktree metadata: env vars from daemon take priority, otherwise detect via git
584
- ...detectWorktreeMetadata()
585
- };
586
- if (opts.flavor === "codex") {
587
- metadata.skills = discoverCodexSkills();
588
- }
589
- return { state, metadata };
590
- }
591
-
592
- function createOfflineSessionStub(sessionTag) {
593
- return {
594
- sessionId: `offline-${sessionTag}`,
595
- sendCodexMessage: () => {
596
- },
597
- sendAgentMessage: () => {
598
- },
599
- sendClaudeSessionMessage: () => {
600
- },
601
- keepAlive: () => {
602
- },
603
- sendSessionEvent: () => {
604
- },
605
- sendSessionDeath: () => {
606
- },
607
- updateLifecycleState: () => {
608
- },
609
- requestControlTransfer: async () => {
610
- },
611
- flush: async () => {
612
- },
613
- close: async () => {
614
- },
615
- updateMetadata: () => {
616
- },
617
- updateAgentState: () => {
618
- },
619
- onUserMessage: () => {
620
- },
621
- rpcHandlerManager: {
622
- registerHandler: () => {
623
- }
624
- }
625
- };
626
- }
627
-
628
- function setupOfflineReconnection(opts) {
629
- const { api: api$1, sessionTag, metadata, state, response, onSessionSwap } = opts;
630
- let session;
631
- let reconnectionHandle = null;
632
- if (!response) {
633
- session = createOfflineSessionStub(sessionTag);
634
- reconnectionHandle = api.startOfflineReconnection({
635
- serverUrl: logger.configuration.serverUrl,
636
- onReconnected: async () => {
637
- const resp = await api$1.getOrCreateSession({ tag: sessionTag, metadata, state });
638
- if (!resp) throw new Error("Server unavailable");
639
- const realSession = api$1.sessionSyncClient(resp);
640
- onSessionSwap(realSession);
641
- return realSession;
642
- },
643
- onNotify: (msg) => {
644
- console.log(msg);
645
- }
646
- });
647
- return { session, reconnectionHandle, isOffline: true };
648
- } else {
649
- session = api$1.sessionSyncClient(response);
650
- return { session, reconnectionHandle: null, isOffline: false };
651
- }
652
- }
653
-
654
201
  const SUPPORTED_CATEGORIES = /* @__PURE__ */ new Set(["mode", "model", "thought_level"]);
655
202
  function isRecord(value) {
656
203
  return !!value && typeof value === "object";
@@ -1191,9 +738,7 @@ function summarizeBashToolOutput(options) {
1191
738
  });
1192
739
  }
1193
740
 
1194
- exports.BasePermissionHandler = BasePermissionHandler;
1195
741
  exports.BaseReasoningProcessor = BaseReasoningProcessor;
1196
- exports.createSessionMetadata = createSessionMetadata;
1197
742
  exports.handleAgentMessageChunk = handleAgentMessageChunk;
1198
743
  exports.handleAgentThoughtChunk = handleAgentThoughtChunk;
1199
744
  exports.handleConfigMetadataEvent = handleConfigMetadataEvent;
@@ -1202,5 +747,4 @@ exports.handlePlanUpdate = handlePlanUpdate;
1202
747
  exports.handleThinkingUpdate = handleThinkingUpdate;
1203
748
  exports.handleToolCall = handleToolCall;
1204
749
  exports.handleToolCallUpdate = handleToolCallUpdate;
1205
- exports.setupOfflineReconnection = setupOfflineReconnection;
1206
750
  exports.summarizeBashToolOutput = summarizeBashToolOutput;