claude-task-worker 0.101.0 → 0.103.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 +17 -2
- package/dist/index.js +82 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ CLI が GitHub ラベルを検知してタスクを起動し、プラグイン
|
|
|
61
61
|
| [Pen CLI](https://docs.pen.dev/for-developers/pen-cli) | `.pen` の編集・参照。UIデザイン先行ワークフロー使用時のみ(要ログイン) |
|
|
62
62
|
| [Playwright](https://playwright.dev/) のブラウザ | Playwright MCP でのブラウザ確認 |
|
|
63
63
|
| [DESIGN.md CLI](https://github.com/google-labs-code/design.md) | `DESIGN.md` の lint。`update-design-md` 使用時のみ(未導入でも動く) |
|
|
64
|
-
| [herdr](https://herdr.dev) | `--project` / `mode: "herdr"` 使用時のみ(`--cloud`
|
|
64
|
+
| [herdr](https://herdr.dev) | `--project` / `mode: "herdr"` 使用時のみ(`--cloud` は herdr に依存しない) |
|
|
65
65
|
| [GitHub MCP](https://github.com/github/github-mcp-server) | GitHub アクセスの高速化・クラウド実行時のプロキシ制限回避(任意。Claude 側のコネクタで有効化) |
|
|
66
66
|
|
|
67
67
|
CLI 本体に npm の実行時依存はない(Node.js 標準モジュールのみで動作する)。
|
|
@@ -205,7 +205,7 @@ npx claude-task-worker cloud-setup
|
|
|
205
205
|
- 完了は `cc-cloud-done` ラベルで検知する。4時間で応答がなければ打ち切り、`cc-need-human-check` を付けて失敗通知する
|
|
206
206
|
- `--project` と併用した場合、`--cloud` は各プロジェクトへそのまま転送される
|
|
207
207
|
- `--cloud` と併用できないコマンド: `init` / `install` / `update` / `usage` / `version`
|
|
208
|
-
-
|
|
208
|
+
- `--cloud` は `mode`(`default` / `herdr`)に依存しない。クラウドセッションの作成は `script` コマンドの疑似 pty で完結し、herdr のペインを使わないため、どちらの `mode` でも同じ経路を通る
|
|
209
209
|
|
|
210
210
|
詳細は [`docs/prd-cloud-worker-execution.md`](./docs/prd-cloud-worker-execution.md) を参照。
|
|
211
211
|
|
|
@@ -258,10 +258,25 @@ CI やクラウド VM など対話ログインできない環境では、環境
|
|
|
258
258
|
| キー | 型 | 既定 | 説明 |
|
|
259
259
|
|---|---|---|---|
|
|
260
260
|
| `fixReviewPointCallbackCommentMessage` | string | - | `fix-review-point` 完了時に PR へ投稿するコメント(未設定なら投稿しない) |
|
|
261
|
+
| `remoteEnvId` | string \| null | `null` | クラウド実行(`--cloud`)時に `--environment` へ渡すクラウド環境ID。`null` なら渡さず claude 側の既定解決に任せる(下記) |
|
|
261
262
|
| `uiDesign` | object | `{ "enabled": false, "designDir": "designs", "yolo": false }` | UIデザイン先行ワークフロー(下記) |
|
|
262
263
|
| `workers` | object | `{}` | ワーカーごとの上書き設定(下記) |
|
|
263
264
|
| `lastRun` | object | `{}` | 定期ワーカーの最終実行時刻。ワーカーが自動更新するため手で編集しない |
|
|
264
265
|
|
|
266
|
+
#### `claude-task-worker.local.json`(ローカル上書き)
|
|
267
|
+
|
|
268
|
+
同じディレクトリに `claude-task-worker.local.json` を置くと、`claude-task-worker.json` と同じキーを書けて**同じキーはローカル側が勝つ**。マージはネストしたオブジェクトのキー単位(`workers.<name>.model` だけを差し替えられる。配列・スカラーは丸ごと置き換え)。
|
|
269
|
+
|
|
270
|
+
コミットしない前提のファイルで、`claude-task-worker init` が `.gitignore` へ登録する。`remoteEnvId` のように各自の環境で値が違う設定を置く。
|
|
271
|
+
|
|
272
|
+
#### クラウド環境の指定(`remoteEnvId`)
|
|
273
|
+
|
|
274
|
+
`--cloud` 実行時に `claude --environment <id>` へ渡す環境ID。指定しない場合の選択は claude CLI に任せる(`~/.claude/settings.json` の `remote.defaultEnvironmentId` → アカウントの最初の `anthropic_cloud` 環境 → 無ければ自動作成)。ID は claude.ai の環境設定、または `/remote-env` で確認できる。自己ホスト環境(`ccpool_...`)も同じキーに書ける。
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{ "remoteEnvId": "env_xxxxxxxx" }
|
|
278
|
+
```
|
|
279
|
+
|
|
265
280
|
#### ワーカーごとの設定
|
|
266
281
|
|
|
267
282
|
未指定のワーカー・フィールドは既定値にフォールバックする。
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ var __export = (target, all) => {
|
|
|
12
12
|
// src/table.ts
|
|
13
13
|
var table_exports = {};
|
|
14
14
|
__export(table_exports, {
|
|
15
|
+
CLOUD_WORKTREE_LABEL: () => CLOUD_WORKTREE_LABEL,
|
|
15
16
|
CONTROL_CHARS: () => CONTROL_CHARS,
|
|
16
17
|
LOG_DISPLAY_LIMIT: () => LOG_DISPLAY_LIMIT,
|
|
17
18
|
TASK_DISPLAY_LIMIT: () => TASK_DISPLAY_LIMIT,
|
|
@@ -29,7 +30,7 @@ __export(table_exports, {
|
|
|
29
30
|
import { format } from "node:util";
|
|
30
31
|
function getDisplayWidth(str) {
|
|
31
32
|
let width = 0;
|
|
32
|
-
for (const char of str) {
|
|
33
|
+
for (const char of str.replace(CONTROL_CHARS, "")) {
|
|
33
34
|
const code = char.codePointAt(0);
|
|
34
35
|
if (code >= 4352 && code <= 4447 || code >= 11904 && code <= 12350 || code >= 12352 && code <= 13247 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 42191 || code >= 44032 && code <= 55215 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141) {
|
|
35
36
|
width += 2;
|
|
@@ -181,10 +182,11 @@ function buildLogTableLines(entries) {
|
|
|
181
182
|
});
|
|
182
183
|
return renderBoxTable(["Time", "#", "Stream", "Log"], [rows]);
|
|
183
184
|
}
|
|
184
|
-
var TASK_DISPLAY_LIMIT, LOG_DISPLAY_LIMIT, logLines, rawLog, rawClear, consoleCaptured, CONTROL_CHARS;
|
|
185
|
+
var CLOUD_WORKTREE_LABEL, TASK_DISPLAY_LIMIT, LOG_DISPLAY_LIMIT, logLines, rawLog, rawClear, consoleCaptured, CONTROL_CHARS;
|
|
185
186
|
var init_table = __esm({
|
|
186
187
|
"src/table.ts"() {
|
|
187
188
|
"use strict";
|
|
189
|
+
CLOUD_WORKTREE_LABEL = "\x1B[36m\u2601 running in cloud\x1B[0m";
|
|
188
190
|
TASK_DISPLAY_LIMIT = 20;
|
|
189
191
|
LOG_DISPLAY_LIMIT = 20;
|
|
190
192
|
logLines = [];
|
|
@@ -1905,11 +1907,13 @@ function checkCloudConfig(input) {
|
|
|
1905
1907
|
}
|
|
1906
1908
|
var DEFAULT_CONFIG = {
|
|
1907
1909
|
fixReviewPointCallbackCommentMessage: "",
|
|
1910
|
+
remoteEnvId: null,
|
|
1908
1911
|
uiDesign: { ...DEFAULT_UI_DESIGN_CONFIG },
|
|
1909
1912
|
lastRun: {},
|
|
1910
1913
|
workers: {}
|
|
1911
1914
|
};
|
|
1912
1915
|
var CONFIG_PATH = join(process.cwd(), "claude-task-worker.json");
|
|
1916
|
+
var LOCAL_CONFIG_PATH = join(process.cwd(), "claude-task-worker.local.json");
|
|
1913
1917
|
function defaultsFor(name) {
|
|
1914
1918
|
return WORKER_DEFAULTS[name] ?? DEFAULT_WORKER_CONFIG;
|
|
1915
1919
|
}
|
|
@@ -2041,18 +2045,44 @@ function parseLastRunEntry(val) {
|
|
|
2041
2045
|
}
|
|
2042
2046
|
return result;
|
|
2043
2047
|
}
|
|
2044
|
-
function
|
|
2045
|
-
|
|
2046
|
-
|
|
2048
|
+
function isPlainObject(val) {
|
|
2049
|
+
return typeof val === "object" && val !== null && !Array.isArray(val);
|
|
2050
|
+
}
|
|
2051
|
+
function mergeConfigRaw(base, local) {
|
|
2052
|
+
const result = { ...base };
|
|
2053
|
+
for (const [key, val] of Object.entries(local)) {
|
|
2054
|
+
const current = result[key];
|
|
2055
|
+
result[key] = isPlainObject(current) && isPlainObject(val) ? mergeConfigRaw(current, val) : val;
|
|
2056
|
+
}
|
|
2057
|
+
return result;
|
|
2058
|
+
}
|
|
2059
|
+
function readRawConfig(path2) {
|
|
2060
|
+
let parsed;
|
|
2047
2061
|
try {
|
|
2048
|
-
|
|
2062
|
+
parsed = JSON.parse(readFileSync(path2, "utf-8"));
|
|
2049
2063
|
} catch (err) {
|
|
2050
|
-
if (err.code === "ENOENT") {
|
|
2051
|
-
return { ...DEFAULT_CONFIG, uiDesign: { ...DEFAULT_UI_DESIGN_CONFIG }, lastRun: {}, workers: {} };
|
|
2052
|
-
}
|
|
2064
|
+
if (err.code === "ENOENT") return {};
|
|
2053
2065
|
throw err;
|
|
2054
2066
|
}
|
|
2067
|
+
if (!isPlainObject(parsed)) {
|
|
2068
|
+
console.warn(`[config] invalid ${path2}: expected object, ignoring`);
|
|
2069
|
+
return {};
|
|
2070
|
+
}
|
|
2071
|
+
return parsed;
|
|
2072
|
+
}
|
|
2073
|
+
function loadConfig() {
|
|
2074
|
+
const raw = mergeConfigRaw(readRawConfig(CONFIG_PATH), readRawConfig(LOCAL_CONFIG_PATH));
|
|
2055
2075
|
const result = { ...DEFAULT_CONFIG, uiDesign: { ...DEFAULT_UI_DESIGN_CONFIG }, lastRun: {}, workers: {} };
|
|
2076
|
+
if ("remoteEnvId" in raw) {
|
|
2077
|
+
const val = raw["remoteEnvId"];
|
|
2078
|
+
if (val === null) {
|
|
2079
|
+
result.remoteEnvId = null;
|
|
2080
|
+
} else if (typeof val === "string" && val.trim().length > 0) {
|
|
2081
|
+
result.remoteEnvId = val.trim();
|
|
2082
|
+
} else {
|
|
2083
|
+
console.warn(`[config] invalid remoteEnvId: ${String(val)}, using default null`);
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2056
2086
|
if ("lastRun" in raw) {
|
|
2057
2087
|
result.lastRun = parseLastRunEntry(raw["lastRun"]);
|
|
2058
2088
|
}
|
|
@@ -2112,6 +2142,14 @@ function writeLastRun(repoRoot, workerName, at = /* @__PURE__ */ new Date()) {
|
|
|
2112
2142
|
writeFileSync(path2, `${JSON.stringify(raw, null, 2)}
|
|
2113
2143
|
`, "utf-8");
|
|
2114
2144
|
}
|
|
2145
|
+
function getRemoteEnvId() {
|
|
2146
|
+
try {
|
|
2147
|
+
return loadConfig().remoteEnvId;
|
|
2148
|
+
} catch (err) {
|
|
2149
|
+
console.warn(`[config] failed to load remoteEnvId, not passing --environment: ${err}`);
|
|
2150
|
+
return null;
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2115
2153
|
function getUiDesignConfig() {
|
|
2116
2154
|
try {
|
|
2117
2155
|
return loadConfig().uiDesign;
|
|
@@ -2175,7 +2213,7 @@ function parseConfigFile(path2) {
|
|
|
2175
2213
|
throw err;
|
|
2176
2214
|
}
|
|
2177
2215
|
}
|
|
2178
|
-
function
|
|
2216
|
+
function readRawConfig2() {
|
|
2179
2217
|
return parseConfigFile(getUserConfigPath());
|
|
2180
2218
|
}
|
|
2181
2219
|
function parseMode(raw, path2) {
|
|
@@ -2201,7 +2239,7 @@ function parsePermission(raw, path2) {
|
|
|
2201
2239
|
}
|
|
2202
2240
|
function loadUserConfig() {
|
|
2203
2241
|
const path2 = getUserConfigPath();
|
|
2204
|
-
const raw =
|
|
2242
|
+
const raw = readRawConfig2();
|
|
2205
2243
|
if (raw === void 0) {
|
|
2206
2244
|
throw new UserConfigError(`config.json not found: ${path2}`);
|
|
2207
2245
|
}
|
|
@@ -2293,7 +2331,7 @@ function getPermissionMode() {
|
|
|
2293
2331
|
function readTopLevel(parse, fallback, label) {
|
|
2294
2332
|
let raw;
|
|
2295
2333
|
try {
|
|
2296
|
-
raw =
|
|
2334
|
+
raw = readRawConfig2();
|
|
2297
2335
|
} catch (err) {
|
|
2298
2336
|
console.warn(`[config] failed to read config file, using default ${label}: ${err}`);
|
|
2299
2337
|
return fallback;
|
|
@@ -2443,6 +2481,7 @@ function buildClaudeArgs({
|
|
|
2443
2481
|
advisorModel,
|
|
2444
2482
|
permissionMode,
|
|
2445
2483
|
cloud,
|
|
2484
|
+
remoteEnvId,
|
|
2446
2485
|
baseRef,
|
|
2447
2486
|
onBranch
|
|
2448
2487
|
}) {
|
|
@@ -2452,6 +2491,7 @@ function buildClaudeArgs({
|
|
|
2452
2491
|
throw new Error("--on-branch and --ref both set the cloud session's base branch; pass one or the other");
|
|
2453
2492
|
}
|
|
2454
2493
|
const advisor = advisorModel?.trim() ?? "";
|
|
2494
|
+
const remoteEnv = remoteEnvId?.trim() ?? "";
|
|
2455
2495
|
const permission = permissionMode ?? DEFAULT_PERMISSION_MODE;
|
|
2456
2496
|
return [
|
|
2457
2497
|
// default モードはプロンプトを引数で渡す(print モード)。herdr モードでは渡さない:
|
|
@@ -2475,6 +2515,9 @@ function buildClaudeArgs({
|
|
|
2475
2515
|
// advisor 未指定(空文字)ならフラグごと省く。値なしの `--advisor` を渡すと
|
|
2476
2516
|
// 後続フラグを値として食われるため、必ずモデル名とセットでのみ付ける。
|
|
2477
2517
|
...advisor === "" ? [] : ["--advisor", advisor],
|
|
2518
|
+
// クラウド環境の指名。値なしの `--environment` は後続フラグを値として食うため、
|
|
2519
|
+
// `--advisor` と同じく ID とセットでのみ付ける。
|
|
2520
|
+
...cloud === true && remoteEnv !== "" ? ["--environment", remoteEnv] : [],
|
|
2478
2521
|
// クラウド実行時は「作成コマンドの共通フラグ」だけをここで返す。`--cloud` 自体は
|
|
2479
2522
|
// 付けない(値として渡す description(=クラウドセッションの初期プロンプト。
|
|
2480
2523
|
// appendCloudDoneInstruction() 適用後のタスクプロンプトそのもの)は
|
|
@@ -2972,7 +3015,9 @@ function run(command, args, id, title, workerName, path2, onComplete, cwd, env,
|
|
|
2972
3015
|
title,
|
|
2973
3016
|
status: "running",
|
|
2974
3017
|
workerName,
|
|
2975
|
-
path
|
|
3018
|
+
// クラウド実行は worktree を持たない(ワーカーが path に undefined を渡す)ため、
|
|
3019
|
+
// 空欄ではなく実行場所が分かる表示を入れる。
|
|
3020
|
+
path: cloud ? CLOUD_WORKTREE_LABEL : path2,
|
|
2976
3021
|
startedAt: /* @__PURE__ */ new Date()
|
|
2977
3022
|
});
|
|
2978
3023
|
ensureRenderInterval();
|
|
@@ -3786,7 +3831,7 @@ function createIssuePollingWorker(config) {
|
|
|
3786
3831
|
// config.json の advisor が false なら advisorModel の指定に関わらず渡さない。
|
|
3787
3832
|
advisorModel: isAdvisorEnabled() ? advisorModel : "",
|
|
3788
3833
|
permissionMode: getPermissionMode(),
|
|
3789
|
-
...cloud ? { cloud: true, baseRef: baseBranch } : {}
|
|
3834
|
+
...cloud ? { cloud: true, baseRef: baseBranch, remoteEnvId: getRemoteEnvId() ?? "" } : {}
|
|
3790
3835
|
});
|
|
3791
3836
|
let cwd;
|
|
3792
3837
|
if (cloud) {
|
|
@@ -4054,6 +4099,7 @@ function createPrPollingWorker(config) {
|
|
|
4054
4099
|
advisorModel: isAdvisorEnabled() ? advisorModel : "",
|
|
4055
4100
|
permissionMode: getPermissionMode(),
|
|
4056
4101
|
cloud: isCloud,
|
|
4102
|
+
remoteEnvId: isCloud ? getRemoteEnvId() ?? "" : void 0,
|
|
4057
4103
|
onBranch: isCloud ? pr.headRefName : void 0
|
|
4058
4104
|
});
|
|
4059
4105
|
if (isCloud) {
|
|
@@ -4660,7 +4706,7 @@ function createScheduledWorker(config) {
|
|
|
4660
4706
|
effort,
|
|
4661
4707
|
advisorModel: isAdvisorEnabled() ? advisorModel : "",
|
|
4662
4708
|
permissionMode: getPermissionMode(),
|
|
4663
|
-
...cloud ? { cloud: true, baseRef: defaultBranch } : {}
|
|
4709
|
+
...cloud ? { cloud: true, baseRef: defaultBranch, remoteEnvId: getRemoteEnvId() ?? "" } : {}
|
|
4664
4710
|
});
|
|
4665
4711
|
await publishLastRunPr(config.name, defaultBranch, new Date(now)).catch(
|
|
4666
4712
|
(err) => console.error(`[${config.name}] publishLastRunPr failed: ${err}`)
|
|
@@ -4748,7 +4794,8 @@ var updateDesignMdWorker = createScheduledWorker({
|
|
|
4748
4794
|
init_table();
|
|
4749
4795
|
|
|
4750
4796
|
// src/commands/init.ts
|
|
4751
|
-
import { mkdir as mkdir2, writeFile as writeFile2, access } from "node:fs/promises";
|
|
4797
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2, access } from "node:fs/promises";
|
|
4798
|
+
import { basename as basename3 } from "node:path";
|
|
4752
4799
|
|
|
4753
4800
|
// src/commands/codegraph.ts
|
|
4754
4801
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
@@ -4937,6 +4984,22 @@ async function createConfig(force) {
|
|
|
4937
4984
|
const result = await writeFileWithMode(CONFIG_PATH, JSON.stringify(initialConfig, null, 2), force);
|
|
4938
4985
|
logWriteResult(result, CONFIG_PATH);
|
|
4939
4986
|
}
|
|
4987
|
+
async function ensureLocalConfigGitIgnore() {
|
|
4988
|
+
const entry = basename3(LOCAL_CONFIG_PATH);
|
|
4989
|
+
const path2 = ".gitignore";
|
|
4990
|
+
let current = "";
|
|
4991
|
+
try {
|
|
4992
|
+
current = await readFile2(path2, "utf-8");
|
|
4993
|
+
} catch {
|
|
4994
|
+
}
|
|
4995
|
+
const next = appendIgnoreEntry(current, entry);
|
|
4996
|
+
if (next === null) {
|
|
4997
|
+
console.log(`[init] Already ignored: ${entry} (${path2})`);
|
|
4998
|
+
return;
|
|
4999
|
+
}
|
|
5000
|
+
await writeFile2(path2, next, "utf-8");
|
|
5001
|
+
console.log(`[init] Added ${entry} to ${path2}`);
|
|
5002
|
+
}
|
|
4940
5003
|
async function init(options = {}) {
|
|
4941
5004
|
const force = options.force ?? false;
|
|
4942
5005
|
console.log(`[init] Creating labels...${force ? " (force mode)" : ""}`);
|
|
@@ -4958,6 +5021,7 @@ async function init(options = {}) {
|
|
|
4958
5021
|
logWriteResult(await writeFileWithMode(workflowPath, ASSIGN_CREATOR_WORKFLOW, force), workflowPath);
|
|
4959
5022
|
console.log("[init] Creating config file...");
|
|
4960
5023
|
await createConfig(force);
|
|
5024
|
+
await ensureLocalConfigGitIgnore();
|
|
4961
5025
|
console.log("[init] Setting up CodeGraph...");
|
|
4962
5026
|
await ensureCodegraphGitIgnore("init");
|
|
4963
5027
|
await runCodegraphInit("init");
|
|
@@ -5119,7 +5183,7 @@ async function install() {
|
|
|
5119
5183
|
}
|
|
5120
5184
|
|
|
5121
5185
|
// src/commands/cloud-setup.ts
|
|
5122
|
-
import { mkdir as mkdir3, writeFile as writeFile3, readFile as
|
|
5186
|
+
import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile3 } from "node:fs/promises";
|
|
5123
5187
|
import { homedir as homedir6 } from "node:os";
|
|
5124
5188
|
import { join as join8 } from "node:path";
|
|
5125
5189
|
var LOG_PREFIX = "cloud-setup";
|
|
@@ -5160,7 +5224,7 @@ async function writeClaudeSettings(force) {
|
|
|
5160
5224
|
const path2 = claudeSettingsPath();
|
|
5161
5225
|
let existing;
|
|
5162
5226
|
try {
|
|
5163
|
-
existing = await
|
|
5227
|
+
existing = await readFile3(path2, "utf-8");
|
|
5164
5228
|
} catch {
|
|
5165
5229
|
existing = null;
|
|
5166
5230
|
}
|