claude-task-worker 0.25.0 → 0.26.1
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/index.js +100 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1639,10 +1639,91 @@ 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
|
|
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
|
+
var MINUTE_MS = 6e4;
|
|
1669
|
+
function ceilToMinute(date) {
|
|
1670
|
+
const remainder = date.getTime() % MINUTE_MS;
|
|
1671
|
+
return remainder === 0 ? date : new Date(date.getTime() + (MINUTE_MS - remainder));
|
|
1672
|
+
}
|
|
1673
|
+
function parseResetsAt(isoString) {
|
|
1674
|
+
const date = new Date(isoString);
|
|
1675
|
+
return Number.isNaN(date.getTime()) ? null : ceilToMinute(date);
|
|
1676
|
+
}
|
|
1677
|
+
function resetStamp(isoString, now = /* @__PURE__ */ new Date()) {
|
|
1678
|
+
const date = parseResetsAt(isoString);
|
|
1679
|
+
if (!date) return "";
|
|
1680
|
+
const reset = jstFields(date);
|
|
1681
|
+
const today = jstFields(now);
|
|
1682
|
+
const time = `${reset.hour}:${reset.minute}`;
|
|
1683
|
+
if (reset.month === today.month && reset.day === today.day) return time;
|
|
1684
|
+
return `${reset.month}/${reset.day} ${time}`;
|
|
1685
|
+
}
|
|
1686
|
+
function resetHour(isoString) {
|
|
1687
|
+
const date = parseResetsAt(isoString);
|
|
1688
|
+
return date ? jstFields(date).hour : "";
|
|
1689
|
+
}
|
|
1690
|
+
function metric(title, pct, resetsAt, now) {
|
|
1691
|
+
const stamp = resetStamp(resetsAt, now);
|
|
1692
|
+
return {
|
|
1693
|
+
title,
|
|
1694
|
+
formattedValue: `${formatG(pct)}%` + (stamp ? ` \u21BB${stamp}` : ""),
|
|
1695
|
+
normalizedValue: Math.round(pct / 100 * 1e4) / 1e4
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function buildRuncatSnapshot(usage, now = /* @__PURE__ */ new Date()) {
|
|
1699
|
+
const bar = `${formatG(usage.fiveHourUtilization)}/${formatG(usage.sevenDayUtilization)}`;
|
|
1700
|
+
const stamp = resetHour(usage.fiveHourResetsAt);
|
|
1701
|
+
return {
|
|
1702
|
+
title: "Claude Code",
|
|
1703
|
+
symbol: "staroflife",
|
|
1704
|
+
metrics: [
|
|
1705
|
+
metric("5h", usage.fiveHourUtilization, usage.fiveHourResetsAt, now),
|
|
1706
|
+
metric("7d", usage.sevenDayUtilization, usage.sevenDayResetsAt, now)
|
|
1707
|
+
],
|
|
1708
|
+
metricsBarValue: stamp ? `${bar} \u21BB${stamp}` : bar,
|
|
1709
|
+
lastUpdatedDate: now.toISOString().replace(/\.\d{3}Z$/, "Z")
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
function writeRuncatUsage(usage, outFile = RUNCAT_OUT_FILE) {
|
|
1713
|
+
const snapshot = buildRuncatSnapshot(usage);
|
|
1714
|
+
const dir = dirname(outFile);
|
|
1715
|
+
const tmp = join2(dir, `.runcat-${process.pid}-${Date.now()}.json`);
|
|
1716
|
+
try {
|
|
1717
|
+
mkdirSync(dir, { recursive: true });
|
|
1718
|
+
writeFileSync(tmp, JSON.stringify(snapshot), "utf-8");
|
|
1719
|
+
renameSync(tmp, outFile);
|
|
1720
|
+
} catch (err) {
|
|
1721
|
+
rmSync(tmp, { force: true });
|
|
1722
|
+
console.error(`[runcat] Failed to write ${outFile}: ${err}`);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// src/slack.ts
|
|
1646
1727
|
var execAsync = promisify2(exec);
|
|
1647
1728
|
var WEBHOOK_URL = process.env.CLAUDE_TASK_WORKER_SLACK_WEBHOOK_URL;
|
|
1648
1729
|
var USAGE_CACHE_PATH = "/tmp/claude-usage-cache.json";
|
|
@@ -1668,7 +1749,7 @@ async function getOAuthToken() {
|
|
|
1668
1749
|
const { stdout } = await execAsync('security find-generic-password -s "Claude Code-credentials" -w');
|
|
1669
1750
|
return extractToken(JSON.parse(stdout.trim()));
|
|
1670
1751
|
} catch {
|
|
1671
|
-
const raw = readFileSync2(
|
|
1752
|
+
const raw = readFileSync2(join3(homedir2(), ".claude", ".credentials.json"), "utf-8");
|
|
1672
1753
|
return extractToken(JSON.parse(raw));
|
|
1673
1754
|
}
|
|
1674
1755
|
}
|
|
@@ -1685,7 +1766,7 @@ function readUsageCache() {
|
|
|
1685
1766
|
}
|
|
1686
1767
|
function writeUsageCache(data) {
|
|
1687
1768
|
try {
|
|
1688
|
-
|
|
1769
|
+
writeFileSync2(USAGE_CACHE_PATH, JSON.stringify({ timestamp: Date.now(), data }));
|
|
1689
1770
|
} catch {
|
|
1690
1771
|
}
|
|
1691
1772
|
}
|
|
@@ -1733,9 +1814,7 @@ function formatResetTimeJST(isoString) {
|
|
|
1733
1814
|
minute: "2-digit"
|
|
1734
1815
|
});
|
|
1735
1816
|
}
|
|
1736
|
-
|
|
1737
|
-
const usage = await fetchUsageInfo();
|
|
1738
|
-
if (!usage) return "";
|
|
1817
|
+
function formatTokenLimitText(usage) {
|
|
1739
1818
|
const fiveH = usage.fiveHourUtilization.toFixed(1);
|
|
1740
1819
|
const sevenD = usage.sevenDayUtilization.toFixed(1);
|
|
1741
1820
|
const emoji = utilizationEmoji(Math.max(usage.fiveHourUtilization, usage.sevenDayUtilization));
|
|
@@ -1743,6 +1822,12 @@ async function buildTokenLimitText() {
|
|
|
1743
1822
|
const sevenDReset = formatResetTimeJST(usage.sevenDayResetsAt);
|
|
1744
1823
|
return ` | ${emoji} 5h: ${fiveH}% (reset: ${fiveHReset}) / 7d: ${sevenD}% (reset: ${sevenDReset})`;
|
|
1745
1824
|
}
|
|
1825
|
+
async function buildTokenLimitText() {
|
|
1826
|
+
const usage = await fetchUsageInfo();
|
|
1827
|
+
if (!usage) return "";
|
|
1828
|
+
writeRuncatUsage(usage);
|
|
1829
|
+
return formatTokenLimitText(usage);
|
|
1830
|
+
}
|
|
1746
1831
|
async function notifyTaskCompleted(workerName, repoName, id, title, url, output) {
|
|
1747
1832
|
const tokenText = await buildTokenLimitText();
|
|
1748
1833
|
const truncatedOutput = output && output.length > 1e3 ? `\u2026${output.slice(-1e3)}` : output;
|
|
@@ -2602,11 +2687,11 @@ async function update() {
|
|
|
2602
2687
|
|
|
2603
2688
|
// src/commands/version.ts
|
|
2604
2689
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
2605
|
-
import { dirname, join as
|
|
2690
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
2606
2691
|
import { fileURLToPath } from "node:url";
|
|
2607
2692
|
function version() {
|
|
2608
|
-
const here =
|
|
2609
|
-
const pkgPath =
|
|
2693
|
+
const here = dirname2(fileURLToPath(import.meta.url));
|
|
2694
|
+
const pkgPath = join4(here, "..", "package.json");
|
|
2610
2695
|
try {
|
|
2611
2696
|
const pkg = JSON.parse(readFileSync3(pkgPath, "utf8"));
|
|
2612
2697
|
console.log(pkg.version ?? "unknown");
|
|
@@ -2661,8 +2746,8 @@ function buildForwardedCommand(argv) {
|
|
|
2661
2746
|
|
|
2662
2747
|
// src/projects-config.ts
|
|
2663
2748
|
import { readFileSync as readFileSync4, statSync } from "node:fs";
|
|
2664
|
-
import { homedir as
|
|
2665
|
-
import { isAbsolute, join as
|
|
2749
|
+
import { homedir as homedir3 } from "node:os";
|
|
2750
|
+
import { isAbsolute, join as join5 } from "node:path";
|
|
2666
2751
|
var RESERVED_ALL = "all";
|
|
2667
2752
|
var ProjectsConfigError = class extends Error {
|
|
2668
2753
|
constructor(message) {
|
|
@@ -2672,8 +2757,8 @@ var ProjectsConfigError = class extends Error {
|
|
|
2672
2757
|
};
|
|
2673
2758
|
function getProjectsConfigPath() {
|
|
2674
2759
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
2675
|
-
const configHome = xdg && xdg.length > 0 ? xdg :
|
|
2676
|
-
return
|
|
2760
|
+
const configHome = xdg && xdg.length > 0 ? xdg : join5(homedir3(), ".config");
|
|
2761
|
+
return join5(configHome, "claude-task-worker", "projects.json");
|
|
2677
2762
|
}
|
|
2678
2763
|
var PROJECTS_CONFIG_PATH = getProjectsConfigPath();
|
|
2679
2764
|
function isDirectory(path) {
|