@pushary/agent-hooks 1.9.6 → 1.9.8
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/CHANGELOG.md +19 -0
- package/README.md +3 -3
- package/data/cursor-plugin/README.md +3 -7
- package/data/vscode-plugin/README.md +1 -1
- package/dist/bin/pushary-bell-hook.js +22 -23
- package/dist/bin/pushary-bell.js +9 -9
- package/dist/bin/pushary-claude.js +27 -28
- package/dist/bin/pushary-clean.js +98 -76
- package/dist/bin/pushary-codex-bridge.js +18 -18
- package/dist/bin/pushary-codex-hook.js +32 -33
- package/dist/bin/pushary-codex.js +13 -13
- package/dist/bin/pushary-connect.js +24 -21
- package/dist/bin/pushary-cowork.js +5 -5
- package/dist/bin/pushary-daemon.js +51 -38
- package/dist/bin/pushary-disconnect.js +187 -52
- package/dist/bin/pushary-doctor.js +68 -56
- package/dist/bin/pushary-elicitation-hook.js +24 -25
- package/dist/bin/pushary-gemini-bridge.js +13 -13
- package/dist/bin/pushary-gemini-hook.js +29 -30
- package/dist/bin/pushary-hook.js +30 -32
- package/dist/bin/pushary-login.js +12 -12
- package/dist/bin/pushary-logout.js +105 -42
- package/dist/bin/pushary-mcp.js +9 -9
- package/dist/bin/pushary-mode.js +28 -31
- package/dist/bin/pushary-notification-hook.js +26 -28
- package/dist/bin/pushary-opencode-hook.js +28 -29
- package/dist/bin/pushary-permission-denied-hook.js +30 -32
- package/dist/bin/pushary-permission-hook.js +29 -31
- package/dist/bin/pushary-post-hook.js +26 -28
- package/dist/bin/pushary-prompt-hook.js +26 -28
- package/dist/bin/pushary-session-end-hook.js +26 -28
- package/dist/bin/pushary-session-start-hook.js +31 -31
- package/dist/bin/pushary-setup.js +98 -106
- package/dist/bin/pushary-stats.js +5 -5
- package/dist/bin/pushary-status.js +34 -18
- package/dist/bin/pushary-stop-hook.js +26 -28
- package/dist/bin/pushary-stopfailure-hook.js +26 -28
- package/dist/bin/pushary-suggestions.js +19 -21
- package/dist/bin/pushary-transcript-register.js +18 -19
- package/dist/bin/pushary-transcripts.js +7 -7
- package/dist/bin/pushary-upgrade.js +67 -31
- package/dist/bin/pushary-wait.js +23 -19
- package/dist/bin/pushary.js +15 -14
- package/dist/{chunk-BSZ7VBVT.js → chunk-2A53H4S6.js} +17 -15
- package/dist/{chunk-D7SOOVHX.js → chunk-2QGYMY7A.js} +83 -3
- package/dist/{chunk-SVTHEMM3.js → chunk-2QTO5YIT.js} +6 -6
- package/dist/{chunk-WN6WYUCV.js → chunk-2VZAALEJ.js} +5 -9
- package/dist/chunk-2WXF3QJR.js +49 -0
- package/dist/{chunk-UKNKYTTY.js → chunk-3I6IVOZV.js} +3 -3
- package/dist/chunk-3Z3A37WD.js +77 -0
- package/dist/{chunk-2QRE6QH2.js → chunk-5QUPKDI5.js} +1 -1
- package/dist/chunk-6TE27XZR.js +69 -0
- package/dist/{chunk-L6USMDTW.js → chunk-7DVNSQWF.js} +59 -15
- package/dist/{chunk-SNJ3BOCP.js → chunk-7PT35RY2.js} +27 -8
- package/dist/{chunk-CBVDW2N6.js → chunk-B64KHETR.js} +3 -3
- package/dist/chunk-BEJRK4DF.js +94 -0
- package/dist/chunk-BXET3ALR.js +46 -0
- package/dist/{chunk-DJ4BB264.js → chunk-CD47ZFFZ.js} +1 -1
- package/dist/{chunk-FBD3QGVJ.js → chunk-CKV3UPMU.js} +2 -2
- package/dist/{chunk-7JTVYR5B.js → chunk-CLOSJ4ES.js} +1 -1
- package/dist/{chunk-DA4FTGTK.js → chunk-DKMD6AWR.js} +4 -4
- package/dist/{chunk-SPXBXN23.js → chunk-DL7XWKYV.js} +7 -5
- package/dist/{chunk-VRT3EEZN.js → chunk-DPGSLWOS.js} +8 -8
- package/dist/{chunk-3BUAEQCY.js → chunk-DUZVXBBU.js} +1 -1
- package/dist/{chunk-6GERGJHF.js → chunk-EUW7JL2K.js} +0 -32
- package/dist/{chunk-75CA37FZ.js → chunk-FQ2GORVG.js} +2 -2
- package/dist/{chunk-WUKUXICK.js → chunk-HRULIYDU.js} +2 -2
- package/dist/{chunk-Q4E56K4X.js → chunk-I5IJRMNV.js} +78 -8
- package/dist/{chunk-MKJ3RTUS.js → chunk-I6MJXLMY.js} +2 -2
- package/dist/{chunk-YPXUD6DW.js → chunk-IAD2RT4L.js} +14 -14
- package/dist/{chunk-LBLCFD5K.js → chunk-IHFDPV7C.js} +2 -2
- package/dist/{chunk-BVCHY4OY.js → chunk-IHO3YQAN.js} +2 -2
- package/dist/{chunk-RDK7FX5F.js → chunk-KF3UZLYI.js} +1 -1
- package/dist/chunk-KFF7G225.js +599 -0
- package/dist/{chunk-TE5M6GGK.js → chunk-KHNFLYJO.js} +204 -28
- package/dist/{chunk-CCDVL63C.js → chunk-KRCR2CRQ.js} +9 -9
- package/dist/{chunk-ZC3TF4LR.js → chunk-LKLVTG3V.js} +18 -9
- package/dist/{chunk-4QKM44N6.js → chunk-LWOO567I.js} +4 -3
- package/dist/{chunk-KK54WQ74.js → chunk-M6BZZFVQ.js} +1 -1
- package/dist/{chunk-RIC6OOJX.js → chunk-MFF3ONG5.js} +21 -1
- package/dist/{chunk-IMGJYFCX.js → chunk-MGRFDGWU.js} +3 -2
- package/dist/{chunk-ZPW4MJOV.js → chunk-MKTJEXZ3.js} +3 -3
- package/dist/{chunk-2I23NFVT.js → chunk-MXHTGVFZ.js} +52 -9
- package/dist/{chunk-5BHROGRB.js → chunk-N4QSPI3B.js} +54 -5
- package/dist/{chunk-DGQTJDSJ.js → chunk-NWDG3MSW.js} +1 -1
- package/dist/chunk-OP7IHC2I.js +24 -0
- package/dist/{chunk-EVFY3VE6.js → chunk-QOLITCIP.js} +1 -1
- package/dist/{chunk-W4Q7NFXU.js → chunk-TCQ43LSG.js} +3 -3
- package/dist/chunk-TCWKTUAE.js +50 -0
- package/dist/{chunk-EZAFBC2C.js → chunk-V5HPPF3E.js} +8 -4
- package/dist/{chunk-Q23MMVTD.js → chunk-WG3K4TCH.js} +1 -1
- package/dist/{chunk-F56SB65Y.js → chunk-WS4H76EP.js} +2 -2
- package/dist/{chunk-HWQNQVY6.js → chunk-WWOHTTVP.js} +2 -2
- package/dist/{chunk-NVGDMTX3.js → chunk-YIG2R3BJ.js} +9 -7
- package/dist/{chunk-HJXZJF6O.js → chunk-ZBHUHJG6.js} +4 -4
- package/dist/{chunk-5AXCOTIT.js → chunk-ZBK6E2OR.js} +1 -1
- package/dist/{chunk-5PMTC2CB.js → chunk-ZN3C6GBG.js} +84 -673
- package/dist/{chunk-GQHZIBAZ.js → chunk-ZSTSEBG7.js} +1 -1
- package/dist/{chunk-PYZC54KA.js → chunk-ZW3XZLJC.js} +61 -17
- package/dist/{global-upgrade-7F5RP45B.js → global-upgrade-I56HNM23.js} +6 -6
- package/dist/{paths-MELXIVBO.js → paths-AGY43CXS.js} +2 -2
- package/dist/reapply-IA5XUKWW.js +57 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +19 -20
- package/dist/{upgrade-lock-AHRBA66K.js → upgrade-lock-B34TAUKV.js} +5 -3
- package/package.json +1 -1
- package/dist/chunk-HT3WMM6Q.js +0 -44
- package/dist/chunk-IR5FRUPQ.js +0 -197
- package/dist/chunk-JUFKJCZG.js +0 -38
- package/dist/chunk-SJN22ADZ.js +0 -86
- package/dist/reapply-NOB2Q6C4.js +0 -35
|
@@ -1,34 +1,200 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addClaudeMcpServer,
|
|
3
|
-
addPusharyToolPermissions,
|
|
4
|
-
isPusharyHook,
|
|
5
|
-
removeClaudeMcpServers
|
|
6
|
-
} from "./chunk-IR5FRUPQ.js";
|
|
7
1
|
import {
|
|
8
2
|
CLAUDE_HOOK_EVENTS,
|
|
9
3
|
addGeminiMcpServer,
|
|
10
|
-
removeGeminiMcpServer
|
|
11
|
-
|
|
4
|
+
removeGeminiMcpServer,
|
|
5
|
+
supportedClaudeEvents
|
|
6
|
+
} from "./chunk-3I6IVOZV.js";
|
|
12
7
|
import {
|
|
13
8
|
CLAUDE_CODE_AGENT,
|
|
14
9
|
parseApplyPatchFiles
|
|
15
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KRCR2CRQ.js";
|
|
16
11
|
import {
|
|
17
12
|
guardBinary,
|
|
18
13
|
holdBudgetOf,
|
|
14
|
+
isProtectedByScope,
|
|
19
15
|
registerHookEntry
|
|
20
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ZBHUHJG6.js";
|
|
21
17
|
import {
|
|
18
|
+
HOOK_LOCATOR_BINARY,
|
|
22
19
|
PHONE_ANSWERED_TOOLS,
|
|
23
20
|
hookCompatibleProfile,
|
|
24
21
|
hookCompatibleProfileBySource,
|
|
25
22
|
toToolLookup,
|
|
26
23
|
withHookHoldBudget
|
|
27
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-I5IJRMNV.js";
|
|
25
|
+
|
|
26
|
+
// src/claude-config.ts
|
|
27
|
+
import { join } from "path";
|
|
28
|
+
import { isDeepStrictEqual } from "util";
|
|
29
|
+
var PUSHARY_MCP_URL = "https://pushary.com/api/mcp/mcp";
|
|
30
|
+
var PUSHARY_PERMISSION_RULE = "mcp__pushary__*";
|
|
31
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
32
|
+
var ensureRecord = (target, key) => {
|
|
33
|
+
const existing = asRecord(target[key]);
|
|
34
|
+
if (existing) return existing;
|
|
35
|
+
const created = {};
|
|
36
|
+
target[key] = created;
|
|
37
|
+
return created;
|
|
38
|
+
};
|
|
39
|
+
var isPusharyPermission = (rule) => typeof rule === "string" && (rule.includes("pushary") || rule.includes("MCP(pushary"));
|
|
40
|
+
var HOOK_BINARIES = /* @__PURE__ */ new Set([
|
|
41
|
+
...CLAUDE_HOOK_EVENTS.map((hook) => hook.binary),
|
|
42
|
+
HOOK_LOCATOR_BINARY
|
|
43
|
+
]);
|
|
44
|
+
var namesPusharyBinary = (command) => command.split(/[\s/\\"']+/).some((segment) => HOOK_BINARIES.has(segment.replace(/\.(cmd|exe)$/i, "")));
|
|
45
|
+
var isPusharyHook = (entry2, scope) => {
|
|
46
|
+
const hooks = asRecord(entry2)?.hooks;
|
|
47
|
+
if (!Array.isArray(hooks)) return false;
|
|
48
|
+
return hooks.some((hook) => {
|
|
49
|
+
const command = String(asRecord(hook)?.command ?? "");
|
|
50
|
+
if (isProtectedByScope(command, scope)) return false;
|
|
51
|
+
return namesPusharyBinary(command);
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
var pusharyMcpServer = (apiKey) => ({
|
|
55
|
+
type: "http",
|
|
56
|
+
url: PUSHARY_MCP_URL,
|
|
57
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
58
|
+
});
|
|
59
|
+
var addClaudeMcpServer = (config, apiKey) => {
|
|
60
|
+
const mcpServers = ensureRecord(config, "mcpServers");
|
|
61
|
+
mcpServers.pushary = pusharyMcpServer(apiKey);
|
|
62
|
+
};
|
|
63
|
+
var isClaudeMcpSnapshot = (value) => {
|
|
64
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
65
|
+
const snapshot = value;
|
|
66
|
+
return typeof snapshot.hadMcpServers === "boolean" && typeof snapshot.mcpServersWasRecord === "boolean" && (!snapshot.hadMcpServers || snapshot.mcpServersWasRecord || Object.hasOwn(snapshot, "mcpServers")) && typeof snapshot.hadPushary === "boolean" && (!snapshot.hadPushary || Object.hasOwn(snapshot, "pushary")) && (!Object.hasOwn(snapshot, "installedPushary") || asRecord(snapshot.installedPushary)?.type === "http" && asRecord(snapshot.installedPushary)?.url === PUSHARY_MCP_URL);
|
|
67
|
+
};
|
|
68
|
+
var captureClaudeMcpServer = (config, apiKey) => {
|
|
69
|
+
const mcpServers = asRecord(config.mcpServers);
|
|
70
|
+
const hadMcpServers = Object.hasOwn(config, "mcpServers");
|
|
71
|
+
return {
|
|
72
|
+
hadMcpServers,
|
|
73
|
+
mcpServersWasRecord: Boolean(mcpServers),
|
|
74
|
+
...hadMcpServers && !mcpServers ? { mcpServers: structuredClone(config.mcpServers) } : {},
|
|
75
|
+
hadPushary: Boolean(mcpServers && Object.hasOwn(mcpServers, "pushary")),
|
|
76
|
+
...mcpServers && Object.hasOwn(mcpServers, "pushary") ? { pushary: structuredClone(mcpServers.pushary) } : {},
|
|
77
|
+
...apiKey ? { installedPushary: pusharyMcpServer(apiKey) } : {}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
var updateClaudeMcpSnapshot = (snapshot, apiKey) => ({
|
|
81
|
+
...snapshot,
|
|
82
|
+
installedPushary: pusharyMcpServer(apiKey)
|
|
83
|
+
});
|
|
84
|
+
var restoreClaudeMcpServer = (config, snapshot) => {
|
|
85
|
+
const mcpServers = asRecord(config.mcpServers);
|
|
86
|
+
const current = asRecord(mcpServers?.pushary);
|
|
87
|
+
if (Object.hasOwn(snapshot, "installedPushary")) {
|
|
88
|
+
if (!isDeepStrictEqual(mcpServers?.pushary, snapshot.installedPushary)) return false;
|
|
89
|
+
} else if (current?.type !== "http" || current.url !== PUSHARY_MCP_URL) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (!snapshot.mcpServersWasRecord) {
|
|
93
|
+
if (Object.keys(mcpServers).length === 1) {
|
|
94
|
+
if (snapshot.hadMcpServers) config.mcpServers = structuredClone(snapshot.mcpServers);
|
|
95
|
+
else delete config.mcpServers;
|
|
96
|
+
} else {
|
|
97
|
+
delete mcpServers.pushary;
|
|
98
|
+
}
|
|
99
|
+
} else if (snapshot.hadPushary) {
|
|
100
|
+
mcpServers.pushary = structuredClone(snapshot.pushary);
|
|
101
|
+
} else {
|
|
102
|
+
delete mcpServers.pushary;
|
|
103
|
+
if (!snapshot.hadMcpServers && Object.keys(mcpServers).length === 0) delete config.mcpServers;
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
};
|
|
107
|
+
var removeClaudeMcpServers = (config) => {
|
|
108
|
+
let changed = false;
|
|
109
|
+
const removeFrom = (target) => {
|
|
110
|
+
const mcpServers = asRecord(target.mcpServers);
|
|
111
|
+
if (!mcpServers?.pushary) return;
|
|
112
|
+
delete mcpServers.pushary;
|
|
113
|
+
if (Object.keys(mcpServers).length === 0) delete target.mcpServers;
|
|
114
|
+
changed = true;
|
|
115
|
+
};
|
|
116
|
+
removeFrom(config);
|
|
117
|
+
const projects = asRecord(config.projects);
|
|
118
|
+
if (projects) {
|
|
119
|
+
for (const project of Object.values(projects)) {
|
|
120
|
+
const projectConfig = asRecord(project);
|
|
121
|
+
if (projectConfig) removeFrom(projectConfig);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return changed;
|
|
125
|
+
};
|
|
126
|
+
var removePusharyToolPermissions = (settings) => {
|
|
127
|
+
const permissions = asRecord(settings.permissions);
|
|
128
|
+
if (!permissions || !Array.isArray(permissions.allow)) return false;
|
|
129
|
+
const filtered = permissions.allow.filter((rule) => !isPusharyPermission(rule));
|
|
130
|
+
if (filtered.length === permissions.allow.length) return false;
|
|
131
|
+
if (filtered.length === 0) delete permissions.allow;
|
|
132
|
+
else permissions.allow = filtered;
|
|
133
|
+
if (Object.keys(permissions).length === 0) delete settings.permissions;
|
|
134
|
+
return true;
|
|
135
|
+
};
|
|
136
|
+
var addPusharyToolPermissions = (settings) => {
|
|
137
|
+
const permissions = ensureRecord(settings, "permissions");
|
|
138
|
+
const allow = Array.isArray(permissions.allow) ? permissions.allow : [];
|
|
139
|
+
const filtered = allow.filter((rule) => !isPusharyPermission(rule));
|
|
140
|
+
if (!filtered.includes(PUSHARY_PERMISSION_RULE)) {
|
|
141
|
+
filtered.push(PUSHARY_PERMISSION_RULE);
|
|
142
|
+
}
|
|
143
|
+
permissions.allow = filtered;
|
|
144
|
+
};
|
|
145
|
+
var addPusharyHooks = (settings, binDir, version = null) => {
|
|
146
|
+
const resolve2 = (name) => guardBinary(binDir ? join(binDir, name) : name);
|
|
147
|
+
const hooks = ensureRecord(settings, "hooks");
|
|
148
|
+
const supported = new Map(supportedClaudeEvents(version).map((hook) => [hook.event, hook]));
|
|
149
|
+
for (const known of CLAUDE_HOOK_EVENTS) {
|
|
150
|
+
const current = Array.isArray(hooks[known.event]) ? hooks[known.event] : [];
|
|
151
|
+
const definition = supported.get(known.event);
|
|
152
|
+
if (definition) {
|
|
153
|
+
hooks[known.event] = registerHookEntry(current, isPusharyHook, entry(definition, resolve2));
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const others = current.filter((item) => !isPusharyHook(item));
|
|
157
|
+
if (others.length > 0) {
|
|
158
|
+
hooks[known.event] = others;
|
|
159
|
+
} else {
|
|
160
|
+
delete hooks[known.event];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var entry = (definition, resolve2) => ({
|
|
165
|
+
...definition.matcher ? { matcher: definition.matcher } : {},
|
|
166
|
+
hooks: [{
|
|
167
|
+
type: "command",
|
|
168
|
+
command: withHookHoldBudget(resolve2(definition.binary), holdBudgetOf(definition)),
|
|
169
|
+
timeout: definition.timeout
|
|
170
|
+
}]
|
|
171
|
+
});
|
|
172
|
+
var removePusharySettings = (settings, scope) => {
|
|
173
|
+
let changed = scope?.keepMcpServer === true ? false : removeClaudeMcpServers(settings);
|
|
174
|
+
if (scope?.keepMcpServer !== true && removePusharyToolPermissions(settings)) changed = true;
|
|
175
|
+
const hooks = asRecord(settings.hooks);
|
|
176
|
+
if (hooks) {
|
|
177
|
+
for (const { event: key } of CLAUDE_HOOK_EVENTS) {
|
|
178
|
+
const entries = hooks[key];
|
|
179
|
+
if (!Array.isArray(entries)) continue;
|
|
180
|
+
const filtered = entries.filter((entry2) => !isPusharyHook(entry2, scope));
|
|
181
|
+
if (filtered.length !== entries.length) {
|
|
182
|
+
if (filtered.length === 0) {
|
|
183
|
+
delete hooks[key];
|
|
184
|
+
} else {
|
|
185
|
+
hooks[key] = filtered;
|
|
186
|
+
}
|
|
187
|
+
changed = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (Object.keys(hooks).length === 0) delete settings.hooks;
|
|
191
|
+
}
|
|
192
|
+
return changed;
|
|
193
|
+
};
|
|
28
194
|
|
|
29
195
|
// src/compatible-config.ts
|
|
30
196
|
import { homedir } from "os";
|
|
31
|
-
import { isAbsolute, join, resolve } from "path";
|
|
197
|
+
import { isAbsolute, join as join2, resolve } from "path";
|
|
32
198
|
var AGENT_FLAG = "--agent";
|
|
33
199
|
var SOURCE_FLAG = "--source";
|
|
34
200
|
var agentArgument = (profile) => `${AGENT_FLAG}=${profile.agentType}`;
|
|
@@ -74,25 +240,25 @@ var normalizeToolCall = (profile, input) => {
|
|
|
74
240
|
const lookup = lookupFor(profile, input);
|
|
75
241
|
return { ...input, tool_name: lookup.tool, tool_input: lookup.input };
|
|
76
242
|
};
|
|
77
|
-
var underHome = (segments, home = homedir()) =>
|
|
243
|
+
var underHome = (segments, home = homedir()) => join2(home, ...segments);
|
|
78
244
|
var compatibleConfigFile = (profile, home) => underHome(profile.configFile, home);
|
|
79
245
|
var compatibleMcpFile = (profile, home) => profile.mcp ? underHome(profile.mcp.file, home) : null;
|
|
80
246
|
var compatibleInstructionsFile = (profile, home) => profile.instructions ? underHome(profile.instructions.file, home) : null;
|
|
81
|
-
var
|
|
82
|
-
var
|
|
83
|
-
const existing =
|
|
247
|
+
var asRecord2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
248
|
+
var ensureRecord2 = (target, key) => {
|
|
249
|
+
const existing = asRecord2(target[key]);
|
|
84
250
|
if (existing) return existing;
|
|
85
251
|
const created = {};
|
|
86
252
|
target[key] = created;
|
|
87
253
|
return created;
|
|
88
254
|
};
|
|
89
|
-
var descend = (config, keyPath) => keyPath.reduce(
|
|
90
|
-
var findMap = (config, keyPath) => keyPath.reduce((node, key) => node &&
|
|
255
|
+
var descend = (config, keyPath) => keyPath.reduce(ensureRecord2, config);
|
|
256
|
+
var findMap = (config, keyPath) => keyPath.reduce((node, key) => node && asRecord2(node[key]), config);
|
|
91
257
|
var pruneEmptyMap = (config, keyPath) => {
|
|
92
258
|
if (keyPath.length === 0) return false;
|
|
93
259
|
const parent = findMap(config, keyPath.slice(0, -1));
|
|
94
260
|
const key = keyPath[keyPath.length - 1];
|
|
95
|
-
const map =
|
|
261
|
+
const map = asRecord2(parent?.[key]);
|
|
96
262
|
if (!parent || !map || Object.keys(map).length > 0) return false;
|
|
97
263
|
delete parent[key];
|
|
98
264
|
return true;
|
|
@@ -114,12 +280,12 @@ var WRITTEN = { ok: true };
|
|
|
114
280
|
var ROOT_KEY = "(root)";
|
|
115
281
|
var dotted = (segments) => segments.join(".") || ROOT_KEY;
|
|
116
282
|
var hooksShapeConflict = (config, profile) => {
|
|
117
|
-
if (!
|
|
283
|
+
if (!asRecord2(config)) return ROOT_KEY;
|
|
118
284
|
const walked = [];
|
|
119
285
|
let node = config;
|
|
120
286
|
for (const key of profile.hooksKeyPath) {
|
|
121
287
|
if (node[key] === void 0) return void 0;
|
|
122
|
-
const nested =
|
|
288
|
+
const nested = asRecord2(node[key]);
|
|
123
289
|
if (!nested) return dotted([...walked, key]);
|
|
124
290
|
walked.push(key);
|
|
125
291
|
node = nested;
|
|
@@ -128,9 +294,9 @@ var hooksShapeConflict = (config, profile) => {
|
|
|
128
294
|
return clash ? dotted([...walked, clash.event]) : void 0;
|
|
129
295
|
};
|
|
130
296
|
var permissionsShapeConflict = (config) => {
|
|
131
|
-
if (!
|
|
297
|
+
if (!asRecord2(config)) return ROOT_KEY;
|
|
132
298
|
if (config.permissions === void 0) return void 0;
|
|
133
|
-
const permissions =
|
|
299
|
+
const permissions = asRecord2(config.permissions);
|
|
134
300
|
if (!permissions) return "permissions";
|
|
135
301
|
return permissions.allow !== void 0 && !Array.isArray(permissions.allow) ? "permissions.allow" : void 0;
|
|
136
302
|
};
|
|
@@ -154,7 +320,7 @@ var entryFor = (profile, definition, resolve2) => ({
|
|
|
154
320
|
var addCompatibleHooks = (config, profile, binDir) => {
|
|
155
321
|
const conflictAt = hooksShapeConflict(config, profile);
|
|
156
322
|
if (conflictAt) return { ok: false, conflictAt };
|
|
157
|
-
const resolve2 = (name) => guardBinary(binDir ?
|
|
323
|
+
const resolve2 = (name) => guardBinary(binDir ? join2(binDir, name) : name);
|
|
158
324
|
const hooks = descend(config, profile.hooksKeyPath);
|
|
159
325
|
const supported = new Map(compatibleHookEvents(profile).map((hook) => [hook.event, hook]));
|
|
160
326
|
for (const known of CLAUDE_HOOK_EVENTS) {
|
|
@@ -177,7 +343,7 @@ var removeCompatibleHooks = (config, profile, scope) => {
|
|
|
177
343
|
for (const { event } of CLAUDE_HOOK_EVENTS) {
|
|
178
344
|
const entries = hooks[event];
|
|
179
345
|
if (!Array.isArray(entries)) continue;
|
|
180
|
-
const kept = entries.filter((
|
|
346
|
+
const kept = entries.filter((entry2) => !isPusharyHook(entry2, scope));
|
|
181
347
|
if (kept.length === entries.length) continue;
|
|
182
348
|
if (kept.length === 0) delete hooks[event];
|
|
183
349
|
else hooks[event] = kept;
|
|
@@ -191,14 +357,14 @@ var hasCompatibleHooks = (config, profile) => {
|
|
|
191
357
|
if (!hooks) return false;
|
|
192
358
|
return compatibleHookEvents(profile).some(({ event }) => {
|
|
193
359
|
const entries = hooks[event];
|
|
194
|
-
return Array.isArray(entries) && entries.some((
|
|
360
|
+
return Array.isArray(entries) && entries.some((entry2) => isPusharyHook(entry2));
|
|
195
361
|
});
|
|
196
362
|
};
|
|
197
363
|
var missingCompatibleHookEvents = (config, profile) => {
|
|
198
364
|
const hooks = findMap(config, profile.hooksKeyPath);
|
|
199
365
|
return compatibleHookEvents(profile).filter(({ event }) => {
|
|
200
366
|
const entries = hooks?.[event];
|
|
201
|
-
return !Array.isArray(entries) || !entries.some((
|
|
367
|
+
return !Array.isArray(entries) || !entries.some((entry2) => isPusharyHook(entry2));
|
|
202
368
|
}).map(({ event }) => event);
|
|
203
369
|
};
|
|
204
370
|
var compatiblePermissionRuleFile = (profile, home) => profile.permissionRuleFile ? underHome(profile.permissionRuleFile, home) : null;
|
|
@@ -210,7 +376,7 @@ var addCompatibleMcpServer = (config, profile, apiKey) => {
|
|
|
210
376
|
}
|
|
211
377
|
addClaudeMcpServer(config, apiKey);
|
|
212
378
|
if (!profile.mcp.trusted) return;
|
|
213
|
-
const server =
|
|
379
|
+
const server = asRecord2(asRecord2(config.mcpServers)?.pushary);
|
|
214
380
|
if (server) server.trust = true;
|
|
215
381
|
};
|
|
216
382
|
var removeCompatibleMcpServer = (config, profile) => {
|
|
@@ -219,6 +385,16 @@ var removeCompatibleMcpServer = (config, profile) => {
|
|
|
219
385
|
};
|
|
220
386
|
|
|
221
387
|
export {
|
|
388
|
+
addClaudeMcpServer,
|
|
389
|
+
isClaudeMcpSnapshot,
|
|
390
|
+
captureClaudeMcpServer,
|
|
391
|
+
updateClaudeMcpSnapshot,
|
|
392
|
+
restoreClaudeMcpServer,
|
|
393
|
+
removeClaudeMcpServers,
|
|
394
|
+
removePusharyToolPermissions,
|
|
395
|
+
addPusharyToolPermissions,
|
|
396
|
+
addPusharyHooks,
|
|
397
|
+
removePusharySettings,
|
|
222
398
|
profileFromArgv,
|
|
223
399
|
activeIdentity,
|
|
224
400
|
activeHookSource,
|
|
@@ -14,36 +14,36 @@ import {
|
|
|
14
14
|
IDLE_PROMPT_NOTIFICATION,
|
|
15
15
|
NOTIFICATION_PUSH_TYPES,
|
|
16
16
|
POSTTOOLUSE_MIRROR_ONLY_TOOLS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-CD47ZFFZ.js";
|
|
18
18
|
import {
|
|
19
19
|
cancelQuestion,
|
|
20
20
|
isPolicyConfig,
|
|
21
21
|
sendNotification,
|
|
22
22
|
waitForAnswer
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-2VZAALEJ.js";
|
|
24
24
|
import {
|
|
25
25
|
clientErrorKindOf,
|
|
26
26
|
reportClientError
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-DKMD6AWR.js";
|
|
28
28
|
import {
|
|
29
29
|
withRetry
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-MKTJEXZ3.js";
|
|
31
31
|
import {
|
|
32
32
|
getMachineId
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-DUZVXBBU.js";
|
|
34
34
|
import {
|
|
35
35
|
reportedInstallSource
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-FQ2GORVG.js";
|
|
37
37
|
import {
|
|
38
38
|
canonicalJson
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-ZBHUHJG6.js";
|
|
40
40
|
import {
|
|
41
41
|
writeFileAtomic
|
|
42
42
|
} from "./chunk-T7E75EKA.js";
|
|
43
43
|
import {
|
|
44
44
|
getApiKey,
|
|
45
45
|
getBaseUrl
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-5QUPKDI5.js";
|
|
47
47
|
import {
|
|
48
48
|
ACTION_BODY_MAX,
|
|
49
49
|
AGENT_LABELS_BY_TYPE,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
resolvePolicy,
|
|
71
71
|
toToolLookup,
|
|
72
72
|
truncateLine
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-I5IJRMNV.js";
|
|
74
74
|
|
|
75
75
|
// src/policy.ts
|
|
76
76
|
import { createHash } from "crypto";
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./chunk-XHKBHWLX.js";
|
|
5
5
|
import {
|
|
6
6
|
readControlMode
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-N4QSPI3B.js";
|
|
8
8
|
import {
|
|
9
9
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DUZVXBBU.js";
|
|
11
11
|
import {
|
|
12
12
|
pusharyDir,
|
|
13
13
|
resolveGlobalBinary
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZBHUHJG6.js";
|
|
15
15
|
import {
|
|
16
16
|
readJsonSafe,
|
|
17
17
|
writeFileAtomic,
|
|
@@ -20,14 +20,14 @@ import {
|
|
|
20
20
|
} from "./chunk-T7E75EKA.js";
|
|
21
21
|
import {
|
|
22
22
|
getApiKey
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-5QUPKDI5.js";
|
|
24
24
|
import {
|
|
25
25
|
CLI_PACKAGE_NAMES,
|
|
26
26
|
cmdShimTarget,
|
|
27
27
|
getPackageVersion,
|
|
28
28
|
globalPackageFolder,
|
|
29
29
|
globalRootFor
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-I5IJRMNV.js";
|
|
31
31
|
|
|
32
32
|
// src/daemon-lifecycle.ts
|
|
33
33
|
import { dirname, join, win32 as win32Path } from "path";
|
|
@@ -38,7 +38,8 @@ import { execFileSync } from "child_process";
|
|
|
38
38
|
var daemonNeedsHandoff = (status) => status.kind === "version-mismatch" || status.kind === "configuration-mismatch" || status.kind === "unresponsive" && status.processAlive === true;
|
|
39
39
|
var DAEMON_REMOTE_PROOF_MAX_AGE_MS = 18e4;
|
|
40
40
|
var DAEMON_REMOTE_PROOF_CLOCK_SKEW_MS = 3e4;
|
|
41
|
-
var DAEMON_STARTUP_TIMEOUT_MS =
|
|
41
|
+
var DAEMON_STARTUP_TIMEOUT_MS = 5e3;
|
|
42
|
+
var DAEMON_COLD_START_TIMEOUT_MS = 3e4;
|
|
42
43
|
var remoteProofIsFresh = (timestamp, now) => {
|
|
43
44
|
if (timestamp === null) return false;
|
|
44
45
|
const age = now - Date.parse(timestamp);
|
|
@@ -719,8 +720,9 @@ var stopDaemonRunning = async (options = {}) => {
|
|
|
719
720
|
safeUnlink(lockPath(dir));
|
|
720
721
|
return { kind: "stopped" };
|
|
721
722
|
};
|
|
723
|
+
var DAEMON_LOGIN_REASONS = ["key_rejected", "plan_inactive", "key_missing", "mac_signed_out"];
|
|
722
724
|
var needsLoginPath = (dir) => join(dir, "daemon-needs-login.json");
|
|
723
|
-
var isLoginReason = (value) => value
|
|
725
|
+
var isLoginReason = (value) => DAEMON_LOGIN_REASONS.includes(value);
|
|
724
726
|
var parseDaemonNeedsLogin = (value) => {
|
|
725
727
|
if (typeof value !== "object" || value === null) return null;
|
|
726
728
|
const record = value;
|
|
@@ -750,7 +752,13 @@ var clearDaemonNeedsLogin = (options = {}) => {
|
|
|
750
752
|
safeUnlink(path);
|
|
751
753
|
return true;
|
|
752
754
|
};
|
|
753
|
-
var
|
|
755
|
+
var DAEMON_LOGIN_BLOCK_DESCRIPTIONS = {
|
|
756
|
+
key_rejected: (at) => `this machine's key was rejected at ${at}; run \`pushary login\` to sign in again`,
|
|
757
|
+
plan_inactive: (at) => `this workspace had no active plan at ${at}; pick one at pushary.com/dashboard/settings?tab=billing, then run \`pushary login\``,
|
|
758
|
+
key_missing: (at) => `this machine had no key at ${at}; run \`pushary login\` to sign in again`,
|
|
759
|
+
mac_signed_out: (at) => `the key this machine shared with the Pushary Mac app was signed out on this Mac at ${at}; run \`pushary login\` to sign in again`
|
|
760
|
+
};
|
|
761
|
+
var describeDaemonLoginBlock = (record) => DAEMON_LOGIN_BLOCK_DESCRIPTIONS[record.reason](record.at);
|
|
754
762
|
var recoverDaemonAfterLogin = (options = {}) => {
|
|
755
763
|
const cleared = clearDaemonNeedsLogin(options);
|
|
756
764
|
if (!cleared || readControlMode(join(options.dir ?? pusharyDir(), "config.json")) === "off" || !hasDaemonServiceDefinition(options)) {
|
|
@@ -1096,7 +1104,7 @@ var ensureDaemonRunning = async (options = {}) => {
|
|
|
1096
1104
|
var waitForDaemonRemoteProof = async (options = {}) => {
|
|
1097
1105
|
const sleep = options.sleep ?? wait;
|
|
1098
1106
|
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
1099
|
-
const attempts = Math.max(1, Math.ceil((options.waitTimeoutMs ??
|
|
1107
|
+
const attempts = Math.max(1, Math.ceil((options.waitTimeoutMs ?? DAEMON_COLD_START_TIMEOUT_MS) / pollIntervalMs));
|
|
1100
1108
|
let status = readDaemonStatus(options);
|
|
1101
1109
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
1102
1110
|
status = readDaemonStatus(options);
|
|
@@ -1107,6 +1115,7 @@ var waitForDaemonRemoteProof = async (options = {}) => {
|
|
|
1107
1115
|
};
|
|
1108
1116
|
|
|
1109
1117
|
export {
|
|
1118
|
+
DAEMON_COLD_START_TIMEOUT_MS,
|
|
1110
1119
|
daemonHasRemoteProof,
|
|
1111
1120
|
daemonServiceManagerAvailable,
|
|
1112
1121
|
DAEMON_LEASE_RENEW_INTERVAL_MS,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pusharyFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TCQ43LSG.js";
|
|
4
4
|
import {
|
|
5
5
|
NetworkError
|
|
6
6
|
} from "./chunk-7QLSKOSU.js";
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
} from "./chunk-KZERVKTD.js";
|
|
10
10
|
import {
|
|
11
11
|
getBaseUrl
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5QUPKDI5.js";
|
|
13
13
|
import {
|
|
14
14
|
isValidApiKey,
|
|
15
15
|
normalizeKeyScope
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-I5IJRMNV.js";
|
|
17
17
|
|
|
18
18
|
// src/session.ts
|
|
19
19
|
var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
|
|
@@ -167,6 +167,7 @@ var describeKeyCheck = (check, baseUrl = getBaseUrl()) => {
|
|
|
167
167
|
|
|
168
168
|
export {
|
|
169
169
|
samePusharyAccount,
|
|
170
|
+
absoluteUrl,
|
|
170
171
|
checkApiKey,
|
|
171
172
|
keyCheckFromResponse,
|
|
172
173
|
describeKeyCheck
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
guardedArgv
|
|
3
|
+
} from "./chunk-ZBHUHJG6.js";
|
|
1
4
|
import {
|
|
2
5
|
HOOK_BUDGETS,
|
|
3
6
|
OPENCODE_APPROVAL_EVENT
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-I5IJRMNV.js";
|
|
5
8
|
|
|
6
9
|
// src/opencode-plugin.ts
|
|
7
10
|
var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
|
|
@@ -298,6 +301,19 @@ var openCodePluginModule = () => ({
|
|
|
298
301
|
}
|
|
299
302
|
});
|
|
300
303
|
var renderOpenCodePlugin = (module, argv) => module.source.replace(module.placeholder, JSON.stringify(argv));
|
|
304
|
+
var COMMAND_LINE = /^const COMMAND = (.*)$/m;
|
|
305
|
+
var isArgv = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
306
|
+
var openCodePluginArgv = (contents) => {
|
|
307
|
+
if (!isOpenCodePluginOurs(contents)) return null;
|
|
308
|
+
const line = contents.match(COMMAND_LINE)?.[1];
|
|
309
|
+
if (line === void 0) return null;
|
|
310
|
+
try {
|
|
311
|
+
const parsed = JSON.parse(line);
|
|
312
|
+
return isArgv(parsed) ? parsed : null;
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
};
|
|
301
317
|
var isOpenCodePluginOurs = (contents) => contents.includes(OPENCODE_PLUGIN_MARKER);
|
|
302
318
|
|
|
303
319
|
// src/opencode-config.ts
|
|
@@ -305,6 +321,8 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync
|
|
|
305
321
|
import { homedir } from "os";
|
|
306
322
|
import { join } from "path";
|
|
307
323
|
var OPENCODE_HOOK_BINARY = "pushary-opencode-hook";
|
|
324
|
+
var OPENCODE_HOOK_ARGS = ["--source", "opencode"];
|
|
325
|
+
var openCodeHookArgv = (resolvedBinary) => guardedArgv({ kind: "binary", path: resolvedBinary ?? OPENCODE_HOOK_BINARY, runtime: "node" }, OPENCODE_HOOK_ARGS);
|
|
308
326
|
var openCodeConfigDirFrom = (home, env = process.env) => env.OPENCODE_CONFIG_DIR?.trim() || join(env.XDG_CONFIG_HOME?.trim() || join(home, ".config"), "opencode");
|
|
309
327
|
var openCodeConfigDir = () => openCodeConfigDirFrom(homedir());
|
|
310
328
|
var OPENCODE_PLUGIN_PATH = `${OPENCODE_PLUGIN_DIR}/${OPENCODE_PLUGIN_FILE}`;
|
|
@@ -361,8 +379,10 @@ export {
|
|
|
361
379
|
OPENCODE_PLUGIN_PLACEHOLDER,
|
|
362
380
|
OPENCODE_PLUGIN_SIBLING,
|
|
363
381
|
OPENCODE_PLUGIN_SIBLING_CONTENTS,
|
|
382
|
+
openCodePluginArgv,
|
|
364
383
|
isOpenCodePluginOurs,
|
|
365
384
|
OPENCODE_HOOK_BINARY,
|
|
385
|
+
openCodeHookArgv,
|
|
366
386
|
openCodeConfigDirFrom,
|
|
367
387
|
openCodeConfigDir,
|
|
368
388
|
openCodePluginDir,
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
codexHooksJsonIn,
|
|
9
9
|
isPusharyCodexCommand,
|
|
10
10
|
resolvePathBinary
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZBHUHJG6.js";
|
|
12
12
|
import {
|
|
13
13
|
getPackageVersion
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-I5IJRMNV.js";
|
|
15
15
|
|
|
16
16
|
// src/codex-app-server.ts
|
|
17
17
|
import { existsSync, realpathSync } from "fs";
|
|
@@ -327,6 +327,7 @@ var readCodexTrustForPusharyHooks = async (options = {}) => {
|
|
|
327
327
|
};
|
|
328
328
|
|
|
329
329
|
export {
|
|
330
|
+
CODEX_HOOK_STATUS,
|
|
330
331
|
assessCodexHookTrust,
|
|
331
332
|
ensureCodexTrustsPusharyHooks,
|
|
332
333
|
readCodexTrustForPusharyHooks
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
keyCheckFromResponse
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LWOO567I.js";
|
|
4
4
|
import {
|
|
5
5
|
installNetworkDefaults
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TCQ43LSG.js";
|
|
7
7
|
import {
|
|
8
8
|
getBaseUrl
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5QUPKDI5.js";
|
|
10
10
|
|
|
11
11
|
// src/retry.ts
|
|
12
12
|
var isRetryable = (err) => {
|