@sideboard-ai/core 0.1.202 → 0.1.203

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 (44) hide show
  1. package/dist/{abletime-KGPD3UUJ.js → abletime-JFGZBDHH.js} +4 -2
  2. package/dist/{abletime-345SE3B4.js → abletime-SISJEPJ3.js} +4 -2
  3. package/dist/abletime-oauth-7TD5Z2QV.js +265 -0
  4. package/dist/abletime-oauth-OSQYFB3E.js +40 -0
  5. package/dist/abletime-rest-QPJTDLKX.js +25 -0
  6. package/dist/abletime-rest-ZJGWYALM.js +24 -0
  7. package/dist/{agents-OXX3ONVY.js → agents-3755WYQM.js} +4 -4
  8. package/dist/{agents-573ZDIX6.js → agents-ZMWL43SP.js} +4 -4
  9. package/dist/{app-settings-V6IHESEQ.js → app-settings-LGHMNHSP.js} +1 -1
  10. package/dist/{app-settings-AXCURTZJ.js → app-settings-YEPF46IJ.js} +1 -1
  11. package/dist/{chunk-7NKY2OX7.js → chunk-2DVCCLII.js} +78 -62
  12. package/dist/chunk-3PYH2RLA.js +388 -0
  13. package/dist/{chunk-A2TAKYSG.js → chunk-5IXJTUST.js} +4 -4
  14. package/dist/chunk-6VEIKW5C.js +390 -0
  15. package/dist/chunk-BFEBFGCS.js +250 -0
  16. package/dist/{chunk-STPZQR5B.js → chunk-CMGRV36E.js} +1 -1
  17. package/dist/{chunk-PGQGP4FD.js → chunk-FZ6IBUKY.js} +36 -218
  18. package/dist/{chunk-7AHAABKN.js → chunk-FZYYEMET.js} +36 -228
  19. package/dist/{chunk-54RSAMBH.js → chunk-LCU6GBZP.js} +2 -2
  20. package/dist/chunk-MHPINQKY.js +260 -0
  21. package/dist/chunk-PJHFNFXA.js +243 -0
  22. package/dist/{chunk-CXFW5LIH.js → chunk-QFBBUFD4.js} +38 -3
  23. package/dist/{chunk-RPX6VDW7.js → chunk-QSEF2YVQ.js} +1 -1
  24. package/dist/{chunk-LJHC62LZ.js → chunk-TNDUTGDV.js} +2 -2
  25. package/dist/{chunk-27GGXX27.js → chunk-TZNJKZ2A.js} +82 -66
  26. package/dist/{chunk-NIVF5NDN.js → chunk-X2TFUFIS.js} +4 -4
  27. package/dist/{chunk-ISV5IFH3.js → chunk-X743YN5Y.js} +38 -3
  28. package/dist/{coordinator-prompt-TY5FHAXC.js → coordinator-prompt-2B2JA2IE.js} +3 -3
  29. package/dist/{coordinator-prompt-BH4EHFOO.js → coordinator-prompt-U4PEZDAW.js} +3 -3
  30. package/dist/{global-workspace-NLLAPQJI.js → global-workspace-JPJ3FKKY.js} +3 -3
  31. package/dist/{global-workspace-5AZEEQRU.js → global-workspace-PU7ZS3LS.js} +3 -3
  32. package/dist/index.cjs +912 -142
  33. package/dist/index.d.cts +61 -9
  34. package/dist/index.d.ts +61 -9
  35. package/dist/index.js +63 -18
  36. package/dist/mcp/run-stdio.cjs +843 -114
  37. package/dist/mcp/run-stdio.js +22 -20
  38. package/dist/{orchestrator-JNSQDRZI.js → orchestrator-3A6KUTNI.js} +5 -5
  39. package/dist/{orchestrator-NCYKEI3E.js → orchestrator-Q33M24ZJ.js} +6 -6
  40. package/dist/{workspaces-RP76JH3J.js → workspaces-IMG7ZRUQ.js} +3 -3
  41. package/dist/{workspaces-PEWYWVHZ.js → workspaces-U6P6DB44.js} +3 -3
  42. package/dist/{worktree-ZQEUKSNE.js → worktree-FL3UIUKQ.js} +2 -2
  43. package/dist/{worktree-72TZWUSH.js → worktree-JSCDJPBU.js} +2 -2
  44. package/package.json +1 -1
@@ -1,200 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import {
4
- httpFetch
5
- } from "./chunk-VKQGAWHY.js";
4
+ textFromAbleTimeDoc
5
+ } from "./chunk-6VEIKW5C.js";
6
+ import {
7
+ assertAbleTimeCredential,
8
+ callAbleTimeTool,
9
+ normalizeAbleTimeHost,
10
+ rewriteAbleTimeError
11
+ } from "./chunk-PJHFNFXA.js";
6
12
  import {
7
- getAbleTimeAccessToken,
8
- getAbleTimeHost,
9
13
  isAbleTimeConnected,
10
14
  saveAbleTimeConnection
11
- } from "./chunk-ISV5IFH3.js";
12
-
13
- // src/integrations/abletime-mcp.ts
14
- var DEFAULT_ABLETIME_HOST = "https://track.abletime.com";
15
- var ABLETIME_MCP_PATH = "/api/public/v2/mcp";
16
- var ABLETIME_MCP_PM_PATH = "/api/public/v2/mcp/pm";
17
- var MCP_PROTOCOL_VERSION = "2025-03-26";
18
- var ABLETIME_PM_TOOL_NAMES = [
19
- "set_task_assignee",
20
- "set_task_priority",
21
- "set_task_stage",
22
- "set_task_dependency",
23
- "set_task_blocked",
24
- "set_task_locked",
25
- "set_task_schedule",
26
- "clear_task_schedule",
27
- "archive_task",
28
- "delete_task"
29
- ];
30
- function abletimeToolUsesPm(name) {
31
- return ABLETIME_PM_TOOL_NAMES.includes(name);
32
- }
33
- function normalizeAbleTimeHost(raw) {
34
- const trimmed = raw?.trim() || DEFAULT_ABLETIME_HOST;
35
- const withScheme = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
36
- return withScheme.replace(/\/+$/, "");
37
- }
38
- function abletimeMcpUrl(host, opts) {
39
- const path = opts?.pm ? ABLETIME_MCP_PM_PATH : ABLETIME_MCP_PATH;
40
- return `${normalizeAbleTimeHost(host)}${path}`;
41
- }
42
- function rewriteAbleTimeError(message) {
43
- if (/INTEGRATION_AGENT_ACCESS_DISABLED|agent access/i.test(message)) {
44
- return `${message} \u2014 Enable Agent access (MCP) in AbleTime Settings \u2192 Integrations \u2192 API Keys.`;
45
- }
46
- if (/INTEGRATION_PAT_REQUIRED|organization api key/i.test(message)) {
47
- return `${message} \u2014 AbleTime MCP needs a personal access token (apt_\u2026), not an organization API key.`;
48
- }
49
- if (/INTEGRATION_PLAN_REQUIRED/i.test(message)) {
50
- return `${message} \u2014 AbleTime plan does not include API access.`;
51
- }
52
- if (/INTEGRATION_KEY_INVALID|INTEGRATION_KEY_MISSING|401|unauthorized|invalid token/i.test(message)) {
53
- return `${message} \u2014 Reconnect AbleTime from Account settings (Profile \u2192 API Access).`;
54
- }
55
- return message;
56
- }
57
- function asRecord(value) {
58
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
59
- }
60
- function parseSseJson(body) {
61
- const blocks = body.split(/\n\n+/);
62
- let last;
63
- for (const block of blocks) {
64
- const data = block.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter((line) => line && line !== "[DONE]").join("\n");
65
- if (!data) continue;
66
- try {
67
- last = JSON.parse(data);
68
- } catch {
69
- }
70
- }
71
- if (last !== void 0) return last;
72
- try {
73
- return JSON.parse(body);
74
- } catch {
75
- throw new Error(`AbleTime MCP returned a non-JSON response: ${body.slice(0, 200)}`);
76
- }
77
- }
78
- function unwrapToolResult(result) {
79
- const record = asRecord(result);
80
- if (!record) return result;
81
- const content = record.content;
82
- if (Array.isArray(content)) {
83
- const texts = content.map((part) => {
84
- const item = asRecord(part);
85
- if (!item) return "";
86
- return typeof item.text === "string" ? item.text : "";
87
- }).filter(Boolean);
88
- if (texts.length === 1) {
89
- const text = texts[0];
90
- try {
91
- return JSON.parse(text);
92
- } catch {
93
- return text;
94
- }
95
- }
96
- if (texts.length > 1) return texts.join("\n");
97
- }
98
- if (record.structuredContent != null) return record.structuredContent;
99
- if (record.isError === true) {
100
- const message = typeof record.message === "string" ? record.message : textsFromUnknown(result) || "AbleTime tool failed";
101
- throw new Error(message);
102
- }
103
- return result;
104
- }
105
- function textsFromUnknown(value) {
106
- const record = asRecord(value);
107
- if (!record) return "";
108
- if (typeof record.message === "string") return record.message;
109
- if (typeof record.error === "string") return record.error;
110
- return "";
111
- }
112
- async function abletimeMcpRequest(method, params, opts) {
113
- const token = (opts?.token ?? getAbleTimeAccessToken())?.trim();
114
- if (!token) {
115
- throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
116
- }
117
- const url = abletimeMcpUrl(
118
- opts?.host ?? (opts?.token ? DEFAULT_ABLETIME_HOST : getAbleTimeHost()),
119
- { pm: opts?.pm }
120
- );
121
- const res = await httpFetch(url, {
122
- method: "POST",
123
- headers: {
124
- "Content-Type": "application/json",
125
- Accept: "application/json, text/event-stream",
126
- Authorization: `Bearer ${token}`,
127
- "MCP-Protocol-Version": MCP_PROTOCOL_VERSION
128
- },
129
- body: JSON.stringify({
130
- jsonrpc: "2.0",
131
- id: 1,
132
- method,
133
- ...params === void 0 ? {} : { params }
134
- })
135
- });
136
- const body = await res.text().catch(() => "");
137
- if (!res.ok) {
138
- throw new Error(
139
- rewriteAbleTimeError(
140
- `AbleTime MCP error ${res.status}${body ? `: ${body.slice(0, 240)}` : ""}`
141
- )
142
- );
143
- }
144
- const contentType = res.headers.get("content-type") ?? "";
145
- const parsed = contentType.includes("text/event-stream") ? parseSseJson(body) : (() => {
146
- try {
147
- return JSON.parse(body);
148
- } catch {
149
- return parseSseJson(body);
150
- }
151
- })();
152
- const rpc = asRecord(parsed);
153
- if (rpc?.error) {
154
- const detail = typeof rpc.error.message === "string" && rpc.error.message.trim() ? rpc.error.message : `AbleTime MCP error ${rpc.error.code ?? ""}`.trim();
155
- throw new Error(rewriteAbleTimeError(detail));
156
- }
157
- if (rpc && "result" in rpc) return rpc.result;
158
- return parsed;
159
- }
160
- async function initializeIfNeeded(opts) {
161
- try {
162
- await abletimeMcpRequest(
163
- "initialize",
164
- {
165
- protocolVersion: MCP_PROTOCOL_VERSION,
166
- capabilities: {},
167
- clientInfo: { name: "sideboard", version: "1.0.0" }
168
- },
169
- opts
170
- );
171
- } catch (err) {
172
- const message = err instanceof Error ? err.message : String(err);
173
- if (/already initialized|not (required|supported)|method not found|-32601/i.test(message)) {
174
- return;
175
- }
176
- throw err;
177
- }
178
- }
179
- async function callAbleTimeTool(name, args = {}, opts) {
180
- if (!opts?.token && !isAbleTimeConnected()) {
181
- throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
182
- }
183
- const requestOpts = { ...opts, pm: opts?.pm ?? abletimeToolUsesPm(name) };
184
- const call = () => abletimeMcpRequest("tools/call", { name, arguments: args }, requestOpts).then((result) => {
185
- return unwrapToolResult(result);
186
- });
187
- try {
188
- return await call();
189
- } catch (err) {
190
- const message = err instanceof Error ? err.message : String(err);
191
- if (/initialize|session|not initialized|-32000/i.test(message)) {
192
- await initializeIfNeeded(requestOpts);
193
- return await call();
194
- }
195
- throw err instanceof Error ? new Error(rewriteAbleTimeError(err.message)) : err;
196
- }
197
- }
15
+ } from "./chunk-X743YN5Y.js";
198
16
 
199
17
  // src/integrations/abletime.ts
200
18
  var CLOSED_STATES = /* @__PURE__ */ new Set([
@@ -205,7 +23,7 @@ var CLOSED_STATES = /* @__PURE__ */ new Set([
205
23
  "archived",
206
24
  "closed"
207
25
  ]);
208
- function asRecord2(value) {
26
+ function asRecord(value) {
209
27
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
210
28
  }
211
29
  function asString(value) {
@@ -222,14 +40,14 @@ function firstString(record, keys) {
222
40
  function firstRecord(record, keys) {
223
41
  if (!record) return null;
224
42
  for (const key of keys) {
225
- const value = asRecord2(record[key]);
43
+ const value = asRecord(record[key]);
226
44
  if (value) return value;
227
45
  }
228
46
  return null;
229
47
  }
230
48
  function asList(value) {
231
49
  if (Array.isArray(value)) return value;
232
- const record = asRecord2(value);
50
+ const record = asRecord(value);
233
51
  if (!record) return [];
234
52
  for (const key of ["data", "tasks", "projects", "items", "results", "nodes"]) {
235
53
  if (Array.isArray(record[key])) return record[key];
@@ -241,7 +59,7 @@ function labelsOf(record) {
241
59
  if (!Array.isArray(raw)) return [];
242
60
  return raw.map((item) => {
243
61
  if (typeof item === "string") return item.trim();
244
- const rec = asRecord2(item);
62
+ const rec = asRecord(item);
245
63
  return rec ? firstString(rec, ["name", "title", "label"]) : "";
246
64
  }).filter(Boolean);
247
65
  }
@@ -249,13 +67,13 @@ function commentsOf(record) {
249
67
  const raw = record.comments ?? record.notes ?? record.discussion;
250
68
  const out = [];
251
69
  for (const item of asList(raw)) {
252
- const rec = asRecord2(item);
70
+ const rec = asRecord(item);
253
71
  if (!rec) continue;
254
- const body = firstString(rec, ["body", "text", "comment", "content", "message"]);
72
+ const body = firstString(rec, ["body", "text", "comment", "message", "contentSanitized"]) || textFromAbleTimeDoc(rec.content);
255
73
  if (!body) continue;
256
- const user = firstString(asRecord2(rec.user) ?? asRecord2(rec.author), ["name", "display_name"]) || firstString(rec, ["user_name", "author"]);
74
+ const user = firstString(asRecord(rec.user) ?? asRecord(rec.author), ["name", "display_name", "username"]) || firstString(rec, ["user_name", "author", "username"]);
257
75
  const comment = { body };
258
- const id = firstString(rec, ["id", "comment_id"]);
76
+ const id = firstString(rec, ["id", "comment_id", "commentId"]);
259
77
  if (id) comment.id = id;
260
78
  const url = firstString(rec, ["url", "permalink"]);
261
79
  if (url) comment.url = url;
@@ -279,11 +97,11 @@ function taskUrl(task, host) {
279
97
  return `${base}/tasks/${slug}`;
280
98
  }
281
99
  function mapAbleTimeTask(raw, host) {
282
- const record = asRecord2(raw);
100
+ const record = asRecord(raw);
283
101
  if (!record) return null;
284
102
  const nested = firstRecord(record, ["task", "data"]) ?? record;
285
- const id = firstString(nested, ["id", "task_id", "taskId"]);
286
- const identifier = firstString(nested, ["reference", "ref", "identifier", "key", "code", "number"]) || id;
103
+ const id = firstString(nested, ["id", "task_id", "taskId", "timeflowTaskId"]);
104
+ const identifier = firstString(nested, ["reference", "ref", "identifier", "key", "code", "number", "taskRef"]) || id;
287
105
  const title = firstString(nested, ["title", "name"]);
288
106
  if (!id && !identifier && !title) return null;
289
107
  const resolvedId = id || identifier;
@@ -294,21 +112,22 @@ function mapAbleTimeTask(raw, host) {
294
112
  identifier: resolvedIdentifier,
295
113
  title: title || resolvedIdentifier,
296
114
  url,
297
- description: firstString(nested, ["description", "body", "details"]) || void 0,
298
- state: firstString(nested, ["state", "board_state", "boardState", "status"]) || void 0,
299
- projectId: firstString(nested, ["project_id", "projectId"]) || firstString(asRecord2(nested.project), ["id"]) || void 0,
300
- categoryId: firstString(nested, ["category_id", "categoryId"]) || firstString(asRecord2(nested.category), ["id"]) || void 0,
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,
301
119
  assignee: assigneeOf(nested),
302
120
  labels: labelsOf(nested),
303
121
  comments: commentsOf(nested),
304
- createdAt: firstString(nested, ["created_at", "createdAt", "created"]) || void 0,
122
+ createdAt: firstString(nested, ["created_at", "createdAt", "created", "dateCreated"]) || void 0,
305
123
  updatedAt: firstString(nested, [
306
124
  "updated_at",
307
125
  "updatedAt",
308
126
  "modified_at",
309
127
  "modifiedAt",
310
128
  "last_activity_at",
311
- "lastActivityAt"
129
+ "lastActivityAt",
130
+ "lastUpdate"
312
131
  ]) || void 0
313
132
  };
314
133
  }
@@ -339,16 +158,16 @@ function issueAttachmentForAbleTimeTask(task) {
339
158
  };
340
159
  }
341
160
  function mapProject(raw) {
342
- const record = asRecord2(raw);
161
+ const record = asRecord(raw);
343
162
  if (!record) return null;
344
- const id = firstString(record, ["id", "project_id"]);
345
- const name = firstString(record, ["name", "title"]);
163
+ const id = firstString(record, ["id", "project_id", "projectId"]);
164
+ const name = firstString(record, ["name", "title", "projectName"]);
346
165
  if (!id && !name) return null;
347
166
  const categories = asList(record.categories ?? record.category).map((item) => {
348
- const rec = asRecord2(item);
167
+ const rec = asRecord(item);
349
168
  if (!rec) return null;
350
- const categoryId = firstString(rec, ["id", "category_id"]);
351
- const categoryName = firstString(rec, ["name", "title"]);
169
+ const categoryId = firstString(rec, ["id", "category_id", "projectCategoryId", "categoryId"]);
170
+ const categoryName = firstString(rec, ["name", "title", "categoryName"]);
352
171
  if (!categoryId && !categoryName) return null;
353
172
  return { id: categoryId || categoryName, name: categoryName || categoryId };
354
173
  }).filter((item) => Boolean(item));
@@ -360,7 +179,7 @@ function isOpenTask(task) {
360
179
  }
361
180
  async function getAbleTimeOrientation(opts) {
362
181
  const raw = await callAbleTimeTool("orientation", {}, opts);
363
- const record = asRecord2(raw);
182
+ const record = asRecord(raw);
364
183
  const viewerRec = firstRecord(record, ["viewer", "user", "actor", "me", "person"]) ?? record;
365
184
  const viewer = {
366
185
  id: firstString(viewerRec, ["id", "user_id"]) || void 0,
@@ -439,7 +258,7 @@ async function commentAbleTimeTask(input, opts) {
439
258
  { id, task_id: id, task: id, body, comment: body, text: body },
440
259
  opts
441
260
  );
442
- const rec = asRecord2(raw);
261
+ const rec = asRecord(raw);
443
262
  return {
444
263
  id: rec ? firstString(rec, ["id", "comment_id"]) || void 0 : void 0,
445
264
  body: rec ? firstString(rec, ["body", "text", "comment"]) || body : body
@@ -629,8 +448,7 @@ async function listAbleTimeAssignedIssues(opts) {
629
448
  };
630
449
  }
631
450
  async function verifyAbleTimeConnection(input) {
632
- const token = input.token.trim();
633
- if (!token) throw new Error("AbleTime personal access token is required");
451
+ const token = assertAbleTimeCredential(input.token);
634
452
  const host = input.host?.trim() || void 0;
635
453
  const orientation = await getAbleTimeOrientation({ token, host });
636
454
  saveAbleTimeConnection({