@smekai/taskplanner 2.1.14
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/LICENSE +21 -0
- package/README.md +156 -0
- package/bin/taskplanner-mcp.js +4 -0
- package/dist/ai/aiInstructions.d.ts +24 -0
- package/dist/ai/codexDeepLink.d.ts +4 -0
- package/dist/ai/planMode.d.ts +1 -0
- package/dist/ai/promptComposer.d.ts +3 -0
- package/dist/config/configManager.d.ts +18 -0
- package/dist/filter/taskFilter.d.ts +7 -0
- package/dist/id/idGenerator.d.ts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +25 -0
- package/dist/mcp-server.js +90 -0
- package/dist/model/config.d.ts +15 -0
- package/dist/model/messages.d.ts +65 -0
- package/dist/model/parseResult.d.ts +9 -0
- package/dist/model/state.d.ts +6 -0
- package/dist/model/task.d.ts +19 -0
- package/dist/parser/taskParser.d.ts +7 -0
- package/dist/parser/taskSerializer.d.ts +3 -0
- package/dist/project/projectSync.d.ts +26 -0
- package/dist/store/fileStore.d.ts +18 -0
- package/dist/store/taskStore.d.ts +70 -0
- package/dist/util/time.d.ts +2 -0
- package/dist/validation/duplicateDetector.d.ts +18 -0
- package/dist/view/boardViewModel.d.ts +13 -0
- package/package.json +51 -0
- package/ui/board/index.html +493 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TaskState } from './state.js';
|
|
2
|
+
export interface TaskPlannerConfig {
|
|
3
|
+
version: number;
|
|
4
|
+
taskplannerVersion: string;
|
|
5
|
+
idPrefix: string;
|
|
6
|
+
nextId: number;
|
|
7
|
+
states: TaskState[];
|
|
8
|
+
priorities: string[];
|
|
9
|
+
tags: string[];
|
|
10
|
+
insertPosition: 'top' | 'bottom';
|
|
11
|
+
aiPlanRequired: boolean;
|
|
12
|
+
readmeAttribution: boolean;
|
|
13
|
+
sortBy: 'priority' | 'name' | 'id' | 'file';
|
|
14
|
+
}
|
|
15
|
+
export declare function createDefaultConfig(): TaskPlannerConfig;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Priority } from './task.js';
|
|
2
|
+
/** Task data sent from extension host to webview */
|
|
3
|
+
export interface TaskViewItem {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
priority: Priority;
|
|
7
|
+
tags: string[];
|
|
8
|
+
epic?: string;
|
|
9
|
+
assignee?: string;
|
|
10
|
+
updatedAt?: string;
|
|
11
|
+
description: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StateViewData {
|
|
14
|
+
name: string;
|
|
15
|
+
tasks: TaskViewItem[];
|
|
16
|
+
totalCount: number;
|
|
17
|
+
hasMore: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface TaskViewData {
|
|
20
|
+
states: StateViewData[];
|
|
21
|
+
filter?: TaskFilter;
|
|
22
|
+
}
|
|
23
|
+
/** Filter criteria for the task list */
|
|
24
|
+
export interface TaskFilter {
|
|
25
|
+
status?: string;
|
|
26
|
+
query?: string;
|
|
27
|
+
tag?: string;
|
|
28
|
+
groupBy?: 'status' | 'assignee' | 'date' | 'none';
|
|
29
|
+
}
|
|
30
|
+
/** Grouped task view for the task list panel */
|
|
31
|
+
export interface GroupViewData {
|
|
32
|
+
label: string;
|
|
33
|
+
tasks: TaskViewItem[];
|
|
34
|
+
totalCount: number;
|
|
35
|
+
hasMore: boolean;
|
|
36
|
+
collapsed?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Messages from webview to extension host */
|
|
39
|
+
export type WebviewMessage = {
|
|
40
|
+
type: 'ready';
|
|
41
|
+
} | {
|
|
42
|
+
type: 'moveTask';
|
|
43
|
+
taskId: string;
|
|
44
|
+
targetState: string;
|
|
45
|
+
targetIndex?: number;
|
|
46
|
+
} | {
|
|
47
|
+
type: 'reorderTask';
|
|
48
|
+
taskId: string;
|
|
49
|
+
newIndex: number;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'deleteTask';
|
|
52
|
+
taskId: string;
|
|
53
|
+
} | {
|
|
54
|
+
type: 'openTask';
|
|
55
|
+
taskId: string;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'applyFilter';
|
|
58
|
+
filter: TaskFilter;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'showAll';
|
|
61
|
+
stateName?: string;
|
|
62
|
+
} | {
|
|
63
|
+
type: 'expandGroup';
|
|
64
|
+
groupLabel: string;
|
|
65
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare enum Priority {
|
|
2
|
+
P0 = "P0",
|
|
3
|
+
P1 = "P1",
|
|
4
|
+
P2 = "P2",
|
|
5
|
+
P3 = "P3",
|
|
6
|
+
P4 = "P4"
|
|
7
|
+
}
|
|
8
|
+
export interface Task {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
priority: Priority;
|
|
13
|
+
tags: string[];
|
|
14
|
+
epic?: string;
|
|
15
|
+
assignee?: string;
|
|
16
|
+
updatedAt?: string;
|
|
17
|
+
plan?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function isPriority(value: string): value is Priority;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ParseResult } from '../model/parseResult.js';
|
|
2
|
+
export declare function parseTasks(rawContent: string): ParseResult;
|
|
3
|
+
export declare function findTaskLineNumber(content: string, taskId: string): number;
|
|
4
|
+
/** Count `## PREFIX-###:` task headings without full parsing (for deferred state loads). */
|
|
5
|
+
export declare function countTaskHeadings(rawContent: string): number;
|
|
6
|
+
/** Highest numeric suffix among `## PREFIX-NNN:` headings in raw markdown, or 0 if none. */
|
|
7
|
+
export declare function maxTaskIdNumber(rawContent: string, prefix: string): number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ConfigManager } from '../config/configManager.js';
|
|
2
|
+
export type VersionSyncStatus = 'installed-newer' | 'equal' | 'installed-older' | 'legacy' | 'invalid-installed';
|
|
3
|
+
export interface VersionSyncComparison {
|
|
4
|
+
status: VersionSyncStatus;
|
|
5
|
+
installedVersion?: string;
|
|
6
|
+
storedVersion?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ProjectSyncOptions {
|
|
9
|
+
force?: boolean;
|
|
10
|
+
syncInstructions?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface ProjectSyncResult extends VersionSyncComparison {
|
|
13
|
+
synchronized: boolean;
|
|
14
|
+
updatedFiles: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Return a stable x.y.z version. SemVer build metadata, including +codex cachebusters,
|
|
18
|
+
* deliberately has no effect on project synchronization.
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeTaskPlannerVersion(value: unknown): string | undefined;
|
|
21
|
+
export declare function compareTaskPlannerVersions(installedValue: unknown, storedValue: unknown): VersionSyncComparison;
|
|
22
|
+
/**
|
|
23
|
+
* Synchronize only TaskPlanner-owned marker blocks and safe config defaults.
|
|
24
|
+
* The recorded version is persisted last so an interrupted sync retries next time.
|
|
25
|
+
*/
|
|
26
|
+
export declare function synchronizeTaskPlannerProject(workspaceRoot: string, configManager: ConfigManager, installedValue: unknown, options?: ProjectSyncOptions): ProjectSyncResult;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Task } from '../model/task.js';
|
|
2
|
+
import { TaskState } from '../model/state.js';
|
|
3
|
+
import { TaskPlannerConfig } from '../model/config.js';
|
|
4
|
+
import { ParseResult } from '../model/parseResult.js';
|
|
5
|
+
export declare class FileStore {
|
|
6
|
+
private tasksDir;
|
|
7
|
+
constructor(tasksDir: string);
|
|
8
|
+
readState(state: TaskState): ParseResult;
|
|
9
|
+
writeState(state: TaskState, tasks: Task[]): void;
|
|
10
|
+
readAllStates(config: TaskPlannerConfig): Map<string, ParseResult>;
|
|
11
|
+
readStateAsync(state: TaskState): Promise<ParseResult>;
|
|
12
|
+
readRawContentAsync(state: TaskState): Promise<string>;
|
|
13
|
+
readAllStatesAsync(config: TaskPlannerConfig): Promise<Map<string, ParseResult>>;
|
|
14
|
+
ensureDirectory(): void;
|
|
15
|
+
initializeStateFiles(config: TaskPlannerConfig): void;
|
|
16
|
+
getStateFilePath(state: TaskState): string;
|
|
17
|
+
readRawContent(state: TaskState): string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Task } from '../model/task.js';
|
|
2
|
+
import { TaskPlannerConfig } from '../model/config.js';
|
|
3
|
+
import { ParseWarning } from '../model/parseResult.js';
|
|
4
|
+
import { ConfigManager } from '../config/configManager.js';
|
|
5
|
+
import { FileStore } from './fileStore.js';
|
|
6
|
+
import { DuplicateResolution } from '../validation/duplicateDetector.js';
|
|
7
|
+
export type TaskStoreListener = () => void;
|
|
8
|
+
export declare function isDeferredStateName(stateName: string): boolean;
|
|
9
|
+
export declare class TaskStore {
|
|
10
|
+
private configManager;
|
|
11
|
+
private tasksByState;
|
|
12
|
+
private parseWarningsByFile;
|
|
13
|
+
/** Done/Rejected not yet fully parsed; `tasksByState` holds [] until loaded. */
|
|
14
|
+
private deferredUnloadedStates;
|
|
15
|
+
/** Heading counts for deferred states (from `countTaskHeadings`). */
|
|
16
|
+
private deferredSectionCounts;
|
|
17
|
+
private listeners;
|
|
18
|
+
private fileStore;
|
|
19
|
+
private idGenerator;
|
|
20
|
+
constructor(configManager: ConfigManager, fileStore: FileStore);
|
|
21
|
+
get config(): TaskPlannerConfig;
|
|
22
|
+
reload(): void;
|
|
23
|
+
/** Reset in-memory state and deferred tracking to a blank slate before a reload. */
|
|
24
|
+
private resetReloadState;
|
|
25
|
+
/** Record a deferred state (raw counted only; tasks loaded lazily). */
|
|
26
|
+
private applyDeferredState;
|
|
27
|
+
/** Record a fully-parsed state's tasks and warnings. */
|
|
28
|
+
private applyParsedState;
|
|
29
|
+
private reloadSync;
|
|
30
|
+
reloadAsync(): Promise<void>;
|
|
31
|
+
/** Parse one state file into memory; clears deferred flag for that state. */
|
|
32
|
+
private parseStateIntoStore;
|
|
33
|
+
reloadState(stateName: string): void;
|
|
34
|
+
/** Load a deferred state (Done/Rejected) if it was not parsed yet. */
|
|
35
|
+
ensureStateLoaded(stateName: string): void;
|
|
36
|
+
/** Load every deferred state (e.g. assignee grouping, search, move picker). */
|
|
37
|
+
ensureAllDeferredStatesLoaded(): void;
|
|
38
|
+
/** Per-state counts for UI: heading count when deferred, else parsed task length. */
|
|
39
|
+
getStateDisplayCounts(): Map<string, number>;
|
|
40
|
+
isStateDeferredUnloaded(stateName: string): boolean;
|
|
41
|
+
getWarnings(): {
|
|
42
|
+
fileName: string;
|
|
43
|
+
warnings: ParseWarning[];
|
|
44
|
+
}[];
|
|
45
|
+
getTasksByState(stateName: string): Task[];
|
|
46
|
+
getAllTasks(): Map<string, Task[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Highest task-ID number across every state. Loaded states read from memory;
|
|
49
|
+
* deferred states (Done/Rejected) scan raw file content so they stay deferred.
|
|
50
|
+
*/
|
|
51
|
+
getMaxTaskIdNumber(): number;
|
|
52
|
+
private findInMemory;
|
|
53
|
+
findTask(taskId: string): {
|
|
54
|
+
task: Task;
|
|
55
|
+
stateName: string;
|
|
56
|
+
} | null;
|
|
57
|
+
createTask(task: Omit<Task, 'id'>, stateName: string): Task;
|
|
58
|
+
moveTask(taskId: string, targetStateName: string, targetIndex?: number): Task | null;
|
|
59
|
+
deleteTask(taskId: string): boolean;
|
|
60
|
+
updateTask(taskId: string, updates: Partial<Omit<Task, 'id'>>): Task | null;
|
|
61
|
+
private static hasChanges;
|
|
62
|
+
reorderTaskToIndex(taskId: string, newIndex: number): boolean;
|
|
63
|
+
reorderTask(taskId: string, direction: 'up' | 'down'): boolean;
|
|
64
|
+
onDidChange(listener: TaskStoreListener): {
|
|
65
|
+
dispose: () => void;
|
|
66
|
+
};
|
|
67
|
+
fixDuplicates(resolutions: DuplicateResolution[]): number;
|
|
68
|
+
private findState;
|
|
69
|
+
private notifyListeners;
|
|
70
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Task } from '../model/task.js';
|
|
2
|
+
import { TaskState } from '../model/state.js';
|
|
3
|
+
export interface DuplicateOccurrence {
|
|
4
|
+
stateName: string;
|
|
5
|
+
task: Task;
|
|
6
|
+
index: number;
|
|
7
|
+
}
|
|
8
|
+
export interface DuplicateConflict {
|
|
9
|
+
taskId: string;
|
|
10
|
+
occurrences: DuplicateOccurrence[];
|
|
11
|
+
}
|
|
12
|
+
export interface DuplicateResolution {
|
|
13
|
+
taskId: string;
|
|
14
|
+
keep: DuplicateOccurrence;
|
|
15
|
+
remove: DuplicateOccurrence[];
|
|
16
|
+
}
|
|
17
|
+
export declare function detectDuplicates(tasksByState: Map<string, Task[]>): DuplicateConflict[];
|
|
18
|
+
export declare function resolveConflict(conflict: DuplicateConflict, states: TaskState[]): DuplicateResolution;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TaskStore } from '../store/taskStore.js';
|
|
2
|
+
import type { ConfigManager } from '../config/configManager.js';
|
|
3
|
+
import type { TaskViewData } from '../model/messages.js';
|
|
4
|
+
import { TaskListSortBy } from '../filter/taskFilter.js';
|
|
5
|
+
export interface BuildBoardViewModelOptions {
|
|
6
|
+
searchQuery?: string;
|
|
7
|
+
sortBy?: TaskListSortBy;
|
|
8
|
+
/**
|
|
9
|
+
* Per-state cap. `undefined` uses the core default (50), `null` disables the cap.
|
|
10
|
+
*/
|
|
11
|
+
limit?: number | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildBoardViewModel(taskStore: TaskStore, configManager: ConfigManager, opts?: BuildBoardViewModelOptions): TaskViewData;
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smekai/taskplanner",
|
|
3
|
+
"version": "2.1.14",
|
|
4
|
+
"description": "TaskPlanner's markdown task board (.tasks/) as a library and as an MCP server.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/smekai/taskplanner#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/smekai/taskplanner.git",
|
|
10
|
+
"directory": "packages/mcp-server"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/smekai/taskplanner/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"taskplanner",
|
|
19
|
+
"tasks",
|
|
20
|
+
"kanban",
|
|
21
|
+
"markdown",
|
|
22
|
+
"agent"
|
|
23
|
+
],
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./mcp-server": "./dist/mcp-server.js",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"bin": {
|
|
36
|
+
"taskplanner-mcp": "bin/taskplanner-mcp.js"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"bin/",
|
|
40
|
+
"dist/",
|
|
41
|
+
"ui/",
|
|
42
|
+
"LICENSE",
|
|
43
|
+
"README.md"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
}
|
|
51
|
+
}
|