claude-task-worker 0.25.0 → 0.26.0

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/dist/index.js +95 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1639,10 +1639,86 @@ function isGeneratedWorktreeName(name) {
1639
1639
 
1640
1640
  // src/slack.ts
1641
1641
  import { exec } from "node:child_process";
1642
- import { readFileSync as readFileSync2, writeFileSync } from "node:fs";
1643
- import { homedir } from "node:os";
1644
- import { join as join2 } from "node:path";
1642
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
1643
+ import { homedir as homedir2 } from "node:os";
1644
+ import { join as join3 } from "node:path";
1645
1645
  import { promisify as promisify2 } from "node:util";
1646
+
1647
+ // src/runcat.ts
1648
+ import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
1649
+ import { homedir } from "node:os";
1650
+ import { dirname, join as join2 } from "node:path";
1651
+ var RUNCAT_OUT_FILE = process.env.RUNCAT_OUT_FILE ?? join2(process.env.HOME ?? homedir(), ".claude", "runcat-usage.json");
1652
+ var JST = "Asia/Tokyo";
1653
+ function formatG(value) {
1654
+ return String(Number(value.toPrecision(6)));
1655
+ }
1656
+ function jstFields(date) {
1657
+ const parts = new Intl.DateTimeFormat("en-US", {
1658
+ timeZone: JST,
1659
+ month: "2-digit",
1660
+ day: "2-digit",
1661
+ hour: "2-digit",
1662
+ minute: "2-digit",
1663
+ hourCycle: "h23"
1664
+ }).formatToParts(date);
1665
+ const pick2 = (type) => parts.find((p) => p.type === type)?.value ?? "";
1666
+ return { month: pick2("month"), day: pick2("day"), hour: pick2("hour"), minute: pick2("minute") };
1667
+ }
1668
+ function parseResetsAt(isoString) {
1669
+ const date = new Date(isoString);
1670
+ return Number.isNaN(date.getTime()) ? null : date;
1671
+ }
1672
+ function resetStamp(isoString, now = /* @__PURE__ */ new Date()) {
1673
+ const date = parseResetsAt(isoString);
1674
+ if (!date) return "";
1675
+ const reset = jstFields(date);
1676
+ const today = jstFields(now);
1677
+ const time = `${reset.hour}:${reset.minute}`;
1678
+ if (reset.month === today.month && reset.day === today.day) return time;
1679
+ return `${reset.month}/${reset.day} ${time}`;
1680
+ }
1681
+ function resetHour(isoString) {
1682
+ const date = parseResetsAt(isoString);
1683
+ return date ? jstFields(date).hour : "";
1684
+ }
1685
+ function metric(title, pct, resetsAt, now) {
1686
+ const stamp = resetStamp(resetsAt, now);
1687
+ return {
1688
+ title,
1689
+ formattedValue: `${formatG(pct)}%` + (stamp ? ` \u21BB${stamp}` : ""),
1690
+ normalizedValue: Math.round(pct / 100 * 1e4) / 1e4
1691
+ };
1692
+ }
1693
+ function buildRuncatSnapshot(usage, now = /* @__PURE__ */ new Date()) {
1694
+ const bar = `${formatG(usage.fiveHourUtilization)}/${formatG(usage.sevenDayUtilization)}`;
1695
+ const stamp = resetHour(usage.fiveHourResetsAt);
1696
+ return {
1697
+ title: "Claude Code",
1698
+ symbol: "staroflife",
1699
+ metrics: [
1700
+ metric("5h", usage.fiveHourUtilization, usage.fiveHourResetsAt, now),
1701
+ metric("7d", usage.sevenDayUtilization, usage.sevenDayResetsAt, now)
1702
+ ],
1703
+ metricsBarValue: stamp ? `${bar} \u21BB${stamp}` : bar,
1704
+ lastUpdatedDate: now.toISOString().replace(/\.\d{3}Z$/, "Z")
1705
+ };
1706
+ }
1707
+ function writeRuncatUsage(usage, outFile = RUNCAT_OUT_FILE) {
1708
+ const snapshot = buildRuncatSnapshot(usage);
1709
+ const dir = dirname(outFile);
1710
+ const tmp = join2(dir, `.runcat-${process.pid}-${Date.now()}.json`);
1711
+ try {
1712
+ mkdirSync(dir, { recursive: true });
1713
+ writeFileSync(tmp, JSON.stringify(snapshot), "utf-8");
1714
+ renameSync(tmp, outFile);
1715
+ } catch (err) {
1716
+ rmSync(tmp, { force: true });
1717
+ console.error(`[runcat] Failed to write ${outFile}: ${err}`);
1718
+ }
1719
+ }
1720
+
1721
+ // src/slack.ts
1646
1722
  var execAsync = promisify2(exec);
1647
1723
  var WEBHOOK_URL = process.env.CLAUDE_TASK_WORKER_SLACK_WEBHOOK_URL;
1648
1724
  var USAGE_CACHE_PATH = "/tmp/claude-usage-cache.json";
@@ -1668,7 +1744,7 @@ async function getOAuthToken() {
1668
1744
  const { stdout } = await execAsync('security find-generic-password -s "Claude Code-credentials" -w');
1669
1745
  return extractToken(JSON.parse(stdout.trim()));
1670
1746
  } catch {
1671
- const raw = readFileSync2(join2(homedir(), ".claude", ".credentials.json"), "utf-8");
1747
+ const raw = readFileSync2(join3(homedir2(), ".claude", ".credentials.json"), "utf-8");
1672
1748
  return extractToken(JSON.parse(raw));
1673
1749
  }
1674
1750
  }
@@ -1685,7 +1761,7 @@ function readUsageCache() {
1685
1761
  }
1686
1762
  function writeUsageCache(data) {
1687
1763
  try {
1688
- writeFileSync(USAGE_CACHE_PATH, JSON.stringify({ timestamp: Date.now(), data }));
1764
+ writeFileSync2(USAGE_CACHE_PATH, JSON.stringify({ timestamp: Date.now(), data }));
1689
1765
  } catch {
1690
1766
  }
1691
1767
  }
@@ -1733,9 +1809,7 @@ function formatResetTimeJST(isoString) {
1733
1809
  minute: "2-digit"
1734
1810
  });
1735
1811
  }
1736
- async function buildTokenLimitText() {
1737
- const usage = await fetchUsageInfo();
1738
- if (!usage) return "";
1812
+ function formatTokenLimitText(usage) {
1739
1813
  const fiveH = usage.fiveHourUtilization.toFixed(1);
1740
1814
  const sevenD = usage.sevenDayUtilization.toFixed(1);
1741
1815
  const emoji = utilizationEmoji(Math.max(usage.fiveHourUtilization, usage.sevenDayUtilization));
@@ -1743,6 +1817,12 @@ async function buildTokenLimitText() {
1743
1817
  const sevenDReset = formatResetTimeJST(usage.sevenDayResetsAt);
1744
1818
  return ` | ${emoji} 5h: ${fiveH}% (reset: ${fiveHReset}) / 7d: ${sevenD}% (reset: ${sevenDReset})`;
1745
1819
  }
1820
+ async function buildTokenLimitText() {
1821
+ const usage = await fetchUsageInfo();
1822
+ if (!usage) return "";
1823
+ writeRuncatUsage(usage);
1824
+ return formatTokenLimitText(usage);
1825
+ }
1746
1826
  async function notifyTaskCompleted(workerName, repoName, id, title, url, output) {
1747
1827
  const tokenText = await buildTokenLimitText();
1748
1828
  const truncatedOutput = output && output.length > 1e3 ? `\u2026${output.slice(-1e3)}` : output;
@@ -2602,11 +2682,11 @@ async function update() {
2602
2682
 
2603
2683
  // src/commands/version.ts
2604
2684
  import { readFileSync as readFileSync3 } from "node:fs";
2605
- import { dirname, join as join3 } from "node:path";
2685
+ import { dirname as dirname2, join as join4 } from "node:path";
2606
2686
  import { fileURLToPath } from "node:url";
2607
2687
  function version() {
2608
- const here = dirname(fileURLToPath(import.meta.url));
2609
- const pkgPath = join3(here, "..", "package.json");
2688
+ const here = dirname2(fileURLToPath(import.meta.url));
2689
+ const pkgPath = join4(here, "..", "package.json");
2610
2690
  try {
2611
2691
  const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
2612
2692
  console.log(pkg.version ?? "unknown");
@@ -2661,8 +2741,8 @@ function buildForwardedCommand(argv) {
2661
2741
 
2662
2742
  // src/projects-config.ts
2663
2743
  import { readFileSync as readFileSync4, statSync } from "node:fs";
2664
- import { homedir as homedir2 } from "node:os";
2665
- import { isAbsolute, join as join4 } from "node:path";
2744
+ import { homedir as homedir3 } from "node:os";
2745
+ import { isAbsolute, join as join5 } from "node:path";
2666
2746
  var RESERVED_ALL = "all";
2667
2747
  var ProjectsConfigError = class extends Error {
2668
2748
  constructor(message) {
@@ -2672,8 +2752,8 @@ var ProjectsConfigError = class extends Error {
2672
2752
  };
2673
2753
  function getProjectsConfigPath() {
2674
2754
  const xdg = process.env.XDG_CONFIG_HOME;
2675
- const configHome = xdg && xdg.length > 0 ? xdg : join4(homedir2(), ".config");
2676
- return join4(configHome, "claude-task-worker", "projects.json");
2755
+ const configHome = xdg && xdg.length > 0 ? xdg : join5(homedir3(), ".config");
2756
+ return join5(configHome, "claude-task-worker", "projects.json");
2677
2757
  }
2678
2758
  var PROJECTS_CONFIG_PATH = getProjectsConfigPath();
2679
2759
  function isDirectory(path) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-task-worker",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "CLI tool that polls GitHub Issues/PRs and delegates work to Claude CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",