@vibetasks/cli 0.5.3 → 0.5.4
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/README.md +88 -0
- package/dist/bin/vibetasks.js +391 -105
- package/dist/chunk-S3G6KYGP.js +134 -0
- package/dist/src/daemon-worker.js +9 -31
- package/package.json +3 -3
- package/dist/chunk-PZF4VRDG.js +0 -430
package/dist/bin/vibetasks.js
CHANGED
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
detectError,
|
|
6
6
|
formatErrorForNotes,
|
|
7
7
|
getErrorSummary
|
|
8
|
-
} from "../chunk-
|
|
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
|
|
14
|
+
import { Command as Command21 } from "commander";
|
|
15
15
|
import { createRequire } from "module";
|
|
16
16
|
|
|
17
17
|
// src/commands/login.ts
|
|
@@ -877,7 +877,8 @@ var listCommand = new Command3("list").description("List tasks").argument("[filt
|
|
|
877
877
|
all: "No active tasks found",
|
|
878
878
|
today: "No tasks due today",
|
|
879
879
|
upcoming: "No upcoming tasks",
|
|
880
|
-
completed: "No completed tasks"
|
|
880
|
+
completed: "No completed tasks",
|
|
881
|
+
archived: "No archived tasks"
|
|
881
882
|
};
|
|
882
883
|
console.log(chalk4.gray(`
|
|
883
884
|
${filterMessages[filter] || "No tasks found"}.
|
|
@@ -918,12 +919,14 @@ ${filterMessages[filter] || "No tasks found"}.
|
|
|
918
919
|
const statusColors = {
|
|
919
920
|
todo: chalk4.gray,
|
|
920
921
|
vibing: chalk4.magenta,
|
|
921
|
-
done: chalk4.green
|
|
922
|
+
done: chalk4.green,
|
|
923
|
+
archived: chalk4.dim
|
|
922
924
|
};
|
|
923
925
|
const statusEmojis = {
|
|
924
926
|
todo: "\u{1F4CB}",
|
|
925
927
|
vibing: "\u26A1",
|
|
926
|
-
done: "\u2713"
|
|
928
|
+
done: "\u2713",
|
|
929
|
+
archived: "\u{1F4E6}"
|
|
927
930
|
};
|
|
928
931
|
const priorityColor = priorityColors[task.priority || "none"];
|
|
929
932
|
const statusColor = statusColors[task.status || "todo"];
|
|
@@ -950,7 +953,8 @@ ${filterMessages[filter] || "No tasks found"}.
|
|
|
950
953
|
all: "active",
|
|
951
954
|
today: "today",
|
|
952
955
|
upcoming: "upcoming",
|
|
953
|
-
completed: "completed"
|
|
956
|
+
completed: "completed",
|
|
957
|
+
archived: "archived"
|
|
954
958
|
};
|
|
955
959
|
console.log(chalk4.gray(`
|
|
956
960
|
Total: ${tasks.length} ${filterLabels[filter]} task${tasks.length === 1 ? "" : "s"}`));
|
|
@@ -981,7 +985,7 @@ import { Command as Command4 } from "commander";
|
|
|
981
985
|
import ora3 from "ora";
|
|
982
986
|
import chalk5 from "chalk";
|
|
983
987
|
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) => {
|
|
988
|
+
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
989
|
const spinner = ora3("Completing task...").start();
|
|
986
990
|
try {
|
|
987
991
|
const authManager = new AuthManager4();
|
|
@@ -1000,6 +1004,10 @@ No task found with ID starting with: ${id}
|
|
|
1000
1004
|
}
|
|
1001
1005
|
taskId = matchingTask.id;
|
|
1002
1006
|
}
|
|
1007
|
+
const contextNotes = options.notes || options.context;
|
|
1008
|
+
if (contextNotes) {
|
|
1009
|
+
await taskOps.updateTask(taskId, { context_notes: contextNotes });
|
|
1010
|
+
}
|
|
1003
1011
|
const task = await taskOps.completeTask(taskId);
|
|
1004
1012
|
const sessionManager2 = getSessionManager();
|
|
1005
1013
|
await sessionManager2.logAction({
|
|
@@ -1011,6 +1019,9 @@ No task found with ID starting with: ${id}
|
|
|
1011
1019
|
spinner.succeed(chalk5.green("Task completed!"));
|
|
1012
1020
|
console.log(chalk5.gray(`
|
|
1013
1021
|
\u2713 ${task.title}`));
|
|
1022
|
+
if (contextNotes) {
|
|
1023
|
+
console.log(chalk5.gray(`Notes: ${contextNotes}`));
|
|
1024
|
+
}
|
|
1014
1025
|
console.log(chalk5.gray(`Completed at: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
1015
1026
|
`));
|
|
1016
1027
|
process.exit(0);
|
|
@@ -1614,7 +1625,7 @@ import { promisify as promisify2 } from "util";
|
|
|
1614
1625
|
import { AuthManager as AuthManager11, TaskOperations as TaskOperations8, createSupabaseClient } from "@vibetasks/core";
|
|
1615
1626
|
import { detectProject as detectProject3 } from "@vibetasks/shared/utils/project-detector";
|
|
1616
1627
|
var execAsync2 = promisify2(exec2);
|
|
1617
|
-
var SUPABASE_URL = "https://
|
|
1628
|
+
var SUPABASE_URL = "https://ihmayqzxqyednchbezya.supabase.co";
|
|
1618
1629
|
var SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNia2t6dGJjb2l0cmZjbGVnaGZkIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njc3NTc0MjgsImV4cCI6MjA4MzMzMzQyOH0.G7ILx-nntP0NbxO1gKt5yASb7nt7OmpJ8qtykeGYbQA";
|
|
1619
1630
|
async function openBrowser2(url) {
|
|
1620
1631
|
const platform = process.platform;
|
|
@@ -2035,7 +2046,7 @@ function showCompletion(auth, claude, project, verify) {
|
|
|
2035
2046
|
console.log(chalk13.cyan(' "What should I work on next?"'));
|
|
2036
2047
|
}
|
|
2037
2048
|
console.log("");
|
|
2038
|
-
console.log(chalk13.gray(" Need help? https://github.com/
|
|
2049
|
+
console.log(chalk13.gray(" Need help? https://github.com/sparktory/vibetasks"));
|
|
2039
2050
|
console.log("");
|
|
2040
2051
|
}
|
|
2041
2052
|
function getSuccessHtml(email) {
|
|
@@ -2223,6 +2234,7 @@ import ora10 from "ora";
|
|
|
2223
2234
|
import inquirer5 from "inquirer";
|
|
2224
2235
|
import { AuthManager as AuthManager12, TaskOperations as TaskOperations9 } from "@vibetasks/core";
|
|
2225
2236
|
import { detectProject as detectProject4 } from "@vibetasks/shared/utils/project-detector";
|
|
2237
|
+
import { generateErrorTaskTitle } from "@vibetasks/shared";
|
|
2226
2238
|
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
2239
|
const interval = parseInt(options.interval || "1000", 10);
|
|
2228
2240
|
if (!options.quiet) {
|
|
@@ -2260,7 +2272,7 @@ Error: ${error.message}
|
|
|
2260
2272
|
}
|
|
2261
2273
|
const recentErrors = /* @__PURE__ */ new Set();
|
|
2262
2274
|
const handleError = async (error) => {
|
|
2263
|
-
const errorHash = `${error.
|
|
2275
|
+
const errorHash = `${error.error_type || "unknown"}:${(error.message || "").substring(0, 50)}`;
|
|
2264
2276
|
if (recentErrors.has(errorHash)) {
|
|
2265
2277
|
return;
|
|
2266
2278
|
}
|
|
@@ -2300,7 +2312,7 @@ Error: ${error.message}
|
|
|
2300
2312
|
case "show":
|
|
2301
2313
|
console.log();
|
|
2302
2314
|
console.log(chalk14.gray("\u2500".repeat(50)));
|
|
2303
|
-
console.log(error.
|
|
2315
|
+
console.log(error.raw_text);
|
|
2304
2316
|
console.log(chalk14.gray("\u2500".repeat(50)));
|
|
2305
2317
|
console.log();
|
|
2306
2318
|
const { afterShow } = await inquirer5.prompt([
|
|
@@ -2369,20 +2381,23 @@ Error: ${error.message}
|
|
|
2369
2381
|
async function createTaskFromError(error, taskOps, projectTag) {
|
|
2370
2382
|
const spinner = ora10("Creating task...").start();
|
|
2371
2383
|
try {
|
|
2372
|
-
const title =
|
|
2384
|
+
const title = generateErrorTaskTitle(error);
|
|
2385
|
+
const category = error.category || "general";
|
|
2373
2386
|
const task = await taskOps.createTask({
|
|
2374
2387
|
title,
|
|
2375
2388
|
notes: formatErrorForNotes(error),
|
|
2376
2389
|
notes_format: "markdown",
|
|
2377
|
-
priority:
|
|
2390
|
+
priority: category === "typescript" ? "medium" : "high",
|
|
2378
2391
|
project_tag: projectTag,
|
|
2379
2392
|
created_by: "human",
|
|
2380
2393
|
// User triggered this
|
|
2381
|
-
status: "todo"
|
|
2394
|
+
status: "todo",
|
|
2395
|
+
source_type: "cli",
|
|
2396
|
+
error_context: error
|
|
2382
2397
|
});
|
|
2383
|
-
const tagName = `error-${
|
|
2398
|
+
const tagName = `error-${category}`;
|
|
2384
2399
|
try {
|
|
2385
|
-
const tag = await taskOps.findOrCreateTag(tagName, getTagColor(
|
|
2400
|
+
const tag = await taskOps.findOrCreateTag(tagName, getTagColor(category));
|
|
2386
2401
|
await taskOps.linkTaskTags(task.id, [tag.id]);
|
|
2387
2402
|
} catch {
|
|
2388
2403
|
}
|
|
@@ -2394,41 +2409,6 @@ async function createTaskFromError(error, taskOps, projectTag) {
|
|
|
2394
2409
|
console.error(chalk14.red(`Error: ${err.message}`));
|
|
2395
2410
|
}
|
|
2396
2411
|
}
|
|
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
2412
|
function getTagColor(category) {
|
|
2433
2413
|
const colors = {
|
|
2434
2414
|
nodejs: "#68A063",
|
|
@@ -2550,11 +2530,12 @@ Restored: ${task2.title}`));
|
|
|
2550
2530
|
console.log(chalk15.gray(" or: vibetasks archive --unarchive <id>\n"));
|
|
2551
2531
|
process.exit(1);
|
|
2552
2532
|
}
|
|
2533
|
+
const validTaskId = taskId;
|
|
2553
2534
|
spinner.start("Archiving task...");
|
|
2554
|
-
let targetId =
|
|
2555
|
-
if (
|
|
2535
|
+
let targetId = validTaskId;
|
|
2536
|
+
if (validTaskId.length < 32) {
|
|
2556
2537
|
const allTasks = await taskOps.getTasks("all", true);
|
|
2557
|
-
const matchingTask = allTasks.find((t) => t.id.startsWith(
|
|
2538
|
+
const matchingTask = allTasks.find((t) => t.id.startsWith(validTaskId));
|
|
2558
2539
|
if (!matchingTask) {
|
|
2559
2540
|
spinner.fail(chalk15.red("Task not found"));
|
|
2560
2541
|
console.error(chalk15.gray(`
|
|
@@ -2595,6 +2576,7 @@ import { spawn } from "child_process";
|
|
|
2595
2576
|
import path3 from "path";
|
|
2596
2577
|
import { fileURLToPath } from "url";
|
|
2597
2578
|
import { AuthManager as AuthManager14, TaskOperations as TaskOperations11 } from "@vibetasks/core";
|
|
2579
|
+
import { generateErrorTaskTitle as generateErrorTaskTitle2 } from "@vibetasks/shared";
|
|
2598
2580
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
2599
2581
|
var __dirname2 = path3.dirname(__filename2);
|
|
2600
2582
|
var daemonCommand = new Command15("daemon").description("Manage the VibeTasks error capture daemon").addCommand(createStartCommand()).addCommand(createStopCommand()).addCommand(createStatusCommand()).addCommand(createConfigureCommand()).addCommand(createCaptureCommand());
|
|
@@ -2763,21 +2745,21 @@ function createCaptureCommand() {
|
|
|
2763
2745
|
process.exit(0);
|
|
2764
2746
|
}
|
|
2765
2747
|
console.log(chalk16.red.bold("\nError Detected!\n"));
|
|
2766
|
-
console.log(chalk16.cyan("Type: ") + chalk16.white(error.
|
|
2767
|
-
console.log(chalk16.cyan("Category: ") + chalk16.white(error.category));
|
|
2768
|
-
console.log(chalk16.cyan("Message: ") + chalk16.white(error.message));
|
|
2769
|
-
if (error.
|
|
2770
|
-
console.log(chalk16.cyan("File: ") + chalk16.white(error.
|
|
2771
|
-
if (error.
|
|
2772
|
-
console.log(chalk16.cyan("Line: ") + chalk16.white(error.
|
|
2748
|
+
console.log(chalk16.cyan("Type: ") + chalk16.white(error.error_type || "Unknown"));
|
|
2749
|
+
console.log(chalk16.cyan("Category: ") + chalk16.white(error.category || "general"));
|
|
2750
|
+
console.log(chalk16.cyan("Message: ") + chalk16.white(error.message || ""));
|
|
2751
|
+
if (error.file_path) {
|
|
2752
|
+
console.log(chalk16.cyan("File: ") + chalk16.white(error.file_path));
|
|
2753
|
+
if (error.line_number) {
|
|
2754
|
+
console.log(chalk16.cyan("Line: ") + chalk16.white(error.line_number.toString()) + (error.column ? chalk16.gray(`:${error.column}`) : ""));
|
|
2773
2755
|
}
|
|
2774
2756
|
}
|
|
2775
2757
|
if (error.suggestion) {
|
|
2776
2758
|
console.log(chalk16.green("\nSuggestion: ") + chalk16.white(error.suggestion));
|
|
2777
2759
|
}
|
|
2778
|
-
if (error.
|
|
2760
|
+
if (error.stack_trace) {
|
|
2779
2761
|
console.log(chalk16.cyan("\nStack Trace (first 5 lines):"));
|
|
2780
|
-
const stackLines = error.
|
|
2762
|
+
const stackLines = error.stack_trace.split("\n").slice(0, 5);
|
|
2781
2763
|
stackLines.forEach((line) => {
|
|
2782
2764
|
console.log(chalk16.gray(" " + line));
|
|
2783
2765
|
});
|
|
@@ -2914,59 +2896,27 @@ async function showNotification(title, message, type = "info", duration) {
|
|
|
2914
2896
|
console.log(chalk16.blue(`[Notification] ${title}: ${message}`));
|
|
2915
2897
|
}
|
|
2916
2898
|
}
|
|
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
2899
|
async function createTaskFromError2(error) {
|
|
2953
2900
|
const spinner = ora12("Creating task from error...").start();
|
|
2954
2901
|
try {
|
|
2955
2902
|
const authManager = new AuthManager14();
|
|
2956
2903
|
const taskOps = await TaskOperations11.fromAuthManager(authManager);
|
|
2957
|
-
const title =
|
|
2904
|
+
const title = generateErrorTaskTitle2(error);
|
|
2958
2905
|
const notes = formatErrorForNotes(error);
|
|
2906
|
+
const category = error.category || "general";
|
|
2959
2907
|
const task = await taskOps.createTask({
|
|
2960
2908
|
title,
|
|
2961
2909
|
notes,
|
|
2962
2910
|
notes_format: "markdown",
|
|
2963
|
-
priority:
|
|
2911
|
+
priority: category === "typescript" ? "medium" : "high",
|
|
2964
2912
|
created_by: "ai",
|
|
2965
|
-
status: "todo"
|
|
2913
|
+
status: "todo",
|
|
2914
|
+
source_type: "cli",
|
|
2915
|
+
error_context: error
|
|
2966
2916
|
});
|
|
2967
|
-
const tagName = `error-${
|
|
2917
|
+
const tagName = `error-${category}`;
|
|
2968
2918
|
try {
|
|
2969
|
-
const tag = await taskOps.findOrCreateTag(tagName, getTagColor2(
|
|
2919
|
+
const tag = await taskOps.findOrCreateTag(tagName, getTagColor2(category));
|
|
2970
2920
|
await taskOps.linkTaskTags(task.id, [tag.id]);
|
|
2971
2921
|
} catch {
|
|
2972
2922
|
}
|
|
@@ -3036,7 +2986,7 @@ var nextCommand = new Command16("next").description("Show and optionally start t
|
|
|
3036
2986
|
}
|
|
3037
2987
|
const nextTask = tasks[0];
|
|
3038
2988
|
if (options.start && nextTask.status !== "vibing") {
|
|
3039
|
-
await taskOps.
|
|
2989
|
+
await taskOps.updateTask(nextTask.id, { status: "vibing" });
|
|
3040
2990
|
console.log(chalk17.green(`
|
|
3041
2991
|
\u26A1 Started vibing on task!
|
|
3042
2992
|
`));
|
|
@@ -3479,10 +3429,344 @@ Error: ${error.message}
|
|
|
3479
3429
|
}
|
|
3480
3430
|
});
|
|
3481
3431
|
|
|
3432
|
+
// src/commands/error.ts
|
|
3433
|
+
import { Command as Command19 } from "commander";
|
|
3434
|
+
import chalk20 from "chalk";
|
|
3435
|
+
import ora14 from "ora";
|
|
3436
|
+
import { AuthManager as AuthManager17, TaskOperations as TaskOperations14 } from "@vibetasks/core";
|
|
3437
|
+
import {
|
|
3438
|
+
parseError,
|
|
3439
|
+
generateErrorTaskTitle as generateErrorTaskTitle3,
|
|
3440
|
+
detectProjectFromError
|
|
3441
|
+
} from "@vibetasks/shared";
|
|
3442
|
+
function formatErrorNotes(error) {
|
|
3443
|
+
const lines = [];
|
|
3444
|
+
lines.push("## Error Details");
|
|
3445
|
+
lines.push("");
|
|
3446
|
+
if (error.error_type) {
|
|
3447
|
+
lines.push(`**Type:** ${error.error_type}`);
|
|
3448
|
+
}
|
|
3449
|
+
if (error.category) {
|
|
3450
|
+
lines.push(`**Category:** ${error.category}`);
|
|
3451
|
+
}
|
|
3452
|
+
if (error.message) {
|
|
3453
|
+
lines.push(`**Message:** ${error.message}`);
|
|
3454
|
+
}
|
|
3455
|
+
if (error.file_path) {
|
|
3456
|
+
lines.push(`**File:** \`${error.file_path}\``);
|
|
3457
|
+
if (error.line_number) {
|
|
3458
|
+
lines.push(`**Line:** ${error.line_number}${error.column ? `:${error.column}` : ""}`);
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
if (error.suggestion) {
|
|
3462
|
+
lines.push("");
|
|
3463
|
+
lines.push("### Suggestion");
|
|
3464
|
+
lines.push(error.suggestion);
|
|
3465
|
+
}
|
|
3466
|
+
if (error.stack_trace) {
|
|
3467
|
+
lines.push("");
|
|
3468
|
+
lines.push("### Stack Trace");
|
|
3469
|
+
lines.push("```");
|
|
3470
|
+
lines.push(error.stack_trace);
|
|
3471
|
+
lines.push("```");
|
|
3472
|
+
}
|
|
3473
|
+
lines.push("");
|
|
3474
|
+
lines.push("### Raw Error");
|
|
3475
|
+
lines.push("```");
|
|
3476
|
+
const rawLines = error.raw_text.split("\n");
|
|
3477
|
+
if (rawLines.length > 30) {
|
|
3478
|
+
lines.push(rawLines.slice(0, 30).join("\n"));
|
|
3479
|
+
lines.push(`... (${rawLines.length - 30} more lines)`);
|
|
3480
|
+
} else {
|
|
3481
|
+
lines.push(error.raw_text);
|
|
3482
|
+
}
|
|
3483
|
+
lines.push("```");
|
|
3484
|
+
return lines.join("\n");
|
|
3485
|
+
}
|
|
3486
|
+
async function readStdin() {
|
|
3487
|
+
if (process.stdin.isTTY) {
|
|
3488
|
+
return null;
|
|
3489
|
+
}
|
|
3490
|
+
return new Promise((resolve) => {
|
|
3491
|
+
let data = "";
|
|
3492
|
+
process.stdin.setEncoding("utf8");
|
|
3493
|
+
process.stdin.on("readable", () => {
|
|
3494
|
+
let chunk;
|
|
3495
|
+
while ((chunk = process.stdin.read()) !== null) {
|
|
3496
|
+
data += chunk;
|
|
3497
|
+
}
|
|
3498
|
+
});
|
|
3499
|
+
process.stdin.on("end", () => {
|
|
3500
|
+
resolve(data || null);
|
|
3501
|
+
});
|
|
3502
|
+
setTimeout(() => {
|
|
3503
|
+
if (!data) resolve(null);
|
|
3504
|
+
}, 100);
|
|
3505
|
+
});
|
|
3506
|
+
}
|
|
3507
|
+
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) => {
|
|
3508
|
+
const spinner = ora14();
|
|
3509
|
+
try {
|
|
3510
|
+
let errorText = errorTextArg;
|
|
3511
|
+
if (!errorText) {
|
|
3512
|
+
const stdinData = await readStdin();
|
|
3513
|
+
if (stdinData) {
|
|
3514
|
+
errorText = stdinData;
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
if (!errorText && options.clipboard) {
|
|
3518
|
+
try {
|
|
3519
|
+
const clipboardy = await import("clipboardy");
|
|
3520
|
+
errorText = await clipboardy.default.read();
|
|
3521
|
+
} catch {
|
|
3522
|
+
console.log(chalk20.yellow("Clipboard not available in this environment"));
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
if (!errorText || !errorText.trim()) {
|
|
3526
|
+
console.log(chalk20.yellow("\nUsage:"));
|
|
3527
|
+
console.log(chalk20.gray(' vibetasks error "TypeError: Cannot read..."'));
|
|
3528
|
+
console.log(chalk20.gray(" npm run build 2>&1 | vibetasks error"));
|
|
3529
|
+
console.log(chalk20.gray(" vibetasks error --clipboard"));
|
|
3530
|
+
console.log("");
|
|
3531
|
+
process.exit(1);
|
|
3532
|
+
}
|
|
3533
|
+
spinner.start("Creating error task...");
|
|
3534
|
+
const authManager = new AuthManager17();
|
|
3535
|
+
const taskOps = await TaskOperations14.fromAuthManager(authManager);
|
|
3536
|
+
const errorContext = parseError(errorText, "terminal");
|
|
3537
|
+
const title = errorContext ? generateErrorTaskTitle3(errorContext) : `Error: ${errorText.split("\n")[0].slice(0, 80)}`;
|
|
3538
|
+
const detectedProject = errorContext ? detectProjectFromError(errorContext) : void 0;
|
|
3539
|
+
const projectTag = options.project || detectedProject;
|
|
3540
|
+
const notes = errorContext ? formatErrorNotes(errorContext) : `\`\`\`
|
|
3541
|
+
${errorText}
|
|
3542
|
+
\`\`\``;
|
|
3543
|
+
const task = await taskOps.createTask({
|
|
3544
|
+
title,
|
|
3545
|
+
notes,
|
|
3546
|
+
priority: "high",
|
|
3547
|
+
status: "todo",
|
|
3548
|
+
project_tag: projectTag,
|
|
3549
|
+
created_by: "human",
|
|
3550
|
+
source_type: "cli",
|
|
3551
|
+
error_context: errorContext || void 0
|
|
3552
|
+
});
|
|
3553
|
+
spinner.succeed(chalk20.green("Error captured!"));
|
|
3554
|
+
console.log("");
|
|
3555
|
+
console.log(chalk20.white(` ${title}`));
|
|
3556
|
+
if (projectTag) {
|
|
3557
|
+
console.log(chalk20.blue(` Project: ${projectTag}`));
|
|
3558
|
+
}
|
|
3559
|
+
console.log(chalk20.gray(` ID: ${task.id.slice(0, 8)}`));
|
|
3560
|
+
console.log(chalk20.gray(` Priority: high`));
|
|
3561
|
+
console.log("");
|
|
3562
|
+
console.log(chalk20.gray("View your tasks: vibetasks list"));
|
|
3563
|
+
} catch (error) {
|
|
3564
|
+
spinner.fail(chalk20.red("Failed to capture error"));
|
|
3565
|
+
console.error(chalk20.gray(error.message));
|
|
3566
|
+
process.exit(1);
|
|
3567
|
+
}
|
|
3568
|
+
});
|
|
3569
|
+
|
|
3570
|
+
// src/commands/inbox.ts
|
|
3571
|
+
import { Command as Command20 } from "commander";
|
|
3572
|
+
import chalk21 from "chalk";
|
|
3573
|
+
import Table3 from "cli-table3";
|
|
3574
|
+
import { AuthManager as AuthManager18, TaskOperations as TaskOperations15 } from "@vibetasks/core";
|
|
3575
|
+
var sourceDisplay = {
|
|
3576
|
+
sentry: { label: "Sentry", color: chalk21.red },
|
|
3577
|
+
ci: { label: "CI", color: chalk21.yellow },
|
|
3578
|
+
github_bug: { label: "GitHub Bug", color: chalk21.magenta },
|
|
3579
|
+
github_feedback: { label: "GitHub", color: chalk21.magenta },
|
|
3580
|
+
email_bug: { label: "Email Bug", color: chalk21.blue },
|
|
3581
|
+
email_feedback: { label: "Email", color: chalk21.blue },
|
|
3582
|
+
slack_bug: { label: "Slack Bug", color: chalk21.cyan },
|
|
3583
|
+
slack_feedback: { label: "Slack", color: chalk21.cyan },
|
|
3584
|
+
manual: { label: "Manual", color: chalk21.gray }
|
|
3585
|
+
};
|
|
3586
|
+
function getSourceType(task) {
|
|
3587
|
+
if (task.source_type) return task.source_type;
|
|
3588
|
+
if (task.sentry_issue_id) return "sentry";
|
|
3589
|
+
if (task.github_issue_id) return task.title?.toLowerCase().includes("bug") ? "github_bug" : "github_feedback";
|
|
3590
|
+
if (task.email_message_id) return task.title?.toLowerCase().includes("bug") ? "email_bug" : "email_feedback";
|
|
3591
|
+
if (task.slack_message_id) return task.title?.toLowerCase().includes("bug") ? "slack_bug" : "slack_feedback";
|
|
3592
|
+
if (task.tags?.some((t) => t.name === "ci")) return "ci";
|
|
3593
|
+
return "manual";
|
|
3594
|
+
}
|
|
3595
|
+
function formatSource(sourceType) {
|
|
3596
|
+
const config = sourceDisplay[sourceType] || sourceDisplay.manual;
|
|
3597
|
+
return config.color(config.label);
|
|
3598
|
+
}
|
|
3599
|
+
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) => {
|
|
3600
|
+
try {
|
|
3601
|
+
const authManager = new AuthManager18();
|
|
3602
|
+
const taskOps = await TaskOperations15.fromAuthManager(authManager);
|
|
3603
|
+
let sourceTypes;
|
|
3604
|
+
if (options.source) {
|
|
3605
|
+
switch (options.source.toLowerCase()) {
|
|
3606
|
+
case "sentry":
|
|
3607
|
+
sourceTypes = ["sentry"];
|
|
3608
|
+
break;
|
|
3609
|
+
case "ci":
|
|
3610
|
+
sourceTypes = ["ci"];
|
|
3611
|
+
break;
|
|
3612
|
+
case "github":
|
|
3613
|
+
sourceTypes = ["github_bug", "github_feedback"];
|
|
3614
|
+
break;
|
|
3615
|
+
case "email":
|
|
3616
|
+
sourceTypes = ["email_bug", "email_feedback"];
|
|
3617
|
+
break;
|
|
3618
|
+
case "slack":
|
|
3619
|
+
sourceTypes = ["slack_bug", "slack_feedback"];
|
|
3620
|
+
break;
|
|
3621
|
+
case "errors":
|
|
3622
|
+
sourceTypes = ["sentry", "ci"];
|
|
3623
|
+
break;
|
|
3624
|
+
case "feedback":
|
|
3625
|
+
sourceTypes = ["github_bug", "github_feedback", "email_bug", "email_feedback", "slack_bug", "slack_feedback"];
|
|
3626
|
+
break;
|
|
3627
|
+
default:
|
|
3628
|
+
console.error(chalk21.red(`Invalid source: ${options.source}`));
|
|
3629
|
+
console.error(chalk21.gray("Valid sources: sentry, ci, github, email, slack, errors, feedback"));
|
|
3630
|
+
process.exit(1);
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
let priority;
|
|
3634
|
+
if (options.priority) {
|
|
3635
|
+
if (!["high", "medium", "low"].includes(options.priority)) {
|
|
3636
|
+
console.error(chalk21.red(`Invalid priority: ${options.priority}`));
|
|
3637
|
+
console.error(chalk21.gray("Valid priorities: high, medium, low"));
|
|
3638
|
+
process.exit(1);
|
|
3639
|
+
}
|
|
3640
|
+
priority = options.priority;
|
|
3641
|
+
}
|
|
3642
|
+
const limit = parseInt(options.limit, 10);
|
|
3643
|
+
const inboxItems = await taskOps.getInboxItems({
|
|
3644
|
+
source_type: sourceTypes,
|
|
3645
|
+
priority,
|
|
3646
|
+
unacknowledged_only: !options.all,
|
|
3647
|
+
limit
|
|
3648
|
+
});
|
|
3649
|
+
if (inboxItems.length === 0) {
|
|
3650
|
+
console.log(chalk21.green("\nInbox is empty! No items need attention.\n"));
|
|
3651
|
+
process.exit(0);
|
|
3652
|
+
}
|
|
3653
|
+
const table = new Table3({
|
|
3654
|
+
head: [
|
|
3655
|
+
chalk21.cyan("ID"),
|
|
3656
|
+
chalk21.cyan("Source"),
|
|
3657
|
+
chalk21.cyan("Title"),
|
|
3658
|
+
chalk21.cyan("Priority"),
|
|
3659
|
+
chalk21.cyan("Status")
|
|
3660
|
+
],
|
|
3661
|
+
colWidths: [10, 14, 40, 10, 10],
|
|
3662
|
+
wordWrap: true
|
|
3663
|
+
});
|
|
3664
|
+
const priorityColors = {
|
|
3665
|
+
high: chalk21.red,
|
|
3666
|
+
medium: chalk21.yellow,
|
|
3667
|
+
low: chalk21.blue,
|
|
3668
|
+
none: chalk21.gray
|
|
3669
|
+
};
|
|
3670
|
+
const statusColors = {
|
|
3671
|
+
todo: chalk21.gray,
|
|
3672
|
+
vibing: chalk21.magenta,
|
|
3673
|
+
done: chalk21.green,
|
|
3674
|
+
archived: chalk21.dim
|
|
3675
|
+
};
|
|
3676
|
+
inboxItems.forEach((item) => {
|
|
3677
|
+
const sourceType = getSourceType(item);
|
|
3678
|
+
const priorityColor = priorityColors[item.priority || "none"];
|
|
3679
|
+
const statusColor = statusColors[item.status || "todo"];
|
|
3680
|
+
const ack = item.context_notes?.includes("[AI_ACKNOWLEDGED]") ? chalk21.dim(" (ack)") : "";
|
|
3681
|
+
table.push([
|
|
3682
|
+
item.id.substring(0, 8),
|
|
3683
|
+
formatSource(sourceType),
|
|
3684
|
+
item.title + ack,
|
|
3685
|
+
priorityColor(item.priority || "none"),
|
|
3686
|
+
statusColor(item.status || "todo")
|
|
3687
|
+
]);
|
|
3688
|
+
});
|
|
3689
|
+
console.log("\n" + chalk21.bold("Inbox Items") + "\n");
|
|
3690
|
+
console.log(table.toString());
|
|
3691
|
+
console.log(chalk21.gray(`
|
|
3692
|
+
Showing ${inboxItems.length} items${options.all ? " (including acknowledged)" : ""}`));
|
|
3693
|
+
console.log(chalk21.gray("Use: vibetasks inbox stats for a summary"));
|
|
3694
|
+
console.log();
|
|
3695
|
+
process.exit(0);
|
|
3696
|
+
} catch (error) {
|
|
3697
|
+
if (error.message.includes("Not authenticated")) {
|
|
3698
|
+
console.error(chalk21.yellow("\nYou need to login first"));
|
|
3699
|
+
console.error(chalk21.gray("Run: vibetasks login\n"));
|
|
3700
|
+
} else {
|
|
3701
|
+
console.error(chalk21.red(`
|
|
3702
|
+
Error: ${error.message}
|
|
3703
|
+
`));
|
|
3704
|
+
}
|
|
3705
|
+
process.exit(1);
|
|
3706
|
+
}
|
|
3707
|
+
});
|
|
3708
|
+
var inboxStatsCommand = new Command20("stats").description("Show inbox statistics").action(async () => {
|
|
3709
|
+
try {
|
|
3710
|
+
const authManager = new AuthManager18();
|
|
3711
|
+
const taskOps = await TaskOperations15.fromAuthManager(authManager);
|
|
3712
|
+
const stats = await taskOps.getInboxStats();
|
|
3713
|
+
console.log("\n" + chalk21.bold("Inbox Statistics") + "\n");
|
|
3714
|
+
console.log(chalk21.white(`Total items: ${stats.total}`));
|
|
3715
|
+
console.log(chalk21.white(`Unacknowledged: ${stats.unacknowledged}`));
|
|
3716
|
+
console.log();
|
|
3717
|
+
console.log(chalk21.cyan("By Source:"));
|
|
3718
|
+
const sources = Object.entries(stats.by_source).filter(([_, count]) => count > 0);
|
|
3719
|
+
if (sources.length === 0) {
|
|
3720
|
+
console.log(chalk21.gray(" No items from any source"));
|
|
3721
|
+
} else {
|
|
3722
|
+
for (const [source, count] of sources) {
|
|
3723
|
+
const config = sourceDisplay[source] || sourceDisplay.manual;
|
|
3724
|
+
console.log(` ${config.color(config.label)}: ${count}`);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
console.log();
|
|
3728
|
+
console.log(chalk21.cyan("By Priority:"));
|
|
3729
|
+
const priorities = Object.entries(stats.by_priority).filter(([_, count]) => count > 0);
|
|
3730
|
+
if (priorities.length === 0) {
|
|
3731
|
+
console.log(chalk21.gray(" No prioritized items"));
|
|
3732
|
+
} else {
|
|
3733
|
+
const priorityColors = {
|
|
3734
|
+
high: chalk21.red,
|
|
3735
|
+
medium: chalk21.yellow,
|
|
3736
|
+
low: chalk21.blue,
|
|
3737
|
+
none: chalk21.gray
|
|
3738
|
+
};
|
|
3739
|
+
for (const [priority, count] of priorities) {
|
|
3740
|
+
const color = priorityColors[priority] || chalk21.gray;
|
|
3741
|
+
console.log(` ${color(priority)}: ${count}`);
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
console.log();
|
|
3745
|
+
if (stats.needs_attention) {
|
|
3746
|
+
console.log(chalk21.yellow("Needs attention! Use: vibetasks inbox"));
|
|
3747
|
+
} else {
|
|
3748
|
+
console.log(chalk21.green("Inbox is under control!"));
|
|
3749
|
+
}
|
|
3750
|
+
console.log();
|
|
3751
|
+
process.exit(0);
|
|
3752
|
+
} catch (error) {
|
|
3753
|
+
if (error.message.includes("Not authenticated")) {
|
|
3754
|
+
console.error(chalk21.yellow("\nYou need to login first"));
|
|
3755
|
+
console.error(chalk21.gray("Run: vibetasks login\n"));
|
|
3756
|
+
} else {
|
|
3757
|
+
console.error(chalk21.red(`
|
|
3758
|
+
Error: ${error.message}
|
|
3759
|
+
`));
|
|
3760
|
+
}
|
|
3761
|
+
process.exit(1);
|
|
3762
|
+
}
|
|
3763
|
+
});
|
|
3764
|
+
inboxCommand.addCommand(inboxStatsCommand);
|
|
3765
|
+
|
|
3482
3766
|
// bin/vibetasks.ts
|
|
3483
3767
|
var require2 = createRequire(import.meta.url);
|
|
3484
3768
|
var pkg = require2("../../package.json");
|
|
3485
|
-
var program = new
|
|
3769
|
+
var program = new Command21();
|
|
3486
3770
|
program.name("vibetasks").description("VibeTasks CLI - Fast task management for vibers").version(pkg.version);
|
|
3487
3771
|
program.addCommand(setupCommand);
|
|
3488
3772
|
program.addCommand(loginCommand);
|
|
@@ -3503,4 +3787,6 @@ program.addCommand(daemonCommand);
|
|
|
3503
3787
|
program.addCommand(nextCommand);
|
|
3504
3788
|
program.addCommand(sessionCommand);
|
|
3505
3789
|
program.addCommand(subtaskCommand);
|
|
3790
|
+
program.addCommand(errorCommand);
|
|
3791
|
+
program.addCommand(inboxCommand);
|
|
3506
3792
|
program.parse();
|