@vibetasks/cli 0.5.3 → 0.5.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.
@@ -5,13 +5,13 @@ import {
5
5
  detectError,
6
6
  formatErrorForNotes,
7
7
  getErrorSummary
8
- } from "../chunk-PZF4VRDG.js";
8
+ } from "../chunk-S3G6KYGP.js";
9
9
  import {
10
10
  daemonConfigManager
11
11
  } from "../chunk-2KRLRG4G.js";
12
12
 
13
13
  // bin/vibetasks.ts
14
- import { Command as Command19 } from "commander";
14
+ import { Command as Command21 } from "commander";
15
15
  import { createRequire } from "module";
16
16
 
17
17
  // src/commands/login.ts
@@ -45,7 +45,12 @@ ${url}
45
45
  `));
46
46
  }
47
47
  }
48
- function getAuthBaseUrl() {
48
+ async function getAuthBaseUrl() {
49
+ const authManager = new AuthManager();
50
+ const configUrl = await authManager.getConfig("auth-url");
51
+ if (configUrl) {
52
+ return String(configUrl);
53
+ }
49
54
  if (process.env.VIBETASKS_AUTH_URL) {
50
55
  return process.env.VIBETASKS_AUTH_URL;
51
56
  }
@@ -58,6 +63,7 @@ async function loginWithBrowser() {
58
63
  console.log(chalk.blue.bold("\n\u{1F510} VibeTasks Browser Login\n"));
59
64
  const spinner = ora("Starting local server...").start();
60
65
  const port = await getAvailablePort();
66
+ const baseUrl = await getAuthBaseUrl();
61
67
  return new Promise((resolve, reject) => {
62
68
  let timeoutId = null;
63
69
  const server = createServer(async (req, res) => {
@@ -258,7 +264,7 @@ async function loginWithBrowser() {
258
264
  </p>
259
265
  <div class="success-badge">Ready to use</div>
260
266
  <div class="button-group">
261
- <a href="https://vibetasks.dev/dashboard" class="button button-primary">Go to Dashboard</a>
267
+ <a href="${baseUrl}/dashboard" class="button button-primary">Go to Dashboard</a>
262
268
  <button onclick="window.close()" class="button button-secondary">Close Window</button>
263
269
  </div>
264
270
  </div>
@@ -314,7 +320,6 @@ Error: ${error.message}`));
314
320
  });
315
321
  server.listen(port, async () => {
316
322
  spinner.text = "Opening browser...";
317
- const baseUrl = getAuthBaseUrl();
318
323
  const authUrl = `${baseUrl}/cli-auth?port=${port}`;
319
324
  spinner.text = "Waiting for authentication in browser...";
320
325
  console.log(chalk.gray(`
@@ -363,6 +368,7 @@ async function getAvailablePort(startPort = 3737) {
363
368
  var loginCommand = new Command("login").description("Authenticate with VibeTasks via browser (Google OAuth)").option("-b, --browser", "Login via browser (default)").action(async () => {
364
369
  console.log(chalk2.blue.bold("\n\u{1F510} VibeTasks Login\n"));
365
370
  console.log(chalk2.gray("Opening browser for Google sign-in...\n"));
371
+ console.log(chalk2.gray("Tip: For local development, run: vibetasks config auth-url http://localhost:3847\n"));
366
372
  await loginWithBrowser();
367
373
  });
368
374
 
@@ -877,7 +883,8 @@ var listCommand = new Command3("list").description("List tasks").argument("[filt
877
883
  all: "No active tasks found",
878
884
  today: "No tasks due today",
879
885
  upcoming: "No upcoming tasks",
880
- completed: "No completed tasks"
886
+ completed: "No completed tasks",
887
+ archived: "No archived tasks"
881
888
  };
882
889
  console.log(chalk4.gray(`
883
890
  ${filterMessages[filter] || "No tasks found"}.
@@ -918,12 +925,14 @@ ${filterMessages[filter] || "No tasks found"}.
918
925
  const statusColors = {
919
926
  todo: chalk4.gray,
920
927
  vibing: chalk4.magenta,
921
- done: chalk4.green
928
+ done: chalk4.green,
929
+ archived: chalk4.dim
922
930
  };
923
931
  const statusEmojis = {
924
932
  todo: "\u{1F4CB}",
925
933
  vibing: "\u26A1",
926
- done: "\u2713"
934
+ done: "\u2713",
935
+ archived: "\u{1F4E6}"
927
936
  };
928
937
  const priorityColor = priorityColors[task.priority || "none"];
929
938
  const statusColor = statusColors[task.status || "todo"];
@@ -950,7 +959,8 @@ ${filterMessages[filter] || "No tasks found"}.
950
959
  all: "active",
951
960
  today: "today",
952
961
  upcoming: "upcoming",
953
- completed: "completed"
962
+ completed: "completed",
963
+ archived: "archived"
954
964
  };
955
965
  console.log(chalk4.gray(`
956
966
  Total: ${tasks.length} ${filterLabels[filter]} task${tasks.length === 1 ? "" : "s"}`));
@@ -981,7 +991,7 @@ import { Command as Command4 } from "commander";
981
991
  import ora3 from "ora";
982
992
  import chalk5 from "chalk";
983
993
  import { AuthManager as AuthManager4, TaskOperations as TaskOperations3 } from "@vibetasks/core";
984
- var doneCommand = new Command4("done").description("Mark a task as complete").argument("<id>", "Task ID, short # (1-99), or first 8 characters").action(async (id) => {
994
+ var doneCommand = new Command4("done").description("Mark a task as complete").argument("<id>", "Task ID, short # (1-99), or first 8 characters").option("-n, --notes <notes>", "Completion notes - what was done, any final notes").option("-c, --context <context>", "Context notes (alias for --notes)").action(async (id, options) => {
985
995
  const spinner = ora3("Completing task...").start();
986
996
  try {
987
997
  const authManager = new AuthManager4();
@@ -1000,6 +1010,10 @@ No task found with ID starting with: ${id}
1000
1010
  }
1001
1011
  taskId = matchingTask.id;
1002
1012
  }
1013
+ const contextNotes = options.notes || options.context;
1014
+ if (contextNotes) {
1015
+ await taskOps.updateTask(taskId, { context_notes: contextNotes });
1016
+ }
1003
1017
  const task = await taskOps.completeTask(taskId);
1004
1018
  const sessionManager2 = getSessionManager();
1005
1019
  await sessionManager2.logAction({
@@ -1011,6 +1025,9 @@ No task found with ID starting with: ${id}
1011
1025
  spinner.succeed(chalk5.green("Task completed!"));
1012
1026
  console.log(chalk5.gray(`
1013
1027
  \u2713 ${task.title}`));
1028
+ if (contextNotes) {
1029
+ console.log(chalk5.gray(`Notes: ${contextNotes}`));
1030
+ }
1014
1031
  console.log(chalk5.gray(`Completed at: ${(/* @__PURE__ */ new Date()).toLocaleString()}
1015
1032
  `));
1016
1033
  process.exit(0);
@@ -1614,7 +1631,7 @@ import { promisify as promisify2 } from "util";
1614
1631
  import { AuthManager as AuthManager11, TaskOperations as TaskOperations8, createSupabaseClient } from "@vibetasks/core";
1615
1632
  import { detectProject as detectProject3 } from "@vibetasks/shared/utils/project-detector";
1616
1633
  var execAsync2 = promisify2(exec2);
1617
- var SUPABASE_URL = "https://cbkkztbcoitrfcleghfd.supabase.co";
1634
+ var SUPABASE_URL = "https://ihmayqzxqyednchbezya.supabase.co";
1618
1635
  var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNia2t6dGJjb2l0cmZjbGVnaGZkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njc3NTc0MjgsImV4cCI6MjA4MzMzMzQyOH0.G7ILx-nntP0NbxO1gKt5yASb7nt7OmpJ8qtykeGYbQA";
1619
1636
  async function openBrowser2(url) {
1620
1637
  const platform = process.platform;
@@ -1743,7 +1760,7 @@ async function runBrowserAuth() {
1743
1760
  res.end();
1744
1761
  });
1745
1762
  server.listen(port, async () => {
1746
- const taskflowPort = process.env.TASKFLOW_WEB_PORT || "2843";
1763
+ const taskflowPort = process.env.TASKFLOW_WEB_PORT || "3847";
1747
1764
  const authUrl = `http://localhost:${taskflowPort}/cli-auth?port=${port}`;
1748
1765
  console.log(chalk13.gray(`
1749
1766
  If browser doesn't open, visit:`));
@@ -2035,7 +2052,7 @@ function showCompletion(auth, claude, project, verify) {
2035
2052
  console.log(chalk13.cyan(' "What should I work on next?"'));
2036
2053
  }
2037
2054
  console.log("");
2038
- console.log(chalk13.gray(" Need help? https://github.com/vyasapps/vibetasks"));
2055
+ console.log(chalk13.gray(" Need help? https://github.com/sparktory/vibetasks"));
2039
2056
  console.log("");
2040
2057
  }
2041
2058
  function getSuccessHtml(email) {
@@ -2223,6 +2240,7 @@ import ora10 from "ora";
2223
2240
  import inquirer5 from "inquirer";
2224
2241
  import { AuthManager as AuthManager12, TaskOperations as TaskOperations9 } from "@vibetasks/core";
2225
2242
  import { detectProject as detectProject4 } from "@vibetasks/shared/utils/project-detector";
2243
+ import { generateErrorTaskTitle } from "@vibetasks/shared";
2226
2244
  var watchCommand = new Command13("watch").description("Monitor clipboard for errors and offer to capture them as tasks").option("-i, --interval <ms>", "Polling interval in milliseconds", "1000").option("-a, --auto", "Auto-create tasks without prompting").option("-q, --quiet", "Minimal output (only show errors)").option("--project <name>", "Override auto-detected project").action(async (options) => {
2227
2245
  const interval = parseInt(options.interval || "1000", 10);
2228
2246
  if (!options.quiet) {
@@ -2260,7 +2278,7 @@ Error: ${error.message}
2260
2278
  }
2261
2279
  const recentErrors = /* @__PURE__ */ new Set();
2262
2280
  const handleError = async (error) => {
2263
- const errorHash = `${error.type}:${error.message.substring(0, 50)}`;
2281
+ const errorHash = `${error.error_type || "unknown"}:${(error.message || "").substring(0, 50)}`;
2264
2282
  if (recentErrors.has(errorHash)) {
2265
2283
  return;
2266
2284
  }
@@ -2300,7 +2318,7 @@ Error: ${error.message}
2300
2318
  case "show":
2301
2319
  console.log();
2302
2320
  console.log(chalk14.gray("\u2500".repeat(50)));
2303
- console.log(error.rawText);
2321
+ console.log(error.raw_text);
2304
2322
  console.log(chalk14.gray("\u2500".repeat(50)));
2305
2323
  console.log();
2306
2324
  const { afterShow } = await inquirer5.prompt([
@@ -2369,20 +2387,23 @@ Error: ${error.message}
2369
2387
  async function createTaskFromError(error, taskOps, projectTag) {
2370
2388
  const spinner = ora10("Creating task...").start();
2371
2389
  try {
2372
- const title = generateTaskTitle(error);
2390
+ const title = generateErrorTaskTitle(error);
2391
+ const category = error.category || "general";
2373
2392
  const task = await taskOps.createTask({
2374
2393
  title,
2375
2394
  notes: formatErrorForNotes(error),
2376
2395
  notes_format: "markdown",
2377
- priority: error.category === "typescript" ? "medium" : "high",
2396
+ priority: category === "typescript" ? "medium" : "high",
2378
2397
  project_tag: projectTag,
2379
2398
  created_by: "human",
2380
2399
  // User triggered this
2381
- status: "todo"
2400
+ status: "todo",
2401
+ source_type: "cli",
2402
+ error_context: error
2382
2403
  });
2383
- const tagName = `error-${error.category}`;
2404
+ const tagName = `error-${category}`;
2384
2405
  try {
2385
- const tag = await taskOps.findOrCreateTag(tagName, getTagColor(error.category));
2406
+ const tag = await taskOps.findOrCreateTag(tagName, getTagColor(category));
2386
2407
  await taskOps.linkTaskTags(task.id, [tag.id]);
2387
2408
  } catch {
2388
2409
  }
@@ -2394,41 +2415,6 @@ async function createTaskFromError(error, taskOps, projectTag) {
2394
2415
  console.error(chalk14.red(`Error: ${err.message}`));
2395
2416
  }
2396
2417
  }
2397
- function generateTaskTitle(error) {
2398
- const prefix = getCategoryPrefix(error.category);
2399
- let title = `${prefix} ${error.type}`;
2400
- if (error.message && error.message.length < 60) {
2401
- title += `: ${error.message}`;
2402
- } else if (error.message) {
2403
- const shortMessage = error.message.split(/[.!?\n]/)[0].trim();
2404
- if (shortMessage.length < 60) {
2405
- title += `: ${shortMessage}`;
2406
- }
2407
- }
2408
- if (error.file) {
2409
- const fileName = error.file.split(/[/\\]/).pop();
2410
- if (fileName && title.length + fileName.length < 100) {
2411
- title += ` in ${fileName}`;
2412
- }
2413
- }
2414
- if (title.length > 120) {
2415
- title = title.substring(0, 117) + "...";
2416
- }
2417
- return title;
2418
- }
2419
- function getCategoryPrefix(category) {
2420
- const prefixes = {
2421
- nodejs: "Fix",
2422
- npm: "Resolve npm",
2423
- expo: "Fix Expo",
2424
- "react-native": "Fix RN",
2425
- webpack: "Fix build",
2426
- typescript: "Fix TS",
2427
- python: "Fix Python",
2428
- generic: "Fix"
2429
- };
2430
- return prefixes[category] || "Fix";
2431
- }
2432
2418
  function getTagColor(category) {
2433
2419
  const colors = {
2434
2420
  nodejs: "#68A063",
@@ -2550,11 +2536,12 @@ Restored: ${task2.title}`));
2550
2536
  console.log(chalk15.gray(" or: vibetasks archive --unarchive <id>\n"));
2551
2537
  process.exit(1);
2552
2538
  }
2539
+ const validTaskId = taskId;
2553
2540
  spinner.start("Archiving task...");
2554
- let targetId = taskId;
2555
- if (taskId.length < 32) {
2541
+ let targetId = validTaskId;
2542
+ if (validTaskId.length < 32) {
2556
2543
  const allTasks = await taskOps.getTasks("all", true);
2557
- const matchingTask = allTasks.find((t) => t.id.startsWith(taskId));
2544
+ const matchingTask = allTasks.find((t) => t.id.startsWith(validTaskId));
2558
2545
  if (!matchingTask) {
2559
2546
  spinner.fail(chalk15.red("Task not found"));
2560
2547
  console.error(chalk15.gray(`
@@ -2595,6 +2582,7 @@ import { spawn } from "child_process";
2595
2582
  import path3 from "path";
2596
2583
  import { fileURLToPath } from "url";
2597
2584
  import { AuthManager as AuthManager14, TaskOperations as TaskOperations11 } from "@vibetasks/core";
2585
+ import { generateErrorTaskTitle as generateErrorTaskTitle2 } from "@vibetasks/shared";
2598
2586
  var __filename2 = fileURLToPath(import.meta.url);
2599
2587
  var __dirname2 = path3.dirname(__filename2);
2600
2588
  var daemonCommand = new Command15("daemon").description("Manage the VibeTasks error capture daemon").addCommand(createStartCommand()).addCommand(createStopCommand()).addCommand(createStatusCommand()).addCommand(createConfigureCommand()).addCommand(createCaptureCommand());
@@ -2763,21 +2751,21 @@ function createCaptureCommand() {
2763
2751
  process.exit(0);
2764
2752
  }
2765
2753
  console.log(chalk16.red.bold("\nError Detected!\n"));
2766
- console.log(chalk16.cyan("Type: ") + chalk16.white(error.type));
2767
- console.log(chalk16.cyan("Category: ") + chalk16.white(error.category));
2768
- console.log(chalk16.cyan("Message: ") + chalk16.white(error.message));
2769
- if (error.file) {
2770
- console.log(chalk16.cyan("File: ") + chalk16.white(error.file));
2771
- if (error.line) {
2772
- console.log(chalk16.cyan("Line: ") + chalk16.white(error.line.toString()) + (error.column ? chalk16.gray(`:${error.column}`) : ""));
2754
+ console.log(chalk16.cyan("Type: ") + chalk16.white(error.error_type || "Unknown"));
2755
+ console.log(chalk16.cyan("Category: ") + chalk16.white(error.category || "general"));
2756
+ console.log(chalk16.cyan("Message: ") + chalk16.white(error.message || ""));
2757
+ if (error.file_path) {
2758
+ console.log(chalk16.cyan("File: ") + chalk16.white(error.file_path));
2759
+ if (error.line_number) {
2760
+ console.log(chalk16.cyan("Line: ") + chalk16.white(error.line_number.toString()) + (error.column ? chalk16.gray(`:${error.column}`) : ""));
2773
2761
  }
2774
2762
  }
2775
2763
  if (error.suggestion) {
2776
2764
  console.log(chalk16.green("\nSuggestion: ") + chalk16.white(error.suggestion));
2777
2765
  }
2778
- if (error.stack) {
2766
+ if (error.stack_trace) {
2779
2767
  console.log(chalk16.cyan("\nStack Trace (first 5 lines):"));
2780
- const stackLines = error.stack.split("\n").slice(0, 5);
2768
+ const stackLines = error.stack_trace.split("\n").slice(0, 5);
2781
2769
  stackLines.forEach((line) => {
2782
2770
  console.log(chalk16.gray(" " + line));
2783
2771
  });
@@ -2914,59 +2902,27 @@ async function showNotification(title, message, type = "info", duration) {
2914
2902
  console.log(chalk16.blue(`[Notification] ${title}: ${message}`));
2915
2903
  }
2916
2904
  }
2917
- function generateTaskTitle2(error) {
2918
- const prefix = getCategoryPrefix2(error.category);
2919
- let title = `${prefix} ${error.type}`;
2920
- if (error.message && error.message.length < 60) {
2921
- title += `: ${error.message}`;
2922
- } else if (error.message) {
2923
- const shortMessage = error.message.split(/[.!?\n]/)[0].trim();
2924
- if (shortMessage.length < 60) {
2925
- title += `: ${shortMessage}`;
2926
- }
2927
- }
2928
- if (error.file) {
2929
- const fileName = error.file.split(/[/\\]/).pop();
2930
- if (fileName && title.length + fileName.length < 100) {
2931
- title += ` in ${fileName}`;
2932
- }
2933
- }
2934
- if (title.length > 120) {
2935
- title = title.substring(0, 117) + "...";
2936
- }
2937
- return title;
2938
- }
2939
- function getCategoryPrefix2(category) {
2940
- const prefixes = {
2941
- nodejs: "Fix",
2942
- npm: "Resolve npm",
2943
- expo: "Fix Expo",
2944
- "react-native": "Fix RN",
2945
- webpack: "Fix build",
2946
- typescript: "Fix TS",
2947
- python: "Fix Python",
2948
- generic: "Fix"
2949
- };
2950
- return prefixes[category] || "Fix";
2951
- }
2952
2905
  async function createTaskFromError2(error) {
2953
2906
  const spinner = ora12("Creating task from error...").start();
2954
2907
  try {
2955
2908
  const authManager = new AuthManager14();
2956
2909
  const taskOps = await TaskOperations11.fromAuthManager(authManager);
2957
- const title = generateTaskTitle2(error);
2910
+ const title = generateErrorTaskTitle2(error);
2958
2911
  const notes = formatErrorForNotes(error);
2912
+ const category = error.category || "general";
2959
2913
  const task = await taskOps.createTask({
2960
2914
  title,
2961
2915
  notes,
2962
2916
  notes_format: "markdown",
2963
- priority: error.category === "typescript" ? "medium" : "high",
2917
+ priority: category === "typescript" ? "medium" : "high",
2964
2918
  created_by: "ai",
2965
- status: "todo"
2919
+ status: "todo",
2920
+ source_type: "cli",
2921
+ error_context: error
2966
2922
  });
2967
- const tagName = `error-${error.category}`;
2923
+ const tagName = `error-${category}`;
2968
2924
  try {
2969
- const tag = await taskOps.findOrCreateTag(tagName, getTagColor2(error.category));
2925
+ const tag = await taskOps.findOrCreateTag(tagName, getTagColor2(category));
2970
2926
  await taskOps.linkTaskTags(task.id, [tag.id]);
2971
2927
  } catch {
2972
2928
  }
@@ -3036,7 +2992,7 @@ var nextCommand = new Command16("next").description("Show and optionally start t
3036
2992
  }
3037
2993
  const nextTask = tasks[0];
3038
2994
  if (options.start && nextTask.status !== "vibing") {
3039
- await taskOps.updateTaskStatus(nextTask.id, "vibing");
2995
+ await taskOps.updateTask(nextTask.id, { status: "vibing" });
3040
2996
  console.log(chalk17.green(`
3041
2997
  \u26A1 Started vibing on task!
3042
2998
  `));
@@ -3479,10 +3435,344 @@ Error: ${error.message}
3479
3435
  }
3480
3436
  });
3481
3437
 
3438
+ // src/commands/error.ts
3439
+ import { Command as Command19 } from "commander";
3440
+ import chalk20 from "chalk";
3441
+ import ora14 from "ora";
3442
+ import { AuthManager as AuthManager17, TaskOperations as TaskOperations14 } from "@vibetasks/core";
3443
+ import {
3444
+ parseError,
3445
+ generateErrorTaskTitle as generateErrorTaskTitle3,
3446
+ detectProjectFromError
3447
+ } from "@vibetasks/shared";
3448
+ function formatErrorNotes(error) {
3449
+ const lines = [];
3450
+ lines.push("## Error Details");
3451
+ lines.push("");
3452
+ if (error.error_type) {
3453
+ lines.push(`**Type:** ${error.error_type}`);
3454
+ }
3455
+ if (error.category) {
3456
+ lines.push(`**Category:** ${error.category}`);
3457
+ }
3458
+ if (error.message) {
3459
+ lines.push(`**Message:** ${error.message}`);
3460
+ }
3461
+ if (error.file_path) {
3462
+ lines.push(`**File:** \`${error.file_path}\``);
3463
+ if (error.line_number) {
3464
+ lines.push(`**Line:** ${error.line_number}${error.column ? `:${error.column}` : ""}`);
3465
+ }
3466
+ }
3467
+ if (error.suggestion) {
3468
+ lines.push("");
3469
+ lines.push("### Suggestion");
3470
+ lines.push(error.suggestion);
3471
+ }
3472
+ if (error.stack_trace) {
3473
+ lines.push("");
3474
+ lines.push("### Stack Trace");
3475
+ lines.push("```");
3476
+ lines.push(error.stack_trace);
3477
+ lines.push("```");
3478
+ }
3479
+ lines.push("");
3480
+ lines.push("### Raw Error");
3481
+ lines.push("```");
3482
+ const rawLines = error.raw_text.split("\n");
3483
+ if (rawLines.length > 30) {
3484
+ lines.push(rawLines.slice(0, 30).join("\n"));
3485
+ lines.push(`... (${rawLines.length - 30} more lines)`);
3486
+ } else {
3487
+ lines.push(error.raw_text);
3488
+ }
3489
+ lines.push("```");
3490
+ return lines.join("\n");
3491
+ }
3492
+ async function readStdin() {
3493
+ if (process.stdin.isTTY) {
3494
+ return null;
3495
+ }
3496
+ return new Promise((resolve) => {
3497
+ let data = "";
3498
+ process.stdin.setEncoding("utf8");
3499
+ process.stdin.on("readable", () => {
3500
+ let chunk;
3501
+ while ((chunk = process.stdin.read()) !== null) {
3502
+ data += chunk;
3503
+ }
3504
+ });
3505
+ process.stdin.on("end", () => {
3506
+ resolve(data || null);
3507
+ });
3508
+ setTimeout(() => {
3509
+ if (!data) resolve(null);
3510
+ }, 100);
3511
+ });
3512
+ }
3513
+ var errorCommand = new Command19("error").description("Capture an error and create a high-priority task").argument("[error-text]", "Error message/stack trace (or pipe from stdin)").option("-p, --project <project>", "Project name").option("--clipboard", "Read error from clipboard").action(async (errorTextArg, options) => {
3514
+ const spinner = ora14();
3515
+ try {
3516
+ let errorText = errorTextArg;
3517
+ if (!errorText) {
3518
+ const stdinData = await readStdin();
3519
+ if (stdinData) {
3520
+ errorText = stdinData;
3521
+ }
3522
+ }
3523
+ if (!errorText && options.clipboard) {
3524
+ try {
3525
+ const clipboardy = await import("clipboardy");
3526
+ errorText = await clipboardy.default.read();
3527
+ } catch {
3528
+ console.log(chalk20.yellow("Clipboard not available in this environment"));
3529
+ }
3530
+ }
3531
+ if (!errorText || !errorText.trim()) {
3532
+ console.log(chalk20.yellow("\nUsage:"));
3533
+ console.log(chalk20.gray(' vibetasks error "TypeError: Cannot read..."'));
3534
+ console.log(chalk20.gray(" npm run build 2>&1 | vibetasks error"));
3535
+ console.log(chalk20.gray(" vibetasks error --clipboard"));
3536
+ console.log("");
3537
+ process.exit(1);
3538
+ }
3539
+ spinner.start("Creating error task...");
3540
+ const authManager = new AuthManager17();
3541
+ const taskOps = await TaskOperations14.fromAuthManager(authManager);
3542
+ const errorContext = parseError(errorText, "terminal");
3543
+ const title = errorContext ? generateErrorTaskTitle3(errorContext) : `Error: ${errorText.split("\n")[0].slice(0, 80)}`;
3544
+ const detectedProject = errorContext ? detectProjectFromError(errorContext) : void 0;
3545
+ const projectTag = options.project || detectedProject;
3546
+ const notes = errorContext ? formatErrorNotes(errorContext) : `\`\`\`
3547
+ ${errorText}
3548
+ \`\`\``;
3549
+ const task = await taskOps.createTask({
3550
+ title,
3551
+ notes,
3552
+ priority: "high",
3553
+ status: "todo",
3554
+ project_tag: projectTag,
3555
+ created_by: "human",
3556
+ source_type: "cli",
3557
+ error_context: errorContext || void 0
3558
+ });
3559
+ spinner.succeed(chalk20.green("Error captured!"));
3560
+ console.log("");
3561
+ console.log(chalk20.white(` ${title}`));
3562
+ if (projectTag) {
3563
+ console.log(chalk20.blue(` Project: ${projectTag}`));
3564
+ }
3565
+ console.log(chalk20.gray(` ID: ${task.id.slice(0, 8)}`));
3566
+ console.log(chalk20.gray(` Priority: high`));
3567
+ console.log("");
3568
+ console.log(chalk20.gray("View your tasks: vibetasks list"));
3569
+ } catch (error) {
3570
+ spinner.fail(chalk20.red("Failed to capture error"));
3571
+ console.error(chalk20.gray(error.message));
3572
+ process.exit(1);
3573
+ }
3574
+ });
3575
+
3576
+ // src/commands/inbox.ts
3577
+ import { Command as Command20 } from "commander";
3578
+ import chalk21 from "chalk";
3579
+ import Table3 from "cli-table3";
3580
+ import { AuthManager as AuthManager18, TaskOperations as TaskOperations15 } from "@vibetasks/core";
3581
+ var sourceDisplay = {
3582
+ sentry: { label: "Sentry", color: chalk21.red },
3583
+ ci: { label: "CI", color: chalk21.yellow },
3584
+ github_bug: { label: "GitHub Bug", color: chalk21.magenta },
3585
+ github_feedback: { label: "GitHub", color: chalk21.magenta },
3586
+ email_bug: { label: "Email Bug", color: chalk21.blue },
3587
+ email_feedback: { label: "Email", color: chalk21.blue },
3588
+ slack_bug: { label: "Slack Bug", color: chalk21.cyan },
3589
+ slack_feedback: { label: "Slack", color: chalk21.cyan },
3590
+ manual: { label: "Manual", color: chalk21.gray }
3591
+ };
3592
+ function getSourceType(task) {
3593
+ if (task.source_type) return task.source_type;
3594
+ if (task.sentry_issue_id) return "sentry";
3595
+ if (task.github_issue_id) return task.title?.toLowerCase().includes("bug") ? "github_bug" : "github_feedback";
3596
+ if (task.email_message_id) return task.title?.toLowerCase().includes("bug") ? "email_bug" : "email_feedback";
3597
+ if (task.slack_message_id) return task.title?.toLowerCase().includes("bug") ? "slack_bug" : "slack_feedback";
3598
+ if (task.tags?.some((t) => t.name === "ci")) return "ci";
3599
+ return "manual";
3600
+ }
3601
+ function formatSource(sourceType) {
3602
+ const config = sourceDisplay[sourceType] || sourceDisplay.manual;
3603
+ return config.color(config.label);
3604
+ }
3605
+ var inboxCommand = new Command20("inbox").description("View inbox items from all sources (Sentry, GitHub, Email, Slack, CI)").option("-s, --source <source>", "Filter by source: sentry, ci, github, email, slack, errors, feedback").option("-p, --priority <priority>", "Filter by priority: high, medium, low").option("-a, --all", "Include acknowledged items").option("-l, --limit <number>", "Maximum items to show", "20").action(async (options) => {
3606
+ try {
3607
+ const authManager = new AuthManager18();
3608
+ const taskOps = await TaskOperations15.fromAuthManager(authManager);
3609
+ let sourceTypes;
3610
+ if (options.source) {
3611
+ switch (options.source.toLowerCase()) {
3612
+ case "sentry":
3613
+ sourceTypes = ["sentry"];
3614
+ break;
3615
+ case "ci":
3616
+ sourceTypes = ["ci"];
3617
+ break;
3618
+ case "github":
3619
+ sourceTypes = ["github_bug", "github_feedback"];
3620
+ break;
3621
+ case "email":
3622
+ sourceTypes = ["email_bug", "email_feedback"];
3623
+ break;
3624
+ case "slack":
3625
+ sourceTypes = ["slack_bug", "slack_feedback"];
3626
+ break;
3627
+ case "errors":
3628
+ sourceTypes = ["sentry", "ci"];
3629
+ break;
3630
+ case "feedback":
3631
+ sourceTypes = ["github_bug", "github_feedback", "email_bug", "email_feedback", "slack_bug", "slack_feedback"];
3632
+ break;
3633
+ default:
3634
+ console.error(chalk21.red(`Invalid source: ${options.source}`));
3635
+ console.error(chalk21.gray("Valid sources: sentry, ci, github, email, slack, errors, feedback"));
3636
+ process.exit(1);
3637
+ }
3638
+ }
3639
+ let priority;
3640
+ if (options.priority) {
3641
+ if (!["high", "medium", "low"].includes(options.priority)) {
3642
+ console.error(chalk21.red(`Invalid priority: ${options.priority}`));
3643
+ console.error(chalk21.gray("Valid priorities: high, medium, low"));
3644
+ process.exit(1);
3645
+ }
3646
+ priority = options.priority;
3647
+ }
3648
+ const limit = parseInt(options.limit, 10);
3649
+ const inboxItems = await taskOps.getInboxItems({
3650
+ source_type: sourceTypes,
3651
+ priority,
3652
+ unacknowledged_only: !options.all,
3653
+ limit
3654
+ });
3655
+ if (inboxItems.length === 0) {
3656
+ console.log(chalk21.green("\nInbox is empty! No items need attention.\n"));
3657
+ process.exit(0);
3658
+ }
3659
+ const table = new Table3({
3660
+ head: [
3661
+ chalk21.cyan("ID"),
3662
+ chalk21.cyan("Source"),
3663
+ chalk21.cyan("Title"),
3664
+ chalk21.cyan("Priority"),
3665
+ chalk21.cyan("Status")
3666
+ ],
3667
+ colWidths: [10, 14, 40, 10, 10],
3668
+ wordWrap: true
3669
+ });
3670
+ const priorityColors = {
3671
+ high: chalk21.red,
3672
+ medium: chalk21.yellow,
3673
+ low: chalk21.blue,
3674
+ none: chalk21.gray
3675
+ };
3676
+ const statusColors = {
3677
+ todo: chalk21.gray,
3678
+ vibing: chalk21.magenta,
3679
+ done: chalk21.green,
3680
+ archived: chalk21.dim
3681
+ };
3682
+ inboxItems.forEach((item) => {
3683
+ const sourceType = getSourceType(item);
3684
+ const priorityColor = priorityColors[item.priority || "none"];
3685
+ const statusColor = statusColors[item.status || "todo"];
3686
+ const ack = item.context_notes?.includes("[AI_ACKNOWLEDGED]") ? chalk21.dim(" (ack)") : "";
3687
+ table.push([
3688
+ item.id.substring(0, 8),
3689
+ formatSource(sourceType),
3690
+ item.title + ack,
3691
+ priorityColor(item.priority || "none"),
3692
+ statusColor(item.status || "todo")
3693
+ ]);
3694
+ });
3695
+ console.log("\n" + chalk21.bold("Inbox Items") + "\n");
3696
+ console.log(table.toString());
3697
+ console.log(chalk21.gray(`
3698
+ Showing ${inboxItems.length} items${options.all ? " (including acknowledged)" : ""}`));
3699
+ console.log(chalk21.gray("Use: vibetasks inbox stats for a summary"));
3700
+ console.log();
3701
+ process.exit(0);
3702
+ } catch (error) {
3703
+ if (error.message.includes("Not authenticated")) {
3704
+ console.error(chalk21.yellow("\nYou need to login first"));
3705
+ console.error(chalk21.gray("Run: vibetasks login\n"));
3706
+ } else {
3707
+ console.error(chalk21.red(`
3708
+ Error: ${error.message}
3709
+ `));
3710
+ }
3711
+ process.exit(1);
3712
+ }
3713
+ });
3714
+ var inboxStatsCommand = new Command20("stats").description("Show inbox statistics").action(async () => {
3715
+ try {
3716
+ const authManager = new AuthManager18();
3717
+ const taskOps = await TaskOperations15.fromAuthManager(authManager);
3718
+ const stats = await taskOps.getInboxStats();
3719
+ console.log("\n" + chalk21.bold("Inbox Statistics") + "\n");
3720
+ console.log(chalk21.white(`Total items: ${stats.total}`));
3721
+ console.log(chalk21.white(`Unacknowledged: ${stats.unacknowledged}`));
3722
+ console.log();
3723
+ console.log(chalk21.cyan("By Source:"));
3724
+ const sources = Object.entries(stats.by_source).filter(([_, count]) => count > 0);
3725
+ if (sources.length === 0) {
3726
+ console.log(chalk21.gray(" No items from any source"));
3727
+ } else {
3728
+ for (const [source, count] of sources) {
3729
+ const config = sourceDisplay[source] || sourceDisplay.manual;
3730
+ console.log(` ${config.color(config.label)}: ${count}`);
3731
+ }
3732
+ }
3733
+ console.log();
3734
+ console.log(chalk21.cyan("By Priority:"));
3735
+ const priorities = Object.entries(stats.by_priority).filter(([_, count]) => count > 0);
3736
+ if (priorities.length === 0) {
3737
+ console.log(chalk21.gray(" No prioritized items"));
3738
+ } else {
3739
+ const priorityColors = {
3740
+ high: chalk21.red,
3741
+ medium: chalk21.yellow,
3742
+ low: chalk21.blue,
3743
+ none: chalk21.gray
3744
+ };
3745
+ for (const [priority, count] of priorities) {
3746
+ const color = priorityColors[priority] || chalk21.gray;
3747
+ console.log(` ${color(priority)}: ${count}`);
3748
+ }
3749
+ }
3750
+ console.log();
3751
+ if (stats.needs_attention) {
3752
+ console.log(chalk21.yellow("Needs attention! Use: vibetasks inbox"));
3753
+ } else {
3754
+ console.log(chalk21.green("Inbox is under control!"));
3755
+ }
3756
+ console.log();
3757
+ process.exit(0);
3758
+ } catch (error) {
3759
+ if (error.message.includes("Not authenticated")) {
3760
+ console.error(chalk21.yellow("\nYou need to login first"));
3761
+ console.error(chalk21.gray("Run: vibetasks login\n"));
3762
+ } else {
3763
+ console.error(chalk21.red(`
3764
+ Error: ${error.message}
3765
+ `));
3766
+ }
3767
+ process.exit(1);
3768
+ }
3769
+ });
3770
+ inboxCommand.addCommand(inboxStatsCommand);
3771
+
3482
3772
  // bin/vibetasks.ts
3483
3773
  var require2 = createRequire(import.meta.url);
3484
3774
  var pkg = require2("../../package.json");
3485
- var program = new Command19();
3775
+ var program = new Command21();
3486
3776
  program.name("vibetasks").description("VibeTasks CLI - Fast task management for vibers").version(pkg.version);
3487
3777
  program.addCommand(setupCommand);
3488
3778
  program.addCommand(loginCommand);
@@ -3503,4 +3793,6 @@ program.addCommand(daemonCommand);
3503
3793
  program.addCommand(nextCommand);
3504
3794
  program.addCommand(sessionCommand);
3505
3795
  program.addCommand(subtaskCommand);
3796
+ program.addCommand(errorCommand);
3797
+ program.addCommand(inboxCommand);
3506
3798
  program.parse();