@task-mcp/shared 1.0.4 → 1.0.7
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/algorithms/critical-path.d.ts.map +1 -1
- package/dist/algorithms/critical-path.js +50 -26
- package/dist/algorithms/critical-path.js.map +1 -1
- package/dist/algorithms/dependency-integrity.d.ts +73 -0
- package/dist/algorithms/dependency-integrity.d.ts.map +1 -0
- package/dist/algorithms/dependency-integrity.js +189 -0
- package/dist/algorithms/dependency-integrity.js.map +1 -0
- package/dist/algorithms/index.d.ts +2 -0
- package/dist/algorithms/index.d.ts.map +1 -1
- package/dist/algorithms/index.js +2 -0
- package/dist/algorithms/index.js.map +1 -1
- package/dist/algorithms/tech-analysis.d.ts +106 -0
- package/dist/algorithms/tech-analysis.d.ts.map +1 -0
- package/dist/algorithms/tech-analysis.js +296 -0
- package/dist/algorithms/tech-analysis.js.map +1 -0
- package/dist/algorithms/tech-analysis.test.d.ts +2 -0
- package/dist/algorithms/tech-analysis.test.d.ts.map +1 -0
- package/dist/algorithms/tech-analysis.test.js +338 -0
- package/dist/algorithms/tech-analysis.test.js.map +1 -0
- package/dist/algorithms/topological-sort.d.ts.map +1 -1
- package/dist/algorithms/topological-sort.js +60 -8
- package/dist/algorithms/topological-sort.js.map +1 -1
- package/dist/schemas/inbox.d.ts +55 -0
- package/dist/schemas/inbox.d.ts.map +1 -0
- package/dist/schemas/inbox.js +25 -0
- package/dist/schemas/inbox.js.map +1 -0
- package/dist/schemas/index.d.ts +3 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +9 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/project.d.ts +154 -41
- package/dist/schemas/project.d.ts.map +1 -1
- package/dist/schemas/project.js +38 -33
- package/dist/schemas/project.js.map +1 -1
- package/dist/schemas/response-format.d.ts +80 -0
- package/dist/schemas/response-format.d.ts.map +1 -0
- package/dist/schemas/response-format.js +17 -0
- package/dist/schemas/response-format.js.map +1 -0
- package/dist/schemas/task.d.ts +592 -94
- package/dist/schemas/task.d.ts.map +1 -1
- package/dist/schemas/task.js +124 -64
- package/dist/schemas/task.js.map +1 -1
- package/dist/schemas/view.d.ts +128 -37
- package/dist/schemas/view.d.ts.map +1 -1
- package/dist/schemas/view.js +38 -24
- package/dist/schemas/view.js.map +1 -1
- package/dist/utils/date.d.ts.map +1 -1
- package/dist/utils/date.js +17 -2
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/hierarchy.d.ts +75 -0
- package/dist/utils/hierarchy.d.ts.map +1 -0
- package/dist/utils/hierarchy.js +179 -0
- package/dist/utils/hierarchy.js.map +1 -0
- package/dist/utils/id.d.ts +51 -1
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +124 -4
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/id.test.d.ts +2 -0
- package/dist/utils/id.test.d.ts.map +1 -0
- package/dist/utils/id.test.js +228 -0
- package/dist/utils/id.test.js.map +1 -0
- package/dist/utils/index.d.ts +4 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +7 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/natural-language.d.ts +45 -0
- package/dist/utils/natural-language.d.ts.map +1 -1
- package/dist/utils/natural-language.js +86 -0
- package/dist/utils/natural-language.js.map +1 -1
- package/dist/utils/projection.d.ts +65 -0
- package/dist/utils/projection.d.ts.map +1 -0
- package/dist/utils/projection.js +181 -0
- package/dist/utils/projection.js.map +1 -0
- package/dist/utils/projection.test.d.ts +2 -0
- package/dist/utils/projection.test.d.ts.map +1 -0
- package/dist/utils/projection.test.js +400 -0
- package/dist/utils/projection.test.js.map +1 -0
- package/package.json +2 -2
- package/src/algorithms/critical-path.ts +56 -24
- package/src/algorithms/dependency-integrity.ts +270 -0
- package/src/algorithms/index.ts +28 -0
- package/src/algorithms/tech-analysis.test.ts +413 -0
- package/src/algorithms/tech-analysis.ts +412 -0
- package/src/algorithms/topological-sort.ts +66 -9
- package/src/schemas/inbox.ts +32 -0
- package/src/schemas/index.ts +31 -0
- package/src/schemas/project.ts +43 -40
- package/src/schemas/response-format.ts +108 -0
- package/src/schemas/task.ts +145 -77
- package/src/schemas/view.ts +43 -33
- package/src/utils/date.ts +18 -2
- package/src/utils/hierarchy.ts +224 -0
- package/src/utils/id.test.ts +281 -0
- package/src/utils/id.ts +139 -4
- package/src/utils/index.ts +46 -2
- package/src/utils/natural-language.ts +113 -0
- package/src/utils/projection.test.ts +505 -0
- package/src/utils/projection.ts +251 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projection Utilities
|
|
3
|
+
*
|
|
4
|
+
* Transform full objects into token-efficient projections.
|
|
5
|
+
* Reduces token usage by 70-88% for list operations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Task } from "../schemas/task.js";
|
|
9
|
+
import type { Project } from "../schemas/project.js";
|
|
10
|
+
import type { InboxItem } from "../schemas/inbox.js";
|
|
11
|
+
import type {
|
|
12
|
+
ResponseFormat,
|
|
13
|
+
TaskSummary,
|
|
14
|
+
TaskPreview,
|
|
15
|
+
ProjectSummary,
|
|
16
|
+
ProjectPreview,
|
|
17
|
+
InboxSummary,
|
|
18
|
+
InboxPreview,
|
|
19
|
+
PaginatedResponse,
|
|
20
|
+
DEFAULT_LIMIT,
|
|
21
|
+
MAX_LIMIT,
|
|
22
|
+
} from "../schemas/response-format.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Project a single task to the specified format
|
|
26
|
+
*/
|
|
27
|
+
export function projectTask(task: Task, format: ResponseFormat): TaskSummary | TaskPreview | Task {
|
|
28
|
+
switch (format) {
|
|
29
|
+
case "concise":
|
|
30
|
+
return {
|
|
31
|
+
id: task.id,
|
|
32
|
+
title: task.title,
|
|
33
|
+
status: task.status,
|
|
34
|
+
priority: task.priority,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
case "standard":
|
|
38
|
+
return {
|
|
39
|
+
id: task.id,
|
|
40
|
+
title: task.title,
|
|
41
|
+
status: task.status,
|
|
42
|
+
priority: task.priority,
|
|
43
|
+
dueDate: task.dueDate,
|
|
44
|
+
tags: task.tags,
|
|
45
|
+
contexts: task.contexts,
|
|
46
|
+
parentId: task.parentId,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
case "detailed":
|
|
50
|
+
default:
|
|
51
|
+
return task;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Project multiple tasks with optional limit
|
|
57
|
+
*/
|
|
58
|
+
export function projectTasks(
|
|
59
|
+
tasks: Task[],
|
|
60
|
+
format: ResponseFormat,
|
|
61
|
+
limit?: number
|
|
62
|
+
): (TaskSummary | TaskPreview | Task)[] {
|
|
63
|
+
const sliced = limit ? tasks.slice(0, limit) : tasks;
|
|
64
|
+
return sliced.map((task) => projectTask(task, format));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Project tasks with pagination
|
|
69
|
+
*/
|
|
70
|
+
export function projectTasksPaginated(
|
|
71
|
+
tasks: Task[],
|
|
72
|
+
format: ResponseFormat,
|
|
73
|
+
limit: number = 20,
|
|
74
|
+
offset: number = 0
|
|
75
|
+
): PaginatedResponse<TaskSummary | TaskPreview | Task> {
|
|
76
|
+
const effectiveLimit = Math.min(limit, 100);
|
|
77
|
+
const sliced = tasks.slice(offset, offset + effectiveLimit);
|
|
78
|
+
const projected = sliced.map((task) => projectTask(task, format));
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
items: projected,
|
|
82
|
+
total: tasks.length,
|
|
83
|
+
limit: effectiveLimit,
|
|
84
|
+
offset,
|
|
85
|
+
hasMore: offset + effectiveLimit < tasks.length,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Project a single project to the specified format
|
|
91
|
+
*/
|
|
92
|
+
export function projectProject(
|
|
93
|
+
project: Project,
|
|
94
|
+
format: ResponseFormat
|
|
95
|
+
): ProjectSummary | ProjectPreview | Project {
|
|
96
|
+
switch (format) {
|
|
97
|
+
case "concise": {
|
|
98
|
+
const summary: ProjectSummary = {
|
|
99
|
+
id: project.id,
|
|
100
|
+
name: project.name,
|
|
101
|
+
status: project.status,
|
|
102
|
+
};
|
|
103
|
+
if (project.completionPercentage !== undefined) {
|
|
104
|
+
summary.completionPercentage = project.completionPercentage;
|
|
105
|
+
}
|
|
106
|
+
return summary;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
case "standard": {
|
|
110
|
+
const preview: ProjectPreview = {
|
|
111
|
+
id: project.id,
|
|
112
|
+
name: project.name,
|
|
113
|
+
status: project.status,
|
|
114
|
+
};
|
|
115
|
+
if (project.completionPercentage !== undefined) {
|
|
116
|
+
preview.completionPercentage = project.completionPercentage;
|
|
117
|
+
}
|
|
118
|
+
if (project.description !== undefined) {
|
|
119
|
+
preview.description = project.description;
|
|
120
|
+
}
|
|
121
|
+
if (project.totalTasks !== undefined) {
|
|
122
|
+
preview.totalTasks = project.totalTasks;
|
|
123
|
+
}
|
|
124
|
+
if (project.completedTasks !== undefined) {
|
|
125
|
+
preview.completedTasks = project.completedTasks;
|
|
126
|
+
}
|
|
127
|
+
return preview;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
case "detailed":
|
|
131
|
+
default:
|
|
132
|
+
return project;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Project multiple projects with optional limit
|
|
138
|
+
*/
|
|
139
|
+
export function projectProjects(
|
|
140
|
+
projects: Project[],
|
|
141
|
+
format: ResponseFormat,
|
|
142
|
+
limit?: number
|
|
143
|
+
): (ProjectSummary | ProjectPreview | Project)[] {
|
|
144
|
+
const sliced = limit ? projects.slice(0, limit) : projects;
|
|
145
|
+
return sliced.map((project) => projectProject(project, format));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Project a single inbox item to the specified format
|
|
150
|
+
*/
|
|
151
|
+
export function projectInboxItem(
|
|
152
|
+
item: InboxItem,
|
|
153
|
+
format: ResponseFormat
|
|
154
|
+
): InboxSummary | InboxPreview | InboxItem {
|
|
155
|
+
switch (format) {
|
|
156
|
+
case "concise":
|
|
157
|
+
return {
|
|
158
|
+
id: item.id,
|
|
159
|
+
content: item.content,
|
|
160
|
+
status: item.status,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
case "standard":
|
|
164
|
+
return {
|
|
165
|
+
id: item.id,
|
|
166
|
+
content: item.content,
|
|
167
|
+
status: item.status,
|
|
168
|
+
capturedAt: item.capturedAt,
|
|
169
|
+
tags: item.tags,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
case "detailed":
|
|
173
|
+
default:
|
|
174
|
+
return item;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Project multiple inbox items with optional limit
|
|
180
|
+
*/
|
|
181
|
+
export function projectInboxItems(
|
|
182
|
+
items: InboxItem[],
|
|
183
|
+
format: ResponseFormat,
|
|
184
|
+
limit?: number
|
|
185
|
+
): (InboxSummary | InboxPreview | InboxItem)[] {
|
|
186
|
+
const sliced = limit ? items.slice(0, limit) : items;
|
|
187
|
+
return sliced.map((item) => projectInboxItem(item, format));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Format response based on format type
|
|
192
|
+
* - concise/standard: JSON string for machine processing
|
|
193
|
+
* - detailed: Human-readable text
|
|
194
|
+
*/
|
|
195
|
+
export function formatResponse<T>(
|
|
196
|
+
data: T | T[],
|
|
197
|
+
format: ResponseFormat,
|
|
198
|
+
detailedFormatter?: (data: T | T[]) => string
|
|
199
|
+
): string {
|
|
200
|
+
if (format === "detailed" && detailedFormatter) {
|
|
201
|
+
return detailedFormatter(data);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Concise and standard: compact JSON
|
|
205
|
+
return JSON.stringify(data);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Apply pagination parameters
|
|
210
|
+
*/
|
|
211
|
+
export function applyPagination<T>(
|
|
212
|
+
items: T[],
|
|
213
|
+
limit: number = 20,
|
|
214
|
+
offset: number = 0
|
|
215
|
+
): { items: T[]; hasMore: boolean; total: number } {
|
|
216
|
+
const effectiveLimit = Math.min(Math.max(1, limit), 100);
|
|
217
|
+
const effectiveOffset = Math.max(0, offset);
|
|
218
|
+
const sliced = items.slice(effectiveOffset, effectiveOffset + effectiveLimit);
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
items: sliced,
|
|
222
|
+
hasMore: effectiveOffset + effectiveLimit < items.length,
|
|
223
|
+
total: items.length,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Truncate string for token efficiency
|
|
229
|
+
*/
|
|
230
|
+
export function truncate(str: string, maxLength: number = 100): string {
|
|
231
|
+
if (str.length <= maxLength) return str;
|
|
232
|
+
return str.slice(0, maxLength - 3) + "...";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Summarize a list of items for token efficiency
|
|
237
|
+
*/
|
|
238
|
+
export function summarizeList<T>(
|
|
239
|
+
items: T[],
|
|
240
|
+
maxDisplay: number = 5,
|
|
241
|
+
getId: (item: T) => string
|
|
242
|
+
): { displayed: T[]; remaining: number; remainingIds: string[] } {
|
|
243
|
+
const displayed = items.slice(0, maxDisplay);
|
|
244
|
+
const remaining = items.slice(maxDisplay);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
displayed,
|
|
248
|
+
remaining: remaining.length,
|
|
249
|
+
remainingIds: remaining.map(getId),
|
|
250
|
+
};
|
|
251
|
+
}
|