@inteeka/task-cli 0.1.11 → 0.1.13
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/cli.js +174 -19
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -78,6 +78,23 @@ var PRODUCTION_HOSTS = {
|
|
|
78
78
|
};
|
|
79
79
|
var ALL_VALID_HOSTS = [PRODUCTION_HOSTS.PRIMARY, PRODUCTION_HOSTS.VERCEL];
|
|
80
80
|
|
|
81
|
+
// ../../packages/constants/src/ai.ts
|
|
82
|
+
var ANTHROPIC_DEFAULT_MODEL = "claude-sonnet-4-6";
|
|
83
|
+
var ANTHROPIC_HEAVY_MODEL = "claude-opus-4-7";
|
|
84
|
+
var CLI_FIX_MODELS = [
|
|
85
|
+
{
|
|
86
|
+
id: ANTHROPIC_DEFAULT_MODEL,
|
|
87
|
+
label: "Sonnet 4.6",
|
|
88
|
+
description: "Default \u2014 fast, cheap, right for most fixes."
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: ANTHROPIC_HEAVY_MODEL,
|
|
92
|
+
label: "Opus 4.7",
|
|
93
|
+
description: "Heavy reasoning \u2014 pick for cross-cutting refactors or tricky bugs."
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
var CLI_FIX_MODEL_IDS = CLI_FIX_MODELS.map((m) => m.id);
|
|
97
|
+
|
|
81
98
|
// ../../packages/constants/src/cli.ts
|
|
82
99
|
var CLI_DEFAULT_PROTECTED_PATHS = Object.freeze([
|
|
83
100
|
// Package manifests + lockfiles
|
|
@@ -2711,6 +2728,143 @@ function clampInt(raw, min, max, fallback) {
|
|
|
2711
2728
|
return Math.min(v, max);
|
|
2712
2729
|
}
|
|
2713
2730
|
|
|
2731
|
+
// src/commands/pr-test.ts
|
|
2732
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
2733
|
+
function registerPrTest(program2) {
|
|
2734
|
+
program2.command("pr-test").description(
|
|
2735
|
+
"Dry-run the full PR pipeline \u2014 cuts a throwaway branch, opens a real PR via the dashboard, then cleans up. Use this to verify your git integration before running task work on real tickets."
|
|
2736
|
+
).option(
|
|
2737
|
+
"--keep",
|
|
2738
|
+
"Leave the PR open and the branches in place after the test (default: clean up)"
|
|
2739
|
+
).option("--silent", "Suppress per-step progress output").action(async (opts) => {
|
|
2740
|
+
await runPrTest(opts);
|
|
2741
|
+
});
|
|
2742
|
+
}
|
|
2743
|
+
async function runPrTest(opts) {
|
|
2744
|
+
const cwd = findRepoRoot();
|
|
2745
|
+
const project = await readProjectConfig(cwd);
|
|
2746
|
+
if (!project) {
|
|
2747
|
+
throw new CliError(
|
|
2748
|
+
CLI_EXIT_CODES.MISCONFIGURATION,
|
|
2749
|
+
"No project link in this repo",
|
|
2750
|
+
"Run 'task link' first."
|
|
2751
|
+
);
|
|
2752
|
+
}
|
|
2753
|
+
const baseBranch = project.cli_base_branch ?? "development";
|
|
2754
|
+
const silent = !!opts.silent;
|
|
2755
|
+
if (!silent) process.stdout.write(`${c.dim(`Step 1/6: assertBaseBranch (${baseBranch})\u2026`)}
|
|
2756
|
+
`);
|
|
2757
|
+
assertBaseBranch(cwd, baseBranch);
|
|
2758
|
+
const timestamp = Date.now();
|
|
2759
|
+
const branchName = `task/pr-test-${timestamp}`;
|
|
2760
|
+
const prTitle = `[task pr-test] CLI dry-run probe ${new Date(timestamp).toISOString()}`;
|
|
2761
|
+
if (!silent) process.stdout.write(`${c.dim(`Step 2/6: createTicketBranch (${branchName})\u2026`)}
|
|
2762
|
+
`);
|
|
2763
|
+
createTicketBranch(cwd, branchName, baseBranch);
|
|
2764
|
+
let pushSucceeded = false;
|
|
2765
|
+
const recover = () => {
|
|
2766
|
+
try {
|
|
2767
|
+
checkoutBranch(cwd, baseBranch);
|
|
2768
|
+
} catch {
|
|
2769
|
+
}
|
|
2770
|
+
deleteLocalBranch(cwd, branchName);
|
|
2771
|
+
};
|
|
2772
|
+
try {
|
|
2773
|
+
if (!silent) process.stdout.write(`${c.dim("Step 3/6: empty commit\u2026")}
|
|
2774
|
+
`);
|
|
2775
|
+
execFileSync6(
|
|
2776
|
+
"git",
|
|
2777
|
+
["commit", "--allow-empty", "-m", `task pr-test: connectivity probe ${timestamp}`],
|
|
2778
|
+
{ cwd, stdio: ["ignore", "pipe", "pipe"] }
|
|
2779
|
+
);
|
|
2780
|
+
if (!silent) process.stdout.write(`${c.dim(`Step 4/6: pushBranch (${branchName})\u2026`)}
|
|
2781
|
+
`);
|
|
2782
|
+
pushBranch(cwd, branchName);
|
|
2783
|
+
pushSucceeded = true;
|
|
2784
|
+
if (!silent) process.stdout.write(`${c.dim("Step 5/6: open PR via dashboard\u2026")}
|
|
2785
|
+
`);
|
|
2786
|
+
const pr = await apiCallOrThrow("POST", `/api/v1/cli/me/git/pr-test`, {
|
|
2787
|
+
body: {
|
|
2788
|
+
project_id: project.project_id,
|
|
2789
|
+
source_branch: branchName,
|
|
2790
|
+
base_branch: baseBranch,
|
|
2791
|
+
title: prTitle
|
|
2792
|
+
}
|
|
2793
|
+
});
|
|
2794
|
+
process.stdout.write(
|
|
2795
|
+
`
|
|
2796
|
+
${c.ok("\u2713 PR opened")} ${c.cyan(pr.pr_url)}
|
|
2797
|
+
repo: ${pr.repo}
|
|
2798
|
+
branch: ${pr.source_branch} \u2192 ${pr.base_branch}
|
|
2799
|
+
number: #${pr.pr_number}
|
|
2800
|
+
|
|
2801
|
+
`
|
|
2802
|
+
);
|
|
2803
|
+
if (opts.keep) {
|
|
2804
|
+
process.stdout.write(
|
|
2805
|
+
`${c.warn("--keep")} ${c.dim("flag set \u2014 PR and branches preserved. Manual cleanup:")}
|
|
2806
|
+
${c.cyan(`task pr-test-cleanup ${pr.pr_number} ${branchName}`)}
|
|
2807
|
+
(or close on GitHub + ${c.cyan(`git push origin --delete ${branchName}`)} + ${c.cyan(`git branch -D ${branchName}`)})
|
|
2808
|
+
`
|
|
2809
|
+
);
|
|
2810
|
+
checkoutBranch(cwd, baseBranch);
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
if (!silent) process.stdout.write(`${c.dim("Step 6/6: cleanup\u2026")}
|
|
2814
|
+
`);
|
|
2815
|
+
const cleanup = await apiCall("POST", `/api/v1/cli/me/git/pr-test/cleanup`, {
|
|
2816
|
+
body: {
|
|
2817
|
+
project_id: project.project_id,
|
|
2818
|
+
pr_number: pr.pr_number,
|
|
2819
|
+
source_branch: branchName
|
|
2820
|
+
}
|
|
2821
|
+
});
|
|
2822
|
+
checkoutBranch(cwd, baseBranch);
|
|
2823
|
+
deleteLocalBranch(cwd, branchName);
|
|
2824
|
+
if (cleanup.ok && cleanup.data) {
|
|
2825
|
+
const { pr_closed, branch_deleted } = cleanup.data;
|
|
2826
|
+
process.stdout.write(
|
|
2827
|
+
`${c.ok("\u2713 Cleanup complete")} \u2014 PR ${pr_closed ? "closed" : c.warn("NOT closed")}, remote branch ${branch_deleted ? "deleted" : c.warn("NOT deleted")}, local branch deleted.
|
|
2828
|
+
`
|
|
2829
|
+
);
|
|
2830
|
+
if (!pr_closed || !branch_deleted) {
|
|
2831
|
+
process.stdout.write(
|
|
2832
|
+
c.dim(` Manually close at: ${pr.pr_url}
|
|
2833
|
+
`) + c.dim(` Manually delete remote: git push origin --delete ${branchName}
|
|
2834
|
+
`)
|
|
2835
|
+
);
|
|
2836
|
+
}
|
|
2837
|
+
} else {
|
|
2838
|
+
process.stdout.write(
|
|
2839
|
+
`${c.warn("Cleanup endpoint failed \u2014 branches & PR may need manual cleanup:")}
|
|
2840
|
+
${c.cyan(pr.pr_url)}
|
|
2841
|
+
${c.cyan(`git push origin --delete ${branchName}`)}
|
|
2842
|
+
`
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
process.stdout.write(
|
|
2846
|
+
`
|
|
2847
|
+
${c.ok("\u2713 pr-test passed")} \u2014 the full CLI \u2192 dashboard \u2192 GitHub PR pipeline works.
|
|
2848
|
+
`
|
|
2849
|
+
);
|
|
2850
|
+
} catch (err) {
|
|
2851
|
+
process.stdout.write(`
|
|
2852
|
+
${c.err("\u2717 pr-test failed")}: ${err.message}
|
|
2853
|
+
`);
|
|
2854
|
+
if (pushSucceeded) {
|
|
2855
|
+
process.stdout.write(
|
|
2856
|
+
c.dim(
|
|
2857
|
+
` The branch was pushed but the PR step failed. Manually clean up:
|
|
2858
|
+
git push origin --delete ${branchName}
|
|
2859
|
+
`
|
|
2860
|
+
)
|
|
2861
|
+
);
|
|
2862
|
+
}
|
|
2863
|
+
recover();
|
|
2864
|
+
throw err;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2714
2868
|
// src/commands/scheduled-task.ts
|
|
2715
2869
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2716
2870
|
|
|
@@ -2721,7 +2875,7 @@ import { platform as platform2 } from "os";
|
|
|
2721
2875
|
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile8, unlink as unlink3, readdir } from "fs/promises";
|
|
2722
2876
|
import { homedir as homedir6 } from "os";
|
|
2723
2877
|
import { join as join8 } from "path";
|
|
2724
|
-
import { execFileSync as
|
|
2878
|
+
import { execFileSync as execFileSync7, spawn as spawn4 } from "child_process";
|
|
2725
2879
|
|
|
2726
2880
|
// src/scheduler/cron-translate.ts
|
|
2727
2881
|
function translateToLaunchd(cron) {
|
|
@@ -2889,17 +3043,17 @@ var launchdAdapter = {
|
|
|
2889
3043
|
const path = plistPath(entry.id);
|
|
2890
3044
|
await writeFile8(path, buildPlist(entry));
|
|
2891
3045
|
try {
|
|
2892
|
-
|
|
3046
|
+
execFileSync7("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2893
3047
|
} catch {
|
|
2894
3048
|
}
|
|
2895
3049
|
if (entry.enabled) {
|
|
2896
|
-
|
|
3050
|
+
execFileSync7("launchctl", ["bootstrap", bootstrapDomain(), path]);
|
|
2897
3051
|
}
|
|
2898
3052
|
},
|
|
2899
3053
|
async remove(id) {
|
|
2900
3054
|
const path = plistPath(id);
|
|
2901
3055
|
try {
|
|
2902
|
-
|
|
3056
|
+
execFileSync7("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2903
3057
|
} catch {
|
|
2904
3058
|
}
|
|
2905
3059
|
try {
|
|
@@ -2964,10 +3118,10 @@ var launchdAdapter = {
|
|
|
2964
3118
|
xml = xml.replace(/\s*<key>Disabled<\/key>\s*<true\/>/, "");
|
|
2965
3119
|
await writeFile8(path, xml);
|
|
2966
3120
|
try {
|
|
2967
|
-
|
|
3121
|
+
execFileSync7("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2968
3122
|
} catch {
|
|
2969
3123
|
}
|
|
2970
|
-
|
|
3124
|
+
execFileSync7("launchctl", ["bootstrap", bootstrapDomain(), path]);
|
|
2971
3125
|
} else {
|
|
2972
3126
|
if (!/<key>Disabled<\/key>/.test(xml)) {
|
|
2973
3127
|
xml = xml.replace(
|
|
@@ -2977,7 +3131,7 @@ var launchdAdapter = {
|
|
|
2977
3131
|
await writeFile8(path, xml);
|
|
2978
3132
|
}
|
|
2979
3133
|
try {
|
|
2980
|
-
|
|
3134
|
+
execFileSync7("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2981
3135
|
} catch {
|
|
2982
3136
|
}
|
|
2983
3137
|
}
|
|
@@ -2985,7 +3139,7 @@ var launchdAdapter = {
|
|
|
2985
3139
|
};
|
|
2986
3140
|
|
|
2987
3141
|
// src/scheduler/cron.ts
|
|
2988
|
-
import { execFileSync as
|
|
3142
|
+
import { execFileSync as execFileSync8, spawn as spawn5 } from "child_process";
|
|
2989
3143
|
|
|
2990
3144
|
// src/scheduler/safe-command.ts
|
|
2991
3145
|
var FORBIDDEN = /[;&|`$()<>\\]/;
|
|
@@ -3040,7 +3194,7 @@ var MARK_OPEN = (id) => `# task-cli:${id}:start`;
|
|
|
3040
3194
|
var MARK_CLOSE = (id) => `# task-cli:${id}:end`;
|
|
3041
3195
|
function readCrontab() {
|
|
3042
3196
|
try {
|
|
3043
|
-
return
|
|
3197
|
+
return execFileSync8("crontab", ["-l"], { encoding: "utf8" });
|
|
3044
3198
|
} catch {
|
|
3045
3199
|
return "";
|
|
3046
3200
|
}
|
|
@@ -3155,7 +3309,7 @@ var cronAdapter = {
|
|
|
3155
3309
|
};
|
|
3156
3310
|
|
|
3157
3311
|
// src/scheduler/windows.ts
|
|
3158
|
-
import { execFileSync as
|
|
3312
|
+
import { execFileSync as execFileSync9, spawn as spawn6 } from "child_process";
|
|
3159
3313
|
var TASK_PREFIX = "TaskCLI_";
|
|
3160
3314
|
function taskName(id) {
|
|
3161
3315
|
return `${TASK_PREFIX}${id.replace(/[^A-Za-z0-9_-]/g, "_")}`;
|
|
@@ -3220,22 +3374,22 @@ function pad(v) {
|
|
|
3220
3374
|
var windowsAdapter = {
|
|
3221
3375
|
async upsert(entry) {
|
|
3222
3376
|
const args = buildSchtasksArgs(entry, entry.command);
|
|
3223
|
-
|
|
3377
|
+
execFileSync9("schtasks.exe", args, { stdio: "ignore" });
|
|
3224
3378
|
if (!entry.enabled) {
|
|
3225
|
-
|
|
3379
|
+
execFileSync9("schtasks.exe", ["/Change", "/TN", taskName(entry.id), "/DISABLE"], {
|
|
3226
3380
|
stdio: "ignore"
|
|
3227
3381
|
});
|
|
3228
3382
|
}
|
|
3229
3383
|
},
|
|
3230
3384
|
async remove(id) {
|
|
3231
3385
|
try {
|
|
3232
|
-
|
|
3386
|
+
execFileSync9("schtasks.exe", ["/Delete", "/TN", taskName(id), "/F"], { stdio: "ignore" });
|
|
3233
3387
|
} catch {
|
|
3234
3388
|
}
|
|
3235
3389
|
},
|
|
3236
3390
|
async list() {
|
|
3237
3391
|
try {
|
|
3238
|
-
const csv =
|
|
3392
|
+
const csv = execFileSync9("schtasks.exe", ["/Query", "/FO", "CSV", "/V"], {
|
|
3239
3393
|
encoding: "utf8"
|
|
3240
3394
|
});
|
|
3241
3395
|
const lines = csv.split(/\r?\n/);
|
|
@@ -3285,7 +3439,7 @@ var windowsAdapter = {
|
|
|
3285
3439
|
},
|
|
3286
3440
|
async setEnabled(id, enabled) {
|
|
3287
3441
|
try {
|
|
3288
|
-
|
|
3442
|
+
execFileSync9(
|
|
3289
3443
|
"schtasks.exe",
|
|
3290
3444
|
["/Change", "/TN", taskName(id), enabled ? "/ENABLE" : "/DISABLE"],
|
|
3291
3445
|
{ stdio: "ignore" }
|
|
@@ -3693,7 +3847,7 @@ function registerConfig(program2) {
|
|
|
3693
3847
|
}
|
|
3694
3848
|
|
|
3695
3849
|
// src/commands/doctor.ts
|
|
3696
|
-
import { execFileSync as
|
|
3850
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
3697
3851
|
import { request as request5 } from "undici";
|
|
3698
3852
|
function registerDoctor(program2) {
|
|
3699
3853
|
program2.command("doctor").description("Diagnose your CLI setup").action(async () => {
|
|
@@ -3741,7 +3895,7 @@ function registerDoctor(program2) {
|
|
|
3741
3895
|
});
|
|
3742
3896
|
}
|
|
3743
3897
|
try {
|
|
3744
|
-
const dirty =
|
|
3898
|
+
const dirty = execFileSync10("git", ["status", "--porcelain"], {
|
|
3745
3899
|
cwd: root,
|
|
3746
3900
|
encoding: "utf8"
|
|
3747
3901
|
}).trim();
|
|
@@ -3765,7 +3919,7 @@ function registerDoctor(program2) {
|
|
|
3765
3919
|
}
|
|
3766
3920
|
function checkBinary(name, command) {
|
|
3767
3921
|
try {
|
|
3768
|
-
const out =
|
|
3922
|
+
const out = execFileSync10(command, ["--version"], { encoding: "utf8" }).trim();
|
|
3769
3923
|
return { name, ok: true, detail: out.split("\n")[0] ?? out };
|
|
3770
3924
|
} catch {
|
|
3771
3925
|
return { name, ok: false, detail: `'${command}' not found on PATH` };
|
|
@@ -3773,7 +3927,7 @@ function checkBinary(name, command) {
|
|
|
3773
3927
|
}
|
|
3774
3928
|
|
|
3775
3929
|
// src/commands/version.ts
|
|
3776
|
-
var CLI_VERSION = true ? "0.1.
|
|
3930
|
+
var CLI_VERSION = true ? "0.1.13" : "0.0.0-dev";
|
|
3777
3931
|
function registerVersion(program2) {
|
|
3778
3932
|
program2.command("version").description("Print the CLI version").action(() => {
|
|
3779
3933
|
process.stdout.write(CLI_VERSION + "\n");
|
|
@@ -3797,6 +3951,7 @@ registerTickets(program);
|
|
|
3797
3951
|
registerTicket(program);
|
|
3798
3952
|
registerWork(program);
|
|
3799
3953
|
registerScan(program);
|
|
3954
|
+
registerPrTest(program);
|
|
3800
3955
|
registerScheduledTask(program);
|
|
3801
3956
|
registerRuns(program);
|
|
3802
3957
|
registerConfig(program);
|