@sideboard-ai/core 0.1.130 → 0.1.132
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/agents/cursor-runner.js +1 -1
- package/dist/{agents-X2I3RNCY.js → agents-CI6NGKRO.js} +4 -3
- package/dist/{agents-7BUQY2WX.js → agents-LGJLZMM3.js} +3 -2
- package/dist/chunk-AQESMTCZ.js +129 -0
- package/dist/{chunk-IUJOI7KK.js → chunk-FSCQXMGI.js} +35 -4
- package/dist/{chunk-YMRT2DU6.js → chunk-LLX3OMHU.js} +25 -50
- package/dist/{chunk-NV73AO7Q.js → chunk-MGYCQAZ6.js} +17 -5
- package/dist/{chunk-ZMUOPTKZ.js → chunk-PK4PQUPU.js} +51 -8
- package/dist/chunk-R7FGPBKL.js +126 -0
- package/dist/{chunk-EKIDHL2T.js → chunk-SIPDL62B.js} +32 -55
- package/dist/{chunk-FMBLOOAO.js → chunk-SMWJAE74.js} +106 -14
- package/dist/{chunk-YALVX3UE.js → chunk-VFXZTSAD.js} +108 -15
- package/dist/{connected-teams-O6D4PM7A.js → connected-teams-3BWNJIRY.js} +2 -1
- package/dist/{connected-teams-ZCOU6KCD.js → connected-teams-S6E3D5C7.js} +2 -1
- package/dist/index.cjs +312 -92
- package/dist/index.d.cts +54 -4
- package/dist/index.d.ts +54 -4
- package/dist/index.js +36 -60
- package/dist/mcp/run-stdio.cjs +270 -62
- package/dist/mcp/run-stdio.js +6 -27
- package/dist/oauth-43NNH6C6.js +12 -0
- package/dist/oauth-FT7EL2PY.js +10 -0
- package/dist/{orchestrator-G6DU3AF3.js → orchestrator-5TN2DJWO.js} +5 -4
- package/dist/{orchestrator-3ZSFTG72.js → orchestrator-JA65XKB6.js} +4 -3
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -1553,11 +1553,40 @@ function humanizeAgentFailDetail(detail) {
|
|
|
1553
1553
|
}
|
|
1554
1554
|
function turnFailChatText(opts) {
|
|
1555
1555
|
const chat = opts.assistantText.trim();
|
|
1556
|
-
if (
|
|
1557
|
-
if (opts.exitCode === 0) return "";
|
|
1556
|
+
if (opts.exitCode === 0) return chat;
|
|
1558
1557
|
const detail = opts.detail.trim();
|
|
1559
|
-
|
|
1560
|
-
|
|
1558
|
+
const fail4 = detail ? humanizeAgentFailDetail(detail) : formatTurnExitError(opts.exitCode ?? 1, "");
|
|
1559
|
+
if (!chat) return fail4;
|
|
1560
|
+
const failCore = fail4.replace(/^exit\s*\d+:\s*/i, "").trim();
|
|
1561
|
+
if (looksLikeAgentFailureMessage(chat) || failCore && chat.includes(failCore) || chat.includes(fail4)) {
|
|
1562
|
+
return chat;
|
|
1563
|
+
}
|
|
1564
|
+
return `${chat}
|
|
1565
|
+
|
|
1566
|
+
${fail4}`;
|
|
1567
|
+
}
|
|
1568
|
+
function shouldFeedErrorBackToAgent(opts) {
|
|
1569
|
+
const detail = opts.detail.trim();
|
|
1570
|
+
const chat = (opts.assistantText ?? "").trim();
|
|
1571
|
+
if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
|
|
1572
|
+
return false;
|
|
1573
|
+
}
|
|
1574
|
+
if (looksLikeInvalidAgentSession(detail) || looksLikeV8Oom(detail) || looksLikeRetryableRunnerCrash(detail)) {
|
|
1575
|
+
return true;
|
|
1576
|
+
}
|
|
1577
|
+
if (/without details|segfault|sig(?:segv|abrt|ill)|fatal error/i.test(detail)) {
|
|
1578
|
+
return true;
|
|
1579
|
+
}
|
|
1580
|
+
return !chat && (opts.partsCount ?? 0) === 0;
|
|
1581
|
+
}
|
|
1582
|
+
function formatAgentErrorContinuePrompt(detail) {
|
|
1583
|
+
const fail4 = humanizeAgentFailDetail(detail.trim()) || "the agent process exited without details";
|
|
1584
|
+
return [
|
|
1585
|
+
"The previous agent process ended before it finished. Error:",
|
|
1586
|
+
fail4,
|
|
1587
|
+
"",
|
|
1588
|
+
"Continue from where you left off. Use the error to recover \u2014 do not restart the whole task unless the error requires it. If you cannot continue, say why."
|
|
1589
|
+
].join("\n");
|
|
1561
1590
|
}
|
|
1562
1591
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
1563
1592
|
const code = exitCode ?? 1;
|
|
@@ -6163,6 +6192,8 @@ var init_global_workspace = __esm({
|
|
|
6163
6192
|
|
|
6164
6193
|
// src/brightsy/config.ts
|
|
6165
6194
|
function brightsyConfigPath() {
|
|
6195
|
+
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
6196
|
+
if (override) return override;
|
|
6166
6197
|
return (0, import_node_path19.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
6167
6198
|
}
|
|
6168
6199
|
function loadBrightsyConfig() {
|
|
@@ -6201,6 +6232,108 @@ var init_accounts = __esm({
|
|
|
6201
6232
|
}
|
|
6202
6233
|
});
|
|
6203
6234
|
|
|
6235
|
+
// src/http/fetch.ts
|
|
6236
|
+
function formatFetchError(err, url) {
|
|
6237
|
+
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
6238
|
+
const cause = err.cause;
|
|
6239
|
+
let detail = "";
|
|
6240
|
+
if (cause instanceof Error) {
|
|
6241
|
+
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
6242
|
+
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
6243
|
+
} else if (cause != null) {
|
|
6244
|
+
detail = ` [${String(cause)}]`;
|
|
6245
|
+
}
|
|
6246
|
+
return `${err.message}${detail} (${url})`;
|
|
6247
|
+
}
|
|
6248
|
+
async function httpFetch(input, init) {
|
|
6249
|
+
const url = typeof input === "string" ? input : input.href;
|
|
6250
|
+
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
6251
|
+
try {
|
|
6252
|
+
return await fn(url, init);
|
|
6253
|
+
} catch (err) {
|
|
6254
|
+
throw new Error(formatFetchError(err, url));
|
|
6255
|
+
}
|
|
6256
|
+
}
|
|
6257
|
+
var injected;
|
|
6258
|
+
var init_fetch = __esm({
|
|
6259
|
+
"src/http/fetch.ts"() {
|
|
6260
|
+
"use strict";
|
|
6261
|
+
injected = null;
|
|
6262
|
+
}
|
|
6263
|
+
});
|
|
6264
|
+
|
|
6265
|
+
// src/brightsy/oauth.ts
|
|
6266
|
+
function brightsyAccessTokenNeedsRefresh(expiresAt, now = Date.now()) {
|
|
6267
|
+
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt) || expiresAt <= 0) {
|
|
6268
|
+
return true;
|
|
6269
|
+
}
|
|
6270
|
+
return now >= expiresAt - REFRESH_SKEW_MS;
|
|
6271
|
+
}
|
|
6272
|
+
function applyGrant(current, grant) {
|
|
6273
|
+
return {
|
|
6274
|
+
access_token: grant.access_token,
|
|
6275
|
+
refresh_token: grant.refresh_token || current.refresh_token,
|
|
6276
|
+
expires_at: grant.expires_at ?? current.expires_at
|
|
6277
|
+
};
|
|
6278
|
+
}
|
|
6279
|
+
async function refreshBrightsyAccessToken(opts) {
|
|
6280
|
+
const endpoint = (opts.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
6281
|
+
const url = `${endpoint}/oauth/token`;
|
|
6282
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
6283
|
+
let res;
|
|
6284
|
+
try {
|
|
6285
|
+
res = await fetchImpl(url, {
|
|
6286
|
+
method: "POST",
|
|
6287
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
6288
|
+
body: new URLSearchParams({
|
|
6289
|
+
grant_type: "refresh_token",
|
|
6290
|
+
refresh_token: opts.refreshToken,
|
|
6291
|
+
client_id: opts.clientId || "brightsy-cli"
|
|
6292
|
+
})
|
|
6293
|
+
});
|
|
6294
|
+
} catch (err) {
|
|
6295
|
+
throw new Error(formatFetchError(err, url));
|
|
6296
|
+
}
|
|
6297
|
+
if (!res.ok) return null;
|
|
6298
|
+
const data = await res.json();
|
|
6299
|
+
if (!data.access_token) return null;
|
|
6300
|
+
return {
|
|
6301
|
+
access_token: data.access_token,
|
|
6302
|
+
refresh_token: data.refresh_token,
|
|
6303
|
+
expires_at: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0
|
|
6304
|
+
};
|
|
6305
|
+
}
|
|
6306
|
+
async function ensureBrightsyLocalConfigFresh(opts) {
|
|
6307
|
+
let cfg;
|
|
6308
|
+
try {
|
|
6309
|
+
cfg = loadBrightsyConfig();
|
|
6310
|
+
} catch {
|
|
6311
|
+
return null;
|
|
6312
|
+
}
|
|
6313
|
+
if (!cfg.refresh_token || !brightsyAccessTokenNeedsRefresh(cfg.expires_at)) {
|
|
6314
|
+
return cfg;
|
|
6315
|
+
}
|
|
6316
|
+
const grant = await refreshBrightsyAccessToken({
|
|
6317
|
+
endpoint: cfg.endpoint || "https://brightsy.ai",
|
|
6318
|
+
refreshToken: cfg.refresh_token,
|
|
6319
|
+
clientId: cfg.oauth_client_id,
|
|
6320
|
+
fetchImpl: opts?.fetchImpl
|
|
6321
|
+
});
|
|
6322
|
+
if (!grant) return cfg;
|
|
6323
|
+
const next = { ...cfg, ...applyGrant(cfg, grant) };
|
|
6324
|
+
saveBrightsyConfig(next);
|
|
6325
|
+
return next;
|
|
6326
|
+
}
|
|
6327
|
+
var REFRESH_SKEW_MS;
|
|
6328
|
+
var init_oauth = __esm({
|
|
6329
|
+
"src/brightsy/oauth.ts"() {
|
|
6330
|
+
"use strict";
|
|
6331
|
+
init_fetch();
|
|
6332
|
+
init_config();
|
|
6333
|
+
REFRESH_SKEW_MS = 6e4;
|
|
6334
|
+
}
|
|
6335
|
+
});
|
|
6336
|
+
|
|
6204
6337
|
// src/brightsy/connected-teams.ts
|
|
6205
6338
|
function storePath4() {
|
|
6206
6339
|
return (0, import_node_path20.join)(appDataDir(), "brightsy-teams.json");
|
|
@@ -6251,7 +6384,6 @@ function applyConnectedTeamToCli(team) {
|
|
|
6251
6384
|
}
|
|
6252
6385
|
async function refreshTeamToken(team) {
|
|
6253
6386
|
if (!team.refresh_token) return team;
|
|
6254
|
-
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
6255
6387
|
const cfg = (() => {
|
|
6256
6388
|
try {
|
|
6257
6389
|
return loadBrightsyConfig();
|
|
@@ -6259,39 +6391,34 @@ async function refreshTeamToken(team) {
|
|
|
6259
6391
|
return null;
|
|
6260
6392
|
}
|
|
6261
6393
|
})();
|
|
6262
|
-
const
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
body: new URLSearchParams({
|
|
6267
|
-
grant_type: "refresh_token",
|
|
6268
|
-
refresh_token: team.refresh_token,
|
|
6269
|
-
client_id: clientId
|
|
6270
|
-
})
|
|
6394
|
+
const grant = await refreshBrightsyAccessToken({
|
|
6395
|
+
endpoint: team.endpoint || "https://brightsy.ai",
|
|
6396
|
+
refreshToken: team.refresh_token,
|
|
6397
|
+
clientId: cfg?.oauth_client_id
|
|
6271
6398
|
});
|
|
6272
|
-
if (!
|
|
6273
|
-
const data = await res.json();
|
|
6274
|
-
if (!data.access_token) return team;
|
|
6399
|
+
if (!grant) return team;
|
|
6275
6400
|
return {
|
|
6276
6401
|
...team,
|
|
6277
|
-
access_token:
|
|
6278
|
-
refresh_token:
|
|
6279
|
-
expires_at:
|
|
6402
|
+
access_token: grant.access_token,
|
|
6403
|
+
refresh_token: grant.refresh_token || team.refresh_token,
|
|
6404
|
+
expires_at: grant.expires_at ?? team.expires_at
|
|
6280
6405
|
};
|
|
6281
6406
|
}
|
|
6282
6407
|
async function ensureConnectedBrightsyTeamTokens() {
|
|
6408
|
+
await ensureBrightsyLocalConfigFresh().catch(() => null);
|
|
6283
6409
|
const teams = readStore4();
|
|
6284
6410
|
if (teams.length === 0) return [];
|
|
6285
6411
|
const next = [];
|
|
6286
6412
|
let changed = false;
|
|
6287
6413
|
for (const team of teams) {
|
|
6288
|
-
|
|
6289
|
-
if (!expired) {
|
|
6414
|
+
if (!team.refresh_token || !brightsyAccessTokenNeedsRefresh(team.expires_at)) {
|
|
6290
6415
|
next.push(team);
|
|
6291
6416
|
continue;
|
|
6292
6417
|
}
|
|
6293
6418
|
const refreshed = await refreshTeamToken(team);
|
|
6294
|
-
if (refreshed.access_token !== team.access_token
|
|
6419
|
+
if (refreshed.access_token !== team.access_token || refreshed.refresh_token !== team.refresh_token || refreshed.expires_at !== team.expires_at) {
|
|
6420
|
+
changed = true;
|
|
6421
|
+
}
|
|
6295
6422
|
next.push(refreshed);
|
|
6296
6423
|
}
|
|
6297
6424
|
if (changed) writeStore2(next);
|
|
@@ -6339,6 +6466,7 @@ var init_connected_teams = __esm({
|
|
|
6339
6466
|
init_paths();
|
|
6340
6467
|
init_accounts();
|
|
6341
6468
|
init_config();
|
|
6469
|
+
init_oauth();
|
|
6342
6470
|
}
|
|
6343
6471
|
});
|
|
6344
6472
|
|
|
@@ -7610,6 +7738,7 @@ function teamEnv(team) {
|
|
|
7610
7738
|
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
7611
7739
|
return {
|
|
7612
7740
|
BRIGHTSY_API_TOKEN: team.access_token,
|
|
7741
|
+
...team.refresh_token ? { BRIGHTSY_REFRESH_TOKEN: team.refresh_token } : {},
|
|
7613
7742
|
BRIGHTSY_ACCOUNT_ID: team.id,
|
|
7614
7743
|
BRIGHTSY_API_URL: endpoint
|
|
7615
7744
|
};
|
|
@@ -7889,10 +8018,15 @@ var init_types = __esm({
|
|
|
7889
8018
|
|
|
7890
8019
|
// src/agents/claude.ts
|
|
7891
8020
|
async function loadMcpServers() {
|
|
8021
|
+
if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
|
|
8022
|
+
return mcpListCache.servers;
|
|
8023
|
+
}
|
|
7892
8024
|
const claude = resolveClaudeExecutable();
|
|
7893
8025
|
const mcpText = await run(claude, ["mcp", "list"], { reject: false });
|
|
7894
|
-
|
|
8026
|
+
const servers = parseMcpList(`${mcpText.stdout}
|
|
7895
8027
|
${mcpText.stderr}`);
|
|
8028
|
+
mcpListCache = { at: Date.now(), servers };
|
|
8029
|
+
return servers;
|
|
7896
8030
|
}
|
|
7897
8031
|
function usageFromClaude(usage) {
|
|
7898
8032
|
if (!usage) return null;
|
|
@@ -8106,7 +8240,7 @@ function parseIssuesJson(raw) {
|
|
|
8106
8240
|
}
|
|
8107
8241
|
return [];
|
|
8108
8242
|
}
|
|
8109
|
-
var import_node_fs22, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
8243
|
+
var import_node_fs22, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
8110
8244
|
var init_claude = __esm({
|
|
8111
8245
|
"src/agents/claude.ts"() {
|
|
8112
8246
|
"use strict";
|
|
@@ -8144,6 +8278,7 @@ var init_claude = __esm({
|
|
|
8144
8278
|
"Skill(claude-in-chrome)"
|
|
8145
8279
|
];
|
|
8146
8280
|
CLAUDE_PROMPT_ARG_MAX = 2e5;
|
|
8281
|
+
mcpListCache = null;
|
|
8147
8282
|
claudeAdapter = {
|
|
8148
8283
|
kind: "claude",
|
|
8149
8284
|
async detect() {
|
|
@@ -9522,10 +9657,13 @@ var init_opencode = __esm({
|
|
|
9522
9657
|
const part = obj.part;
|
|
9523
9658
|
const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
|
|
9524
9659
|
if (!id) return null;
|
|
9660
|
+
const flagged = obj.isError === true || obj.is_error === true;
|
|
9661
|
+
const errText2 = formatUnknownDetail(obj.error);
|
|
9525
9662
|
return {
|
|
9526
9663
|
type: "tool_result",
|
|
9527
9664
|
id,
|
|
9528
|
-
content: part?.output ?? part?.content ?? obj.output ?? obj.content
|
|
9665
|
+
content: part?.output ?? part?.content ?? obj.output ?? obj.content ?? (errText2 || void 0),
|
|
9666
|
+
isError: flagged || Boolean(errText2)
|
|
9529
9667
|
};
|
|
9530
9668
|
}
|
|
9531
9669
|
if (obj.type === "step_finish" || obj.type === "step-finish") {
|
|
@@ -12021,7 +12159,48 @@ function isMergedPrState(prUrl, prState) {
|
|
|
12021
12159
|
if (!prUrl?.trim()) return false;
|
|
12022
12160
|
return (prState ?? "").trim().toUpperCase() === "MERGED";
|
|
12023
12161
|
}
|
|
12024
|
-
function
|
|
12162
|
+
function groupCreatedAt(group) {
|
|
12163
|
+
let min = group[0]?.createdAt ?? "";
|
|
12164
|
+
for (const t of group) {
|
|
12165
|
+
if (t.createdAt && t.createdAt < min) min = t.createdAt;
|
|
12166
|
+
}
|
|
12167
|
+
return min;
|
|
12168
|
+
}
|
|
12169
|
+
function groupUpdatedAt(group) {
|
|
12170
|
+
let max = group[0]?.updatedAt ?? "";
|
|
12171
|
+
for (const t of group) {
|
|
12172
|
+
if (t.updatedAt && t.updatedAt > max) max = t.updatedAt;
|
|
12173
|
+
}
|
|
12174
|
+
return max;
|
|
12175
|
+
}
|
|
12176
|
+
function sortThreadsInWorktree(list) {
|
|
12177
|
+
return [...list].sort((a, b) => {
|
|
12178
|
+
const created = a.createdAt.localeCompare(b.createdAt);
|
|
12179
|
+
if (created !== 0) return created;
|
|
12180
|
+
return a.id.localeCompare(b.id);
|
|
12181
|
+
});
|
|
12182
|
+
}
|
|
12183
|
+
function compareWorktreeGroups(a, b, mode, labelOf) {
|
|
12184
|
+
if (mode === "name") {
|
|
12185
|
+
const named = (labelOf?.(a) ?? a[0]?.id ?? "").localeCompare(
|
|
12186
|
+
labelOf?.(b) ?? b[0]?.id ?? "",
|
|
12187
|
+
void 0,
|
|
12188
|
+
{ sensitivity: "base" }
|
|
12189
|
+
);
|
|
12190
|
+
if (named !== 0) return named;
|
|
12191
|
+
} else if (mode === "activity") {
|
|
12192
|
+
const activity = groupUpdatedAt(b).localeCompare(groupUpdatedAt(a));
|
|
12193
|
+
if (activity !== 0) return activity;
|
|
12194
|
+
} else {
|
|
12195
|
+
const created = groupCreatedAt(b).localeCompare(groupCreatedAt(a));
|
|
12196
|
+
if (created !== 0) return created;
|
|
12197
|
+
}
|
|
12198
|
+
return (a[0]?.id ?? "").localeCompare(b[0]?.id ?? "");
|
|
12199
|
+
}
|
|
12200
|
+
function defaultWorktreeGroupLabel(group) {
|
|
12201
|
+
return worktreeDisplayLabelForGroup(group);
|
|
12202
|
+
}
|
|
12203
|
+
function groupHomeBoardWorktrees(threads, sort = DEFAULT_WORKTREE_SORT, labelOf = defaultWorktreeGroupLabel) {
|
|
12025
12204
|
const map = /* @__PURE__ */ new Map();
|
|
12026
12205
|
for (const t of threads) {
|
|
12027
12206
|
const key = normalizeWorktreePath(t.worktreePath);
|
|
@@ -12029,7 +12208,7 @@ function groupHomeBoardWorktrees(threads) {
|
|
|
12029
12208
|
list.push(t);
|
|
12030
12209
|
map.set(key, list);
|
|
12031
12210
|
}
|
|
12032
|
-
return [...map.values()].map((list) => list.sort((a, b) =>
|
|
12211
|
+
return [...map.values()].map((list) => sortThreadsInWorktree(list)).sort((a, b) => compareWorktreeGroups(a, b, sort, labelOf));
|
|
12033
12212
|
}
|
|
12034
12213
|
function classifyWorktreeColumn(group) {
|
|
12035
12214
|
if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
|
|
@@ -12328,8 +12507,7 @@ function assembleHomeBoard(input) {
|
|
|
12328
12507
|
const kind = input.kind ?? "all";
|
|
12329
12508
|
const limit = Math.max(1, input.limit ?? BOARD_PAGE_SIZE);
|
|
12330
12509
|
const wsName = input.workspaceName ?? (() => "");
|
|
12331
|
-
const
|
|
12332
|
-
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t)).sort(byUpdated);
|
|
12510
|
+
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t));
|
|
12333
12511
|
const columns = emptyColumns();
|
|
12334
12512
|
const hidden = emptyHidden();
|
|
12335
12513
|
const totals = {
|
|
@@ -12384,7 +12562,7 @@ function assembleHomeBoard(input) {
|
|
|
12384
12562
|
}
|
|
12385
12563
|
return { columns, hidden, totals };
|
|
12386
12564
|
}
|
|
12387
|
-
var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
|
|
12565
|
+
var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULT_WORKTREE_SORT, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
|
|
12388
12566
|
var init_home_board = __esm({
|
|
12389
12567
|
"src/board/home-board.ts"() {
|
|
12390
12568
|
"use strict";
|
|
@@ -12397,6 +12575,7 @@ var init_home_board = __esm({
|
|
|
12397
12575
|
{ id: "done", title: "Merged" }
|
|
12398
12576
|
];
|
|
12399
12577
|
HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
|
|
12578
|
+
DEFAULT_WORKTREE_SORT = "created";
|
|
12400
12579
|
DEFAULTISH_BRANCH = /^(main|master|develop|development|trunk|default|head)$/;
|
|
12401
12580
|
BOARD_PAGE_SIZE = 40;
|
|
12402
12581
|
HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). create_thread reuses a live worktree for the same ticket, PR, or named branch \u2014 do not recreate it. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
|
|
@@ -15900,6 +16079,11 @@ var init_orchestrator = __esm({
|
|
|
15900
16079
|
turnBaselines = /* @__PURE__ */ new Map();
|
|
15901
16080
|
/** Timers for orchestration session-quota auto-resume. */
|
|
15902
16081
|
quotaResumeTimers = /* @__PURE__ */ new Map();
|
|
16082
|
+
/**
|
|
16083
|
+
* Threads that already got a crash-continue turn. Cleared on a successful
|
|
16084
|
+
* finish or a user send so a later crash can recover again.
|
|
16085
|
+
*/
|
|
16086
|
+
crashContinued = /* @__PURE__ */ new Set();
|
|
15903
16087
|
maxConcurrent;
|
|
15904
16088
|
runningCount = 0;
|
|
15905
16089
|
constructor(opts) {
|
|
@@ -16113,6 +16297,29 @@ var init_orchestrator = __esm({
|
|
|
16113
16297
|
);
|
|
16114
16298
|
}
|
|
16115
16299
|
}
|
|
16300
|
+
/**
|
|
16301
|
+
* Cursor-style recovery: after a runner crash, feed the error back as the
|
|
16302
|
+
* next prompt so the same agent can continue instead of sitting on lastError.
|
|
16303
|
+
*/
|
|
16304
|
+
maybeEnqueueCrashContinue(threadId, opts) {
|
|
16305
|
+
if (this.crashContinued.has(threadId)) return;
|
|
16306
|
+
if (this.haltDrain.has(threadId)) return;
|
|
16307
|
+
if (!shouldFeedErrorBackToAgent({
|
|
16308
|
+
detail: opts.detail,
|
|
16309
|
+
assistantText: opts.assistantText,
|
|
16310
|
+
partsCount: opts.partsCount
|
|
16311
|
+
})) {
|
|
16312
|
+
return;
|
|
16313
|
+
}
|
|
16314
|
+
const thread = readThread(threadId);
|
|
16315
|
+
if (!thread || thread.status === "archived") return;
|
|
16316
|
+
this.crashContinued.add(threadId);
|
|
16317
|
+
const prompt = formatAgentErrorContinuePrompt(opts.detail);
|
|
16318
|
+
const queue = [prompt, ...thread.queue];
|
|
16319
|
+
updateThread(threadId, { queue });
|
|
16320
|
+
this.emit({ type: "queue_changed", threadId, queue });
|
|
16321
|
+
this.haltDrain.delete(threadId);
|
|
16322
|
+
}
|
|
16116
16323
|
getThreads(includeArchived = false) {
|
|
16117
16324
|
return listThreads({ includeArchived });
|
|
16118
16325
|
}
|
|
@@ -16212,15 +16419,20 @@ var init_orchestrator = __esm({
|
|
|
16212
16419
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
16213
16420
|
}
|
|
16214
16421
|
const queue = [...current.queue, prompt];
|
|
16422
|
+
this.crashContinued.delete(thread.id);
|
|
16215
16423
|
this.haltDrain.delete(thread.id);
|
|
16216
|
-
const
|
|
16424
|
+
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
16425
|
+
const patch = { queue };
|
|
16426
|
+
if (!inFlight) patch.status = "queued";
|
|
16217
16427
|
const pid = current.agentPid;
|
|
16218
16428
|
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
16219
16429
|
patch.agentPid = null;
|
|
16220
16430
|
}
|
|
16221
16431
|
updateThread(thread.id, patch);
|
|
16222
16432
|
this.emit({ type: "queue_changed", threadId: thread.id, queue });
|
|
16223
|
-
|
|
16433
|
+
if (!inFlight) {
|
|
16434
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
16435
|
+
}
|
|
16224
16436
|
if (thisProcessShouldDrainAgentQueues()) {
|
|
16225
16437
|
void this.drainQueue(thread.id);
|
|
16226
16438
|
}
|
|
@@ -16541,7 +16753,7 @@ var init_orchestrator = __esm({
|
|
|
16541
16753
|
let parts = result.parts;
|
|
16542
16754
|
let usage = result.usage ?? void 0;
|
|
16543
16755
|
let exitCode = result.exitCode;
|
|
16544
|
-
if (this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
|
|
16756
|
+
if (!this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
|
|
16545
16757
|
const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
|
|
16546
16758
|
if (sessionId) {
|
|
16547
16759
|
const { recoverFinishedCursorRun: recoverFinishedCursorRun2 } = await Promise.resolve().then(() => (init_cursor_recover(), cursor_recover_exports));
|
|
@@ -16562,7 +16774,7 @@ var init_orchestrator = __esm({
|
|
|
16562
16774
|
}
|
|
16563
16775
|
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
16564
16776
|
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
16565
|
-
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) &&
|
|
16777
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && shouldRetryFailedAgentTurn(detail, {
|
|
16566
16778
|
hasSession: Boolean(this.requireThread(threadId).sessionId)
|
|
16567
16779
|
})) {
|
|
16568
16780
|
updateThread(threadId, { sessionId: null });
|
|
@@ -16658,7 +16870,11 @@ var init_orchestrator = __esm({
|
|
|
16658
16870
|
)) {
|
|
16659
16871
|
updateThread(threadId, { sessionId: null });
|
|
16660
16872
|
}
|
|
16661
|
-
|
|
16873
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
16874
|
+
void syncThreadBranchFromGit(threadId).catch(() => void 0);
|
|
16875
|
+
} else {
|
|
16876
|
+
await syncThreadBranchFromGit(threadId);
|
|
16877
|
+
}
|
|
16662
16878
|
if (this.stoppedTurns.has(threadId)) {
|
|
16663
16879
|
const stopped = writeLiveStatus(threadId, "stopped");
|
|
16664
16880
|
if (stopped?.status === "stopped") {
|
|
@@ -16682,9 +16898,16 @@ var init_orchestrator = __esm({
|
|
|
16682
16898
|
});
|
|
16683
16899
|
}
|
|
16684
16900
|
this.emit({ type: "turn_finished", threadId, exitCode });
|
|
16685
|
-
if (exitCode
|
|
16901
|
+
if (exitCode === 0) {
|
|
16902
|
+
this.crashContinued.delete(threadId);
|
|
16903
|
+
} else {
|
|
16686
16904
|
const blob = [chatText, detail].filter(Boolean).join("\n");
|
|
16687
16905
|
void this.maybeHandleOrchestrationQuotaFailover(threadId, blob);
|
|
16906
|
+
this.maybeEnqueueCrashContinue(threadId, {
|
|
16907
|
+
detail: detail || failDetail,
|
|
16908
|
+
assistantText: chatText,
|
|
16909
|
+
partsCount: parts.length
|
|
16910
|
+
});
|
|
16688
16911
|
}
|
|
16689
16912
|
}
|
|
16690
16913
|
} catch (err) {
|
|
@@ -16704,6 +16927,11 @@ var init_orchestrator = __esm({
|
|
|
16704
16927
|
}
|
|
16705
16928
|
this.emit({ type: "turn_finished", threadId, exitCode: 1 });
|
|
16706
16929
|
void this.maybeHandleOrchestrationQuotaFailover(threadId, message);
|
|
16930
|
+
this.maybeEnqueueCrashContinue(threadId, {
|
|
16931
|
+
detail: message,
|
|
16932
|
+
assistantText: "",
|
|
16933
|
+
partsCount: 0
|
|
16934
|
+
});
|
|
16707
16935
|
}
|
|
16708
16936
|
} finally {
|
|
16709
16937
|
this.startingTurns.delete(threadId);
|
|
@@ -17677,34 +17905,14 @@ init_worktree();
|
|
|
17677
17905
|
init_run();
|
|
17678
17906
|
init_app_settings();
|
|
17679
17907
|
|
|
17680
|
-
// src/
|
|
17681
|
-
|
|
17682
|
-
function formatFetchError(err, url) {
|
|
17683
|
-
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
17684
|
-
const cause = err.cause;
|
|
17685
|
-
let detail = "";
|
|
17686
|
-
if (cause instanceof Error) {
|
|
17687
|
-
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
17688
|
-
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
17689
|
-
} else if (cause != null) {
|
|
17690
|
-
detail = ` [${String(cause)}]`;
|
|
17691
|
-
}
|
|
17692
|
-
return `${err.message}${detail} (${url})`;
|
|
17693
|
-
}
|
|
17694
|
-
async function httpFetch(input, init) {
|
|
17695
|
-
const url = typeof input === "string" ? input : input.href;
|
|
17696
|
-
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
17697
|
-
try {
|
|
17698
|
-
return await fn(url, init);
|
|
17699
|
-
} catch (err) {
|
|
17700
|
-
throw new Error(formatFetchError(err, url));
|
|
17701
|
-
}
|
|
17702
|
-
}
|
|
17908
|
+
// src/integrations/linear.ts
|
|
17909
|
+
init_fetch();
|
|
17703
17910
|
|
|
17704
17911
|
// src/integrations/linear-oauth.ts
|
|
17705
17912
|
var import_node_crypto9 = require("crypto");
|
|
17706
17913
|
var import_node_http = require("http");
|
|
17707
17914
|
init_app_settings();
|
|
17915
|
+
init_fetch();
|
|
17708
17916
|
|
|
17709
17917
|
// src/integrations/linear-app.ts
|
|
17710
17918
|
var BAKED_LINEAR_CLIENT_ID = "39a15abc7ea5bea17c47f47f85ff5fd0";
|
|
@@ -17713,7 +17921,7 @@ var BAKED_LINEAR_CLIENT_ID = "39a15abc7ea5bea17c47f47f85ff5fd0";
|
|
|
17713
17921
|
var LINEAR_OAUTH_PORT = 19848;
|
|
17714
17922
|
var LINEAR_OAUTH_REDIRECT = `http://127.0.0.1:${LINEAR_OAUTH_PORT}/callback`;
|
|
17715
17923
|
var LINEAR_TOKEN = "https://api.linear.app/oauth/token";
|
|
17716
|
-
var
|
|
17924
|
+
var REFRESH_SKEW_MS2 = 5 * 6e4;
|
|
17717
17925
|
function linearOAuthCredentials() {
|
|
17718
17926
|
const settings = loadAppSettings();
|
|
17719
17927
|
const clientId = process.env.SIDEBOARD_LINEAR_CLIENT_ID?.trim() || settings.integrations.linearClientId?.trim() || BAKED_LINEAR_CLIENT_ID.trim();
|
|
@@ -17781,7 +17989,7 @@ async function getLinearAuthToken(settings = loadAppSettings()) {
|
|
|
17781
17989
|
const refresh = settings.integrations.linearRefreshToken?.trim() || "";
|
|
17782
17990
|
const expiresAt = settings.integrations.linearTokenExpiresAt ?? 0;
|
|
17783
17991
|
const apiKey = settings.integrations.linearApiKey?.trim() || "";
|
|
17784
|
-
if (access && (!refresh || Date.now() < expiresAt -
|
|
17992
|
+
if (access && (!refresh || Date.now() < expiresAt - REFRESH_SKEW_MS2)) {
|
|
17785
17993
|
return access;
|
|
17786
17994
|
}
|
|
17787
17995
|
if (refresh) {
|
package/dist/mcp/run-stdio.js
CHANGED
|
@@ -31,12 +31,15 @@ import {
|
|
|
31
31
|
slackTokenFor,
|
|
32
32
|
syncBoardPins,
|
|
33
33
|
updateSchedule
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-SMWJAE74.js";
|
|
35
35
|
import {
|
|
36
36
|
listModelsForAgent,
|
|
37
37
|
sideboardMcpProfile
|
|
38
|
-
} from "../chunk-
|
|
39
|
-
import "../chunk-
|
|
38
|
+
} from "../chunk-PK4PQUPU.js";
|
|
39
|
+
import "../chunk-LLX3OMHU.js";
|
|
40
|
+
import {
|
|
41
|
+
httpFetch
|
|
42
|
+
} from "../chunk-R7FGPBKL.js";
|
|
40
43
|
import "../chunk-SYLTXDRF.js";
|
|
41
44
|
import "../chunk-N5PM7HGQ.js";
|
|
42
45
|
import "../chunk-KLBOWJ74.js";
|
|
@@ -79,30 +82,6 @@ import { z as z4 } from "zod";
|
|
|
79
82
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
80
83
|
import { basename } from "path";
|
|
81
84
|
|
|
82
|
-
// src/http/fetch.ts
|
|
83
|
-
var injected = null;
|
|
84
|
-
function formatFetchError(err, url) {
|
|
85
|
-
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
86
|
-
const cause = err.cause;
|
|
87
|
-
let detail = "";
|
|
88
|
-
if (cause instanceof Error) {
|
|
89
|
-
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
90
|
-
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
91
|
-
} else if (cause != null) {
|
|
92
|
-
detail = ` [${String(cause)}]`;
|
|
93
|
-
}
|
|
94
|
-
return `${err.message}${detail} (${url})`;
|
|
95
|
-
}
|
|
96
|
-
async function httpFetch(input, init) {
|
|
97
|
-
const url = typeof input === "string" ? input : input.href;
|
|
98
|
-
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
99
|
-
try {
|
|
100
|
-
return await fn(url, init);
|
|
101
|
-
} catch (err) {
|
|
102
|
-
throw new Error(formatFetchError(err, url));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
85
|
// src/integrations/linear-oauth.ts
|
|
107
86
|
import { createHash, randomBytes } from "crypto";
|
|
108
87
|
import { createServer } from "http";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
brightsyAccessTokenNeedsRefresh,
|
|
5
|
+
ensureBrightsyLocalConfigFresh,
|
|
6
|
+
refreshBrightsyAccessToken
|
|
7
|
+
} from "./chunk-R7FGPBKL.js";
|
|
8
|
+
export {
|
|
9
|
+
brightsyAccessTokenNeedsRefresh,
|
|
10
|
+
ensureBrightsyLocalConfigFresh,
|
|
11
|
+
refreshBrightsyAccessToken
|
|
12
|
+
};
|
|
@@ -4,15 +4,16 @@ import {
|
|
|
4
4
|
isPidAlive,
|
|
5
5
|
startOrchestration,
|
|
6
6
|
waitForPidExit
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-VFXZTSAD.js";
|
|
8
|
+
import "./chunk-MGYCQAZ6.js";
|
|
9
|
+
import "./chunk-SIPDL62B.js";
|
|
10
|
+
import "./chunk-AQESMTCZ.js";
|
|
10
11
|
import "./chunk-VE22NWBD.js";
|
|
11
12
|
import "./chunk-HULESWLI.js";
|
|
12
13
|
import "./chunk-HZPO3SSZ.js";
|
|
13
14
|
import "./chunk-QTUESPAW.js";
|
|
14
15
|
import "./chunk-AXQ4ZWHK.js";
|
|
15
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-FSCQXMGI.js";
|
|
16
17
|
import "./chunk-DCOZABNT.js";
|
|
17
18
|
import "./chunk-UDQI3N47.js";
|
|
18
19
|
import "./chunk-FKOIHGKV.js";
|
|
@@ -6,9 +6,10 @@ import {
|
|
|
6
6
|
isPidAlive,
|
|
7
7
|
startOrchestration,
|
|
8
8
|
waitForPidExit
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-SMWJAE74.js";
|
|
10
|
+
import "./chunk-PK4PQUPU.js";
|
|
11
|
+
import "./chunk-LLX3OMHU.js";
|
|
12
|
+
import "./chunk-R7FGPBKL.js";
|
|
12
13
|
import "./chunk-SYLTXDRF.js";
|
|
13
14
|
import "./chunk-N5PM7HGQ.js";
|
|
14
15
|
import "./chunk-KLBOWJ74.js";
|