@inteeka/task-cli 0.1.4 → 0.1.6
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 +141 -59
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -416,6 +416,9 @@ function sleep(ms) {
|
|
|
416
416
|
|
|
417
417
|
// src/api/client.ts
|
|
418
418
|
import { request as request3 } from "undici";
|
|
419
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
420
|
+
import { homedir as homedir2 } from "os";
|
|
421
|
+
import { join as join2 } from "path";
|
|
419
422
|
|
|
420
423
|
// src/auth/refresh.ts
|
|
421
424
|
import { request as request2 } from "undici";
|
|
@@ -480,6 +483,32 @@ async function manualRefresh() {
|
|
|
480
483
|
}
|
|
481
484
|
|
|
482
485
|
// src/api/client.ts
|
|
486
|
+
async function dumpServerError(method, path, status, rawBody, headers) {
|
|
487
|
+
try {
|
|
488
|
+
const dir = join2(homedir2(), ".cache", "task", "api-debug");
|
|
489
|
+
await mkdir2(dir, { recursive: true });
|
|
490
|
+
const file = join2(dir, `${Date.now()}-${status}.log`);
|
|
491
|
+
const safeHeaders = { ...headers };
|
|
492
|
+
delete safeHeaders["Authorization"];
|
|
493
|
+
delete safeHeaders["authorization"];
|
|
494
|
+
await writeFile2(
|
|
495
|
+
file,
|
|
496
|
+
[
|
|
497
|
+
`## ${method} ${path}`,
|
|
498
|
+
`## status ${status}`,
|
|
499
|
+
"",
|
|
500
|
+
"## request_headers",
|
|
501
|
+
JSON.stringify(safeHeaders, null, 2),
|
|
502
|
+
"",
|
|
503
|
+
"## response_body",
|
|
504
|
+
rawBody || "(empty)"
|
|
505
|
+
].join("\n")
|
|
506
|
+
);
|
|
507
|
+
process.stderr.write(` (server response saved to ${file})
|
|
508
|
+
`);
|
|
509
|
+
} catch {
|
|
510
|
+
}
|
|
511
|
+
}
|
|
483
512
|
async function apiCall(method, path, options = {}) {
|
|
484
513
|
const authenticated = options.authenticated !== false;
|
|
485
514
|
let creds = null;
|
|
@@ -537,19 +566,32 @@ async function apiCall(method, path, options = {}) {
|
|
|
537
566
|
);
|
|
538
567
|
}
|
|
539
568
|
const status = res.statusCode;
|
|
540
|
-
let
|
|
569
|
+
let rawBody;
|
|
541
570
|
try {
|
|
542
|
-
|
|
571
|
+
rawBody = await res.body.text();
|
|
543
572
|
} catch {
|
|
544
|
-
|
|
573
|
+
rawBody = "";
|
|
574
|
+
}
|
|
575
|
+
let parsed;
|
|
576
|
+
if (rawBody) {
|
|
577
|
+
try {
|
|
578
|
+
parsed = JSON.parse(rawBody);
|
|
579
|
+
} catch {
|
|
580
|
+
parsed = void 0;
|
|
581
|
+
}
|
|
545
582
|
}
|
|
546
583
|
if (status >= 200 && status < 300) {
|
|
547
584
|
const body = parsed;
|
|
548
585
|
return { ok: true, status, data: body?.data ?? parsed };
|
|
549
586
|
}
|
|
587
|
+
if (status >= 500) {
|
|
588
|
+
await dumpServerError(method, path, status, rawBody, headers).catch(() => void 0);
|
|
589
|
+
}
|
|
550
590
|
const errBody = parsed;
|
|
551
591
|
const code = errBody?.error?.code ?? `HTTP_${status}`;
|
|
552
|
-
const
|
|
592
|
+
const requestId = errBody?.error?.request_id;
|
|
593
|
+
const baseMessage = errBody?.error?.message ?? `Request failed with status ${status}`;
|
|
594
|
+
const message = requestId ? `${baseMessage} (request_id: ${requestId})` : baseMessage;
|
|
553
595
|
if (status === 401 && (code === "UNAUTHORIZED" || code === "TOKEN_EXPIRED" || code === "INVALID_GRANT")) {
|
|
554
596
|
await clearCredentials();
|
|
555
597
|
throw new CliError(
|
|
@@ -591,10 +633,10 @@ async function apiCallOrThrow(method, path, options = {}) {
|
|
|
591
633
|
}
|
|
592
634
|
|
|
593
635
|
// src/config/local-config.ts
|
|
594
|
-
import { mkdir as
|
|
595
|
-
import { homedir as
|
|
596
|
-
import { dirname as dirname2, join as
|
|
597
|
-
var CONFIG_PATH =
|
|
636
|
+
import { mkdir as mkdir3, readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
|
|
637
|
+
import { homedir as homedir3 } from "os";
|
|
638
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
639
|
+
var CONFIG_PATH = join3(homedir3(), ".config", "task", "config.json");
|
|
598
640
|
var DEFAULT_CONFIG = {
|
|
599
641
|
api_url: process.env["TASK_API_URL"] ?? "http://localhost:3400",
|
|
600
642
|
default_project: null,
|
|
@@ -614,8 +656,8 @@ async function readLocalConfig() {
|
|
|
614
656
|
}
|
|
615
657
|
}
|
|
616
658
|
async function writeLocalConfig(config) {
|
|
617
|
-
await
|
|
618
|
-
await
|
|
659
|
+
await mkdir3(dirname2(CONFIG_PATH), { recursive: true });
|
|
660
|
+
await writeFile3(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
619
661
|
}
|
|
620
662
|
async function setConfigValue(key, value) {
|
|
621
663
|
const cfg = await readLocalConfig();
|
|
@@ -734,14 +776,14 @@ function registerAuthRefresh(program2) {
|
|
|
734
776
|
}
|
|
735
777
|
|
|
736
778
|
// src/commands/link.ts
|
|
737
|
-
import { readFile as readFile4, writeFile as
|
|
779
|
+
import { readFile as readFile4, writeFile as writeFile5, appendFile, access } from "fs/promises";
|
|
738
780
|
import { constants as fsConstants } from "fs";
|
|
739
|
-
import { join as
|
|
781
|
+
import { join as join5 } from "path";
|
|
740
782
|
import inquirer from "inquirer";
|
|
741
783
|
|
|
742
784
|
// src/config/project.ts
|
|
743
|
-
import { mkdir as
|
|
744
|
-
import { dirname as dirname3, join as
|
|
785
|
+
import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile4, unlink as unlink2 } from "fs/promises";
|
|
786
|
+
import { dirname as dirname3, join as join4, resolve } from "path";
|
|
745
787
|
import { execSync } from "child_process";
|
|
746
788
|
function findRepoRoot(start = process.cwd()) {
|
|
747
789
|
try {
|
|
@@ -752,7 +794,7 @@ function findRepoRoot(start = process.cwd()) {
|
|
|
752
794
|
}
|
|
753
795
|
}
|
|
754
796
|
function configPath(repoRoot) {
|
|
755
|
-
return
|
|
797
|
+
return join4(repoRoot ?? findRepoRoot(), ".task", "config.json");
|
|
756
798
|
}
|
|
757
799
|
async function readProjectConfig(repoRoot) {
|
|
758
800
|
const path = configPath(repoRoot);
|
|
@@ -766,8 +808,8 @@ async function readProjectConfig(repoRoot) {
|
|
|
766
808
|
}
|
|
767
809
|
async function writeProjectConfig(config, repoRoot) {
|
|
768
810
|
const path = configPath(repoRoot);
|
|
769
|
-
await
|
|
770
|
-
await
|
|
811
|
+
await mkdir4(dirname3(path), { recursive: true });
|
|
812
|
+
await writeFile4(path, JSON.stringify(config, null, 2));
|
|
771
813
|
}
|
|
772
814
|
async function clearProjectConfig(repoRoot) {
|
|
773
815
|
const path = configPath(repoRoot);
|
|
@@ -864,7 +906,7 @@ async function resolveProject(projects, opts) {
|
|
|
864
906
|
return picked;
|
|
865
907
|
}
|
|
866
908
|
async function ensureGitignored(repoRoot) {
|
|
867
|
-
const gitignorePath =
|
|
909
|
+
const gitignorePath = join5(repoRoot, ".gitignore");
|
|
868
910
|
let existing = null;
|
|
869
911
|
try {
|
|
870
912
|
await access(gitignorePath, fsConstants.F_OK);
|
|
@@ -879,7 +921,7 @@ async function ensureGitignored(repoRoot) {
|
|
|
879
921
|
await appendFile(gitignorePath, block);
|
|
880
922
|
return "added";
|
|
881
923
|
}
|
|
882
|
-
await
|
|
924
|
+
await writeFile5(gitignorePath, "# task CLI link config\n.task/\n");
|
|
883
925
|
return "created";
|
|
884
926
|
}
|
|
885
927
|
|
|
@@ -1108,9 +1150,9 @@ import inquirer2 from "inquirer";
|
|
|
1108
1150
|
|
|
1109
1151
|
// src/agent/agent-service.ts
|
|
1110
1152
|
import { spawn } from "child_process";
|
|
1111
|
-
import { mkdir as
|
|
1112
|
-
import { homedir as
|
|
1113
|
-
import { join as
|
|
1153
|
+
import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
|
|
1154
|
+
import { homedir as homedir4 } from "os";
|
|
1155
|
+
import { join as join6 } from "path";
|
|
1114
1156
|
|
|
1115
1157
|
// src/agent/allowed-tools.ts
|
|
1116
1158
|
var ALLOWED_TOOLS = CLI_ALLOWED_TOOLS;
|
|
@@ -1167,10 +1209,10 @@ async function runAgent(args) {
|
|
|
1167
1209
|
let outputLogPath = null;
|
|
1168
1210
|
let logHandle = null;
|
|
1169
1211
|
if (args.silent) {
|
|
1170
|
-
const dir =
|
|
1171
|
-
await
|
|
1172
|
-
outputLogPath =
|
|
1173
|
-
await
|
|
1212
|
+
const dir = join6(homedir4(), ".cache", "task", "runs");
|
|
1213
|
+
await mkdir5(dir, { recursive: true });
|
|
1214
|
+
outputLogPath = join6(dir, `${args.runId}.log`);
|
|
1215
|
+
await writeFile6(outputLogPath, "");
|
|
1174
1216
|
const { createWriteStream } = await import("fs");
|
|
1175
1217
|
logHandle = createWriteStream(outputLogPath, { flags: "a" });
|
|
1176
1218
|
}
|
|
@@ -1706,9 +1748,9 @@ function autopilotExitCode(code, status) {
|
|
|
1706
1748
|
|
|
1707
1749
|
// src/scan/llm.ts
|
|
1708
1750
|
import { spawn as spawn2 } from "child_process";
|
|
1709
|
-
import { mkdir as
|
|
1710
|
-
import { homedir as
|
|
1711
|
-
import { join as
|
|
1751
|
+
import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
|
|
1752
|
+
import { homedir as homedir5 } from "os";
|
|
1753
|
+
import { join as join7 } from "path";
|
|
1712
1754
|
var FIX_PROMPT_JSON_SCHEMA = {
|
|
1713
1755
|
type: "object",
|
|
1714
1756
|
required: ["summary", "suspected_files", "proposed_changes", "confidence"],
|
|
@@ -1900,10 +1942,10 @@ function readEnvelopeTokens(raw, userPrompt, innerText) {
|
|
|
1900
1942
|
async function maybeDumpDebug(ticketId, stdout, stderr) {
|
|
1901
1943
|
if (!DEBUG && stdout.length === 0 && stderr.length === 0) return null;
|
|
1902
1944
|
try {
|
|
1903
|
-
const dir =
|
|
1904
|
-
await
|
|
1905
|
-
const path =
|
|
1906
|
-
await
|
|
1945
|
+
const dir = join7(homedir5(), ".cache", "task", "scan-debug");
|
|
1946
|
+
await mkdir6(dir, { recursive: true });
|
|
1947
|
+
const path = join7(dir, `${ticketId}-${Date.now()}.log`);
|
|
1948
|
+
await writeFile7(
|
|
1907
1949
|
path,
|
|
1908
1950
|
["## ticket_id", ticketId, "", "## stdout", stdout, "", "## stderr", stderr].join("\n")
|
|
1909
1951
|
);
|
|
@@ -1970,7 +2012,13 @@ function parseStructuredJson(raw) {
|
|
|
1970
2012
|
function registerScan(program2) {
|
|
1971
2013
|
program2.command("scan").description(
|
|
1972
2014
|
"Drive the AI fix-prompt autopilot loop locally \u2014 same flow as the /task-autopilot skill, run by the CLI binary"
|
|
1973
|
-
).option(
|
|
2015
|
+
).option(
|
|
2016
|
+
"--project <slugOrId>",
|
|
2017
|
+
"Restrict to one project (default: the linked project from .task/config.json, falling back to every visible project if the repo is not linked)"
|
|
2018
|
+
).option(
|
|
2019
|
+
"--all-projects",
|
|
2020
|
+
"Override the linked-project default and scan every CLI-eligible project the admin token can see"
|
|
2021
|
+
).option("--max <n>", "Max submissions per project token", "50").option("--batch <n>", "Tickets per /prepare batch (1-10)", "5").option("--api-url <url>", "Override TASK_API_URL").option("--silent", "Suppress per-ticket progress chrome").action(async (opts) => {
|
|
1974
2022
|
await runScan(opts);
|
|
1975
2023
|
});
|
|
1976
2024
|
}
|
|
@@ -1992,10 +2040,26 @@ async function runScan(opts) {
|
|
|
1992
2040
|
);
|
|
1993
2041
|
}
|
|
1994
2042
|
const localCfg = await readLocalConfig();
|
|
1995
|
-
const
|
|
2043
|
+
const linkedProject = await readProjectConfig(findRepoRoot());
|
|
2044
|
+
const apiUrl = (opts.apiUrl ?? process.env["TASK_API_URL"] ?? localCfg.api_url ?? linkedProject?.api_url ?? "http://localhost:3400").replace(/\/$/, "");
|
|
1996
2045
|
const max = clampInt(opts.max, 1, 500, 50);
|
|
1997
2046
|
const batchSize = clampInt(opts.batch, 1, 10, 5);
|
|
1998
2047
|
const silent = !!opts.silent || localCfg.silent;
|
|
2048
|
+
if (opts.project && opts.allProjects) {
|
|
2049
|
+
throw new CliError(
|
|
2050
|
+
CLI_EXIT_CODES.MISCONFIGURATION,
|
|
2051
|
+
"--project and --all-projects are mutually exclusive"
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
let projectFilter = null;
|
|
2055
|
+
let filterSource = null;
|
|
2056
|
+
if (opts.project) {
|
|
2057
|
+
projectFilter = opts.project;
|
|
2058
|
+
filterSource = "flag";
|
|
2059
|
+
} else if (linkedProject && !opts.allProjects) {
|
|
2060
|
+
projectFilter = linkedProject.project_id;
|
|
2061
|
+
filterSource = "link";
|
|
2062
|
+
}
|
|
1999
2063
|
const api = new AutopilotApi({ apiUrl, apiKey, actorEmail });
|
|
2000
2064
|
if (!silent) process.stdout.write(`${c.dim("Discovering eligible projects\u2026")}
|
|
2001
2065
|
`);
|
|
@@ -2004,15 +2068,33 @@ async function runScan(opts) {
|
|
|
2004
2068
|
process.stdout.write(c.dim("No CLI-eligible tickets across any visible project.\n"));
|
|
2005
2069
|
return;
|
|
2006
2070
|
}
|
|
2007
|
-
const projects =
|
|
2008
|
-
(p) => p.project_id ===
|
|
2071
|
+
const projects = projectFilter ? all.filter(
|
|
2072
|
+
(p) => p.project_id === projectFilter || p.project_slug === projectFilter || `${p.organisation_slug}/${p.project_slug}` === projectFilter
|
|
2009
2073
|
) : all;
|
|
2010
2074
|
if (projects.length === 0) {
|
|
2075
|
+
if (filterSource === "link" && linkedProject) {
|
|
2076
|
+
throw new CliError(
|
|
2077
|
+
CLI_EXIT_CODES.GENERIC_ERROR,
|
|
2078
|
+
`Linked project ${linkedProject.organisation_slug}/${linkedProject.project_slug} has no CLI-eligible tickets right now`,
|
|
2079
|
+
"Mark a ticket as CLI-eligible from the dashboard, or pass --all-projects to scan everything the admin token can see."
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2011
2082
|
throw new CliError(
|
|
2012
2083
|
CLI_EXIT_CODES.GENERIC_ERROR,
|
|
2013
2084
|
`Project "${opts.project}" not found among eligible projects`
|
|
2014
2085
|
);
|
|
2015
2086
|
}
|
|
2087
|
+
if (!silent && filterSource === "link" && linkedProject) {
|
|
2088
|
+
process.stdout.write(
|
|
2089
|
+
`${c.dim("Scanning linked project")} ${c.bold(`${linkedProject.organisation_slug}/${linkedProject.project_slug}`)}${c.dim(" \u2014 pass --all-projects to scan every visible project.")}
|
|
2090
|
+
`
|
|
2091
|
+
);
|
|
2092
|
+
} else if (!silent && filterSource === null && !linkedProject) {
|
|
2093
|
+
process.stdout.write(
|
|
2094
|
+
`${c.dim("Repo is not linked. Scanning every visible project \u2014 run")} ${c.cyan("task link")} ${c.dim("to scope future runs to one project.")}
|
|
2095
|
+
`
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2016
2098
|
const aggregates = [];
|
|
2017
2099
|
const claudePath = localCfg.claude_path ?? void 0;
|
|
2018
2100
|
let interrupted = false;
|
|
@@ -2196,9 +2278,9 @@ import { randomUUID as randomUUID3 } from "crypto";
|
|
|
2196
2278
|
import { platform as platform2 } from "os";
|
|
2197
2279
|
|
|
2198
2280
|
// src/scheduler/launchd.ts
|
|
2199
|
-
import { mkdir as
|
|
2200
|
-
import { homedir as
|
|
2201
|
-
import { join as
|
|
2281
|
+
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile8, unlink as unlink3, readdir } from "fs/promises";
|
|
2282
|
+
import { homedir as homedir6 } from "os";
|
|
2283
|
+
import { join as join8 } from "path";
|
|
2202
2284
|
import { execFileSync as execFileSync5, spawn as spawn3 } from "child_process";
|
|
2203
2285
|
|
|
2204
2286
|
// src/scheduler/cron-translate.ts
|
|
@@ -2300,14 +2382,14 @@ function expandField(field, min, max) {
|
|
|
2300
2382
|
}
|
|
2301
2383
|
|
|
2302
2384
|
// src/scheduler/launchd.ts
|
|
2303
|
-
var PLIST_DIR =
|
|
2385
|
+
var PLIST_DIR = join8(homedir6(), "Library", "LaunchAgents");
|
|
2304
2386
|
var LABEL_PREFIX = "com.inteeka.task.cli.";
|
|
2305
2387
|
var SAFE_ID_RE = /^[0-9a-zA-Z._-]+$/;
|
|
2306
2388
|
function plistPath(id) {
|
|
2307
2389
|
if (!SAFE_ID_RE.test(id) || id.includes("..")) {
|
|
2308
2390
|
throw new Error(`Refusing to compute plist path for unsafe id: ${id}`);
|
|
2309
2391
|
}
|
|
2310
|
-
return
|
|
2392
|
+
return join8(PLIST_DIR, `${LABEL_PREFIX}${id}.plist`);
|
|
2311
2393
|
}
|
|
2312
2394
|
function buildPlist(entry) {
|
|
2313
2395
|
const calendars = translateToLaunchd(entry.cron);
|
|
@@ -2343,9 +2425,9 @@ ${fields}
|
|
|
2343
2425
|
` <string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>`,
|
|
2344
2426
|
` </dict>`,
|
|
2345
2427
|
` <key>StandardOutPath</key>`,
|
|
2346
|
-
` <string>${escapeXml(
|
|
2428
|
+
` <string>${escapeXml(join8(homedir6(), ".cache", "task", "launchd-stdout.log"))}</string>`,
|
|
2347
2429
|
` <key>StandardErrorPath</key>`,
|
|
2348
|
-
` <string>${escapeXml(
|
|
2430
|
+
` <string>${escapeXml(join8(homedir6(), ".cache", "task", "launchd-stderr.log"))}</string>`,
|
|
2349
2431
|
!entry.enabled ? ` <key>Disabled</key>
|
|
2350
2432
|
<true/>` : "",
|
|
2351
2433
|
"</dict>",
|
|
@@ -2363,9 +2445,9 @@ function bootstrapDomain() {
|
|
|
2363
2445
|
}
|
|
2364
2446
|
var launchdAdapter = {
|
|
2365
2447
|
async upsert(entry) {
|
|
2366
|
-
await
|
|
2448
|
+
await mkdir7(PLIST_DIR, { recursive: true });
|
|
2367
2449
|
const path = plistPath(entry.id);
|
|
2368
|
-
await
|
|
2450
|
+
await writeFile8(path, buildPlist(entry));
|
|
2369
2451
|
try {
|
|
2370
2452
|
execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2371
2453
|
} catch {
|
|
@@ -2394,7 +2476,7 @@ var launchdAdapter = {
|
|
|
2394
2476
|
for (const file of ours) {
|
|
2395
2477
|
const id = file.slice(LABEL_PREFIX.length, -".plist".length);
|
|
2396
2478
|
try {
|
|
2397
|
-
const xml = await readFile5(
|
|
2479
|
+
const xml = await readFile5(join8(PLIST_DIR, file), "utf8");
|
|
2398
2480
|
const cron = xml.match(/<key>StartCalendarInterval<\/key>[\s\S]*?<\/array>/)?.[0] ?? "";
|
|
2399
2481
|
const command = xml.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/)?.[1] ?? "";
|
|
2400
2482
|
const disabled = /<key>Disabled<\/key>\s*<true\/>/.test(xml);
|
|
@@ -2440,7 +2522,7 @@ var launchdAdapter = {
|
|
|
2440
2522
|
}
|
|
2441
2523
|
if (enabled) {
|
|
2442
2524
|
xml = xml.replace(/\s*<key>Disabled<\/key>\s*<true\/>/, "");
|
|
2443
|
-
await
|
|
2525
|
+
await writeFile8(path, xml);
|
|
2444
2526
|
try {
|
|
2445
2527
|
execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
2446
2528
|
} catch {
|
|
@@ -2452,7 +2534,7 @@ var launchdAdapter = {
|
|
|
2452
2534
|
"</dict>\n</plist>",
|
|
2453
2535
|
" <key>Disabled</key>\n <true/>\n</dict>\n</plist>"
|
|
2454
2536
|
);
|
|
2455
|
-
await
|
|
2537
|
+
await writeFile8(path, xml);
|
|
2456
2538
|
}
|
|
2457
2539
|
try {
|
|
2458
2540
|
execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
|
|
@@ -2805,10 +2887,10 @@ var unsupportedAdapter = {
|
|
|
2805
2887
|
};
|
|
2806
2888
|
|
|
2807
2889
|
// src/scheduler/registry.ts
|
|
2808
|
-
import { mkdir as
|
|
2809
|
-
import { homedir as
|
|
2810
|
-
import { dirname as dirname4, join as
|
|
2811
|
-
var REGISTRY_PATH =
|
|
2890
|
+
import { mkdir as mkdir8, readFile as readFile6, writeFile as writeFile9 } from "fs/promises";
|
|
2891
|
+
import { homedir as homedir7 } from "os";
|
|
2892
|
+
import { dirname as dirname4, join as join9 } from "path";
|
|
2893
|
+
var REGISTRY_PATH = join9(homedir7(), ".config", "task", "schedules.json");
|
|
2812
2894
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2813
2895
|
function looksLikeRegistryRow(value) {
|
|
2814
2896
|
if (!value || typeof value !== "object") return false;
|
|
@@ -2828,8 +2910,8 @@ async function readRegistry() {
|
|
|
2828
2910
|
}
|
|
2829
2911
|
}
|
|
2830
2912
|
async function writeRegistry(rows) {
|
|
2831
|
-
await
|
|
2832
|
-
await
|
|
2913
|
+
await mkdir8(dirname4(REGISTRY_PATH), { recursive: true });
|
|
2914
|
+
await writeFile9(REGISTRY_PATH, JSON.stringify(rows, null, 2));
|
|
2833
2915
|
}
|
|
2834
2916
|
async function upsertRegistry(row) {
|
|
2835
2917
|
if (!UUID_RE.test(row.id)) {
|
|
@@ -3069,8 +3151,8 @@ function stripAnsi(s) {
|
|
|
3069
3151
|
|
|
3070
3152
|
// src/commands/runs.ts
|
|
3071
3153
|
import { readFile as readFile7 } from "fs/promises";
|
|
3072
|
-
import { homedir as
|
|
3073
|
-
import { join as
|
|
3154
|
+
import { homedir as homedir8 } from "os";
|
|
3155
|
+
import { join as join10 } from "path";
|
|
3074
3156
|
function registerRuns(program2) {
|
|
3075
3157
|
const cmd = program2.command("runs").description("Inspect agentic CLI run history");
|
|
3076
3158
|
cmd.command("list").description("List recent runs").option("--limit <n>", "Max rows", "50").option("--ticket <id>", "Filter by ticket").option("--schedule <id>", "Filter by schedule").action(async (opts) => {
|
|
@@ -3099,7 +3181,7 @@ function registerRuns(program2) {
|
|
|
3099
3181
|
process.stdout.write(JSON.stringify(row, null, 2) + "\n");
|
|
3100
3182
|
});
|
|
3101
3183
|
cmd.command("logs <id>").description("Show captured agent output for a run, if available").action(async (id) => {
|
|
3102
|
-
const localPath =
|
|
3184
|
+
const localPath = join10(homedir8(), ".cache", "task", "runs", `${id}.log`);
|
|
3103
3185
|
try {
|
|
3104
3186
|
const text = await readFile7(localPath, "utf8");
|
|
3105
3187
|
process.stdout.write(text);
|
|
@@ -3251,7 +3333,7 @@ function checkBinary(name, command) {
|
|
|
3251
3333
|
}
|
|
3252
3334
|
|
|
3253
3335
|
// src/commands/version.ts
|
|
3254
|
-
var CLI_VERSION = true ? "0.1.
|
|
3336
|
+
var CLI_VERSION = true ? "0.1.6" : "0.0.0-dev";
|
|
3255
3337
|
function registerVersion(program2) {
|
|
3256
3338
|
program2.command("version").description("Print the CLI version").action(() => {
|
|
3257
3339
|
process.stdout.write(CLI_VERSION + "\n");
|