claude-task-worker 0.122.0 → 0.124.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/dist/chunk-HFU27QHT.js +579 -0
- package/dist/{chunk-NS334FXZ.js → chunk-XJCZF5SA.js} +70 -382
- package/dist/{dispatcher-JKUMXTJ2.js → dispatcher-CIAW3Z6X.js} +1 -1
- package/dist/gh.d.ts +3 -0
- package/dist/{herdr-runner-33D6C2KI.js → herdr-runner-TNX2W4G6.js} +1 -1
- package/dist/index.js +18 -17
- package/dist/lib.js +6 -5
- package/dist/{table-DWVMNDS3.js → table-OOKBQVW5.js} +7 -1
- package/dist/table.d.ts +7 -0
- package/dist/user-config.d.ts +1 -0
- package/package.json +1 -1
- package/dist/chunk-N42YU3GJ.js +0 -184
|
@@ -1,41 +1,50 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CLOUD_WORKTREE_LABEL,
|
|
3
|
+
DEFAULT_PERMISSION_MODE,
|
|
4
|
+
INHERIT_CONFIG_FLAG,
|
|
3
5
|
TASK_DISPLAY_LIMIT,
|
|
4
6
|
buildLogTableLines,
|
|
5
7
|
buildTaskTableLines,
|
|
8
|
+
findProjectNameByPath,
|
|
9
|
+
getInheritConfigPath,
|
|
10
|
+
getPermissionMode,
|
|
11
|
+
getRunMode,
|
|
12
|
+
hasCloudFlag,
|
|
13
|
+
hasDebugFlag,
|
|
14
|
+
isAdvisorEnabled,
|
|
6
15
|
logLines,
|
|
7
16
|
pushLogLine,
|
|
8
17
|
selectRecentTasks,
|
|
9
18
|
writeScreen
|
|
10
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-HFU27QHT.js";
|
|
11
20
|
|
|
12
21
|
// src/gh.ts
|
|
13
22
|
import { createRequire } from "node:module";
|
|
14
23
|
var childProcess = createRequire(import.meta.url)("node:child_process");
|
|
15
24
|
function execGh(args) {
|
|
16
|
-
return new Promise((
|
|
25
|
+
return new Promise((resolve3, reject) => {
|
|
17
26
|
childProcess.execFile("gh", args, (error, stdout, stderr) => {
|
|
18
27
|
if (error) {
|
|
19
28
|
reject(new Error(`gh ${args.join(" ")} failed: ${stderr || error.message}`));
|
|
20
29
|
return;
|
|
21
30
|
}
|
|
22
|
-
|
|
31
|
+
resolve3(stdout.trim());
|
|
23
32
|
});
|
|
24
33
|
});
|
|
25
34
|
}
|
|
26
35
|
function execGhAllowExit(args, allowedCodes) {
|
|
27
|
-
return new Promise((
|
|
36
|
+
return new Promise((resolve3, reject) => {
|
|
28
37
|
childProcess.execFile("gh", args, (error, stdout, stderr) => {
|
|
29
38
|
if (error) {
|
|
30
39
|
const code = error.code;
|
|
31
40
|
if (typeof code === "number" && allowedCodes.includes(code)) {
|
|
32
|
-
|
|
41
|
+
resolve3(stdout.trim());
|
|
33
42
|
return;
|
|
34
43
|
}
|
|
35
44
|
reject(new Error(`gh ${args.join(" ")} failed: ${stderr || error.message}`));
|
|
36
45
|
return;
|
|
37
46
|
}
|
|
38
|
-
|
|
47
|
+
resolve3(stdout.trim());
|
|
39
48
|
});
|
|
40
49
|
});
|
|
41
50
|
}
|
|
@@ -184,23 +193,37 @@ async function listPrsClosingIssue(issueNumber) {
|
|
|
184
193
|
}
|
|
185
194
|
async function fetchPrRef(owner, name, prNumber) {
|
|
186
195
|
try {
|
|
187
|
-
const parsed = JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]));
|
|
188
196
|
return {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
headRefName: parsed?.head?.ref ?? "",
|
|
192
|
-
baseRefName: parsed?.base?.ref ?? "",
|
|
193
|
-
createdAt: parsed?.created_at ?? "",
|
|
194
|
-
headRepo: parsed?.head?.repo?.full_name ?? "",
|
|
195
|
-
headSha: parsed?.head?.sha ?? "",
|
|
196
|
-
title: parsed?.title ?? "",
|
|
197
|
-
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
197
|
+
...toPrRef(JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]))),
|
|
198
|
+
number: prNumber
|
|
198
199
|
};
|
|
199
200
|
} catch (err) {
|
|
200
201
|
console.error(`[gh] failed to read PR #${prNumber}: ${err}`);
|
|
201
202
|
return null;
|
|
202
203
|
}
|
|
203
204
|
}
|
|
205
|
+
function toPrRef(parsed) {
|
|
206
|
+
return {
|
|
207
|
+
number: Number(parsed?.number),
|
|
208
|
+
state: parsed?.merged_at ? "MERGED" : String(parsed?.state ?? "").toUpperCase(),
|
|
209
|
+
headRefName: parsed?.head?.ref ?? "",
|
|
210
|
+
baseRefName: parsed?.base?.ref ?? "",
|
|
211
|
+
createdAt: parsed?.created_at ?? "",
|
|
212
|
+
headRepo: parsed?.head?.repo?.full_name ?? "",
|
|
213
|
+
headSha: parsed?.head?.sha ?? "",
|
|
214
|
+
title: parsed?.title ?? "",
|
|
215
|
+
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
async function listOpenPrsByBase(base) {
|
|
219
|
+
const { owner, name } = await getRepoInfo();
|
|
220
|
+
const output = await execGh([
|
|
221
|
+
"api",
|
|
222
|
+
`repos/${owner}/${name}/pulls?state=open&base=${encodeURIComponent(base)}&per_page=100`,
|
|
223
|
+
"--paginate"
|
|
224
|
+
]);
|
|
225
|
+
return JSON.parse(output).map(toPrRef);
|
|
226
|
+
}
|
|
204
227
|
async function getPrDetail(prNumber) {
|
|
205
228
|
const { owner, name } = await getRepoInfo();
|
|
206
229
|
return fetchPrRef(owner, name, prNumber);
|
|
@@ -355,7 +378,7 @@ async function withRetry(fn, maxRetries = 5, baseDelayMs = 1e3) {
|
|
|
355
378
|
if (attempt === maxRetries) throw err;
|
|
356
379
|
const delayMs = baseDelayMs * Math.pow(2, attempt - 1);
|
|
357
380
|
console.error(`[gh] Attempt ${attempt}/${maxRetries} failed, retrying in ${delayMs}ms...`);
|
|
358
|
-
await new Promise((
|
|
381
|
+
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
359
382
|
}
|
|
360
383
|
}
|
|
361
384
|
throw new Error("unreachable");
|
|
@@ -454,97 +477,10 @@ async function createLabel(name, color, force) {
|
|
|
454
477
|
}
|
|
455
478
|
}
|
|
456
479
|
|
|
457
|
-
// src/dispatch-args.ts
|
|
458
|
-
import { resolve } from "node:path";
|
|
459
|
-
var FLAG_INCOMPATIBLE_COMMANDS = [
|
|
460
|
-
"init",
|
|
461
|
-
"apply-labels",
|
|
462
|
-
"install",
|
|
463
|
-
"update",
|
|
464
|
-
"cloud-setup",
|
|
465
|
-
"usage",
|
|
466
|
-
"version",
|
|
467
|
-
"list-workers"
|
|
468
|
-
];
|
|
469
|
-
function collectFlagValues(argv, flag) {
|
|
470
|
-
const values = [];
|
|
471
|
-
for (let i = 0; i < argv.length; i++) {
|
|
472
|
-
if (argv[i] !== flag) continue;
|
|
473
|
-
const raw = argv[i + 1];
|
|
474
|
-
if (!raw || raw.startsWith("--")) {
|
|
475
|
-
console.error(`[dispatcher] ${flag} requires a value`);
|
|
476
|
-
process.exit(1);
|
|
477
|
-
}
|
|
478
|
-
values.push(raw);
|
|
479
|
-
}
|
|
480
|
-
return values;
|
|
481
|
-
}
|
|
482
|
-
function parseProjectFilters() {
|
|
483
|
-
return collectFlagValues(process.argv, "--project");
|
|
484
|
-
}
|
|
485
|
-
function hasProjectFilter() {
|
|
486
|
-
return process.argv.includes("--project");
|
|
487
|
-
}
|
|
488
|
-
function assertProjectCompatibleCommand(command) {
|
|
489
|
-
if (FLAG_INCOMPATIBLE_COMMANDS.includes(command)) {
|
|
490
|
-
console.error(`[dispatcher] --project cannot be used with the "${command}" command`);
|
|
491
|
-
process.exit(1);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
var cachedCloudFlag;
|
|
495
|
-
function hasCloudFlag() {
|
|
496
|
-
if (cachedCloudFlag === void 0) {
|
|
497
|
-
cachedCloudFlag = process.argv.includes("--cloud");
|
|
498
|
-
}
|
|
499
|
-
return cachedCloudFlag;
|
|
500
|
-
}
|
|
501
|
-
var cachedDebugFlag;
|
|
502
|
-
function hasDebugFlag() {
|
|
503
|
-
if (cachedDebugFlag === void 0) {
|
|
504
|
-
cachedDebugFlag = process.argv.includes("--debug");
|
|
505
|
-
}
|
|
506
|
-
return cachedDebugFlag;
|
|
507
|
-
}
|
|
508
|
-
var INHERIT_CONFIG_FLAG = "--inherit-config";
|
|
509
|
-
var cachedInheritConfigPath;
|
|
510
|
-
function getInheritConfigPath() {
|
|
511
|
-
if (cachedInheritConfigPath === void 0) {
|
|
512
|
-
const values = collectFlagValues(process.argv, INHERIT_CONFIG_FLAG);
|
|
513
|
-
cachedInheritConfigPath = values.length > 0 ? resolve(values[values.length - 1]) : null;
|
|
514
|
-
}
|
|
515
|
-
return cachedInheritConfigPath;
|
|
516
|
-
}
|
|
517
|
-
function assertCloudCompatibleCommand(command) {
|
|
518
|
-
if (FLAG_INCOMPATIBLE_COMMANDS.includes(command)) {
|
|
519
|
-
console.error(`[worker] --cloud cannot be used with the "${command}" command`);
|
|
520
|
-
process.exit(1);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
function shellQuote(value) {
|
|
524
|
-
if (value === "") return "''";
|
|
525
|
-
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
526
|
-
}
|
|
527
|
-
function buildForwardedCommand(argv) {
|
|
528
|
-
const tokens = [];
|
|
529
|
-
for (let i = 0; i < argv.length; i++) {
|
|
530
|
-
if (argv[i] === "--project") {
|
|
531
|
-
i++;
|
|
532
|
-
continue;
|
|
533
|
-
}
|
|
534
|
-
if (argv[i] === INHERIT_CONFIG_FLAG && i + 1 < argv.length) {
|
|
535
|
-
tokens.push(argv[i], resolve(argv[i + 1]));
|
|
536
|
-
i++;
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
tokens.push(argv[i]);
|
|
540
|
-
}
|
|
541
|
-
return ["claude-task-worker", ...tokens.map(shellQuote)].join(" ");
|
|
542
|
-
}
|
|
543
|
-
|
|
544
480
|
// src/config.ts
|
|
545
481
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
546
482
|
import { homedir } from "node:os";
|
|
547
|
-
import { dirname, isAbsolute, join, normalize, relative, resolve
|
|
483
|
+
import { dirname, isAbsolute, join, normalize, relative, resolve, sep as SEP } from "node:path";
|
|
548
484
|
var DEFAULT_UI_DESIGN_CONFIG = {
|
|
549
485
|
enabled: false,
|
|
550
486
|
designDir: "designs",
|
|
@@ -946,8 +882,8 @@ function parseWorkerFilesEntry(val) {
|
|
|
946
882
|
}
|
|
947
883
|
function resolveWorkerFilePath(entry, configDir, home) {
|
|
948
884
|
if (entry === "~") return home;
|
|
949
|
-
if (entry.startsWith("~/")) return
|
|
950
|
-
return
|
|
885
|
+
if (entry.startsWith("~/")) return resolve(home, entry.slice(2));
|
|
886
|
+
return resolve(configDir, entry);
|
|
951
887
|
}
|
|
952
888
|
function isPlainObject(val) {
|
|
953
889
|
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
@@ -984,13 +920,13 @@ function resolveInheritedRelativePaths(raw, configDir, repoRoot) {
|
|
|
984
920
|
if (isPlainObject(uiDesign) && typeof uiDesign.designDir === "string" && uiDesign.designDir.length > 0) {
|
|
985
921
|
result["uiDesign"] = {
|
|
986
922
|
...uiDesign,
|
|
987
|
-
designDir: relative(repoRoot,
|
|
923
|
+
designDir: relative(repoRoot, resolve(configDir, uiDesign.designDir)) || "."
|
|
988
924
|
};
|
|
989
925
|
}
|
|
990
926
|
const workerFiles = raw["workerFiles"];
|
|
991
927
|
if (Array.isArray(workerFiles)) {
|
|
992
928
|
result["workerFiles"] = workerFiles.map(
|
|
993
|
-
(entry) => typeof entry === "string" && entry.trim().length > 0 && !entry.trim().startsWith("~") ?
|
|
929
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0 && !entry.trim().startsWith("~") ? resolve(configDir, entry.trim()) : entry
|
|
994
930
|
);
|
|
995
931
|
}
|
|
996
932
|
return result;
|
|
@@ -1146,242 +1082,6 @@ function getUiDesignConfig() {
|
|
|
1146
1082
|
}
|
|
1147
1083
|
}
|
|
1148
1084
|
|
|
1149
|
-
// src/user-config.ts
|
|
1150
|
-
import { readFileSync as readFileSync2, statSync } from "node:fs";
|
|
1151
|
-
import { homedir as homedir2 } from "node:os";
|
|
1152
|
-
import { isAbsolute as isAbsolute2, join as join2, resolve as resolve3 } from "node:path";
|
|
1153
|
-
var RESERVED_ALL = "all";
|
|
1154
|
-
var DEFAULT_RUN_MODE = "default";
|
|
1155
|
-
var DEFAULT_ADVISOR_ENABLED = false;
|
|
1156
|
-
var PERMISSION_MODES = [
|
|
1157
|
-
"manual",
|
|
1158
|
-
"auto",
|
|
1159
|
-
"acceptEdits",
|
|
1160
|
-
"dontAsk",
|
|
1161
|
-
"plan",
|
|
1162
|
-
"bypassPermissions"
|
|
1163
|
-
];
|
|
1164
|
-
var DEFAULT_PERMISSION_MODE = "bypassPermissions";
|
|
1165
|
-
var UserConfigError = class extends Error {
|
|
1166
|
-
constructor(message) {
|
|
1167
|
-
super(message);
|
|
1168
|
-
this.name = "UserConfigError";
|
|
1169
|
-
}
|
|
1170
|
-
};
|
|
1171
|
-
function getConfigDir() {
|
|
1172
|
-
const xdg = process.env.XDG_CONFIG_HOME;
|
|
1173
|
-
const configHome = xdg && xdg.length > 0 ? xdg : join2(homedir2(), ".config");
|
|
1174
|
-
return join2(configHome, "claude-task-worker");
|
|
1175
|
-
}
|
|
1176
|
-
function getUserConfigPath() {
|
|
1177
|
-
return join2(getConfigDir(), "config.json");
|
|
1178
|
-
}
|
|
1179
|
-
function isDirectory(path2) {
|
|
1180
|
-
try {
|
|
1181
|
-
return statSync(path2).isDirectory();
|
|
1182
|
-
} catch {
|
|
1183
|
-
return false;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
function parseConfigFile(path2) {
|
|
1187
|
-
let content;
|
|
1188
|
-
try {
|
|
1189
|
-
content = readFileSync2(path2, "utf-8");
|
|
1190
|
-
} catch (err) {
|
|
1191
|
-
if (err.code === "ENOENT") return void 0;
|
|
1192
|
-
throw err;
|
|
1193
|
-
}
|
|
1194
|
-
try {
|
|
1195
|
-
return JSON.parse(content);
|
|
1196
|
-
} catch (err) {
|
|
1197
|
-
if (err instanceof SyntaxError) {
|
|
1198
|
-
throw new UserConfigError(`config file contains invalid JSON: ${path2}: ${err.message}`);
|
|
1199
|
-
}
|
|
1200
|
-
throw err;
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
function readRawConfig2() {
|
|
1204
|
-
return parseConfigFile(getUserConfigPath());
|
|
1205
|
-
}
|
|
1206
|
-
function parseMode(raw, path2) {
|
|
1207
|
-
if (!("mode" in raw)) return DEFAULT_RUN_MODE;
|
|
1208
|
-
const value = raw["mode"];
|
|
1209
|
-
if (value === "default" || value === "herdr") return value;
|
|
1210
|
-
console.warn(`[config] invalid mode: ${JSON.stringify(value)} in ${path2}, using "${DEFAULT_RUN_MODE}"`);
|
|
1211
|
-
return DEFAULT_RUN_MODE;
|
|
1212
|
-
}
|
|
1213
|
-
function parseAdvisor(raw, path2) {
|
|
1214
|
-
if (!("advisor" in raw)) return DEFAULT_ADVISOR_ENABLED;
|
|
1215
|
-
const value = raw["advisor"];
|
|
1216
|
-
if (typeof value === "boolean") return value;
|
|
1217
|
-
console.warn(`[config] invalid advisor: ${JSON.stringify(value)} in ${path2}, using ${DEFAULT_ADVISOR_ENABLED}`);
|
|
1218
|
-
return DEFAULT_ADVISOR_ENABLED;
|
|
1219
|
-
}
|
|
1220
|
-
function parsePermission(raw, path2) {
|
|
1221
|
-
if (!("permission" in raw)) return DEFAULT_PERMISSION_MODE;
|
|
1222
|
-
const value = raw["permission"];
|
|
1223
|
-
if (typeof value === "string" && PERMISSION_MODES.includes(value)) return value;
|
|
1224
|
-
console.warn(`[config] invalid permission: ${JSON.stringify(value)} in ${path2}, using "${DEFAULT_PERMISSION_MODE}"`);
|
|
1225
|
-
return DEFAULT_PERMISSION_MODE;
|
|
1226
|
-
}
|
|
1227
|
-
function loadUserConfig() {
|
|
1228
|
-
const path2 = getUserConfigPath();
|
|
1229
|
-
const raw = readRawConfig2();
|
|
1230
|
-
if (raw === void 0) {
|
|
1231
|
-
throw new UserConfigError(`config.json not found: ${path2}`);
|
|
1232
|
-
}
|
|
1233
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1234
|
-
throw new UserConfigError(`config.json must contain a JSON object: ${path2}`);
|
|
1235
|
-
}
|
|
1236
|
-
if (!("projects" in raw) || typeof raw["projects"] !== "object" || raw["projects"] === null || Array.isArray(raw["projects"])) {
|
|
1237
|
-
throw new UserConfigError(`config.json must contain a "projects" section as an object: ${path2}`);
|
|
1238
|
-
}
|
|
1239
|
-
if ("projectGroups" in raw && (typeof raw["projectGroups"] !== "object" || raw["projectGroups"] === null || Array.isArray(raw["projectGroups"]))) {
|
|
1240
|
-
throw new UserConfigError(`config.json "projectGroups" must be an object: ${path2}`);
|
|
1241
|
-
}
|
|
1242
|
-
const mode = parseMode(raw, path2);
|
|
1243
|
-
const advisor = parseAdvisor(raw, path2);
|
|
1244
|
-
const permission = parsePermission(raw, path2);
|
|
1245
|
-
const rawProjects = raw["projects"];
|
|
1246
|
-
const rawProjectGroups = "projectGroups" in raw ? raw["projectGroups"] : {};
|
|
1247
|
-
const projectKeys = Object.keys(rawProjects);
|
|
1248
|
-
const groupKeys = Object.keys(rawProjectGroups);
|
|
1249
|
-
if (projectKeys.includes(RESERVED_ALL) || groupKeys.includes(RESERVED_ALL)) {
|
|
1250
|
-
throw new UserConfigError(
|
|
1251
|
-
`"${RESERVED_ALL}" is a reserved word and cannot be used as a key in "projects" or "projectGroups"`
|
|
1252
|
-
);
|
|
1253
|
-
}
|
|
1254
|
-
const groupKeySet = new Set(groupKeys);
|
|
1255
|
-
const duplicateKeys = projectKeys.filter((key) => groupKeySet.has(key));
|
|
1256
|
-
if (duplicateKeys.length > 0) {
|
|
1257
|
-
throw new UserConfigError(
|
|
1258
|
-
`"projects" and "projectGroups" share the same key namespace; duplicate keys are not allowed: ${duplicateKeys.join(", ")}`
|
|
1259
|
-
);
|
|
1260
|
-
}
|
|
1261
|
-
const projects = {};
|
|
1262
|
-
for (const [name, value] of Object.entries(rawProjects)) {
|
|
1263
|
-
if (name === "__proto__") {
|
|
1264
|
-
throw new UserConfigError(`"__proto__" cannot be used as a key in "projects": ${path2}`);
|
|
1265
|
-
}
|
|
1266
|
-
if (typeof value !== "string" || !isAbsolute2(value)) {
|
|
1267
|
-
console.warn(`[config] invalid projects.${name}: expected an absolute path, skipping`);
|
|
1268
|
-
continue;
|
|
1269
|
-
}
|
|
1270
|
-
if (!isDirectory(value)) {
|
|
1271
|
-
console.warn(`[config] projects.${name} does not exist as a directory: ${value}, skipping`);
|
|
1272
|
-
continue;
|
|
1273
|
-
}
|
|
1274
|
-
projects[name] = value;
|
|
1275
|
-
}
|
|
1276
|
-
const projectGroups = {};
|
|
1277
|
-
for (const [groupName, value] of Object.entries(rawProjectGroups)) {
|
|
1278
|
-
if (groupName === "__proto__") {
|
|
1279
|
-
throw new UserConfigError(`"__proto__" cannot be used as a key in "projectGroups": ${path2}`);
|
|
1280
|
-
}
|
|
1281
|
-
if (!Array.isArray(value)) {
|
|
1282
|
-
console.warn(`[config] invalid projectGroups.${groupName}: expected an array, skipping`);
|
|
1283
|
-
continue;
|
|
1284
|
-
}
|
|
1285
|
-
const members = [];
|
|
1286
|
-
for (const member of value) {
|
|
1287
|
-
if (typeof member !== "string" || !Object.prototype.hasOwnProperty.call(projects, member)) {
|
|
1288
|
-
console.warn(`[config] projectGroups.${groupName} references unknown project "${String(member)}", skipping`);
|
|
1289
|
-
continue;
|
|
1290
|
-
}
|
|
1291
|
-
members.push(member);
|
|
1292
|
-
}
|
|
1293
|
-
projectGroups[groupName] = members;
|
|
1294
|
-
}
|
|
1295
|
-
return { mode, advisor, permission, projects, projectGroups };
|
|
1296
|
-
}
|
|
1297
|
-
var cachedRunMode;
|
|
1298
|
-
function getRunMode() {
|
|
1299
|
-
if (cachedRunMode === void 0) {
|
|
1300
|
-
cachedRunMode = readRunMode();
|
|
1301
|
-
}
|
|
1302
|
-
return cachedRunMode;
|
|
1303
|
-
}
|
|
1304
|
-
var cachedAdvisorEnabled;
|
|
1305
|
-
function isAdvisorEnabled() {
|
|
1306
|
-
if (cachedAdvisorEnabled === void 0) {
|
|
1307
|
-
cachedAdvisorEnabled = readAdvisorEnabled();
|
|
1308
|
-
}
|
|
1309
|
-
return cachedAdvisorEnabled;
|
|
1310
|
-
}
|
|
1311
|
-
var cachedPermissionMode;
|
|
1312
|
-
function getPermissionMode() {
|
|
1313
|
-
if (cachedPermissionMode === void 0) {
|
|
1314
|
-
cachedPermissionMode = readTopLevel(parsePermission, DEFAULT_PERMISSION_MODE, "permission");
|
|
1315
|
-
}
|
|
1316
|
-
return cachedPermissionMode;
|
|
1317
|
-
}
|
|
1318
|
-
function readTopLevel(parse, fallback, label) {
|
|
1319
|
-
let raw;
|
|
1320
|
-
try {
|
|
1321
|
-
raw = readRawConfig2();
|
|
1322
|
-
} catch (err) {
|
|
1323
|
-
console.warn(`[config] failed to read config file, using default ${label}: ${err}`);
|
|
1324
|
-
return fallback;
|
|
1325
|
-
}
|
|
1326
|
-
if (raw === void 0) return fallback;
|
|
1327
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1328
|
-
return fallback;
|
|
1329
|
-
}
|
|
1330
|
-
return parse(raw, getUserConfigPath());
|
|
1331
|
-
}
|
|
1332
|
-
function readAdvisorEnabled() {
|
|
1333
|
-
return readTopLevel(parseAdvisor, DEFAULT_ADVISOR_ENABLED, "advisor");
|
|
1334
|
-
}
|
|
1335
|
-
function readRunMode() {
|
|
1336
|
-
return readTopLevel(parseMode, DEFAULT_RUN_MODE, "mode");
|
|
1337
|
-
}
|
|
1338
|
-
function findProjectNameByPath(path2) {
|
|
1339
|
-
let config;
|
|
1340
|
-
try {
|
|
1341
|
-
config = loadUserConfig();
|
|
1342
|
-
} catch {
|
|
1343
|
-
return void 0;
|
|
1344
|
-
}
|
|
1345
|
-
const target = resolve3(path2);
|
|
1346
|
-
for (const [name, projectPath] of Object.entries(config.projects)) {
|
|
1347
|
-
if (resolve3(projectPath) === target) return name;
|
|
1348
|
-
}
|
|
1349
|
-
return void 0;
|
|
1350
|
-
}
|
|
1351
|
-
function resolveTargetProjects(requested, config) {
|
|
1352
|
-
const resolved = /* @__PURE__ */ new Map();
|
|
1353
|
-
for (const name of requested) {
|
|
1354
|
-
if (name === RESERVED_ALL) {
|
|
1355
|
-
for (const [projectName, projectPath] of Object.entries(config.projects)) {
|
|
1356
|
-
resolved.set(projectName, { name: projectName, path: projectPath });
|
|
1357
|
-
}
|
|
1358
|
-
continue;
|
|
1359
|
-
}
|
|
1360
|
-
if (Object.prototype.hasOwnProperty.call(config.projects, name)) {
|
|
1361
|
-
resolved.set(name, { name, path: config.projects[name] });
|
|
1362
|
-
continue;
|
|
1363
|
-
}
|
|
1364
|
-
if (Object.prototype.hasOwnProperty.call(config.projectGroups, name)) {
|
|
1365
|
-
for (const projectName of config.projectGroups[name]) {
|
|
1366
|
-
const projectPath = config.projects[projectName];
|
|
1367
|
-
if (projectPath === void 0) continue;
|
|
1368
|
-
resolved.set(projectName, { name: projectName, path: projectPath });
|
|
1369
|
-
}
|
|
1370
|
-
continue;
|
|
1371
|
-
}
|
|
1372
|
-
const availableProjects = Object.keys(config.projects).join(", ") || "(none)";
|
|
1373
|
-
const availableGroups = Object.keys(config.projectGroups).join(", ") || "(none)";
|
|
1374
|
-
throw new UserConfigError(
|
|
1375
|
-
`Unknown project or group: "${name}". Available projects: ${availableProjects}. Available groups: ${availableGroups}.`
|
|
1376
|
-
);
|
|
1377
|
-
}
|
|
1378
|
-
const resolvedProjects = Array.from(resolved.values());
|
|
1379
|
-
if (resolvedProjects.length === 0) {
|
|
1380
|
-
throw new UserConfigError(`No projects resolved from requested targets: ${requested.join(", ")}`);
|
|
1381
|
-
}
|
|
1382
|
-
return resolvedProjects;
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
1085
|
// src/claude-args.ts
|
|
1386
1086
|
import { mkdirSync, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1387
1087
|
import os from "node:os";
|
|
@@ -1589,7 +1289,7 @@ ${buildCloudGitHubAccessInstruction()}`;
|
|
|
1589
1289
|
${principles}`;
|
|
1590
1290
|
return target ? appendCloudDoneInstruction(withPrinciples, target, debug) : withPrinciples;
|
|
1591
1291
|
}
|
|
1592
|
-
function
|
|
1292
|
+
function shellQuote(value) {
|
|
1593
1293
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
1594
1294
|
}
|
|
1595
1295
|
function buildScriptCommand(command, args, platform = process.platform) {
|
|
@@ -1597,7 +1297,7 @@ function buildScriptCommand(command, args, platform = process.platform) {
|
|
|
1597
1297
|
return { command: "script", args: ["-q", "/dev/null", command, ...args] };
|
|
1598
1298
|
}
|
|
1599
1299
|
if (platform === "linux") {
|
|
1600
|
-
return { command: "script", args: ["-qec", [command, ...args].map(
|
|
1300
|
+
return { command: "script", args: ["-qec", [command, ...args].map(shellQuote).join(" "), "/dev/null"] };
|
|
1601
1301
|
}
|
|
1602
1302
|
throw new Error(`unsupported platform for script(1): ${platform}`);
|
|
1603
1303
|
}
|
|
@@ -1695,7 +1395,7 @@ var herdrTasks = /* @__PURE__ */ new Map();
|
|
|
1695
1395
|
var herdrAbortSignal = { aborted: false };
|
|
1696
1396
|
var tasks = /* @__PURE__ */ new Map();
|
|
1697
1397
|
function pushTaskLogLine(id, stream, text) {
|
|
1698
|
-
pushLogLine({ id, stream, text: text.replace(/\r$/, ""), time: /* @__PURE__ */ new Date() });
|
|
1398
|
+
pushLogLine({ id, stream, text: text.replace(/\r$/, ""), time: /* @__PURE__ */ new Date(), path: tasks.get(id)?.path });
|
|
1699
1399
|
}
|
|
1700
1400
|
function makeLogFeeder(id, stream) {
|
|
1701
1401
|
let partial = "";
|
|
@@ -1806,7 +1506,7 @@ function resolveProjectName(cwd = process.cwd()) {
|
|
|
1806
1506
|
return findProjectNameByPath(cwd) ?? basename(cwd);
|
|
1807
1507
|
}
|
|
1808
1508
|
async function runViaHerdr(args, prompt, id, onComplete, cwd, env) {
|
|
1809
|
-
const { startHerdrTask, stopHerdrTask, taskTabLabel, waitForHerdrTask } = await import("./herdr-runner-
|
|
1509
|
+
const { startHerdrTask, stopHerdrTask, taskTabLabel, waitForHerdrTask } = await import("./herdr-runner-TNX2W4G6.js");
|
|
1810
1510
|
const { getCurrentWorkspaceId } = await import("./herdr-NDLUM6JF.js");
|
|
1811
1511
|
const label = taskTabLabel(resolveProjectName(), id);
|
|
1812
1512
|
let task;
|
|
@@ -1890,17 +1590,17 @@ async function pollCloudWaiters() {
|
|
|
1890
1590
|
if (cloudWaiters.size === 0) break;
|
|
1891
1591
|
for (let waited = 0; waited < CLOUD_POLL_INTERVAL_MS; waited += 1e3) {
|
|
1892
1592
|
if (herdrAbortSignal.aborted) break;
|
|
1893
|
-
await new Promise((
|
|
1593
|
+
await new Promise((resolve3) => setTimeout(resolve3, 1e3));
|
|
1894
1594
|
}
|
|
1895
1595
|
}
|
|
1896
1596
|
}
|
|
1897
1597
|
function waitForCloudTask(id, target) {
|
|
1898
|
-
return new Promise((
|
|
1598
|
+
return new Promise((resolve3) => {
|
|
1899
1599
|
cloudWaiters.set(`${target.type}:${target.number}:${id}`, {
|
|
1900
1600
|
type: target.type,
|
|
1901
1601
|
number: target.number,
|
|
1902
1602
|
deadline: Date.now() + CLOUD_TASK_TIMEOUT_MS,
|
|
1903
|
-
settle:
|
|
1603
|
+
settle: resolve3
|
|
1904
1604
|
});
|
|
1905
1605
|
ensureCloudPollLoop();
|
|
1906
1606
|
});
|
|
@@ -1925,7 +1625,7 @@ async function flagOrphanedCloudSession(target, reason, cloudSessionId) {
|
|
|
1925
1625
|
});
|
|
1926
1626
|
}
|
|
1927
1627
|
async function createCloudSession(args, initialPrompt, cwd, env) {
|
|
1928
|
-
const { extractCloudSessionId, normalizePtyOutput } = await import("./herdr-runner-
|
|
1628
|
+
const { extractCloudSessionId, normalizePtyOutput } = await import("./herdr-runner-TNX2W4G6.js");
|
|
1929
1629
|
const spec = buildScriptCommand("claude", buildCloudCreateArgs(args, initialPrompt));
|
|
1930
1630
|
const child = spawn(spec.command, spec.args, {
|
|
1931
1631
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -1933,7 +1633,7 @@ async function createCloudSession(args, initialPrompt, cwd, env) {
|
|
|
1933
1633
|
...env ? { env: { ...process.env, ...env } } : {}
|
|
1934
1634
|
});
|
|
1935
1635
|
let output = "";
|
|
1936
|
-
return await new Promise((
|
|
1636
|
+
return await new Promise((resolve3, reject) => {
|
|
1937
1637
|
let settled = false;
|
|
1938
1638
|
const finish = (err, sessionId) => {
|
|
1939
1639
|
if (settled) return;
|
|
@@ -1944,7 +1644,7 @@ async function createCloudSession(args, initialPrompt, cwd, env) {
|
|
|
1944
1644
|
child.kill();
|
|
1945
1645
|
reject(err);
|
|
1946
1646
|
} else {
|
|
1947
|
-
|
|
1647
|
+
resolve3(sessionId);
|
|
1948
1648
|
}
|
|
1949
1649
|
};
|
|
1950
1650
|
const scan = () => {
|
|
@@ -2110,10 +1810,10 @@ function run(command, args, id, title, workerName, path2, onComplete, cwd, env,
|
|
|
2110
1810
|
});
|
|
2111
1811
|
}
|
|
2112
1812
|
function waitForAllProcesses() {
|
|
2113
|
-
return new Promise((
|
|
1813
|
+
return new Promise((resolve3) => {
|
|
2114
1814
|
const check = () => {
|
|
2115
1815
|
if (childProcesses.size === 0 && herdrTasks.size === 0) {
|
|
2116
|
-
|
|
1816
|
+
resolve3();
|
|
2117
1817
|
} else {
|
|
2118
1818
|
setTimeout(check, 500);
|
|
2119
1819
|
}
|
|
@@ -2387,16 +2087,16 @@ function isGeneratedWorktreeName(name) {
|
|
|
2387
2087
|
|
|
2388
2088
|
// src/slack.ts
|
|
2389
2089
|
import { exec } from "node:child_process";
|
|
2390
|
-
import { readFileSync as
|
|
2391
|
-
import { homedir as
|
|
2392
|
-
import { join as
|
|
2090
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2091
|
+
import { homedir as homedir3 } from "node:os";
|
|
2092
|
+
import { join as join3 } from "node:path";
|
|
2393
2093
|
import { promisify as promisify2 } from "node:util";
|
|
2394
2094
|
|
|
2395
2095
|
// src/runcat.ts
|
|
2396
2096
|
import { mkdirSync as mkdirSync2, renameSync as renameSync2, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2397
|
-
import { homedir as
|
|
2398
|
-
import { dirname as dirname2, join as
|
|
2399
|
-
var RUNCAT_OUT_FILE = process.env.RUNCAT_OUT_FILE ??
|
|
2097
|
+
import { homedir as homedir2 } from "node:os";
|
|
2098
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
2099
|
+
var RUNCAT_OUT_FILE = process.env.RUNCAT_OUT_FILE ?? join2(process.env.HOME ?? homedir2(), ".claude", "runcat-usage.json");
|
|
2400
2100
|
var JST = "Asia/Tokyo";
|
|
2401
2101
|
function formatG(value) {
|
|
2402
2102
|
return String(Number(value.toPrecision(6)));
|
|
@@ -2460,7 +2160,7 @@ function buildRuncatSnapshot(usage, now = /* @__PURE__ */ new Date()) {
|
|
|
2460
2160
|
function writeRuncatUsage(usage, outFile = RUNCAT_OUT_FILE) {
|
|
2461
2161
|
const snapshot = buildRuncatSnapshot(usage);
|
|
2462
2162
|
const dir = dirname2(outFile);
|
|
2463
|
-
const tmp =
|
|
2163
|
+
const tmp = join2(dir, `.runcat-${process.pid}-${Date.now()}.json`);
|
|
2464
2164
|
try {
|
|
2465
2165
|
mkdirSync2(dir, { recursive: true });
|
|
2466
2166
|
writeFileSync3(tmp, JSON.stringify(snapshot), "utf-8");
|
|
@@ -2497,13 +2197,13 @@ async function getOAuthToken() {
|
|
|
2497
2197
|
const { stdout } = await execAsync('security find-generic-password -s "Claude Code-credentials" -w');
|
|
2498
2198
|
return extractToken(JSON.parse(stdout.trim()));
|
|
2499
2199
|
} catch {
|
|
2500
|
-
const raw =
|
|
2200
|
+
const raw = readFileSync2(join3(homedir3(), ".claude", ".credentials.json"), "utf-8");
|
|
2501
2201
|
return extractToken(JSON.parse(raw));
|
|
2502
2202
|
}
|
|
2503
2203
|
}
|
|
2504
2204
|
function readUsageCache() {
|
|
2505
2205
|
try {
|
|
2506
|
-
const raw =
|
|
2206
|
+
const raw = readFileSync2(USAGE_CACHE_PATH, "utf-8");
|
|
2507
2207
|
const cached = JSON.parse(raw);
|
|
2508
2208
|
if (Date.now() - cached.timestamp < USAGE_CACHE_TTL_SECONDS * 1e3) {
|
|
2509
2209
|
return cached.data;
|
|
@@ -2642,12 +2342,12 @@ async function notifyError(workerName, repoName, error) {
|
|
|
2642
2342
|
import { createRequire as createRequire2 } from "node:module";
|
|
2643
2343
|
import { promisify as promisify3 } from "node:util";
|
|
2644
2344
|
import { readdir, rm, stat } from "node:fs/promises";
|
|
2645
|
-
import { basename as basename2, resolve as
|
|
2345
|
+
import { basename as basename2, resolve as resolve2, sep } from "node:path";
|
|
2646
2346
|
var childProcess2 = createRequire2(import.meta.url)("node:child_process");
|
|
2647
2347
|
var execFileAsync2 = (command, args) => promisify3(childProcess2.execFile)(command, args);
|
|
2648
2348
|
var WORKTREES_DIR = ".claude/worktrees";
|
|
2649
2349
|
function isManagedWorktreePath(path2) {
|
|
2650
|
-
return
|
|
2350
|
+
return resolve2(path2).startsWith(resolve2(WORKTREES_DIR) + sep);
|
|
2651
2351
|
}
|
|
2652
2352
|
async function pathExists(path2) {
|
|
2653
2353
|
try {
|
|
@@ -2741,7 +2441,7 @@ async function removeWorktree(worktreeId) {
|
|
|
2741
2441
|
const worktreePath = getWorktreePath(worktreeId);
|
|
2742
2442
|
let entry;
|
|
2743
2443
|
try {
|
|
2744
|
-
entry = (await listWorktreeEntries()).find((e) =>
|
|
2444
|
+
entry = (await listWorktreeEntries()).find((e) => resolve2(e.path) === resolve2(worktreePath));
|
|
2745
2445
|
} catch (error) {
|
|
2746
2446
|
console.error(`[worktree] Failed to list worktrees:`, error);
|
|
2747
2447
|
}
|
|
@@ -3367,6 +3067,7 @@ export {
|
|
|
3367
3067
|
getIssueBody,
|
|
3368
3068
|
getIssueState,
|
|
3369
3069
|
listPrsClosingIssue,
|
|
3070
|
+
listOpenPrsByBase,
|
|
3370
3071
|
getPrDetail,
|
|
3371
3072
|
closeIssue,
|
|
3372
3073
|
parseClosingIssueNumbers,
|
|
@@ -3387,13 +3088,6 @@ export {
|
|
|
3387
3088
|
commentOnIssue,
|
|
3388
3089
|
createPullRequest,
|
|
3389
3090
|
createLabel,
|
|
3390
|
-
parseProjectFilters,
|
|
3391
|
-
hasProjectFilter,
|
|
3392
|
-
assertProjectCompatibleCommand,
|
|
3393
|
-
hasCloudFlag,
|
|
3394
|
-
getInheritConfigPath,
|
|
3395
|
-
assertCloudCompatibleCommand,
|
|
3396
|
-
buildForwardedCommand,
|
|
3397
3091
|
DEFAULT_UI_DESIGN_CONFIG,
|
|
3398
3092
|
SCHEDULED_WORKER_NAMES,
|
|
3399
3093
|
CLOUD_DONE_LABEL,
|
|
@@ -3414,12 +3108,6 @@ export {
|
|
|
3414
3108
|
writeLastRun,
|
|
3415
3109
|
getRemoteEnvId,
|
|
3416
3110
|
getUiDesignConfig,
|
|
3417
|
-
UserConfigError,
|
|
3418
|
-
loadUserConfig,
|
|
3419
|
-
getRunMode,
|
|
3420
|
-
isAdvisorEnabled,
|
|
3421
|
-
getPermissionMode,
|
|
3422
|
-
resolveTargetProjects,
|
|
3423
3111
|
buildScriptCommand,
|
|
3424
3112
|
buildClaudeExecution,
|
|
3425
3113
|
buildClaudeEnv,
|
|
@@ -3,7 +3,7 @@ async function loadHerdr() {
|
|
|
3
3
|
return await import("./herdr-NDLUM6JF.js");
|
|
4
4
|
}
|
|
5
5
|
async function loadTable() {
|
|
6
|
-
return await import("./table-
|
|
6
|
+
return await import("./table-OOKBQVW5.js");
|
|
7
7
|
}
|
|
8
8
|
var { getDisplayWidth, truncateToWidth, padToWidth, buildLogTableLines, logLines, writeScreen } = await loadTable();
|
|
9
9
|
var POLL_INTERVAL_MS = 7 * 1e3;
|