@pushary/agent-hooks 0.89.5 → 0.89.6
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/bin/pushary-claude.js +1 -1
- package/dist/bin/pushary-clean.js +1 -1
- package/dist/bin/pushary-daemon.js +43 -5
- package/dist/bin/pushary-doctor.js +1 -1
- package/dist/bin/pushary-setup.js +39 -9
- package/dist/bin/pushary-upgrade.js +36 -196
- package/dist/chunk-5TASNKRX.js +210 -0
- package/dist/{chunk-TRQ46MXR.js → chunk-NQNCSPEH.js} +6 -3
- package/package.json +1 -1
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
inspectConfiguredManagedProviders
|
|
4
|
+
} from "../chunk-5TASNKRX.js";
|
|
5
|
+
import "../chunk-475T3XIO.js";
|
|
2
6
|
import {
|
|
3
7
|
HEARTBEAT_INTERVAL_MS,
|
|
4
8
|
sendHeartbeat
|
|
5
9
|
} from "../chunk-VP7SDXYG.js";
|
|
10
|
+
import "../chunk-OBI4YMCT.js";
|
|
11
|
+
import "../chunk-7TS2G4QG.js";
|
|
12
|
+
import "../chunk-ATBKJNWS.js";
|
|
13
|
+
import "../chunk-AIGDBRIJ.js";
|
|
6
14
|
import {
|
|
7
15
|
DAEMON_LEASE_RENEW_INTERVAL_MS,
|
|
8
16
|
acquireDaemonLease,
|
|
17
|
+
daemonServiceManagerAvailable,
|
|
9
18
|
ensureDaemonRunning,
|
|
19
|
+
hasDaemonServiceDefinition,
|
|
10
20
|
manageDaemonService,
|
|
11
21
|
parseDaemonAction,
|
|
12
22
|
readDaemonStatus,
|
|
13
23
|
replaceDaemonService,
|
|
14
24
|
requestDaemonHandoff,
|
|
15
25
|
stopDaemonRunning
|
|
16
|
-
} from "../chunk-
|
|
26
|
+
} from "../chunk-NQNCSPEH.js";
|
|
17
27
|
import {
|
|
18
28
|
detectProviderLiveCapabilities,
|
|
19
|
-
hasSpawnProvider
|
|
29
|
+
hasSpawnProvider,
|
|
30
|
+
resolveControlPolicy
|
|
20
31
|
} from "../chunk-NKHEHEUM.js";
|
|
21
32
|
import {
|
|
22
33
|
findLiveProcessBySpawnId,
|
|
@@ -32,11 +43,16 @@ import {
|
|
|
32
43
|
getMachineId
|
|
33
44
|
} from "../chunk-2HYPZLYY.js";
|
|
34
45
|
import "../chunk-V37ZXMH3.js";
|
|
46
|
+
import {
|
|
47
|
+
readControlMode
|
|
48
|
+
} from "../chunk-L3YUHEB6.js";
|
|
35
49
|
import {
|
|
36
50
|
exitOnHelpFlag
|
|
37
51
|
} from "../chunk-LURY4WNF.js";
|
|
38
52
|
import "../chunk-3XTFX4CL.js";
|
|
53
|
+
import "../chunk-BC3VCZ3E.js";
|
|
39
54
|
import "../chunk-DINDL2CF.js";
|
|
55
|
+
import "../chunk-OFRNZWC4.js";
|
|
40
56
|
import {
|
|
41
57
|
EXIT
|
|
42
58
|
} from "../chunk-KZERVKTD.js";
|
|
@@ -174,9 +190,12 @@ var normalizeLaunchAgent = (requestedAgent) => {
|
|
|
174
190
|
if (requestedAgent === "codex" || requestedAgent === "gemini") return requestedAgent;
|
|
175
191
|
return null;
|
|
176
192
|
};
|
|
177
|
-
var providerLaunchError = (requestedAgent, binaries) => {
|
|
193
|
+
var providerLaunchError = (requestedAgent, binaries, configuredProviders) => {
|
|
178
194
|
const agent = normalizeLaunchAgent(requestedAgent);
|
|
179
195
|
if (!agent) return `Unsupported agent provider: ${requestedAgent}`;
|
|
196
|
+
if (configuredProviders && !configuredProviders.includes(agent)) {
|
|
197
|
+
return `${agent === "claude" ? "Claude Code" : agent === "codex" ? "Codex" : "Gemini"} is not configured for Pushary on this machine`;
|
|
198
|
+
}
|
|
180
199
|
if (binaries[agent]) return null;
|
|
181
200
|
return agent === "claude" ? "Claude Code is not installed on this machine" : `${agent === "codex" ? "Codex" : "Gemini"} CLI is not installed on this machine`;
|
|
182
201
|
};
|
|
@@ -241,7 +260,8 @@ var runSpawnDaemon = async () => {
|
|
|
241
260
|
const machineId = getMachineId();
|
|
242
261
|
const baseUrl = getBaseUrl();
|
|
243
262
|
const pusharyBin = resolveBinary("pushary") ?? "pushary";
|
|
244
|
-
const
|
|
263
|
+
const configuredProviders = inspectConfiguredManagedProviders();
|
|
264
|
+
const providerCapabilities = detectProviderLiveCapabilities(configuredProviders);
|
|
245
265
|
const siblingEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary.js") : "";
|
|
246
266
|
const codexBridgeEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary-codex-bridge.js") : "pushary-codex-bridge";
|
|
247
267
|
const geminiBridgeEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary-gemini-bridge.js") : "pushary-gemini-bridge";
|
|
@@ -298,7 +318,7 @@ var runSpawnDaemon = async () => {
|
|
|
298
318
|
claude: agent === "claude" ? providerBin ?? null : null,
|
|
299
319
|
codex: agent === "codex" ? providerBin ?? null : null,
|
|
300
320
|
gemini: agent === "gemini" ? providerBin ?? null : null
|
|
301
|
-
});
|
|
321
|
+
}, configuredProviders);
|
|
302
322
|
if (unavailable) return Promise.reject(new Error(unavailable));
|
|
303
323
|
spawnTimestamps.push(Date.now());
|
|
304
324
|
const cwd = directory.cwd;
|
|
@@ -598,6 +618,24 @@ var main = async () => {
|
|
|
598
618
|
`);
|
|
599
619
|
return status.kind === "running" ? EXIT.OK : EXIT.UNREACHABLE;
|
|
600
620
|
}
|
|
621
|
+
if (action === "install" || action === "start" || action === "restart") {
|
|
622
|
+
if (!getApiKey()) {
|
|
623
|
+
process.stderr.write("[pushary] daemon service has no readable API key; re-run setup.\n");
|
|
624
|
+
return EXIT.FAILED;
|
|
625
|
+
}
|
|
626
|
+
const status = readDaemonStatus();
|
|
627
|
+
const controlPolicy = resolveControlPolicy({
|
|
628
|
+
mode: readControlMode() ?? (action === "install" ? "on" : null),
|
|
629
|
+
providerAvailable: hasSpawnProvider(detectProviderLiveCapabilities(inspectConfiguredManagedProviders())),
|
|
630
|
+
managerAvailable: daemonServiceManagerAvailable(),
|
|
631
|
+
servicePresent: status.kind !== "absent" || hasDaemonServiceDefinition()
|
|
632
|
+
});
|
|
633
|
+
if (controlPolicy !== "enabled") {
|
|
634
|
+
process.stderr.write(`[pushary] daemon service is ${controlPolicy}; run setup with --control on to configure phone-start safely.
|
|
635
|
+
`);
|
|
636
|
+
return EXIT.FAILED;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
601
639
|
if (action === "install") {
|
|
602
640
|
const installed = await replaceDaemonService();
|
|
603
641
|
if (installed.kind !== "ok") {
|
|
@@ -55,8 +55,9 @@ import {
|
|
|
55
55
|
ensureDaemonRunning,
|
|
56
56
|
hasDaemonServiceDefinition,
|
|
57
57
|
readDaemonStatus,
|
|
58
|
-
replaceDaemonService
|
|
59
|
-
|
|
58
|
+
replaceDaemonService,
|
|
59
|
+
stopDaemonService
|
|
60
|
+
} from "../chunk-NQNCSPEH.js";
|
|
60
61
|
import {
|
|
61
62
|
detectProviderLiveCapabilities,
|
|
62
63
|
hasSpawnProvider,
|
|
@@ -1934,7 +1935,7 @@ var main = async () => {
|
|
|
1934
1935
|
const failed = [];
|
|
1935
1936
|
const completed = [];
|
|
1936
1937
|
const skipped = [];
|
|
1937
|
-
let
|
|
1938
|
+
let controlLifecycleFailure = null;
|
|
1938
1939
|
if (agents.length === 0) {
|
|
1939
1940
|
console.log(`
|
|
1940
1941
|
${check} API key saved. No agents configured.`);
|
|
@@ -1977,8 +1978,8 @@ var main = async () => {
|
|
|
1977
1978
|
markStep("control:disable");
|
|
1978
1979
|
const disabled = await disableDaemonService();
|
|
1979
1980
|
if (disabled.kind !== "ok") {
|
|
1980
|
-
|
|
1981
|
-
console.log(` ${yellow("!")} Could not fully disable phone-start: ${
|
|
1981
|
+
controlLifecycleFailure = disabled.detail;
|
|
1982
|
+
console.log(` ${yellow("!")} Could not fully disable phone-start: ${controlLifecycleFailure}`);
|
|
1982
1983
|
} else {
|
|
1983
1984
|
console.log(` ${check} Phone-start background service disabled.`);
|
|
1984
1985
|
}
|
|
@@ -2045,7 +2046,7 @@ var main = async () => {
|
|
|
2045
2046
|
keyCheck: "locked",
|
|
2046
2047
|
rc: rc.kind,
|
|
2047
2048
|
control: controlMode,
|
|
2048
|
-
daemon:
|
|
2049
|
+
daemon: controlLifecycleFailure ? "unavailable" : "skipped",
|
|
2049
2050
|
exitCode: report.exitCode
|
|
2050
2051
|
});
|
|
2051
2052
|
await reportSetupOutcome({
|
|
@@ -2074,12 +2075,41 @@ var main = async () => {
|
|
|
2074
2075
|
const providerAvailable = hasSpawnProvider(controlCapabilities);
|
|
2075
2076
|
const managerAvailable = daemonServiceManagerAvailable();
|
|
2076
2077
|
const servicePresent = readDaemonStatus().kind !== "absent" || hasDaemonServiceDefinition();
|
|
2077
|
-
|
|
2078
|
+
let controlPolicy = resolveControlPolicy({
|
|
2078
2079
|
mode: controlMode,
|
|
2079
2080
|
providerAvailable,
|
|
2080
2081
|
managerAvailable,
|
|
2081
2082
|
servicePresent
|
|
2082
2083
|
});
|
|
2084
|
+
if (controlPolicy === "legacy") {
|
|
2085
|
+
let legacyRuntimeFailure = null;
|
|
2086
|
+
try {
|
|
2087
|
+
await installGlobally2();
|
|
2088
|
+
const replaced = await replaceDaemonService();
|
|
2089
|
+
if (replaced.kind !== "ok") throw new Error(replaced.detail);
|
|
2090
|
+
} catch (err) {
|
|
2091
|
+
legacyRuntimeFailure = formatError(err);
|
|
2092
|
+
}
|
|
2093
|
+
let retired = legacyRuntimeFailure !== null;
|
|
2094
|
+
let stopped = retired ? await disableDaemonService() : await stopDaemonService();
|
|
2095
|
+
if (!retired && stopped.kind !== "ok") {
|
|
2096
|
+
legacyRuntimeFailure = stopped.detail;
|
|
2097
|
+
retired = true;
|
|
2098
|
+
stopped = await disableDaemonService();
|
|
2099
|
+
}
|
|
2100
|
+
if (stopped.kind !== "ok") {
|
|
2101
|
+
controlLifecycleFailure = [legacyRuntimeFailure, stopped.detail].filter(Boolean).join("; ");
|
|
2102
|
+
console.log(` ${yellow("!")} Could not make the legacy phone-start service safe: ${controlLifecycleFailure}`);
|
|
2103
|
+
} else if (retired) {
|
|
2104
|
+
controlPolicy = resolveControlPolicy({
|
|
2105
|
+
mode: controlMode,
|
|
2106
|
+
providerAvailable,
|
|
2107
|
+
managerAvailable,
|
|
2108
|
+
servicePresent: false
|
|
2109
|
+
});
|
|
2110
|
+
console.log(` ${yellow("!")} Retired the legacy phone-start service because it could not be safely repinned: ${legacyRuntimeFailure}`);
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2083
2113
|
if (controlMode === "on" && controlPolicy !== "enabled") {
|
|
2084
2114
|
console.log(` ${yellow("!")} Phone-start was required, but this machine has no supported provider or native background-service manager.`);
|
|
2085
2115
|
} else if (controlPolicy === "legacy") {
|
|
@@ -2102,7 +2132,7 @@ var main = async () => {
|
|
|
2102
2132
|
failed,
|
|
2103
2133
|
reachChecked,
|
|
2104
2134
|
reachesYou,
|
|
2105
|
-
daemonReady:
|
|
2135
|
+
daemonReady: controlLifecycleFailure ? false : daemon === null ? null : daemon.kind === "running" || daemon.kind === "started",
|
|
2106
2136
|
// null when the check did not run, so it changes nothing. Only an outright
|
|
2107
2137
|
// `false` is allowed to hold back "Setup complete.".
|
|
2108
2138
|
roundTripAnswered: roundTrip === null ? null : roundTrip.kind === "answered" ? true : roundTrip.kind === "unanswered" ? false : null
|
|
@@ -2147,7 +2177,7 @@ var main = async () => {
|
|
|
2147
2177
|
roundTrip: roundTrip === null ? "skipped" : roundTrip.kind,
|
|
2148
2178
|
rc: rc.kind,
|
|
2149
2179
|
rcPath: rc.path,
|
|
2150
|
-
daemon:
|
|
2180
|
+
daemon: controlLifecycleFailure ? "unavailable" : daemon?.kind ?? "skipped",
|
|
2151
2181
|
control: controlMode,
|
|
2152
2182
|
controlPolicy,
|
|
2153
2183
|
controlCapabilities,
|
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
addGeminiHooks,
|
|
9
|
-
addGeminiMcpServer,
|
|
10
|
-
addPusharyHooks,
|
|
11
|
-
addPusharyToolPermissions,
|
|
12
|
-
hasGeminiHooks
|
|
13
|
-
} from "../chunk-7TS2G4QG.js";
|
|
3
|
+
reapplyAllAgents
|
|
4
|
+
} from "../chunk-5TASNKRX.js";
|
|
5
|
+
import "../chunk-475T3XIO.js";
|
|
6
|
+
import "../chunk-OBI4YMCT.js";
|
|
7
|
+
import "../chunk-7TS2G4QG.js";
|
|
14
8
|
import "../chunk-ATBKJNWS.js";
|
|
15
|
-
import
|
|
16
|
-
guardBinary
|
|
17
|
-
} from "../chunk-AIGDBRIJ.js";
|
|
9
|
+
import "../chunk-AIGDBRIJ.js";
|
|
18
10
|
import {
|
|
19
11
|
daemonServiceManagerAvailable,
|
|
20
12
|
disableDaemonService,
|
|
21
13
|
ensureDaemonRunning,
|
|
22
14
|
hasDaemonServiceDefinition,
|
|
23
15
|
readDaemonStatus,
|
|
24
|
-
replaceDaemonService
|
|
25
|
-
|
|
16
|
+
replaceDaemonService,
|
|
17
|
+
stopDaemonService
|
|
18
|
+
} from "../chunk-NQNCSPEH.js";
|
|
26
19
|
import {
|
|
27
20
|
detectProviderLiveCapabilities,
|
|
28
21
|
hasSpawnProvider,
|
|
@@ -34,24 +27,15 @@ import {
|
|
|
34
27
|
import {
|
|
35
28
|
execNpm,
|
|
36
29
|
npmErrorMessage,
|
|
37
|
-
resolveGlobalBinDir,
|
|
38
30
|
resolveGlobalBinary
|
|
39
31
|
} from "../chunk-PZA7G4CN.js";
|
|
40
32
|
import "../chunk-2HYPZLYY.js";
|
|
41
33
|
import {
|
|
42
|
-
CODEX_HOOK_BINARY,
|
|
43
|
-
addCodexHookTrust,
|
|
44
|
-
addCodexHooks,
|
|
45
|
-
addCodexMcpServer,
|
|
46
34
|
claudeJson,
|
|
47
35
|
codexConfigToml,
|
|
48
|
-
codexHookPositions,
|
|
49
|
-
codexHooksJson,
|
|
50
36
|
cursorPluginDir,
|
|
51
37
|
geminiSettings,
|
|
52
|
-
|
|
53
|
-
vscodePluginDir,
|
|
54
|
-
vscodePluginMcp
|
|
38
|
+
vscodePluginDir
|
|
55
39
|
} from "../chunk-V37ZXMH3.js";
|
|
56
40
|
import {
|
|
57
41
|
readControlMode
|
|
@@ -66,202 +50,49 @@ import {
|
|
|
66
50
|
} from "../chunk-DINDL2CF.js";
|
|
67
51
|
import "../chunk-OFRNZWC4.js";
|
|
68
52
|
import "../chunk-KZERVKTD.js";
|
|
69
|
-
import
|
|
70
|
-
readJsonSafe
|
|
71
|
-
} from "../chunk-6MTNS63X.js";
|
|
53
|
+
import "../chunk-6MTNS63X.js";
|
|
72
54
|
import {
|
|
73
55
|
getApiKey
|
|
74
56
|
} from "../chunk-2UMNXADU.js";
|
|
75
57
|
import "../chunk-L4C2JXJS.js";
|
|
76
58
|
|
|
77
59
|
// bin/pushary-upgrade.ts
|
|
78
|
-
import { existsSync
|
|
79
|
-
import { homedir as homedir2 } from "os";
|
|
80
|
-
import { join as join2 } from "path";
|
|
81
|
-
import { execFileSync } from "child_process";
|
|
82
|
-
|
|
83
|
-
// src/reapply.ts
|
|
84
|
-
import { join, dirname } from "path";
|
|
60
|
+
import { existsSync } from "fs";
|
|
85
61
|
import { homedir } from "os";
|
|
86
|
-
import {
|
|
87
|
-
import {
|
|
88
|
-
var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
|
|
89
|
-
var CLAUDE_JSON = join(homedir(), ".claude.json");
|
|
90
|
-
var readJson = (filePath) => {
|
|
91
|
-
const result = readJsonSafe(filePath);
|
|
92
|
-
if (result.kind === "ok") return result.value;
|
|
93
|
-
if (result.kind === "missing") return {};
|
|
94
|
-
return null;
|
|
95
|
-
};
|
|
96
|
-
var writeJson = (filePath, data) => {
|
|
97
|
-
const dir = dirname(filePath);
|
|
98
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
99
|
-
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
100
|
-
};
|
|
101
|
-
var hasPusharyClaudeHooks = (settings) => JSON.stringify(settings.hooks ?? {}).includes("pushary-hook");
|
|
102
|
-
var hasPusharyMcp = (claudeJson2) => !!claudeJson2.mcpServers?.pushary;
|
|
103
|
-
var reapplyClaudeSettings = (apiKey, paths = {}) => {
|
|
104
|
-
const settingsPath = paths.settingsPath ?? CLAUDE_SETTINGS;
|
|
105
|
-
const claudeJsonPath = paths.claudeJsonPath ?? CLAUDE_JSON;
|
|
106
|
-
const settings = readJson(settingsPath);
|
|
107
|
-
const claudeJson2 = readJson(claudeJsonPath);
|
|
108
|
-
const configured = settings != null && hasPusharyClaudeHooks(settings) || claudeJson2 != null && hasPusharyMcp(claudeJson2);
|
|
109
|
-
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
110
|
-
const settingsWritable = settings != null;
|
|
111
|
-
const claudeJsonWritable = claudeJson2 != null;
|
|
112
|
-
let hooks = false;
|
|
113
|
-
let mcp = false;
|
|
114
|
-
try {
|
|
115
|
-
if (!settingsWritable) throw new Error("settings.json could not be parsed");
|
|
116
|
-
const s = settings;
|
|
117
|
-
addPusharyToolPermissions(s);
|
|
118
|
-
addPusharyHooks(s, resolveGlobalBinDir("pushary-hook"), detectClaudeVersion());
|
|
119
|
-
writeJson(settingsPath, s);
|
|
120
|
-
hooks = true;
|
|
121
|
-
} catch {
|
|
122
|
-
}
|
|
123
|
-
if (apiKey) {
|
|
124
|
-
try {
|
|
125
|
-
if (!claudeJsonWritable) throw new Error(".claude.json could not be parsed");
|
|
126
|
-
const cj = claudeJson2;
|
|
127
|
-
addClaudeMcpServer(cj, apiKey);
|
|
128
|
-
writeJson(claudeJsonPath, cj);
|
|
129
|
-
mcp = true;
|
|
130
|
-
} catch {
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
134
|
-
};
|
|
135
|
-
var readToml = (filePath) => {
|
|
136
|
-
try {
|
|
137
|
-
const raw = readFileSync(filePath, "utf-8");
|
|
138
|
-
return raw.trim() === "" ? {} : parseTOML(raw);
|
|
139
|
-
} catch {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
var reapplyCodexSettings = (apiKey, paths = {}) => {
|
|
144
|
-
const configPath = paths.configPath ?? codexConfigToml();
|
|
145
|
-
const hooksPath = paths.hooksPath ?? codexHooksJson();
|
|
146
|
-
const config = readToml(configPath);
|
|
147
|
-
const hooksConfig = readJson(hooksPath);
|
|
148
|
-
const configured = config != null && !!config.mcp_servers?.pushary || hooksConfig != null && hasCodexHooks(hooksConfig);
|
|
149
|
-
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
150
|
-
const command = guardBinary(resolveGlobalBinary(CODEX_HOOK_BINARY) ?? CODEX_HOOK_BINARY);
|
|
151
|
-
let hooks = false;
|
|
152
|
-
let mcp = false;
|
|
153
|
-
if (hooksConfig != null) {
|
|
154
|
-
try {
|
|
155
|
-
addCodexHooks(hooksConfig, command);
|
|
156
|
-
writeJson(hooksPath, hooksConfig);
|
|
157
|
-
hooks = true;
|
|
158
|
-
} catch {
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (config != null) {
|
|
162
|
-
try {
|
|
163
|
-
if (hooks) addCodexHookTrust(config, hooksPath, command, codexHookPositions(hooksConfig ?? void 0));
|
|
164
|
-
if (apiKey) {
|
|
165
|
-
addCodexMcpServer(config, apiKey);
|
|
166
|
-
mcp = true;
|
|
167
|
-
}
|
|
168
|
-
if (hooks || apiKey) writeFileSync(configPath, stringifyTOML(config), "utf-8");
|
|
169
|
-
} catch {
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
173
|
-
};
|
|
174
|
-
var reapplyGeminiSettings = (apiKey, paths = {}) => {
|
|
175
|
-
const settingsPath = paths.settingsPath ?? join(homedir(), ".gemini", "settings.json");
|
|
176
|
-
const settings = readJson(settingsPath);
|
|
177
|
-
if (settings == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
178
|
-
const configured = hasGeminiHooks(settings) || !!settings.mcpServers?.pushary;
|
|
179
|
-
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
180
|
-
let hooks = false;
|
|
181
|
-
let mcp = false;
|
|
182
|
-
try {
|
|
183
|
-
addGeminiHooks(settings, guardBinary(resolveGlobalBinary(GEMINI_HOOK_BINARY) ?? GEMINI_HOOK_BINARY));
|
|
184
|
-
hooks = true;
|
|
185
|
-
if (apiKey) {
|
|
186
|
-
addGeminiMcpServer(settings, apiKey);
|
|
187
|
-
mcp = true;
|
|
188
|
-
}
|
|
189
|
-
writeJson(settingsPath, settings);
|
|
190
|
-
} catch {
|
|
191
|
-
}
|
|
192
|
-
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
193
|
-
};
|
|
194
|
-
var reapplyPluginMcp = (mcpPath, apiKey) => {
|
|
195
|
-
const mcpConfig = readJson(mcpPath);
|
|
196
|
-
if (mcpConfig == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
197
|
-
const servers = mcpConfig.mcpServers;
|
|
198
|
-
if (!servers?.pushary) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
199
|
-
if (!apiKey) return { configured: true, reapplied: false, hooks: false, mcp: false };
|
|
200
|
-
try {
|
|
201
|
-
addClaudeMcpServer(mcpConfig, apiKey);
|
|
202
|
-
writeJson(mcpPath, mcpConfig);
|
|
203
|
-
return { configured: true, reapplied: true, hooks: false, mcp: true };
|
|
204
|
-
} catch {
|
|
205
|
-
return { configured: true, reapplied: false, hooks: false, mcp: false };
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
var reapplyCursorPlugin = (apiKey, paths = {}) => reapplyPluginMcp(
|
|
209
|
-
paths.pluginMcpPath ?? join(homedir(), ".cursor", "plugins", "local", "pushary", "mcp.json"),
|
|
210
|
-
apiKey
|
|
211
|
-
);
|
|
212
|
-
var reapplyVsCodePlugin = (apiKey, paths = {}) => reapplyPluginMcp(paths.pluginMcpPath ?? vscodePluginMcp(), apiKey);
|
|
213
|
-
var reapplyAllAgents = (apiKey) => {
|
|
214
|
-
const runners = [
|
|
215
|
-
{ id: "claude", label: "Claude Code", run: () => reapplyClaudeSettings(apiKey) },
|
|
216
|
-
{ id: "codex", label: "Codex", run: () => reapplyCodexSettings(apiKey) },
|
|
217
|
-
{ id: "gemini", label: "Gemini CLI", run: () => reapplyGeminiSettings(apiKey) },
|
|
218
|
-
{ id: "cursor", label: "Cursor", run: () => reapplyCursorPlugin(apiKey) },
|
|
219
|
-
{ id: "vscode", label: "VS Code", run: () => reapplyVsCodePlugin(apiKey) }
|
|
220
|
-
];
|
|
221
|
-
const done = [];
|
|
222
|
-
for (const runner of runners) {
|
|
223
|
-
try {
|
|
224
|
-
const result = runner.run();
|
|
225
|
-
if (result.configured) done.push({ id: runner.id, label: runner.label, result });
|
|
226
|
-
} catch {
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return done;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
// bin/pushary-upgrade.ts
|
|
62
|
+
import { join } from "path";
|
|
63
|
+
import { execFileSync } from "child_process";
|
|
233
64
|
exitOnHelpFlag("upgrade");
|
|
234
65
|
var detectInstallModes = () => {
|
|
235
66
|
const candidates = [
|
|
236
67
|
{
|
|
237
68
|
label: "Cursor plugin",
|
|
238
69
|
upgrade: "updates itself through Cursor",
|
|
239
|
-
present:
|
|
70
|
+
present: existsSync(cursorPluginDir())
|
|
240
71
|
},
|
|
241
72
|
{
|
|
242
73
|
label: "VS Code plugin",
|
|
243
74
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents vscode",
|
|
244
|
-
present:
|
|
75
|
+
present: existsSync(vscodePluginDir())
|
|
245
76
|
},
|
|
246
77
|
{
|
|
247
78
|
label: "Codex config",
|
|
248
79
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents codex",
|
|
249
|
-
present:
|
|
80
|
+
present: existsSync(codexConfigToml())
|
|
250
81
|
},
|
|
251
82
|
{
|
|
252
83
|
label: "Claude Code config",
|
|
253
84
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents claude_code",
|
|
254
|
-
present:
|
|
85
|
+
present: existsSync(claudeJson())
|
|
255
86
|
},
|
|
256
87
|
{
|
|
257
88
|
label: "Gemini config",
|
|
258
89
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents gemini_cli",
|
|
259
|
-
present:
|
|
90
|
+
present: existsSync(geminiSettings())
|
|
260
91
|
},
|
|
261
92
|
{
|
|
262
93
|
label: "Hermes plugin (pip)",
|
|
263
94
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents hermes",
|
|
264
|
-
present:
|
|
95
|
+
present: existsSync(join(homedir(), ".hermes"))
|
|
265
96
|
}
|
|
266
97
|
];
|
|
267
98
|
return candidates.filter((candidate) => candidate.present).map(({ label, upgrade }) => ({ label, upgrade }));
|
|
@@ -305,14 +136,23 @@ var finishUpgrade = async () => {
|
|
|
305
136
|
servicePresent: serviceWasPresent
|
|
306
137
|
});
|
|
307
138
|
let daemonReady = true;
|
|
139
|
+
let legacyStopFailure = null;
|
|
308
140
|
if (controlPolicy === "disabled" && serviceWasPresent) {
|
|
309
141
|
daemonReady = (await disableDaemonService()).kind === "ok";
|
|
310
|
-
} else if (
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
142
|
+
} else if (controlPolicy === "legacy") {
|
|
143
|
+
const stopped = await stopDaemonService();
|
|
144
|
+
legacyStopFailure = stopped.kind === "ok" ? null : stopped.detail;
|
|
145
|
+
daemonReady = false;
|
|
146
|
+
} else if (controlPolicy === "enabled") {
|
|
147
|
+
if (!apiKey) {
|
|
148
|
+
daemonReady = false;
|
|
149
|
+
} else {
|
|
150
|
+
const service = await replaceDaemonService();
|
|
151
|
+
const daemon = service.kind === "ok" ? await ensureDaemonRunning({ spawnDaemon: () => {
|
|
152
|
+
} }) : null;
|
|
153
|
+
daemonReady = service.kind === "ok" && (daemon?.kind === "running" || daemon?.kind === "started");
|
|
154
|
+
}
|
|
155
|
+
} else if (controlMode === "on" && controlPolicy === "unsupported") {
|
|
316
156
|
daemonReady = false;
|
|
317
157
|
}
|
|
318
158
|
console.log();
|
|
@@ -331,7 +171,7 @@ var finishUpgrade = async () => {
|
|
|
331
171
|
}
|
|
332
172
|
console.log();
|
|
333
173
|
if (!daemonReady) {
|
|
334
|
-
console.error(controlPolicy === "disabled" ? "Upgrade installed, but the disabled background service could not be fully removed. Re-run setup with --control off." : controlPolicy === "legacy" ?
|
|
174
|
+
console.error(controlPolicy === "disabled" ? "Upgrade installed, but the disabled background service could not be fully removed. Re-run setup with --control off." : controlPolicy === "legacy" ? legacyStopFailure ? `Upgrade installed, but the legacy background service could not be stopped: ${legacyStopFailure}. Run setup with --control off.` : "Upgrade installed and the legacy background service was stopped, but it cannot be safely adopted. Run setup with --control off, or restore its provider and native service manager." : controlPolicy === "enabled" && !apiKey ? "Upgrade installed, but phone-start could not be reconciled because no API key was readable. Re-run setup." : "Upgrade installed, but the background service did not start. Run: pushary daemon install");
|
|
335
175
|
process.exitCode = 1;
|
|
336
176
|
return;
|
|
337
177
|
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectClaudeVersion
|
|
3
|
+
} from "./chunk-475T3XIO.js";
|
|
4
|
+
import {
|
|
5
|
+
claudeWired,
|
|
6
|
+
codexWired,
|
|
7
|
+
geminiWired
|
|
8
|
+
} from "./chunk-OBI4YMCT.js";
|
|
9
|
+
import {
|
|
10
|
+
GEMINI_HOOK_BINARY,
|
|
11
|
+
addClaudeMcpServer,
|
|
12
|
+
addGeminiHooks,
|
|
13
|
+
addGeminiMcpServer,
|
|
14
|
+
addPusharyHooks,
|
|
15
|
+
addPusharyToolPermissions,
|
|
16
|
+
hasGeminiHooks
|
|
17
|
+
} from "./chunk-7TS2G4QG.js";
|
|
18
|
+
import {
|
|
19
|
+
guardBinary
|
|
20
|
+
} from "./chunk-AIGDBRIJ.js";
|
|
21
|
+
import {
|
|
22
|
+
resolveGlobalBinDir,
|
|
23
|
+
resolveGlobalBinary
|
|
24
|
+
} from "./chunk-PZA7G4CN.js";
|
|
25
|
+
import {
|
|
26
|
+
CODEX_HOOK_BINARY,
|
|
27
|
+
addCodexHookTrust,
|
|
28
|
+
addCodexHooks,
|
|
29
|
+
addCodexMcpServer,
|
|
30
|
+
codexConfigToml,
|
|
31
|
+
codexHookPositions,
|
|
32
|
+
codexHooksJson,
|
|
33
|
+
hasCodexHooks,
|
|
34
|
+
vscodePluginMcp
|
|
35
|
+
} from "./chunk-V37ZXMH3.js";
|
|
36
|
+
import {
|
|
37
|
+
readJsonSafe
|
|
38
|
+
} from "./chunk-6MTNS63X.js";
|
|
39
|
+
|
|
40
|
+
// src/reapply.ts
|
|
41
|
+
import { join, dirname } from "path";
|
|
42
|
+
import { homedir } from "os";
|
|
43
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
44
|
+
import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
|
|
45
|
+
var CLAUDE_SETTINGS = join(homedir(), ".claude", "settings.json");
|
|
46
|
+
var CLAUDE_JSON = join(homedir(), ".claude.json");
|
|
47
|
+
var readJson = (filePath) => {
|
|
48
|
+
const result = readJsonSafe(filePath);
|
|
49
|
+
if (result.kind === "ok") return result.value;
|
|
50
|
+
if (result.kind === "missing") return {};
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
var writeJson = (filePath, data) => {
|
|
54
|
+
const dir = dirname(filePath);
|
|
55
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
56
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
57
|
+
};
|
|
58
|
+
var hasPusharyClaudeHooks = (settings) => JSON.stringify(settings.hooks ?? {}).includes("pushary-hook");
|
|
59
|
+
var hasPusharyMcp = (claudeJson) => !!claudeJson.mcpServers?.pushary;
|
|
60
|
+
var reapplyClaudeSettings = (apiKey, paths = {}) => {
|
|
61
|
+
const settingsPath = paths.settingsPath ?? CLAUDE_SETTINGS;
|
|
62
|
+
const claudeJsonPath = paths.claudeJsonPath ?? CLAUDE_JSON;
|
|
63
|
+
const settings = readJson(settingsPath);
|
|
64
|
+
const claudeJson = readJson(claudeJsonPath);
|
|
65
|
+
const configured = settings != null && hasPusharyClaudeHooks(settings) || claudeJson != null && hasPusharyMcp(claudeJson);
|
|
66
|
+
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
67
|
+
const settingsWritable = settings != null;
|
|
68
|
+
const claudeJsonWritable = claudeJson != null;
|
|
69
|
+
let hooks = false;
|
|
70
|
+
let mcp = false;
|
|
71
|
+
try {
|
|
72
|
+
if (!settingsWritable) throw new Error("settings.json could not be parsed");
|
|
73
|
+
const s = settings;
|
|
74
|
+
addPusharyToolPermissions(s);
|
|
75
|
+
addPusharyHooks(s, resolveGlobalBinDir("pushary-hook"), detectClaudeVersion());
|
|
76
|
+
writeJson(settingsPath, s);
|
|
77
|
+
hooks = true;
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
if (apiKey) {
|
|
81
|
+
try {
|
|
82
|
+
if (!claudeJsonWritable) throw new Error(".claude.json could not be parsed");
|
|
83
|
+
const cj = claudeJson;
|
|
84
|
+
addClaudeMcpServer(cj, apiKey);
|
|
85
|
+
writeJson(claudeJsonPath, cj);
|
|
86
|
+
mcp = true;
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
91
|
+
};
|
|
92
|
+
var readToml = (filePath) => {
|
|
93
|
+
try {
|
|
94
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
95
|
+
return raw.trim() === "" ? {} : parseTOML(raw);
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var inspectConfiguredManagedProviders = (paths = {}) => {
|
|
101
|
+
const providers = [];
|
|
102
|
+
const claudeSettings = readJson(paths.claudeSettingsPath ?? CLAUDE_SETTINGS);
|
|
103
|
+
const claudeJson = readJson(paths.claudeJsonPath ?? CLAUDE_JSON);
|
|
104
|
+
if (claudeWired({ claudeJson, settings: claudeSettings, skillExists: false })) {
|
|
105
|
+
providers.push("claude");
|
|
106
|
+
}
|
|
107
|
+
const codexConfig = readToml(paths.codexConfigPath ?? codexConfigToml());
|
|
108
|
+
const codexHooks = readJson(paths.codexHooksPath ?? codexHooksJson());
|
|
109
|
+
if (codexWired({ config: codexConfig, hooks: codexHooks, skillExists: false })) {
|
|
110
|
+
providers.push("codex");
|
|
111
|
+
}
|
|
112
|
+
const gemini = readJson(paths.geminiSettingsPath ?? join(homedir(), ".gemini", "settings.json"));
|
|
113
|
+
if (geminiWired({ settings: gemini })) {
|
|
114
|
+
providers.push("gemini");
|
|
115
|
+
}
|
|
116
|
+
return providers;
|
|
117
|
+
};
|
|
118
|
+
var reapplyCodexSettings = (apiKey, paths = {}) => {
|
|
119
|
+
const configPath = paths.configPath ?? codexConfigToml();
|
|
120
|
+
const hooksPath = paths.hooksPath ?? codexHooksJson();
|
|
121
|
+
const config = readToml(configPath);
|
|
122
|
+
const hooksConfig = readJson(hooksPath);
|
|
123
|
+
const configured = config != null && !!config.mcp_servers?.pushary || hooksConfig != null && hasCodexHooks(hooksConfig);
|
|
124
|
+
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
125
|
+
const command = guardBinary(resolveGlobalBinary(CODEX_HOOK_BINARY) ?? CODEX_HOOK_BINARY);
|
|
126
|
+
let hooks = false;
|
|
127
|
+
let mcp = false;
|
|
128
|
+
if (hooksConfig != null) {
|
|
129
|
+
try {
|
|
130
|
+
addCodexHooks(hooksConfig, command);
|
|
131
|
+
writeJson(hooksPath, hooksConfig);
|
|
132
|
+
hooks = true;
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (config != null) {
|
|
137
|
+
try {
|
|
138
|
+
if (hooks) addCodexHookTrust(config, hooksPath, command, codexHookPositions(hooksConfig ?? void 0));
|
|
139
|
+
if (apiKey) {
|
|
140
|
+
addCodexMcpServer(config, apiKey);
|
|
141
|
+
mcp = true;
|
|
142
|
+
}
|
|
143
|
+
if (hooks || apiKey) writeFileSync(configPath, stringifyTOML(config), "utf-8");
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
148
|
+
};
|
|
149
|
+
var reapplyGeminiSettings = (apiKey, paths = {}) => {
|
|
150
|
+
const settingsPath = paths.settingsPath ?? join(homedir(), ".gemini", "settings.json");
|
|
151
|
+
const settings = readJson(settingsPath);
|
|
152
|
+
if (settings == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
153
|
+
const configured = hasGeminiHooks(settings) || !!settings.mcpServers?.pushary;
|
|
154
|
+
if (!configured) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
155
|
+
let hooks = false;
|
|
156
|
+
let mcp = false;
|
|
157
|
+
try {
|
|
158
|
+
addGeminiHooks(settings, guardBinary(resolveGlobalBinary(GEMINI_HOOK_BINARY) ?? GEMINI_HOOK_BINARY));
|
|
159
|
+
hooks = true;
|
|
160
|
+
if (apiKey) {
|
|
161
|
+
addGeminiMcpServer(settings, apiKey);
|
|
162
|
+
mcp = true;
|
|
163
|
+
}
|
|
164
|
+
writeJson(settingsPath, settings);
|
|
165
|
+
} catch {
|
|
166
|
+
}
|
|
167
|
+
return { configured: true, reapplied: hooks || mcp, hooks, mcp };
|
|
168
|
+
};
|
|
169
|
+
var reapplyPluginMcp = (mcpPath, apiKey) => {
|
|
170
|
+
const mcpConfig = readJson(mcpPath);
|
|
171
|
+
if (mcpConfig == null) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
172
|
+
const servers = mcpConfig.mcpServers;
|
|
173
|
+
if (!servers?.pushary) return { configured: false, reapplied: false, hooks: false, mcp: false };
|
|
174
|
+
if (!apiKey) return { configured: true, reapplied: false, hooks: false, mcp: false };
|
|
175
|
+
try {
|
|
176
|
+
addClaudeMcpServer(mcpConfig, apiKey);
|
|
177
|
+
writeJson(mcpPath, mcpConfig);
|
|
178
|
+
return { configured: true, reapplied: true, hooks: false, mcp: true };
|
|
179
|
+
} catch {
|
|
180
|
+
return { configured: true, reapplied: false, hooks: false, mcp: false };
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
var reapplyCursorPlugin = (apiKey, paths = {}) => reapplyPluginMcp(
|
|
184
|
+
paths.pluginMcpPath ?? join(homedir(), ".cursor", "plugins", "local", "pushary", "mcp.json"),
|
|
185
|
+
apiKey
|
|
186
|
+
);
|
|
187
|
+
var reapplyVsCodePlugin = (apiKey, paths = {}) => reapplyPluginMcp(paths.pluginMcpPath ?? vscodePluginMcp(), apiKey);
|
|
188
|
+
var reapplyAllAgents = (apiKey) => {
|
|
189
|
+
const runners = [
|
|
190
|
+
{ id: "claude", label: "Claude Code", run: () => reapplyClaudeSettings(apiKey) },
|
|
191
|
+
{ id: "codex", label: "Codex", run: () => reapplyCodexSettings(apiKey) },
|
|
192
|
+
{ id: "gemini", label: "Gemini CLI", run: () => reapplyGeminiSettings(apiKey) },
|
|
193
|
+
{ id: "cursor", label: "Cursor", run: () => reapplyCursorPlugin(apiKey) },
|
|
194
|
+
{ id: "vscode", label: "VS Code", run: () => reapplyVsCodePlugin(apiKey) }
|
|
195
|
+
];
|
|
196
|
+
const done = [];
|
|
197
|
+
for (const runner of runners) {
|
|
198
|
+
try {
|
|
199
|
+
const result = runner.run();
|
|
200
|
+
if (result.configured) done.push({ id: runner.id, label: runner.label, result });
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return done;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
inspectConfiguredManagedProviders,
|
|
209
|
+
reapplyAllAgents
|
|
210
|
+
};
|
|
@@ -265,7 +265,7 @@ var parseDaemonAction = (argv) => {
|
|
|
265
265
|
return DAEMON_ACTIONS.has(action) ? action : null;
|
|
266
266
|
};
|
|
267
267
|
var manageDaemonService = (action, options = {}) => {
|
|
268
|
-
const definition = action === "uninstall" ? buildDaemonService({
|
|
268
|
+
const definition = action === "uninstall" || action === "stop" ? buildDaemonService({
|
|
269
269
|
platform: options.platform ?? process.platform,
|
|
270
270
|
homeDir: options.homeDir ?? homedir(),
|
|
271
271
|
stateDir: options.stateDir ?? pusharyDir(),
|
|
@@ -559,12 +559,12 @@ var stopDaemonRunning = async (options = {}) => {
|
|
|
559
559
|
safeUnlink(lockPath(dir));
|
|
560
560
|
return { kind: "stopped" };
|
|
561
561
|
};
|
|
562
|
-
var
|
|
562
|
+
var deactivateDaemonService = async (action, options) => {
|
|
563
563
|
const platform = options.platform ?? process.platform;
|
|
564
564
|
const supported = ["darwin", "linux", "win32"].includes(platform);
|
|
565
565
|
const managerAvailable = supported && daemonServiceManagerAvailable(options);
|
|
566
566
|
const definitionPresent = supported && hasDaemonServiceDefinition(options);
|
|
567
|
-
const service = definitionPresent && !managerAvailable ? { kind: "failed", detail: "Native background-service manager is unavailable" } : managerAvailable ? manageDaemonService(
|
|
567
|
+
const service = definitionPresent && !managerAvailable ? { kind: "failed", detail: "Native background-service manager is unavailable" } : managerAvailable ? manageDaemonService(action, options) : { kind: "ok" };
|
|
568
568
|
const stopped = await stopDaemonRunning(options);
|
|
569
569
|
const failures = [
|
|
570
570
|
service.kind === "ok" ? null : service.detail,
|
|
@@ -572,6 +572,8 @@ var disableDaemonService = async (options = {}) => {
|
|
|
572
572
|
].filter((detail) => detail !== null);
|
|
573
573
|
return failures.length > 0 ? { kind: "failed", detail: failures.join("; ") } : { kind: "ok" };
|
|
574
574
|
};
|
|
575
|
+
var stopDaemonService = async (options = {}) => deactivateDaemonService("stop", options);
|
|
576
|
+
var disableDaemonService = async (options = {}) => deactivateDaemonService("uninstall", options);
|
|
575
577
|
var replaceDaemonService = async (options = {}) => {
|
|
576
578
|
const stopped = await stopDaemonRunning(options);
|
|
577
579
|
return stopped.kind === "unavailable" ? stopped : manageDaemonService("install", options);
|
|
@@ -642,6 +644,7 @@ export {
|
|
|
642
644
|
acquireDaemonLease,
|
|
643
645
|
requestDaemonHandoff,
|
|
644
646
|
stopDaemonRunning,
|
|
647
|
+
stopDaemonService,
|
|
645
648
|
disableDaemonService,
|
|
646
649
|
replaceDaemonService,
|
|
647
650
|
ensureDaemonRunning
|