hamster-wheel-cli 0.3.1 → 0.3.4

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.
@@ -0,0 +1,2 @@
1
+ [agent]
2
+ glm = "goose run --text"
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  本项目遵循语义化版本,变更日志以时间倒序记录。
4
4
 
5
+ ## [0.3.4] - 2025-12-25
6
+ ### Fixed
7
+ - `agent set` 允许透传包含 `--` 的子命令参数,避免 `unknown option` 报错。
8
+
9
+ ## [0.3.3] - 2025-12-25
10
+ ### Fixed
11
+ - `--version` 改为从 `package.json` 读取版本号,避免硬编码不一致。
12
+
13
+ ## [0.3.2] - 2025-12-24
14
+ ### Fixed
15
+ - webhook 的 `project` 字段固定为首次识别的仓库目录名,切换 worktree 后保持不变。
16
+
5
17
  ## [0.3.1] - 2025-12-24
6
18
  ### Added
7
19
  - webhook 在“计划生成”阶段新增 `plan` 字段,携带计划原文便于下游对接。
package/README.md CHANGED
@@ -106,6 +106,12 @@ wheel-ai agent delete claude
106
106
  wheel-ai agent list
107
107
  ```
108
108
 
109
+ 当 agent 命令包含以 `-`/`--` 开头的参数时,已支持直接透传;如需显式终止解析可使用 `--`,例如:
110
+ ```bash
111
+ wheel-ai agent set glm goose run --text
112
+ wheel-ai agent set glm -- goose run --text
113
+ ```
114
+
109
115
  在 run 中使用 agent:
110
116
  ```bash
111
117
  wheel-ai run --use-agent claude -t "补充文档"
@@ -148,7 +154,7 @@ Payload 示例:
148
154
  字段说明:
149
155
  - `event`:`task_start` / `iteration_start` / `task_end`
150
156
  - `task`:任务描述(仅 `task_start` 会携带)
151
- - `project`:当前工作目录名称(仅文件夹名,不含路径)
157
+ - `project`:首次识别的仓库根目录名称(仅文件夹名,不含路径),切换 worktree 后保持不变
152
158
  - `branch`:分支名(可能为空)
153
159
  - `iteration`:当前轮次(任务开始为 0)
154
160
  - `stage`:当前节点描述
package/dist/cli.js CHANGED
@@ -35,6 +35,7 @@ __export(cli_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(cli_exports);
37
37
  var import_node_child_process = require("child_process");
38
+ var import_node_path12 = __toESM(require("path"));
38
39
  var import_fs_extra12 = __toESM(require("fs-extra"));
39
40
  var import_commander = require("commander");
40
41
 
@@ -2520,14 +2521,14 @@ async function safeRemove(logFile, logger) {
2520
2521
  }
2521
2522
  }
2522
2523
  async function createRunTracker(options) {
2523
- const { logFile, command, path: path12, logger } = options;
2524
+ const { logFile, command, path: path13, logger } = options;
2524
2525
  if (!logFile) return null;
2525
2526
  const update = async (round, tokenUsed) => {
2526
2527
  const metadata = {
2527
2528
  command,
2528
2529
  round,
2529
2530
  tokenUsed,
2530
- path: path12,
2531
+ path: path13,
2531
2532
  pid: process.pid
2532
2533
  };
2533
2534
  await safeWrite(logFile, metadata, logger);
@@ -3045,6 +3046,7 @@ async function runLoop(config) {
3045
3046
  const logger = new Logger({ verbose: config.verbose, logFile: config.logFile });
3046
3047
  const repoRoot = await getRepoRoot(config.cwd, logger);
3047
3048
  logger.debug(`\u4ED3\u5E93\u6839\u76EE\u5F55: ${repoRoot}`);
3049
+ const initialProjectName = import_node_path9.default.basename(repoRoot);
3048
3050
  let branchName = config.git.branchName;
3049
3051
  let workDir = repoRoot;
3050
3052
  let worktreeCreated = false;
@@ -3063,7 +3065,7 @@ async function runLoop(config) {
3063
3065
  let commitCreated = false;
3064
3066
  let pushSucceeded = false;
3065
3067
  const preWorktreeRecords = [];
3066
- const resolveProjectName = () => import_node_path9.default.basename(workDir);
3068
+ const resolveProjectName = () => initialProjectName;
3067
3069
  const notifyWebhook = async (event, iteration, stage, plan) => {
3068
3070
  const project = resolveProjectName();
3069
3071
  const payload = event === "task_start" ? buildWebhookPayload({
@@ -4120,6 +4122,26 @@ var RUN_OPTION_FLAG_MAP = new Map(
4120
4122
  );
4121
4123
  var USE_ALIAS_FLAG = "--use-alias";
4122
4124
  var USE_AGENT_FLAG = "--use-agent";
4125
+ var PACKAGE_VERSION_FALLBACK = "0.0.0";
4126
+ async function resolveCliVersion() {
4127
+ const candidatePaths = [
4128
+ import_node_path12.default.resolve(__dirname, "..", "package.json"),
4129
+ import_node_path12.default.resolve(process.cwd(), "package.json")
4130
+ ];
4131
+ for (const candidatePath of candidatePaths) {
4132
+ const exists = await import_fs_extra12.default.pathExists(candidatePath);
4133
+ if (!exists) continue;
4134
+ try {
4135
+ const pkg = await import_fs_extra12.default.readJson(candidatePath);
4136
+ if (typeof pkg?.version === "string") {
4137
+ const trimmed = pkg.version.trim();
4138
+ if (trimmed.length > 0) return trimmed;
4139
+ }
4140
+ } catch {
4141
+ }
4142
+ }
4143
+ return PACKAGE_VERSION_FALLBACK;
4144
+ }
4123
4145
  function parseInteger(value, defaultValue) {
4124
4146
  const parsed = Number.parseInt(value, 10);
4125
4147
  if (Number.isNaN(parsed)) return defaultValue;
@@ -4462,11 +4484,13 @@ async function runForegroundWithDetach(options) {
4462
4484
  async function runCli(argv) {
4463
4485
  const globalConfig = await loadGlobalConfig(defaultLogger);
4464
4486
  const effectiveArgv = applyShortcutArgv(argv, globalConfig);
4487
+ const cliVersion = await resolveCliVersion();
4465
4488
  const program = new import_commander.Command();
4466
- program.name("wheel-ai").description("\u57FA\u4E8E AI CLI \u7684\u6301\u7EED\u8FED\u4EE3\u5F00\u53D1\u5DE5\u5177").version("0.2.1");
4489
+ program.name("wheel-ai").description("\u57FA\u4E8E AI CLI \u7684\u6301\u7EED\u8FED\u4EE3\u5F00\u53D1\u5DE5\u5177").version(cliVersion);
4490
+ program.enablePositionalOptions();
4467
4491
  program.addHelpText(
4468
4492
  "after",
4469
- "\nalias \u7BA1\u7406\uFF1A\n wheel-ai alias set <name> <options...>\n wheel-ai alias list\n wheel-ai alias delete <name>\n\nalias/agent \u53E0\u52A0\uFF1A\n wheel-ai run --use-alias <name> [--use-alias <name>...]\n wheel-ai run --use-agent <name> [--use-agent <name>...]\n \u540C\u540D\u9009\u9879\u6309\u51FA\u73B0\u987A\u5E8F\u8986\u76D6\u3002\n"
4493
+ "\nalias \u7BA1\u7406\uFF1A\n wheel-ai alias set <name> <options...>\n wheel-ai alias list\n wheel-ai alias delete <name>\n\nalias/agent \u53E0\u52A0\uFF1A\n wheel-ai run --use-alias <name> [--use-alias <name>...]\n wheel-ai run --use-agent <name> [--use-agent <name>...]\n \u540C\u540D\u9009\u9879\u6309\u51FA\u73B0\u987A\u5E8F\u8986\u76D6\u3002\n\nagent \u5F55\u5165\u5305\u542B\u9009\u9879\u65F6\u4F7F\u7528 -- \u7EC8\u6B62\u89E3\u6790\uFF1A\n wheel-ai agent set <name> -- <command...>\n \u4F8B\u5982\uFF1Awheel-ai agent set glm -- goose run --text\n"
4470
4494
  );
4471
4495
  program.command("run").option("-t, --task <task>", "\u9700\u8981\u5B8C\u6210\u7684\u4EFB\u52A1\u63CF\u8FF0\uFF08\u53EF\u91CD\u590D\u4F20\u5165\uFF0C\u72EC\u7ACB\u5904\u7406\uFF09", collect, []).option("--use-alias <name>", "\u53E0\u52A0 alias \u914D\u7F6E\uFF08\u53EF\u91CD\u590D\uFF09", collect, []).option("--use-agent <name>", "\u53E0\u52A0 agent \u914D\u7F6E\uFF08\u53EF\u91CD\u590D\uFF09", collect, []).option("-i, --iterations <number>", "\u6700\u5927\u8FED\u4EE3\u6B21\u6570", (value) => parseInteger(value, 5), 5).option("--ai-cli <command>", "AI CLI \u547D\u4EE4", "claude").option("--ai-args <args...>", "AI CLI \u53C2\u6570", []).option("--ai-prompt-arg <flag>", "\u7528\u4E8E\u4F20\u5165 prompt \u7684\u53C2\u6570\uFF08\u4E3A\u7A7A\u5219\u4F7F\u7528 stdin\uFF09").option("--notes-file <path>", "\u6301\u4E45\u5316\u8BB0\u5FC6\u6587\u4EF6", defaultNotesPath()).option("--plan-file <path>", "\u8BA1\u5212\u6587\u4EF6", defaultPlanPath()).option("--workflow-doc <path>", "AI \u5DE5\u4F5C\u6D41\u7A0B\u8BF4\u660E\u6587\u4EF6", defaultWorkflowDoc()).option("--worktree", "\u5728\u72EC\u7ACB worktree \u4E0A\u6267\u884C", false).option("--branch <name>", "worktree \u5206\u652F\u540D\uFF08\u9ED8\u8BA4\u81EA\u52A8\u751F\u6210\u6216\u5F53\u524D\u5206\u652F\uFF09").option("--worktree-path <path>", "worktree \u8DEF\u5F84\uFF0C\u9ED8\u8BA4 ../worktrees/<branch>").option("--base-branch <name>", "\u521B\u5EFA\u5206\u652F\u7684\u57FA\u7EBF\u5206\u652F", "main").option("--skip-install", "\u8DF3\u8FC7\u5F00\u59CB\u4EFB\u52A1\u524D\u7684\u4F9D\u8D56\u68C0\u67E5", false).option("--run-tests", "\u8FD0\u884C\u5355\u5143\u6D4B\u8BD5\u547D\u4EE4", false).option("--run-e2e", "\u8FD0\u884C e2e \u6D4B\u8BD5\u547D\u4EE4", false).option("--unit-command <cmd>", "\u5355\u5143\u6D4B\u8BD5\u547D\u4EE4", "yarn test").option("--e2e-command <cmd>", "e2e \u6D4B\u8BD5\u547D\u4EE4", "yarn e2e").option("--auto-commit", "\u81EA\u52A8 git commit", false).option("--auto-push", "\u81EA\u52A8 git push", false).option("--pr", "\u4F7F\u7528 gh \u521B\u5EFA PR", false).option("--pr-title <title>", "PR \u6807\u9898").option("--pr-body <path>", "PR \u63CF\u8FF0\u6587\u4EF6\u8DEF\u5F84\uFF08\u53EF\u7559\u7A7A\u81EA\u52A8\u751F\u6210\uFF09").option("--draft", "\u4EE5\u8349\u7A3F\u5F62\u5F0F\u521B\u5EFA PR", false).option("--reviewer <user...>", "PR reviewers", collect, []).option("--auto-merge", "PR \u68C0\u67E5\u901A\u8FC7\u540E\u81EA\u52A8\u5408\u5E76", false).option("--webhook <url>", "webhook \u901A\u77E5 URL\uFF08\u53EF\u91CD\u590D\uFF09", collect, []).option("--webhook-timeout <ms>", "webhook \u8BF7\u6C42\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09", (value) => parseInteger(value, 8e3)).option("--multi-task-mode <mode>", "\u591A\u4EFB\u52A1\u6267\u884C\u6A21\u5F0F\uFF08relay/serial/serial-continue/parallel\uFF0C\u6216\u4E2D\u6587\u63CF\u8FF0\uFF09", "relay").option("--stop-signal <token>", "AI \u8F93\u51FA\u4E2D\u7684\u505C\u6B62\u6807\u8BB0", "<<DONE>>").option("--log-file <path>", "\u65E5\u5FD7\u8F93\u51FA\u6587\u4EF6\u8DEF\u5F84").option("--background", "\u5207\u5165\u540E\u53F0\u8FD0\u884C", false).option("-v, --verbose", "\u8F93\u51FA\u8C03\u8BD5\u65E5\u5FD7", false).option("--skip-quality", "\u8DF3\u8FC7\u4EE3\u7801\u8D28\u91CF\u68C0\u67E5", false).action(async (options) => {
4472
4496
  const rawRunArgs = extractRunCommandArgs(effectiveArgv);
@@ -4685,7 +4709,7 @@ async function runCli(argv) {
4685
4709
  await upsertAgentEntry(normalized, commandLine);
4686
4710
  console.log(`\u5DF2\u65B0\u589E agent\uFF1A${normalized}`);
4687
4711
  });
4688
- agentCommand.command("set <name> [command...]").description("\u5199\u5165 agent").allowUnknownOption(true).allowExcessArguments(true).action(async (name) => {
4712
+ agentCommand.command("set <name> [command...]").description("\u5199\u5165 agent").passThroughOptions().allowUnknownOption(true).allowExcessArguments(true).action(async (name) => {
4689
4713
  const normalized = normalizeAgentName(name);
4690
4714
  if (!normalized) {
4691
4715
  throw new Error("agent \u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u5305\u542B\u7A7A\u767D\u5B57\u7B26");