@towles/tool 0.0.96 → 0.0.103
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/bin/run.ts +4 -3
- package/package.json +8 -37
- package/src/cli.ts +19 -0
- package/src/commands/agentboard.ts +264 -217
- package/src/commands/auto-claude/index.ts +74 -91
- package/src/commands/auto-claude/list.ts +33 -43
- package/src/commands/auto-claude/retry.test.ts +10 -6
- package/src/commands/auto-claude/retry.ts +26 -39
- package/src/commands/auto-claude/status.ts +10 -17
- package/src/commands/config.test.ts +4 -10
- package/src/commands/config.ts +14 -28
- package/src/commands/doctor.ts +156 -178
- package/src/commands/gh/branch-clean.ts +28 -43
- package/src/commands/gh/branch.ts +22 -37
- package/src/commands/gh/index.ts +10 -0
- package/src/commands/gh/pr.ts +82 -100
- package/src/commands/graph/index.ts +59 -70
- package/src/commands/install.ts +91 -115
- package/src/commands/journal/daily-notes.ts +16 -24
- package/src/commands/journal/index.ts +10 -0
- package/src/commands/journal/meeting.ts +16 -34
- package/src/commands/journal/note.ts +16 -34
- package/src/commands/shared.ts +21 -0
- package/src/lib/auto-claude/templates.test.ts +16 -11
- package/src/lib/graph/parser.test.ts +11 -10
- package/src/utils/git/gh-cli-wrapper.test.ts +6 -5
- package/src/commands/base.ts +0 -32
|
@@ -2,10 +2,10 @@ import { rmSync, writeFileSync, mkdirSync } from "node:fs";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { defineCommand } from "citty";
|
|
6
6
|
import consola from "consola";
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { debugArg } from "../shared.js";
|
|
9
9
|
import {
|
|
10
10
|
STEP_NAMES,
|
|
11
11
|
fetchIssue,
|
|
@@ -21,95 +21,75 @@ import {
|
|
|
21
21
|
} from "../../lib/auto-claude/index.js";
|
|
22
22
|
import type { IssueContext, StepName } from "../../lib/auto-claude/index.js";
|
|
23
23
|
|
|
24
|
-
export default
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
static override args = {
|
|
30
|
-
prompt: Args.string({
|
|
31
|
-
description: "Run a single prompt (skips issue pipeline)",
|
|
24
|
+
export default defineCommand({
|
|
25
|
+
meta: { name: "auto-claude", description: "Automated issue-to-PR pipeline using Claude Code" },
|
|
26
|
+
args: {
|
|
27
|
+
prompt: {
|
|
28
|
+
type: "positional" as const,
|
|
32
29
|
required: false,
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
static override examples = [
|
|
37
|
-
{
|
|
38
|
-
description: "Run a single prompt",
|
|
39
|
-
command: '<%= config.bin %> auto-claude "Fix the login bug in auth.ts"',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
description: "Process a specific issue",
|
|
43
|
-
command: "<%= config.bin %> auto-claude --issue 42",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
description: "Run until plan step",
|
|
47
|
-
command: "<%= config.bin %> auto-claude --issue 42 --until plan",
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
description: "Reset local state for an issue",
|
|
51
|
-
command: "<%= config.bin %> auto-claude --reset 42",
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
description: "Loop mode: poll for labeled issues",
|
|
55
|
-
command: "<%= config.bin %> auto-claude --loop",
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
description: "Loop with custom interval",
|
|
59
|
-
command: "<%= config.bin %> auto-claude --loop --interval 45",
|
|
30
|
+
description: "Run a single prompt (skips issue pipeline)",
|
|
60
31
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
...BaseCommand.baseFlags,
|
|
65
|
-
"max-turns": Flags.integer({
|
|
32
|
+
debug: debugArg,
|
|
33
|
+
"max-turns": {
|
|
34
|
+
type: "string" as const,
|
|
66
35
|
description: "Maximum conversation turns for prompt mode (default: 10)",
|
|
67
|
-
default: 10,
|
|
68
|
-
}
|
|
69
|
-
issue:
|
|
70
|
-
|
|
36
|
+
default: "10",
|
|
37
|
+
},
|
|
38
|
+
issue: {
|
|
39
|
+
type: "string" as const,
|
|
40
|
+
alias: "i",
|
|
71
41
|
description: "Process a specific issue number",
|
|
72
|
-
}
|
|
73
|
-
until:
|
|
74
|
-
|
|
42
|
+
},
|
|
43
|
+
until: {
|
|
44
|
+
type: "string" as const,
|
|
45
|
+
alias: "u",
|
|
75
46
|
description: `Stop after this step (${STEP_NAMES.join(", ")})`,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
47
|
+
},
|
|
48
|
+
reset: {
|
|
49
|
+
type: "string" as const,
|
|
79
50
|
description: "Delete local state for an issue (force restart)",
|
|
80
|
-
}
|
|
81
|
-
model:
|
|
51
|
+
},
|
|
52
|
+
model: {
|
|
53
|
+
type: "string" as const,
|
|
82
54
|
description: "Claude model to use (default: opus)",
|
|
83
55
|
default: "opus",
|
|
84
|
-
}
|
|
85
|
-
loop:
|
|
56
|
+
},
|
|
57
|
+
loop: {
|
|
58
|
+
type: "boolean" as const,
|
|
86
59
|
description: "Poll for labeled issues continuously",
|
|
87
60
|
default: false,
|
|
88
|
-
}
|
|
89
|
-
interval:
|
|
61
|
+
},
|
|
62
|
+
interval: {
|
|
63
|
+
type: "string" as const,
|
|
90
64
|
description: "Poll interval in minutes (default: 30)",
|
|
91
|
-
}
|
|
92
|
-
limit:
|
|
65
|
+
},
|
|
66
|
+
limit: {
|
|
67
|
+
type: "string" as const,
|
|
93
68
|
description: "Max issues per iteration (default: 1)",
|
|
94
|
-
default: 1,
|
|
95
|
-
}
|
|
96
|
-
label:
|
|
69
|
+
default: "1",
|
|
70
|
+
},
|
|
71
|
+
label: {
|
|
72
|
+
type: "string" as const,
|
|
97
73
|
description: "Trigger label (default: auto-claude)",
|
|
98
|
-
}
|
|
99
|
-
"main-branch":
|
|
74
|
+
},
|
|
75
|
+
"main-branch": {
|
|
76
|
+
type: "string" as const,
|
|
100
77
|
description: "Override main branch detection",
|
|
101
|
-
}
|
|
102
|
-
"scope-path":
|
|
78
|
+
},
|
|
79
|
+
"scope-path": {
|
|
80
|
+
type: "string" as const,
|
|
103
81
|
description: "Path within repo to scope work (default: .)",
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
subCommands: {
|
|
85
|
+
list: () => import("./list.js").then((m) => m.default),
|
|
86
|
+
status: () => import("./status.js").then((m) => m.default),
|
|
87
|
+
retry: () => import("./retry.js").then((m) => m.default),
|
|
88
|
+
},
|
|
89
|
+
async run({ args }) {
|
|
110
90
|
// Prompt mode: run a single prompt with structured output, skip issue pipeline
|
|
111
91
|
if (args.prompt) {
|
|
112
|
-
await initConfig({ model:
|
|
92
|
+
await initConfig({ model: args.model });
|
|
113
93
|
|
|
114
94
|
const promptDir = join(tmpdir(), "tt-auto-claude");
|
|
115
95
|
mkdirSync(promptDir, { recursive: true });
|
|
@@ -118,41 +98,44 @@ export default class AutoClaude extends BaseCommand {
|
|
|
118
98
|
|
|
119
99
|
const result = await runClaude({
|
|
120
100
|
promptFile,
|
|
121
|
-
maxTurns:
|
|
101
|
+
maxTurns: Number(args["max-turns"]),
|
|
122
102
|
});
|
|
123
103
|
|
|
124
104
|
if (result.is_error) {
|
|
125
|
-
|
|
105
|
+
consola.error("Claude reported an error");
|
|
106
|
+
process.exit(1);
|
|
126
107
|
}
|
|
127
108
|
return;
|
|
128
109
|
}
|
|
129
110
|
|
|
130
111
|
// Issue pipeline mode
|
|
131
112
|
const cfg = await initConfig({
|
|
132
|
-
triggerLabel:
|
|
133
|
-
mainBranch:
|
|
134
|
-
scopePath:
|
|
135
|
-
model:
|
|
113
|
+
triggerLabel: args.label,
|
|
114
|
+
mainBranch: args["main-branch"],
|
|
115
|
+
scopePath: args["scope-path"],
|
|
116
|
+
model: args.model,
|
|
136
117
|
});
|
|
137
118
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
119
|
+
const resetIssue = args.reset ? Number(args.reset) : undefined;
|
|
120
|
+
if (resetIssue) {
|
|
121
|
+
const issueDir = join(process.cwd(), `.auto-claude/issue-${resetIssue}`);
|
|
122
|
+
log(`Resetting state for issue-${resetIssue}...`);
|
|
141
123
|
rmSync(issueDir, { recursive: true, force: true });
|
|
142
124
|
log(`Cleaned ${issueDir}`);
|
|
143
125
|
return;
|
|
144
126
|
}
|
|
145
127
|
|
|
146
|
-
const untilStep =
|
|
147
|
-
const loopMode =
|
|
148
|
-
const intervalMs = (
|
|
149
|
-
const limit =
|
|
128
|
+
const untilStep = args.until as StepName | undefined;
|
|
129
|
+
const loopMode = args.loop as boolean;
|
|
130
|
+
const intervalMs = (args.interval ? Number(args.interval) : cfg.loopIntervalMinutes) * 60_000;
|
|
131
|
+
const limit = Number(args.limit);
|
|
150
132
|
|
|
151
133
|
if (loopMode) {
|
|
152
134
|
registerShutdownHandlers();
|
|
153
135
|
log(`Loop mode — interval: ${intervalMs / 60_000}min, limit: ${limit}`);
|
|
154
136
|
}
|
|
155
137
|
|
|
138
|
+
const issueNumber = args.issue ? Number(args.issue) : undefined;
|
|
156
139
|
let iteration = 0;
|
|
157
140
|
|
|
158
141
|
do {
|
|
@@ -177,8 +160,8 @@ export default class AutoClaude extends BaseCommand {
|
|
|
177
160
|
|
|
178
161
|
log("Fetching labeled issues…");
|
|
179
162
|
let contexts: IssueContext[];
|
|
180
|
-
if (
|
|
181
|
-
const ctx = await fetchIssue(
|
|
163
|
+
if (issueNumber) {
|
|
164
|
+
const ctx = await fetchIssue(issueNumber);
|
|
182
165
|
contexts = ctx ? [ctx] : [];
|
|
183
166
|
} else {
|
|
184
167
|
contexts = await fetchIssues(limit);
|
|
@@ -212,8 +195,8 @@ export default class AutoClaude extends BaseCommand {
|
|
|
212
195
|
} while (loopMode);
|
|
213
196
|
|
|
214
197
|
log("Done.");
|
|
215
|
-
}
|
|
216
|
-
}
|
|
198
|
+
},
|
|
199
|
+
});
|
|
217
200
|
|
|
218
201
|
async function syncWithRemote(): Promise<void> {
|
|
219
202
|
const cfg = getConfig();
|
|
@@ -1,61 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
2
|
import consola from "consola";
|
|
3
3
|
import { colors } from "consola/utils";
|
|
4
4
|
import { Fzf } from "fzf";
|
|
5
5
|
import prompts from "prompts";
|
|
6
6
|
import type { Choice } from "prompts";
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { debugArg } from "../shared.js";
|
|
9
9
|
import { buildIssueChoices, computeColumnLayout } from "../gh/branch.js";
|
|
10
10
|
import { STEP_NAMES, fetchIssue, initConfig, runPipeline } from "../../lib/auto-claude/index.js";
|
|
11
11
|
import type { StepName } from "../../lib/auto-claude/index.js";
|
|
12
12
|
import { getIssues, isGithubCliInstalled } from "../../utils/git/gh-cli-wrapper.js";
|
|
13
13
|
import { getTerminalColumns } from "../../utils/render.js";
|
|
14
14
|
|
|
15
|
-
export default
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
description: "Pick an issue and run until plan step",
|
|
25
|
-
command: "<%= config.bin %> auto-claude list --until plan",
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
static override flags = {
|
|
30
|
-
...BaseCommand.baseFlags,
|
|
31
|
-
until: Flags.string({
|
|
32
|
-
char: "u",
|
|
15
|
+
export default defineCommand({
|
|
16
|
+
meta: { name: "list", description: "Interactively pick an auto-claude issue to process" },
|
|
17
|
+
args: {
|
|
18
|
+
debug: debugArg,
|
|
19
|
+
until: {
|
|
20
|
+
type: "string" as const,
|
|
21
|
+
alias: "u",
|
|
33
22
|
description: `Stop after this step (${STEP_NAMES.join(", ")})`,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
},
|
|
24
|
+
label: {
|
|
25
|
+
type: "string" as const,
|
|
37
26
|
description: "Trigger label (default: auto-claude)",
|
|
38
|
-
}
|
|
39
|
-
"main-branch":
|
|
27
|
+
},
|
|
28
|
+
"main-branch": {
|
|
29
|
+
type: "string" as const,
|
|
40
30
|
description: "Override main branch detection",
|
|
41
|
-
}
|
|
42
|
-
"scope-path":
|
|
31
|
+
},
|
|
32
|
+
"scope-path": {
|
|
33
|
+
type: "string" as const,
|
|
43
34
|
description: "Path within repo to scope work (default: .)",
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
async run(): Promise<void> {
|
|
48
|
-
const { flags } = await this.parse(AutoClaudeList);
|
|
49
|
-
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
async run({ args }) {
|
|
50
38
|
const cfg = await initConfig({
|
|
51
|
-
triggerLabel:
|
|
52
|
-
mainBranch:
|
|
53
|
-
scopePath:
|
|
39
|
+
triggerLabel: args.label,
|
|
40
|
+
mainBranch: args["main-branch"],
|
|
41
|
+
scopePath: args["scope-path"],
|
|
54
42
|
});
|
|
55
43
|
|
|
56
44
|
const cliInstalled = await isGithubCliInstalled();
|
|
57
45
|
if (!cliInstalled) {
|
|
58
|
-
|
|
46
|
+
consola.error("GitHub CLI (gh) is not installed");
|
|
47
|
+
process.exit(1);
|
|
59
48
|
}
|
|
60
49
|
|
|
61
50
|
const issues = await getIssues({ cwd: process.cwd(), label: cfg.triggerLabel });
|
|
@@ -89,7 +78,7 @@ export default class AutoClaudeList extends BaseCommand {
|
|
|
89
78
|
{
|
|
90
79
|
onCancel: () => {
|
|
91
80
|
consola.info(colors.dim("Canceled"));
|
|
92
|
-
|
|
81
|
+
process.exit(0);
|
|
93
82
|
},
|
|
94
83
|
},
|
|
95
84
|
);
|
|
@@ -101,14 +90,15 @@ export default class AutoClaudeList extends BaseCommand {
|
|
|
101
90
|
|
|
102
91
|
const ctx = await fetchIssue(result.issueNumber);
|
|
103
92
|
if (!ctx) {
|
|
104
|
-
|
|
93
|
+
consola.error(`Could not fetch issue #${result.issueNumber}`);
|
|
94
|
+
process.exit(1);
|
|
105
95
|
}
|
|
106
96
|
|
|
107
|
-
const untilStep =
|
|
97
|
+
const untilStep = args.until as StepName | undefined;
|
|
108
98
|
await runPipeline(ctx, untilStep);
|
|
109
99
|
} catch (e) {
|
|
110
100
|
consola.error(e);
|
|
111
|
-
|
|
101
|
+
process.exit(1);
|
|
112
102
|
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
103
|
+
},
|
|
104
|
+
});
|
|
@@ -5,6 +5,8 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import consola from "consola";
|
|
6
6
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
7
7
|
|
|
8
|
+
import type { Mock } from "vitest";
|
|
9
|
+
|
|
8
10
|
import type { ExecSafeFn } from "../../lib/auto-claude/labels.js";
|
|
9
11
|
import { LABELS } from "../../lib/auto-claude/labels.js";
|
|
10
12
|
import { retryIssues } from "./retry.js";
|
|
@@ -12,15 +14,17 @@ import { retryIssues } from "./retry.js";
|
|
|
12
14
|
// Suppress consola output during tests
|
|
13
15
|
consola.level = -999;
|
|
14
16
|
|
|
15
|
-
const mockExecSafe
|
|
17
|
+
const mockExecSafe = vi.fn().mockResolvedValue({ stdout: "", ok: true }) as Mock & ExecSafeFn;
|
|
16
18
|
|
|
17
19
|
function getGhEditCalls() {
|
|
18
|
-
return
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
return mockExecSafe.mock.calls
|
|
21
|
+
.filter(
|
|
22
|
+
(call: unknown[]) =>
|
|
23
|
+
call[0] === "gh" &&
|
|
24
|
+
(call[1] as string[])?.[0] === "issue" &&
|
|
25
|
+
(call[1] as string[])?.[1] === "edit",
|
|
22
26
|
)
|
|
23
|
-
.map(([
|
|
27
|
+
.map((call: unknown[]) => call[1] as string[]);
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
describe("retryIssues", () => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { rmSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
5
|
import consola from "consola";
|
|
6
6
|
import { colors } from "consola/utils";
|
|
7
7
|
import prompts from "prompts";
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { debugArg } from "../shared.js";
|
|
10
10
|
import { initConfig } from "../../lib/auto-claude/index.js";
|
|
11
11
|
import { LABELS, removeLabel, setLabel } from "../../lib/auto-claude/labels.js";
|
|
12
12
|
import type { ExecSafeFn } from "../../lib/auto-claude/labels.js";
|
|
@@ -47,54 +47,41 @@ export async function retryIssues(
|
|
|
47
47
|
return selected.length;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export default
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
description: "Retry a specific issue",
|
|
60
|
-
command: "<%= config.bin %> auto-claude retry --issue 42",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
description: "Retry and clean local artifacts",
|
|
64
|
-
command: "<%= config.bin %> auto-claude retry --issue 42 --clean",
|
|
65
|
-
},
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
static override flags = {
|
|
69
|
-
...BaseCommand.baseFlags,
|
|
70
|
-
issue: Flags.integer({
|
|
71
|
-
char: "i",
|
|
50
|
+
export default defineCommand({
|
|
51
|
+
meta: { name: "retry", description: "Retry failed auto-claude issues by swapping labels" },
|
|
52
|
+
args: {
|
|
53
|
+
debug: debugArg,
|
|
54
|
+
issue: {
|
|
55
|
+
type: "string" as const,
|
|
56
|
+
alias: "i",
|
|
72
57
|
description: "Issue number to retry",
|
|
73
|
-
}
|
|
74
|
-
clean:
|
|
58
|
+
},
|
|
59
|
+
clean: {
|
|
60
|
+
type: "boolean" as const,
|
|
75
61
|
description: "Delete local .auto-claude/issue-{N}/ artifacts",
|
|
76
62
|
default: false,
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const { flags } = await this.parse(AutoClaudeRetry);
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
async run({ args }) {
|
|
66
|
+
const issueNumber = args.issue ? Number(args.issue) : undefined;
|
|
82
67
|
|
|
83
68
|
const cfg = await initConfig();
|
|
84
69
|
|
|
85
70
|
const cliInstalled = await isGithubCliInstalled();
|
|
86
71
|
if (!cliInstalled) {
|
|
87
|
-
|
|
72
|
+
consola.error("GitHub CLI (gh) is not installed");
|
|
73
|
+
process.exit(1);
|
|
88
74
|
}
|
|
89
75
|
|
|
90
76
|
const failedIssues = await getIssues({ cwd: process.cwd(), label: LABELS.failed });
|
|
91
77
|
|
|
92
78
|
let selected: Issue[];
|
|
93
79
|
|
|
94
|
-
if (
|
|
95
|
-
const match = failedIssues.find((i) => i.number ===
|
|
80
|
+
if (issueNumber) {
|
|
81
|
+
const match = failedIssues.find((i) => i.number === issueNumber);
|
|
96
82
|
if (!match) {
|
|
97
|
-
|
|
83
|
+
consola.error(`Issue #${issueNumber} not found with '${LABELS.failed}' label`);
|
|
84
|
+
process.exit(1);
|
|
98
85
|
}
|
|
99
86
|
selected = [match];
|
|
100
87
|
} else {
|
|
@@ -122,7 +109,7 @@ export default class AutoClaudeRetry extends BaseCommand {
|
|
|
122
109
|
{
|
|
123
110
|
onCancel: () => {
|
|
124
111
|
consola.info(colors.dim("Canceled"));
|
|
125
|
-
|
|
112
|
+
process.exit(0);
|
|
126
113
|
},
|
|
127
114
|
},
|
|
128
115
|
);
|
|
@@ -135,7 +122,7 @@ export default class AutoClaudeRetry extends BaseCommand {
|
|
|
135
122
|
selected = failedIssues.filter((i) => result.selected.includes(i.number));
|
|
136
123
|
}
|
|
137
124
|
|
|
138
|
-
const count = await retryIssues(cfg.repo, cfg.triggerLabel, selected,
|
|
125
|
+
const count = await retryIssues(cfg.repo, cfg.triggerLabel, selected, args.clean as boolean);
|
|
139
126
|
consola.box(`Retried ${count} issue(s)`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
127
|
+
},
|
|
128
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
+
import { defineCommand } from "citty";
|
|
4
5
|
import consola from "consola";
|
|
5
6
|
import { colors } from "consola/utils";
|
|
6
7
|
|
|
@@ -8,7 +9,7 @@ import type { Issue } from "../../utils/git/gh-cli-wrapper.js";
|
|
|
8
9
|
import { getIssues, isGithubCliInstalled } from "../../utils/git/gh-cli-wrapper.js";
|
|
9
10
|
import { ARTIFACTS } from "../../lib/auto-claude/prompt-templates/index.js";
|
|
10
11
|
import { LABELS } from "../../lib/auto-claude/labels.js";
|
|
11
|
-
import {
|
|
12
|
+
import { debugArg } from "../shared.js";
|
|
12
13
|
|
|
13
14
|
/** All labels that indicate an issue is part of the auto-claude pipeline. */
|
|
14
15
|
const ALL_AC_LABELS = ["auto-claude", ...Object.values(LABELS)] as const;
|
|
@@ -86,22 +87,14 @@ export async function fetchAllAcIssues(cwd: string): Promise<Issue[]> {
|
|
|
86
87
|
return [...issueMap.values()].sort((a, b) => a.number - b.number);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
export default
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
static override examples = [
|
|
95
|
-
{
|
|
96
|
-
description: "Show status of all auto-claude issues",
|
|
97
|
-
command: "<%= config.bin %> auto-claude status",
|
|
98
|
-
},
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
async run(): Promise<void> {
|
|
90
|
+
export default defineCommand({
|
|
91
|
+
meta: { name: "status", description: "Show pipeline status for auto-claude issues" },
|
|
92
|
+
args: { debug: debugArg },
|
|
93
|
+
async run() {
|
|
102
94
|
const cliInstalled = await isGithubCliInstalled();
|
|
103
95
|
if (!cliInstalled) {
|
|
104
|
-
|
|
96
|
+
consola.error("GitHub CLI (gh) is not installed");
|
|
97
|
+
process.exit(1);
|
|
105
98
|
}
|
|
106
99
|
|
|
107
100
|
const cwd = process.cwd();
|
|
@@ -119,5 +112,5 @@ export default class AutoClaudeStatus extends BaseCommand {
|
|
|
119
112
|
const artifacts = checkArtifacts(issue.number, cwd);
|
|
120
113
|
consola.log(formatIssueStatus(issue, artifacts));
|
|
121
114
|
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
115
|
+
},
|
|
116
|
+
});
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration tests for oclif config command
|
|
3
|
-
* Note: consola outputs to stderr with different log levels
|
|
4
|
-
*/
|
|
5
1
|
import { describe, it, expect } from "vitest";
|
|
6
|
-
import { runCommand } from "
|
|
2
|
+
import { runCommand } from "citty";
|
|
7
3
|
|
|
8
4
|
describe("config command", () => {
|
|
9
|
-
it("runs config
|
|
10
|
-
const {
|
|
11
|
-
|
|
12
|
-
expect(stderr).toContain("User Config");
|
|
13
|
-
expect(stderr).toContain("Working Directory");
|
|
5
|
+
it("runs config without throwing", async () => {
|
|
6
|
+
const { default: configCmd } = await import("./config.js");
|
|
7
|
+
await expect(runCommand(configCmd, { rawArgs: [] })).resolves.toBeDefined();
|
|
14
8
|
});
|
|
15
9
|
});
|
package/src/commands/config.ts
CHANGED
|
@@ -1,42 +1,28 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
1
2
|
import consola from "consola";
|
|
2
|
-
import {
|
|
3
|
+
import { withSettings, debugArg } from "./shared.js";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
static override examples = [
|
|
11
|
-
{ description: "Display configuration", command: "<%= config.bin %> <%= command.id %>" },
|
|
12
|
-
{ description: "Use alias", command: "<%= config.bin %> cfg" },
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
async run(): Promise<void> {
|
|
16
|
-
await this.parse(Config);
|
|
5
|
+
export default defineCommand({
|
|
6
|
+
meta: { name: "config", description: "Display current configuration settings" },
|
|
7
|
+
args: { debug: debugArg },
|
|
8
|
+
async run({ args }) {
|
|
9
|
+
const { settingsFile, settings } = await withSettings(args.debug);
|
|
17
10
|
|
|
18
11
|
consola.info("Configuration");
|
|
19
12
|
consola.log("");
|
|
20
13
|
|
|
21
|
-
consola.info(`Settings File: ${
|
|
14
|
+
consola.info(`Settings File: ${settingsFile.path}`);
|
|
22
15
|
consola.log("");
|
|
23
16
|
|
|
24
17
|
consola.warn("User Config:");
|
|
25
|
-
consola.log(` Daily Path Template: ${
|
|
26
|
-
consola.log(
|
|
27
|
-
|
|
28
|
-
);
|
|
29
|
-
consola.log(` Note Path Template: ${this.userSettings.journalSettings.notePathTemplate}`);
|
|
30
|
-
consola.log(` Editor: ${this.userSettings.preferredEditor}`);
|
|
18
|
+
consola.log(` Daily Path Template: ${settings.journalSettings.dailyPathTemplate}`);
|
|
19
|
+
consola.log(` Meeting Path Template: ${settings.journalSettings.meetingPathTemplate}`);
|
|
20
|
+
consola.log(` Note Path Template: ${settings.journalSettings.notePathTemplate}`);
|
|
21
|
+
consola.log(` Editor: ${settings.preferredEditor}`);
|
|
31
22
|
consola.log("");
|
|
32
23
|
|
|
33
24
|
consola.warn("Working Directory:");
|
|
34
25
|
consola.log(` ${process.cwd()}`);
|
|
35
26
|
consola.log("");
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
consola.log(" Run `tt completion` to generate shell completions");
|
|
39
|
-
consola.log(" Bash/Zsh: tt completion >> ~/.bashrc (or ~/.zshrc)");
|
|
40
|
-
consola.log(" Fish: tt completion > ~/.config/fish/completions/tt.fish");
|
|
41
|
-
}
|
|
42
|
-
}
|
|
27
|
+
},
|
|
28
|
+
});
|