@inteeka/task-cli 0.1.4 → 0.1.5

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 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 parsed;
569
+ let rawBody;
541
570
  try {
542
- parsed = await res.body.json();
571
+ rawBody = await res.body.text();
543
572
  } catch {
544
- parsed = void 0;
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 message = errBody?.error?.message ?? `Request failed with status ${status}`;
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 mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
595
- import { homedir as homedir2 } from "os";
596
- import { dirname as dirname2, join as join2 } from "path";
597
- var CONFIG_PATH = join2(homedir2(), ".config", "task", "config.json");
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 mkdir2(dirname2(CONFIG_PATH), { recursive: true });
618
- await writeFile2(CONFIG_PATH, JSON.stringify(config, null, 2));
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 writeFile4, appendFile, access } from "fs/promises";
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 join4 } from "path";
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 mkdir3, readFile as readFile3, writeFile as writeFile3, unlink as unlink2 } from "fs/promises";
744
- import { dirname as dirname3, join as join3, resolve } from "path";
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 join3(repoRoot ?? findRepoRoot(), ".task", "config.json");
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 mkdir3(dirname3(path), { recursive: true });
770
- await writeFile3(path, JSON.stringify(config, null, 2));
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 = join4(repoRoot, ".gitignore");
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 writeFile4(gitignorePath, "# task CLI link config\n.task/\n");
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 mkdir4, writeFile as writeFile5 } from "fs/promises";
1112
- import { homedir as homedir3 } from "os";
1113
- import { join as join5 } from "path";
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 = join5(homedir3(), ".cache", "task", "runs");
1171
- await mkdir4(dir, { recursive: true });
1172
- outputLogPath = join5(dir, `${args.runId}.log`);
1173
- await writeFile5(outputLogPath, "");
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 mkdir5, writeFile as writeFile6 } from "fs/promises";
1710
- import { homedir as homedir4 } from "os";
1711
- import { join as join6 } from "path";
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 = join6(homedir4(), ".cache", "task", "scan-debug");
1904
- await mkdir5(dir, { recursive: true });
1905
- const path = join6(dir, `${ticketId}-${Date.now()}.log`);
1906
- await writeFile6(
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
  );
@@ -2196,9 +2238,9 @@ import { randomUUID as randomUUID3 } from "crypto";
2196
2238
  import { platform as platform2 } from "os";
2197
2239
 
2198
2240
  // src/scheduler/launchd.ts
2199
- import { mkdir as mkdir6, readFile as readFile5, writeFile as writeFile7, unlink as unlink3, readdir } from "fs/promises";
2200
- import { homedir as homedir5 } from "os";
2201
- import { join as join7 } from "path";
2241
+ import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile8, unlink as unlink3, readdir } from "fs/promises";
2242
+ import { homedir as homedir6 } from "os";
2243
+ import { join as join8 } from "path";
2202
2244
  import { execFileSync as execFileSync5, spawn as spawn3 } from "child_process";
2203
2245
 
2204
2246
  // src/scheduler/cron-translate.ts
@@ -2300,14 +2342,14 @@ function expandField(field, min, max) {
2300
2342
  }
2301
2343
 
2302
2344
  // src/scheduler/launchd.ts
2303
- var PLIST_DIR = join7(homedir5(), "Library", "LaunchAgents");
2345
+ var PLIST_DIR = join8(homedir6(), "Library", "LaunchAgents");
2304
2346
  var LABEL_PREFIX = "com.inteeka.task.cli.";
2305
2347
  var SAFE_ID_RE = /^[0-9a-zA-Z._-]+$/;
2306
2348
  function plistPath(id) {
2307
2349
  if (!SAFE_ID_RE.test(id) || id.includes("..")) {
2308
2350
  throw new Error(`Refusing to compute plist path for unsafe id: ${id}`);
2309
2351
  }
2310
- return join7(PLIST_DIR, `${LABEL_PREFIX}${id}.plist`);
2352
+ return join8(PLIST_DIR, `${LABEL_PREFIX}${id}.plist`);
2311
2353
  }
2312
2354
  function buildPlist(entry) {
2313
2355
  const calendars = translateToLaunchd(entry.cron);
@@ -2343,9 +2385,9 @@ ${fields}
2343
2385
  ` <string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>`,
2344
2386
  ` </dict>`,
2345
2387
  ` <key>StandardOutPath</key>`,
2346
- ` <string>${escapeXml(join7(homedir5(), ".cache", "task", "launchd-stdout.log"))}</string>`,
2388
+ ` <string>${escapeXml(join8(homedir6(), ".cache", "task", "launchd-stdout.log"))}</string>`,
2347
2389
  ` <key>StandardErrorPath</key>`,
2348
- ` <string>${escapeXml(join7(homedir5(), ".cache", "task", "launchd-stderr.log"))}</string>`,
2390
+ ` <string>${escapeXml(join8(homedir6(), ".cache", "task", "launchd-stderr.log"))}</string>`,
2349
2391
  !entry.enabled ? ` <key>Disabled</key>
2350
2392
  <true/>` : "",
2351
2393
  "</dict>",
@@ -2363,9 +2405,9 @@ function bootstrapDomain() {
2363
2405
  }
2364
2406
  var launchdAdapter = {
2365
2407
  async upsert(entry) {
2366
- await mkdir6(PLIST_DIR, { recursive: true });
2408
+ await mkdir7(PLIST_DIR, { recursive: true });
2367
2409
  const path = plistPath(entry.id);
2368
- await writeFile7(path, buildPlist(entry));
2410
+ await writeFile8(path, buildPlist(entry));
2369
2411
  try {
2370
2412
  execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
2371
2413
  } catch {
@@ -2394,7 +2436,7 @@ var launchdAdapter = {
2394
2436
  for (const file of ours) {
2395
2437
  const id = file.slice(LABEL_PREFIX.length, -".plist".length);
2396
2438
  try {
2397
- const xml = await readFile5(join7(PLIST_DIR, file), "utf8");
2439
+ const xml = await readFile5(join8(PLIST_DIR, file), "utf8");
2398
2440
  const cron = xml.match(/<key>StartCalendarInterval<\/key>[\s\S]*?<\/array>/)?.[0] ?? "";
2399
2441
  const command = xml.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/)?.[1] ?? "";
2400
2442
  const disabled = /<key>Disabled<\/key>\s*<true\/>/.test(xml);
@@ -2440,7 +2482,7 @@ var launchdAdapter = {
2440
2482
  }
2441
2483
  if (enabled) {
2442
2484
  xml = xml.replace(/\s*<key>Disabled<\/key>\s*<true\/>/, "");
2443
- await writeFile7(path, xml);
2485
+ await writeFile8(path, xml);
2444
2486
  try {
2445
2487
  execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
2446
2488
  } catch {
@@ -2452,7 +2494,7 @@ var launchdAdapter = {
2452
2494
  "</dict>\n</plist>",
2453
2495
  " <key>Disabled</key>\n <true/>\n</dict>\n</plist>"
2454
2496
  );
2455
- await writeFile7(path, xml);
2497
+ await writeFile8(path, xml);
2456
2498
  }
2457
2499
  try {
2458
2500
  execFileSync5("launchctl", ["bootout", bootstrapDomain(), path], { stdio: "ignore" });
@@ -2805,10 +2847,10 @@ var unsupportedAdapter = {
2805
2847
  };
2806
2848
 
2807
2849
  // src/scheduler/registry.ts
2808
- import { mkdir as mkdir7, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
2809
- import { homedir as homedir6 } from "os";
2810
- import { dirname as dirname4, join as join8 } from "path";
2811
- var REGISTRY_PATH = join8(homedir6(), ".config", "task", "schedules.json");
2850
+ import { mkdir as mkdir8, readFile as readFile6, writeFile as writeFile9 } from "fs/promises";
2851
+ import { homedir as homedir7 } from "os";
2852
+ import { dirname as dirname4, join as join9 } from "path";
2853
+ var REGISTRY_PATH = join9(homedir7(), ".config", "task", "schedules.json");
2812
2854
  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
2855
  function looksLikeRegistryRow(value) {
2814
2856
  if (!value || typeof value !== "object") return false;
@@ -2828,8 +2870,8 @@ async function readRegistry() {
2828
2870
  }
2829
2871
  }
2830
2872
  async function writeRegistry(rows) {
2831
- await mkdir7(dirname4(REGISTRY_PATH), { recursive: true });
2832
- await writeFile8(REGISTRY_PATH, JSON.stringify(rows, null, 2));
2873
+ await mkdir8(dirname4(REGISTRY_PATH), { recursive: true });
2874
+ await writeFile9(REGISTRY_PATH, JSON.stringify(rows, null, 2));
2833
2875
  }
2834
2876
  async function upsertRegistry(row) {
2835
2877
  if (!UUID_RE.test(row.id)) {
@@ -3069,8 +3111,8 @@ function stripAnsi(s) {
3069
3111
 
3070
3112
  // src/commands/runs.ts
3071
3113
  import { readFile as readFile7 } from "fs/promises";
3072
- import { homedir as homedir7 } from "os";
3073
- import { join as join9 } from "path";
3114
+ import { homedir as homedir8 } from "os";
3115
+ import { join as join10 } from "path";
3074
3116
  function registerRuns(program2) {
3075
3117
  const cmd = program2.command("runs").description("Inspect agentic CLI run history");
3076
3118
  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 +3141,7 @@ function registerRuns(program2) {
3099
3141
  process.stdout.write(JSON.stringify(row, null, 2) + "\n");
3100
3142
  });
3101
3143
  cmd.command("logs <id>").description("Show captured agent output for a run, if available").action(async (id) => {
3102
- const localPath = join9(homedir7(), ".cache", "task", "runs", `${id}.log`);
3144
+ const localPath = join10(homedir8(), ".cache", "task", "runs", `${id}.log`);
3103
3145
  try {
3104
3146
  const text = await readFile7(localPath, "utf8");
3105
3147
  process.stdout.write(text);
@@ -3251,7 +3293,7 @@ function checkBinary(name, command) {
3251
3293
  }
3252
3294
 
3253
3295
  // src/commands/version.ts
3254
- var CLI_VERSION = true ? "0.1.4" : "0.0.0-dev";
3296
+ var CLI_VERSION = true ? "0.1.5" : "0.0.0-dev";
3255
3297
  function registerVersion(program2) {
3256
3298
  program2.command("version").description("Print the CLI version").action(() => {
3257
3299
  process.stdout.write(CLI_VERSION + "\n");