@sideboard-ai/core 0.1.263 → 0.1.266

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