@sideboard-ai/core 0.1.264 → 0.1.267

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 (68) hide show
  1. package/dist/{abletime-6AOJI2YZ.js → abletime-4ZSDI4YP.js} +9 -6
  2. package/dist/{abletime-U75ZGDIX.js → abletime-JNQAHLHH.js} +7 -4
  3. package/dist/{abletime-oauth-TA2YDCYX.js → abletime-oauth-4RXZH2KU.js} +3 -3
  4. package/dist/{abletime-oauth-LOAHGG4X.js → abletime-oauth-DCEIINYT.js} +5 -5
  5. package/dist/{abletime-rest-CTA5WV26.js → abletime-rest-KVBJFVFD.js} +3 -3
  6. package/dist/{abletime-rest-YZPFM6IY.js → abletime-rest-VN6PZ6P2.js} +5 -5
  7. package/dist/agents/cursor-runner.js +7 -5
  8. package/dist/{agents-3TUMFSMH.js → agents-G3JTULM2.js} +7 -5
  9. package/dist/{agents-6FWDRVA2.js → agents-XRXJCAWJ.js} +11 -10
  10. package/dist/{app-settings-RKFFUIFQ.js → app-settings-L5HGYXWJ.js} +1 -3
  11. package/dist/{app-settings-MVZPM6WW.js → app-settings-RAC4PSSP.js} +3 -5
  12. package/dist/{caffeinate-hold-UAGLSGMM.js → caffeinate-hold-7JM5H5P3.js} +2 -2
  13. package/dist/{chunk-F5MFNUAA.js → chunk-27Z4MEQ5.js} +1 -1
  14. package/dist/{chunk-EK3KVT7I.js → chunk-2XIRV7FS.js} +53 -1254
  15. package/dist/{chunk-3H7O27X2.js → chunk-3VBS6MES.js} +39 -1017
  16. package/dist/chunk-4ECDIKAS.js +2273 -0
  17. package/dist/{chunk-H547WSSZ.js → chunk-4RZRHTSZ.js} +1 -1
  18. package/dist/{chunk-QN5DL2QO.js → chunk-5DZUWGKV.js} +1 -1
  19. package/dist/chunk-5N4Q46SG.js +392 -0
  20. package/dist/{chunk-YKYEHDMX.js → chunk-AGXZAMOF.js} +5 -5
  21. package/dist/{chunk-RKPBIB2U.js → chunk-DB7MVDYS.js} +33 -7
  22. package/dist/{chunk-BOMSJUXW.js → chunk-DBFAFI5A.js} +5 -5
  23. package/dist/chunk-FAGK33E2.js +994 -0
  24. package/dist/{chunk-A5SAYFJ4.js → chunk-FIBZEFKA.js} +4 -390
  25. package/dist/{chunk-5PK53SAP.js → chunk-GONPMH36.js} +5 -5
  26. package/dist/{chunk-L5WGAIL2.js → chunk-GZXKUUJO.js} +35 -9
  27. package/dist/{chunk-Z2LGMV6C.js → chunk-H5XL4KUS.js} +21 -0
  28. package/dist/{chunk-T3AYRQJZ.js → chunk-HSRN2CSL.js} +473 -2487
  29. package/dist/{chunk-TJ673EZT.js → chunk-JANCPF7Z.js} +2 -2
  30. package/dist/chunk-KZ2CDZBZ.js +828 -0
  31. package/dist/{chunk-6YY7XPPL.js → chunk-L6CYOON4.js} +5 -5
  32. package/dist/{chunk-6YOXQVJ7.js → chunk-LAIBYKZS.js} +3 -3
  33. package/dist/{chunk-4ALDX5IO.js → chunk-NWE3NOWQ.js} +3 -3
  34. package/dist/{chunk-36FOBJBF.js → chunk-OIENQEGG.js} +63 -38
  35. package/dist/{chunk-2QUQH2SZ.js → chunk-PAH7KDL2.js} +68 -24
  36. package/dist/{chunk-XAISOBBG.js → chunk-TQRSVE7D.js} +1 -1
  37. package/dist/chunk-UKSJO36E.js +1224 -0
  38. package/dist/{chunk-CEMNIGQH.js → chunk-UN5Q7POQ.js} +1 -1
  39. package/dist/{chunk-5ZPT5YAV.js → chunk-USBZ7PH4.js} +1 -1
  40. package/dist/chunk-UXI52MLJ.js +826 -0
  41. package/dist/chunk-X7RP3TQB.js +2385 -0
  42. package/dist/{chunk-QX6QUZVD.js → chunk-ZSGSVFWD.js} +424 -2611
  43. package/dist/conductor-MLM5NGTP.js +104 -0
  44. package/dist/conductor-NRKTEN5X.js +105 -0
  45. package/dist/{connected-teams-7CENZDWU.js → connected-teams-JIUOSZ6C.js} +2 -2
  46. package/dist/{coordinator-prompt-J7DKHOCH.js → coordinator-prompt-4GHKCVRH.js} +7 -7
  47. package/dist/{coordinator-prompt-HZCQZ6C5.js → coordinator-prompt-BKRQDZFT.js} +3 -3
  48. package/dist/{cursor-recover-FALSNEZN.js → cursor-recover-MB3T2K5T.js} +2 -2
  49. package/dist/{global-workspace-TI26K25J.js → global-workspace-EEWJOMED.js} +9 -3
  50. package/dist/{global-workspace-6LDUZ2NF.js → global-workspace-EWFL4HPW.js} +13 -7
  51. package/dist/index.cjs +3918 -2592
  52. package/dist/index.d.cts +363 -68
  53. package/dist/index.d.ts +363 -68
  54. package/dist/index.js +4181 -3462
  55. package/dist/{managed-accounts-4BLTJKAN.js → managed-accounts-46A4KRUE.js} +2 -2
  56. package/dist/mcp/run-stdio.cjs +1894 -2012
  57. package/dist/mcp/run-stdio.js +719 -1445
  58. package/dist/{orchestrator-5YU46YNS.js → orchestrator-6ZQ2CYS4.js} +9 -6
  59. package/dist/{orchestrator-4JSG7BWC.js → orchestrator-MA3MHYIM.js} +15 -13
  60. package/dist/{paths-IUR3ABNG.js → paths-HYT5WOOX.js} +1 -1
  61. package/dist/{thread-store-FJ5CDX2M.js → thread-store-B3ZM4QEZ.js} +3 -3
  62. package/dist/{workspaces-QJ3XIPUJ.js → workspaces-F33Z4CEY.js} +3 -3
  63. package/dist/{workspaces-WOQHJFRQ.js → workspaces-SLP24Z3S.js} +7 -7
  64. package/dist/{worktree-6U2FA5LO.js → worktree-ACW23KJ5.js} +6 -6
  65. package/dist/{worktree-KQA4ON2G.js → worktree-C7RPVHZ7.js} +2 -2
  66. package/package.json +1 -1
  67. package/dist/chunk-CEOTK5GZ.js +0 -479
  68. package/dist/chunk-K7B25HO4.js +0 -477
@@ -1,477 +0,0 @@
1
- import {
2
- textFromAbleTimeDoc
3
- } from "./chunk-YKYEHDMX.js";
4
- import {
5
- assertAbleTimeCredential,
6
- callAbleTimeTool,
7
- normalizeAbleTimeHost,
8
- rewriteAbleTimeError
9
- } from "./chunk-6YY7XPPL.js";
10
- import {
11
- isAbleTimeConnected,
12
- saveAbleTimeConnection
13
- } from "./chunk-2QUQH2SZ.js";
14
-
15
- // src/integrations/abletime.ts
16
- var CLOSED_STATES = /* @__PURE__ */ new Set([
17
- "done",
18
- "completed",
19
- "canceled",
20
- "cancelled",
21
- "archived",
22
- "closed"
23
- ]);
24
- function asRecord(value) {
25
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
26
- }
27
- function asString(value) {
28
- return typeof value === "string" ? value.trim() : "";
29
- }
30
- function firstString(record, keys) {
31
- if (!record) return "";
32
- for (const key of keys) {
33
- const value = asString(record[key]);
34
- if (value) return value;
35
- }
36
- return "";
37
- }
38
- function firstRecord(record, keys) {
39
- if (!record) return null;
40
- for (const key of keys) {
41
- const value = asRecord(record[key]);
42
- if (value) return value;
43
- }
44
- return null;
45
- }
46
- function asList(value) {
47
- if (Array.isArray(value)) return value;
48
- const record = asRecord(value);
49
- if (!record) return [];
50
- for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
51
- if (Array.isArray(record[key])) return record[key];
52
- }
53
- return [];
54
- }
55
- function labelsOf(record) {
56
- const raw = record.tags ?? record.labels ?? record.tag_names;
57
- if (!Array.isArray(raw)) return [];
58
- return raw.map((item) => {
59
- if (typeof item === "string") return item.trim();
60
- const rec = asRecord(item);
61
- return rec ? firstString(rec, ["name", "title", "label"]) : "";
62
- }).filter(Boolean);
63
- }
64
- function commentsOf(record) {
65
- const raw = record.comments ?? record.notes ?? record.discussion;
66
- const out = [];
67
- for (const item of asList(raw)) {
68
- const rec = asRecord(item);
69
- if (!rec) continue;
70
- const body = firstString(rec, ["body", "text", "comment", "message", "contentSanitized"]) || textFromAbleTimeDoc(rec.content);
71
- if (!body) continue;
72
- const user = firstString(asRecord(rec.user) ?? asRecord(rec.author), ["name", "display_name", "username"]) || firstString(rec, ["user_name", "author", "username"]);
73
- const comment = { body };
74
- const id = firstString(rec, ["id", "comment_id", "commentId"]);
75
- if (id) comment.id = id;
76
- const url = firstString(rec, ["url", "permalink"]);
77
- if (url) comment.url = url;
78
- const createdAt = firstString(rec, ["created_at", "createdAt", "created"]);
79
- if (createdAt) comment.createdAt = createdAt;
80
- if (user) comment.user = user;
81
- out.push(comment);
82
- }
83
- return out;
84
- }
85
- function assigneeOf(record) {
86
- const nested = firstRecord(record, ["assignee", "assigned_to", "user", "owner"]);
87
- const name = firstString(nested, ["name", "display_name", "full_name", "email"]) || firstString(record, ["assignee_name", "assigneeName"]);
88
- if (!name) return void 0;
89
- const id = firstString(nested, ["id", "user_id"]);
90
- return { id: id || void 0, name };
91
- }
92
- function taskUrl(task, host) {
93
- const base = normalizeAbleTimeHost(host);
94
- const slug = encodeURIComponent(task.identifier || task.id);
95
- return `${base}/tasks/${slug}`;
96
- }
97
- function mapAbleTimeTask(raw, host) {
98
- const record = asRecord(raw);
99
- if (!record) return null;
100
- const nested = firstRecord(record, ["task", "data"]) ?? record;
101
- const id = firstString(nested, ["id", "task_id", "taskId", "timeflowTaskId"]);
102
- const identifier = firstString(nested, ["reference", "ref", "identifier", "key", "code", "number", "taskRef"]) || id;
103
- const title = firstString(nested, ["title", "name"]);
104
- if (!id && !identifier && !title) return null;
105
- const resolvedId = id || identifier;
106
- const resolvedIdentifier = identifier || id;
107
- const url = firstString(nested, ["url", "permalink", "html_url"]) || taskUrl({ id: resolvedId, identifier: resolvedIdentifier }, host);
108
- return {
109
- id: resolvedId,
110
- identifier: resolvedIdentifier,
111
- title: title || resolvedIdentifier,
112
- url,
113
- description: firstString(nested, ["description", "body", "details", "descriptionSanitized"]) || textFromAbleTimeDoc(nested.description) || void 0,
114
- state: firstString(nested, ["state", "board_state", "boardState", "status", "taskState"]) || void 0,
115
- projectId: firstString(nested, ["project_id", "projectId"]) || firstString(asRecord(nested.project), ["id"]) || void 0,
116
- categoryId: firstString(nested, ["category_id", "categoryId", "projectCategoryId"]) || firstString(asRecord(nested.category), ["id"]) || void 0,
117
- assignee: assigneeOf(nested),
118
- labels: labelsOf(nested),
119
- comments: commentsOf(nested),
120
- createdAt: firstString(nested, ["created_at", "createdAt", "created", "dateCreated"]) || void 0,
121
- updatedAt: firstString(nested, [
122
- "updated_at",
123
- "updatedAt",
124
- "modified_at",
125
- "modifiedAt",
126
- "last_activity_at",
127
- "lastActivityAt",
128
- "lastUpdate"
129
- ]) || void 0
130
- };
131
- }
132
- function toAbleTimeIssueInfo(task) {
133
- return {
134
- id: task.id || task.identifier,
135
- identifier: task.identifier,
136
- title: task.title,
137
- url: task.url,
138
- labels: task.labels,
139
- provider: "abletime",
140
- assignee: task.assignee?.name,
141
- assignees: task.assignee?.name ? [task.assignee.name] : void 0,
142
- ...task.createdAt ? { createdAt: task.createdAt } : {},
143
- ...task.updatedAt ? { updatedAt: task.updatedAt } : {}
144
- };
145
- }
146
- function issueAttachmentForAbleTimeTask(task) {
147
- return {
148
- id: `abletime-${task.id || task.identifier}`,
149
- name: task.identifier || task.title,
150
- kind: "issue",
151
- content: [
152
- `Linked issue: ${task.identifier} \u2014 ${task.title}`,
153
- task.url ? `URL: ${task.url}` : null,
154
- task.labels.length ? `Labels: ${task.labels.join(", ")}` : null
155
- ].filter(Boolean).join("\n")
156
- };
157
- }
158
- function mapProject(raw) {
159
- const record = asRecord(raw);
160
- if (!record) return null;
161
- const id = firstString(record, ["id", "project_id", "projectId"]);
162
- const name = firstString(record, ["name", "title", "projectName"]);
163
- if (!id && !name) return null;
164
- const categories = asList(record.categories ?? record.category).map((item) => {
165
- const rec = asRecord(item);
166
- if (!rec) return null;
167
- const categoryId = firstString(rec, ["id", "category_id", "projectCategoryId", "categoryId"]);
168
- const categoryName = firstString(rec, ["name", "title", "categoryName"]);
169
- if (!categoryId && !categoryName) return null;
170
- return { id: categoryId || categoryName, name: categoryName || categoryId };
171
- }).filter((item) => Boolean(item));
172
- return { id: id || name, name: name || id, categories };
173
- }
174
- function isOpenTask(task) {
175
- const state = (task.state ?? "").toLowerCase();
176
- return !state || !CLOSED_STATES.has(state);
177
- }
178
- async function getAbleTimeOrientation(opts) {
179
- const raw = await callAbleTimeTool("orientation", {}, opts);
180
- const record = asRecord(raw);
181
- const viewerRec = firstRecord(record, ["viewer", "principal", "user", "actor", "me", "person"]) ?? record;
182
- const viewer = {
183
- id: firstString(viewerRec, ["id", "user_id"]) || void 0,
184
- name: firstString(viewerRec, ["name", "display_name", "full_name"]) || firstString(record, ["name"]) || void 0
185
- };
186
- const projects = asList(
187
- record?.projects ?? record?.current_projects ?? record?.currentProjects
188
- ).map(mapProject).filter((item) => Boolean(item));
189
- const tasks = asList(record?.tasks ?? record?.active_tasks ?? record?.activeTasks).map((item) => mapAbleTimeTask(item, opts?.host)).filter((item) => Boolean(item));
190
- return { viewer, projects, tasks, raw };
191
- }
192
- async function listAbleTimeProjects(opts) {
193
- const raw = await callAbleTimeTool("list_projects", { include_categories: true }, opts);
194
- return asList(raw).map(mapProject).filter((item) => Boolean(item));
195
- }
196
- async function listAbleTimeTasks(opts) {
197
- const args = {};
198
- if (opts?.projectId) {
199
- args.project_id = opts.projectId;
200
- args.project = opts.projectId;
201
- }
202
- if (opts?.query) args.query = opts.query;
203
- const raw = await callAbleTimeTool("list_tasks", args, opts);
204
- const tasks = asList(raw).map((item) => mapAbleTimeTask(item, opts?.host)).filter((item) => Boolean(item));
205
- return opts?.includeClosed ? tasks : tasks.filter(isOpenTask);
206
- }
207
- async function searchAbleTimeTasks(query, opts) {
208
- const q = query.trim();
209
- if (!q) return [];
210
- const raw = await callAbleTimeTool("search_tasks", { query: q, q }, opts);
211
- return asList(raw).map((item) => mapAbleTimeTask(item, opts?.host)).filter((item) => Boolean(item)).filter(isOpenTask);
212
- }
213
- async function getAbleTimeTask(id, opts) {
214
- const raw = await callAbleTimeTool("get_task", { id, task_id: id }, opts);
215
- const task = mapAbleTimeTask(raw, opts?.host);
216
- if (!task) throw new Error(`AbleTime task not found: ${id}`);
217
- return task;
218
- }
219
- async function createAbleTimeTask(input, opts) {
220
- const title = input.title.trim();
221
- if (!title) throw new Error("AbleTime task title is required");
222
- const project = await resolveAbleTimeProject(input.projectId, opts);
223
- const category = resolveAbleTimeCategory(project, input.categoryId);
224
- const parent = input.parent?.trim();
225
- const descriptionParts = [
226
- parent ? `Spin-off of ${parent}.` : null,
227
- input.description?.trim() || null
228
- ].filter(Boolean);
229
- const raw = await callAbleTimeTool(
230
- "create_task",
231
- {
232
- title,
233
- description: descriptionParts.join("\n\n") || void 0,
234
- state: input.state ?? "todo",
235
- project: project.id,
236
- project_id: project.id,
237
- category: category?.id,
238
- category_id: category?.id,
239
- parent,
240
- parent_id: parent,
241
- related_task_id: parent
242
- },
243
- opts
244
- );
245
- const task = mapAbleTimeTask(raw, opts?.host);
246
- if (!task) throw new Error("AbleTime create_task returned no task");
247
- return task;
248
- }
249
- async function commentAbleTimeTask(input, opts) {
250
- const id = input.id.trim();
251
- const body = input.body.trim();
252
- if (!id) throw new Error("AbleTime task id is required");
253
- if (!body) throw new Error("AbleTime comment body is required");
254
- const raw = await callAbleTimeTool(
255
- "create_comment",
256
- { id, task_id: id, task: id, body, comment: body, text: body },
257
- opts
258
- );
259
- const rec = asRecord(raw);
260
- return {
261
- id: rec ? firstString(rec, ["id", "comment_id"]) || void 0 : void 0,
262
- body: rec ? firstString(rec, ["body", "text", "comment"]) || body : body
263
- };
264
- }
265
- function isAbleTimeNoneToken(value) {
266
- if (value == null) return true;
267
- const s = value.trim();
268
- return !s || /^(none|clear|unschedule|null)$/i.test(s);
269
- }
270
- function taskIdArgs(id) {
271
- return { id, task_id: id, task: id };
272
- }
273
- function ableTimeDependencyTarget(thisId, type, relatedId) {
274
- const s = type.trim().toLowerCase().replace(/[\s_-]+/g, "");
275
- if (s === "none" || s === "clear" || s === "null") {
276
- return { taskId: thisId, dependsOn: null };
277
- }
278
- if (s === "blockedby" || s === "blocked" || s === "dependson" || s === "waiton") {
279
- return { taskId: thisId, dependsOn: relatedId };
280
- }
281
- if (s === "blocks" || s === "blocking") {
282
- return { taskId: relatedId, dependsOn: thisId };
283
- }
284
- throw new Error(
285
- `AbleTime relation type must be blocks or blockedBy (got ${type}). AbleTime models one wait-on dependency.`
286
- );
287
- }
288
- async function setAbleTimeTaskDependency(taskId, dependsOn, opts) {
289
- const args = {
290
- ...taskIdArgs(taskId)
291
- };
292
- if (dependsOn) {
293
- args.depends_on = dependsOn;
294
- args.depends_on_id = dependsOn;
295
- args.dependency = dependsOn;
296
- args.dependency_id = dependsOn;
297
- args.blocked_by = dependsOn;
298
- args.wait_on = dependsOn;
299
- args.related_task_id = dependsOn;
300
- } else {
301
- args.depends_on = null;
302
- args.dependency = null;
303
- args.blocked_by = null;
304
- args.clear = true;
305
- }
306
- await callAbleTimeTool("set_task_dependency", args, opts);
307
- }
308
- async function updateAbleTimeTask(input, opts) {
309
- const id = input.id.trim();
310
- if (!id) throw new Error("AbleTime task id is required");
311
- const title = input.title?.trim();
312
- const description = input.description;
313
- const state = input.state?.trim();
314
- const addRelations = input.relations?.length ? input.relations : void 0;
315
- const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
316
- const updateArgs = { ...taskIdArgs(id) };
317
- if (title) updateArgs.title = title;
318
- if (description !== void 0) updateArgs.description = description;
319
- if (input.labels !== void 0) {
320
- updateArgs.tags = input.labels;
321
- updateArgs.labels = input.labels;
322
- updateArgs.tag_names = input.labels;
323
- }
324
- if (input.project !== void 0) {
325
- const projectName = (input.project ?? "").trim();
326
- if (isAbleTimeNoneToken(projectName)) {
327
- throw new Error("AbleTime tasks stay in a project \u2014 pass a project name or id");
328
- }
329
- const project = await resolveAbleTimeProject(projectName, opts);
330
- updateArgs.project = project.id;
331
- updateArgs.project_id = project.id;
332
- }
333
- if (input.parent !== void 0) {
334
- if (isAbleTimeNoneToken(input.parent)) {
335
- updateArgs.parent = null;
336
- updateArgs.parent_id = null;
337
- updateArgs.related_task_id = null;
338
- } else {
339
- const parent = (input.parent ?? "").trim();
340
- updateArgs.parent = parent;
341
- updateArgs.parent_id = parent;
342
- updateArgs.related_task_id = parent;
343
- }
344
- }
345
- const hasUpdateFields = Boolean(title) || description !== void 0 || input.labels !== void 0 || input.project !== void 0 || input.parent !== void 0;
346
- if (!hasUpdateFields && !state && !addRelations && !removeRelations) {
347
- throw new Error(
348
- "abletime_update_task needs at least one of title, description, state, labels, project, parent, relations, removeRelations"
349
- );
350
- }
351
- if (state) {
352
- await callAbleTimeTool(
353
- "set_task_state",
354
- { ...taskIdArgs(id), state },
355
- opts
356
- ).catch(async () => {
357
- await callAbleTimeTool(
358
- "update_task",
359
- { ...updateArgs, state },
360
- opts
361
- );
362
- });
363
- }
364
- if (hasUpdateFields) {
365
- await callAbleTimeTool("update_task", updateArgs, opts);
366
- }
367
- for (const rel of removeRelations ?? []) {
368
- const related = rel.issue.trim() || id;
369
- const target = ableTimeDependencyTarget(id, rel.type, related);
370
- await setAbleTimeTaskDependency(target.taskId, null, opts);
371
- }
372
- for (const rel of addRelations ?? []) {
373
- const related = rel.issue.trim();
374
- if (!related) throw new Error("AbleTime relations.issue is required (id or CRM-232)");
375
- const target = ableTimeDependencyTarget(id, rel.type, related);
376
- if (!target.dependsOn) {
377
- await setAbleTimeTaskDependency(target.taskId, null, opts);
378
- continue;
379
- }
380
- await setAbleTimeTaskDependency(target.taskId, target.dependsOn, opts);
381
- }
382
- return getAbleTimeTask(id, opts);
383
- }
384
- async function resolveAbleTimeProject(projectId, opts) {
385
- const wanted = projectId?.trim().toLowerCase();
386
- const fromOrientation = (await getAbleTimeOrientation(opts).catch(() => null))?.projects ?? [];
387
- const listed = fromOrientation.length > 0 ? fromOrientation : await listAbleTimeProjects(opts);
388
- if (listed.length === 0) {
389
- throw new Error(
390
- rewriteAbleTimeError(
391
- "AbleTime has no projects to create a task in \u2014 create a project in AbleTime first."
392
- )
393
- );
394
- }
395
- if (!wanted) return listed[0];
396
- const found = listed.find(
397
- (project) => project.id.toLowerCase() === wanted || project.name.toLowerCase() === wanted
398
- );
399
- if (!found) {
400
- const names = listed.map((project) => project.name).join(", ") || "(none)";
401
- throw new Error(`AbleTime project not found: ${projectId}. Known: ${names}`);
402
- }
403
- return found;
404
- }
405
- function resolveAbleTimeCategory(project, categoryId) {
406
- if (project.categories.length === 0) return void 0;
407
- const wanted = categoryId?.trim().toLowerCase();
408
- if (!wanted) return project.categories[0];
409
- return project.categories.find(
410
- (category) => category.id.toLowerCase() === wanted || category.name.toLowerCase() === wanted
411
- ) ?? project.categories[0];
412
- }
413
- function titlesMatch(a, b) {
414
- return a.trim().toLowerCase() === b.trim().toLowerCase();
415
- }
416
- async function ensureAbleTimeTask(input, opts) {
417
- const title = input.title.trim();
418
- if (!title) throw new Error("AbleTime task title is required");
419
- const searched = await searchAbleTimeTasks(title, opts).catch(() => []);
420
- const exact = searched.find((task) => titlesMatch(task.identifier, title)) || searched.find((task) => titlesMatch(task.title, title));
421
- if (exact) return { ...exact, created: false };
422
- const created = await createAbleTimeTask(
423
- {
424
- title,
425
- description: input.description,
426
- projectId: input.projectId,
427
- categoryId: input.categoryId,
428
- state: "todo"
429
- },
430
- opts
431
- );
432
- return { ...created, created: true };
433
- }
434
- async function listAbleTimeAssignedIssues(opts) {
435
- if (!opts?.token && !isAbleTimeConnected()) {
436
- throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
437
- }
438
- const [orientation, listed] = await Promise.all([
439
- getAbleTimeOrientation(opts).catch(() => null),
440
- listAbleTimeTasks(opts)
441
- ]);
442
- const issues = listed.map(toAbleTimeIssueInfo);
443
- return {
444
- viewer: orientation?.viewer ?? {},
445
- issues
446
- };
447
- }
448
- async function verifyAbleTimeConnection(input) {
449
- const token = assertAbleTimeCredential(input.token);
450
- const host = input.host?.trim() || void 0;
451
- const orientation = await getAbleTimeOrientation({ token, host });
452
- saveAbleTimeConnection({
453
- accessToken: token,
454
- host,
455
- viewerName: orientation.viewer.name
456
- });
457
- return orientation.viewer;
458
- }
459
-
460
- export {
461
- taskUrl,
462
- mapAbleTimeTask,
463
- toAbleTimeIssueInfo,
464
- issueAttachmentForAbleTimeTask,
465
- getAbleTimeOrientation,
466
- listAbleTimeProjects,
467
- listAbleTimeTasks,
468
- searchAbleTimeTasks,
469
- getAbleTimeTask,
470
- createAbleTimeTask,
471
- commentAbleTimeTask,
472
- ableTimeDependencyTarget,
473
- updateAbleTimeTask,
474
- ensureAbleTimeTask,
475
- listAbleTimeAssignedIssues,
476
- verifyAbleTimeConnection
477
- };