@sideboard-ai/core 0.1.188 → 0.1.190

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.
@@ -12,7 +12,7 @@ import {
12
12
  ensureCursorRipgrepPath,
13
13
  fetchCursorTurnCostUsd,
14
14
  formatUnknownDetail
15
- } from "../chunk-ZSFQLR7Y.js";
15
+ } from "../chunk-FY64F2ZQ.js";
16
16
  import {
17
17
  dropNestedElectronEnvFromProcess
18
18
  } from "../chunk-4TR3HZFT.js";
@@ -38,7 +38,7 @@ import {
38
38
  resolveQuotaFallbackAgent,
39
39
  turnCostUsdFromCursorUsage,
40
40
  whichOnPath
41
- } from "./chunk-QU663NPO.js";
41
+ } from "./chunk-GBWKMWUQ.js";
42
42
  import "./chunk-HVIEYTUK.js";
43
43
  import "./chunk-Y4MIXGPA.js";
44
44
  import "./chunk-VKQGAWHY.js";
@@ -32,7 +32,7 @@ import {
32
32
  resolveLoginCommand,
33
33
  resolveQuotaFallbackAgent,
34
34
  whichOnPath
35
- } from "./chunk-ISOCLQEX.js";
35
+ } from "./chunk-OLDZXO53.js";
36
36
  import "./chunk-VIODP5PT.js";
37
37
  import "./chunk-WXKXSZN4.js";
38
38
  import "./chunk-6K64FJDD.js";
@@ -44,7 +44,7 @@ import {
44
44
  parseCursorRunnerLine,
45
45
  preferredCursorCostCents,
46
46
  turnCostUsdFromCursorUsage
47
- } from "./chunk-ZSFQLR7Y.js";
47
+ } from "./chunk-FY64F2ZQ.js";
48
48
  import {
49
49
  ORCHESTRATOR_AGENT_KINDS,
50
50
  assertOrchestratorCapableAgent,
@@ -86,13 +86,21 @@ function looksLikeHugeToolResultDump(text) {
86
86
  if (t.length < 4e3) return false;
87
87
  return looksLikeMinifiedJsDump(t);
88
88
  }
89
+ function looksLikeJobWaitResult(rec) {
90
+ if (typeof rec.delta === "string") {
91
+ return typeof rec.status === "string" || typeof rec.id === "string" || typeof rec.stillRunning === "boolean";
92
+ }
93
+ if (typeof rec.stopped === "boolean") {
94
+ return typeof rec.id === "string" || typeof rec.status === "string";
95
+ }
96
+ return rec.started === true || rec.reason === "already-running";
97
+ }
89
98
  function clipJobWaitResultJson(content) {
90
99
  const trimmed = content.trim();
91
100
  if (!trimmed.startsWith("{")) return void 0;
92
101
  try {
93
102
  const rec = JSON.parse(trimmed);
94
- const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
95
- if (!isJob) return void 0;
103
+ if (!looksLikeJobWaitResult(rec)) return void 0;
96
104
  if (typeof rec.delta === "string" && rec.delta.length > 3500) {
97
105
  rec.delta = `\u2026(truncated ${rec.delta.length} chars)
98
106
  ${rec.delta.slice(-3500)}`;
@@ -150,7 +158,7 @@ function looksLikeHomebrewLibuvCrash(text) {
150
158
  return /Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(text);
151
159
  }
152
160
  var NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
153
- var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
161
+ var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 24 LTS (`brew install node@24`) and retry.";
154
162
  var BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
155
163
  var V8_OOM_SUMMARY = "Agent ran out of memory (JavaScript heap). If it keeps happening, exclude large files from the project folder.";
156
164
  var MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
@@ -265,7 +273,7 @@ function humanizeAgentFailDetail(detail) {
265
273
  return /ran out of memory/i.test(raw) ? raw : V8_OOM_SUMMARY;
266
274
  }
267
275
  if (/homebrew node \+ shared libuv|Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(raw)) {
268
- return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
276
+ return /brew install node@(?:22|24)/i.test(raw) ? raw : `${raw} \u2014 install Node 24 LTS (\`brew install node@24\`) and retry.`;
269
277
  }
270
278
  if (/uv_run|spineventloopinternal|uv__io_poll|cursor runner crashed in node/i.test(lower)) {
271
279
  return /retry the turn/i.test(raw) ? raw : BUNDLED_NODE_CRASH_SUMMARY;
@@ -549,7 +557,7 @@ function unpackedAsarPath(filePath) {
549
557
  function nodeReadableScriptPath(scriptPath) {
550
558
  return unpackedAsarPath(scriptPath) ?? scriptPath;
551
559
  }
552
- var PREFERRED_LTS_MAJORS = [24, 22, 20];
560
+ var PREFERRED_LTS_MAJORS = [24, 22];
553
561
  function parseNodeMajor(version) {
554
562
  const match = /^v?(\d+)/.exec(version.trim());
555
563
  if (!match) return null;
@@ -559,7 +567,7 @@ function parseNodeMajor(version) {
559
567
  function scoreNodeForAgentRuntime(candidate) {
560
568
  const major = parseNodeMajor(candidate.version);
561
569
  if (major == null) return Number.NEGATIVE_INFINITY;
562
- if (major < 20) return major - 100;
570
+ if (major < 22) return major - 100;
563
571
  const posix = candidate.path.replace(/\\/g, "/");
564
572
  let score = 0;
565
573
  if (major % 2 === 0) {
@@ -229,13 +229,21 @@ function looksLikeHugeToolResultDump(text) {
229
229
  if (t.length < 4e3) return false;
230
230
  return looksLikeMinifiedJsDump(t);
231
231
  }
232
+ function looksLikeJobWaitResult(rec) {
233
+ if (typeof rec.delta === "string") {
234
+ return typeof rec.status === "string" || typeof rec.id === "string" || typeof rec.stillRunning === "boolean";
235
+ }
236
+ if (typeof rec.stopped === "boolean") {
237
+ return typeof rec.id === "string" || typeof rec.status === "string";
238
+ }
239
+ return rec.started === true || rec.reason === "already-running";
240
+ }
232
241
  function clipJobWaitResultJson(content) {
233
242
  const trimmed = content.trim();
234
243
  if (!trimmed.startsWith("{")) return void 0;
235
244
  try {
236
245
  const rec = JSON.parse(trimmed);
237
- const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
238
- if (!isJob) return void 0;
246
+ if (!looksLikeJobWaitResult(rec)) return void 0;
239
247
  if (typeof rec.delta === "string" && rec.delta.length > 3500) {
240
248
  rec.delta = `\u2026(truncated ${rec.delta.length} chars)
241
249
  ${rec.delta.slice(-3500)}`;
@@ -293,7 +301,7 @@ function looksLikeHomebrewLibuvCrash(text) {
293
301
  return /Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(text);
294
302
  }
295
303
  var NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
296
- var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
304
+ var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 24 LTS (`brew install node@24`) and retry.";
297
305
  var BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
298
306
  var V8_OOM_SUMMARY = "Agent ran out of memory (JavaScript heap). If it keeps happening, exclude large files from the project folder.";
299
307
  var MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
@@ -408,7 +416,7 @@ function humanizeAgentFailDetail(detail) {
408
416
  return /ran out of memory/i.test(raw) ? raw : V8_OOM_SUMMARY;
409
417
  }
410
418
  if (/homebrew node \+ shared libuv|Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(raw)) {
411
- return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
419
+ return /brew install node@(?:22|24)/i.test(raw) ? raw : `${raw} \u2014 install Node 24 LTS (\`brew install node@24\`) and retry.`;
412
420
  }
413
421
  if (/uv_run|spineventloopinternal|uv__io_poll|cursor runner crashed in node/i.test(lower)) {
414
422
  return /retry the turn/i.test(raw) ? raw : BUNDLED_NODE_CRASH_SUMMARY;
@@ -1533,7 +1541,7 @@ function unpackedAsarPath(filePath) {
1533
1541
  function nodeReadableScriptPath(scriptPath) {
1534
1542
  return unpackedAsarPath(scriptPath) ?? scriptPath;
1535
1543
  }
1536
- var PREFERRED_LTS_MAJORS = [24, 22, 20];
1544
+ var PREFERRED_LTS_MAJORS = [24, 22];
1537
1545
  function parseNodeMajor(version) {
1538
1546
  const match = /^v?(\d+)/.exec(version.trim());
1539
1547
  if (!match) return null;
@@ -1543,7 +1551,7 @@ function parseNodeMajor(version) {
1543
1551
  function scoreNodeForAgentRuntime(candidate) {
1544
1552
  const major = parseNodeMajor(candidate.version);
1545
1553
  if (major == null) return Number.NEGATIVE_INFINITY;
1546
- if (major < 20) return major - 100;
1554
+ if (major < 22) return major - 100;
1547
1555
  const posix = candidate.path.replace(/\\/g, "/");
1548
1556
  let score = 0;
1549
1557
  if (major % 2 === 0) {
@@ -33,7 +33,7 @@ import {
33
33
  summarizeTurnStderr,
34
34
  toolDescription,
35
35
  turnFailChatText
36
- } from "./chunk-QU663NPO.js";
36
+ } from "./chunk-GBWKMWUQ.js";
37
37
  import {
38
38
  extractPresentedPlan,
39
39
  readPlanFile,
@@ -402,7 +402,7 @@ async function continueSourceThread(threadId, prompt) {
402
402
  await continueOnReply(threadId, prompt);
403
403
  return;
404
404
  }
405
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-7A66YINC.js");
405
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-BHJELEFM.js");
406
406
  await getOrchestrator2().send(threadId, prompt);
407
407
  } catch {
408
408
  }
@@ -5972,7 +5972,7 @@ function formatIssueToolsDirective(opts) {
5972
5972
  ];
5973
5973
  if (opts.linear) {
5974
5974
  lines.push(
5975
- "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
5975
+ "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state, cycle), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
5976
5976
  );
5977
5977
  }
5978
5978
  if (github) {
@@ -6458,7 +6458,7 @@ function formatScheduledPrompt(name, prompt) {
6458
6458
  ${prompt}`;
6459
6459
  }
6460
6460
  async function defaultDeps() {
6461
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-7A66YINC.js");
6461
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-BHJELEFM.js");
6462
6462
  const orch = getOrchestrator2();
6463
6463
  return {
6464
6464
  findThread: (id) => findThreadByRef(id),
@@ -29,7 +29,7 @@ import {
29
29
  packagedMcpStdioPath,
30
30
  parseCursorRunnerLine,
31
31
  resolveNodeLaunch
32
- } from "./chunk-ZSFQLR7Y.js";
32
+ } from "./chunk-FY64F2ZQ.js";
33
33
  import {
34
34
  claudeChromeEnabled,
35
35
  isAbleTimeConnected,
@@ -24,7 +24,7 @@ import {
24
24
  stripBrightsyNdjsonNoise,
25
25
  sumUsageList,
26
26
  toolDescription
27
- } from "./chunk-ISOCLQEX.js";
27
+ } from "./chunk-OLDZXO53.js";
28
28
  import {
29
29
  SLACK_REPLY_FORMATTING,
30
30
  addWorkspace,
@@ -124,7 +124,7 @@ import {
124
124
  shouldRetryFailedAgentTurn,
125
125
  summarizeTurnStderr,
126
126
  turnFailChatText
127
- } from "./chunk-ZSFQLR7Y.js";
127
+ } from "./chunk-FY64F2ZQ.js";
128
128
  import {
129
129
  assertOrchestratorCapableAgent,
130
130
  childEnvWithAppSettings,
@@ -467,7 +467,7 @@ async function continueSourceThread(threadId, prompt) {
467
467
  await continueOnReply(threadId, prompt);
468
468
  return;
469
469
  }
470
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-ZMXSPFSF.js");
470
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-HWNGCDGW.js");
471
471
  await getOrchestrator2().send(threadId, prompt);
472
472
  } catch {
473
473
  }
@@ -3874,7 +3874,7 @@ async function createThread(input, _onSetupLine) {
3874
3874
  return readThread(thread.id) ?? thread;
3875
3875
  }
3876
3876
  async function listLinearIssues(agent, repoPath) {
3877
- const { getAdapter: getAdapter2 } = await import("./agents-XPWKGOVT.js");
3877
+ const { getAdapter: getAdapter2 } = await import("./agents-DTPVTDB5.js");
3878
3878
  await requireAgent(agent, { requireLinear: true });
3879
3879
  const adapter = getAdapter2(agent);
3880
3880
  if (!adapter.listLinearIssues) {
@@ -6130,7 +6130,7 @@ function formatIssueToolsDirective(opts) {
6130
6130
  ];
6131
6131
  if (opts.linear) {
6132
6132
  lines.push(
6133
- "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
6133
+ "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state, cycle), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
6134
6134
  );
6135
6135
  }
6136
6136
  if (github) {
@@ -6805,7 +6805,7 @@ function formatScheduledPrompt(name, prompt) {
6805
6805
  ${prompt}`;
6806
6806
  }
6807
6807
  async function defaultDeps() {
6808
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ZMXSPFSF.js");
6808
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-HWNGCDGW.js");
6809
6809
  const orch = getOrchestrator2();
6810
6810
  return {
6811
6811
  findThread: (id) => findThreadByRef(id),
package/dist/index.cjs CHANGED
@@ -8687,13 +8687,21 @@ function looksLikeHugeToolResultDump(text7) {
8687
8687
  if (t.length < 4e3) return false;
8688
8688
  return looksLikeMinifiedJsDump(t);
8689
8689
  }
8690
+ function looksLikeJobWaitResult(rec) {
8691
+ if (typeof rec.delta === "string") {
8692
+ return typeof rec.status === "string" || typeof rec.id === "string" || typeof rec.stillRunning === "boolean";
8693
+ }
8694
+ if (typeof rec.stopped === "boolean") {
8695
+ return typeof rec.id === "string" || typeof rec.status === "string";
8696
+ }
8697
+ return rec.started === true || rec.reason === "already-running";
8698
+ }
8690
8699
  function clipJobWaitResultJson(content) {
8691
8700
  const trimmed = content.trim();
8692
8701
  if (!trimmed.startsWith("{")) return void 0;
8693
8702
  try {
8694
8703
  const rec = JSON.parse(trimmed);
8695
- const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
8696
- if (!isJob) return void 0;
8704
+ if (!looksLikeJobWaitResult(rec)) return void 0;
8697
8705
  if (typeof rec.delta === "string" && rec.delta.length > 3500) {
8698
8706
  rec.delta = `\u2026(truncated ${rec.delta.length} chars)
8699
8707
  ${rec.delta.slice(-3500)}`;
@@ -8859,7 +8867,7 @@ function humanizeAgentFailDetail(detail) {
8859
8867
  return /ran out of memory/i.test(raw) ? raw : V8_OOM_SUMMARY;
8860
8868
  }
8861
8869
  if (/homebrew node \+ shared libuv|Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(raw)) {
8862
- return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
8870
+ return /brew install node@(?:22|24)/i.test(raw) ? raw : `${raw} \u2014 install Node 24 LTS (\`brew install node@24\`) and retry.`;
8863
8871
  }
8864
8872
  if (/uv_run|spineventloopinternal|uv__io_poll|cursor runner crashed in node/i.test(lower)) {
8865
8873
  return /retry the turn/i.test(raw) ? raw : BUNDLED_NODE_CRASH_SUMMARY;
@@ -8937,7 +8945,7 @@ var init_error_detail = __esm({
8937
8945
  "use strict";
8938
8946
  NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
8939
8947
  NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
8940
- HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
8948
+ HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 24 LTS (`brew install node@24`) and retry.";
8941
8949
  BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
8942
8950
  V8_OOM_SUMMARY = "Agent ran out of memory (JavaScript heap). If it keeps happening, exclude large files from the project folder.";
8943
8951
  MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
@@ -10807,7 +10815,7 @@ function parseNodeMajor(version) {
10807
10815
  function scoreNodeForAgentRuntime(candidate) {
10808
10816
  const major = parseNodeMajor(candidate.version);
10809
10817
  if (major == null) return Number.NEGATIVE_INFINITY;
10810
- if (major < 20) return major - 100;
10818
+ if (major < 22) return major - 100;
10811
10819
  const posix = candidate.path.replace(/\\/g, "/");
10812
10820
  let score = 0;
10813
10821
  if (major % 2 === 0) {
@@ -10968,7 +10976,7 @@ var init_node_launch = __esm({
10968
10976
  init_packaged_runtime();
10969
10977
  AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
10970
10978
  MAX_OLD_SPACE_FLAG = /(?:^|\s)(--max[-_]old[-_]space[-_]size)(?:[= ](\d+))?(?=\s|$)/;
10971
- PREFERRED_LTS_MAJORS = [24, 22, 20];
10979
+ PREFERRED_LTS_MAJORS = [24, 22];
10972
10980
  }
10973
10981
  });
10974
10982
 
@@ -20023,7 +20031,7 @@ function formatIssueToolsDirective(opts) {
20023
20031
  ];
20024
20032
  if (opts.linear) {
20025
20033
  lines.push(
20026
- "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
20034
+ "- Linear: `linear_search_issues` (assignee=me; pass `updatedSince` for \u201Cany updates since yesterday?\u201D \u2014 new tickets, edits, and comments), `linear_get_issue` (comments; pass `include=full` if crush.truncated), `linear_comment`, `linear_update_issue` (state, cycle), `linear_create_issue` (pass `parent` for spin-offs; call `linear_list_teams` first). Scope errors: reconnect Linear in Settings \u2192 Issues."
20027
20035
  );
20028
20036
  }
20029
20037
  if (github) {
@@ -23595,6 +23603,7 @@ __export(index_exports, {
23595
23603
  listLinearIssues: () => listLinearIssues,
23596
23604
  listLinearIssuesDirect: () => listLinearIssuesDirect,
23597
23605
  listLinearIssuesFiltered: () => listLinearIssuesFiltered,
23606
+ listLinearTeamCycles: () => listLinearTeamCycles,
23598
23607
  listLinearTeams: () => listLinearTeams,
23599
23608
  listModelsForAgent: () => listModelsForAgent,
23600
23609
  listOpencodeModels: () => listOpencodeModels,
@@ -23731,6 +23740,7 @@ __export(index_exports, {
23731
23740
  resolveGitHubIssueRepo: () => resolveGitHubIssueRepo,
23732
23741
  resolveGithubAgentToken: () => resolveGithubAgentToken,
23733
23742
  resolveGithubRepoSlug: () => resolveGithubRepoSlug,
23743
+ resolveLinearCycle: () => resolveLinearCycle,
23734
23744
  resolveLinearState: () => resolveLinearState,
23735
23745
  resolveLinearTeam: () => resolveLinearTeam,
23736
23746
  resolveLoginCommand: () => resolveLoginCommand,
@@ -24316,7 +24326,7 @@ var LIST_ISSUE_FIELDS = `
24316
24326
  assignee { id name }
24317
24327
  team { id key }
24318
24328
  labels(first: 10) { nodes { name } }
24319
- cycle { name number startsAt endsAt completedAt }
24329
+ cycle { id name number startsAt endsAt completedAt }
24320
24330
  `;
24321
24331
  var ISSUE_REF_FIELDS = `
24322
24332
  id
@@ -24342,7 +24352,7 @@ var ISSUE_FIELDS = `
24342
24352
  creator { id name }
24343
24353
  team { id key name }
24344
24354
  labels(first: 50) { nodes { name } }
24345
- cycle { name number startsAt endsAt completedAt }
24355
+ cycle { id name number startsAt endsAt completedAt }
24346
24356
  project { id name }
24347
24357
  parent { ${ISSUE_REF_FIELDS} }
24348
24358
  children(first: 25) { nodes { ${ISSUE_REF_FIELDS} } }
@@ -24427,6 +24437,19 @@ query SideboardTeams {
24427
24437
  key
24428
24438
  name
24429
24439
  states(first: 50) { nodes { id name type } }
24440
+ activeCycle { id name number startsAt endsAt completedAt }
24441
+ }
24442
+ }
24443
+ }
24444
+ `;
24445
+ var TEAM_CYCLES_QUERY = `
24446
+ query SideboardTeamCycles($id: String!) {
24447
+ team(id: $id) {
24448
+ id
24449
+ key
24450
+ activeCycle { id name number startsAt endsAt completedAt }
24451
+ cycles(first: 40) {
24452
+ nodes { id name number startsAt endsAt completedAt }
24430
24453
  }
24431
24454
  }
24432
24455
  }
@@ -24519,11 +24542,26 @@ function linearCycleIsActive(cycle, now = Date.now()) {
24519
24542
  if (Number.isFinite(end) && now > end) return false;
24520
24543
  return true;
24521
24544
  }
24545
+ function cycleDisplayName(node) {
24546
+ return String(node?.name ?? (node?.number != null ? `Cycle ${node.number}` : "")).trim();
24547
+ }
24548
+ function mapNamedCycle(node) {
24549
+ if (!node?.id) return null;
24550
+ const name = cycleDisplayName(node);
24551
+ if (!name) return null;
24552
+ return {
24553
+ id: String(node.id),
24554
+ name,
24555
+ number: typeof node.number === "number" ? node.number : void 0,
24556
+ isActive: linearCycleIsActive(node)
24557
+ };
24558
+ }
24522
24559
  function mapCycle(node) {
24523
24560
  if (!node?.name && node?.number == null) return null;
24524
- const name = String(node.name ?? (node.number != null ? `Cycle ${node.number}` : "")).trim();
24561
+ const name = cycleDisplayName(node);
24525
24562
  if (!name) return null;
24526
24563
  return {
24564
+ ...node.id ? { id: String(node.id) } : {},
24527
24565
  name,
24528
24566
  number: typeof node.number === "number" ? node.number : void 0,
24529
24567
  isActive: linearCycleIsActive(node)
@@ -24662,6 +24700,10 @@ function toIssueInfo(issue) {
24662
24700
  };
24663
24701
  }
24664
24702
  function mapTeam(node) {
24703
+ const cycles = (node.cycles?.nodes ?? []).flatMap((c) => {
24704
+ const cycle = mapNamedCycle(c);
24705
+ return cycle ? [cycle] : [];
24706
+ });
24665
24707
  return {
24666
24708
  id: String(node.id ?? ""),
24667
24709
  key: String(node.key ?? ""),
@@ -24669,7 +24711,9 @@ function mapTeam(node) {
24669
24711
  states: (node.states?.nodes ?? []).flatMap((s) => {
24670
24712
  const state = mapState(s);
24671
24713
  return state ? [state] : [];
24672
- })
24714
+ }),
24715
+ activeCycle: mapNamedCycle(node.activeCycle),
24716
+ ...cycles.length ? { cycles } : {}
24673
24717
  };
24674
24718
  }
24675
24719
  function resolveLinearTeam(teams, team) {
@@ -24696,6 +24740,34 @@ function resolveLinearState(team, state) {
24696
24740
  }
24697
24741
  return found;
24698
24742
  }
24743
+ function resolveLinearCycle(team, cycle) {
24744
+ if (cycle == null) return null;
24745
+ const s = cycle.trim();
24746
+ if (!s || /^(none|clear|unschedule|null)$/i.test(s)) return null;
24747
+ if (/^(current|active|this)$/i.test(s)) {
24748
+ const active = team.activeCycle ?? team.cycles?.find((c) => c.isActive);
24749
+ if (!active?.id) {
24750
+ throw new Error(`Linear team ${team.key} has no active cycle`);
24751
+ }
24752
+ return active.id;
24753
+ }
24754
+ const lower = s.toLowerCase();
24755
+ const asNumber = Number.parseInt(s, 10);
24756
+ const seen = /* @__PURE__ */ new Set();
24757
+ const cycles = [team.activeCycle, ...team.cycles ?? []].filter(
24758
+ (c) => {
24759
+ if (!c?.id || seen.has(c.id)) return false;
24760
+ seen.add(c.id);
24761
+ return true;
24762
+ }
24763
+ );
24764
+ const found = cycles.find((c) => c.id === s) || cycles.find((c) => c.name.toLowerCase() === lower) || (Number.isInteger(asNumber) ? cycles.find((c) => c.number === asNumber) : void 0);
24765
+ if (!found) {
24766
+ const available = cycles.map((c) => c.number != null ? `${c.name} (${c.number})` : c.name).join(", ") || "(none)";
24767
+ throw new Error(`Linear cycle not found on ${team.key}: ${cycle}. Available: ${available}`);
24768
+ }
24769
+ return found.id;
24770
+ }
24699
24771
  function normalizePriority(priority) {
24700
24772
  if (priority == null) return void 0;
24701
24773
  if (!Number.isInteger(priority) || priority < 0 || priority > 4) {
@@ -24805,7 +24877,12 @@ async function listLinearCommentsSince(opts) {
24805
24877
  first,
24806
24878
  filter: {
24807
24879
  createdAt: { gte: opts.since },
24808
- issue: buildLinearIssueFilter({ assignee, query: query || void 0 })
24880
+ issue: buildLinearIssueFilter({
24881
+ assignee,
24882
+ // Search hits may match identifier/comments — do not also require
24883
+ // title/description contains when an allowlist is already applied.
24884
+ query: restrictToIssues ? void 0 : query || void 0
24885
+ })
24809
24886
  }
24810
24887
  },
24811
24888
  opts
@@ -24843,6 +24920,19 @@ async function listLinearTeams(opts) {
24843
24920
  teams: (json.teams?.nodes ?? []).map(mapTeam)
24844
24921
  };
24845
24922
  }
24923
+ async function listLinearTeamCycles(teamId, opts) {
24924
+ const json = await linearGraphql(TEAM_CYCLES_QUERY, { id: teamId }, opts);
24925
+ if (!json.team?.id) {
24926
+ throw new Error(`Linear team not found: ${teamId}`);
24927
+ }
24928
+ const mapped = mapTeam(json.team);
24929
+ return {
24930
+ id: mapped.id,
24931
+ key: mapped.key,
24932
+ activeCycle: mapped.activeCycle,
24933
+ cycles: mapped.cycles ?? []
24934
+ };
24935
+ }
24846
24936
  async function getLinearIssue(id, opts) {
24847
24937
  const issueId = id.trim();
24848
24938
  if (!issueId) throw new Error("Linear issue id is required (uuid or ENG-123)");
@@ -24898,16 +24988,28 @@ async function updateLinearIssue(input, opts) {
24898
24988
  if (input.description !== void 0) {
24899
24989
  mutationInput.description = input.description;
24900
24990
  }
24991
+ const needsTeam = Boolean(input.state?.trim()) || input.cycle !== void 0;
24992
+ const existing = needsTeam ? await getLinearIssue(issueId, opts) : void 0;
24901
24993
  if (input.state?.trim()) {
24902
- const existing = await getLinearIssue(issueId, opts);
24903
24994
  const { teams } = await listLinearTeams(opts);
24904
- const teamRef = existing.team?.key || existing.team?.id;
24995
+ const teamRef = existing?.team?.key || existing?.team?.id;
24905
24996
  const team = teamRef ? resolveLinearTeam(teams, teamRef) : void 0;
24906
24997
  if (!team?.states.length) {
24907
- throw new Error(`Linear issue ${existing.identifier} has no workflow states to resolve "${input.state}"`);
24998
+ throw new Error(`Linear issue ${existing?.identifier ?? issueId} has no workflow states to resolve "${input.state}"`);
24908
24999
  }
24909
25000
  mutationInput.stateId = resolveLinearState(team, input.state).id;
24910
25001
  }
25002
+ if (input.cycle !== void 0) {
25003
+ const teamId = existing?.team?.id;
25004
+ if (!teamId) {
25005
+ throw new Error(`Linear issue ${existing?.identifier ?? issueId} has no team to resolve a cycle`);
25006
+ }
25007
+ const cycles = await listLinearTeamCycles(teamId, opts);
25008
+ mutationInput.cycleId = resolveLinearCycle(
25009
+ { ...cycles, key: cycles.key || existing?.team?.key || teamId },
25010
+ input.cycle
25011
+ );
25012
+ }
24911
25013
  if (input.assignee !== void 0) {
24912
25014
  const assignee = input.assignee?.trim() || null;
24913
25015
  if (assignee === "me") {
@@ -24921,7 +25023,7 @@ async function updateLinearIssue(input, opts) {
24921
25023
  mutationInput.priority = normalizePriority(input.priority);
24922
25024
  }
24923
25025
  if (Object.keys(mutationInput).length === 0) {
24924
- throw new Error("linear_update_issue needs at least one of title, description, state, assignee, priority");
25026
+ throw new Error("linear_update_issue needs at least one of title, description, state, assignee, priority, cycle");
24925
25027
  }
24926
25028
  const json = await linearGraphql(ISSUE_UPDATE, { id: issueId, input: mutationInput }, opts);
24927
25029
  if (!json.issueUpdate?.success || !json.issueUpdate.issue) {
@@ -25081,7 +25183,7 @@ async function listGitHubIssueCommentsSince(opts) {
25081
25183
  }).filter((n) => n != null)
25082
25184
  );
25083
25185
  if (restrictToIssues && allowed.size === 0) return [];
25084
- const pageSize = Math.min(GITHUB_ISSUE_COMMENTS_PAGE_SIZE, Math.max(1, limit));
25186
+ const pageSize = GITHUB_ISSUE_COMMENTS_PAGE_SIZE;
25085
25187
  const out = [];
25086
25188
  for (let page = 1; page <= GITHUB_ISSUE_COMMENTS_MAX_PAGES; page++) {
25087
25189
  const path2 = `repos/${slug}/issues/comments?since=${encodeURIComponent(opts.since)}&sort=created&direction=desc&per_page=${pageSize}&page=${page}`;
@@ -27050,7 +27152,7 @@ var prioritySchema = import_zod6.z.number().int().min(0).max(4).optional().descr
27050
27152
  function registerLinearTools(server) {
27051
27153
  server.tool(
27052
27154
  "linear_list_teams",
27053
- "List Linear teams (id, key, name) and workflow states. Use team key on create; state name or type on create/update.",
27155
+ 'List Linear teams (id, key, name), workflow states, and the active cycle. Use team key on create; state name or type on create/update; cycle name/"current"/"none" on update.',
27054
27156
  {},
27055
27157
  async () => {
27056
27158
  try {
@@ -27137,14 +27239,15 @@ function registerLinearTools(server) {
27137
27239
  );
27138
27240
  server.tool(
27139
27241
  "linear_update_issue",
27140
- "Update a Linear issue (uuid or ENG-123). Pass title, description, state, assignee, and/or priority. When reviewing a PR or ticket, wait until they type a next step before changing the ticket \u2014 do not ask_user after the review. The author is notified.",
27242
+ 'Update a Linear issue (uuid or ENG-123). Pass title, description, state, assignee, priority, and/or cycle. Cycle is name, number, "current"/"active", or "none" to unschedule. When reviewing a PR or ticket, wait until they type a next step before changing the ticket \u2014 do not ask_user after the review. The author is notified.',
27141
27243
  {
27142
27244
  id: import_zod6.z.string(),
27143
27245
  title: import_zod6.z.string().optional(),
27144
27246
  description: import_zod6.z.string().optional(),
27145
27247
  state: import_zod6.z.string().optional(),
27146
27248
  assignee: import_zod6.z.string().nullable().optional(),
27147
- priority: prioritySchema
27249
+ priority: prioritySchema,
27250
+ cycle: import_zod6.z.string().nullable().optional().describe('Cycle name, number, "current"/"active", or "none" to unschedule.')
27148
27251
  },
27149
27252
  async (args) => {
27150
27253
  try {
@@ -31723,6 +31826,7 @@ init_outbound_watch();
31723
31826
  listLinearIssues,
31724
31827
  listLinearIssuesDirect,
31725
31828
  listLinearIssuesFiltered,
31829
+ listLinearTeamCycles,
31726
31830
  listLinearTeams,
31727
31831
  listModelsForAgent,
31728
31832
  listOpencodeModels,
@@ -31859,6 +31963,7 @@ init_outbound_watch();
31859
31963
  resolveGitHubIssueRepo,
31860
31964
  resolveGithubAgentToken,
31861
31965
  resolveGithubRepoSlug,
31966
+ resolveLinearCycle,
31862
31967
  resolveLinearState,
31863
31968
  resolveLinearTeam,
31864
31969
  resolveLoginCommand,