@goodandready/dsh-voice 0.9.23 → 0.9.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/updater.js +8 -52
  2. package/package.json +1 -1
package/lib/updater.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Implements canonical DSH plugin-updater specification.
3
3
 
4
4
  import { spawn } from 'node:child_process';
5
- import { existsSync, readFileSync, unlinkSync, statSync } from 'node:fs';
5
+ import { existsSync, readFileSync, statSync } from 'node:fs';
6
6
  import { readFile } from 'node:fs/promises';
7
7
  import { homedir } from 'node:os';
8
8
  import { basename, dirname, isAbsolute, resolve } from 'node:path';
@@ -196,58 +196,16 @@ export function isProcessAlive(pid) {
196
196
 
197
197
  export function checkProfileLock(profileDir) {
198
198
  const lockPath = resolve(profileDir, 'package.json.lock');
199
- if (!existsSync(lockPath)) return { locked: false };
200
- let initialStat;
201
- try { initialStat = statSync(lockPath); } catch { return { locked: false }; }
202
- const pid = readLockPid(lockPath);
203
- if (pid !== null) {
204
- if (isProcessAlive(pid)) {
205
- return { locked: true, pid };
206
- }
207
- // Stale lock: PID is not running.
208
- // Verify before unlinking: re-check PID and stat to ensure a concurrent live successor
209
- // was not written during the check (#205).
210
- try {
211
- const p1 = readLockPid(lockPath);
212
- if (p1 !== null && isProcessAlive(p1)) return { locked: true, pid: p1 };
213
- const p2 = readLockPid(lockPath);
214
- if (p2 !== null && isProcessAlive(p2)) return { locked: true, pid: p2 };
215
- const p3 = readLockPid(lockPath);
216
- if (p3 !== null && isProcessAlive(p3)) return { locked: true, pid: p3 };
217
- const currentStat = statSync(lockPath);
218
- if (currentStat.mtimeMs !== initialStat.mtimeMs || currentStat.size !== initialStat.size) {
219
- const live = readLockPid(lockPath);
220
- if (live !== null && isProcessAlive(live)) return { locked: true, pid: live };
221
- }
222
- const finalPid = readLockPid(lockPath);
223
- if (finalPid !== null && isProcessAlive(finalPid)) {
224
- return { locked: true, pid: finalPid };
225
- }
226
- if (p1 === pid && p2 === pid && p3 === pid && finalPid === pid) {
227
- unlinkSync(lockPath);
228
- return { locked: false, cleanedStale: true };
229
- }
230
- return { locked: false };
231
- } catch {
232
- if (!existsSync(lockPath)) return { locked: false };
233
- const currentPid = readLockPid(lockPath);
234
- if (currentPid !== null && isProcessAlive(currentPid)) {
235
- return { locked: true, pid: currentPid };
236
- }
237
- return { locked: false };
238
- }
239
- }
240
- // Lockfile without valid PID: check age (> 10 min)
241
199
  try {
242
- const stat = statSync(lockPath);
243
- if (Date.now() - stat.mtimeMs > 10 * 60_000) {
244
- try { unlinkSync(lockPath); } catch {}
245
- return { locked: false, cleanedStale: true };
200
+ statSync(lockPath);
201
+ } catch (err) {
202
+ if (err && err.code === 'ENOENT') {
203
+ return { locked: false };
246
204
  }
247
- return { locked: true, pid: null };
248
- } catch {
249
- return { locked: false };
205
+ return { locked: true, pid: null, error: err?.code || 'EUNKNOWN' };
250
206
  }
207
+ const pid = readLockPid(lockPath);
208
+ return { locked: true, pid };
251
209
  }
252
210
 
253
211
  async function installExact(target, packageSpec, options) {
@@ -282,13 +240,11 @@ async function installExact(target, packageSpec, options) {
282
240
  child.once('error', error => {
283
241
  clearTimeout(timeoutTimer);
284
242
  if (killTimer) clearTimeout(killTimer);
285
- checkProfileLock(target.profileDir);
286
243
  reject(error);
287
244
  });
288
245
  child.once('exit', code => {
289
246
  clearTimeout(timeoutTimer);
290
247
  if (killTimer) clearTimeout(killTimer);
291
- checkProfileLock(target.profileDir);
292
248
  if (timedOut) {
293
249
  reject(new Error('Update timed out; use the normal DSH update flow.'));
294
250
  } else if (code === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-voice",
3
- "version": "0.9.23",
3
+ "version": "0.9.25",
4
4
  "description": "Voice input for DeepSeek Harness: dictation chunked by pauses and voice messages, each with its own provider fallback chain (Deepgram, Groq, HuggingFace, local whisper.cpp, plus any OpenAI-compatible API of your own).",
5
5
  "license": "MIT",
6
6
  "type": "module",