octie-cli 1.0.0
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 +523 -0
- package/dist/cli/commands/approve.d.ts +27 -0
- package/dist/cli/commands/approve.d.ts.map +1 -0
- package/dist/cli/commands/approve.js +119 -0
- package/dist/cli/commands/approve.js.map +1 -0
- package/dist/cli/commands/batch.d.ts +15 -0
- package/dist/cli/commands/batch.d.ts.map +1 -0
- package/dist/cli/commands/batch.js +521 -0
- package/dist/cli/commands/batch.js.map +1 -0
- package/dist/cli/commands/create.d.ts +9 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +321 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +9 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +143 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/export.d.ts +9 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +66 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/find.d.ts +16 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +252 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/get.d.ts +9 -0
- package/dist/cli/commands/get.d.ts.map +1 -0
- package/dist/cli/commands/get.js +74 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +9 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +200 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/import.d.ts +9 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +807 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +57 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +175 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/merge.d.ts +9 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +113 -0
- package/dist/cli/commands/merge.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +94 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +423 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/wire.d.ts +15 -0
- package/dist/cli/commands/wire.d.ts.map +1 -0
- package/dist/cli/commands/wire.js +164 -0
- package/dist/cli/commands/wire.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +100 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output/json.d.ts +16 -0
- package/dist/cli/output/json.d.ts.map +1 -0
- package/dist/cli/output/json.js +29 -0
- package/dist/cli/output/json.js.map +1 -0
- package/dist/cli/output/markdown.d.ts +15 -0
- package/dist/cli/output/markdown.d.ts.map +1 -0
- package/dist/cli/output/markdown.js +206 -0
- package/dist/cli/output/markdown.js.map +1 -0
- package/dist/cli/output/table.d.ts +23 -0
- package/dist/cli/output/table.d.ts.map +1 -0
- package/dist/cli/output/table.js +150 -0
- package/dist/cli/output/table.js.map +1 -0
- package/dist/cli/utils/helpers.d.ts +126 -0
- package/dist/cli/utils/helpers.d.ts.map +1 -0
- package/dist/cli/utils/helpers.js +325 -0
- package/dist/cli/utils/helpers.js.map +1 -0
- package/dist/core/graph/algorithms.d.ts +11 -0
- package/dist/core/graph/algorithms.d.ts.map +1 -0
- package/dist/core/graph/algorithms.js +14 -0
- package/dist/core/graph/algorithms.js.map +1 -0
- package/dist/core/graph/cycle.d.ts +155 -0
- package/dist/core/graph/cycle.d.ts.map +1 -0
- package/dist/core/graph/cycle.js +297 -0
- package/dist/core/graph/cycle.js.map +1 -0
- package/dist/core/graph/index.d.ts +223 -0
- package/dist/core/graph/index.d.ts.map +1 -0
- package/dist/core/graph/index.js +475 -0
- package/dist/core/graph/index.js.map +1 -0
- package/dist/core/graph/operations.d.ts +240 -0
- package/dist/core/graph/operations.d.ts.map +1 -0
- package/dist/core/graph/operations.js +503 -0
- package/dist/core/graph/operations.js.map +1 -0
- package/dist/core/graph/sort.d.ts +76 -0
- package/dist/core/graph/sort.d.ts.map +1 -0
- package/dist/core/graph/sort.js +254 -0
- package/dist/core/graph/sort.js.map +1 -0
- package/dist/core/graph/traversal.d.ts +122 -0
- package/dist/core/graph/traversal.d.ts.map +1 -0
- package/dist/core/graph/traversal.js +336 -0
- package/dist/core/graph/traversal.js.map +1 -0
- package/dist/core/models/task-node.d.ts +328 -0
- package/dist/core/models/task-node.d.ts.map +1 -0
- package/dist/core/models/task-node.js +1090 -0
- package/dist/core/models/task-node.js.map +1 -0
- package/dist/core/registry/index.d.ts +102 -0
- package/dist/core/registry/index.d.ts.map +1 -0
- package/dist/core/registry/index.js +249 -0
- package/dist/core/registry/index.js.map +1 -0
- package/dist/core/registry/root-guard.d.ts +19 -0
- package/dist/core/registry/root-guard.d.ts.map +1 -0
- package/dist/core/registry/root-guard.js +28 -0
- package/dist/core/registry/root-guard.js.map +1 -0
- package/dist/core/storage/atomic-write.d.ts +181 -0
- package/dist/core/storage/atomic-write.d.ts.map +1 -0
- package/dist/core/storage/atomic-write.js +379 -0
- package/dist/core/storage/atomic-write.js.map +1 -0
- package/dist/core/storage/file-store.d.ts +148 -0
- package/dist/core/storage/file-store.d.ts.map +1 -0
- package/dist/core/storage/file-store.js +423 -0
- package/dist/core/storage/file-store.js.map +1 -0
- package/dist/core/storage/indexer.d.ts +138 -0
- package/dist/core/storage/indexer.d.ts.map +1 -0
- package/dist/core/storage/indexer.js +350 -0
- package/dist/core/storage/indexer.js.map +1 -0
- package/dist/core/utils/status-helpers.d.ts +59 -0
- package/dist/core/utils/status-helpers.d.ts.map +1 -0
- package/dist/core/utils/status-helpers.js +149 -0
- package/dist/core/utils/status-helpers.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +504 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +182 -0
- package/dist/types/index.js.map +1 -0
- package/dist/web/routes/graph.d.ts +17 -0
- package/dist/web/routes/graph.d.ts.map +1 -0
- package/dist/web/routes/graph.js +277 -0
- package/dist/web/routes/graph.js.map +1 -0
- package/dist/web/routes/projects.d.ts +14 -0
- package/dist/web/routes/projects.d.ts.map +1 -0
- package/dist/web/routes/projects.js +102 -0
- package/dist/web/routes/projects.js.map +1 -0
- package/dist/web/routes/tasks.d.ts +17 -0
- package/dist/web/routes/tasks.d.ts.map +1 -0
- package/dist/web/routes/tasks.js +538 -0
- package/dist/web/routes/tasks.js.map +1 -0
- package/dist/web/server.d.ts +121 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +389 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web-ui/assets/index-BB0qvF1y.css +1 -0
- package/dist/web-ui/assets/index-Vmm72oKY.js +34 -0
- package/dist/web-ui/index.html +14 -0
- package/dist/web-ui/vite.svg +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI utility functions
|
|
3
|
+
*/
|
|
4
|
+
import type { TaskGraphStore } from '../../core/graph/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Get the project path from options or auto-detect
|
|
7
|
+
*/
|
|
8
|
+
export declare function getProjectPath(projectOption?: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Load the project graph
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadGraph(projectPath: string): Promise<TaskGraphStore>;
|
|
13
|
+
/**
|
|
14
|
+
* Save the project graph
|
|
15
|
+
*/
|
|
16
|
+
export declare function saveGraph(projectPath: string, graph: TaskGraphStore): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Format success message
|
|
19
|
+
*/
|
|
20
|
+
export declare function success(message: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Format error message
|
|
23
|
+
*/
|
|
24
|
+
export declare function error(message: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Format warning message
|
|
27
|
+
*/
|
|
28
|
+
export declare function warning(message: string): void;
|
|
29
|
+
/**
|
|
30
|
+
* Format info message
|
|
31
|
+
*/
|
|
32
|
+
export declare function info(message: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Format verbose message (only shown if --verbose flag is set)
|
|
35
|
+
*/
|
|
36
|
+
export declare function verbose(message: string, verbose: boolean): void;
|
|
37
|
+
/**
|
|
38
|
+
* Create a spinner for long-running operations
|
|
39
|
+
*/
|
|
40
|
+
export declare function createSpinner(message: string, enabled: boolean): {
|
|
41
|
+
start: () => void;
|
|
42
|
+
stop: (finalMessage: string) => void;
|
|
43
|
+
fail: (finalMessage: string) => void;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Parse comma-separated list
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseList(value: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* Parse multiple IDs from various formats
|
|
51
|
+
* Supports:
|
|
52
|
+
* - "id1","id2","id3" (quoted CSV format)
|
|
53
|
+
* - id1,id2,id3 (simple comma-separated)
|
|
54
|
+
* - Single ID (backward compatible)
|
|
55
|
+
*
|
|
56
|
+
* Used with Commander.js collector pattern:
|
|
57
|
+
* .option('--ids <id>', 'IDs to process', parseMultipleIds, [])
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseMultipleIds(value: string, previous: string[]): string[];
|
|
60
|
+
/**
|
|
61
|
+
* Validate UUID format
|
|
62
|
+
*/
|
|
63
|
+
export declare function isValidUUID(id: string): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Format task ID for display
|
|
66
|
+
*/
|
|
67
|
+
export declare function formatTaskId(id: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Format status for display
|
|
70
|
+
*/
|
|
71
|
+
export declare function formatStatus(status: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Format priority for display
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatPriority(priority: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Truncate text to fit width
|
|
78
|
+
*/
|
|
79
|
+
export declare function truncate(text: string, maxWidth: number): string;
|
|
80
|
+
/**
|
|
81
|
+
* Format error for CLI output
|
|
82
|
+
* Provides consistent error formatting with code, message, and suggestion
|
|
83
|
+
*/
|
|
84
|
+
export declare function formatError(error: unknown, verbose?: boolean): string;
|
|
85
|
+
/**
|
|
86
|
+
* Get suggestion for an error code
|
|
87
|
+
* Returns a suggestion string for the given error code
|
|
88
|
+
*/
|
|
89
|
+
export declare function getErrorSuggestion(code: string): string | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Exit with error message
|
|
92
|
+
* Formats and displays error, then exits with code 1
|
|
93
|
+
*/
|
|
94
|
+
export declare function exitWithError(error: unknown, verbose?: boolean): never;
|
|
95
|
+
/**
|
|
96
|
+
* Retry options for recovery operations
|
|
97
|
+
*/
|
|
98
|
+
export interface RetryOptions {
|
|
99
|
+
/** Maximum number of retry attempts */
|
|
100
|
+
maxRetries: number;
|
|
101
|
+
/** Delay between retries in milliseconds */
|
|
102
|
+
delayMs: number;
|
|
103
|
+
/** Exponential backoff multiplier */
|
|
104
|
+
backoffMultiplier?: number;
|
|
105
|
+
/** Operation name for error messages */
|
|
106
|
+
operationName?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Retry a function with exponential backoff
|
|
110
|
+
* Useful for file operations that may fail due to concurrent access
|
|
111
|
+
*/
|
|
112
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
113
|
+
/**
|
|
114
|
+
* Prompt user for confirmation
|
|
115
|
+
* Returns true if user confirms (y/yes), false otherwise
|
|
116
|
+
*/
|
|
117
|
+
export declare function confirmPrompt(message: string): Promise<boolean>;
|
|
118
|
+
/**
|
|
119
|
+
* Attempt to recover from a corrupted project file
|
|
120
|
+
* Tries to restore from backup and provides actionable suggestions
|
|
121
|
+
*/
|
|
122
|
+
export declare function attemptRecovery(projectPath: string): Promise<{
|
|
123
|
+
success: boolean;
|
|
124
|
+
message: string;
|
|
125
|
+
}>;
|
|
126
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI utility functions
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { findProjectPath, TaskStorage } from '../../core/storage/file-store.js';
|
|
7
|
+
import { OctieError, ERROR_SUGGESTIONS } from '../../types/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get the project path from options or auto-detect
|
|
10
|
+
*/
|
|
11
|
+
export async function getProjectPath(projectOption) {
|
|
12
|
+
if (projectOption) {
|
|
13
|
+
return path.resolve(projectOption);
|
|
14
|
+
}
|
|
15
|
+
// Auto-detect project path
|
|
16
|
+
const detectedPath = await findProjectPath();
|
|
17
|
+
if (detectedPath) {
|
|
18
|
+
return detectedPath;
|
|
19
|
+
}
|
|
20
|
+
throw new Error('No Octie project found. Run `octie init` first or specify --project <path>');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Load the project graph
|
|
24
|
+
*/
|
|
25
|
+
export async function loadGraph(projectPath) {
|
|
26
|
+
const storage = new TaskStorage({ projectDir: projectPath });
|
|
27
|
+
if (!(await storage.exists())) {
|
|
28
|
+
throw new Error(`No Octie project found at ${projectPath}`);
|
|
29
|
+
}
|
|
30
|
+
return await storage.load();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Save the project graph
|
|
34
|
+
*/
|
|
35
|
+
export async function saveGraph(projectPath, graph) {
|
|
36
|
+
const storage = new TaskStorage({ projectDir: projectPath });
|
|
37
|
+
await storage.save(graph);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Format success message
|
|
41
|
+
*/
|
|
42
|
+
export function success(message) {
|
|
43
|
+
console.log(chalk.green('✓'), message);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format error message
|
|
47
|
+
*/
|
|
48
|
+
export function error(message) {
|
|
49
|
+
console.error(chalk.red('✗'), message);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Format warning message
|
|
53
|
+
*/
|
|
54
|
+
export function warning(message) {
|
|
55
|
+
console.warn(chalk.yellow('⚠'), message);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Format info message
|
|
59
|
+
*/
|
|
60
|
+
export function info(message) {
|
|
61
|
+
console.log(chalk.blue('ℹ'), message);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Format verbose message (only shown if --verbose flag is set)
|
|
65
|
+
*/
|
|
66
|
+
export function verbose(message, verbose) {
|
|
67
|
+
if (verbose) {
|
|
68
|
+
console.log(chalk.gray(message));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a spinner for long-running operations
|
|
73
|
+
*/
|
|
74
|
+
export function createSpinner(message, enabled) {
|
|
75
|
+
// Simple spinner implementation
|
|
76
|
+
let dots = 0;
|
|
77
|
+
let interval = null;
|
|
78
|
+
return {
|
|
79
|
+
start: () => {
|
|
80
|
+
if (!enabled)
|
|
81
|
+
return;
|
|
82
|
+
process.stdout.write(`\r${chalk.cyan('○')} ${message}`);
|
|
83
|
+
interval = setInterval(() => {
|
|
84
|
+
dots = (dots + 1) % 4;
|
|
85
|
+
const dotStr = '.'.repeat(dots);
|
|
86
|
+
process.stdout.write(`\r${chalk.cyan('○')} ${message}${dotStr}`);
|
|
87
|
+
}, 100);
|
|
88
|
+
},
|
|
89
|
+
stop: (finalMessage) => {
|
|
90
|
+
if (interval) {
|
|
91
|
+
clearInterval(interval);
|
|
92
|
+
interval = null;
|
|
93
|
+
}
|
|
94
|
+
if (enabled) {
|
|
95
|
+
process.stdout.write(`\r${chalk.green('✓')} ${finalMessage}\n`);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
fail: (finalMessage) => {
|
|
99
|
+
if (interval) {
|
|
100
|
+
clearInterval(interval);
|
|
101
|
+
interval = null;
|
|
102
|
+
}
|
|
103
|
+
if (enabled) {
|
|
104
|
+
process.stdout.write(`\r${chalk.red('✗')} ${finalMessage}\n`);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Parse comma-separated list
|
|
111
|
+
*/
|
|
112
|
+
export function parseList(value) {
|
|
113
|
+
if (!value)
|
|
114
|
+
return [];
|
|
115
|
+
return value.split(',').map(item => item.trim()).filter(Boolean);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parse multiple IDs from various formats
|
|
119
|
+
* Supports:
|
|
120
|
+
* - "id1","id2","id3" (quoted CSV format)
|
|
121
|
+
* - id1,id2,id3 (simple comma-separated)
|
|
122
|
+
* - Single ID (backward compatible)
|
|
123
|
+
*
|
|
124
|
+
* Used with Commander.js collector pattern:
|
|
125
|
+
* .option('--ids <id>', 'IDs to process', parseMultipleIds, [])
|
|
126
|
+
*/
|
|
127
|
+
export function parseMultipleIds(value, previous) {
|
|
128
|
+
if (!value)
|
|
129
|
+
return previous;
|
|
130
|
+
// Check for quoted CSV format: "id1","id2","id3"
|
|
131
|
+
// This happens when user wraps in quotes to prevent shell parsing
|
|
132
|
+
const quotedCsvMatch = value.match(/^"([^"]+)"(?:,"([^"]+)")*/);
|
|
133
|
+
if (quotedCsvMatch) {
|
|
134
|
+
// Extract all quoted values
|
|
135
|
+
const quotedValues = value.match(/"([^"]+)"/g);
|
|
136
|
+
if (quotedValues) {
|
|
137
|
+
const ids = quotedValues.map(v => v.replace(/"/g, '').trim()).filter(Boolean);
|
|
138
|
+
return previous.concat(ids);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Fall back to simple comma-separated: id1,id2,id3
|
|
142
|
+
if (value.includes(',')) {
|
|
143
|
+
const ids = value.split(',').map(item => item.trim()).filter(Boolean);
|
|
144
|
+
return previous.concat(ids);
|
|
145
|
+
}
|
|
146
|
+
// Single ID (backward compatible)
|
|
147
|
+
return previous.concat([value.trim()]);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Validate UUID format
|
|
151
|
+
*/
|
|
152
|
+
export function isValidUUID(id) {
|
|
153
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
154
|
+
return uuidRegex.test(id);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Format task ID for display
|
|
158
|
+
*/
|
|
159
|
+
export function formatTaskId(id) {
|
|
160
|
+
return chalk.cyan(id);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Format status for display
|
|
164
|
+
*/
|
|
165
|
+
export function formatStatus(status) {
|
|
166
|
+
const statusColors = {
|
|
167
|
+
ready: chalk.cyan,
|
|
168
|
+
in_progress: chalk.blue,
|
|
169
|
+
in_review: chalk.magenta,
|
|
170
|
+
completed: chalk.green,
|
|
171
|
+
blocked: chalk.red,
|
|
172
|
+
// Legacy status support (for backward compatibility with old data)
|
|
173
|
+
not_started: chalk.gray,
|
|
174
|
+
pending: chalk.yellow,
|
|
175
|
+
};
|
|
176
|
+
const colorFn = statusColors[status] || chalk.white;
|
|
177
|
+
return colorFn(status.replace('_', ' '));
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Format priority for display
|
|
181
|
+
*/
|
|
182
|
+
export function formatPriority(priority) {
|
|
183
|
+
const priorityColors = {
|
|
184
|
+
top: chalk.red,
|
|
185
|
+
second: chalk.yellow,
|
|
186
|
+
later: chalk.gray,
|
|
187
|
+
};
|
|
188
|
+
const colorFn = priorityColors[priority] || chalk.white;
|
|
189
|
+
return colorFn(priority);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Truncate text to fit width
|
|
193
|
+
*/
|
|
194
|
+
export function truncate(text, maxWidth) {
|
|
195
|
+
if (text.length <= maxWidth)
|
|
196
|
+
return text;
|
|
197
|
+
return text.substring(0, maxWidth - 3) + '...';
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Format error for CLI output
|
|
201
|
+
* Provides consistent error formatting with code, message, and suggestion
|
|
202
|
+
*/
|
|
203
|
+
export function formatError(error, verbose = false) {
|
|
204
|
+
// Handle OctieError with suggestion
|
|
205
|
+
if (error instanceof OctieError) {
|
|
206
|
+
const lines = [];
|
|
207
|
+
// Error header with code
|
|
208
|
+
lines.push(chalk.red.bold(`Error [${error.code}]:`) + ' ' + chalk.red(error.message));
|
|
209
|
+
// Add suggestion if available
|
|
210
|
+
if (error.suggestion) {
|
|
211
|
+
lines.push('');
|
|
212
|
+
lines.push(chalk.yellow('Suggestion:') + ' ' + error.suggestion);
|
|
213
|
+
}
|
|
214
|
+
// Add stack trace in verbose mode
|
|
215
|
+
if (verbose && error.stack) {
|
|
216
|
+
lines.push('');
|
|
217
|
+
lines.push(chalk.gray('Stack trace:'));
|
|
218
|
+
lines.push(chalk.gray(error.stack.split('\n').slice(1).join('\n')));
|
|
219
|
+
}
|
|
220
|
+
return lines.join('\n');
|
|
221
|
+
}
|
|
222
|
+
// Handle standard Error
|
|
223
|
+
if (error instanceof Error) {
|
|
224
|
+
const lines = [];
|
|
225
|
+
lines.push(chalk.red.bold('Error:') + ' ' + chalk.red(error.message));
|
|
226
|
+
if (verbose && error.stack) {
|
|
227
|
+
lines.push('');
|
|
228
|
+
lines.push(chalk.gray('Stack trace:'));
|
|
229
|
+
lines.push(chalk.gray(error.stack.split('\n').slice(1).join('\n')));
|
|
230
|
+
}
|
|
231
|
+
return lines.join('\n');
|
|
232
|
+
}
|
|
233
|
+
// Handle unknown error types
|
|
234
|
+
return chalk.red.bold('Error:') + ' ' + chalk.red(String(error));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get suggestion for an error code
|
|
238
|
+
* Returns a suggestion string for the given error code
|
|
239
|
+
*/
|
|
240
|
+
export function getErrorSuggestion(code) {
|
|
241
|
+
return ERROR_SUGGESTIONS[code];
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Exit with error message
|
|
245
|
+
* Formats and displays error, then exits with code 1
|
|
246
|
+
*/
|
|
247
|
+
export function exitWithError(error, verbose = false) {
|
|
248
|
+
console.error(formatError(error, verbose));
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Retry a function with exponential backoff
|
|
253
|
+
* Useful for file operations that may fail due to concurrent access
|
|
254
|
+
*/
|
|
255
|
+
export async function withRetry(fn, options) {
|
|
256
|
+
const { maxRetries, delayMs, backoffMultiplier = 2, operationName = 'operation' } = options;
|
|
257
|
+
let lastError;
|
|
258
|
+
let currentDelay = delayMs;
|
|
259
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
260
|
+
try {
|
|
261
|
+
return await fn();
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
265
|
+
if (attempt < maxRetries) {
|
|
266
|
+
if (process.env.VERBOSE === 'true') {
|
|
267
|
+
console.log(chalk.yellow(`Retry ${attempt}/${maxRetries} for ${operationName} after ${currentDelay}ms...`));
|
|
268
|
+
}
|
|
269
|
+
await new Promise(resolve => setTimeout(resolve, currentDelay));
|
|
270
|
+
currentDelay *= backoffMultiplier;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw new Error(`${operationName} failed after ${maxRetries} attempts. Last error: ${lastError?.message}`);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Prompt user for confirmation
|
|
278
|
+
* Returns true if user confirms (y/yes), false otherwise
|
|
279
|
+
*/
|
|
280
|
+
export async function confirmPrompt(message) {
|
|
281
|
+
const readline = await import('node:readline/promises');
|
|
282
|
+
const { stdin, stdout } = await import('node:process');
|
|
283
|
+
const rl = readline.createInterface({
|
|
284
|
+
input: stdin,
|
|
285
|
+
output: stdout,
|
|
286
|
+
});
|
|
287
|
+
try {
|
|
288
|
+
const answer = await rl.question(message + ' ');
|
|
289
|
+
const normalized = answer.trim().toLowerCase();
|
|
290
|
+
return normalized === 'y' || normalized === 'yes';
|
|
291
|
+
}
|
|
292
|
+
finally {
|
|
293
|
+
rl.close();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Attempt to recover from a corrupted project file
|
|
298
|
+
* Tries to restore from backup and provides actionable suggestions
|
|
299
|
+
*/
|
|
300
|
+
export async function attemptRecovery(projectPath) {
|
|
301
|
+
const storage = new TaskStorage({ projectDir: projectPath });
|
|
302
|
+
try {
|
|
303
|
+
// Check if backup exists
|
|
304
|
+
const backups = await storage.listBackups();
|
|
305
|
+
if (backups.length === 0) {
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
message: 'No backup files available for recovery. You may need to re-initialize the project.',
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
// Attempt to restore
|
|
312
|
+
await storage.restoreFromBackup();
|
|
313
|
+
return {
|
|
314
|
+
success: true,
|
|
315
|
+
message: `Successfully restored from backup: ${backups[0]}`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
return {
|
|
320
|
+
success: false,
|
|
321
|
+
message: `Recovery failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/cli/utils/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,aAAsB;IACzD,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,2BAA2B;IAC3B,MAAM,YAAY,GAAG,MAAM,eAAe,EAAE,CAAC;IAC7C,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,KAAK,CACb,4EAA4E,CAC7E,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,WAAmB;IACjD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAE7D,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,WAAmB,EAAE,KAAqB;IACxE,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,OAAgB;IACvD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,OAAgB;IAC7D,gCAAgC;IAChC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,QAAQ,GAA0B,IAAI,CAAC;IAE3C,OAAO;QACL,KAAK,EAAE,GAAG,EAAE;YACV,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC;YACxD,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAC1B,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBACtB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;YACnE,CAAC,EAAE,GAAG,CAAC,CAAC;QACV,CAAC;QACD,IAAI,EAAE,CAAC,YAAoB,EAAE,EAAE;YAC7B,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,YAAY,IAAI,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,YAAoB,EAAE,EAAE;YAC7B,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxB,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,YAAY,IAAI,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,QAAkB;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAE5B,iDAAiD;IACjD,kEAAkE;IAClE,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAChE,IAAI,cAAc,EAAE,CAAC;QACnB,4BAA4B;QAC5B,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9E,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,kCAAkC;IAClC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,MAAM,SAAS,GACb,iEAAiE,CAAC;IACpE,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,YAAY,GAA4C;QAC5D,KAAK,EAAE,KAAK,CAAC,IAAI;QACjB,WAAW,EAAE,KAAK,CAAC,IAAI;QACvB,SAAS,EAAE,KAAK,CAAC,OAAO;QACxB,SAAS,EAAE,KAAK,CAAC,KAAK;QACtB,OAAO,EAAE,KAAK,CAAC,GAAG;QAClB,mEAAmE;QACnE,WAAW,EAAE,KAAK,CAAC,IAAI;QACvB,OAAO,EAAE,KAAK,CAAC,MAAM;KACtB,CAAC;IAEF,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,cAAc,GAA4C;QAC9D,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,IAAI;KAClB,CAAC;IAEF,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC;IACxD,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB;IACrD,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,UAAmB,KAAK;IAClE,oCAAoC;IACpC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,yBAAyB;QACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtF,8BAA8B;QAC9B,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;QACnE,CAAC;QAED,kCAAkC;QAClC,IAAI,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,wBAAwB;IACxB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAEtE,IAAI,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,6BAA6B;IAC7B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,UAAmB,KAAK;IACpE,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAgBD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,EAAoB,EACpB,OAAqB;IAErB,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,GAAG,CAAC,EAAE,aAAa,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAC5F,IAAI,SAA4B,CAAC;IACjC,IAAI,YAAY,GAAG,OAAO,CAAC;IAE3B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBACzB,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;oBACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,OAAO,IAAI,UAAU,QAAQ,aAAa,UAAU,YAAY,OAAO,CAAC,CAAC,CAAC;gBAC9G,CAAC;gBACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;gBAChE,YAAY,IAAI,iBAAiB,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,GAAG,aAAa,iBAAiB,UAAU,0BAA0B,SAAS,EAAE,OAAO,EAAE,CAC1F,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe;IACjD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IACxD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAEvD,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,CAAC;IACpD,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,yBAAyB;QACzB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,oFAAoF;aAC9F,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAClC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,sCAAsC,OAAO,CAAC,CAAC,CAAC,EAAE;SAC5D,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,oBAAoB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACtF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph algorithms entry point
|
|
3
|
+
*
|
|
4
|
+
* Exports all graph algorithm functions for convenient importing.
|
|
5
|
+
*
|
|
6
|
+
* @module core/graph/algorithms
|
|
7
|
+
*/
|
|
8
|
+
export { topologicalSort, findCriticalPath, isValidDAG, getExecutionLevels, clearSortCache, } from './sort.js';
|
|
9
|
+
export { detectCycle, hasCycle, getCyclicNodes, findShortestCycle, findCyclesForTask, validateAcyclic, getCycleStatistics, wouldCreateCycle, } from './cycle.js';
|
|
10
|
+
export { bfsTraversal, dfsFindPath, findAllPaths, findShortestPath, areConnected, getDistance, getConnectedComponents, } from './traversal.js';
|
|
11
|
+
//# sourceMappingURL=algorithms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.d.ts","sourceRoot":"","sources":["../../../src/core/graph/algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,WAAW,EACX,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,sBAAsB,GACvB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph algorithms entry point
|
|
3
|
+
*
|
|
4
|
+
* Exports all graph algorithm functions for convenient importing.
|
|
5
|
+
*
|
|
6
|
+
* @module core/graph/algorithms
|
|
7
|
+
*/
|
|
8
|
+
// Topological sort
|
|
9
|
+
export { topologicalSort, findCriticalPath, isValidDAG, getExecutionLevels, clearSortCache, } from './sort.js';
|
|
10
|
+
// Cycle detection
|
|
11
|
+
export { detectCycle, hasCycle, getCyclicNodes, findShortestCycle, findCyclesForTask, validateAcyclic, getCycleStatistics, wouldCreateCycle, } from './cycle.js';
|
|
12
|
+
// Traversal
|
|
13
|
+
export { bfsTraversal, dfsFindPath, findAllPaths, findShortestPath, areConnected, getDistance, getConnectedComponents, } from './traversal.js';
|
|
14
|
+
//# sourceMappingURL=algorithms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.js","sourceRoot":"","sources":["../../../src/core/graph/algorithms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mBAAmB;AACnB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,cAAc,GACf,MAAM,WAAW,CAAC;AAEnB,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,YAAY;AACZ,OAAO,EACL,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,sBAAsB,GACvB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph cycle detection algorithms
|
|
3
|
+
*
|
|
4
|
+
* Implements DFS-based cycle detection with three-color marking.
|
|
5
|
+
* Detects all cycles and returns cycle paths for debugging.
|
|
6
|
+
* Time complexity: O(V + E) where V = vertices, E = edges
|
|
7
|
+
*
|
|
8
|
+
* @module core/graph/cycle
|
|
9
|
+
*/
|
|
10
|
+
import type { TaskGraphStore } from './index.js';
|
|
11
|
+
import type { CycleDetectionResult } from '../../types/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* Detect cycles using DFS with three-color marking
|
|
14
|
+
*
|
|
15
|
+
* Algorithm:
|
|
16
|
+
* 1. Mark all nodes as WHITE (unvisited)
|
|
17
|
+
* 2. For each WHITE node, start DFS traversal
|
|
18
|
+
* 3. Mark node as GRAY when entering, BLACK when exiting
|
|
19
|
+
* 4. If we encounter a GRAY node during traversal, we found a cycle
|
|
20
|
+
* 5. Check for self-loops (task blocking itself) before DFS
|
|
21
|
+
* 6. Reconstruct cycle path using parent pointers
|
|
22
|
+
*
|
|
23
|
+
* Time Complexity: O(V + E)
|
|
24
|
+
* Space Complexity: O(V) for recursion stack and state tracking
|
|
25
|
+
*
|
|
26
|
+
* @param graph - Task graph store
|
|
27
|
+
* @returns Cycle detection result with all detected cycles
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const result = detectCycle(graph);
|
|
32
|
+
* if (result.hasCycle) {
|
|
33
|
+
* console.error('Found cycles:', result.cycles);
|
|
34
|
+
* for (const cycle of result.cycles) {
|
|
35
|
+
* console.error('Cycle:', cycle.join(' -> '));
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectCycle(graph: TaskGraphStore): CycleDetectionResult;
|
|
41
|
+
/**
|
|
42
|
+
* Check if a graph contains any cycles
|
|
43
|
+
* Convenience function that returns a boolean
|
|
44
|
+
*
|
|
45
|
+
* @param graph - Task graph store
|
|
46
|
+
* @returns true if graph contains at least one cycle
|
|
47
|
+
*/
|
|
48
|
+
export declare function hasCycle(graph: TaskGraphStore): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Get all nodes involved in cycles
|
|
51
|
+
*
|
|
52
|
+
* @param graph - Task graph store
|
|
53
|
+
* @returns Set of task IDs that are part of at least one cycle
|
|
54
|
+
*/
|
|
55
|
+
export declare function getCyclicNodes(graph: TaskGraphStore): Set<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Find the shortest cycle in the graph
|
|
58
|
+
* Useful for identifying the most critical circular dependency
|
|
59
|
+
*
|
|
60
|
+
* @param graph - Task graph store
|
|
61
|
+
* @returns Shortest cycle array, or empty array if no cycles
|
|
62
|
+
*/
|
|
63
|
+
export declare function findShortestCycle(graph: TaskGraphStore): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Find all cycles involving a specific task
|
|
66
|
+
*
|
|
67
|
+
* @param graph - Task graph store
|
|
68
|
+
* @param taskId - Task ID to find cycles for
|
|
69
|
+
* @returns Array of cycles that include the specified task
|
|
70
|
+
*/
|
|
71
|
+
export declare function findCyclesForTask(graph: TaskGraphStore, taskId: string): string[][];
|
|
72
|
+
/**
|
|
73
|
+
* Validate that a graph is acyclic (DAG)
|
|
74
|
+
* Throws an error if cycles are detected
|
|
75
|
+
*
|
|
76
|
+
* @param graph - Task graph store
|
|
77
|
+
* @throws {CircularDependencyError} If graph contains cycles
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateAcyclic(graph: TaskGraphStore): void;
|
|
80
|
+
/**
|
|
81
|
+
* Get cycle statistics
|
|
82
|
+
*
|
|
83
|
+
* @param graph - Task graph store
|
|
84
|
+
* @returns Object with cycle count and nodes in cycles
|
|
85
|
+
*/
|
|
86
|
+
export declare function getCycleStatistics(graph: TaskGraphStore): {
|
|
87
|
+
cycleCount: number;
|
|
88
|
+
nodesInCycles: number;
|
|
89
|
+
totalNodes: number;
|
|
90
|
+
cyclesByLength: Record<number, number>;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Result of reference validation
|
|
94
|
+
*/
|
|
95
|
+
export interface ReferenceValidationResult {
|
|
96
|
+
/** True if any invalid references were found */
|
|
97
|
+
hasInvalidReferences: boolean;
|
|
98
|
+
/** List of invalid references found */
|
|
99
|
+
invalidReferences: Array<{
|
|
100
|
+
/** Task ID that has the invalid reference */
|
|
101
|
+
taskId: string;
|
|
102
|
+
/** Blocker ID that doesn't exist */
|
|
103
|
+
invalidBlockerId: string;
|
|
104
|
+
}>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Validate that all blocker references point to existing tasks
|
|
108
|
+
*
|
|
109
|
+
* Checks each task's blockers array to ensure all referenced tasks exist.
|
|
110
|
+
* This catches orphaned references that could occur from:
|
|
111
|
+
* - Manual JSON editing
|
|
112
|
+
* - Bugs in edge manipulation
|
|
113
|
+
* - Incomplete graph operations
|
|
114
|
+
*
|
|
115
|
+
* @param graph - Task graph store
|
|
116
|
+
* @returns Validation result with any invalid references found
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const result = validateReferences(graph);
|
|
121
|
+
* if (result.hasInvalidReferences) {
|
|
122
|
+
* for (const ref of result.invalidReferences) {
|
|
123
|
+
* console.error(`Task ${ref.taskId} has missing blocker: ${ref.invalidBlockerId}`);
|
|
124
|
+
* }
|
|
125
|
+
* }
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function validateReferences(graph: TaskGraphStore): ReferenceValidationResult;
|
|
129
|
+
/**
|
|
130
|
+
* Check if adding an edge would create a cycle
|
|
131
|
+
*
|
|
132
|
+
* When adding a blocker relationship (blockerId → taskId), this function
|
|
133
|
+
* checks if there's already a path from taskId to blockerId. If so,
|
|
134
|
+
* adding the edge would create a cycle.
|
|
135
|
+
*
|
|
136
|
+
* Also rejects self-blocking (taskId === blockerId).
|
|
137
|
+
*
|
|
138
|
+
* @param graph - Task graph store
|
|
139
|
+
* @param blockerId - The task that will block (source of edge)
|
|
140
|
+
* @param taskId - The task being blocked (target of edge)
|
|
141
|
+
* @returns true if adding this edge would create a cycle
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* // Before adding blocker, check for cycle
|
|
146
|
+
* if (wouldCreateCycle(graph, blockerId, taskId)) {
|
|
147
|
+
* console.error('Cannot add blocker: would create a cycle');
|
|
148
|
+
* } else {
|
|
149
|
+
* task.addBlocker(blockerId);
|
|
150
|
+
* graph.addEdge(blockerId, taskId);
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare function wouldCreateCycle(graph: TaskGraphStore, blockerId: string, taskId: string): boolean;
|
|
155
|
+
//# sourceMappingURL=cycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cycle.d.ts","sourceRoot":"","sources":["../../../src/core/graph/cycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAajE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,oBAAoB,CA4EvE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAGvD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAWjE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CAUjE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAInF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAU3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAgBA;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,gDAAgD;IAChD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uCAAuC;IACvC,iBAAiB,EAAE,KAAK,CAAC;QACvB,6CAA6C;QAC7C,MAAM,EAAE,MAAM,CAAC;QACf,oCAAoC;QACpC,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACJ;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,yBAAyB,CAkBnF;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAkCT"}
|