@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.
- package/README.md +88 -0
- package/dist/bin/vibetasks.js +401 -109
- 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
|
|
@@ -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="
|
|
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://
|
|
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 || "
|
|
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/
|
|
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.
|
|
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.
|
|
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 =
|
|
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:
|
|
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-${
|
|
2404
|
+
const tagName = `error-${category}`;
|
|
2384
2405
|
try {
|
|
2385
|
-
const tag = await taskOps.findOrCreateTag(tagName, getTagColor(
|
|
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 =
|
|
2555
|
-
if (
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
2766
|
+
if (error.stack_trace) {
|
|
2779
2767
|
console.log(chalk16.cyan("\nStack Trace (first 5 lines):"));
|
|
2780
|
-
const stackLines = error.
|
|
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 =
|
|
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:
|
|
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-${
|
|
2923
|
+
const tagName = `error-${category}`;
|
|
2968
2924
|
try {
|
|
2969
|
-
const tag = await taskOps.findOrCreateTag(tagName, getTagColor2(
|
|
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.
|
|
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
|
|
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();
|