@sideboard-ai/core 0.1.184 → 0.1.186
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.
- package/dist/{chunk-IMCIHSIF.js → chunk-3QTEXR7L.js} +20 -14
- package/dist/{chunk-4IQQEJ2C.js → chunk-VTIVVVEC.js} +20 -14
- package/dist/index.cjs +110 -72
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +93 -61
- package/dist/mcp/run-stdio.cjs +110 -72
- package/dist/mcp/run-stdio.js +93 -61
- package/dist/{orchestrator-4GLAG7YH.js → orchestrator-RJEULR5I.js} +1 -1
- package/dist/{orchestrator-DKVX67MH.js → orchestrator-RNDMJXAY.js} +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2213,13 +2213,10 @@ type LinearAssignedIssuesResult = {
|
|
|
2213
2213
|
};
|
|
2214
2214
|
/** `me`, `unassigned`, `all`, a Linear user id, or a display name. */
|
|
2215
2215
|
type LinearAssigneeFilter = string;
|
|
2216
|
-
/**
|
|
2217
|
-
* Linear `IssueFilter` for open issues. Default assignee is `me` so existing
|
|
2218
|
-
* Home / Create-from callers stay assigned-to-you unless they ask otherwise.
|
|
2219
|
-
*/
|
|
2220
2216
|
declare function buildLinearIssueFilter(input?: {
|
|
2221
2217
|
assignee?: string | null;
|
|
2222
2218
|
updatedSince?: string | null;
|
|
2219
|
+
query?: string | null;
|
|
2223
2220
|
}): Record<string, unknown>;
|
|
2224
2221
|
/**
|
|
2225
2222
|
* List or search open Linear issues. `assignee` is `me` (default when there is
|
|
@@ -2234,13 +2231,16 @@ declare function listLinearIssuesFiltered(opts?: {
|
|
|
2234
2231
|
updatedSince?: string | null;
|
|
2235
2232
|
}): Promise<LinearAssignedIssuesResult>;
|
|
2236
2233
|
/**
|
|
2237
|
-
* Comments created at/after `since` on issues matching the same assignee
|
|
2238
|
-
* One GraphQL query — do not get_issue each ticket to check for new comments.
|
|
2234
|
+
* Comments created at/after `since` on issues matching the same assignee / search
|
|
2235
|
+
* filter. One GraphQL query — do not get_issue each ticket to check for new comments.
|
|
2236
|
+
* Pass `issueIdentifiers` (search hits) to keep only those tickets; an empty
|
|
2237
|
+
* allowlist means no comments.
|
|
2239
2238
|
*/
|
|
2240
2239
|
declare function listLinearCommentsSince(opts: {
|
|
2241
2240
|
since: string;
|
|
2242
2241
|
assignee?: string | null;
|
|
2243
2242
|
query?: string;
|
|
2243
|
+
issueIdentifiers?: string[];
|
|
2244
2244
|
limit?: number;
|
|
2245
2245
|
apiKey?: string | null;
|
|
2246
2246
|
}): Promise<IssueActivityComment[]>;
|
|
@@ -2364,7 +2364,8 @@ declare function resolveGitHubIssueRepo(repoPath?: string | null): Promise<{
|
|
|
2364
2364
|
declare function toGitHubIssueInfo(issue: GitHubIssue): IssueInfo;
|
|
2365
2365
|
/**
|
|
2366
2366
|
* Repo issue comments created at/after `since`. Pass `issueIdentifiers` (#12)
|
|
2367
|
-
* to keep only comments on that inbox page —
|
|
2367
|
+
* to keep only comments on that inbox page — paginated REST, not N issue views.
|
|
2368
|
+
* An empty allowlist means no comments (do not fall through to the whole repo).
|
|
2368
2369
|
*/
|
|
2369
2370
|
declare function listGitHubIssueCommentsSince(opts: {
|
|
2370
2371
|
since: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -2213,13 +2213,10 @@ type LinearAssignedIssuesResult = {
|
|
|
2213
2213
|
};
|
|
2214
2214
|
/** `me`, `unassigned`, `all`, a Linear user id, or a display name. */
|
|
2215
2215
|
type LinearAssigneeFilter = string;
|
|
2216
|
-
/**
|
|
2217
|
-
* Linear `IssueFilter` for open issues. Default assignee is `me` so existing
|
|
2218
|
-
* Home / Create-from callers stay assigned-to-you unless they ask otherwise.
|
|
2219
|
-
*/
|
|
2220
2216
|
declare function buildLinearIssueFilter(input?: {
|
|
2221
2217
|
assignee?: string | null;
|
|
2222
2218
|
updatedSince?: string | null;
|
|
2219
|
+
query?: string | null;
|
|
2223
2220
|
}): Record<string, unknown>;
|
|
2224
2221
|
/**
|
|
2225
2222
|
* List or search open Linear issues. `assignee` is `me` (default when there is
|
|
@@ -2234,13 +2231,16 @@ declare function listLinearIssuesFiltered(opts?: {
|
|
|
2234
2231
|
updatedSince?: string | null;
|
|
2235
2232
|
}): Promise<LinearAssignedIssuesResult>;
|
|
2236
2233
|
/**
|
|
2237
|
-
* Comments created at/after `since` on issues matching the same assignee
|
|
2238
|
-
* One GraphQL query — do not get_issue each ticket to check for new comments.
|
|
2234
|
+
* Comments created at/after `since` on issues matching the same assignee / search
|
|
2235
|
+
* filter. One GraphQL query — do not get_issue each ticket to check for new comments.
|
|
2236
|
+
* Pass `issueIdentifiers` (search hits) to keep only those tickets; an empty
|
|
2237
|
+
* allowlist means no comments.
|
|
2239
2238
|
*/
|
|
2240
2239
|
declare function listLinearCommentsSince(opts: {
|
|
2241
2240
|
since: string;
|
|
2242
2241
|
assignee?: string | null;
|
|
2243
2242
|
query?: string;
|
|
2243
|
+
issueIdentifiers?: string[];
|
|
2244
2244
|
limit?: number;
|
|
2245
2245
|
apiKey?: string | null;
|
|
2246
2246
|
}): Promise<IssueActivityComment[]>;
|
|
@@ -2364,7 +2364,8 @@ declare function resolveGitHubIssueRepo(repoPath?: string | null): Promise<{
|
|
|
2364
2364
|
declare function toGitHubIssueInfo(issue: GitHubIssue): IssueInfo;
|
|
2365
2365
|
/**
|
|
2366
2366
|
* Repo issue comments created at/after `since`. Pass `issueIdentifiers` (#12)
|
|
2367
|
-
* to keep only comments on that inbox page —
|
|
2367
|
+
* to keep only comments on that inbox page — paginated REST, not N issue views.
|
|
2368
|
+
* An empty allowlist means no comments (do not fall through to the whole repo).
|
|
2368
2369
|
*/
|
|
2369
2370
|
declare function listGitHubIssueCommentsSince(opts: {
|
|
2370
2371
|
since: string;
|
package/dist/index.js
CHANGED
|
@@ -238,7 +238,7 @@ import {
|
|
|
238
238
|
worktreeCleanupSettings,
|
|
239
239
|
wrapReviewSkillMarkdown,
|
|
240
240
|
writeWorktreeFile
|
|
241
|
-
} from "./chunk-
|
|
241
|
+
} from "./chunk-VTIVVVEC.js";
|
|
242
242
|
import {
|
|
243
243
|
LEGACY_PLAN_FILE_REL,
|
|
244
244
|
PLAN_FILE_NAME,
|
|
@@ -1518,12 +1518,27 @@ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
|
1518
1518
|
function assigneeFilterKey(assignee) {
|
|
1519
1519
|
return (assignee ?? "").trim();
|
|
1520
1520
|
}
|
|
1521
|
+
function applyLinearIssueQueryFilter(filter, query) {
|
|
1522
|
+
const term = query?.trim();
|
|
1523
|
+
if (!term) return;
|
|
1524
|
+
const or = [
|
|
1525
|
+
{ title: { containsIgnoreCase: term } },
|
|
1526
|
+
{ description: { containsIgnoreCase: term } }
|
|
1527
|
+
];
|
|
1528
|
+
const identifierMatch = term.match(/^[A-Za-z][\w]*-(\d+)$/);
|
|
1529
|
+
const asNumber = identifierMatch ? Number(identifierMatch[1]) : /^\d+$/.test(term) ? Number(term) : NaN;
|
|
1530
|
+
if (Number.isFinite(asNumber) && asNumber > 0) {
|
|
1531
|
+
or.push({ number: { eq: asNumber } });
|
|
1532
|
+
}
|
|
1533
|
+
filter.or = or;
|
|
1534
|
+
}
|
|
1521
1535
|
function buildLinearIssueFilter(input) {
|
|
1522
1536
|
const filter = {
|
|
1523
1537
|
state: { type: { nin: ["completed", "canceled"] } }
|
|
1524
1538
|
};
|
|
1525
1539
|
const since = input?.updatedSince?.trim();
|
|
1526
1540
|
if (since) filter.updatedAt = { gte: since };
|
|
1541
|
+
applyLinearIssueQueryFilter(filter, input?.query);
|
|
1527
1542
|
const raw = assigneeFilterKey(input?.assignee) || "me";
|
|
1528
1543
|
const key = raw.toLowerCase();
|
|
1529
1544
|
if (key === "all" || key === "*") return filter;
|
|
@@ -1589,6 +1604,11 @@ async function listLinearIssuesFiltered(opts) {
|
|
|
1589
1604
|
async function listLinearCommentsSince(opts) {
|
|
1590
1605
|
const first = Math.max(1, Math.min(250, opts.limit ?? 200));
|
|
1591
1606
|
const query = opts.query?.trim() ?? "";
|
|
1607
|
+
const restrictToIssues = opts.issueIdentifiers != null;
|
|
1608
|
+
const allowed = new Set(
|
|
1609
|
+
(opts.issueIdentifiers ?? []).map((id) => id.trim()).filter(Boolean)
|
|
1610
|
+
);
|
|
1611
|
+
if (restrictToIssues && allowed.size === 0) return [];
|
|
1592
1612
|
const assignee = assigneeFilterKey(opts.assignee) || (query ? "all" : "me");
|
|
1593
1613
|
const json = await linearGraphql(
|
|
1594
1614
|
COMMENTS_SINCE_QUERY,
|
|
@@ -1596,7 +1616,7 @@ async function listLinearCommentsSince(opts) {
|
|
|
1596
1616
|
first,
|
|
1597
1617
|
filter: {
|
|
1598
1618
|
createdAt: { gte: opts.since },
|
|
1599
|
-
issue: buildLinearIssueFilter({ assignee })
|
|
1619
|
+
issue: buildLinearIssueFilter({ assignee, query: query || void 0 })
|
|
1600
1620
|
}
|
|
1601
1621
|
},
|
|
1602
1622
|
opts
|
|
@@ -1604,6 +1624,7 @@ async function listLinearCommentsSince(opts) {
|
|
|
1604
1624
|
const out = [];
|
|
1605
1625
|
for (const node of json.comments?.nodes ?? []) {
|
|
1606
1626
|
const identifier = String(node.issue?.identifier ?? "").trim();
|
|
1627
|
+
if (restrictToIssues && !allowed.has(identifier)) continue;
|
|
1607
1628
|
const body = previewIssueCommentBody(String(node.body ?? ""));
|
|
1608
1629
|
if (!identifier && !body) continue;
|
|
1609
1630
|
out.push({
|
|
@@ -1833,10 +1854,32 @@ function issueNumberFromApiUrl(url) {
|
|
|
1833
1854
|
const number = Number(match[1]);
|
|
1834
1855
|
return Number.isFinite(number) && number > 0 ? number : null;
|
|
1835
1856
|
}
|
|
1857
|
+
var GITHUB_ISSUE_COMMENTS_PAGE_SIZE = 100;
|
|
1858
|
+
var GITHUB_ISSUE_COMMENTS_MAX_PAGES = 5;
|
|
1859
|
+
function parseGitHubIssueCommentNode(item, allowed) {
|
|
1860
|
+
const rec = item && typeof item === "object" ? item : null;
|
|
1861
|
+
if (!rec) return null;
|
|
1862
|
+
const issueUrl = typeof rec.issue_url === "string" ? rec.issue_url : "";
|
|
1863
|
+
const number = issueNumberFromApiUrl(issueUrl);
|
|
1864
|
+
if (number == null) return null;
|
|
1865
|
+
if (allowed && !allowed.has(number)) return null;
|
|
1866
|
+
const body = previewIssueCommentBody(typeof rec.body === "string" ? rec.body : "");
|
|
1867
|
+
const user = rec.user && typeof rec.user === "object" ? String(rec.user.login ?? "").trim() : "";
|
|
1868
|
+
const createdAt = typeof rec.created_at === "string" ? rec.created_at : typeof rec.createdAt === "string" ? rec.createdAt : void 0;
|
|
1869
|
+
const url = typeof rec.html_url === "string" ? rec.html_url : void 0;
|
|
1870
|
+
return {
|
|
1871
|
+
identifier: `#${number}`,
|
|
1872
|
+
...user ? { author: user } : {},
|
|
1873
|
+
...createdAt ? { createdAt } : {},
|
|
1874
|
+
body,
|
|
1875
|
+
...url ? { url } : {}
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1836
1878
|
async function listGitHubIssueCommentsSince(opts) {
|
|
1837
1879
|
const limit = Math.max(1, Math.min(250, opts.limit ?? 200));
|
|
1838
1880
|
const { cwd, slug } = await resolveGitHubIssueRepo(opts.repoPath);
|
|
1839
1881
|
if (!slug) return [];
|
|
1882
|
+
const restrictToIssues = opts.issueIdentifiers != null;
|
|
1840
1883
|
const allowed = new Set(
|
|
1841
1884
|
(opts.issueIdentifiers ?? []).map((id) => {
|
|
1842
1885
|
try {
|
|
@@ -1846,36 +1889,27 @@ async function listGitHubIssueCommentsSince(opts) {
|
|
|
1846
1889
|
}
|
|
1847
1890
|
}).filter((n) => n != null)
|
|
1848
1891
|
);
|
|
1849
|
-
|
|
1850
|
-
const
|
|
1851
|
-
if (result.exitCode !== 0 || !result.stdout.trim()) return [];
|
|
1852
|
-
let parsed;
|
|
1853
|
-
try {
|
|
1854
|
-
parsed = JSON.parse(result.stdout);
|
|
1855
|
-
} catch {
|
|
1856
|
-
return [];
|
|
1857
|
-
}
|
|
1858
|
-
if (!Array.isArray(parsed)) return [];
|
|
1892
|
+
if (restrictToIssues && allowed.size === 0) return [];
|
|
1893
|
+
const pageSize = Math.min(GITHUB_ISSUE_COMMENTS_PAGE_SIZE, Math.max(1, limit));
|
|
1859
1894
|
const out = [];
|
|
1860
|
-
for (
|
|
1861
|
-
const
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
if (out.length >= limit) break;
|
|
1895
|
+
for (let page = 1; page <= GITHUB_ISSUE_COMMENTS_MAX_PAGES; page++) {
|
|
1896
|
+
const path2 = `repos/${slug}/issues/comments?since=${encodeURIComponent(opts.since)}&sort=created&direction=desc&per_page=${pageSize}&page=${page}`;
|
|
1897
|
+
const result = await gh(["api", path2], cwd, { reject: false });
|
|
1898
|
+
if (result.exitCode !== 0 || !result.stdout.trim()) break;
|
|
1899
|
+
let parsed;
|
|
1900
|
+
try {
|
|
1901
|
+
parsed = JSON.parse(result.stdout);
|
|
1902
|
+
} catch {
|
|
1903
|
+
break;
|
|
1904
|
+
}
|
|
1905
|
+
if (!Array.isArray(parsed) || parsed.length === 0) break;
|
|
1906
|
+
for (const item of parsed) {
|
|
1907
|
+
const comment = parseGitHubIssueCommentNode(item, restrictToIssues ? allowed : null);
|
|
1908
|
+
if (!comment) continue;
|
|
1909
|
+
out.push(comment);
|
|
1910
|
+
if (out.length >= limit) return out;
|
|
1911
|
+
}
|
|
1912
|
+
if (parsed.length < pageSize) break;
|
|
1879
1913
|
}
|
|
1880
1914
|
return out;
|
|
1881
1915
|
}
|
|
@@ -2081,20 +2115,19 @@ async function listIssues(repoPath, opts) {
|
|
|
2081
2115
|
const assignee = opts?.assignee?.trim() || void 0;
|
|
2082
2116
|
const since = opts?.updatedSince ? parseIssueSince(opts.updatedSince) : void 0;
|
|
2083
2117
|
if (source === "linear") {
|
|
2084
|
-
const
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
since
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
]);
|
|
2118
|
+
const listed = await listLinearIssuesFiltered({
|
|
2119
|
+
assignee,
|
|
2120
|
+
query,
|
|
2121
|
+
limit: opts?.limit,
|
|
2122
|
+
updatedSince: since
|
|
2123
|
+
});
|
|
2124
|
+
const comments2 = since ? await listLinearCommentsSince({
|
|
2125
|
+
since,
|
|
2126
|
+
assignee,
|
|
2127
|
+
query,
|
|
2128
|
+
issueIdentifiers: query ? listed.issues.map((issue) => issue.identifier) : void 0,
|
|
2129
|
+
limit: opts?.limit
|
|
2130
|
+
}) : void 0;
|
|
2098
2131
|
return {
|
|
2099
2132
|
source,
|
|
2100
2133
|
preferredSource,
|
|
@@ -3762,20 +3795,19 @@ function registerLinearTools(server) {
|
|
|
3762
3795
|
try {
|
|
3763
3796
|
const page = clampMcpIssueLimit(limit);
|
|
3764
3797
|
const since = updatedSince ? parseIssueSince(updatedSince) : void 0;
|
|
3765
|
-
const
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
since
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
]);
|
|
3798
|
+
const listed = await listLinearIssuesFiltered({
|
|
3799
|
+
query,
|
|
3800
|
+
assignee,
|
|
3801
|
+
limit: page + 1,
|
|
3802
|
+
updatedSince: since
|
|
3803
|
+
});
|
|
3804
|
+
const comments = since ? await listLinearCommentsSince({
|
|
3805
|
+
since,
|
|
3806
|
+
assignee,
|
|
3807
|
+
query,
|
|
3808
|
+
issueIdentifiers: query ? listed.issues.map((issue) => issue.identifier) : void 0,
|
|
3809
|
+
limit: page + 1
|
|
3810
|
+
}) : void 0;
|
|
3779
3811
|
return mcpJson(
|
|
3780
3812
|
formatListedIssuesForMcp(
|
|
3781
3813
|
{
|
|
@@ -4880,7 +4912,7 @@ async function startMcpServer() {
|
|
|
4880
4912
|
);
|
|
4881
4913
|
server.tool(
|
|
4882
4914
|
"wait_for_job",
|
|
4883
|
-
"Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true,
|
|
4915
|
+
"Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
|
|
4884
4916
|
{
|
|
4885
4917
|
id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
|
|
4886
4918
|
timeoutMs: z9.number().optional()
|
|
@@ -4894,7 +4926,7 @@ async function startMcpServer() {
|
|
|
4894
4926
|
);
|
|
4895
4927
|
server.tool(
|
|
4896
4928
|
"stop_job",
|
|
4897
|
-
"Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress.
|
|
4929
|
+
"Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
|
|
4898
4930
|
{
|
|
4899
4931
|
id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
|
|
4900
4932
|
reason: z9.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
|