dyson-swarm 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/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +29 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +44 -0
- package/dist/paths.js.map +1 -0
- package/dist/tasks/file-utils.d.ts +50 -0
- package/dist/tasks/file-utils.d.ts.map +1 -0
- package/dist/tasks/file-utils.js +157 -0
- package/dist/tasks/file-utils.js.map +1 -0
- package/dist/tasks/index.d.ts +4 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +4 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/tasks/manager.d.ts +58 -0
- package/dist/tasks/manager.d.ts.map +1 -0
- package/dist/tasks/manager.js +330 -0
- package/dist/tasks/manager.js.map +1 -0
- package/dist/tasks/types.d.ts +35 -0
- package/dist/tasks/types.d.ts.map +1 -0
- package/dist/tasks/types.js +2 -0
- package/dist/tasks/types.js.map +1 -0
- package/package.json +44 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base directory for dyson configuration and state (per-directory)
|
|
3
|
+
*/
|
|
4
|
+
export declare function getDysonDir(cwdProvider?: () => string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Path to the tasks directory
|
|
7
|
+
*/
|
|
8
|
+
export declare function getTasksDir(cwdProvider?: () => string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Path to the task lockfile
|
|
11
|
+
*/
|
|
12
|
+
export declare function getTaskLockFile(cwdProvider?: () => string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Path to a task status directory
|
|
15
|
+
*/
|
|
16
|
+
export declare function getTaskStatusDir(status: 'open' | 'in-progress' | 'closed', cwdProvider?: () => string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Path to a specific task directory
|
|
19
|
+
*/
|
|
20
|
+
export declare function getTaskDir(taskId: string, status: 'open' | 'in-progress' | 'closed', cwdProvider?: () => string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Path to a specific task file
|
|
23
|
+
*/
|
|
24
|
+
export declare function getTaskFile(taskId: string, status: 'open' | 'in-progress' | 'closed', cwdProvider?: () => string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Path to sub-tasks directory within a task
|
|
27
|
+
*/
|
|
28
|
+
export declare function getSubtasksDir(taskId: string, status: 'open' | 'in-progress' | 'closed', cwdProvider?: () => string): string;
|
|
29
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,GAAE,MAAM,MAA4B,GAAG,MAAM,CAEnF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAElE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAE9G;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAExH;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAEzH;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAE5H"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Base directory for dyson configuration and state (per-directory)
|
|
4
|
+
*/
|
|
5
|
+
export function getDysonDir(cwdProvider = () => process.cwd()) {
|
|
6
|
+
return join(resolve(cwdProvider()), '.swarm');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Path to the tasks directory
|
|
10
|
+
*/
|
|
11
|
+
export function getTasksDir(cwdProvider) {
|
|
12
|
+
return join(getDysonDir(cwdProvider), 'tasks');
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Path to the task lockfile
|
|
16
|
+
*/
|
|
17
|
+
export function getTaskLockFile(cwdProvider) {
|
|
18
|
+
return join(getTasksDir(cwdProvider), 'lockfile');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Path to a task status directory
|
|
22
|
+
*/
|
|
23
|
+
export function getTaskStatusDir(status, cwdProvider) {
|
|
24
|
+
return join(getTasksDir(cwdProvider), status);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Path to a specific task directory
|
|
28
|
+
*/
|
|
29
|
+
export function getTaskDir(taskId, status, cwdProvider) {
|
|
30
|
+
return join(getTaskStatusDir(status, cwdProvider), taskId);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Path to a specific task file
|
|
34
|
+
*/
|
|
35
|
+
export function getTaskFile(taskId, status, cwdProvider) {
|
|
36
|
+
return join(getTaskDir(taskId, status, cwdProvider), `${taskId}.task`);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Path to sub-tasks directory within a task
|
|
40
|
+
*/
|
|
41
|
+
export function getSubtasksDir(taskId, status, cwdProvider) {
|
|
42
|
+
return join(getTaskDir(taskId, status, cwdProvider), 'sub-tasks');
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,cAA4B,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;IACzE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,WAA0B;IACpD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,WAA0B;IACxD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAyC,EAAE,WAA0B;IACpG,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,MAAyC,EAAE,WAA0B;IAC9G,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,MAAyC,EAAE,WAA0B;IAC/G,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,MAAyC,EAAE,WAA0B;IAClH,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Task, TaskFrontmatter } from './types.js';
|
|
2
|
+
export declare class TaskFileUtils {
|
|
3
|
+
/**
|
|
4
|
+
* Parse task file with frontmatter
|
|
5
|
+
*/
|
|
6
|
+
static parseTaskFile(filePath: string): Promise<{
|
|
7
|
+
frontmatter: TaskFrontmatter;
|
|
8
|
+
description: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Parse task content string with frontmatter
|
|
12
|
+
*/
|
|
13
|
+
static parseTaskContent(content: string): {
|
|
14
|
+
frontmatter: TaskFrontmatter;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Convert task to task file string with frontmatter
|
|
19
|
+
*/
|
|
20
|
+
static taskToFileString(task: Task): string;
|
|
21
|
+
/**
|
|
22
|
+
* Write task to task file
|
|
23
|
+
*/
|
|
24
|
+
static writeTaskFile(filePath: string, task: Task): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Generate task ID (UUID v4)
|
|
27
|
+
*/
|
|
28
|
+
static generateTaskId(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Ensure directory exists
|
|
31
|
+
*/
|
|
32
|
+
static ensureDir(dirPath: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if file exists
|
|
35
|
+
*/
|
|
36
|
+
static fileExists(filePath: string): Promise<boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if directory exists
|
|
39
|
+
*/
|
|
40
|
+
static dirExists(dirPath: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Get all task IDs from a status directory
|
|
43
|
+
*/
|
|
44
|
+
static getTaskIdsFromDir(statusDir: string): Promise<string[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Get all sub-task IDs from a task's sub-tasks directory
|
|
47
|
+
*/
|
|
48
|
+
static getSubtaskIdsFromDir(subtasksDir: string): Promise<string[]>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=file-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.d.ts","sourceRoot":"","sources":["../../src/tasks/file-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAExD,qBAAa,aAAa;IACxB;;OAEG;WACU,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,eAAe,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAK5G;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,eAAe,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE;IAgD/F;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAa3C;;OAEG;WACU,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM;IAQ/B;;OAEG;WACU,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD;;OAEG;WACU,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS3D;;OAEG;WACU,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASzD;;OAEG;WACU,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAsBpE;;OAEG;WACU,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAiB1E"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export class TaskFileUtils {
|
|
4
|
+
/**
|
|
5
|
+
* Parse task file with frontmatter
|
|
6
|
+
*/
|
|
7
|
+
static async parseTaskFile(filePath) {
|
|
8
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
9
|
+
return this.parseTaskContent(content);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse task content string with frontmatter
|
|
13
|
+
*/
|
|
14
|
+
static parseTaskContent(content) {
|
|
15
|
+
const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
16
|
+
const match = content.match(frontmatterRegex);
|
|
17
|
+
if (!match) {
|
|
18
|
+
throw new Error('Invalid task file format: missing frontmatter');
|
|
19
|
+
}
|
|
20
|
+
const frontmatterStr = match[1];
|
|
21
|
+
const description = match[2].trim();
|
|
22
|
+
// Parse YAML-like frontmatter
|
|
23
|
+
const frontmatter = {
|
|
24
|
+
title: '',
|
|
25
|
+
};
|
|
26
|
+
const lines = frontmatterStr.split('\n');
|
|
27
|
+
for (const line of lines) {
|
|
28
|
+
const trimmedLine = line.trim();
|
|
29
|
+
if (!trimmedLine || trimmedLine.startsWith('#'))
|
|
30
|
+
continue;
|
|
31
|
+
const colonIndex = trimmedLine.indexOf(':');
|
|
32
|
+
if (colonIndex === -1)
|
|
33
|
+
continue;
|
|
34
|
+
const key = trimmedLine.substring(0, colonIndex).trim();
|
|
35
|
+
let value = trimmedLine.substring(colonIndex + 1).trim();
|
|
36
|
+
// Remove quotes if present
|
|
37
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
38
|
+
value = value.slice(1, -1);
|
|
39
|
+
}
|
|
40
|
+
else if (value.startsWith("'") && value.endsWith("'")) {
|
|
41
|
+
value = value.slice(1, -1);
|
|
42
|
+
}
|
|
43
|
+
if (key === 'title') {
|
|
44
|
+
frontmatter.title = value;
|
|
45
|
+
}
|
|
46
|
+
else if (key === 'assignee') {
|
|
47
|
+
frontmatter.assignee = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!frontmatter.title) {
|
|
51
|
+
throw new Error('Invalid task file format: missing title in frontmatter');
|
|
52
|
+
}
|
|
53
|
+
return { frontmatter, description };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Convert task to task file string with frontmatter
|
|
57
|
+
*/
|
|
58
|
+
static taskToFileString(task) {
|
|
59
|
+
const frontmatter = [`title: "${task.frontmatter.title}"`];
|
|
60
|
+
if (task.frontmatter.assignee) {
|
|
61
|
+
frontmatter.push(`assignee: "${task.frontmatter.assignee}"`);
|
|
62
|
+
}
|
|
63
|
+
const frontmatterStr = frontmatter.join('\n');
|
|
64
|
+
const description = task.description || '';
|
|
65
|
+
return `---\n${frontmatterStr}\n---\n${description}`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Write task to task file
|
|
69
|
+
*/
|
|
70
|
+
static async writeTaskFile(filePath, task) {
|
|
71
|
+
const taskString = this.taskToFileString(task);
|
|
72
|
+
await fs.writeFile(filePath, taskString, 'utf-8');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Generate task ID (UUID v4)
|
|
76
|
+
*/
|
|
77
|
+
static generateTaskId() {
|
|
78
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
79
|
+
const r = Math.random() * 16 | 0;
|
|
80
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
81
|
+
return v.toString(16);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Ensure directory exists
|
|
86
|
+
*/
|
|
87
|
+
static async ensureDir(dirPath) {
|
|
88
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if file exists
|
|
92
|
+
*/
|
|
93
|
+
static async fileExists(filePath) {
|
|
94
|
+
try {
|
|
95
|
+
await fs.access(filePath);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if directory exists
|
|
104
|
+
*/
|
|
105
|
+
static async dirExists(dirPath) {
|
|
106
|
+
try {
|
|
107
|
+
const stats = await fs.stat(dirPath);
|
|
108
|
+
return stats.isDirectory();
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get all task IDs from a status directory
|
|
116
|
+
*/
|
|
117
|
+
static async getTaskIdsFromDir(statusDir) {
|
|
118
|
+
if (!(await this.dirExists(statusDir))) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
const entries = await fs.readdir(statusDir, { withFileTypes: true });
|
|
122
|
+
return entries
|
|
123
|
+
.filter(entry => {
|
|
124
|
+
// For main tasks, we look for directories
|
|
125
|
+
if (entry.isDirectory())
|
|
126
|
+
return true;
|
|
127
|
+
// For subtasks, we look for .task files
|
|
128
|
+
if (entry.isFile() && entry.name.endsWith('.task'))
|
|
129
|
+
return true;
|
|
130
|
+
return false;
|
|
131
|
+
})
|
|
132
|
+
.map(entry => {
|
|
133
|
+
// For directories, return the directory name
|
|
134
|
+
if (entry.isDirectory())
|
|
135
|
+
return entry.name;
|
|
136
|
+
// For files, remove the .task extension
|
|
137
|
+
return entry.name.replace('.task', '');
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get all sub-task IDs from a task's sub-tasks directory
|
|
142
|
+
*/
|
|
143
|
+
static async getSubtaskIdsFromDir(subtasksDir) {
|
|
144
|
+
const subtaskIds = [];
|
|
145
|
+
if (!(await this.dirExists(subtasksDir))) {
|
|
146
|
+
return subtaskIds;
|
|
147
|
+
}
|
|
148
|
+
const statuses = ['open', 'in-progress', 'closed'];
|
|
149
|
+
for (const status of statuses) {
|
|
150
|
+
const statusDir = join(subtasksDir, status);
|
|
151
|
+
const taskIds = await this.getTaskIdsFromDir(statusDir);
|
|
152
|
+
subtaskIds.push(...taskIds);
|
|
153
|
+
}
|
|
154
|
+
return subtaskIds;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=file-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../src/tasks/file-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Task, TaskStatus, CreateTaskOptions, UpdateTaskOptions, TaskFilter, TaskManagerOptions } from './types.js';
|
|
2
|
+
export declare class TaskManager {
|
|
3
|
+
private cwdProvider;
|
|
4
|
+
constructor(options?: TaskManagerOptions);
|
|
5
|
+
/**
|
|
6
|
+
* Execute an operation with the task lock held
|
|
7
|
+
*/
|
|
8
|
+
private withLock;
|
|
9
|
+
/**
|
|
10
|
+
* Get task status from file path
|
|
11
|
+
*/
|
|
12
|
+
private getTaskStatusFromPath;
|
|
13
|
+
/**
|
|
14
|
+
* Load a task from its file
|
|
15
|
+
*/
|
|
16
|
+
private loadTaskFromFile;
|
|
17
|
+
/**
|
|
18
|
+
* Load subtasks for a given task
|
|
19
|
+
*/
|
|
20
|
+
private loadSubtasks;
|
|
21
|
+
/**
|
|
22
|
+
* Load a specific subtask
|
|
23
|
+
*/
|
|
24
|
+
private loadSubtask;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new task
|
|
27
|
+
*/
|
|
28
|
+
createTask(options: CreateTaskOptions): Promise<Task>;
|
|
29
|
+
/**
|
|
30
|
+
* Get a task by ID
|
|
31
|
+
*/
|
|
32
|
+
getTask(taskId: string): Promise<Task | null>;
|
|
33
|
+
/**
|
|
34
|
+
* List tasks with optional filtering
|
|
35
|
+
*/
|
|
36
|
+
listTasks(filter?: TaskFilter): Promise<Task[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Update a task
|
|
39
|
+
*/
|
|
40
|
+
updateTask(taskId: string, options: UpdateTaskOptions): Promise<Task | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Change task status
|
|
43
|
+
*/
|
|
44
|
+
changeTaskStatus(taskId: string, newStatus: TaskStatus): Promise<Task | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Delete a task
|
|
47
|
+
*/
|
|
48
|
+
deleteTask(taskId: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Assign a task to someone
|
|
51
|
+
*/
|
|
52
|
+
assignTask(taskId: string, assignee: string): Promise<Task | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Unassign a task
|
|
55
|
+
*/
|
|
56
|
+
unassignTask(taskId: string): Promise<Task | null>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAWzH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAe;gBAEtB,OAAO,GAAE,kBAAuB;IAI5C;;OAEG;YACW,QAAQ;IA0BtB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;OAEG;YACW,gBAAgB;IAuB9B;;OAEG;YACW,YAAY;IAoB1B;;OAEG;YACW,WAAW;IAqBzB;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoD3D;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAWnD;;OAEG;IACG,SAAS,CAAC,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAgCzD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAyElF;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IA0CnF;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAclD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIxE;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;CAGzD"}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import lock from 'proper-lockfile';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
+
import { TaskFileUtils } from './file-utils.js';
|
|
6
|
+
import { getTasksDir, getTaskLockFile, getTaskStatusDir, getTaskDir, getTaskFile, getSubtasksDir, } from '../paths.js';
|
|
7
|
+
export class TaskManager {
|
|
8
|
+
cwdProvider;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.cwdProvider = options.cwdProvider || (() => process.cwd());
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Execute an operation with the task lock held
|
|
14
|
+
*/
|
|
15
|
+
async withLock(operation) {
|
|
16
|
+
const lockfilePath = getTaskLockFile(this.cwdProvider);
|
|
17
|
+
// Ensure tasks directory exists
|
|
18
|
+
await TaskFileUtils.ensureDir(getTasksDir(this.cwdProvider));
|
|
19
|
+
// Create the lockfile if it doesn't exist
|
|
20
|
+
if (!(await TaskFileUtils.fileExists(lockfilePath))) {
|
|
21
|
+
await fs.writeFile(lockfilePath, '', 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
const release = await lock.lock(lockfilePath, {
|
|
24
|
+
retries: {
|
|
25
|
+
retries: 10,
|
|
26
|
+
minTimeout: 100,
|
|
27
|
+
maxTimeout: 1000,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
return await operation();
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
await release();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get task status from file path
|
|
39
|
+
*/
|
|
40
|
+
getTaskStatusFromPath(taskPath) {
|
|
41
|
+
if (taskPath.includes('/in-progress/'))
|
|
42
|
+
return 'in-progress';
|
|
43
|
+
if (taskPath.includes('/closed/'))
|
|
44
|
+
return 'closed';
|
|
45
|
+
return 'open';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Load a task from its file
|
|
49
|
+
*/
|
|
50
|
+
async loadTaskFromFile(taskId, status) {
|
|
51
|
+
const taskFile = getTaskFile(taskId, status, this.cwdProvider);
|
|
52
|
+
if (!(await TaskFileUtils.fileExists(taskFile))) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const { frontmatter, description } = await TaskFileUtils.parseTaskFile(taskFile);
|
|
57
|
+
const subtasks = await this.loadSubtasks(taskId, status);
|
|
58
|
+
return {
|
|
59
|
+
id: taskId,
|
|
60
|
+
frontmatter,
|
|
61
|
+
description,
|
|
62
|
+
status,
|
|
63
|
+
subtasks,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new Error(`Failed to load task ${taskId}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Load subtasks for a given task
|
|
72
|
+
*/
|
|
73
|
+
async loadSubtasks(parentId, parentStatus) {
|
|
74
|
+
const subtasksDir = getSubtasksDir(parentId, parentStatus, this.cwdProvider);
|
|
75
|
+
const subtasks = [];
|
|
76
|
+
// Check each status directory for subtasks
|
|
77
|
+
for (const status of ['open', 'in-progress', 'closed']) {
|
|
78
|
+
const statusDir = join(subtasksDir, status);
|
|
79
|
+
const taskIds = await TaskFileUtils.getTaskIdsFromDir(statusDir);
|
|
80
|
+
for (const subtaskId of taskIds) {
|
|
81
|
+
const subtask = await this.loadSubtask(subtaskId, parentId, status);
|
|
82
|
+
if (subtask) {
|
|
83
|
+
subtasks.push(subtask);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return subtasks;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Load a specific subtask
|
|
91
|
+
*/
|
|
92
|
+
async loadSubtask(taskId, parentId, status) {
|
|
93
|
+
const subtaskFile = join(getSubtasksDir(parentId, 'open', this.cwdProvider), status, `${taskId}.task`);
|
|
94
|
+
if (!(await TaskFileUtils.fileExists(subtaskFile))) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const { frontmatter, description } = await TaskFileUtils.parseTaskFile(subtaskFile);
|
|
99
|
+
return {
|
|
100
|
+
id: taskId,
|
|
101
|
+
frontmatter,
|
|
102
|
+
description,
|
|
103
|
+
status,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Failed to load subtask ${taskId}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create a new task
|
|
112
|
+
*/
|
|
113
|
+
async createTask(options) {
|
|
114
|
+
return this.withLock(async () => {
|
|
115
|
+
const taskId = uuidv4();
|
|
116
|
+
const task = {
|
|
117
|
+
id: taskId,
|
|
118
|
+
frontmatter: {
|
|
119
|
+
title: options.title,
|
|
120
|
+
assignee: options.assignee,
|
|
121
|
+
},
|
|
122
|
+
description: options.description,
|
|
123
|
+
status: options.assignee ? 'in-progress' : 'open',
|
|
124
|
+
subtasks: [],
|
|
125
|
+
};
|
|
126
|
+
// Create task directory and file
|
|
127
|
+
const taskDir = getTaskDir(taskId, task.status, this.cwdProvider);
|
|
128
|
+
const taskFile = getTaskFile(taskId, task.status, this.cwdProvider);
|
|
129
|
+
await TaskFileUtils.ensureDir(taskDir);
|
|
130
|
+
await TaskFileUtils.writeTaskFile(taskFile, task);
|
|
131
|
+
// Create subtasks if provided
|
|
132
|
+
if (options.subtasks && options.subtasks.length > 0) {
|
|
133
|
+
const subtasks = [];
|
|
134
|
+
for (const subtaskOptions of options.subtasks) {
|
|
135
|
+
const subtaskId = uuidv4();
|
|
136
|
+
const subtask = {
|
|
137
|
+
id: subtaskId,
|
|
138
|
+
frontmatter: {
|
|
139
|
+
title: subtaskOptions.title,
|
|
140
|
+
},
|
|
141
|
+
description: subtaskOptions.description,
|
|
142
|
+
status: 'open',
|
|
143
|
+
};
|
|
144
|
+
const subtaskDir = join(getSubtasksDir(taskId, task.status, this.cwdProvider), 'open');
|
|
145
|
+
const subtaskFile = join(subtaskDir, `${subtaskId}.task`);
|
|
146
|
+
await TaskFileUtils.ensureDir(subtaskDir);
|
|
147
|
+
await TaskFileUtils.writeTaskFile(subtaskFile, subtask);
|
|
148
|
+
subtasks.push(subtask);
|
|
149
|
+
}
|
|
150
|
+
task.subtasks = subtasks;
|
|
151
|
+
}
|
|
152
|
+
return task;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get a task by ID
|
|
157
|
+
*/
|
|
158
|
+
async getTask(taskId) {
|
|
159
|
+
return this.withLock(async () => {
|
|
160
|
+
// Try each status
|
|
161
|
+
for (const status of ['open', 'in-progress', 'closed']) {
|
|
162
|
+
const task = await this.loadTaskFromFile(taskId, status);
|
|
163
|
+
if (task)
|
|
164
|
+
return task;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* List tasks with optional filtering
|
|
171
|
+
*/
|
|
172
|
+
async listTasks(filter = {}) {
|
|
173
|
+
return this.withLock(async () => {
|
|
174
|
+
const tasks = [];
|
|
175
|
+
const statuses = filter.status ? [filter.status] : ['open', 'in-progress', 'closed'];
|
|
176
|
+
for (const status of statuses) {
|
|
177
|
+
const statusDir = getTaskStatusDir(status, this.cwdProvider);
|
|
178
|
+
const taskIds = await TaskFileUtils.getTaskIdsFromDir(statusDir);
|
|
179
|
+
for (const taskId of taskIds) {
|
|
180
|
+
const task = await this.loadTaskFromFile(taskId, status);
|
|
181
|
+
if (task) {
|
|
182
|
+
// Apply filters
|
|
183
|
+
if (filter.assignee && task.frontmatter.assignee !== filter.assignee) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (filter.hasSubtasks !== undefined) {
|
|
187
|
+
const hasSubtasks = task.subtasks && task.subtasks.length > 0;
|
|
188
|
+
if (filter.hasSubtasks !== hasSubtasks) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
tasks.push(task);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return tasks;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Update a task
|
|
201
|
+
*/
|
|
202
|
+
async updateTask(taskId, options) {
|
|
203
|
+
return this.withLock(async () => {
|
|
204
|
+
// Find the task
|
|
205
|
+
let task = null;
|
|
206
|
+
let currentStatus = null;
|
|
207
|
+
for (const status of ['open', 'in-progress', 'closed']) {
|
|
208
|
+
task = await this.loadTaskFromFile(taskId, status);
|
|
209
|
+
if (task) {
|
|
210
|
+
currentStatus = status;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (!task || !currentStatus) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
// Update fields
|
|
218
|
+
if (options.title !== undefined) {
|
|
219
|
+
task.frontmatter.title = options.title;
|
|
220
|
+
}
|
|
221
|
+
if (options.description !== undefined) {
|
|
222
|
+
task.description = options.description;
|
|
223
|
+
}
|
|
224
|
+
if (options.assignee !== undefined) {
|
|
225
|
+
task.frontmatter.assignee = options.assignee;
|
|
226
|
+
}
|
|
227
|
+
// Update status based on assignee
|
|
228
|
+
let newStatus = currentStatus;
|
|
229
|
+
if (options.assignee && currentStatus === 'open') {
|
|
230
|
+
newStatus = 'in-progress';
|
|
231
|
+
}
|
|
232
|
+
else if (options.assignee === undefined && (currentStatus === 'in-progress' || currentStatus === 'closed')) {
|
|
233
|
+
newStatus = 'open';
|
|
234
|
+
// Remove assignee when going back to open
|
|
235
|
+
task.frontmatter.assignee = undefined;
|
|
236
|
+
}
|
|
237
|
+
// If status changed, move the task
|
|
238
|
+
if (newStatus !== currentStatus) {
|
|
239
|
+
// Remove old task directory
|
|
240
|
+
const oldTaskDir = getTaskDir(taskId, currentStatus, this.cwdProvider);
|
|
241
|
+
const newTaskDir = getTaskDir(taskId, newStatus, this.cwdProvider);
|
|
242
|
+
await TaskFileUtils.ensureDir(newTaskDir);
|
|
243
|
+
// Move subtasks directory if it exists
|
|
244
|
+
const oldSubtasksDir = getSubtasksDir(taskId, currentStatus, this.cwdProvider);
|
|
245
|
+
const newSubtasksDir = getSubtasksDir(taskId, newStatus, this.cwdProvider);
|
|
246
|
+
if (await TaskFileUtils.dirExists(oldSubtasksDir)) {
|
|
247
|
+
await fs.rename(oldSubtasksDir, newSubtasksDir);
|
|
248
|
+
}
|
|
249
|
+
// Write new task file
|
|
250
|
+
task.status = newStatus;
|
|
251
|
+
const newTaskFile = getTaskFile(taskId, newStatus, this.cwdProvider);
|
|
252
|
+
await TaskFileUtils.writeTaskFile(newTaskFile, task);
|
|
253
|
+
// Remove old directory
|
|
254
|
+
await fs.rm(oldTaskDir, { recursive: true, force: true });
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// Just update the file
|
|
258
|
+
task.status = newStatus;
|
|
259
|
+
const taskFile = getTaskFile(taskId, currentStatus, this.cwdProvider);
|
|
260
|
+
await TaskFileUtils.writeTaskFile(taskFile, task);
|
|
261
|
+
}
|
|
262
|
+
return task;
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Change task status
|
|
267
|
+
*/
|
|
268
|
+
async changeTaskStatus(taskId, newStatus) {
|
|
269
|
+
return this.withLock(async () => {
|
|
270
|
+
// Find the task without calling getTask (which would cause deadlock)
|
|
271
|
+
let task = null;
|
|
272
|
+
let currentStatus = null;
|
|
273
|
+
for (const status of ['open', 'in-progress', 'closed']) {
|
|
274
|
+
task = await this.loadTaskFromFile(taskId, status);
|
|
275
|
+
if (task) {
|
|
276
|
+
currentStatus = status;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (!task || !currentStatus)
|
|
281
|
+
return null;
|
|
282
|
+
if (currentStatus === newStatus)
|
|
283
|
+
return task;
|
|
284
|
+
const oldTaskDir = getTaskDir(taskId, currentStatus, this.cwdProvider);
|
|
285
|
+
const newTaskDir = getTaskDir(taskId, newStatus, this.cwdProvider);
|
|
286
|
+
await TaskFileUtils.ensureDir(newTaskDir);
|
|
287
|
+
// Move subtasks directory if it exists
|
|
288
|
+
const oldSubtasksDir = getSubtasksDir(taskId, currentStatus, this.cwdProvider);
|
|
289
|
+
const newSubtasksDir = getSubtasksDir(taskId, newStatus, this.cwdProvider);
|
|
290
|
+
if (await TaskFileUtils.dirExists(oldSubtasksDir)) {
|
|
291
|
+
await fs.rename(oldSubtasksDir, newSubtasksDir);
|
|
292
|
+
}
|
|
293
|
+
// Update status and write new task file
|
|
294
|
+
task.status = newStatus;
|
|
295
|
+
const newTaskFile = getTaskFile(taskId, newStatus, this.cwdProvider);
|
|
296
|
+
await TaskFileUtils.writeTaskFile(newTaskFile, task);
|
|
297
|
+
// Remove old directory
|
|
298
|
+
await fs.rm(oldTaskDir, { recursive: true, force: true });
|
|
299
|
+
return task;
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Delete a task
|
|
304
|
+
*/
|
|
305
|
+
async deleteTask(taskId) {
|
|
306
|
+
return this.withLock(async () => {
|
|
307
|
+
for (const status of ['open', 'in-progress', 'closed']) {
|
|
308
|
+
const taskDir = getTaskDir(taskId, status, this.cwdProvider);
|
|
309
|
+
if (await TaskFileUtils.dirExists(taskDir)) {
|
|
310
|
+
await fs.rm(taskDir, { recursive: true, force: true });
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return false;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Assign a task to someone
|
|
319
|
+
*/
|
|
320
|
+
async assignTask(taskId, assignee) {
|
|
321
|
+
return this.updateTask(taskId, { assignee });
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Unassign a task
|
|
325
|
+
*/
|
|
326
|
+
async unassignTask(taskId) {
|
|
327
|
+
return this.updateTask(taskId, { assignee: undefined });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/tasks/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type TaskStatus = 'open' | 'in-progress' | 'closed';
|
|
2
|
+
export interface TaskFrontmatter {
|
|
3
|
+
title: string;
|
|
4
|
+
assignee?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface Task {
|
|
7
|
+
id: string;
|
|
8
|
+
frontmatter: TaskFrontmatter;
|
|
9
|
+
description: string;
|
|
10
|
+
status: TaskStatus;
|
|
11
|
+
subtasks?: Task[];
|
|
12
|
+
}
|
|
13
|
+
export interface CreateTaskOptions {
|
|
14
|
+
title: string;
|
|
15
|
+
description: string;
|
|
16
|
+
assignee?: string;
|
|
17
|
+
subtasks?: Array<{
|
|
18
|
+
title: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
export interface UpdateTaskOptions {
|
|
23
|
+
title?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
assignee?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface TaskFilter {
|
|
28
|
+
status?: TaskStatus;
|
|
29
|
+
assignee?: string;
|
|
30
|
+
hasSubtasks?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface TaskManagerOptions {
|
|
33
|
+
cwdProvider?: () => string;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tasks/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dyson-swarm",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A markdown-based issue tracking system library",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsx src/index.ts",
|
|
20
|
+
"test": "vitest --run",
|
|
21
|
+
"test:watch": "vitest --watch",
|
|
22
|
+
"test:coverage": "vitest --coverage"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"issue-tracker",
|
|
26
|
+
"markdown",
|
|
27
|
+
"tasks",
|
|
28
|
+
"git"
|
|
29
|
+
],
|
|
30
|
+
"author": "",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"proper-lockfile": "^4.1.2",
|
|
34
|
+
"uuid": "^13.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
39
|
+
"@types/uuid": "^10.0.0",
|
|
40
|
+
"tsx": "^4.0.0",
|
|
41
|
+
"typescript": "^5.0.0",
|
|
42
|
+
"vitest": "^1.6.1"
|
|
43
|
+
}
|
|
44
|
+
}
|