@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.
Files changed (98) hide show
  1. package/dist/algorithms/critical-path.d.ts.map +1 -1
  2. package/dist/algorithms/critical-path.js +50 -26
  3. package/dist/algorithms/critical-path.js.map +1 -1
  4. package/dist/algorithms/dependency-integrity.d.ts +73 -0
  5. package/dist/algorithms/dependency-integrity.d.ts.map +1 -0
  6. package/dist/algorithms/dependency-integrity.js +189 -0
  7. package/dist/algorithms/dependency-integrity.js.map +1 -0
  8. package/dist/algorithms/index.d.ts +2 -0
  9. package/dist/algorithms/index.d.ts.map +1 -1
  10. package/dist/algorithms/index.js +2 -0
  11. package/dist/algorithms/index.js.map +1 -1
  12. package/dist/algorithms/tech-analysis.d.ts +106 -0
  13. package/dist/algorithms/tech-analysis.d.ts.map +1 -0
  14. package/dist/algorithms/tech-analysis.js +296 -0
  15. package/dist/algorithms/tech-analysis.js.map +1 -0
  16. package/dist/algorithms/tech-analysis.test.d.ts +2 -0
  17. package/dist/algorithms/tech-analysis.test.d.ts.map +1 -0
  18. package/dist/algorithms/tech-analysis.test.js +338 -0
  19. package/dist/algorithms/tech-analysis.test.js.map +1 -0
  20. package/dist/algorithms/topological-sort.d.ts.map +1 -1
  21. package/dist/algorithms/topological-sort.js +60 -8
  22. package/dist/algorithms/topological-sort.js.map +1 -1
  23. package/dist/schemas/inbox.d.ts +55 -0
  24. package/dist/schemas/inbox.d.ts.map +1 -0
  25. package/dist/schemas/inbox.js +25 -0
  26. package/dist/schemas/inbox.js.map +1 -0
  27. package/dist/schemas/index.d.ts +3 -1
  28. package/dist/schemas/index.d.ts.map +1 -1
  29. package/dist/schemas/index.js +9 -1
  30. package/dist/schemas/index.js.map +1 -1
  31. package/dist/schemas/project.d.ts +154 -41
  32. package/dist/schemas/project.d.ts.map +1 -1
  33. package/dist/schemas/project.js +38 -33
  34. package/dist/schemas/project.js.map +1 -1
  35. package/dist/schemas/response-format.d.ts +80 -0
  36. package/dist/schemas/response-format.d.ts.map +1 -0
  37. package/dist/schemas/response-format.js +17 -0
  38. package/dist/schemas/response-format.js.map +1 -0
  39. package/dist/schemas/task.d.ts +592 -94
  40. package/dist/schemas/task.d.ts.map +1 -1
  41. package/dist/schemas/task.js +124 -64
  42. package/dist/schemas/task.js.map +1 -1
  43. package/dist/schemas/view.d.ts +128 -37
  44. package/dist/schemas/view.d.ts.map +1 -1
  45. package/dist/schemas/view.js +38 -24
  46. package/dist/schemas/view.js.map +1 -1
  47. package/dist/utils/date.d.ts.map +1 -1
  48. package/dist/utils/date.js +17 -2
  49. package/dist/utils/date.js.map +1 -1
  50. package/dist/utils/hierarchy.d.ts +75 -0
  51. package/dist/utils/hierarchy.d.ts.map +1 -0
  52. package/dist/utils/hierarchy.js +179 -0
  53. package/dist/utils/hierarchy.js.map +1 -0
  54. package/dist/utils/id.d.ts +51 -1
  55. package/dist/utils/id.d.ts.map +1 -1
  56. package/dist/utils/id.js +124 -4
  57. package/dist/utils/id.js.map +1 -1
  58. package/dist/utils/id.test.d.ts +2 -0
  59. package/dist/utils/id.test.d.ts.map +1 -0
  60. package/dist/utils/id.test.js +228 -0
  61. package/dist/utils/id.test.js.map +1 -0
  62. package/dist/utils/index.d.ts +4 -2
  63. package/dist/utils/index.d.ts.map +1 -1
  64. package/dist/utils/index.js +7 -2
  65. package/dist/utils/index.js.map +1 -1
  66. package/dist/utils/natural-language.d.ts +45 -0
  67. package/dist/utils/natural-language.d.ts.map +1 -1
  68. package/dist/utils/natural-language.js +86 -0
  69. package/dist/utils/natural-language.js.map +1 -1
  70. package/dist/utils/projection.d.ts +65 -0
  71. package/dist/utils/projection.d.ts.map +1 -0
  72. package/dist/utils/projection.js +181 -0
  73. package/dist/utils/projection.js.map +1 -0
  74. package/dist/utils/projection.test.d.ts +2 -0
  75. package/dist/utils/projection.test.d.ts.map +1 -0
  76. package/dist/utils/projection.test.js +400 -0
  77. package/dist/utils/projection.test.js.map +1 -0
  78. package/package.json +2 -2
  79. package/src/algorithms/critical-path.ts +56 -24
  80. package/src/algorithms/dependency-integrity.ts +270 -0
  81. package/src/algorithms/index.ts +28 -0
  82. package/src/algorithms/tech-analysis.test.ts +413 -0
  83. package/src/algorithms/tech-analysis.ts +412 -0
  84. package/src/algorithms/topological-sort.ts +66 -9
  85. package/src/schemas/inbox.ts +32 -0
  86. package/src/schemas/index.ts +31 -0
  87. package/src/schemas/project.ts +43 -40
  88. package/src/schemas/response-format.ts +108 -0
  89. package/src/schemas/task.ts +145 -77
  90. package/src/schemas/view.ts +43 -33
  91. package/src/utils/date.ts +18 -2
  92. package/src/utils/hierarchy.ts +224 -0
  93. package/src/utils/id.test.ts +281 -0
  94. package/src/utils/id.ts +139 -4
  95. package/src/utils/index.ts +46 -2
  96. package/src/utils/natural-language.ts +113 -0
  97. package/src/utils/projection.test.ts +505 -0
  98. 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
+ }