claude-task-worker 0.137.0 → 0.139.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.
- package/README.md +1 -1
- package/dist/{chunk-R4T3CDMO.js → chunk-74OXBTVA.js} +50 -29
- package/dist/claude-args.d.ts +1 -0
- package/dist/index.js +13 -9
- package/dist/lib.js +1 -1
- package/dist/runcat.d.ts +2 -2
- package/dist/slack.d.ts +20 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ claude-task-worker <command> [--epic <issue-number>]... [--label <label>]... [--
|
|
|
139
139
|
| `install` / `update` | 上記「セットアップ」を参照 |
|
|
140
140
|
| `cloud-setup [--force]` | クラウド VM 側の準備(下記「`--cloud`」を参照) |
|
|
141
141
|
| `list-workers` | プリセットとカスタムの全ワーカーを名前・種別・有効/無効・ロード元で表示(`workerFiles` のロード失敗時は exit 1) |
|
|
142
|
-
| `usage` | Claude API 使用状況(5時間/7日間の利用率とリセット時刻)を表示し、Slack
|
|
142
|
+
| `usage` | Claude API 使用状況(5時間/7日間の利用率とリセット時刻)を表示し、Slack にも通知。以降は360秒(6分)ごとに取得し直して表示・RunCat 用スナップショットを更新し続ける(Ctrl-C で終了。Slack 通知は起動時のみ)。プランによって返らない窓(Ultra の5時間枠など)は省いて表示する |
|
|
143
143
|
| `version` | CLI のバージョンを表示(`--version` / `-v` も可) |
|
|
144
144
|
|
|
145
145
|
### `--epic <issue-number>`
|
|
@@ -1303,6 +1303,9 @@ function buildCloudGitHubAccessInstruction() {
|
|
|
1303
1303
|
function buildCloudToolRestriction() {
|
|
1304
1304
|
return `\u30AF\u30E9\u30A6\u30C9\u5B9F\u884C\u3067\u306F \`--disallowedTools\` \u30D5\u30E9\u30B0\u306B\u3088\u308B\u30C4\u30FC\u30EB\u5236\u9650\u304C\u53CD\u6620\u3055\u308C\u306A\u3044\u305F\u3081\u3001\u4EE5\u4E0B\u306E\u30C4\u30FC\u30EB\u3092\u4F7F\u308F\u306A\u3044\u3053\u3068: ${DISALLOWED_TOOLS.join(", ")}`;
|
|
1305
1305
|
}
|
|
1306
|
+
function buildCloudFinalMessageInstruction() {
|
|
1307
|
+
return "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u6700\u7D42\u30E1\u30C3\u30BB\u30FC\u30B8\uFF08\u30BF\u30FC\u30F3\u3092\u7D42\u3048\u308B\u3068\u304D\u306E\u6700\u5F8C\u306E\u767A\u8A00\uFF09\u306F\u3001\u4F55\u3092\u3057\u305F\u304B\u30FB\u3069\u3053\u3067\u6B62\u307E\u3063\u305F\u304B\u306E\u4E8B\u5B9F\u306E\u5831\u544A\u306B\u3068\u3069\u3081\u308B\u3053\u3068\u3002\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306B\u8FD4\u4FE1\u3059\u308B\u4EBA\u306F\u3044\u306A\u3044\u305F\u3081\u3001\u8AAD\u307F\u624B\u3078\u306E\u4F9D\u983C\u30FB\u8CEA\u554F\u30FB\u5224\u65AD\u306E\u8981\u6C42\uFF08\u300C\u301C\u3092\u5224\u65AD\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u300D\u300C\u301C\u3057\u3066\u304F\u3060\u3055\u3044\u300D\u300C\u301C\u3057\u307E\u3059\u304B\u300D\uFF09\u3067\u7DE0\u3081\u306A\u3044\u3053\u3068\u3002\u4EBA\u306E\u5224\u65AD\u304C\u5FC5\u8981\u306A\u4E8B\u9805\u306F\u3001\u30B9\u30AD\u30EB\u306E\u624B\u9806\u3069\u304A\u308A GitHub \u306E\u30E9\u30D9\u30EB\u3068\u30B3\u30E1\u30F3\u30C8\u3067\u5F15\u304D\u7D99\u304E\u3001\u6700\u7D42\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u306F\u300C`cc-need-human-check` \u3092\u4ED8\u3051\u3066 PR #N \u306B\u7406\u7531\u3092\u30B3\u30E1\u30F3\u30C8\u3057\u305F\u300D\u306E\u3088\u3046\u306B\u3001\u5F15\u304D\u7D99\u3044\u3060\u4E8B\u5B9F\u3060\u3051\u3092\u66F8\u304F\u3053\u3068\u3002";
|
|
1308
|
+
}
|
|
1306
1309
|
function buildCloudPrompt(prompt, model, target, debug = false, startedAt) {
|
|
1307
1310
|
const principles = `\u4EE5\u4E0B\u306F\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u5B9F\u884C\u539F\u5247\u3067\u3042\u308B\u3002\u30AF\u30E9\u30A6\u30C9\u5B9F\u884C\u3067\u306F\u30B7\u30B9\u30C6\u30E0\u30D7\u30ED\u30F3\u30D7\u30C8\u306B\u3088\u308B\u6CE8\u5165\u304C\u53CD\u6620\u3055\u308C\u306A\u3044\u305F\u3081\u3001\u30D7\u30ED\u30F3\u30D7\u30C8\u672C\u6587\u3068\u3057\u3066\u6E21\u3057\u3066\u3044\u308B\u3002
|
|
1308
1311
|
|
|
@@ -1310,7 +1313,9 @@ ${systemPromptFor(model)}
|
|
|
1310
1313
|
|
|
1311
1314
|
${buildCloudToolRestriction()}
|
|
1312
1315
|
|
|
1313
|
-
${buildCloudGitHubAccessInstruction()}
|
|
1316
|
+
${buildCloudGitHubAccessInstruction()}
|
|
1317
|
+
|
|
1318
|
+
${buildCloudFinalMessageInstruction()}`;
|
|
1314
1319
|
const withPrinciples = `${prompt}
|
|
1315
1320
|
|
|
1316
1321
|
${principles}`;
|
|
@@ -2167,6 +2172,7 @@ function ceilToMinute(date) {
|
|
|
2167
2172
|
return remainder === 0 ? date : new Date(date.getTime() + (MINUTE_MS - remainder));
|
|
2168
2173
|
}
|
|
2169
2174
|
function parseResetsAt(isoString) {
|
|
2175
|
+
if (!isoString) return null;
|
|
2170
2176
|
const date = new Date(isoString);
|
|
2171
2177
|
return Number.isNaN(date.getTime()) ? null : ceilToMinute(date);
|
|
2172
2178
|
}
|
|
@@ -2192,15 +2198,17 @@ function metric(title, pct, resetsAt, now) {
|
|
|
2192
2198
|
};
|
|
2193
2199
|
}
|
|
2194
2200
|
function buildRuncatSnapshot(usage, now = /* @__PURE__ */ new Date()) {
|
|
2195
|
-
const
|
|
2196
|
-
|
|
2201
|
+
const windows = [
|
|
2202
|
+
["5h", usage.fiveHourUtilization, usage.fiveHourResetsAt],
|
|
2203
|
+
["7d", usage.sevenDayUtilization, usage.sevenDayResetsAt]
|
|
2204
|
+
];
|
|
2205
|
+
const present = windows.filter((w) => w[1] !== null);
|
|
2206
|
+
const bar = present.map(([, pct]) => formatG(pct)).join("/");
|
|
2207
|
+
const stamp = present.length > 0 ? resetHour(present[0][2]) : "";
|
|
2197
2208
|
return {
|
|
2198
2209
|
title: "Claude Code",
|
|
2199
2210
|
symbol: "staroflife",
|
|
2200
|
-
metrics: [
|
|
2201
|
-
metric("5h", usage.fiveHourUtilization, usage.fiveHourResetsAt, now),
|
|
2202
|
-
metric("7d", usage.sevenDayUtilization, usage.sevenDayResetsAt, now)
|
|
2203
|
-
],
|
|
2211
|
+
metrics: present.map(([title, pct, resetsAt]) => metric(title, pct, resetsAt, now)),
|
|
2204
2212
|
metricsBarValue: stamp ? `${bar} \u21BB${stamp}` : bar,
|
|
2205
2213
|
lastUpdatedDate: now.toISOString().replace(/\.\d{3}Z$/, "Z")
|
|
2206
2214
|
};
|
|
@@ -2214,7 +2222,10 @@ function writeRuncatUsage(usage, outFile = RUNCAT_OUT_FILE) {
|
|
|
2214
2222
|
writeFileSync3(tmp, JSON.stringify(snapshot), "utf-8");
|
|
2215
2223
|
renameSync2(tmp, outFile);
|
|
2216
2224
|
} catch (err) {
|
|
2217
|
-
|
|
2225
|
+
try {
|
|
2226
|
+
rmSync(tmp, { force: true });
|
|
2227
|
+
} catch {
|
|
2228
|
+
}
|
|
2218
2229
|
console.error(`[runcat] Failed to write ${outFile}: ${err}`);
|
|
2219
2230
|
}
|
|
2220
2231
|
}
|
|
@@ -2223,6 +2234,7 @@ function writeRuncatUsage(usage, outFile = RUNCAT_OUT_FILE) {
|
|
|
2223
2234
|
var execAsync = promisify2(exec);
|
|
2224
2235
|
var WEBHOOK_URL = process.env.CLAUDE_TASK_WORKER_SLACK_WEBHOOK_URL;
|
|
2225
2236
|
var USAGE_CACHE_PATH = "/tmp/claude-usage-cache.json";
|
|
2237
|
+
var USAGE_POLL_INTERVAL_SECONDS = 360;
|
|
2226
2238
|
var USAGE_CACHE_TTL_SECONDS = 360;
|
|
2227
2239
|
async function send(payload) {
|
|
2228
2240
|
if (!WEBHOOK_URL) return;
|
|
@@ -2236,6 +2248,14 @@ async function send(payload) {
|
|
|
2236
2248
|
console.error(`[slack] Failed to send notification: ${err}`);
|
|
2237
2249
|
}
|
|
2238
2250
|
}
|
|
2251
|
+
function parseUsageResponse(body) {
|
|
2252
|
+
return {
|
|
2253
|
+
fiveHourUtilization: body.five_hour?.utilization ?? null,
|
|
2254
|
+
fiveHourResetsAt: body.five_hour?.resets_at ?? null,
|
|
2255
|
+
sevenDayUtilization: body.seven_day?.utilization ?? null,
|
|
2256
|
+
sevenDayResetsAt: body.seven_day?.resets_at ?? null
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2239
2259
|
function extractToken(credentials) {
|
|
2240
2260
|
if (typeof credentials === "string") return credentials;
|
|
2241
2261
|
return credentials.claudeAiOauth?.accessToken ?? credentials.oauth_token ?? credentials.access_token ?? "";
|
|
@@ -2266,8 +2286,8 @@ function writeUsageCache(data) {
|
|
|
2266
2286
|
} catch {
|
|
2267
2287
|
}
|
|
2268
2288
|
}
|
|
2269
|
-
async function fetchUsageInfo() {
|
|
2270
|
-
const cached = readUsageCache();
|
|
2289
|
+
async function fetchUsageInfo(fresh) {
|
|
2290
|
+
const cached = fresh ? null : readUsageCache();
|
|
2271
2291
|
if (cached) return cached;
|
|
2272
2292
|
try {
|
|
2273
2293
|
const token = await getOAuthToken();
|
|
@@ -2281,13 +2301,7 @@ async function fetchUsageInfo() {
|
|
|
2281
2301
|
console.error(`[slack] Usage API returned ${res.status}`);
|
|
2282
2302
|
return null;
|
|
2283
2303
|
}
|
|
2284
|
-
const
|
|
2285
|
-
const data = {
|
|
2286
|
-
fiveHourUtilization: body.five_hour.utilization,
|
|
2287
|
-
fiveHourResetsAt: body.five_hour.resets_at,
|
|
2288
|
-
sevenDayUtilization: body.seven_day.utilization,
|
|
2289
|
-
sevenDayResetsAt: body.seven_day.resets_at
|
|
2290
|
-
};
|
|
2304
|
+
const data = parseUsageResponse(await res.json());
|
|
2291
2305
|
writeUsageCache(data);
|
|
2292
2306
|
return data;
|
|
2293
2307
|
} catch (err) {
|
|
@@ -2310,17 +2324,23 @@ function formatResetTimeJST(isoString) {
|
|
|
2310
2324
|
minute: "2-digit"
|
|
2311
2325
|
});
|
|
2312
2326
|
}
|
|
2327
|
+
function formatWindow(label, utilization, resetsAt) {
|
|
2328
|
+
if (utilization === null) return null;
|
|
2329
|
+
const reset = resetsAt ? ` (reset: ${formatResetTimeJST(resetsAt)})` : "";
|
|
2330
|
+
return `${label}: ${utilization.toFixed(1)}%${reset}`;
|
|
2331
|
+
}
|
|
2313
2332
|
function formatTokenLimitText(usage) {
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2333
|
+
const parts = [
|
|
2334
|
+
formatWindow("5h", usage.fiveHourUtilization, usage.fiveHourResetsAt),
|
|
2335
|
+
formatWindow("7d", usage.sevenDayUtilization, usage.sevenDayResetsAt)
|
|
2336
|
+
].filter((p) => p !== null);
|
|
2337
|
+
if (parts.length === 0) return "";
|
|
2338
|
+
const values = [usage.fiveHourUtilization, usage.sevenDayUtilization].filter((v) => v !== null);
|
|
2339
|
+
return ` | ${utilizationEmoji(Math.max(...values))} ${parts.join(" / ")}`;
|
|
2340
|
+
}
|
|
2341
|
+
async function buildTokenLimitText(fresh = false) {
|
|
2342
|
+
const usage = await fetchUsageInfo(fresh);
|
|
2343
|
+
if (!usage) return null;
|
|
2324
2344
|
writeRuncatUsage(usage);
|
|
2325
2345
|
return formatTokenLimitText(usage);
|
|
2326
2346
|
}
|
|
@@ -2348,7 +2368,7 @@ function buildTaskNotificationText(params) {
|
|
|
2348
2368
|
return `${sessionUrlPrefix}${body}`;
|
|
2349
2369
|
}
|
|
2350
2370
|
async function notifyTaskCompleted(workerName, repoName, id, title, url, output, cloud) {
|
|
2351
|
-
const tokenText = await buildTokenLimitText();
|
|
2371
|
+
const tokenText = await buildTokenLimitText() ?? "";
|
|
2352
2372
|
await send({
|
|
2353
2373
|
text: buildTaskNotificationText({
|
|
2354
2374
|
status: "completed",
|
|
@@ -2364,7 +2384,7 @@ async function notifyTaskCompleted(workerName, repoName, id, title, url, output,
|
|
|
2364
2384
|
});
|
|
2365
2385
|
}
|
|
2366
2386
|
async function notifyTaskFailed(workerName, repoName, id, title, url, output, cloud) {
|
|
2367
|
-
const tokenText = await buildTokenLimitText();
|
|
2387
|
+
const tokenText = await buildTokenLimitText() ?? "";
|
|
2368
2388
|
await send({
|
|
2369
2389
|
text: buildTaskNotificationText({
|
|
2370
2390
|
status: "failed",
|
|
@@ -3179,6 +3199,7 @@ export {
|
|
|
3179
3199
|
waitForAllProcesses,
|
|
3180
3200
|
shutdown,
|
|
3181
3201
|
generateWorktreeName,
|
|
3202
|
+
USAGE_POLL_INTERVAL_SECONDS,
|
|
3182
3203
|
send,
|
|
3183
3204
|
buildTokenLimitText,
|
|
3184
3205
|
notifyTaskCompleted,
|
package/dist/claude-args.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export declare function buildCloudWorktreeInstruction(prompt: string): string;
|
|
|
41
41
|
export declare function buildCloudCheckoutInstruction(target: CloudPromptTarget): string;
|
|
42
42
|
export declare function buildCloudGitHubAccessInstruction(): string;
|
|
43
43
|
export declare function buildCloudToolRestriction(): string;
|
|
44
|
+
export declare function buildCloudFinalMessageInstruction(): string;
|
|
44
45
|
export declare function buildCloudPrompt(prompt: string, model: string, target?: CloudPromptTarget, debug?: boolean, startedAt?: Date): string;
|
|
45
46
|
export declare function shellQuote(value: string): string;
|
|
46
47
|
export declare function buildScriptCommand(command: string, args: string[], platform?: string): {
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
INHERIT_CONFIG_KEY,
|
|
8
8
|
LOCAL_CONFIG_PATH,
|
|
9
9
|
SCHEDULED_WORKER_NAMES,
|
|
10
|
+
USAGE_POLL_INTERVAL_SECONDS,
|
|
10
11
|
addAssignee,
|
|
11
12
|
addLabel,
|
|
12
13
|
bodyMentionsIssue,
|
|
@@ -64,7 +65,7 @@ import {
|
|
|
64
65
|
shutdown,
|
|
65
66
|
waitForAllProcesses,
|
|
66
67
|
writeLastRun
|
|
67
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-74OXBTVA.js";
|
|
68
69
|
import {
|
|
69
70
|
UserConfigError,
|
|
70
71
|
assertCloudCompatibleCommand,
|
|
@@ -1822,15 +1823,18 @@ if (hasProjectFilter()) {
|
|
|
1822
1823
|
await cloudSetup({ force: process.argv.slice(3).includes("--force") });
|
|
1823
1824
|
})();
|
|
1824
1825
|
} else if (workerType === "usage") {
|
|
1825
|
-
|
|
1826
|
-
const text = await buildTokenLimitText();
|
|
1827
|
-
if (
|
|
1828
|
-
console.error(
|
|
1829
|
-
|
|
1826
|
+
const pollUsage = async (notify) => {
|
|
1827
|
+
const text = await buildTokenLimitText(true);
|
|
1828
|
+
if (text === null) {
|
|
1829
|
+
console.error(`[usage] ${(/* @__PURE__ */ new Date()).toISOString()} Failed to fetch usage info`);
|
|
1830
|
+
return;
|
|
1830
1831
|
}
|
|
1831
|
-
console.log(
|
|
1832
|
-
await send({ text: `\u{1F4CA} Usage${text}` });
|
|
1833
|
-
}
|
|
1832
|
+
console.log(`[usage] ${(/* @__PURE__ */ new Date()).toISOString()}${text}`);
|
|
1833
|
+
if (notify) await send({ text: `\u{1F4CA} Usage${text}` });
|
|
1834
|
+
};
|
|
1835
|
+
void pollUsage(true);
|
|
1836
|
+
setInterval(() => void pollUsage(false), USAGE_POLL_INTERVAL_SECONDS * 1e3);
|
|
1837
|
+
console.log(`[usage] polling every ${USAGE_POLL_INTERVAL_SECONDS}s (Ctrl-C to stop)`);
|
|
1834
1838
|
} else if (workerType === "list-workers") {
|
|
1835
1839
|
for (const e of PRESET_WORKERS) printWorkerRow(e.definition.name, "preset", "preset");
|
|
1836
1840
|
for (const c of customWorkers) printWorkerRow(c.definition.name, "custom", c.source);
|
package/dist/lib.js
CHANGED
package/dist/runcat.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ export interface RuncatSnapshot {
|
|
|
12
12
|
lastUpdatedDate: string;
|
|
13
13
|
}
|
|
14
14
|
/** 'HH:MM' 形式。日を跨ぐ場合は 'MM/DD HH:MM' として日付も付ける。不正値は空文字。 */
|
|
15
|
-
export declare function resetStamp(isoString: string, now?: Date): string;
|
|
15
|
+
export declare function resetStamp(isoString: string | null, now?: Date): string;
|
|
16
16
|
/** 'HH' のみ。バーのように幅が限られる用途向け。不正値は空文字。 */
|
|
17
|
-
export declare function resetHour(isoString: string): string;
|
|
17
|
+
export declare function resetHour(isoString: string | null): string;
|
|
18
18
|
export declare function buildRuncatSnapshot(usage: UsageInfo, now?: Date): RuncatSnapshot;
|
|
19
19
|
/**
|
|
20
20
|
* RunCat Neo 用のスナップショットを書き出す。
|
package/dist/slack.d.ts
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
/** `usage` コマンドが利用状況をポーリングする間隔 */
|
|
2
|
+
export declare const USAGE_POLL_INTERVAL_SECONDS = 360;
|
|
1
3
|
export declare function send(payload: Record<string, unknown>): Promise<void>;
|
|
2
4
|
export interface UsageInfo {
|
|
3
|
-
fiveHourUtilization: number;
|
|
4
|
-
fiveHourResetsAt: string;
|
|
5
|
-
sevenDayUtilization: number;
|
|
6
|
-
sevenDayResetsAt: string;
|
|
5
|
+
fiveHourUtilization: number | null;
|
|
6
|
+
fiveHourResetsAt: string | null;
|
|
7
|
+
sevenDayUtilization: number | null;
|
|
8
|
+
sevenDayResetsAt: string | null;
|
|
7
9
|
}
|
|
10
|
+
interface UsageWindow {
|
|
11
|
+
utilization?: number | null;
|
|
12
|
+
resets_at?: string | null;
|
|
13
|
+
}
|
|
14
|
+
/** usage API のレスポンスを UsageInfo へ。欠けている窓は null にする(throw しない) */
|
|
15
|
+
export declare function parseUsageResponse(body: {
|
|
16
|
+
five_hour?: UsageWindow | null;
|
|
17
|
+
seven_day?: UsageWindow | null;
|
|
18
|
+
}): UsageInfo;
|
|
19
|
+
/** 返ってきた窓だけを並べる。どちらも無ければ空文字 */
|
|
20
|
+
export declare function formatTokenLimitText(usage: UsageInfo): string;
|
|
8
21
|
/**
|
|
9
22
|
* 現在の利用状況を取得し、RunCat Neo 用スナップショットを更新したうえで通知に添えるテキストを返す。
|
|
10
23
|
* ワーカーの完了/失敗通知はすべてここを通るため、タスクが終わるたびに RunCat 側も最新化される
|
|
11
24
|
* (Slack webhook 未設定でも通知が no-op になるだけで、スナップショットの更新は行われる)。
|
|
25
|
+
* 取得に失敗したときだけ null を返す(どの枠も返らない正常応答は空文字)。
|
|
12
26
|
*/
|
|
13
|
-
export declare function buildTokenLimitText(): Promise<string>;
|
|
27
|
+
export declare function buildTokenLimitText(fresh?: boolean): Promise<string | null>;
|
|
14
28
|
/**
|
|
15
29
|
* 通知本文へ載せる output を末尾1000文字に切り詰める。
|
|
16
30
|
* 案内文(CLOUD_FAILURE_GUIDANCE)は appendCloudFailureGuidance が output の先頭に
|
|
@@ -44,3 +58,4 @@ export declare function notifyTaskFailed(workerName: string, repoName: string, i
|
|
|
44
58
|
sessionId?: string;
|
|
45
59
|
}): Promise<void>;
|
|
46
60
|
export declare function notifyError(workerName: string, repoName: string, error: unknown): Promise<void>;
|
|
61
|
+
export {};
|