taskchef 7.22.3 → 7.22.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.22.3",
3
+ "version": "7.22.4",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.22.3",
3
+ "version": "7.22.4",
4
4
  "description": "A non-blocking interactive dispatcher for visible Codex tasks.",
5
5
  "license": "MIT",
6
6
  "author": "Favo Yang",
package/src/usage.js CHANGED
@@ -1,5 +1,12 @@
1
1
  import { execFile as execFileCallback } from "node:child_process";
2
- import { existsSync } from "node:fs";
2
+ import {
3
+ closeSync,
4
+ constants as fsConstants,
5
+ existsSync,
6
+ fchmodSync,
7
+ fstatSync,
8
+ openSync,
9
+ } from "node:fs";
3
10
  import { lstat, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
4
11
  import { createRequire } from "node:module";
5
12
  import path from "node:path";
@@ -356,10 +363,28 @@ export function managedCcusageInvocation({
356
363
  };
357
364
  }
358
365
 
366
+ export function ensureCcusageExecutable(command, {
367
+ platform = process.platform,
368
+ } = {}) {
369
+ if (platform === "win32") return;
370
+ const descriptor = openSync(command, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
371
+ try {
372
+ const file = fstatSync(descriptor);
373
+ if (!file.isFile()) throw new Error("ccusage native binary is not a regular file");
374
+ if ((file.mode & 0o100) === 0) fchmodSync(descriptor, file.mode | 0o100);
375
+ } finally {
376
+ closeSync(descriptor);
377
+ }
378
+ }
379
+
359
380
  async function resolveManagedCcusageInvocation(invocation, run, timeoutMs) {
360
- if (invocation.resolvesNative !== true) return invocation;
381
+ if (invocation.resolvesNative !== true) {
382
+ ensureCcusageExecutable(invocation.command);
383
+ return invocation;
384
+ }
361
385
  if (npxResolvedCcusageInvocation !== null
362
386
  && existsSync(npxResolvedCcusageInvocation.command)) {
387
+ ensureCcusageExecutable(npxResolvedCcusageInvocation.command);
363
388
  return npxResolvedCcusageInvocation;
364
389
  }
365
390
  npxResolvedCcusageInvocation = null;
@@ -374,6 +399,7 @@ async function resolveManagedCcusageInvocation(invocation, run, timeoutMs) {
374
399
  || !existsSync(command)) {
375
400
  throw new Error("npx returned an invalid ccusage executable");
376
401
  }
402
+ ensureCcusageExecutable(command);
377
403
  npxResolvedCcusageInvocation = {
378
404
  command,
379
405
  args: [],
@@ -504,7 +530,9 @@ export async function readCcusageThreadUsage(threadId, {
504
530
  const invocation = command === null
505
531
  ? managedCcusageInvocation()
506
532
  : { command, args: commandArgs, version: null };
507
- const resolvedInvocation = await resolveManagedCcusageInvocation(invocation, run, timeoutMs);
533
+ const resolvedInvocation = command === null
534
+ ? await resolveManagedCcusageInvocation(invocation, run, timeoutMs)
535
+ : invocation;
508
536
  const invoke = (args, options) => run(
509
537
  resolvedInvocation.command,
510
538
  [...resolvedInvocation.args, ...args],