MCPcopy Create free account
hub / github.com/tiann/hapi / isRunnerRunningCurrentlyInstalledHappyVersion

Function isRunnerRunningCurrentlyInstalledHappyVersion

cli/src/runner/controlClient.ts:163–235  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

161 * @returns true if versions match, false if versions differ or no runner running
162 */
163export async function isRunnerRunningCurrentlyInstalledHappyVersion(): Promise<boolean> {
164 logger.debug('[RUNNER CONTROL] Checking if runner is running same version');
165 const runningRunner = await checkIfRunnerRunningAndCleanupStaleState();
166 if (!runningRunner) {
167 logger.debug('[RUNNER CONTROL] No runner running, returning false');
168 return false;
169 }
170
171 const state = await readRunnerState();
172 if (!state) {
173 logger.debug('[RUNNER CONTROL] No runner state found, returning false');
174 return false;
175 }
176
177 const settings = await readSettings();
178 const currentApiUrl = process.env.HAPI_API_URL
179 || settings.apiUrl
180 || settings.serverUrl
181 || configuration.apiUrl;
182 const currentCliApiToken = process.env.CLI_API_TOKEN
183 || settings.cliApiToken
184 || configuration.cliApiToken;
185 const currentMachineId = settings.machineId;
186
187 try {
188 // When HAPI_DISABLE_VERSION_HANDOFF=1 is set on the live runner (operator
189 // owns supervision via systemd/tmux/custom rebuild pipelines), a fresh CLI invocation must NOT
190 // treat the running runner as stale just because source mtimes shifted.
191 // Otherwise `hapi runner start` would kill the live runner mid-rebuild.
192 //
193 // Per Codex review #814 [Major]: the env var is commonly only set on the
194 // supervising service (systemd unit file), NOT on the operator's
195 // interactive shell. To honour the running runner's opt-out from any
196 // caller, OR the live env-var check with the persisted-at-start snapshot
197 // in state.startedWithVersionHandoffDisabled.
198 if (
199 process.env.HAPI_DISABLE_VERSION_HANDOFF === '1'
200 || state.startedWithVersionHandoffDisabled === true
201 ) {
202 logger.debug('[RUNNER CONTROL] Version handoff disabled (env or persisted state), skipping mtime/version drift check');
203 } else {
204 const currentCliMtimeMs = getInstalledCliMtimeMs();
205 if (typeof currentCliMtimeMs === 'number' && typeof state.startedWithCliMtimeMs === 'number') {
206 logger.debug(`[RUNNER CONTROL] Current CLI mtime: ${currentCliMtimeMs}, Runner started with mtime: ${state.startedWithCliMtimeMs}`);
207 if (currentCliMtimeMs !== state.startedWithCliMtimeMs) {
208 return false;
209 }
210 } else {
211 const currentCliVersion = packageJson.version;
212 logger.debug(`[RUNNER CONTROL] Current CLI version: ${currentCliVersion}, Runner started with version: ${state.startedWithCliVersion}`);
213 if (currentCliVersion !== state.startedWithCliVersion) {
214 return false;
215 }
216 }
217 }
218
219 const currentIdentityMatches = isRunnerStateCompatibleWithIdentity(state, {
220 apiUrl: currentApiUrl,

Callers 2

startRunnerFunction · 0.90
claude.tsFile · 0.90

Calls 7

readRunnerStateFunction · 0.90
readSettingsFunction · 0.90
hashRunnerCliApiTokenFunction · 0.90
getInstalledCliMtimeMsFunction · 0.85
debugMethod · 0.80

Tested by

no test coverage detected