@zonease/happy 0.6.40 → 0.6.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-C7FyJfZ1.cjs → api-CIE4_cWd.cjs} +4 -4
- package/dist/{api-D6WL40-U.mjs → api-Ew6xr81i.mjs} +4 -4
- package/dist/{auth-DO9GexAR.mjs → auth-BzYevJo2.mjs} +4 -4
- package/dist/{auth-DCsIoZLT.cjs → auth-Dor79zTL.cjs} +4 -4
- package/dist/{auth-C7ZScWEw.cjs → auth-G9fZpVJ2.cjs} +2 -2
- package/dist/{auth-DxJ3VvrX.mjs → auth-Q2STUNI-.mjs} +2 -2
- package/dist/{browser-AoVGRX7y.mjs → browser-BI7s-V8E.mjs} +1 -1
- package/dist/{browser-DzgO4oaD.cjs → browser-qDIIAL7S.cjs} +1 -1
- package/dist/{claudeLocal-CWNGpJ0-.mjs → claudeLocal-Db2tDC4X.mjs} +1 -1
- package/dist/{claudeLocal-C6BdzhDx.cjs → claudeLocal-f4uBLJaM.cjs} +1 -1
- package/dist/{config-DZk-mJ0K.mjs → config-CHjDs8AS.mjs} +1 -1
- package/dist/{config-CclB3QW9.cjs → config-CSBlEik9.cjs} +1 -1
- package/dist/{connect-k9CqDJ-T.cjs → connect-CJoTliii.cjs} +5 -5
- package/dist/{connect-BXLUKJ5P.mjs → connect-O_nA5BOC.mjs} +5 -5
- package/dist/{controlClient-B23M-WPp.cjs → controlClient-CEz_p1zc.cjs} +1 -1
- package/dist/{controlClient-DB5tDU7V.mjs → controlClient-DoS9JqQC.mjs} +1 -1
- package/dist/cursorApprovalHook-B0v1kGa7.mjs +95 -0
- package/dist/cursorApprovalHook-DRAHfTXU.cjs +97 -0
- package/dist/cursorApprovalServer-DzY8yJlI.cjs +167 -0
- package/dist/cursorApprovalServer-JjPkdjGR.mjs +164 -0
- package/dist/{deviceKeys-BTdo34Uz.mjs → deviceKeys-B4aqjnE6.mjs} +2 -2
- package/dist/{deviceKeys-C540DcXl.cjs → deviceKeys-DyUn0bEx.cjs} +2 -2
- package/dist/{doctor-BQGLhrcI.cjs → doctor-BJSuVRUZ.cjs} +3 -3
- package/dist/{doctor-CU4JLGQ1.mjs → doctor-DRnft_5-.mjs} +3 -3
- package/dist/{downloadImage-DZXI3mXL.mjs → downloadImage-BpVF7A79.mjs} +7 -40
- package/dist/{downloadImage-cQ1Z7hkC.cjs → downloadImage-Cijmufpr.cjs} +5 -39
- package/dist/{enroll-Bo-CNio1.cjs → enroll-C2gunHdt.cjs} +3 -3
- package/dist/{enroll-B55BQR56.mjs → enroll-CysDL6ee.mjs} +3 -3
- package/dist/{evidence-DTYRAaOZ.mjs → evidence-DPutCuUr.mjs} +1 -1
- package/dist/{evidence-DQp8QWcv.cjs → evidence-DsQ-h-_W.cjs} +1 -1
- package/dist/{formatImageMessage-DbKSSjMx.mjs → formatImageMessage-6aV9YFWr.mjs} +1 -1
- package/dist/{formatImageMessage-CixDYY6G.cjs → formatImageMessage-BPK_Ivfe.cjs} +1 -1
- package/dist/gitWorktree-C6jLoaMw.cjs +39 -0
- package/dist/gitWorktree-CzJDU2BV.mjs +37 -0
- package/dist/{index-CDTNgfUf.cjs → index-BeKrqPYR.cjs} +25 -1
- package/dist/{index-CPKdvi7J.mjs → index-DTV7drqs.mjs} +25 -1
- package/dist/index.cjs +106 -41
- package/dist/index.mjs +106 -41
- package/dist/{install-B1e6rdy7.mjs → install-BsTA2tZn.mjs} +2 -2
- package/dist/{install-CgUPGIoF.mjs → install-DBg0xQ3g.mjs} +1 -1
- package/dist/{install-D7Ir7ciZ.cjs → install-DlOppA-e.cjs} +2 -2
- package/dist/{install-DSDufaPd.cjs → install-Tyhs6rUp.cjs} +1 -1
- package/dist/lib.cjs +4 -4
- package/dist/lib.d.cts +3 -2
- package/dist/lib.d.mts +3 -2
- package/dist/lib.mjs +4 -4
- package/dist/{loadableToolOutput-Bfei9wPq.mjs → loadableToolOutput-2dMPAp4N.mjs} +3 -456
- package/dist/{loadableToolOutput-CbLGtvST.cjs → loadableToolOutput-DPGTtKJM.cjs} +2 -458
- package/dist/{persistence-CBTtC_dm.cjs → persistence-BcQmjobZ.cjs} +7 -4
- package/dist/{persistence-DKfF81pd.mjs → persistence-D9tMm6bj.mjs} +8 -5
- package/dist/push-Cnm6JQMD.cjs +80 -0
- package/dist/push-Dxsugkes.mjs +78 -0
- package/dist/{run-BVZsMNwN.mjs → run-BEflQaQ2.mjs} +12 -9
- package/dist/{run-CURx7LhK.cjs → run-CiPWWhXt.cjs} +12 -9
- package/dist/{runClaude-CL3Kt5ex.cjs → runClaude-BVXsyCHb.cjs} +19 -18
- package/dist/{runClaude-6Gi0sYQy.mjs → runClaude-sPkSqHWY.mjs} +16 -15
- package/dist/{runCodex-YKyVBkJ3.cjs → runCodex-BAwhdmSA.cjs} +19 -17
- package/dist/{runCodex-ClwEgJ7M.mjs → runCodex-C4rHkIyw.mjs} +16 -14
- package/dist/runCursor-CD5wC3gA.cjs +578 -0
- package/dist/runCursor-DiHLWMs8.mjs +576 -0
- package/dist/{runGemini-BPWxVr60.mjs → runGemini-B-93gOqB.mjs} +18 -16
- package/dist/{runGemini-Xz2W1spn.cjs → runGemini-Cto-adir.cjs} +21 -19
- package/dist/{runOneShot-DjZyCvDI.cjs → runOneShot-BfIzE9W4.cjs} +3 -3
- package/dist/{runOneShot-CdCWiiLr.mjs → runOneShot-DGjlYVhR.mjs} +3 -3
- package/dist/{serve-B8vaWQA0.cjs → serve-CqL6NWDr.cjs} +7 -7
- package/dist/{serve-B48JttQ3.mjs → serve-ttlqF5jn.mjs} +7 -7
- package/dist/{session-BZO25zxp.cjs → session-BZhGpQUJ.cjs} +5 -5
- package/dist/{session-BXboDn2V.mjs → session-Co0REU9e.mjs} +5 -5
- package/dist/{sessionKeyCache-CDmexJ9p.cjs → sessionKeyCache-BwFUGgMs.cjs} +1 -1
- package/dist/{sessionKeyCache-B6cGadYL.mjs → sessionKeyCache-pXTjpETo.mjs} +1 -1
- package/dist/{sessionList-CgAYZpNj.mjs → sessionList-DaufR-sA.mjs} +2 -2
- package/dist/{sessionList-lQ-nqEhc.cjs → sessionList-fG5uAPzU.cjs} +2 -2
- package/dist/{sessionSummary-CcORiQSq.cjs → sessionSummary-CjZPt6nr.cjs} +3 -3
- package/dist/{sessionSummary-DCWQoaDP.mjs → sessionSummary-Dv6dPABg.mjs} +3 -3
- package/dist/setupOfflineReconnection-B6coH9QN.cjs +461 -0
- package/dist/setupOfflineReconnection-DW5il97B.mjs +457 -0
- package/dist/{spawnHappyCLI-KiazE3kL.cjs → spawnHappyCLI-Cfu7C1uM.cjs} +1 -1
- package/dist/{spawnHappyCLI-yBIP_Oqi.mjs → spawnHappyCLI-DhUeycct.mjs} +1 -1
- package/dist/{ssh-q5uZhqBf.mjs → ssh-8tPIKk-i.mjs} +9 -6
- package/dist/{ssh-yMllSHu5.cjs → ssh-C4YTSHXL.cjs} +9 -5
- package/dist/{task-wNX1N2i4.mjs → task-CH-oidFy.mjs} +6 -6
- package/dist/{task-_nr7J19j.cjs → task-DFW-PecP.cjs} +6 -6
- package/dist/{uninstall-Dxf6_4mQ.mjs → uninstall-CeioRZNI.mjs} +2 -2
- package/dist/{uninstall-Buaz7d-X.cjs → uninstall-yTSL3X6Y.cjs} +2 -2
- package/dist/{update-CGlIfa8e.cjs → update-Bju28vNP.cjs} +3 -3
- package/dist/{update-CnnoX2cV.mjs → update-Derd2hoX.mjs} +3 -3
- package/package.json +1 -1
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { l as logger, c as configuration, p as packageJson } from './persistence-D9tMm6bj.mjs';
|
|
2
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
3
|
+
import os, { homedir } from 'node:os';
|
|
4
|
+
import { join, basename, dirname } from 'node:path';
|
|
5
|
+
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
6
|
+
import { r as resolveToolsDir, b as startOfflineReconnection } from './api-Ew6xr81i.mjs';
|
|
7
|
+
import { d as detectGitWorktree } from './gitWorktree-CzJDU2BV.mjs';
|
|
8
|
+
|
|
9
|
+
class BasePermissionHandler {
|
|
10
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
11
|
+
session;
|
|
12
|
+
pushClient;
|
|
13
|
+
isResetting = false;
|
|
14
|
+
isUserInteractionTool(toolName) {
|
|
15
|
+
return ["AskUserQuestion", "ExitPlanMode", "exit_plan_mode"].includes(toolName);
|
|
16
|
+
}
|
|
17
|
+
constructor(session, pushClient) {
|
|
18
|
+
this.session = session;
|
|
19
|
+
this.pushClient = pushClient;
|
|
20
|
+
this.setupRpcHandler();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Update the session reference (used after offline reconnection swaps sessions).
|
|
24
|
+
* This is critical for avoiding stale session references after onSessionSwap.
|
|
25
|
+
*/
|
|
26
|
+
updateSession(newSession) {
|
|
27
|
+
logger.debug(`${this.getLogPrefix()} Session reference updated`);
|
|
28
|
+
this.session = newSession;
|
|
29
|
+
this.setupRpcHandler();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Setup RPC handler for permission responses.
|
|
33
|
+
*/
|
|
34
|
+
setupRpcHandler() {
|
|
35
|
+
this.session.rpcHandlerManager.registerHandler(
|
|
36
|
+
"permission",
|
|
37
|
+
async (response) => {
|
|
38
|
+
const pending = this.pendingRequests.get(response.id);
|
|
39
|
+
if (!pending) {
|
|
40
|
+
logger.debug(`${this.getLogPrefix()} Permission request not found or already resolved`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.pendingRequests.delete(response.id);
|
|
44
|
+
const result = response.approved ? { decision: response.decision === "approved_for_session" ? "approved_for_session" : "approved" } : { decision: response.decision === "denied" ? "denied" : "abort" };
|
|
45
|
+
pending.resolve(result);
|
|
46
|
+
if (response.approved && (response.mode === "bypassPermissions" || response.decision === "approved_for_session")) {
|
|
47
|
+
this.approvePendingRequestsForSession(response);
|
|
48
|
+
}
|
|
49
|
+
this.session.updateAgentState((currentState) => {
|
|
50
|
+
const request = currentState.requests?.[response.id];
|
|
51
|
+
if (!request) return currentState;
|
|
52
|
+
const { [response.id]: _, ...remainingRequests } = currentState.requests || {};
|
|
53
|
+
let res = {
|
|
54
|
+
...currentState,
|
|
55
|
+
requests: remainingRequests,
|
|
56
|
+
completedRequests: {
|
|
57
|
+
...currentState.completedRequests,
|
|
58
|
+
[response.id]: {
|
|
59
|
+
...request,
|
|
60
|
+
completedAt: Date.now(),
|
|
61
|
+
status: response.approved ? "approved" : "denied",
|
|
62
|
+
decision: result.decision,
|
|
63
|
+
mode: response.mode,
|
|
64
|
+
allowedTools: response.allowTools
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return res;
|
|
69
|
+
});
|
|
70
|
+
logger.debug(`${this.getLogPrefix()} Permission ${response.approved ? "approved" : "denied"} for ${pending.toolName}`);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
approvePendingRequestsForSession(response) {
|
|
75
|
+
const pendingSnapshot = Array.from(this.pendingRequests.entries());
|
|
76
|
+
const completedAt = Date.now();
|
|
77
|
+
for (const [id, pending] of pendingSnapshot) {
|
|
78
|
+
if (this.isUserInteractionTool(pending.toolName)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
this.pendingRequests.delete(id);
|
|
82
|
+
pending.resolve({ decision: "approved_for_session" });
|
|
83
|
+
}
|
|
84
|
+
if (pendingSnapshot.length === 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.session.updateAgentState((currentState) => {
|
|
88
|
+
const requests = { ...currentState.requests || {} };
|
|
89
|
+
const completedRequests = { ...currentState.completedRequests };
|
|
90
|
+
let changed = false;
|
|
91
|
+
for (const [id, pending] of pendingSnapshot) {
|
|
92
|
+
if (this.isUserInteractionTool(pending.toolName)) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const request = requests[id];
|
|
96
|
+
if (!request) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
delete requests[id];
|
|
100
|
+
completedRequests[id] = {
|
|
101
|
+
...request,
|
|
102
|
+
completedAt,
|
|
103
|
+
status: "approved",
|
|
104
|
+
decision: "approved_for_session",
|
|
105
|
+
mode: response.mode,
|
|
106
|
+
allowedTools: response.allowTools
|
|
107
|
+
};
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
if (!changed) {
|
|
111
|
+
return currentState;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
...currentState,
|
|
115
|
+
requests,
|
|
116
|
+
completedRequests
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Add a pending request to the agent state and send a push notification.
|
|
122
|
+
*/
|
|
123
|
+
addPendingRequestToState(toolCallId, toolName, input) {
|
|
124
|
+
this.pushClient.sendToAllDevices(
|
|
125
|
+
"Permission Request",
|
|
126
|
+
`${this.getAgentName()} wants to ${toolName}`,
|
|
127
|
+
{
|
|
128
|
+
sessionId: this.session.sessionId,
|
|
129
|
+
requestId: toolCallId,
|
|
130
|
+
tool: toolName,
|
|
131
|
+
type: "permission_request"
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
this.session.updateAgentState((currentState) => ({
|
|
135
|
+
...currentState,
|
|
136
|
+
requests: {
|
|
137
|
+
...currentState.requests,
|
|
138
|
+
[toolCallId]: {
|
|
139
|
+
tool: toolName,
|
|
140
|
+
arguments: input,
|
|
141
|
+
createdAt: Date.now()
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Reset state for new sessions.
|
|
148
|
+
* This method is idempotent - safe to call multiple times.
|
|
149
|
+
*/
|
|
150
|
+
reset() {
|
|
151
|
+
if (this.isResetting) {
|
|
152
|
+
logger.debug(`${this.getLogPrefix()} Reset already in progress, skipping`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.isResetting = true;
|
|
156
|
+
try {
|
|
157
|
+
const pendingSnapshot = Array.from(this.pendingRequests.entries());
|
|
158
|
+
this.pendingRequests.clear();
|
|
159
|
+
for (const [id, pending] of pendingSnapshot) {
|
|
160
|
+
try {
|
|
161
|
+
pending.reject(new Error("Session reset"));
|
|
162
|
+
} catch (err) {
|
|
163
|
+
logger.debug(`${this.getLogPrefix()} Error rejecting pending request ${id}:`, err);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
this.session.updateAgentState((currentState) => {
|
|
167
|
+
const pendingRequests = currentState.requests || {};
|
|
168
|
+
const completedRequests = { ...currentState.completedRequests };
|
|
169
|
+
for (const [id, request] of Object.entries(pendingRequests)) {
|
|
170
|
+
completedRequests[id] = {
|
|
171
|
+
...request,
|
|
172
|
+
completedAt: Date.now(),
|
|
173
|
+
status: "canceled",
|
|
174
|
+
reason: "Session reset"
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
...currentState,
|
|
179
|
+
requests: {},
|
|
180
|
+
completedRequests
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
logger.debug(`${this.getLogPrefix()} Permission handler reset`);
|
|
184
|
+
} finally {
|
|
185
|
+
this.isResetting = false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const DEFAULT_MAX_SKILLS = 400;
|
|
191
|
+
const DEFAULT_MAX_DEPTH = 10;
|
|
192
|
+
const SKILL_FILE = "SKILL.md";
|
|
193
|
+
const IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
194
|
+
".git",
|
|
195
|
+
"node_modules",
|
|
196
|
+
"dist",
|
|
197
|
+
"build",
|
|
198
|
+
"references",
|
|
199
|
+
"assets",
|
|
200
|
+
"templates"
|
|
201
|
+
]);
|
|
202
|
+
function parseFrontMatter(content) {
|
|
203
|
+
if (!content.startsWith("---")) return {};
|
|
204
|
+
const end = content.indexOf("\n---", 3);
|
|
205
|
+
if (end < 0) return {};
|
|
206
|
+
const block = content.slice(3, end).split(/\r?\n/);
|
|
207
|
+
const result = {};
|
|
208
|
+
for (let i = 0; i < block.length; i++) {
|
|
209
|
+
const line = block[i];
|
|
210
|
+
const match = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line.trim());
|
|
211
|
+
if (!match) continue;
|
|
212
|
+
const [, key, rawValue] = match;
|
|
213
|
+
let value = rawValue.trim().replace(/^['"]|['"]$/g, "");
|
|
214
|
+
if ((rawValue.trim() === ">-" || rawValue.trim() === ">" || rawValue.trim() === "|-" || rawValue.trim() === "|") && key === "description") {
|
|
215
|
+
const continuation = [];
|
|
216
|
+
while (i + 1 < block.length && /^\s+/.test(block[i + 1])) {
|
|
217
|
+
i++;
|
|
218
|
+
continuation.push(block[i].trim());
|
|
219
|
+
}
|
|
220
|
+
value = continuation.join(rawValue.trim().startsWith("|") ? "\n" : " ").trim();
|
|
221
|
+
}
|
|
222
|
+
if (key === "name" && value) result.name = value;
|
|
223
|
+
if (key === "description" && value) result.description = value;
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
function deriveSkillName(skillFilePath) {
|
|
228
|
+
return basename(dirname(skillFilePath));
|
|
229
|
+
}
|
|
230
|
+
function collectSkillFiles(root, maxDepth, maxFiles) {
|
|
231
|
+
const files = [];
|
|
232
|
+
function walk(dir, depth) {
|
|
233
|
+
if (files.length >= maxFiles || depth > maxDepth) return;
|
|
234
|
+
let entries;
|
|
235
|
+
try {
|
|
236
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
237
|
+
} catch {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
for (const entry of entries) {
|
|
241
|
+
if (files.length >= maxFiles) return;
|
|
242
|
+
const fullPath = join(dir, entry.name);
|
|
243
|
+
if (entry.isFile() && entry.name === SKILL_FILE) {
|
|
244
|
+
files.push(fullPath);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (!entry.isDirectory()) continue;
|
|
248
|
+
if (IGNORED_DIRECTORIES.has(entry.name)) continue;
|
|
249
|
+
walk(fullPath, depth + 1);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (existsSync(root)) {
|
|
253
|
+
walk(root, 0);
|
|
254
|
+
}
|
|
255
|
+
return files;
|
|
256
|
+
}
|
|
257
|
+
function skillRoots(homeDir, includePluginCache) {
|
|
258
|
+
const roots = [
|
|
259
|
+
{ path: join(homeDir, ".agents", "skills"), source: "agents" },
|
|
260
|
+
{ path: join(homeDir, ".codex", "skills"), source: "codex" },
|
|
261
|
+
{ path: join(homeDir, ".claude", "skills"), source: "claude" }
|
|
262
|
+
];
|
|
263
|
+
if (includePluginCache) {
|
|
264
|
+
roots.push(
|
|
265
|
+
{ path: join(homeDir, ".codex", "plugins", "cache"), source: "codex-plugin-cache" },
|
|
266
|
+
{ path: join(homeDir, ".codex", ".tmp", "plugins", "plugins"), source: "codex-plugin-marketplace" }
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
return roots;
|
|
270
|
+
}
|
|
271
|
+
function discoverCodexSkills(options = {}) {
|
|
272
|
+
const homeDir = options.homeDir ?? homedir();
|
|
273
|
+
const maxSkills = options.maxSkills ?? DEFAULT_MAX_SKILLS;
|
|
274
|
+
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
275
|
+
const includePluginCache = options.includePluginCache ?? true;
|
|
276
|
+
const result = [];
|
|
277
|
+
const seen = /* @__PURE__ */ new Set();
|
|
278
|
+
for (const root of skillRoots(homeDir, includePluginCache)) {
|
|
279
|
+
if (result.length >= maxSkills) break;
|
|
280
|
+
const skillFiles = collectSkillFiles(root.path, maxDepth, maxSkills - result.length);
|
|
281
|
+
for (const skillFile of skillFiles) {
|
|
282
|
+
if (result.length >= maxSkills) break;
|
|
283
|
+
let content = "";
|
|
284
|
+
try {
|
|
285
|
+
content = readFileSync(skillFile, "utf8");
|
|
286
|
+
} catch {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const frontMatter = parseFrontMatter(content);
|
|
290
|
+
const name = (frontMatter.name || deriveSkillName(skillFile)).trim();
|
|
291
|
+
if (!name) continue;
|
|
292
|
+
const key = name.toLowerCase();
|
|
293
|
+
if (seen.has(key)) continue;
|
|
294
|
+
seen.add(key);
|
|
295
|
+
result.push({
|
|
296
|
+
name,
|
|
297
|
+
description: frontMatter.description,
|
|
298
|
+
source: root.source
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function detectWorkspaceSubdirectories(cwd) {
|
|
306
|
+
try {
|
|
307
|
+
const entries = readdirSync(cwd, { withFileTypes: true });
|
|
308
|
+
const repos = [];
|
|
309
|
+
for (const entry of entries) {
|
|
310
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
311
|
+
const subDir = join(cwd, entry.name);
|
|
312
|
+
const info = detectGitWorktree(subDir);
|
|
313
|
+
if (info.isWorktree && info.worktreeBasePath && info.worktreeBranchName) {
|
|
314
|
+
repos.push({
|
|
315
|
+
path: subDir,
|
|
316
|
+
basePath: info.worktreeBasePath,
|
|
317
|
+
branchName: info.worktreeBranchName,
|
|
318
|
+
displayName: entry.name
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (repos.length > 0) {
|
|
323
|
+
return {
|
|
324
|
+
isWorktree: true,
|
|
325
|
+
workspaceRepos: repos,
|
|
326
|
+
workspacePath: cwd
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
} catch {
|
|
330
|
+
}
|
|
331
|
+
return {};
|
|
332
|
+
}
|
|
333
|
+
function detectWorktreeMetadata() {
|
|
334
|
+
if (process.env.HAPPY_WORKSPACE_REPOS) {
|
|
335
|
+
try {
|
|
336
|
+
const repos = JSON.parse(process.env.HAPPY_WORKSPACE_REPOS);
|
|
337
|
+
return {
|
|
338
|
+
isWorktree: true,
|
|
339
|
+
workspaceRepos: repos,
|
|
340
|
+
workspacePath: process.env.HAPPY_WORKSPACE_PATH
|
|
341
|
+
};
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (process.env.HAPPY_WORKTREE_BASE_PATH) {
|
|
346
|
+
return {
|
|
347
|
+
isWorktree: true,
|
|
348
|
+
worktreeBasePath: process.env.HAPPY_WORKTREE_BASE_PATH,
|
|
349
|
+
worktreeBranchName: process.env.HAPPY_WORKTREE_BRANCH_NAME
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const info = detectGitWorktree(process.cwd());
|
|
353
|
+
if (info.isWorktree) {
|
|
354
|
+
return {
|
|
355
|
+
isWorktree: true,
|
|
356
|
+
worktreeBasePath: info.worktreeBasePath,
|
|
357
|
+
worktreeBranchName: info.worktreeBranchName
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const workspaceResult = detectWorkspaceSubdirectories(process.cwd());
|
|
361
|
+
if (workspaceResult.isWorktree) {
|
|
362
|
+
return workspaceResult;
|
|
363
|
+
}
|
|
364
|
+
return {};
|
|
365
|
+
}
|
|
366
|
+
function createSessionMetadata(opts) {
|
|
367
|
+
const state = {
|
|
368
|
+
controlledByUser: false
|
|
369
|
+
};
|
|
370
|
+
const metadata = {
|
|
371
|
+
path: process.cwd(),
|
|
372
|
+
host: os.hostname(),
|
|
373
|
+
version: packageJson.version,
|
|
374
|
+
os: os.platform(),
|
|
375
|
+
machineId: opts.machineId,
|
|
376
|
+
homeDir: os.homedir(),
|
|
377
|
+
happyHomeDir: configuration.happyHomeDir,
|
|
378
|
+
happyLibDir: projectPath(),
|
|
379
|
+
happyToolsDir: resolveToolsDir(),
|
|
380
|
+
startedFromDaemon: opts.startedBy === "daemon",
|
|
381
|
+
hostPid: process.pid,
|
|
382
|
+
startedBy: opts.startedBy || "terminal",
|
|
383
|
+
lifecycleState: "running",
|
|
384
|
+
lifecycleStateSince: Date.now(),
|
|
385
|
+
flavor: opts.flavor,
|
|
386
|
+
// Worktree metadata: env vars from daemon take priority, otherwise detect via git
|
|
387
|
+
...detectWorktreeMetadata()
|
|
388
|
+
};
|
|
389
|
+
if (opts.flavor === "codex") {
|
|
390
|
+
metadata.skills = discoverCodexSkills();
|
|
391
|
+
}
|
|
392
|
+
return { state, metadata };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function createOfflineSessionStub(sessionTag) {
|
|
396
|
+
return {
|
|
397
|
+
sessionId: `offline-${sessionTag}`,
|
|
398
|
+
sendCodexMessage: () => {
|
|
399
|
+
},
|
|
400
|
+
sendAgentMessage: () => {
|
|
401
|
+
},
|
|
402
|
+
sendClaudeSessionMessage: () => {
|
|
403
|
+
},
|
|
404
|
+
keepAlive: () => {
|
|
405
|
+
},
|
|
406
|
+
sendSessionEvent: () => {
|
|
407
|
+
},
|
|
408
|
+
sendSessionDeath: () => {
|
|
409
|
+
},
|
|
410
|
+
updateLifecycleState: () => {
|
|
411
|
+
},
|
|
412
|
+
requestControlTransfer: async () => {
|
|
413
|
+
},
|
|
414
|
+
flush: async () => {
|
|
415
|
+
},
|
|
416
|
+
close: async () => {
|
|
417
|
+
},
|
|
418
|
+
updateMetadata: () => {
|
|
419
|
+
},
|
|
420
|
+
updateAgentState: () => {
|
|
421
|
+
},
|
|
422
|
+
onUserMessage: () => {
|
|
423
|
+
},
|
|
424
|
+
rpcHandlerManager: {
|
|
425
|
+
registerHandler: () => {
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function setupOfflineReconnection(opts) {
|
|
432
|
+
const { api, sessionTag, metadata, state, response, onSessionSwap } = opts;
|
|
433
|
+
let session;
|
|
434
|
+
let reconnectionHandle = null;
|
|
435
|
+
if (!response) {
|
|
436
|
+
session = createOfflineSessionStub(sessionTag);
|
|
437
|
+
reconnectionHandle = startOfflineReconnection({
|
|
438
|
+
serverUrl: configuration.serverUrl,
|
|
439
|
+
onReconnected: async () => {
|
|
440
|
+
const resp = await api.getOrCreateSession({ tag: sessionTag, metadata, state });
|
|
441
|
+
if (!resp) throw new Error("Server unavailable");
|
|
442
|
+
const realSession = api.sessionSyncClient(resp);
|
|
443
|
+
onSessionSwap(realSession);
|
|
444
|
+
return realSession;
|
|
445
|
+
},
|
|
446
|
+
onNotify: (msg) => {
|
|
447
|
+
console.log(msg);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
return { session, reconnectionHandle, isOffline: true };
|
|
451
|
+
} else {
|
|
452
|
+
session = api.sessionSyncClient(response);
|
|
453
|
+
return { session, reconnectionHandle: null, isOffline: false };
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export { BasePermissionHandler as B, createSessionMetadata as c, setupOfflineReconnection as s };
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var child_process = require('child_process');
|
|
4
4
|
var path = require('node:path');
|
|
5
5
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
6
|
-
var logger = require('./persistence-
|
|
6
|
+
var logger = require('./persistence-BcQmjobZ.cjs');
|
|
7
7
|
var fs = require('node:fs');
|
|
8
8
|
|
|
9
9
|
let cachedRuntime = null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
4
|
-
import { l as logger } from './persistence-
|
|
4
|
+
import { l as logger } from './persistence-D9tMm6bj.mjs';
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
|
|
7
7
|
let cachedRuntime = null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { io } from 'socket.io-client';
|
|
2
|
-
import { c as configuration,
|
|
3
|
-
import { e as ensureDeviceKey, l as listDevices, r as readCachedDeviceNames, a as readCachedDeviceKey, p as pruneDeviceAliases, d as deviceExec } from './deviceKeys-
|
|
4
|
-
import { execOnDeviceViaDaemon } from './controlClient-
|
|
2
|
+
import { c as configuration, g as decrypt, h as decodeBase64, e as encodeBase64, f as encrypt } from './persistence-D9tMm6bj.mjs';
|
|
3
|
+
import { e as ensureDeviceKey, l as listDevices, r as readCachedDeviceNames, a as readCachedDeviceKey, p as pruneDeviceAliases, d as deviceExec } from './deviceKeys-B4aqjnE6.mjs';
|
|
4
|
+
import { execOnDeviceViaDaemon } from './controlClient-DoS9JqQC.mjs';
|
|
5
5
|
import 'node:fs/promises';
|
|
6
6
|
import 'node:fs';
|
|
7
7
|
import 'node:os';
|
|
@@ -12,10 +12,10 @@ import 'tweetnacl';
|
|
|
12
12
|
import 'chalk';
|
|
13
13
|
import 'fs';
|
|
14
14
|
import 'axios';
|
|
15
|
-
import './auth-
|
|
15
|
+
import './auth-Q2STUNI-.mjs';
|
|
16
16
|
import 'qrcode-terminal';
|
|
17
17
|
import './time-DgsBLJA_.mjs';
|
|
18
|
-
import './browser-
|
|
18
|
+
import './browser-BI7s-V8E.mjs';
|
|
19
19
|
import 'open';
|
|
20
20
|
import 'react';
|
|
21
21
|
import 'ink';
|
|
@@ -87,6 +87,9 @@ async function resolveFromServer(credentials, query) {
|
|
|
87
87
|
await pruneDeviceAliases(device.id, device.name);
|
|
88
88
|
return { device, key, variant };
|
|
89
89
|
}
|
|
90
|
+
async function resolveDeviceForCommand(credentials, query) {
|
|
91
|
+
return await resolveFromCache(query) ?? await resolveFromServer(credentials, query);
|
|
92
|
+
}
|
|
90
93
|
async function runOnDevice(credentials, query, command, options = {}) {
|
|
91
94
|
const cached = await resolveFromCache(query);
|
|
92
95
|
const resolved = cached ?? await resolveFromServer(credentials, query);
|
|
@@ -356,4 +359,4 @@ async function sshPickAndConnect(credentials) {
|
|
|
356
359
|
return await sshDevice(credentials, chosen.id);
|
|
357
360
|
}
|
|
358
361
|
|
|
359
|
-
export { parseSshArgs, pickCachedDeviceId, runOnDevice, sshDevice, sshPickAndConnect };
|
|
362
|
+
export { parseSshArgs, pickCachedDeviceId, resolveDeviceForCommand, runOnDevice, sshDevice, sshPickAndConnect };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var socket_ioClient = require('socket.io-client');
|
|
4
|
-
var logger = require('./persistence-
|
|
5
|
-
var deviceKeys = require('./deviceKeys-
|
|
6
|
-
var controlClient = require('./controlClient-
|
|
4
|
+
var logger = require('./persistence-BcQmjobZ.cjs');
|
|
5
|
+
var deviceKeys = require('./deviceKeys-DyUn0bEx.cjs');
|
|
6
|
+
var controlClient = require('./controlClient-CEz_p1zc.cjs');
|
|
7
7
|
require('node:fs/promises');
|
|
8
8
|
require('node:fs');
|
|
9
9
|
require('node:os');
|
|
@@ -14,10 +14,10 @@ require('tweetnacl');
|
|
|
14
14
|
require('chalk');
|
|
15
15
|
require('fs');
|
|
16
16
|
require('axios');
|
|
17
|
-
require('./auth-
|
|
17
|
+
require('./auth-G9fZpVJ2.cjs');
|
|
18
18
|
require('qrcode-terminal');
|
|
19
19
|
require('./time-Bj2HRkKH.cjs');
|
|
20
|
-
require('./browser-
|
|
20
|
+
require('./browser-qDIIAL7S.cjs');
|
|
21
21
|
require('open');
|
|
22
22
|
require('react');
|
|
23
23
|
require('ink');
|
|
@@ -89,6 +89,9 @@ async function resolveFromServer(credentials, query) {
|
|
|
89
89
|
await deviceKeys.pruneDeviceAliases(device.id, device.name);
|
|
90
90
|
return { device, key, variant };
|
|
91
91
|
}
|
|
92
|
+
async function resolveDeviceForCommand(credentials, query) {
|
|
93
|
+
return await resolveFromCache(query) ?? await resolveFromServer(credentials, query);
|
|
94
|
+
}
|
|
92
95
|
async function runOnDevice(credentials, query, command, options = {}) {
|
|
93
96
|
const cached = await resolveFromCache(query);
|
|
94
97
|
const resolved = cached ?? await resolveFromServer(credentials, query);
|
|
@@ -360,6 +363,7 @@ async function sshPickAndConnect(credentials) {
|
|
|
360
363
|
|
|
361
364
|
exports.parseSshArgs = parseSshArgs;
|
|
362
365
|
exports.pickCachedDeviceId = pickCachedDeviceId;
|
|
366
|
+
exports.resolveDeviceForCommand = resolveDeviceForCommand;
|
|
363
367
|
exports.runOnDevice = runOnDevice;
|
|
364
368
|
exports.sshDevice = sshDevice;
|
|
365
369
|
exports.sshPickAndConnect = sshPickAndConnect;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { r as readCredentials } from './persistence-
|
|
4
|
-
import { r as runSessionList } from './sessionList-
|
|
5
|
-
import { r as runSessionSummary } from './sessionSummary-
|
|
3
|
+
import { r as readCredentials } from './persistence-D9tMm6bj.mjs';
|
|
4
|
+
import { r as runSessionList } from './sessionList-DaufR-sA.mjs';
|
|
5
|
+
import { r as runSessionSummary } from './sessionSummary-Dv6dPABg.mjs';
|
|
6
6
|
import { p as parseWorkflowArgs, s as stringFlag, b as booleanFlag, n as numberFlag, a as printOrWriteOutput } from './workflowCommon-B0d01Y_a.mjs';
|
|
7
7
|
import 'node:fs/promises';
|
|
8
8
|
import 'node:fs';
|
|
@@ -12,14 +12,14 @@ import 'node:crypto';
|
|
|
12
12
|
import 'tweetnacl';
|
|
13
13
|
import 'fs';
|
|
14
14
|
import 'axios';
|
|
15
|
-
import './auth-
|
|
15
|
+
import './auth-Q2STUNI-.mjs';
|
|
16
16
|
import 'qrcode-terminal';
|
|
17
17
|
import './time-DgsBLJA_.mjs';
|
|
18
|
-
import './browser-
|
|
18
|
+
import './browser-BI7s-V8E.mjs';
|
|
19
19
|
import 'open';
|
|
20
20
|
import 'react';
|
|
21
21
|
import 'ink';
|
|
22
|
-
import './sessionKeyCache-
|
|
22
|
+
import './sessionKeyCache-pXTjpETo.mjs';
|
|
23
23
|
|
|
24
24
|
function printTaskHelp() {
|
|
25
25
|
console.log(`
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var path = require('node:path');
|
|
5
|
-
var logger = require('./persistence-
|
|
6
|
-
var sessionList = require('./sessionList-
|
|
7
|
-
var sessionSummary = require('./sessionSummary-
|
|
5
|
+
var logger = require('./persistence-BcQmjobZ.cjs');
|
|
6
|
+
var sessionList = require('./sessionList-fG5uAPzU.cjs');
|
|
7
|
+
var sessionSummary = require('./sessionSummary-CjZPt6nr.cjs');
|
|
8
8
|
var workflowCommon = require('./workflowCommon-Bl568-rt.cjs');
|
|
9
9
|
require('node:fs/promises');
|
|
10
10
|
require('node:fs');
|
|
@@ -14,14 +14,14 @@ require('node:crypto');
|
|
|
14
14
|
require('tweetnacl');
|
|
15
15
|
require('fs');
|
|
16
16
|
require('axios');
|
|
17
|
-
require('./auth-
|
|
17
|
+
require('./auth-G9fZpVJ2.cjs');
|
|
18
18
|
require('qrcode-terminal');
|
|
19
19
|
require('./time-Bj2HRkKH.cjs');
|
|
20
|
-
require('./browser-
|
|
20
|
+
require('./browser-qDIIAL7S.cjs');
|
|
21
21
|
require('open');
|
|
22
22
|
require('react');
|
|
23
23
|
require('ink');
|
|
24
|
-
require('./sessionKeyCache-
|
|
24
|
+
require('./sessionKeyCache-BwFUGgMs.cjs');
|
|
25
25
|
|
|
26
26
|
function printTaskHelp() {
|
|
27
27
|
console.log(`
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { l as logger } from './persistence-
|
|
1
|
+
import { l as logger } from './persistence-D9tMm6bj.mjs';
|
|
2
2
|
import { existsSync, unlinkSync } from 'fs';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import os from 'os';
|
|
6
6
|
import { s as systemdScopeFor, i as isRootUser, S as SERVICE_NAME } from './systemdScope-BeOtAkhk.mjs';
|
|
7
|
-
import { stopDaemon } from './controlClient-
|
|
7
|
+
import { stopDaemon } from './controlClient-DoS9JqQC.mjs';
|
|
8
8
|
import 'node:fs/promises';
|
|
9
9
|
import 'node:fs';
|
|
10
10
|
import 'node:os';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./persistence-
|
|
3
|
+
var logger = require('./persistence-BcQmjobZ.cjs');
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var child_process = require('child_process');
|
|
6
6
|
var path = require('path');
|
|
7
7
|
var os = require('os');
|
|
8
8
|
var systemdScope = require('./systemdScope-DW3-UoKB.cjs');
|
|
9
|
-
var controlClient = require('./controlClient-
|
|
9
|
+
var controlClient = require('./controlClient-CEz_p1zc.cjs');
|
|
10
10
|
require('node:fs/promises');
|
|
11
11
|
require('node:fs');
|
|
12
12
|
require('node:os');
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_child_process = require('node:child_process');
|
|
5
5
|
var fs = require('node:fs');
|
|
6
|
-
var logger = require('./persistence-
|
|
7
|
-
var controlClient = require('./controlClient-
|
|
8
|
-
var spawnHappyCLI = require('./spawnHappyCLI-
|
|
6
|
+
var logger = require('./persistence-BcQmjobZ.cjs');
|
|
7
|
+
var controlClient = require('./controlClient-CEz_p1zc.cjs');
|
|
8
|
+
var spawnHappyCLI = require('./spawnHappyCLI-Cfu7C1uM.cjs');
|
|
9
9
|
require('node:fs/promises');
|
|
10
10
|
require('node:os');
|
|
11
11
|
require('node:path');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { execFileSync, execSync } from 'node:child_process';
|
|
3
3
|
import { realpathSync } from 'node:fs';
|
|
4
|
-
import { p as packageJson } from './persistence-
|
|
5
|
-
import { checkIfDaemonRunningAndCleanupStaleState, stopDaemon } from './controlClient-
|
|
6
|
-
import { s as spawnHappyCLI } from './spawnHappyCLI-
|
|
4
|
+
import { p as packageJson } from './persistence-D9tMm6bj.mjs';
|
|
5
|
+
import { checkIfDaemonRunningAndCleanupStaleState, stopDaemon } from './controlClient-DoS9JqQC.mjs';
|
|
6
|
+
import { s as spawnHappyCLI } from './spawnHappyCLI-DhUeycct.mjs';
|
|
7
7
|
import 'node:fs/promises';
|
|
8
8
|
import 'node:os';
|
|
9
9
|
import 'node:path';
|